Browse Source

Make `complex32` use higher precision where possible for calculations

gingerBill 1 year ago
parent
commit
a3fe5754d9
2 changed files with 9 additions and 69 deletions
  1. 6 56
      core/math/cmplx/cmplx.odin
  2. 3 13
      core/math/cmplx/cmplx_invtrig.odin

+ 6 - 56
core/math/cmplx/cmplx.odin

@@ -229,7 +229,7 @@ sqrt_complex128 :: proc "contextless" (x: complex128) -> complex128 {
 }
 }
 
 
 ln_complex32 :: proc "contextless" (x: complex32) -> complex32 {
 ln_complex32 :: proc "contextless" (x: complex32) -> complex32 {
-	return complex(math.ln(abs(x)), phase(x))
+	return complex32(ln_complex64(complex64(x)))
 }
 }
 ln_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 ln_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 	return complex(math.ln(abs(x)), phase(x))
 	return complex(math.ln(abs(x)), phase(x))
@@ -240,26 +240,7 @@ ln_complex128 :: proc "contextless" (x: complex128) -> complex128 {
 
 
 
 
 exp_complex32 :: proc "contextless" (x: complex32) -> complex32 {
 exp_complex32 :: proc "contextless" (x: complex32) -> complex32 {
-	switch re, im := real(x), imag(x); {
-	case math.is_inf(re, 0):
-		switch {
-		case re > 0 && im == 0:
-			return x
-		case math.is_inf(im, 0) || math.is_nan(im):
-			if re < 0 {
-				return complex(0, math.copy_sign(0, im))
-			} else {
-				return complex(math.inf_f64(1.0), math.nan_f64())
-			}
-		}
-	case math.is_nan(re):
-		if im == 0 {
-			return complex(math.nan_f16(), im)
-		}
-	}
-	r := math.exp(real(x))
-	s, c := math.sincos(imag(x))
-	return complex(r*c, r*s)
+	return complex32(exp_complex64(complex64(x)))
 }
 }
 exp_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 exp_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 	switch re, im := real(x), imag(x); {
 	switch re, im := real(x), imag(x); {
@@ -308,37 +289,7 @@ exp_complex128 :: proc "contextless" (x: complex128) -> complex128 {
 
 
 
 
 pow_complex32 :: proc "contextless" (x, y: complex32) -> complex32 {
 pow_complex32 :: proc "contextless" (x, y: complex32) -> complex32 {
-	if x == 0 { // Guaranteed also true for x == -0.
-		if is_nan(y) {
-			return nan_complex32()
-		}
-		r, i := real(y), imag(y)
-		switch {
-		case r == 0:
-			return 1
-		case r < 0:
-			if i == 0 {
-				return complex(math.inf_f16(1), 0)
-			}
-			return inf_complex32()
-		case r > 0:
-			return 0
-		}
-		unreachable()
-	}
-	modulus := abs(x)
-	if modulus == 0 {
-		return complex(0, 0)
-	}
-	r := math.pow(modulus, real(y))
-	arg := phase(x)
-	theta := real(y) * arg
-	if imag(y) != 0 {
-		r *= math.exp(-imag(y) * arg)
-		theta += imag(y) * math.ln(modulus)
-	}
-	s, c := math.sincos(theta)
-	return complex(r*c, r*s)
+	return complex32(pow_complex64(complex64(x), complex64(y)))
 }
 }
 pow_complex64 :: proc "contextless" (x, y: complex64) -> complex64 {
 pow_complex64 :: proc "contextless" (x, y: complex64) -> complex64 {
 	if x == 0 { // Guaranteed also true for x == -0.
 	if x == 0 { // Guaranteed also true for x == -0.
@@ -410,7 +361,7 @@ pow_complex128 :: proc "contextless" (x, y: complex128) -> complex128 {
 
 
 
 
 log10_complex32 :: proc "contextless" (x: complex32) -> complex32 {
 log10_complex32 :: proc "contextless" (x: complex32) -> complex32 {
-	return math.LN10*ln(x)
+	return complex32(log10_complex64(complex64(x)))
 }
 }
 log10_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 log10_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 	return math.LN10*ln(x)
 	return math.LN10*ln(x)
@@ -421,7 +372,7 @@ log10_complex128 :: proc "contextless" (x: complex128) -> complex128 {
 
 
 
 
 phase_complex32 :: proc "contextless" (x:  complex32) -> f16 {
 phase_complex32 :: proc "contextless" (x:  complex32) -> f16 {
-	return math.atan2(imag(x), real(x))
+	return f16(phase_complex64(complex64(x)))
 }
 }
 phase_complex64 :: proc "contextless" (x:  complex64) -> f32 {
 phase_complex64 :: proc "contextless" (x:  complex64) -> f32 {
 	return math.atan2(imag(x), real(x))
 	return math.atan2(imag(x), real(x))
@@ -432,8 +383,7 @@ phase_complex128 :: proc "contextless" (x:  complex128) -> f64 {
 
 
 
 
 rect_complex32 :: proc "contextless" (r, θ: f16) -> complex32 {
 rect_complex32 :: proc "contextless" (r, θ: f16) -> complex32 {
-	s, c := math.sincos(θ)
-	return complex(r*c, r*s)
+	return complex32(rect_complex64(f32(r), f32(θ)))
 }
 }
 rect_complex64 :: proc "contextless" (r, θ: f32) -> complex64 {
 rect_complex64 :: proc "contextless" (r, θ: f32) -> complex64 {
 	s, c := math.sincos(θ)
 	s, c := math.sincos(θ)

+ 3 - 13
core/math/cmplx/cmplx_invtrig.odin

@@ -61,8 +61,7 @@ atanh :: proc{
 
 
 
 
 acos_complex32 :: proc "contextless" (x: complex32) -> complex32 {
 acos_complex32 :: proc "contextless" (x: complex32) -> complex32 {
-	w := asin(x)
-	return complex(math.PI/2 - real(w), -imag(w))
+	return complex32(acos_complex64(complex64(x)))
 }
 }
 acos_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 acos_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 	w := asin(x)
 	w := asin(x)
@@ -75,14 +74,7 @@ acos_complex128 :: proc "contextless" (x: complex128) -> complex128 {
 
 
 
 
 acosh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
 acosh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
-	if x == 0 {
-		return complex(0, math.copy_sign(math.PI/2, imag(x)))
-	}
-	w := acos(x)
-	if imag(w) <= 0 {
-		return complex(-imag(w), real(w))
-	}
-	return complex(imag(w), -real(w))
+	return complex32(acosh_complex64(complex64(x)))
 }
 }
 acosh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 acosh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 	if x == 0 {
 	if x == 0 {
@@ -257,9 +249,7 @@ atan_complex128 :: proc "contextless" (x: complex128) -> complex128 {
 }
 }
 
 
 atanh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
 atanh_complex32 :: proc "contextless" (x: complex32) -> complex32 {
-	z := complex(-imag(x), real(x)) // z = i * x
-	z = atan(z)
-	return complex(imag(z), -real(z)) // z = -i * z
+	return complex32(atanh_complex64(complex64(x)))
 }
 }
 atanh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 atanh_complex64 :: proc "contextless" (x: complex64) -> complex64 {
 	z := complex(-imag(x), real(x)) // z = i * x
 	z := complex(-imag(x), real(x)) // z = i * x