0.2.0 DEVRANDOM

This commit is contained in:
rob tillaart 2022-07-03 20:27:42 +02:00
parent d4d2ed7e9f
commit 43049f375f
13 changed files with 591 additions and 233 deletions

View File

@ -0,0 +1,183 @@
//
// FILE: DEVRANDOM.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// PURPOSE: Arduino library for a /dev/random stream - useful for testing
// URL: https://github.com/RobTillaart/DEVRANDOM
//
// HISTORY:
// 0.1.0 2020-06-23 initial version
// 0.1.1 2020-12-18 add Arduino-CI + unit tests
// + getMode() + flush()
// 0.1.2 2021-01-15 add constructors with seed.
// 0.1.3 2021-12-15 update library.json, license, minor edits
//
// 0.2.0 2022-07-02 add Marsaglia PRNG, is portable over platforms
// becomes mode 3
// improved reseeding
// split off .cpp file
// add examples
#include "DEVRANDOM.h"
DEVRANDOM::DEVRANDOM()
{
_next = _rnd();
};
DEVRANDOM::DEVRANDOM(const char * str)
{
this->print(str);
_next = _rnd();
};
DEVRANDOM::DEVRANDOM(const uint32_t value)
{
this->print(value);
_next = _rnd();
};
DEVRANDOM::DEVRANDOM(const float value)
{
this->print(value, 6);
_next = _rnd();
};
int DEVRANDOM::available()
{
return 1;
};
int DEVRANDOM::peek()
{
return _next;
};
int DEVRANDOM::read()
{
uint8_t x = _next;
_next = _rnd();
return x;
};
// keep CI happy as parent class flush is virtual.
void DEVRANDOM::flush()
{
};
size_t DEVRANDOM::write(const uint8_t data)
{
return write(&data, 1);
};
size_t DEVRANDOM::write(const uint8_t * buffer, size_t size)
{
uint32_t tmp = _seed;
for (size_t i = 0; i < size; i++)
{
_seed = _seed * (_seed << 8) + buffer[i];
}
if (_mode == 0)
{
randomSeed(_seed);
}
if (_mode == 3)
{
_m_z = (_seed == 0) ? 1 : _seed;
_m_w = ( tmp == 0) ? 2 : tmp;
}
return size;
};
void DEVRANDOM::useMarsaglia()
{
_mode = 3;
};
void DEVRANDOM::useAnalogRead(uint8_t pin)
{
_mode = 2;
_pin = pin;
};
void DEVRANDOM::useDigitalRead(uint8_t pin)
{
_mode = 1;
_pin = pin;
pinMode(_pin, INPUT);
};
void DEVRANDOM::useRandom()
{
_mode = 0;
};
uint8_t DEVRANDOM::getMode()
{
return _mode;
};
int DEVRANDOM::_rnd()
{
if (_mode == 0 ) return random(256);
if (_mode == 1 ) return _digitalRead();
if (_mode == 2 ) return _analogRead();
if (_mode == 3 ) return _marsaglia();
return 0;
}
int DEVRANDOM::_digitalRead()
{
uint8_t value = 0;
for (uint8_t i = 0; i < 8; i++)
{
value <<= 1;
if (digitalRead(_pin)) value++;
}
return value ^ _seed;
}
int DEVRANDOM::_analogRead()
{
uint8_t value = 0;
for (uint8_t i = 0; i < 8; i++)
{
value <<= 1;
if (analogRead(_pin) & 1) value++;
}
return value ^ _seed;
}
// An example of a simple pseudo-random number generator is the
// Multiply-with-carry method invented by George Marsaglia.
// two initializers (not null)
uint32_t DEVRANDOM::_marsaglia()
{
_m_z = 36969L * (_m_z & 65535L) + (_m_z >> 16);
_m_w = 18000L * (_m_w & 65535L) + (_m_w >> 16);
return (_m_z << 16) + _m_w; /* 32-bit result */
}
// -- END OF FILE --

View File

