IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 10, 2009, 4:53:42 PM (17 years ago)
Author:
Paul Price
Message:

Changing API for psRandomAlloc() to make it easier to be deterministic. psRandomAlloc() now takes only a single argument, which is the generator type (only PS_RANDOM_TAUS is currently supported; others could easily be added). The seed used by the generator is set by psRandomSeed(). This allows us to use the same seed for the random number generator over multiple calls, which means that we can be deterministic by setting the seed. The old API for psRandomAlloc() is available using psRandomAllocSpecific(). Added to the configuration setup in psModules to include recording the random seed, and setting if desired. Updated all our products to use this API. Some fixes and updates to the configuration run-time information dumping. ppImage now dumps the configuration at the end, allowing the list of files in the run-time information to be set.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/math/psRandom.c

    r20547 r23259  
    2929#include <inttypes.h>
    3030
     31#include "psAbort.h"
    3132#include "psMemory.h"
    3233#include "psRandom.h"
     
    3839
    3940
     41unsigned long seed = 0;                 // Seed for RNG
     42
     43
    4044psU64 p_psRandomGetSystemSeed(bool log)
    4145{
    42     FILE*  fd;
    43     psU64  seedVal = 0;
    44     time_t timeVal;
     46    psU64 seedVal = 0;                  // Seed value to return
    4547
    46     fd = fopen("/dev/urandom","r");
    47     if(fd == NULL) {
    48         // Read system clock to get seed
    49         seedVal = (psU64)time(&timeVal);
    50     } else {
    51         // Read urandom to get seed
    52         if (fread(&seedVal, sizeof(psU64),1,fd)) {;} // ignore return value
    53         // Close file
    54         fclose(fd);
     48    // Since zero is a special value in our context, don't allow the final value chosen to be zero
     49    while (seedVal == 0) {
     50        FILE *fd = fopen("/dev/urandom", "r");
     51        if (fd) {
     52            // Read urandom to get seed
     53            if (fread(&seedVal, sizeof(psU64), 1, fd)) {;} // ignore return value
     54            // Close file
     55            fclose(fd);
     56        } else {
     57            // Read system clock to get seed
     58            time_t timeVal;                 // Time value
     59            seedVal = (psU64)time(&timeVal);
     60        }
    5561    }
    5662
     
    6369}
    6470
    65 psRandom *psRandomAlloc(psRandomType type,
    66                         unsigned long seed)
     71psU64 psRandomSeed(psU64 value)
    6772{
    68     gsl_rng   *r      = NULL;
    69     psRandom  *myRNG  = NULL;
     73    while (value == 0) {
     74        value = p_psRandomGetSystemSeed(true);
     75    }
     76    seed = value;
     77    return seed;
     78}
    7079
     80// Destructor for psRandom
     81static void randomFree(psRandom *rng)
     82{
     83    if (rng->gsl) {
     84        gsl_rng_free(rng->gsl);
     85    }
     86    return;
     87}
     88
     89// Constructor for psRandom
     90static psRandom *randomAlloc(psRandomType type)
     91{
     92    psRandom *rng = psAlloc(sizeof(psRandom)); // Random number generator to return
     93    psMemSetDeallocator(rng, (psFreeFunc)randomFree);
     94
     95    rng->type = type;
     96
     97    const gsl_rng_type *gslType;        // Type of RNG according to GSL
    7198    switch (type) {
    72     case PS_RANDOM_TAUS:
    73         myRNG = (psRandom*)psAlloc(sizeof(psRandom));
    74         r = gsl_rng_alloc(gsl_rng_taus);
    75         myRNG->gsl = r;
    76         if(seed == 0) {
    77             gsl_rng_set(myRNG->gsl, p_psRandomGetSystemSeed(true));
    78         } else {
    79             gsl_rng_set(myRNG->gsl, seed);
    80         }
    81         myRNG->type = type;
     99      case PS_RANDOM_TAUS:
     100        gslType = gsl_rng_taus;
    82101        break;
    83 
    84     default:
    85         psError(PS_ERR_UNEXPECTED_NULL, true, _("Unknown Random Number Generator Type"));
     102      default:
     103        psAbort("Unknown Random Number Generator Type: %x", type);
    86104        break;
    87105    }
    88106
    89     return(myRNG);
     107    rng->gsl = gsl_rng_alloc(gslType);
     108    return rng;
    90109}
    91110
    92 void psRandomReset(psRandom *rand,
    93                    unsigned long seed)
     111psRandom *psRandomAlloc(psRandomType type)
    94112{
    95     // Check null psRandom
    96     if(rand==NULL) {
    97         psError(PS_ERR_UNEXPECTED_NULL,
    98                 true,
    99                 _("Random variable is NULL."));
    100     } else {
    101         // Check seed value to see if system seed should be used
    102         if(seed == 0) {
    103             gsl_rng_set(rand->gsl,p_psRandomGetSystemSeed(true));
    104         } else {
    105             gsl_rng_set(rand->gsl, seed);
    106         }
     113    psRandom *rng = randomAlloc(type);
     114    psRandomReset(rng);
     115
     116    return rng;
     117}
     118
     119psRandom *psRandomAllocSpecific(psRandomType type, psU64 specificSeed)
     120{
     121    psRandom *rng = randomAlloc(type);
     122    if (specificSeed == 0) {
     123        specificSeed = p_psRandomGetSystemSeed(true);
    107124    }
     125    gsl_rng_set(rng->gsl, specificSeed);
     126    return rng;
     127}
     128
     129bool psRandomReset(psRandom *rand)
     130{
     131    PS_ASSERT_RANDOM_NON_NULL(rand, false);
     132    if (seed == 0) {
     133        seed = p_psRandomGetSystemSeed(true);
     134    }
     135    gsl_rng_set(rand->gsl, seed);
     136    return true;
    108137}
    109138
    110139double psRandomUniform(const psRandom *r)
    111140{
    112     // Check null psRandom variable
    113     if(r == NULL) {
    114         psError(PS_ERR_UNEXPECTED_NULL,
    115                 true,
    116                 _("Random variable is NULL."));
    117         return(0);
    118     } else {
    119         return(gsl_rng_uniform(r->gsl));
    120     }
     141    PS_ASSERT_RANDOM_NON_NULL(r, NAN);
     142    return gsl_rng_uniform(r->gsl);
    121143}
    122144
    123145double psRandomGaussian(const psRandom *r)
    124146{
    125     // Check null psRandom variable
    126     if(r == NULL) {
    127         psError(PS_ERR_UNEXPECTED_NULL,
    128                 true,
    129                 _("Random variable is NULL."));
    130         return(0);
    131     } else {
    132         // XXX: What should sigma be?
    133         return(gsl_ran_gaussian(r->gsl, 1.0));
    134     }
     147    PS_ASSERT_RANDOM_NON_NULL(r, NAN);
     148    return gsl_ran_gaussian(r->gsl, 1.0);
    135149}
    136150
    137151double p_psRandomGaussian(const psRandom *r, double sigma)
    138152{
    139     // Check null psRandom variable
    140     if(r == NULL) {
    141         psError(PS_ERR_UNEXPECTED_NULL,
    142                 true,
    143                 _("Random variable is NULL."));
    144         return(0);
    145     } else {
    146         return(gsl_ran_gaussian(r->gsl, sigma));
    147     }
     153    PS_ASSERT_RANDOM_NON_NULL(r, NAN);
     154    return gsl_ran_gaussian(r->gsl, sigma);
    148155}
    149156
    150157double psRandomPoisson(const psRandom *r, double mean)
    151158{
    152     // Check null psRandom variable
    153     if(r == NULL) {
    154         psError(PS_ERR_UNEXPECTED_NULL,
    155                 true,
    156                 _("Random variable is NULL."));
    157         return(0);
    158     } else {
    159         return((psF64) gsl_ran_poisson(r->gsl, mean));
    160     }
     159    PS_ASSERT_RANDOM_NON_NULL(r, NAN);
     160    return gsl_ran_poisson(r->gsl, mean);
    161161}
    162162
Note: See TracChangeset for help on using the changeset viewer.