From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30783 invoked by alias); 25 Feb 2008 08:46:01 -0000 Received: (qmail 30763 invoked by uid 22791); 25 Feb 2008 08:46:00 -0000 X-Spam-Check-By: sourceware.org Received: from nf-out-0910.google.com (HELO nf-out-0910.google.com) (64.233.182.185) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 25 Feb 2008 08:45:17 +0000 Received: by nf-out-0910.google.com with SMTP id h3so1326703nfh.6 for ; Mon, 25 Feb 2008 00:45:14 -0800 (PST) Received: by 10.151.26.12 with SMTP id d12mr973777ybj.74.1203929113468; Mon, 25 Feb 2008 00:45:13 -0800 (PST) Received: from ?192.168.0.5? ( [90.193.94.85]) by mx.google.com with ESMTPS id k5sm7763005nfd.23.2008.02.25.00.45.11 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 25 Feb 2008 00:45:12 -0800 (PST) Mime-Version: 1.0 (Apple Message framework v753) To: Fortran List Message-Id: <4EAB6E62-FA2D-4184-A676-99CB401C7740@gmail.com> Content-Type: multipart/mixed; boundary=Apple-Mail-6-136120990 Cc: gcc-patches list Subject: [libgfortran,patch] Scramble bytes in the user-provided random seeds (PR 32812) From: FX Coudert Date: Mon, 25 Feb 2008 09:00:00 -0000 X-Mailer: Apple Mail (2.753) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2008-02/txt/msg01137.txt.bz2 --Apple-Mail-6-136120990 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=ISO-8859-1; delsp=yes; format=flowed Content-length: 1298 Hi all, Current library implementation of RANDOM_NUMBER() is such that the=20=20 highest bits of the user-provided seed determine the mots significant=20=20 bits of floating-points values return, and the lowest bits of the=20=20 seed control the least significant bits of fp values. Thus, a user=20=20 providing us with a seed with good lower bits but poor higher bits=20=20 will find that the fp values are not very random at all... one such=20=20 example being the use of DATE_AND_TIME to provide for random seeds. This patch adds a little to the quality of implementation by adding a=20=20 (bijective) scrambling operation between the seed the user gives us=20=20 and the seed we actually use. Two functions, scramble_seed and=20=20 unscramble_seed, are used when RANDOM_NUMBER() is called with a PUT=3D=20= =20 or GET=3D argument, which shuffles bytes of the seed. Regtested on x86_64-linux, with both -m32 and -m64. Tested manually=20=20 with different seeds of different qualities. FX PS: Of course, we're not adding quality to poor seeds (I'm not=20=20 changing entropy with a bijective function!). We're just providing a=20=20 little invisible help to one particular case of half-bad, half-good=20=20 seeds. --=20 Fran=E7ois-Xavier Coudert http://www.homepages.ucl.ac.uk/~uccafco/ --Apple-Mail-6-136120990 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name=random.ChangeLog Content-Disposition: attachment; filename=random.ChangeLog Content-length: 280 2008-02-25 Francois-Xavier Coudert PR libfortran/32812 * intrinsics/random.c (scramble_seed, unscramble_seed): New functions. (random_seed_i4): Scramble the seed the user gives us before storing it, and unscramble it when we return it back later. --Apple-Mail-6-136120990 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name=random.diff Content-Disposition: attachment; filename=random.diff Content-length: 2540 Index: intrinsics/random.c =================================================================== --- intrinsics/random.c (revision 132592) +++ intrinsics/random.c (working copy) @@ -639,6 +639,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 +670,7 @@ void random_seed_i4 (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); @@ -673,9 +697,15 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc 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 seeds with quality only in the lower or upper part. */ + scramble_seed ((unsigned char *) kiss_seed, seed, 4*kiss_size); } /* Return the seed to GET data. */ @@ -689,9 +719,14 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc if (((get->dim[0].ubound + 1 - get->dim[0].lbound)) < kiss_size) runtime_error ("Array size of GET is too small."); - /* This code now should do correct strides. */ + /* Unscramble the seed. */ + unscramble_seed (seed, (unsigned char *) kiss_seed, 4*kiss_size); + + /* Then copy it back to the user variable. */ 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); --Apple-Mail-6-136120990--