From 269913ede03e56d8179b91c3a6bf7bb9fb94a8fa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 4 Nov 2022 14:26:31 +0000 Subject: [PATCH] Implement `acos` in native Odin --- core/math/math.odin | 111 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 5 deletions(-) diff --git a/core/math/math.odin b/core/math/math.odin index e2249dcb9..5f79275b6 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -1379,9 +1379,10 @@ atan2_f64be :: proc "contextless" (y, x: f64be) -> f64be { } atan2 :: proc{ - atan2_f16, atan2_f16le, atan2_f16be, - atan2_f32, atan2_f32le, atan2_f32be, - atan2_f64, atan2_f64le, atan2_f64be, + atan2_f64, atan2_f32, atan2_f16, + atan2_f64le, atan2_f64be, + atan2_f32le, atan2_f32be, + atan2_f16le, atan2_f16be, } atan :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { @@ -1392,8 +1393,108 @@ asin :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { return atan2(sqrt(1 - x*x), x) } -acos :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { - return 2 * atan2(sqrt(1 + x), sqrt(1 - x)) +acos_f64 :: proc "contextless" (x: f64) -> f64 { + /* origin: FreeBSD /usr/src/lib/msun/src/e_acos.c */ + /* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + + pio2_hi :: 0h3FF921FB54442D18 + pio2_lo :: 0h3C91A62633145C07 + pS0 :: 0h3FC5555555555555 + pS1 :: 0hBFD4D61203EB6F7D + pS2 :: 0h3FC9C1550E884455 + pS3 :: 0hBFA48228B5688F3B + pS4 :: 0h3F49EFE07501B288 + pS5 :: 0h3F023DE10DFDF709 + qS1 :: 0hC0033A271C8A2D4B + qS2 :: 0h40002AE59C598AC8 + qS3 :: 0hBFE6066C1B8D0159 + qS4 :: 0h3FB3B8C5B12E9282 + + R :: #force_inline proc "contextless" (z: f64) -> f64 { + p, q: f64 + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))) + q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4))) + return p/q + } + + z, w, s, c, df: f64 + dwords := transmute([2]u32)x + hx := dwords[1] + ix := hx & 0x7fffffff + /* |x| >= 1 or nan */ + if ix >= 0x3ff00000 { + lx := dwords[0] + + if (ix-0x3ff00000 | lx) == 0 { + /* acos(1)=0, acos(-1)=pi */ + if hx >> 31 != 0 { + return 2*pio2_hi + 1e-120 + } + return 0 + } + return 0/(x-x) + } + /* |x| < 0.5 */ + if ix < 0x3fe00000 { + if ix <= 0x3c600000 { /* |x| < 2**-57 */ + return pio2_hi + 1e-120 + } + return pio2_hi - (x - (pio2_lo-x*R(x*x))) + } + /* x < -0.5 */ + if hx >> 31 != 0 { + z = (1.0+x)*0.5 + s = sqrt(z) + w = R(z)*s-pio2_lo + return 2*(pio2_hi - (s+w)) + } + /* x > 0.5 */ + z = (1.0-x)*0.5 + s = sqrt(z) + df = s + (^u64)(&df)^ &= 0xffffffff_00000000 + c = (z-df*df)/(s+df) + w = R(z)*s+c + return 2*(df+w) +} +acos_f64le :: proc "contextless" (x: f64le) -> f64le { + return f64le(acos_f64(f64(x))) +} +acos_f64be :: proc "contextless" (x: f64be) -> f64be { + return f64be(acos_f64(f64(x))) +} +acos_f32 :: proc "contextless" (x: f32) -> f32 { + return f32(acos_f64(f64(x))) +} +acos_f32le :: proc "contextless" (x: f32le) -> f32le { + return f32le(acos_f64(f64(x))) +} +acos_f32be :: proc "contextless" (x: f32be) -> f32be { + return f32be(acos_f64(f64(x))) +} +acos_f16 :: proc "contextless" (x: f16) -> f16 { + return f16(acos_f64(f64(x))) +} +acos_f16le :: proc "contextless" (x: f16le) -> f16le { + return f16le(acos_f64(f64(x))) +} +acos_f16be :: proc "contextless" (x: f16be) -> f16be { + return f16be(acos_f64(f64(x))) +} +acos :: proc{ + acos_f64, acos_f32, acos_f16, + acos_f64le, acos_f64be, + acos_f32le, acos_f32be, + acos_f16le, acos_f16be, } sinh :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {