Browse Source

big: Split up `int_is_*` comparison tests.

Jeroen van Rijn 4 years ago
parent
commit
fd95f50c56
5 changed files with 358 additions and 267 deletions
  1. 3 3
      core/math/big/build.bat
  2. 51 157
      core/math/big/compare.odin
  3. 6 10
      core/math/big/example.odin
  4. 297 57
      core/math/big/internal.odin
  5. 1 40
      core/math/big/prime.odin

+ 3 - 3
core/math/big/build.bat

@@ -1,10 +1,10 @@
 @echo off
-odin run . -vet
+:odin run . -vet
 : -o:size
 :odin build . -build-mode:shared -show-timings -o:minimal -no-bounds-check
 :odin build . -build-mode:shared -show-timings -o:size -no-bounds-check
 :odin build . -build-mode:shared -show-timings -o:size
-:odin build . -build-mode:shared -show-timings -o:speed -no-bounds-check
+odin build . -build-mode:shared -show-timings -o:speed -no-bounds-check
 :odin build . -build-mode:shared -show-timings -o:speed
 
-:python test.py
+python test.py

+ 51 - 157
core/math/big/compare.odin

@@ -9,199 +9,93 @@ package big
 	The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
 
 	This file contains various comparison routines.
+
+	We essentially just check if params are initialized before punting to the `internal_*` versions.
+	This has the side benefit of being able to add additional characteristics to numbers, like NaN,
+	and keep support for that contained.
 */
 
 import "core:intrinsics"
-import "core:mem"
 
 int_is_initialized :: proc(a: ^Int) -> bool {
-	if a == nil {
-		return false;
-	}
-	raw := transmute(mem.Raw_Dynamic_Array)a.digit;
-	return raw.cap >= _MIN_DIGIT_COUNT;
+	if a == nil { return false; }
+
+	return #force_inline internal_int_is_initialized(a);
 }
 
-int_is_zero :: proc(a: ^Int) -> (res: bool, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return false, err;
-	}
-	return a.used == 0, nil;
+int_is_zero :: proc(a: ^Int) -> (zero: bool, err: Error) {
+	if a == nil { return false, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a); err != nil { return false, err; }
+
+	return #force_inline internal_is_zero(a), nil;
 }
 
-int_is_positive :: proc(a: ^Int) -> (res: bool, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return false, err;
-	}
-	return a.sign == .Zero_or_Positive, nil;
+int_is_positive :: proc(a: ^Int) -> (positive: bool, err: Error) {
+	if a == nil { return false, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a); err != nil { return false, err; }
+
+	return #force_inline internal_is_positive(a), nil;
 }
 
-int_is_negative :: proc(a: ^Int) -> (res: bool, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return false, err;
-	}
-	return a.sign == .Negative, nil;
+int_is_negative :: proc(a: ^Int) -> (negative: bool, err: Error) {
+	if a == nil { return false, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a); err != nil { return false, err; }
+
+	return #force_inline internal_is_negative(a), nil;
 }
 
-int_is_even :: proc(a: ^Int) -> (res: bool, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return false, err;
-	}
-
-	res, err = is_zero(a);
-	if err != nil {
-		return false, err;
-	} else if res == true {
-		return true, nil;
-	}
-
-	res = false;
-	if a.used > 0 && a.digit[0] & 1 == 0 {
-		res = true;
-	}
-	return res, nil;
+int_is_even :: proc(a: ^Int) -> (even: bool, err: Error) {
+	if a == nil { return false, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a); err != nil { return false, err; }
+
+	return #force_inline internal_is_even(a), nil;
 }
 
-int_is_odd :: proc(a: ^Int) -> (res: bool, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return false, err;
-	}
+int_is_odd :: proc(a: ^Int) -> (odd: bool, err: Error) {
+	if a == nil { return false, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a); err != nil { return false, err; }
 
-	res, err = is_even(a);
-	return !res, err;
+	return #force_inline internal_is_odd(a), nil;
 }
 
