commit e089ea45150cedd9e8edc4b2c22e55580e98a25e
parent 46190589404158b83117581c002ced9751ef4a55
Author: Sebastian <sebastian@sebsite.pw>
Date: Fri, 27 May 2022 22:28:35 -0400
math: add atan2f64
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
2 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/math/data+test.ha b/math/data+test.ha
@@ -115,6 +115,18 @@ const TEST_ATAN: [_]f64 = [
1.0696031952318783760193244e+00,
-1.4561721938838084990898679e+00,
];
+const TEST_ATAN2: [_]f64 = [
+ 1.1088291730037004444527075e+00,
+ 9.1218183188715804018797795e-01,
+ 1.5984772603216203736068915e+00,
+ 2.0352918654092086637227327e+00,
+ 8.0391819139044720267356014e-01,
+ 1.2861075249894661588866752e+00,
+ 1.0889904479131695712182587e+00,
+ 1.3044821793397925293797357e+00,
+ 1.3902530903455392306872261e+00,
+ 2.2859857424479142655411058e+00,
+];
const TEST_ATANH: [_]f64 = [
5.4651163712251938116878204e-01,
1.0299474112843111224914709e+00,
diff --git a/math/trig.ha b/math/trig.ha
@@ -1013,6 +1013,59 @@ export fn atanhf64(x: f64) f64 = {
assert(isnan(atanhf64(NAN)));
};
+// Returns the arctangent, in radians, of y / x.
+export fn atan2f64(y: f64, x: f64) f64 = {
+ if (isnan(y) || isnan(x)) {
+ return NAN;
+ } else if (y == 0f64) {
+ x = if (x >= 0f64 && signf64(x) > 0) 0f64 else PI;
+ return copysignf64(x, y);
+ } else if (x == 0f64) {
+ return copysignf64(PI / 2f64, y);
+ } else if (isinf(x)) {
+ if (signf64(x) > 0) {
+ x = if (isinf(y)) PI / 4f64 else 0f64;
+ return copysignf64(x, y);
+ } else {
+ x = if (isinf(y)) 3f64 * PI / 4f64 else PI;
+ return copysignf64(x, y);
+ };
+ } else if (isinf(y)) {
+ return copysignf64(PI / 2f64, y);
+ };
+
+ const q = atanf64(y / x);
+ if (x < 0f64) {
+ return if (q <= 0f64) q + PI else q - PI;
+ };
+ return q;
+};
+
+@test fn atan2() void = {
+ for (let idx = 0z; idx < 10; idx += 1) {
+ assert(isclose(
+ atan2f64(10f64, TEST_INPUTS[idx]),
+ TEST_ATAN2[idx]));
+ };
+ assert(isnan(atan2f64(-INF, NAN)));
+ assert(atan2f64(-PI, INF) == -0f64);
+ assert(isnan(atan2f64(-PI, NAN)));
+ assert(atan2f64(-0f64, 0f64) == -0f64);
+ assert(atan2f64(-0f64, PI) == -0f64);
+ assert(atan2f64(-0f64, INF) == -0f64);
+ assert(isnan(atan2f64(-0f64, NAN)));
+ assert(atan2f64(0f64, 0f64) == 0f64);
+ assert(atan2f64(0f64, PI) == 0f64);
+ assert(atan2f64(0f64, INF) == 0f64);
+ assert(isnan(atan2f64(0f64, NAN)));
+ assert(atan2f64(PI, INF) == 0f64);
+ assert(atan2f64(1f64, INF) == 0f64);
+ assert(atan2f64(-1f64, INF) == -0f64);
+ assert(isnan(atan2f64(PI, NAN)));
+ assert(isnan(atan2f64(INF, NAN)));
+ assert(isnan(atan2f64(NAN, NAN)));
+};
+
// Returns the square root of a*a + b*b, taking care to avoid unnecessary
// overflow and underflow.
export fn hypotf64(a: f64, b: f64) f64 = {