1 /*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13 
14 #ifndef HAVE_SRAND48
15 
16 #include <math.h>
17 #include <stdlib.h>
18 #include <spatialindex/tools/rand48.h>
19 
20 #define	RAND48_SEED_0	(0x330e)
21 #define	RAND48_SEED_1	(0xabcd)
22 #define	RAND48_SEED_2	(0x1234)
23 #define	RAND48_MULT_0	(0xe66d)
24 #define	RAND48_MULT_1	(0xdeec)
25 #define	RAND48_MULT_2	(0x0005)
26 #define	RAND48_ADD	(0x000b)
27 
28 
29  /* Internal function to compute next state of the generator.  */
30 static void _dorand48(unsigned short[3]);
31 
32 /* Unfortunately, 3 __globals, which the exported functions must access */
33 unsigned short __rand48_Seed[3] = {
34 	RAND48_SEED_0,
35 	RAND48_SEED_1,
36 	RAND48_SEED_2
37 };
38 unsigned short __rand48_Mult[3] = {
39 	RAND48_MULT_0,
40 	RAND48_MULT_1,
41 	RAND48_MULT_2
42 };
43 unsigned short __rand48_Add = RAND48_ADD;
44 
45 /* Internal function to compute next state of the generator.  */
46 	static void
_dorand48(unsigned short xseed[3])47 _dorand48(unsigned short xseed[3])
48 {
49 	unsigned long accu;
50 	unsigned short temp[2];
51 
52 	accu = (unsigned long) __rand48_Mult[0] * (unsigned long) xseed[0] +
53 	 (unsigned long) __rand48_Add;
54 	temp[0] = (unsigned short) accu;	/* lower 16 bits */
55 	accu >>= sizeof(unsigned short) * 8;
56 	accu += (unsigned long) __rand48_Mult[0] * (unsigned long) xseed[1] +
57 		 (unsigned long) __rand48_Mult[1] * (unsigned long) xseed[0];
58 	temp[1] = (unsigned short) accu;	/* middle 16 bits */
59 	accu >>= sizeof(unsigned short) * 8;
60 	accu += __rand48_Mult[0] * xseed[2] + __rand48_Mult[1] * xseed[1] +
61 			__rand48_Mult[2] * xseed[0];
62 	xseed[0] = temp[0];
63 	xseed[1] = temp[1];
64 	xseed[2] = (unsigned short) accu;
65 }
66 
67 	extern void
srand48(long seed)68 srand48(long seed) __THROW
69 {
70 	__rand48_Seed[0] = RAND48_SEED_0;
71 	__rand48_Seed[1] = (unsigned short) seed;
72 	__rand48_Seed[2] = (unsigned short) (seed >> 16);
73 	__rand48_Mult[0] = RAND48_MULT_0;
74 	__rand48_Mult[1] = RAND48_MULT_1;
75 	__rand48_Mult[2] = RAND48_MULT_2;
76 	__rand48_Add = RAND48_ADD;
77 }
78 
79 	extern unsigned short *
seed48(unsigned short xseed[3])80 seed48(unsigned short xseed[3]) __THROW
81 {
82 	static unsigned short sseed[3];
83 
84 	sseed[0] = __rand48_Seed[0];
85 	sseed[1] = __rand48_Seed[1];
86 	sseed[2] = __rand48_Seed[2];
87 	__rand48_Seed[0] = xseed[0];
88 	__rand48_Seed[1] = xseed[1];
89 	__rand48_Seed[2] = xseed[2];
90 	__rand48_Mult[0] = RAND48_MULT_0;
91 	__rand48_Mult[1] = RAND48_MULT_1;
92 	__rand48_Mult[2] = RAND48_MULT_2;
93 	__rand48_Add = RAND48_ADD;
94 	return sseed;
95 }
96 
97 	extern long
nrand48(unsigned short xseed[3])98 nrand48(unsigned short xseed[3]) __THROW
99 {
100 	_dorand48(xseed);
101 	return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
102 }
103 	extern long
mrand48(void)104 mrand48(void) __THROW
105 {
106 	_dorand48(__rand48_Seed);
107 	return ((long) __rand48_Seed[2] << 16) + (long) __rand48_Seed[1];
108 }
109 
110 	extern long
lrand48(void)111 lrand48(void) __THROW
112 {
113 	_dorand48(__rand48_Seed);
114 	return ((long) __rand48_Seed[2] << 15) + ((long) __rand48_Seed[1] >> 1);
115 }
116 
117 	extern void
lcong48(unsigned short p[7])118 lcong48(unsigned short p[7]) __THROW
119 {
120 	__rand48_Seed[0] = p[0];
121 	__rand48_Seed[1] = p[1];
122 	__rand48_Seed[2] = p[2];
123 	__rand48_Mult[0] = p[3];
124 	__rand48_Mult[1] = p[4];
125 	__rand48_Mult[2] = p[5];
126 	__rand48_Add = p[6];
127 }
128 	extern long
jrand48(unsigned short xseed[3])129 jrand48(unsigned short xseed[3]) __THROW
130 {
131 	_dorand48(xseed);
132 	return ((long) xseed[2] << 16) + (long) xseed[1];
133 }
134 
135 	extern double
erand48(unsigned short xseed[3])136 erand48(unsigned short xseed[3]) __THROW
137 {
138 	_dorand48(xseed);
139 	return ldexp((double) xseed[0], -48) +
140 	       ldexp((double) xseed[1], -32) +
141 	       ldexp((double) xseed[2], -16);
142 }
143 
144 	extern double
drand48(void)145 drand48(void) __THROW
146 {
147 	return erand48(__rand48_Seed);
148 }
149 
150 #endif
151