Browse Source

Add Endian versions of math routines.

Jeroen van Rijn 4 years ago
parent
commit
55fc2c00c0
1 changed files with 191 additions and 28 deletions
  1. 191 28
      core/math/math.odin

+ 191 - 28
core/math/math.odin

@@ -96,36 +96,170 @@ foreign _ {
 	ldexp_f64 :: proc(val: f64, exp: i32) -> f64 ---;
 }
 
-sqrt      :: proc{sqrt_f16,    sqrt_f32,    sqrt_f64};
-sin       :: proc{sin_f16,     sin_f32,     sin_f64};
-cos       :: proc{cos_f16,     cos_f32,     cos_f64};
-pow       :: proc{pow_f16,     pow_f32,     pow_f64};
-fmuladd   :: proc{fmuladd_f16, fmuladd_f32, fmuladd_f64};
-ln        :: proc{ln_f16,      ln_f32,      ln_f64};
-exp       :: proc{exp_f16,     exp_f32,     exp_f64};
+sqrt_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(sqrt_f16(f16(x))); }
+sqrt_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(sqrt_f16(f16(x))); }
+sqrt_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(sqrt_f32(f32(x))); }
+sqrt_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(sqrt_f32(f32(x))); }
+sqrt_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(sqrt_f64(f64(x))); }
+sqrt_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(sqrt_f64(f64(x))); }
+sqrt       :: proc{
+	sqrt_f16, sqrt_f16le, sqrt_f16be,
+	sqrt_f32, sqrt_f32le, sqrt_f32be,
+	sqrt_f64, sqrt_f64le, sqrt_f64be,
+};
 
