------- Comment #2 from fxcoudert at gcc dot gnu dot org 2007-08-10 19:04 ------- I guess we have to scramble the seed given by the user, something like this:
Index: intrinsics/random.c =================================================================== --- intrinsics/random.c (revision 127331) +++ intrinsics/random.c (working copy) @@ -32,6 +32,7 @@ Boston, MA 02110-1301, USA. */ #include "config.h" #include "libgfortran.h" #include <gthr.h> +#include <string.h> extern void random_r4 (GFC_REAL_4 *); iexport_proto(random_r4); @@ -639,6 +640,29 @@ arandom_r16 (gfc_array_r16 *x) #endif + + +static void +scramble_seed (unsigned char *dest, unsigned char *src, int size) +{ + int i; + + for (i = 0; i < size; i++) + dest[(i % 2) * (size / 2) + i / 2] = src[i]; +} + + +static void +unscramble_seed (unsigned char *dest, unsigned char *src, int size) +{ + int i; + + for (i = 0; i < size; i++) + dest[i] = src[(i % 2) * (size / 2) + i / 2]; +} + + + /* random_seed is used to seed the PRNG with either a default set of seeds or user specified set of seeds. random_seed must be called with no argument or exactly one argument. */ @@ -647,6 +671,7 @@ void random_seed (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get) { int i; + unsigned char seed[4*kiss_size]; __gthread_mutex_lock (&random_lock); @@ -654,10 +679,8 @@ random_seed (GFC_INTEGER_4 *size, gfc_ar { /* From the standard: "If no argument is present, the processor assigns a processor-dependent value to the seed." */ - for (i=0; i<kiss_size; i++) kiss_seed[i] = kiss_default_seed[i]; - } if (size != NULL) @@ -673,9 +696,15 @@ random_seed (GFC_INTEGER_4 *size, gfc_ar if (((put->dim[0].ubound + 1 - put->dim[0].lbound)) < kiss_size) runtime_error ("Array size of PUT is too small."); - /* This code now should do correct strides. */ + /* We copy the seed given by the user. */ for (i = 0; i < kiss_size; i++) - kiss_seed[i] =(GFC_UINTEGER_4) put->data[i * put->dim[0].stride]; + memcpy (seed + i * sizeof(GFC_UINTEGER_4), + &(put->data[(kiss_size - 1 - i) * put->dim[0].stride]), + sizeof(GFC_UINTEGER_4)); + + /* We put it after scrambling the bytes, to paper around users who + provide low-quality seeds. */ + scramble_seed ((unsigned char *) kiss_seed, seed, 4*kiss_size); } /* Return the seed to GET data. */ @@ -689,9 +718,14 @@ random_seed (GFC_INTEGER_4 *size, gfc_ar if (((get->dim[0].ubound + 1 - get->dim[0].lbound)) < kiss_size) runtime_error ("Array size of GET is too small."); + /* Unscramble the seed. */ + unscramble_seed (seed, (unsigned char *) kiss_seed, 4*kiss_size); + /* This code now should do correct strides. */ for (i = 0; i < kiss_size; i++) - get->data[i * get->dim[0].stride] = (GFC_INTEGER_4) kiss_seed[i]; + memcpy (&(get->data[(kiss_size - 1 - i) * get->dim[0].stride]), + seed + i * sizeof(GFC_UINTEGER_4), + sizeof(GFC_UINTEGER_4)); } __gthread_mutex_unlock (&random_lock); This doesn't make miracles (i.e. provide you with a good seed when you input a particularly poor one), but at least it makes using the VALUES of DATE_AND_TIME less frustrating (by generating visibly different streams of PRN). -- fxcoudert at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |patch http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32812