-platform_int_is_power_of_two :: proc(a: int) -> bool {
+platform_int_is_power_of_two :: #force_inline proc(a: int) -> bool {
 	return ((a) != 0) && (((a) & ((a) - 1)) == 0);
 }
 
 int_is_power_of_two :: proc(a: ^Int) -> (res: bool, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return false, err;
-	}
-
-	/*
-		Early out for Int == 0.
-	*/
-	if a.used == 0 {
-		return false, nil;
-	}
-
-	/*
-		For an `Int` to be a power of two, its top limb has to be a power of two.
-	*/
-	if !platform_int_is_power_of_two(int(a.digit[a.used - 1])) {
-		return false, nil;
-	}
-
-	/*
-		That was the only limb, so it's a power of two.
-	*/
-	if a.used == 1 {
-		return true, nil;
-	}
-
-	/*
-		For an Int to be a power of two, all limbs except the top one have to be zero.
-	*/
-	for i := 1; i < a.used; i += 1 {
-		if a.digit[i - 1] != 0 {
-			return false, nil;
-		}
-	}
-	return true, nil;
+	if a == nil { return false, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a); err != nil { return false, err; }
+
+	return #force_inline internal_is_power_of_two(a), nil;
 }
 
 /*
 	Compare two `Int`s, signed.
 */
-int_compare :: proc(a, b: ^Int) -> (res: int, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return 0, err;
-	}
-	if err = clear_if_uninitialized(b); err != nil {
-		return 0, err;
-	}
-
-	neg: bool;
-	if neg, err = is_negative(a); err != nil {
-		return 0, err;
-	}
-
-	/* Compare based on sign */
-	if a.sign != b.sign {
-		res = -1 if neg else +1;
-		return res, nil;
-	}
-
-	/* If negative, compare in the opposite direction */
-	if neg {
-		return cmp_mag(b, a);
-	}
-	return cmp_mag(a, b);
+int_compare :: proc(a, b: ^Int) -> (comparison: int, err: Error) {
+	if a == nil || b == nil { return 0, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a, b); err != nil {	return 0, err; }
+
+	return #force_inline internal_cmp(a, b), nil;
 }
+int_cmp :: int_compare;
 
 /*
 	Compare an `Int` to an unsigned number upto the size of the backing type.
 */
-int_compare_digit :: proc(a: ^Int, u: DIGIT) -> (res: int, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return 0, err;
-	}
-
-	/* Compare based on sign */
-	neg: bool;
-	if neg, err = is_neg(a); err != nil {
-		return 0, err;
-	}
-	if neg {
-		return -1, nil;
-	}
-
-	/* Compare based on magnitude */
-	if a.used > 1 {
-		return +1, nil;
-	}
-
-	/* Compare the only digit in `a` to `u`. */
-	if a.digit[0] != u {
-		if a.digit[0] > u {
-			return +1, nil;
-		}
-		return -1, nil;
-	}
-
-	return 0, nil;
+int_compare_digit :: proc(a: ^Int, b: DIGIT) -> (comparison: int, err: Error) {
+	if a == nil { return 0, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a); err != nil { return 0, err; }
+
+	return #force_inline internal_cmp_digit(a, b), nil;
 }
 
 /*
 	Compare the magnitude of two `Int`s, unsigned.
 */
 int_compare_magnitude :: proc(a, b: ^Int) -> (res: int, err: Error) {
-	if err = clear_if_uninitialized(a); err != nil {
-		return 0, err;
-	}
-	if err = clear_if_uninitialized(b); err != nil {
-		return 0, err;
-	}
-
-	/* Compare based on used digits */
-	if a.used != b.used {
-		if a.used > b.used {
-			return +1, nil;
-		}
-		return -1, nil;
-	}
-
-	/* Same number of used digits, compare based on their value */
-	for n := a.used - 1; n >= 0; n -= 1 {
-		if a.digit[n] != b.digit[n] {
-			if a.digit[n] > b.digit[n] {
-				return +1, nil;
-			}
-			return -1, nil;
-		}
-	}
-
-   	return 0, nil;
+	if a == nil || b == nil { return 0, .Invalid_Pointer; }
+	if err = clear_if_uninitialized(a, b); err != nil { return 0, err; }
+
+	return #force_inline internal_cmp_mag(a, b), nil;
 }

+ 6 - 10
core/math/big/example.odin

