diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-07-28 21:09:52 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-08-11 20:59:51 +0200 |
| commit | 85aa4dd670ce308eaf51b6eefd10dd62a227c998 (patch) | |
| tree | e06d3bede43a0851441d0613215053a948ff3267 | |
| parent | 74258a170a20fd5a8fb6afe420b7d877d674c100 (diff) | |
big: Start test suite.
| -rw-r--r-- | core/math/big/common.odin | 17 | ||||
| -rw-r--r-- | core/math/big/example.odin | 27 | ||||
| -rw-r--r-- | core/math/big/test.odin | 44 | ||||
| -rw-r--r-- | core/math/big/test.py | 79 |
4 files changed, 146 insertions, 21 deletions
diff --git a/core/math/big/common.odin b/core/math/big/common.odin index dd17a678f..59e76a9aa 100644 --- a/core/math/big/common.odin +++ b/core/math/big/common.odin @@ -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 */ diff --git a/core/math/big/example.odin b/core/math/big/example.odin index f6b7236c6..6dad8ebd7 100644 --- a/core/math/big/example.odin +++ b/core/math/big/example.odin @@ -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() { diff --git a/core/math/big/test.odin b/core/math/big/test.odin new file mode 100644 index 000000000..f1bdcff99 --- /dev/null +++ b/core/math/big/test.odin @@ -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}; +}
\ No newline at end of file diff --git a/core/math/big/test.py b/core/math/big/test.py new file mode 100644 index 000000000..c0e2c2173 --- /dev/null +++ b/core/math/big/test.py @@ -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)
\ No newline at end of file |