Skip to content

Instantly share code, notes, and snippets.

@jrandom
Last active August 29, 2015 14:19
Show Gist options
  • Save jrandom/62d6741e5d1eb65a8060 to your computer and use it in GitHub Desktop.
Save jrandom/62d6741e5d1eb65a8060 to your computer and use it in GitHub Desktop.
Mutatable Value Macro
//
// Mutatable_Value.h
// Tools/Genetics
//
#ifndef Tools_Genetics_Mutateable_Value_h
#define Tools_Genetics_Mutateable_Value_h
// ================================================================================ Standard Includes
// Standard Includes
// --------------------------------------------------------------------------------
#include <limits>
#include <utility>
// ================================================================================ Tools Includes
// Tools Includes
// --------------------------------------------------------------------------------
#include "Tools/Core/Math.h"
#include "Tools/Core/Random.h"
#include "Tools/File/Raw.h"
namespace Genetics
{
// ============================================================================ Mutateable_ ##
// Mutatable_ ##
//
// Utility class to simplify basic mutating values. Created as a macro since
// C++ doesn't allow for floating-point template value arguments.
//
// I am so very sorry...
// ----------------------------------------------------------------------------
#define Declare_Mutatable_Value(TAG, VALUE_TYPE, VALUE_MIN, VALUE_MAX, VALUE_DEFAULT) \
\
class Mutatable_ ## TAG final\
{ \
public:\
/* -------------------------------------------------------------------- Types */ \
using This_t = Mutatable_ ## TAG;\
using Value_t = VALUE_TYPE;\
using Pair_t = std::pair< This_t, This_t >;\
using Value_Pair_t = std::pair< Value_t, Value_t >;\
\
private:\
/* -------------------------------------------------------------------- Constants */ \
static constexpr Value_t Value_Min = Value_t( VALUE_MIN );\
static constexpr Value_t Value_Max = Value_t( VALUE_MAX );\
\
/* -------------------------------------------------------------------- State */ \
Value_t _value;\
\
\
public:\
/* ==================================================================== Constructors */ \
/* Constructors */ \
/* -------------------------------------------------------------------- Construct( zero ) */ \
Mutatable_ ## TAG () noexcept\
\
: _value( VALUE_DEFAULT )\
{}\
\
/* -------------------------------------------------------------------- Construct( value ) */ \
Mutatable_ ## TAG ( Value_t value ) noexcept\
\
: _value( Math::Clamp(value, Value_Min, Value_Max) )\
{}\
\
/* -------------------------------------------------------------------- Construct( copy ) */ \
Mutatable_ ## TAG ( const This_t & source ) noexcept\
\
: _value( source._value )\
{} \
\
/* -------------------------------------------------------------------- Construct( random ) */ \
Mutatable_ ## TAG ( Random::Generator & rng ) noexcept\
\
: _value( rng.Number(Value_Min, Value_Max) )\
{}\
\
/* -------------------------------------------------------------------- Construct( random with initial allowed range ) */ \
Mutatable_ ## TAG ( Random::Generator & rng, \
const Value_Pair_t min_max_initial_range ) noexcept\
\
: Mutatable_ ## TAG( rng.Number(min_max_initial_range.first, min_max_initial_range.second) )\
{}\
\
/* -------------------------------------------------------------------- Construct( muatate ) */ \
Mutatable_ ## TAG ( const This_t & source,\
Random::Generator & rng,\
const float mutation_rate ) noexcept\
\
: _value( rng.Chance( mutation_rate )\
? rng.Number( Value_Min, Value_Max )\
: source._value )\
{}\
\
/* -------------------------------------------------------------------- Construct( from file ) */ \
Mutatable_ ## TAG ( File::Raw_In & infile )\
\
: _value( Value_From_File(infile) )\
{}\
\
\
public:\
/* ==================================================================== Accessors and Overloads */ \
/* Accessors and Overloads*/ \
/* -------------------------------------------------------------------- */ \
Value_t Value () const noexcept { return _value; }\
operator Value_t() const noexcept { return _value; }\
\
This_t & operator=( Value_t value ) noexcept { _value = Math::Clamp(value, Value_Min, Value_Max ); return *this; }\
\
\
public:\
/* ==================================================================== Public API */ \
/* Public API */ \
/* -------------------------------------------------------------------- Duplicate() */ \
static Pair_t Duplicate( const This_t & source, \
Random::Generator & rng ) \
{\
/* Standard duplication has no special case, so rng is unused here */ \
/* I apologize for all the compiler warnings this incurs. */ \
return { source, source }; \
}\
\
/* -------------------------------------------------------------------- Persist() */ \
void Persist( File::Raw_Out & outfile ) const\
{\
outfile.Write( _value );\
}\
\
\
private:\
/* ==================================================================== Private Static API */ \
/* Private Static API */ \
/* -------------------------------------------------------------------- Value_From_File() */ \
static Value_t Value_From_File( File::Raw_In & infile )\
{\
Value_t value;\
\
infile.Read_Into( &value );\
\
return value;\
}\
}
// ============================================================================ Mutatable Value Presets
// Mutatable Value Presets
// ----------------------------------------------------------------------------
Declare_Mutatable_Value( Float_01, float, 0.0f, 1.0f, 0.0f );
Declare_Mutatable_Value( Double_01, double, 0.0, 1.0, 0.0 );
Declare_Mutatable_Value( Float_PosNeg1, float, -1.0f, 1.0f, 0.0f );
Declare_Mutatable_Value( Double_PosNeg1, double, -1.0, 1.0, 0.0 );
Declare_Mutatable_Value( Float_PosNeg2, float, -2.0f, 2.0f, 0.0f );
Declare_Mutatable_Value( Double_PosNeg2, double, -2.0, 2.0, 0.0 );
Declare_Mutatable_Value( Int8, int_fast8_t, std::numeric_limits< int8_t >::min(), std::numeric_limits< int8_t >::max(), int_fast8_t (0) );
Declare_Mutatable_Value( Int16, int_fast16_t, std::numeric_limits< int16_t >::min(), std::numeric_limits< int16_t >::max(), int_fast16_t(0) );
Declare_Mutatable_Value( Int32, int_fast32_t, std::numeric_limits< int32_t >::min(), std::numeric_limits< int32_t >::max(), int_fast32_t(0) );
Declare_Mutatable_Value( Int64, int_fast64_t, std::numeric_limits< int64_t >::min(), std::numeric_limits< int64_t >::max(), int_fast64_t(0) );
Declare_Mutatable_Value( Uint8, uint_fast8_t, std::numeric_limits< uint8_t >::min(), std::numeric_limits< uint8_t >::max(), uint_fast8_t (0) );
Declare_Mutatable_Value( Uint16, uint_fast16_t, std::numeric_limits< uint16_t>::min(), std::numeric_limits< uint16_t >::max(), uint_fast16_t(0) );
Declare_Mutatable_Value( Uint32, uint_fast32_t, std::numeric_limits< uint32_t>::min(), std::numeric_limits< uint32_t >::max(), uint_fast32_t(0) );
Declare_Mutatable_Value( Uint64, uint_fast64_t, std::numeric_limits< uint64_t>::min(), std::numeric_limits< uint64_t >::max(), uint_fast64_t(0) );
using Mutatable_Probability = Mutatable_Float_01;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment