#
source:
trunk/third/gmp/tests/misc.c
@
22254

Revision 22254, 8.1 KB checked in by ghudson, 19 years ago (diff) |
---|

Line | |
---|---|

1 | /* Miscellaneous test program support routines. |

2 | |

3 | Copyright 2000, 2001, 2002 Free Software Foundation, Inc. |

4 | |

5 | This file is part of the GNU MP Library. |

6 | |

7 | The GNU MP Library is free software; you can redistribute it and/or modify |

8 | it under the terms of the GNU Lesser General Public License as published by |

9 | the Free Software Foundation; either version 2.1 of the License, or (at your |

10 | option) any later version. |

11 | |

12 | The GNU MP Library is distributed in the hope that it will be useful, but |

13 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |

14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |

15 | License for more details. |

16 | |

17 | You should have received a copy of the GNU Lesser General Public License |

18 | along with the GNU MP Library; see the file COPYING.LIB. If not, write to |

19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |

20 | MA 02111-1307, USA. */ |

21 | |

22 | #include "config.h" |

23 | |

24 | #include <ctype.h> |

25 | #include <stdio.h> |

26 | #include <stdlib.h> /* for getenv */ |

27 | #include <string.h> |

28 | |

29 | #if TIME_WITH_SYS_TIME |

30 | # include <sys/time.h> /* for struct timeval */ |

31 | # include <time.h> |

32 | #else |

33 | # if HAVE_SYS_TIME_H |

34 | # include <sys/time.h> |

35 | # else |

36 | # include <time.h> |

37 | # endif |

38 | #endif |

39 | |

40 | #include "gmp.h" |

41 | #include "gmp-impl.h" |

42 | #include "tests.h" |

43 | |

44 | |

45 | /* The various tests setups and final checks, collected up together. */ |

46 | void |

47 | tests_start (void) |

48 | { |

49 | tests_memory_start (); |

50 | tests_rand_start (); |

51 | } |

52 | void |

53 | tests_end (void) |

54 | { |

55 | tests_rand_end (); |

56 | tests_memory_end (); |

57 | } |

58 | |

59 | |

60 | void |

61 | tests_rand_start (void) |

62 | { |

63 | gmp_randstate_ptr rands; |

64 | char *perform_seed; |

65 | unsigned long seed; |

66 | |

67 | if (__gmp_rands_initialized) |

68 | { |

69 | printf ("Please let tests_start() initialize the global __gmp_rands.\n"); |

70 | printf ("ie. ensure that function is called before the first use of RANDS.\n"); |

71 | abort (); |

72 | } |

73 | rands = RANDS; |

74 | |

75 | perform_seed = getenv ("GMP_CHECK_RANDOMIZE"); |

76 | if (perform_seed != NULL) |

77 | { |

78 | seed = atoi (perform_seed); |

79 | if (! (seed == 0 || seed == 1)) |

80 | { |

81 | printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed); |

82 | gmp_randseed_ui (rands, seed); |

83 | } |

84 | else |

85 | { |

86 | #if HAVE_GETTIMEOFDAY |

87 | struct timeval tv; |

88 | gettimeofday (&tv, NULL); |

89 | seed = tv.tv_sec ^ (tv.tv_usec << 12); |

90 | #else |

91 | time_t tv; |

92 | time (&tv); |

93 | seed = tv; |

94 | #endif |

95 | gmp_randseed_ui (rands, seed); |

96 | printf ("Seed GMP_CHECK_RANDOMIZE=%lu (include this in bug reports)\n", seed); |

97 | } |

98 | fflush (stdout); |

99 | } |

100 | } |

101 | void |

102 | tests_rand_end (void) |

103 | { |

104 | RANDS_CLEAR (); |

105 | } |

106 | |

107 | |

108 | /* Only used if CPU calling conventions checking is available. */ |

109 | mp_limb_t (*calling_conventions_function) _PROTO ((ANYARGS)); |

110 | |

111 | |

112 | /* Return p advanced to the next multiple of "align" bytes. "align" must be |

113 | a power of 2. Care is taken not to assume sizeof(int)==sizeof(pointer). |

114 | Using "unsigned long" avoids a warning on hpux. */ |

115 | void * |

116 | align_pointer (void *p, size_t align) |

117 | { |

118 | unsigned long d; |

119 | d = ((unsigned long) p) & (align-1); |

120 | d = (d != 0 ? align-d : 0); |

121 | return (void *) (((char *) p) + d); |

122 | } |

