#include <stdlib.h> #include <stdio.h> #include <math.h> #include "oracle.h" void oracle(double* data,long start,long n){ // I picked randomish seeds. It shouldn't matter much long seeds[] = {28470,31023,4437}; double w; int i; // Advance the seeds // Double the number of values to skip point since // each data point takes two random numbers. rand_look_ahead(start*2,seeds); // To approximate the long term behavior of a random walk, // assume that the start steps before we began // reached a distance of sqrt(start)/2 from the origin w = rand_advance(seeds); w *= sqrt(start)/2; for(i=0;i<n;++i){ data[2*i] = w; w += rand_advance(seeds)*2-1; } w = rand_advance(seeds); w *= sqrt(start)/2; for(i=0;i<n;++i){ data[2*i+1] = w; w += rand_advance(seeds)*2-1; } } // Based on // https://en.wikipedia.org/wiki/Wichmann%E2%80%93Hill void rand_look_ahead(long n,long* seeds){ const static long m[] = {30269,30307,30323}; const static long t[] = {171,172,170}; int i; for(i=0;i<3;++i){ seeds[i] *= pow_mod(t[i],n,m[i]); seeds[i] %= m[i]; } } double rand_advance(long* seeds){ const static long m[] = {30269,30307,30323}; const static long t[] = {171,172,170}; int i; double sum = 0; for(i=0;i<3;++i){ seeds[i] = seeds[i]*t[i] % m[i]; sum += (double)seeds[i] / m[i]; } double x = sum - (int)sum; return x; } long pow_mod(long b,long p,long m){ if(p == 0) return 1; long a; if(p%2 == 0){ a = pow_mod(b,p/2,m); return a*a % m; } a = pow_mod(b,p-1,m); return a*b % m; }