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 179371c9d4SSatish Balay static double _dorander48(PetscRandom_Rander48 *r48) { 18003ee160SMatthew G. Knepley unsigned long accu; 19003ee160SMatthew G. Knepley unsigned short temp[2]; 20003ee160SMatthew G. Knepley 21e4e5cec9SBarry Smith accu = (unsigned long)r48->mult[0] * (unsigned long)r48->seed[0] + (unsigned long)r48->add; 22003ee160SMatthew G. Knepley temp[0] = (unsigned short)accu; /* lower 16 bits */ 23003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 24e4e5cec9SBarry Smith accu += (unsigned long)r48->mult[0] * (unsigned long)r48->seed[1] + (unsigned long)r48->mult[1] * (unsigned long)r48->seed[0]; 25003ee160SMatthew G. Knepley temp[1] = (unsigned short)accu; /* middle 16 bits */ 26003ee160SMatthew G. Knepley accu >>= sizeof(unsigned short) * 8; 27e4e5cec9SBarry Smith accu += r48->mult[0] * r48->seed[2] + r48->mult[1] * r48->seed[1] + r48->mult[2] * r48->seed[0]; 28e4e5cec9SBarry Smith r48->seed[0] = temp[0]; 29e4e5cec9SBarry Smith r48->seed[1] = temp[1]; 30e4e5cec9SBarry Smith r48->seed[2] = (unsigned short)accu; 31e4e5cec9SBarry Smith return ldexp((double)r48->seed[0], -48) + ldexp((double)r48->seed[1], -32) + ldexp((double)r48->seed[2], -16); 32003ee160SMatthew G. Knepley } 33003ee160SMatthew G. Knepley 349371c9d4SSatish Balay static PetscErrorCode PetscRandomSeed_Rander48(PetscRandom r) { 35e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48 *)r->data; 36e4e5cec9SBarry Smith 37003ee160SMatthew G. Knepley PetscFunctionBegin; 38e4e5cec9SBarry Smith r48->seed[0] = RANDER48_SEED_0; 39e4e5cec9SBarry Smith r48->seed[1] = (unsigned short)r->seed; 40e4e5cec9SBarry Smith r48->seed[2] = (unsigned short)(r->seed >> 16); 41e4e5cec9SBarry Smith r48->mult[0] = RANDER48_MULT_0; 42e4e5cec9SBarry Smith r48->mult[1] = RANDER48_MULT_1; 43e4e5cec9SBarry Smith r48->mult[2] = RANDER48_MULT_2; 44e4e5cec9SBarry Smith r48->add = RANDER48_ADD; 45003ee160SMatthew G. Knepley PetscFunctionReturn(0); 46003ee160SMatthew G. Knepley } 47003ee160SMatthew G. Knepley 489371c9d4SSatish Balay static PetscErrorCode PetscRandomGetValue_Rander48(PetscRandom r, PetscScalar *val) { 49e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48 *)r->data; 50e4e5cec9SBarry Smith 51003ee160SMatthew G. Knepley PetscFunctionBegin; 52003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 53003ee160SMatthew G. Knepley if (r->iset) { 549f0394f4SBarry Smith *val = PetscRealPart(r->low) + PetscImaginaryPart(r->low) * PETSC_i; 55ad540459SPierre Jolivet if (PetscRealPart(r->width)) *val += PetscRealPart(r->width) * _dorander48(r48); 56ad540459SPierre Jolivet if (PetscImaginaryPart(r->width)) *val += PetscImaginaryPart(r->width) * _dorander48(r48) * PETSC_i; 57003ee160SMatthew G. Knepley } else { 58e4e5cec9SBarry Smith *val = _dorander48(r48) + _dorander48(r48) * PETSC_i; 59003ee160SMatthew G. Knepley } 60003ee160SMatthew G. Knepley #else 61e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 62e4e5cec9SBarry Smith else *val = _dorander48(r48); 63003ee160SMatthew G. Knepley #endif 64003ee160SMatthew G. Knepley PetscFunctionReturn(0); 65003ee160SMatthew G. Knepley } 66003ee160SMatthew G. Knepley 679371c9d4SSatish Balay static PetscErrorCode PetscRandomGetValueReal_Rander48(PetscRandom r, PetscReal *val) { 68e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48 *)r->data; 69e4e5cec9SBarry Smith 70003ee160SMatthew G. Knepley PetscFunctionBegin; 71003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 72e4e5cec9SBarry Smith if (r->iset) *val = PetscRealPart(r->width) * _dorander48(r48) + PetscRealPart(r->low); 73e4e5cec9SBarry Smith else *val = _dorander48(r48); 74003ee160SMatthew G. Knepley #else 75e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 76e4e5cec9SBarry Smith else *val = _dorander48(r48); 77003ee160SMatthew G. Knepley #endif 78003ee160SMatthew G. Knepley PetscFunctionReturn(0); 79003ee160SMatthew G. Knepley } 80003ee160SMatthew G. Knepley 819371c9d4SSatish Balay static PetscErrorCode PetscRandomDestroy_Rander48(PetscRandom r) { 82e4e5cec9SBarry Smith PetscFunctionBegin; 839566063dSJacob Faibussowitsch PetscCall(PetscFree(r->data)); 84e4e5cec9SBarry Smith PetscFunctionReturn(0); 85e4e5cec9SBarry Smith } 86e4e5cec9SBarry Smith 87003ee160SMatthew G. Knepley static struct _PetscRandomOps PetscRandomOps_Values = { 88267267bdSJacob Faibussowitsch PetscDesignatedInitializer(seed, PetscRandomSeed_Rander48), 89267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalue, PetscRandomGetValue_Rander48), 90267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluereal, PetscRandomGetValueReal_Rander48), 91267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalues, NULL), 92267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluesreal, NULL), 93267267bdSJacob Faibussowitsch PetscDesignatedInitializer(destroy, PetscRandomDestroy_Rander48), 94003ee160SMatthew G. Knepley }; 95003ee160SMatthew G. Knepley 96003ee160SMatthew G. Knepley /*MC 97b3bd51deSBarry Smith PETSCRANDER48 - simple portable reimplementation of basic Unix drand48() random number generator that should generate the 98b3bd51deSBarry Smith exact same random numbers on any system. 99003ee160SMatthew G. Knepley 100003ee160SMatthew G. Knepley Options Database Keys: 1011179163eSBarry Smith . -random_type <rand,rand48,rander48,sprng> - select the random number generator at runtime 102003ee160SMatthew G. Knepley 10395452b02SPatrick Sanan Notes: 104811af0c4SBarry Smith This is the default random number generate provided by `PetscRandomCreate()` if you do not set a particular implementation. 105e4e5cec9SBarry Smith 106811af0c4SBarry Smith Each `PetscRandom` object created with this type has its own seed and its own history, so multiple `PetscRandom` objects of this type 107e4e5cec9SBarry Smith will not interfer with random numbers generated by other objects. Each PETSc object of this type will produce the exact same set of 108811af0c4SBarry Smith random numbers so if you wish different `PetscRandom` objects of this type set different seeds for each one after you create them with 109811af0c4SBarry Smith `PetscRandomSetSeed()` followed by `PetscRandomSeed()`. 110e4e5cec9SBarry Smith 111003ee160SMatthew G. Knepley Level: beginner 112003ee160SMatthew G. Knepley 1131179163eSBarry Smith .seealso: `PetscRandomCreate()`, `PetscRandomSetType()`, `PETSCRAND`, `PETSCRAND48`, `PETSCRANDER48`, `PETSCSPRNG`, `PetscRandomSetSeed()`, 1141179163eSBarry Smith `PetscRandomSeed()`, `PetscRandomSetFromOptions()` 115003ee160SMatthew G. Knepley M*/ 116003ee160SMatthew G. Knepley 1179371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rander48(PetscRandom r) { 118e4e5cec9SBarry Smith PetscRandom_Rander48 *r48; 119003ee160SMatthew G. Knepley 120003ee160SMatthew G. Knepley PetscFunctionBegin; 121*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&r48)); 122e4e5cec9SBarry Smith /* r48 does not need to be initialized because PetscRandomSeed() is always called before use and sets the needed values */ 123e4e5cec9SBarry Smith r->data = r48; 1249566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(r->ops, &PetscRandomOps_Values, sizeof(PetscRandomOps_Values))); 1259566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)r, PETSCRANDER48)); 126003ee160SMatthew G. Knepley PetscFunctionReturn(0); 127003ee160SMatthew G. Knepley } 128