@ -2,145 +2,72 @@
//
// FILE: DEVRANDOM.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.3
// VERSION: 0.2.0
// PURPOSE: Arduino library for a /dev/random stream - useful for testing
// URL: https://github.com/RobTillaart/DEVRANDOM
//
// HISTORY:
// 0.1.0 2020-06-23 initial version
// 0.1.1 2020-12-18 add Arduino-CI + unit tests
// + getMode() + flush()
// 0.1.2 2021-01-15 add constructors with seed.
// 0.1.3 2021-12-15 update library.json, license, minor edits
#include "Arduino.h"
#define DEVRANDOM_LIB_VERSION (F("0.1.3"))
#define DEVRANDOM_LIB_VERSION (F("0.2.0"))
#define DEVRANDOM_MODE_SW 0
#define DEVRANDOM_MODE_HW 1
#define DEVRANDOM_MODE_AR 2
#define DEVRANDOM_MODE_RANDOM 0
#define DEVRANDOM_MODE_DIGITALREAD 1
#define DEVRANDOM_MODE_ANALOGREAD 2
#define DEVRANDOM_MODE_MARSAGLIA 3
class DEVRANDOM : public Stream
{
public:
DEVRANDOM()
{
_seed = 0;
_next = random(256);
_mode = 0;
_pin = 0;
};
DEVRANDOM();
DEVRANDOM(const char * str);
DEVRANDOM(const uint32_t value);
DEVRANDOM(const float value);
int available();
int peek();
int read();
// keep CI happy as parent class flush is virtual.
void flush();
// for reseeding, including via print() and println().
size_t write(const uint8_t data);
size_t write(const uint8_t * buffer, size_t size);
// build in random is the default mode.
void useRandom();
void useDigitalRead(uint8_t pin);
void useAnalogRead(uint8_t pin);
void useMarsaglia();
uint8_t getMode();
DEVRANDOM(const char * str)
{
this->print(str);
_next = random(256);
_mode = 0;
_pin = 0;
};
DEVRANDOM(const uint32_t value)
{
this->print(value);
_next = random(256);
_mode = 0;
_pin = 0;
};
DEVRANDOM(const float value)
{
this->print(value, 6);
_next = random(256);
_mode = 0;
_pin = 0;
};
int available() { return 1; };
int peek() { return _next; };
int read()
{
uint8_t x = _next;
_next = _rnd();
return x;
};
// keep CI happy as parent class flush is virtual.
void flush() {};
size_t write(const uint8_t data)
{
_seed = (_seed << 8) + data;
randomSeed(_seed);
return 1;
};
void useAR(uint8_t pin) { _mode = 2; _pin = pin; };
void useHW(uint8_t pin) { _mode = 1; _pin = pin; pinMode(_pin, INPUT); };
void useSW() { _mode = 0; };
uint8_t getMode() { return _mode; };
// will be obsolete in future
void useAR(uint8_t pin) { useAnalogRead(pin); };
void useHW(uint8_t pin) { useDigitalRead(pin); };
void useSW() { useRandom(); };
private:
uint8_t _next;
uint32_t _seed;
uint8_t _mode;
uint8_t _pin;
uint8_t _next = 0;
uint32_t _seed = 0;
uint8_t _mode = 0;
uint8_t _pin = 0;
// Marsaglia 'constants'
uint32_t _m_w = 1;
uint32_t _m_z = 2;
int _rnd();
int _digitalRead();
int _analogRead();
uint32_t _marsaglia();
int _rnd()
{
if (_mode == 0 ) return random(256);
if (_mode == 1 ) return _hardware();
if (_mode == 2 ) return _analog();
return 0;
}
int _hardware()
{
uint8_t value = 0;
for (uint8_t i = 0; i < 8; i++)
{
value <<= 1;
if (digitalRead(_pin)) value++;
}
return value ^ _seed;
}
int _analog()
{
uint8_t value = 0;
for (uint8_t i = 0; i < 8; i++)
{
value <<= 1;
if (analogRead(_pin) & 1) value++;
}
return value ^ _seed;
}
};
// TODO alternative random number generator so all platforms behave same.
// Marsaglia ?
// -- END OF FILE --

View File

