From aa7604469a3310a9481ee232da4fe4c292f045d3 Mon Sep 17 00:00:00 2001 From: Nick Ufer Date: Sun, 6 Oct 2024 18:36:47 +0200 Subject: [PATCH] feat: adds affine_sigmoid() and affine_sigmoid_approx() refactor: removes sigmoid_fast() --- core/math/math_funcs.h | 15 ++++++-- core/variant/variant_utility.cpp | 11 ++++-- core/variant/variant_utility.h | 3 +- doc/classes/@GlobalScope.xml | 60 ++++++++++++++++++++++---------- 4 files changed, 64 insertions(+), 25 deletions(-) diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 3e1ecb00be4..9134ccf6411 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -764,8 +764,19 @@ class Math { 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)); } + static _ALWAYS_INLINE_ double sigmoid_affine(double p_x, double p_amplitude, double p_y_translation) { + return p_amplitude / (1.0 + ::exp(-p_x)) + p_y_translation; + } + static _ALWAYS_INLINE_ float sigmoid_affine(float p_x, float p_amplitude, float p_y_translation) { + return p_amplitude / (1.0f + expf(-p_x)) + p_y_translation; + } + + static _ALWAYS_INLINE_ double sigmoid_affine_approx(double p_x, double p_amplitude, double p_y_translation) { + return p_amplitude * (0.5 + p_x / (4.0 + fabs(p_x))) + p_y_translation; + } + static _ALWAYS_INLINE_ float sigmoid_affine_approx(float p_x, float p_amplitude, float p_y_translation) { + return p_amplitude * (0.5f + p_x / (4.0f + fabsf(p_x))) + p_y_translation; + } }; #endif // MATH_FUNCS_H diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index ec2169f9027..65eaf5aa8e8 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -647,8 +647,12 @@ double VariantUtilityFunctions::sigmoid_approx(double x) { return Math::sigmoid_approx(x); } -double VariantUtilityFunctions::sigmoid_fast(double x) { - return Math::sigmoid_fast(x); +double VariantUtilityFunctions::sigmoid_affine(double x, double amplitude, double y_translation) { + return Math::sigmoid_affine(x, amplitude, y_translation); +} + +double VariantUtilityFunctions::sigmoid_affine_approx(double x, double amplitude, double y_translation) { + return Math::sigmoid_affine_approx(x, amplitude, y_translation); } Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { @@ -1801,7 +1805,8 @@ void Variant::_register_variant_utility_functions() { 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); + FUNCBINDR(sigmoid_affine, sarray("x", "amplitude", "y_translation"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(sigmoid_affine_approx, sarray("x", "amplitude", "y_translation"), Variant::UTILITY_FUNC_TYPE_MATH); // Random diff --git a/core/variant/variant_utility.h b/core/variant/variant_utility.h index d1c309f6be7..f4dcbbfdf30 100644 --- a/core/variant/variant_utility.h +++ b/core/variant/variant_utility.h @@ -117,7 +117,8 @@ struct VariantUtilityFunctions { 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); + static double sigmoid_affine(double x, double amplitude, double y_translation); + static double sigmoid_affine_approx(double x, double amplitude, double y_translation); // Random static void randomize(); static int64_t randi(); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 5b818c71681..e2c7a0f6e48 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1194,41 +1194,63 @@ [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], which maps the input value into the range (0, 1). + Computes an affine-transformed sigmoid for [param x], which allows scaling by [param amplitude] and translation by [param y_translate]. + The affine sigmoid function is defined as: + [codeblock] + affine_sigmoid(x, amplitude, y_translate) = (amplitude / (1 + exp(-x))) + y_translate + [/codeblock] + This function modifies the standard sigmoid by introducing scaling and vertical translation. + [codeblock] + var result = affine_sigmoid(0.0, 1.0, 0.0) # result is 0.5 + var result = affine_sigmoid(1.0, 2.0, -1.0) # result is approximately 0.46 + var result = affine_sigmoid(-1.0, 3.0, 2.0) # result is approximately 2.81 + var result = affine_sigmoid(1.0, 2.0, 2.5) # result is approximately 3.96 + [/codeblock] + [b]Note:[/b] This is a more accurate but computationally heavier version of the affine sigmoid. For faster approximations, see [method affine_sigmoid_approx]. + + + + + + + + + Computes an approximation of the affine-transformed sigmoid function for [param x], allowing scaling by [param amplitude] and translation by [param y_translate]. The approximation function is defined as: [codeblock] - sigmoid_approx(x) = 0.5 + (x / (4 + abs(x))) + affine_sigmoid_approx(x, amplitude, y_translate) = amplitude * (0.5 + (x / (4 + abs(x)))) + y_translate [/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. + This function approximates the affine sigmoid, offering faster computation at the cost of some precision. It is useful in performance-sensitive environments where both transformation and speed are needed. [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 + var result = affine_sigmoid_approx(0.0, 1.0, 0.0) # result is 0.5 + var result = affine_sigmoid_approx(2.0, 2.0, 1.0) # result is approximately 2.67 + var result = affine_sigmoid_approx(-1.0, 3.0, 0.5) # result is approximately 1.4 + var result = affine_sigmoid_approx(1.0, 2.0, 2.5) # result is approximately 3.9 [/codeblock] - + - Computes a fast approximation of the sigmoid function for [param x], which maps the input value into the range (-1, 1). - The fast sigmoid function is defined as: + Computes an approximation of the sigmoid function for [param x], which maps the input value into the range (0, 1). + The approximation function is defined as: [codeblock] - fast_sigmoid(x) = x / (1 + abs(x)) + sigmoid_approx(x) = 0.5 + (x / (4 + 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. + 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_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 + 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]