diff options
| author | dam <dam@gudinoff> | 2023-05-02 17:42:22 +0100 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2023-05-02 17:42:22 +0100 |
| commit | e39cc9078a253cf5b2adc6b0de11b54e7934bc9b (patch) | |
| tree | a4cf02d11f3bd6ae33bf686df3a0e8037cd2d85c | |
| parent | f993b20d0f4400d1b9e4c918f5cbbcb3cddbb8a0 (diff) | |
| download | task-time-tracker-e39cc9078a253cf5b2adc6b0de11b54e7934bc9b.tar.zst task-time-tracker-e39cc9078a253cf5b2adc6b0de11b54e7934bc9b.zip | |
Prototyping branchless integer saturated arithmetics.
| -rw-r--r-- | Math_Ext.jai | 172 | ||||
| -rw-r--r-- | ttt.jai | 120 |
2 files changed, 174 insertions, 118 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 @@ -474,6 +474,7 @@ update_total_times :: (db: *Database) { totals: []s64 = db.total_times; memset(totals.data, 0, NUM_WEEK_DAYS * size_of(s64)); for db.tasks { + // TODO Try to use local variables instead of total sub...something... the indexes thingy. times : []s64 = it.times; totals[0] = add_int64(totals[0], times[0]); totals[1] = add_int64(totals[1], times[1]); @@ -1163,121 +1164,6 @@ read_enter_confirmation :: inline (row: int, style: int, message: string) -> boo } main :: () { - - - add :: (value_a: s64, value_b: s64) -> s64, 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; // Signal 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; // Signal 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; - // TODO Implement signal handling and see modules/Debug.jai for examples. @@ -1293,9 +1179,7 @@ main :: () { } home_path, success_path := get_absolute_path(home_dir); // Returns temporary memory. - - - + if success_path == false { print_error("Failed to find home directory '%'.", home_dir); exit(1); |
