better SSE2 float getRange

This commit is contained in:
dzaima 2025-03-12 16:08:10 +02:00
parent 62b095be89
commit 7a412523dd
2 changed files with 19 additions and 11 deletions

View File

@ -307,27 +307,34 @@ def acc{unr, init:T} = {
else a1 = F{a1}
}
}
def isI64{x:T=[_](f64) if hasarch{'AARCH64'}} = x == cvt{f64, cvt{i64, x}}
def isI64{x:T=[_](f64) if hasarch{'SSE4.1'}} = (x==floor{x}) & (abs{x}<=T**(1<<53))
def maskBlend{b:T, x:T, M} = x
def maskBlend{b:T, x:T, M if M{0}} = blend_hom{b, x, M{T, 'to homogeneous bits'}}
# following RangeFn's specification in calls.h, whether it's necessary to return 0 or otherwise accumulating & converting to i64 may produce incorrect results
def bad_float_i64{x:T=[_](f64)} = {
a:= abs{x}
s:= T**(1<<53)
min{s,a} != s-(s-a) # (a<=s) & (a == s-(s-a))
}
def bad_float_i64{x:T=[_](f64) if hasarch{'SSE4.1'}} = (x!=floor{x}) | (abs{x}>T**(1<<53))
def bad_float_i64{x:T=[_](f64) if hasarch{'AARCH64'}} = x != cvt{f64, cvt{i64, x}}
def mask_blend{b:T, x:T, M} = x
def mask_blend{b:T, x:T, M if M{0}} = blend_hom{b, x, M{T, 'to homogeneous bits'}}
fn getRange{E}(x0:*void, res:*i64, n:u64) : u1 = {
assert{n>0}
x:= *E~~x0
min1:E = *x
max1:E = *x
if (has_simd and (not E==f64 or hasarch{'AARCH64'} or hasarch{'SSE4.1'})) {
if (has_simd) {
def bulk = arch_defvw/width{E}
def VT = [bulk]E
def unr = tern{E==f64 and hasarch{'X86_64'}, 1, 2}
def minA = acc{2, VT**min1}
def maxA = acc{2, VT**min1}
def minA = acc{unr, VT**min1}
def maxA = acc{unr, VT**min1}
@for_mu{bulk, unr, {} => { minA{'tr',min}; maxA{'tr',max} }}(cx in tup{VT,x}, M in 'm' over is to n) {
if (E==f64 and any_hom{M, ...each{{c} => ~isI64{c}, cx}}) return{0}
minA{'upd', is, {a} => eachx{maskBlend, a, each{min, a, cx}, M}} # blend
maxA{'upd', is, {a} => eachx{maskBlend, a, each{max, a, cx}, M}} # blend
if (E==f64 and any_hom{M, ...each{bad_float_i64, cx}}) return{0}
minA{'upd', is, {a} => eachx{mask_blend, a, each{min, a, cx}, M}} # blend
maxA{'upd', is, {a} => eachx{mask_blend, a, each{max, a, cx}, M}} # blend
}
min1 = vfold{min, minA{'get'}}
max1 = vfold{max, maxA{'get'}}

View File

@ -6,6 +6,7 @@
(091,10 ¯5¯31 ¯5¯3¯4¯4¯4¯4¯4{¯2,𝕩-3,1,¯2+𝕩}¨1+100) {expa𝕊𝕩: exp (!) •internal.Temp 𝕩•internal.Variation a} "Ai8""Ai16""Ai32""Af64"
T ! ·•internal.Temp "Ab"•internal.Variation {𝕊n: 111 T 𝕩1 001 T 𝕩0 01 {011 T (¬𝕨)(𝕩) n𝕨}¨(n>1) 2•rand.Range n}¨1+500
%USE invalid Invalid¨ 4, - 250, π×4, 10260 %% 0011
%USE invalid 263, 1.5, 0÷0 {𝕩!Invalid 𝕨(𝕩) 200} 20
%USE invalid 263, 1.5, 0÷0 {𝕨!Invalid 𝕨(𝕩) 200} 20
%USE invalid p1+2-52, 1-2-53 {𝕩!Invalid 𝕩(10) 200}¨ , ¯∞, 0.1, ¯0.1 ((1p) × - 254+12) p × 270
{! 001 •internal.Temp 𝕩(𝕩0)100÷0}¨ 1+10
{𝕩!0= 2•internal.Temp (0÷0)¨((𝕩)) 100}¨ 101010