~ubuntu-branches/ubuntu/utopic/dropbear/utopic-proposed

« back to all changes in this revision

Viewing changes to libtommath/demo/demo.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Johnston
  • Date: 2005-12-08 19:20:21 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051208192021-nyp9rwnt77nsg6ty
Tags: 0.47-1
* New upstream release.
* SECURITY: Fix incorrect buffer sizing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 
10
10
#include "tommath.h"
11
11
 
12
 
void ndraw(mp_int *a, char *name)
 
12
void ndraw(mp_int * a, char *name)
13
13
{
14
 
   char buf[4096];
 
14
   char buf[16000];
 
15
 
15
16
   printf("%s: ", name);
16
 
   mp_toradix(a, buf, 64);
 
17
   mp_toradix(a, buf, 10);
17
18
   printf("%s\n", buf);
18
19
}
19
20
 
20
 
static void draw(mp_int *a)
 
21
static void draw(mp_int * a)
21
22
{
22
23
   ndraw(a, "");
23
24
}
39
40
int myrng(unsigned char *dst, int len, void *dat)
40
41
{
41
42
   int x;
42
 
   for (x = 0; x < len; x++) dst[x] = rand() & 0xFF;
 
43
 
 
44
   for (x = 0; x < len; x++)
 
45
      dst[x] = rand() & 0xFF;
43
46
   return len;
44
47
}
45
48
 
46
49
 
47
50
 
48
 
   char cmd[4096], buf[4096];
 
