diff options
Diffstat (limited to 'Math_Ext.jai')
| -rw-r--r-- | Math_Ext.jai | 172 |
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 |
