Annotation of OpenXM_contrib/gmp/tests/rand/findlc.c, Revision 1.1.1.1
1.1 maekawa 1: /*
2: Copyright (C) 2000 Free Software Foundation, Inc.
3:
4: This file is part of the GNU MP Library.
5:
6: The GNU MP Library is free software; you can redistribute it and/or modify
7: it under the terms of the GNU Lesser General Public License as published by
8: the Free Software Foundation; either version 2.1 of the License, or (at your
9: option) any later version.
10:
11: The GNU MP Library is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14: License for more details.
15:
16: You should have received a copy of the GNU Lesser General Public License
17: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
18: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19: MA 02111-1307, USA.
20: */
21:
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <unistd.h>
25: #include <signal.h>
26: #include <math.h>
27: #include "gmp.h"
28: #include "gmpstat.h"
29:
30: #define RCSID(msg) \
31: static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
32:
33: RCSID("$Id: findlc.c,v 1.3 2000/07/24 17:04:39 tege Exp $");
34:
35: int g_debug = 0;
36:
37: static mpz_t a;
38:
39: static void
40: sh_status (int sig)
41: {
42: printf ("sh_status: signal %d caught. dumping status.\n", sig);
43:
44: printf (" a = ");
45: mpz_out_str (stdout, 10, a);
46: printf ("\n");
47: fflush (stdout);
48:
49: if (SIGSEGV == sig) /* remove SEGV handler */
50: signal (SIGSEGV, SIG_DFL);
51: }
52:
53: /* Input is a modulus (m). We shall find multiplyer (a) and adder (c)
54: conforming to the rules found in the first comment block in file
55: mpz/urandom.c.
56:
57: Then run a spectral test on the generator and discard any
58: multipliers not passing. */
59:
60: /* TODO:
61:
62: . find a better algorithm than a+=8; bigger jumps perhaps?
63:
64: */
65:
66: void
67: mpz_true_random (mpz_t s, unsigned long int nbits)
68: {
69: #if __FreeBSD__
70: FILE *fs;
71: char c[1];
72: int i;
73:
74: mpz_set_ui (s, 0);
75: for (i = 0; i < nbits; i += 8)
76: {
77: for (;;)
78: {
79: int nread;
80: fs = fopen ("/dev/random", "r");
81: nread = fread (c, 1, 1, fs);
82: fclose (fs);
83: if (nread != 0)
84: break;
85: sleep (1);
86: }
87: mpz_mul_2exp (s, s, 8);
88: mpz_add_ui (s, s, ((unsigned long int) c[0]) & 0xff);
89: printf ("%d random bits\n", i + 8);
90: }
91: if (nbits % 8 != 0)
92: mpz_mod_2exp (s, s, nbits);
93: #endif
94: }
95:
96: int
97: main (int argc, char *argv[])
98: {
99: const char usage[] = "usage: findlc [-dv] m2exp [low_merit [high_merit]]\n";
100: int f;
101: int v_lose, m_lose, v_best, m_best;
102: int c;
103: int debug = 1;
104: int cnt_high_merit;
105: mpz_t m;
106: unsigned long int m2exp;
107: #define DIMS 6 /* dimensions run in spectral test */
108: mpf_t v[DIMS-1]; /* spectral test result (there's no v
109: for 1st dimension */
110: mpf_t f_merit, low_merit, high_merit;
111: mpz_t acc, minus8;
112: mpz_t min, max;
113: mpz_t s;
114:
115:
116: mpz_init (m);
117: mpz_init (a);
118: for (f = 0; f < DIMS-1; f++)
119: mpf_init (v[f]);
120: mpf_init (f_merit);
121: mpf_init_set_d (low_merit, .1);
122: mpf_init_set_d (high_merit, .1);
123:
124: while ((c = getopt (argc, argv, "a:di:hv")) != -1)
125: switch (c)
126: {
127: case 'd': /* debug */
128: g_debug++;
129: break;
130:
131: case 'v': /* print version */
132: puts (rcsid[1]);
133: exit (0);
134:
135: case 'h':
136: case '?':
137: default:
138: fputs (usage, stderr);
139: exit (1);
140: }
141:
142: argc -= optind;
143: argv += optind;
144:
145: if (argc < 1)
146: {
147: fputs (usage, stderr);
148: exit (1);
149: }
150:
151: /* Install signal handler. */
152: if (SIG_ERR == signal (SIGSEGV, sh_status))
153: {
154: perror ("signal (SIGSEGV)");
155: exit (1);
156: }
157: if (SIG_ERR == signal (SIGHUP, sh_status))
158: {
159: perror ("signal (SIGHUP)");
160: exit (1);
161: }
162:
163: printf ("findlc: version: %s\n", rcsid[1]);
164: m2exp = atol (argv[0]);
165: mpz_init_set_ui (m, 1);
166: mpz_mul_2exp (m, m, m2exp);
167: printf ("m = 0x");
168: mpz_out_str (stdout, 16, m);
169: puts ("");
170:
171: if (argc > 1) /* have low_merit */
172: mpf_set_str (low_merit, argv[1], 0);
173: if (argc > 2) /* have high_merit */
174: mpf_set_str (high_merit, argv[2], 0);
175:
176: if (debug)
177: {
178: fprintf (stderr, "low_merit = ");
179: mpf_out_str (stderr, 10, 2, low_merit);
180: fprintf (stderr, "; high_merit = ");
181: mpf_out_str (stderr, 10, 2, high_merit);
182: fputs ("\n", stderr);
183: }
184:
185: mpz_init (minus8);
186: mpz_set_si (minus8, -8L);
187: mpz_init_set_ui (acc, 0);
188: mpz_init (s);
189: mpz_init_set_d (min, 0.01 * pow (2.0, (double) m2exp));
190: mpz_init_set_d (max, 0.99 * pow (2.0, (double) m2exp));
191:
192: mpz_true_random (s, m2exp); /* Start. */
193: mpz_setbit (s, 0); /* Make it odd. */
194:
195: v_best = m_best = 2*(DIMS-1);
196: for (;;)
197: {
198: mpz_add (acc, acc, s);
199: mpz_mod_2exp (acc, acc, m2exp);
200: #if later
201: mpz_and_si (a, acc, -8L);
202: #else
203: mpz_and (a, acc, minus8);
204: #endif
205: mpz_add_ui (a, a, 5);
206: if (mpz_cmp (a, min) <= 0 || mpz_cmp (a, max) >= 0)
207: continue;
208:
209: spectral_test (v, DIMS, a, m);
210: for (f = 0, v_lose = m_lose = 0, cnt_high_merit = DIMS-1;
211: f < DIMS-1; f++)
212: {
213: merit (f_merit, f + 2, v[f], m);
214:
215: if (mpf_cmp_ui (v[f], 1 << (30 / (f + 2) + (f == 2))) < 0)
216: v_lose++;
217:
218: if (mpf_cmp (f_merit, low_merit) < 0)
219: m_lose++;
220:
221: if (mpf_cmp (f_merit, high_merit) >= 0)
222: cnt_high_merit--;
223: }
224:
225: if (0 == v_lose && 0 == m_lose)
226: {
227: mpz_out_str (stdout, 10, a); puts (""); fflush (stdout);
228: if (0 == cnt_high_merit)
229: break; /* leave loop */
230: }
231: if (v_lose < v_best)
232: {
233: v_best = v_lose;
234: printf ("best (v_lose=%d; m_lose=%d): ", v_lose, m_lose);
235: mpz_out_str (stdout, 10, a); puts (""); fflush (stdout);
236: }
237: if (m_lose < m_best)
238: {
239: m_best = m_lose;
240: printf ("best (v_lose=%d; m_lose=%d): ", v_lose, m_lose);
241: mpz_out_str (stdout, 10, a); puts (""); fflush (stdout);
242: }
243: }
244:
245: mpz_clear (m);
246: mpz_clear (a);
247: for (f = 0; f < DIMS-1; f++)
248: mpf_clear (v[f]);
249: mpf_clear (f_merit);
250: mpf_clear (low_merit);
251: mpf_clear (high_merit);
252:
253: printf ("done.\n");
254: return 0;
255: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>