51
char cmd[4096], buf[4096];
49
52
int main(void)
50
53
{
51
54
   mp_int a, b, c, d, e, f;
52
 
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, inv_n,
53
 
                 div2_n, mul2_n, add_d_n, sub_d_n, t;
 
55
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
 
56
      gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t;
54
57
   unsigned rr;
55
58
   int i, n, err, cnt, ix, old_kara_m, old_kara_s;
 
59
   mp_digit mp;
56
60
 
57
61
 
58
62
   mp_init(&a);
65
69
   srand(time(NULL));
66
70
 
67
71
#if 0
68
 
  // test mp_get_int
69
 
  printf("Testing: mp_get_int\n");
70
 
  for(i=0;i<1000;++i) {
71
 
    t = ((unsigned long)rand()*rand()+1)&0xFFFFFFFF;
72
 
    mp_set_int(&a,t);
73
 
    if (t!=mp_get_int(&a)) { 
74
 
      printf("mp_get_int() bad result!\n");
75
 
      return 1;
76
 
    }
77
 
  }
78
 
  mp_set_int(&a,0);
79
 
  if (mp_get_int(&a)!=0)
80
 
  { printf("mp_get_int() bad result!\n");
81
 
    return 1;
82
 
  }
83
 
  mp_set_int(&a,0xffffffff);
84
 
  if (mp_get_int(&a)!=0xffffffff)
85
 
  { printf("mp_get_int() bad result!\n");
86
 
    return 1;
87
 
  }
88
 
 
89
 
  // test mp_sqrt
90
 
  printf("Testing: mp_sqrt\n");
91
 
  for (i=0;i<1000;++i) { 
92
 
    printf("%6d\r", i); fflush(stdout);
93
 
    n = (rand()&15)+1;
94
 
    mp_rand(&a,n);
95
 
    if (mp_sqrt(&a,&b) != MP_OKAY)
96
 
    { printf("mp_sqrt() error!\n");
97
 
      return 1;
98
 
    }
99
 
    mp_n_root(&a,2,&a);
100
 
    if (mp_cmp_mag(&b,&a) != MP_EQ)
101
 
    { printf("mp_sqrt() bad result!\n");
102
 
      return 1;
103
 
    }
104
 
  }
105
 
 
106
 
  printf("\nTesting: mp_is_square\n");
107
 
  for (i=0;i<1000;++i) {
108
 
    printf("%6d\r", i); fflush(stdout);
109
 
 
110
 
    /* test mp_is_square false negatives */
111
 
    n = (rand()&7)+1;
112
 
    mp_rand(&a,n);
113
 
    mp_sqr(&a,&a);
114
 
    if (mp_is_square(&a,&n)!=MP_OKAY) { 
115
 
      printf("fn:mp_is_square() error!\n");
116
 
      return 1;
117
 
    }
118
 
    if (n==0) { 
119
 
      printf("fn:mp_is_square() bad result!\n");
120
 
      return 1;
121
 
    }
122
 
 
123
 
    /* test for false positives */
124
 
    mp_add_d(&a, 1, &a);
125
 
    if (mp_is_square(&a,&n)!=MP_OKAY) { 
126
 
      printf("fp:mp_is_square() error!\n");
127
 
      return 1;
128
 
    }
129
 
    if (n==1) { 
130
 
      printf("fp:mp_is_square() bad result!\n");
131
 
      return 1;
132
 
    }
133
 
 
134
 
  }
135
 
  printf("\n\n");
 
72
   // test montgomery 
 
73
   printf("Testing montgomery...\n");
 
74
   for (i = 1; i < 10; i++) {
 
75
      printf("Testing digit size: %d\n", i);
 
76
      for (n = 0; n < 1000; n++) {
 
77
         mp_rand(&a, i);
 
78
         a.dp[0] |= 1;
 
79
 
 
80
         // let's see if R is right
 
81
         mp_montgomery_calc_normalization(&b, &a);
 
82
         mp_montgomery_setup(&a, &mp);
 
83
 
 
84
         // now test a random reduction 
 
85
         for (ix = 0; ix < 100; ix++) {
 
86
             mp_rand(&c, 1 + abs(rand()) % (2*i));
 
87
             mp_copy(&c, &d);
 
88
             mp_copy(&c, &e);
 
89
 
 
90
             mp_mod(&d, &a, &d);
 
91
             mp_montgomery_reduce(&c, &a, mp);
 
92
             mp_mulmod(&c, &b, &a, &c);
 
93
 
 
94
             if (mp_cmp(&c, &d) != MP_EQ) { 
 
95
printf("d = e mod a, c = e MOD a\n");
 
96
mp_todecimal(&a, buf); printf("a = %s\n", buf);
 
97
mp_todecimal(&e, buf); printf("e = %s\n", buf);
 
98
mp_todecimal(&d, buf); printf("d = %s\n", buf);
 
99
mp_todecimal(&c, buf); printf("c = %s\n", buf);
 
100
printf("compare no compare!\n"); exit(EXIT_FAILURE); }
 
101
         }
 
102
      }
 
103
   }
 
104
   printf("done\n");
 
105
 
 
106
   // test mp_get_int
 
107
   printf("Testing: mp_get_int\n");
 
108
   for (i = 0; i < 1000; ++i) {
 
109
      t = ((unsigned long) rand() * rand() + 1) & 0xFFFFFFFF;
 
110
      mp_set_int(&a, t);
 
111
      if (t != mp_get_int(&a)) {
 
112
         printf("mp_get_int() bad result!\n");
 
113
         return 1;
 
114
      }
 
115
   }
 
116
   mp_set_int(&a, 0);
 
117
   if (mp_get_int(&a) != 0) {
 
118
      printf("mp_get_int() bad result!\n");
 
119
      return 1;
 
120
   }
 
121
   mp_set_int(&a, 0xffffffff);
 
122
   if (mp_get_int(&a) != 0xffffffff) {
 
123
      printf("mp_get_int() bad result!\n");
 
124
      return 1;
 
125
   }
 
126
   // test mp_sqrt
 
127
   printf("Testing: mp_sqrt\n");
 
128
   for (i = 0; i < 1000; ++i) {
 
129
      printf("%6d\r", i);
 
130
      fflush(stdout);
 
131
      n = (rand() & 15) + 1;
 
132
      mp_rand(&a, n);
 
133
      if (mp_sqrt(&a, &b) != MP_OKAY) {
 
134
         printf("mp_sqrt() error!\n");
 
135
         return 1;
 
136
      }
 
137
      mp_n_root(&a, 2, &a);
 
138
      if (mp_cmp_mag(&b, &a) != MP_EQ) {
 
139
         printf("mp_sqrt() bad result!\n");
 
140
         return 1;
 
141
      }
 
142
   }
 
143
 
 
144
   printf("\nTesting: mp_is_square\n");
 
145
   for (i = 0; i < 1000; ++i) {
 
146
      printf("%6d\r", i);
 
147
      fflush(stdout);
 
148
 
 
149
      /* test mp_is_square false negatives */
 
150
      n = (rand() & 7) + 1;
 
151
      mp_rand(&a, n);
 
152
      mp_sqr(&a, &a);
 
153
      if (mp_is_square(&a, &n) != MP_OKAY) {
 
154
         printf("fn:mp_is_square() error!\n");
 
155
         return 1;
 
156
      }
 
157
      if (n == 0) {
 
158
         printf("fn:mp_is_square() bad result!\n");
 
159
         return 1;
 
160
      }
 
161
 
 
162
      /* test for false positives */
 
163
      mp_add_d(&a, 1, &a);
 
164
      if (mp_is_square(&a, &n) != MP_OKAY) {
 
165
         printf("fp:mp_is_square() error!\n");
 
166
         return 1;
 
167
      }
 
168
      if (n == 1) {
 
169
         printf("fp:mp_is_square() bad result!\n");
 
170
         return 1;
 
171
      }
 
172
 
 
173
   }
 
174
   printf("\n\n");
136
175
 
137
176
   /* test for size */
138
 
   for (ix = 10; ix < 256; ix++) {
139
 
       printf("Testing (not safe-prime): %9d bits    \r", ix); fflush(stdout);
140
 
       err = mp_prime_random_ex(&a, 8, ix, (rand()&1)?LTM_PRIME_2MSB_OFF:LTM_PRIME_2MSB_ON, myrng, NULL);
141
 
       if (err != MP_OKAY) {
142
 
          printf("failed with err code %d\n", err);
143
 
          return EXIT_FAILURE;
144
 
       }
145
 
       if (mp_count_bits(&a) != ix) {
146
 
          printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
147
 
          return EXIT_FAILURE;
148
 
       }
 
177
   for (ix = 10; ix < 128; ix++) {
 
178
      printf("Testing (not safe-prime): %9d bits    \r", ix);
 
179
      fflush(stdout);
 
180
      err =
 
181
         mp_prime_random_ex(&a, 8, ix,
 
182
                            (rand() & 1) ? LTM_PRIME_2MSB_OFF :
 
183
                            LTM_PRIME_2MSB_ON, myrng, NULL);
 
184
      if (err != MP_OKAY) {
 
185
         printf("failed with err code %d\n", err);
 
186
         return EXIT_FAILURE;
 
187
      }
 
188
      if (mp_count_bits(&a) != ix) {
 
189
         printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
 
190
         return EXIT_FAILURE;
 
191
      }
149
192
   }
150
193
 
151
 
   for (ix = 16; ix < 256; ix++) {
152
 
       printf("Testing (   safe-prime): %9d bits    \r", ix); fflush(stdout);
153
 
       err = mp_prime_random_ex(&a, 8, ix, ((rand()&1)?LTM_PRIME_2MSB_OFF:LTM_PRIME_2MSB_ON)|LTM_PRIME_SAFE, myrng, NULL);
154
 
       if (err != MP_OKAY) {
155
 
          printf("failed with err code %d\n", err);
156
 
          return EXIT_FAILURE;
157
 
       }
158
 
       if (mp_count_bits(&a) != ix) {
159
 
          printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
160
 
          return EXIT_FAILURE;
161
 
       }
162
 
       /* let's see if it's really a safe prime */
163
 
       mp_sub_d(&a, 1, &a);
164
 
       mp_div_2(&a, &a);
165
 
       mp_prime_is_prime(&a, 8, &cnt);
166
 
       if (cnt != MP_YES) {
167
 
          printf("sub is not prime!\n");
168
 
          return EXIT_FAILURE;
169
 
       }
 
194
   for (ix = 16; ix < 128; ix++) {
 
195
      printf("Testing (   safe-prime): %9d bits    \r", ix);
 
196
      fflush(stdout);
 
197
      err =
 
198
         mp_prime_random_ex(&a, 8, ix,
 
199
                            ((rand() & 1) ? LTM_PRIME_2MSB_OFF :
 
200
                             LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng,
 
201
                            NULL);
 
202
      if (err != MP_OKAY) {
 
203
         printf("failed with err code %d\n", err);
 
204
         return EXIT_FAILURE;
 
205
      }
 
206
      if (mp_count_bits(&a) != ix) {
 
207
         printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
 
208
         return EXIT_FAILURE;
 
209
      }
 
210
      /* let's see if it's really a safe prime */
 
211
      mp_sub_d(&a, 1, &a);
 
212
      mp_div_2(&a, &a);
 
213
      mp_prime_is_prime(&a, 8, &cnt);
 
214
      if (cnt != MP_YES) {
 
215
         printf("sub is not prime!\n");
 
216
         return EXIT_FAILURE;
 
217
      }
170
218
   }
171
219
 
172
220
   printf("\n\n");
194
242
   printf("testing mp_cnt_lsb...\n");
195
243
   mp_set(&a, 1);
196
244
   for (ix = 0; ix < 1024; ix++) {
197
 
       if (mp_cnt_lsb(&a) != ix) {
198
 
          printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
199
 
          return 0;
200
 
       }
201
 
       mp_mul_2(&a, &a);
 
245
      if (mp_cnt_lsb(&a) != ix) {
 
246
         printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
 
247
         return 0;
 
248
      }
 
249
      mp_mul_2(&a, &a);
202
250
   }
203
251
 
204
252
/* test mp_reduce_2k */
205
253
   printf("Testing mp_reduce_2k...\n");
206
254
   for (cnt = 3; cnt <= 128; ++cnt) {
207
 
       mp_digit tmp;
208
 
       mp_2expt(&a, cnt);
209
 
       mp_sub_d(&a, 2, &a);  /* a = 2**cnt - 2 */
210
 
 
211
 
 
212
 
       printf("\nTesting %4d bits", cnt);
213
 
       printf("(%d)", mp_reduce_is_2k(&a));
214
 
       mp_reduce_2k_setup(&a, &tmp);
215
 
       printf("(%d)", tmp);
216
 
       for (ix = 0; ix < 1000; ix++) {
217
 
           if (!(ix & 127)) {printf("."); fflush(stdout); }
218
 
           mp_rand(&b, (cnt/DIGIT_BIT  + 1) * 2);
219
 
           mp_copy(&c, &b);
220
 
           mp_mod(&c, &a, &c);
221
 
           mp_reduce_2k(&b, &a, 1);
222
 
           if (mp_cmp(&c, &b)) {
223
 
              printf("FAILED\n");
224
 
              exit(0);
225
 
           }
226
 
        }
227
 
    }
 
255
      mp_digit tmp;
 
256
 
 
257
      mp_2expt(&a, cnt);
 
258
      mp_sub_d(&a, 2, &a);      /* a = 2**cnt - 2 */
 
259
 
 
260
 
 
261
      printf("\nTesting %4d bits", cnt);
 
262
      printf("(%d)", mp_reduce_is_2k(&a));
 
263
      mp_reduce_2k_setup(&a, &tmp);
 
264
      printf("(%d)", tmp);
 
265
      for (ix = 0; ix < 1000; ix++) {
 
266
         if (!(ix & 127)) {
 
267
            printf(".");
 
268
            fflush(stdout);
 
269
         }
 
270
         mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2);
 
271
         mp_copy(&c, &b);
 
272
         mp_mod(&c, &a, &c);
 
273
         mp_reduce_2k(&b, &a, 2);
 
274
         if (mp_cmp(&c, &b)) {
 
275
            printf("FAILED\n");
 
276
            exit(0);
 
277
         }
 
278
      }
 
279
   }
228
280
 
229
281
/* test mp_div_3  */
230
282
   printf("Testing mp_div_3...\n");
231
283
   mp_set(&d, 3);
232
 
   for (cnt = 0; cnt < 10000; ) {
 
284
   for (cnt = 0; cnt < 10000;) {
233
285
      mp_digit r1, r2;
234
286
 
235
 
      if (!(++cnt & 127)) printf("%9d\r", cnt);
 
287
      if (!(++cnt & 127))
 
288
         printf("%9d\r", cnt);
236
289
      mp_rand(&a, abs(rand()) % 128 + 1);
237
290
      mp_div(&a, &d, &b, &e);
238
291
      mp_div_3(&a, &c, &r2);
239
292
 
240
293
      if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
241
 
         printf("\n\nmp_div_3 => Failure\n");
 
294
         printf("\n\nmp_div_3 => Failure\n");
242
295
      }
243
296
   }
244
297
   printf("\n\nPassed div_3 testing\n");
246
299
/* test the DR reduction */
247
300
   printf("testing mp_dr_reduce...\n");
248
301
   for (cnt = 2; cnt < 32; cnt++) {
249
 
       printf("%d digit modulus\n", cnt);
250
 
       mp_grow(&a, cnt);
251
 
       mp_zero(&a);
252
 
       for (ix = 1; ix < cnt; ix++) {
253
 
           a.dp[ix] = MP_MASK;
254
 
       }
255
 
       a.used = cnt;
256
 
       a.dp[0] = 3;
 
302
      printf("%d digit modulus\n", cnt);
 
303
      mp_grow(&a, cnt);
 
304
      mp_zero(&a);
 
305
      for (ix = 1; ix < cnt; ix++) {
 
306
         a.dp[ix] = MP_MASK;
 
307
      }
 
308
      a.used = cnt;
 
309
      a.dp[0] = 3;
257
310
 
258
 
       mp_rand(&b, cnt - 1);
259
 
       mp_copy(&b, &c);
 
311
      mp_rand(&b, cnt - 1);
 
312
      mp_copy(&b, &c);
260
313
 
261
314
      rr = 0;
262
315
      do {
263
 
         if (!(rr & 127)) { printf("%9lu\r", rr); fflush(stdout); }
264
 
         mp_sqr(&b, &b); mp_add_d(&b, 1, &b);
265
 
         mp_copy(&b, &c);
266
 
 
267
 
         mp_mod(&b, &a, &b);
268
 
         mp_dr_reduce(&c, &a, (((mp_digit)1)<<DIGIT_BIT)-a.dp[0]);
269
 
 
270
 
         if (mp_cmp(&b, &c) != MP_EQ) {
271
 
            printf("Failed on trial %lu\n", rr); exit(-1);
272
 
 
273
 
         }
 
316
         if (!(rr & 127)) {
 
317
            printf("%9lu\r", rr);
 
318
            fflush(stdout);
 
319
         }
 
320
         mp_sqr(&b, &b);
 
321
         mp_add_d(&b, 1, &b);
 
322
         mp_copy(&b, &c);
 
323
 
 
324
         mp_mod(&b, &a, &b);
 
325
         mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]);
 
326
 
 
327
         if (mp_cmp(&b, &c) != MP_EQ) {
 
328
            printf("Failed on trial %lu\n", rr);
 
329
            exit(-1);
 
330
 
 
331
         }
274
332
      } while (++rr < 500);
275
333
      printf("Passed DR test for %d digits\n", cnt);
276
334
   }
