From 7f21c7f30e7b11437f20a708e4b9344c50e0ef9a Mon Sep 17 00:00:00 2001 From: Nick Ufer Date: Fri, 4 Oct 2024 16:09:36 +0200 Subject: [PATCH] feat: adds sigmoid(), sigmoid_approx() and sigmoid_fast() functions --- core/math/math_funcs.h | 9 +++++ core/variant/variant_utility.cpp | 16 +++++++++ core/variant/variant_utility.h | 3 ++ doc/classes/@GlobalScope.xml | 57 ++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 1afc5f4bbbd..3e1ecb00be4 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -757,6 +757,15 @@ class Math { } return p_target; } + + static _ALWAYS_INLINE_ double sigmoid(double p_x) { return 1.0 / (1.0 + ::exp(-p_x)); } + static _ALWAYS_INLINE_ float sigmoid(float p_x) { return 1.0f / (1.0f + expf(-p_x)); } + + static _ALWAYS_INLINE_ double sigmoid_approx(double p_x) { return 0.5 + p_x / (4.0 + fabs(p_x)); } + static _ALWAYS_INLINE_ float sigmoid_approx(float p_x) { return 0.5f + p_x / (4.0f + fabsf(p_x)); } + + static _ALWAYS_INLINE_ double sigmoid_fast(double p_x) { return p_x / (1.0 + fabs(p_x)); } + static _ALWAYS_INLINE_ float sigmoid_fast(float p_x) { return p_x / (1.0f + fabsf(p_x)); } }; #endif // MATH_FUNCS_H diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 384fe6c4a66..ec2169f9027 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -639,6 +639,18 @@ double VariantUtilityFunctions::pingpong(double value, double length) { return Math::pingpong(value, length); } +double VariantUtilityFunctions::sigmoid(double x) { + return Math::sigmoid(x); +} + +double VariantUtilityFunctions::sigmoid_approx(double x) { + return Math::sigmoid_approx(x); +} + +double VariantUtilityFunctions::sigmoid_fast(double x) { + return Math::sigmoid_fast(x); +} + Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; @@ -1787,6 +1799,10 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(nearest_po2, sarray("value"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(pingpong, sarray("value", "length"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(sigmoid, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(sigmoid_approx, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(sigmoid_fast, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + // Random FUNCBIND(randomize, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); diff --git a/core/variant/variant_utility.h b/core/variant/variant_utility.h index 75cde4942b5..d1c309f6be7 100644 --- a/core/variant/variant_utility.h +++ b/core/variant/variant_utility.h @@ -115,6 +115,9 @@ struct VariantUtilityFunctions { static double clampf(double x, double min, double max); static int64_t clampi(int64_t x, int64_t min, int64_t max); static int64_t nearest_po2(int64_t x); + static double sigmoid(double x); + static double sigmoid_approx(double x); + static double sigmoid_fast(double x); // Random static void randomize(); static int64_t randi(); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 55d00b6cf90..6156512a4b3 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -473,6 +473,63 @@ [/codeblock] + + + + + Computes the sigmoid of [param x], which maps the input value into the range (0, 1). + The sigmoid function is defined as: + [codeblock] + sigmoid(x) = 1 / (1 + exp(-x)) + [/codeblock] + This is the most accurate implementation of the sigmoid. + [codeblock] + var result = sigmoid(0.0) # result is 0.5 + var result = sigmoid(1.0) # result is approximately 0.88 + var result = sigmoid(-1.0) # result is approximately 0.27 + var result = sigmoid(5.0) # result is approximately 0.99 + [/codeblock] + [b]Note:[/b] For faster but less accurate approximation, see [method sigmoid_approx] or [method sigmoid_fast]. + + + + + + + Computes an approximation of the sigmoid function for [param x]. + The approximation is defined as: + [codeblock] + sigmoid_approx(x) = 0.5 + (x / (4 + abs(x))) + [/codeblock] + This function is faster than the standard [method sigmoid], especially useful in performance-sensitive environments where a balance between accuracy and speed is desired. + It provides a closer approximation to the sigmoid than the [method sigmoid_fast] function, especially around [param x] = 0. + [codeblock] + var result = sigmoid_approx(0.0) # result is 0.5 + var result = sigmoid_approx(2.0) # result is approximately 0.83 + var result = sigmoid_approx(-1.0) # result is approximately 0.3 + var result = sigmoid_approx(5.0) # result is approximately 1.05 + [/codeblock] + + + + + + + Computes a fast approximation of the sigmoid function for [param x]. + The fast sigmoid is defined as: + [codeblock] + fast_sigmoid(x) = x / (1 + abs(x)) + [/codeblock] + This function is faster to compute than the standard [method sigmoid] and [method sigmoid_approx], but is less accurate, particularly in the steep transition area around 0. + It is commonly used in real-time systems and machine learning where performance is critical. + [codeblock] + var result = sigmoid_fast(0.0) # result is 0 + var result = sigmoid_fast(2.0) # result is approximately 0.67 + var result = sigmoid_fast(-1.0) # result is approximately -0.5 + var result = sigmoid_fast(5.0) # result is approximately 0.83 + [/codeblock] + +