diff --git a/lean/Makefile b/lean/Makefile index 61a42e0..18b51bb 100644 --- a/lean/Makefile +++ b/lean/Makefile @@ -1,5 +1,7 @@ SRC_C = $(wildcard src/*.c) SRC_CXX = $(wildcard src/*.cpp) +SRC_CXX+= $(wildcard src/rng/*.cpp) + INCLUDE = include PROJECT=shuffle3 @@ -41,6 +43,7 @@ debug: | dirs $(PROJECT)-debug dirs: @mkdir -p obj/c{,xx}/src + @mkdir -p obj/cxx/src/rng obj/c/%.o: %.c $(CC) -c $< $(CFLAGS) -o $@ $(LDFLAGS) diff --git a/lean/include/rng.h b/lean/include/rng.h new file mode 100644 index 0000000..8334d6c --- /dev/null +++ b/lean/include/rng.h @@ -0,0 +1,6 @@ +#ifndef _RNG_H +#define _RNG_H + +// C interface to C++ RNG impls + +#endif /* _RNG_H */ diff --git a/lean/include/rng/frng.hpp b/lean/include/rng/frng.hpp new file mode 100644 index 0000000..7a634a6 --- /dev/null +++ b/lean/include/rng/frng.hpp @@ -0,0 +1,17 @@ + +#include "impl.hpp" + +namespace rng +{ + struct frng : public RNG + { + inline frng(double s1, double s2) : state({s1, s2}){} + inline frng(const std::array& ar) : state(ar){} + inline frng(std::array&& ar) : state(ar){} + inline frng(const double (&ar)[2]) : state({ar[0], ar[1]}) {} + protected: + double sample(); + private: + std::array state; + }; +} diff --git a/lean/include/rng/impl.hpp b/lean/include/rng/impl.hpp new file mode 100644 index 0000000..ca10bd8 --- /dev/null +++ b/lean/include/rng/impl.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +/// Base class for RNG impls +struct RNG { + virtual unsigned char byte(); + virtual void bytes(unsigned char* ptr, std::size_t len); + + template + inline void bytes(unsigned char (&arr)[N]) { return bytes(arr, N); } + template + inline void bytes(std::array& array) { return bytes(&array[0], N); } + inline void bytes(std::vector& vec) { return bytes(&vec[0], vec.size()); } + + bool chance(); + virtual bool chance(double chance); + + virtual std::int32_t next_int(); + inline std::int32_t next_int(std::int32_t max) { return next_int(0, max); } + std::int32_t next_int(std::int32_t min, std::int32_t max); + + virtual std::int64_t next_long(); + + inline std::int64_t next_long(std::int64_t max) { return next_long(0, max); } + std::int64_t next_long(std::int64_t min, std::int64_t max); + + inline float next_float() { return (float)sample(); } + inline double next_double() { return sample(); } +protected: + virtual double sample() = 0; +}; diff --git a/lean/src/rng.cpp b/lean/src/rng.cpp new file mode 100644 index 0000000..1fd804b --- /dev/null +++ b/lean/src/rng.cpp @@ -0,0 +1,47 @@ + +#include +#include + +inline unsigned char RNG::byte() +{ + return (unsigned char)next_int(255); +} + +void RNG::bytes(unsigned char* ptr, std::size_t len) +{ + for(std::size_t i=0;i +#include +#include + +template +constexpr inline double dot(const std::array& v, const std::array& u) +{ + double res=0; + for(std::size_t i=0;i& state) + { + const constexpr std::array vec2 = { 12.9898, 78.223 }; + return fract(sin(dot(state, vec2)) * 43758.5453); + } + inline void update_state(std::array& state, double r) + { + float v1 = (float)state[0]; + float v2 = (float)state[1]; + + std::array nvec = { + r, + (double)v2, + }; + + state[0] = sample_double(nvec); + + nvec[1] = (double)v1; + state[1] = sample_double(nvec); + } + double frng::sample() + { + double res = sample_double(state); + update_state(state, res); + return res; + } +}