From 37be8d40912a2fbf118efffdcf357aa68b78ec08 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 13 Aug 2021 14:55:53 +0200 Subject: [PATCH] big: Add `internal_invmod`. --- core/math/big/internal.odin | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 695dca04d..6610c8429 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -1740,6 +1740,29 @@ internal_int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (er } internal_neg :: proc { internal_int_neg, }; +/* + hac 14.61, pp608. +*/ +internal_int_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { + context.allocator = allocator; + /* + For all n in N and n > 0, n = 0 mod 1. + */ + if internal_is_positive(a) && internal_cmp(b, 1) == 0 { return internal_zero(dest); } + + /* + `b` cannot be negative and has to be > 1 + */ + if internal_is_negative(b) && internal_cmp(b, 1) != 1 { return .Invalid_Argument; } + + /* + If the modulus is odd we can use a faster routine instead. + */ + if internal_is_odd(b) { return _private_inverse_modulo_odd(dest, a, b); } + + return _private_inverse_modulo(dest, a, b); +} +internal_invmod :: proc{ internal_int_inverse_modulo, }; /* Helpers to extract values from the `Int`. @@ -1991,7 +2014,11 @@ internal_int_get :: proc(a: ^Int, $T: typeid) -> (res: T, err: Error) where intr internal_get :: proc { internal_int_get, }; internal_int_get_float :: proc(a: ^Int) -> (res: f64, err: Error) { - l := min(a.used, 17); // log2(max(f64)) is approximately 1020, or 17 legs. + /* + log2(max(f64)) is approximately 1020, or 17 legs with the 64-bit storage. + */ + legs :: 1020 / _DIGIT_BITS; + l := min(a.used, legs); fac := f64(1 << _DIGIT_BITS); d := 0.0;