@@ -75,16 +75,12 @@ demo :: proc() {
 	a, b, c, d, e, f := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
 	defer destroy(a, b, c, d, e, f);
 
-	n := 1_024;
-	k := 3;
-
-	{
-		SCOPED_TIMING(.choose);
-		choose(a, n, k);
-	}
-	
-	fmt.printf("%v choose %v ", n, k);
-	print("= ", a);
+	power_of_two(a, 3112);
+	fmt.printf("a is power of two: %v\n", internal_is_power_of_two(a));
+	sub(a, a, 1);
+	fmt.printf("a is power of two: %v\n", internal_is_power_of_two(a));
+	add(a, a, 1);
+	fmt.printf("a is power of two: %v\n", internal_is_power_of_two(a));
 }
 
 main :: proc() {

+ 297 - 57
core/math/big/internal.odin

@@ -25,6 +25,8 @@ package big
 	Exceptions include `quotient` and `remainder`, which are allowed to be `nil` when the calling code doesn't need them.
 
 	Check the comments above each `internal_*` implementation to see what constraints it expects to have met.
+
+	TODO: Handle +/- Infinity and NaN.
 */
 
 import "core:mem"
@@ -107,6 +109,7 @@ internal_int_add_unsigned :: proc(dest, a, b: ^Int, allocator := context.allocat
 	*/
 	return clamp(dest);
 }
+internal_add_unsigned :: proc { internal_int_add_unsigned, };
 
 /*
 	Low-level addition, signed. Handbook of Applied Cryptography, algorithm 14.7.
@@ -136,6 +139,7 @@ internal_int_add_signed :: proc(dest, a, b: ^Int, allocator := context.allocator
 	dest.sign = x.sign;
 	return #force_inline internal_int_sub_unsigned(dest, x, y, allocator);
 }
+internal_add_signed :: proc { internal_int_add_signed, };
 
 /*
 	Low-level addition Int+DIGIT, signed. Handbook of Applied Cryptography, algorithm 14.7.
@@ -246,7 +250,6 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) {
 	*/
 	return clamp(dest);	
 }
-
 internal_add :: proc { internal_int_add_signed, internal_int_add_digit, };
 
 /*
@@ -314,6 +317,7 @@ internal_int_sub_unsigned :: proc(dest, number, decrease: ^Int, allocator := con
 	*/
 	return clamp(dest);
 }
