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