Mail Archives: djgpp-workers/1999/01/09/08:00:11
Here's the patch to add *rand48() functions to libc. This time with
documentation.
Holmboe, Symphony 7,
MartinS
diff -rNu src.org/libc/compat/stdlib/makefile src/libc/compat/stdlib/makefile
--- src.org/libc/compat/stdlib/makefile Sat Jul 25 18:58:44 1998
+++ src/libc/compat/stdlib/makefile Wed Jan 6 20:05:08 1999
@@ -20,6 +20,7 @@
SRC += fcvtbuf.c
SRC += fcvt.c
SRC += gcvt.c
+SRC += rand48.c
include $(TOP)/../makefile.inc
diff -rNu src.org/libc/compat/stdlib/rand48.c src/libc/compat/stdlib/rand48.c
--- src.org/libc/compat/stdlib/rand48.c Thu Jan 1 00:00:00 1970
+++ src/libc/compat/stdlib/rand48.c Sat Jan 9 13:29:34 1999
@@ -0,0 +1,186 @@
+/*
+ * File rand48.c.
+ *
+ * Copyright (C) 1999 Martin Strömberg <ams AT ludd DOT luth DOT se>.
+ *
+ * This software may be used freely so long as this copyright notice is
+ * left intact. There is no warranty on this software.
+ *
+ */
+
+#include "stdlib.h"
+
+#define RAND48_MULT0 (0xe66d)
+#define RAND48_MULT1 (0xdeec)
+#define RAND48_MULT2 (0x0005)
+#define RAND48_ADD (0x000b)
+
+static unsigned short internal_state[3] = {1, 0, 0};
+static unsigned short multiplier0 = RAND48_MULT0;
+static unsigned short multiplier1 = RAND48_MULT1;
+static unsigned short multiplier2 = RAND48_MULT2;
+static unsigned short additiver = RAND48_ADD;
+
+static void next(
+ unsigned short state[]
+ )
+{
+ unsigned short new_state[3];
+ unsigned long tmp;
+
+ tmp = state[0] * multiplier0 + additiver;
+ new_state[0] = (unsigned short)(tmp & 0xffff);
+
+ tmp = (tmp >> 8*sizeof(unsigned short))
+ + state[0] * multiplier1
+ + state[1] * multiplier0;
+ new_state[1] = (unsigned short)(tmp & 0xffff);
+
+ tmp = (tmp >> 8*sizeof(unsigned short))
+ + state[0] * multiplier2
+ + state[1] * multiplier1
+ + state[2] * multiplier0;
+ new_state[2] = (unsigned short)(tmp & 0xffff);
+
+ memcpy(state, new_state, 3*sizeof(unsigned short));
+}
+
+double drand48(void)
+{
+ return(erand48(internal_state));
+}
+
+double erand48(
+ unsigned short state[3]
+ )
+{
+ int i; /* Counter. */
+ double pot = 0.5; /* A potential of 0.5. */
+ double result = 0.0;
+
+ next(state);
+
+ for(i = 0; i < 8*sizeof(unsigned short); i++)
+ {
+ if( (state[2] << i) & 0x8000 )
+ {
+ result += pot;
+ }
+ pot /= 2.0;
+ if( (state[1] << i) & 0x8000 )
+ {
+ result += pot;
+ }
+ pot /= 2.0;
+ if( (state[0] << i) & 0x8000 )
+ {
+ result += pot;
+ }
+ pot /= 2.0;
+ }
+
+ return(result);
+
+}
+
+
+unsigned long lrand48(void)
+{
+ return(nrand48(internal_state));
+}
+
+
+unsigned long nrand48(
+ unsigned short state[3]
+ )
+{
+
+ next(state);
+ return( ((unsigned long)state[2]) * 0x8000
+ + ( ((unsigned long)state[1]) >> 1 )
+ );
+
+}
+
+
+long mrand48(void)
+{
+ return(jrand48(internal_state));
+}
+
+
+long jrand48(
+ unsigned short state[3]
+ )
+{
+
+ next(state);
+ if( (state[2] & 0x8000) )
+ {
+ return( -1.0 * ((long)(state[2] & 0x7fff)) * 0x10000 + ((unsigned long)state[1]) );
+ }
+ else
+ {
+ return( ((long)(state[2] & 0x7fff)) * 0x10000 + ((unsigned long)state[1]) );
+ }
+
+}
+
+void srand48(
+ long seedval
+ )
+{
+
+ /* Restore default multipliers and additiver. */
+ multiplier0 = RAND48_MULT0;
+ multiplier1 = RAND48_MULT1;
+ multiplier2 = RAND48_MULT2;
+ additiver = RAND48_ADD;
+
+ /* Setup the new state. */
+ internal_state[0] = 0x330e;
+ internal_state[1] = (seedval & 0xffff);
+ internal_state[2] = ( (seedval >> 16) & 0xffff);
+
+}
+
+unsigned short *seed48(
+ unsigned short state_seed[3]
+ )
+{
+ static unsigned short old_state[3];
+
+ /* Restore default multipliers and additiver. */
+ multiplier0 = RAND48_MULT0;
+ multiplier1 = RAND48_MULT1;
+ multiplier2 = RAND48_MULT2;
+ additiver = RAND48_ADD;
+
+ /* Remember old state. */
+ memcpy(old_state, internal_state, 3*sizeof(unsigned short));
+
+ /* Setup the new state. */
+ memcpy(internal_state, state_seed, 3*sizeof(unsigned short));
+
+ return(old_state);
+}
+
+void lcong48(
+ unsigned short param[7]
+ )
+{
+
+ /* Set the state. */
+ internal_state[0] = param[0];
+ internal_state[1] = param[1];
+ internal_state[2] = param[2];
+
+ /* Set the multipilers. */
+ multiplier0 = param[3];
+ multiplier1 = param[4];
+ multiplier2 = param[5];
+
+ /* Set the additiver. */
+ additiver = param[6];
+
+}
diff -rNu src.org/libc/compat/stdlib/rand48.txh src/libc/compat/stdlib/rand48.txh
--- src.org/libc/compat/stdlib/rand48.txh Thu Jan 1 00:00:00 1970
+++ src/libc/compat/stdlib/rand48.txh Thu Jan 7 09:39:36 1999
@@ -0,0 +1,80 @@
+@node rand48, random number
+@subheading Syntax
+
+@example
+#include <stdlib.h>
+
+double drand48(void);
+double erand48(unsigned short state[3]);
+unsigned long lrand48(void);
+unsigned long nrand48(unsigned short state[3]);
+long mrand48(void);
+long jrand48(unsigned short state[3]);
+void srand48(long seed);
+unsigned short *seed48(unsigned short state_seed[3]);
+void lcong48(unsigned short param[7]);
+@end example
+
+@subheading Description
+
+This is the family of *rand48 functions. The basis for these functions
+is the linear congruential formula X[n+1] = (a*X[n] + c) mod 2^48, n
+>= 0. a = 0x5deece66d and c = 0xb at start and after a call to either
+@code{srand48()} or @code{seed48()}. A call to @code{lcong48()}
+changes a and c (and the internal state).
+
+@code{drand48()} and @code{erand48()} return @code{double}s uniformly
+distributed in the interval [0.0, 1.0).
+
+@code{lrand48()} and @code{nrand48()} return @code{unsigned long}s
+uniformly distributed in the interval [0, 2^31).
+
+@code{mrand48()} and @code{jrand48()} return @code{long}s uniformly
+distributed in the interval [-2^31, 2^31).
+
+@code{erand48()}, @code{jrand48()} and @code{nrand48()} requires the
+state of the random generator to be passed.
+
+@code{drand48()}, @code{lrand48()} and @code{mrand48()} uses an
+internal state (common with all three functions) which should be
+initialised with a call to one of the functions @code{srand48()},
+@code{seed48()} or @code{lcong48()}.
+
+@code{srand48()} sets the high order 32 bits to the argument
+@code{seed}. The low order 16 bits are set to the arbitrary value
+0x330e.
+
+@code{seed48()} sets the internal state according to the argument
+@code{state_seed} (@code{state_seed[0]} is least significant). The
+previous state of the random generator is saved in an internal
+(static) buffer, to which a pointer is returned.
+
+@code{lcong48()} sets the internal state to @code{param[0-2]}, a to
+@code{param[3-5]} (@code{param[0]} and @code{param[3]} are least
+significant) and c to @code{param[6]}.
+
+@subheading Return Value
+
+A random number.
+
+@subheading Portability
+
+@portability !ansi, !posix
+
+@subheading Example
+
+@example
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+int main(void)
+@{
+
+ srand48(time(NULL));
+ printf("%.12f is a random number in [0.0, 1.0).\n", drand48());
+
+ exit(0);
+@}
+
+@end example
- Raw text -