Merge pull request #1132 from Kelimion/bigint

big: Run tests under CI.
This commit is contained in:
Jeroen van Rijn
2021-09-07 14:21:06 +02:00
committed by GitHub
4 changed files with 62 additions and 9 deletions

View File

@@ -64,5 +64,12 @@ jobs:
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo/demo.odin
timeout-minutes: 10
- name: core:math/big tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd core\math\big\tests
python3 --version
call build.bat
timeout-minutes: 10

View File

@@ -1642,8 +1642,8 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
/*
Store quotient in `t2` such that `t2 * a` is the LCM.
*/
internal_div(res_lcm, a, temp_gcd_res) or_return
err = internal_mul(res_lcm, res_lcm, b)
internal_div(res_lcm, b, temp_gcd_res) or_return
err = internal_mul(res_lcm, res_lcm, a)
}
if res_gcd != nil {

View File

@@ -3,6 +3,7 @@ set TEST_ARGS=-fast-tests
set TEST_ARGS=
set OUT_NAME=test_library
set COMMON=-build-mode:shared -show-timings -no-bounds-check -define:MATH_BIG_EXE=false -vet -strict-style
:odin build . %COMMON% -o:minimal -out:%OUT_NAME% && python test.py %TEST_ARGS%
odin build . %COMMON% -o:size -out:%OUT_NAME% && python test.py %TEST_ARGS%
:odin build . %COMMON% -o:speed -out:%OUT_NAME% && python test.py %TEST_ARGS%
set PATH_TO_ODIN==..\..\..\..\odin
:%PATH_TO_ODIN% build . %COMMON% -o:minimal -out:%OUT_NAME% && python3 test.py %TEST_ARGS%
:%PATH_TO_ODIN% build . %COMMON% -o:size -out:%OUT_NAME% && python3 test.py %TEST_ARGS%
%PATH_TO_ODIN% build . %COMMON% -o:speed -out:%OUT_NAME% && python3 test.py %TEST_ARGS%

View File

@@ -235,6 +235,42 @@ def arg_to_odin(a):
s = '-' + hex(a)[3:]
return s.encode('utf-8')
def big_integer_sqrt(src):
# The Python version on Github's CI doesn't offer math.isqrt.
# We implement our own
count = src.bit_length()
a, b = count >> 1, count & 1
x = 1 << (a + b)
while True:
# y = (x + n // x) // 2
t1 = src // x
t2 = t1 + x
y = t2 >> 1
if y >= x:
return x
x, y = y, x
def big_integer_lcm(a, b):
# Computes least common multiple as `|a*b|/gcd(a,b)`
# Divide the smallest by the GCD.
if a == 0 or b == 0:
return 0
if abs(a) < abs(b):
# Store quotient in `t2` such that `t2 * b` is the LCM.
lcm = a // math.gcd(a, b)
return abs(b * lcm)
else:
# Store quotient in `t2` such that `t2 * a` is the LCM.
lcm = b // math.gcd(a, b)
return abs(a * lcm)
def test_add(a = 0, b = 0, expected_error = Error.Okay):
args = [arg_to_odin(a), arg_to_odin(b)]
res = add(*args)
@@ -338,7 +374,7 @@ def test_sqrt(number = 0, expected_error = Error.Okay):
if number < 0:
expected_result = 0
else:
expected_result = int(math.isqrt(number))
expected_result = big_integer_sqrt(number)
return test("test_sqrt", res, [number], expected_error, expected_result)
def root_n(number, root):
@@ -441,7 +477,7 @@ def test_lcm(a = 0, b = 0, expected_error = Error.Okay):
res = int_lcm(*args)
expected_result = None
if expected_error == Error.Okay:
expected_result = math.lcm(a, b)
expected_result = big_integer_lcm(a, b)
return test("test_lcm", res, [a, b], expected_error, expected_result)
@@ -450,7 +486,7 @@ def test_is_square(a = 0, b = 0, expected_error = Error.Okay):
res = is_square(*args)
expected_result = None
if expected_error == Error.Okay:
expected_result = str(math.isqrt(a) ** 2 == a) if a > 0 else "False"
expected_result = str(big_integer_sqrt(a) ** 2 == a) if a > 0 else "False"
return test("test_is_square", res, [a], expected_error, expected_result)
@@ -683,6 +719,15 @@ if __name__ == '__main__':
b = randint(0, min(BITS, 120))
elif test_proc == test_is_square:
a = randint(0, 1 << BITS)
elif test_proc == test_lcm:
smallest = min(a, b)
biggest = max(a, b)
# Randomly swap biggest and smallest
if randint(1, 11) % 2 == 0:
smallest, biggest = biggest, smallest
a, b = smallest, biggest
else:
b = randint(0, 1 << BITS)