/* (c) 2022 cepstrum.co.jp */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define MATH_PI 3.14159265358979323846
#define MATH_E 2.7182818284590452354
#define CLK_TICK 16
//-----------------------------------------------------
// execute RDTSC instruction and return cycle counter value
inline unsigned long long rdtsc(void) {
unsigned long long result;
__asm__ volatile ("rdtsc" : "=A" (result));
return result;
}
//-----------------------------------------------------
// physical(?) random number generator
uint32_t physical_rand32bit(void) {
uint32_t y;
char s1[80], s2[80];
unsigned long long start_clk;
unsigned long long stop_clk;
unsigned rnd_bit;
unsigned i;
y=0;
for (i=0; i<32; i=i+1) {
start_clk=rdtsc();
sprintf(s1, "%70.40lf", (double)y*MATH_PI); // meaningless, waste time...
sprintf(s2, "%lf", atof(s1)*MATH_E); // meaningless, waste time...
sprintf(s1, "%lf", atof(s2)/MATH_PI); // meaningless, waste time...
sprintf(s2, "%s", s1); // meaningless, waste time...
stop_clk=rdtsc();
rnd_bit=((stop_clk-start_clk)/CLK_TICK)%2;
y=(y<<1)|rnd_bit;
//printf("%u %u %u\n", (unsigned)(stop_clk-start_clk)/CLK_TICK, (unsigned)stop_clk, (unsigned)start_clk);
}
return y;
}
//-----------------------------------------------------
// convert unsigned 32bit value to 16bit seed for RNG
// unsigned 32bit value : 0-4294967295
// seed 16bit value : 1-65535
// 4294967296=2^32
// 65535=2^16-1
uint16_t rand32bit2seed16bit(uint32_t x) {
return ((double)x/(double)4294967296UL)*(double)65535.0+1;
}
//-----------------------------------------------------
// test physical_rand32bit() and rand32bit2seed16bit()
int main() {
unsigned i;
unsigned rand32bit, seed16bit;
for (i=0; i<20; i=i+1) {
rand32bit=physical_rand32bit();
seed16bit=rand32bit2seed16bit(rand32bit);
printf("%#010x %5u\n", rand32bit, seed16bit);
}
for (i=0; i<100; i=i+1) {
rand32bit=physical_rand32bit();
seed16bit=rand32bit2seed16bit(rand32bit);
printf("%8u", seed16bit);
}
}