+internal_sub_unsigned :: proc { internal_int_sub_unsigned, };
 
 /*
 	Low-level subtraction, signed. Handbook of Applied Cryptography, algorithm 14.9.
@@ -915,6 +919,204 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int) -> (err: Er
 	return clamp(remainder);
 }
 
+/*
+	=============================    Low-level helpers    =============================
+
+
+	`internal_*` helpers don't return an `Error` like their public counterparts do,
+	because they expect not to be passed `nil` or uninitialized inputs.
+
+	This makes them more suitable for `internal_*` functions and some of the
+	public ones that have already satisfied these constraints.
+*/
+
+/*
+	This procedure will return `true` if the `Int` is initialized, `false` if not.
+	Assumes `a` not to be `nil`.
+*/
+internal_int_is_initialized :: #force_inline proc(a: ^Int) -> (initialized: bool) {
+	raw := transmute(mem.Raw_Dynamic_Array)a.digit;
+	return raw.cap >= _MIN_DIGIT_COUNT;
+}
+internal_is_initialized :: proc { internal_int_is_initialized, };
+
+/*
+	This procedure will return `true` if the `Int` is zero, `false` if not.
+	Assumes `a` not to be `nil`.
+*/
+internal_int_is_zero :: #force_inline proc(a: ^Int) -> (zero: bool) {
+	return a.used == 0;
+}
+internal_is_zero :: proc { internal_int_is_zero, };
+
+/*
+	This procedure will return `true` if the `Int` is positive, `false` if not.
+	Assumes `a` not to be `nil`.
+*/
+internal_int_is_positive :: #force_inline proc(a: ^Int) -> (positive: bool) {
+	return a.sign == .Zero_or_Positive;
+}
+internal_is_positive :: proc { internal_int_is_positive, };
+
+/*
+	This procedure will return `true` if the `Int` is negative, `false` if not.
+	Assumes `a` not to be `nil`.
+*/
+internal_int_is_negative :: #force_inline proc(a: ^Int) -> (negative: bool) {
+	return a.sign == .Negative;
+}
+internal_is_negative :: proc { internal_int_is_negative, };
+
+/*
+	This procedure will return `true` if the `Int` is even, `false` if not.
+	Assumes `a` not to be `nil`.
+*/
+internal_int_is_even :: #force_inline proc(a: ^Int) -> (even: bool) {
+	if internal_is_zero(a) { return true; }
+
+	/*
+		`a.used` > 0 here, because the above handled `is_zero`.
+		We don't need to explicitly test it.
+	*/
+	return a.digit[0] & 1 == 0;
+}
+internal_is_even :: proc { internal_int_is_even, };
+
+/*
+	This procedure will return `true` if the `Int` is even, `false` if not.
+	Assumes `a` not to be `nil`.
+*/
+internal_int_is_odd :: #force_inline proc(a: ^Int) -> (odd: bool) {
+	return !internal_int_is_even(a);
+}
+internal_is_odd :: proc { internal_int_is_odd, };
+
+
+/*
+	This procedure will return `true` if the `Int` is a power of two, `false` if not.
+	Assumes `a` not to be `nil`.
+*/
+internal_int_is_power_of_two :: #force_inline proc(a: ^Int) -> (power_of_two: bool) {
+	/*
+		Early out for Int == 0.
+	*/
+	if #force_inline internal_is_zero(a) { return true; }
+
+	/*
+		For an `Int` to be a power of two, its bottom limb has to be a power of two.
+	*/
+	if ! #force_inline platform_int_is_power_of_two(int(a.digit[a.used - 1])) { return false; }
+
+	/*
+		We've established that the bottom limb is a power of two.
+		If it's the only limb, that makes the entire Int a power of two.
+	*/
+	if a.used == 1 { return true; }
+
+	/*
+		For an `Int` to be a power of two, all limbs except the top one have to be zero.
+	*/
+	for i := 1; i < a.used && a.digit[i - 1] != 0; i += 1 { return false; }
+
+	return true;
+}
+internal_is_power_of_two :: proc { internal_int_is_power_of_two, };
+
+/*
+	Compare two `Int`s, signed.
+	Returns -1 if `a` < `b`, 0 if `a` == `b` and 1 if `b` > `a`.
+
+	Expects `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`.
+*/
+internal_int_compare :: #force_inline proc(a, b: ^Int) -> (comparison: int) {
+	a_is_negative := #force_inline internal_is_negative(a);
+
+	/*
+		Compare based on sign.
+	*/
+	if a.sign != b.sign { return -1 if a_is_negative else +1; }
+
+	/*
+		If `a` is negative, compare in the opposite direction */
+	if a_is_negative { return #force_inline internal_compare_magnitude(b, a); }
+
+	return #force_inline internal_compare_magnitude(a, b);
+}
+internal_compare :: proc { internal_int_compare, internal_int_compare_digit, };
+internal_cmp :: internal_compare;
+
+/*
+	Compare an `Int` to an unsigned number upto the size of the backing type.
+
+	Returns -1 if `a` < `b`, 0 if `a` == `b` and 1 if `b` > `a`.
+
+	Expects `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`.
+*/
+internal_int_compare_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (comparison: int) {
+	/*
+		Compare based on sign.
+	*/
+
+	if #force_inline internal_is_negative(a) { return -1; }
+
+	/*
+		Compare based on magnitude.
+	*/
+	if a.used > 1 { return +1; }
+
+	/*
+		Compare the only digit in `a` to `b`.
+	*/
+	switch {
+	case a.digit[0] < b:
+		return -1;
+	case a.digit[0] == b:
+		return  0;
+	case a.digit[0] > b:
+		return +1;
+	case:
+		/*
+			Unreachable.
+			Just here because Odin complains about a missing return value at the bottom of the proc otherwise.
+		*/
+		return;
+	}
+}
+internal_compare_digit :: proc { internal_int_compare_digit, };
+internal_cmp_digit :: internal_compare_digit;
+
+/*
+	Compare the magnitude of two `Int`s, unsigned.
+*/
+internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: int) {
+	/*
+		Compare based on used digits.
+	*/
+	if a.used != b.used {
+		if a.used > b.used {
+			return +1;
+		}
+		return -1;
+	}
+
+	/*
+		Same number of used digits, compare based on their value.
+	*/
+	#no_bounds_check for n := a.used - 1; n >= 0; n -= 1 {
+		if a.digit[n] != b.digit[n] {
+			if a.digit[n] > b.digit[n] {
+				return +1;
+			}
+			return -1;
+		}
+	}
+
+   	return 0;
+}
+internal_compare_magnitude :: proc { internal_int_compare_magnitude, };
+internal_cmp_mag :: internal_compare_magnitude;
+
+
 internal_int_zero_unused :: #force_inline proc(dest: ^Int, old_used := -1) {
 	/*
 		If we don't pass the number of previously used DIGITs, we zero all remaining ones.
@@ -1689,67 +1891,105 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int) -> (err: Error) {
 	Tables used by `internal_*` and `_*`.
 */
 
