big: Add workaround for DLL globals bug.

This commit is contained in:
Jeroen van Rijn
2021-08-14 13:51:17 +02:00
parent dc02566a84
commit 0db86a0638
6 changed files with 46 additions and 23 deletions

View File

@@ -1,8 +1,8 @@
@echo off
odin run . -vet
:odin run . -vet
: -o:size
:odin build . -build-mode:shared -show-timings -o:minimal -no-bounds-check && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:size -no-bounds-check && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:size && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:speed -no-bounds-check && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:speed && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:minimal -no-bounds-check -define:MATH_BIG_EXE=false && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:size -no-bounds-check -define:MATH_BIG_EXE=false && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:size -define:MATH_BIG_EXE=false && python test.py -fast-tests
odin build . -build-mode:shared -show-timings -o:speed -no-bounds-check -define:MATH_BIG_EXE=false && python test.py -fast-tests
:odin build . -build-mode:shared -show-timings -o:speed -define:MATH_BIG_EXE=false && python test.py -fast-tests

View File

@@ -27,10 +27,22 @@ import "core:intrinsics"
`initialize_constants` also replaces the other `_DEFAULT_*` cutoffs with custom compile-time values if so `#config`ured.
*/
MUL_KARATSUBA_CUTOFF := initialize_constants();
SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF;
MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF;
SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF;
/*
There is a bug with DLL globals. They don't get set.
To allow tests to run we add `-define:MATH_BIG_EXE=false` to hardcode the cutoffs for now.
*/
when #config(MATH_BIG_EXE, true) {
MUL_KARATSUBA_CUTOFF := initialize_constants();
SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF;
MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF;
SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF;
} else {
MUL_KARATSUBA_CUTOFF := _DEFAULT_MUL_KARATSUBA_CUTOFF;
SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF;
MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF;
SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF;
}
/*
These defaults were tuned on an AMD A8-6600K (64-bit) using libTomMath's `make tune`.

View File

@@ -206,16 +206,16 @@ demo :: proc() {
a, b, c, d, e, f := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
defer destroy(a, b, c, d, e, f);
power_of_two(a, 14_500);
print("a: ", a);
atoi(a, "12980742146337069150589594264770969721", 10);
print("a: ", a, 10, true, true, true);
atoi(b, "4611686018427387904", 10);
print("b: ", b, 10, true, true, true);
power_of_two(b, 10_500);
if err := internal_int_divmod(c, d, a, b); err != nil {
if err := internal_divmod(c, d, a, b); err != nil {
fmt.printf("Error: %v\n", err);
}
print("c: ", c);
print("d: ", d);
print("c: ", d);
}
main :: proc() {

View File

@@ -36,6 +36,8 @@ import "core:mem"
import "core:intrinsics"
import rnd "core:math/rand"
import "core:fmt"
/*
Low-level addition, unsigned. Handbook of Applied Cryptography, algorithm 14.7.
@@ -714,7 +716,6 @@ internal_sqr :: proc (dest, src: ^Int, allocator := context.allocator) -> (res:
*/
internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator;
if denominator.used == 0 { return .Division_by_Zero; }
/*
If numerator < denominator then quotient = 0, remainder = numerator.
@@ -729,7 +730,8 @@ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, a
return nil;
}
if (denominator.used > 2 * MUL_KARATSUBA_CUTOFF) && (denominator.used <= (numerator.used/3) * 2) {
if (denominator.used > 2 * MUL_KARATSUBA_CUTOFF) && (denominator.used <= (numerator.used / 3) * 2) {
assert(denominator.used >= 160 && numerator.used >= 240, "MUL_KARATSUBA_CUTOFF global not properly set.");
err = _private_int_div_recursive(quotient, remainder, numerator, denominator);
// err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator);
} else {

View File

@@ -26,7 +26,9 @@ PyRes :: struct {
@export test_initialize_constants :: proc "c" () -> (res: u64) {
context = runtime.default_context();
return u64(initialize_constants());
res = u64(initialize_constants());
//assert(MUL_KARATSUBA_CUTOFF >= 40);
return res;
}
@export test_error_string :: proc "c" (err: Error) -> (res: cstring) {

View File

@@ -66,6 +66,8 @@ timed_or_fast.add_argument(
args = parser.parse_args()
EXIT_ON_FAIL = args.exit_on_fail
#
# How many iterations of each random test do we want to run?
#
@@ -153,7 +155,7 @@ class Res(Structure):
_fields_ = [("res", c_char_p), ("err", c_uint64)]
initialize_constants = load(l.test_initialize_constants, [], c_uint64)
initialize_constants()
print("initialize_constants: ", initialize_constants())
error_string = load(l.test_error_string, [c_byte], c_char_p)
@@ -211,7 +213,7 @@ def test(test_name: "", res: Res, param=[], expected_error = Error.Okay, expecte
print(error, flush=True)
passed = False
if args.exit_on_fail and not passed: exit(res.err)
if EXIT_ON_FAIL and not passed: exit(res.err)
return passed
@@ -257,7 +259,7 @@ def test_sqr(a = 0, b = 0, expected_error = Error.Okay):
try:
res = sqr(*args)
except OSError as e:
print("{} while trying to square {} x {}.".format(e, a))
print("{} while trying to square {}.".format(e, a))
if EXIT_ON_FAIL: exit(3)
return False
@@ -268,7 +270,12 @@ def test_sqr(a = 0, b = 0, expected_error = Error.Okay):
def test_div(a = 0, b = 0, expected_error = Error.Okay):
args = [arg_to_odin(a), arg_to_odin(b)]
res = div(*args)
try:
res = div(*args)
except OSError as e:
print("{} while trying divide to {} / {}.".format(e, a, b))
if EXIT_ON_FAIL: exit(3)
return False
expected_result = None
if expected_error == Error.Okay:
#