mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-17 16:38:22 +00:00
big: Start test suite.
This commit is contained in:
@@ -66,6 +66,23 @@ Error :: enum byte {
|
||||
Unimplemented = 127,
|
||||
};
|
||||
|
||||
Error_String :: #partial [Error]string{
|
||||
.None = "None",
|
||||
.Out_Of_Memory = "Out of memory",
|
||||
.Invalid_Pointer = "Invalid pointer",
|
||||
.Invalid_Argument = "Invalid argument",
|
||||
|
||||
.Unknown_Error = "Unknown error",
|
||||
.Max_Iterations_Reached = "Max iterations reached",
|
||||
.Buffer_Overflow = "Buffer overflow",
|
||||
.Integer_Overflow = "Integer overflow",
|
||||
|
||||
.Division_by_Zero = "Division by zero",
|
||||
.Math_Domain_Error = "Math domain error",
|
||||
|
||||
.Unimplemented = "Unimplemented",
|
||||
};
|
||||
|
||||
Primality_Flag :: enum u8 {
|
||||
Blum_Blum_Shub = 0, /* BBS style prime */
|
||||
Safe = 1, /* Safe prime (p-1)/2 == prime */
|
||||
|
||||
@@ -13,7 +13,7 @@ package big
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:time"
|
||||
import rnd "core:math/rand"
|
||||
// import rnd "core:math/rand"
|
||||
|
||||
print_configation :: proc() {
|
||||
fmt.printf(
|
||||
@@ -66,28 +66,13 @@ print :: proc(name: string, a: ^Int, base := i8(10)) {
|
||||
}
|
||||
|
||||
demo :: proc() {
|
||||
err: Error;
|
||||
as: string;
|
||||
// err: Error;
|
||||
|
||||
r := &rnd.Rand{};
|
||||
rnd.init(r, 12345);
|
||||
// r := &rnd.Rand{};
|
||||
// rnd.init(r, 12345);
|
||||
|
||||
destination, source, quotient, remainder, numerator, denominator := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
|
||||
defer destroy(destination, source, quotient, remainder, numerator, denominator);
|
||||
|
||||
err = rand(destination, 120, r);
|
||||
for _ in 0 ..< 10_000 {
|
||||
if err != .None {
|
||||
fmt.printf("set error: %v\n", err);
|
||||
} else {
|
||||
s := time.tick_now();
|
||||
as, err = itoa(destination, 16);
|
||||
e := time.tick_since(s);
|
||||
Timings[.itoa].t += e; Timings[.itoa].c += 1;
|
||||
//assert(as == "ADCC737B67B0FCD7F189074CBE088B718141A383F9CF09B4D3824A09A3AEBAC155B810C29D62385F8F85616794C25393A757CEDEEBE3B0FE24573894DF7842A76F543D64A78FFD24D325CE044E9A0F69DE00CFFCC41427170096BC6D3537C856CD930A3794F03DB558CD5DB6A65971E618C5D0DBAE1E7AF52DDB8F5F84CD5BFC0B2EEEDBFB70E6B38677A01B8EF75CF434CA68677495", as);
|
||||
delete(as);
|
||||
}
|
||||
}
|
||||
// destination, source, quotient, remainder, numerator, denominator := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
|
||||
// defer destroy(destination, source, quotient, remainder, numerator, denominator);
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
|
||||
44
core/math/big/test.odin
Normal file
44
core/math/big/test.odin
Normal file
@@ -0,0 +1,44 @@
|
||||
//+ignore
|
||||
package big
|
||||
|
||||
/*
|
||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||
Made available under Odin's BSD-2 license.
|
||||
|
||||
An arbitrary precision mathematics implementation in Odin.
|
||||
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
||||
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
||||
|
||||
This file contains basic arithmetic operations like `add`, `sub`, `mul`, `div`, ...
|
||||
*/
|
||||
|
||||
import "core:runtime"
|
||||
import "core:strings"
|
||||
|
||||
PyRes :: struct {
|
||||
res: cstring,
|
||||
err: Error,
|
||||
}
|
||||
|
||||
@export test_error_string :: proc "c" (err: Error) -> (res: cstring) {
|
||||
context = runtime.default_context();
|
||||
es := Error_String;
|
||||
return strings.clone_to_cstring(es[err], context.temp_allocator);
|
||||
}
|
||||
|
||||
@export test_add_two :: proc "c" (a, b: cstring, radix := int(10)) -> (res: PyRes) {
|
||||
context = runtime.default_context();
|
||||
err: Error;
|
||||
|
||||
aa, bb, sum := &Int{}, &Int{}, &Int{};
|
||||
defer destroy(aa, bb, sum);
|
||||
|
||||
if err = atoi(aa, string(a), i8(radix)); err != .None { return PyRes{res=":add_two:atoi(a):", err=err}; }
|
||||
if err = atoi(bb, string(b), i8(radix)); err != .None { return PyRes{res=":add_two:atoi(b):", err=err}; }
|
||||
if err = add(sum, aa, bb); err != .None { return PyRes{res=":add_two:add(sum,a,b):", err=err}; }
|
||||
|
||||
r: cstring;
|
||||
r, err = int_itoa_cstring(sum, i8(radix), context.temp_allocator);
|
||||
if err != .None { return PyRes{res=":add_two:itoa(sum):", err=err}; }
|
||||
return PyRes{res = r, err = .None};
|
||||
}
|
||||
79
core/math/big/test.py
Normal file
79
core/math/big/test.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from math import *
|
||||
from ctypes import *
|
||||
import os
|
||||
|
||||
#
|
||||
# Where is the DLL? If missing, build using: `odin build . -build-mode:dll`
|
||||
#
|
||||
LIB_PATH = os.getcwd() + os.sep + "big.dll"
|
||||
|
||||
#
|
||||
# Result values will be passed in a struct { res: cstring, err: Error }
|
||||
#
|
||||
class Res(Structure):
|
||||
_fields_ = [("res", c_char_p), ("err", c_byte)]
|
||||
|
||||
#
|
||||
# Error enum values
|
||||
#
|
||||
E_None = 0
|
||||
E_Out_Of_Memory = 1
|
||||
E_Invalid_Pointer = 2
|
||||
E_Invalid_Argument = 3
|
||||
E_Unknown_Error = 4
|
||||
E_Max_Iterations_Reached = 5
|
||||
E_Buffer_Overflow = 6
|
||||
E_Integer_Overflow = 7
|
||||
E_Division_by_Zero = 8
|
||||
E_Math_Domain_Error = 9
|
||||
E_Unimplemented = 127
|
||||
|
||||
#
|
||||
# Set up exported procedures
|
||||
#
|
||||
|
||||
try:
|
||||
l = cdll.LoadLibrary(LIB_PATH)
|
||||
except:
|
||||
print("Couldn't find or load " + LIB_PATH + ".")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
l.test_add_two.argtypes = [c_char_p, c_char_p, c_longlong]
|
||||
l.test_add_two.restype = Res
|
||||
except:
|
||||
print("Couldn't find exported function 'test_add_two'")
|
||||
exit(2)
|
||||
|
||||
add_two = l.test_add_two
|
||||
|
||||
try:
|
||||
l.test_error_string.argtypes = [c_byte]
|
||||
l.test_error_string.restype = c_char_p
|
||||
except:
|
||||
print("Couldn't find exported function 'test_error_string'")
|
||||
exit(2)
|
||||
|
||||
def error(res: Res, param=[]):
|
||||
if res.err != E_None:
|
||||
error_type = l.test_error_string(res.err).decode('utf-8')
|
||||
error_loc = res.res.decode('utf-8')
|
||||
|
||||
error_string = "'{}' error in '{}'".format(error_type, error_loc)
|
||||
if len(param):
|
||||
error_string += " with params {}".format(param)
|
||||
|
||||
print(error_string, flush=True)
|
||||
os._exit(res.err)
|
||||
|
||||
|
||||
def test_add_two(a = 0, b = 0, radix = 10):
|
||||
res = add_two(str(a).encode('utf-8'), str(b).encode('utf-8'), radix)
|
||||
error(res, [str(a), str(b), radix])
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("---- core:math/big tests ----")
|
||||
print()
|
||||
|
||||
test_add_two(1234, 5432, 10)
|
||||
test_add_two(1234, 5432, 110)
|
||||
Reference in New Issue
Block a user