1003ee160SMatthew G. Knepley #include <../src/sys/classes/random/randomimpl.h> 2003ee160SMatthew G. Knepley 3003ee160SMatthew 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. */ 4003ee160SMatthew G. Knepley #define RANDER48_SEED_0 (0x330e) 5003ee160SMatthew G. Knepley #define RANDER48_SEED_1 (0xabcd) 6003ee160SMatthew G. Knepley #define RANDER48_SEED_2 (0x1234) 7003ee160SMatthew G. Knepley #define RANDER48_MULT_0 (0xe66d) 8003ee160SMatthew G. Knepley #define RANDER48_MULT_1 (0xdeec) 9003ee160SMatthew G. Knepley #define RANDER48_MULT_2 (0x0005) 10003ee160SMatthew G. Knepley #define RANDER48_ADD (0x000b) 11003ee160SMatthew G. Knepley 12003ee160SMatthew G. Knepley unsigned short _rander48_seed[3] = { 13003ee160SMatthew G. Knepley RANDER48_SEED_0, 14003ee160SMatthew G. Knepley RANDER48_SEED_1, 15003ee160SMatthew G. Knepley RANDER48_SEED_2 16003ee160SMatthew G. Knepley }; 17003ee160SMatthew G. Knepley unsigned short _rander48_mult[3] = { 18003ee160SMatthew G. Knepley RANDER48_MULT_0, 19003ee160SMatthew G. Knepley RANDER48_MULT_1, 20003ee160SMatthew G. Knepley RANDER48_MULT_2 21003ee160SMatthew G. Knepley }; 22003ee160SMatthew G. Knepley unsigned short _rander48_add = RANDER48_ADD; 23003ee160SMatthew G. Knepley 24003ee160SMatthew G. Knepley void _dorander48(unsigned short xseed[3]) 25003ee160SMatthew G. Knepley { 26003ee160SMatthew G. Knepley unsigned long accu; 27003ee160SMatthew G. Knepley unsigned short temp[2]; 28003ee160SMatthew G. Knepley 29003ee160SMatthew G. Knepley accu = (unsigned long) _rander48_mult[0] * (unsigned long) xseed[0] + (unsigned long)_rander48_add; 30003ee160SMatthew G. Knepley temp[0] = (unsigned short) accu; /* lower 16 bits */ 31003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 32003ee160SMatthew G. Knepley accu += (unsigned long) _rander48_mult[0] * (unsigned long) xseed[1] + (unsigned long) _rander48_mult[1] * (unsigned long) xseed[0]; 33003ee160SMatthew G. Knepley temp[1] = (unsigned short)accu; /* middle 16 bits */ 34003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 35003ee160SMatthew G. Knepley accu += _rander48_mult[0] * xseed[2] + _rander48_mult[1] * xseed[1] + _rander48_mult[2] * xseed[0]; 36003ee160SMatthew G. Knepley xseed[0] = temp[0]; 37003ee160SMatthew G. Knepley xseed[1] = temp[1]; 38003ee160SMatthew G. Knepley xseed[2] = (unsigned short) accu; 39003ee160SMatthew G. Knepley } 40003ee160SMatthew G. Knepley 41003ee160SMatthew G. Knepley double erander48(unsigned short xseed[3]) 42003ee160SMatthew G. Knepley { 43003ee160SMatthew G. Knepley _dorander48(xseed); 44003ee160SMatthew G. Knepley return ldexp((double) xseed[0], -48) + ldexp((double) xseed[1], -32) + ldexp((double) xseed[2], -16); 45003ee160SMatthew G. Knepley } 46003ee160SMatthew G. Knepley 47003ee160SMatthew G. Knepley double drander48() { 48003ee160SMatthew G. Knepley return erander48(_rander48_seed); 49003ee160SMatthew G. Knepley } 50003ee160SMatthew G. Knepley 51003ee160SMatthew G. Knepley void srander48(long seed) { 52003ee160SMatthew G. Knepley _rander48_seed[0] = RANDER48_SEED_0; 53003ee160SMatthew G. Knepley _rander48_seed[1] = (unsigned short) seed; 54003ee160SMatthew G. Knepley _rander48_seed[2] = (unsigned short) (seed >> 16); 55003ee160SMatthew G. Knepley _rander48_mult[0] = RANDER48_MULT_0; 56003ee160SMatthew G. Knepley _rander48_mult[1] = RANDER48_MULT_1; 57003ee160SMatthew G. Knepley _rander48_mult[2] = RANDER48_MULT_2; 58003ee160SMatthew G. Knepley _rander48_add = RANDER48_ADD; 59003ee160SMatthew G. Knepley } 60003ee160SMatthew G. Knepley 61003ee160SMatthew G. Knepley #undef __FUNCT__ 62003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomSeed_Rander48" 63003ee160SMatthew G. Knepley PetscErrorCode PetscRandomSeed_Rander48(PetscRandom r) 64003ee160SMatthew G. Knepley { 65003ee160SMatthew G. Knepley PetscFunctionBegin; 66003ee160SMatthew G. Knepley srander48(r->seed); 67003ee160SMatthew G. Knepley PetscFunctionReturn(0); 68003ee160SMatthew G. Knepley } 69003ee160SMatthew G. Knepley 70003ee160SMatthew G. Knepley #undef __FUNCT__ 71003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValue_Rander48" 72003ee160SMatthew G. Knepley PetscErrorCode PetscRandomGetValue_Rander48(PetscRandom r, PetscScalar *val) 73003ee160SMatthew G. Knepley { 74003ee160SMatthew G. Knepley PetscFunctionBegin; 75003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 76003ee160SMatthew G. Knepley if (r->iset) { 77*9f0394f4SBarry Smith *val = PetscRealPart(r->low) + PetscImaginaryPart(r->low) * PETSC_i; 78*9f0394f4SBarry Smith if (PetscRealPart(r->width)) { 79*9f0394f4SBarry Smith *val += PetscRealPart(r->width)* drander48(); 80*9f0394f4SBarry Smith } 81*9f0394f4SBarry Smith if (PetscImaginaryPart(r->width)) { 82*9f0394f4SBarry Smith *val += PetscImaginaryPart(r->width)* drander48() * PETSC_i; 83*9f0394f4SBarry Smith } 84003ee160SMatthew G. Knepley } else { 85*9f0394f4SBarry Smith *val = drander48() + drander48()*PETSC_i; 86003ee160SMatthew G. Knepley } 87003ee160SMatthew G. Knepley #else 88003ee160SMatthew G. Knepley if (r->iset) *val = r->width * drander48() + r->low; 89003ee160SMatthew G. Knepley else *val = drander48(); 90003ee160SMatthew G. Knepley #endif 91003ee160SMatthew G. Knepley PetscFunctionReturn(0); 92003ee160SMatthew G. Knepley } 93003ee160SMatthew G. Knepley 94003ee160SMatthew G. Knepley #undef __FUNCT__ 95003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValueReal_Rander48" 96003ee160SMatthew G. Knepley PetscErrorCode PetscRandomGetValueReal_Rander48(PetscRandom r, PetscReal *val) 97003ee160SMatthew G. Knepley { 98003ee160SMatthew G. Knepley PetscFunctionBegin; 99003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 100003ee160SMatthew G. Knepley if (r->iset) *val = PetscRealPart(r->width)*drander48() + PetscRealPart(r->low); 101003ee160SMatthew G. Knepley else *val = drander48(); 102003ee160SMatthew G. Knepley #else 103003ee160SMatthew G. Knepley if (r->iset) *val = r->width * drander48() + r->low; 104003ee160SMatthew G. Knepley else *val = drander48(); 105003ee160SMatthew G. Knepley #endif 106003ee160SMatthew G. Knepley PetscFunctionReturn(0); 107003ee160SMatthew G. Knepley } 108003ee160SMatthew G. Knepley 109003ee160SMatthew G. Knepley static struct _PetscRandomOps PetscRandomOps_Values = { 110003ee160SMatthew G. Knepley /* 0 */ 111003ee160SMatthew G. Knepley PetscRandomSeed_Rander48, 112003ee160SMatthew G. Knepley PetscRandomGetValue_Rander48, 113003ee160SMatthew G. Knepley PetscRandomGetValueReal_Rander48, 114003ee160SMatthew G. Knepley 0, 115003ee160SMatthew G. Knepley /* 5 */ 116003ee160SMatthew G. Knepley 0 117003ee160SMatthew G. Knepley }; 118003ee160SMatthew G. Knepley 119003ee160SMatthew G. Knepley /*MC 120003ee160SMatthew G. Knepley PETSCRANDER48 - simple reimplementation of basic Unix drand48() random number generator, because Microsoft 121003ee160SMatthew G. Knepley 122003ee160SMatthew G. Knepley Options Database Keys: 123003ee160SMatthew G. Knepley . -random_type <rand,rand48,rander48,sprng> 124003ee160SMatthew G. Knepley 125003ee160SMatthew G. Knepley Level: beginner 126003ee160SMatthew G. Knepley 127003ee160SMatthew G. Knepley .seealso: RandomCreate(), RandomSetType(), PETSCRAND, PETSCRAND48, PETSCRANDER48, PETSCSPRNG 128003ee160SMatthew G. Knepley M*/ 129003ee160SMatthew G. Knepley 130003ee160SMatthew G. Knepley #undef __FUNCT__ 131003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomCreate_Rander48" 132003ee160SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rander48(PetscRandom r) 133003ee160SMatthew G. Knepley { 134003ee160SMatthew G. Knepley PetscErrorCode ierr; 135003ee160SMatthew G. Knepley 136003ee160SMatthew G. Knepley PetscFunctionBegin; 137003ee160SMatthew G. Knepley ierr = PetscMemcpy(r->ops, &PetscRandomOps_Values, sizeof(PetscRandomOps_Values));CHKERRQ(ierr); 138003ee160SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) r, PETSCRANDER48);CHKERRQ(ierr); 139003ee160SMatthew G. Knepley PetscFunctionReturn(0); 140003ee160SMatthew G. Knepley } 141