diff options
Diffstat (limited to 'Math_Ext.jai')
| -rw-r--r-- | Math_Ext.jai | 67 |
1 files changed, 34 insertions, 33 deletions
diff --git a/Math_Ext.jai b/Math_Ext.jai index 5aafbd5..c3111d8 100644 --- a/Math_Ext.jai +++ b/Math_Ext.jai @@ -159,7 +159,8 @@ test_math_ext :: () { set_build_options_dc(.{do_output=false}); if errors > 0 print("# Found % %!\n", errors, ifx errors == 1 then "error" else "errors"); else print(" No errors found.\n"); -/* PERFORMANCE TEST +/* + // Performance test. #import "Random"; best_generic: float; best_asm: float; @@ -175,7 +176,7 @@ test_math_ext :: () { set_build_options_dc(.{do_output=false}); performance_test :: () -> sum_size: s64, time_generic: Apollo_Time, time_asm: Apollo_Time { - SUM_SIZE := 2000000; + SUM_SIZE := 200;//0000; numbers: [..] s64; array_reserve(*numbers, SUM_SIZE); @@ -185,7 +186,7 @@ test_math_ext :: () { set_build_options_dc(.{do_output=false}); sum := 0; start := current_time_monotonic(); - for numbers sum = add_bad(sum, it); + for numbers sum = add(sum, it, true); time := current_time_monotonic() - start; sum_asm := 0; @@ -276,7 +277,7 @@ add :: (x: $Tx, y: $Ty) -> result: $Tr, saturated: bool #modify { #insert INTEGE mov limit: gpr, MAX; mov sign: gpr, x; shr.SIZE sign, BITS; - add.SIZE limit, sign; + add.SIZE limit, sign; // If sign is 1, then limit will overflow from MAX to MIN. mov result, x; add.SIZE result, y; @@ -297,11 +298,11 @@ add :: (x: $Tx, y: $Ty) -> result: $Tr, saturated: bool #modify { #insert INTEGE U_ADD_ASM :: #string DONE #asm { - mov limit: gpr, MAX; + mov max: gpr, MAX; mov result, x; add.SIZE result, y; setc saturated; - cmovc result, limit; + cmovc result, max; } DONE @@ -320,7 +321,7 @@ add :: (x: $Tx, y: $Ty) -> result: $Tr, saturated: bool #modify { #insert INTEGE } } -sub :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } //#dump +sub :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } // #dump { #if CPU != .X64 { @@ -355,7 +356,7 @@ sub :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER mov limit: gpr, MAX; mov sign: gpr, x; shr.SIZE sign, BITS; - add.SIZE limit, sign; + add.SIZE limit, sign; // If sign is 1, then limit will overflow from MAX to MIN. mov result, x; sub.SIZE result, y; @@ -400,7 +401,7 @@ sub :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER } -mul :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } //#dump +mul :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } // #dump { #if CPU != .X64 { @@ -441,7 +442,7 @@ mul :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER mov sign: gpr, x; xor sign, y; shr.SIZE sign, BITS; - add.SIZE limit, sign; + add.SIZE limit, sign; // If sign is 1, then limit will overflow from MAX to MIN. mov result, x; imul.SIZE result, y; @@ -467,7 +468,7 @@ mul :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER mov result, x; mul.SIZE r_d:, result, y; setc saturated; - sbb max:, max; // SBB performs: dst = dst - (src + CF). Thus, max = 0xFF...FF if CF is 1, otherwise 0x00...00. TODO Improve comment. + sbb max:, max; // If CF: max = -1 (all bits set); otherwise: max = 0. or result, max; } DONE @@ -479,7 +480,7 @@ mul :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER mov result, x; mul.SIZE result, y; setc saturated; - sbb max:, max; // SBB performs: dst = dst - (src + CF). Thus, max = 0xFF...FF if CF is 1, otherwise 0x00...00. TODO Improve comment. + sbb max:, max; // If CF: max = -1 (all bits set); otherwise: max = 0. or result, max; } DONE @@ -499,7 +500,7 @@ mul :: (x: $Tx, y: $Ty) -> result: $Tr, overflow: bool #modify { #insert INTEGER } } -div :: (x: $Tx, y: $Ty) -> result: $Tr, remainder: Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } //#dump +div :: (x: $Tx, y: $Ty) -> result: $Tr, remainder: Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } // #dump { #if CPU != .X64 { @@ -532,25 +533,23 @@ div :: (x: $Tx, y: $Ty) -> result: $Tr, remainder: Tr, saturated: bool #modify { result === a; remainder === d; - // Calculate dividend limit (MIN+1) for the div(MIN/-1) problem. - mov limit: gpr, MIN; - inc limit; - // Detect div(MIN/-1) and flag it on ZF. mov xT: gpr, MIN; mov xV: gpr, x; xor.SIZE xT, xV; mov yT: gpr, y; xor.SIZE yT, -1; - // - or.SIZE xT, yT; // Affect ZF. + or.SIZE xT, yT; + mov limit: gpr, LIMIT; mov result, x; - cmovz result, limit; // Apply dividend limit if ZF. + cmovz result, limit; // If ZF: limit dividend to MIN-1. setz saturated; cqo remainder, result; // Prepare dividend high bits. idiv.SIZE remainder, result, y; - sub.SIZE remainder, saturated; // If saturated: remainder = 0 - 1; otherwise: remainder = x - 0. + + // If saturated: remainder = 0 - 1; otherwise: remainder = x - 0. + sub.SIZE remainder, saturated; } DONE @@ -559,36 +558,36 @@ div :: (x: $Tx, y: $Ty) -> result: $Tr, remainder: Tr, saturated: bool #modify { result === a; remainder === d; - // Calculate dividend limit (MIN+1) for the div(MIN/-1) problem. - mov limit: gpr, MIN; - inc limit; - // Detect div(MIN/-1) and flag it on ZF. mov t_x: gpr, x; mov t_y: gpr, y; xor.SIZE t_x, MIN; xor.SIZE t_y, -1; - // - or.SIZE t_x, t_y; // Affect ZF. + or.SIZE t_x, t_y; + mov limit: gpr, LIMIT; mov result, x; - cmovz result, limit; // Apply dividend limit if ZF. + cmovz result, limit; // If ZF: limit dividend to MIN-1. setz saturated; idiv.SIZE result, y; + + // Extract remainder from result's high bits. mov remainder, result; sar remainder, 8; - sub.SIZE remainder, saturated; // If saturated: remainder = 0 - 1; otherwise: remainder = x - 0. + + // If saturated: remainder = 0 - 1; otherwise: remainder = x - 0. + sub.SIZE remainder, saturated; } DONE #if Tr == s8 - #insert #run replace(replace(S_DIV_ASM_8BITS, ".SIZE", ".b"), "MIN", "-128"); + #insert #run replace(replace(replace(S_DIV_ASM_8BITS, ".SIZE", ".b"), "MIN", "-128"), "LIMIT", "-127"); #if Tr == s16 - #insert #run replace(replace(S_DIV_ASM, ".SIZE", ".w"), "MIN", "-32768"); + #insert #run replace(replace(replace(S_DIV_ASM, ".SIZE", ".w"), "MIN", "-32768"), "LIMIT", "-32767"); #if Tr == s32 - #insert #run replace(replace(S_DIV_ASM, ".SIZE", ".d"), "MIN", "-2147483648"); + #insert #run replace(replace(replace(S_DIV_ASM, ".SIZE", ".d"), "MIN", "-2147483648"), "LIMIT", "-2147483647"); #if Tr == s64 - #insert #run replace(replace(S_DIV_ASM, ".SIZE", ".q"), "MIN", "-9223372036854775808"); + #insert #run replace(replace(replace(S_DIV_ASM, ".SIZE", ".q"), "MIN", "-9223372036854775808"), "LIMIT", "-9223372036854775807"); U_DIV_ASM :: #string DONE @@ -611,6 +610,8 @@ div :: (x: $Tx, y: $Ty) -> result: $Tr, remainder: Tr, saturated: bool #modify { mov saturated, 0; mov result, x; div.SIZE result, y; + + // Extract remainder from result's high bits. mov remainder, result; sar remainder, 8; } |
