1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <stdio.h>
21: #include <math.h>
22: #include <gmp.h>
23: #include <string.h>
24: #include <limits.h>
25: #include <assert.h>
26:
27: #define PRINT_ERRORS 0
28:
29: #define TOL 80
30: #define N2 17
31: #define FRAC (32*4)
32:
33: #define mpbpl (CHAR_BIT * sizeof (mp_limb_t))
34: #define SZ (FRAC / mpbpl + 1)
35: typedef mp_limb_t mp1[SZ], mp2[SZ * 2];
36:
37:
38: static const char exp1[102] = "2"
39: "b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a7"
40: "84d9045190cfef324e7738926cfbe5f4bf8d8d8c31d763da07";
41: static const char hexdig[] = "0123456789abcdef";
42:
43: static void
44: print_mpn_hex (const mp_limb_t *x, unsigned size)
45: {
46: char value[size + 1];
47: unsigned i;
48: const unsigned final = (size * 4 > SZ * mpbpl) ? SZ * mpbpl / 4 : size;
49:
50: memset (value, '0', size);
51:
52: for (i = 0; i < final ; i++)
53: value[size - 1 - i] = hexdig[x[i * 4 / mpbpl] >> (i * 4) % mpbpl & 0xf];
54:
55: value[size] = '\0';
56: fputs (value, stdout);
57: }
58:
59: static void
60: exp_mpn (mp1 ex, mp1 x)
61: {
62: unsigned n;
63: mp1 xp;
64: mp2 tmp;
65: mp_limb_t chk, round;
66: mp1 tol;
67:
68: memset (xp, 0, sizeof (mp1));
69: memset (ex, 0, sizeof (mp1));
70: xp[FRAC / mpbpl] = (mp_limb_t)1 << FRAC % mpbpl;
71: memset (tol,0, sizeof (mp1));
72: tol[(FRAC - TOL) / mpbpl] = (mp_limb_t)1 << (FRAC - TOL) % mpbpl;
73:
74: n = 0;
75:
76: do
77: {
78:
79:
80: mpn_mul_n (tmp, xp, x, SZ);
81: assert (tmp[SZ * 2 - 1] == 0);
82: if (n > 0)
83: round = mpn_divmod_1 (xp, tmp + FRAC / mpbpl, SZ, n);
84: chk = mpn_add_n (ex, ex, xp, SZ);
85: assert (chk == 0);
86: n++;
87: assert (n < 80);
88: }
89: while (n < 10 || mpn_cmp (xp, tol, SZ) >= 0);
90: }
91:
92: static int
93: mpn_bitsize(const mp_limb_t *SRC_PTR, mp_size_t SIZE)
94: {
95: int i, j;
96: for (i = SIZE - 1; i > 0; i--)
97: if (SRC_PTR[i] != 0)
98: break;
99: for (j = mpbpl - 1; j >= 0; j--)
100: if ((SRC_PTR[i] & (mp_limb_t)1 << j) != 0)
101: break;
102:
103: return i * mpbpl + j;
104: }
105:
106: int
107: main (void)
108: {
109: mp1 ex, x, xt, e2, e3;
110: int i;
111: int errors = 0;
112: int failures = 0;
113: mp1 maxerror;
114: int maxerror_s = 0;
115: const double sf = pow (2, mpbpl);
116:
117:
118: assert (FRAC / mpbpl * mpbpl == FRAC);
119:
120: memset (maxerror, 0, sizeof (mp1));
121: memset (xt, 0, sizeof (mp1));
122: xt[(FRAC - N2) / mpbpl] = (mp_limb_t)1 << (FRAC - N2) % mpbpl;
123:
124: for (i = 0; i < 1 << N2; i++)
125: {
126: int e2s, e3s, j;
127: double de2;
128:
129: mpn_mul_1 (x,xt,SZ,i);
130: exp_mpn (ex, x);
131: de2 = exp (i / (double) (1 << N2));
132: for (j = SZ-1; j >= 0; j--)
133: {
134: e2[j] = (mp_limb_t) de2;
135: de2 = (de2 - e2[j]) * sf;
136: }
137: if (mpn_cmp (ex,e2,SZ) >= 0)
138: mpn_sub_n (e3,ex,e2,SZ);
139: else
140: mpn_sub_n (e3,e2,ex,SZ);
141:
142: e2s = mpn_bitsize (e2,SZ);
143: e3s = mpn_bitsize (e3,SZ);
144: if (e3s >= 0 && e2s - e3s < 54)
145: {
146: #if PRINT_ERRORS
147: printf ("%06x ", i * (0x100000 / (1 << N2)));
148: print_mpn_hex (ex, (FRAC / 4) + 1);
149: fputs ("\n ",stdout);
150: print_mpn_hex (e2, (FRAC / 4) + 1);
151: printf ("\n %c ",
152: e2s - e3s < 54 ? e2s - e3s == 53 ? 'e' : 'F' : 'P');
153: print_mpn_hex (e3, (FRAC / 4) + 1);
154: putchar ('\n');
155: #endif
156: errors += (e2s - e3s == 53);
157: failures += (e2s - e3s < 53);
158: }
159: if (e3s >= maxerror_s
160: && mpn_cmp (e3, maxerror, SZ) > 0)
161: {
162: memcpy (maxerror, e3, sizeof (mp1));
163: maxerror_s = e3s;
164: }
165: }
166:
167:
168: memset (x, '\0', sizeof (mp1));
169: x[FRAC / mpbpl] = (mp_limb_t)1 << FRAC % mpbpl;
170: exp_mpn (ex, x);
171:
172: memset (e2, '\0', sizeof (mp1));
173: for (i = -1; i < 100 && i < FRAC / 4; i++)
174: e2[(FRAC - i * 4 - 4) / mpbpl] |= ((mp_limb_t) (strchr (hexdig,
175: exp1[i + 1])
176: - hexdig)
177: << (FRAC - i * 4 - 4) % mpbpl);
178:
179: if (mpn_cmp (ex, e2, SZ) >= 0)
180: mpn_sub_n (e3, ex, e2, SZ);
181: else
182: mpn_sub_n (e3, e2, ex, SZ);
183:
184: printf ("%d failures; %d errors; error rate %0.2f%%\n", failures, errors,
185: errors * 100.0 / (double) (1 << N2));
186: fputs ("maximum error: ", stdout);
187: print_mpn_hex (maxerror, (FRAC / 4) + 1);
188: fputs ("\nerror in exp(1): ", stdout);
189: print_mpn_hex (e3, (FRAC / 4) + 1);
190: putchar ('\n');
191:
192: return failures == 0 ? 0 : 1;
193: }