frng constexpr sampling

lean
Avril 4 years ago
parent 160c736289
commit acd07b6346
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,6 +1,17 @@
#ifndef _RNG_H #ifndef _RNG_H
#define _RNG_H #define _RNG_H
// C interface to C++ RNG impls #ifdef __cplusplus
extern "C" {
#endif
// Tests
void frng_test();
#ifdef __cplusplus
}
// RNG interfaces
#include <rng/frng.hpp>
#endif
#endif /* _RNG_H */ #endif /* _RNG_H */

@ -1,17 +1,62 @@
#include "impl.hpp" #include "impl.hpp"
#include <cmath>
namespace rng namespace rng
{ {
struct frng : public RNG struct frng : public RNG
{ {
template<std::size_t N>
static constexpr inline double dot(const std::array<double, N>& v, const std::array<double, N>& u)
{
double res=0;
for(std::size_t i=0;i<N;i++)
{
res += v[i] * u[i];
}
return res;
}
static inline constexpr double fract(double x)
{
return x - floor(x);
}
static inline constexpr double sample_double(const std::array<double, 2>& state)
{
const constexpr std::array<double, 2> vec2 = { 12.9898, 78.223 };
return fract(sin(dot(state, vec2)) * 43758.5453);
}
inline frng(double s1, double s2) : state({s1, s2}){} inline frng(double s1, double s2) : state({s1, s2}){}
inline frng(const std::array<double, 2>& ar) : state(ar){} inline frng(const std::array<double, 2>& ar) : state(ar){}
inline frng(std::array<double, 2>&& ar) : state(ar){} inline frng(std::array<double, 2>&& ar) : state(ar){}
inline frng(const double (&ar)[2]) : state({ar[0], ar[1]}) {} inline frng(const double (&ar)[2]) : state({ar[0], ar[1]}) {}
inline constexpr double next_double() override { return sample(); }
inline constexpr float next_float() override { return (float)sample(); }
protected: protected:
double sample(); inline constexpr double sample() override
{
double res = sample_double(state);
update_state(state, res);
return res;
}
private: private:
std::array<double, 2> state; std::array<double, 2> state;
static inline constexpr void update_state(std::array<double, 2>& state, double r)
{
float v1 = (float)state[0];
float v2 = (float)state[1];
std::array<double, 2> nvec = {
r,
(double)v2,
};
state[0] = sample_double(nvec);
nvec[1] = (double)v1;
state[1] = sample_double(nvec);
}
}; };
} }

@ -27,8 +27,8 @@ struct RNG {
inline std::int64_t next_long(std::int64_t max) { return next_long(0, max); } 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); std::int64_t next_long(std::int64_t min, std::int64_t max);
inline float next_float() { return (float)sample(); } inline virtual float next_float() { return (float)sample(); }
inline double next_double() { return sample(); } inline virtual double next_double() { return sample(); }
protected: protected:
virtual double sample() = 0; virtual double sample() = 0;
}; };

@ -8,6 +8,7 @@
#include <panic.h> #include <panic.h>
#include <reinterpret.h> #include <reinterpret.h>
#include <map.h> #include <map.h>
#include <rng.h>
_Static_assert(sizeof(float)==sizeof(uint32_t), "float is not 32 bits"); _Static_assert(sizeof(float)==sizeof(uint32_t), "float is not 32 bits");
@ -42,6 +43,8 @@ int main(int argc, char** argv)
{ {
struct prog_args args = {.argc = argc, .argv = argv}; struct prog_args args = {.argc = argc, .argv = argv};
frng_test();
if( argv[1] ) { if( argv[1] ) {
map_and_then(argv[1], &map_callback, &args); map_and_then(argv[1], &map_callback, &args);
} }

@ -1,48 +1,26 @@
#include <rng/impl.hpp> #include <rng/impl.hpp>
#include <rng/frng.hpp> #include <rng/frng.hpp>
#include <cmath> #include <iostream>
template<std::size_t N> namespace rng {
constexpr inline double dot(const std::array<double, N>& v, const std::array<double, N>& u) using namespace std;
{ inline void test()
double res=0;
for(std::size_t i=0;i<N;i++)
{ {
res += v[i] * u[i]; frng rng(1.0, 2.0);
}
return res;
}
inline constexpr double fract(double x) for(int i=0;i<10;i++) {
{ double d = rng.next_double();
return x - floor(x); long l = rng.next_long(0, 100);
}
namespace rng { cout << "Sampled: " << d << endl;
inline constexpr double sample_double(const std::array<double, 2>& state) cout << "Long: " << l << endl;
{ }
const constexpr std::array<double, 2> vec2 = { 12.9898, 78.223 };
return fract(sin(dot(state, vec2)) * 43758.5453);
} }
inline void update_state(std::array<double, 2>& state, double r)
{
float v1 = (float)state[0];
float v2 = (float)state[1];
std::array<double, 2> nvec = { }
r,
(double)v2,
};
state[0] = sample_double(nvec);
nvec[1] = (double)v1; extern "C" void frng_test()
state[1] = sample_double(nvec); {
} rng::test();
double frng::sample()
{
double res = sample_double(state);
update_state(state, res);
return res;
}
} }

Loading…
Cancel
Save