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 17d71ae5a4SJacob Faibussowitsch static double _dorander48(PetscRandom_Rander48 *r48) 18d71ae5a4SJacob Faibussowitsch { 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 35d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscRandomSeed_Rander48(PetscRandom r) 36d71ae5a4SJacob Faibussowitsch { 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 50d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscRandomGetValue_Rander48(PetscRandom r, PetscScalar *val) 51d71ae5a4SJacob Faibussowitsch { 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; 58ad540459SPierre Jolivet if (PetscRealPart(r->width)) *val += PetscRealPart(r->width) * _dorander48(r48); 59ad540459SPierre Jolivet if (PetscImaginaryPart(r->width)) *val += PetscImaginaryPart(r->width) * _dorander48(r48) * PETSC_i; 60003ee160SMatthew G. Knepley } else { 61e4e5cec9SBarry Smith *val = _dorander48(r48) + _dorander48(r48) * PETSC_i; 62003ee160SMatthew G. Knepley } 63003ee160SMatthew G. Knepley #else 64e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 65e4e5cec9SBarry Smith else *val = _dorander48(r48); 66003ee160SMatthew G. Knepley #endif 67003ee160SMatthew G. Knepley PetscFunctionReturn(0); 68003ee160SMatthew G. Knepley } 69003ee160SMatthew G. Knepley 70d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscRandomGetValueReal_Rander48(PetscRandom r, PetscReal *val) 71d71ae5a4SJacob Faibussowitsch { 72e4e5cec9SBarry Smith PetscRandom_Rander48 *r48 = (PetscRandom_Rander48 *)r->data; 73e4e5cec9SBarry Smith 74003ee160SMatthew G. Knepley PetscFunctionBegin; 75003ee160SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX) 76e4e5cec9SBarry Smith if (r->iset) *val = PetscRealPart(r->width) * _dorander48(r48) + PetscRealPart(r->low); 77e4e5cec9SBarry Smith else *val = _dorander48(r48); 78003ee160SMatthew G. Knepley #else 79e4e5cec9SBarry Smith if (r->iset) *val = r->width * _dorander48(r48) + r->low; 80e4e5cec9SBarry Smith else *val = _dorander48(r48); 81003ee160SMatthew G. Knepley #endif 82003ee160SMatthew G. Knepley PetscFunctionReturn(0); 83003ee160SMatthew G. Knepley } 84003ee160SMatthew G. Knepley 85d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscRandomDestroy_Rander48(PetscRandom r) 86d71ae5a4SJacob Faibussowitsch { 87e4e5cec9SBarry Smith PetscFunctionBegin; 889566063dSJacob Faibussowitsch PetscCall(PetscFree(r->data)); 89e4e5cec9SBarry Smith PetscFunctionReturn(0); 90e4e5cec9SBarry Smith } 91e4e5cec9SBarry Smith 92003ee160SMatthew G. Knepley static struct _PetscRandomOps PetscRandomOps_Values = { 93267267bdSJacob Faibussowitsch PetscDesignatedInitializer(seed, PetscRandomSeed_Rander48), 94267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalue, PetscRandomGetValue_Rander48), 95267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluereal, PetscRandomGetValueReal_Rander48), 96267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalues, NULL), 97267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluesreal, NULL), 98267267bdSJacob Faibussowitsch PetscDesignatedInitializer(destroy, PetscRandomDestroy_Rander48), 99003ee160SMatthew G. Knepley }; 100003ee160SMatthew G. Knepley 101003ee160SMatthew G. Knepley /*MC 102b3bd51deSBarry Smith PETSCRANDER48 - simple portable reimplementation of basic Unix drand48() random number generator that should generate the 103b3bd51deSBarry Smith exact same random numbers on any system. 104003ee160SMatthew G. Knepley 105003ee160SMatthew G. Knepley Options Database Keys: 1061179163eSBarry Smith . -random_type <rand,rand48,rander48,sprng> - select the random number generator at runtime 107003ee160SMatthew G. Knepley 10895452b02SPatrick Sanan Notes: 109811af0c4SBarry Smith This is the default random number generate provided by `PetscRandomCreate()` if you do not set a particular implementation. 110e4e5cec9SBarry Smith 111811af0c4SBarry Smith Each `PetscRandom` object created with this type has its own seed and its own history, so multiple `PetscRandom` objects of this type 112*d5b43468SJose E. Roman will not interfere with random numbers generated by other objects. Each PETSc object of this type will produce the exact same set of 113811af0c4SBarry Smith random numbers so if you wish different `PetscRandom` objects of this type set different seeds for each one after you create them with 114811af0c4SBarry Smith `PetscRandomSetSeed()` followed by `PetscRandomSeed()`. 115e4e5cec9SBarry Smith 116003ee160SMatthew G. Knepley Level: beginner 117003ee160SMatthew G. Knepley 1181179163eSBarry Smith .seealso: `PetscRandomCreate()`, `PetscRandomSetType()`, `PETSCRAND`, `PETSCRAND48`, `PETSCRANDER48`, `PETSCSPRNG`, `PetscRandomSetSeed()`, 1191179163eSBarry Smith `PetscRandomSeed()`, `PetscRandomSetFromOptions()` 120003ee160SMatthew G. Knepley M*/ 121003ee160SMatthew G. Knepley 122d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscRandomCreate_Rander48(PetscRandom r) 123d71ae5a4SJacob Faibussowitsch { 124e4e5cec9SBarry Smith PetscRandom_Rander48 *r48; 125003ee160SMatthew G. Knepley 126003ee160SMatthew G. Knepley PetscFunctionBegin; 1274dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&r48)); 128e4e5cec9SBarry Smith /* r48 does not need to be initialized because PetscRandomSeed() is always called before use and sets the needed values */ 129e4e5cec9SBarry Smith r->data = r48; 1309566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(r->ops, &PetscRandomOps_Values, sizeof(PetscRandomOps_Values))); 1319566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)r, PETSCRANDER48)); 132003ee160SMatthew G. Knepley PetscFunctionReturn(0); 133003ee160SMatthew G. Knepley } 134