277
335
 
278
336
#endif
279
337
 
 
338
/* test the mp_reduce_2k_l code */
 
339
#if 0
 
340
#if 0
 
341
/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
 
342
   mp_2expt(&a, 1024);
 
343
   mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
 
344
   mp_sub(&a, &b, &a);
 
345
#elif 1
 
346
/*  p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F  */
 
347
   mp_2expt(&a, 2048);
 
348
   mp_read_radix(&b,
 
349
                 "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
 
350
                 16);
 
351
   mp_sub(&a, &b, &a);
 
352
#endif
 
353
 
 
354
   mp_todecimal(&a, buf);
 
355
   printf("p==%s\n", buf);
 
356
/* now mp_reduce_is_2k_l() should return */
 
357
   if (mp_reduce_is_2k_l(&a) != 1) {
 
358
      printf("mp_reduce_is_2k_l() return 0, should be 1\n");
 
359
      return EXIT_FAILURE;
 
360
   }
 
361
   mp_reduce_2k_setup_l(&a, &d);
 
362
   /* now do a million square+1 to see if it varies */
 
363
   mp_rand(&b, 64);
 
364
   mp_mod(&b, &a, &b);
 
365
   mp_copy(&b, &c);
 
366
   printf("testing mp_reduce_2k_l...");
 
