aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Math_Ext.jai67
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;
}