summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/math.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/lib/math.c b/lib/math.c
index cbacb7e..7ace577 100644
--- a/lib/math.c
+++ b/lib/math.c
@@ -14,6 +14,36 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/**
+ * This module bundles various mathematical functions.
+ *
+ * Functions can be individually imported and directly accessed using the
+ * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#named_import named import}
+ * syntax:
+ *
+ * ```
+ * import { pow, rand } from 'math';
+ *
+ * let x = pow(2, 5);
+ * let y = rand();
+ * ```
+ *
+ * Alternatively, the module namespace can be imported
+ * using a wildcard import statement:
+ *
+ * ```
+ * import * as math from 'math';
+ *
+ * let x = math.pow(2, 5);
+ * let y = math.rand();
+ * ```
+ *
+ * Additionally, the math module namespace may also be imported by invoking the
+ * `ucode` interpreter with the `-lmath` switch.
+ *
+ * @module math
+ */
+
#include <math.h>
#include <errno.h>
#include <sys/time.h>
@@ -22,6 +52,18 @@
static bool srand_called = false;
+/**
+ * Returns the absolute value of the given numeric value.
+ *
+ * @function module:math#abs
+ *
+ * @param {*} number
+ * The number to return the absolute value for.
+ *
+ * @returns {number}
+ * Returns the absolute value or `NaN` if the given argument could
+ * not be converted to a number.
+ */
static uc_value_t *
uc_abs(uc_vm_t *vm, size_t nargs)
{
@@ -64,6 +106,45 @@ uc_abs(uc_vm_t *vm, size_t nargs)
return res;
}
+/**
+ * Calculates the principal value of the arc tangent of `y`/`x`,
+ * using the signs of the two arguments to determine the quadrant
+ * of the result.
+ *
+ * On success, this function returns the principal value of the arc
+ * tangent of `y`/`x` in radians; the return value is in the range [-pi, pi].
+ *
+ * - If `y` is +0 (-0) and `x` is less than 0, +pi (-pi) is returned.
+ * - If `y` is +0 (-0) and `x` is greater than 0, +0 (-0) is returned.
+ * - If `y` is less than 0 and `x` is +0 or -0, -pi/2 is returned.
+ * - If `y` is greater than 0 and `x` is +0 or -0, pi/2 is returned.
+ * - If either `x` or `y` is NaN, a NaN is returned.
+ * - If `y` is +0 (-0) and `x` is -0, +pi (-pi) is returned.
+ * - If `y` is +0 (-0) and `x` is +0, +0 (-0) is returned.
+ * - If `y` is a finite value greater (less) than 0, and `x` is negative
+ * infinity, +pi (-pi) is returned.
+ * - If `y` is a finite value greater (less) than 0, and `x` is positive
+ * infinity, +0 (-0) is returned.
+ * - If `y` is positive infinity (negative infinity), and `x` is finite,
+ * pi/2 (-pi/2) is returned.
+ * - If `y` is positive infinity (negative infinity) and `x` is negative
+ * infinity, +3*pi/4 (-3*pi/4) is returned.
+ * - If `y` is positive infinity (negative infinity) and `x` is positive
+ * infinity, +pi/4 (-pi/4) is returned.
+ *
+ * When either `x` or `y` can't be converted to a numeric value, `NaN` is
+ * returned.
+ *
+ * @function module:math#atan2
+ *
+ * @param {*} y
+ * The `y` value.
+ *
+ * @param {*} x
+ * The `x` value.
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_atan2(uc_vm_t *vm, size_t nargs)
{
@@ -76,6 +157,20 @@ uc_atan2(uc_vm_t *vm, size_t nargs)
return ucv_double_new(atan2(d1, d2));
}
+/**
+ * Calculates the cosine of `x`, where `x` is given in radians.
+ *
+ * Returns the resulting consine value.
+ *
+ * Returns `NaN` if the `x` value can't be converted to a number.
+ *
+ * @function module:math#cos
+ *
+ * @param {number} x
+ * Radians value to calculate cosine for.
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_cos(uc_vm_t *vm, size_t nargs)
{
@@ -87,6 +182,26 @@ uc_cos(uc_vm_t *vm, size_t nargs)
return ucv_double_new(cos(d));
}
+/**
+ * Calculates the value of `e` (the base of natural logarithms)
+ * raised to the power of `x`.
+ *
+ * On success, returns the exponential value of `x`.
+ *
+ * - If `x` is positive infinity, positive infinity is returned.
+ * - If `x` is negative infinity, `+0` is returned.
+ * - If the result underflows, a range error occurs, and zero is returned.
+ * - If the result overflows, a range error occurs, and `Infinity` is returned.
+ *
+ * Returns `NaN` if the `x` value can't be converted to a number.
+ *
+ * @function module:math#exp
+ *
+ * @param {number} x
+ * Power to raise `e` to.
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_exp(uc_vm_t *vm, size_t nargs)
{
@@ -98,6 +213,27 @@ uc_exp(uc_vm_t *vm, size_t nargs)
return ucv_double_new(exp(d));
}
+/**
+ * Calculates the natural logarithm of `x`.
+ *
+ * On success, returns the natural logarithm of `x`.
+ *
+ * - If `x` is `1`, the result is `+0`.
+ * - If `x` is positive nfinity, positive infinity is returned.
+ * - If `x` is zero, then a pole error occurs, and the function
+ * returns negative infinity.
+ * - If `x` is negative (including negative infinity), then a domain
+ * error occurs, and `NaN` is returned.
+ *
+ * Returns `NaN` if the `x` value can't be converted to a number.
+ *
+ * @function module:math#log
+ *
+ * @param {number} x
+ * Value to calulate natural logarithm of.
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_log(uc_vm_t *vm, size_t nargs)
{
@@ -109,6 +245,23 @@ uc_log(uc_vm_t *vm, size_t nargs)
return ucv_double_new(log(d));
}
+/**
+ * Calculates the sine of `x`, where `x` is given in radians.
+ *
+ * Returns the resulting sine value.
+ *
+ * - When `x` is positive or negative infinity, a domain error occurs
+ * and `NaN` is returned.
+ *
+ * Returns `NaN` if the `x` value can't be converted to a number.
+ *
+ * @function module:math#sin
+ *
+ * @param {number} x
+ * Radians value to calculate sine for.
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_sin(uc_vm_t *vm, size_t nargs)
{
@@ -120,6 +273,24 @@ uc_sin(uc_vm_t *vm, size_t nargs)
return ucv_double_new(sin(d));
}
+/**
+ * Calculates the nonnegative square root of `x`.
+ *
+ * Returns the resulting square root value.
+ *
+ * - If `x` is `+0` (`-0`) then `+0` (`-0`) is returned.
+ * - If `x` is positive infinity, positive infinity is returned.
+ * - If `x` is less than `-0`, a domain error occurs, and `NaN` is returned.
+ *
+ * Returns `NaN` if the `x` value can't be converted to a number.
+ *
+ * @function module:math#sqrt
+ *
+ * @param {number} x
+ * Value to calculate square root for.
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_sqrt(uc_vm_t *vm, size_t nargs)
{
@@ -131,6 +302,62 @@ uc_sqrt(uc_vm_t *vm, size_t nargs)
return ucv_double_new(sqrt(d));
}
+/**
+ * Calculates the value of `x` raised to the power of `y`.
+ *
+ * On success, returns the value of `x` raised to the power of `y`.
+ *
+ * - If the result overflows, a range error occurs, and the function
+ * returns `Infinity`.
+ * - If result underflows, and is not representable, a range error
+ * occurs, and `0.0` with the appropriate sign is returned.
+ * - If `x` is `+0` or `-0`, and `y` is an odd integer less than `0`,
+ * a pole error occurs `Infinity` is returned, with the same sign
+ * as `x`.
+ * - If `x` is `+0` or `-0`, and `y` is less than `0` and not an odd
+ * integer, a pole error occurs and `Infinity` is returned.
+ * - If `x` is `+0` (`-0`), and `y` is an odd integer greater than `0`,
+ * the result is `+0` (`-0`).
+ * - If `x` is `0`, and `y` greater than `0` and not an odd integer,
+ * the result is `+0`.
+ * - If `x` is `-1`, and `y` is positive infinity or negative infinity,
+ * the result is `1.0`.
+ * - If `x` is `+1`, the result is `1.0` (even if `y` is `NaN`).
+ * - If `y` is `0`, the result is `1.0` (even if `x` is `NaN`).
+ * - If `x` is a finite value less than `0`, and `y` is a finite
+ * noninteger, a domain error occurs, and `NaN` is returned.
+ * - If the absolute value of `x` is less than `1`, and `y` is negative
+ * infinity, the result is positive infinity.
+ * - If the absolute value of `x` is greater than `1`, and `y` is
+ * negative infinity, the result is `+0`.
+ * - If the absolute value of `x` is less than `1`, and `y` is positive
+ * infinity, the result is `+0`.
+ * - If the absolute value of `x` is greater than `1`, and `y` is positive
+ * infinity, the result is positive infinity.
+ * - If `x` is negative infinity, and `y` is an odd integer less than `0`,
+ * the result is `-0`.
+ * - If `x` is negative infinity, and `y` less than `0` and not an odd
+ * integer, the result is `+0`.
+ * - If `x` is negative infinity, and `y` is an odd integer greater than
+ * `0`, the result is negative infinity.
+ * - If `x` is negative infinity, and `y` greater than `0` and not an odd
+ * integer, the result is positive infinity.
+ * - If `x` is positive infinity, and `y` less than `0`, the result is `+0`.
+ * - If `x` is positive infinity, and `y` greater than `0`, the result is
+ * positive infinity.
+ *
+ * Returns `NaN` if either the `x` or `y` value can't be converted to a number.
+ *
+ * @function module:math#pow
+ *
+ * @param {number} x
+ * The base value.
+ *
+ * @param {number} y
+ * The power value.
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_pow(uc_vm_t *vm, size_t nargs)
{
@@ -143,6 +370,27 @@ uc_pow(uc_vm_t *vm, size_t nargs)
return ucv_double_new(pow(x, y));
}
+/**
+ * Produces a pseudo-random positive integer.
+ *
+ * Returns the calculated pseuo-random value. The value is within the range
+ * `0` to `RAND_MAX` inclusive where `RAND_MAX` is a platform specific value
+ * guaranteed to be at least `32767`.
+ *
+ * The {@link module:math~srand `srand()`} function sets its argument as the
+ * seed for a new sequence of pseudo-random integers to be returned by `rand()`. These sequences are
+ * repeatable by calling {@link module:math~srand `srand()`} with the same
+ * seed value.
+ *
+ * If no seed value is explicitly set by calling
+ * {@link module:math~srand `srand()`} prior to the first call to `rand()`,
+ * the math module will automatically seed the PRNG once, using the current
+ * time of day in milliseconds as seed value.
+ *
+ * @function module:math#rand
+ *
+ * @returns {number}
+ */
static uc_value_t *
uc_rand(uc_vm_t *vm, size_t nargs)
{
@@ -158,6 +406,21 @@ uc_rand(uc_vm_t *vm, size_t nargs)
return ucv_int64_new(rand());
}
+/**
+ * Seeds the pseudo-random number generator.
+ *
+ * This functions seeds the PRNG with the given value and thus affects the
+ * pseudo-random integer sequence produced by subsequent calls to
+ * {@link module:math~rand `rand()`}.
+ *
+ * Setting the same seed value will result in the same pseudo-random numbers
+ * produced by {@link module:math~rand `rand()`}.
+ *
+ * @function module:math#srand
+ *
+ * @param {number} seed
+ * The seed value.
+ */
static uc_value_t *
uc_srand(uc_vm_t *vm, size_t nargs)
{
@@ -169,6 +432,24 @@ uc_srand(uc_vm_t *vm, size_t nargs)
return NULL;
}
+/**
+ * Tests whether `x` is a `NaN` double.
+ *
+ * This functions checks whether the given argument is of type `double` with
+ * a `NaN` (not a number) value.
+ *
+ * Returns `true` if the value is `NaN`, otherwise false.
+ *
+ * Note that a value can also be checked for `NaN` with the expression
+ * `x !== x` which only evaluates to `true` if `x` is `NaN`.
+ *
+ * @function module:math#isnan
+ *
+ * @param {number} x
+ * The value to test.
+ *
+ * @returns {boolean}
+ */
static uc_value_t *
uc_isnan(uc_vm_t *vm, size_t nargs)
{