bigint: Add count_bits and more prep.

This commit is contained in:
Jeroen van Rijn
2021-08-11 20:59:50 +02:00
parent dfd5a993a2
commit 905d5459a9
4 changed files with 41 additions and 20 deletions
-1
View File
@@ -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 `a` is negative and `|a|` >= `digit`, call `dest = |a| - digit`
*/ */
if is_neg(a) && (a.used > 1 || a.digit[0] >= 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. Temporarily fix `a`'s sign.
*/ */
+15 -16
View File
@@ -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. The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
*/ */
import "core:intrinsics"
/* /*
Tunables Tunables
*/ */
@@ -97,26 +99,23 @@ when size_of(rawptr) == 8 {
/* /*
We can use u128 as an intermediary. We can use u128 as an intermediary.
*/ */
DIGIT :: distinct(u64); DIGIT :: distinct(u64);
_DIGIT_BITS :: 60; _WORD :: distinct(u128);
_WORD :: u128;
_MAX_COMBA :: 1 << (128 - (2 * _DIGIT_BITS)) ;
_WARRAY :: 1 << ((128 - (2 * _DIGIT_BITS)) + 1);
} else { } else {
DIGIT :: distinct(u32); DIGIT :: distinct(u32);
_DIGIT_BITS :: 28; _WORD :: distinct(u64);
_WORD :: u64;
_MAX_COMBA :: 1 << ( 64 - (2 * _DIGIT_BITS)) ;
_WARRAY :: 1 << (( 64 - (2 * _DIGIT_BITS)) + 1);
} }
#assert(size_of(_WORD) == 2 * size_of(DIGIT)); #assert(size_of(_WORD) == 2 * size_of(DIGIT));
_MASK :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1);
_DIGIT_MAX :: _MASK;
_BITS_IN_BYTE :: 8; _DIGIT_TYPE_BITS :: 8 * size_of(DIGIT);
_BITS_IN_TYPE :: #force_inline proc($T) -> int where intrinsics.type_is_integer(T) { _WORD_TYPE_BITS :: 8 * size_of(_WORD);
return _BITS_IN_BYTE * size_of(T);
} _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 { Order :: enum i8 {
LSB_First = -1, LSB_First = -1,
+3 -3
View File
@@ -75,9 +75,9 @@ demo :: proc() {
err = sub(c, a, b); err = sub(c, a, b);
// err = add(c, a, b); // err = add(c, a, b);
fmt.printf("Error: %v\n", err); fmt.printf("Error: %v\n", err);
fmt.printf("a: %v\n", print_int(a)); fmt.printf("a: %v, bits: %v\n", print_int(a), count_bits(a));
fmt.printf("b: %v\n", print_int(b)); fmt.printf("b: %v, bits: %v\n", print_int(b), count_bits(b));
fmt.printf("c: %v\n", print_int(c)); fmt.printf("c: %v, bits: %v\n", print_int(c), count_bits(c));
} }
main :: proc() { main :: proc() {
+23
View File
@@ -217,6 +217,29 @@ minus_one :: proc(a: ^Int, minimize := false) -> (err: Error) {
return .OK; 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. Internal helpers.
*/ */