diff --git a/core/math/bigint/basic.odin b/core/math/bigint/basic.odin index 8bab5b50d..a174799ba 100644 --- a/core/math/bigint/basic.odin +++ b/core/math/bigint/basic.odin @@ -89,7 +89,6 @@ add_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) { If `a` is negative and `|a|` >= `digit`, call `dest = |a| - digit` */ if is_neg(a) && (a.used > 1 || a.digit[0] >= digit) { - fmt.print("a = neg, %v\n", print_int(a)); /* Temporarily fix `a`'s sign. */ diff --git a/core/math/bigint/bigint.odin b/core/math/bigint/bigint.odin index 6e146b0cb..8f6cb1cf7 100644 --- a/core/math/bigint/bigint.odin +++ b/core/math/bigint/bigint.odin @@ -9,6 +9,8 @@ package bigint The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. */ +import "core:intrinsics" + /* Tunables */ @@ -97,26 +99,23 @@ when size_of(rawptr) == 8 { /* We can use u128 as an intermediary. */ - DIGIT :: distinct(u64); - _DIGIT_BITS :: 60; - _WORD :: u128; - _MAX_COMBA :: 1 << (128 - (2 * _DIGIT_BITS)) ; - _WARRAY :: 1 << ((128 - (2 * _DIGIT_BITS)) + 1); + DIGIT :: distinct(u64); + _WORD :: distinct(u128); } else { - DIGIT :: distinct(u32); - _DIGIT_BITS :: 28; - _WORD :: u64; - _MAX_COMBA :: 1 << ( 64 - (2 * _DIGIT_BITS)) ; - _WARRAY :: 1 << (( 64 - (2 * _DIGIT_BITS)) + 1); + DIGIT :: distinct(u32); + _WORD :: distinct(u64); } #assert(size_of(_WORD) == 2 * size_of(DIGIT)); -_MASK :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1); -_DIGIT_MAX :: _MASK; -_BITS_IN_BYTE :: 8; -_BITS_IN_TYPE :: #force_inline proc($T) -> int where intrinsics.type_is_integer(T) { - return _BITS_IN_BYTE * size_of(T); -} +_DIGIT_TYPE_BITS :: 8 * size_of(DIGIT); +_WORD_TYPE_BITS :: 8 * size_of(_WORD); + +_DIGIT_BITS :: _DIGIT_TYPE_BITS - 4; + +_MASK :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1); +_DIGIT_MAX :: _MASK; +_MAX_COMBA :: 1 << (_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) ; +_WARRAY :: 1 << ((_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) + 1); Order :: enum i8 { LSB_First = -1, diff --git a/core/math/bigint/example.odin b/core/math/bigint/example.odin index 082e695c3..145a8fc75 100644 --- a/core/math/bigint/example.odin +++ b/core/math/bigint/example.odin @@ -75,9 +75,9 @@ demo :: proc() { err = sub(c, a, b); // err = add(c, a, b); fmt.printf("Error: %v\n", err); - fmt.printf("a: %v\n", print_int(a)); - fmt.printf("b: %v\n", print_int(b)); - fmt.printf("c: %v\n", print_int(c)); + fmt.printf("a: %v, bits: %v\n", print_int(a), count_bits(a)); + fmt.printf("b: %v, bits: %v\n", print_int(b), count_bits(b)); + fmt.printf("c: %v, bits: %v\n", print_int(c), count_bits(c)); } main :: proc() { diff --git a/core/math/bigint/helpers.odin b/core/math/bigint/helpers.odin index 170beb1bc..3d25230f2 100644 --- a/core/math/bigint/helpers.odin +++ b/core/math/bigint/helpers.odin @@ -217,6 +217,29 @@ minus_one :: proc(a: ^Int, minimize := false) -> (err: Error) { return .OK; } +/* + Count bits in an `Int`. +*/ +count_bits :: proc(a: ^Int) -> (count: int) { + assert_initialized(a); + /* + Fast path for zero. + */ + if is_zero(a) { + return 0; + } + /* + Get the number of DIGITs and use it. + */ + count = (a.used - 1) * _DIGIT_BITS; + /* + Take the last DIGIT and count the bits in it. + */ + clz := int(intrinsics.count_leading_zeros(a.digit[a.used - 1])); + count += (_DIGIT_TYPE_BITS - clz); + return; +} + /* Internal helpers. */