# PRNG based on sine-wave oscillator

112 views

### Aleksey Vaneev

Sep 16, 2020, 4:18:31 PM9/16/20
to prng
Here's a PractRand class for your experimentation. Basically, every point on a sinewave is a random number. Extracting "double" value's mantissa may probably work better - faster and longer period. "si" must be a multiple of PI, any values between 0.1/pi and 0.001/pi work fine.

class DummyRNG : public PractRand::RNGs::vRNG8 {
public:
double si;
double sincr;
double muls;
double svalue1;
double svalue2;

DummyRNG() {
si = 0.01 / 3.14159265358979324;
sincr = 2.0 * cos( si );

muls = 256.0 * 256.0 * 256.0 * 256.0 * 256.0 * 256.0;

seed( 0 );
}

Uint8 raw8() {
uint64_t v = (uint64_t) svalue1;

const double tmp = svalue1;
svalue1 = sincr * svalue1 - svalue2;
svalue2 = tmp;

return (Uint8) ( v ^ ( v >> 8 ) ^ ( v >> 16 ) ^ ( v >> 24 ) ^ ( v >> 32 ) ^
( v >> 40 ));
}
void walk_state(PractRand::StateWalkingObject *walker) {
}
void seed(Uint64 sv) {
const double ph = ( sv & 0xFFFFFFFFFFFFULL ) * 2.0 *
3.14159265358979324 / muls;

svalue1 = sin( ph ) * muls;
svalue2 = sin( ph - si ) * muls;
}
std::string get_name() const {return "SINEWAVE";}
};

### Aleksey Vaneev

Sep 16, 2020, 5:19:10 PM9/16/20
to prng
Ah, yeah, it works similarly well with direct exponent extraction, twice as fast per byte.

class DummyRNG : public PractRand::RNGs::vRNG16 {

public:
double si;
double sincr;
double svalue1;
double svalue2;

DummyRNG() {
si = 0.01 / 3.14159265358979324;
sincr = 2.0 * cos( si );

seed( 0 );
}

Uint16 raw16() {
uint64_t Value = ( *(uint64_t*) &svalue1 ) >> 4;

const double tmp = svalue1;
svalue1 = sincr * svalue1 - svalue2;
svalue2 = tmp;

return (Uint16) ( Value ^ Value >> 16 ^ Value >> 32 );

}
void walk_state(PractRand::StateWalkingObject *walker) {
}
void seed(Uint64 sv) {
const double ph = sv * 3.40612158008655459e-19;

svalue1 = sin( ph );
svalue2 = sin( ph - si );

}
std::string get_name() const {return "SINEWAVE";}
};