source: trunk/src/bignum.c@ 474

Last change on this file since 474 was 454, checked in by katerina, 10 years ago

Fix for ticket #355 (use calloc instead of malloc).

File size: 35.5 KB
RevLine 
[1]1/* Implementation of bignums by Henrik.Johansson@Nexus.Comm.SE in 1991
2 * version 1.2
3 */
4
5/* Modifications in this file (Nov 1999, Rainer Wichmann):
6 * - a few compiler warnings fixed:
7 * gcc insists on 'if ( ( b_eq_qr = ((b == q) || (b == r)) ) )'
8 * instead of 'if ( b_eq_qr = ((b == q) || (b == r)) )'
9 * - code that is not used in samhain is #defined out by:
10 * #if (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER))
11 * or
12 * #ifdef UNUSED_CODE
13 * - the error message (error_string[]) is enclosed in N_(),_() macros
14 * - the following four #includes have been added
15 */
16#include "config_xor.h"
17
18
19#include <string.h>
20
21#ifdef HAVE_MEMORY_H
22#include <memory.h>
23#endif
24
25#include "samhain.h"
26#include "bignum.h"
27
28
29#if (!defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H)) && (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER))
30
31#define DIGIT BIGNUM_DIGIT
32#define DIGIT2 BIGNUM_TWO_DIGITS
33
34#ifndef TRUE
35#define TRUE (1 == 1)
36#endif
37#ifndef FALSE
38#define FALSE (1 != 1)
39#endif
40
41
42#define MIN_ALLOC ((sizeof(long) / sizeof(DIGIT)) << 1)
43
44/* Don't expect the "sign" field to have the right value (BIG_SIGN_0) at
45 * all times, so compare real content of bignum with zerop.
46 * Maybe it would be better to be sure at all times that the sign is right?
47 */
48#define zerop(BIG) ((*(BIG)->dp == 0) && ((BIG)->dgs_used == 1))
49#define uonep(BIG) ((*(BIG)->dp == 1) && ((BIG)->dgs_used == 1))
50#define NEGATE_SIGN(SGN) (-(SGN))
51
52#define DIGIT_BITS BIGNUM_DIGIT_BITS
53#define DIGIT2_BITS BIGNUM_TWO_DIGITS_BITS
54
55#define DIGIT_PART(N) ((DIGIT)((N) & ((((DIGIT2)1) << DIGIT_BITS) - 1)))
56#define RESULT_MINUSP(RES) (((RES) & ((DIGIT2)1 << (DIGIT2_BITS - 1))) != 0)
57#define SHIFT_DIGIT_DOWN(N) (DIGIT_PART((N) >> DIGIT_BITS))
58#define SHIFT_DIGIT_UP(N) ((DIGIT2)((N) << DIGIT_BITS))
59
60#define DIGIT_BASE (((DIGIT2)1) << DIGIT_BITS)
61#define MAX_DIGIT ((((DIGIT2)1) << DIGIT_BITS) - 1)
62
63#define uint unsigned int
64#define ulong unsigned long
65
66char *last_string = NULL;
67char *big_end_string = NULL;
68
69ulong length_last_string;
70static char big_base_digits1[] =
71N_("00112233445566778899AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz");
72static char error_string[] = N_("(big_errno != 0, something has gone wrong)");
73static char big_base_digits[73] = "\0";
74
75bignum big_one;
76bignum tmp_string, tmp_add, tmp_mul, tmp_q, tmp_r, tmp_rand, tmp_round;
77DIGIT *tmp_digits;
78ulong tmp_ulong;
79
80/* #define COUNT_ALLOC */
81#ifdef COUNT_ALLOC
82ulong dgs_alloc = 0, digits_freed = 0;
83#endif
84
85int big_errno = BIG_OK;
86
87double log2tbl[] =
88{
89 -1.0, -1.0,
90 1.000000000000000, 1.584961891174317, 2.000000000000002, 2.321928024291994,
91 2.584960937500003, 2.807353973388675, 3.000000000000004, 3.169923782348637,
92 3.321928024291997, 3.459430694580083, 3.584960937500005, 3.700439453125006,
93 3.807353973388678, 3.906888961791999, 4.000000000000014, 4.087459564208999,
94 4.169921875000016, 4.247924804687517, 4.321926116943377, 4.392314910888691,
95 4.459430694580098, 4.523559570312520, 4.584960937500021, 4.643856048584007,
96 4.700439453125023, 4.754886627197290, 4.807353973388697, 4.857978820800807,
97 4.906887054443386, 4.954193115234403, 5.000000000000028, 5.044391632080107,
98 5.087459564209015, 5.129280090332062, 5.169921875000032
99};
100
101struct digit_blocks
102{
103 int digCnt;
104 DIGIT dig_base;
105} big_block[37]; /* The code uses index 2 to 36 */
106
107
108/* ----------------------------------------------------------------------
109 * All static utility functions are placed first in this file.
110 */
111
112#ifndef HAVE_STRCHR
113static char * strchr (char * str_ptr, char ch)
114{
115 do
116 {
117 if (*str_ptr == ch)
118 {
119 return str_ptr;
120 }
121 } while (*str_ptr++ != '\0');
122 return NULL;
123}
124#endif
125
126#if 0
127
128extern int printf();
129
130static void
131print_digits(prefix, a)
132char *prefix;
133bignum *a;
134{
135 unsigned long i;
136 ulong tmp;
137
138 printf("%s", prefix);
139 if (a->sign == BIG_SIGN_MINUS)
140 {
141 printf("- ");
142 }
143 else
144 {
145 if (a->sign == BIG_SIGN_PLUS)
146 {
147 printf("+ ");
148 }
149 else
150 {
151 printf("+/- ");
152 }
153 }
154 for (i = a->dgs_used - 1; i > 0; i--)
155 {
156 tmp = a->dp[i];
157 printf("%lu, ", tmp);
158 }
159 tmp = *a->dp;
160 printf("%lu\n", tmp);
161}
162
163#else
164
165#define print_digits(prefix, big) /* */
166
167#endif
168
169static void
170init_digit_blocks(void)
171{
172 uint digcnt, base;
173 DIGIT maxdigit, curdigit, tmp;
174
175 for (base = 2; base <= 36; base++)
176 {
177 tmp = ((1 << (DIGIT_BITS - 1)) / base);
178 maxdigit = tmp * 2;
179 curdigit = 1;
180 digcnt = 0;
181 while (curdigit < maxdigit)
182 {
183 digcnt++;
184 curdigit *= base;
185 }
186 big_block[base].digCnt = digcnt;
187 big_block[base].dig_base = curdigit;
188 }
189}
190
191#ifdef COUNT_ALLOC
192static void
193free_digits(DIGIT * dp, ulong count)
194{
195 /* Mar 4 2000 R. Wichmann: check for dp == NULL */
196 if (!dp)
197 return;
198 digits_freed += count;
199 free((char *)dp);
200 dp = NULL;
201}
202#else
203/* June 5 2000 R. Wichmann: check for dp == NULL */
204/* #define free_digits(DP,CNT) free((char *)DP) */
205static void
206free_digits(DIGIT * dp, ulong count)
207{
208 /* Mar 4 2000 R. Wichmann: check for dp == NULL */
209 if (!dp)
210 return;
[435]211 (void) count;
[1]212 free((char *)dp);
213 dp = NULL;
214}
215#endif
216
217static DIGIT *
218allocate_digits(ulong alloclen)
219{
220 DIGIT *digit_ptr;
221
222 if (big_errno != BIG_OK)
223 {
224 return NULL;
225 }
226#ifdef COUNT_ALLOC
227 dgs_alloc += alloclen;
228#endif
[454]229 digit_ptr = calloc(alloclen, sizeof(DIGIT));
[1]230 if (digit_ptr == NULL)
231 {
232 big_errno = BIG_MEMERR;
233 return NULL;
234 }
235 return digit_ptr;
236}
237
238static bigerr_t
239newsize(DIGIT **dp_p, ulong *cursize_p, ulong minsz, ulong newsz)
240{
241 if (*cursize_p >= minsz)
242 {
243 return big_errno;
244 }
245 free_digits(*dp_p, *cursize_p);
246 if (newsz < MIN_ALLOC)
247 {
248 newsz = MIN_ALLOC;
249 }
250 if ((*dp_p = allocate_digits(newsz)) == NULL)
251 {
252 return big_errno;
253 }
254 *cursize_p = newsz;
255 return big_errno;
256}
257
258/* `memcpy' uses an `int' as counter. If an int can't hold a big enough
259 * counter, then `digits_cpy' becomes a function (and a little slower,
260 * probably. Unfortunately `memcpy' takes a signed counter, but _that_
261 * size of numbers are almost too big! Or isn't it?
262 */
263#ifdef MEMCPY_LONG_COUNTER
264/* extern char *memcpy(); */
265#define digits_cpy(dst, src, count) memcpy((char *)(dst), (char *)(src), \
266 (count) * sizeof(DIGIT))
267#else
268static void
269digits_cpy(DIGIT *dst, DIGIT *src, ulong count)
270{
271 while (count-- > 0)
272 {
273 *dst++ = *src++;
274 }
275}
276#endif
277
278static DIGIT *
279copy_digits(DIGIT *src, ulong cp_count, ulong alloclen)
280{
281 DIGIT *dst;
282
283 if (big_errno != BIG_OK)
284 {
285 return NULL;
286 }
287 if ((dst = allocate_digits(alloclen)) == NULL)
288 {
289 return NULL;
290 }
291 digits_cpy(dst, src, cp_count);
292 return dst;
293}
294
295static void
296add_digit(bignum * a, DIGIT d)
297{
298 DIGIT2 res = d;
299 DIGIT *last_digit, *digit_ptr = a->dp, *digvect;
300
301 last_digit = digit_ptr + a->dgs_used;
302 while (digit_ptr < last_digit)
303 {
304 res = *digit_ptr + res;
305 *digit_ptr = DIGIT_PART(res);
306 res = SHIFT_DIGIT_DOWN(res);
307 digit_ptr++;
308 if (res == 0)
309 {
310 break;
311 }
312 }
313 if (res != 0)
314 {
315 if (a->dgs_used < a->dgs_alloc)
316 {
317 *digit_ptr = DIGIT_PART(res);
318 }
319 else
320 {
321 if ((digvect = copy_digits(a->dp, a->dgs_used,
322 a->dgs_used + 4)) == NULL)
323 {
324 return; /* big_errno will be set to last error */
325 }
326 digvect[a->dgs_used] = DIGIT_PART(res);
327 free_digits(a->dp, a->dgs_alloc);
328 a->dgs_alloc = a->dgs_used + 4;
329 a->dp = digvect;
330 }
331 a->dgs_used++;
332 }
333}
334
335static DIGIT
336vect_div_digit(DIGIT *digvect, ulong *len, DIGIT d)
337{
338 DIGIT *digit_ptr = digvect + *len - 1, newval;
339 DIGIT2 rest = 0;
340
341 if (d == 0)
342 {
343 big_errno = BIG_DIV_ZERO;
344 return -1;
345 }
346 if (d == 1)
347 {
348 return 0;
349 }
350 while (digit_ptr >= digvect)
351 {
352 rest = (DIGIT2)SHIFT_DIGIT_UP(rest);
353 newval = DIGIT_PART((*digit_ptr + rest) / d);
354 rest = (*digit_ptr + rest) % d;
355 *digit_ptr = newval;
356 digit_ptr--;
357 }
358 if (*len > 1)
359 {
360 if (digvect[*len - 1] == 0)
361 {
362 *len -= 1;
363 }
364 }
365 return DIGIT_PART(rest);
366}
367
368static DIGIT
369udiv_digit(bignum *a, DIGIT d)
370{
371 DIGIT res;
372
373 res = vect_div_digit(a->dp, &a->dgs_used, d);
374 if (zerop(a))
375 {
376 a->sign = BIG_SIGN_0;
377 }
378 return res;
379}
380
381static DIGIT
382vect_mul_digit(DIGIT *digvect, ulong len, DIGIT x)
383{
384 DIGIT *digit_ptr = digvect + len;
385 DIGIT2 res = 0;
386
387 while (digvect < digit_ptr)
388 {
389 res += *digvect * (DIGIT2)x;
390 *digvect = DIGIT_PART(res);
391 res = SHIFT_DIGIT_DOWN(res);
392 digvect++;
393 }
394 return DIGIT_PART(res);
395}
396
397static void
398umul_digit(bignum *a, DIGIT x)
399{
400 DIGIT ovfl, *digvect;
401
402 ovfl = vect_mul_digit(a->dp, a->dgs_used, x);
403 if (ovfl != 0)
404 {
405 if (a->dgs_used < a->dgs_alloc)
406 {
407 a->dp[a->dgs_used] = ovfl;
408 }
409 else
410 {
411 digvect = copy_digits(a->dp,
412 a->dgs_used,
413 a->dgs_used + 4);
414 digvect[a->dgs_used] = ovfl;
415 free_digits(a->dp, a->dgs_alloc);
416 a->dgs_alloc = a->dgs_used + 4;
417 a->dp = digvect;
418 }
419 a->dgs_used++;
420 }
421}
422
423static int
424ucompare_digits(bignum *a, bignum *b)
425{
426 DIGIT *a_ptr, *b_ptr;
427
428 if (a->dgs_used == b->dgs_used)
429 {
430 a_ptr = a->dp + a->dgs_used - 1;
431 b_ptr = b->dp + b->dgs_used - 1;
432 while ((*a_ptr == *b_ptr) && (a_ptr >= a->dp))
433 {
434 a_ptr--;
435 b_ptr--;
436 }
437 if (a_ptr < a->dp)
438 {
439 return 0;
440 }
441 else
442 {
443 return (*a_ptr > *b_ptr) ? 1 : -1;
444 }
445 }
446 return (a->dgs_used > b->dgs_used) ? 1 : -1;
447}
448
449static void
450uadd_digits(bignum *a, bignum *b, bignum *c)
451{
452 DIGIT *dp_x, *dp_y, *dp_z, *res_dp, *end_x, *end_y;
453 ulong len_x, len_y;
454 DIGIT2 res = 0;
455
456 if (a->dgs_used > b->dgs_used)
457 {
458 dp_x = a->dp;
459 len_x = a->dgs_used;
460 dp_y = b->dp;
461 len_y = b->dgs_used;
462 }
463 else
464 {
465 dp_x = b->dp;
466 len_x = b->dgs_used;
467 dp_y = a->dp;
468 len_y = a->dgs_used;
469 }
470 end_x = dp_x + len_x;
471 end_y = dp_y + len_y;
472 if (c->dgs_alloc >= len_x)
473 {
474 dp_z = c->dp;
475 }
476 else
477 {
478 if (newsize(&tmp_add.dp, &tmp_add.dgs_alloc,
479 len_x, len_x + 4) != BIG_OK)
480 {
481 return;
482 }
483 dp_z = tmp_add.dp;
484 }
485 res_dp = dp_z;
486 while (dp_y < end_y)
487 {
488 res += ((DIGIT2)*dp_x++) + *dp_y++;
489 *res_dp++ = DIGIT_PART(res);
490 res = SHIFT_DIGIT_DOWN(res);
491 }
492 while (dp_x < end_x)
493 {
494 res += *dp_x++;
495 *res_dp++ = DIGIT_PART(res);
496 res = SHIFT_DIGIT_DOWN(res);
497 }
498 if (res != 0)
499 {
500 *res_dp++ = DIGIT_PART(res);
501 }
502
503 if (dp_z != c->dp)
504 {
505 tmp_digits = c->dp;
506 c->dp = tmp_add.dp;
507 tmp_add.dp = tmp_digits;
508
509 tmp_ulong = c->dgs_alloc;
510 c->dgs_alloc = tmp_add.dgs_alloc;
511 tmp_add.dgs_alloc = tmp_ulong;
512 }
513 c->dgs_used = res_dp - c->dp;
514}
515
516static void
517usub_digits(bignum *a, bignum *b, bignum *c)
518{
519 DIGIT *dp_x, *dp_y, *dp_z, *res_dp, *end_x, *end_y;
520 ulong len_x, len_y;
521 DIGIT2 res = 0;
522
523 dp_x = a->dp;
524 len_x = a->dgs_used;
525 dp_y = b->dp;
526 len_y = b->dgs_used;
527
528 end_x = dp_x + len_x;
529 end_y = dp_y + len_y;
530 if (c->dgs_alloc >= len_x)
531 {
532 dp_z = c->dp;
533 }
534 else
535 {
536 if (newsize(&tmp_add.dp, &tmp_add.dgs_alloc,
537 len_x, len_x + 2) != BIG_OK)
538 {
539 return;
540 }
541 dp_z = tmp_add.dp;
542 }
543 res_dp = dp_z;
544 while (dp_y < end_y)
545 {
546 res = ((DIGIT2)*dp_x++) - *dp_y++ - RESULT_MINUSP(res);
547 *res_dp++ = DIGIT_PART(res);
548 }
549 while (dp_x < end_x)
550 {
551 res = *dp_x++ - RESULT_MINUSP(res);
552 *res_dp++ = DIGIT_PART(res);
553 }
554#ifdef BIG_CHECK_LIMITS
555 if (RESULT_MINUSP(res) != 0)
556 {
557 big_errno = BIG_ALGERR;
558 return;
559 }
560#endif
561 while ((*--res_dp == 0) && (res_dp > dp_z))
562 {
563 /* Move pointer down until we reach a non-zero */
564 }
565 if (dp_z != c->dp)
566 {
567 tmp_digits = c->dp;
568 c->dp = tmp_add.dp;
569 tmp_add.dp = tmp_digits;
570
571 tmp_ulong = tmp_add.dgs_alloc;
572 tmp_add.dgs_alloc = c->dgs_alloc;
573 c->dgs_alloc = tmp_ulong;
574 }
575 c->dgs_used = res_dp - dp_z + 1;
576}
577
578/*
579 * This (pseudo) random number generator is not very good. It has a long
580 * period [ 2 ^ (DIGIT_BITS * 2) (?)] before it starts with the same sequence
581 * again, but the lower bits are "less random" than they should be. I've
582 * solved it by using word of double length, and returning the upper bits.
583 * Please mail me if you know how to make it into a "more random" generator.
584 * One important thing though: it will have to reasonably fast.
585 * The good thing with this one is that it is very portable, but that doesn't
586 * help much when you want _good_ random numbers.
587 * Henrik.Johansson@Nexus.Comm.SE
588 */
589#ifdef UNUSED_CODE
590static DIGIT
591rand(void)
592{
593 static DIGIT2 x1 = 33, x2 = 45; /* Just give them two starting values */
594
595 if (x2 = BIG_RAND_A2 * x2 + BIG_RAND_C2, x2 == 45)
596 {
597 x1 = BIG_RAND_A1 * x1 + BIG_RAND_C1;
598 }
599 return SHIFT_DIGIT_DOWN(x1 + x2); /* Skip least significant bits */
600}
601/* UNUSED_CODE */
602#endif
603
604/* ----------------------------------------------------------------------
605 * All external functions comes here.
606 */
607
608bigerr_t
609big_init_pkg()
610{
611 strcpy (big_base_digits, _(big_base_digits1)); /* known to fit */
612 init_digit_blocks();
613 big_create(&tmp_string);
614 big_create(&tmp_add);
615 big_create(&tmp_mul);
616 big_create(&tmp_q);
617 big_create(&tmp_r);
618 big_create(&tmp_rand);
619 big_create(&big_one);
620 big_set_long((long)1, &big_one);
621 length_last_string = 10;
[454]622 if ((last_string = calloc(1,length_last_string)) == NULL)
[1]623 {
624 big_errno = BIG_MEMERR;
625 }
626 return big_errno;
627}
628
629void
630big_release_pkg()
631{
632 big_destroy(&tmp_string);
633 big_destroy(&tmp_add);
634 big_destroy(&tmp_mul);
635 big_destroy(&tmp_q);
636 big_destroy(&tmp_r);
637 big_destroy(&tmp_round);
638 big_destroy(&big_one);
639 if (last_string != NULL)
640 free(last_string);
641#ifdef COUNT_ALLOC
642 printf("Allocated digits: %lu\n", dgs_alloc);
643 printf("Freed digits: %lu\n", digits_freed);
644#endif
645}
646
647bigerr_t
648big_create(a)
649bignum *a;
650{
651 /* Make sure that big_create alway returns a NULL bignum
652 * that can safely be destroyed.
653 */
654 if (a != NULL)
655 {
656 a->dp = NULL;
657 }
658 if (big_errno != BIG_OK)
659 {
660 return big_errno;
661 }
662 if (a == NULL)
663 {
664 big_errno = BIG_ARGERR;
665 return big_errno;
666 }
667
668 a->sign = BIG_SIGN_0;
669 a->dgs_used = 1;
670 if ((a->dp = allocate_digits((long)sizeof(long))) == NULL)
671 {
672 return big_errno;
673 }
674 a->dgs_alloc = sizeof(long);
675 *a->dp = 0;
676 return big_errno;
677}
678
679void
680big_destroy(a)
681bignum *a;
682{
683 /* Mar 4, 2000 R. Wichmann: check for a == NULL */
684 /* free_digits() checks for a->dp == NULL */
685 if (a != NULL)
686 free_digits(a->dp, a->dgs_alloc);
687}
688
689ulong
690big_bitcount(a)
691bignum *a;
692{
693 int bits = 0;
694 DIGIT high_digit;
695
696 if (big_errno != BIG_OK)
697 {
698 return 0;
699 }
700 high_digit = a->dp[a->dgs_used - 1];
701 while (high_digit != 0)
702 {
703 bits++;
704 high_digit >>= 1;
705 }
706 return DIGIT_BITS * (a->dgs_used - 1) + bits;
707}
708
709bigerr_t
710big_set_big(a, b)
711bignum *a;
712bignum *b;
713{
714 if ((big_errno != BIG_OK) || (a == b))
715 {
716 return big_errno;
717 }
718 if (newsize(&b->dp, &b->dgs_alloc, a->dgs_used, a->dgs_used) != BIG_OK)
719 {
720 return big_errno;
721 }
722 b->dgs_used = a->dgs_used;
723 b->sign = a->sign;
724 digits_cpy(b->dp, a->dp, a->dgs_used);
725 return big_errno;
726}
727
728
729void
730big_set_ulong(n, a)
731ulong n;
732bignum *a;
733{
734 unsigned int i;
735
736 if (big_errno != BIG_OK)
737 {
738 return;
739 }
740 if (n == 0)
741 {
742 *a->dp = 0;
743 a->dgs_used = 1;
744 a->sign = BIG_SIGN_0;
745 }
746 else
747 {
748 a->dgs_used = 0;
749 for (i = 0; i < sizeof(long) / sizeof(DIGIT); i++)
750 {
751 if (n == 0)
752 {
753 break;
754 }
755 a->dgs_used++;
756 a->dp[i] = DIGIT_PART(n);
757 n = SHIFT_DIGIT_DOWN(n);
758 }
759 a->sign = BIG_SIGN_PLUS;
760 }
761 print_digits("set_(u)long: a = ", a);
762}
763
764void
765big_set_long(n, a)
766long n;
767bignum *a;
768{
769 ulong m;
770
771 m = (n < 0) ? - n : n;
772 big_set_ulong(m, a);
773 if (!(n >= 0))
774 {
775 a->sign = BIG_SIGN_MINUS;
776 }
777}
778
779
780bigerr_t
781big_set_string(numstr, base, a)
782char *numstr;
783int base;
784bignum *a;
785{
786 char *src, *maxdigit, *chrptr;
787 DIGIT dig_base, dig_sum, last_base;
788 int cnt, maxcnt;
789
790 if (big_errno != BIG_OK)
791 {
792 return big_errno;
793 }
794
795 big_end_string = numstr;
796 if ((base < 2) || (base > 36) || (numstr == NULL) || (a == NULL))
797 {
798 big_errno = BIG_ARGERR;
799 return big_errno;
800 }
801
802 src = numstr;
803
804 maxdigit = big_base_digits + (base << 1);
805
806 maxcnt = big_block[base].digCnt;
807 dig_base = big_block[base].dig_base;
808 a->dgs_used = 1;
809 *a->dp = 0;
810 a->sign = BIG_SIGN_PLUS; /* Assume it will be positive */
811 while (strchr(" \t\n\r", *src) != NULL) /* Skip whitespaces */
812 {
813 src++;
814 }
815 if ((*src == '-') || (*src == '+')) /* First non-white is a sign? */
816 {
817 a->sign = (*src == '-') ? BIG_SIGN_MINUS : BIG_SIGN_PLUS;
818 src++;
819 }
820 chrptr = strchr(big_base_digits, *src);
821 if ((chrptr == NULL) || (chrptr >= maxdigit)) /* Next chr not a digit? */
822 {
823 big_end_string = src;
824 big_errno = BIG_ARGERR;
825 return big_errno;
826 }
827 while (*src == '0') /* Next chr a '0'? */
828 {
829 src++; /* Read past all '0'es */
830 }
831 chrptr = strchr(big_base_digits, *src);
832 if ((chrptr == NULL) || (chrptr >= maxdigit)) /* Next char not a digit */
833 {
834 big_end_string = src;
835 a->sign = BIG_SIGN_0; /* It was just a plain 0 */
836 return big_errno;
837 }
838 dig_sum = 0;
839 cnt = 0;
840 while ((chrptr = strchr(big_base_digits, *src)),
841 (chrptr != NULL) && (chrptr < maxdigit))
842 {
843 dig_sum = dig_sum * base + ((chrptr - big_base_digits) >> 1);
844 if (++cnt >= maxcnt)
845 {
846 umul_digit(a, dig_base);
847 add_digit(a, dig_sum);
848 dig_sum = 0;
849 cnt = 0;
850 }
851 src++;
852 }
853 if (cnt > 0)
854 {
855 last_base = base;
856 while (--cnt > 0)
857 {
858 last_base *= base;
859 }
860 umul_digit(a, last_base);
861 add_digit(a, dig_sum);
862 }
863 big_end_string = src;
864 return big_errno;
865}
866
867
868int
869big_ulong(a, n)
870bignum *a;
871ulong *n;
872{
873 ulong old_n;
874 DIGIT *dp;
875
876 if (big_errno != BIG_OK)
877 {
878 return FALSE;
879 }
880 if (a->dgs_used > sizeof(ulong) / sizeof(DIGIT))
881 {
882 return FALSE;
883 }
884 dp = a->dp + a->dgs_used - 1;
885 old_n = *n = *dp--;
886 while ((dp >= a->dp) && (old_n < *n))
887 {
888 old_n = *n;
889 *n = SHIFT_DIGIT_UP(*n) + *dp--;
890 }
891 if (old_n >= *n)
892 {
893 return FALSE;
894 }
895 return FALSE;
896}
897
898int
899big_long(a, n)
900bignum *a;
901long *n;
902{
903 long old_n;
904 DIGIT *dp;
905
906 if (a->dgs_used > sizeof(ulong) / sizeof(DIGIT))
907 {
908 return FALSE;
909 }
910 dp = a->dp + a->dgs_used - 1;
911 old_n = *n = *dp--;
912 while ((dp >= a->dp) && (old_n <= *n))
913 {
914 old_n = *n;
915 *n = SHIFT_DIGIT_UP(*n) + *dp--;
916 }
917 if (old_n >= *n)
918 {
919 return FALSE;
920 }
921 if (a->sign == BIG_SIGN_MINUS)
922 {
[249]923 *n = -*n;
[1]924 }
925 return FALSE;
926}
927
928
929char *
930big_string(a, base)
931bignum *a;
932int base;
933{
934 ulong bit_length, str_length;
935 char *dst;
936 DIGIT dig_base, rem;
937 int cnt, maxcnt;
938
939 if (big_errno != BIG_OK)
940 {
941 return _(error_string);
942 }
943 big_set_big(a, &tmp_string);
944 /* Need more room than minimum here... */
945 bit_length = tmp_string.dgs_used * DIGIT_BITS;
946 /* bit_length = big_bitcount(&tmp_string); */
947 str_length = (ulong)(bit_length / log2tbl[base] + 4);
948 if (str_length > length_last_string)
949 {
950 if (last_string != NULL)
951 free(last_string);
[454]952 if ((last_string = calloc(1,str_length)) == NULL)
[1]953 {
954 big_errno = BIG_MEMERR;
955 return NULL;
956 }
957 length_last_string = str_length;
958 }
959
960 dst = last_string + length_last_string - 1;
961 *dst-- = '\0';
962 maxcnt = big_block[base].digCnt;
963 dig_base = big_block[base].dig_base;
964 while (tmp_string.dgs_used > 1)
965 {
966 rem = udiv_digit(&tmp_string, dig_base);
967 for (cnt = 0; cnt < maxcnt; cnt++)
968 {
969 *dst-- = big_base_digits[(rem % base) << 1];
970 rem /= base;
971 }
972 }
973 rem = *tmp_string.dp;
974 do
975 {
976 *dst-- = big_base_digits[(rem % base) << 1];
977 rem /= base;
978 } while (rem != 0);
979
980 if (a->sign == BIG_SIGN_MINUS)
981 {
982 *dst = '-';
983 }
984 else
985 {
986 dst++;
987 }
988 return dst;
989}
990
991bigerr_t
992big_negate(a, b)
993bignum *a;
994bignum *b;
995{
996 big_set_big(a, b);
997 b->sign = NEGATE_SIGN(a->sign);
998 return big_errno;
999}
1000
1001int
1002big_sign(a)
1003bignum *a;
1004{
1005 return a->sign;
1006}
1007
1008bigerr_t
1009big_abs(a, b)
1010bignum *a;
1011bignum *b;
1012{
1013 big_set_big(a, b);
1014 if (a->sign == BIG_SIGN_MINUS)
1015 {
1016 b->sign = NEGATE_SIGN(a->sign);
1017 }
1018 return big_errno;
1019}
1020
1021int
1022big_compare(a, b)
1023bignum *a;
1024bignum *b;
1025{
1026 if (a->sign == b->sign)
1027 {
1028 if (a->sign == 0)
1029 {
1030 return 0;
1031 }
1032 return
1033 (a->sign == BIG_SIGN_MINUS)
1034 ? -ucompare_digits(a, b)
1035 : ucompare_digits(a, b);
1036 }
1037 return b->sign - a->sign;
1038}
1039
1040int
1041big_lessp(a, b)
1042bignum *a;
1043bignum *b;
1044{
1045 return big_compare(a, b) < 0;
1046}
1047
1048int
1049big_leqp(a, b)
1050bignum *a;
1051bignum *b;
1052{
1053 return !(big_compare(a, b) > 0);
1054}
1055
1056int
1057big_equalp(a, b)
1058bignum *a;
1059bignum *b;
1060{
1061 return big_compare(a, b) == 0;
1062}
1063
1064int
1065big_geqp(a, b)
1066bignum *a;
1067bignum *b;
1068{
1069 return !(big_compare(a, b) < 0);
1070}
1071
1072int
1073big_greaterp(a, b)
1074bignum *a;
1075bignum *b;
1076{
1077 return big_compare(a, b) > 0;
1078}
1079
1080int
1081big_zerop(a)
1082bignum *a;
1083{
1084 return a->sign == BIG_SIGN_0;
1085}
1086
1087int
1088big_evenp(a)
1089bignum *a;
1090{
1091 return ((*a->dp & 0x01) == 0);
1092}
1093
1094int
1095big_oddp(a)
1096bignum *a;
1097{
1098 return ((*a->dp & 0x01) == 1);
1099}
1100
1101bigerr_t
1102big_add(a, b, c)
1103bignum *a;
1104bignum *b;
1105bignum *c;
1106{
1107 int cmp;
1108
1109 if (big_errno != BIG_OK)
1110 {
1111 return big_errno;
1112 }
1113 print_digits("add:\ta = ", a);
1114 print_digits("\tb = ", b);
1115 if (a->sign == b->sign)
1116 {
1117 uadd_digits(a, b, c);
1118 c->sign = a->sign;
1119 }
1120 else
1121 {
1122 cmp = ucompare_digits(a, b);
1123 if (cmp < 0)
1124 {
1125 usub_digits(b, a, c);
1126 if (zerop(c))
1127 {
1128 c->sign = BIG_SIGN_0;
1129 }
1130 else
1131 {
1132 c->sign = b->sign;
1133 }
1134 }
1135 else if (cmp > 0)
1136 {
1137 usub_digits(a, b, c);
1138 if (zerop(c))
1139 {
1140 c->sign = BIG_SIGN_0;
1141 }
1142 else
1143 {
1144 c->sign = a->sign;
1145 }
1146 }
1147 else
1148 {
1149 c->dgs_used = 1;
1150 *c->dp = 0;
1151 c->sign = BIG_SIGN_0;
1152 }
1153 }
1154 print_digits("\tc = ", c);
1155 return big_errno;
1156}
1157
1158bigerr_t
1159big_sub(a, b, c)
1160bignum *a;
1161bignum *b;
1162bignum *c;
1163{
1164 int cmp;
1165
1166 if (big_errno != BIG_OK)
1167 {
1168 return big_errno;
1169 }
1170 print_digits("sub:\ta = ", a);
1171 print_digits("\tb = ", b);
1172 if (a->sign == BIG_SIGN_0)
1173 {
1174 big_set_big(b, c);
1175 big_negate(c, c);
1176 print_digits("\tc = ", c);
1177 return big_errno;
1178 }
1179 if (b->sign == BIG_SIGN_0)
1180 {
1181 big_set_big(a, c);
1182 print_digits("\tc = ", c);
1183 return big_errno;
1184 }
1185
1186 cmp = ucompare_digits(a, b);
1187 if (cmp <= 0)
1188 {
1189 if (a->sign != b->sign)
1190 {
1191 uadd_digits(a, b, c);
1192 c->sign = a->sign;
1193 }
1194 else
1195 {
1196 usub_digits(b, a, c);
1197 c->sign = (zerop(c) ? BIG_SIGN_0 : NEGATE_SIGN(a->sign));
1198 }
1199 }
1200 else if (cmp > 0)
1201 {
1202 if (a->sign != b->sign)
1203 {
1204 uadd_digits(a, b, c);
1205 c->sign = a->sign;
1206 }
1207 else
1208 {
1209 usub_digits(a, b, c);
1210 c->sign = (zerop(c) ? BIG_SIGN_0 : b->sign);
1211 }
1212 }
1213 else
1214 {
1215 c->dgs_used = 1;
1216 *c->dp = 0;
1217 c->sign = BIG_SIGN_0;
1218 }
1219 print_digits("\tc = ", c);
1220 return big_errno;
1221}
1222
1223bigerr_t
1224big_mul(a, b, c)
1225bignum *a;
1226bignum *b;
1227bignum *c;
1228{
1229 DIGIT *dp_x, *dp_xstart, *dp_xend;
1230 DIGIT *dp_y, *dp_ystart, *dp_yend;
1231 DIGIT *dp_z, *dp_zstart, *dp_zend, *dp_zsumstart;
1232 ulong len_x, len_y /* , len_z */;
1233 DIGIT2 res;
1234 DIGIT tmp_res; /* Without use of this, gcc (v 1.39) generates */
1235 /* erroneous code on a sun386 machine */
1236 /* Should be removed with #ifdef's, when */
1237 /* not on a sun386, but... */
1238
1239 if (big_errno != BIG_OK)
1240 {
1241 return big_errno;
1242 }
1243 print_digits("mul:\ta = ", a);
1244 print_digits("\tb = ", b);
1245
1246 if (zerop(a) || zerop(b))
1247 {
1248 c->sign = BIG_SIGN_0;
1249 c->dgs_used = 1;
1250 *c->dp = 0;
1251 print_digits("(a=0 || b=0)c = ", c);
1252 return big_errno;
1253 }
1254 if (uonep(a))
1255 {
1256 big_set_big(b, c);
1257 c->sign = (a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS;
1258 print_digits("(abs(a)=1)c = ", c);
1259 return big_errno;
1260 }
1261 if (uonep(b))
1262 {
1263 big_set_big(a, c);
1264 c->sign = (a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS;
1265 print_digits("(abs(b)=1)c = ", c);
1266 return big_errno;
1267 }
1268
1269 if (a->dgs_used < b->dgs_used)
1270 {
1271 dp_xstart = a->dp;
1272 len_x = a->dgs_used;
1273 dp_ystart = b->dp;
1274 len_y = b->dgs_used;
1275 }
1276 else
1277 {
1278 dp_xstart = b->dp;
1279 len_x = b->dgs_used;
1280 dp_ystart = a->dp;
1281 len_y = a->dgs_used;
1282 }
1283 if ((c == a) || (c == b))
1284 {
1285 if (newsize(&tmp_mul.dp, &tmp_mul.dgs_alloc,
1286 len_x + len_y, len_x + len_y + 2) != BIG_OK)
1287 {
1288 return big_errno;
1289 }
1290 dp_zsumstart = tmp_mul.dp;
1291 /* len_z = tmp_mul.dgs_alloc; */
1292 }
1293 else
1294 {
1295 if (newsize(&c->dp, &c->dgs_alloc,
1296 len_x + len_y, len_x + len_y + 2) != BIG_OK)
1297 {
1298 return big_errno;
1299 }
1300 dp_zsumstart = c->dp;
1301 /* len_z = c->dgs_alloc; */
1302 }
1303
1304 dp_xend = dp_xstart + len_x;
1305 dp_yend = dp_ystart + len_y;
1306 dp_zend = dp_zsumstart + len_y;
1307
1308 for (dp_z = dp_zsumstart; dp_z < dp_zend; dp_z++)
1309 {
1310 *dp_z = 0; /* Zero out rightmost digits */
1311 }
1312
1313 dp_zstart = dp_zsumstart;
1314
1315 for (dp_x = dp_xstart; dp_x < dp_xend; dp_x++)
1316 {
1317 dp_z = dp_zstart;
1318 tmp_res = 0;
1319 for (dp_y = dp_ystart; dp_y < dp_yend; dp_y++)
1320 {
1321 res = (DIGIT2)(*dp_x) * (*dp_y) + (*dp_z) + tmp_res;
1322 *dp_z++ = DIGIT_PART(res);
1323 tmp_res = SHIFT_DIGIT_DOWN(res);
1324 }
1325 *dp_z = tmp_res;
1326 dp_zstart++;
1327 }
1328 if (dp_zsumstart != c->dp)
1329 {
1330 tmp_digits = c->dp;
1331 c->dp = tmp_mul.dp;
1332 tmp_mul.dp = tmp_digits;
1333
1334 tmp_ulong = c->dgs_alloc;
1335 c->dgs_alloc = tmp_mul.dgs_alloc;
1336 tmp_mul.dgs_alloc = tmp_ulong;
1337 }
1338 if (*dp_z == 0)
1339 {
1340 dp_z--;
1341 }
1342 c->dgs_used = dp_z - dp_zsumstart + 1;
1343 c->sign = a->sign * b->sign;
1344 print_digits("\tc = ", c);
1345 return big_errno;
1346}
1347
1348bigerr_t
1349big_trunc(a, b, q, r)
1350bignum *a;
1351bignum *b;
1352bignum *q;
1353bignum *r;
1354{
1355 DIGIT *v_end, *q_end, *r_end, *src, *dst;
1356 DIGIT norm, qhat, t1, t2, t3, v1, v2, u1, u2, u3;
1357 DIGIT2 temp, res, carry;
1358 long a_l, b_l, q_l, r_l;
1359#if 0
1360 ulong i;
1361#endif
1362 ulong j, m, n;
1363 int cmp, q_eq_a, q_eq_b, r_eq_a, r_eq_b;
1364
1365 if (big_errno != BIG_OK)
1366 {
1367 return big_errno;
1368 }
1369 print_digits("div:\ta = ", a);
1370 print_digits("\tb = ", b);
1371 if (zerop(b))
1372 {
1373 big_errno = BIG_DIV_ZERO;
1374 return big_errno;
1375 }
1376
1377 if (q == r)
1378 {
1379 big_errno = BIG_ARGERR;
1380 return big_errno;
1381 }
1382
1383 if (b->dgs_used == 1)
1384 {
1385 big_set_big(a, q);
1386 q->sign = ((a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS);
1387 *r->dp = udiv_digit(q, *b->dp);
1388 r->dgs_used = 1;
1389 r->sign = (zerop(r) ? BIG_SIGN_0 : a->sign);
1390 print_digits("\t3:q = ", q);
1391 print_digits("\t r = ", r);
1392 return big_errno;
1393 }
1394
1395 if (big_long(a, &a_l)) /* Pretend it is a signed value */
1396 {
1397 big_long(b, &b_l); /* |a| < |b| so this will succeed */
1398 q_l = a_l / b_l; /* Compute with unsigned operators */
1399 r_l = a_l % b_l;
1400 big_set_long((long)q_l, q);
1401 big_set_long((long)r_l, r);
1402 print_digits("\t4:q = ", q);
1403 print_digits("\t r = ", r);
1404 return big_errno;
1405 }
1406
1407 cmp = ucompare_digits(a, b); /* Unsigned compare, that is... */
1408 if (cmp < 0)
1409 {
1410 big_set_big(a, r); /* r = a (don't care about big_errno here) */
1411 q->sign = BIG_SIGN_0; /* q = 0 */
1412 *q->dp = 0;
1413 q->dgs_used = 1;
1414 print_digits("\t1:q = ", q);
1415 print_digits("\t r = ", r);
1416 return big_errno;
1417 }
1418 else
1419 if (cmp == 0)
1420 {
1421 q->sign = ((a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS);
1422 *q->dp = 1; /* q = 1 */
1423 q->dgs_used = 1;
1424 r->sign = BIG_SIGN_0; /* r = 0 */
1425 *r->dp = 0;
1426 r->dgs_used = 1;
1427 print_digits("\t2:q = ", q);
1428 print_digits("\t r = ", r);
1429 return big_errno;
1430 }
1431
1432 q_eq_a = (q == a);
1433 q_eq_b = (q == b);
1434 if (q_eq_a || q_eq_b)
1435 {
1436 q = &tmp_q;
1437 }
1438
1439 r_eq_a = (r == a);
1440 r_eq_b = (r == b);
1441 if (r_eq_a || r_eq_b)
1442 {
1443 r = &tmp_r;
1444 }
1445
1446 if (newsize(&r->dp, &r->dgs_alloc, /* At least one more dig in r */
1447 a->dgs_used + 1, a->dgs_used + 2) != BIG_OK)
1448 {
1449 return big_errno;
1450 }
1451 big_set_big(a, r);
1452 r->dp[a->dgs_used] = 0; /* In case no overflow in mult. */
1453
1454 n = b->dgs_used;
1455 v_end = b->dp + n - 1;
1456 norm = DIGIT_PART((DIGIT_BASE / ((DIGIT2)*v_end + 1)));
1457 if (norm != 1)
1458 {
1459 umul_digit(r, norm);
1460 umul_digit(b, norm);
1461 print_digits("r = ", r);
1462 print_digits("b = ", b);
1463 }
1464 m = a->dgs_used + 1 - b->dgs_used;
1465 r_end = r->dp + a->dgs_used;
1466
1467 if (newsize(&q->dp, &q->dgs_alloc, m, m + 2) != BIG_OK)
1468 {
1469 return big_errno;
1470 }
1471 q_end = q->dp + m - 1;
1472
1473 v1 = *v_end;
1474 v2 = *(v_end - 1);
1475
1476 for (j = 0; j < m; j++) /* m steps through division */
1477 {
1478 u1 = *r_end; /* routine */
1479 u2 = *(r_end - 1);
1480 u3 = *(r_end - 2);
1481 qhat = ((u1 == v1) ?
1482 MAX_DIGIT :
1483 DIGIT_PART(((DIGIT2)u1 * DIGIT_BASE + u2) / v1));
1484 while (1)
1485 {
1486 t3 = DIGIT_PART(temp = (DIGIT2)qhat * v2);
1487 t2 = DIGIT_PART(temp = SHIFT_DIGIT_DOWN(temp) + v1 * (DIGIT2)qhat);
1488 t1 = DIGIT_PART(SHIFT_DIGIT_DOWN(temp));
1489#if 0
1490 printf("t1 = %lu, ", (ulong)t1);
1491 printf("t2 = %lu, ", (ulong)t2);
1492 printf("t3 = %lu\n", (ulong)t3);
1493#endif
1494 if (t1 < u1) break;
1495 if (t1 > u1) {--qhat; continue; }
1496 if (t2 < u2) break;
1497 if (t2 > u2) { --qhat; continue; }
1498 if (t3 <= u3) break;
1499 qhat--;
1500 }
1501
1502 /* This is a tricky one - multiply and subtract simultaneously */
1503 carry = 1;
1504 res = 0;
1505 src = b->dp;
1506 dst = r->dp + m - j - 1;
1507 while (src <= v_end)
1508 {
1509 res = (DIGIT2)qhat * *(src++) + SHIFT_DIGIT_DOWN(res);
1510 carry += (DIGIT2)(*dst) + MAX_DIGIT - DIGIT_PART(res);
1511 *(dst++) = DIGIT_PART(carry);
1512 carry = DIGIT_PART(SHIFT_DIGIT_DOWN(carry));
1513 }
1514 carry += (DIGIT2)(*dst) + MAX_DIGIT - SHIFT_DIGIT_DOWN(res);
1515 *dst = DIGIT_PART(carry);
1516 carry = DIGIT_PART(SHIFT_DIGIT_DOWN(carry));
1517
1518 if (carry == 0)
1519 {
1520 qhat--;
1521 src = b->dp;
1522 dst = r->dp + m - j - 1;
1523 while (dst <= r_end)
1524 {
1525 carry = (DIGIT2)(*dst) + *src++ + SHIFT_DIGIT_DOWN(carry);
1526 *dst++ = DIGIT_PART(carry);
1527 }
1528 *dst = 0;
1529 }
1530 *(q_end - j) = DIGIT_PART(qhat);
1531 r_end--;
1532 }
1533 r->sign = a->sign;
1534#if 0
1535 i = r->dgs_used;
1536#endif
1537 while ((*r_end == 0) && (r_end > r->dp))
1538 {
1539 r_end--;
1540 }
1541 if (r_end == r->dp)
1542 {
1543 r->dgs_used = 1;
1544 r->sign = BIG_SIGN_0;
1545 }
1546 else
1547 {
1548 r->dgs_used = r_end - r->dp + 1;
1549 r->sign = a->sign;
1550 }
1551 if (norm != 1)
1552 {
1553 udiv_digit(b, norm);
1554 udiv_digit(r, norm);
1555 }
1556 while ((*q_end == 0) && (q_end > q->dp)) /* This is not needed!(?) */
1557 {
1558 q_end--;
1559 }
1560 /* was ifdef'd out already in original */
1561#if 0
1562 i = m - 1;
1563 while ((i > 0) && (q->dp[i--] == 0))
1564 {
1565 /* Loop through all zeroes */
1566 }
1567#endif
1568 q->dgs_used = q_end - q->dp + 1;
1569 q->sign = ((a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS);
1570
1571 if (q_eq_a)
1572 {
1573 big_set_big(q, a);
1574 }
1575 else
1576 if (q_eq_b)
1577 {
1578 big_set_big(q, b);
1579 }
1580
1581 if (r_eq_b)
1582 {
1583 big_set_big(r, b);
1584 }
1585 else
1586 if (r_eq_a)
1587 {
1588 big_set_big(r, a);
1589 }
1590
1591 print_digits("\t5:q = ", q);
1592 print_digits("\t r = ", r);
1593 return big_errno;
1594}
1595
1596bigerr_t
1597big_floor(a, b, q, r)
1598bignum *a;
1599bignum *b;
1600bignum *q;
1601bignum *r;
1602{
1603 int b_eq_qr, sign_eq;
1604
1605 if ( ( b_eq_qr = ((b == q) || (b == r)) ) )
1606 {
1607 big_set_big(b, &tmp_mul);
1608 }
1609 sign_eq = a->sign == b->sign;
1610 big_trunc(a, b, q, r);
1611 if (sign_eq)
1612 {
1613 return big_errno;
1614 }
1615 if (!zerop(r))
1616 {
1617 if (b_eq_qr)
1618 {
1619 big_add(r, &tmp_mul, r);
1620 }
1621 else
1622 {
1623 big_add(r, b, r);
1624 }
1625 print_digits("big_one = ", &big_one);
1626 big_sub(q, &big_one, q);
1627 }
1628 return big_errno;
1629}
1630
1631bigerr_t
1632big_ceil(a, b, q, r)
1633bignum *a;
1634bignum *b;
1635bignum *q;
1636bignum *r;
1637{
1638 int b_eq_qr, sign_diff;
1639
1640 if ( ( b_eq_qr = ((b == q) || (b == r)) ) )
1641 {
1642 big_set_big(b, &tmp_mul);
1643 }
1644 sign_diff = a->sign != b->sign;
1645 big_trunc(a, b, q, r);
1646 if (sign_diff)
1647 {
1648 return big_errno;
1649 }
1650 if (!zerop(r))
1651 {
1652 if (b_eq_qr)
1653 {
1654 big_sub(r, &tmp_mul, r);
1655 }
1656 else
1657 {
1658 big_sub(r, b, r);
1659 }
1660 big_add(q, &big_one, q);
1661 }
1662 return big_errno;
1663}
1664
1665#ifdef UNUSED_CODE
1666/* This one doesn't work to 100%. I was a little braindamaged when I wrote
1667 * this, but I'll eventually fix it. Zzzzzzz.
1668 */
1669bigerr_t
1670big_round(a, b, q, r)
1671bignum *a;
1672bignum *b;
1673bignum *q;
1674bignum *r;
1675{
1676 int b_eq_qr, b_neg_p, a_sgn_neq_b_sgn;
1677
1678 if ( ( b_eq_qr = ((b == q) || (b == r)) ) )
1679 {
1680 big_set_big(b, &tmp_round);
1681 }
1682 b_neg_p = b->sign == BIG_SIGN_MINUS;
1683 a_sgn_neq_b_sgn = a->sign != b->sign;
1684 big_trunc(a, b, q, r);
1685
1686 big_set_big(r, &tmp_add);
1687 umul_digit(&tmp_add, 2);
1688 if (ucompare_digits(&tmp_add, b) > 0) /* |2 * r| > |b| */
1689 {
1690 if (q->sign == BIG_SIGN_0)
1691 {
1692 if (a_sgn_neq_b_sgn)
1693 {
1694 big_sub(q, &big_one, q);
1695 }
1696 else
1697 {
1698 big_add(q, &big_one, q);
1699 }
1700 }
1701 else
1702 {
1703 if (q->sign == BIG_SIGN_MINUS)
1704 {
1705 big_sub(q, &big_one, q);
1706 }
1707 else
1708 {
1709 big_add(q, &big_one, q);
1710 }
1711 }
1712 if (b_eq_qr)
1713 {
1714 if (q->sign == BIG_SIGN_PLUS)
1715 {
1716 big_sub(r, &tmp_round, r);
1717 }
1718 else
1719 {
1720 big_add(r, &tmp_round, r);
1721 }
1722 }
1723 else
1724 {
1725 if (q->sign == BIG_SIGN_PLUS)
1726 {
1727 big_sub(r, b, r);
1728 }
1729 else
1730 {
1731 big_add(r, b, r);
1732 }
1733 }
1734 }
1735 return big_errno;
1736}
1737
1738bigerr_t
1739big_random(a, b)
1740bignum *a;
1741bignum *b;
1742{
1743 unsigned long i;
1744 int a_sgn = a->sign;
1745
1746 if (big_errno != BIG_OK)
1747 {
1748 return big_errno;
1749 }
1750 if (zerop(a)) /* a = 0 -> big_random => 0 (special case) */
1751 {
1752 *b->dp = 0;
1753 b->dgs_used = 1;
1754 b->sign = a_sgn;
1755 return big_errno;
1756 }
1757 if (newsize(&tmp_rand.dp, &tmp_rand.dgs_alloc,
1758 a->dgs_used + 1, a->dgs_used + 1) != BIG_OK)
1759 {
1760 return big_errno;
1761 }
1762 for (i = 0; i <= a->dgs_used; i++)
1763 {
1764 tmp_rand.dp[i] = rand();
1765 }
1766 while (tmp_rand.dp[a->dgs_used] == 0) /* Make sure high digit is non-0 */
1767 {
1768 tmp_rand.dp[a->dgs_used] = rand();
1769 }
1770 tmp_rand.dgs_used = a->dgs_used + 1;
1771 tmp_rand.sign = BIG_SIGN_PLUS;
1772 a->sign = BIG_SIGN_PLUS;
1773 big_trunc(&tmp_rand, a, &tmp_q, b); /* Dangerous to use tmp_q here... */
1774 a->sign = a_sgn;
1775 b->sign = zerop(&tmp_rand) ? BIG_SIGN_0 : a_sgn;
1776 return big_errno;
1777}
1778
1779/* UNUSED_CODE */
1780#endif
1781
1782/* ----------------------------------------------------------------------
1783 * External functions that do not need to know anything about the internal
1784 * representation of a bignum.
1785 */
1786
1787#ifdef UNUSED_CODE
1788
1789int
1790big_expt(a, z, x)
1791bignum *a;
1792unsigned long z;
1793bignum *x;
1794{
1795 bignum b;
1796
1797 big_create(&b);
1798 big_set_big(a, &b);
1799 big_set_long((long)1, x);
1800
1801 while ((z != 0) && (big_errno == BIG_OK))
1802 {
1803 while ((z & 0x01) == 0)
1804 {
1805 z >>= 1;
1806 big_mul(&b, &b, &b);
1807 }
1808 z -= 1;
1809 big_mul(x, &b, x);
1810 }
1811
1812 big_destroy(&b);
1813 return big_errno;
1814}
1815
1816/* UNUSED_CODE */
1817#endif
1818
1819int
1820big_exptmod(a_in, z_in, n, x)
1821bignum *a_in;
1822bignum *z_in;
1823bignum *n;
1824bignum *x;
1825{
1826 bignum a, z, b0, b1, b2, dummy;
1827
1828 big_create(&a);
1829 big_create(&z);
1830 big_create(&b0);
1831 big_create(&b1);
1832 big_create(&b2);
1833 big_create(&dummy);
1834
1835 big_set_big(a_in, &a);
1836 big_set_big(z_in, &z);
1837 big_set_long((long)1, x);
1838 big_set_long((long)0, &b0);
1839 big_set_long((long)1, &b1);
1840 big_set_long((long)2, &b2);
1841
1842 /* No foolproof testing on big_errno - it really ought to be done */
1843 while ((big_compare(&z, &b0) != 0) && (big_errno == BIG_OK))
1844 {
1845 while (big_evenp(&z) && (big_errno == BIG_OK))
1846 {
1847 big_trunc(&z, &b2, &z, &dummy);
1848 big_mul(&a, &a, &a);
1849 big_trunc(&a, n, &dummy, &a);
1850 }
1851 big_sub(&z, &b1, &z);
1852 big_mul(x, &a, x);
1853 big_trunc(x, n, &dummy, x);
1854 }
1855
1856 big_destroy(&dummy);
1857 big_destroy(&b2);
1858 big_destroy(&b1);
1859 big_destroy(&b0);
1860 big_destroy(&z);
1861 big_destroy(&a);
1862
1863 return big_errno;
1864}
1865
1866#ifdef UNUSED_CODE
1867
1868int
1869big_gcd(a, b, g)
1870bignum *a;
1871bignum *b;
1872bignum *g;
1873{
1874 bignum a1, b1, tmp;
1875
1876 if (big_zerop(b))
1877 {
1878 big_abs(a, g);
1879 return big_errno;
1880 }
1881
1882 big_create(&a1);
1883 big_create(&b1);
1884 big_create(&tmp);
1885
1886 big_abs(a, &a1);
1887 big_abs(b, &b1);
1888
1889 while (!big_zerop(&b1) && (big_errno == BIG_OK))
1890 {
1891 big_floor(&a1, &b1, &tmp, &a1);
1892 if (big_zerop(&a1))
1893 {
1894 break;
1895 }
1896 big_floor(&b1, &a1, &tmp, &b1);
1897 }
1898
1899 if (big_zerop(&a1))
1900 {
1901 big_set_big(&b1, g);
1902 }
1903 else
1904 {
1905 big_set_big(&a1, g);
1906 }
1907
1908 big_destroy(&tmp);
1909 big_destroy(&b1);
1910 big_destroy(&a1);
1911
1912 return big_errno;
1913}
1914/* UNUSED_CODE */
1915#endif
1916
1917/* #if (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)) */
1918#endif
1919
Note: See TracBrowser for help on using the repository browser.