rnd32 -funktiosta tuli tosi hyvä. Läpäisee kaikki random-testit mennen tullen.
/**********************
* Jouni Aro 20.7.2020 *
**********************/
/******************************************************
* Ohessa kooditiedosto Xrandom.cpp, joka käyttää *
* alkulukuja. *
* *
* Sen main -funktio tutkii, kuinka pitkiä numero- *
* ketjuja rnd32 -funktio tuottaa. *
* *
* Koodi menee liian kryptiseksi, jos mukaan sekoittaa *
* neliöjuuri 2:n bitit. Koodi Xrandom.cpp toimii nyt *
* alkuluvuilla. *
******************************************************/
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <assert.h>
typedef unsigned short uint16;
typedef unsigned long uint32;
inline void setBit(char *a, int bitNro)
{
a[bitNro>>3]|=(char)(1<<(bitNro&7));
}
inline void clrBit(char *a, int bitNro)
{
a[bitNro>>3]&=(char)~(1<<(bitNro&7));
}
inline int testBit(char *a, int bitNro)
{
int v=(char)bitNro&7;
int e=(int)bitNro>>3;
return a[e]&(1<<v)? 1: 0;
}
int primeNumber(int x)
{
if (x<2) return (int)0;
else if (x==2) return 1;
else if (!(x%2)) return 0;
else
{
int end=(int)(sqrt((double)x)+2.0);
for (int y=3; y<end; y+=2)
if (!(x%y)) return 0;
return (int)0x01;
}
}
class Eratos
{
public:
Eratos(void);
~Eratos(void);
unsigned getN(void);
uint32 swap(uint32, uint32);
private:
char *E;
unsigned f;
uint16 *Memory;
unsigned N, BitSize;
void backward(void);
void MakePrimeNumbers(char*);
};
inline unsigned Eratos::getN(void)
{
return N;
}
inline uint32 Eratos::swap(uint32 a, uint32 b)
{
if (a>=N||b>=N) assert(0);
uint16 tmp = Memory[a];
Memory[a] = Memory[b];
Memory[b] = (uint16) tmp;
return uint32(Memory[a]^Memory[b]);
}
///////////////////////
#define SL 17 // shl //
///////////////////////
Eratos::Eratos(void)
{
memset(this,0,sizeof(Eratos));
E=new char[N=(0x0001<<SL)];
Memory=new uint16[1<<16];
BitSize=(0x01<<SL)<<3;
MakePrimeNumbers(E);
for (f=N=0; f<BitSize; f++)
if (testBit(E, f))
{
Memory[(int)N] = (uint16) f;
if ((++N) == (1<<16)) break;
}
if (N!=(1<<16))
assert((int)0);
else backward();
}
void Eratos::backward(void)
{
for (--N; N; N--)
if (primeNumber(N))
{
N+=1;
break;
}
}
Eratos::~Eratos(void)
{
delete[] Memory;
delete[] E;
}
void Eratos::MakePrimeNumbers(char *X)
{
memset(X, 0xff, sizeof(char)*N);
int end=(int)sqrt(double(BitSize))+2;
clrBit((char*)X, 0);
clrBit((char*)X, 1);
for (int x=2; x<=end; x++)
{
if (testBit((char*)X, x))
{
for (int y=x+x; y<(int)BitSize; y+=x)
clrBit((char*)X, y);
}
}
}
/////////////////////////////////////
unsigned rnd32(void) //
{ //
static Eratos *E=new Eratos; //
static unsigned long r1=1L; //
static unsigned long r2=2L; //
r1 -= 0x012357bfL; //
r2 += 0xfedca201L; //
unsigned a=E->getN(); //
unsigned b=E->getN(); //
r1 ^= E->swap(~r1%a, (~r2)%b); //
r2 ^= E->swap(r1%a, r2%b)<<16; //
r1 += (r1>>16)^(r2<<16); //
r2 -= (r1<<16)^(r2>>16); //
return r1^r2; //
} //
/////////////////////////////////////
/////////////////////////////////////
#define KPL 17 // Tällä parametril-//
// la voi säätää tutkittavan //
// numerosarjan pituutta. main- //
// funktio ottaa sitten selvää //
// sekvenssin jakaumasta. //
/////////////////////////////////////
int main(int argc, char** argv)
{
unsigned maxKpl[KPL];
unsigned ketjut[KPL];
memset(maxKpl, 0, sizeof(unsigned)*KPL);
memset(ketjut, 0, sizeof(unsigned)*KPL);
for (int n, ede=0, print=0;;)
{
n=rnd32()%KPL;
ketjut[n]+=1;
for (int i=0; i<KPL; i++)
{
if (ketjut[i]!=maxKpl[i])
{
if (ketjut[i]>maxKpl[i])
{
maxKpl[i]=ketjut[i];
print=1;
}
}
}
if (n!=ede && print==0)
{
ede=n;
memset(ketjut, 0, sizeof(unsigned)*KPL);
}
if (print)
{
print=0;
memset(ketjut, 0, sizeof(unsigned)*KPL);
printf("| ");
for (int i=0; i<KPL; i++)
printf("%u | ", maxKpl[i]);
printf("\n");
}
}
return 0;
}Aihe on jo aika vanha, joten et voi enää vastata siihen.