comparison libtommath/demo/demo.c @ 284:eed26cff980b

propagate from branch 'au.asn.ucc.matt.ltm.dropbear' (head 6c790cad5a7fa866ad062cb3a0c279f7ba788583) to branch 'au.asn.ucc.matt.dropbear' (head fff0894a0399405a9410ea1c6d118f342cf2aa64)
author Matt Johnston <matt@ucc.asn.au>
date Wed, 08 Mar 2006 13:23:49 +0000
parents
children 5ff8218bcee9
comparison
equal deleted inserted replaced
283:bd240aa12ba7 284:eed26cff980b
1 #include <time.h>
2
3 #ifdef IOWNANATHLON
4 #include <unistd.h>
5 #define SLEEP sleep(4)
6 #else
7 #define SLEEP
8 #endif
9
10 #include "tommath.h"
11
12 void ndraw(mp_int * a, char *name)
13 {
14 char buf[16000];
15
16 printf("%s: ", name);
17 mp_toradix(a, buf, 10);
18 printf("%s\n", buf);
19 }
20
21 static void draw(mp_int * a)
22 {
23 ndraw(a, "");
24 }
25
26
27 unsigned long lfsr = 0xAAAAAAAAUL;
28
29 int lbit(void)
30 {
31 if (lfsr & 0x80000000UL) {
32 lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL;
33 return 1;
34 } else {
35 lfsr <<= 1;
36 return 0;
37 }
38 }
39
40 int myrng(unsigned char *dst, int len, void *dat)
41 {
42 int x;
43
44 for (x = 0; x < len; x++)
45 dst[x] = rand() & 0xFF;
46 return len;
47 }
48
49
50
51 char cmd[4096], buf[4096];
52 int main(void)
53 {
54 mp_int a, b, c, d, e, f;
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;
57 unsigned rr;
58 int i, n, err, cnt, ix, old_kara_m, old_kara_s;
59 mp_digit mp;
60
61
62 mp_init(&a);
63 mp_init(&b);
64 mp_init(&c);
65 mp_init(&d);
66 mp_init(&e);
67 mp_init(&f);
68
69 srand(time(NULL));
70
71 #if 0
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");
175
176 /* test for size */
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 }
192 }
193
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 }
218 }
219
220 printf("\n\n");
221
222 mp_read_radix(&a, "123456", 10);
223 mp_toradix_n(&a, buf, 10, 3);
224 printf("a == %s\n", buf);
225 mp_toradix_n(&a, buf, 10, 4);
226 printf("a == %s\n", buf);
227 mp_toradix_n(&a, buf, 10, 30);
228 printf("a == %s\n", buf);
229
230
231 #if 0
232 for (;;) {
233 fgets(buf, sizeof(buf), stdin);
234 mp_read_radix(&a, buf, 10);
235 mp_prime_next_prime(&a, 5, 1);
236 mp_toradix(&a, buf, 10);
237 printf("%s, %lu\n", buf, a.dp[0] & 3);
238 }
239 #endif
240
241 /* test mp_cnt_lsb */
242 printf("testing mp_cnt_lsb...\n");
243 mp_set(&a, 1);
244 for (ix = 0; ix < 1024; ix++) {
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);
250 }
251
252 /* test mp_reduce_2k */
253 printf("Testing mp_reduce_2k...\n");
254 for (cnt = 3; cnt <= 128; ++cnt) {
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 }
280
281 /* test mp_div_3 */
282 printf("Testing mp_div_3...\n");
283 mp_set(&d, 3);
284 for (cnt = 0; cnt < 10000;) {
285 mp_digit r1, r2;
286
287 if (!(++cnt & 127))
288 printf("%9d\r", cnt);
289 mp_rand(&a, abs(rand()) % 128 + 1);
290 mp_div(&a, &d, &b, &e);
291 mp_div_3(&a, &c, &r2);
292
293 if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
294 printf("\n\nmp_div_3 => Failure\n");
295 }
296 }
297 printf("\n\nPassed div_3 testing\n");
298
299 /* test the DR reduction */
300 printf("testing mp_dr_reduce...\n");
301 for (cnt = 2; cnt < 32; cnt++) {
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;
310
311 mp_rand(&b, cnt - 1);
312 mp_copy(&b, &c);
313
314 rr = 0;
315 do {
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 }
332 } while (++rr < 500);
333 printf("Passed DR test for %d digits\n", cnt);
334 }
335
336 #endif
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
387 div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
388 sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
389 sub_d_n = 0;
390
391 /* force KARA and TOOM to enable despite cutoffs */
392 KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 110;
393 TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 150;
394
395 for (;;) {
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 }
734 }
735 return 0;
736 }