+///
+/// The function calculates the greatest common divisor of two integers
+/// \\(x, y \in \mathbb{Z}\\). The greatest common divisor is the largest positive
+/// integer that is divisible by both \\(x\\) and \\(y\\).
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.gcd(1, 1)
+/// |> should.equal(1)
+///
+/// maths.gcd(100, 10)
+/// |> should.equal(10)
+///
+/// maths.gcd(-36, -17)
+/// |> should.equal(1)
+/// }
+///
+///
+///
+///
+///
+/// Given two integers, \\(x\\) (dividend) and \\(y\\) (divisor), the Euclidean modulo
+/// of \\(x\\) by \\(y\\), denoted as \\(x \mod y\\), is the remainder \\(r\\) of the
+/// division of \\(x\\) by \\(y\\), such that:
+///
+/// \\[
+/// x = q \cdot y + r \quad \text{and} \quad 0 \leq r < |y|,
+/// \\]
+///
+/// where \\(q\\) is an integer that represents the quotient of the division.
+///
+/// Note that like the Gleam division operator `/` this will return `0` if one of
+/// the arguments is `0`.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.int_euclidean_modulo(15, 4)
+/// |> should.equal(3)
+///
+/// maths.int_euclidean_modulo(-3, -2)
+/// |> should.equal(1)
+///
+/// maths.int_euclidean_modulo(5, 0)
+/// |> should.equal(0)
+/// }
+///
+///
+///
+///
+/// The function calculates the least common multiple of two integers
+/// \\(x, y \in \mathbb{Z}\\). The least common multiple is the smallest positive
+/// integer that has both \\(x\\) and \\(y\\) as factors.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.lcm(1, 1)
+/// |> should.equal(1)
+///
+/// maths.lcm(100, 10)
+/// |> should.equal(100)
+///
+/// maths.lcm(-36, -17)
+/// |> should.equal(612)
+/// }
+///
+///
+///
+///
+/// Calculate the weighted sum of the elements in a list:
+///
+/// \\[
+/// \sum_{i=1}^n w_i x_i
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\) is
+/// the value in the input list indexed by \\(i\\), while the \\(w_i \in \mathbb{R}\\)
+/// are corresponding positive weights.
+///
+///
+/// Example:
+///
+/// import gleam/float
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// []
+/// |> maths.float_weighted_sum()
+/// |> should.equal(Ok(0.0))
+///
+/// [#(1.0, 1.0), #(2.0, 1.0), #(3.0, 1.0)]
+/// |> maths.float_weighted_sum()
+/// |> should.equal(Ok(6.0))
+///
+/// [#(9.0, 0.5), #(10.0, 0.5), #(10.0, 0.5)]
+/// |> maths.float_weighted_sum()
+/// |> should.equal(Ok(14.5))
+/// }
+///
+///
+///
+///
+/// Calculate the weighted product of the elements in a list:
+///
+/// \\[
+/// \prod_{i=1}^n x_i^{w_i}
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\) is
+/// the value in the input list indexed by \\(i\\), while the \\(w_i \in \mathbb{R}\\)
+/// are corresponding positive weights.
+///
+///
+/// Example:
+///
+/// import gleam/float
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// []
+/// |> maths.float_weighted_product()
+/// |> should.equal(Ok(1.0))
+///
+/// [#(1.0, 1.0), #(2.0, 1.0), #(3.0, 1.0)]
+/// |> maths.float_weighted_product()
+/// |> should.equal(Ok(6.0))
+///
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+/// let assert Ok(result) =
+/// [#(9.0, 0.5), #(10.0, 0.5), #(10.0, 0.5)]
+/// |> maths.float_weighted_product()
+/// result
+/// |> maths.is_close(30.0, 0.0, tolerance)
+/// |> should.be_true()
+/// }
+///
+///
+///
+///
+/// Calculate the cumulative sum of the elements in a list:
+///
+/// \\[
+/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
+/// \\]
+///
+/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(n\\)
+/// elements. That is, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\)
+/// is the value in the input list indexed by \\(i\\). The value \\(v_j\\) is thus the
+/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// []
+/// |> maths.float_cumulative_sum()
+/// |> should.equal([])
+///
+/// [1.0, 2.0, 3.0]
+/// |> maths.float_cumulative_sum()
+/// |> should.equal([1.0, 3.0, 6.0])
+/// }
+///
+///
+///
+///
+/// Calculate the cumulative sum of the elements in a list:
+///
+/// \\[
+/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
+/// \\]
+///
+/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(n\\)
+/// elements. That is, \\(n\\) is the length of the list and \\(x_i \in \mathbb{Z}\\)
+/// is the value in the input list indexed by \\(i\\). The value \\(v_j\\) is thus the
+/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// []
+/// |> maths.int_cumulative_sum()
+/// |> should.equal([])
+///
+/// [1, 2, 3]
+/// |> maths.int_cumulative_sum()
+/// |> should.equal([1, 3, 6])
+/// }
+///
+///
+///
+///
+/// Calculate the cumulative product of the elements in a list:
+///
+/// \\[
+/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
+/// \\]
+///
+/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative product of
+/// \\(n\\) elements. That is, \\(n\\) is the length of the list and
+/// \\(x_i \in \mathbb{R}\\) is the value in the input list indexed by \\(i\\). The
+/// value \\(v_j\\) is thus the sum of the \\(1\\) to \\(j\\) first elements in the
+/// given list.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// []
+/// |> maths.float_cumulative_product()
+/// |> should.equal([])
+///
+/// [1.0, 2.0, 3.0]
+/// |> maths.float_cumulative_product()
+/// |> should.equal([1.0, 2.0, 6.0])
+/// }
+///
+///
+///
+///
+/// Calculate the cumulative product of the elements in a list:
+///
+/// \\[
+/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
+/// \\]
+///
+/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative product of
+/// \\(n\\) elements. That is, \\(n\\) is the length of the list and
+/// \\(x_i \in \mathbb{Z}\\) is the value in the input list indexed by \\(i\\). The
+/// value \\(v_j\\) is thus the product of the \\(1\\) to \\(j\\) first elements in the
+/// given list.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// []
+/// |> maths.int_cumulative_product()
+/// |> should.equal([])
+///
+/// [1, 2, 3]
+/// |> maths.int_cumulative_product()
+/// |> should.equal([1, 2, 6])
+/// }
+///
+///
+///
+///
+pub fn polar_to_cartesian(r: Float, theta: Float) -> #(Float, Float) {
+ // Calculate x and y
+ let x = r *. cos(theta)
+ let y = r *. sin(theta)
+ #(x, y)
+}
+
+///
+///
+/// The inverse cosine function:
+///
+/// \\[
+/// \forall x \in \[-1, 1\], \\; \cos^{-1}{(x)} = y \in \[0, \pi \]
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\[-1, 1\]\\) as input and returns a
+/// numeric value \\(y\\) that lies in the range \\(\[0, \pi \]\\) (an angle in radians).
+/// If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.acos(1.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.acos(1.1)
+/// |> should.be_error()
+///
+/// maths.acos(-1.1)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The inverse hyperbolic cosine function:
+///
+/// \\[
+/// \forall x \in [1, +\infty\), \\; \cosh^{-1}{(x)} = y \in \[0, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\[1, +\infty\)\\) as input and returns
+/// a numeric value \\(y\\) that lies in the range \\(\[0, +\infty\)\\) (an angle in radians).
+/// If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.acosh(1.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.acosh(0.0)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The inverse sine function:
+///
+/// \\[
+/// \forall x \in \[-1, 1\], \\; \sin^{-1}{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\[-1, 1\]\\) as input and returns a numeric
+/// value \\(y\\) that lies in the range \\(\[-\frac{\pi}{2}, \frac{\pi}{2}\]\\) (an angle in
+/// radians). If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.asin(0.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.asin(1.1)
+/// |> should.be_error()
+///
+/// maths.asin(-1.1)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The inverse hyperbolic sine function:
+///
+/// \\[
+/// \forall x \in \(-\infty, \infty\), \\; \sinh^{-1}{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input and
+/// returns a numeric value \\(y\\) that lies in the range \\(\(-\infty, +\infty\)\\) (an angle in
+/// radians).
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.asinh(0.0)
+/// |> should.equal(0.0)
+/// }
+///
+///
+///
+///
+/// The inverse tangent function:
+///
+/// \\[
+/// \forall x \in \(-\infty, \infty\), \\; \tan^{-1}{(x)} = y \in \[-\frac{\pi}{2}, \frac{\pi}{2}\]
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input and
+/// returns a numeric value \\(y\\) that lies in the range \\(\[-\frac{\pi}{2}, \frac{\pi}{2}\]\\)
+/// (an angle in radians).
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.atan(0.0)
+/// |> should.equal(0.0)
+/// }
+///
+///
+///
+///
+/// The inverse 2-argument tangent function:
+///
+/// \\[
+/// \text{atan2}(y, x) =
+/// \begin{cases}
+/// \tan^{-1}(\frac y x) &\text{if } x > 0, \\\\
+/// \tan^{-1}(\frac y x) + \pi &\text{if } x < 0 \text{ and } y \ge 0, \\\\
+/// \tan^{-1}(\frac y x) - \pi &\text{if } x < 0 \text{ and } y < 0, \\\\
+/// +\frac{\pi}{2} &\text{if } x = 0 \text{ and } y > 0, \\\\
+/// -\frac{\pi}{2} &\text{if } x = 0 \text{ and } y < 0, \\\\
+/// \text{undefined} &\text{if } x = 0 \text{ and } y = 0.
+/// \end{cases}
+/// \\]
+///
+/// The function returns the angle in radians from the x-axis to the line containing the
+/// origin \\(\(0, 0\)\\) and a point given as input with coordinates \\(\(x, y\)\\). The numeric
+/// value returned by \\(\text{atan2}(y, x)\\) is in the range \\(\[-\pi, \pi\]\\).
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.atan2(0.0, 0.0)
+/// |> should.equal(0.0)
+/// }
+///
+///
+///
+///
+/// The inverse hyperbolic tangent function:
+///
+/// \\[
+/// \forall x \in \(-1, 1\), \\; \tanh^{-1}{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-1, 1\)\\) as input and returns
+/// a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\) (an angle in radians).
+/// If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.atanh(0.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.atanh(1.0)
+/// |> should.be_error()
+///
+/// maths.atanh(-1.0)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The cosine function:
+///
+/// \\[
+/// \forall x \in \(-\infty, +\infty\), \\; \cos{(x)} = y \in \[-1, 1\]
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) (an angle in
+/// radians) as input and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.cos(0.0)
+/// |> should.equal(1.0)
+///
+/// maths.cos(maths.pi())
+/// |> should.equal(-1.0)
+/// }
+///
+///
+///
+///
+/// The hyperbolic cosine function:
+///
+/// \\[
+/// \forall x \in \(-\infty, \infty\), \\; \cosh{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) as input (an angle
+/// in radians) and returns a numeric value \\(y\\) that lies in the range
+/// \\(\(-\infty, \infty\)\\). If the input value is too large an overflow error might occur.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.cosh(0.0)
+/// |> should.equal(0.0)
+/// }
+///
+///
+///
+///
+/// The sine function:
+///
+/// \\[
+/// \forall x \in \(-\infty, +\infty\), \\; \sin{(x)} = y \in \[-1, 1\]
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) (an angle in
+/// radians) as input and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.sin(0.0)
+/// |> should.equal(0.0)
+///
+/// maths.sin(0.5 *. maths.pi())
+/// |> should.equal(1.0)
+/// }
+///
+///
+///
+///
+/// The hyperbolic sine function:
+///
+/// \\[
+/// \forall x \in \(-\infty, +\infty\), \\; \sinh{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input
+/// (an angle in radians) and returns a numeric value \\(y\\) that lies in the range
+/// \\(\(-\infty, +\infty\)\\). If the input value is too large an overflow error might occur.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.sinh(0.0)
+/// |> should.equal(0.0)
+/// }
+///
+///
+///
+///
+/// The tangent function:
+///
+/// \\[
+/// \forall x \in \(-\infty, +\infty\), \\; \tan{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input
+/// (an angle in radians) and returns a numeric value \\(y\\) that lies in the range
+/// \\(\(-\infty, +\infty\)\\).
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.tan(0.0)
+/// |> should.equal(0.0)
+/// }
+///
+///
+///
+///
+/// The hyperbolic tangent function:
+///
+/// \\[
+/// \forall x \in \(-\infty, \infty\), \\; \tanh{(x)} = y \in \[-1, 1\]
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) as input (an angle
+/// in radians) and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// maths.tanh(0.0)
+/// |> should.equal(0.0)
+///
+/// maths.tanh(25.0)
+/// |> should.equal(1.0)
+///
+/// maths.tanh(-25.0)
+/// |> should.equal(-1.0)
+/// }
+///
+///
+///
+///
+/// The natural logarithm function:
+///
+/// \\[
+/// \forall x \in \(0, \infty\), \\; \log_{e}{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns
+/// a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
+/// If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// maths.natural_logarithm(1.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.natural_logarithm(maths.e())
+/// |> should.equal(Ok(1.0))
+///
+/// maths.natural_logarithm(-1.0)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+///
+/// The base \\(b\\) logarithm function (computed through the "change of base" formula):
+///
+/// \\[
+/// \forall x \in \(0, \infty\) \textnormal{ and } b > 1, \\; \log_{b}{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) and a base \\(b > 1\\)
+/// as input and returns a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
+/// If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// maths.logarithm(1.0, 10.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.logarithm(maths.e(), maths.e())
+/// |> should.equal(Ok(1.0))
+///
+/// maths.logarithm(-1.0, 2.0)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+///
+/// The base-2 logarithm function:
+///
+/// \\[
+/// \forall x \in \(0, \infty), \\; \log_{2}{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns a
+/// numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
+/// If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// maths.logarithm_2(1.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.logarithm_2(2.0)
+/// |> should.equal(Ok(1.0))
+///
+/// maths.logarithm_2(-1.0)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The base-10 logarithm function:
+///
+/// \\[
+/// \forall x \in \(0, \infty), \\; \log_{10}{(x)} = y \in \(-\infty, +\infty\)
+/// \\]
+///
+/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns a
+/// numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
+/// If the input value is outside the domain of the function an error is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// maths.logarithm_10(1.0)
+/// |> should.equal(Ok(0.0))
+///
+/// maths.logarithm_10(10.0)
+/// |> should.equal(Ok(1.0))
+///
+/// maths.logarithm_10(-1.0)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The \\(n\\)'th root function: \\(y = \sqrt[n]{x} = x^{\frac{1}{n}}\\).
+///
+/// Note that the function is not defined if the input is negative (\\(x < 0\\)). An error will be
+/// returned as an imaginary number will otherwise have to be returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.nth_root(-1.0, 2)
+/// |> should.be_error()
+///
+/// maths.nth_root(1.0, 2)
+/// |> should.equal(Ok(1.0))
+///
+/// maths.nth_root(27.0, 3)
+/// |> should.equal(Ok(3.0))
+///
+/// maths.nth_root(256.0, 4)
+/// |> should.equal(Ok(4.0))
+/// }
+///
+///
+///
+///
+pub fn nth_root(x: Float, n: Int) -> Result(Float, Nil) {
+ // In the following check:
+ // 1. If x is negative then return an error as it will otherwise be an
+ // imaginary number
+ case x >=. 0.0 && n >= 1 {
+ True -> float.power(x, 1.0 /. int.to_float(n))
+ False -> Error(Nil)
+ }
+}
+
+///
+///
+/// The function rounds a float to a specific number of digits (after the decimal place or before
+/// if negative). In particular, the input \\(x\\) is rounded to the nearest integer value (at the
+/// specified digit) with ties (fractional values of 0.5) being rounded to the nearest even
+/// integer.
+///
+///
+/// Details
+///
+/// The rounding mode rounds \\(12.0654\\) to:
+/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
+/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
+/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
+/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
+///
+/// It is also possible to specify a negative number of digits. In that case, the negative
+/// number refers to the digits before the decimal point.
+/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
+/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
+/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
+///
+///
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.round_to_nearest(12.0654, 2)
+/// |> should.equal(12.07)
+/// }
+///
+///
+///
+///
+/// The function rounds a float to a specific number of digits (after the decimal place or before
+/// if negative). In particular, the input \\(x\\) is rounded to the nearest integer value (at the
+/// specified digit) with ties (fractional values of 0.5) being rounded away from zero (C/C++
+/// rounding behaviour).
+///
+///
+/// Details
+///
+/// The rounding mode rounds \\(12.0654\\) to:
+/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
+/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
+/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
+/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
+///
+/// It is also possible to specify a negative number of digits. In that case, the negative
+/// number refers to the digits before the decimal point.
+/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
+/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
+/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
+///
+///
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.round_ties_away(12.0654, 2)
+/// |> should.equal(12.07)
+/// }
+///
+///
+///
+///
+/// The function rounds a float to a specific number of digits (after the decimal place or before
+/// if negative). In particular, the input \\(x\\) is rounded to the nearest integer value (at the
+/// specified digit) with ties (fractional values of 0.5) being rounded towards \\(+\infty\\)
+/// (Java/JavaScript rounding behaviour).
+///
+///
+/// Details
+///
+/// The rounding mode rounds \\(12.0654\\) to:
+/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
+/// - \\(12.1\\) for 1 digits after the decimal point (`digits = 1`)
+/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
+/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
+///
+/// It is also possible to specify a negative number of digits. In that case, the negative
+/// number refers to the digits before the decimal point.
+/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
+/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
+/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
+///
+///
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.round_ties_up(12.0654, 2)
+/// |> should.equal(12.07)
+/// }
+///
+///
+///
+///
+/// The function rounds a float to a specific number of digits (after the decimal place or before
+/// if negative). In particular, the input \\(x\\) is rounded to the nearest integer value (at the
+/// specified digit) that is less than or equal to the absolute value of the input \\(x\\). This
+/// rounding behaviour is similar to behaviour of the Gleam stdlib `truncate` function.
+///
+///
+/// Details
+///
+/// The rounding mode rounds \\(12.0654\\) to:
+/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
+/// - \\(12.0\\) for 1 digit after the decimal point (`digits = 1`)
+/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
+/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
+///
+/// It is also possible to specify a negative number of digits. In that case, the negative
+/// number refers to the digits before the decimal point.
+/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
+/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
+/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
+///
+///
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.round_to_zero(12.0654, 2)
+/// |> should.equal(12.06)
+/// }
+///
+///
+///
+///
+/// The function rounds a float to a specific number of digits (after the decimal place or before
+/// if negative). In particular, the input \\(x\\) is rounded to the nearest integer value (at the
+/// specified digit) that is less than or equal to the input \\(x\\). This rounding behaviour is
+/// similar to behaviour of the Gleam stdlib `floor` function.
+///
+///
+/// Details
+///
+/// The rounding mode rounds \\(12.0654\\) to:
+/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
+/// - \\(12.0\\) for 1 digits after the decimal point (`digits = 1`)
+/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
+/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
+///
+/// It is also possible to specify a negative number of digits. In that case, the negative
+/// number refers to the digits before the decimal point.
+/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
+/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
+/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
+///
+///
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.round_down(12.0654, 2)
+/// |> should.equal(12.06)
+/// }
+///
+///
+///
+///
+/// The function rounds a float to a specific number of digits (after the decimal place or before
+/// if negative). In particular, the input \\(x\\) is rounded to the nearest integer value (at the
+/// specified digit) that is larger than or equal to the input \\(x\\). This rounding behaviour is
+/// similar to behaviour of the Gleam stdlib `ceiling` function.
+///
+///
+/// Details
+///
+/// The rounding mode rounds \\(12.0654\\) to:
+/// - \\(13.0\\) for 0 digits after the decimal point (`digits = 0`)
+/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
+/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
+/// - \\(12.066\\) for 3 digits after the decimal point (`digits = 3`)
+///
+/// It is also possible to specify a negative number of digits. In that case, the negative
+/// number refers to the digits before the decimal point.
+/// - \\(20.0\\) for 1 digit places before the decimal point (`digit = -1`)
+/// - \\(100.0\\) for 2 digits before the decimal point (`digits = -2`)
+/// - \\(1000.0\\) for 3 digits before the decimal point (`digits = -3`)
+///
+///
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.round_up(12.0654, 2)
+/// |> should.equal(12.07)
+/// }
+///
+///
+///
+///
+/// The function takes an input \\(x \in \mathbb{R}\\) and returns the sign of
+/// the input, indicating whether it is positive (+1.0), negative (-1.0), or
+/// zero (0.0).
+///
+///
+///
+/// The function takes an input \\(x \in \mathbb{Z}\\) and returns the sign of
+/// the input, indicating whether it is positive (+1), negative (-1), or zero
+/// (0).
+///
+///
+///
+pub fn float_copy_sign(x: Float, y: Float) -> Float {
+ case float_sign(x) == float_sign(y) {
+ // x and y have the same sign, just return x
+ True -> x
+ // x and y have different signs:
+ // - x is positive and y is negative, then flip sign of x
+ // - x is negative and y is positive, then flip sign of x
+ False -> float_flip_sign(x)
+ }
+}
+
+///
+///
+pub fn int_copy_sign(x: Int, y: Int) -> Int {
+ case int_sign(x) == int_sign(y) {
+ // x and y have the same sign, just return x
+ True -> x
+ // x and y have different signs:
+ // - x is positive and y is negative, then flip sign of x
+ // - x is negative and y is positive, then flip sign of x
+ False -> int_flip_sign(x)
+ }
+}
+
+///
+///
+/// The minmax function takes two arguments \\(x, y\\) along with a function
+/// for comparing \\(x, y\\). The function returns a tuple with the smallest
+/// value first and largest second.
+///
+///
+/// Example
+///
+/// import gleam/float
+/// import gleam/int
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.minmax(2.0, 1.5, float.compare)
+/// |> should.equal(#(1.5, 2.0))
+///
+/// maths.minmax(1, 2, int.compare)
+/// |> should.equal(#(1, 2))
+/// }
+///
+///
+///
+///
+/// A combinatorial function for computing the number of \\(k\\)-combinations of \\(n\\) elements
+/// with repetitions:
+///
+/// \\[
+/// C^*(n, k) = \binom{n + k - 1}{k} = \frac{(n + k - 1)!}{k! (n - 1)!}
+/// \\]
+///
+/// Also known as the "stars and bars" problem in maths. Furthermore, the implementation uses an
+/// efficient iterative multiplicative formula for computing the result.
+///
+///
+/// Details
+///
+/// A \\(k\\)-combination with repetitions is a sequence of \\(k\\) elements selected from
+/// \\(n\\) elements where the order of selection does not matter and elements are allowed to
+/// repeat. For example, consider selecting 2 elements from a list of 3 elements: `["A", "B", "C"]`.
+/// In this case, possible selections are:
+/// - `["A", "A"], ["A", "B"], ["A", "C"]`
+/// - `["B", "B"], ["B", "C"], ["C", "C"]`
+///
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.combination_with_repetitions(-1, 1)
+/// |> should.be_error()
+///
+/// maths.combination_with_repetitions(2, 3)
+/// |> should.equal(Ok(4))
+///
+/// maths.combination_with_repetitions(13, 5)
+/// |> should.equal(Ok(6188))
+/// }
+///
+///
+///
+///
+/// A combinatorial function for computing the number of \\(k\\)-combinations of \\(n\\) elements
+/// without repetitions:
+///
+/// \\[
+/// C(n, k) = \binom{n}{k} = \frac{n!}{k! (n-k)!}
+/// \\]
+///
+/// Also known as "\\(n\\) choose \\(k\\)" or the binomial coefficient.
+///
+///
+///
+/// Details
+///
+/// A \\(k\\)-combination without repetition is a sequence of \\(k\\) elements selected from
+/// \\(n\\) elements where the order of selection does not matter and elements are not allowed to
+/// repeat. For example, consider selecting 2 elements from a list of 3 elements:
+/// `["A", "B", "C"]`. In this case, possible selections are:
+/// - `["A", "B"]`
+/// - `["A", "C"]`
+/// - `["B", "C"]`
+///
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.combination(-1, 1)
+/// |> should.be_error()
+///
+/// maths.combination(4, 0)
+/// |> should.equal(Ok(1))
+///
+/// maths.combination(4, 4)
+/// |> should.equal(Ok(1))
+///
+/// maths.combination(13, 5)
+/// |> should.equal(Ok(1287))
+/// }
+///
+///
+///
+///
+pub fn combination(n: Int, k: Int) -> Result(Int, Nil) {
+ case n, k {
+ _, _ if n < 0 -> Error(Nil)
+ _, _ if k < 0 -> Error(Nil)
+ _, _ if k == 0 || k == n -> Ok(1)
+ _, _ -> {
+ let min = case k < n - k {
+ True -> k
+ False -> n - k
+ }
+ Ok(
+ list.fold(list.range(1, min), 1, fn(acc, x) { acc * { n + 1 - x } / x }),
+ )
+ }
+ }
+}
+
+///
+///
+/// A combinatorial function for computing the number of \\(k\\)-permutations without
+/// repetitions:
+///
+/// \\[
+/// P(n, k) = \binom{n}{k} \cdot k! = \frac{n!}{(n - k)!}
+/// \\]
+///
+/// The implementation uses an efficient iterative multiplicative formula for computing the result.
+///
+///
+/// Details
+///
+/// A \\(k\\)-permutation without repetitions is a sequence of \\(k\\) elements selected from \
+/// \\(n\\) elements where the order of selection matters and elements are not allowed to repeat.
+/// For example, consider selecting 2 elements from a list of 3 elements: `["A", "B", "C"]`. In
+/// this case, possible selections are:
+/// - `["A", "B"], ["B", "A"]`
+/// - `["A", "C"], ["C", "A"]`
+/// - `["B", "C"], ["C", "B"]`
+///
+///
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.permutation(-1, 1)
+/// |> should.be_error()
+///
+/// maths.permutation(4, 0)
+/// |> should.equal(Ok(1))
+///
+/// maths.permutation(4, 2)
+/// |> should.equal(Ok(12))
+///
+/// maths.permutation(13, 5)
+/// |> should.equal(Ok(154_440))
+/// }
+///
+///
+///
+///
+/// A combinatorial function for computing the number of \\(k\\)-permutations with repetitions:
+///
+/// \\[
+/// P^*(n, k) = n^k
+/// \\]
+///
+///
+/// Details
+///
+/// A \\(k\\)-permutation with repetitions is a sequence of \\(k\\) elements selected from \\(n\\)
+/// elements where the order of selection matters and elements are allowed to repeat. For example,
+/// consider selecting 2 elements from a list of 3 elements: `["A", "B", "C"]`. In this case,
+/// possible selections are:
+/// - `["A", "A"], ["A", "B"], ["A", "C"]`
+/// - `["B", "A"], ["B", "B"], ["B", "C"]`
+/// - `["C", "A"], ["C", "B"], ["C", "C"]`
+///
+///
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.permutation_with_repetitions(1, -1)
+/// |> should.be_error()
+///
+/// maths.permutation_with_repetitions(2, 3)
+/// |> should.equal(Ok(8))
+///
+/// maths.permutation_with_repetitions(4, 4)
+/// |> should.equal(Ok(256))
+///
+/// maths.permutation_with_repetitions(6, 3)
+/// |> should.equal(Ok(216))
+/// }
+///
+///
+///
+///
+/// Generates all possible combinations of \\(k\\) elements selected from a given list of size
+/// \\(n\\). The function handles the case without repetitions, that is, repeated elements
+/// are not treated as distinct.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// // All 2-combinations of [1, 2, 3] without repetition
+/// let assert Ok(combinations) = maths.list_combination([1, 2, 3], 2)
+///
+/// combinations
+/// |> yielder.to_list()
+/// |> should.equal([[1, 2], [1, 3], [2, 3]])
+/// }
+///
+///
+///
+///
+/// Generates all possible combinations of \\(k\\) elements selected from a given list of size
+/// \\(n\\). The function handles the case when the repetition of elements is allowed, that is,
+/// repeated elements are treated as distinct.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// // All 2-combinations of [1, 2, 3] with repetition
+/// let assert Ok(combinations) =
+/// maths.list_combination_with_repetitions([1, 2, 3], 2)
+///
+/// combinations
+/// |> yielder.to_list()
+/// |> should.equal([[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]])
+/// }
+///
+///
+///
+///
+/// Generates all possible permutations of \\(k\\) elements selected from a given list of size
+/// \\(n\\). The function handles the case without repetitions, that is, repeated elements are
+/// not treated as distinct.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// // All 2-permutations of [1, 2] without repetition
+/// let assert Ok(permutations) =
+/// [1, 2]
+/// |> maths.list_permutation(2)
+/// permutations
+/// |> yielder.to_list()
+/// |> should.equal([[1, 2], [2, 1]])
+/// }
+///
+///
+///
+///
+/// Generates all possible permutations of \\(k\\) elements selected from a given list of size
+/// \\(n\\). The function handles the case when the repetition of elements is allowed, that is,
+/// repeated elements are treated as distinct.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// // All 2-permutations of [1, 2] with repetition
+/// let assert Ok(permutations) =
+/// [1, 2]
+/// |> maths.list_permutation_with_repetitions(2)
+/// permutations
+/// |> yielder.to_list()
+/// |> set.from_list()
+/// |> should.equal(set.from_list([[1, 1], [1, 2], [2, 2], [2, 1]]))
+/// }
+///
+///
+///
+///
+/// Calculate the \\(p\\)-norm of a list (representing a vector):
+///
+/// \\[
+/// \left( \sum_{i=1}^n \left|x_{i}\right|^{p} \right)^{\frac{1}{p}}
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the list and \\(x_i\\) is the value in
+/// the input list indexed by \\(i\\).
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// [1.0, 1.0, 1.0]
+/// |> maths.norm(1.0)
+/// |> should.equal(Ok(3.0))
+///
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+/// let assert Ok(result) =
+/// [1.0, 2.0, 3.0]
+/// |> maths.norm(2.0)
+/// result
+/// |> maths.is_close(3.7416573867739413, 0.0, tolerance)
+/// |> should.be_true()
+/// }
+///
+///
+///
+///
+/// Calculate the weighted \\(p\\)-norm of a list (representing a vector):
+///
+/// \\[
+/// \left( \sum_{i=1}^n w_{i} \left|x_{i}\right|^{p} \right)^{\frac{1}{p}}
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the list and \\(x_i\\) is the value in
+/// the input list indexed by \\(i\\), while \\(w_i \in \mathbb{R}_{+}\\) is
+/// a corresponding positive weight.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// [#(1.0, 0.5), #(1.0, 0.5), #(1.0, 0.5)]
+/// |> maths.norm_with_weights(1.0)
+/// |> should.equal(Ok(1.5))
+///
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+/// let assert Ok(result) =
+/// [#(1.0, 0.5), #(2.0, 0.5), #(3.0, 0.5)]
+/// |> maths.norm_with_weights(2.0)
+/// result
+/// |> maths.is_close(2.6457513110645907, 0.0, tolerance)
+/// |> should.be_true()
+/// }
+///
+///
+///
+///
+/// Calculate the weighted Manhattan distance between two lists (representing
+/// vectors):
+///
+/// \\[
+/// \sum_{i=1}^n w_{i} \left|x_i - y_i \right|
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the two lists and \\(x_i, y_i\\) are the
+/// values in the respective input lists indexed by \\(i\\), while the
+/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.manhattan_distance_with_weights([#(1.0, 2.0, 0.5), #(2.0, 3.0, 1.0)])
+/// |> should.equal(Ok(1.5))
+/// }
+///
+///
+///
+///
+/// Calculate the Minkowski distance between two lists (representing
+/// vectors):
+///
+/// \\[
+/// \left( \sum_{i=1}^n w_{i} \left|x_i - y_i \right|^{p} \right)^{\frac{1}{p}}
+/// \\]
+///
+/// In the formula, \\(p >= 1\\) is the order, \\(n\\) is the length of the two lists
+/// and \\(x_i, y_i\\) are the values in the respective input lists indexed by \\(i\\).
+///
+/// The Minkowski distance is a generalization of the Euclidean distance
+/// (\\(p=2\\)) and the Manhattan distance (\\(p = 1\\)).
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+///
+/// let assert Ok(result) =
+/// maths.minkowski_distance([#(1.0, 2.0), #(3.0, 4.0), #(5.0, 6.0)], 4.0)
+/// result
+/// |> maths.is_close(1.3160740129524924, 0.0, tolerance)
+/// |> should.be_true()
+/// }
+///
+///
+///
+///
+/// Calculate the arithmetic mean of the elements in a list:
+///
+/// \\[
+/// \bar{x} = \frac{1}{n}\sum_{i=1}^n x_i
+/// \\]
+///
+/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
+/// is the sample point in the input list indexed by \\(i\\).
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// []
+/// |> maths.mean()
+/// |> should.be_error()
+///
+/// [1.0, 2.0, 3.0]
+/// |> maths.mean()
+/// |> should.equal(Ok(2.0))
+/// }
+///
+///
+///
+///
+/// Calculate the sample variance of the elements in a list:
+///
+/// \\[
+/// s^{2} = \frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})
+/// \\]
+///
+/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
+/// is the sample point in the input list indexed by \\(i\\).
+/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
+/// Degrees of Freedom". It is typically set to \\(d = 1\\), which gives an unbiased estimate.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// // Degrees of freedom
+/// let ddof = 1
+///
+/// []
+/// |> maths.variance(ddof)
+/// |> should.be_error()
+///
+/// [1.0, 2.0, 3.0]
+/// |> maths.variance(ddof)
+/// |> should.equal(Ok(1.0))
+/// }
+///
+///
+///
+///
+/// Calculate the sample standard deviation of the elements in a list:
+/// \\[
+/// s = \left(\frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})\right)^{\frac{1}{2}}
+/// \\]
+///
+/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
+/// is the sample point in the input list indexed by \\(i\\).
+/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
+/// Degrees of Freedom", and is typically set to \\(d = 1\\), which gives an unbiased estimate.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// // Degrees of freedom
+/// let ddof = 1
+///
+/// []
+/// |> maths.standard_deviation(ddof)
+/// |> should.be_error()
+///
+/// [1.0, 2.0, 3.0]
+/// |> maths.standard_deviation(ddof)
+/// |> should.equal(Ok(1.0))
+/// }
+///
+///
+///
+///
+/// The Jaccard index measures similarity between two sets of elements. Mathematically, the
+/// Jaccard index is defined as:
+///
+/// \\[
+/// \frac{|X \cap Y|}{|X \cup Y|} \\; \in \\; \left[0, 1\right]
+/// \\]
+///
+/// where:
+///
+/// - \\(X\\) and \\(Y\\) are two sets being compared
+/// - \\(|X \cap Y|\\) represents the size of the intersection of the two sets
+/// - \\(|X \cup Y|\\) denotes the size of the union of the two sets
+///
+/// The value of the Jaccard index ranges from 0 to 1, where 0 indicates that the
+/// two sets share no elements and 1 indicates that the sets are identical. The
+/// Jaccard index is a special case of the [Tversky index](#tversky_index) (with
+/// \\(\alpha=\beta=1\\)).
+///
+///
+/// Example:
+///
+/// import gleam/set
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let xset = set.from_list(["cat", "dog", "hippo", "monkey"])
+/// let yset = set.from_list(["monkey", "rhino", "ostrich", "salmon"])
+/// maths.jaccard_index(xset, yset)
+/// |> should.equal(1.0 /. 7.0)
+/// }
+///
+///
+///
+///
+/// The Sørensen-Dice coefficient measures the similarity between two sets of elements.
+/// Mathematically, the coefficient is defined as:
+///
+/// \\[
+/// \frac{2 |X \cap Y|}{|X| + |Y|} \\; \in \\; \left[0, 1\right]
+/// \\]
+///
+/// where:
+///
+/// - \\(X\\) and \\(Y\\) are two sets being compared
+/// - \\(|X \cap Y|\\) is the size of the intersection of the two sets (i.e., the
+/// number of elements common to both sets)
+/// - \\(|X|\\) and \\(|Y|\\) are the sizes of the sets \\(X\\) and \\(Y\\), respectively
+///
+/// The coefficient ranges from 0 to 1, where 0 indicates no similarity (the sets
+/// share no elements) and 1 indicates perfect similarity (the sets are identical).
+/// The higher the coefficient, the greater the similarity between the two sets.
+/// The Sørensen-Dice coefficient is a special case of the
+/// [Tversky index](#tversky_index) (with \\(\alpha=\beta=0.5\\)).
+///
+///
+/// Example:
+///
+/// import gleam/set
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let xset = set.from_list(["cat", "dog", "hippo", "monkey"])
+/// let yset = set.from_list(["monkey", "rhino", "ostrich", "salmon", "spider"])
+/// maths.sorensen_dice_coefficient(xset, yset)
+/// |> should.equal(2.0 *. 1.0 /. { 4.0 +. 5.0 })
+/// }
+///
+///
+///
+///
+/// The Tversky index is a generalization of the Jaccard index and Sørensen-Dice
+/// coefficient, which adds flexibility in measuring similarity between two sets using two
+/// parameters, \\(\alpha\\) and \\(\beta\\). These parameters allow for asymmetric
+/// similarity measures between sets. The Tversky index is defined as:
+///
+/// \\[
+/// \frac{|X \cap Y|}{|X \cap Y| + \alpha|X - Y| + \beta|Y - X|}
+/// \\]
+///
+/// where:
+///
+/// - \\(X\\) and \\(Y\\) are the sets being compared
+/// - \\(|X - Y|\\) and \\(|Y - X|\\) are the sizes of the relative complements of
+/// \\(Y\\) in \\(X\\) and \\(X\\) in \\(Y\\), respectively,
+/// - \\(\alpha\\) and \\(\beta\\) are parameters that weight the relative importance
+/// of the elements unique to \\(X\\) and \\(Y\\)
+///
+/// The Tversky index reduces to the Jaccard index when \\(\alpha = \beta = 1\\) and
+/// to the Sørensen-Dice coefficient when \\(\alpha = \beta = 0.5\\). In general, the
+/// Tversky index can take on any non-negative value, including 0. The index equals
+/// 0 when there is no intersection between the two sets, indicating no similarity.
+/// The Tversky index does not have a strict upper limit of 1 when \\(\alpha \neq \beta\\).
+///
+///
+/// Example:
+///
+/// import gleam/set
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let yset = set.from_list(["cat", "dog", "hippo", "monkey"])
+/// let xset = set.from_list(["monkey", "rhino", "ostrich", "salmon"])
+/// // Test Jaccard index (alpha = beta = 1)
+/// maths.tversky_index(xset, yset, 1.0, 1.0)
+/// |> should.equal(Ok(1.0 /. 7.0))
+/// }
+///
+///
+///
+///
+/// The Overlap coefficient, also known as the Szymkiewicz–Simpson coefficient, is
+/// a measure of similarity between two sets that focuses on the size of the
+/// intersection relative to the smaller of the two sets. It is defined
+/// mathematically as:
+///
+/// \\[
+/// \frac{|X \cap Y|}{\min(|X|, |Y|)} \\; \in \\; \left[0, 1\right]
+/// \\]
+///
+/// where:
+///
+/// - \\(X\\) and \\(Y\\) are the sets being compared
+/// - \\(|X \cap Y|\\) is the size of the intersection of the sets
+/// - \\(\min(|X|, |Y|)\\) is the size of the smaller set among \\(X\\) and \\(Y\\)
+///
+/// The coefficient ranges from 0 to 1, where 0 indicates no overlap and 1
+/// indicates that the smaller set is a suyset of the larger set. This
+/// measure is especially useful in situations where the similarity in terms
+/// of the proportion of overlap is more relevant than the difference in sizes
+/// between the two sets.
+///
+///
+/// Example:
+///
+/// import gleam/set
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let set_a = set.from_list(["horse", "dog", "hippo", "monkey", "bird"])
+/// let set_b = set.from_list(["monkey", "bird", "ostrich", "salmon"])
+/// maths.overlap_coefficient(set_a, set_b)
+/// |> should.equal(2.0 /. 4.0)
+/// }
+///
+///
+///
+///
+/// Calculate the cosine similarity between two lists (representing
+/// vectors):
+///
+/// \\[
+/// \frac{\sum_{i=1}^n x_i \cdot y_i}
+/// {\left(\sum_{i=1}^n x_i^2\right)^{\frac{1}{2}}
+/// \cdot
+/// \left(\sum_{i=1}^n y_i^2\right)^{\frac{1}{2}}}
+/// \\; \in \\; \left[-1, 1\right]
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the two lists and \\(x_i\\), \\(y_i\\) are
+/// the values in the respective input lists indexed by \\(i\\).
+///
+/// The cosine similarity provides a value between -1 and 1, where 1 means the
+/// vectors are in the same direction, -1 means they are in exactly opposite
+/// directions, and 0 indicates orthogonality.
+///
+///
+/// Example:
+///
+/// import gleam/option
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// // Two orthogonal vectors
+/// maths.cosine_similarity([#(-1.0, 1.0), #(1.0, 1.0), #(0.0, -1.0)])
+/// |> should.equal(Ok(0.0))
+///
+/// // Two identical (parallel) vectors
+/// maths.cosine_similarity([#(1.0, 1.0), #(2.0, 2.0), #(3.0, 3.0)])
+/// |> should.equal(Ok(1.0))
+///
+/// // Two parallel, but oppositely oriented vectors
+/// maths.cosine_similarity([#(-1.0, 1.0), #(-2.0, 2.0), #(-3.0, 3.0)])
+/// |> should.equal(Ok(-1.0))
+/// }
+///
+///
+///
+///
+/// Calculate the Bray-Curtis distance between two lists:
+///
+/// \\[
+/// \frac{\sum_{i=1}^n \left| x_i - y_i \right|}
+/// {\sum_{i=1}^n \left| x_i + y_i \right|}
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the two lists, and \\(x_i, y_i\\) are the values
+/// in the respective input lists indexed by \\(i\\).
+///
+/// The Bray-Curtis distance is in the range \\([0, 1]\\) if all entries \\(x_i, y_i\\) are
+/// positive.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.canberra_distance([])
+/// |> should.be_error()
+///
+/// maths.canberra_distance_with_weights([#(1.0, -2.0, 0.5), #(2.0, -1.0, 1.0)])
+/// |> should.equal(Ok(1.5))
+/// }
+///
+///
+///
+///
+/// Calculate the weighted Bray-Curtis distance between two lists:
+///
+/// \\[
+/// \frac{\sum_{i=1}^n w_{i} \left| x_i - y_i \right|}
+/// {\sum_{i=1}^n w_{i}\left| x_i + y_i \right|}
+/// \\]
+///
+/// In the formula, \\(n\\) is the length of the two lists, and \\(x_i, y_i\\) are the values
+/// in the respective input lists indexed by \\(i\\), while the
+/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights.
+///
+/// The Bray-Curtis distance is in the range \\([0, 1]\\) if all entries \\(x_i, y_i\\) are
+/// positive and \\(w_i = 1.0\\;\forall i=1...n\\).
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.braycurtis_distance_with_weights([])
+/// |> should.be_error()
+///
+/// maths.braycurtis_distance_with_weights([#(1.0, 3.0, 0.5), #(2.0, 4.0, 1.0)])
+/// |> should.equal(Ok(0.375))
+/// }
+///
+///
+///
+///
+/// Determine if a given value \\(x\\) is close to or equivalent to a reference value
+/// \\(y\\) based on supplied relative \\(r_{tol}\\) and absolute \\(a_{tol}\\) tolerance
+/// values. The equivalance of the two given values are then determined based on
+/// the equation:
+///
+/// \\[
+/// \|x - y\| \leq (a_{tol} + r_{tol} \cdot \|y\|)
+/// \\]
+///
+/// `True` is returned if the statement holds, otherwise `False` is returned.
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let value = 99.
+/// let reference_value = 100.
+/// // We set 'absolute_tolerance' and 'relative_tolerance' such that the values are
+/// // equivalent if 'value' is within 1 percent of 'reference_value' +/- 0.1
+/// let relative_tolerance = 0.01
+/// let absolute_tolerance = 0.10
+/// maths.is_close(value, reference_value, relative_tolerance, absolute_tolerance)
+/// |> should.be_true()
+/// }
+///
+///
+///
+///
+/// Determine if each value \\(x_i\\) is close to or equivalent to its corresponding reference value
+/// \\(y_i\\), in a list of value pairs \\((x_i, y_i)\\), based on supplied relative \\(r_{tol}\\)
+/// and absolute \\(a_{tol}\\) tolerance values. The equivalence of each pair \\((x_i, y_i)\\) is
+/// determined by the equation:
+///
+/// \\[
+/// \|x_i - y_i\| \leq (a_{tol} + r_{tol} \cdot \|y_i\|), \\; \forall i=1,...,n.
+/// \\]
+///
+/// A list of `Bool` values is returned, where each entry indicates if the corresponding pair
+/// satisfies the condition. If all conditions are satisfied, the list will contain only `True`
+/// values.
+///
+///
+/// Example:
+///
+/// import gleam/list
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let value = 99.0
+/// let reference_value = 100.0
+/// let xarr = list.repeat(value, 42)
+/// let yarr = list.repeat(reference_value, 42)
+/// let arr = list.zip(xarr, yarr)
+/// // We set 'absolute_tolerance' and 'relative_tolerance' such that
+/// // the values are equivalent if 'value' is within 1 percent of
+/// // 'reference_value' +/- 0.1
+/// let relative_tolerance = 0.01
+/// let absolute_tolerance = 0.1
+/// let assert Ok(result) =
+/// maths.all_close(arr, relative_tolerance, absolute_tolerance)
+/// result
+/// |> list.all(fn(x) { x == True })
+/// |> should.be_true()
+/// }
+///
+///
+///
+///
+/// Determine if a given value \\(x\\) is fractional, i.e., if it contains a fractional part:
+///
+/// \\[
+/// x - \lfloor x \rfloor > 0
+/// \\]
+///
+/// `True` is returned if the given value is fractional (i.e., it has a non-zero decimal part),
+/// otherwise `False` is returned.
+///
+///
+/// Example
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// maths.is_fractional(0.3333)
+/// |> should.equal(True)
+///
+/// maths.is_fractional(1.0)
+/// |> should.equal(False)
+/// }
+///
+///
+///
+///
+/// A function that determines if a given integer value \\(x \in \mathbb{Z}\\) is a power of
+/// another integer value \\(y \in \mathbb{Z}\\), i.e., the function evaluates whether \\(x\\) can
+/// be expressed as \\(y^n\\) for some integer \\(n \geq 0\\), by computing the base-\\(y\\)
+/// logarithm of \\(x\\):
+///
+/// \\[
+/// n = \log_y(x)
+/// \\]
+///
+/// If \\(n\\) is an integer (i.e., it has no fractional part), then \\(x\\) is a power of \\(y\\)
+/// and `True` is returned. Otherwise `False` is returned.
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// // Check if 4 is a power of 2 (it is)
+/// maths.is_power(4, 2)
+/// |> should.equal(True)
+///
+/// // Check if 5 is a power of 2 (it is not)
+/// maths.is_power(5, 2)
+/// |> should.equal(False)
+/// }
+///
+///
+///
+///
+/// A function that tests whether a given integer value \\(n \in \mathbb{Z}\\) is a
+/// perfect number. A number is perfect if it is equal to the sum of its proper
+/// positive divisors.
+///
+///
+/// Details
+///
+/// For example:
+/// - \\(6\\) is a perfect number since the divisors of 6 are \\(1 + 2 + 3 = 6\\).
+/// - \\(28\\) is a perfect number since the divisors of 28 are \\(1 + 2 + 4 + 7 + 14 = 28\\).
+///
+///
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.is_perfect(6)
+/// |> should.equal(True)
+///
+/// maths.is_perfect(28)
+/// |> should.equal(True)
+/// }
+///
+///
+///
+///
+/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is a
+/// prime number. A prime number is a natural number greater than 1 that has no
+/// positive divisors other than 1 and itself.
+///
+/// The function uses the Miller-Rabin primality test to assess if \\(x\\) is prime.
+/// It is a probabilistic test, so it can mistakenly identify a composite number
+/// as prime. However, the probability of such errors decreases with more testing
+/// iterations (the function uses 64 iterations internally, which is typically
+/// more than sufficient). The Miller-Rabin test is particularly useful for large
+/// numbers.
+///
+///
+/// Details
+///
+/// Examples of prime numbers:
+/// - \\(2\\) is a prime number since it has only two divisors: \\(1\\) and \\(2\\).
+/// - \\(7\\) is a prime number since it has only two divisors: \\(1\\) and \\(7\\).
+/// - \\(4\\) is not a prime number since it has divisors other than \\(1\\) and itself, such
+/// as \\(2\\).
+///
+///
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.is_prime(2)
+/// |> should.equal(True)
+///
+/// maths.is_prime(4)
+/// |> should.equal(False)
+///
+/// // Test the 2nd Carmichael number
+/// maths.is_prime(1105)
+/// |> should.equal(False)
+/// }
+///
+///
+///
+///
+/// A function that tests whether a given integer \\(m \in \mathbb{Z}\\) is a multiple of another
+/// integer \\(k \in \mathbb{Z}\\), such that \\(m = k \cdot q\\), with \\(q \in \mathbb{Z}\\).
+///
+///
+/// Details
+///
+/// For example:
+/// - \\(m = 15\\) is a multiple of \\(k = 5\\) because \\(15 = 5 \cdot 3\\).
+/// - \\(m = 14\\) is not a multiple of \\(k = 5\\) because \\(\frac{14}{5}\\) does not yield an
+/// integer quotient.
+///
+///
+///
+///
+/// Example:
+///
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// maths.is_multiple(15, 5)
+/// |> should.equal(True)
+///
+/// maths.is_multiple(14, 5)
+/// |> should.equal(False)
+/// }
+///
+///
+///
+///
+/// The beta function over the real numbers:
+///
+/// \\[
+/// \text{B}(x, y) = \frac{\Gamma(x) \cdot \Gamma(y)}{\Gamma(x + y)}
+/// \\]
+///
+/// The beta function is evaluated through the use of the gamma function.
+///
+///
+///
+pub fn erf(x: Float) -> Float {
+ let assert [a1, a2, a3, a4, a5] = [
+ 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429,
+ ]
+ let p = 0.3275911
+
+ let sign = float_sign(x)
+ let x = float.absolute_value(x)
+
+ // Formula 7.1.26 given in Abramowitz and Stegun.
+ let t = 1.0 /. { 1.0 +. p *. x }
+ let y =
+ 1.0
+ -. { { { { a5 *. t +. a4 } *. t +. a3 } *. t +. a2 } *. t +. a1 }
+ *. t
+ *. exponential(-1.0 *. x *. x)
+ sign *. y
+}
+
+///
+///
+/// The gamma function over the real numbers. The function is essentially equal to
+/// the factorial for any positive integer argument: \\(\Gamma(n) = (n - 1)!\\)
+///
+/// The implemented gamma function is approximated through Lanczos approximation
+/// using the same coefficients used by the GNU Scientific Library.
+///
+///
+///
+/// The lower incomplete gamma function over the real numbers.
+///
+/// The implemented incomplete gamma function is evaluated through a power series
+/// expansion.
+///
+///
+///
+/// The function returns an iterator generating evenly spaced values within a specified interval
+/// `[start, stop)` based on a given increment size.
+///
+/// Note that if `increment > 0`, the sequence progresses from `start` towards `stop`, while if
+/// `increment < 0`, the sequence progresses from `start` towards `stop` in reverse.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// maths.arange(1.0, 5.0, 1.0)
+/// |> yielder.to_list()
+/// |> should.equal([1.0, 2.0, 3.0, 4.0])
+///
+/// // No points returned since
+/// // start is smaller than stop and the step is positive
+/// maths.arange(5.0, 1.0, 1.0)
+/// |> yielder.to_list()
+/// |> should.equal([])
+///
+/// // Points returned since
+/// // start smaller than stop but negative step
+/// maths.arange(5.0, 1.0, -1.0)
+/// |> yielder.to_list()
+/// |> should.equal([5.0, 4.0, 3.0, 2.0])
+/// }
+///
+///
+///
+///
+/// The function returns an iterator for generating linearly spaced points over a specified
+/// interval. The endpoint of the interval can optionally be included/excluded. The number of
+/// points and whether the endpoint is included determine the spacing between values.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+/// let assert Ok(linspace) = maths.linear_space(10.0, 20.0, 5, True)
+/// let pairs =
+/// linspace |> yielder.to_list() |> list.zip([10.0, 12.5, 15.0, 17.5, 20.0])
+/// let assert Ok(result) = maths.all_close(pairs, 0.0, tolerance)
+/// result
+/// |> list.all(fn(x) { x == True })
+/// |> should.be_true()
+///
+/// // A negative number of points (-5) does not work
+/// maths.linear_space(10.0, 50.0, -5, True)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The function returns an iterator for generating logarithmically spaced points over a specified
+/// interval. The endpoint of the interval can optionally be included/excluded. The number of
+/// points, base, and whether the endpoint is included determine the spacing between values.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+/// let assert Ok(logspace) = maths.logarithmic_space(1.0, 3.0, 3, True, 10.0)
+/// let pairs = logspace |> yielder.to_list() |> list.zip([10.0, 100.0, 1000.0])
+/// let assert Ok(result) = maths.all_close(pairs, 0.0, tolerance)
+/// result
+/// |> list.all(fn(x) { x == True })
+/// |> should.be_true()
+///
+/// // A negative number of points (-3) does not work
+/// maths.logarithmic_space(1.0, 3.0, -3, False, 10.0)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The function returns an iterator of numbers spaced evenly on a log scale (a geometric
+/// progression). Each point in the list is a constant multiple of the previous. The function is
+/// similar to the [`logarithmic_space`](#logarithmic_space) function, but with endpoints
+/// specified directly.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example () {
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+/// let assert Ok(logspace) = maths.geometric_space(10.0, 1000.0, 3, True)
+/// let pairs = logspace |> yielder.to_list() |> list.zip([10.0, 100.0, 1000.0])
+/// let assert Ok(result) = maths.all_close(pairs, 0.0, tolerance)
+/// result
+/// |> list.all(fn(x) { x == True })
+/// |> should.be_true()
+///
+/// // Input (start and stop can't be equal to 0.0)
+/// maths.geometric_space(0.0, 1000.0, 3, False)
+/// |> should.be_error()
+///
+/// maths.geometric_space(-1000.0, 0.0, 3, False)
+/// |> should.be_error()
+///
+/// // A negative number of points (-3) does not work
+/// maths.geometric_space(10.0, 1000.0, -3, False)
+/// |> should.be_error()
+/// }
+///
+///
+///
+///
+/// The function returns an iterator of exponentially spaced points over a specified interval. The
+/// endpoint of the interval can optionally be included/excluded. The number of points and whether
+/// the endpoint is included determine the spacing between values. The sequence is generated by
+/// computing intermediate values in a logarithmic domain and transforming them into the exponential
+/// domain.
+///
+///
+/// Example:
+///
+/// import gleam/yielder
+/// import gleeunit/should
+/// import gleam_community/maths
+///
+/// pub fn example() {
+/// let assert Ok(tolerance) = float.power(10.0, -6.0)
+/// let assert Ok(exp_space) = maths.exponential_space(1.0, 1000.0, 4, True)
+/// let expected = [1.0, 10.0, 100.0, 1000.0]
+/// let pairs = exp_space |> yielder.to_list() |> list.zip(expected)
+/// let assert Ok(result) = maths.all_close(pairs, 0.0, tolerance)
+/// result |> list.all(fn(x) { x == True }) |> should.be_true()
+/// }
+///
+///
+///
-///
-/// The function calculates the greatest common divisor of two integers
-/// \\(x, y \in \mathbb{Z}\\). The greatest common divisor is the largest positive
-/// integer that is divisible by both \\(x\\) and \\(y\\).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example() {
-/// arithmetics.gcd(1, 1)
-/// |> should.equal(1)
-///
-/// arithmetics.gcd(100, 10)
-/// |> should.equal(10)
-///
-/// arithmetics.gcd(-36, -17)
-/// |> should.equal(1)
-/// }
-///
-///
-///
-///
-///
-/// Given two integers, \\(x\\) (dividend) and \\(y\\) (divisor), the Euclidean modulo
-/// of \\(x\\) by \\(y\\), denoted as \\(x \mod y\\), is the remainder \\(r\\) of the
-/// division of \\(x\\) by \\(y\\), such that:
-///
-/// \\[
-/// x = q \cdot y + r \quad \text{and} \quad 0 \leq r < |y|,
-/// \\]
-///
-/// where \\(q\\) is an integer that represents the quotient of the division.
-///
-/// The Euclidean modulo function of two numbers, is the remainder operation most
-/// commonly utilized in mathematics. This differs from the standard truncating
-/// modulo operation frequently employed in programming via the `%` operator.
-/// Unlike the `%` operator, which may return negative results depending on the
-/// divisor's sign, the Euclidean modulo function is designed to always yield a
-/// positive outcome, ensuring consistency with mathematical conventions.
-///
-/// Note that like the Gleam division operator `/` this will return `0` if one of
-/// the arguments is `0`.
-///
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example() {
-/// arithmetics.euclidean_modulo(15, 4)
-/// |> should.equal(3)
-///
-/// arithmetics.euclidean_modulo(-3, -2)
-/// |> should.equal(1)
-///
-/// arithmetics.euclidean_modulo(5, 0)
-/// |> should.equal(0)
-/// }
-///
-///
-///
-///
-/// The function calculates the least common multiple of two integers
-/// \\(x, y \in \mathbb{Z}\\). The least common multiple is the smallest positive
-/// integer that has both \\(x\\) and \\(y\\) as factors.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example() {
-/// arithmetics.lcm(1, 1)
-/// |> should.equal(1)
-///
-/// arithmetics.lcm(100, 10)
-/// |> should.equal(100)
-///
-/// arithmetics.lcm(-36, -17)
-/// |> should.equal(612)
-/// }
-///
-///
-///
-///
-/// Calculate the (weighted) sum of the elements in a list:
-///
-/// \\[
-/// \sum_{i=1}^n w_i x_i
-/// \\]
-///
-/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\) is
-/// the value in the input list indexed by \\(i\\), while the \\(w_i \in \mathbb{R}\\)
-/// are corresponding weights (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// // An empty list returns an error
-/// []
-/// |> arithmetics.float_sum(option.None)
-/// |> should.equal(0.0)
-///
-/// // Valid input returns a result
-/// [1.0, 2.0, 3.0]
-/// |> arithmetics.float_sum(option.None)
-/// |> should.equal(6.0)
-/// }
-///
-///
-///
-///
-/// Calculate the sum of the elements in a list:
-///
-/// \\[
-/// \sum_{i=1}^n x_i
-/// \\]
-///
-/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{Z}\\) is
-/// the value in the input list indexed by \\(i\\).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// // An empty list returns 0
-/// []
-/// |> arithmetics.int_sum()
-/// |> should.equal(0)
-///
-/// // Valid input returns a result
-/// [1, 2, 3]
-/// |> arithmetics.int_sum()
-/// |> should.equal(6)
-/// }
-///
-///
-///
-///
-/// Calculate the (weighted) product of the elements in a list:
-///
-/// \\[
-/// \prod_{i=1}^n x_i^{w_i}
-/// \\]
-///
-/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\) is
-/// the value in the input list indexed by \\(i\\), while the \\(w_i \in \mathbb{R}\\)
-/// are corresponding weights (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// // An empty list returns 1.0
-/// []
-/// |> arithmetics.float_product(option.None)
-/// |> should.equal(1.0)
-///
-/// // Valid input returns a result
-/// [1.0, 2.0, 3.0]
-/// |> arithmetics.float_product(option.None)
-/// |> should.equal(6.0)
-/// }
-///
-///
-///
-///
-/// Calculate the product of the elements in a list:
-///
-/// \\[
-/// \prod_{i=1}^n x_i
-/// \\]
-///
-/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{Z}\\) is
-/// the value in the input list indexed by \\(i\\).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// // An empty list returns 1
-/// []
-/// |> arithmetics.int_product()
-/// |> should.equal(1)
-///
-/// // Valid input returns a result
-/// [1, 2, 3]
-/// |> arithmetics.int_product()
-/// |> should.equal(6)
-/// }
-///
-///
-///
-///
-/// Calculate the cumulative sum of the elements in a list:
-///
-/// \\[
-/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
-/// \\]
-///
-/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(n\\)
-/// elements. That is, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\)
-/// is the value in the input list indexed by \\(i\\). The value \\(v_j\\) is thus the
-/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// []
-/// |> arithmetics.float_cumulative_sum()
-/// |> should.equal([])
-///
-/// // Valid input returns a result
-/// [1.0, 2.0, 3.0]
-/// |> arithmetics.float_cumulative_sum()
-/// |> should.equal([1.0, 3.0, 6.0])
-/// }
-///
-///
-///
-///
-/// Calculate the cumulative sum of the elements in a list:
-///
-/// \\[
-/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
-/// \\]
-///
-/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(n\\)
-/// elements. That is, \\(n\\) is the length of the list and \\(x_i \in \mathbb{Z}\\)
-/// is the value in the input list indexed by \\(i\\). The value \\(v_j\\) is thus the
-/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// []
-/// |> arithmetics.int_cumulative_sum()
-/// |> should.equal([])
-///
-/// // Valid input returns a result
-/// [1, 2, 3]
-/// |> arithmetics.int_cumulative_sum()
-/// |> should.equal([1, 3, 6])
-/// }
-///
-///
-///
-///
-/// Calculate the cumulative product of the elements in a list:
-///
-/// \\[
-/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
-/// \\]
-///
-/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative product of
-/// \\(n\\) elements. That is, \\(n\\) is the length of the list and
-/// \\(x_i \in \mathbb{R}\\) is the value in the input list indexed by \\(i\\). The
-/// value \\(v_j\\) is thus the sum of the \\(1\\) to \\(j\\) first elements in the
-/// given list.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// // An empty list returns an error
-/// []
-/// |> arithmetics.float_cumulative_product()
-/// |> should.equal([])
-///
-/// // Valid input returns a result
-/// [1.0, 2.0, 3.0]
-/// |> arithmetics.float_cumulative_product()
-/// |> should.equal([1.0, 2.0, 6.0])
-/// }
-///
-///
-///
-///
-/// Calculate the cumulative product of the elements in a list:
-///
-/// \\[
-/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
-/// \\]
-///
-/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative product of
-/// \\(n\\) elements. That is, \\(n\\) is the length of the list and
-/// \\(x_i \in \mathbb{Z}\\) is the value in the input list indexed by \\(i\\). The
-/// value \\(v_j\\) is thus the product of the \\(1\\) to \\(j\\) first elements in the
-/// given list.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/arithmetics
-///
-/// pub fn example () {
-/// // An empty list returns an error
-/// []
-/// |> arithmetics.int_cumulative_product()
-/// |> should.equal([])
-///
-/// // Valid input returns a result
-/// [1, 2, 3]
-/// |> arithmetics.int_cumulative_product()
-/// |> should.equal([1, 2, 6])
-/// }
-///
-///
-///
-///
-/// A combinatorial function for computing the number of \\(k\\)-combinations of \\(n\\) elements.
-///
-/// **Without Repetitions:**
-///
-/// \\[
-/// C(n, k) = \binom{n}{k} = \frac{n!}{k! (n-k)!}
-/// \\]
-/// Also known as "\\(n\\) choose \\(k\\)" or the binomial coefficient.
-///
-/// **With Repetitions:**
-///
-/// \\[
-/// C^*(n, k) = \binom{n + k - 1}{k} = \frac{(n + k - 1)!}{k! (n - 1)!}
-/// \\]
-/// Also known as the "stars and bars" problem in combinatorics.
-///
-/// The implementation uses an efficient iterative multiplicative formula for computing the result.
-///
-///
-/// Details
-///
-/// A \\(k\\)-combination is a sequence of \\(k\\) elements selected from \\(n\\) elements where
-/// the order of selection does not matter. For example, consider selecting 2 elements from a list
-/// of 3 elements: `["A", "B", "C"]`:
-///
-/// - For \\(k\\)-combinations (without repetitions), where order does not matter, the possible
-/// selections are:
-/// - `["A", "B"]`
-/// - `["A", "C"]`
-/// - `["B", "C"]`
-///
-/// - For \\(k\\)-combinations (with repetitions), where order does not matter but elements can
-/// repeat, the possible selections are:
-/// - `["A", "A"], ["A", "B"], ["A", "C"]`
-/// - `["B", "B"], ["B", "C"], ["C", "C"]`
-///
-/// - On the contrary, for \\(k\\)-permutations (without repetitions), the order matters, so the
-/// possible selections are:
-/// - `["A", "B"], ["B", "A"]`
-/// - `["A", "C"], ["C", "A"]`
-/// - `["B", "C"], ["C", "B"]`
-///
-///
-/// Example:
-///
-/// import gleam/option
-/// import gleeunit/should
-/// import gleam_community/maths/combinatorics
-///
-/// pub fn example() {
-/// // Invalid input gives an error
-/// combinatorics.combination(-1, 1, option.None)
-/// |> should.be_error()
-///
-/// // Valid input: n = 4 and k = 0
-/// combinatorics.combination(4, 0, option.Some(combinatorics.WithoutRepetitions))
-/// |> should.equal(Ok(1))
-///
-/// // Valid input: k = n (n = 4, k = 4)
-/// combinatorics.combination(4, 4, option.Some(combinatorics.WithoutRepetitions))
-/// |> should.equal(Ok(1))
-///
-/// // Valid input: combinations with repetition (n = 2, k = 3)
-/// combinatorics.combination(2, 3, option.Some(combinatorics.WithRepetitions))
-/// |> should.equal(Ok(4))
-///
-///
-///
-///
-/// A combinatorial function for computing the number of \\(k\\)-permutations.
-///
-/// **Without** repetitions:
-///
-/// \\[
-/// P(n, k) = \binom{n}{k} \cdot k! = \frac{n!}{(n - k)!}
-/// \\]
-///
-/// **With** repetitions:
-///
-/// \\[
-/// P^*(n, k) = n^k
-/// \\]
-///
-/// The implementation uses an efficient iterative multiplicative formula for computing the result.
-///
-///
-/// Details
-///
-/// A \\(k\\)-permutation (without repetitions) is a sequence of \\(k\\) elements selected from \
-/// \\(n\\) elements where the order of selection matters. For example, consider selecting 2
-/// elements from a list of 3 elements: `["A", "B", "C"]`:
-///
-/// - For \\(k\\)-permutations (without repetitions), the order matters, so the possible selections
-/// are:
-/// - `["A", "B"], ["B", "A"]`
-/// - `["A", "C"], ["C", "A"]`
-/// - `["B", "C"], ["C", "B"]`
-///
-/// - For \\(k\\)-permutations (with repetitions), the order also matters, but we have repeated
-/// selections:
-/// - `["A", "A"], ["A", "B"], ["A", "C"]`
-/// - `["B", "A"], ["B", "B"], ["B", "C"]`
-/// - `["C", "A"], ["C", "B"], ["C", "C"]`
-///
-/// - On the contrary, for \\(k\\)-combinations (without repetitions), where order does not matter,
-/// the possible selections are:
-/// - `["A", "B"]`
-/// - `["A", "C"]`
-/// - `["B", "C"]`
-///
-///
-///
-/// Example:
-///
-/// import gleam/option
-/// import gleeunit/should
-/// import gleam_community/maths/combinatorics
-///
-/// pub fn example() {
-/// // Invalid input gives an error
-/// combinatorics.permutation(-1, 1, option.None)
-/// |> should.be_error()
-///
-/// // Valid input returns a result (n = 4, k = 0)
-/// combinatorics.permutation(4, 0, option.Some(combinatorics.WithoutRepetitions))
-/// |> should.equal(Ok(1))
-///
-/// // Valid input returns the correct number of permutations (n = 4, k = 2)
-/// combinatorics.permutation(4, 2, option.Some(combinatorics.WithoutRepetitions))
-/// |> should.equal(Ok(12))
-/// }
-///
-///
-///
-///
-/// Generates all possible combinations of \\(k\\) elements selected from a given list of size
-/// \\(n\\).
-///
-/// The function can handle cases with and without repetitions
-/// (see more details [here](#combination)). Also, note that repeated elements are treated as
-/// distinct.
-///
-///
-/// Example:
-///
-/// import gleam/set
-/// import gleam/option
-/// import gleam/iterator
-/// import gleeunit/should
-/// import gleam_community/maths/combinatorics
-///
-/// pub fn example () {
-/// // Generate all 3-combinations without repetition
-/// let assert Ok(result) =
-/// combinatorics.list_combination(
-/// [1, 2, 3, 4],
-/// 3,
-/// option.Some(combinatorics.WithoutRepetitions),
-/// )
-///
-/// result
-/// |> iterator.to_list()
-/// |> set.from_list()
-/// |> should.equal(set.from_list([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]))
-/// }
-///
-///
-///
-///
-/// A function that produces a number of type `Float` from an `Int`.
-///
-/// Note: The function is equivalent to the `int.to_float` function in the Gleam stdlib.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/conversion
-///
-/// pub fn example() {
-/// conversion.int_to_float(-1)
-/// |> should.equal(-1.0)
-///
-/// conversion.int_to_float(1)
-/// |> should.equal(1.0)
-/// }
-///
-///
-///
-///
-/// The function returns the integral part of a given floating point value.
-/// That is, everything after the decimal point of a given floating point value is discarded
-/// and only the integer value before the decimal point is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/conversion
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// conversion.float_to_int(12.0654)
-/// |> should.equal(12)
-///
-/// // Note: Making the following function call is equivalent
-/// // but instead of returning a value of type 'Int' a value
-/// // of type 'Float' is returned.
-/// piecewise.round(12.0654, option.Some(0), option.Some(piecewise.RoundToZero))
-/// |> should.equal(Ok(12.0))
-/// }
-///
-///
-///
-///
-/// The inverse cosine function:
-///
-/// \\[
-/// \forall x \in \[-1, 1\], \\; \cos^{-1}{(x)} = y \in \[0, \pi \]
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\[-1, 1\]\\) as input and returns a
-/// numeric value \\(y\\) that lies in the range \\(\[0, \pi \]\\) (an angle in radians).
-/// If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.acos(1.0)
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.acos(1.1)
-/// |> should.be_error()
-///
-/// elementary.acos(-1.1)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The inverse hyperbolic cosine function:
-///
-/// \\[
-/// \forall x \in [1, +\infty\), \\; \cosh^{-1}{(x)} = y \in \[0, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\[1, +\infty\)\\) as input and returns
-/// a numeric value \\(y\\) that lies in the range \\(\[0, +\infty\)\\) (an angle in radians).
-/// If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.acosh(1.0)
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.acosh(0.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The inverse sine function:
-///
-/// \\[
-/// \forall x \in \[-1, 1\], \\; \sin^{-1}{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\[-1, 1\]\\) as input and returns a numeric
-/// value \\(y\\) that lies in the range \\(\[-\frac{\pi}{2}, \frac{\pi}{2}\]\\) (an angle in
-/// radians). If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.asin(0.0)
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.asin(1.1)
-/// |> should.be_error()
-///
-/// elementary.asin(-1.1)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The inverse hyperbolic sine function:
-///
-/// \\[
-/// \forall x \in \(-\infty, \infty\), \\; \sinh^{-1}{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input and
-/// returns a numeric value \\(y\\) that lies in the range \\(\(-\infty, +\infty\)\\) (an angle in
-/// radians).
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.asinh(0.0)
-/// |> should.equal(0.0)
-/// }
-///
-///
-///
-///
-/// The inverse tangent function:
-///
-/// \\[
-/// \forall x \in \(-\infty, \infty\), \\; \tan^{-1}{(x)} = y \in \[-\frac{\pi}{2}, \frac{\pi}{2}\]
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input and
-/// returns a numeric value \\(y\\) that lies in the range \\(\[-\frac{\pi}{2}, \frac{\pi}{2}\]\\)
-/// (an angle in radians).
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.atan(0.0)
-/// |> should.equal(0.0)
-/// }
-///
-///
-///
-///
-/// The inverse 2-argument tangent function:
-///
-/// \\[
-/// \text{atan2}(y, x) =
-/// \begin{cases}
-/// \tan^{-1}(\frac y x) &\text{if } x > 0, \\\\
-/// \tan^{-1}(\frac y x) + \pi &\text{if } x < 0 \text{ and } y \ge 0, \\\\
-/// \tan^{-1}(\frac y x) - \pi &\text{if } x < 0 \text{ and } y < 0, \\\\
-/// +\frac{\pi}{2} &\text{if } x = 0 \text{ and } y > 0, \\\\
-/// -\frac{\pi}{2} &\text{if } x = 0 \text{ and } y < 0, \\\\
-/// \text{undefined} &\text{if } x = 0 \text{ and } y = 0.
-/// \end{cases}
-/// \\]
-///
-/// The function returns the angle in radians from the x-axis to the line containing the
-/// origin \\(\(0, 0\)\\) and a point given as input with coordinates \\(\(x, y\)\\). The numeric
-/// value returned by \\(\text{atan2}(y, x)\\) is in the range \\(\[-\pi, \pi\]\\).
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.atan2(0.0, 0.0)
-/// |> should.equal(0.0)
-/// }
-///
-///
-///
-///
-/// The inverse hyperbolic tangent function:
-///
-/// \\[
-/// \forall x \in \(-1, 1\), \\; \tanh^{-1}{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-1, 1\)\\) as input and returns
-/// a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\) (an angle in radians).
-/// If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.atanh(0.0)
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.atanh(1.0)
-/// |> should.be_error()
-///
-/// elementary.atanh(-1.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The cosine function:
-///
-/// \\[
-/// \forall x \in \(-\infty, +\infty\), \\; \cos{(x)} = y \in \[-1, 1\]
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) (an angle in
-/// radians) as input and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.cos(0.0)
-/// |> should.equal(1.0)
-///
-/// elementary.cos(elementary.pi())
-/// |> should.equal(-1.0)
-/// }
-///
-///
-///
-///
-/// The hyperbolic cosine function:
-///
-/// \\[
-/// \forall x \in \(-\infty, \infty\), \\; \cosh{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) as input (an angle
-/// in radians) and returns a numeric value \\(y\\) that lies in the range
-/// \\(\(-\infty, \infty\)\\). If the input value is too large an overflow error might occur.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.cosh(0.0)
-/// |> should.equal(0.0)
-/// }
-///
-///
-///
-///
-/// The sine function:
-///
-/// \\[
-/// \forall x \in \(-\infty, +\infty\), \\; \sin{(x)} = y \in \[-1, 1\]
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) (an angle in
-/// radians) as input and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.sin(0.0)
-/// |> should.equal(0.0)
-///
-/// elementary.sin(0.5 *. elementary.pi())
-/// |> should.equal(1.0)
-/// }
-///
-///
-///
-///
-/// The hyperbolic sine function:
-///
-/// \\[
-/// \forall x \in \(-\infty, +\infty\), \\; \sinh{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input
-/// (an angle in radians) and returns a numeric value \\(y\\) that lies in the range
-/// \\(\(-\infty, +\infty\)\\). If the input value is too large an overflow error might occur.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.sinh(0.0)
-/// |> should.equal(0.0)
-/// }
-///
-///
-///
-///
-/// The tangent function:
-///
-/// \\[
-/// \forall x \in \(-\infty, +\infty\), \\; \tan{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input
-/// (an angle in radians) and returns a numeric value \\(y\\) that lies in the range
-/// \\(\(-\infty, +\infty\)\\).
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.tan(0.0)
-/// |> should.equal(0.0)
-/// }
-///
-///
-///
-///
-/// The hyperbolic tangent function:
-///
-/// \\[
-/// \forall x \in \(-\infty, \infty\), \\; \tanh{(x)} = y \in \[-1, 1\]
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) as input (an angle
-/// in radians) and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example () {
-/// elementary.tanh(0.0)
-/// |> should.equal(0.0)
-///
-/// elementary.tanh(25.0)
-/// |> should.equal(1.0)
-///
-/// elementary.tanh(-25.0)
-/// |> should.equal(-1.0)
-/// }
-///
-///
-///
-///
-/// The natural logarithm function:
-///
-/// \\[
-/// \forall x \in \(0, \infty\), \\; \log_{e}{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns
-/// a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
-/// If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example () {
-/// elementary.natural_logarithm(1.0)
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.natural_logarithm(elementary.e())
-/// |> should.equal(Ok(1.0))
-///
-/// elementary.natural_logarithm(-1.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-///
-/// The base \\(b\\) logarithm function (computed through the "change of base" formula):
-///
-/// \\[
-/// \forall x \in \(0, \infty\) \textnormal{ and } b > 1, \\; \log_{b}{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) and a base \\(b > 1\\)
-/// as input and returns a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
-/// If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/elementary
-///
-/// pub fn example () {
-/// elementary.logarithm(1.0, option.Some(10.0))
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.logarithm(elementary.e(), option.Some(elementary.e()))
-/// |> should.equal(Ok(1.0))
-///
-/// elementary.logarithm(-1.0, option.Some(2.0))
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-///
-/// The The base-2 logarithm function:
-///
-/// \\[
-/// \forall x \in \(0, \infty), \\; \log_{2}{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns a
-/// numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
-/// If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example () {
-/// elementary.logarithm_2(1.0)
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.logarithm_2(2.0)
-/// |> should.equal(Ok(1.0))
-///
-/// elementary.logarithm_2(-1.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The base-10 logarithm function:
-///
-/// \\[
-/// \forall x \in \(0, \infty), \\; \log_{10}{(x)} = y \in \(-\infty, +\infty\)
-/// \\]
-///
-/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns a
-/// numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
-/// If the input value is outside the domain of the function an error is returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example () {
-/// elementary.logarithm_10(1.0)
-/// |> should.equal(Ok(0.0))
-///
-/// elementary.logarithm_10(10.0)
-/// |> should.equal(Ok(1.0))
-///
-/// elementary.logarithm_10(-1.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The exponentiation function: \\(y = x^{a}\\).
-///
-/// Note that the function is not defined if:
-/// 1. The base is negative (\\(x < 0\\)) and the exponent is fractional
-/// (\\(a = \frac{n}{m}\\) is an irrreducible fraction). An error will be returned
-/// as an imaginary number will otherwise have to be returned.
-/// 2. The base is zero (\\(x = 0\\)) and the exponent is negative (\\(a < 0\\)) then the
-/// expression is equivalent to the exponent \\(y\\) divided by \\(0\\) and an
-/// error will have to be returned as the expression is otherwise undefined.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.power(2., -1.)
-/// |> should.equal(Ok(0.5))
-///
-/// elementary.power(2., 2.)
-/// |> should.equal(Ok(4.0))
-///
-/// elementary.power(-1., 0.5)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-pub fn power(x: Float, y: Float) -> Result(Float, Nil) {
- let fractional = do_ceiling(y) -. y >. 0.0
- // In the following check:
- // 1. If the base (x) is negative and the exponent (y) is fractional
- // then return an error as it will otherwise be an imaginary number
- // 2. If the base (x) is 0 and the exponent (y) is negative then the
- // expression is equivalent to the exponent (y) divided by 0 and an
- // error should be returned
- case { x <. 0.0 && fractional } || { x == 0.0 && y <. 0.0 } {
- True -> Error(Nil)
- False ->
- do_power(x, y)
- |> Ok
- }
-}
-
-@external(erlang, "math", "pow")
-@external(javascript, "../../maths.mjs", "power")
-fn do_power(a: Float, b: Float) -> Float
-
-@external(erlang, "math", "ceil")
-@external(javascript, "../../maths.mjs", "ceiling")
-fn do_ceiling(a: Float) -> Float
-
-///
-///
-/// The square root function: \\(y = \sqrt[2]{x} = x^{\frac{1}{2}}\\).
-///
-/// Note that the function is not defined if:
-/// 1. The input is negative (\\(x < 0\\)). An error will be returned
-/// as an imaginary number will otherwise have to be returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.square_root(1.0)
-/// |> should.equal(Ok(1.0))
-///
-/// elementary.square_root(4.0)
-/// |> should.equal(Ok(2.0))
-///
-/// elementary.square_root(-1.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-pub fn square_root(x: Float) -> Result(Float, Nil) {
- // In the following check:
- // 1. If x is negative then return an error as it will otherwise be an
- // imaginary number
- case x <. 0.0 {
- True -> Error(Nil)
- False -> power(x, 1.0 /. 2.0)
- }
-}
-
-///
-///
-/// The cube root function: \\(y = \sqrt[3]{x} = x^{\frac{1}{3}}\\).
-///
-/// Note that the function is not defined if:
-/// 1. The input is negative (\\(x < 0\\)). An error will be returned
-/// as an imaginary number will otherwise have to be returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.cube_root(1.0)
-/// |> should.equal(Ok(1.0))
-///
-/// elementary.cube_root(27.0)
-/// |> should.equal(Ok(3.0))
-///
-/// elementary.cube_root(-1.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-pub fn cube_root(x: Float) -> Result(Float, Nil) {
- // In the following check:
- // 1. If x is negative then return an error as it will otherwise be an
- // imaginary number
- case x <. 0.0 {
- True -> Error(Nil)
- False -> power(x, 1.0 /. 3.0)
- }
-}
-
-///
-///
-/// The \\(n\\)'th root function: \\(y = \sqrt[n]{x} = x^{\frac{1}{n}}\\).
-///
-/// Note that the function is not defined if:
-/// 1. The input is negative (\\(x < 0\\)). An error will be returned
-/// as an imaginary number will otherwise have to be returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-///
-/// pub fn example() {
-/// elementary.nth_root(1.0, 2)
-/// |> should.equal(Ok(1.0))
-///
-/// elementary.nth_root(27.0, 3)
-/// |> should.equal(Ok(3.0))
-///
-/// elementary.nth_root(256.0, 4)
-/// |> should.equal(Ok(4.0))
-///
-/// elementary.nth_root(-1.0, 2)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-pub fn nth_root(x: Float, n: Int) -> Result(Float, Nil) {
- // In the following check:
- // 1. If x is negative then return an error as it will otherwise be an
- // imaginary number
- case x >=. 0.0 && n >= 1 {
- True -> power(x, 1.0 /. int.to_float(n))
- False -> Error(Nil)
- }
-}
-
-///
-///
-/// Calculate the arithmetic mean of the elements in a list:
-///
-/// \\[
-/// \bar{x} = \frac{1}{n}\sum_{i=1}^n x_i
-/// \\]
-///
-/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
-/// is the sample point in the input list indexed by \\(i\\).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/metrics
-///
-/// pub fn example () {
-/// // An empty list returns an error
-/// []
-/// |> metrics.mean()
-/// |> should.be_error()
-///
-/// // Valid input returns a result
-/// [1., 2., 3.]
-/// |> metrics.mean()
-/// |> should.equal(Ok(2.))
-/// }
-///
-///
-///
-///
-/// Calculate the sample variance of the elements in a list:
-///
-/// \\[
-/// s^{2} = \frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})
-/// \\]
-///
-/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
-/// is the sample point in the input list indexed by \\(i\\).
-/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
-/// Degrees of Freedom", and is by default set to \\(d = 0\\), which gives a biased
-/// estimate of the sample variance. Setting \\(d = 1\\) gives an unbiased estimate.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/metrics
-///
-/// pub fn example () {
-/// // Degrees of freedom
-/// let ddof = 1
-///
-/// // An empty list returns an error
-/// []
-/// |> metrics.variance(ddof)
-/// |> should.be_error()
-///
-/// // Valid input returns a result
-/// [1., 2., 3.]
-/// |> metrics.variance(ddof)
-/// |> should.equal(Ok(1.))
-/// }
-///
-///
-///
-///
-/// Calculate the sample standard deviation of the elements in a list:
-/// \\[
-/// s = \left(\frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})\right)^{\frac{1}{2}}
-/// \\]
-///
-/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
-/// is the sample point in the input list indexed by \\(i\\).
-/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
-/// Degrees of Freedom", and is by default set to \\(d = 0\\), which gives a biased
-/// estimate of the sample standard deviation. Setting \\(d = 1\\) gives an unbiased
-/// estimate.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/metrics
-///
-/// pub fn example () {
-/// // Degrees of freedom
-/// let ddof = 1
-///
-/// // An empty list returns an error
-/// []
-/// |> metrics.standard_deviationddof)
-/// |> should.be_error()
-///
-/// // Valid input returns a result
-/// [1., 2., 3.]
-/// |> metrics.standard_deviation(ddof)
-/// |> should.equal(Ok(1.))
-/// }
-///
-///
-///
-///
-/// The Jaccard index measures similarity between two sets of elements.
-/// Mathematically, the Jaccard index is defined as:
-///
-/// \\[
-/// \frac{|X \cap Y|}{|X \cup Y|} \\; \in \\; \left[0, 1\right]
-/// \\]
-///
-/// where:
-///
-/// - \\(X\\) and \\(Y\\) are two sets being compared,
-/// - \\(|X \cap Y|\\) represents the size of the intersection of the two sets
-/// - \\(|X \cup Y|\\) denotes the size of the union of the two sets
-///
-/// The value of the Jaccard index ranges from 0 to 1, where 0 indicates that the
-/// two sets share no elements and 1 indicates that the sets are identical. The
-/// Jaccard index is a special case of the [Tversky index](#tversky_index) (with
-/// \\(\alpha=\beta=1\\)).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/metrics
-/// import gleam/set
-///
-/// pub fn example () {
-/// let xset = set.from_list(["cat", "dog", "hippo", "monkey"])
-/// let yset =
-/// set.from_list(["monkey", "rhino", "ostrich", "salmon"])
-/// metrics.jaccard_index(xset, yset)
-/// |> should.equal(1.0 /. 7.0)
-/// }
-///
-///
-///
-///
-/// The Sørensen-Dice coefficient measures the similarity between two sets of
-/// elements. Mathematically, the coefficient is defined as:
-///
-/// \\[
-/// \frac{2 |X \cap Y|}{|X| + |Y|} \\; \in \\; \left[0, 1\right]
-/// \\]
-///
-/// where:
-/// - \\(X\\) and \\(Y\\) are two sets being compared
-/// - \\(|X \cap Y|\\) is the size of the intersection of the two sets (i.e., the
-/// number of elements common to both sets)
-/// - \\(|X|\\) and \\(|Y|\\) are the sizes of the sets \\(X\\) and \\(Y\\), respectively
-///
-/// The coefficient ranges from 0 to 1, where 0 indicates no similarity (the sets
-/// share no elements) and 1 indicates perfect similarity (the sets are identical).
-/// The higher the coefficient, the greater the similarity between the two sets.
-/// The Sørensen-Dice coefficient is a special case of the
-/// [Tversky index](#tversky_index) (with \\(\alpha=\beta=0.5\\)).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/metrics
-/// import gleam/set
-///
-/// pub fn example () {
-/// let xset = set.from_list(["cat", "dog", "hippo", "monkey"])
-/// let yset =
-/// set.from_list(["monkey", "rhino", "ostrich", "salmon", "spider"])
-/// metrics.sorensen_dice_coefficient(xset, yset)
-/// |> should.equal(2.0 *. 1.0 /. { 4.0 +. 5.0 })
-/// }
-///
-///
-///
-///
-/// The Tversky index is a generalization of the Jaccard index and Sørensen-Dice
-/// coefficient, which adds flexibility through two parameters, \\(\alpha\\) and
-/// \\(\beta\\), allowing for asymmetric similarity measures between sets. The
-/// Tversky index is defined as:
-///
-/// \\[
-/// \frac{|X \cap Y|}{|X \cap Y| + \alpha|X - Y| + \beta|Y - X|}
-/// \\]
-///
-/// where:
-///
-/// - \\(X\\) and \\(Y\\) are the sets being compared
-/// - \\(|X - Y|\\) and \\(|Y - X|\\) are the sizes of the relative complements of
-/// \\(Y\\) in \\(X\\) and \\(X\\) in \\(Y\\), respectively,
-/// - \\(\alpha\\) and \\(\beta\\) are parameters that weigh the relative importance
-/// of the elements unique to \\(X\\) and \\(Y\\)
-///
-/// The Tversky index reduces to the Jaccard index when \\(\alpha = \beta = 1\\) and
-/// to the Sørensen-Dice coefficient when \\(\alpha = \beta = 0.5\\). In general, the
-/// Tversky index can take on any non-negative value, including 0. The index equals
-/// 0 when there is no intersection between the two sets, indicating no similarity.
-/// However, unlike similarity measures bounded strictly between 0 and 1, the
-/// Tversky index does not have a strict upper limit of 1 when \\(\alpha \neq \beta\\).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/metrics
-/// import gleam/set
-///
-/// pub fn example () {
-/// let yset = set.from_list(["cat", "dog", "hippo", "monkey"])
-/// let xset =
-/// set.from_list(["monkey", "rhino", "ostrich", "salmon"])
-/// // Test Jaccard index (alpha = beta = 1)
-/// metrics.tversky_index(xset, yset, 1.0, 1.0)
-/// |> should.equal(1.0 /. 7.0)
-/// }
-///
-///
-///
-///
-/// The Overlap coefficient, also known as the Szymkiewicz–Simpson coefficient, is
-/// a measure of similarity between two sets that focuses on the size of the
-/// intersection relative to the smaller of the two sets. It is defined
-/// mathematically as:
-///
-/// \\[
-/// \frac{|X \cap Y|}{\min(|X|, |Y|)} \\; \in \\; \left[0, 1\right]
-/// \\]
-///
-/// where:
-///
-/// - \\(X\\) and \\(Y\\) are the sets being compared
-/// - \\(|X \cap Y|\\) is the size of the intersection of the sets
-/// - \\(\min(|X|, |Y|)\\) is the size of the smaller set among \\(X\\) and \\(Y\\)
-///
-/// The coefficient ranges from 0 to 1, where 0 indicates no overlap and 1
-/// indicates that the smaller set is a suyset of the larger set. This
-/// measure is especially useful in situations where the similarity in terms
-/// of the proportion of overlap is more relevant than the difference in sizes
-/// between the two sets.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/metrics
-/// import gleam/set
-///
-/// pub fn example () {
-/// let set_a =
-/// set.from_list(["horse", "dog", "hippo", "monkey", "bird"])
-/// let set_b =
-/// set.from_list(["monkey", "bird", "ostrich", "salmon"])
-/// metrics.overlap_coefficient(set_a, set_b)
-/// |> should.equal(2.0 /. 4.0)
-/// }
-///
-///
-///
-///
-/// Calculate the (weighted) cosine similarity between two lists (representing
-/// vectors):
-///
-/// \\[
-/// \frac{\sum_{i=1}^n w_{i} \cdot x_i \cdot y_i}
-/// {\left(\sum_{i=1}^n w_{i} \cdot x_i^2\right)^{\frac{1}{2}}
-/// \cdot
-/// \left(\sum_{i=1}^n w_{i} \cdot y_i^2\right)^{\frac{1}{2}}}
-/// \\; \in \\; \left[-1, 1\right]
-/// \\]
-///
-/// In the formula, \\(n\\) is the length of the two lists and \\(x_i\\), \\(y_i\\) are
-/// the values in the respective input lists indexed by \\(i\\), while the
-/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
-/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
-///
-/// The cosine similarity provides a value between -1 and 1, where 1 means the
-/// vectors are in the same direction, -1 means they are in exactly opposite
-/// directions, and 0 indicates orthogonality.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/metrics
-///
-/// pub fn example() {
-/// // Two orthogonal vectors
-/// metrics.cosine_similarity([-1.0, 1.0, 0.0], [1.0, 1.0, -1.0], option.None)
-/// |> should.equal(Ok(0.0))
-///
-/// // Two identical (parallel) vectors
-/// metrics.cosine_similarity([1.0, 2.0, 3.0], [1.0, 2.0, 3.0], option.None)
-/// |> should.equal(Ok(1.0))
-///
-/// // Two parallel, but oppositely oriented vectors
-/// metrics.cosine_similarity([-1.0, -2.0, -3.0], [1.0, 2.0, 3.0], option.None)
-/// |> should.equal(Ok(-1.0))
-/// }
-///
-///
-///
-///
-/// The ceiling function rounds a given input value \\(x \in \mathbb{R}\\) to the nearest integer
-/// value (at the specified digit) that is larger than or equal to the input \\(x\\).
-///
-/// Note: The ceiling function is used as an alias for the rounding function [`round`](#round)
-/// with rounding mode `RoundUp`.
-///
-///
-/// Details
-///
-/// For example, \\(12.0654\\) is rounded to:
-/// - \\(13.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
-/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.066\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
-/// For example, \\(12.0654\\) is rounded to:
-/// - \\(20.0\\) for 1 digit places before the decimal point (`digit = -1`)
-/// - \\(100.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(1000.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-///
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// piecewise.ceiling(12.0654, option.Some(1))
-/// |> should.equal(12.1)
-///
-/// piecewise.ceiling(12.0654, option.Some(2))
-/// |> should.equal(12.07)
-///
-/// piecewise.ceiling(12.0654, option.Some(3))
-/// |> should.equal(12.066)
-/// }
-///
-///
-///
-///
-/// The floor function rounds input \\(x \in \mathbb{R}\\) to the nearest integer value (at the
-/// specified digit) that is less than or equal to the input \\(x\\).
-///
-/// Note: The floor function is used as an alias for the rounding function [`round`](#round)
-/// with rounding mode `RoundDown`.
-///
-///
-/// Details
-///
-/// For example, \\(12.0654\\) is rounded to:
-/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.0\\) for 1 digits after the decimal point (`digits = 1`)
-/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
-/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-///
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// piecewise.floor(12.0654, option.Some(1))
-/// |> should.equal(12.0)
-///
-/// piecewise.floor(12.0654, option.Some(2))
-/// |> should.equal(12.06)
-///
-/// piecewise.floor(12.0654, option.Some(3))
-/// |> should.equal(12.065)
-/// }
-///
-///
-///
-///
-/// The truncate function rounds a given input \\(x \in \mathbb{R}\\) to the nearest integer
-/// value (at the specified digit) that is less than or equal to the absolute value of the
-/// input \\(x\\).
-///
-/// Note: The truncate function is used as an alias for the rounding function [`round`](#round)
-/// with rounding mode `RoundToZero`.
-///
-///
-/// Details
-///
-/// For example, \\(12.0654\\) is rounded to:
-/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.0\\) for 1 digits after the decimal point (`digits = 1`)
-/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
-/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-///
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// piecewise.truncate(12.0654, option.Some(1))
-/// |> should.equal(12.0)
-///
-/// piecewise.truncate(12.0654, option.Some(2))
-/// |> should.equal(12.06)
-///
-/// piecewise.truncate(12.0654, option.Some(3))
-/// |> should.equal(12.065)
-/// }
-///
-///
-///
-///
-/// The function rounds a float to a specific number of digits (after the decimal place or before
-/// if negative) using a specified rounding mode.
-///
-/// Valid rounding modes include:
-/// - `RoundNearest` (default): The input \\(x\\) is rounded to the nearest integer value (at the
-/// specified digit) with ties (fractional values of 0.5) being rounded to the nearest even
-/// integer.
-/// - `RoundTiesAway`: The input \\(x\\) is rounded to the nearest integer value (at the
-/// specified digit) with ties (fractional values of 0.5) being rounded away from zero (C/C++
-/// rounding behavior).
-/// - `RoundTiesUp`: The input \\(x\\) is rounded to the nearest integer value (at the specified
-/// digit) with ties (fractional values of 0.5) being rounded towards \\(+\infty\\)
-/// (Java/JavaScript rounding behaviour).
-/// - `RoundToZero`: The input \\(x\\) is rounded to the nearest integer value (at the specified
-/// digit) that is less than or equal to the absolute value of the input \\(x\\). An alias for
-/// this rounding mode is [`truncate`](#truncate).
-/// - `RoundDown`: The input \\(x\\) is rounded to the nearest integer value (at the specified
-/// digit) that is less than or equal to the input \\(x\\). An alias for this rounding mode is
-/// [`floor`](#floor).
-/// - `RoundUp`: The input \\(x\\) is rounded to the nearest integer value (at the specified
-/// digit) that is larger than or equal to the input \\(x\\). An alias for this rounding mode
-/// is [`ceiling`](#ceiling).
-///
-///
-/// Details
-///
-/// The `RoundNearest` rounding mode, rounds \\(12.0654\\) to:
-/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
-/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
-/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-/// The `RoundTiesAway` rounding mode, rounds \\(12.0654\\) to:
-/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
-/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
-/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-/// The `RoundTiesUp` rounding mode, rounds \\(12.0654\\) to:
-/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.1\\) for 1 digits after the decimal point (`digits = 1`)
-/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
-/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-/// The `RoundToZero` rounding mode, rounds \\(12.0654\\) to:
-/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.0\\) for 1 digit after the decimal point (`digits = 1`)
-/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
-/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-/// The `RoundDown` rounding mode, rounds \\(12.0654\\) to:
-/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.0\\) for 1 digits after the decimal point (`digits = 1`)
-/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
-/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-/// The `RoundUp` rounding mode, rounds \\(12.0654\\) to:
-/// - \\(13.0\\) for 0 digits after the decimal point (`digits = 0`)
-/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
-/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
-/// - \\(12.066\\) for 3 digits after the decimal point (`digits = 3`)
-///
-/// It is also possible to specify a negative number of digits. In that case, the negative
-/// number refers to the digits before the decimal point.
-/// - \\(20.0\\) for 1 digit places before the decimal point (`digit = -1`)
-/// - \\(100.0\\) for 2 digits before the decimal point (`digits = -2`)
-/// - \\(1000.0\\) for 3 digits before the decimal point (`digits = -3`)
-///
-///
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/option
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// // The default number of digits is 0 if None is provided
-/// piecewise.round(12.0654, option.None, option.Some(piecewise.RoundNearest))
-/// |> should.equal(12.0)
-///
-/// // The default rounding mode is "RoundNearest" if None is provided
-/// piecewise.round(12.0654, option.None, option.None)
-/// |> should.equal(12.0)
-///
-/// // Try different rounding modes
-/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundNearest))
-/// |> should.equal(12.07)
-///
-/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundTiesAway))
-/// |> should.equal(12.07)
-///
-/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundTiesUp))
-/// |> should.equal(12.07)
-///
-/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundToZero))
-/// |> should.equal(12.06)
-///
-/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundDown))
-/// |> should.equal(12.06)
-///
-/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundUp))
-/// |> should.equal(12.07)
-/// }
-///
-///
-///
-///
-/// The function takes an input \\(x \in \mathbb{R}\\) and returns the sign of
-/// the input, indicating whether it is positive (+1.0), negative (-1.0), or
-/// zero (0.0).
-///
-///
-///
-/// The function takes an input \\(x \in \mathbb{Z}\\) and returns the sign of
-/// the input, indicating whether it is positive (+1), negative (-1), or zero
-/// (0).
-///
-///
-///
-pub fn float_copy_sign(x: Float, y: Float) -> Float {
- case float_sign(x) == float_sign(y) {
- // x and y have the same sign, just return x
- True -> x
- // x and y have different signs:
- // - x is positive and y is negative, then flip sign of x
- // - x is negative and y is positive, then flip sign of x
- False -> float_flip_sign(x)
- }
-}
-
-///
-///
-pub fn int_copy_sign(x: Int, y: Int) -> Int {
- case int_sign(x) == int_sign(y) {
- // x and y have the same sign, just return x
- True -> x
- // x and y have different signs:
- // - x is positive and y is negative, then flip sign of x
- // - x is negative and y is positive, then flip sign of x
- False -> int_flip_sign(x)
- }
-}
-
-///
-///
-/// The minimum function takes two arguments \\(x, y\\) along with a function
-/// for comparing \\(x, y\\). The function returns the smallest of the two given
-/// values.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/float
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// piecewise.minimum(2.0, 1.5, float.compare)
-/// |> should.equal(1.5)
-///
-/// piecewise.minimum(1.5, 2.0, float.compare)
-/// |> should.equal(1.5)
-/// }
-///
-///
-///
-///
-pub fn minimum(x: a, y: a, compare: fn(a, a) -> order.Order) {
- case compare(x, y) {
- order.Lt -> x
- order.Eq -> x
- order.Gt -> y
- }
-}
-
-///
-///
-/// The maximum function takes two arguments \\(x, y\\) along with a function
-/// for comparing \\(x, y\\). The function returns the largest of the two given
-/// values.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/float
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// piecewise.maximum(2.0, 1.5, float.compare)
-/// |> should.equal(1.5)
-///
-/// piecewise.maximum(1.5, 2.0, float.compare)
-/// |> should.equal(1.5)
-/// }
-///
-///
-///
-///
-pub fn maximum(x: a, y: a, compare: fn(a, a) -> order.Order) {
- case compare(x, y) {
- order.Lt -> y
- order.Eq -> y
- order.Gt -> x
- }
-}
-
-///
-///
-/// The minmax function takes two arguments \\(x, y\\) along with a function
-/// for comparing \\(x, y\\). The function returns a tuple with the smallest
-/// value first and largest second.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam/float
-/// import gleam_community/maths/piecewise
-///
-/// pub fn example() {
-/// piecewise.minmax(2.0, 1.5, float.compare)
-/// |> should.equal(#(1.5, 2.0))
-///
-/// piecewise.minmax(1.5, 2.0, float.compare)
-/// |> should.equal(#(1.5, 2.0))
-/// }
-///
-///
-///
-///
-/// Determine if a given value \\(a\\) is close to or equivalent to a reference value
-/// \\(b\\) based on supplied relative \\(r_{tol}\\) and absolute \\(a_{tol}\\) tolerance
-/// values. The equivalance of the two given values are then determined based on
-/// the equation:
-///
-/// \\[
-/// \|a - b\| \leq (a_{tol} + r_{tol} \cdot \|b\|)
-/// \\]
-///
-/// `True` is returned if statement holds, otherwise `False` is returned.
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/predicates
-///
-/// pub fn example () {
-/// let val = 99.
-/// let ref_val = 100.
-/// // We set 'atol' and 'rtol' such that the values are equivalent
-/// // if 'val' is within 1 percent of 'ref_val' +/- 0.1
-/// let rtol = 0.01
-/// let atol = 0.10
-/// floatx.is_close(val, ref_val, rtol, atol)
-/// |> should.be_true()
-/// }
-///
-///
-///
-///
-/// Determine if a list of values are close to or equivalent to a another list of
-/// reference values.
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam/list
-/// import gleam_community/maths/predicates
-///
-/// pub fn example () {
-/// let val = 99.
-/// let ref_val = 100.
-/// let xarr = list.repeat(val, 42)
-/// let yarr = list.repeat(ref_val, 42)
-/// // We set 'atol' and 'rtol' such that the values are equivalent
-/// // if 'val' is within 1 percent of 'ref_val' +/- 0.1
-/// let rtol = 0.01
-/// let atol = 0.10
-/// predicates.all_close(xarr, yarr, rtol, atol)
-/// |> fn(zarr: Result(List(Bool), Nil)) -> Result(Bool, Nil) {
-/// case zarr {
-/// Ok(arr) ->
-/// arr
-/// |> list.all(fn(a) { a })
-/// |> Ok
-/// _ -> Nil |> Error
-/// }
-/// }
-/// |> should.equal(Ok(True))
-/// }
-///
-///
-///
-///
-/// Determine if a given value is fractional.
-///
-/// `True` is returned if the given value is fractional, otherwise `False` is
-/// returned.
-///
-///
-/// Example
-///
-/// import gleeunit/should
-/// import gleam_community/maths/predicates
-///
-/// pub fn example () {
-/// predicates.is_fractional(0.3333)
-/// |> should.equal(True)
-///
-/// predicates.is_fractional(1.0)
-/// |> should.equal(False)
-/// }
-///
-///
-///
-///
-/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is a
-/// power of another integer value \\(y \in \mathbb{Z}\\).
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/predicates
-///
-/// pub fn example() {
-/// // Check if 4 is a power of 2 (it is)
-/// predicates.is_power(4, 2)
-/// |> should.equal(True)
-///
-/// // Check if 5 is a power of 2 (it is not)
-/// predicates.is_power(5, 2)
-/// |> should.equal(False)
-/// }
-///
-///
-///
-///
-/// A function that tests whether a given integer value \\(n \in \mathbb{Z}\\) is a
-/// perfect number. A number is perfect if it is equal to the sum of its proper
-/// positive divisors.
-///
-///
-/// Details
-///
-/// For example:
-/// - \\(6\\) is a perfect number since the divisors of 6 are \\(1 + 2 + 3 = 6\\).
-/// - \\(28\\) is a perfect number since the divisors of 28 are \\(1 + 2 + 4 + 7 + 14 = 28\\).
-///
-///
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/predicates
-///
-/// pub fn example() {
-/// predicates.is_perfect(6)
-/// |> should.equal(True)
-///
-/// predicates.is_perfect(28)
-/// |> should.equal(True)
-/// }
-///
-///
-///
-///
-/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is a
-/// prime number. A prime number is a natural number greater than 1 that has no
-/// positive divisors other than 1 and itself.
-///
-/// The function uses the Miller-Rabin primality test to assess if \\(x\\) is prime.
-/// It is a probabilistic test, so it can mistakenly identify a composite number
-/// as prime. However, the probability of such errors decreases with more testing
-/// iterations (the function uses 64 iterations internally, which is typically
-/// more than sufficient). The Miller-Rabin test is particularly useful for large
-/// numbers.
-///
-///
-/// Details
-///
-/// Examples of prime numbers:
-/// - \\(2\\) is a prime number since it has only two divisors: \\(1\\) and \\(2\\).
-/// - \\(7\\) is a prime number since it has only two divisors: \\(1\\) and \\(7\\).
-/// - \\(4\\) is not a prime number since it has divisors other than \\(1\\) and itself, such
-/// as \\(2\\).
-///
-///
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/predicates
-///
-/// pub fn example() {
-/// predicates.is_prime(2)
-/// |> should.equal(True)
-///
-/// predicates.is_prime(4)
-/// |> should.equal(False)
-///
-/// // Test the 2nd Carmichael number
-/// predicates.is_prime(1105)
-/// |> should.equal(False)
-/// }
-///
-///
-///
-///
-/// A function that tests whether a given integer \\(m \in \mathbb{Z}\\) is a multiple of another
-/// integer \\(k \in \mathbb{Z}\\), such that \\(m = k \times q\\), with \\(q \in \mathbb{Z}\\).
-///
-///
-/// Details
-///
-/// For example:
-/// - \\(m = 15\\) is a multiple of \\(k = 5\\) because \\(15 = 5 \times 3\\).
-/// - \\(m = 14\\) is not a multiple of \\(k = 5\\) because \\(14 \div 5\\) does not yield an
-/// integer quotient.
-///
-///
-///
-///
-/// Example:
-///
-/// import gleeunit/should
-/// import gleam_community/maths/predicates
-///
-/// pub fn example() {
-/// predicates.is_multiple(15, 5)
-/// |> should.equal(True)
-///
-/// predicates.is_multiple(14, 5)
-/// |> should.equal(False)
-/// }
-///
-///
-///
-///
-/// The function returns an iterator generating evenly spaced values within a given interval.
-/// based on a start value but excludes the stop value. The spacing between values is determined
-/// by the step size provided. The function supports both positive and negative step values.
-///
-///
-/// Example:
-///
-/// import gleam/iterator
-/// import gleeunit/should
-/// import gleam_community/maths/sequences
-///
-/// pub fn example () {
-/// sequences.arange(1.0, 5.0, 1.0)
-/// |> iterator.to_list()
-/// |> should.equal([1.0, 2.0, 3.0, 4.0])
-///
-/// // No points returned since
-/// // start is smaller than stop and the step is positive
-/// sequences.arange(5.0, 1.0, 1.0)
-/// |> iterator.to_list()
-/// |> should.equal([])
-///
-/// // Points returned since
-/// // start smaller than stop but negative step
-/// sequences.arange(5.0, 1.0, -1.0)
-/// |> iterator.to_list()
-/// |> should.equal([5.0, 4.0, 3.0, 2.0])
-/// }
-///
-///
-///
-///
-/// The function returns an iterator for generating linearly spaced points over a specified
-/// interval. The endpoint of the interval can optionally be included/excluded. The number of
-/// points and whether the endpoint is included determine the spacing between values.
-///
-///
-/// Example:
-///
-/// import gleam/iterator
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-/// import gleam_community/maths/sequences
-/// import gleam_community/maths/predicates
-///
-/// pub fn example () {
-/// let assert Ok(tol) = elementary.power(10.0, -6.0)
-/// let assert Ok(linspace) = sequences.linear_space(10.0, 20.0, 5, True)
-/// let assert Ok(result) =
-/// predicates.all_close(
-/// linspace |> iterator.to_list(),
-/// [10.0, 12.5, 15.0, 17.5, 20.0],
-/// 0.0,
-/// tol,
-/// )
-///
-/// result
-/// |> list.all(fn(x) { x == True })
-/// |> should.be_true()
-///
-/// // A negative number of points (-5) does not work
-/// sequences.linear_space(10.0, 50.0, -5, True)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The function returns an iterator of logarithmically spaced points over a specified interval.
-/// The endpoint of the interval can optionally be included/excluded. The number of points, base,
-/// and whether the endpoint is included determine the spacing between values.
-///
-///
-/// Example:
-///
-/// import gleam/iterator
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-/// import gleam_community/maths/sequences
-/// import gleam_community/maths/predicates
-///
-/// pub fn example () {
-/// let assert Ok(tol) = elementary.power(10.0, -6.0)
-/// let assert Ok(logspace) = sequences.logarithmic_space(1.0, 3.0, 3, True, 10.0)
-/// let assert Ok(result) =
-/// predicates.all_close(
-/// logspace |> iterator.to_list(),
-/// [10.0, 100.0, 1000.0],
-/// 0.0,
-/// tol,
-/// )
-/// result
-/// |> list.all(fn(x) { x == True })
-/// |> should.be_true()
-///
-/// // A negative number of points (-3) does not work
-/// sequences.logarithmic_space(1.0, 3.0, -3, False, 10.0)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The function returns an iterator of numbers spaced evenly on a log scale (a geometric
-/// progression). Each point in the list is a constant multiple of the previous. The function is
-/// similar to the [`logarithmic_space`](#logarithmic_space) function, but with endpoints
-/// specified directly.
-///
-///
-/// Example:
-///
-/// import gleam/iterator
-/// import gleeunit/should
-/// import gleam_community/maths/elementary
-/// import gleam_community/maths/sequences
-/// import gleam_community/maths/predicates
-///
-/// pub fn example () {
-/// let assert Ok(tol) = elementary.power(10.0, -6.0)
-/// let assert Ok(logspace) = sequences.geometric_space(10.0, 1000.0, 3, True)
-/// let assert Ok(result) =
-/// predicates.all_close(
-/// logspace |> iterator.to_list(),
-/// [10.0, 100.0, 1000.0],
-/// 0.0,
-/// tol,
-/// )
-/// result
-/// |> list.all(fn(x) { x == True })
-/// |> should.be_true()
-///
-/// // Input (start and stop can't be equal to 0.0)
-/// sequences.geometric_space(0.0, 1000.0, 3, False)
-/// |> should.be_error()
-///
-/// sequences.geometric_space(-1000.0, 0.0, 3, False)
-/// |> should.be_error()
-///
-/// // A negative number of points (-3) does not work
-/// sequences.geometric_space(10.0, 1000.0, -3, False)
-/// |> should.be_error()
-/// }
-///
-///
-///
-///
-/// The beta function over the real numbers:
-///
-/// \\[
-/// \text{B}(x, y) = \frac{\Gamma(x) \cdot \Gamma(y)}{\Gamma(x + y)}
-/// \\]
-///
-/// The beta function is evaluated through the use of the gamma function.
-///
-///
-///
-pub fn erf(x: Float) -> Float {
- let assert [a1, a2, a3, a4, a5] = [
- 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429,
- ]
- let p = 0.3275911
-
- let sign = piecewise.float_sign(x)
- let x = piecewise.float_absolute_value(x)
-
- // Formula 7.1.26 given in Abramowitz and Stegun.
- let t = 1.0 /. { 1.0 +. p *. x }
- let y =
- 1.0
- -. { { { { a5 *. t +. a4 } *. t +. a3 } *. t +. a2 } *. t +. a1 }
- *. t
- *. elementary.exponential(-1.0 *. x *. x)
- sign *. y
-}
-
-///
-///
-/// The gamma function over the real numbers. The function is essentially equal to
-/// the factorial for any positive integer argument: \\(\Gamma(n) = (n - 1)!\\)
-///
-/// The implemented gamma function is approximated through Lanczos approximation
-/// using the same coefficients used by the GNU Scientific Library.
-///
-///
-///
-/// The lower incomplete gamma function over the real numbers.
-///
-/// The implemented incomplete gamma function is evaluated through a power series
-/// expansion.
-///
-///