This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug libfortran/32812] random_seed and date_and_time
- From: "fxcoudert at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 10 Aug 2007 19:04:27 -0000
- Subject: [Bug libfortran/32812] random_seed and date_and_time
- References: <bug-32812-10391@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- 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