123 | |

124 | |

125 | /* Note that memory allocated with this function can never be freed, because |

126 | the start address of the block allocated is lost. */ |

127 | void * |

128 | __gmp_allocate_func_aligned (size_t bytes, size_t align) |

129 | { |

130 | return align_pointer ((*__gmp_allocate_func) (bytes + align-1), align); |

131 | } |

132 | |

133 | |

134 | void * |

135 | __gmp_allocate_or_reallocate (void *ptr, size_t oldsize, size_t newsize) |

136 | { |

137 | if (ptr == NULL) |

138 | return (*__gmp_allocate_func) (newsize); |

139 | else |

140 | return (*__gmp_reallocate_func) (ptr, oldsize, newsize); |

141 | } |

142 | |

143 | char * |

144 | __gmp_allocate_strdup (const char *s) |

145 | { |

146 | size_t len; |

147 | char *t; |

148 | len = strlen (s); |

149 | t = (*__gmp_allocate_func) (len+1); |

150 | memcpy (t, s, len+1); |

151 | return t; |

152 | } |

153 | |

154 | |

155 | char * |

156 | strtoupper (char *s_orig) |

157 | { |

158 | char *s; |

159 | for (s = s_orig; *s != '\0'; s++) |

160 | if (isascii (*s)) |

161 | *s = toupper (*s); |

162 | return s_orig; |

163 | } |

164 | |

165 | |

166 | void |

167 | mpz_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size) |

168 | { |

169 | ASSERT (size >= 0); |

170 | MPN_NORMALIZE (p, size); |

171 | MPZ_REALLOC (z, size); |

172 | MPN_COPY (PTR(z), p, size); |

173 | SIZ(z) = size; |

174 | } |

175 | |

176 | void |

177 | mpz_init_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size) |

178 | { |

179 | ASSERT (size >= 0); |

180 | |

181 | MPN_NORMALIZE (p, size); |

182 | ALLOC(z) = MAX (size, 1); |

183 | PTR(z) = __GMP_ALLOCATE_FUNC_LIMBS (ALLOC(z)); |

184 | SIZ(z) = size; |

185 | MPN_COPY (PTR(z), p, size); |

186 | } |

187 | |

188 | |

189 | /* Find least significant limb position where p1,size and p2,size differ. */ |

190 | mp_size_t |

191 | mpn_diff_lowest (mp_srcptr p1, mp_srcptr p2, mp_size_t size) |

192 | { |

193 | mp_size_t i; |

194 | |

195 | for (i = 0; i < size; i++) |

196 | if (p1[i] != p2[i]) |

197 | return i; |

198 | |

199 | /* no differences */ |

200 | return -1; |

201 | } |

202 | |

203 | |

204 | /* Find most significant limb position where p1,size and p2,size differ. */ |

205 | mp_size_t |

206 | mpn_diff_highest (mp_srcptr p1, mp_srcptr p2, mp_size_t size) |

207 | { |

208 | mp_size_t i; |

209 | |

210 | for (i = size-1; i >= 0; i--) |

211 | if (p1[i] != p2[i]) |

212 | return i; |

213 | |

214 | /* no differences */ |

215 | return -1; |

216 | } |

217 | |

218 | |

219 | /* Find least significant byte position where p1,size and p2,size differ. */ |

220 | mp_size_t |

221 | byte_diff_lowest (const void *p1, const void *p2, mp_size_t size) |

222 | { |

223 | mp_size_t i; |

224 | |

225 | for (i = 0; i < size; i++) |

226 | if (((const char *) p1)[i] != ((const char *) p2)[i]) |

227 | return i; |

228 | |

229 | /* no differences */ |

230 | return -1; |

231 | } |

232 | |

233 | |

234 | /* Find most significant limb position where p1,size and p2,size differ. */ |

235 | mp_size_t |

236 | byte_diff_highest (const void *p1, const void *p2, mp_size_t size) |

237 | { |

238 | mp_size_t i; |

239 | |

240 | for (i = size-1; i >= 0; i--) |

241 | if (((const char *) p1)[i] != ((const char *) p2)[i]) |

242 | return i; |

243 | |

244 | /* no differences */ |

245 | return -1; |

246 | } |

247 | |

248 | |

249 | void |

250 | mpz_set_str_or_abort (mpz_ptr z, const char *str, int base) |

