diff --git a/core/libs/prx/libc/src/Math.cpp b/core/libs/prx/libc/src/Math.cpp index 9d6a8aebd..105066f22 100644 --- a/core/libs/prx/libc/src/Math.cpp +++ b/core/libs/prx/libc/src/Math.cpp @@ -121,6 +121,18 @@ float APS5_VABI atanf_nid_postfix(float x) { return std::atan(x); } double APS5_VABI atan2_nid_postfix(double y, double x) { return std::atan2(y, x); } float APS5_VABI powf_nid_postfix(float base, float exp) { return std::pow(base, exp); } double APS5_VABI pow_nid_postfix(double base, double exp) { return std::pow(base, exp); } +float APS5_VABI __powisf2_nid_postfix(float base, int exponent) { + const bool reciprocal = exponent < 0; + float result = 1.0f; + unsigned int magnitude = reciprocal ? 0u - static_cast(exponent) : static_cast(exponent); + while (magnitude != 0u) { + if ((magnitude & 1u) != 0u) result *= base; + magnitude >>= 1u; + if (magnitude == 0u) break; + base *= base; + } + return reciprocal ? 1.0f / result : result; +} float APS5_VABI expf_nid_postfix(float x) { return std::exp(x); } float APS5_VABI exp2f_nid_postfix(float x) { return std::exp2(x); } float APS5_VABI logf_nid_postfix(float x) { return std::log(x); } diff --git a/core/libs/tests/GuestMath.cpp b/core/libs/tests/GuestMath.cpp index 6d56671b5..682b501f6 100644 --- a/core/libs/tests/GuestMath.cpp +++ b/core/libs/tests/GuestMath.cpp @@ -53,6 +53,7 @@ float APS5_VABI log1pf_nid_postfix(float); double APS5_VABI expm1_nid_postfix(double); float APS5_VABI logbf_nid_postfix(float); double APS5_VABI exp2_nid_postfix(double); +float APS5_VABI __powisf2_nid_postfix(float, int); double APS5_VABI ldexp_nid_postfix(double, int); double APS5_VABI scalbn_nid_postfix(double, int); float APS5_VABI scalbnf_nid_postfix(float, int); @@ -491,6 +492,21 @@ int main() { Require(abs_nid_postfix(-42) == 42); Require(abs_nid_postfix(std::numeric_limits::max()) == std::numeric_limits::max()); Require(abs_nid_postfix(std::numeric_limits::min()) == std::numeric_limits::min()); + Require(__powisf2_nid_postfix(2.0f, 10) == 1024.0f); + Require(__powisf2_nid_postfix(2.0f, -10) == 0.0009765625f); + Require(__powisf2_nid_postfix(-2.0f, 3) == -8.0f); + Require(__powisf2_nid_postfix(-2.0f, -3) == -0.125f); + Require(__powisf2_nid_postfix(-2.0f, 4) == 16.0f); + Require(__powisf2_nid_postfix(0.0f, 0) == 1.0f); + Require(__powisf2_nid_postfix(std::numeric_limits::quiet_NaN(), 0) == 1.0f); + Require(std::isnan(__powisf2_nid_postfix(std::numeric_limits::quiet_NaN(), 1))); + Require(__powisf2_nid_postfix(-1.0f, std::numeric_limits::min()) == 1.0f); + Require(__powisf2_nid_postfix(-1.0f, std::numeric_limits::max()) == -1.0f); + Require(__powisf2_nid_postfix(2.0f, std::numeric_limits::min()) == 0.0f); + Require(std::isinf(__powisf2_nid_postfix(0.0f, -1))); + Require(std::signbit(__powisf2_nid_postfix(-0.0f, 3))); + Require(std::isinf(__powisf2_nid_postfix(-0.0f, -3)) && std::signbit(__powisf2_nid_postfix(-0.0f, -3))); + Require(__powisf2_nid_postfix(2.0f, -127) == 0x1p-127f); CheckHyperbolic(); CheckHypotSpecialValue(); }