v2 / vlib / math / big / integer.v
1227 lines · 1105 sloc · 30.56 KB · 1820a5584b9bc606d0b5d12f6a60dfc62e98fe96
Raw
1module big
2
3import math
4import math.bits
5import strings
6
7const digit_array = '0123456789abcdefghijklmnopqrstuvwxyz'.bytes()
8// vfmt off
9const radix_options = {
10 2: 59, 3: 37, 4: 29, 5: 25, 6: 23, 7: 21, 8: 19, 9: 18, 10: 18,
11 11: 17, 12: 16, 13: 16, 14: 15, 15: 15, 16: 14, 17: 14, 18: 14,
12 19: 14, 20: 13, 21: 13, 22: 13, 23: 13, 24: 13, 25: 12, 26: 12,
13 27: 12, 28: 12, 29: 12, 30: 12, 31: 12, 32: 11, 33: 11, 34: 11,
14 35: 11, 36: 11
15}
16// vfmt on
17pub const digit_bits = 60 // 60bits
18const max_digit = (u64(1) << digit_bits) - u64(1)
19// big.Integer
20// -----------
21// It has the following properties:
22// 1. Every "digit" is an integer in the range [0, 2^digit_bits-1).
23// 2. The signum can be one of three values: -1, 0, +1 for
24// negative, zero, and positive values, respectively.
25// 3. There should be no leading zeros in the digit array.
26// 4. The digits are stored in little endian format, that is,
27// the digits with a lower positional value (towards the right
28// when represented as a string) have a lower index, and vice versa.
29// 5. zero's signum is zero, digits.len = 0
30pub struct Integer {
31 digits []u64 // in one u64, use only `digit_bits` store a digit
32pub:
33 signum int
34 is_const bool
35}
36
37@[unsafe]
38fn (mut x Integer) free() {
39 if x.is_const {
40 return
41 }
42 unsafe { x.digits.free() }
43}
44
45fn (x Integer) clone() Integer {
46 return Integer{
47 digits: x.digits.clone()
48 signum: x.signum
49 is_const: false
50 }
51}
52
53fn int_signum(value int) int {
54 if value == 0 {
55 return 0
56 }
57 return if value < 0 { -1 } else { 1 }
58}
59
60// integer_from_int creates a new `big.Integer` from the given int value.
61pub fn integer_from_int(value int) Integer {
62 if value == 0 {
63 return zero_int
64 }
65 if value == min_int {
66 return Integer{
67 digits: [u64(0x80000000)]
68 signum: -1
69 }
70 } else {
71 return Integer{
72 digits: [u64(iabs(value))]
73 signum: int_signum(value)
74 }
75 }
76}
77
78// integer_from_u32 creates a new `big.Integer` from the given u32 value.
79pub fn integer_from_u32(value u32) Integer {
80 if value == 0 {
81 return zero_int
82 }
83 return Integer{
84 digits: [u64(value)]
85 signum: 1
86 }
87}
88
89// integer_from_i64 creates a new `big.Integer` from the given i64 value.
90pub fn integer_from_i64(value i64) Integer {
91 if value == 0 {
92 return zero_int
93 }
94
95 signum_value := if value < 0 { -1 } else { 1 }
96 abs_value := if value == i64(-9223372036854775808) {
97 u64(0x8000000000000000)
98 } else {
99 u64(value * signum_value)
100 }
101
102 lower := u64(abs_value & max_digit)
103 upper := u64(abs_value >> digit_bits)
104
105 if upper == 0 {
106 return Integer{
107 digits: [lower]
108 signum: signum_value
109 }
110 } else {
111 return Integer{
112 digits: [lower, upper]
113 signum: signum_value
114 }
115 }
116}
117
118// integer_from_u64 creates a new `big.Integer` from the given u64 value.
119pub fn integer_from_u64(value u64) Integer {
120 if value == 0 {
121 return zero_int
122 }
123
124 lower := u64(value & max_digit)
125 upper := u64(value >> digit_bits)
126
127 if upper == 0 {
128 return Integer{
129 digits: [lower]
130 signum: 1
131 }
132 } else {
133 return Integer{
134 digits: [lower, upper]
135 signum: 1
136 }
137 }
138}
139
140@[params]
141pub struct IntegerConfig {
142pub:
143 signum int = 1
144}
145
146// integer_from_bytes creates a new `big.Integer` from the given byte array.
147// By default, positive integers are assumed.
148// If you want a negative integer, use in the following manner:
149// `value := big.integer_from_bytes(bytes, signum: -1)`
150@[direct_array_access]
151pub fn integer_from_bytes(oinput []u8, config IntegerConfig) Integer {
152 // Thank you to Miccah (@mcastorina) for this implementation and relevant unit tests.
153 if oinput.len == 0 {
154 return zero_int
155 }
156 // Ignore leading 0 bytes:
157 mut first_non_zero_index := -1
158 for i in 0 .. oinput.len {
159 if oinput[i] != 0 {
160 first_non_zero_index = i
161 break
162 }
163 }
164 if first_non_zero_index == -1 {
165 return zero_int
166 }
167 input := oinput[first_non_zero_index..]
168
169 mut carry_bits := 0
170 mut carry_value := u64(0)
171 mut digits := []u64{}
172
173 for i := input.len - 1; i >= 0; i-- {
174 byte_value := input[i]
175 for shift in 0 .. 8 {
176 bit := (byte_value >> u8(shift)) & 1
177 carry_value = (carry_value >> 1) | (u64(bit) << (digit_bits - 1))
178 carry_bits++
179 if carry_bits == digit_bits {
180 digits << carry_value
181 carry_value = 0
182 carry_bits = 0
183 }
184 }
185 }
186
187 if carry_bits > 0 {
188 remaining_shift := digit_bits - carry_bits
189 digits << (carry_value >> remaining_shift)
190 }
191
192 // Remove trailing zeros
193 shrink_tail_zeros(mut digits)
194
195 if digits.len == 0 {
196 return zero_int
197 }
198
199 return Integer{
200 digits: digits
201 signum: config.signum
202 }
203}
204
205// integer_from_string creates a new `big.Integer` from the decimal digits specified in the given string.
206// For other bases, use `big.integer_from_radix` instead.
207pub fn integer_from_string(characters string) !Integer {
208 return integer_from_radix(characters, 10)
209}
210
211// integer_from_radix creates a new `big.Integer` from the given string and radix.
212pub fn integer_from_radix(all_characters string, radix u32) !Integer {
213 if radix < 2 || radix > 36 {
214 return error('math.big: Radix must be between 2 and 36 (inclusive)')
215 }
216 characters := all_characters.to_lower()
217 validate_string(characters, radix)!
218 return integer_from_regular_string(characters, radix)
219}
220
221@[direct_array_access]
222fn validate_string(characters string, radix u32) ! {
223 sign_present := characters.len > 0 && (characters[0] == `+` || characters[0] == `-`)
224
225 start_index := if sign_present { 1 } else { 0 }
226
227 for index := start_index; index < characters.len; index++ {
228 digit := characters[index]
229 value := digit_array.index(digit)
230
231 if value == -1 {
232 return error('math.big: Invalid character ${digit}')
233 }
234 if value >= radix {
235 return error('math.big: Invalid character ${digit} for base ${radix}')
236 }
237 }
238}
239
240@[direct_array_access]
241fn integer_from_regular_string(characters string, radix u32) Integer {
242 sign_present := characters.len > 0 && (characters[0] == `+` || characters[0] == `-`)
243
244 signum := if sign_present {
245 if characters[0] == `-` { -1 } else { 1 }
246 } else {
247 1
248 }
249
250 start_index := if sign_present { 1 } else { 0 }
251
252 mut result := zero_int
253 radix_int := integer_from_u32(radix)
254 pow := radix_options[int(radix)]
255 radix_pow := radix_int.pow(u32(pow))
256 for i := start_index; i < characters.len; i += pow {
257 end := math.min(i + pow, characters.len)
258 num_str := characters[i..end]
259 if num_str.len == pow {
260 result *= radix_pow
261 } else {
262 result *= radix_int.pow(u32(num_str.len))
263 }
264 result += integer_from_u64(regular_string_to_radix(num_str, radix))
265 }
266
267 return Integer{
268 digits: result.digits.clone()
269 signum: result.signum * signum
270 }
271}
272
273fn regular_string_to_radix(characters string, radix u32) u64 {
274 mut result := u64(0)
275
276 for c in characters {
277 result = result * radix + u64(digit_array.index(c))
278 }
279 return result
280}
281
282// abs returns the absolute value of the integer `a`.
283pub fn (a Integer) abs() Integer {
284 return if a.signum == 0 {
285 zero_int
286 } else {
287 Integer{
288 digits: a.digits.clone()
289 signum: 1
290 }
291 }
292}
293
294// neg returns the result of negation of the integer `a`.
295pub fn (a Integer) neg() Integer {
296 return if a.signum == 0 {
297 zero_int
298 } else {
299 Integer{
300 digits: a.digits.clone()
301 signum: -a.signum
302 }
303 }
304}
305
306// + returns the sum of the integers `augend` and `addend`.
307pub fn (augend Integer) + (addend Integer) Integer {
308 // Quick exits
309 if augend.signum == 0 {
310 return addend.clone()
311 }
312 if addend.signum == 0 {
313 return augend.clone()
314 }
315 // Non-zero cases
316 if augend.signum == addend.signum {
317 return augend.add(addend)
318 }
319 // Unequal signs
320 if augend.abs_cmp(addend) < 0 {
321 return augend.subtract(addend).neg()
322 } else {
323 return augend.subtract(addend)
324 }
325}
326
327// - returns the difference of the integers `minuend` and `subtrahend`
328pub fn (minuend Integer) - (subtrahend Integer) Integer {
329 // Quick exits
330 if minuend.signum == 0 {
331 return subtrahend.neg()
332 }
333 if subtrahend.signum == 0 {
334 return minuend.clone()
335 }
336 // Non-zero cases
337 if minuend.signum == subtrahend.signum {
338 return minuend.subtract(subtrahend)
339 }
340 // Unequal signs:
341 return minuend.add(subtrahend)
342}
343
344fn (integer Integer) add(addend Integer) Integer {
345 a := integer.digits
346 b := addend.digits
347 mut storage := []u64{len: imax(a.len, b.len) + 1}
348 add_digit_array(a, b, mut storage)
349 return Integer{
350 signum: integer.signum
351 digits: storage
352 }
353}
354
355fn (integer Integer) subtract(subtrahend Integer) Integer {
356 cmp := integer.abs_cmp(subtrahend)
357 if cmp == 0 {
358 return zero_int
359 }
360 a, b := if cmp > 0 { integer, subtrahend } else { subtrahend, integer }
361 mut storage := []u64{len: a.digits.len}
362 subtract_digit_array(a.digits, b.digits, mut storage)
363 return Integer{
364 signum: cmp * a.signum
365 digits: storage
366 }
367}
368
369// * returns the product of the integers `multiplicand` and `multiplier`.
370pub fn (multiplicand Integer) * (multiplier Integer) Integer {
371 // Quick exits
372 if multiplicand.signum == 0 || multiplier.signum == 0 {
373 return zero_int
374 }
375 if multiplicand == one_int {
376 return multiplier.clone()
377 }
378 if multiplier == one_int {
379 return multiplicand.clone()
380 }
381 // The final sign is the product of the signs
382 mut storage := []u64{len: multiplicand.digits.len + multiplier.digits.len}
383 multiply_digit_array(multiplicand.digits, multiplier.digits, mut storage)
384 return Integer{
385 signum: multiplicand.signum * multiplier.signum
386 digits: storage
387 }
388}
389
390// div_mod_internal is an entirely unchecked (in terms of division by zero) method for division.
391// This should only be used for internal calculations involving a definitive non-zero
392// divisor.
393//
394// DO NOT use this method if the divisor has any chance of being 0.
395fn (dividend Integer) div_mod_internal(divisor Integer) (Integer, Integer) {
396 mut q := []u64{len: int_max(1, dividend.digits.len - divisor.digits.len + 1)}
397 mut r := []u64{len: dividend.digits.len}
398 mut q_signum := 0
399 mut r_signum := 0
400
401 divide_digit_array(dividend.digits, divisor.digits, mut q, mut r)
402 if dividend.signum > 0 && divisor.signum > 0 {
403 q_signum = 1
404 r_signum = 1
405 } else if dividend.signum > 0 && divisor.signum < 0 {
406 q_signum = -1
407 r_signum = 1
408 } else if dividend.signum < 0 && divisor.signum > 0 {
409 q_signum = -1
410 r_signum = -1
411 } else {
412 q_signum = 1
413 r_signum = -1
414 }
415 quotient := Integer{
416 signum: if q.len == 0 { 0 } else { q_signum }
417 digits: q
418 }
419 remainder := Integer{
420 signum: if r.len == 0 { 0 } else { r_signum }
421 digits: r
422 }
423 return quotient, remainder
424}
425
426// div_mod returns the quotient and remainder from the division of the integers `dividend`
427// divided by `divisor`.
428//
429// WARNING: this method will panic if `divisor == 0`. Refer to div_mod_checked for a safer version.
430@[inline]
431pub fn (dividend Integer) div_mod(divisor Integer) (Integer, Integer) {
432 if _unlikely_(divisor.signum == 0) {
433 panic('math.big: Cannot divide by zero')
434 }
435 return dividend.div_mod_internal(divisor)
436}
437
438// div_mod_checked returns the quotient and remainder from the division of the integers `dividend`
439// divided by `divisor`. An error is returned if `divisor == 0`.
440@[inline]
441pub fn (dividend Integer) div_mod_checked(divisor Integer) !(Integer, Integer) {
442 if _unlikely_(divisor.signum == 0) {
443 return error('math.big: Cannot divide by zero')
444 }
445 return dividend.div_mod_internal(divisor)
446}
447
448// / returns the quotient of `dividend` divided by `divisor`.
449//
450// WARNING: this method will panic if `divisor == 0`. For a division method that returns a Result
451// refer to `div_checked`.
452@[inline]
453pub fn (dividend Integer) / (divisor Integer) Integer {
454 q, _ := dividend.div_mod(divisor)
455 return q
456}
457
458// % returns the remainder of `dividend` divided by `divisor`.
459//
460// WARNING: this method will panic if `divisor == 0`. For a modular division method that
461// returns a Result refer to `mod_checked`.
462// Note: in V, `assert big.integer_from_i64(-10) % big.integer_from_i64(7) == big.integer_from_i64(-3)` passes.
463// In other words, the result is negative 3, and is NOT positive 4.
464@[inline]
465pub fn (dividend Integer) % (divisor Integer) Integer {
466 _, r := dividend.div_mod(divisor)
467 return r
468}
469
470// div_checked returns the quotient of `dividend` divided by `divisor`
471// or an error if `divisor == 0`.
472@[inline]
473pub fn (dividend Integer) div_checked(divisor Integer) !Integer {
474 q, _ := dividend.div_mod_checked(divisor)!
475 return q
476}
477
478// mod_checked returns the remainder of `dividend` divided by `divisor`
479// or an error if `divisor == 0`.
480@[inline]
481pub fn (dividend Integer) mod_checked(divisor Integer) !Integer {
482 _, r := dividend.div_mod_checked(divisor)!
483 return r
484}
485
486// modulo_euclid returns the result of mathematical modulus.
487// The result is always non-negative for positive `divisor`.
488//
489// WARNING: this method will panic if `divisor == 0`.
490@[inline]
491pub fn (dividend Integer) mod_euclid(divisor Integer) Integer {
492 r := dividend % divisor
493 if r < zero_int {
494 return r + divisor.abs()
495 } else {
496 return r
497 }
498}
499
500// mod_euclid_checked returns the result of mathematical modulus.
501// The result is always non-negative for positive `divisor`
502// or an error if `divisor == 0`.
503@[inline]
504pub fn (dividend Integer) mod_euclid_checked(divisor Integer) !Integer {
505 r := dividend.mod_checked(divisor)!
506 if r < zero_int {
507 return r + divisor.abs()
508 } else {
509 return r
510 }
511}
512
513// mask_bits is the equivalent of `a % 2^n` (only when `a >= 0`), however doing a full division
514// run for this would be a lot of work when we can simply "cut off" all bits to the left of
515// the `n`th bit.
516@[direct_array_access]
517fn (a Integer) mask_bits(n u32) Integer {
518 $if debug {
519 assert a.signum >= 0
520 }
521
522 if a.digits.len == 0 || n == 0 {
523 return zero_int
524 }
525
526 w := n / digit_bits
527 b := n % digit_bits
528
529 if w >= a.digits.len {
530 return a
531 }
532
533 return Integer{
534 digits: if b == 0 {
535 mut storage := []u64{len: int(w)}
536 for i := 0; i < storage.len; i++ {
537 storage[i] = a.digits[i]
538 }
539 storage
540 } else {
541 mut storage := []u64{len: int(w) + 1}
542 for i := 0; i < storage.len; i++ {
543 storage[i] = a.digits[i]
544 }
545 storage[w] &= ~(u64(-1) << b)
546 storage
547 }
548 signum: 1
549 }
550}
551
552// pow returns the integer `base` raised to the power of the u32 `exponent`.
553pub fn (base Integer) pow(exponent u32) Integer {
554 if exponent == 0 {
555 return one_int
556 }
557 if exponent == 1 {
558 return base.clone()
559 }
560 mut n := exponent
561 mut x := base
562 mut y := one_int
563 for n > 1 {
564 if n & 1 == 1 {
565 y *= x
566 }
567 x *= x
568 n >>= 1
569 }
570 return x * y
571}
572
573// mod_pow returns the integer `base` raised to the power of the u32 `exponent` modulo the integer `modulus`.
574pub fn (base Integer) mod_pow(exponent u64, modulus Integer) Integer {
575 if exponent == 0 {
576 return one_int
577 }
578 if exponent == 1 {
579 return base % modulus
580 }
581 mut n := exponent
582 mut x := base % modulus
583 mut y := one_int
584 for n > 1 {
585 if n & 1 == 1 {
586 y = (y * x) % modulus
587 }
588 x = (x * x) % modulus
589 n >>= 1
590 }
591 return x * y % modulus
592}
593
594// big_mod_pow returns the integer `base` raised to the power of the integer `exponent` modulo the integer `modulus`.
595@[direct_array_access]
596pub fn (base Integer) big_mod_pow(exponent Integer, modulus Integer) !Integer {
597 if exponent.signum < 0 {
598 return error('math.big: Exponent needs to be non-negative.')
599 }
600
601 // this goes first as otherwise 1 could be returned incorrectly if base == 1
602 if modulus.bit_len() <= 1 {
603 return zero_int
604 }
605
606 // x^0 == 1 || 1^x == 1
607 if exponent.signum == 0 || base.bit_len() == 1 {
608 return one_int
609 }
610
611 // 0^x == 0 (x != 0 due to previous clause)
612 if base.signum == 0 {
613 return zero_int
614 }
615
616 if exponent.bit_len() == 1 {
617 // x^1 without mod == x
618 if modulus.signum == 0 {
619 return base
620 }
621 // x^1 (mod m) === x % m
622 return base % modulus
623 }
624
625 // the amount of precomputation in windowed exponentiation (done in the montgomery and binary
626 // windowed exponentiation algorithms) is far too costly for small sized exponents, so
627 // we redirect the call to mod_pow
628 return if exponent.digits.len > 1 {
629 if modulus.is_odd() {
630 // modulus is odd, therefore we use the normal
631 // montgomery modular exponentiation algorithm
632 base.mont_odd(exponent, modulus)
633 } else if modulus.is_power_of_2() {
634 base.exp_binary(exponent, modulus)
635 } else {
636 base.mont_even(exponent, modulus)
637 }
638 } else {
639 base.mod_pow(exponent.digits[0], modulus)
640 }
641}
642
643// inc increments `a` by 1 in place.
644pub fn (mut a Integer) inc() {
645 a = a + one_int
646}
647
648// dec decrements `a` by 1 in place.
649pub fn (mut a Integer) dec() {
650 a = a - one_int
651}
652
653// == returns `true` if the integers `a` and `b` are equal in value and sign.
654@[inline]
655pub fn (a Integer) == (b Integer) bool {
656 return a.signum == b.signum && a.digits.len == b.digits.len && a.digits == b.digits
657}
658
659// abs_cmp returns the result of comparing the magnitudes of the integers `a` and `b`.
660// It returns a negative int if `|a| < |b|`, 0 if `|a| == |b|`, and a positive int if `|a| > |b|`.
661@[inline]
662pub fn (a Integer) abs_cmp(b Integer) int {
663 return compare_digit_array(a.digits, b.digits)
664}
665
666// < returns `true` if the integer `a` is less than `b`.
667pub fn (a Integer) < (b Integer) bool {
668 // Quick exits based on signum value:
669 if a.signum < b.signum {
670 return true
671 }
672 if a.signum > b.signum {
673 return false
674 }
675 // They have equal sign
676 signum := a.signum
677 if signum == 0 { // Are they both zero?
678 return false
679 }
680 // If they are negative, the one with the larger absolute value is smaller
681 cmp := a.abs_cmp(b)
682 return if signum < 0 { cmp > 0 } else { cmp < 0 }
683}
684
685// get_bit checks whether the bit at the given index is set.
686@[direct_array_access]
687pub fn (a Integer) get_bit(i u32) bool {
688 target_index := i / digit_bits
689 offset := i % digit_bits
690 if target_index >= a.digits.len {
691 return false
692 }
693 return (a.digits[target_index] >> offset) & 1 != 0
694}
695
696// set_bit sets the bit at the given index to the given value.
697pub fn (mut a Integer) set_bit(i u32, value bool) {
698 target_index := i / digit_bits
699 offset := i % digit_bits
700
701 if target_index >= a.digits.len {
702 if value {
703 a = one_int.left_shift(i).bitwise_or(a)
704 }
705 return
706 }
707
708 mut copy := a.digits.clone()
709
710 if value {
711 copy[target_index] |= u64(1) << offset
712 } else {
713 copy[target_index] &= ~(u64(1) << offset)
714 }
715
716 a = Integer{
717 signum: a.signum
718 digits: copy
719 }
720}
721
722// bitwise_or returns the "bitwise or" of the integers `|a|` and `|b|`.
723//
724// Note: both operands are treated as absolute values.
725pub fn (a Integer) bitwise_or(b Integer) Integer {
726 mut result := []u64{len: imax(a.digits.len, b.digits.len)}
727 bitwise_or_digit_array(a.digits, b.digits, mut result)
728 return Integer{
729 digits: result
730 signum: if result.len == 0 { 0 } else { 1 }
731 }
732}
733
734// bitwise_and returns the "bitwise and" of the integers `|a|` and `|b|`.
735//
736// Note: both operands are treated as absolute values.
737pub fn (a Integer) bitwise_and(b Integer) Integer {
738 mut result := []u64{len: imax(a.digits.len, b.digits.len)}
739 bitwise_and_digit_array(a.digits, b.digits, mut result)
740 return Integer{
741 digits: result
742 signum: if result.len == 0 { 0 } else { 1 }
743 }
744}
745
746// bitwise_not returns the "bitwise not" of the integer `|a|`.
747//
748// Note: the integer is treated as an absolute value.
749pub fn (a Integer) bitwise_not() Integer {
750 mut result := []u64{len: a.digits.len}
751 bitwise_not_digit_array(a.digits, mut result)
752 return Integer{
753 digits: result
754 signum: if result.len == 0 { 0 } else { 1 }
755 }
756}
757
758// bitwise_com returns "bitwise complement" of integer `a`.
759//
760// Note: this function consider the sign of the input.
761pub fn (a Integer) bitwise_com() Integer {
762 return if a.signum == -1 {
763 a.abs() - one_int
764 } else {
765 (a + one_int).neg()
766 }
767}
768
769// bitwise_xor returns the "bitwise exclusive or" of the integers `|a|` and `|b|`.
770//
771// Note: both operands are treated as absolute values.
772pub fn (a Integer) bitwise_xor(b Integer) Integer {
773 mut result := []u64{len: imax(a.digits.len, b.digits.len)}
774 bitwise_xor_digit_array(a.digits, b.digits, mut result)
775 return Integer{
776 digits: result
777 signum: if result.len == 0 { 0 } else { 1 }
778 }
779}
780
781// left_shift returns the integer `a` shifted left by `amount` bits.
782@[direct_array_access]
783pub fn (a Integer) left_shift(amount u32) Integer {
784 if a.signum == 0 {
785 return a
786 }
787 if amount == 0 {
788 return a
789 }
790 normalised_amount := amount % digit_bits
791 digit_offset := int(amount / digit_bits)
792 mut new_array := []u64{len: a.digits.len + digit_offset}
793 for index in 0 .. a.digits.len {
794 new_array[index + digit_offset] = a.digits[index]
795 }
796 if normalised_amount > 0 {
797 shift_digits_left(new_array, normalised_amount, mut new_array)
798 }
799 return Integer{
800 digits: new_array
801 signum: a.signum
802 }
803}
804
805// right_shift returns the integer `a` shifted right by `amount` bits.
806@[direct_array_access]
807pub fn (a Integer) right_shift(amount u32) Integer {
808 if a.signum == 0 {
809 return a
810 }
811 if amount == 0 {
812 return a
813 }
814 normalised_amount := amount % digit_bits
815 digit_offset := int(amount / digit_bits)
816 if digit_offset >= a.digits.len {
817 return zero_int
818 }
819 mut new_array := []u64{len: a.digits.len - digit_offset}
820 for index in 0 .. new_array.len {
821 new_array[index] = a.digits[index + digit_offset]
822 }
823 if normalised_amount > 0 {
824 shift_digits_right(new_array, normalised_amount, mut new_array)
825 }
826 return Integer{
827 digits: new_array
828 signum: if new_array.len > 0 { a.signum } else { 0 }
829 }
830}
831
832// bin_str returns the binary string representation of the integer `a`.
833@[direct_array_access]
834pub fn (integer Integer) bin_str() string {
835 return integer.radix_str(2)
836}
837
838// hex returns the hexadecimal string representation of the integer `a`.
839@[direct_array_access]
840pub fn (integer Integer) hex() string {
841 return integer.radix_str(16)
842}
843
844// radix_str returns the string representation of the integer `a` in the specified radix.
845pub fn (integer Integer) radix_str(radix u32) string {
846 if integer.signum == 0 || radix == 0 {
847 return '0'
848 }
849 return integer.general_radix_str(int(radix))
850}
851
852fn (integer Integer) general_radix_str(radix int) string {
853 $if debug {
854 assert radix != 0
855 }
856 divisor := integer_from_int(radix).pow(u32(radix_options[radix]))
857
858 mut current := integer.abs()
859 mut digit := zero_int
860 mut sb := strings.new_builder(integer.digits.len * radix_options[radix]) // XXX
861 mut st := []string{cap: integer.digits.len * radix_options[radix]}
862 for current.signum > 0 {
863 current, digit = current.div_mod_internal(divisor)
864 st << general_str(current, digit, radix)
865 }
866 if integer.signum == -1 {
867 sb.write_string('-')
868 }
869 for st.len > 0 {
870 sb.write_string(st.pop())
871 }
872 return sb.str()
873}
874
875fn general_str(quotient Integer, remainder Integer, radix int) string {
876 if quotient.signum == 0 && remainder.signum == 0 {
877 return '0'
878 }
879 divisor := integer_from_int(radix)
880
881 mut current := remainder.abs()
882 mut digit := zero_int
883 mut sb := strings.new_builder(radix_options[radix])
884 mut st := []u8{cap: radix_options[radix]}
885 for current.signum > 0 {
886 current, digit = current.div_mod_internal(divisor)
887 st << digit_array[digit.int()]
888 }
889 if quotient.signum > 0 {
890 sb.write_string(strings.repeat(48, radix_options[radix] - st.len))
891 }
892 for st.len > 0 {
893 sb.write_u8(st.pop())
894 }
895 return sb.str()
896}
897
898// str returns the decimal string representation of the integer `a`.
899pub fn (integer Integer) str() string {
900 return integer.radix_str(u32(10))
901}
902
903// int returns the integer value of the integer `a`.
904// NOTE: This may cause loss of precision.
905@[direct_array_access]
906pub fn (a Integer) int() int {
907 if a.signum == 0 {
908 return 0
909 }
910 // Check for minimum value int
911 if a.digits[0] >= 2147483648 && a.signum == -1 {
912 return -2147483648
913 }
914 // Rest of the values should be fine
915 value := int(a.digits[0] & 0x7fffffff)
916 return value * a.signum
917}
918
919// bytes returns the a byte representation of the integer a, along with the signum int.
920// NOTE: The byte array returned is in big endian order.
921@[direct_array_access]
922pub fn (a Integer) bytes() ([]u8, int) {
923 if a.signum == 0 {
924 return []u8{len: 0}, 0
925 }
926 bit_len := a.bit_len()
927 mut bytes := []u8{cap: bit_len / 8 + 1}
928 mut current_byte := u8(0)
929 mut bits_in_byte := 0
930 mut digit := a.digits.last()
931 mut bit := u8(0)
932
933 // pad first byte
934 bits_in_byte = 8 - bit_len % 8
935 if bits_in_byte == 8 {
936 bits_in_byte = 0
937 }
938 // MSB digit
939 mut msb_bits := bit_len % digit_bits
940 if msb_bits == 0 {
941 msb_bits = digit_bits
942 }
943 for i := msb_bits - 1; i >= 0; i-- {
944 bit = u8((digit >> i) & 1)
945 current_byte = (current_byte << 1) | u8(bit)
946 bits_in_byte++
947 if bits_in_byte == 8 {
948 bytes << current_byte
949 current_byte = 0
950 bits_in_byte = 0
951 }
952 }
953
954 for i := a.digits.len - 2; i >= 0; i-- {
955 digit = a.digits[i]
956 for shift := digit_bits - 1; shift >= 0; shift-- {
957 bit = u8((digit >> shift) & 1)
958 current_byte = (current_byte << 1) | bit
959 bits_in_byte++
960 if bits_in_byte == 8 {
961 bytes << current_byte
962 current_byte = 0
963 bits_in_byte = 0
964 }
965 }
966 }
967
968 return bytes, a.signum
969}
970
971// factorial returns the factorial of the integer `a`.
972pub fn (a Integer) factorial() Integer {
973 if a.signum == 0 {
974 return one_int
975 }
976 mut product := one_int
977 mut current := a
978 for current.signum != 0 {
979 product *= current
980 current.dec()
981 }
982 return product
983}
984
985// isqrt returns the closest integer square root of the integer `a`.
986//
987// WARNING: this method will panic if `a < 0`. Refer to isqrt_checked for a safer version.
988@[inline]
989pub fn (a Integer) isqrt() Integer {
990 return a.isqrt_checked() or { panic(err) }
991}
992
993// isqrt returns the closest integer square root of the integer `a`.
994// An error is returned if `a < 0`.
995pub fn (a Integer) isqrt_checked() !Integer {
996 if a.signum < 0 {
997 return error('math.big: Cannot calculate square root of negative integer')
998 }
999 if a.signum == 0 {
1000 return a
1001 }
1002 if a.digits.len == 1 && a.digits.last() == 1 {
1003 return a
1004 }
1005
1006 mut shift := a.bit_len()
1007 if shift & 1 == 1 {
1008 shift += 1
1009 }
1010 mut result := zero_int
1011 for shift >= 0 {
1012 result = result.left_shift(1)
1013 larger := result + one_int
1014 if (larger * larger).abs_cmp(a.right_shift(u32(shift))) <= 0 {
1015 result = larger
1016 }
1017 shift -= 2
1018 }
1019 return result
1020}
1021
1022@[inline]
1023fn bi_min(a Integer, b Integer) Integer {
1024 return if a < b { a } else { b }
1025}
1026
1027@[inline]
1028fn bi_max(a Integer, b Integer) Integer {
1029 return if a > b { a } else { b }
1030}
1031
1032// gcd returns the greatest common divisor of the two integers `a` and `b`.
1033pub fn (a Integer) gcd(b Integer) Integer {
1034 // The cutoff is determined empirically, using vlib/v/tests/bench/math_big_gcd/bench_euclid.v .
1035 if b.digits.len < 8 {
1036 return a.gcd_euclid(b)
1037 }
1038 return a.gcd_binary(b)
1039}
1040
1041// gcd_binary returns the greatest common divisor of the two integers `a` and `b`.
1042// Note that gcd_binary is faster than gcd_euclid, for large integers (over 8 bytes long).
1043// Inspired by the 2013-christmas-special by D. Lemire & R. Corderoy https://en.algorithmica.org/hpc/analyzing-performance/gcd/
1044// For more information, refer to the Wikipedia article: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
1045// Discussion and further information: https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor/
1046pub fn (a Integer) gcd_binary(b Integer) Integer {
1047 if a.signum == 0 {
1048 return b.abs()
1049 }
1050 if b.signum == 0 {
1051 return a.abs()
1052 }
1053 if a.abs_cmp(one_int) == 0 || b.abs_cmp(one_int) == 0 {
1054 return one_int
1055 }
1056
1057 mut aa, az := a.abs().rsh_to_set_bit()
1058 mut bb, bz := b.abs().rsh_to_set_bit()
1059 shift := umin(az, bz)
1060
1061 for aa.signum != 0 {
1062 diff := bb - aa
1063 bb = bi_min(aa, bb)
1064 aa, _ = diff.abs().rsh_to_set_bit()
1065 }
1066 return bb.left_shift(shift)
1067}
1068
1069// gcd_euclid returns the greatest common divisor of the two integers `a` and `b`.
1070// Note that gcd_euclid is faster than gcd_binary, for very-small-integers up to 8-byte/u64.
1071pub fn (a Integer) gcd_euclid(b Integer) Integer {
1072 if a.signum == 0 {
1073 return b.abs()
1074 }
1075 if b.signum == 0 {
1076 return a.abs()
1077 }
1078 if a.signum < 0 {
1079 return a.neg().gcd_euclid(b)
1080 }
1081 if b.signum < 0 {
1082 return a.gcd_euclid(b.neg())
1083 }
1084 mut x := a
1085 mut y := b
1086 mut r := x % y
1087 for r.signum != 0 {
1088 x = y
1089 y = r
1090 r = x % y
1091 }
1092 return y
1093}
1094
1095// mod_inverse calculates the multiplicative inverse of the integer `a` in the ring `ℤ/nℤ`.
1096// Therefore, the return value `x` satisfies `a * x == 1 (mod m)`.
1097// An error is returned if `a` and `n` are not relatively prime, i.e. `gcd(a, n) != 1` or
1098// if n <= 1
1099@[inline]
1100pub fn (a Integer) mod_inverse(n Integer) !Integer {
1101 return if n.bit_len() <= 1 {
1102 error('math.big: Modulus `n` must be greater than 1')
1103 } else if a.gcd(n) != one_int {
1104 error('math.big: No multiplicative inverse')
1105 } else {
1106 a.mod_inv(n)
1107 }
1108}
1109
1110// this is an internal function, therefore we assume valid inputs,
1111// i.e. m > 1 and gcd(a, m) = 1
1112// see pub fn mod_inverse for details on the result
1113// -----
1114// the algorithm is based on the Extended Euclidean algorithm which computes `ax + by = d`
1115// in this case `b` is the input integer `a` and `a` is the input modulus `m`. The extended
1116// Euclidean algorithm calculates the greatest common divisor `d` and two coefficients `x` and `y`
1117// satisfying the above equality.
1118//
1119// For the sake of clarity, we refer to the input integer `a` as `b` and the integer `m` as `a`.
1120// If `gcd(a, b) = d = 1` then the coefficient `y` is known to be the multiplicative inverse of
1121// `b` in ring `Z/aZ`, since reducing `ax + by = 1` by `a` yields `by == 1 (mod a)`.
1122@[direct_array_access]
1123fn (a Integer) mod_inv(m Integer) Integer {
1124 mut n := Integer{
1125 digits: m.digits.clone()
1126 signum: 1
1127 }
1128 mut b := a
1129 mut x := one_int
1130 mut y := zero_int
1131 if b.signum < 0 || b.abs_cmp(n) >= 0 {
1132 b = b % n
1133 }
1134 mut sign := -1
1135
1136 for b != zero_int {
1137 q, r := if n.bit_len() == b.bit_len() {
1138 one_int, n - b
1139 } else {
1140 // safe because the loop terminates if b == 0
1141 n.div_mod_internal(b)
1142 }
1143
1144 n = b
1145 b = r
1146
1147 // tmp := q * x + y
1148 tmp := if q == one_int {
1149 x
1150 } else if q.digits.len == 1 && q.digits[0] & (q.digits[0] - 1) == 0 {
1151 x.left_shift(u32(bits.trailing_zeros_64(q.digits[0])))
1152 } else {
1153 q * x
1154 } + y
1155
1156 y = x
1157 x = tmp
1158 sign = -sign
1159 }
1160
1161 if sign < 0 {
1162 y = m - y
1163 }
1164
1165 $if debug {
1166 assert n == one_int
1167 }
1168
1169 return if y.signum > 0 && y.abs_cmp(m) < 0 {
1170 y
1171 } else {
1172 y % m
1173 }
1174}
1175
1176// rsh_to_set_bit returns the integer `x` shifted right until it is odd and an exponent satisfying
1177// `x = x1 * 2^n`
1178// we don't return `2^n`, because the caller may be able to use `n` without allocating an Integer
1179@[direct_array_access; inline]
1180fn (x Integer) rsh_to_set_bit() (Integer, u32) {
1181 if x.digits.len == 0 {
1182 return zero_int, 0
1183 }
1184
1185 mut n := u32(0)
1186 for x.digits[n] == 0 {
1187 n++
1188 }
1189 n = (n * digit_bits) + u32(bits.trailing_zeros_64(x.digits[n]))
1190 return x.right_shift(n), n
1191}
1192
1193// is_odd returns true if the integer `x` is odd, therefore an integer of the form `2k + 1`.
1194// An input of 0 returns false.
1195@[direct_array_access; inline]
1196pub fn (x Integer) is_odd() bool {
1197 return x.digits.len != 0 && x.digits[0] & 1 == 1
1198}
1199
1200// is_power_of_2 returns true when the integer `x` satisfies `2^n`, where `n >= 0`
1201@[direct_array_access; inline]
1202pub fn (x Integer) is_power_of_2() bool {
1203 if x.signum <= 0 {
1204 return false
1205 }
1206
1207 // check if all but the most significant digit are 0
1208 for i := 0; i < x.digits.len - 1; i++ {
1209 if x.digits[i] != 0 {
1210 return false
1211 }
1212 }
1213 n := x.digits.last()
1214 return n & (n - u64(1)) == 0
1215}
1216
1217// bit_len returns the number of bits required to represent the integer `a`.
1218@[inline]
1219pub fn (x Integer) bit_len() int {
1220 if x.signum == 0 {
1221 return 0
1222 }
1223 if x.digits.len == 0 {
1224 return 0
1225 }
1226 return x.digits.len * digit_bits - (bits.leading_zeros_64(x.digits.last()) - (64 - digit_bits))
1227}
1228