367
   fflush(stdout);
 
368
   for (cnt = 0; cnt < (1UL << 20); cnt++) {
 
369
      mp_sqr(&b, &b);
 
370
      mp_add_d(&b, 1, &b);
 
371
      mp_reduce_2k_l(&b, &a, &d);
 
372
      mp_sqr(&c, &c);
 
373
      mp_add_d(&c, 1, &c);
 
374
      mp_mod(&c, &a, &c);
 
375
      if (mp_cmp(&b, &c) != MP_EQ) {
 
376
         printf("mp_reduce_2k_l() failed at step %lu\n", cnt);
 
377
         mp_tohex(&b, buf);
 
378
         printf("b == %s\n", buf);
 
379
         mp_tohex(&c, buf);
 
380
         printf("c == %s\n", buf);
 
381
         return EXIT_FAILURE;
 
382
      }
 
383
   }
 
384
   printf("...Passed\n");
 
385
#endif
 
386
 
280
387
   div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
281
 
   sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n = sub_d_n= 0;
 
388
      sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
 
389
      sub_d_n = 0;
282
390
 
283
391
   /* force KARA and TOOM to enable despite cutoffs */
284
392
   KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 110;
285
 
   TOOM_SQR_CUTOFF      = TOOM_MUL_CUTOFF      = 150;
 
393
   TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 150;
286
394
 