+_private_prime_table := []DIGIT{
+	0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+	0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+	0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+	0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
+	0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+	0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+	0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+	0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+	0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+	0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+	0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+	0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+	0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+	0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+	0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+	0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+	0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+	0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+	0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+	0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+	0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+	0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+	0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+	0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+	0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+	0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+	0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+	0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+	0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+	0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+	0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+	0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653,
+};
+
 when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) {
 	_factorial_table := [35]_WORD{
-/* f(00): */                                                   1,
-/* f(01): */                                                   1,
-/* f(02): */                                                   2,
-/* f(03): */                                                   6,
-/* f(04): */                                                  24,
-/* f(05): */                                                 120,
-/* f(06): */                                                 720,
-/* f(07): */                                               5_040,
-/* f(08): */                                              40_320,
-/* f(09): */                                             362_880,
-/* f(10): */                                           3_628_800,
-/* f(11): */                                          39_916_800,
-/* f(12): */                                         479_001_600,
-/* f(13): */                                       6_227_020_800,
-/* f(14): */                                      87_178_291_200,
-/* f(15): */                                   1_307_674_368_000,
-/* f(16): */                                  20_922_789_888_000,
-/* f(17): */                                 355_687_428_096_000,
-/* f(18): */                               6_402_373_705_728_000,
-/* f(19): */                             121_645_100_408_832_000,
-/* f(20): */                           2_432_902_008_176_640_000,
-/* f(21): */                          51_090_942_171_709_440_000,
-/* f(22): */                       1_124_000_727_777_607_680_000,
-/* f(23): */                      25_852_016_738_884_976_640_000,
-/* f(24): */                     620_448_401_733_239_439_360_000,
-/* f(25): */                  15_511_210_043_330_985_984_000_000,
-/* f(26): */                 403_291_461_126_605_635_584_000_000,
-/* f(27): */              10_888_869_450_418_352_160_768_000_000,
-/* f(28): */             304_888_344_611_713_860_501_504_000_000,
-/* f(29): */           8_841_761_993_739_701_954_543_616_000_000,
-/* f(30): */         265_252_859_812_191_058_636_308_480_000_000,
-/* f(31): */       8_222_838_654_177_922_817_725_562_880_000_000,
-/* f(32): */     263_130_836_933_693_530_167_218_012_160_000_000,
-/* f(33): */   8_683_317_618_811_886_495_518_194_401_280_000_000,
-/* f(34): */ 295_232_799_039_604_140_847_618_609_643_520_000_000,
+/* f(00): */                                                     1,
+/* f(01): */                                                     1,
+/* f(02): */                                                     2,
+/* f(03): */                                                     6,
+/* f(04): */                                                    24,
+/* f(05): */                                                   120,
+/* f(06): */                                                   720,
+/* f(07): */                                                 5_040,
+/* f(08): */                                                40_320,
+/* f(09): */                                               362_880,
+/* f(10): */                                             3_628_800,
+/* f(11): */                                            39_916_800,
+/* f(12): */                                           479_001_600,
+/* f(13): */                                         6_227_020_800,
+/* f(14): */                                        87_178_291_200,
+/* f(15): */                                     1_307_674_368_000,
+/* f(16): */                                    20_922_789_888_000,
+/* f(17): */                                   355_687_428_096_000,
+/* f(18): */                                 6_402_373_705_728_000,
+/* f(19): */                               121_645_100_408_832_000,
+/* f(20): */                             2_432_902_008_176_640_000,
+/* f(21): */                            51_090_942_171_709_440_000,
+/* f(22): */                         1_124_000_727_777_607_680_000,
+/* f(23): */                        25_852_016_738_884_976_640_000,
+/* f(24): */                       620_448_401_733_239_439_360_000,
+/* f(25): */                    15_511_210_043_330_985_984_000_000,
+/* f(26): */                   403_291_461_126_605_635_584_000_000,
+/* f(27): */                10_888_869_450_418_352_160_768_000_000,
+/* f(28): */               304_888_344_611_713_860_501_504_000_000,
+/* f(29): */             8_841_761_993_739_701_954_543_616_000_000,
+/* f(30): */           265_252_859_812_191_058_636_308_480_000_000,
+/* f(31): */         8_222_838_654_177_922_817_725_562_880_000_000,
+/* f(32): */       263_130_836_933_693_530_167_218_012_160_000_000,
+/* f(33): */     8_683_317_618_811_886_495_518_194_401_280_000_000,
+/* f(34): */   295_232_799_039_604_140_847_618_609_643_520_000_000,
 	};
 } else {
 	_factorial_table := [21]_WORD{
-/* f(00): */                                                   1,
-/* f(01): */                                                   1,
-/* f(02): */                                                   2,
-/* f(03): */                                                   6,
-/* f(04): */                                                  24,
-/* f(05): */                                                 120,
-/* f(06): */                                                 720,
-/* f(07): */                                               5_040,
-/* f(08): */                                              40_320,
-/* f(09): */                                             362_880,
-/* f(10): */                                           3_628_800,
-/* f(11): */                                          39_916_800,
-/* f(12): */                                         479_001_600,
-/* f(13): */                                       6_227_020_800,
-/* f(14): */                                      87_178_291_200,
-/* f(15): */                                   1_307_674_368_000,
-/* f(16): */                                  20_922_789_888_000,
-/* f(17): */                                 355_687_428_096_000,
-/* f(18): */                               6_402_373_705_728_000,
-/* f(19): */                             121_645_100_408_832_000,
-/* f(20): */                           2_432_902_008_176_640_000,
+/* f(00): */                                                     1,
+/* f(01): */                                                     1,
+/* f(02): */                                                     2,
+/* f(03): */                                                     6,
+/* f(04): */                                                    24,
+/* f(05): */                                                   120,
+/* f(06): */                                                   720,
+/* f(07): */                                                 5_040,
+/* f(08): */                                                40_320,
+/* f(09): */                                               362_880,
+/* f(10): */                                             3_628_800,
+/* f(11): */                                            39_916_800,
+/* f(12): */                                           479_001_600,
+/* f(13): */                                         6_227_020_800,
+/* f(14): */                                        87_178_291_200,
+/* f(15): */                                     1_307_674_368_000,
+/* f(16): */                                    20_922_789_888_000,
+/* f(17): */                                   355_687_428_096_000,
+/* f(18): */                                 6_402_373_705_728_000,
+/* f(19): */                               121_645_100_408_832_000,
+/* f(20): */                             2_432_902_008_176_640_000,
 	};
 };
 

+ 1 - 40
core/math/big/prime.odin

@@ -18,7 +18,7 @@ package big
 int_prime_is_divisible :: proc(a: ^Int) -> (res: bool, err: Error) {
 
 	rem: DIGIT;
-	for prime in _PRIME_TABLE {
+	for prime in _private_prime_table {
 		if rem, err = mod(a, prime); err != nil { return false, err; }
 		if rem == 0 { return true, nil; }
 	}
@@ -27,42 +27,3 @@ int_prime_is_divisible :: proc(a: ^Int) -> (res: bool, err: Error) {
 	*/
 	return false, nil;
 }
-
-
-_PRIME_TABLE := []DIGIT{
-	0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
-	0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
-	0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
-	0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
-	0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
-	0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
-	0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
-	0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
-
-	0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
-	0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
-	0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
-	0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
-	0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
-	0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
-	0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
-	0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
-
-	0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
-	0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
-	0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
-	0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
-	0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
-	0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
-	0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
-	0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
-
-	0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
-	0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
-	0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
-	0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
-	0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
-	0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
-	0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
-	0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653,
-};