Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add inverse hyperbolic functions asinh(), acosh() & atanh() #78404

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions core/math/math_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ class Math {
static _ALWAYS_INLINE_ double atan2(double p_y, double p_x) { return ::atan2(p_y, p_x); }
static _ALWAYS_INLINE_ float atan2(float p_y, float p_x) { return ::atan2f(p_y, p_x); }

static _ALWAYS_INLINE_ double asinh(double p_x) { return ::asinh(p_x); }
static _ALWAYS_INLINE_ float asinh(float p_x) { return ::asinhf(p_x); }

// Always does clamping so always safe to use.
static _ALWAYS_INLINE_ double acosh(double p_x) { return p_x < 1 ? 0 : ::acosh(p_x); }
static _ALWAYS_INLINE_ float acosh(float p_x) { return p_x < 1 ? 0 : ::acoshf(p_x); }

// Always does clamping so always safe to use.
static _ALWAYS_INLINE_ double atanh(double p_x) { return p_x <= -1 ? -INFINITY : (p_x >= 1 ? INFINITY : ::atanh(p_x)); }
static _ALWAYS_INLINE_ float atanh(float p_x) { return p_x <= -1 ? -INFINITY : (p_x >= 1 ? INFINITY : ::atanhf(p_x)); }

static _ALWAYS_INLINE_ double sqrt(double p_x) { return ::sqrt(p_x); }
static _ALWAYS_INLINE_ float sqrt(float p_x) { return ::sqrtf(p_x); }

Expand Down
16 changes: 16 additions & 0 deletions core/variant/variant_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ double VariantUtilityFunctions::atan2(double y, double x) {
return Math::atan2(y, x);
}

double VariantUtilityFunctions::asinh(double arg) {
return Math::asinh(arg);
}

double VariantUtilityFunctions::acosh(double arg) {
return Math::acosh(arg);
}

double VariantUtilityFunctions::atanh(double arg) {
return Math::atanh(arg);
}

double VariantUtilityFunctions::sqrt(double x) {
return Math::sqrt(x);
}
Expand Down Expand Up @@ -1502,6 +1514,10 @@ void Variant::_register_variant_utility_functions() {

FUNCBINDR(atan2, sarray("y", "x"), Variant::UTILITY_FUNC_TYPE_MATH);

FUNCBINDR(asinh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(acosh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(atanh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);

FUNCBINDR(sqrt, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(fmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(fposmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
Expand Down
3 changes: 3 additions & 0 deletions core/variant/variant_utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ struct VariantUtilityFunctions {
static double acos(double arg);
static double atan(double arg);
static double atan2(double y, double x);
static double asinh(double arg);
static double acosh(double arg);
static double atanh(double arg);
static double sqrt(double x);
static double fmod(double b, double r);
static double fposmod(double b, double r);
Expand Down
39 changes: 39 additions & 0 deletions doc/classes/@GlobalScope.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@
[/codeblock]
</description>
</method>
<method name="acosh">
<return type="float" />
<param index="0" name="x" type="float" />
<description>
Returns the hyperbolic arc (also called inverse) cosine of [param x], returning a value in radians. Use it to get the angle from an angle's cosine in hyperbolic space if [param x] is larger or equal to 1. For values of [param x] lower than 1, it will return 0, in order to prevent [method acosh] from returning [constant @GDScript.NAN].
[codeblock]
var a = acosh(2) # Returns 1.31695789692482
cosh(a) # Returns 2

var b = acosh(-1) # Returns 0
[/codeblock]
</description>
</method>
<method name="asin">
<return type="float" />
<param index="0" name="x" type="float" />
Expand All @@ -83,6 +96,17 @@
[/codeblock]
</description>
</method>
<method name="asinh">
<return type="float" />
<param index="0" name="x" type="float" />
<description>
Returns the hyperbolic arc (also called inverse) sine of [param x], returning a value in radians. Use it to get the angle from an angle's sine in hyperbolic space.
[codeblock]
var a = asinh(0.9) # Returns 0.8088669356527824
sinh(a) # Returns 0.9
[/codeblock]
</description>
</method>
<method name="atan">
<return type="float" />
<param index="0" name="x" type="float" />
Expand All @@ -107,6 +131,21 @@
[/codeblock]
</description>
</method>
<method name="atanh">
<return type="float" />
<param index="0" name="x" type="float" />
<description>
Returns the hyperbolic arc (also called inverse) tangent of [param x], returning a value in radians. Use it to get the angle from an angle's tangent in hyperbolic space if [param x] is between -1 and 1 (non-inclusive).
In mathematics, the inverse hyperbolic tangent is only defined for -1 &lt; [param x] &lt; 1 in the real set, so values equal or lower to -1 for [param x] return negative [constant @GDScript.INF] and values equal or higher than 1 return positive [constant @GDScript.INF] in order to prevent [method atanh] from returning [constant @GDScript.NAN].
[codeblock]
var a = atanh(0.9) # Returns 1.47221948958322
tanh(a) # Returns 0.9

var b = atanh(-2) # Returns -inf
tanh(b) # Returns -1
[/codeblock]
</description>
</method>
<method name="bezier_derivative">
<return type="float" />
<param index="0" name="start" type="float" />
Expand Down
31 changes: 31 additions & 0 deletions tests/core/math/test_math_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,37 @@ TEST_CASE_TEMPLATE("[Math] asin/acos/atan", T, float, double) {
CHECK(Math::atan((T)450.0) == doctest::Approx((T)1.5685741082));
}

TEST_CASE_TEMPLATE("[Math] asinh/acosh/atanh", T, float, double) {
CHECK(Math::asinh((T)-2.0) == doctest::Approx((T)-1.4436354751));
CHECK(Math::asinh((T)-0.1) == doctest::Approx((T)-0.0998340788));
CHECK(Math::asinh((T)0.1) == doctest::Approx((T)0.0998340788));
CHECK(Math::asinh((T)0.5) == doctest::Approx((T)0.4812118250));
CHECK(Math::asinh((T)1.0) == doctest::Approx((T)0.8813735870));
CHECK(Math::asinh((T)2.0) == doctest::Approx((T)1.4436354751));

CHECK(Math::acosh((T)-2.0) == doctest::Approx((T)0.0));
CHECK(Math::acosh((T)-0.1) == doctest::Approx((T)0.0));
CHECK(Math::acosh((T)0.1) == doctest::Approx((T)0.0));
CHECK(Math::acosh((T)0.5) == doctest::Approx((T)0.0));
CHECK(Math::acosh((T)1.0) == doctest::Approx((T)0.0));
CHECK(Math::acosh((T)2.0) == doctest::Approx((T)1.3169578969));
CHECK(Math::acosh((T)450.0) == doctest::Approx((T)6.8023935287));

CHECK(Math::is_inf(Math::atanh((T)-2.0)));
CHECK(Math::atanh((T)-2.0) < (T)0.0);
CHECK(Math::is_inf(Math::atanh((T)-1.0)));
CHECK(Math::atanh((T)-1.0) < (T)0.0);
CHECK(Math::atanh((T)-0.1) == doctest::Approx((T)-0.1003353477));
CHECK(Math::atanh((T)0.1) == doctest::Approx((T)0.1003353477));
CHECK(Math::atanh((T)0.5) == doctest::Approx((T)0.5493061443));
CHECK(Math::is_inf(Math::atanh((T)1.0)));
CHECK(Math::atanh((T)1.0) > (T)0.0);
CHECK(Math::is_inf(Math::atanh((T)1.5)));
CHECK(Math::atanh((T)1.5) > (T)0.0);
CHECK(Math::is_inf(Math::atanh((T)450.0)));
CHECK(Math::atanh((T)450.0) > (T)0.0);
}

TEST_CASE_TEMPLATE("[Math] sinc/sincn/atan2", T, float, double) {
CHECK(Math::sinc((T)-0.1) == doctest::Approx((T)0.9983341665));
CHECK(Math::sinc((T)0.1) == doctest::Approx((T)0.9983341665));
Expand Down