287
395
   for (;;) {
288
 
       /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
289
 
       switch (abs(rand()) % 7) {
290
 
           case 0:  mp_clear(&a); mp_init(&a); break;
291
 
           case 1:  mp_clear(&b); mp_init(&b); break;
292
 
           case 2:  mp_clear(&c); mp_init(&c); break;
293
 
           case 3:  mp_clear(&d); mp_init(&d); break;
294
 
           case 4:  mp_clear(&e); mp_init(&e); break;
295
 
           case 5:  mp_clear(&f); mp_init(&f); break;
296
 
           case 6:  break; /* don't clear any */
297
 
       }
298
 
 
299
 
 
300
 
       printf("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ", add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
301
 
       fgets(cmd, 4095, stdin);
302
 
       cmd[strlen(cmd)-1] = 0;
303
 
       printf("%s  ]\r",cmd); fflush(stdout);
304
 
       if (!strcmp(cmd, "mul2d")) { ++mul2d_n;
305
 
          fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
306
 
          fgets(buf, 4095, stdin); sscanf(buf, "%d", &rr);
307
 
          fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
308
 
 
309
 
          mp_mul_2d(&a, rr, &a);
310
 
          a.sign = b.sign;
311
 
          if (mp_cmp(&a, &b) != MP_EQ) {
312
 
             printf("mul2d failed, rr == %d\n",rr);
313
 
             draw(&a);
314
 
             draw(&b);
315
 
             return 0;
316
 
          }
317
 
       } else if (!strcmp(cmd, "div2d")) { ++div2d_n;
318
 
          fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
319
 
          fgets(buf, 4095, stdin); sscanf(buf, "%d", &rr);
320
 
          fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
321
 
 
322
 
          mp_div_2d(&a, rr, &a, &e);
323
 
          a.sign = b.sign;
324
 
          if (a.used == b.used && a.used == 0) { a.sign = b.sign = MP_ZPOS; }
325
 
          if (mp_cmp(&a, &b) != MP_EQ) {
326
 
             printf("div2d failed, rr == %d\n",rr);
327
 
             draw(&a);
328
 
             draw(&b);
329
 
             return 0;
330
 
          }
331
 
       } else if (!strcmp(cmd, "add")) { ++add_n;
332
 
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
333
 
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
334
 
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
335
 
          mp_copy(&a, &d);
336
 
          mp_add(&d, &b, &d);
337
 
          if (mp_cmp(&c, &d) != MP_EQ) {
338
 
             printf("add %lu failure!\n", add_n);
339
 
draw(&a);draw(&b);draw(&c);draw(&d);
340
 
             return 0;
341
 
          }
342
 
 
343
 
          /* test the sign/unsigned storage functions */
344
 
 
345
 
          rr = mp_signed_bin_size(&c);
346
 
          mp_to_signed_bin(&c, (unsigned char *)cmd);
347
 
          memset(cmd+rr, rand()&255, sizeof(cmd)-rr);
348
 
          mp_read_signed_bin(&d, (unsigned char *)cmd, rr);
349
 
          if (mp_cmp(&c, &d) != MP_EQ) {
350
 
             printf("mp_signed_bin failure!\n");
351
 
             draw(&c);
352
 
             draw(&d);
353
 
             return 0;
354
 
          }
355
 
 
356
 
 
357
 
          rr = mp_unsigned_bin_size(&c);
358
 
          mp_to_unsigned_bin(&c, (unsigned char *)cmd);
359
 
          memset(cmd+rr, rand()&255, sizeof(cmd)-rr);
360
 
          mp_read_unsigned_bin(&d, (unsigned char *)cmd, rr);
361
 
          if (mp_cmp_mag(&c, &d) != MP_EQ) {
362
 
             printf("mp_unsigned_bin failure!\n");
363
 
             draw(&c);
364
 
             draw(&d);
365
 
             return 0;
366
 
          }
367
 
 
368
 
       } else if (!strcmp(cmd, "sub")) { ++sub_n;
369
 
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
370
 
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
371
 
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
372
 
          mp_copy(&a, &d);
373
 
          mp_sub(&d, &b, &d);
374
 
          if (mp_cmp(&c, &d) != MP_EQ) {
375
 
             printf("sub %lu failure!\n", sub_n);
376
 
draw(&a);draw(&b);draw(&c);draw(&d);
377
 
             return 0;
378
 
          }
379
 
       } else if (!strcmp(cmd, "mul")) { ++mul_n;
380
 
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
381
 
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
382
 
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
383
 
          mp_copy(&a, &d);
384
 
          mp_mul(&d, &b, &d);
385
 
          if (mp_cmp(&c, &d) != MP_EQ) {
386
 
             printf("mul %lu failure!\n", mul_n);
387
 
draw(&a);draw(&b);draw(&c);draw(&d);
388
 
             return 0;
389
 
          }
390
 
       } else if (!strcmp(cmd, "div")) { ++div_n;
391
 
          fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
392
 
          fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
393
 
          fgets(buf, 4095, stdin); mp_read_radix(&c, buf, 64);
394
 
          fgets(buf, 4095, stdin); mp_read_radix(&d, buf, 64);
395
 
 
396
 
          mp_div(&a, &b, &e, &f);
397
 
          if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
398
 
             printf("div %lu failure!\n", div_n);
399
 
draw(&a);draw(&b);draw(&c);draw(&d); draw(&e); draw(&f);
400
 
             return 0;
401
 
          }
402
 
 
403
 
       } else if (!strcmp(cmd, "sqr")) { ++sqr_n;
404
 
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
405
 
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
406
 
          mp_copy(&a, &c);
407
 
          mp_sqr(&c, &c);
408
 
          if (mp_cmp(&b, &c) != MP_EQ) {
409
 
             printf("sqr %lu failure!\n", sqr_n);
410
 
draw(&a);draw(&b);draw(&c);
411
 
             return 0;
412
 
          }
413
 
       } else if (!strcmp(cmd, "gcd")) { ++gcd_n;
414
 
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
415
 
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
416
 
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
417
 
          mp_copy(&a, &d);
418
 
          mp_gcd(&d, &b, &d);
419
 
          d.sign = c.sign;
420
 
          if (mp_cmp(&c, &d) != MP_EQ) {
421
 
             printf("gcd %lu failure!\n", gcd_n);
422
 
draw(&a);draw(&b);draw(&c);draw(&d);
423
 
             return 0;
424
 
          }
425
 
       } else if (!strcmp(cmd, "lcm")) { ++lcm_n;
426
 
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
427
 
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
428
 
             fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
429
 
             mp_copy(&a, &d);
430
 
             mp_lcm(&d, &b, &d);
431
 
             d.sign = c.sign;
432
 
             if (mp_cmp(&c, &d) != MP_EQ) {
433
 
                printf("lcm %lu failure!\n", lcm_n);
434
 
   draw(&a);draw(&b);draw(&c);draw(&d);
435
 
                return 0;
436
 
             }
437
 
       } else if (!strcmp(cmd, "expt")) {  ++expt_n;
438
 
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
439
 
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
440
 
             fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
441
 
             fgets(buf, 4095, stdin);  mp_read_radix(&d, buf, 64);
442
 
             mp_copy(&a, &e);
443
 
             mp_exptmod(&e, &b, &c, &e);
444
 
             if (mp_cmp(&d, &e) != MP_EQ) {
445
 
                printf("expt %lu failure!\n", expt_n);
446
 
   draw(&a);draw(&b);draw(&c);draw(&d); draw(&e);
447
 
                return 0;
448
 
             }
449
 
       } else if (!strcmp(cmd, "invmod")) {  ++inv_n;
450
 
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
451
 
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
452
 
             fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
453
 
             mp_invmod(&a, &b, &d);
454
 
             mp_mulmod(&d,&a,&b,&e);
455
 
             if (mp_cmp_d(&e, 1) != MP_EQ) {
456
 
                printf("inv [wrong value from MPI?!] failure\n");
457
 
                draw(&a);draw(&b);draw(&c);draw(&d);
458
 
                mp_gcd(&a, &b, &e);
459
 
                draw(&e);
460
 
                return 0;
461
 
             }
462
 
 
463
 
       } else if (!strcmp(cmd, "div2")) { ++div2_n;
464
 
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
465
 
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
466
 
             mp_div_2(&a, &c);
467
 
             if (mp_cmp(&c, &b) != MP_EQ) {
468
 
                 printf("div_2 %lu failure\n", div2_n);
469
 
                 draw(&a);
470
 
                 draw(&b);
471
 
                 draw(&c);
472
 
                 return 0;
473
 
             }
474
 
       } else if (!strcmp(cmd, "mul2")) { ++mul2_n;
475
 
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
476
 
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
477
 
             mp_mul_2(&a, &c);
478
 
             if (mp_cmp(&c, &b) != MP_EQ) {
479
 
                 printf("mul_2 %lu failure\n", mul2_n);
480
 
                 draw(&a);
481
 
                 draw(&b);
482
 
                 draw(&c);
483
 
                 return 0;
484
 
             }
485
 
       } else if (!strcmp(cmd, "add_d")) { ++add_d_n;
486
 
              fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
487
 
              fgets(buf, 4095, stdin); sscanf(buf, "%d", &ix);
488
 
              fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
489
 
              mp_add_d(&a, ix, &c);
490
 
              if (mp_cmp(&b, &c) != MP_EQ) {
491
 
                 printf("add_d %lu failure\n", add_d_n);
492
 
                 draw(&a);
493
 
                 draw(&b);
494
 
                 draw(&c);
495
 
                 printf("d == %d\n", ix);
496
 
                 return 0;
497
 
              }
498
 
       } else if (!strcmp(cmd, "sub_d")) { ++sub_d_n;
499
 
              fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
500
 
              fgets(buf, 4095, stdin); sscanf(buf, "%d", &ix);
501
 
              fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
502
 
              mp_sub_d(&a, ix, &c);
503
 
              if (mp_cmp(&b, &c) != MP_EQ) {
504
 
                 printf("sub_d %lu failure\n", sub_d_n);
505
 
                 draw(&a);
506
 
                 draw(&b);
507
 
                 draw(&c);
508
 
                 printf("d == %d\n", ix);
509
 
                 return 0;
510
 
              }
511
 
       }
 
396
      /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
 
397
      switch (abs(rand()) % 7) {
 
398
      case 0:
 
399
         mp_clear(&a);
 
400
         mp_init(&a);
 
401
         break;
 
402
      case 1:
 
403
         mp_clear(&b);
 
404
         mp_init(&b);
 
405
         break;
 
406
      case 2:
 
407
         mp_clear(&c);
 
408
         mp_init(&c);
 
409
         break;
 
410
      case 3:
 
411
         mp_clear(&d);
 
412
         mp_init(&d);
 
413
         break;
 
414
      case 4:
 
415
         mp_clear(&e);
 
416
         mp_init(&e);
 
417
         break;
 
418
      case 5:
 
419
         mp_clear(&f);
 
420
         mp_init(&f);
 
421
         break;
 
422
      case 6:
 
423
         break;                 /* don't clear any */
 
424
      }
 
425
 
 
426
 
 
427
      printf
 
428
         ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
 
429
          add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
 
430
          expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
 
431
      fgets(cmd, 4095, stdin);
 
432
      cmd[strlen(cmd) - 1] = 0;
 
433
      printf("%s  ]\r", cmd);
 
434
      fflush(stdout);
 
435
      if (!strcmp(cmd, "mul2d")) {
 
436
         ++mul2d_n;
 
437
         fgets(buf, 4095, stdin);
 
438
         mp_read_radix(&a, buf, 64);
 
439
         fgets(buf, 4095, stdin);
 
440
         sscanf(buf, "%d", &rr);
 
441
         fgets(buf, 4095, stdin);
 
442
         mp_read_radix(&b, buf, 64);
 
443
 
 
444
         mp_mul_2d(&a, rr, &a);
 
445
         a.sign = b.sign;
 
446
         if (mp_cmp(&a, &b) != MP_EQ) {
 
447
            printf("mul2d failed, rr == %d\n", rr);
 
448
            draw(&a);
 
449
            draw(&b);
 
450
            return 0;
 
451
         }
 
452
      } else if (!strcmp(cmd, "div2d")) {
 
453
         ++div2d_n;
 
454
         fgets(buf, 4095, stdin);
 
455
         mp_read_radix(&a, buf, 64);
 
456
         fgets(buf, 4095, stdin);
 
457
         sscanf(buf, "%d", &rr);
 
458
         fgets(buf, 4095, stdin);
 
459
         mp_read_radix(&b, buf, 64);
 
460
 
 
461
         mp_div_2d(&a, rr, &a, &e);
 
462
         a.sign = b.sign;
 
463
         if (a.used == b.used && a.used == 0) {
 
464
            a.sign = b.sign = MP_ZPOS;
 
465
         }
 
466
         if (mp_cmp(&a, &b) != MP_EQ) {
 
467
            printf("div2d failed, rr == %d\n", rr);
 
468
            draw(&a);
 
469
            draw(&b);
 
470
            return 0;
 
471
         }
 
472
      } else if (!strcmp(cmd, "add")) {
 
473
         ++add_n;
 
474
         fgets(buf, 4095, stdin);
 
475
         mp_read_radix(&a, buf, 64);
 
476
         fgets(buf, 4095, stdin);
 
477
         mp_read_radix(&b, buf, 64);
 
478
         fgets(buf, 4095, stdin);
 
479
         mp_read_radix(&c, buf, 64);
 
480
         mp_copy(&a, &d);
 
481
         mp_add(&d, &b, &d);
 
482
         if (mp_cmp(&c, &d) != MP_EQ) {
 
483
            printf("add %lu failure!\n", add_n);
 
484
            draw(&a);
 
485
            draw(&b);
 
486
            draw(&c);
 
487
            draw(&d);
 
488
            return 0;
 
489
         }
 
490
 
 
491
         /* test the sign/unsigned storage functions */
 
492
 
 
493
         rr = mp_signed_bin_size(&c);
 
494
         mp_to_signed_bin(&c, (unsigned char *) cmd);
 
495
         memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
 
496
         mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
 
497
         if (mp_cmp(&c, &d) != MP_EQ) {
 
498
            printf("mp_signed_bin failure!\n");
 
499
            draw(&c);
 
500
            draw(&d);
 
501
            return 0;
 
502
         }
 
503
 
 
504
 
 
505
         rr = mp_unsigned_bin_size(&c);
 
506
         mp_to_unsigned_bin(&c, (unsigned char *) cmd);
 
507
         memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
 
508
         mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
 
509
         if (mp_cmp_mag(&c, &d) != MP_EQ) {
 
510
            printf("mp_unsigned_bin failure!\n");
 
511
            draw(&c);
 
512
            draw(&d);
 
513
            return 0;
 
514
         }
 
515
 
 
516
      } else if (!strcmp(cmd, "sub")) {
 
517
         ++sub_n;
 
518
         fgets(buf, 4095, stdin);
 
519
         mp_read_radix(&a, buf, 64);
 
520
         fgets(buf, 4095, stdin);
 
521
         mp_read_radix(&b, buf, 64);
 
522
         fgets(buf, 4095, stdin);
 
523
         mp_read_radix(&c, buf, 64);
 
524
         mp_copy(&a, &d);
 
525
         mp_sub(&d, &b, &d);
 
526
         if (mp_cmp(&c, &d) != MP_EQ) {
 
527
            printf("sub %lu failure!\n", sub_n);
 
528
            draw(&a);
 
529
            draw(&b);
 
530
            draw(&c);
 
531
            draw(&d);
 
532
            return 0;
 
533
         }
 
534
      } else if (!strcmp(cmd, "mul")) {
 
535
         ++mul_n;
 
536
         fgets(buf, 4095, stdin);
 
537
         mp_read_radix(&a, buf, 64);
 
538
         fgets(buf, 4095, stdin);
 
539
         mp_read_radix(&b, buf, 64);
 
540
         fgets(buf, 4095, stdin);
 
541
         mp_read_radix(&c, buf, 64);
 
542
         mp_copy(&a, &d);
 
543
         mp_mul(&d, &b, &d);
 
544
         if (mp_cmp(&c, &d) != MP_EQ) {
 
545
            printf("mul %lu failure!\n", mul_n);
 
546
            draw(&a);
 
547
            draw(&b);
 
548
            draw(&c);
 
549
            draw(&d);
 
550
            return 0;
 
551
         }
 
552
      } else if (!strcmp(cmd, "div")) {
 
553
         ++div_n;
 
554
         fgets(buf, 4095, stdin);
 
555
         mp_read_radix(&a, buf, 64);
 
556
         fgets(buf, 4095, stdin);
 
557
         mp_read_radix(&b, buf, 64);
 
558
         fgets(buf, 4095, stdin);
 
559
         mp_read_radix(&c, buf, 64);
 
560
         fgets(buf, 4095, stdin);
 
561
         mp_read_radix(&d, buf, 64);
 
562
 
 
563
         mp_div(&a, &b, &e, &f);
 
564
         if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
 
565
            printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
 
566
                   mp_cmp(&d, &f));
 
567
            draw(&a);
 
568
            draw(&b);
 
569
            draw(&c);
 
570
            draw(&d);
 
571
            draw(&e);
 
572
            draw(&f);
 
573
            return 0;
 
574
         }
 
