1d6cc7855SJacob Faibussowitsch #include <petsc/private/randomimpl.h> 2003ee160SMatthew G. Knepley 3e4e5cec9SBarry Smith typedef struct { 4e4e5cec9SBarry Smith unsigned short seed[3]; 5e4e5cec9SBarry Smith unsigned short mult[3]; 6e4e5cec9SBarry Smith unsigned short add; 7e4e5cec9SBarry Smith } PetscRandom_Rander48; 8e4e5cec9SBarry 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 17e4e5cec9SBarry 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 22e4e5cec9SBarry 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; 25e4e5cec9SBarry 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; 28e4e5cec9SBarry Smith accu += r48->mult[0] * r48->seed[2] + r48->mult[1] * r48->seed[1] + r48->mult[2] * r48->seed[0]; 29e4e5cec9SBarry Smith r48->seed[0] = temp[0]; 30e4e5cec9SBarry Smith r48->seed[1] = temp[1]; 31e4e5cec9SBarry Smith r48->seed[2] = (unsigned short) accu; 32e4e5cec9SBarry 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 35e4e5cec9SBarry Smith static PetscErrorCode PetscRandomSeed_Rander48(PetscRandom r) 36003ee160SMatthew G. Knepley { 37e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48*)r->data; 38e4e5cec9SBarry Smith 39003ee160SMatthew G. Knepley PetscFunctionBegin; 40e4e5cec9SBarry Smith r48->seed[0] = RANDER48_SEED_0; 41e4e5cec9SBarry Smith r48->seed[1] = (unsigned short) r->seed; 42e4e5cec9SBarry Smith r48->seed[2] = (unsigned short) (r->seed >> 16); 43e4e5cec9SBarry Smith r48->mult[0] = RANDER48_MULT_0; 44e4e5cec9SBarry Smith r48->mult[1] = RANDER48_MULT_1; 45e4e5cec9SBarry Smith r48->mult[2] = RANDER48_MULT_2; 46e4e5cec9SBarry Smith r48->add = RANDER48_ADD; 47003ee160SMatthew G. Knepley PetscFunctionReturn(0); 48003ee160SMatthew G. Knepley } 49003ee160SMatthew G. Knepley 50e4e5cec9SBarry Smith static PetscErrorCode PetscRandomGetValue_Rander48(PetscRandom r, PetscScalar *val) 51003ee160SMatthew G. Knepley { 52e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48*)r->data; 53e4e5cec9SBarry Smith 54003ee160SMatthew G. Knepley PetscFunctionBegin; 55003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 56003ee160SMatthew G. Knepley if (r->iset) { 579f0394f4SBarry Smith *val = PetscRealPart(r->low) + PetscImaginaryPart(r->low) * PETSC_i; 589f0394f4SBarry Smith if (PetscRealPart(r->width)) { 59e4e5cec9SBarry Smith *val += PetscRealPart(r->width)* _dorander48(r48); 609f0394f4SBarry Smith } 619f0394f4SBarry Smith if (PetscImaginaryPart(r->width)) { 62e4e5cec9SBarry Smith *val += PetscImaginaryPart(r->width)* _dorander48(r48) * PETSC_i; 639f0394f4SBarry Smith } 64003ee160SMatthew G. Knepley } else { 65e4e5cec9SBarry Smith *val = _dorander48(r48) + _dorander48(r48)*PETSC_i; 66003ee160SMatthew G. Knepley } 67003ee160SMatthew G. Knepley #else 68e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 69e4e5cec9SBarry Smith else *val = _dorander48(r48); 70003ee160SMatthew G. Knepley #endif 71003ee160SMatthew G. Knepley PetscFunctionReturn(0); 72003ee160SMatthew G. Knepley } 73003ee160SMatthew G. Knepley 74e4e5cec9SBarry Smith static PetscErrorCode PetscRandomGetValueReal_Rander48(PetscRandom r, PetscReal *val) 75003ee160SMatthew G. Knepley { 76e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48*)r->data; 77e4e5cec9SBarry Smith 78003ee160SMatthew G. Knepley PetscFunctionBegin; 79003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 80e4e5cec9SBarry Smith if (r->iset) *val = PetscRealPart(r->width)*_dorander48(r48) + PetscRealPart(r->low); 81e4e5cec9SBarry Smith else *val = _dorander48(r48); 82003ee160SMatthew G. Knepley #else 83e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 84e4e5cec9SBarry Smith else *val = _dorander48(r48); 85003ee160SMatthew G. Knepley #endif 86003ee160SMatthew G. Knepley PetscFunctionReturn(0); 87003ee160SMatthew G. Knepley } 88003ee160SMatthew G. Knepley 89e4e5cec9SBarry Smith static PetscErrorCode PetscRandomDestroy_Rander48(PetscRandom r) 90e4e5cec9SBarry Smith { 91e4e5cec9SBarry Smith PetscErrorCode ierr; 92e4e5cec9SBarry Smith 93e4e5cec9SBarry Smith PetscFunctionBegin; 94e4e5cec9SBarry Smith ierr = PetscFree(r->data);CHKERRQ(ierr); 95e4e5cec9SBarry Smith PetscFunctionReturn(0); 96e4e5cec9SBarry Smith } 97e4e5cec9SBarry Smith 98003ee160SMatthew G. Knepley static struct _PetscRandomOps PetscRandomOps_Values = { 99*267267bdSJacob Faibussowitsch PetscDesignatedInitializer(seed,PetscRandomSeed_Rander48), 100*267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalue,PetscRandomGetValue_Rander48), 101*267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluereal,PetscRandomGetValueReal_Rander48), 102*267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalues,NULL), 103*267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluesreal,NULL), 104*267267bdSJacob Faibussowitsch PetscDesignatedInitializer(destroy,PetscRandomDestroy_Rander48), 105003ee160SMatthew G. Knepley }; 106003ee160SMatthew G. Knepley 107003ee160SMatthew G. Knepley /*MC 108b3bd51deSBarry Smith PETSCRANDER48 - simple portable reimplementation of basic Unix drand48() random number generator that should generate the 109b3bd51deSBarry Smith exact same random numbers on any system. 110003ee160SMatthew G. Knepley 111003ee160SMatthew G. Knepley Options Database Keys: 112003ee160SMatthew G. Knepley . -random_type <rand,rand48,rander48,sprng> 113003ee160SMatthew G. Knepley 11495452b02SPatrick Sanan Notes: 11595452b02SPatrick Sanan This is the default random number generate provided by PetscRandomCreate() if you do not set a particular implementation. 116e4e5cec9SBarry Smith 117e4e5cec9SBarry Smith Each PetscRandom object created with this type has its own seed and its own history, so multiple PetscRandom objects of this type 118e4e5cec9SBarry Smith will not interfer with random numbers generated by other objects. Each PETSc object of this type will produce the exact same set of 119e4e5cec9SBarry Smith random numbers so if you wish different PetscObjects of this type set different seeds for each one after you create them with 120e4e5cec9SBarry Smith PetscRandomSetSeed() followed by PetscRandomSeed(). 121e4e5cec9SBarry Smith 122003ee160SMatthew G. Knepley Level: beginner 123003ee160SMatthew G. Knepley 124808ba619SStefano Zampini .seealso: PetscRandomCreate(), PetscRandomSetType(), PETSCRAND, PETSCRAND48, PETSCRANDER48, PETSCSPRNG, PetscRandomSetSeed(), PetscRandomSeed() 125003ee160SMatthew G. Knepley M*/ 126003ee160SMatthew G. Knepley 127003ee160SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rander48(PetscRandom r) 128003ee160SMatthew G. Knepley { 129003ee160SMatthew G. Knepley PetscErrorCode ierr; 130e4e5cec9SBarry Smith PetscRandom_Rander48 *r48; 131003ee160SMatthew G. Knepley 132003ee160SMatthew G. Knepley PetscFunctionBegin; 133e4e5cec9SBarry Smith ierr = PetscNewLog(r,&r48);CHKERRQ(ierr); 134e4e5cec9SBarry Smith /* r48 does not need to be initialized because PetscRandomSeed() is always called before use and sets the needed values */ 135e4e5cec9SBarry Smith r->data = r48; 136003ee160SMatthew G. Knepley ierr = PetscMemcpy(r->ops, &PetscRandomOps_Values, sizeof(PetscRandomOps_Values));CHKERRQ(ierr); 137003ee160SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) r, PETSCRANDER48);CHKERRQ(ierr); 138003ee160SMatthew G. Knepley PetscFunctionReturn(0); 139003ee160SMatthew G. Knepley } 140