Skip to content

Commit

Permalink
AK: Implement atan2() in terms of atan() on non-x86
Browse files Browse the repository at this point in the history
atan() isn't implemented yet on non-x86, so this isn't super useful yet.
But it does handle a couple corner cases correctly already, and those
are even enough to make all the atan2 tests in Tests/LibC/TestMath.cpp
pass 🙃
  • Loading branch information
nico committed Dec 24, 2024
1 parent 982c8cc commit 69b2b86
Showing 1 changed file with 61 additions and 3 deletions.
64 changes: 61 additions & 3 deletions AK/Math.h
Original file line number Diff line number Diff line change
Expand Up @@ -809,10 +809,68 @@ constexpr T atan2(T y, T x)
return ret;
#else
# if defined(AK_OS_SERENITY)
// TODO: Add implementation for this function.
TODO();
# endif
if (__builtin_isnan(y))
return y;
if (__builtin_isnan(x))
return x;

// SPECIAL VALUES
// atan2(±0, -0) returns ±pi.
if (y == 0 && x == 0 && signbit(x))
return copysign(Pi<T>, y);

// atan2(±0, +0) returns ±0.
if (y == 0 && x == 0 && !signbit(x))
return y;

// atan2(±0, x) returns ±pi for x < 0.
if (y == 0 && x < 0)
return copysign(Pi<T>, y);

// atan2(±0, x) returns ±0 for x > 0.
if (y == 0 && x > 0)
return y;

// atan2(y, ±0) returns +pi/2 for y > 0.
if (y > 0 && x == 0)
return Pi<T> / 2;

// atan2(y, ±0) returns -pi/2 for y < 0.
if (y < 0 && x == 0)
return -Pi<T> / 2;

// atan2(±y, -infinity) returns ±pi for finite y > 0.
if (!__builtin_isinf(y) && y > 0 && __builtin_isinf(x) && signbit(x))
return copysign(Pi<T>, y);

// atan2(±y, +infinity) returns ±0 for finite y > 0.
if (!__builtin_isinf(y) && y > 0 && __builtin_isinf(x) && !signbit(x))
return copysign(static_cast<T>(0), y);

// atan2(±infinity, x) returns ±pi/2 for finite x.
if (__builtin_isinf(y) && !__builtin_isinf(x))
return copysign(Pi<T> / 2, y);

// atan2(±infinity, -infinity) returns ±3*pi/4.
if (__builtin_isinf(y) && __builtin_isinf(x) && signbit(x))
return copysign(3 * Pi<T> / 4, y);

// atan2(±infinity, +infinity) returns ±pi/4.
if (__builtin_isinf(y) && __builtin_isinf(x) && !signbit(x))
return copysign(Pi<T> / 4, y);

// Check quadrant, going counterclockwise.
if (y > 0 && x > 0)
return atan(y / x);
if (y > 0 && x < 0)
return atan(y / x) + Pi<T>;
if (y < 0 && x < 0)
return atan(y / x) - Pi<T>;
// y < 0 && x > 0
return atan(y / x);
# else
return __builtin_atan2(y, x);
# endif
#endif
}

Expand Down

0 comments on commit 69b2b86

Please sign in to comment.