1003ee160SMatthew G. Knepley #include <../src/sys/classes/random/randomimpl.h> 2003ee160SMatthew G. Knepley 3*e4e5cec9SBarry Smith typedef struct { 4*e4e5cec9SBarry Smith unsigned short seed[3]; 5*e4e5cec9SBarry Smith unsigned short mult[3]; 6*e4e5cec9SBarry Smith unsigned short add; 7*e4e5cec9SBarry Smith } PetscRandom_Rander48; 8*e4e5cec9SBarry Smith 9003ee160SMatthew G. Knepley #define RANDER48_SEED_0 (0x330e) 10003ee160SMatthew G. Knepley #define RANDER48_SEED_1 (0xabcd) 11003ee160SMatthew G. Knepley #define RANDER48_SEED_2 (0x1234) 12003ee160SMatthew G. Knepley #define RANDER48_MULT_0 (0xe66d) 13003ee160SMatthew G. Knepley #define RANDER48_MULT_1 (0xdeec) 14003ee160SMatthew G. Knepley #define RANDER48_MULT_2 (0x0005) 15003ee160SMatthew G. Knepley #define RANDER48_ADD (0x000b) 16003ee160SMatthew G. Knepley 17*e4e5cec9SBarry Smith static double _dorander48(PetscRandom_Rander48 *r48) 18003ee160SMatthew G. Knepley { 19003ee160SMatthew G. Knepley unsigned long accu; 20003ee160SMatthew G. Knepley unsigned short temp[2]; 21003ee160SMatthew G. Knepley 22*e4e5cec9SBarry Smith accu = (unsigned long) r48->mult[0] * (unsigned long) r48->seed[0] + (unsigned long)r48->add; 23003ee160SMatthew G. Knepley temp[0] = (unsigned short) accu; /* lower 16 bits */ 24003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 25*e4e5cec9SBarry Smith accu += (unsigned long) r48->mult[0] * (unsigned long) r48->seed[1] + (unsigned long) r48->mult[1] * (unsigned long) r48->seed[0]; 26003ee160SMatthew G. Knepley temp[1] = (unsigned short)accu; /* middle 16 bits */ 27003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 28*e4e5cec9SBarry Smith accu += r48->mult[0] * r48->seed[2] + r48->mult[1] * r48->seed[1] + r48->mult[2] * r48->seed[0]; 29*e4e5cec9SBarry Smith r48->seed[0] = temp[0]; 30*e4e5cec9SBarry Smith r48->seed[1] = temp[1]; 31*e4e5cec9SBarry Smith r48->seed[2] = (unsigned short) accu; 32*e4e5cec9SBarry Smith return ldexp((double) r48->seed[0], -48) + ldexp((double) r48->seed[1], -32) + ldexp((double) r48->seed[2], -16); 33003ee160SMatthew G. Knepley } 34003ee160SMatthew G. Knepley 35003ee160SMatthew G. Knepley #undef __FUNCT__ 36003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomSeed_Rander48" 37*e4e5cec9SBarry Smith static PetscErrorCode PetscRandomSeed_Rander48(PetscRandom r) 38003ee160SMatthew G. Knepley { 39*e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48*)r->data; 40*e4e5cec9SBarry Smith 41003ee160SMatthew G. Knepley PetscFunctionBegin; 42*e4e5cec9SBarry Smith r48->seed[0] = RANDER48_SEED_0; 43*e4e5cec9SBarry Smith r48->seed[1] = (unsigned short) r->seed; 44*e4e5cec9SBarry Smith r48->seed[2] = (unsigned short) (r->seed >> 16); 45*e4e5cec9SBarry Smith r48->mult[0] = RANDER48_MULT_0; 46*e4e5cec9SBarry Smith r48->mult[1] = RANDER48_MULT_1; 47*e4e5cec9SBarry Smith r48->mult[2] = RANDER48_MULT_2; 48*e4e5cec9SBarry Smith r48->add = RANDER48_ADD; 49003ee160SMatthew G. Knepley PetscFunctionReturn(0); 50003ee160SMatthew G. Knepley } 51003ee160SMatthew G. Knepley 52003ee160SMatthew G. Knepley #undef __FUNCT__ 53003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValue_Rander48" 54*e4e5cec9SBarry Smith static PetscErrorCode PetscRandomGetValue_Rander48(PetscRandom r, PetscScalar *val) 55003ee160SMatthew G. Knepley { 56*e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48*)r->data; 57*e4e5cec9SBarry Smith 58003ee160SMatthew G. Knepley PetscFunctionBegin; 59003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 60003ee160SMatthew G. Knepley if (r->iset) { 619f0394f4SBarry Smith *val = PetscRealPart(r->low) + PetscImaginaryPart(r->low) * PETSC_i; 629f0394f4SBarry Smith if (PetscRealPart(r->width)) { 63*e4e5cec9SBarry Smith *val += PetscRealPart(r->width)* _dorander48(r48); 649f0394f4SBarry Smith } 659f0394f4SBarry Smith if (PetscImaginaryPart(r->width)) { 66*e4e5cec9SBarry Smith *val += PetscImaginaryPart(r->width)* _dorander48(r48) * PETSC_i; 679f0394f4SBarry Smith } 68003ee160SMatthew G. Knepley } else { 69*e4e5cec9SBarry Smith *val = _dorander48(r48) + _dorander48(r48)*PETSC_i; 70003ee160SMatthew G. Knepley } 71003ee160SMatthew G. Knepley #else 72*e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 73*e4e5cec9SBarry Smith else *val = _dorander48(r48); 74003ee160SMatthew G. Knepley #endif 75003ee160SMatthew G. Knepley PetscFunctionReturn(0); 76003ee160SMatthew G. Knepley } 77003ee160SMatthew G. Knepley 78003ee160SMatthew G. Knepley #undef __FUNCT__ 79003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomGetValueReal_Rander48" 80*e4e5cec9SBarry Smith static PetscErrorCode PetscRandomGetValueReal_Rander48(PetscRandom r, PetscReal *val) 81003ee160SMatthew G. Knepley { 82*e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48*)r->data; 83*e4e5cec9SBarry Smith 84003ee160SMatthew G. Knepley PetscFunctionBegin; 85003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 86*e4e5cec9SBarry Smith if (r->iset) *val = PetscRealPart(r->width)*_dorander48(r48) + PetscRealPart(r->low); 87*e4e5cec9SBarry Smith else *val = _dorander48(r48); 88003ee160SMatthew G. Knepley #else 89*e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 90*e4e5cec9SBarry Smith else *val = _dorander48(r48); 91003ee160SMatthew G. Knepley #endif 92003ee160SMatthew G. Knepley PetscFunctionReturn(0); 93003ee160SMatthew G. Knepley } 94003ee160SMatthew G. Knepley 95*e4e5cec9SBarry Smith #undef __FUNCT__ 96*e4e5cec9SBarry Smith #define __FUNCT__ "PetscRandomDestroy_Rander48" 97*e4e5cec9SBarry Smith static PetscErrorCode PetscRandomDestroy_Rander48(PetscRandom r) 98*e4e5cec9SBarry Smith { 99*e4e5cec9SBarry Smith PetscErrorCode ierr; 100*e4e5cec9SBarry Smith 101*e4e5cec9SBarry Smith PetscFunctionBegin; 102*e4e5cec9SBarry Smith ierr = PetscFree(r->data);CHKERRQ(ierr); 103*e4e5cec9SBarry Smith PetscFunctionReturn(0); 104*e4e5cec9SBarry Smith } 105*e4e5cec9SBarry Smith 106003ee160SMatthew G. Knepley static struct _PetscRandomOps PetscRandomOps_Values = { 107003ee160SMatthew G. Knepley /* 0 */ 108003ee160SMatthew G. Knepley PetscRandomSeed_Rander48, 109003ee160SMatthew G. Knepley PetscRandomGetValue_Rander48, 110003ee160SMatthew G. Knepley PetscRandomGetValueReal_Rander48, 111*e4e5cec9SBarry Smith PetscRandomDestroy_Rander48, 112003ee160SMatthew G. Knepley /* 5 */ 113003ee160SMatthew G. Knepley 0 114003ee160SMatthew G. Knepley }; 115003ee160SMatthew G. Knepley 116003ee160SMatthew G. Knepley /*MC 117b3bd51deSBarry Smith PETSCRANDER48 - simple portable reimplementation of basic Unix drand48() random number generator that should generate the 118b3bd51deSBarry Smith exact same random numbers on any system. 119003ee160SMatthew G. Knepley 120003ee160SMatthew G. Knepley Options Database Keys: 121003ee160SMatthew G. Knepley . -random_type <rand,rand48,rander48,sprng> 122003ee160SMatthew G. Knepley 123*e4e5cec9SBarry Smith Notes: This is the default random number generate provided by PetscRandomCreate() if you do not set a particular implementation. 124*e4e5cec9SBarry Smith 125*e4e5cec9SBarry Smith Each PetscRandom object created with this type has its own seed and its own history, so multiple PetscRandom objects of this type 126*e4e5cec9SBarry Smith will not interfer with random numbers generated by other objects. Each PETSc object of this type will produce the exact same set of 127*e4e5cec9SBarry Smith random numbers so if you wish different PetscObjects of this type set different seeds for each one after you create them with 128*e4e5cec9SBarry Smith PetscRandomSetSeed() followed by PetscRandomSeed(). 129*e4e5cec9SBarry Smith 130003ee160SMatthew G. Knepley Level: beginner 131003ee160SMatthew G. Knepley 132*e4e5cec9SBarry Smith .seealso: RandomCreate(), RandomSetType(), PETSCRAND, PETSCRAND48, PETSCRANDER48, PETSCSPRNG, PetscRandomSetSeed(), PetscRandomSeed() 133003ee160SMatthew G. Knepley M*/ 134003ee160SMatthew G. Knepley 135003ee160SMatthew G. Knepley #undef __FUNCT__ 136003ee160SMatthew G. Knepley #define __FUNCT__ "PetscRandomCreate_Rander48" 137003ee160SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rander48(PetscRandom r) 138003ee160SMatthew G. Knepley { 139003ee160SMatthew G. Knepley PetscErrorCode ierr; 140*e4e5cec9SBarry Smith PetscRandom_Rander48 *r48; 141003ee160SMatthew G. Knepley 142003ee160SMatthew G. Knepley PetscFunctionBegin; 143*e4e5cec9SBarry Smith ierr = PetscNewLog(r,&r48);CHKERRQ(ierr); 144*e4e5cec9SBarry Smith /* r48 does not need to be initialized because PetscRandomSeed() is always called before use and sets the needed values */ 145*e4e5cec9SBarry Smith r->data = r48; 146003ee160SMatthew G. Knepley ierr = PetscMemcpy(r->ops, &PetscRandomOps_Values, sizeof(PetscRandomOps_Values));CHKERRQ(ierr); 147003ee160SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) r, PETSCRANDER48);CHKERRQ(ierr); 148003ee160SMatthew G. Knepley PetscFunctionReturn(0); 149003ee160SMatthew G. Knepley } 150