瀏覽代碼

bigint: Prepare for multiplication.

Jeroen van Rijn 4 年之前
父節點
當前提交
dfd5a993a2
共有 2 個文件被更改,包括 53 次插入11 次删除
  1. 23 8
      core/math/bigint/bigint.odin
  2. 30 3
      core/math/bigint/example.odin

+ 23 - 8
core/math/bigint/bigint.odin

@@ -19,14 +19,20 @@ when _LOW_MEMORY {
 	_DEFAULT_DIGIT_COUNT :: 32;
 	_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 {
 Sign :: enum u8 {
 	Zero_or_Positive = 0,
 	Zero_or_Positive = 0,
@@ -94,15 +100,24 @@ when size_of(rawptr) == 8 {
 	DIGIT       :: distinct(u64);
 	DIGIT       :: distinct(u64);
 	_DIGIT_BITS :: 60;
 	_DIGIT_BITS :: 60;
 	_WORD       :: 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;
 	_DIGIT_BITS :: 28;
 	_WORD       :: 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);
 _MASK          :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1);
 _DIGIT_MAX     :: _MASK;
 _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 {
 Order :: enum i8 {
 	LSB_First = -1,
 	LSB_First = -1,
 	MSB_First =  1,
 	MSB_First =  1,

+ 30 - 3
core/math/bigint/example.odin

@@ -13,6 +13,34 @@ package bigint
 import "core:fmt"
 import "core:fmt"
 import "core:mem"
 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 {
 print_int :: proc(a: ^Int, print_raw := false) -> string {
 	if print_raw {
 	if print_raw {
 		return fmt.tprintf("%v", a);
 		return fmt.tprintf("%v", a);
@@ -44,7 +72,7 @@ demo :: proc() {
 	fmt.printf("c: %v\n", print_int(c, true));
 	fmt.printf("c: %v\n", print_int(c, true));
 
 
 	fmt.println("=== Add ===");
 	fmt.println("=== Add ===");
-	err = sub(a, a, DIGIT(42));
+	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\n", print_int(a));
@@ -57,8 +85,7 @@ main :: proc() {
 	mem.tracking_allocator_init(&ta, context.allocator);
 	mem.tracking_allocator_init(&ta, context.allocator);
 	context.allocator = mem.tracking_allocator(&ta);
 	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();
 	demo();
 
 
 	if len(ta.allocation_map) > 0 {
 	if len(ta.allocation_map) > 0 {