www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/01/20/15:06:23

From: Martin Str|mberg <ams AT ludd DOT luth DOT se>
Message-Id: <199901202005.VAA21625@father.ludd.luth.se>
Subject: rand48 patch 2
To: djgpp-workers AT delorie DOT com (DJGPP-WORKERS)
Date: Wed, 20 Jan 1999 21:05:56 +0100 (MET)
X-Mailer: ELM [version 2.4ME+ PL15 (25)]
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

Here's the patch to add *rand48() to libc. I've received almost no
feedback (one comment from Eli), so I'm a little hesitant if this
should be added yet. Test it please.


Right,

							MartinS
diff -ruN include.org/stdlib.h include/stdlib.h
--- include.org/stdlib.h	Sat Jul 25 18:58:46 1998
+++ include/stdlib.h	Wed Jan  6 20:56:42 1999
@@ -83,18 +83,27 @@
 long double	_atold(const char *_s);
 long long	atoll(const char *_s);
 void		cfree(void *_ptr);
+double          drand48(void);
 char *		ecvtbuf(double _val, int _nd, int *_dp, int *_sn, char *_bf);
 char *		ecvt(double _val, int _nd, int *_dp, int *_sn);
+double          erand48(unsigned short state[3]);
 char *		fcvtbuf(double _val, int _nd, int *_dp, int *_sn, char *_bf);
 char *		fcvt(double _val, int _nd, int *_dp, int *_sn);
 char *		gcvt(double _val, int _nd, char *_buf);
 char *		getpass(const char *_prompt);
 int		getlongpass(const char *_prompt, char *_buffer, int _max_len);
 char *		itoa(int value, char *buffer, int radix);
+long            jrand48(unsigned short state[3]);
 long long	llabs(long long _i);
 lldiv_t		lldiv(long long _numer, long long _denom);
+void            lcong48(unsigned short param[7]);
+unsigned long   lrand48(void);
+long            mrand48(void);
+unsigned long   nrand48(unsigned short state[3]);
 int		putenv(const char *_val);
+unsigned short *seed48(unsigned short state_seed[3]);
 int		setenv(const char *_var, const char *_val, int _replace);
+void            srand48(long seedval);
 int		stackavail(void);
 long double	_strtold(const char *_s, char **_endptr);
 long long	strtoll(const char *_s, char **_endptr, int _base);
diff -ruN 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 -ruN 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	Mon Jan 11 09:20:40 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 -ruN 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	Sun Jan 10 16:56:16 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
+@var{seed}. The low order 16 bits are set to the arbitrary value
+0x330e. 
+
+@code{seed48} sets the internal state according to the argument
+@var{state_seed} (@var{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 @var{param[0-2]}, a to 
+@var{param[3-5]} (@var{param[0]} and @var{param[3]} are least
+significant) and c to @var{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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019