@ -29,33 +29,61 @@ device of a Linux system. It can be used for testing with streams.
### Streeam interface
to read and to reseed the random generator.
To read and to reseed the random generator.
- **available()** There is always 1 next byte available
- **peek()** will give you next byte
- **read()** will give you next byte and generate a new one.
- **write()** data will be used for reseeding the random number generator (RNG)
(SW mode only, in HW mode and AN mode the seed is used to XOR the value, so it
does have some effect);
- **flush()** to keep the CI happy.
- **int available()** There is always 1 next byte available.
- **int peek()** will give you next byte.
- **int read()** will give you next byte and generate a new one.
- **size_t write(uint8_t data)** data will be used for reseeding the random number generator (RNG), mode 0 and 3.
In digitalRead and analogRead mode the seed is used to XOR
the value, so it does have some effect.
- **size_t write(uint8_t \* buffer, size_t size)** speeds up reseeding
for some print / println calls.
- **void flush()** to keep the CI happy.
As **write()** reseeds the RNG, printing to **DEVRANDOM** will also reseed the RNG.
E.g. **dr.println("Hello world");** or **dr.println(3.45678);** will reseed DEVRANDOM too.
See examples.
If footprint is an issue one could remove the **size_t write(uint8_t \* buffer, size_t size)**
from the library and implement a stripped version in **write()**.
Reseeding will become slower but as reseeding is not used that often
this might be a good trade off.
### Random generator selection
- **useSW()** use a software random number generator. This is the default.
By default the build-in random number generator is used.
This can be replaced by a RNG of your choice.
- **useHW(uint8_t pin)** use digitalRead to read 8 bits from a defined pin.
- **void useRandom()** use the build in software random number generator. This is the default, but platform dependant.
- **void useDigitalRead(uint8_t pin)** use digitalRead to read 8 bits from a defined pin.
One can build a hardware RNG that flips between 0 and 1 very rapidly and unpredictably.
Connect this signal to the pin and it will be read and generate a random byte.
The seed value from the write is used as an XOR byte.
- **useAR(uint8_t pin)** use the analogRead to read 8 bits
This can be fed with an analogue noise source.
- **void useAnalogRead(uint8_t pin)** use the analogRead to read 8 bits
This can be fed with any analogue noise source.
The seed value from the write is used as a XOR byte.
- **getMode()** returns the source of randomness => 0 = SW, 1 = HW, 2 = AR (see above).
- **void useMarsaglia()** uses the Marsaglia pseudo random generator.
This one is quite fast and good, and more important portable.
- **uint8_t getMode()** returns the source of randomness.
As **write()** reseeds the RNG, printing to **DEVRANDOM** will also reseed the RNG.
E.g. **dr.println("Hello world");** would reseed it too.
| Mode | DEVRANDOM_MODE | Type |
|:-------:|:----------------:|:----------------------|
| 0 | build in random | depends on platform
| 1 | digitalRead | hardware external
| 2 | analogRead | hardware external
| 3 | Marsaglia | software portable PRNG
There might be other RNG's in the future.
If you have an interesting and fast PRNG to be included please let me know.
### Obsolete
To be obsolete in a next release.
- **useSW()** replaced by **useRandom()**.
- **useHW(uint8_t pin)** replaced by **useDigitalRead()**.
- **useAR(uint8_t pin)** replaced by **useAnalogRead()**.
## Operation
@ -79,6 +107,14 @@ So a password generator is a bit more difficult (and a good exercise).
## Future
- improve documentation
- add Marsaglia PRG
-
- improve documentation.
- add examples.
- add other (portable) PRNG.
- **available()** returns 1,
- should that be more e.g. INT_MAX
- a random number > 0 ?
- ?
- when changing mode should \_next == **peek()** be reset?
- yes, think so ```_next = _rnd();```
- when already in that mode? (=> complex)

View File

@ -0,0 +1,44 @@
//
// FILE: DEVRANDOM_compile_time_random_seed.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo compile time random seed
// DATE: 2020-06-23
// (c) : MIT
//
#include "DEVRANDOM.h"
DEVRANDOM dr;
uint32_t i = 0, start, stop;
volatile int x;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.println();
// setup compile time random seed
dr.print(__FILE__);
dr.print(__DATE__);
dr.print(__TIME__);
}
void loop()
{
i++;
if (dr.available())
{
Serial.print("\t");
Serial.print(dr.read());
if ((i % 10) == 9 ) Serial.println();
}
delay(100);
}
// -- END OF FILE --

View File

