Rizin
unix-like reverse engineering framework and cli tools
prng.h
Go to the documentation of this file.
1 /******************************************************************************/
2 #ifdef JEMALLOC_H_TYPES
3 
4 /*
5  * Simple linear congruential pseudo-random number generator:
6  *
7  * prng(y) = (a*x + c) % m
8  *
9  * where the following constants ensure maximal period:
10  *
11  * a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.
12  * c == Odd number (relatively prime to 2^n).
13  * m == 2^32
14  *
15  * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.
16  *
17  * This choice of m has the disadvantage that the quality of the bits is
18  * proportional to bit position. For example, the lowest bit has a cycle of 2,
19  * the next has a cycle of 4, etc. For this reason, we prefer to use the upper
20  * bits.
21  */
22 
23 #define PRNG_A_32 UINT32_C(1103515241)
24 #define PRNG_C_32 UINT32_C(12347)
25 
26 #define PRNG_A_64 UINT64_C(6364136223846793005)
27 #define PRNG_C_64 UINT64_C(1442695040888963407)
28 
29 #endif /* JEMALLOC_H_TYPES */
30 /******************************************************************************/
31 #ifdef JEMALLOC_H_STRUCTS
32 
33 #endif /* JEMALLOC_H_STRUCTS */
34 /******************************************************************************/
35 #ifdef JEMALLOC_H_EXTERNS
36 
37 #endif /* JEMALLOC_H_EXTERNS */
38 /******************************************************************************/
39 #ifdef JEMALLOC_H_INLINES
40 
41 #ifndef JEMALLOC_ENABLE_INLINE
44 size_t prng_state_next_zu(size_t state);
45 
46 uint32_t prng_lg_range_u32(uint32_t *state, unsigned lg_range,
47  bool atomic);
48 uint64_t prng_lg_range_u64(uint64_t *state, unsigned lg_range);
49 size_t prng_lg_range_zu(size_t *state, unsigned lg_range, bool atomic);
50 
53 size_t prng_range_zu(size_t *state, size_t range, bool atomic);
54 #endif
55 
56 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PRNG_C_))
59 {
60 
61  return ((state * PRNG_A_32) + PRNG_C_32);
62 }
63 
66 {
67 
68  return ((state * PRNG_A_64) + PRNG_C_64);
69 }
70 
73 {
74 
75 #if LG_SIZEOF_PTR == 2
76  return ((state * PRNG_A_32) + PRNG_C_32);
77 #elif LG_SIZEOF_PTR == 3
78  return ((state * PRNG_A_64) + PRNG_C_64);
79 #else
80 #error Unsupported pointer size
81 #endif
82 }
83 
85 prng_lg_range_u32(uint32_t *state, unsigned lg_range, bool atomic)
86 {
87  uint32_t ret, state1;
88 
89  if (lg_range <1 || lg_range >32) {
90  return 0;
91  }
92 #if 0
93  assert(lg_range > 0);
94  assert(lg_range <= 32);
95 #endif
96 
97  if (atomic) {
98  uint32_t state0;
99 
100  do {
101  state0 = atomic_read_uint32(state);
102  state1 = prng_state_next_u32(state0);
103  } while (atomic_cas_uint32(state, state0, state1));
104  } else {
105  state1 = prng_state_next_u32(*state);
106  *state = state1;
107  }
108  ret = state1 >> (32 - lg_range);
109 
110  return (ret);
111 }
112 
113 /* 64-bit atomic operations cannot be supported on all relevant platforms. */
115 prng_lg_range_u64(uint64_t *state, unsigned lg_range)
116 {
117  uint64_t ret, state1;
118 
119  if (lg_range <1 || lg_range > 64) {
120  return 0;
121  }
122 #if 0
123  assert(lg_range > 0);
124  assert(lg_range <= 64);
125 #endif
126 
127  state1 = prng_state_next_u64(*state);
128  *state = state1;
129  ret = state1 >> (64 - lg_range);
130 
131  return (ret);
132 }
133 
135 prng_lg_range_zu(size_t *state, unsigned lg_range, bool atomic)
136 {
137  size_t ret, state1;
138 
139 #if 0
140  assert(lg_range > 0);
141  assert(lg_range <= ZU(1) << (3 + LG_SIZEOF_PTR));
142 #endif
143 
144  if (atomic) {
145  size_t state0;
146 
147  do {
148  state0 = atomic_read_z(state);
149  state1 = prng_state_next_zu(state0);
150  } while (atomic_cas_z(state, state0, state1));
151  } else {
152  state1 = prng_state_next_zu(*state);
153  *state = state1;
154  }
155  ret = state1 >> ((ZU(1) << (3 + LG_SIZEOF_PTR)) - lg_range);
156 
157  return (ret);
158 }
159 
162 {
163  uint32_t ret;
164  unsigned lg_range;
165 
166 #if 0
167  assert(range > 1);
168 #endif
169 if (range <2) {
170 return 0;
171 }
172 
173  /* Compute the ceiling of lg(range). */
174  lg_range = ffs_u32(pow2_ceil_u32(range)) - 1;
175 
176  /* Generate a result in [0..range) via repeated trial. */
177  do {
178  ret = prng_lg_range_u32(state, lg_range, atomic);
179  } while (ret >= range);
180 
181  return (ret);
182 }
183 
186 {
187  uint64_t ret;
188  unsigned lg_range;
189 
190  // assert(range > 1);
191 
192  /* Compute the ceiling of lg(range). */
193  lg_range = ffs_u64(pow2_ceil_u64(range)) - 1;
194 
195  /* Generate a result in [0..range) via repeated trial. */
196  do {
197  ret = prng_lg_range_u64(state, lg_range);
198  } while (ret >= range);
199 
200  return (ret);
201 }
202 
204 prng_range_zu(size_t *state, size_t range, bool atomic)
205 {
206  size_t ret;
207  unsigned lg_range;
208  assert(range > 1);
209 
210  /* Compute the ceiling of lg(range). */
211  lg_range = ffs_u64(pow2_ceil_u64(range)) - 1;
212 
213  /* Generate a result in [0..range) via repeated trial. */
214  do {
215  ret = prng_lg_range_zu(state, lg_range, atomic);
216  } while (ret >= range);
217 
218  return (ret);
219 }
220 #endif
221 
222 #endif /* JEMALLOC_H_INLINES */
223 /******************************************************************************/
#define LG_SIZEOF_PTR
Definition: jemalloc.h:51
#define ZU(z)
#define JEMALLOC_ALWAYS_INLINE
assert(limit<=UINT32_MAX/2)
#define pow2_ceil_u64
#define prng_state_next_u64
#define prng_range_u32
#define prng_state_next_zu
#define prng_lg_range_u64
#define prng_lg_range_u32
#define prng_state_next_u32
#define atomic_cas_uint32
#define ffs_u64
#define prng_range_zu
#define atomic_cas_z
#define prng_lg_range_zu
#define pow2_ceil_u32
#define ffs_u32
#define prng_range_u64
unsigned int uint32_t
Definition: sftypes.h:29
unsigned long uint64_t
Definition: sftypes.h:28
Definition: dis.h:43