aboutsummaryrefslogtreecommitdiff
path: root/Math_Ext.jai
diff options
context:
space:
mode:
Diffstat (limited to 'Math_Ext.jai')
-rw-r--r--Math_Ext.jai172
1 files changed, 172 insertions, 0 deletions
diff --git a/Math_Ext.jai b/Math_Ext.jai
new file mode 100644
index 0000000..5a02756
--- /dev/null
+++ b/Math_Ext.jai
@@ -0,0 +1,172 @@
+#import "Basic";
+#import "Compiler";
+#import "Math";
+
+#run test_math_ext();
+
+test_math_ext :: () {
+
+ set_build_options_dc(.{do_output=false});
+
+ write_strings("=====================\n", "--- Test Math_Ext ---\n");
+
+ Test_Inputs :: struct(ia: $T, ib: T, ir: T, is: bool) {
+ // t: Type;
+ a := ia;
+ b := ib;
+ r := ir;
+ s := is;
+ };
+
+/*
+ tests := Test_Inputs.[
+ // .{1, 2, 3, false},
+ ];
+
+ for * tests {
+ result, saturated := add(cast(it.t)it.a, cast(it.t)it.b);
+ assert(result == it.r && saturated == it.s, "Failed: % %\n", result, saturated);
+ }
+*/
+
+
+ t1a := S64_MAX;
+ t1b := 0;
+ t1v, t1r := add(t1a, t1b);
+ assert(t1v == S64_MAX && t1r == false, "Failed: % %\n", t1v, t1r);
+ write_string("t1: OK\n");
+
+ // t2a := S64_MAX;
+ // t2b := 1;
+ // t2v, t2r := add(t2a, t2b);
+ // assert(t2v == S64_MAX && t2r == true, "Failed: % %\n", t2v, t2r);
+}
+
+
+add_int64 :: (x :s64, y: s64) -> s64 #dump { // TODO Comparing implementations.
+ return
+ ifx (y > 0 && x > S64_MAX - y) then S64_MAX else
+ ifx (y < 0 && x < S64_MIN - y) then S64_MIN else
+ x + y;
+}
+
+sub_int64 :: (x :s64, y :s64) -> s64 {
+ return
+ ifx (y < 0 && x > S64_MAX + y) then S64_MAX else
+ ifx (y > 0 && x < S64_MIN + y) then S64_MIN else
+ x - y;
+}
+
+add :: (value_a: s64, value_b: s64) -> result: s64, saturated: bool #dump { // TODO Comparing implementaitons using dump
+ result: s64 = ---;
+ flag: bool = ---;
+ #asm {
+ mov d: gpr === d, 9223372036854775807;
+ mov a: gpr === a, value_a;
+ mov b: gpr === b, value_b;
+ add a, b;
+ seto flag; // Flag overflow.
+ mov result, a;
+ mov a, value_a;
+ shr a, 63;
+ add a, d;
+ mov c: gpr, value_a;
+ xor c, b;
+ xor b, result;
+ not b;
+ or c, b;
+ test c, c;
+ cmovns result, a;
+ }
+ return result, flag;
+}
+
+/*
+// value_a: s64 = 2;
+// value_b: s64 = S64_MAX-1;
+value_a: s64 = -2;
+value_b: s64 = S64_MIN+1;
+print(">%\n", S64_MAX);
+argx := get_command_line_arguments();
+if argx.count > 1
+ value_a = parse_int(*argx[1]);
+if argx.count > 2
+ value_b = parse_int(*argx[2]);
+
+result: s64 = ---;
+flags: s64;// = ---;
+#asm LAHF_SAHF { // TODO Remove LAHF_SAHF it not required.
+
+ // Code from https://locklessinc.com/articles/sat_arithmetic/
+
+
+ // value_a === b;
+ // value_b === c;
+ // add value_a, value_b;
+ // mov result, value_a;
+
+ // Version 1
+ // mov b: gpr === b, value_a;
+ // mov c: gpr === c, value_b;
+ // add b, c;
+ // mov result, b;
+ // seto flags;
+ // cmovns b, c;
+
+// s64b sat_adds64b(s64b x, s64b y)
+// {
+// u64b ux = x;
+// u64b uy = y;
+// u64b res = ux + uy;
+//
+// ux = (ux >> 63) + LONG_MAX;
+//
+// /* Force compiler to use cmovns instruction */
+// if ((s64b) ((ux ^ uy) | ~(uy ^ res)) >= 0)
+// {
+// res = ux;
+// }
+//
+// return res;
+// }
+ // Version 2 - WORKS
+ mov d: gpr === d, 9223372036854775807;
+ mov a: gpr === a, value_a;
+ mov b: gpr === b, value_b;
+ add a, b;
+ seto flags; // Flag overflow.
+ mov result, a;
+ mov a, value_a;
+ shr a, 63;
+ add a, d;
+ mov c: gpr, value_a;
+ xor c, b;
+ xor b, result;
+ not b;
+ or c, b;
+ test c, c;
+ cmovns result, a;
+
+// s64b sat_subs64b(s64b x, s64b y)
+// {
+// u64b ux = x;
+// u64b uy = y;
+// u64b res = ux - uy;
+//
+// ux = (ux >> 63) + LONG_MAX;
+//
+// // Force compiler to use cmovns instruction
+// if ((s64b)((ux ^ uy) & (ux ^ res)) < 0)
+// {
+// res = ux;
+// }
+//
+// return res;
+// }
+ // TODO Use https://godbolt.org/ to help
+
+}
+print("% + % = %\n", value_a, value_b, result);
+print("flag: %\n", flags);
+return;
+*/ \ No newline at end of file