From dfd5a993a28c404d2b6f5b06ab6c3663b40cf3de Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 17 Jul 2021 00:03:40 +0200 Subject: [PATCH] bigint: Prepare for multiplication. --- core/math/bigint/bigint.odin | 31 +++++++++++++++++++++++-------- core/math/bigint/example.odin | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/core/math/bigint/bigint.odin b/core/math/bigint/bigint.odin index 1445bc69d..6e146b0cb 100644 --- a/core/math/bigint/bigint.odin +++ b/core/math/bigint/bigint.odin @@ -19,14 +19,20 @@ when _LOW_MEMORY { _DEFAULT_DIGIT_COUNT :: 32; } -// /* tunable cutoffs */ -// #ifndef MP_FIXED_CUTOFFS -// extern int -// MP_MUL_KARATSUBA_CUTOFF, -// MP_SQR_KARATSUBA_CUTOFF, -// MP_MUL_TOOM_CUTOFF, -// MP_SQR_TOOM_CUTOFF; -// #endif +_MUL_KARATSUBA_CUTOFF :: #config(MUL_KARATSUBA_CUTOFF, _DEFAULT_MUL_KARATSUBA_CUTOFF); +_SQR_KARATSUBA_CUTOFF :: #config(SQR_KARATSUBA_CUTOFF, _DEFAULT_SQR_KARATSUBA_CUTOFF); +_MUL_TOOM_CUTOFF :: #config(MUL_TOOM_CUTOFF, _DEFAULT_MUL_TOOM_CUTOFF); +_SQR_TOOM_CUTOFF :: #config(SQR_TOOM_CUTOFF, _DEFAULT_SQR_TOOM_CUTOFF); + +/* + These defaults were tuned on an AMD A8-6600K (64-bit) using libTomMath's `make tune`. + TODO(Jeroen): Port this tuning algorithm and tune them for more modern processors. +*/ +_DEFAULT_MUL_KARATSUBA_CUTOFF :: 80; +_DEFAULT_SQR_KARATSUBA_CUTOFF :: 120; +_DEFAULT_MUL_TOOM_CUTOFF :: 350; +_DEFAULT_SQR_TOOM_CUTOFF :: 400; + Sign :: enum u8 { Zero_or_Positive = 0, @@ -94,15 +100,24 @@ when size_of(rawptr) == 8 { DIGIT :: distinct(u64); _DIGIT_BITS :: 60; _WORD :: u128; + _MAX_COMBA :: 1 << (128 - (2 * _DIGIT_BITS)) ; + _WARRAY :: 1 << ((128 - (2 * _DIGIT_BITS)) + 1); } else { DIGIT :: distinct(u32); _DIGIT_BITS :: 28; _WORD :: u64; + _MAX_COMBA :: 1 << ( 64 - (2 * _DIGIT_BITS)) ; + _WARRAY :: 1 << (( 64 - (2 * _DIGIT_BITS)) + 1); } #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); +} + Order :: enum i8 { LSB_First = -1, MSB_First = 1, diff --git a/core/math/bigint/example.odin b/core/math/bigint/example.odin index 69dab47dd..082e695c3 100644 --- a/core/math/bigint/example.odin +++ b/core/math/bigint/example.odin @@ -13,6 +13,34 @@ package bigint import "core:fmt" import "core:mem" +print_configation :: proc() { + fmt.printf( +`Configuration: + DIGIT_BITS %v + MIN_DIGIT_COUNT %v + MAX_DIGIT_COUNT %v + EFAULT_DIGIT_COUNT %v + MAX_COMBA %v + WARRAY %v + MUL_KARATSUBA_CUTOFF %v + SQR_KARATSUBA_CUTOFF %v + MUL_TOOM_CUTOFF %v + SQR_TOOM_CUTOFF %v +`, _DIGIT_BITS, +_MIN_DIGIT_COUNT, +_MAX_DIGIT_COUNT, +_DEFAULT_DIGIT_COUNT, +_MAX_COMBA, +_WARRAY, +_MUL_KARATSUBA_CUTOFF, +_SQR_KARATSUBA_CUTOFF, +_MUL_TOOM_CUTOFF, +_SQR_TOOM_CUTOFF, +); + + fmt.println(); +} + print_int :: proc(a: ^Int, print_raw := false) -> string { if print_raw { return fmt.tprintf("%v", a); @@ -44,7 +72,7 @@ demo :: proc() { fmt.printf("c: %v\n", print_int(c, true)); fmt.println("=== Add ==="); - err = sub(a, a, DIGIT(42)); + err = sub(c, a, b); // err = add(c, a, b); fmt.printf("Error: %v\n", err); fmt.printf("a: %v\n", print_int(a)); @@ -57,8 +85,7 @@ main :: proc() { mem.tracking_allocator_init(&ta, context.allocator); context.allocator = mem.tracking_allocator(&ta); - fmt.printf("_DIGIT_BITS: %v\n_MIN_DIGIT_COUNT: %v\n_MAX_DIGIT_COUNT: %v\n_DEFAULT_DIGIT_COUNT: %v\n\n", _DIGIT_BITS, _MIN_DIGIT_COUNT, _MAX_DIGIT_COUNT, _DEFAULT_DIGIT_COUNT); - + // print_configation(); demo(); if len(ta.allocation_map) > 0 {