This is the mail archive of the gsl-discuss@sources.redhat.com mailing list for the GSL project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RN generators Seed


On Tue, 26 Aug 2003, Maura Edelweiss Monville wrote:

> Thank you very much. 
> Since I 'm using a RN generator from GSL I'm definitely interested in
> the gsl-compatible call wrapper for /dev/random. 
> I guess it is not in the same web site as the othe GSL goodies ... 
> I would appreciate being given the possibility to download it. 
> I develop on SuSE 8.2.

I'm including BOTH the code to generate a good random number seed from
/dev/random as a direct subroutine call (at the very end of this message) 
AND the wrapper code below.  The gsl rng god (if listening) is welcome to 
add /dev/random  to the gsl rng list of supported generators if they so desire.

[If you do you'll probably want to make error handling gsl-consistent (I'm
sloppy) and perhaps insert a stat/test for /dev/random's existence at the
point where the generator is actually added to the list of generators, as it
may not exist on some architectures where gsl runs.  You also MAY want to add
a gsl_rng_set_dev_random(random) function that just sets the seed from
/dev/random -- or not.]



To use the wrapper in your gsl routine, save dev_random.c below, add it to your 
makefile so it will compile and link.  Add the following into your header
file(s) (ordinarily they'd be in <gsl/gsl_rng.h>).

 const gsl_rng_type **types;    /* where all the rng types go */
 gsl_rng *random;               /* global gsl random number generator */

You'll then need a fragment like the following in your startup code to add the new type to the gsl
list of rng's BEFORE trying to use the new generator in any way:

%< Snip snip snip ==================================================================
 /*
  * Now add new RNG's onto the GSL types list.  Apparently this is all that is
  * needed -- they subsequently just "work" in the gsl call format.  This is code
  * taken from gsl types.c where N is apparently a hard-coded value.  This means
  * that we cannot CURRENTLY go over 100 generators total without e.g.
  * increasing N in the gsl sources.
  */
#define N 100
#define GSL_VAR

/* List new rng types to be added. */
 GSL_VAR const gsl_rng_type *gsl_rng_dev_random;

 int i,devrandom;

 /*
  * get to the end of the list of built in gsl generators
  */
 types = gsl_rng_types_setup ();
 i = 0;
 while(types[i] != NULL){
   i++;
   /* insert list code if desired */
 }
 /*
  * and add the new one(s)...
  */
 if(i < N){
   i = devrandom; /* save the index/type of the new generator */
   types[i++] = (gsl_rng_dev_random);
 }

%< Snip snip snip ==================================================================

Thereafter you should be able to use /dev/random just like any other gsl rng,
e.g.
       gsl_rng *random;
       random = gsl_rng_alloc (types[randnum]);
       random_max = gsl_rng_max(random);
       for(i = 0;i<100;i++){
         printf("%s returns a random int = %d\n",
           gsl_rng_name(random),    /* should return string "/dev/random", */
           gsl_rng_get(random));     /* should return a random int from /dev/random */
       }

(or the like, I'm not testing this code for typos:-) should return 100 random
ints from /dev/random.  If you run long enough loops of this, you can actually
see /dev/random "hang" from time to time waiting for entropy...

Really this is a pretty cool interface and it's remarkably easy to add your own rng's 
to it.

All code in this note is GPL v2, BTW and can be freely added to the GSL or
anybody's personal code, just to complete the formalities there.

   rgb

-- 
Robert G. Brown	                       http://www.phy.duke.edu/~rgb/
Duke University Dept. of Physics, Box 90305
Durham, N.C. 27708-0305
Phone: 1-919-660-2567  Fax: 919-660-2525     email:rgb@phy.duke.edu


%< Snip snip snip =============== dev_random.c ================================
/* dev_random
 * 
 * Copyright (C) 2003 Robert G. Brown
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gsl/gsl_rng.h>

/*
 * This is a wrapping of the /dev/random hardware rng
 */

static unsigned long int dev_random_get (void *vstate);
static double dev_random_get_double (void *vstate);
static void dev_random_set (void *vstate, unsigned long int s);

typedef struct
  {
    FILE *fp;
  }
dev_random_state_t;

static unsigned long int
dev_random_get (void *vstate)
{
  dev_random_state_t *state = (dev_random_state_t *) vstate;
  unsigned long int j;

  if(state->fp != NULL) {
    fread(&j,sizeof(j),1,state->fp);
    return j;
  } else {
    fprintf(stderr,"Error: /dev/random not open.  Exiting.\n");
    exit(0);
  }

}

static double
dev_random_get_double (void *vstate)
{
  return dev_random_get (vstate) / (double) UINT_MAX;
}

static void
dev_random_set (void *vstate, unsigned long int s)
{
  dev_random_state_t *state = (dev_random_state_t *) vstate;

 if ((state->fp = fopen("/dev/random","r")) == NULL) {
   fprintf(stderr,"Error: Cannot open /dev/random, exiting.\n");
   exit(0);
 }

 return;

}

static const gsl_rng_type dev_random_type =
{"/dev/random",			/* name */
 UINT_MAX,			/* RAND_MAX */
 0,				/* RAND_MIN */
 sizeof (dev_random_state_t),
 &dev_random_set,
 &dev_random_get,
 &dev_random_get_double};

const gsl_rng_type *gsl_rng_dev_random = &dev_random_type;

%< Snip snip snip =============== end of dev_random.c   ============================

%< Snip snip snip =============== random_seed.c  ===================================
/*
 *========================================================================
 * $Id: random_seed.c,v 1.2 2003/06/10 15:21:15 rgb Exp $
 *
 * See copyright in copyright.h and the accompanying file COPYING
 *========================================================================
 */

/*
 * *========================================================================
 * NOTE WELL:  This routine automagically falls back on setting from clock if
 * /dev/random is not available.  It also is missing some includes -- presuming
 * it will be put somewhere with either a shared header (where e.g. verbose is
 * defined) that has them or you'll add them by hand so it can standalone...
 * *========================================================================
 */

unsigned long int random_seed()
{

 unsigned long int seed;
 struct timeval tv;
 FILE *devrandom;

 if ((devrandom = fopen("/dev/random","r")) == NULL) {
   gettimeofday(&tv,0);
   seed = tv.tv_sec + tv.tv_usec;
   if(verbose) printf("Got seed %u from gettimeofday()\n",seed);
 } else {
   fread(&seed,sizeof(seed),1,devrandom);
   if(verbose) printf("Got seed %u from /dev/random\n",seed);
   fclose(devrandom);
 }

 return(seed);

}

%< Snip snip snip ==================================================================



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]