Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Aug 2014 12:51:52 +0300
From:      Vitaly Magerya <vmagerya@gmail.com>
To:        Chenguang Li <horus.li@gmail.com>, freebsd-hackers@freebsd.org
Subject:   Re: On changing rand(3) to random(3) in awk(1)
Message-ID:  <53FEFBB8.5040305@gmail.com>
In-Reply-To: <F70B9462-0898-47EF-AF83-47509F21F84E@gmail.com>
References:  <F70B9462-0898-47EF-AF83-47509F21F84E@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2014-08-28 09:21, Chenguang Li wrote:
> Since the original rand(3) could not provide a fair, "one-shot" randomness in awk(1),
> I am writing this to suggest that we change *rand(3) to *random(3), which only requires
> modifying a few lines of code[1], but will result in better random number generation.
> BTW, OSX & gawk already have this. Previous discussion can be found here[2].
>
> What do you think?

I think this is a useful change; in particular, srandom(3) seems to do
a much better job of coping with sequential seeds than srand(3), which
solves a big problem with using 'srand' in our awk.

> Index: main.c
> ===================================================================
> --- main.c      (revision 270740)
> +++ main.c      (working copy)
> @@ -74,7 +74,7 @@
>         signal(SIGFPE, fpecatch);
>
>         srand_seed = 1;
> -       srand(srand_seed);
> +       srandom(srand_seed);
>
>         yyin = NULL;
>         symtab = makesymtab(NSYMTAB/NSYMTAB);
> Index: run.c
> ===================================================================
> --- run.c       (revision 270740)
> +++ run.c       (working copy)
> @@ -1522,7 +1522,7 @@
>                 break;
>         case FRAND:
>                 /* in principle, rand() returns something in 0..RAND_MAX */
> -               u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
> +               u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX;

You should not use RAND_MAX with random(3), since it returns values
between 0 and 0x7fffffff (inclusive); RAND_MAX only applies to rand(3).

A better patch would be something like this:

> -               /* in principle, rand() returns something in 0..RAND_MAX */
> -               u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
> +               /* random() returns values in [0, 2147483647] */
> +               u = (Awkfloat) random() / 2147483648;

Also, awk(1) man page should be updated; it currently says:

>        rand   random number on (0,1)

... while it should say:

>        rand   random number on [0,1)

>                 break;
>         case FSRAND:
>                 if (isrec(x))   /* no argument provided */
> @@ -1530,7 +1530,7 @@
>                 else
>                         u = getfval(x);
>                 tmp = u;
> -               srand((unsigned int) u);
> +               srandom((unsigned int) u);

You should probably use 'unsigned long' here.

>                 u = srand_seed;
>                 srand_seed = tmp;
>                 break;

Otherwise, the patch looks fine.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53FEFBB8.5040305>