@ -1,10 +1,8 @@
//
// FILE: DEVRANDOM_demo.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2020-06-23
// (c) : MIT
//
@ -22,68 +20,103 @@ void setup()
Serial.println(__FILE__);
Serial.println();
Serial.println("SOFTWARE:\t");
dr.useSW();
start = millis();
while (millis() - start < 1000)
{
x = dr.read();
i++;
}
Serial.print("nrs per second:");
Serial.println(i);
Serial.println(x);
Serial.println("Reseeding compile time");
start = micros();
dr.print(__FILE__);
dr.print(__DATE__);
dr.print(__TIME__);
dr.print(PI);
stop = micros();
Serial.print("reseeding: ");
Serial.println(stop - start);
Serial.println();
delay(1000);
Serial.println("HW PULSES:\t");
dr.useHW(4);
start = millis();
while (millis() - start < 1000)
{
x = dr.read();
i++;
}
Serial.print("nrs per second: ");
Serial.println(i);
Serial.println(x);
delay(1000);
Serial.println("ANALOG:\t");
dr.useAR(A0);
start = millis();
while (millis() - start < 1000)
{
x = dr.read();
i++;
}
Serial.print("nrs per second: ");
Serial.println(i);
Serial.println(x);
delay(1000);
dr.useSW();
Serial.println("Build in random");
dr.useRandom();
i = 0;
start = millis();
while (millis() - start < 1000)
{
x = dr.read();
i++;
}
Serial.print("nrs per second: ");
Serial.println(i);
Serial.println(x);
Serial.println();
delay(1000);
Serial.println("DigitalRead");
dr.useDigitalRead(4);
i = 0;
start = millis();
while (millis() - start < 1000)
{
x = dr.read();
i++;
}
Serial.print("nrs per second: ");
Serial.println(i);
Serial.println(x);
Serial.println();
delay(1000);
Serial.println("AnalogRead");
dr.useAnalogRead(A0);
i = 0;
start = millis();
while (millis() - start < 1000)
{
x = dr.read();
i++;
}
Serial.print("nrs per second: ");
Serial.println(i);
Serial.println(x);
Serial.println();
delay(1000);
Serial.println("MARSAGLIA");
dr.useMarsaglia();
i = 0;
start = millis();
while (millis() - start < 1000)
{
x = dr.read();
i++;
}
Serial.print("nrs per second: ");
Serial.println(i);
Serial.println(x);
Serial.println();
delay(1000);
uint32_t x;
fscanf((FILE*)&dr, "%lu", &x);
Serial.print("UINT32: ");
Serial.println(x, HEX);
uint16_t y;
fscanf((FILE*)&dr, "%u", &y);
Serial.print("UINT16: ");
Serial.println(y, HEX);
// float f;
// fscanf((FILE*)&dr, "%e", &f); // does not work on UNO.
// Serial.print("FLOAT: ");
// Serial.println(f, 4);
//
// char str[24];
// fscanf((FILE*)&dr, "%20s", str); // "works, but unusable garbage"
// Serial.print("STRING: ");
// Serial.println(str);
// float f;
// fscanf((FILE*)&dr, "%e", &f); // does not work on UNO.
// Serial.print("FLOAT: ");
// Serial.println(f, 4);
//
// char str[24];
// fscanf((FILE*)&dr, "%20s", str); // "works, but unusable garbage"
// Serial.print("STRING: ");
// Serial.println(str);
// reset i counter for loop()
Serial.println();
i = 0;
delay(1000);
}

View File

@ -0,0 +1,21 @@
...Arduino\libraries\DEVRANDOM\examples\DEVRANDOM_demo\DEVRANDOM_demo.ino
Build in random
nrs per second: 10211
0
DigitalRead
nrs per second: 31345
0
AnalogRead
nrs per second: 1106
0
MARSAGLIA
nrs per second: 53296
57
UINT32: D004D104
UINT16: CF04
124 7 188 97 60 33 242 214 29
4 56 129 142 60 61 166 50 213 78
14 60 251 237 162 77 59 178 119 79
216 25 161 54 245 42 250 202 63 167
137 65 38 81 8 247 150 207 60 215

View File