-ldexp :: proc{ldexp_f16, ldexp_f32, ldexp_f64};
+sin_f16le :: proc(θ: f16le) -> f16le { return #force_inline f16le(sin_f16(f16(θ))); }
+sin_f16be :: proc(θ: f16be) -> f16be { return #force_inline f16be(sin_f16(f16(θ))); }
+sin_f32le :: proc(θ: f32le) -> f32le { return #force_inline f32le(sin_f32(f32(θ))); }
+sin_f32be :: proc(θ: f32be) -> f32be { return #force_inline f32be(sin_f32(f32(θ))); }
+sin_f64le :: proc(θ: f64le) -> f64le { return #force_inline f64le(sin_f64(f64(θ))); }
+sin_f64be :: proc(θ: f64be) -> f64be { return #force_inline f64be(sin_f64(f64(θ))); }
+sin       :: proc{
+	sin_f16, sin_f16le, sin_f16be,
+	sin_f32, sin_f32le, sin_f32be,
+	sin_f64, sin_f64le, sin_f64be,
+};
 
-log_f16 :: proc(x, base: f16) -> f16 { return ln(x) / ln(base); }
-log_f32 :: proc(x, base: f32) -> f32 { return ln(x) / ln(base); }
-log_f64 :: proc(x, base: f64) -> f64 { return ln(x) / ln(base); }
-log     :: proc{log_f16, log_f32, log_f64};
+cos_f16le :: proc(θ: f16le) -> f16le { return #force_inline f16le(cos_f16(f16(θ))); }
+cos_f16be :: proc(θ: f16be) -> f16be { return #force_inline f16be(cos_f16(f16(θ))); }
+cos_f32le :: proc(θ: f32le) -> f32le { return #force_inline f32le(cos_f32(f32(θ))); }
+cos_f32be :: proc(θ: f32be) -> f32be { return #force_inline f32be(cos_f32(f32(θ))); }
+cos_f64le :: proc(θ: f64le) -> f64le { return #force_inline f64le(cos_f64(f64(θ))); }
+cos_f64be :: proc(θ: f64be) -> f64be { return #force_inline f64be(cos_f64(f64(θ))); }
+cos       :: proc{
+	cos_f16, cos_f16le, cos_f16be,
+	cos_f32, cos_f32le, cos_f32be,
+	cos_f64, cos_f64le, cos_f64be,
+};
+
+pow_f16le :: proc(x, power: f16le) -> f16le { return #force_inline f16le(pow_f16(f16(x), f16(power))); }
+pow_f16be :: proc(x, power: f16be) -> f16be { return #force_inline f16be(pow_f16(f16(x), f16(power))); }
+pow_f32le :: proc(x, power: f32le) -> f32le { return #force_inline f32le(pow_f32(f32(x), f32(power))); }
+pow_f32be :: proc(x, power: f32be) -> f32be { return #force_inline f32be(pow_f32(f32(x), f32(power))); }
+pow_f64le :: proc(x, power: f64le) -> f64le { return #force_inline f64le(pow_f64(f64(x), f64(power))); }
+pow_f64be :: proc(x, power: f64be) -> f64be { return #force_inline f64be(pow_f64(f64(x), f64(power))); }
+pow       :: proc{
+	pow_f16, pow_f16le, pow_f16be,
+	pow_f32, pow_f32le, pow_f32be,
+	pow_f64, pow_f64le, pow_f64be,
+};
+
+fmuladd_f16le :: proc(a, b, c: f16le) -> f16le { return #force_inline f16le(fmuladd_f16(f16(a), f16(b), f16(c))); }
+fmuladd_f16be :: proc(a, b, c: f16be) -> f16be { return #force_inline f16be(fmuladd_f16(f16(a), f16(b), f16(c))); }
+fmuladd_f32le :: proc(a, b, c: f32le) -> f32le { return #force_inline f32le(fmuladd_f32(f32(a), f32(b), f32(c))); }
+fmuladd_f32be :: proc(a, b, c: f32be) -> f32be { return #force_inline f32be(fmuladd_f32(f32(a), f32(b), f32(c))); }
+fmuladd_f64le :: proc(a, b, c: f64le) -> f64le { return #force_inline f64le(fmuladd_f64(f64(a), f64(b), f64(c))); }
+fmuladd_f64be :: proc(a, b, c: f64be) -> f64be { return #force_inline f64be(fmuladd_f64(f64(a), f64(b), f64(c))); }
+fmuladd       :: proc{
+	fmuladd_f16, fmuladd_f16le, fmuladd_f16be,
+	fmuladd_f32, fmuladd_f32le, fmuladd_f32be,
+	fmuladd_f64, fmuladd_f64le, fmuladd_f64be,
+};
+
+ln_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(ln_f16(f16(x))); }
+ln_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(ln_f16(f16(x))); }
+ln_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(ln_f32(f32(x))); }
+ln_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(ln_f32(f32(x))); }
+ln_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))); }
+ln_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))); }
+ln       :: proc{
+	ln_f16, ln_f16le, ln_f16be,
+	ln_f32, ln_f32le, ln_f32be,
+	ln_f64, ln_f64le, ln_f64be,
+};
 
-log2_f16 :: proc(x: f16) -> f16 { return ln(x)/LN2; }
-log2_f32 :: proc(x: f32) -> f32 { return ln(x)/LN2; }
-log2_f64 :: proc(x: f64) -> f64 { return ln(x)/LN2; }
-log2     :: proc{log2_f16, log2_f32, log2_f64};
+exp_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(exp_f16(f16(x))); }
+exp_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(exp_f16(f16(x))); }
+exp_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(exp_f32(f32(x))); }
+exp_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(exp_f32(f32(x))); }
+exp_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(exp_f64(f64(x))); }
+exp_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(exp_f64(f64(x))); }
+exp       :: proc{
+	exp_f16, exp_f16le, exp_f16be,
+	exp_f32, exp_f32le, exp_f32be,
+	exp_f64, exp_f64le, exp_f64be,
+};
+
+ldexp_f16le :: proc(val: f16le, exp: i32) -> f16le { return #force_inline f16le(ldexp_f16(f16(val), exp)); }
+ldexp_f16be :: proc(val: f16be, exp: i32) -> f16be { return #force_inline f16be(ldexp_f16(f16(val), exp)); }
+ldexp_f32le :: proc(val: f32le, exp: i32) -> f32le { return #force_inline f32le(ldexp_f32(f32(val), exp)); }
+ldexp_f32be :: proc(val: f32be, exp: i32) -> f32be { return #force_inline f32be(ldexp_f32(f32(val), exp)); }
+ldexp_f64le :: proc(val: f64le, exp: i32) -> f64le { return #force_inline f64le(ldexp_f64(f64(val), exp)); }
+ldexp_f64be :: proc(val: f64be, exp: i32) -> f64be { return #force_inline f64be(ldexp_f64(f64(val), exp)); }
+ldexp       :: proc{
+	ldexp_f16, ldexp_f16le, ldexp_f16be,
+	ldexp_f32, ldexp_f32le, ldexp_f32be,
+	ldexp_f64, ldexp_f64le, ldexp_f64be,
+};
+
+
+log_f16   :: proc(x, base: f16)   -> f16   { return ln(x) / ln(base); }
+log_f16le :: proc(x, base: f16le) -> f16le { return f16le(log_f16(f16(x), f16(base))); }
+log_f16be :: proc(x, base: f16be) -> f16be { return f16be(log_f16(f16(x), f16(base))); }
+
+log_f32   :: proc(x, base: f32)   -> f32   { return ln(x) / ln(base); }
+log_f32le :: proc(x, base: f32le) -> f32le { return f32le(log_f32(f32(x), f32(base))); }
+log_f32be :: proc(x, base: f32be) -> f32be { return f32be(log_f32(f32(x), f32(base))); }
+
+log_f64   :: proc(x, base: f64)   -> f64   { return ln(x) / ln(base); }
+log_f64le :: proc(x, base: f64le) -> f64le { return f64le(log_f64(f64(x), f64(base))); }
+log_f64be :: proc(x, base: f64be) -> f64be { return f64be(log_f64(f64(x), f64(base))); }
+log       :: proc{
+	log_f16, log_f16le, log_f16be,
+	log_f32, log_f32le, log_f32be,
+	log_f64, log_f64le, log_f64be,
+};
 
-log10_f16 :: proc(x: f16) -> f16 { return ln(x)/LN10; }
-log10_f32 :: proc(x: f32) -> f32 { return ln(x)/LN10; }
-log10_f64 :: proc(x: f64) -> f64 { return ln(x)/LN10; }
-log10     :: proc{log10_f16, log10_f32, log10_f64};
+log2_f16   :: proc(x: f16)   -> f16   { return ln(x)/LN2; }
+log2_f16le :: proc(x: f16le) -> f16le { return f16le(log2_f16(f16(x))); }
+log2_f16be :: proc(x: f16be) -> f16be { return f16be(log2_f16(f16(x))); }
+
+log2_f32   :: proc(x: f32)   -> f32   { return ln(x)/LN2; }
+log2_f32le :: proc(x: f32le) -> f32le { return f32le(log2_f32(f32(x))); }
+log2_f32be :: proc(x: f32be) -> f32be { return f32be(log2_f32(f32(x))); }
+
+log2_f64   :: proc(x: f64)   -> f64   { return ln(x)/LN2; }
+log2_f64le :: proc(x: f64le) -> f64le { return f64le(log2_f64(f64(x))); }
+log2_f64be :: proc(x: f64be) -> f64be { return f64be(log2_f64(f64(x))); }
+log2       :: proc{
+	log2_f16, log2_f16le, log2_f16be,
+	log2_f32, log2_f32le, log2_f32be,
+	log2_f64, log2_f64le, log2_f64be,
+};
 
+log10_f16   :: proc(x: f16)   -> f16   { return ln(x)/LN10; }
+log10_f16le :: proc(x: f16le) -> f16le { return f16le(log10_f16(f16(x))); }
+log10_f16be :: proc(x: f16be) -> f16be { return f16be(log10_f16(f16(x))); }
+
+log10_f32   :: proc(x: f32)   -> f32   { return ln(x)/LN10; }
+log10_f32le :: proc(x: f32le) -> f32le { return f32le(log10_f32(f32(x))); }
+log10_f32be :: proc(x: f32be) -> f32be { return f32be(log10_f32(f32(x))); }
+
+log10_f64   :: proc(x: f64)   -> f64   { return ln(x)/LN10; }
+log10_f64le :: proc(x: f64le) -> f64le { return f64le(log10_f64(f64(x))); }
+log10_f64be :: proc(x: f64be) -> f64be { return f64be(log10_f64(f64(x))); }
+log10       :: proc{
+	log10_f16, log10_f16le, log10_f16be,
+	log10_f32, log10_f32le, log10_f32be,
+	log10_f64, log10_f64le, log10_f64be,
+};
 
-tan_f16 :: proc(θ: f16) -> f16 { return sin(θ)/cos(θ); }
-tan_f32 :: proc(θ: f32) -> f32 { return sin(θ)/cos(θ); }
-tan_f64 :: proc(θ: f64) -> f64 { return sin(θ)/cos(θ); }
-tan     :: proc{tan_f16, tan_f32, tan_f64};
+tan_f16   :: proc(θ: f16)   -> f16   { return sin(θ)/cos(θ); }
+tan_f16le :: proc(θ: f16le) -> f16le { return f16le(tan_f16(f16(θ))); }
+tan_f16be :: proc(θ: f16be) -> f16be { return f16be(tan_f16(f16(θ))); }
+
+tan_f32   :: proc(θ: f32)   -> f32   { return sin(θ)/cos(θ); }
+tan_f32le :: proc(θ: f32le) -> f32le { return f32le(tan_f32(f32(θ))); }
+tan_f32be :: proc(θ: f32be) -> f32be { return f32be(tan_f32(f32(θ))); }
+
+tan_f64   :: proc(θ: f64)   -> f64   { return sin(θ)/cos(θ); }
+tan_f64le :: proc(θ: f64le) -> f64le { return f64le(tan_f64(f64(θ))); }
+tan_f64be :: proc(θ: f64be) -> f64be { return f64be(tan_f64(f64(θ))); }
+tan       :: proc{
+	tan_f16, tan_f16le, tan_f16be,
+	tan_f32, tan_f32le, tan_f32be,
+	tan_f64, tan_f64le, tan_f64be,
+};
 
 lerp :: proc(a, b: $T, t: $E) -> (x: T) { return a*(1-t) + b*t; }
 saturate :: proc(a: $T) -> (x: T) { return clamp(a, 0, 1); };
@@ -135,6 +269,14 @@ unlerp_f32 :: proc(a, b, x: f32) -> (t: f32) { return (x-a)/(b-a); }
 unlerp_f64 :: proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
 unlerp     :: proc{unlerp_f16, unlerp_f32, unlerp_f64};
 
+remap :: proc(old_value, old_min, old_max, new_min, new_max: $T) -> (x: T) where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) {
+	old_range := old_max - old_min;
+	new_range := new_max - new_min;
+	if old_range == 0 {
+		return new_range / 2;
+	}
+	return ((old_value - old_min) / old_range) * new_range + new_min;
+}
 
 wrap :: proc(x, y: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) {
 	tmp := mod(x, y);
@@ -709,6 +851,13 @@ is_inf_f16 :: proc(x: f16, sign: int = 0) -> bool {
 	}
 	return class == .Inf || class == .Neg_Inf;
 }
+is_inf_f16le :: proc(x: f16le, sign: int = 0) -> bool {
+	return #force_inline is_inf_f16(f16(x), sign);
+}
+is_inf_f16be :: proc(x: f16be, sign: int = 0) -> bool {
+	return #force_inline is_inf_f16(f16(x), sign);
+}
+
 is_inf_f32 :: proc(x: f32, sign: int = 0) -> bool {
 	class := classify(abs(x));
 	switch {
@@ -719,6 +868,13 @@ is_inf_f32 :: proc(x: f32, sign: int = 0) -> bool {
 	}
 	return class == .Inf || class == .Neg_Inf;
 }
+is_inf_f32le :: proc(x: f32le, sign: int = 0) -> bool {
+	return #force_inline is_inf_f32(f32(x), sign);
+}
+is_inf_f32be :: proc(x: f32be, sign: int = 0) -> bool {
+	return #force_inline is_inf_f32(f32(x), sign);
+}
+
 is_inf_f64 :: proc(x: f64, sign: int = 0) -> bool {
 	class := classify(abs(x));
 	switch {
@@ -729,8 +885,17 @@ is_inf_f64 :: proc(x: f64, sign: int = 0) -> bool {
 	}
 	return class == .Inf || class == .Neg_Inf;
 }
-is_inf :: proc{is_inf_f16, is_inf_f32, is_inf_f64};
-
+is_inf_f64le :: proc(x: f64le, sign: int = 0) -> bool {
+	return #force_inline is_inf_f64(f64(x), sign);
+}
+is_inf_f64be :: proc(x: f64be, sign: int = 0) -> bool {
+	return #force_inline is_inf_f64(f64(x), sign);
+}
+is_inf :: proc{
+	is_inf_f16, is_inf_f16le, is_inf_f16be,
+	is_inf_f32, is_inf_f32le, is_inf_f32be,
+	is_inf_f64, is_inf_f64le, is_inf_f64be,
+};
 
 inf_f16 :: proc(sign: int) -> f16 {
 	return f16(inf_f16(sign));
@@ -759,8 +924,6 @@ nan_f64 :: proc() -> f64 {
 	return transmute(f64)v;
 }
 
-
-
 is_power_of_two :: proc(x: int) -> bool {
 	return x > 0 && (x & (x-1)) == 0;
 }