source: trunk/src/bignum.c@ 592

Last change on this file since 592 was 592, checked in by katerina, 38 hours ago

Fixes for compiler warnings.

File size: 35.3 KB
Line 
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 = ((1U << (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;
211 (void) count;
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
229 digit_ptr = calloc(alloclen, sizeof(DIGIT));
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 int retval = 0;
428
429 if (a->dgs_used == b->dgs_used)
430 {
431 a_ptr = a->dp + a->dgs_used - 1;
432 b_ptr = b->dp + b->dgs_used - 1;
433 while ((*a_ptr == *b_ptr) && (a_ptr >= a->dp))
434 {
435 a_ptr--;
436 b_ptr--;
437 }
438 if (a_ptr < a->dp)
439 {
440 return retval;
441 }
442 else
443 {
444 if (retval == 0)
445 retval = (*a_ptr > *b_ptr) ? 1 : -1;
446 }
447 return retval;
448 }
449 return (a->dgs_used > b->dgs_used) ? 1 : -1;
450}
451
452static void
453uadd_digits(bignum *a, bignum *b, bignum *c)
454{
455 DIGIT *dp_x, *dp_y, *dp_z, *res_dp, *end_x, *end_y;
456 ulong len_x, len_y;
457 DIGIT2 res = 0;
458
459 if (a->dgs_used > b->dgs_used)
460 {
461 dp_x = a->dp;
462 len_x = a->dgs_used;
463 dp_y = b->dp;
464 len_y = b->dgs_used;
465 }
466 else
467 {
468 dp_x = b->dp;
469 len_x = b->dgs_used;
470 dp_y = a->dp;
471 len_y = a->dgs_used;
472 }
473 end_x = dp_x + len_x;
474 end_y = dp_y + len_y;
475 if (c->dgs_alloc >= len_x)
476 {
477 dp_z = c->dp;
478 }
479 else
480 {
481 if (newsize(&tmp_add.dp, &tmp_add.dgs_alloc,
482 len_x, len_x + 4) != BIG_OK)
483 {
484 return;
485 }
486 dp_z = tmp_add.dp;
487 }
488 res_dp = dp_z;
489 while (dp_y < end_y)
490 {
491 res += ((DIGIT2)*dp_x++) + *dp_y++;
492 *res_dp++ = DIGIT_PART(res);
493 res = SHIFT_DIGIT_DOWN(res);
494 }
495 while (dp_x < end_x)
496 {
497 res += *dp_x++;
498 *res_dp++ = DIGIT_PART(res);
499 res = SHIFT_DIGIT_DOWN(res);
500 }
501 if (res != 0)
502 {
503 *res_dp++ = DIGIT_PART(res);
504 }
505
506 if (dp_z != c->dp)
507 {
508 tmp_digits = c->dp;
509 c->dp = tmp_add.dp;
510 tmp_add.dp = tmp_digits;
511
512 tmp_ulong = c->dgs_alloc;
513 c->dgs_alloc = tmp_add.dgs_alloc;
514 tmp_add.dgs_alloc = tmp_ulong;
515 }
516 c->dgs_used = res_dp - c->dp;
517}
518
519static void
520usub_digits(bignum *a, bignum *b, bignum *c)
521{
522 DIGIT *dp_x, *dp_y, *dp_z, *res_dp, *end_x, *end_y;
523 ulong len_x, len_y;
524 DIGIT2 res = 0;
525
526 dp_x = a->dp;
527 len_x = a->dgs_used;
528 dp_y = b->dp;
529 len_y = b->dgs_used;
530
531 end_x = dp_x + len_x;
532 end_y = dp_y + len_y;
533 if (c->dgs_alloc >= len_x)
534 {
535 dp_z = c->dp;
536 }
537 else
538 {
539 if (newsize(&tmp_add.dp, &tmp_add.dgs_alloc,
540 len_x, len_x + 2) != BIG_OK)
541 {
542 return;
543 }
544 dp_z = tmp_add.dp;
545 }
546 res_dp = dp_z;
547 while (dp_y < end_y)
548 {
549 res = ((DIGIT2)*dp_x++) - *dp_y++ - RESULT_MINUSP(res);
550 *res_dp++ = DIGIT_PART(res);
551 }
552 while (dp_x < end_x)
553 {
554 res = *dp_x++ - RESULT_MINUSP(res);
555 *res_dp++ = DIGIT_PART(res);
556 }
557#ifdef BIG_CHECK_LIMITS
558 if (RESULT_MINUSP(res) != 0)
559 {
560 big_errno = BIG_ALGERR;
561 return;
562 }
563#endif
564 while ((*--res_dp == 0) && (res_dp > dp_z))
565 {
566 /* Move pointer down until we reach a non-zero */
567 }
568 if (dp_z != c->dp)
569 {
570 tmp_digits = c->dp;
571 c->dp = tmp_add.dp;
572 tmp_add.dp = tmp_digits;
573
574 tmp_ulong = tmp_add.dgs_alloc;
575 tmp_add.dgs_alloc = c->dgs_alloc;
576 c->dgs_alloc = tmp_ulong;
577 }
578 c->dgs_used = res_dp - dp_z + 1;
579}
580
581/*
582 * This (pseudo) random number generator is not very good. It has a long
583 * period [ 2 ^ (DIGIT_BITS * 2) (?)] before it starts with the same sequence
584 * again, but the lower bits are "less random" than they should be. I've
585 * solved it by using word of double length, and returning the upper bits.
586 * Please mail me if you know how to make it into a "more random" generator.
587 * One important thing though: it will have to reasonably fast.
588 * The good thing with this one is that it is very portable, but that doesn't
589 * help much when you want _good_ random numbers.
590 * Henrik.Johansson@Nexus.Comm.SE
591 */
592#ifdef UNUSED_CODE
593static DIGIT
594rand(void)
595{
596 static DIGIT2 x1 = 33, x2 = 45; /* Just give them two starting values */
597
598 if (x2 = BIG_RAND_A2 * x2 + BIG_RAND_C2, x2 == 45)
599 {
600 x1 = BIG_RAND_A1 * x1 + BIG_RAND_C1;
601 }
602 return SHIFT_DIGIT_DOWN(x1 + x2); /* Skip least significant bits */
603}
604/* UNUSED_CODE */
605#endif
606
607/* ----------------------------------------------------------------------
608 * All external functions comes here.
609 */
610
611bigerr_t
612big_init_pkg()
613{
614 strcpy (big_base_digits, _(big_base_digits1)); /* known to fit */
615 init_digit_blocks();
616 big_create(&tmp_string);
617 big_create(&tmp_add);
618 big_create(&tmp_mul);
619 big_create(&tmp_q);
620 big_create(&tmp_r);
621 big_create(&tmp_rand);
622 big_create(&big_one);
623 big_set_long((long)1, &big_one);
624 length_last_string = 10;
625 if ((last_string = calloc(1,length_last_string)) == NULL)
626 {
627 big_errno = BIG_MEMERR;
628 }
629 return big_errno;
630}
631
632void
633big_release_pkg()
634{
635 big_destroy(&tmp_string);
636 big_destroy(&tmp_add);
637 big_destroy(&tmp_mul);
638 big_destroy(&tmp_q);
639 big_destroy(&tmp_r);
640 big_destroy(&tmp_round);
641 big_destroy(&big_one);
642 if (last_string != NULL)
643 free(last_string);
644#ifdef COUNT_ALLOC
645 printf("Allocated digits: %lu\n", dgs_alloc);
646 printf("Freed digits: %lu\n", digits_freed);
647#endif
648}
649
650bigerr_t
651big_create(bignum * a)
652{
653 /* Make sure that big_create alway returns a NULL bignum
654 * that can safely be destroyed.
655 */
656 if (a != NULL)
657 {
658 a->dp = NULL;
659 }
660 if (big_errno != BIG_OK)
661 {
662 return big_errno;
663 }
664 if (a == NULL)
665 {
666 big_errno = BIG_ARGERR;
667 return big_errno;
668 }
669
670 a->sign = BIG_SIGN_0;
671 a->dgs_used = 1;
672 if ((a->dp = allocate_digits((long)sizeof(long))) == NULL)
673 {
674 return big_errno;
675 }
676 a->dgs_alloc = sizeof(long);
677 *a->dp = 0;
678 return big_errno;
679}
680
681void
682big_destroy(bignum *a)
683{
684 /* Mar 4, 2000 R. Wichmann: check for a == NULL */
685 /* free_digits() checks for a->dp == NULL */
686 if (a != NULL)
687 free_digits(a->dp, a->dgs_alloc);
688}
689
690ulong
691big_bitcount(bignum *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(bignum *a, bignum *b)
711{
712 if ((big_errno != BIG_OK) || (a == b))
713 {
714 return big_errno;
715 }
716 if (newsize(&b->dp, &b->dgs_alloc, a->dgs_used, a->dgs_used) != BIG_OK)
717 {
718 return big_errno;
719 }
720 b->dgs_used = a->dgs_used;
721 b->sign = a->sign;
722 digits_cpy(b->dp, a->dp, a->dgs_used);
723 return big_errno;
724}
725
726
727void
728big_set_ulong(ulong n, bignum *a)
729{
730 unsigned int i;
731
732 if (big_errno != BIG_OK)
733 {
734 return;
735 }
736 if (n == 0)
737 {
738 *a->dp = 0;
739 a->dgs_used = 1;
740 a->sign = BIG_SIGN_0;
741 }
742 else
743 {
744 a->dgs_used = 0;
745 for (i = 0; i < sizeof(long) / sizeof(DIGIT); i++)
746 {
747 if (n == 0)
748 {
749 break;
750 }
751 a->dgs_used++;
752 a->dp[i] = DIGIT_PART(n);
753 n = SHIFT_DIGIT_DOWN(n);
754 }
755 a->sign = BIG_SIGN_PLUS;
756 }
757 print_digits("set_(u)long: a = ", a);
758}
759
760void
761big_set_long(long n, bignum *a)
762{
763 ulong m;
764
765 m = (n < 0) ? - n : n;
766 big_set_ulong(m, a);
767 if (!(n >= 0))
768 {
769 a->sign = BIG_SIGN_MINUS;
770 }
771}
772
773
774bigerr_t
775big_set_string(char * numstr, int base, bignum *a)
776{
777 char *src, *maxdigit, *chrptr;
778 DIGIT dig_base, dig_sum, last_base;
779 int cnt, maxcnt;
780
781 if (big_errno != BIG_OK)
782 {
783 return big_errno;
784 }
785
786 big_end_string = numstr;
787 if ((base < 2) || (base > 36) || (numstr == NULL) || (a == NULL))
788 {
789 big_errno = BIG_ARGERR;
790 return big_errno;
791 }
792
793 src = numstr;
794
795 maxdigit = big_base_digits + (base << 1);
796
797 maxcnt = big_block[base].digCnt;
798 dig_base = big_block[base].dig_base;
799 a->dgs_used = 1;
800 *a->dp = 0;
801 a->sign = BIG_SIGN_PLUS; /* Assume it will be positive */
802 while (strchr(" \t\n\r", *src) != NULL) /* Skip whitespaces */
803 {
804 src++;
805 }
806 if ((*src == '-') || (*src == '+')) /* First non-white is a sign? */
807 {
808 a->sign = (*src == '-') ? BIG_SIGN_MINUS : BIG_SIGN_PLUS;
809 src++;
810 }
811 chrptr = strchr(big_base_digits, *src);
812 if ((chrptr == NULL) || (chrptr >= maxdigit)) /* Next chr not a digit? */
813 {
814 big_end_string = src;
815 big_errno = BIG_ARGERR;
816 return big_errno;
817 }
818 while (*src == '0') /* Next chr a '0'? */
819 {
820 src++; /* Read past all '0'es */
821 }
822 chrptr = strchr(big_base_digits, *src);
823 if ((chrptr == NULL) || (chrptr >= maxdigit)) /* Next char not a digit */
824 {
825 big_end_string = src;
826 a->sign = BIG_SIGN_0; /* It was just a plain 0 */
827 return big_errno;
828 }
829 dig_sum = 0;
830 cnt = 0;
831 while ((chrptr = strchr(big_base_digits, *src)),
832 (chrptr != NULL) && (chrptr < maxdigit))
833 {
834 dig_sum = dig_sum * base + ((chrptr - big_base_digits) >> 1);
835 if (++cnt >= maxcnt)
836 {
837 umul_digit(a, dig_base);
838 add_digit(a, dig_sum);
839 dig_sum = 0;
840 cnt = 0;
841 }
842 src++;
843 }
844 if (cnt > 0)
845 {
846 last_base = base;
847 while (--cnt > 0)
848 {
849 last_base *= base;
850 }
851 umul_digit(a, last_base);
852 add_digit(a, dig_sum);
853 }
854 big_end_string = src;
855 return big_errno;
856}
857
858
859int
860big_ulong(bignum *a, ulong *n)
861{
862 ulong old_n;
863 DIGIT *dp;
864
865 if (big_errno != BIG_OK)
866 {
867 return FALSE;
868 }
869 if (a->dgs_used > sizeof(ulong) / sizeof(DIGIT))
870 {
871 return FALSE;
872 }
873 dp = a->dp + a->dgs_used - 1;
874 old_n = *n = *dp--;
875 while ((dp >= a->dp) && (old_n < *n))
876 {
877 old_n = *n;
878 *n = SHIFT_DIGIT_UP(*n) + *dp--;
879 }
880 if (old_n >= *n)
881 {
882 return FALSE;
883 }
884 return FALSE;
885}
886
887int
888big_long(bignum *a, long *n)
889{
890 long old_n;
891 DIGIT *dp;
892
893 if (a->dgs_used > sizeof(ulong) / sizeof(DIGIT))
894 {
895 return FALSE;
896 }
897 dp = a->dp + a->dgs_used - 1;
898 old_n = *n = *dp--;
899 while ((dp >= a->dp) && (old_n <= *n))
900 {
901 old_n = *n;
902 *n = SHIFT_DIGIT_UP(*n) + *dp--;
903 }
904 if (old_n >= *n)
905 {
906 return FALSE;
907 }
908 if (a->sign == BIG_SIGN_MINUS)
909 {
910 *n = -*n;
911 }
912 return FALSE;
913}
914
915
916char *
917big_string(bignum *a, int base)
918{
919 ulong bit_length, str_length;
920 char *dst;
921 DIGIT dig_base, rem;
922 int cnt, maxcnt;
923
924 if (big_errno != BIG_OK)
925 {
926 return _(error_string);
927 }
928 big_set_big(a, &tmp_string);
929 /* Need more room than minimum here... */
930 bit_length = tmp_string.dgs_used * DIGIT_BITS;
931 /* bit_length = big_bitcount(&tmp_string); */
932 str_length = (ulong)(bit_length / log2tbl[base] + 4);
933 if (str_length > length_last_string)
934 {
935 if (last_string != NULL)
936 free(last_string);
937 if ((last_string = calloc(1,str_length)) == NULL)
938 {
939 big_errno = BIG_MEMERR;
940 return NULL;
941 }
942 length_last_string = str_length;
943 }
944
945 dst = last_string + length_last_string - 1;
946 *dst-- = '\0';
947 maxcnt = big_block[base].digCnt;
948 dig_base = big_block[base].dig_base;
949 while (tmp_string.dgs_used > 1)
950 {
951 rem = udiv_digit(&tmp_string, dig_base);
952 for (cnt = 0; cnt < maxcnt; cnt++)
953 {
954 *dst-- = big_base_digits[(rem % base) << 1];
955 rem /= base;
956 }
957 }
958 rem = *tmp_string.dp;
959 do
960 {
961 *dst-- = big_base_digits[(rem % base) << 1];
962 rem /= base;
963 } while (rem != 0);
964
965 if (a->sign == BIG_SIGN_MINUS)
966 {
967 *dst = '-';
968 }
969 else
970 {
971 dst++;
972 }
973 return dst;
974}
975
976bigerr_t
977big_negate(bignum *a, bignum *b)
978{
979 big_set_big(a, b);
980 b->sign = NEGATE_SIGN(a->sign);
981 return big_errno;
982}
983
984int
985big_sign(bignum *a)
986{
987 return a->sign;
988}
989
990bigerr_t
991big_abs(bignum *a, bignum *b)
992{
993 big_set_big(a, b);
994 if (a->sign == BIG_SIGN_MINUS)
995 {
996 b->sign = NEGATE_SIGN(a->sign);
997 }
998 return big_errno;
999}
1000
1001int
1002big_compare(bignum *a, bignum *b)
1003{
1004 if (a->sign == b->sign)
1005 {
1006 if (a->sign == 0)
1007 {
1008 return 0;
1009 }
1010 return
1011 (a->sign == BIG_SIGN_MINUS)
1012 ? -ucompare_digits(a, b)
1013 : ucompare_digits(a, b);
1014 }
1015 return b->sign - a->sign;
1016}
1017
1018int
1019big_lessp(bignum *a, bignum *b)
1020{
1021 return big_compare(a, b) < 0;
1022}
1023
1024int
1025big_leqp(bignum *a, bignum *b)
1026{
1027 return !(big_compare(a, b) > 0);
1028}
1029
1030int
1031big_equalp(bignum *a, bignum *b)
1032{
1033 return big_compare(a, b) == 0;
1034}
1035
1036int
1037big_geqp(bignum *a, bignum *b)
1038{
1039 return !(big_compare(a, b) < 0);
1040}
1041
1042int
1043big_greaterp(bignum *a, bignum *b)
1044{
1045 return big_compare(a, b) > 0;
1046}
1047
1048int
1049big_zerop(bignum *a)
1050{
1051 return a->sign == BIG_SIGN_0;
1052}
1053
1054int
1055big_evenp(bignum *a)
1056{
1057 return ((*a->dp & 0x01) == 0);
1058}
1059
1060int
1061big_oddp(bignum *a)
1062{
1063 return ((*a->dp & 0x01) == 1);
1064}
1065
1066bigerr_t
1067big_add(bignum *a, bignum *b, bignum *c)
1068{
1069 int cmp;
1070
1071 if (big_errno != BIG_OK)
1072 {
1073 return big_errno;
1074 }
1075 print_digits("add:\ta = ", a);
1076 print_digits("\tb = ", b);
1077 if (a->sign == b->sign)
1078 {
1079 uadd_digits(a, b, c);
1080 c->sign = a->sign;
1081 }
1082 else
1083 {
1084 cmp = ucompare_digits(a, b);
1085 if (cmp < 0)
1086 {
1087 usub_digits(b, a, c);
1088 if (zerop(c))
1089 {
1090 c->sign = BIG_SIGN_0;
1091 }
1092 else
1093 {
1094 c->sign = b->sign;
1095 }
1096 }
1097 else if (cmp > 0)
1098 {
1099 usub_digits(a, b, c);
1100 if (zerop(c))
1101 {
1102 c->sign = BIG_SIGN_0;
1103 }
1104 else
1105 {
1106 c->sign = a->sign;
1107 }
1108 }
1109 else
1110 {
1111 c->dgs_used = 1;
1112 *c->dp = 0;
1113 c->sign = BIG_SIGN_0;
1114 }
1115 }
1116 print_digits("\tc = ", c);
1117 return big_errno;
1118}
1119
1120bigerr_t
1121big_sub(bignum *a, bignum *b, bignum *c)
1122{
1123 int cmp;
1124
1125 if (big_errno != BIG_OK)
1126 {
1127 return big_errno;
1128 }
1129 print_digits("sub:\ta = ", a);
1130 print_digits("\tb = ", b);
1131 if (a->sign == BIG_SIGN_0)
1132 {
1133 big_set_big(b, c);
1134 big_negate(c, c);
1135 print_digits("\tc = ", c);
1136 return big_errno;
1137 }
1138 if (b->sign == BIG_SIGN_0)
1139 {
1140 big_set_big(a, c);
1141 print_digits("\tc = ", c);
1142 return big_errno;
1143 }
1144
1145 cmp = ucompare_digits(a, b);
1146 if (cmp <= 0)
1147 {
1148 if (a->sign != b->sign)
1149 {
1150 uadd_digits(a, b, c);
1151 c->sign = a->sign;
1152 }
1153 else
1154 {
1155 usub_digits(b, a, c);
1156 c->sign = (zerop(c) ? BIG_SIGN_0 : NEGATE_SIGN(a->sign));
1157 }
1158 }
1159 else if (cmp > 0)
1160 {
1161 if (a->sign != b->sign)
1162 {
1163 uadd_digits(a, b, c);
1164 c->sign = a->sign;
1165 }
1166 else
1167 {
1168 usub_digits(a, b, c);
1169 c->sign = (zerop(c) ? BIG_SIGN_0 : b->sign);
1170 }
1171 }
1172 else
1173 {
1174 c->dgs_used = 1;
1175 *c->dp = 0;
1176 c->sign = BIG_SIGN_0;
1177 }
1178 print_digits("\tc = ", c);
1179 return big_errno;
1180}
1181
1182bigerr_t
1183big_mul(bignum *a, bignum *b, bignum *c)
1184{
1185 DIGIT *dp_x, *dp_xstart, *dp_xend;
1186 DIGIT *dp_y, *dp_ystart, *dp_yend;
1187 DIGIT *dp_z, *dp_zstart, *dp_zend, *dp_zsumstart;
1188 ulong len_x, len_y /* , len_z */;
1189 DIGIT2 res;
1190 DIGIT tmp_res; /* Without use of this, gcc (v 1.39) generates */
1191 /* erroneous code on a sun386 machine */
1192 /* Should be removed with #ifdef's, when */
1193 /* not on a sun386, but... */
1194
1195 if (big_errno != BIG_OK)
1196 {
1197 return big_errno;
1198 }
1199 print_digits("mul:\ta = ", a);
1200 print_digits("\tb = ", b);
1201
1202 if (zerop(a) || zerop(b))
1203 {
1204 c->sign = BIG_SIGN_0;
1205 c->dgs_used = 1;
1206 *c->dp = 0;
1207 print_digits("(a=0 || b=0)c = ", c);
1208 return big_errno;
1209 }
1210 if (uonep(a))
1211 {
1212 big_set_big(b, c);
1213 c->sign = (a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS;
1214 print_digits("(abs(a)=1)c = ", c);
1215 return big_errno;
1216 }
1217 if (uonep(b))
1218 {
1219 big_set_big(a, c);
1220 c->sign = (a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS;
1221 print_digits("(abs(b)=1)c = ", c);
1222 return big_errno;
1223 }
1224
1225 if (a->dgs_used < b->dgs_used)
1226 {
1227 dp_xstart = a->dp;
1228 len_x = a->dgs_used;
1229 dp_ystart = b->dp;
1230 len_y = b->dgs_used;
1231 }
1232 else
1233 {
1234 dp_xstart = b->dp;
1235 len_x = b->dgs_used;
1236 dp_ystart = a->dp;
1237 len_y = a->dgs_used;
1238 }
1239 if ((c == a) || (c == b))
1240 {
1241 if (newsize(&tmp_mul.dp, &tmp_mul.dgs_alloc,
1242 len_x + len_y, len_x + len_y + 2) != BIG_OK)
1243 {
1244 return big_errno;
1245 }
1246 dp_zsumstart = tmp_mul.dp;
1247 /* len_z = tmp_mul.dgs_alloc; */
1248 }
1249 else
1250 {
1251 if (newsize(&c->dp, &c->dgs_alloc,
1252 len_x + len_y, len_x + len_y + 2) != BIG_OK)
1253 {
1254 return big_errno;
1255 }
1256 dp_zsumstart = c->dp;
1257 /* len_z = c->dgs_alloc; */
1258 }
1259
1260 dp_xend = dp_xstart + len_x;
1261 dp_yend = dp_ystart + len_y;
1262 dp_zend = dp_zsumstart + len_y;
1263
1264 for (dp_z = dp_zsumstart; dp_z < dp_zend; dp_z++)
1265 {
1266 *dp_z = 0; /* Zero out rightmost digits */
1267 }
1268
1269 dp_zstart = dp_zsumstart;
1270
1271 for (dp_x = dp_xstart; dp_x < dp_xend; dp_x++)
1272 {
1273 dp_z = dp_zstart;
1274 tmp_res = 0;
1275 for (dp_y = dp_ystart; dp_y < dp_yend; dp_y++)
1276 {
1277 res = (DIGIT2)(*dp_x) * (*dp_y) + (*dp_z) + tmp_res;
1278 *dp_z++ = DIGIT_PART(res);
1279 tmp_res = SHIFT_DIGIT_DOWN(res);
1280 }
1281 *dp_z = tmp_res;
1282 dp_zstart++;
1283 }
1284 if (dp_zsumstart != c->dp)
1285 {
1286 tmp_digits = c->dp;
1287 c->dp = tmp_mul.dp;
1288 tmp_mul.dp = tmp_digits;
1289
1290 tmp_ulong = c->dgs_alloc;
1291 c->dgs_alloc = tmp_mul.dgs_alloc;
1292 tmp_mul.dgs_alloc = tmp_ulong;
1293 }
1294 if (*dp_z == 0)
1295 {
1296 dp_z--;
1297 }
1298 c->dgs_used = dp_z - dp_zsumstart + 1;
1299 c->sign = a->sign * b->sign;
1300 print_digits("\tc = ", c);
1301 return big_errno;
1302}
1303
1304bigerr_t
1305big_trunc(bignum *a, bignum *b, bignum *q, bignum *r)
1306{
1307 DIGIT *v_end, *q_end, *r_end, *src, *dst;
1308 DIGIT norm, qhat, t1, t2, t3, v1, v2, u1, u2, u3;
1309 DIGIT2 temp, res, carry;
1310 long a_l, b_l, q_l, r_l;
1311#if 0
1312 ulong i;
1313#endif
1314 ulong j, m, n;
1315 int cmp, q_eq_a, q_eq_b, r_eq_a, r_eq_b;
1316
1317 if (big_errno != BIG_OK)
1318 {
1319 return big_errno;
1320 }
1321 print_digits("div:\ta = ", a);
1322 print_digits("\tb = ", b);
1323 if (zerop(b))
1324 {
1325 big_errno = BIG_DIV_ZERO;
1326 return big_errno;
1327 }
1328
1329 if (q == r)
1330 {
1331 big_errno = BIG_ARGERR;
1332 return big_errno;
1333 }
1334
1335 if (b->dgs_used == 1)
1336 {
1337 big_set_big(a, q);
1338 q->sign = ((a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS);
1339 *r->dp = udiv_digit(q, *b->dp);
1340 r->dgs_used = 1;
1341 r->sign = (zerop(r) ? BIG_SIGN_0 : a->sign);
1342 print_digits("\t3:q = ", q);
1343 print_digits("\t r = ", r);
1344 return big_errno;
1345 }
1346
1347 if (big_long(a, &a_l)) /* Pretend it is a signed value */
1348 {
1349 big_long(b, &b_l); /* |a| < |b| so this will succeed */
1350 q_l = a_l / b_l; /* Compute with unsigned operators */
1351 r_l = a_l % b_l;
1352 big_set_long((long)q_l, q);
1353 big_set_long((long)r_l, r);
1354 print_digits("\t4:q = ", q);
1355 print_digits("\t r = ", r);
1356 return big_errno;
1357 }
1358
1359 cmp = ucompare_digits(a, b); /* Unsigned compare, that is... */
1360 if (cmp < 0)
1361 {
1362 big_set_big(a, r); /* r = a (don't care about big_errno here) */
1363 q->sign = BIG_SIGN_0; /* q = 0 */
1364 *q->dp = 0;
1365 q->dgs_used = 1;
1366 print_digits("\t1:q = ", q);
1367 print_digits("\t r = ", r);
1368 return big_errno;
1369 }
1370 else
1371 if (cmp == 0)
1372 {
1373 q->sign = ((a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS);
1374 *q->dp = 1; /* q = 1 */
1375 q->dgs_used = 1;
1376 r->sign = BIG_SIGN_0; /* r = 0 */
1377 *r->dp = 0;
1378 r->dgs_used = 1;
1379 print_digits("\t2:q = ", q);
1380 print_digits("\t r = ", r);
1381 return big_errno;
1382 }
1383
1384 q_eq_a = (q == a);
1385 q_eq_b = (q == b);
1386 if (q_eq_a || q_eq_b)
1387 {
1388 q = &tmp_q;
1389 }
1390
1391 r_eq_a = (r == a);
1392 r_eq_b = (r == b);
1393 if (r_eq_a || r_eq_b)
1394 {
1395 r = &tmp_r;
1396 }
1397
1398 if (newsize(&r->dp, &r->dgs_alloc, /* At least one more dig in r */
1399 a->dgs_used + 1, a->dgs_used + 2) != BIG_OK)
1400 {
1401 return big_errno;
1402 }
1403 big_set_big(a, r);
1404 r->dp[a->dgs_used] = 0; /* In case no overflow in mult. */
1405
1406 n = b->dgs_used;
1407 v_end = b->dp + n - 1;
1408 norm = DIGIT_PART((DIGIT_BASE / ((DIGIT2)*v_end + 1)));
1409 if (norm != 1)
1410 {
1411 umul_digit(r, norm);
1412 umul_digit(b, norm);
1413 print_digits("r = ", r);
1414 print_digits("b = ", b);
1415 }
1416 m = a->dgs_used + 1 - b->dgs_used;
1417 r_end = r->dp + a->dgs_used;
1418
1419 if (newsize(&q->dp, &q->dgs_alloc, m, m + 2) != BIG_OK)
1420 {
1421 return big_errno;
1422 }
1423 q_end = q->dp + m - 1;
1424
1425 v1 = *v_end;
1426 v2 = *(v_end - 1);
1427
1428 for (j = 0; j < m; j++) /* m steps through division */
1429 {
1430 u1 = *r_end; /* routine */
1431 u2 = *(r_end - 1);
1432 u3 = *(r_end - 2);
1433 qhat = ((u1 == v1) ?
1434 MAX_DIGIT :
1435 DIGIT_PART(((DIGIT2)u1 * DIGIT_BASE + u2) / v1));
1436 while (1)
1437 {
1438 t3 = DIGIT_PART(temp = (DIGIT2)qhat * v2);
1439 t2 = DIGIT_PART(temp = SHIFT_DIGIT_DOWN(temp) + v1 * (DIGIT2)qhat);
1440 t1 = DIGIT_PART(SHIFT_DIGIT_DOWN(temp));
1441#if 0
1442 printf("t1 = %lu, ", (ulong)t1);
1443 printf("t2 = %lu, ", (ulong)t2);
1444 printf("t3 = %lu\n", (ulong)t3);
1445#endif
1446 if (t1 < u1) break;
1447 if (t1 > u1) {--qhat; continue; }
1448 if (t2 < u2) break;
1449 if (t2 > u2) { --qhat; continue; }
1450 if (t3 <= u3) break;
1451 qhat--;
1452 }
1453
1454 /* This is a tricky one - multiply and subtract simultaneously */
1455 carry = 1;
1456 res = 0;
1457 src = b->dp;
1458 dst = r->dp + m - j - 1;
1459 while (src <= v_end)
1460 {
1461 res = (DIGIT2)qhat * *(src++) + SHIFT_DIGIT_DOWN(res);
1462 carry += (DIGIT2)(*dst) + MAX_DIGIT - DIGIT_PART(res);
1463 *(dst++) = DIGIT_PART(carry);
1464 carry = DIGIT_PART(SHIFT_DIGIT_DOWN(carry));
1465 }
1466 carry += (DIGIT2)(*dst) + MAX_DIGIT - SHIFT_DIGIT_DOWN(res);
1467 *dst = DIGIT_PART(carry);
1468 carry = DIGIT_PART(SHIFT_DIGIT_DOWN(carry));
1469
1470 if (carry == 0)
1471 {
1472 qhat--;
1473 src = b->dp;
1474 dst = r->dp + m - j - 1;
1475 while (dst <= r_end)
1476 {
1477 carry = (DIGIT2)(*dst) + *src++ + SHIFT_DIGIT_DOWN(carry);
1478 *dst++ = DIGIT_PART(carry);
1479 }
1480 *dst = 0;
1481 }
1482 *(q_end - j) = DIGIT_PART(qhat);
1483 r_end--;
1484 }
1485 r->sign = a->sign;
1486#if 0
1487 i = r->dgs_used;
1488#endif
1489 while ((*r_end == 0) && (r_end > r->dp))
1490 {
1491 r_end--;
1492 }
1493 if (r_end == r->dp)
1494 {
1495 r->dgs_used = 1;
1496 r->sign = BIG_SIGN_0;
1497 }
1498 else
1499 {
1500 r->dgs_used = r_end - r->dp + 1;
1501 r->sign = a->sign;
1502 }
1503 if (norm != 1)
1504 {
1505 udiv_digit(b, norm);
1506 udiv_digit(r, norm);
1507 }
1508 while ((*q_end == 0) && (q_end > q->dp)) /* This is not needed!(?) */
1509 {
1510 q_end--;
1511 }
1512 /* was ifdef'd out already in original */
1513#if 0
1514 i = m - 1;
1515 while ((i > 0) && (q->dp[i--] == 0))
1516 {
1517 /* Loop through all zeroes */
1518 }
1519#endif
1520 q->dgs_used = q_end - q->dp + 1;
1521 q->sign = ((a->sign == b->sign) ? BIG_SIGN_PLUS : BIG_SIGN_MINUS);
1522
1523 if (q_eq_a)
1524 {
1525 big_set_big(q, a);
1526 }
1527 else
1528 if (q_eq_b)
1529 {
1530 big_set_big(q, b);
1531 }
1532
1533 if (r_eq_b)
1534 {
1535 big_set_big(r, b);
1536 }
1537 else
1538 if (r_eq_a)
1539 {
1540 big_set_big(r, a);
1541 }
1542
1543 print_digits("\t5:q = ", q);
1544 print_digits("\t r = ", r);
1545 return big_errno;
1546}
1547
1548bigerr_t
1549big_floor(bignum *a, bignum *b, bignum *q, bignum *r)
1550{
1551 int b_eq_qr, sign_eq;
1552
1553 if ( ( b_eq_qr = ((b == q) || (b == r)) ) )
1554 {
1555 big_set_big(b, &tmp_mul);
1556 }
1557 sign_eq = a->sign == b->sign;
1558 big_trunc(a, b, q, r);
1559 if (sign_eq)
1560 {
1561 return big_errno;
1562 }
1563 if (!zerop(r))
1564 {
1565 if (b_eq_qr)
1566 {
1567 big_add(r, &tmp_mul, r);
1568 }
1569 else
1570 {
1571 big_add(r, b, r);
1572 }
1573 print_digits("big_one = ", &big_one);
1574 big_sub(q, &big_one, q);
1575 }
1576 return big_errno;
1577}
1578
1579bigerr_t
1580big_ceil(bignum *a, bignum *b, bignum *q, bignum *r)
1581{
1582 int b_eq_qr, sign_diff;
1583
1584 if ( ( b_eq_qr = ((b == q) || (b == r)) ) )
1585 {
1586 big_set_big(b, &tmp_mul);
1587 }
1588 sign_diff = a->sign != b->sign;
1589 big_trunc(a, b, q, r);
1590 if (sign_diff)
1591 {
1592 return big_errno;
1593 }
1594 if (!zerop(r))
1595 {
1596 if (b_eq_qr)
1597 {
1598 big_sub(r, &tmp_mul, r);
1599 }
1600 else
1601 {
1602 big_sub(r, b, r);
1603 }
1604 big_add(q, &big_one, q);
1605 }
1606 return big_errno;
1607}
1608
1609#ifdef UNUSED_CODE
1610/* This one doesn't work to 100%. I was a little braindamaged when I wrote
1611 * this, but I'll eventually fix it. Zzzzzzz.
1612 */
1613bigerr_t
1614big_round(bignum *a, bignum *b, bignum *q, bignum *r)
1615{
1616 int b_eq_qr, b_neg_p, a_sgn_neq_b_sgn;
1617
1618 if ( ( b_eq_qr = ((b == q) || (b == r)) ) )
1619 {
1620 big_set_big(b, &tmp_round);
1621 }
1622 b_neg_p = b->sign == BIG_SIGN_MINUS;
1623 a_sgn_neq_b_sgn = a->sign != b->sign;
1624 big_trunc(a, b, q, r);
1625
1626 big_set_big(r, &tmp_add);
1627 umul_digit(&tmp_add, 2);
1628 if (ucompare_digits(&tmp_add, b) > 0) /* |2 * r| > |b| */
1629 {
1630 if (q->sign == BIG_SIGN_0)
1631 {
1632 if (a_sgn_neq_b_sgn)
1633 {
1634 big_sub(q, &big_one, q);
1635 }
1636 else
1637 {
1638 big_add(q, &big_one, q);
1639 }
1640 }
1641 else
1642 {
1643 if (q->sign == BIG_SIGN_MINUS)
1644 {
1645 big_sub(q, &big_one, q);
1646 }
1647 else
1648 {
1649 big_add(q, &big_one, q);
1650 }
1651 }
1652 if (b_eq_qr)
1653 {
1654 if (q->sign == BIG_SIGN_PLUS)
1655 {
1656 big_sub(r, &tmp_round, r);
1657 }
1658 else
1659 {
1660 big_add(r, &tmp_round, r);
1661 }
1662 }
1663 else
1664 {
1665 if (q->sign == BIG_SIGN_PLUS)
1666 {
1667 big_sub(r, b, r);
1668 }
1669 else
1670 {
1671 big_add(r, b, r);
1672 }
1673 }
1674 }
1675 return big_errno;
1676}
1677
1678bigerr_t
1679big_random(bignum *a, bignum *b)
1680{
1681 unsigned long i;
1682 int a_sgn = a->sign;
1683
1684 if (big_errno != BIG_OK)
1685 {
1686 return big_errno;
1687 }
1688 if (zerop(a)) /* a = 0 -> big_random => 0 (special case) */
1689 {
1690 *b->dp = 0;
1691 b->dgs_used = 1;
1692 b->sign = a_sgn;
1693 return big_errno;
1694 }
1695 if (newsize(&tmp_rand.dp, &tmp_rand.dgs_alloc,
1696 a->dgs_used + 1, a->dgs_used + 1) != BIG_OK)
1697 {
1698 return big_errno;
1699 }
1700 for (i = 0; i <= a->dgs_used; i++)
1701 {
1702 tmp_rand.dp[i] = rand();
1703 }
1704 while (tmp_rand.dp[a->dgs_used] == 0) /* Make sure high digit is non-0 */
1705 {
1706 tmp_rand.dp[a->dgs_used] = rand();
1707 }
1708 tmp_rand.dgs_used = a->dgs_used + 1;
1709 tmp_rand.sign = BIG_SIGN_PLUS;
1710 a->sign = BIG_SIGN_PLUS;
1711 big_trunc(&tmp_rand, a, &tmp_q, b); /* Dangerous to use tmp_q here... */
1712 a->sign = a_sgn;
1713 b->sign = zerop(&tmp_rand) ? BIG_SIGN_0 : a_sgn;
1714 return big_errno;
1715}
1716
1717/* UNUSED_CODE */
1718#endif
1719
1720/* ----------------------------------------------------------------------
1721 * External functions that do not need to know anything about the internal
1722 * representation of a bignum.
1723 */
1724
1725#ifdef UNUSED_CODE
1726
1727int
1728big_expt(bignum *a, unsigned long z, bignum *x)
1729{
1730 bignum b;
1731
1732 big_create(&b);
1733 big_set_big(a, &b);
1734 big_set_long((long)1, x);
1735
1736 while ((z != 0) && (big_errno == BIG_OK))
1737 {
1738 while ((z & 0x01) == 0)
1739 {
1740 z >>= 1;
1741 big_mul(&b, &b, &b);
1742 }
1743 z -= 1;
1744 big_mul(x, &b, x);
1745 }
1746
1747 big_destroy(&b);
1748 return big_errno;
1749}
1750
1751/* UNUSED_CODE */
1752#endif
1753
1754int
1755big_exptmod(bignum *a_in, bignum *z_in, bignum *n, bignum *x)
1756{
1757 bignum a, z, b0, b1, b2, dummy;
1758
1759 big_create(&a);
1760 big_create(&z);
1761 big_create(&b0);
1762 big_create(&b1);
1763 big_create(&b2);
1764 big_create(&dummy);
1765
1766 big_set_big(a_in, &a);
1767 big_set_big(z_in, &z);
1768 big_set_long((long)1, x);
1769 big_set_long((long)0, &b0);
1770 big_set_long((long)1, &b1);
1771 big_set_long((long)2, &b2);
1772
1773 /* No foolproof testing on big_errno - it really ought to be done */
1774 while ((big_compare(&z, &b0) != 0) && (big_errno == BIG_OK))
1775 {
1776 while (big_evenp(&z) && (big_errno == BIG_OK))
1777 {
1778 big_trunc(&z, &b2, &z, &dummy);
1779 big_mul(&a, &a, &a);
1780 big_trunc(&a, n, &dummy, &a);
1781 }
1782 big_sub(&z, &b1, &z);
1783 big_mul(x, &a, x);
1784 big_trunc(x, n, &dummy, x);
1785 }
1786
1787 big_destroy(&dummy);
1788 big_destroy(&b2);
1789 big_destroy(&b1);
1790 big_destroy(&b0);
1791 big_destroy(&z);
1792 big_destroy(&a);
1793
1794 return big_errno;
1795}
1796
1797#ifdef UNUSED_CODE
1798
1799int
1800big_gcd(bignum *a, bignum *b, bignum *g)
1801{
1802 bignum a1, b1, tmp;
1803
1804 if (big_zerop(b))
1805 {
1806 big_abs(a, g);
1807 return big_errno;
1808 }
1809
1810 big_create(&a1);
1811 big_create(&b1);
1812 big_create(&tmp);
1813
1814 big_abs(a, &a1);
1815 big_abs(b, &b1);
1816
1817 while (!big_zerop(&b1) && (big_errno == BIG_OK))
1818 {
1819 big_floor(&a1, &b1, &tmp, &a1);
1820 if (big_zerop(&a1))
1821 {
1822 break;
1823 }
1824 big_floor(&b1, &a1, &tmp, &b1);
1825 }
1826
1827 if (big_zerop(&a1))
1828 {
1829 big_set_big(&b1, g);
1830 }
1831 else
1832 {
1833 big_set_big(&a1, g);
1834 }
1835
1836 big_destroy(&tmp);
1837 big_destroy(&b1);
1838 big_destroy(&a1);
1839
1840 return big_errno;
1841}
1842/* UNUSED_CODE */
1843#endif
1844
1845/* #if (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)) */
1846#endif
1847
Note: See TracBrowser for help on using the repository browser.