Skip to content

Commit

Permalink
feat: adds affine_sigmoid() and affine_sigmoid_approx()
Browse files Browse the repository at this point in the history
refactor: removes sigmoid_fast()
  • Loading branch information
NickUfer committed Oct 6, 2024
1 parent 245633d commit aa76044
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 25 deletions.
15 changes: 13 additions & 2 deletions core/math/math_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 8 additions & 3 deletions core/variant/variant_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion core/variant/variant_utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
60 changes: 41 additions & 19 deletions doc/classes/@GlobalScope.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1194,41 +1194,63 @@
[b]Note:[/b] For faster but less accurate approximation, see [method sigmoid_approx] or [method sigmoid_fast].
</description>
</method>
<method name="sigmoid_approx">
<method name="sigmoid_affine">
<return type="float" />
<param index="0" name="x" type="float" />
<param index="1" name="amplitude" type="float" />
<param index="2" name="y_translation" type="float" />
<description>
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].
</description>
</method>
<method name="sigmoid_affine_approx">
<return type="float" />
<param index="0" name="x" type="float" />
<param index="1" name="amplitude" type="float" />
<param index="2" name="y_translation" type="float" />
<description>
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]
</description>
</method>
<method name="sigmoid_fast">
<method name="sigmoid_approx">
<return type="float" />
<param index="0" name="x" type="float" />
<description>
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]
</description>
</method>
Expand Down

0 comments on commit aa76044

Please sign in to comment.