Introduction
Introduction Statistics Contact Development Disclaimer Help
zrand.c - libzahl - big integer library
git clone git://git.suckless.org/libzahl
Log
Files
Refs
README
LICENSE
---
zrand.c (3981B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include "internals.h"
3
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <time.h>
7 #include <unistd.h>
8
9 #ifndef FAST_RANDOM_PATHNAME
10 # define FAST_RANDOM_PATHNAME "/dev/urandom"
11 #endif
12
13 #ifndef SECURE_RANDOM_PATHNAME
14 # define SECURE_RANDOM_PATHNAME "/dev/random"
15 #endif
16
17
18 static void
19 zrand_libc_rand(void *out, size_t n, void *statep)
20 {
21 static char inited = 0;
22
23 unsigned int ri;
24 double rd;
25 unsigned char *buf = out;
26
27 if (!inited) {
28 inited = 1;
29 srand((unsigned)((intptr_t)out | time(NULL)));
30 }
31
32 while (n--) {
33 ri = (unsigned)rand();
34 rd = (double)ri / ((double)RAND_MAX + 1);
35 #ifdef GOOD_RAND
36 rd *= 256 * 256;
37 ri = (unsigned int)rd;
38 buf[n] = (unsigned char)((ri >> 0) & 255);
39 if (!n--) break;
40 buf[n] = (unsigned char)((ri >> 8) & 255);
41 #else
42 rd *= 256;
43 buf[n] = (unsigned char)rd;
44 #endif
45 }
46
47 (void) statep;
48 }
49
50 static void
51 zrand_libc_rand48(void *out, size_t n, void *statep)
52 {
53 static char inited = 0;
54
55 long int r0, r1;
56 unsigned char *buf = out;
57
58 if (!inited) {
59 inited = 1;
60 srand48((intptr_t)out | time(NULL));
61 }
62
63 while (n--) {
64 r0 = lrand48() & 15;
65 r1 = lrand48() & 15;
66 buf[n] = (unsigned char)((r0 << 4) | r1);
67 }
68
69 (void) statep;
70 }
71
72 static void
73 zrand_libc_random(void *out, size_t n, void *statep)
74 {
75 static char inited = 0;
76
77 long int ri;
78 unsigned char *buf = out;
79
80 if (!inited) {
81 inited = 1;
82 srandom((unsigned)((intptr_t)out | time(NULL)));
83 }
84
85 while (n--) {
86 ri = random();
87 buf[n] = (unsigned char)((ri >> 0) & 255);
88 if (!n--) break;
89 buf[n] = (unsigned char)((ri >> 8) & 255);
90 if (!n--) break;
91 buf[n] = (unsigned char)((ri >> 16) & 255);
92 }
93
94 (void) statep;
95 }
96
97 static void
98 zrand_fd(void *out, size_t n, void *statep)
99 {
100 int fd = *(int *)statep;
101 ssize_t read_just;
102 size_t read_total = 0;
103 char *buf = out;
104
105 while (n) {
106 read_just = read(fd, buf + read_total, n);
107 if (check(read_just < 0))
108 libzahl_failure(errno);
109 read_total += (size_t)read_just;
110 n -= (size_t)read_just;
111 }
112 }
113
114 static void
115 zrand_get_random_bits(z_t r, size_t bits, void (*fun)(void *, size_t, vo…
116 {
117 size_t n, chars = CEILING_BITS_TO_CHARS(bits);
118 zahl_char_t mask = 1;
119
120 ENSURE_SIZE(r, chars);
121
122 fun(r->chars, chars * sizeof(zahl_char_t), statep);
123
124 bits = BITS_IN_LAST_CHAR(bits);
125 mask <<= bits;
126 mask -= 1;
127
128 r->chars[chars - 1] &= mask;
129 for (n = chars; n--;) {
130 if (likely(r->chars[n])) {
131 r->used = n + 1;
132 SET_SIGNUM(r, 1);
133 return;
134 }
135 }
136 SET_SIGNUM(r, 0);
137 }
138
139 void
140 zrand(z_t r, enum zranddev dev, enum zranddist dist, z_t n)
141 {
142 #define RANDOM_UNIFORM(RETRY)\
143 do {\
144 if (check(znegative(n)))\
145 libzahl_failure(-ZERROR_NEGATIVE);\
146 bits = zbits(n);\
147 do\
148 zrand_get_random_bits(r, bits, random_fun, state…
149 while (RETRY && unlikely(zcmpmag(r, n) > 0));\
150 } while (0)
151
152
153 const char *pathname = 0;
154 size_t bits;
155 int fd = -1;
156 void *statep = 0;
157 void (*random_fun)(void *, size_t, void *) = &zrand_fd;
158
159 switch (dev) {
160 case FAST_RANDOM:
161 pathname = FAST_RANDOM_PATHNAME;
162 break;
163 case SECURE_RANDOM:
164 pathname = SECURE_RANDOM_PATHNAME;
165 break;
166 case LIBC_RAND_RANDOM:
167 random_fun = &zrand_libc_rand;
168 break;
169 case DEFAULT_RANDOM:
170 case FASTEST_RANDOM:
171 case LIBC_RANDOM_RANDOM:
172 random_fun = &zrand_libc_random;
173 break;
174 case LIBC_RAND48_RANDOM:
175 random_fun = &zrand_libc_rand48;
176 break;
177 default:
178 libzahl_failure(EINVAL);
179 }
180
181 if (unlikely(zzero(n))) {
182 SET_SIGNUM(r, 0);
183 return;
184 }
185
186 if (pathname) {
187 fd = open(pathname, O_RDONLY);
188 if (check(fd < 0))
189 libzahl_failure(errno);
190 statep = &fd;
191 }
192
193 switch (dist) {
194 case QUASIUNIFORM:
195 RANDOM_UNIFORM(0);
196 zadd(r, r, libzahl_const_1);
197 zmul(r, r, n);
198 zrsh(r, r, bits);
199 break;
200
201 case UNIFORM:
202 RANDOM_UNIFORM(1);
203 break;
204
205 case MODUNIFORM:
206 RANDOM_UNIFORM(0);
207 if (unlikely(zcmpmag(r, n) > 0))
208 zsub(r, r, n);
209 break;
210
211 default:
212 #if !defined(ZAHL_UNSAFE)
213 libzahl_failure(EINVAL);
214 #endif
215 break;
216 }
217
218 if (fd >= 0)
219 close(fd);
220 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.