mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-18 20:40:28 +00:00
big: Add workaround for DLL globals bug.
This commit is contained in:
@@ -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
|
||||
@@ -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`.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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:
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user