575
 
 
576
      } else if (!strcmp(cmd, "sqr")) {
 
577
         ++sqr_n;
 
578
         fgets(buf, 4095, stdin);
 
579
         mp_read_radix(&a, buf, 64);
 
580
         fgets(buf, 4095, stdin);
 
581
         mp_read_radix(&b, buf, 64);
 
582
         mp_copy(&a, &c);
 
583
         mp_sqr(&c, &c);
 
584
         if (mp_cmp(&b, &c) != MP_EQ) {
 
585
            printf("sqr %lu failure!\n", sqr_n);
 
586
            draw(&a);
 
587
            draw(&b);
 
588
            draw(&c);
 
589
            return 0;
 
590
         }
 
591
      } else if (!strcmp(cmd, "gcd")) {
 
592
         ++gcd_n;
 
593
         fgets(buf, 4095, stdin);
 
594
         mp_read_radix(&a, buf, 64);
 
595
         fgets(buf, 4095, stdin);
 
596
         mp_read_radix(&b, buf, 64);
 
597
         fgets(buf, 4095, stdin);
 
598
         mp_read_radix(&c, buf, 64);
 
599
         mp_copy(&a, &d);
 
600
         mp_gcd(&d, &b, &d);
 
601
         d.sign = c.sign;
 
602
         if (mp_cmp(&c, &d) != MP_EQ) {
 
603
            printf("gcd %lu failure!\n", gcd_n);
 
604
            draw(&a);
 
605
            draw(&b);
 
606
            draw(&c);
 
607
            draw(&d);
 
608
            return 0;
 
609
         }
 
610
      } else if (!strcmp(cmd, "lcm")) {
 
611
         ++lcm_n;
 
612
         fgets(buf, 4095, stdin);
 
613
         mp_read_radix(&a, buf, 64);
 
614
         fgets(buf, 4095, stdin);
 
615
         mp_read_radix(&b, buf, 64);
 
616
         fgets(buf, 4095, stdin);
 
617
         mp_read_radix(&c, buf, 64);
 
618
         mp_copy(&a, &d);
 
619
         mp_lcm(&d, &b, &d);
 
620
         d.sign = c.sign;
 
621
         if (mp_cmp(&c, &d) != MP_EQ) {
 
622
            printf("lcm %lu failure!\n", lcm_n);
 
623
            draw(&a);
 
624
            draw(&b);
 
625
            draw(&c);
 
626
            draw(&d);
 
627
            return 0;
 
628
         }
 
629
      } else if (!strcmp(cmd, "expt")) {
 
630
         ++expt_n;
 
631
         fgets(buf, 4095, stdin);
 
632
         mp_read_radix(&a, buf, 64);
 
633
         fgets(buf, 4095, stdin);
 
634
         mp_read_radix(&b, buf, 64);
 
635
         fgets(buf, 4095, stdin);
 
636
         mp_read_radix(&c, buf, 64);
 
637
         fgets(buf, 4095, stdin);
 
638
         mp_read_radix(&d, buf, 64);
 
639
         mp_copy(&a, &e);
 
640
         mp_exptmod(&e, &b, &c, &e);
 
641
         if (mp_cmp(&d, &e) != MP_EQ) {
 
642
            printf("expt %lu failure!\n", expt_n);
 
643
            draw(&a);
 
644
            draw(&b);
 
645
            draw(&c);
 
646
            draw(&d);
 
647
            draw(&e);
 
648
            return 0;
 
649
         }
 
650
      } else if (!strcmp(cmd, "invmod")) {
 
651
         ++inv_n;
 
652
         fgets(buf, 4095, stdin);
 
653
         mp_read_radix(&a, buf, 64);
 
654
         fgets(buf, 4095, stdin);
 
655
         mp_read_radix(&b, buf, 64);
 
656
         fgets(buf, 4095, stdin);
 
657
         mp_read_radix(&c, buf, 64);
 
658
         mp_invmod(&a, &b, &d);
 
659
         mp_mulmod(&d, &a, &b, &e);
 
660
         if (mp_cmp_d(&e, 1) != MP_EQ) {
 
661
            printf("inv [wrong value from MPI?!] failure\n");
 
662
            draw(&a);
 
663
            draw(&b);
 
664
            draw(&c);
 
665
            draw(&d);
 
666
            mp_gcd(&a, &b, &e);
 
667
            draw(&e);
 
668
            return 0;
 
669
         }
 
670
 
 
671
      } else if (!strcmp(cmd, "div2")) {
 
672
         ++div2_n;
 
673
         fgets(buf, 4095, stdin);
 
674
         mp_read_radix(&a, buf, 64);
 
675
         fgets(buf, 4095, stdin);
 
676
         mp_read_radix(&b, buf, 64);
 
677
         mp_div_2(&a, &c);
 
678
         if (mp_cmp(&c, &b) != MP_EQ) {
 
679
            printf("div_2 %lu failure\n", div2_n);
 
680
            draw(&a);
 
681
            draw(&b);
 
682
            draw(&c);
 
683
            return 0;
 
684
         }
 
685
      } else if (!strcmp(cmd, "mul2")) {
 
686
         ++mul2_n;
 
687
         fgets(buf, 4095, stdin);
 
688
         mp_read_radix(&a, buf, 64);
 
689
         fgets(buf, 4095, stdin);
 
690
         mp_read_radix(&b, buf, 64);
 
691
         mp_mul_2(&a, &c);
 
692
         if (mp_cmp(&c, &b) != MP_EQ) {
 
693
            printf("mul_2 %lu failure\n", mul2_n);
 
694
            draw(&a);
 
695
            draw(&b);
 
696
            draw(&c);
 
697
            return 0;
 
698
         }
 
699
      } else if (!strcmp(cmd, "add_d")) {
 
700
         ++add_d_n;
 
701
         fgets(buf, 4095, stdin);
 
702
         mp_read_radix(&a, buf, 64);
 
703
         fgets(buf, 4095, stdin);
 
704
         sscanf(buf, "%d", &ix);
 
705
         fgets(buf, 4095, stdin);
 
706
         mp_read_radix(&b, buf, 64);
 
707
         mp_add_d(&a, ix, &c);
 
708
         if (mp_cmp(&b, &c) != MP_EQ) {
 
709
            printf("add_d %lu failure\n", add_d_n);
 
710
            draw(&a);
 
711
            draw(&b);
 
712
            draw(&c);
 
713
            printf("d == %d\n", ix);
 
714
            return 0;
 
715
         }
 
716
      } else if (!strcmp(cmd, "sub_d")) {
 
717
         ++sub_d_n;
 
718
         fgets(buf, 4095, stdin);
 
719
         mp_read_radix(&a, buf, 64);
 
720
         fgets(buf, 4095, stdin);
 
721
         sscanf(buf, "%d", &ix);
 
722
         fgets(buf, 4095, stdin);
 
723
         mp_read_radix(&b, buf, 64);
 
724
         mp_sub_d(&a, ix, &c);
 
725
         if (mp_cmp(&b, &c) != MP_EQ) {
 
726
            printf("sub_d %lu failure\n", sub_d_n);
 
727
            draw(&a);
 
728
            draw(&b);
 
729
            draw(&c);
 
730
            printf("d == %d\n", ix);
 
731
            return 0;
 
732
         }
 
733
      }
512
734
   }
513
735
   return 0;
514
736
}
515