251 | { |

252 | if (mpz_set_str (z, str, base) != 0) |

253 | { |

254 | fprintf (stderr, "ERROR: mpz_set_str failed\n"); |

255 | fprintf (stderr, " str = \"%s\"\n", str); |

256 | fprintf (stderr, " base = %d\n", base); |

257 | abort(); |

258 | } |

259 | } |

260 | |

261 | void |

262 | mpq_set_str_or_abort (mpq_ptr q, const char *str, int base) |

263 | { |

264 | if (mpq_set_str (q, str, base) != 0) |

265 | { |

266 | fprintf (stderr, "ERROR: mpq_set_str failed\n"); |

267 | fprintf (stderr, " str = \"%s\"\n", str); |

268 | fprintf (stderr, " base = %d\n", base); |

269 | abort(); |

270 | } |

271 | } |

272 | |

273 | void |

274 | mpf_set_str_or_abort (mpf_ptr f, const char *str, int base) |

275 | { |

276 | if (mpf_set_str (f, str, base) != 0) |

277 | { |

278 | fprintf (stderr, "ERROR mpf_set_str failed\n"); |

279 | fprintf (stderr, " str = \"%s\"\n", str); |

280 | fprintf (stderr, " base = %d\n", base); |

281 | abort(); |

282 | } |

283 | } |

284 | |

285 | |

286 | /* Whether the absolute value of z is a power of 2. */ |

287 | int |

288 | mpz_pow2abs_p (mpz_srcptr z) |

289 | { |

290 | mp_size_t size, i; |

291 | mp_srcptr ptr; |

292 | |

293 | size = SIZ (z); |

294 | if (size == 0) |

295 | return 0; /* zero is not a power of 2 */ |

296 | size = ABS (size); |

297 | |

298 | ptr = PTR (z); |

299 | for (i = 0; i < size-1; i++) |

300 | if (ptr[i] != 0) |

301 | return 0; /* non-zero low limb means not a power of 2 */ |

302 | |

303 | return POW2_P (ptr[i]); /* high limb power of 2 */ |

304 | } |

305 | |

306 | void |

307 | mpz_flipbit (mpz_ptr r, unsigned long bit) |

308 | { |

309 | if (mpz_tstbit (r, bit)) |

310 | mpz_clrbit (r, bit); |

311 | else |

312 | mpz_setbit (r, bit); |

313 | } |

314 | |

315 | |

316 | /* Exponentially distributed between 0 and 2^nbits-1, meaning the number of |

317 | bits in the result is uniformly distributed between 0 and nbits-1. |

318 | |

319 | FIXME: This is not a proper exponential distribution, since the |

320 | probability function will have a stepped shape due to using a uniform |

321 | distribution after choosing how many bits. */ |

322 | |

323 | void |

324 | mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) |

325 | { |

326 | mpz_urandomb (rop, rstate, urandom () % nbits); |

327 | } |

328 | |

329 | void |

330 | mpz_erandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) |

331 | { |

332 | mpz_erandomb (rop, rstate, nbits); |

333 | if (mpz_sgn (rop) == 0) |

334 | mpz_set_ui (rop, 1L); |

335 | } |

336 | |

337 | void |

338 | mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) |

339 | { |

340 | mpz_rrandomb (rop, rstate, urandom () % nbits); |

341 | } |

342 | |

343 | void |

344 | mpz_errandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) |

345 | { |

346 | mpz_errandomb (rop, rstate, nbits); |

347 | if (mpz_sgn (rop) == 0) |

348 | mpz_set_ui (rop, 1L); |

349 | } |

350 | |

351 | void |

352 | mpz_negrandom (mpz_ptr rop, gmp_randstate_t rstate) |

353 | { |

354 | mp_limb_t n; |

355 | _gmp_rand (&n, rstate, 1); |

356 | if (n != 0) |

357 | mpz_neg (rop, rop); |

358 | } |

359 | |

360 | mp_limb_t |

361 | urandom (void) |

362 | { |

363 | #if GMP_NAIL_BITS == 0 |

364 | mp_limb_t n; |

365 | _gmp_rand (&n, RANDS, BITS_PER_MP_LIMB); |

366 | return n; |

367 | #else |

368 | mp_limb_t n[2]; |

369 | _gmp_rand (n, RANDS, BITS_PER_MP_LIMB); |

370 | return n[0] + (n[1] << GMP_NUMB_BITS); |

371 | #endif |

372 | } |

**Note:**See TracBrowser for help on using the repository browser.