aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2021-07-28 21:09:52 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2021-08-11 20:59:51 +0200
commit85aa4dd670ce308eaf51b6eefd10dd62a227c998 (patch)
treee06d3bede43a0851441d0613215053a948ff3267
parent74258a170a20fd5a8fb6afe420b7d877d674c100 (diff)
big: Start test suite.
-rw-r--r--core/math/big/common.odin17
-rw-r--r--core/math/big/example.odin27
-rw-r--r--core/math/big/test.odin44
-rw-r--r--core/math/big/test.py79
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