1*003ee160SMatthew G. Knepley #include <../src/sys/classes/random/randomimpl.h> 2*003ee160SMatthew G. Knepley 3*003ee160SMatthew G. Knepley /* This shit is even more random than drand48(). It is random enough to run on Windows. Fuck you Microsoft, and your utter failure to implement POSIX. */ 4*003ee160SMatthew G. Knepley #define RANDER48_SEED_0 (0x330e) 5*003ee160SMatthew G. Knepley #define RANDER48_SEED_1 (0xabcd) 6*003ee160SMatthew G. Knepley #define RANDER48_SEED_2 (0x1234) 7*003ee160SMatthew G. Knepley #define RANDER48_MULT_0 (0xe66d) 8*003ee160SMatthew G. Knepley #define RANDER48_MULT_1 (0xdeec) 9*003ee160SMatthew G. Knepley #define RANDER48_MULT_2 (0x0005) 10*003ee160SMatthew G. Knepley #define RANDER48_ADD (0x000b) 11*003ee160SMatthew G. Knepley 12*003ee160SMatthew G. Knepley unsigned short _rander48_seed[3] = { 13*003ee160SMatthew G. Knepley RANDER48_SEED_0, 14*003ee160SMatthew G. Knepley RANDER48_SEED_1, 15*003ee160SMatthew G. Knepley RANDER48_SEED_2 16*003ee160SMatthew G. Knepley }; 17*003ee160SMatthew G. Knepley unsigned short _rander48_mult[3] = { 18*003ee160SMatthew G. Knepley RANDER48_MULT_0, 19*003ee160SMatthew G. Knepley RANDER48_MULT_1, 20*003ee160SMatthew G. Knepley RANDER48_MULT_2 21*003ee160SMatthew G. Knepley }; 22*003ee160SMatthew G. Knepley unsigned short _rander48_add = RANDER48_ADD; 23*003ee160SMatthew G. Knepley 24*003ee160SMatthew G. Knepley void _dorander48(unsigned short xseed[3]) 25*003ee160SMatthew G. Knepley { 26*003ee160SMatthew G. Knepley unsigned long accu; 27*003ee160SMatthew G. Knepley unsigned short temp[2]; 28*003ee160SMatthew G. Knepley 29*003ee160SMatthew G. Knepley accu = (unsigned long) _rander48_mult[0] * (unsigned long) xseed[0] + (unsigned long)_rander48_add; 30*003ee160SMatthew G. Knepley temp[0] = (unsigned short) accu; /* lower 16 bits */ 31*003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 32*003ee160SMatthew G. Knepley accu += (unsigned long) _rander48_mult[0] * (unsigned long) xseed[1] + (unsigned long) _rander48_mult[1] * (unsigned long) xseed[0]; 33*003ee160SMatthew G. Knepley temp[1] = (unsigned short)accu; /* middle 16 bits */ 34*003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 35*003ee160SMatthew G. Knepley accu += _rander48_mult[0] * xseed[2] + _rander48_mult[1] * xseed[1] + _rander48_mult[2] * xseed[0]; 36*003ee160SMatthew G. Knepley xseed[0] = temp[0]; 37*003ee160SMatthew G. Knepley xseed[1] = temp[1]; 38*003ee160SMatthew G. Knepley xseed[2] = (unsigned short) accu; 39*003ee160SMatthew G. Knepley } 40*003ee160SMatthew G. Knepley 41*003ee160SMatthew G. Knepley double erander48(unsigned short xseed[3]) 42*003ee160SMatthew G. Knepley { 43*003ee160SMatthew G. Knepley _dorander48(xseed); 44*003ee160SMatthew G. Knepley return ldexp((double) xseed[0], -48) + ldexp((double) xseed[1], -32) + ldexp((double) xseed[2], -16); 45*003ee160SMatthew G. Knepley } 46*003ee160SMatthew G. Knepley 47*003ee160SMatthew G. Knepley double drander48() { 48*003ee160SMatthew G. Knepley return erander48(_rander48_seed); 49*003ee160SMatthew G. Knepley } 50*003ee160SMatthew G. Knepley 51*003ee160SMatthew G. Knepley void srander48(long seed) { 52*003ee160SMatthew G. Knepley _rander48_seed[0] = RANDER48_SEED_0; 53*003ee160SMatthew G. Knepley _rander48_seed[1] = (unsigned short) seed; 54*003ee160SMatthew G. Knepley _rander48_seed[2] = (unsigned short) (seed >> 16); 55*003ee160SMatthew G. Knepley _rander48_mult[0] = RANDER48_MULT_0; 56*003ee160SMatthew G. Knepley _rander48_mult[1] = RANDER48_MULT_1; 57*003ee160SMatthew G. Knepley _rander48_mult[2] = RANDER48_MULT_2; 58*003ee160SMatthew G. Knepley _rander48_add = RANDER48_ADD; 59*003ee160SMatthew G. Knepley } 60*003ee160SMatthew G. Knepley 61*003ee160SMatthew G. Knepley #undef __FUNCT__ 62*003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomSeed_Rander48" 63*003ee160SMatthew G. Knepley PetscErrorCode PetscRandomSeed_Rander48(PetscRandom r) 64*003ee160SMatthew G. Knepley { 65*003ee160SMatthew G. Knepley PetscFunctionBegin; 66*003ee160SMatthew G. Knepley srander48(r->seed); 67*003ee160SMatthew G. Knepley PetscFunctionReturn(0); 68*003ee160SMatthew G. Knepley } 69*003ee160SMatthew G. Knepley 70*003ee160SMatthew G. Knepley #undef __FUNCT__ 71*003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValue_Rander48" 72*003ee160SMatthew G. Knepley PetscErrorCode PetscRandomGetValue_Rander48(PetscRandom r, PetscScalar *val) 73*003ee160SMatthew G. Knepley { 74*003ee160SMatthew G. Knepley PetscFunctionBegin; 75*003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 76*003ee160SMatthew G. Knepley if (r->iset) { 77*003ee160SMatthew G. Knepley *val = PetscRealPart(r->width)*(PetscReal) drander48() + PetscRealPart(r->low) + (PetscImaginaryPart(r->width)*(PetscReal) drander48() + PetscImaginaryPart(r->low)) * PETSC_i; 78*003ee160SMatthew G. Knepley } else { 79*003ee160SMatthew G. Knepley *val = (PetscReal) drander48() + ((PetscReal) drander48())*PETSC_i; 80*003ee160SMatthew G. Knepley } 81*003ee160SMatthew G. Knepley #else 82*003ee160SMatthew G. Knepley if (r->iset) *val = r->width * drander48() + r->low; 83*003ee160SMatthew G. Knepley else *val = drander48(); 84*003ee160SMatthew G. Knepley #endif 85*003ee160SMatthew G. Knepley PetscFunctionReturn(0); 86*003ee160SMatthew G. Knepley } 87*003ee160SMatthew G. Knepley 88*003ee160SMatthew G. Knepley #undef __FUNCT__ 89*003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValueReal_Rander48" 90*003ee160SMatthew G. Knepley PetscErrorCode PetscRandomGetValueReal_Rander48(PetscRandom r, PetscReal *val) 91*003ee160SMatthew G. Knepley { 92*003ee160SMatthew G. Knepley PetscFunctionBegin; 93*003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 94*003ee160SMatthew G. Knepley if (r->iset) *val = PetscRealPart(r->width)*drander48() + PetscRealPart(r->low); 95*003ee160SMatthew G. Knepley else *val = drander48(); 96*003ee160SMatthew G. Knepley #else 97*003ee160SMatthew G. Knepley if (r->iset) *val = r->width * drander48() + r->low; 98*003ee160SMatthew G. Knepley else *val = drander48(); 99*003ee160SMatthew G. Knepley #endif 100*003ee160SMatthew G. Knepley PetscFunctionReturn(0); 101*003ee160SMatthew G. Knepley } 102*003ee160SMatthew G. Knepley 103*003ee160SMatthew G. Knepley static struct _PetscRandomOps PetscRandomOps_Values = { 104*003ee160SMatthew G. Knepley /* 0 */ 105*003ee160SMatthew G. Knepley PetscRandomSeed_Rander48, 106*003ee160SMatthew G. Knepley PetscRandomGetValue_Rander48, 107*003ee160SMatthew G. Knepley PetscRandomGetValueReal_Rander48, 108*003ee160SMatthew G. Knepley 0, 109*003ee160SMatthew G. Knepley /* 5 */ 110*003ee160SMatthew G. Knepley 0 111*003ee160SMatthew G. Knepley }; 112*003ee160SMatthew G. Knepley 113*003ee160SMatthew G. Knepley /*MC 114*003ee160SMatthew G. Knepley PETSCRANDER48 - simple reimplementation of basic Unix drand48() random number generator, because Microsoft 115*003ee160SMatthew G. Knepley 116*003ee160SMatthew G. Knepley Options Database Keys: 117*003ee160SMatthew G. Knepley . -random_type <rand,rand48,rander48,sprng> 118*003ee160SMatthew G. Knepley 119*003ee160SMatthew G. Knepley Level: beginner 120*003ee160SMatthew G. Knepley 121*003ee160SMatthew G. Knepley .seealso: RandomCreate(), RandomSetType(), PETSCRAND, PETSCRAND48, PETSCRANDER48, PETSCSPRNG 122*003ee160SMatthew G. Knepley M*/ 123*003ee160SMatthew G. Knepley 124*003ee160SMatthew G. Knepley #undef __FUNCT__ 125*003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomCreate_Rander48" 126*003ee160SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rander48(PetscRandom r) 127*003ee160SMatthew G. Knepley { 128*003ee160SMatthew G. Knepley PetscErrorCode ierr; 129*003ee160SMatthew G. Knepley 130*003ee160SMatthew G. Knepley PetscFunctionBegin; 131*003ee160SMatthew G. Knepley ierr = PetscMemcpy(r->ops, &PetscRandomOps_Values, sizeof(PetscRandomOps_Values));CHKERRQ(ierr); 132*003ee160SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) r, PETSCRANDER48);CHKERRQ(ierr); 133*003ee160SMatthew G. Knepley PetscFunctionReturn(0); 134*003ee160SMatthew G. Knepley } 135