2 * Copyright (c) 2010 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @file Big integers.
31 * Sysel type @c int should accomodate large numbers. This implementation
32 * is limited by the available memory and range of the @c size_t type used
44 static void bigint_sign_comb(bool_t srf_a
, bigint_t
*a
, bool_t srf_b
,
45 bigint_t
*b
, bigint_t
*dest
);
46 static void bigint_add_abs(bigint_t
*a
, bigint_t
*b
, bigint_t
*dest
);
47 static void bigint_sub_abs(bigint_t
*a
, bigint_t
*b
, bigint_t
*dest
);
48 static void bigint_shift_mul_dig(bigint_t
*a
, bigint_word_t b
, size_t shift
,
51 static void bigint_alloc(bigint_t
*bigint
, size_t length
);
52 static void bigint_refine_len(bigint_t
*bigint
);
54 /** Initialize bigint with value from small integer.
56 * Initializes a bigint structure with the provided small value.
58 * @param value Initial value (small int).
60 void bigint_init(bigint_t
*bigint
, int value
)
66 #ifdef DEBUG_BIGINT_TRACE
67 printf("Initialize bigint with int value %d.\n", value
);
71 bigint
->negative
= b_true
;
74 bigint
->negative
= b_false
;
77 /* Determine length. */
85 /* Allocate digit array. */
86 bigint_alloc(bigint
, length
);
90 for (idx
= 0; idx
< length
; ++idx
) {
91 bigint
->digit
[idx
] = t
% BIGINT_BASE
;
96 /** Shallow copy of integer.
99 * @param dest Destination.
101 void bigint_shallow_copy(bigint_t
*src
, bigint_t
*dest
)
103 #ifdef DEBUG_BIGINT_TRACE
104 printf("Shallow copy of bigint.\n");
106 dest
->negative
= src
->negative
;
107 dest
->digit
= src
->digit
;
108 dest
->length
= src
->length
;
110 /** Clone big integer.
113 * @param dest Destination.
115 void bigint_clone(bigint_t
*src
, bigint_t
*dest
)
119 #ifdef DEBUG_BIGINT_TRACE
120 printf("Clone bigint.\n");
123 dest
->negative
= src
->negative
;
125 /* Allocate dest digit array. */
126 bigint_alloc(dest
, src
->length
);
129 for (idx
= 0; idx
< dest
->length
; ++idx
)
130 dest
->digit
[idx
] = src
->digit
[idx
];
133 /** Compute big integer with reversed sign.
136 * @param dest Destination.
138 void bigint_reverse_sign(bigint_t
*src
, bigint_t
*dest
)
142 #ifdef DEBUG_BIGINT_TRACE
143 printf("Reverse-sign copy of bigint.\n");
145 /* Copy reversed sign. */
146 dest
->negative
= !src
->negative
;
148 /* Allocate dest digit array. */
149 bigint_alloc(dest
, src
->length
);
152 for (idx
= 0; idx
< dest
->length
; ++idx
)
153 dest
->digit
[idx
] = src
->digit
[idx
];
156 /** Destroy big integer.
158 * Any bigint that is initialized via bigint_init() or any other bigint
159 * function that constructs a new bigint value should be destroyed with
160 * this function to free memory associated with the bigint. It should
161 * also be used to destroy a bigint before it is reused.
163 * @param bigint The bigint to destroy.
165 void bigint_destroy(bigint_t
*bigint
)
167 #ifdef DEBUG_BIGINT_TRACE
168 printf("Destroy bigint.\n");
170 bigint
->negative
= b_false
;
175 bigint
->digit
= NULL
;
178 /** Get value of big integer.
180 * Allows to obtain the value of big integer, provided that it fits
181 * into a small integer.
183 * @param bigint Bigint to obtain value from.
184 * @param dval Place to store value.
185 * @return EOK on success, ELIMIT if bigint is too big to fit
188 errno_t
bigint_get_value_int(bigint_t
*bigint
, int *dval
)
195 #ifdef DEBUG_BIGINT_TRACE
196 printf("Get int value of bigint.\n");
199 for (idx
= 0; idx
< bigint
->length
; ++idx
) {
200 val
= val
* BIGINT_BASE
+ bigint
->digit
[idx
];
203 if (bigint
->negative
)
206 /* If the value did not fit @c val now contains garbage. Verify. */
207 bigint_init(&vval
, val
);
209 bigint_sub(bigint
, &vval
, &diff
);
210 zf
= bigint_is_zero(&diff
);
212 bigint_destroy(&vval
);
213 bigint_destroy(&diff
);
215 /* If the difference is not zero, the verification failed. */
223 /** Determine if bigint is zero.
225 * @param bigint Big integer.
226 * @return b_true if @a bigint is zero, b_false otherwise.
228 bool_t
bigint_is_zero(bigint_t
*bigint
)
230 #ifdef DEBUG_BIGINT_TRACE
231 printf("Determine if bigint is zero.\n");
233 return (bigint
->length
== 0);
236 /** Determine if bigint is negative.
238 * @param bigint Big integer.
239 * @return b_true if @a bigint is negative, b_false otherwise.
241 bool_t
bigint_is_negative(bigint_t
*bigint
)
243 #ifdef DEBUG_BIGINT_TRACE
244 printf("Determine if bigint is negative\n");
246 /* Verify that we did not accidentaly introduce a negative zero. */
247 assert(bigint
->negative
== b_false
|| bigint
->length
> 0);
249 return bigint
->negative
;
252 /** Divide bigint by (unsigned) digit.
254 * @param a Bigint dividend.
255 * @param b Divisor digit.
256 * @param quot Output bigint quotient.
257 * @param rem Output remainder digit.
259 void bigint_div_digit(bigint_t
*a
, bigint_word_t b
, bigint_t
*quot
,
264 bigint_dword_t da
, db
;
267 #ifdef DEBUG_BIGINT_TRACE
268 printf("Divide bigint by digit.\n");
271 bigint_alloc(quot
, lbound
);
273 quot
->negative
= a
->negative
;
280 da
= a
->digit
[idx
] + r
* BIGINT_BASE
;
286 quot
->digit
[idx
] = q
;
289 bigint_refine_len(quot
);
293 /** Add two big integers.
295 * The big integers @a a and @a b are added and the result is stored in
298 * @param a First addend.
299 * @param b Second addend.
300 * @param dest Destination bigint.
302 void bigint_add(bigint_t
*a
, bigint_t
*b
, bigint_t
*dest
)
304 #ifdef DEBUG_BIGINT_TRACE
305 printf("Add bigints.\n");
307 bigint_sign_comb(b_false
, a
, b_false
, b
, dest
);
310 /** Subtract two big integers.
312 * The big integers @a a and @a b are subtracted and the result is stored in
316 * @param b Subtrahend.
317 * @param dest Destination bigint.
319 void bigint_sub(bigint_t
*a
, bigint_t
*b
, bigint_t
*dest
)
321 #ifdef DEBUG_BIGINT_TRACE
322 printf("Subtract bigints.\n");
324 bigint_sign_comb(b_false
, a
, b_true
, b
, dest
);
327 /** Multiply two big integers.
329 * The big integers @a a and @a b are multiplied and the result is stored in
332 * @param a First factor.
333 * @param b Second factor.
334 * @param dest Destination bigint.
336 void bigint_mul(bigint_t
*a
, bigint_t
*b
, bigint_t
*dest
)
343 #ifdef DEBUG_BIGINT_TRACE
344 printf("Multiply bigints.\n");
346 bigint_init(&sum
, 0);
347 for (idx
= 0; idx
< b
->length
; ++idx
) {
348 bigint_shift_mul_dig(a
, b
->digit
[idx
], idx
, &dprod
);
349 bigint_add(&dprod
, &sum
, &tmp
);
350 bigint_destroy(&dprod
);
352 bigint_destroy(&sum
);
353 bigint_shallow_copy(&tmp
, &sum
);
357 sum
.negative
= !sum
.negative
;
359 bigint_shallow_copy(&sum
, dest
);
362 /** Convert bigint to string.
364 * @param bigint Bigint to convert.
365 * @param dptr Place to store pointer to new string.
367 void bigint_get_as_string(bigint_t
*bigint
, char **dptr
)
369 static const char digits
[] = { '0', '1', '2', '3', '4', '5', '6',
378 #ifdef DEBUG_BIGINT_TRACE
379 printf("Convert bigint to string.\n");
381 static_assert(BIGINT_BASE
>= 10, "");
383 /* Compute number of characters. */
386 if (bigint_is_zero(bigint
) || bigint
->negative
)
387 nchars
+= 1; /* '0' or '-' */
389 bigint_clone(bigint
, &val
);
390 while (bigint_is_zero(&val
) != b_true
) {
391 bigint_div_digit(&val
, 10, &tmp
, &rem
);
392 bigint_destroy(&val
);
393 bigint_shallow_copy(&tmp
, &val
);
397 bigint_destroy(&val
);
399 /* Store characters to array. */
401 str
= malloc(nchars
* sizeof(char) + 1);
403 printf("Memory allocation failed.\n");
407 if (bigint_is_zero(bigint
)) {
409 } else if (bigint
->negative
) {
414 bigint_clone(bigint
, &val
);
415 while (bigint_is_zero(&val
) != b_true
) {
416 bigint_div_digit(&val
, 10, &tmp
, &rem
);
417 bigint_destroy(&val
);
418 bigint_shallow_copy(&tmp
, &val
);
420 str
[nchars
- idx
] = digits
[(int) rem
];
424 bigint_destroy(&val
);
429 /** Print bigint to standard output.
431 * @param bigint Bigint to print.
433 void bigint_print(bigint_t
*bigint
)
437 #ifdef DEBUG_BIGINT_TRACE
438 printf("Print bigint.\n");
440 bigint_get_as_string(bigint
, &str
);
445 /** Compute sign combination of two big integers.
447 * Of the big integers @a a and @a b each is optionally sign-reversed and then
448 * they are added and the result is stored in @a dest.
450 * @param srf_a First sign reversal flag.
451 * @param a First bigint.
452 * @param srf_b Second sign reversal flag.
453 * @param b Second bigint.
454 * @param dest Destination bigint.
456 static void bigint_sign_comb(bool_t srf_a
, bigint_t
*a
, bool_t srf_b
,
457 bigint_t
*b
, bigint_t
*dest
)
461 #ifdef DEBUG_BIGINT_TRACE
462 printf("Signed combination of two bigints.\n");
464 /* Compute resulting signs of combination elements. */
465 neg_a
= (srf_a
!= a
->negative
);
466 neg_b
= (srf_b
!= b
->negative
);
468 if (neg_a
== neg_b
) {
469 bigint_add_abs(a
, b
, dest
);
470 dest
->negative
= neg_a
;
472 bigint_sub_abs(a
, b
, dest
);
473 dest
->negative
= (neg_a
!= dest
->negative
);
477 /** Add absolute values of two big integers.
479 * The absolute values of big integers @a a and @a b are added and the result
480 * is stored in @a dest.
482 * @param a First addend.
483 * @param b Second addend.
484 * @param dest Destination bigint.
486 static void bigint_add_abs(bigint_t
*a
, bigint_t
*b
, bigint_t
*dest
)
490 bigint_dword_t da
, db
;
492 bigint_word_t res
, carry
;
494 #ifdef DEBUG_BIGINT_TRACE
495 printf("Add absolute values of bigints.\n");
497 /* max(a->length, b->length) + 1 */
498 lbound
= (a
->length
> b
->length
? a
->length
: b
->length
) + 1;
499 dest
->negative
= b_false
;
501 bigint_alloc(dest
, lbound
);
504 for (idx
= 0; idx
< lbound
; ++idx
) {
505 da
= idx
< a
->length
? a
->digit
[idx
] : 0;
506 db
= idx
< b
->length
? b
->digit
[idx
] : 0;
508 tmp
= da
+ db
+ (bigint_word_t
) carry
;
510 carry
= (bigint_word_t
) (tmp
/ BIGINT_BASE
);
511 res
= (bigint_word_t
) (tmp
% BIGINT_BASE
);
513 dest
->digit
[idx
] = res
;
516 /* If our lbound is correct, carry must be zero. */
519 bigint_refine_len(dest
);
522 /** Subtract absolute values of two big integers.
524 * The absolute values of big integers @a a and @a b are subtracted and the
525 * result is stored in @a dest.
528 * @param b Subtrahend.
529 * @param dest Destination bigint.
531 static void bigint_sub_abs(bigint_t
*a
, bigint_t
*b
, bigint_t
*dest
)
535 bigint_dword_t da
, db
;
537 bigint_word_t res
, borrow
;
539 #ifdef DEBUG_BIGINT_TRACE
540 printf("Subtract absolute values of bigints.\n");
542 /* max(a->length, b->length) */
543 lbound
= a
->length
> b
->length
? a
->length
: b
->length
;
545 bigint_alloc(dest
, lbound
);
548 for (idx
= 0; idx
< lbound
; ++idx
) {
549 da
= idx
< a
->length
? a
->digit
[idx
] : 0;
550 db
= idx
< b
->length
? b
->digit
[idx
] : 0;
552 if (da
> db
+ borrow
) {
553 tmp
= da
- db
- borrow
;
556 tmp
= da
+ BIGINT_BASE
- db
- borrow
;
560 res
= (bigint_word_t
) tmp
;
561 dest
->digit
[idx
] = res
;
565 /* We subtracted the greater number from the smaller. */
566 dest
->negative
= b_true
;
569 * Now we must complement the number to get the correct
570 * absolute value. We do this by subtracting from 10..0
571 * (0 repeated lbound-times).
575 for (idx
= 0; idx
< lbound
; ++idx
) {
577 db
= dest
->digit
[idx
];
579 if (da
> db
+ borrow
) {
580 tmp
= da
- db
- borrow
;
583 tmp
= da
+ BIGINT_BASE
- db
- borrow
;
587 res
= (bigint_word_t
) tmp
;
588 dest
->digit
[idx
] = res
;
591 /* The last step is the '1'. */
594 dest
->negative
= b_false
;
597 bigint_refine_len(dest
);
600 /** Multiply big integer by digit.
602 * @param a Bigint factor.
603 * @param b Digit factor.
604 * @param dest Destination bigint.
606 static void bigint_shift_mul_dig(bigint_t
*a
, bigint_word_t b
, size_t shift
,
612 bigint_dword_t da
, db
;
614 bigint_word_t res
, carry
;
616 #ifdef DEBUG_BIGINT_TRACE
617 printf("Multiply bigint by digit.\n");
619 /* Compute length bound and allocate. */
620 lbound
= a
->length
+ shift
+ 1;
621 bigint_alloc(dest
, lbound
);
624 dest
->negative
= a
->negative
;
626 for (idx
= 0; idx
< shift
; ++idx
)
627 dest
->digit
[idx
] = 0;
630 for (idx
= 0; idx
< lbound
- shift
; ++idx
) {
631 da
= idx
< a
->length
? a
->digit
[idx
] : 0;
634 tmp
= da
* db
+ (bigint_word_t
) carry
;
636 carry
= (bigint_word_t
) (tmp
/ BIGINT_BASE
);
637 res
= (bigint_word_t
) (tmp
% BIGINT_BASE
);
639 dest
->digit
[shift
+ idx
] = res
;
642 /* If our lbound is correct, carry must be zero. */
645 bigint_refine_len(dest
);
648 /** Allocate bigint of the given length.
650 * @param bigint Bigint whose digit array should be allocated.
651 * @param length Length of array (also set as bigint length).
653 static void bigint_alloc(bigint_t
*bigint
, size_t length
)
657 #ifdef DEBUG_BIGINT_TRACE
658 printf("Allocate bigint digit array.\n");
660 /* malloc() sometimes cannot allocate blocks of zero size. */
666 bigint
->digit
= malloc(a_length
* sizeof(bigint_word_t
));
667 if (bigint
->digit
== NULL
) {
668 printf("Memory allocation failed.\n");
672 bigint
->length
= length
;
675 /** Adjust length field of bigint to be exact.
677 * When bigint is allocated with bigint_alloc() its length can be
678 * imprecise (higher than actually number of non-zero digits).
679 * Then this function is used to lower @c length to the exact value.
681 static void bigint_refine_len(bigint_t
*bigint
)
683 #ifdef DEBUG_BIGINT_TRACE
684 printf("Refine bigint length.\n");
686 while (bigint
->length
> 0 && bigint
->digit
[bigint
->length
- 1] == 0)
689 if (bigint
->length
== 0)
690 bigint
->negative
= b_false
;