1003ee160SMatthew G. Knepley #include <../src/sys/classes/random/randomimpl.h> 2003ee160SMatthew G. Knepley 3003ee160SMatthew G. Knepley #define RANDER48_SEED_0 (0x330e) 4003ee160SMatthew G. Knepley #define RANDER48_SEED_1 (0xabcd) 5003ee160SMatthew G. Knepley #define RANDER48_SEED_2 (0x1234) 6003ee160SMatthew G. Knepley #define RANDER48_MULT_0 (0xe66d) 7003ee160SMatthew G. Knepley #define RANDER48_MULT_1 (0xdeec) 8003ee160SMatthew G. Knepley #define RANDER48_MULT_2 (0x0005) 9003ee160SMatthew G. Knepley #define RANDER48_ADD (0x000b) 10003ee160SMatthew G. Knepley 11003ee160SMatthew G. Knepley unsigned short _rander48_seed[3] = { 12003ee160SMatthew G. Knepley RANDER48_SEED_0, 13003ee160SMatthew G. Knepley RANDER48_SEED_1, 14003ee160SMatthew G. Knepley RANDER48_SEED_2 15003ee160SMatthew G. Knepley }; 16003ee160SMatthew G. Knepley unsigned short _rander48_mult[3] = { 17003ee160SMatthew G. Knepley RANDER48_MULT_0, 18003ee160SMatthew G. Knepley RANDER48_MULT_1, 19003ee160SMatthew G. Knepley RANDER48_MULT_2 20003ee160SMatthew G. Knepley }; 21003ee160SMatthew G. Knepley unsigned short _rander48_add = RANDER48_ADD; 22003ee160SMatthew G. Knepley 23003ee160SMatthew G. Knepley void _dorander48(unsigned short xseed[3]) 24003ee160SMatthew G. Knepley { 25003ee160SMatthew G. Knepley unsigned long accu; 26003ee160SMatthew G. Knepley unsigned short temp[2]; 27003ee160SMatthew G. Knepley 28003ee160SMatthew G. Knepley accu = (unsigned long) _rander48_mult[0] * (unsigned long) xseed[0] + (unsigned long)_rander48_add; 29003ee160SMatthew G. Knepley temp[0] = (unsigned short) accu; /* lower 16 bits */ 30003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 31003ee160SMatthew G. Knepley accu += (unsigned long) _rander48_mult[0] * (unsigned long) xseed[1] + (unsigned long) _rander48_mult[1] * (unsigned long) xseed[0]; 32003ee160SMatthew G. Knepley temp[1] = (unsigned short)accu; /* middle 16 bits */ 33003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 34003ee160SMatthew G. Knepley accu += _rander48_mult[0] * xseed[2] + _rander48_mult[1] * xseed[1] + _rander48_mult[2] * xseed[0]; 35003ee160SMatthew G. Knepley xseed[0] = temp[0]; 36003ee160SMatthew G. Knepley xseed[1] = temp[1]; 37003ee160SMatthew G. Knepley xseed[2] = (unsigned short) accu; 38003ee160SMatthew G. Knepley } 39003ee160SMatthew G. Knepley 40003ee160SMatthew G. Knepley double erander48(unsigned short xseed[3]) 41003ee160SMatthew G. Knepley { 42003ee160SMatthew G. Knepley _dorander48(xseed); 43003ee160SMatthew G. Knepley return ldexp((double) xseed[0], -48) + ldexp((double) xseed[1], -32) + ldexp((double) xseed[2], -16); 44003ee160SMatthew G. Knepley } 45003ee160SMatthew G. Knepley 46003ee160SMatthew G. Knepley double drander48() { 47003ee160SMatthew G. Knepley return erander48(_rander48_seed); 48003ee160SMatthew G. Knepley } 49003ee160SMatthew G. Knepley 50003ee160SMatthew G. Knepley void srander48(long seed) { 51003ee160SMatthew G. Knepley _rander48_seed[0] = RANDER48_SEED_0; 52003ee160SMatthew G. Knepley _rander48_seed[1] = (unsigned short) seed; 53003ee160SMatthew G. Knepley _rander48_seed[2] = (unsigned short) (seed >> 16); 54003ee160SMatthew G. Knepley _rander48_mult[0] = RANDER48_MULT_0; 55003ee160SMatthew G. Knepley _rander48_mult[1] = RANDER48_MULT_1; 56003ee160SMatthew G. Knepley _rander48_mult[2] = RANDER48_MULT_2; 57003ee160SMatthew G. Knepley _rander48_add = RANDER48_ADD; 58003ee160SMatthew G. Knepley } 59003ee160SMatthew G. Knepley 60003ee160SMatthew G. Knepley #undef __FUNCT__ 61003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomSeed_Rander48" 62003ee160SMatthew G. Knepley PetscErrorCode PetscRandomSeed_Rander48(PetscRandom r) 63003ee160SMatthew G. Knepley { 64003ee160SMatthew G. Knepley PetscFunctionBegin; 65003ee160SMatthew G. Knepley srander48(r->seed); 66003ee160SMatthew G. Knepley PetscFunctionReturn(0); 67003ee160SMatthew G. Knepley } 68003ee160SMatthew G. Knepley 69003ee160SMatthew G. Knepley #undef __FUNCT__ 70003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValue_Rander48" 71003ee160SMatthew G. Knepley PetscErrorCode PetscRandomGetValue_Rander48(PetscRandom r, PetscScalar *val) 72003ee160SMatthew G. Knepley { 73003ee160SMatthew G. Knepley PetscFunctionBegin; 74003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 75003ee160SMatthew G. Knepley if (r->iset) { 769f0394f4SBarry Smith *val = PetscRealPart(r->low) + PetscImaginaryPart(r->low) * PETSC_i; 779f0394f4SBarry Smith if (PetscRealPart(r->width)) { 789f0394f4SBarry Smith *val += PetscRealPart(r->width)* drander48(); 799f0394f4SBarry Smith } 809f0394f4SBarry Smith if (PetscImaginaryPart(r->width)) { 819f0394f4SBarry Smith *val += PetscImaginaryPart(r->width)* drander48() * PETSC_i; 829f0394f4SBarry Smith } 83003ee160SMatthew G. Knepley } else { 849f0394f4SBarry Smith *val = drander48() + drander48()*PETSC_i; 85003ee160SMatthew G. Knepley } 86003ee160SMatthew G. Knepley #else 87003ee160SMatthew G. Knepley if (r->iset) *val = r->width * drander48() + r->low; 88003ee160SMatthew G. Knepley else *val = drander48(); 89003ee160SMatthew G. Knepley #endif 90003ee160SMatthew G. Knepley PetscFunctionReturn(0); 91003ee160SMatthew G. Knepley } 92003ee160SMatthew G. Knepley 93003ee160SMatthew G. Knepley #undef __FUNCT__ 94003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValueReal_Rander48" 95003ee160SMatthew G. Knepley PetscErrorCode PetscRandomGetValueReal_Rander48(PetscRandom r, PetscReal *val) 96003ee160SMatthew G. Knepley { 97003ee160SMatthew G. Knepley PetscFunctionBegin; 98003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 99003ee160SMatthew G. Knepley if (r->iset) *val = PetscRealPart(r->width)*drander48() + PetscRealPart(r->low); 100003ee160SMatthew G. Knepley else *val = drander48(); 101003ee160SMatthew G. Knepley #else 102003ee160SMatthew G. Knepley if (r->iset) *val = r->width * drander48() + r->low; 103003ee160SMatthew G. Knepley else *val = drander48(); 104003ee160SMatthew G. Knepley #endif 105003ee160SMatthew G. Knepley PetscFunctionReturn(0); 106003ee160SMatthew G. Knepley } 107003ee160SMatthew G. Knepley 108003ee160SMatthew G. Knepley static struct _PetscRandomOps PetscRandomOps_Values = { 109003ee160SMatthew G. Knepley /* 0 */ 110003ee160SMatthew G. Knepley PetscRandomSeed_Rander48, 111003ee160SMatthew G. Knepley PetscRandomGetValue_Rander48, 112003ee160SMatthew G. Knepley PetscRandomGetValueReal_Rander48, 113003ee160SMatthew G. Knepley 0, 114003ee160SMatthew G. Knepley /* 5 */ 115003ee160SMatthew G. Knepley 0 116003ee160SMatthew G. Knepley }; 117003ee160SMatthew G. Knepley 118003ee160SMatthew G. Knepley /*MC 119*b3bd51deSBarry Smith PETSCRANDER48 - simple portable reimplementation of basic Unix drand48() random number generator that should generate the 120*b3bd51deSBarry Smith exact same random numbers on any system. 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