1
by brian
clean slate |
1 |
/******************************************************************
|
2 |
Random numbers and hashing
|
|
3 |
||
4 |
(c) 1994, 1995 Innobase Oy
|
|
5 |
||
6 |
Created 5/30/1994 Heikki Tuuri
|
|
7 |
*******************************************************************/
|
|
8 |
||
9 |
#define UT_HASH_RANDOM_MASK 1463735687 |
|
10 |
#define UT_HASH_RANDOM_MASK2 1653893711 |
|
11 |
#define UT_RND1 151117737 |
|
12 |
#define UT_RND2 119785373 |
|
13 |
#define UT_RND3 85689495 |
|
14 |
#define UT_RND4 76595339 |
|
15 |
#define UT_SUM_RND2 98781234 |
|
16 |
#define UT_SUM_RND3 126792457 |
|
17 |
#define UT_SUM_RND4 63498502 |
|
18 |
#define UT_XOR_RND1 187678878 |
|
19 |
#define UT_XOR_RND2 143537923 |
|
20 |
||
21 |
extern ulint ut_rnd_ulint_counter; |
|
22 |
||
23 |
/************************************************************
|
|
24 |
This is used to set the random number seed. */
|
|
25 |
UNIV_INLINE |
|
26 |
void |
|
27 |
ut_rnd_set_seed(
|
|
28 |
/*============*/
|
|
29 |
ulint seed) /* in: seed */ |
|
30 |
{
|
|
31 |
ut_rnd_ulint_counter = seed; |
|
32 |
}
|
|
33 |
||
34 |
/************************************************************
|
|
35 |
The following function generates a series of 'random' ulint integers. */
|
|
36 |
UNIV_INLINE |
|
37 |
ulint |
|
38 |
ut_rnd_gen_next_ulint(
|
|
39 |
/*==================*/
|
|
40 |
/* out: the next 'random' number */ |
|
41 |
ulint rnd) /* in: the previous random number value */ |
|
42 |
{
|
|
43 |
ulint n_bits; |
|
44 |
||
45 |
n_bits = 8 * sizeof(ulint); |
|
46 |
||
47 |
rnd = UT_RND2 * rnd + UT_SUM_RND3; |
|
48 |
rnd = UT_XOR_RND1 ^ rnd; |
|
49 |
rnd = (rnd << 20) + (rnd >> (n_bits - 20)); |
|
50 |
rnd = UT_RND3 * rnd + UT_SUM_RND4; |
|
51 |
rnd = UT_XOR_RND2 ^ rnd; |
|
52 |
rnd = (rnd << 20) + (rnd >> (n_bits - 20)); |
|
53 |
rnd = UT_RND1 * rnd + UT_SUM_RND2; |
|
54 |
||
55 |
return(rnd); |
|
56 |
}
|
|
57 |
||
58 |
/************************************************************
|
|
59 |
The following function generates 'random' ulint integers which
|
|
60 |
enumerate the value space of ulint integers in a pseudo random
|
|
61 |
fashion. Note that the same integer is repeated always after
|
|
62 |
2 to power 32 calls to the generator (if ulint is 32-bit). */
|
|
63 |
UNIV_INLINE |
|
64 |
ulint |
|
65 |
ut_rnd_gen_ulint(void) |
|
66 |
/*==================*/
|
|
67 |
/* out: the 'random' number */ |
|
68 |
{
|
|
69 |
ulint rnd; |
|
70 |
ulint n_bits; |
|
71 |
||
72 |
n_bits = 8 * sizeof(ulint); |
|
73 |
||
74 |
ut_rnd_ulint_counter = UT_RND1 * ut_rnd_ulint_counter + UT_RND2; |
|
75 |
||
76 |
rnd = ut_rnd_gen_next_ulint(ut_rnd_ulint_counter); |
|
77 |
||
78 |
return(rnd); |
|
79 |
}
|
|
80 |
||
81 |
/************************************************************
|
|
82 |
Generates a random integer from a given interval. */
|
|
83 |
UNIV_INLINE |
|
84 |
ulint |
|
85 |
ut_rnd_interval(
|
|
86 |
/*============*/
|
|
87 |
/* out: the 'random' number */ |
|
88 |
ulint low, /* in: low limit; can generate also this value */ |
|
89 |
ulint high) /* in: high limit; can generate also this value */ |
|
90 |
{
|
|
91 |
ulint rnd; |
|
92 |
||
93 |
ut_ad(high >= low); |
|
94 |
||
95 |
if (low == high) { |
|
96 |
||
97 |
return(low); |
|
98 |
} |
|
99 |
||
100 |
rnd = ut_rnd_gen_ulint(); |
|
101 |
||
102 |
return(low + (rnd % (high - low + 1))); |
|
103 |
}
|
|
104 |
||
105 |
/*************************************************************
|
|
106 |
Generates a random iboolean value. */
|
|
107 |
UNIV_INLINE |
|
108 |
ibool |
|
109 |
ut_rnd_gen_ibool(void) |
|
110 |
/*=================*/
|
|
111 |
/* out: the random value */ |
|
112 |
{
|
|
113 |
ulint x; |
|
114 |
||
115 |
x = ut_rnd_gen_ulint(); |
|
116 |
||
117 |
if (((x >> 20) + (x >> 15)) & 1) { |
|
118 |
||
119 |
return(TRUE); |
|
120 |
} |
|
121 |
||
122 |
return(FALSE); |
|
123 |
}
|
|
124 |
||
125 |
/***********************************************************
|
|
126 |
The following function generates a hash value for a ulint integer
|
|
127 |
to a hash table of size table_size, which should be a prime
|
|
128 |
or some random number for the hash table to work reliably. */
|
|
129 |
UNIV_INLINE |
|
130 |
ulint |
|
131 |
ut_hash_ulint(
|
|
132 |
/*==========*/
|
|
133 |
/* out: hash value */ |
|
134 |
ulint key, /* in: value to be hashed */ |
|
135 |
ulint table_size) /* in: hash table size */ |
|
136 |
{
|
|
137 |
key = key ^ UT_HASH_RANDOM_MASK2; |
|
138 |
||
139 |
return(key % table_size); |
|
140 |
}
|
|
141 |
||
142 |
/*****************************************************************
|
|
143 |
Folds a pair of ulints. */
|
|
144 |
UNIV_INLINE |
|
145 |
ulint |
|
146 |
ut_fold_ulint_pair(
|
|
147 |
/*===============*/
|
|
148 |
/* out: folded value */ |
|
149 |
ulint n1, /* in: ulint */ |
|
150 |
ulint n2) /* in: ulint */ |
|
151 |
{
|
|
152 |
return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1) |
|
153 |
^ UT_HASH_RANDOM_MASK) + n2); |
|
154 |
}
|
|
155 |
||
156 |
/*****************************************************************
|
|
157 |
Folds a dulint. */
|
|
158 |
UNIV_INLINE |
|
159 |
ulint |
|
160 |
ut_fold_dulint(
|
|
161 |
/*===========*/
|
|
162 |
/* out: folded value */ |
|
163 |
dulint d) /* in: dulint */ |
|
164 |
{
|
|
165 |
return(ut_fold_ulint_pair(ut_dulint_get_low(d), |
|
166 |
ut_dulint_get_high(d))); |
|
167 |
}
|
|
168 |
||
169 |
/*****************************************************************
|
|
170 |
Folds a character string ending in the null character. */
|
|
171 |
UNIV_INLINE |
|
172 |
ulint |
|
173 |
ut_fold_string(
|
|
174 |
/*===========*/
|
|
175 |
/* out: folded value */ |
|
176 |
const char* str) /* in: null-terminated string */ |
|
177 |
{
|
|
178 |
#ifdef UNIV_DEBUG |
|
179 |
ulint i = 0; |
|
180 |
#endif
|
|
181 |
ulint fold = 0; |
|
182 |
||
183 |
ut_ad(str); |
|
184 |
||
185 |
while (*str != '\0') { |
|
186 |
||
187 |
#ifdef UNIV_DEBUG |
|
188 |
i++; |
|
189 |
ut_a(i < 100); |
|
190 |
#endif
|
|
191 |
||
192 |
fold = ut_fold_ulint_pair(fold, (ulint)(*str)); |
|
193 |
str++; |
|
194 |
} |
|
195 |
||
196 |
return(fold); |
|
197 |
}
|
|
198 |
||
199 |
/*****************************************************************
|
|
200 |
Folds a binary string. */
|
|
201 |
UNIV_INLINE |
|
202 |
ulint |
|
203 |
ut_fold_binary(
|
|
204 |
/*===========*/
|
|
205 |
/* out: folded value */ |
|
206 |
const byte* str, /* in: string of bytes */ |
|
207 |
ulint len) /* in: length */ |
|
208 |
{
|
|
209 |
const byte* str_end = str + len; |
|
210 |
ulint fold = 0; |
|
211 |
||
212 |
ut_ad(str); |
|
213 |
||
214 |
while (str < str_end) { |
|
215 |
fold = ut_fold_ulint_pair(fold, (ulint)(*str)); |
|
216 |
||
217 |
str++; |
|
218 |
} |
|
219 |
||
220 |
return(fold); |
|
221 |
}
|