@ -15,10 +15,9 @@
#include "DEVRANDOM.h"
#define PASSWORD_SIZE 8
#define MAX_PASSWORD_SIZE 24
char pw[PASSWORD_SIZE + 1];
char pw[MAX_PASSWORD_SIZE + 1];
DEVRANDOM dr;
@ -37,9 +36,16 @@ void setup()
Serial.println(__FILE__);
Serial.println();
// dr.useDR(5);
// dr.useAR(A0);
dr.useSW(); // for proof of concept this is OK
// compile time randomization
// comment if you want same seed every time.
dr.print(__FILE__);
dr.print(__DATE__);
dr.print(__TIME__);
// dr.useDigitalRead(5);
// dr.useAnalogRead(A0);
// dr.useMarsaglia(); // faster than build in random (UNO).
dr.useRandom(); // for proof of concept this is OK
}
@ -48,7 +54,7 @@ void loop()
Serial.print('\t');
uint32_t start = micros();
int cnt = generatePassword();
int cnt = generatePassword(12);
uint32_t stop = micros();
mx = max(cnt, mx);
@ -63,20 +69,22 @@ void loop()
}
int generatePassword()
int generatePassword(int length)
{
int idx = 0;
bool b[4] = { false, false, false, false };
bool done = false;
int count = 0;
if (length > MAX_PASSWORD_SIZE) length = MAX_PASSWORD_SIZE;
while (! done)
{
count++;
idx = 0;
b[0] = b[1] = b[2] = b[3] = false;
while (idx < PASSWORD_SIZE)
while (idx < length)
{
uint8_t x = dr.read() % 4;
switch (x)

View File

@ -1,10 +1,8 @@
//
// FILE: DEVRANDOM_demo.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2020-06-23
// (c) : MIT
//
// USE WITH SERIAL PLOTTER
@ -14,7 +12,7 @@
DEVRANDOM dr;
volatile int x, y, z;
volatile int a, b, c, d;
void setup()
@ -23,24 +21,32 @@ void setup()
Serial.println(__FILE__);
Serial.println();
Serial.println("SOFTWARE\tDIGITAL\tANALOG");
Serial.println("SOFTWARE\tDIGITAL\tANALOG\tMARSAGLIA");
}
void loop()
{
dr.useSW();
x = dr.read();
dr.useHW(4);
x = dr.read();
dr.useAR(A0);
x = dr.read();
dr.useRandom();
a = dr.read();
a = dr.read();
dr.useDigitalRead(4);
b = dr.read();
b = dr.read();
dr.useAnalogRead(A0);
c = dr.read();
c = dr.read();
dr.useMarsaglia();
d = dr.read();
d = dr.read();
Serial.print(x);
Serial.print(a);
Serial.print("\t");
Serial.print(y);
Serial.print(b);
Serial.print("\t");
Serial.print(z);
Serial.print(c);
Serial.print("\t");
Serial.print(d);
Serial.println();
}

View File

@ -0,0 +1,57 @@
//
// FILE: DEVRANDOM_run_time_random_seed.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo compile time random seed
// DATE: 2020-06-23
// (c) : MIT
//
#include "DEVRANDOM.h"
DEVRANDOM dr;
uint32_t i = 0, start, stop;
volatile int x;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
// setup compile time random seed
// dr.print(__FILE__);
// dr.print(__DATE__);
// dr.print(__TIME__);
// setup run time random seed
Serial.println("send 8 chars");
for (int i = 0; i < 8; i++)
{
while (Serial.available() == 0);
dr.print(Serial.read(), HEX);
dr.print(micros() * (micros() << 7));
dr.read(); // flush intermediate results
}
// flush input
while (Serial.available()) Serial.read();
}
void loop()
{
i++;
if (dr.available())
{
Serial.print("\t");
Serial.print(dr.read());
if ((i % 10) == 0 ) Serial.println();
}
delay(100);
}
// -- END OF FILE --

View File

@ -6,9 +6,16 @@ DEVRANDOM KEYWORD1
# Methods and Functions (KEYWORD2)
useAR KEYWORD2
useHW KEYWORD2
useSW KEYWORD2
available KEYWORD2
peek KEYWORD2
read KEYWORD2
flush KEYWORD2
write KEYWORD2
useMarsaglia KEYWORD2
useAnalogRead KEYWORD2
useDigitalRead KEYWORD2
useRandom KEYWORD2
getMode KEYWORD2
@ -18,7 +25,8 @@ getMode KEYWORD2
# Constants (LITERAL1)
#DEVRANDOM_LIB_VERSION LITERAL1
DEVRANDOM_MODE_SW LITERAL1
DEVRANDOM_MODE_HW LITERAL1
DEVRANDOM_MODE_AR LITERAL1
DEVRANDOM_MODE_RANDOM LITERAL1
DEVRANDOM_MODE_DIGITALREAD LITERAL1
DEVRANDOM_MODE_ANALOGREAD LITERAL1
DEVRANDOM_MODE_MARSAGLIA LITERAL1

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/DEVRANDOM.git"
},
"version": "0.1.3",
"version": "0.2.0",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=DEVRANDOM
version=0.1.3
version=0.2.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library to wrap a random generator in a stream

View File

@ -40,50 +40,67 @@ unittest_teardown()
unittest(test_constants)
{
assertEqual(0, DEVRANDOM_MODE_SW);
assertEqual(1, DEVRANDOM_MODE_HW);
assertEqual(2, DEVRANDOM_MODE_AR);
assertEqual(0, DEVRANDOM_MODE_RANDOM);
assertEqual(1, DEVRANDOM_MODE_DIGITALREAD);
assertEqual(2, DEVRANDOM_MODE_ANALOGREAD);
assertEqual(3, DEVRANDOM_MODE_MARSAGLIA);
}
unittest(test_constructor)
{
DEVRANDOM dr;
assertEqual(DEVRANDOM_MODE_SW, dr.getMode());
dr.useHW(4);
assertEqual(DEVRANDOM_MODE_HW, dr.getMode());
dr.useAR(0);
assertEqual(DEVRANDOM_MODE_AR, dr.getMode());
dr.useSW();
assertEqual(DEVRANDOM_MODE_SW, dr.getMode());
assertEqual(DEVRANDOM_MODE_RANDOM, dr.getMode());
dr.useDigitalRead(4);
assertEqual(DEVRANDOM_MODE_DIGITALREAD, dr.getMode());
dr.useAnalogRead(0);
assertEqual(DEVRANDOM_MODE_ANALOGREAD, dr.getMode());
dr.useMarsaglia();
assertEqual(DEVRANDOM_MODE_MARSAGLIA, dr.getMode());
dr.useRandom();
assertEqual(DEVRANDOM_MODE_RANDOM, dr.getMode());
}
unittest(test_constructor_seed)
{
DEVRANDOM dr_str("hello world");
assertEqual(DEVRANDOM_MODE_SW, dr_str.getMode());
assertEqual(DEVRANDOM_MODE_RANDOM, dr_str.getMode());
DEVRANDOM dr_int((uint32_t)123456789);
assertEqual(DEVRANDOM_MODE_SW, dr_int.getMode());
assertEqual(DEVRANDOM_MODE_RANDOM, dr_int.getMode());
DEVRANDOM dr_float((float)PI);
assertEqual(DEVRANDOM_MODE_SW, dr_float.getMode());
assertEqual(DEVRANDOM_MODE_RANDOM, dr_float.getMode());
}
unittest(test_generator_mode)
unittest(test_read)
{
DEVRANDOM dr;
assertEqual(1, dr.available());
fprintf(stderr, "read() >= 0test\n");
for (int i = 0; i < 10; i++)
{
assertLessOrEqual(0, dr.read());
}
}
unittest(test_generator_mode_random)
{
DEVRANDOM dr;
assertEqual(1, dr.available());
fprintf(stderr, "peak == read test\n");
fprintf(stderr, "peek() == read() test\n");
for (int i = 0; i < 10; i++)
{
int n = dr.peek();
@ -92,6 +109,24 @@ unittest(test_generator_mode)
}
}
unittest(test_generator_mode_Marsaglia)
{
DEVRANDOM dr;
dr.useMarsaglia();
assertEqual(1, dr.available());
fprintf(stderr, "peek() == read() test\n");
for (int i = 0; i < 10; i++)
{
int n = dr.peek();
fprintf(stderr,"\t%d\t%d\n", i, n);
assertEqual(n, dr.read());
}
}
unittest_main()
// --------