mirror of
https://github.com/sigmasternchen/gleam-community-maths
synced 2025-03-15 07:59:01 +00:00
♻️ Replace error types with Nil for better DX with other error-producing functions.
This commit is contained in:
parent
6d5241e222
commit
2bd3b76a79
9 changed files with 450 additions and 626 deletions
|
@ -20,11 +20,11 @@
|
||||||
////<style>
|
////<style>
|
||||||
//// .katex { font-size: 1.1em; }
|
//// .katex { font-size: 1.1em; }
|
||||||
////</style>
|
////</style>
|
||||||
////
|
////
|
||||||
//// ---
|
//// ---
|
||||||
////
|
////
|
||||||
//// Arithmetics: A module containing a collection of fundamental mathematical functions relating to simple arithmetics (addition, subtraction, multiplication, etc.), but also number theory.
|
//// Arithmetics: A module containing a collection of fundamental mathematical functions relating to simple arithmetics (addition, subtraction, multiplication, etc.), but also number theory.
|
||||||
////
|
////
|
||||||
//// * **Division functions**
|
//// * **Division functions**
|
||||||
//// * [`gcd`](#gcd)
|
//// * [`gcd`](#gcd)
|
||||||
//// * [`lcm`](#lcm)
|
//// * [`lcm`](#lcm)
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
//// * [`int_cumulative_sum`](#int_cumulative_sum)
|
//// * [`int_cumulative_sum`](#int_cumulative_sum)
|
||||||
//// * [`float_cumulative_product`](#float_cumulative_product)
|
//// * [`float_cumulative_product`](#float_cumulative_product)
|
||||||
//// * [`int_cumulative_product`](#int_cumulative_product)
|
//// * [`int_cumulative_product`](#int_cumulative_product)
|
||||||
////
|
////
|
||||||
|
|
||||||
import gleam/int
|
import gleam/int
|
||||||
import gleam/list
|
import gleam/list
|
||||||
|
@ -57,7 +57,7 @@ import gleam_community/maths/piecewise
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function calculates the greatest common divisor of two integers
|
/// The function calculates the greatest common divisor of two integers
|
||||||
/// \\(x, y \in \mathbb{Z}\\). The greatest common divisor is the largest positive
|
/// \\(x, y \in \mathbb{Z}\\). The greatest common divisor is the largest positive
|
||||||
/// integer that is divisible by both \\(x\\) and \\(y\\).
|
/// integer that is divisible by both \\(x\\) and \\(y\\).
|
||||||
///
|
///
|
||||||
|
@ -70,7 +70,7 @@ import gleam_community/maths/piecewise
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// arithmetics.gcd(1, 1)
|
/// arithmetics.gcd(1, 1)
|
||||||
/// |> should.equal(1)
|
/// |> should.equal(1)
|
||||||
///
|
///
|
||||||
/// arithmetics.gcd(100, 10)
|
/// arithmetics.gcd(100, 10)
|
||||||
/// |> should.equal(10)
|
/// |> should.equal(10)
|
||||||
///
|
///
|
||||||
|
@ -107,24 +107,24 @@ fn do_gcd(x: Int, y: Int) -> Int {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// Given two integers, \\(x\\) (dividend) and \\(y\\) (divisor), the Euclidean modulo
|
/// 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
|
/// of \\(x\\) by \\(y\\), denoted as \\(x \mod y\\), is the remainder \\(r\\) of the
|
||||||
/// division of \\(x\\) by \\(y\\), such that:
|
/// division of \\(x\\) by \\(y\\), such that:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// x = q \cdot y + r \quad \text{and} \quad 0 \leq r < |y|,
|
/// 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.
|
/// where \\(q\\) is an integer that represents the quotient of the division.
|
||||||
///
|
///
|
||||||
/// The Euclidean modulo function of two numbers, is the remainder operation most
|
/// The Euclidean modulo function of two numbers, is the remainder operation most
|
||||||
/// commonly utilized in mathematics. This differs from the standard truncating
|
/// commonly utilized in mathematics. This differs from the standard truncating
|
||||||
/// modulo operation frequently employed in programming via the `%` operator.
|
/// modulo operation frequently employed in programming via the `%` operator.
|
||||||
/// Unlike the `%` operator, which may return negative results depending on the
|
/// Unlike the `%` operator, which may return negative results depending on the
|
||||||
/// divisor's sign, the Euclidean modulo function is designed to always yield a
|
/// divisor's sign, the Euclidean modulo function is designed to always yield a
|
||||||
/// positive outcome, ensuring consistency with mathematical conventions.
|
/// positive outcome, ensuring consistency with mathematical conventions.
|
||||||
///
|
///
|
||||||
/// Note that like the Gleam division operator `/` this will return `0` if one of
|
/// Note that like the Gleam division operator `/` this will return `0` if one of
|
||||||
/// the arguments is `0`.
|
/// the arguments is `0`.
|
||||||
///
|
///
|
||||||
|
@ -138,7 +138,7 @@ fn do_gcd(x: Int, y: Int) -> Int {
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// arithmetics.euclidean_modulo(15, 4)
|
/// arithmetics.euclidean_modulo(15, 4)
|
||||||
/// |> should.equal(3)
|
/// |> should.equal(3)
|
||||||
///
|
///
|
||||||
/// arithmetics.euclidean_modulo(-3, -2)
|
/// arithmetics.euclidean_modulo(-3, -2)
|
||||||
/// |> should.equal(1)
|
/// |> should.equal(1)
|
||||||
///
|
///
|
||||||
|
@ -168,7 +168,7 @@ pub fn int_euclidean_modulo(x: Int, y: Int) -> Int {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function calculates the least common multiple of two integers
|
/// The function calculates the least common multiple of two integers
|
||||||
/// \\(x, y \in \mathbb{Z}\\). The least common multiple is the smallest positive
|
/// \\(x, y \in \mathbb{Z}\\). The least common multiple is the smallest positive
|
||||||
/// integer that has both \\(x\\) and \\(y\\) as factors.
|
/// integer that has both \\(x\\) and \\(y\\) as factors.
|
||||||
///
|
///
|
||||||
|
@ -181,7 +181,7 @@ pub fn int_euclidean_modulo(x: Int, y: Int) -> Int {
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// arithmetics.lcm(1, 1)
|
/// arithmetics.lcm(1, 1)
|
||||||
/// |> should.equal(1)
|
/// |> should.equal(1)
|
||||||
///
|
///
|
||||||
/// arithmetics.lcm(100, 10)
|
/// arithmetics.lcm(100, 10)
|
||||||
/// |> should.equal(100)
|
/// |> should.equal(100)
|
||||||
///
|
///
|
||||||
|
@ -208,7 +208,7 @@ pub fn lcm(x: Int, y: Int) -> Int {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function returns all the positive divisors of an integer, including the
|
/// The function returns all the positive divisors of an integer, including the
|
||||||
/// number itself.
|
/// number itself.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -260,7 +260,7 @@ fn find_divisors(n: Int) -> List(Int) {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function returns all the positive divisors of an integer, excluding the
|
/// The function returns all the positive divisors of an integer, excluding the
|
||||||
/// number iteself.
|
/// number iteself.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -362,7 +362,7 @@ pub fn float_sum(arr: List(Float), weights: option.Option(List(Float))) -> Float
|
||||||
/// \sum_{i=1}^n x_i
|
/// \sum_{i=1}^n x_i
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{Z}\\) is
|
/// 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\\).
|
/// the value in the input list indexed by \\(i\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -414,7 +414,7 @@ pub fn int_sum(arr: List(Int)) -> Int {
|
||||||
/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\) is
|
/// 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}\\)
|
/// 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).
|
/// are corresponding weights (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -444,7 +444,7 @@ pub fn int_sum(arr: List(Int)) -> Int {
|
||||||
pub fn float_product(
|
pub fn float_product(
|
||||||
arr: List(Float),
|
arr: List(Float),
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case arr, weights {
|
case arr, weights {
|
||||||
[], _ ->
|
[], _ ->
|
||||||
1.0
|
1.0
|
||||||
|
@ -454,22 +454,16 @@ pub fn float_product(
|
||||||
|> list.fold(1.0, fn(acc: Float, a: Float) -> Float { a *. acc })
|
|> list.fold(1.0, fn(acc: Float, a: Float) -> Float { a *. acc })
|
||||||
|> Ok
|
|> Ok
|
||||||
_, option.Some(warr) -> {
|
_, option.Some(warr) -> {
|
||||||
let results =
|
list.zip(arr, warr)
|
||||||
list.zip(arr, warr)
|
|> list.map(fn(a: #(Float, Float)) -> Result(Float, Nil) {
|
||||||
|> list.map(fn(a: #(Float, Float)) -> Result(Float, String) {
|
pair.first(a)
|
||||||
pair.first(a)
|
|> elementary.power(pair.second(a))
|
||||||
|> elementary.power(pair.second(a))
|
})
|
||||||
})
|
|> result.all
|
||||||
|> result.all
|
|> result.map(fn(prods) {
|
||||||
case results {
|
prods
|
||||||
Ok(prods) ->
|
|> list.fold(1.0, fn(acc: Float, a: Float) -> Float { a *. acc })
|
||||||
prods
|
})
|
||||||
|> list.fold(1.0, fn(acc: Float, a: Float) -> Float { a *. acc })
|
|
||||||
|> Ok
|
|
||||||
Error(msg) ->
|
|
||||||
msg
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,7 +480,7 @@ pub fn float_product(
|
||||||
/// \prod_{i=1}^n x_i
|
/// \prod_{i=1}^n x_i
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{Z}\\) is
|
/// 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\\).
|
/// the value in the input list indexed by \\(i\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -536,7 +530,7 @@ pub fn int_product(arr: List(Int)) -> Int {
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(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}\\)
|
/// 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
|
/// 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.
|
/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
|
||||||
///
|
///
|
||||||
|
@ -586,7 +580,7 @@ pub fn float_cumulative_sum(arr: List(Float)) -> List(Float) {
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(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}\\)
|
/// 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
|
/// 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.
|
/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
|
||||||
///
|
///
|
||||||
|
@ -635,10 +629,10 @@ pub fn int_cumulative_sum(arr: List(Int)) -> List(Int) {
|
||||||
/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
/// 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
|
/// 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
|
/// \\(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
|
/// \\(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
|
/// value \\(v_j\\) is thus the sum of the \\(1\\) to \\(j\\) first elements in the
|
||||||
/// given list.
|
/// given list.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -687,9 +681,9 @@ pub fn float_cumulative_product(arr: List(Float)) -> List(Float) {
|
||||||
/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
/// 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
|
/// 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
|
/// \\(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
|
/// \\(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
|
/// value \\(v_j\\) is thus the product of the \\(1\\) to \\(j\\) first elements in the
|
||||||
/// given list.
|
/// given list.
|
||||||
///
|
///
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
////<style>
|
////<style>
|
||||||
//// .katex { font-size: 1.1em; }
|
//// .katex { font-size: 1.1em; }
|
||||||
////</style>
|
////</style>
|
||||||
////
|
////
|
||||||
//// ---
|
//// ---
|
||||||
////
|
////
|
||||||
//// Combinatorics: A module that offers mathematical functions related to counting, arrangements,
|
//// Combinatorics: A module that offers mathematical functions related to counting, arrangements,
|
||||||
//// and permutations/combinations.
|
//// and permutations/combinations.
|
||||||
////
|
////
|
||||||
//// * **Combinatorial functions**
|
//// * **Combinatorial functions**
|
||||||
//// * [`combination`](#combination)
|
//// * [`combination`](#combination)
|
||||||
//// * [`factorial`](#factorial)
|
//// * [`factorial`](#factorial)
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
//// * [`list_combination`](#list_combination)
|
//// * [`list_combination`](#list_combination)
|
||||||
//// * [`list_permutation`](#list_permutation)
|
//// * [`list_permutation`](#list_permutation)
|
||||||
//// * [`cartesian_product`](#cartesian_product)
|
//// * [`cartesian_product`](#cartesian_product)
|
||||||
////
|
////
|
||||||
|
|
||||||
import gleam/iterator
|
import gleam/iterator
|
||||||
import gleam/list
|
import gleam/list
|
||||||
|
@ -70,26 +70,26 @@ pub type CombinatoricsMode {
|
||||||
/// Also known as the "stars and bars" problem in combinatorics.
|
/// Also known as the "stars and bars" problem in combinatorics.
|
||||||
///
|
///
|
||||||
/// The implementation uses an efficient iterative multiplicative formula for computing the result.
|
/// The implementation uses an efficient iterative multiplicative formula for computing the result.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Details</summary>
|
/// <summary>Details</summary>
|
||||||
///
|
///
|
||||||
/// A \\(k\\)-combination is a sequence of \\(k\\) elements selected from \\(n\\) elements where
|
/// 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
|
/// the order of selection does not matter. For example, consider selecting 2 elements from a list
|
||||||
/// of 3 elements: `["A", "B", "C"]`:
|
/// of 3 elements: `["A", "B", "C"]`:
|
||||||
///
|
///
|
||||||
/// - For \\(k\\)-combinations (without repetitions), where order does not matter, the possible
|
/// - For \\(k\\)-combinations (without repetitions), where order does not matter, the possible
|
||||||
/// selections are:
|
/// selections are:
|
||||||
/// - `["A", "B"]`
|
/// - `["A", "B"]`
|
||||||
/// - `["A", "C"]`
|
/// - `["A", "C"]`
|
||||||
/// - `["B", "C"]`
|
/// - `["B", "C"]`
|
||||||
///
|
///
|
||||||
/// - For \\(k\\)-combinations (with repetitions), where order does not matter but elements can
|
/// - For \\(k\\)-combinations (with repetitions), where order does not matter but elements can
|
||||||
/// repeat, the possible selections are:
|
/// repeat, the possible selections are:
|
||||||
/// - `["A", "A"], ["A", "B"], ["A", "C"]`
|
/// - `["A", "A"], ["A", "B"], ["A", "C"]`
|
||||||
/// - `["B", "B"], ["B", "C"], ["C", "C"]`
|
/// - `["B", "B"], ["B", "C"], ["C", "C"]`
|
||||||
///
|
///
|
||||||
/// - On the contrary, for \\(k\\)-permutations (without repetitions), the order matters, so the
|
/// - On the contrary, for \\(k\\)-permutations (without repetitions), the order matters, so the
|
||||||
/// possible selections are:
|
/// possible selections are:
|
||||||
/// - `["A", "B"], ["B", "A"]`
|
/// - `["A", "B"], ["B", "A"]`
|
||||||
/// - `["A", "C"], ["C", "A"]`
|
/// - `["A", "C"], ["C", "A"]`
|
||||||
|
@ -106,15 +106,15 @@ pub type CombinatoricsMode {
|
||||||
/// // Invalid input gives an error
|
/// // Invalid input gives an error
|
||||||
/// combinatorics.combination(-1, 1, option.None)
|
/// combinatorics.combination(-1, 1, option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Valid input: n = 4 and k = 0
|
/// // Valid input: n = 4 and k = 0
|
||||||
/// combinatorics.combination(4, 0, option.Some(combinatorics.WithoutRepetitions))
|
/// combinatorics.combination(4, 0, option.Some(combinatorics.WithoutRepetitions))
|
||||||
/// |> should.equal(Ok(1))
|
/// |> should.equal(Ok(1))
|
||||||
///
|
///
|
||||||
/// // Valid input: k = n (n = 4, k = 4)
|
/// // Valid input: k = n (n = 4, k = 4)
|
||||||
/// combinatorics.combination(4, 4, option.Some(combinatorics.WithoutRepetitions))
|
/// combinatorics.combination(4, 4, option.Some(combinatorics.WithoutRepetitions))
|
||||||
/// |> should.equal(Ok(1))
|
/// |> should.equal(Ok(1))
|
||||||
///
|
///
|
||||||
/// // Valid input: combinations with repetition (n = 2, k = 3)
|
/// // Valid input: combinations with repetition (n = 2, k = 3)
|
||||||
/// combinatorics.combination(2, 3, option.Some(combinatorics.WithRepetitions))
|
/// combinatorics.combination(2, 3, option.Some(combinatorics.WithRepetitions))
|
||||||
/// |> should.equal(Ok(4))
|
/// |> should.equal(Ok(4))
|
||||||
|
@ -125,17 +125,15 @@ pub type CombinatoricsMode {
|
||||||
/// <small>Back to top ↑</small>
|
/// <small>Back to top ↑</small>
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn combination(
|
pub fn combination(
|
||||||
n: Int,
|
n: Int,
|
||||||
k: Int,
|
k: Int,
|
||||||
mode: option.Option(CombinatoricsMode),
|
mode: option.Option(CombinatoricsMode),
|
||||||
) -> Result(Int, String) {
|
) -> Result(Int, Nil) {
|
||||||
case n, k {
|
case n, k {
|
||||||
_, _ if n < 0 ->
|
_, _ if n < 0 -> Error(Nil)
|
||||||
"Invalid input argument: n < 0. Valid input is n >= 0." |> Error
|
_, _ if k < 0 -> Error(Nil)
|
||||||
_, _ if k < 0 ->
|
|
||||||
"Invalid input argument: k < 0. Valid input is k >= 0." |> Error
|
|
||||||
_, _ -> {
|
_, _ -> {
|
||||||
case mode {
|
case mode {
|
||||||
option.Some(WithRepetitions) -> combination_with_repetitions(n, k)
|
option.Some(WithRepetitions) -> combination_with_repetitions(n, k)
|
||||||
|
@ -145,12 +143,11 @@ pub fn combination(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combination_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
fn combination_with_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||||
{ n + k - 1 }
|
combination_without_repetitions(n + k - 1, k)
|
||||||
|> combination_without_repetitions(k)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combination_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
fn combination_without_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||||
case n, k {
|
case n, k {
|
||||||
_, _ if k == 0 || k == n -> {
|
_, _ if k == 0 || k == n -> {
|
||||||
1 |> Ok
|
1 |> Ok
|
||||||
|
@ -202,17 +199,11 @@ fn combination_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn factorial(n) -> Result(Int, String) {
|
pub fn factorial(n) -> Result(Int, Nil) {
|
||||||
case n {
|
case n {
|
||||||
_ if n < 0 ->
|
_ if n < 0 -> Error(Nil)
|
||||||
"Invalid input argument: n < 0. Valid input is n >= 0."
|
0 -> Ok(1)
|
||||||
|> Error
|
1 -> Ok(1)
|
||||||
0 ->
|
|
||||||
1
|
|
||||||
|> Ok
|
|
||||||
1 ->
|
|
||||||
1
|
|
||||||
|> Ok
|
|
||||||
_ ->
|
_ ->
|
||||||
list.range(1, n)
|
list.range(1, n)
|
||||||
|> list.fold(1, fn(acc: Int, x: Int) -> Int { acc * x })
|
|> list.fold(1, fn(acc: Int, x: Int) -> Int { acc * x })
|
||||||
|
@ -227,50 +218,50 @@ pub fn factorial(n) -> Result(Int, String) {
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A combinatorial function for computing the number of \\(k\\)-permutations.
|
/// A combinatorial function for computing the number of \\(k\\)-permutations.
|
||||||
///
|
///
|
||||||
/// **Without** repetitions:
|
/// **Without** repetitions:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// P(n, k) = \binom{n}{k} \cdot k! = \frac{n!}{(n - k)!}
|
/// P(n, k) = \binom{n}{k} \cdot k! = \frac{n!}{(n - k)!}
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// **With** repetitions:
|
/// **With** repetitions:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// P^*(n, k) = n^k
|
/// P^*(n, k) = n^k
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// The implementation uses an efficient iterative multiplicative formula for computing the result.
|
/// The implementation uses an efficient iterative multiplicative formula for computing the result.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Details</summary>
|
/// <summary>Details</summary>
|
||||||
///
|
///
|
||||||
/// A \\(k\\)-permutation (without repetitions) is a sequence of \\(k\\) elements selected from \
|
/// 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
|
/// \\(n\\) elements where the order of selection matters. For example, consider selecting 2
|
||||||
/// elements from a list of 3 elements: `["A", "B", "C"]`:
|
/// elements from a list of 3 elements: `["A", "B", "C"]`:
|
||||||
///
|
///
|
||||||
/// - For \\(k\\)-permutations (without repetitions), the order matters, so the possible selections
|
/// - For \\(k\\)-permutations (without repetitions), the order matters, so the possible selections
|
||||||
/// are:
|
/// are:
|
||||||
/// - `["A", "B"], ["B", "A"]`
|
/// - `["A", "B"], ["B", "A"]`
|
||||||
/// - `["A", "C"], ["C", "A"]`
|
/// - `["A", "C"], ["C", "A"]`
|
||||||
/// - `["B", "C"], ["C", "B"]`
|
/// - `["B", "C"], ["C", "B"]`
|
||||||
///
|
///
|
||||||
/// - For \\(k\\)-permutations (with repetitions), the order also matters, but we have repeated
|
/// - For \\(k\\)-permutations (with repetitions), the order also matters, but we have repeated
|
||||||
/// selections:
|
/// selections:
|
||||||
/// - `["A", "A"], ["A", "B"], ["A", "C"]`
|
/// - `["A", "A"], ["A", "B"], ["A", "C"]`
|
||||||
/// - `["B", "A"], ["B", "B"], ["B", "C"]`
|
/// - `["B", "A"], ["B", "B"], ["B", "C"]`
|
||||||
/// - `["C", "A"], ["C", "B"], ["C", "C"]`
|
/// - `["C", "A"], ["C", "B"], ["C", "C"]`
|
||||||
///
|
///
|
||||||
/// - On the contrary, for \\(k\\)-combinations (without repetitions), where order does not matter,
|
/// - On the contrary, for \\(k\\)-combinations (without repetitions), where order does not matter,
|
||||||
/// the possible selections are:
|
/// the possible selections are:
|
||||||
/// - `["A", "B"]`
|
/// - `["A", "B"]`
|
||||||
/// - `["A", "C"]`
|
/// - `["A", "C"]`
|
||||||
/// - `["B", "C"]`
|
/// - `["B", "C"]`
|
||||||
/// </details>
|
/// </details>
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
/// import gleam/option
|
/// import gleam/option
|
||||||
/// import gleeunit/should
|
/// import gleeunit/should
|
||||||
/// import gleam_community/maths/combinatorics
|
/// import gleam_community/maths/combinatorics
|
||||||
|
@ -300,22 +291,16 @@ pub fn permutation(
|
||||||
n: Int,
|
n: Int,
|
||||||
k: Int,
|
k: Int,
|
||||||
mode: option.Option(CombinatoricsMode),
|
mode: option.Option(CombinatoricsMode),
|
||||||
) -> Result(Int, String) {
|
) -> Result(Int, Nil) {
|
||||||
case n, k {
|
case n, k, mode {
|
||||||
_, _ if n < 0 ->
|
_, _, _ if n < 0 -> Error(Nil)
|
||||||
"Invalid input argument: n < 0. Valid input is n >= 0." |> Error
|
_, _, _ if k < 0 -> Error(Nil)
|
||||||
_, _ if k < 0 ->
|
_, _, option.Some(WithRepetitions) -> permutation_with_repetitions(n, k)
|
||||||
"Invalid input argument: k < 0. Valid input is k >= 0." |> Error
|
_, _, _ -> permutation_without_repetitions(n, k)
|
||||||
_, _ -> {
|
|
||||||
case mode {
|
|
||||||
option.Some(WithRepetitions) -> permutation_with_repetitions(n, k)
|
|
||||||
_ -> permutation_without_repetitions(n, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn permutation_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
fn permutation_without_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||||
case n, k {
|
case n, k {
|
||||||
_, _ if k < 0 || k > n -> {
|
_, _ if k < 0 || k > n -> {
|
||||||
0 |> Ok
|
0 |> Ok
|
||||||
|
@ -330,7 +315,7 @@ fn permutation_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn permutation_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
fn permutation_with_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||||
let n_float = conversion.int_to_float(n)
|
let n_float = conversion.int_to_float(n)
|
||||||
let k_float = conversion.int_to_float(k)
|
let k_float = conversion.int_to_float(k)
|
||||||
// 'n' ank 'k' are positive integers, so no errors here...
|
// 'n' ank 'k' are positive integers, so no errors here...
|
||||||
|
@ -346,11 +331,11 @@ fn permutation_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Generates all possible combinations of \\(k\\) elements selected from a given list of size
|
/// Generates all possible combinations of \\(k\\) elements selected from a given list of size
|
||||||
/// \\(n\\).
|
/// \\(n\\).
|
||||||
///
|
///
|
||||||
/// The function can handle cases with and without repetitions
|
/// The function can handle cases with and without repetitions
|
||||||
/// (see more details [here](#combination)). Also, note that repeated elements are treated as
|
/// (see more details [here](#combination)). Also, note that repeated elements are treated as
|
||||||
/// distinct.
|
/// distinct.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -370,7 +355,7 @@ fn permutation_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||||
/// 3,
|
/// 3,
|
||||||
/// option.Some(combinatorics.WithoutRepetitions),
|
/// option.Some(combinatorics.WithoutRepetitions),
|
||||||
/// )
|
/// )
|
||||||
///
|
///
|
||||||
/// result
|
/// result
|
||||||
/// |> iterator.to_list()
|
/// |> iterator.to_list()
|
||||||
/// |> set.from_list()
|
/// |> set.from_list()
|
||||||
|
@ -388,29 +373,20 @@ pub fn list_combination(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
k: Int,
|
k: Int,
|
||||||
mode: option.Option(CombinatoricsMode),
|
mode: option.Option(CombinatoricsMode),
|
||||||
) -> Result(iterator.Iterator(List(a)), String) {
|
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||||
case k {
|
case k, mode {
|
||||||
_ if k < 0 ->
|
_, _ if k < 0 -> Error(Nil)
|
||||||
"Invalid input argument: k < 0. Valid input is k >= 0."
|
_, option.Some(WithRepetitions) -> list_combination_with_repetitions(arr, k)
|
||||||
|> Error
|
_, _ -> list_combination_without_repetitions(arr, k)
|
||||||
_ ->
|
|
||||||
case mode {
|
|
||||||
option.Some(WithRepetitions) ->
|
|
||||||
list_combination_with_repetitions(arr, k)
|
|
||||||
_ -> list_combination_without_repetitions(arr, k)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_combination_without_repetitions(
|
fn list_combination_without_repetitions(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
k: Int,
|
k: Int,
|
||||||
) -> Result(iterator.Iterator(List(a)), String) {
|
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||||
case k, list.length(arr) {
|
case k, list.length(arr) {
|
||||||
_, arr_length if k > arr_length -> {
|
_, arr_length if k > arr_length -> Error(Nil)
|
||||||
"Invalid input argument: k > length(arr). Valid input is 0 <= k <= length(arr)."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
// Special case: When k = n, then the entire list is the only valid combination
|
// Special case: When k = n, then the entire list is the only valid combination
|
||||||
_, arr_length if k == arr_length -> {
|
_, arr_length if k == arr_length -> {
|
||||||
iterator.single(arr) |> Ok
|
iterator.single(arr) |> Ok
|
||||||
|
@ -446,7 +422,7 @@ fn do_list_combination_without_repetitions(
|
||||||
fn list_combination_with_repetitions(
|
fn list_combination_with_repetitions(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
k: Int,
|
k: Int,
|
||||||
) -> Result(iterator.Iterator(List(a)), String) {
|
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||||
Ok(do_list_combination_with_repetitions(iterator.from_list(arr), k, []))
|
Ok(do_list_combination_with_repetitions(iterator.from_list(arr), k, []))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,11 +452,11 @@ fn do_list_combination_with_repetitions(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Generates all possible permutations of \\(k\\) elements selected from a given list of size
|
/// Generates all possible permutations of \\(k\\) elements selected from a given list of size
|
||||||
/// \\(n\\).
|
/// \\(n\\).
|
||||||
///
|
///
|
||||||
/// The function can handle cases with and without repetitions
|
/// The function can handle cases with and without repetitions
|
||||||
/// (see more details [here](#permutation)). Also, note that repeated elements are treated as
|
/// (see more details [here](#permutation)). Also, note that repeated elements are treated as
|
||||||
/// distinct.
|
/// distinct.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -500,7 +476,7 @@ fn do_list_combination_with_repetitions(
|
||||||
/// 3,
|
/// 3,
|
||||||
/// option.Some(combinatorics.WithoutRepetitions),
|
/// option.Some(combinatorics.WithoutRepetitions),
|
||||||
/// )
|
/// )
|
||||||
///
|
///
|
||||||
/// result
|
/// result
|
||||||
/// |> iterator.to_list()
|
/// |> iterator.to_list()
|
||||||
/// |> set.from_list()
|
/// |> set.from_list()
|
||||||
|
@ -523,22 +499,17 @@ fn do_list_combination_with_repetitions(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn list_permutation(
|
pub fn list_permutation(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
k: Int,
|
k: Int,
|
||||||
mode: option.Option(CombinatoricsMode),
|
mode: option.Option(CombinatoricsMode),
|
||||||
) -> Result(iterator.Iterator(List(a)), String) {
|
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||||
case k {
|
case k, mode {
|
||||||
_ if k < 0 ->
|
_, _ if k < 0 -> Error(Nil)
|
||||||
"Invalid input argument: k < 0. Valid input is k >= 0."
|
_, option.Some(WithRepetitions) ->
|
||||||
|> Error
|
Ok(list_permutation_with_repetitions(arr, k))
|
||||||
_ ->
|
_, _ -> list_permutation_without_repetitions(arr, k)
|
||||||
case mode {
|
|
||||||
option.Some(WithRepetitions) ->
|
|
||||||
list_permutation_with_repetitions(arr, k)
|
|
||||||
_ -> list_permutation_without_repetitions(arr, k)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,12 +529,9 @@ fn remove_first_by_index(
|
||||||
fn list_permutation_without_repetitions(
|
fn list_permutation_without_repetitions(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
k: Int,
|
k: Int,
|
||||||
) -> Result(iterator.Iterator(List(a)), String) {
|
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||||
case k, list.length(arr) {
|
case k, list.length(arr) {
|
||||||
_, arr_length if k > arr_length -> {
|
_, arr_length if k > arr_length -> Error(Nil)
|
||||||
"Invalid input argument: k > length(arr). Valid input is 0 <= k <= length(arr)."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
_, _ -> {
|
_, _ -> {
|
||||||
let indexed_arr = list.index_map(arr, fn(x, i) { #(i, x) })
|
let indexed_arr = list.index_map(arr, fn(x, i) { #(i, x) })
|
||||||
Ok(do_list_permutation_without_repetitions(
|
Ok(do_list_permutation_without_repetitions(
|
||||||
|
@ -594,9 +562,9 @@ fn do_list_permutation_without_repetitions(
|
||||||
fn list_permutation_with_repetitions(
|
fn list_permutation_with_repetitions(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
k: Int,
|
k: Int,
|
||||||
) -> Result(iterator.Iterator(List(a)), String) {
|
) -> iterator.Iterator(List(a)) {
|
||||||
let indexed_arr = list.index_map(arr, fn(x, i) { #(i, x) })
|
let indexed_arr = list.index_map(arr, fn(x, i) { #(i, x) })
|
||||||
Ok(do_list_permutation_with_repetitions(indexed_arr, k))
|
do_list_permutation_with_repetitions(indexed_arr, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_list_permutation_with_repetitions(
|
fn do_list_permutation_with_repetitions(
|
||||||
|
@ -636,7 +604,7 @@ fn do_list_permutation_with_repetitions(
|
||||||
/// set.from_list([])
|
/// set.from_list([])
|
||||||
/// |> combinatorics.cartesian_product(set.from_list([]))
|
/// |> combinatorics.cartesian_product(set.from_list([]))
|
||||||
/// |> should.equal(set.from_list([]))
|
/// |> should.equal(set.from_list([]))
|
||||||
///
|
///
|
||||||
/// // Cartesian product of two sets with numeric values
|
/// // Cartesian product of two sets with numeric values
|
||||||
/// set.from_list([1.0, 10.0])
|
/// set.from_list([1.0, 10.0])
|
||||||
/// |> combinatorics.cartesian_product(set.from_list([1.0, 2.0]))
|
/// |> combinatorics.cartesian_product(set.from_list([1.0, 2.0]))
|
||||||
|
|
|
@ -20,11 +20,11 @@
|
||||||
////<style>
|
////<style>
|
||||||
//// .katex { font-size: 1.1em; }
|
//// .katex { font-size: 1.1em; }
|
||||||
////</style>
|
////</style>
|
||||||
////
|
////
|
||||||
//// ---
|
//// ---
|
||||||
////
|
////
|
||||||
//// Elementary: A module containing a comprehensive set of foundational mathematical functions and constants.
|
//// Elementary: A module containing a comprehensive set of foundational mathematical functions and constants.
|
||||||
////
|
////
|
||||||
//// * **Trigonometric and hyperbolic functions**
|
//// * **Trigonometric and hyperbolic functions**
|
||||||
//// * [`acos`](#acos)
|
//// * [`acos`](#acos)
|
||||||
//// * [`acosh`](#acosh)
|
//// * [`acosh`](#acosh)
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
//// * [`pi`](#pi)
|
//// * [`pi`](#pi)
|
||||||
//// * [`tau`](#tau)
|
//// * [`tau`](#tau)
|
||||||
//// * [`e`](#e)
|
//// * [`e`](#e)
|
||||||
////
|
////
|
||||||
|
|
||||||
import gleam/int
|
import gleam/int
|
||||||
import gleam/option
|
import gleam/option
|
||||||
|
@ -98,14 +98,10 @@ import gleam/option
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn acos(x: Float) -> Result(Float, String) {
|
pub fn acos(x: Float) -> Result(Float, Nil) {
|
||||||
case x >=. -1.0 && x <=. 1.0 {
|
case x >=. -1.0 && x <=. 1.0 {
|
||||||
True ->
|
True -> Ok(do_acos(x))
|
||||||
do_acos(x)
|
False -> Error(Nil)
|
||||||
|> Ok
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,14 +146,10 @@ fn do_acos(a: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn acosh(x: Float) -> Result(Float, String) {
|
pub fn acosh(x: Float) -> Result(Float, Nil) {
|
||||||
case x >=. 1.0 {
|
case x >=. 1.0 {
|
||||||
True ->
|
True -> Ok(do_acosh(x))
|
||||||
do_acosh(x)
|
False -> Error(Nil)
|
||||||
|> Ok
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: x < 1. Valid input is x >= 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +170,7 @@ fn do_acosh(a: Float) -> Float
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// The function takes a number \\(x\\) in its domain \\(\[-1, 1\]\\) as input and returns a numeric
|
/// 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
|
/// 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.
|
/// radians). If the input value is outside the domain of the function an error is returned.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -205,14 +197,10 @@ fn do_acosh(a: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn asin(x: Float) -> Result(Float, String) {
|
pub fn asin(x: Float) -> Result(Float, Nil) {
|
||||||
case x >=. -1.0 && x <=. 1.0 {
|
case x >=. -1.0 && x <=. 1.0 {
|
||||||
True ->
|
True -> Ok(do_asin(x))
|
||||||
do_asin(x)
|
False -> Error(Nil)
|
||||||
|> Ok
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,8 +220,8 @@ fn do_asin(a: Float) -> Float
|
||||||
/// \forall x \in \(-\infty, \infty\), \\; \sinh^{-1}{(x)} = y \in \(-\infty, +\infty\)
|
/// \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
|
/// 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
|
/// returns a numeric value \\(y\\) that lies in the range \\(\(-\infty, +\infty\)\\) (an angle in
|
||||||
/// radians).
|
/// radians).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -274,7 +262,7 @@ fn do_asinh(a: Float) -> Float
|
||||||
/// \forall x \in \(-\infty, \infty\), \\; \tan^{-1}{(x)} = y \in \[-\frac{\pi}{2}, \frac{\pi}{2}\]
|
/// \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
|
/// 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}\]\\)
|
/// returns a numeric value \\(y\\) that lies in the range \\(\[-\frac{\pi}{2}, \frac{\pi}{2}\]\\)
|
||||||
/// (an angle in radians).
|
/// (an angle in radians).
|
||||||
///
|
///
|
||||||
|
@ -394,14 +382,10 @@ fn do_atan2(a: Float, b: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn atanh(x: Float) -> Result(Float, String) {
|
pub fn atanh(x: Float) -> Result(Float, Nil) {
|
||||||
case x >. -1.0 && x <. 1.0 {
|
case x >. -1.0 && x <. 1.0 {
|
||||||
True ->
|
True -> Ok(do_atanh(x))
|
||||||
do_atanh(x)
|
False -> Error(Nil)
|
||||||
|> Ok
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: x > -1 or x < 1. Valid input is -1. < x < 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +405,7 @@ fn do_atanh(a: Float) -> Float
|
||||||
/// \forall x \in \(-\infty, +\infty\), \\; \cos{(x)} = y \in \[-1, 1\]
|
/// \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
|
/// 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\]\\).
|
/// radians) as input and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -465,8 +449,8 @@ fn do_cos(a: Float) -> Float
|
||||||
/// \forall x \in \(-\infty, \infty\), \\; \cosh{(x)} = y \in \(-\infty, +\infty\)
|
/// \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
|
/// 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
|
/// 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.
|
/// \\(\(-\infty, \infty\)\\). If the input value is too large an overflow error might occur.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -507,7 +491,7 @@ fn do_cosh(a: Float) -> Float
|
||||||
/// \forall x \in \(-\infty, +\infty\), \\; \sin{(x)} = y \in \[-1, 1\]
|
/// \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
|
/// 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\]\\).
|
/// radians) as input and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -753,14 +737,10 @@ fn do_exponential(a: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn natural_logarithm(x: Float) -> Result(Float, String) {
|
pub fn natural_logarithm(x: Float) -> Result(Float, Nil) {
|
||||||
case x >. 0.0 {
|
case x >. 0.0 {
|
||||||
True ->
|
True -> Ok(do_natural_logarithm(x))
|
||||||
do_natural_logarithm(x)
|
False -> Error(Nil)
|
||||||
|> Ok
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,7 +760,7 @@ fn do_natural_logarithm(a: Float) -> Float
|
||||||
/// \forall x \in \(0, \infty\) \textnormal{ and } b > 1, \\; \log_{b}{(x)} = y \in \(-\infty, +\infty\)
|
/// \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\\)
|
/// 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\)\\).
|
/// 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.
|
/// If the input value is outside the domain of the function an error is returned.
|
||||||
///
|
///
|
||||||
|
@ -810,30 +790,19 @@ fn do_natural_logarithm(a: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String) {
|
pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, Nil) {
|
||||||
case x >. 0.0 {
|
case x >. 0.0, base {
|
||||||
True ->
|
True, option.Some(a) ->
|
||||||
case base {
|
case a >. 0.0 && a != 1.0 {
|
||||||
option.Some(a) ->
|
False -> Error(Nil)
|
||||||
case a >. 0.0 && a != 1.0 {
|
True -> {
|
||||||
True -> {
|
// Apply the "change of base formula"
|
||||||
// Apply the "change of base formula"
|
let assert Ok(numerator) = logarithm_10(x)
|
||||||
let assert Ok(numerator) = logarithm_10(x)
|
let assert Ok(denominator) = logarithm_10(a)
|
||||||
let assert Ok(denominator) = logarithm_10(a)
|
Ok(numerator /. denominator)
|
||||||
numerator /. denominator
|
}
|
||||||
|> Ok
|
|
||||||
}
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
_ ->
|
|
||||||
"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
_ ->
|
_, _ -> Error(Nil)
|
||||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,7 +818,7 @@ pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String)
|
||||||
/// \forall x \in \(0, \infty), \\; \log_{2}{(x)} = y \in \(-\infty, +\infty\)
|
/// \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
|
/// 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\)\\).
|
/// 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.
|
/// If the input value is outside the domain of the function an error is returned.
|
||||||
///
|
///
|
||||||
|
@ -877,14 +846,10 @@ pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String)
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn logarithm_2(x: Float) -> Result(Float, String) {
|
pub fn logarithm_2(x: Float) -> Result(Float, Nil) {
|
||||||
case x >. 0.0 {
|
case x >. 0.0 {
|
||||||
True ->
|
True -> Ok(do_logarithm_2(x))
|
||||||
do_logarithm_2(x)
|
False -> Error(Nil)
|
||||||
|> Ok
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,7 +869,7 @@ fn do_logarithm_2(a: Float) -> Float
|
||||||
/// \forall x \in \(0, \infty), \\; \log_{10}{(x)} = y \in \(-\infty, +\infty\)
|
/// \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
|
/// 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\)\\).
|
/// 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.
|
/// If the input value is outside the domain of the function an error is returned.
|
||||||
///
|
///
|
||||||
|
@ -932,14 +897,10 @@ fn do_logarithm_2(a: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn logarithm_10(x: Float) -> Result(Float, String) {
|
pub fn logarithm_10(x: Float) -> Result(Float, Nil) {
|
||||||
case x >. 0.0 {
|
case x >. 0.0 {
|
||||||
True ->
|
True -> Ok(do_logarithm_10(x))
|
||||||
do_logarithm_10(x)
|
False -> Error(Nil)
|
||||||
|> Ok
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,7 +954,7 @@ fn do_logarithm_10(a: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn power(x: Float, y: Float) -> Result(Float, String) {
|
pub fn power(x: Float, y: Float) -> Result(Float, Nil) {
|
||||||
let fractional: Bool = do_ceiling(y) -. y >. 0.0
|
let fractional: Bool = do_ceiling(y) -. y >. 0.0
|
||||||
// In the following check:
|
// In the following check:
|
||||||
// 1. If the base (x) is negative and the exponent (y) is fractional
|
// 1. If the base (x) is negative and the exponent (y) is fractional
|
||||||
|
@ -1002,9 +963,7 @@ pub fn power(x: Float, y: Float) -> Result(Float, String) {
|
||||||
// expression is equivalent to the exponent (y) divided by 0 and an
|
// expression is equivalent to the exponent (y) divided by 0 and an
|
||||||
// error should be returned
|
// error should be returned
|
||||||
case { x <. 0.0 && fractional } || { x == 0.0 && y <. 0.0 } {
|
case { x <. 0.0 && fractional } || { x == 0.0 && y <. 0.0 } {
|
||||||
True ->
|
True -> Error(Nil)
|
||||||
"Invalid input argument: x < 0 and y is fractional or x = 0 and y < 0."
|
|
||||||
|> Error
|
|
||||||
False ->
|
False ->
|
||||||
do_power(x, y)
|
do_power(x, y)
|
||||||
|> Ok
|
|> Ok
|
||||||
|
@ -1055,19 +1014,13 @@ fn do_ceiling(a: Float) -> Float
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn square_root(x: Float) -> Result(Float, String) {
|
pub fn square_root(x: Float) -> Result(Float, Nil) {
|
||||||
// In the following check:
|
// In the following check:
|
||||||
// 1. If x is negative then return an error as it will otherwise be an
|
// 1. If x is negative then return an error as it will otherwise be an
|
||||||
// imaginary number
|
// imaginary number
|
||||||
case x <. 0.0 {
|
case x <. 0.0 {
|
||||||
True ->
|
True -> Error(Nil)
|
||||||
"Invalid input argument: x < 0."
|
False -> power(x, 1.0 /. 2.0)
|
||||||
|> Error
|
|
||||||
False -> {
|
|
||||||
let assert Ok(result) = power(x, 1.0 /. 2.0)
|
|
||||||
result
|
|
||||||
|> Ok
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,19 +1060,13 @@ pub fn square_root(x: Float) -> Result(Float, String) {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn cube_root(x: Float) -> Result(Float, String) {
|
pub fn cube_root(x: Float) -> Result(Float, Nil) {
|
||||||
// In the following check:
|
// In the following check:
|
||||||
// 1. If x is negative then return an error as it will otherwise be an
|
// 1. If x is negative then return an error as it will otherwise be an
|
||||||
// imaginary number
|
// imaginary number
|
||||||
case x <. 0.0 {
|
case x <. 0.0 {
|
||||||
True ->
|
True -> Error(Nil)
|
||||||
"Invalid input argument: x < 0."
|
False -> power(x, 1.0 /. 3.0)
|
||||||
|> Error
|
|
||||||
False -> {
|
|
||||||
let assert Ok(result) = power(x, 1.0 /. 3.0)
|
|
||||||
result
|
|
||||||
|> Ok
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1162,25 +1109,13 @@ pub fn cube_root(x: Float) -> Result(Float, String) {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn nth_root(x: Float, n: Int) -> Result(Float, String) {
|
pub fn nth_root(x: Float, n: Int) -> Result(Float, Nil) {
|
||||||
// In the following check:
|
// In the following check:
|
||||||
// 1. If x is negative then return an error as it will otherwise be an
|
// 1. If x is negative then return an error as it will otherwise be an
|
||||||
// imaginary number
|
// imaginary number
|
||||||
case x <. 0.0 {
|
case x >=. 0.0 && n >= 1 {
|
||||||
True ->
|
True -> power(x, 1.0 /. int.to_float(n))
|
||||||
"Invalid input argument: x < 0. Valid input is x > 0"
|
False -> Error(Nil)
|
||||||
|> Error
|
|
||||||
False ->
|
|
||||||
case n >= 1 {
|
|
||||||
True -> {
|
|
||||||
let assert Ok(result) = power(x, 1.0 /. int.to_float(n))
|
|
||||||
result
|
|
||||||
|> Ok
|
|
||||||
}
|
|
||||||
False ->
|
|
||||||
"Invalid input argument: n < 1. Valid input is n >= 2."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,18 @@
|
||||||
////<style>
|
////<style>
|
||||||
//// .katex { font-size: 1.1em; }
|
//// .katex { font-size: 1.1em; }
|
||||||
////</style>
|
////</style>
|
||||||
////
|
////
|
||||||
//// ---
|
//// ---
|
||||||
////
|
////
|
||||||
//// Metrics: A module offering functions for calculating distances and other
|
//// Metrics: A module offering functions for calculating distances and other
|
||||||
//// types of metrics.
|
//// types of metrics.
|
||||||
////
|
////
|
||||||
//// Disclaimer: In this module, the terms "distance" and "metric" are used in
|
//// Disclaimer: In this module, the terms "distance" and "metric" are used in
|
||||||
//// a broad and practical sense. That is, they are used to denote any difference
|
//// a broad and practical sense. That is, they are used to denote any difference
|
||||||
//// or discrepancy between two inputs. Consequently, they may not align with their
|
//// or discrepancy between two inputs. Consequently, they may not align with their
|
||||||
//// precise mathematical definitions (in particular, some "distance" functions in
|
//// precise mathematical definitions (in particular, some "distance" functions in
|
||||||
//// this module do not satisfy the triangle inequality).
|
//// this module do not satisfy the triangle inequality).
|
||||||
////
|
////
|
||||||
//// * **Distance measures**
|
//// * **Distance measures**
|
||||||
//// * [`norm`](#norm)
|
//// * [`norm`](#norm)
|
||||||
//// * [`manhattan_distance`](#manhattan_distance)
|
//// * [`manhattan_distance`](#manhattan_distance)
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
//// * [`median`](#median)
|
//// * [`median`](#median)
|
||||||
//// * [`variance`](#variance)
|
//// * [`variance`](#variance)
|
||||||
//// * [`standard_deviation`](#standard_deviation)
|
//// * [`standard_deviation`](#standard_deviation)
|
||||||
////
|
////
|
||||||
|
|
||||||
import gleam/bool
|
import gleam/bool
|
||||||
import gleam/float
|
import gleam/float
|
||||||
|
@ -59,6 +59,7 @@ import gleam/int
|
||||||
import gleam/list
|
import gleam/list
|
||||||
import gleam/option
|
import gleam/option
|
||||||
import gleam/pair
|
import gleam/pair
|
||||||
|
import gleam/result
|
||||||
import gleam/set
|
import gleam/set
|
||||||
import gleam_community/maths/arithmetics
|
import gleam_community/maths/arithmetics
|
||||||
import gleam_community/maths/conversion
|
import gleam_community/maths/conversion
|
||||||
|
@ -72,21 +73,15 @@ fn validate_lists(
|
||||||
xarr: List(Float),
|
xarr: List(Float),
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Bool, String) {
|
) -> Result(Bool, Nil) {
|
||||||
case xarr, yarr {
|
case xarr, yarr {
|
||||||
[], _ ->
|
[], _ -> Error(Nil)
|
||||||
"Invalid input argument: The list xarr is empty."
|
_, [] -> Error(Nil)
|
||||||
|> Error
|
|
||||||
_, [] ->
|
|
||||||
"Invalid input argument: The list yarr is empty."
|
|
||||||
|> Error
|
|
||||||
_, _ -> {
|
_, _ -> {
|
||||||
let xarr_length: Int = list.length(xarr)
|
let xarr_length: Int = list.length(xarr)
|
||||||
let yarr_length: Int = list.length(yarr)
|
let yarr_length: Int = list.length(yarr)
|
||||||
case xarr_length == yarr_length, weights {
|
case xarr_length == yarr_length, weights {
|
||||||
False, _ ->
|
False, _ -> Error(Nil)
|
||||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
|
||||||
|> Error
|
|
||||||
True, option.None -> {
|
True, option.None -> {
|
||||||
True
|
True
|
||||||
|> Ok
|
|> Ok
|
||||||
|
@ -97,9 +92,7 @@ fn validate_lists(
|
||||||
True -> {
|
True -> {
|
||||||
validate_weights(warr)
|
validate_weights(warr)
|
||||||
}
|
}
|
||||||
False ->
|
False -> Error(Nil)
|
||||||
"Invalid input argument: length(weights) != length(xarr) and length(weights) != length(yarr). Valid input is when length(weights) == length(xarr) == length(yarr)."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,16 +100,12 @@ fn validate_lists(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_weights(warr: List(Float)) -> Result(Bool, String) {
|
fn validate_weights(warr: List(Float)) -> Result(Bool, Nil) {
|
||||||
// Check that all the given weights are positive
|
// Check that all the given weights are positive
|
||||||
let assert Ok(minimum) = piecewise.list_minimum(warr, float.compare)
|
let assert Ok(minimum) = piecewise.list_minimum(warr, float.compare)
|
||||||
case minimum >=. 0.0 {
|
case minimum >=. 0.0 {
|
||||||
False ->
|
False -> Error(Nil)
|
||||||
"Invalid input argument: One or more weights are negative. Valid input is when all weights are >= 0."
|
True -> Ok(True)
|
||||||
|> Error
|
|
||||||
True ->
|
|
||||||
True
|
|
||||||
|> Ok
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +121,7 @@ fn validate_weights(warr: List(Float)) -> Result(Bool, String) {
|
||||||
/// \left( \sum_{i=1}^n w_{i} \left|x_{i}\right|^{p} \right)^{\frac{1}{p}}
|
/// \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
|
/// 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
|
/// the input list indexed by \\(i\\), while \\(w_i \in \mathbb{R}_{+}\\) is
|
||||||
/// a corresponding positive weight (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
/// a corresponding positive weight (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
|
@ -147,14 +136,14 @@ fn validate_weights(warr: List(Float)) -> Result(Bool, String) {
|
||||||
///
|
///
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||||
///
|
///
|
||||||
/// let assert Ok(result) =
|
/// let assert Ok(result) =
|
||||||
/// [1.0, 1.0, 1.0]
|
/// [1.0, 1.0, 1.0]
|
||||||
/// |> metrics.norm(1.0, option.None)
|
/// |> metrics.norm(1.0, option.None)
|
||||||
/// result
|
/// result
|
||||||
/// |> predicates.is_close(3.0, 0.0, tol)
|
/// |> predicates.is_close(3.0, 0.0, tol)
|
||||||
/// |> should.be_true()
|
/// |> should.be_true()
|
||||||
///
|
///
|
||||||
/// let assert Ok(result) =
|
/// let assert Ok(result) =
|
||||||
/// [1.0, 1.0, 1.0]
|
/// [1.0, 1.0, 1.0]
|
||||||
/// |> metrics.norm(-1.0, option.None)
|
/// |> metrics.norm(-1.0, option.None)
|
||||||
|
@ -174,7 +163,7 @@ pub fn norm(
|
||||||
arr: List(Float),
|
arr: List(Float),
|
||||||
p: Float,
|
p: Float,
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case arr, weights {
|
case arr, weights {
|
||||||
[], _ ->
|
[], _ ->
|
||||||
0.0
|
0.0
|
||||||
|
@ -224,10 +213,7 @@ pub fn norm(
|
||||||
|> Error
|
|> Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
False -> {
|
False -> Error(Nil)
|
||||||
"Invalid input argument: length(weights) != length(arr). Valid input is when length(weights) == length(arr)."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,16 +225,16 @@ pub fn norm(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Calculate the (weighted) Manhattan distance between two lists (representing
|
/// Calculate the (weighted) Manhattan distance between two lists (representing
|
||||||
/// vectors):
|
/// vectors):
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \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
|
/// 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
|
/// values in the respective input lists indexed by \\(i\\), while the
|
||||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -266,11 +252,11 @@ pub fn norm(
|
||||||
/// // Empty lists returns an error
|
/// // Empty lists returns an error
|
||||||
/// metrics.manhattan_distance([], [], option.None)
|
/// metrics.manhattan_distance([], [], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Differing lengths returns error
|
/// // Differing lengths returns error
|
||||||
/// metrics.manhattan_distance([], [1.0], option.None)
|
/// metrics.manhattan_distance([], [1.0], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// let assert Ok(result) =
|
/// let assert Ok(result) =
|
||||||
/// metrics.manhattan_distance([0.0, 0.0], [1.0, 2.0], option.None)
|
/// metrics.manhattan_distance([0.0, 0.0], [1.0, 2.0], option.None)
|
||||||
/// result
|
/// result
|
||||||
|
@ -289,7 +275,7 @@ pub fn manhattan_distance(
|
||||||
xarr: List(Float),
|
xarr: List(Float),
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
minkowski_distance(xarr, yarr, 1.0, weights)
|
minkowski_distance(xarr, yarr, 1.0, weights)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,12 +292,12 @@ pub fn manhattan_distance(
|
||||||
/// \left( \sum_{i=1}^n w_{i} \left|x_i - y_i \right|^{p} \right)^{\frac{1}{p}}
|
/// \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
|
/// 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\\).
|
/// and \\(x_i, y_i\\) are the values in the respective input lists indexed by \\(i\\).
|
||||||
/// The \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
/// The \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
/// The Minkowski distance is a generalization of both the Euclidean distance
|
/// The Minkowski distance is a generalization of both the Euclidean distance
|
||||||
/// (\\(p=2\\)) and the Manhattan distance (\\(p = 1\\)).
|
/// (\\(p=2\\)) and the Manhattan distance (\\(p = 1\\)).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -325,11 +311,11 @@ pub fn manhattan_distance(
|
||||||
///
|
///
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||||
///
|
///
|
||||||
/// // Empty lists returns an error
|
/// // Empty lists returns an error
|
||||||
/// metrics.minkowski_distance([], [], 1.0, option.None)
|
/// metrics.minkowski_distance([], [], 1.0, option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Differing lengths returns error
|
/// // Differing lengths returns error
|
||||||
/// metrics.minkowski_distance([], [1.0], 1.0, option.None)
|
/// metrics.minkowski_distance([], [1.0], 1.0, option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
|
@ -337,7 +323,7 @@ pub fn manhattan_distance(
|
||||||
/// // Test order < 1
|
/// // Test order < 1
|
||||||
/// metrics.minkowski_distance([0.0, 0.0], [0.0, 0.0], -1.0, option.None)
|
/// metrics.minkowski_distance([0.0, 0.0], [0.0, 0.0], -1.0, option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// let assert Ok(result) =
|
/// let assert Ok(result) =
|
||||||
/// metrics.minkowski_distance([0.0, 0.0], [1.0, 2.0], 1.0, option.None)
|
/// metrics.minkowski_distance([0.0, 0.0], [1.0, 2.0], 1.0, option.None)
|
||||||
/// result
|
/// result
|
||||||
|
@ -357,28 +343,18 @@ pub fn minkowski_distance(
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
p: Float,
|
p: Float,
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case validate_lists(xarr, yarr, weights) {
|
use _ <- result.try(validate_lists(xarr, yarr, weights))
|
||||||
Error(msg) ->
|
case p <. 1.0 {
|
||||||
msg
|
True -> Error(Nil)
|
||||||
|> Error
|
False -> {
|
||||||
Ok(_) -> {
|
let differences: List(Float) =
|
||||||
case p <. 1.0 {
|
list.zip(xarr, yarr)
|
||||||
True ->
|
|> list.map(fn(tuple: #(Float, Float)) -> Float {
|
||||||
"Invalid input argument: p < 1. Valid input is p >= 1."
|
pair.first(tuple) -. pair.second(tuple)
|
||||||
|> Error
|
})
|
||||||
False -> {
|
|
||||||
let differences: List(Float) =
|
|
||||||
list.zip(xarr, yarr)
|
|
||||||
|> list.map(fn(tuple: #(Float, Float)) -> Float {
|
|
||||||
pair.first(tuple) -. pair.second(tuple)
|
|
||||||
})
|
|
||||||
|
|
||||||
let assert Ok(result) = norm(differences, p, weights)
|
norm(differences, p, weights)
|
||||||
result
|
|
||||||
|> Ok
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,7 +365,7 @@ pub fn minkowski_distance(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Calculate the (weighted) Euclidean distance between two lists (representing
|
/// Calculate the (weighted) Euclidean distance between two lists (representing
|
||||||
/// vectors):
|
/// vectors):
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
|
@ -398,7 +374,7 @@ pub fn minkowski_distance(
|
||||||
///
|
///
|
||||||
/// In the formula, \\(n\\) is the length of the two lists and \\(x_i, y_i\\) are the
|
/// 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
|
/// values in the respective input lists indexed by \\(i\\), while the
|
||||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -412,15 +388,15 @@ pub fn minkowski_distance(
|
||||||
///
|
///
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||||
///
|
///
|
||||||
/// // Empty lists returns an error
|
/// // Empty lists returns an error
|
||||||
/// metrics.euclidean_distance([], [], option.None)
|
/// metrics.euclidean_distance([], [], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Differing lengths returns an error
|
/// // Differing lengths returns an error
|
||||||
/// metrics.euclidean_distance([], [1.0], option.None)
|
/// metrics.euclidean_distance([], [1.0], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// let assert Ok(result) =
|
/// let assert Ok(result) =
|
||||||
/// metrics.euclidean_distance([0.0, 0.0], [1.0, 2.0], option.None)
|
/// metrics.euclidean_distance([0.0, 0.0], [1.0, 2.0], option.None)
|
||||||
/// result
|
/// result
|
||||||
|
@ -439,7 +415,7 @@ pub fn euclidean_distance(
|
||||||
xarr: List(Float),
|
xarr: List(Float),
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
minkowski_distance(xarr, yarr, 2.0, weights)
|
minkowski_distance(xarr, yarr, 2.0, weights)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +431,7 @@ pub fn euclidean_distance(
|
||||||
/// \text{max}_{i=1}^n \left|x_i - y_i \right|
|
/// \text{max}_{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
|
/// 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\\).
|
/// values in the respective input lists indexed by \\(i\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -470,11 +446,11 @@ pub fn euclidean_distance(
|
||||||
/// // Empty lists returns an error
|
/// // Empty lists returns an error
|
||||||
/// metrics.chebyshev_distance([], [])
|
/// metrics.chebyshev_distance([], [])
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Differing lengths returns error
|
/// // Differing lengths returns error
|
||||||
/// metrics.chebyshev_distance([], [1.0])
|
/// metrics.chebyshev_distance([], [1.0])
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// metrics.chebyshev_distance([-5.0, -10.0, -3.0], [-1.0, -12.0, -3.0])
|
/// metrics.chebyshev_distance([-5.0, -10.0, -3.0], [-1.0, -12.0, -3.0])
|
||||||
/// |> should.equal(Ok(4.0))
|
/// |> should.equal(Ok(4.0))
|
||||||
/// }
|
/// }
|
||||||
|
@ -489,7 +465,7 @@ pub fn euclidean_distance(
|
||||||
pub fn chebyshev_distance(
|
pub fn chebyshev_distance(
|
||||||
xarr: List(Float),
|
xarr: List(Float),
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case validate_lists(xarr, yarr, option.None) {
|
case validate_lists(xarr, yarr, option.None) {
|
||||||
Error(msg) ->
|
Error(msg) ->
|
||||||
msg
|
msg
|
||||||
|
@ -545,11 +521,9 @@ pub fn chebyshev_distance(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn mean(arr: List(Float)) -> Result(Float, String) {
|
pub fn mean(arr: List(Float)) -> Result(Float, Nil) {
|
||||||
case arr {
|
case arr {
|
||||||
[] ->
|
[] -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
|
||||||
|> Error
|
|
||||||
_ ->
|
_ ->
|
||||||
arr
|
arr
|
||||||
|> arithmetics.float_sum(option.None)
|
|> arithmetics.float_sum(option.None)
|
||||||
|
@ -632,14 +606,14 @@ fn do_median(
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Calculate the sample variance of the elements in a list:
|
/// Calculate the sample variance of the elements in a list:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// s^{2} = \frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})
|
/// 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\\)
|
/// 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\\).
|
/// is the sample point in the input list indexed by \\(i\\).
|
||||||
/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
|
/// 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
|
/// 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.
|
/// estimate of the sample variance. Setting \\(d = 1\\) gives an unbiased estimate.
|
||||||
///
|
///
|
||||||
|
@ -671,34 +645,27 @@ fn do_median(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, Nil) {
|
||||||
case arr {
|
case arr, ddof {
|
||||||
[] ->
|
[], _ -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
_, _ if ddof < 0 -> Error(Nil)
|
||||||
|> Error
|
_, _ -> {
|
||||||
_ ->
|
let assert Ok(mean) = mean(arr)
|
||||||
case ddof < 0 {
|
arr
|
||||||
True ->
|
|> list.map(fn(a: Float) -> Float {
|
||||||
"Invalid input argument: ddof < 0. Valid input is ddof >= 0."
|
let assert Ok(result) = elementary.power(a -. mean, 2.0)
|
||||||
|> Error
|
result
|
||||||
False -> {
|
})
|
||||||
let assert Ok(mean) = mean(arr)
|
|> arithmetics.float_sum(option.None)
|
||||||
arr
|
|> fn(a: Float) -> Float {
|
||||||
|> list.map(fn(a: Float) -> Float {
|
a
|
||||||
let assert Ok(result) = elementary.power(a -. mean, 2.0)
|
/. {
|
||||||
result
|
conversion.int_to_float(list.length(arr))
|
||||||
})
|
-. conversion.int_to_float(ddof)
|
||||||
|> arithmetics.float_sum(option.None)
|
|
||||||
|> fn(a: Float) -> Float {
|
|
||||||
a
|
|
||||||
/. {
|
|
||||||
conversion.int_to_float(list.length(arr))
|
|
||||||
-. conversion.int_to_float(ddof)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|> Ok
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|> Ok
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,11 +680,11 @@ pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
||||||
/// s = \left(\frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})\right)^{\frac{1}{2}}
|
/// 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\\)
|
/// 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\\).
|
/// is the sample point in the input list indexed by \\(i\\).
|
||||||
/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
|
/// 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
|
/// 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 of the sample standard deviation. Setting \\(d = 1\\) gives an unbiased
|
||||||
/// estimate.
|
/// estimate.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -748,25 +715,18 @@ pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn standard_deviation(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
pub fn standard_deviation(arr: List(Float), ddof: Int) -> Result(Float, Nil) {
|
||||||
case arr {
|
case arr, ddof {
|
||||||
[] ->
|
[], _ -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
_, _ if ddof < 0 -> Error(Nil)
|
||||||
|> Error
|
_, _ -> {
|
||||||
_ ->
|
let assert Ok(variance) = variance(arr, ddof)
|
||||||
case ddof < 0 {
|
// The computed variance will always be positive
|
||||||
True ->
|
// So an error should never be returned
|
||||||
"Invalid input argument: ddof < 0. Valid input is ddof >= 0."
|
let assert Ok(stdev) = elementary.square_root(variance)
|
||||||
|> Error
|
stdev
|
||||||
False -> {
|
|> Ok
|
||||||
let assert Ok(variance) = variance(arr, ddof)
|
}
|
||||||
// The computed variance will always be positive
|
|
||||||
// So an error should never be returned
|
|
||||||
let assert Ok(stdev) = elementary.square_root(variance)
|
|
||||||
stdev
|
|
||||||
|> Ok
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,24 +736,24 @@ pub fn standard_deviation(arr: List(Float), ddof: Int) -> Result(Float, String)
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The Jaccard index measures similarity between two sets of elements.
|
/// The Jaccard index measures similarity between two sets of elements.
|
||||||
/// Mathematically, the Jaccard index is defined as:
|
/// Mathematically, the Jaccard index is defined as:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \frac{|X \cap Y|}{|X \cup Y|} \\; \in \\; \left[0, 1\right]
|
/// \frac{|X \cap Y|}{|X \cup Y|} \\; \in \\; \left[0, 1\right]
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// where:
|
/// where:
|
||||||
///
|
///
|
||||||
/// - \\(X\\) and \\(Y\\) are two sets being compared,
|
/// - \\(X\\) and \\(Y\\) are two sets being compared,
|
||||||
/// - \\(|X \cap Y|\\) represents the size of the intersection of the two sets
|
/// - \\(|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
|
/// - \\(|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
|
/// 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
|
/// 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
|
/// Jaccard index is a special case of the [Tversky index](#tversky_index) (with
|
||||||
/// \\(\alpha=\beta=1\\)).
|
/// \\(\alpha=\beta=1\\)).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -827,25 +787,25 @@ pub fn jaccard_index(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The Sørensen-Dice coefficient measures the similarity between two sets of
|
/// The Sørensen-Dice coefficient measures the similarity between two sets of
|
||||||
/// elements. Mathematically, the coefficient is defined as:
|
/// elements. Mathematically, the coefficient is defined as:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \frac{2 |X \cap Y|}{|X| + |Y|} \\; \in \\; \left[0, 1\right]
|
/// \frac{2 |X \cap Y|}{|X| + |Y|} \\; \in \\; \left[0, 1\right]
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// where:
|
/// where:
|
||||||
/// - \\(X\\) and \\(Y\\) are two sets being compared
|
/// - \\(X\\) and \\(Y\\) are two sets being compared
|
||||||
/// - \\(|X \cap Y|\\) is the size of the intersection of the two sets (i.e., the
|
/// - \\(|X \cap Y|\\) is the size of the intersection of the two sets (i.e., the
|
||||||
/// number of elements common to both sets)
|
/// number of elements common to both sets)
|
||||||
/// - \\(|X|\\) and \\(|Y|\\) are the sizes of the sets \\(X\\) and \\(Y\\), respectively
|
/// - \\(|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
|
/// 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).
|
/// 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 higher the coefficient, the greater the similarity between the two sets.
|
||||||
/// The Sørensen-Dice coefficient is a special case of the
|
/// The Sørensen-Dice coefficient is a special case of the
|
||||||
/// [Tversky index](#tversky_index) (with \\(\alpha=\beta=0.5\\)).
|
/// [Tversky index](#tversky_index) (with \\(\alpha=\beta=0.5\\)).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -878,31 +838,31 @@ pub fn sorensen_dice_coefficient(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
||||||
/// <small>Spot a typo? Open an issue!</small>
|
/// <small>Spot a typo? Open an issue!</small>
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The Tversky index is a generalization of the Jaccard index and Sørensen-Dice
|
/// The Tversky index is a generalization of the Jaccard index and Sørensen-Dice
|
||||||
/// coefficient, which adds flexibility through two parameters, \\(\alpha\\) and
|
/// coefficient, which adds flexibility through two parameters, \\(\alpha\\) and
|
||||||
/// \\(\beta\\), allowing for asymmetric similarity measures between sets. The
|
/// \\(\beta\\), allowing for asymmetric similarity measures between sets. The
|
||||||
/// Tversky index is defined as:
|
/// Tversky index is defined as:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \frac{|X \cap Y|}{|X \cap Y| + \alpha|X - Y| + \beta|Y - X|}
|
/// \frac{|X \cap Y|}{|X \cap Y| + \alpha|X - Y| + \beta|Y - X|}
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// where:
|
/// where:
|
||||||
///
|
///
|
||||||
/// - \\(X\\) and \\(Y\\) are the sets being compared
|
/// - \\(X\\) and \\(Y\\) are the sets being compared
|
||||||
/// - \\(|X - Y|\\) and \\(|Y - X|\\) are the sizes of the relative complements of
|
/// - \\(|X - Y|\\) and \\(|Y - X|\\) are the sizes of the relative complements of
|
||||||
/// \\(Y\\) in \\(X\\) and \\(X\\) in \\(Y\\), respectively,
|
/// \\(Y\\) in \\(X\\) and \\(X\\) in \\(Y\\), respectively,
|
||||||
/// - \\(\alpha\\) and \\(\beta\\) are parameters that weigh the relative importance
|
/// - \\(\alpha\\) and \\(\beta\\) are parameters that weigh the relative importance
|
||||||
/// of the elements unique to \\(X\\) and \\(Y\\)
|
/// of the elements unique to \\(X\\) and \\(Y\\)
|
||||||
///
|
///
|
||||||
/// The Tversky index reduces to the Jaccard index when \\(\alpha = \beta = 1\\) and
|
/// 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
|
/// 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
|
/// 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.
|
/// 0 when there is no intersection between the two sets, indicating no similarity.
|
||||||
/// However, unlike similarity measures bounded strictly between 0 and 1, the
|
/// 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\\).
|
/// Tversky index does not have a strict upper limit of 1 when \\(\alpha \neq \beta\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -931,7 +891,7 @@ pub fn tversky_index(
|
||||||
yset: set.Set(a),
|
yset: set.Set(a),
|
||||||
alpha: Float,
|
alpha: Float,
|
||||||
beta: Float,
|
beta: Float,
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case alpha >=. 0.0, beta >=. 0.0 {
|
case alpha >=. 0.0, beta >=. 0.0 {
|
||||||
True, True -> {
|
True, True -> {
|
||||||
let intersection: Float =
|
let intersection: Float =
|
||||||
|
@ -950,18 +910,7 @@ pub fn tversky_index(
|
||||||
/. { intersection +. alpha *. difference1 +. beta *. difference2 }
|
/. { intersection +. alpha *. difference1 +. beta *. difference2 }
|
||||||
|> Ok
|
|> Ok
|
||||||
}
|
}
|
||||||
False, True -> {
|
_, _ -> Error(Nil)
|
||||||
"Invalid input argument: alpha < 0. Valid input is alpha >= 0."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
True, False -> {
|
|
||||||
"Invalid input argument: beta < 0. Valid input is beta >= 0."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
_, _ -> {
|
|
||||||
"Invalid input argument: alpha < 0 and beta < 0. Valid input is alpha >= 0 and beta >= 0."
|
|
||||||
|> Error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,10 +919,10 @@ pub fn tversky_index(
|
||||||
/// <small>Spot a typo? Open an issue!</small>
|
/// <small>Spot a typo? Open an issue!</small>
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The Overlap coefficient, also known as the Szymkiewicz–Simpson coefficient, is
|
/// 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
|
/// 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
|
/// intersection relative to the smaller of the two sets. It is defined
|
||||||
/// mathematically as:
|
/// mathematically as:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
|
@ -986,10 +935,10 @@ pub fn tversky_index(
|
||||||
/// - \\(|X \cap Y|\\) is the size of the intersection of the sets
|
/// - \\(|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\\)
|
/// - \\(\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
|
/// 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
|
/// indicates that the smaller set is a suyset of the larger set. This
|
||||||
/// measure is especially useful in situations where the similarity in terms
|
/// measure is especially useful in situations where the similarity in terms
|
||||||
/// of the proportion of overlap is more relevant than the difference in sizes
|
/// of the proportion of overlap is more relevant than the difference in sizes
|
||||||
/// between the two sets.
|
/// between the two sets.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -1031,27 +980,27 @@ pub fn overlap_coefficient(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
||||||
/// <small>Spot a typo? Open an issue!</small>
|
/// <small>Spot a typo? Open an issue!</small>
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Calculate the (weighted) cosine similarity between two lists (representing
|
/// Calculate the (weighted) cosine similarity between two lists (representing
|
||||||
/// vectors):
|
/// vectors):
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \frac{\sum_{i=1}^n w_{i} \cdot x_i \cdot y_i}
|
/// \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}}
|
/// {\left(\sum_{i=1}^n w_{i} \cdot x_i^2\right)^{\frac{1}{2}}
|
||||||
/// \cdot
|
/// \cdot
|
||||||
/// \left(\sum_{i=1}^n w_{i} \cdot y_i^2\right)^{\frac{1}{2}}}
|
/// \left(\sum_{i=1}^n w_{i} \cdot y_i^2\right)^{\frac{1}{2}}}
|
||||||
/// \\; \in \\; \left[-1, 1\right]
|
/// \\; \in \\; \left[-1, 1\right]
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// In the formula, \\(n\\) is the length of the two lists and \\(x_i\\), \\(y_i\\) are
|
/// 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
|
/// the values in the respective input lists indexed by \\(i\\), while the
|
||||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
/// The cosine similarity provides a value between -1 and 1, where 1 means the
|
/// 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
|
/// vectors are in the same direction, -1 means they are in exactly opposite
|
||||||
/// directions, and 0 indicates orthogonality.
|
/// directions, and 0 indicates orthogonality.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -1063,11 +1012,11 @@ pub fn overlap_coefficient(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
||||||
/// // Two orthogonal vectors
|
/// // Two orthogonal vectors
|
||||||
/// metrics.cosine_similarity([-1.0, 1.0, 0.0], [1.0, 1.0, -1.0], option.None)
|
/// metrics.cosine_similarity([-1.0, 1.0, 0.0], [1.0, 1.0, -1.0], option.None)
|
||||||
/// |> should.equal(Ok(0.0))
|
/// |> should.equal(Ok(0.0))
|
||||||
///
|
///
|
||||||
/// // Two identical (parallel) vectors
|
/// // Two identical (parallel) vectors
|
||||||
/// metrics.cosine_similarity([1.0, 2.0, 3.0], [1.0, 2.0, 3.0], option.None)
|
/// metrics.cosine_similarity([1.0, 2.0, 3.0], [1.0, 2.0, 3.0], option.None)
|
||||||
/// |> should.equal(Ok(1.0))
|
/// |> should.equal(Ok(1.0))
|
||||||
///
|
///
|
||||||
/// // Two parallel, but oppositely oriented vectors
|
/// // Two parallel, but oppositely oriented vectors
|
||||||
/// metrics.cosine_similarity([-1.0, -2.0, -3.0], [1.0, 2.0, 3.0], option.None)
|
/// metrics.cosine_similarity([-1.0, -2.0, -3.0], [1.0, 2.0, 3.0], option.None)
|
||||||
/// |> should.equal(Ok(-1.0))
|
/// |> should.equal(Ok(-1.0))
|
||||||
|
@ -1084,7 +1033,7 @@ pub fn cosine_similarity(
|
||||||
xarr: List(Float),
|
xarr: List(Float),
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case validate_lists(xarr, yarr, weights) {
|
case validate_lists(xarr, yarr, weights) {
|
||||||
Error(msg) ->
|
Error(msg) ->
|
||||||
msg
|
msg
|
||||||
|
@ -1135,7 +1084,7 @@ pub fn cosine_similarity(
|
||||||
/// <small>Spot a typo? Open an issue!</small>
|
/// <small>Spot a typo? Open an issue!</small>
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Calculate the (weighted) Canberra distance between two lists:
|
/// Calculate the (weighted) Canberra distance between two lists:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
|
@ -1143,10 +1092,10 @@ pub fn cosine_similarity(
|
||||||
/// {\left| x_i \right| + \left| y_i \right|}
|
/// {\left| x_i \right| + \left| y_i \right|}
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// In the formula, \\(n\\) is the length of the two lists, and \\(x_i, y_i\\) are the
|
/// 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
|
/// values in the respective input lists indexed by \\(i\\), while the
|
||||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
|
@ -1159,15 +1108,15 @@ pub fn cosine_similarity(
|
||||||
/// // Empty lists returns an error
|
/// // Empty lists returns an error
|
||||||
/// metrics.canberra_distance([], [], option.None)
|
/// metrics.canberra_distance([], [], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Different sized lists returns an error
|
/// // Different sized lists returns an error
|
||||||
/// metrics.canberra_distance([1.0, 2.0], [1.0, 2.0, 3.0, 4.0], option.None)
|
/// metrics.canberra_distance([1.0, 2.0], [1.0, 2.0, 3.0, 4.0], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Valid inputs
|
/// // Valid inputs
|
||||||
/// metrics.canberra_distance([1.0, 2.0], [-2.0, -1.0], option.None)
|
/// metrics.canberra_distance([1.0, 2.0], [-2.0, -1.0], option.None)
|
||||||
/// |> should.equal(Ok(2.0))
|
/// |> should.equal(Ok(2.0))
|
||||||
///
|
///
|
||||||
/// metrics.canberra_distance([1.0, 0.0], [0.0, 2.0], option.Some([1.0, 0.5]))
|
/// metrics.canberra_distance([1.0, 0.0], [0.0, 2.0], option.Some([1.0, 0.5]))
|
||||||
/// }
|
/// }
|
||||||
/// </details>
|
/// </details>
|
||||||
|
@ -1182,7 +1131,7 @@ pub fn canberra_distance(
|
||||||
xarr: List(Float),
|
xarr: List(Float),
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case validate_lists(xarr, yarr, weights) {
|
case validate_lists(xarr, yarr, weights) {
|
||||||
Error(msg) ->
|
Error(msg) ->
|
||||||
msg
|
msg
|
||||||
|
@ -1223,7 +1172,7 @@ fn canberra_distance_helper(tuple: #(Float, Float)) -> Float {
|
||||||
/// <small>Spot a typo? Open an issue!</small>
|
/// <small>Spot a typo? Open an issue!</small>
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Calculate the (weighted) Bray-Curtis distance between two lists:
|
/// Calculate the (weighted) Bray-Curtis distance between two lists:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
|
@ -1231,11 +1180,11 @@ fn canberra_distance_helper(tuple: #(Float, Float)) -> Float {
|
||||||
/// {\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 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
|
/// in the respective input lists indexed by \\(i\\), while the
|
||||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||||
///
|
///
|
||||||
/// The Bray-Curtis distance is in the range \\([0, 1]\\) if all entries \\(x_i, y_i\\) are
|
/// The Bray-Curtis distance is in the range \\([0, 1]\\) if all entries \\(x_i, y_i\\) are
|
||||||
/// positive.
|
/// positive.
|
||||||
///
|
///
|
||||||
|
@ -1250,15 +1199,15 @@ fn canberra_distance_helper(tuple: #(Float, Float)) -> Float {
|
||||||
/// // Empty lists returns an error
|
/// // Empty lists returns an error
|
||||||
/// metrics.braycurtis_distance([], [], option.None)
|
/// metrics.braycurtis_distance([], [], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Different sized lists returns an error
|
/// // Different sized lists returns an error
|
||||||
/// metrics.braycurtis_distance([1.0, 2.0], [1.0, 2.0, 3.0, 4.0], option.None)
|
/// metrics.braycurtis_distance([1.0, 2.0], [1.0, 2.0, 3.0, 4.0], option.None)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// // Valid inputs
|
/// // Valid inputs
|
||||||
/// metrics.braycurtis_distance([1.0, 0.0], [0.0, 2.0], option.None)
|
/// metrics.braycurtis_distance([1.0, 0.0], [0.0, 2.0], option.None)
|
||||||
/// |> should.equal(Ok(1.0))
|
/// |> should.equal(Ok(1.0))
|
||||||
///
|
///
|
||||||
/// metrics.braycurtis_distance([1.0, 2.0], [3.0, 4.0], option.Some([0.5, 1.0]))
|
/// metrics.braycurtis_distance([1.0, 2.0], [3.0, 4.0], option.Some([0.5, 1.0]))
|
||||||
/// |> should.equal(Ok(0.375))
|
/// |> should.equal(Ok(0.375))
|
||||||
/// }
|
/// }
|
||||||
|
@ -1275,7 +1224,7 @@ pub fn braycurtis_distance(
|
||||||
xarr: List(Float),
|
xarr: List(Float),
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
weights: option.Option(List(Float)),
|
weights: option.Option(List(Float)),
|
||||||
) -> Result(Float, String) {
|
) -> Result(Float, Nil) {
|
||||||
case validate_lists(xarr, yarr, weights) {
|
case validate_lists(xarr, yarr, weights) {
|
||||||
Error(msg) ->
|
Error(msg) ->
|
||||||
msg
|
msg
|
||||||
|
|
|
@ -69,7 +69,7 @@ import gleam_community/maths/elementary
|
||||||
/// The ceiling function rounds a given input value \\(x \in \mathbb{R}\\) to the nearest integer
|
/// 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\\).
|
/// 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)
|
/// Note: The ceiling function is used as an alias for the rounding function [`round`](#round)
|
||||||
/// with rounding mode `RoundUp`.
|
/// with rounding mode `RoundUp`.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -124,10 +124,10 @@ pub fn ceiling(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The floor function rounds input \\(x \in \mathbb{R}\\) to the nearest integer value (at the
|
/// 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\\).
|
/// 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)
|
/// Note: The floor function is used as an alias for the rounding function [`round`](#round)
|
||||||
/// with rounding mode `RoundDown`.
|
/// with rounding mode `RoundDown`.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -139,7 +139,7 @@ pub fn ceiling(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
/// - \\(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
|
/// 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.
|
/// number refers to the digits before the decimal point.
|
||||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
/// - \\(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 2 digits before the decimal point (`digits = -2`)
|
||||||
|
@ -182,11 +182,11 @@ pub fn floor(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The truncate function rounds a given input \\(x \in \mathbb{R}\\) to the nearest integer
|
/// 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
|
/// value (at the specified digit) that is less than or equal to the absolute value of the
|
||||||
/// input \\(x\\).
|
/// input \\(x\\).
|
||||||
///
|
///
|
||||||
/// Note: The truncate function is used as an alias for the rounding function [`round`](#round)
|
/// Note: The truncate function is used as an alias for the rounding function [`round`](#round)
|
||||||
/// with rounding mode `RoundToZero`.
|
/// with rounding mode `RoundToZero`.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -198,7 +198,7 @@ pub fn floor(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
/// - \\(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
|
/// 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.
|
/// number refers to the digits before the decimal point.
|
||||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
/// - \\(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 2 digits before the decimal point (`digits = -2`)
|
||||||
|
@ -241,18 +241,18 @@ pub fn truncate(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function rounds a float to a specific number of digits (after the decimal place or before
|
/// The function rounds a float to a specific number of digits (after the decimal place or before
|
||||||
/// if negative) using a specified rounding mode.
|
/// if negative) using a specified rounding mode.
|
||||||
///
|
///
|
||||||
/// Valid rounding modes include:
|
/// Valid rounding modes include:
|
||||||
/// - `RoundNearest` (default): The input \\(x\\) is rounded to the nearest integer value (at the
|
/// - `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
|
/// specified digit) with ties (fractional values of 0.5) being rounded to the nearest even
|
||||||
/// integer.
|
/// integer.
|
||||||
/// - `RoundTiesAway`: The input \\(x\\) is rounded to the nearest integer value (at the
|
/// - `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++
|
/// specified digit) with ties (fractional values of 0.5) being rounded away from zero (C/C++
|
||||||
/// rounding behavior).
|
/// rounding behavior).
|
||||||
/// - `RoundTiesUp`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
/// - `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\\)
|
/// digit) with ties (fractional values of 0.5) being rounded towards \\(+\infty\\)
|
||||||
/// (Java/JavaScript rounding behaviour).
|
/// (Java/JavaScript rounding behaviour).
|
||||||
/// - `RoundToZero`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
/// - `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
|
/// digit) that is less than or equal to the absolute value of the input \\(x\\). An alias for
|
||||||
|
@ -260,8 +260,8 @@ pub fn truncate(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// - `RoundDown`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
/// - `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
|
/// digit) that is less than or equal to the input \\(x\\). An alias for this rounding mode is
|
||||||
/// [`floor`](#floor).
|
/// [`floor`](#floor).
|
||||||
/// - `RoundUp`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
/// - `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
|
/// digit) that is larger than or equal to the input \\(x\\). An alias for this rounding mode
|
||||||
/// is [`ceiling`](#ceiling).
|
/// is [`ceiling`](#ceiling).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -273,7 +273,7 @@ pub fn truncate(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
||||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
/// - \\(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
|
/// 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.
|
/// number refers to the digits before the decimal point.
|
||||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
/// - \\(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 2 digits before the decimal point (`digits = -2`)
|
||||||
|
@ -285,7 +285,7 @@ pub fn truncate(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
||||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
/// - \\(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
|
/// 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.
|
/// number refers to the digits before the decimal point.
|
||||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
/// - \\(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 2 digits before the decimal point (`digits = -2`)
|
||||||
|
@ -309,7 +309,7 @@ pub fn truncate(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
/// - \\(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
|
/// 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.
|
/// number refers to the digits before the decimal point.
|
||||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
/// - \\(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 2 digits before the decimal point (`digits = -2`)
|
||||||
|
@ -321,7 +321,7 @@ pub fn truncate(x: Float, digits: option.Option(Int)) -> Float {
|
||||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
/// - \\(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
|
/// 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.
|
/// number refers to the digits before the decimal point.
|
||||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
/// - \\(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 2 digits before the decimal point (`digits = -2`)
|
||||||
|
@ -500,7 +500,7 @@ fn do_ceiling(a: Float) -> Float
|
||||||
/// The absolute value:
|
/// The absolute value:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \forall x \in \mathbb{R}, \\; |x| \in \mathbb{R}_{+}.
|
/// \forall x \in \mathbb{R}, \\; |x| \in \mathbb{R}_{+}.
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// The function takes an input \\(x\\) and returns a positive float value.
|
/// The function takes an input \\(x\\) and returns a positive float value.
|
||||||
|
@ -529,7 +529,7 @@ pub fn float_absolute_value(x: Float) -> Float {
|
||||||
/// The absolute value:
|
/// The absolute value:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \forall x \in \mathbb{Z}, \\; |x| \in \mathbb{Z}_{+}.
|
/// \forall x \in \mathbb{Z}, \\; |x| \in \mathbb{Z}_{+}.
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// The function takes an input \\(x\\) and returns a positive integer value.
|
/// The function takes an input \\(x\\) and returns a positive integer value.
|
||||||
|
@ -709,7 +709,7 @@ fn do_int_sign(a: Int) -> Int
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function takes two arguments \\(x, y \in \mathbb{R}\\) and returns \\(x\\)
|
/// The function takes two arguments \\(x, y \in \mathbb{R}\\) and returns \\(x\\)
|
||||||
/// such that it has the same sign as \\(y\\).
|
/// such that it has the same sign as \\(y\\).
|
||||||
///
|
///
|
||||||
/// <div style="text-align: right;">
|
/// <div style="text-align: right;">
|
||||||
|
@ -735,7 +735,7 @@ pub fn float_copy_sign(x: Float, y: Float) -> Float {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function takes two arguments \\(x, y \in \mathbb{Z}\\) and returns \\(x\\)
|
/// The function takes two arguments \\(x, y \in \mathbb{Z}\\) and returns \\(x\\)
|
||||||
/// such that it has the same sign as \\(y\\).
|
/// such that it has the same sign as \\(y\\).
|
||||||
///
|
///
|
||||||
/// <div style="text-align: right;">
|
/// <div style="text-align: right;">
|
||||||
|
@ -949,11 +949,9 @@ pub fn minmax(x: a, y: a, compare: fn(a, a) -> order.Order) -> #(a, a) {
|
||||||
pub fn list_minimum(
|
pub fn list_minimum(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
compare: fn(a, a) -> order.Order,
|
compare: fn(a, a) -> order.Order,
|
||||||
) -> Result(a, String) {
|
) -> Result(a, Nil) {
|
||||||
case arr {
|
case arr {
|
||||||
[] ->
|
[] -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
|
||||||
|> Error
|
|
||||||
[x, ..rest] ->
|
[x, ..rest] ->
|
||||||
Ok(
|
Ok(
|
||||||
list.fold(rest, x, fn(acc: a, element: a) {
|
list.fold(rest, x, fn(acc: a, element: a) {
|
||||||
|
@ -1003,11 +1001,9 @@ pub fn list_minimum(
|
||||||
pub fn list_maximum(
|
pub fn list_maximum(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
compare: fn(a, a) -> order.Order,
|
compare: fn(a, a) -> order.Order,
|
||||||
) -> Result(a, String) {
|
) -> Result(a, Nil) {
|
||||||
case arr {
|
case arr {
|
||||||
[] ->
|
[] -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
|
||||||
|> Error
|
|
||||||
[x, ..rest] ->
|
[x, ..rest] ->
|
||||||
Ok(
|
Ok(
|
||||||
list.fold(rest, x, fn(acc: a, element: a) {
|
list.fold(rest, x, fn(acc: a, element: a) {
|
||||||
|
@ -1063,11 +1059,9 @@ pub fn list_maximum(
|
||||||
pub fn arg_minimum(
|
pub fn arg_minimum(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
compare: fn(a, a) -> order.Order,
|
compare: fn(a, a) -> order.Order,
|
||||||
) -> Result(List(Int), String) {
|
) -> Result(List(Int), Nil) {
|
||||||
case arr {
|
case arr {
|
||||||
[] ->
|
[] -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
|
||||||
|> Error
|
|
||||||
_ -> {
|
_ -> {
|
||||||
let assert Ok(min) =
|
let assert Ok(min) =
|
||||||
arr
|
arr
|
||||||
|
@ -1133,11 +1127,9 @@ pub fn arg_minimum(
|
||||||
pub fn arg_maximum(
|
pub fn arg_maximum(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
compare: fn(a, a) -> order.Order,
|
compare: fn(a, a) -> order.Order,
|
||||||
) -> Result(List(Int), String) {
|
) -> Result(List(Int), Nil) {
|
||||||
case arr {
|
case arr {
|
||||||
[] ->
|
[] -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
|
||||||
|> Error
|
|
||||||
_ -> {
|
_ -> {
|
||||||
let assert Ok(max) =
|
let assert Ok(max) =
|
||||||
arr
|
arr
|
||||||
|
@ -1203,11 +1195,9 @@ pub fn arg_maximum(
|
||||||
pub fn extrema(
|
pub fn extrema(
|
||||||
arr: List(a),
|
arr: List(a),
|
||||||
compare: fn(a, a) -> order.Order,
|
compare: fn(a, a) -> order.Order,
|
||||||
) -> Result(#(a, a), String) {
|
) -> Result(#(a, a), Nil) {
|
||||||
case arr {
|
case arr {
|
||||||
[] ->
|
[] -> Error(Nil)
|
||||||
"Invalid input argument: The list is empty."
|
|
||||||
|> Error
|
|
||||||
[x, ..rest] ->
|
[x, ..rest] ->
|
||||||
Ok(
|
Ok(
|
||||||
list.fold(rest, #(x, x), fn(acc: #(a, a), element: a) {
|
list.fold(rest, #(x, x), fn(acc: #(a, a), element: a) {
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
////<style>
|
////<style>
|
||||||
//// .katex { font-size: 1.1em; }
|
//// .katex { font-size: 1.1em; }
|
||||||
////</style>
|
////</style>
|
||||||
////
|
////
|
||||||
//// ---
|
//// ---
|
||||||
////
|
////
|
||||||
//// Predicates: A module containing functions for testing various mathematical
|
//// Predicates: A module containing functions for testing various mathematical
|
||||||
//// properties of numbers.
|
//// properties of numbers.
|
||||||
////
|
////
|
||||||
//// * **Tests**
|
//// * **Tests**
|
||||||
//// * [`is_close`](#is_close)
|
//// * [`is_close`](#is_close)
|
||||||
//// * [`list_all_close`](#all_close)
|
//// * [`list_all_close`](#all_close)
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
//// * [`is_divisible`](#is_divisible)
|
//// * [`is_divisible`](#is_divisible)
|
||||||
//// * [`is_multiple`](#is_multiple)
|
//// * [`is_multiple`](#is_multiple)
|
||||||
//// * [`is_prime`](#is_prime)
|
//// * [`is_prime`](#is_prime)
|
||||||
////
|
////
|
||||||
|
|
||||||
import gleam/int
|
import gleam/int
|
||||||
import gleam/list
|
import gleam/list
|
||||||
|
@ -54,16 +54,16 @@ import gleam_community/maths/piecewise
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Determine if a given value \\(a\\) is close to or equivalent to a reference value
|
/// 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
|
/// \\(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
|
/// values. The equivalance of the two given values are then determined based on
|
||||||
/// the equation:
|
/// the equation:
|
||||||
///
|
///
|
||||||
/// \\[
|
/// \\[
|
||||||
/// \|a - b\| \leq (a_{tol} + r_{tol} \cdot \|b\|)
|
/// \|a - b\| \leq (a_{tol} + r_{tol} \cdot \|b\|)
|
||||||
/// \\]
|
/// \\]
|
||||||
///
|
///
|
||||||
/// `True` is returned if statement holds, otherwise `False` is returned.
|
/// `True` is returned if statement holds, otherwise `False` is returned.
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example</summary>
|
/// <summary>Example</summary>
|
||||||
///
|
///
|
||||||
|
@ -135,7 +135,7 @@ fn float_absolute_difference(a: Float, b: Float) -> Float {
|
||||||
/// let rtol: Float = 0.01
|
/// let rtol: Float = 0.01
|
||||||
/// let atol: Float = 0.10
|
/// let atol: Float = 0.10
|
||||||
/// predicates.all_close(xarr, yarr, rtol, atol)
|
/// predicates.all_close(xarr, yarr, rtol, atol)
|
||||||
/// |> fn(zarr: Result(List(Bool), String)) -> Result(Bool, Nil) {
|
/// |> fn(zarr: Result(List(Bool), Nil)) -> Result(Bool, Nil) {
|
||||||
/// case zarr {
|
/// case zarr {
|
||||||
/// Ok(arr) ->
|
/// Ok(arr) ->
|
||||||
/// arr
|
/// arr
|
||||||
|
@ -159,13 +159,11 @@ pub fn all_close(
|
||||||
yarr: List(Float),
|
yarr: List(Float),
|
||||||
rtol: Float,
|
rtol: Float,
|
||||||
atol: Float,
|
atol: Float,
|
||||||
) -> Result(List(Bool), String) {
|
) -> Result(List(Bool), Nil) {
|
||||||
let xlen: Int = list.length(xarr)
|
let xlen: Int = list.length(xarr)
|
||||||
let ylen: Int = list.length(yarr)
|
let ylen: Int = list.length(yarr)
|
||||||
case xlen == ylen {
|
case xlen == ylen {
|
||||||
False ->
|
False -> Error(Nil)
|
||||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
|
||||||
|> Error
|
|
||||||
True ->
|
True ->
|
||||||
list.zip(xarr, yarr)
|
list.zip(xarr, yarr)
|
||||||
|> list.map(fn(z: #(Float, Float)) -> Bool {
|
|> list.map(fn(z: #(Float, Float)) -> Bool {
|
||||||
|
@ -182,10 +180,10 @@ pub fn all_close(
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// Determine if a given value is fractional.
|
/// Determine if a given value is fractional.
|
||||||
///
|
///
|
||||||
/// `True` is returned if the given value is fractional, otherwise `False` is
|
/// `True` is returned if the given value is fractional, otherwise `False` is
|
||||||
/// returned.
|
/// returned.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example</summary>
|
/// <summary>Example</summary>
|
||||||
///
|
///
|
||||||
|
@ -195,7 +193,7 @@ pub fn all_close(
|
||||||
/// pub fn example () {
|
/// pub fn example () {
|
||||||
/// predicates.is_fractional(0.3333)
|
/// predicates.is_fractional(0.3333)
|
||||||
/// |> should.equal(True)
|
/// |> should.equal(True)
|
||||||
///
|
///
|
||||||
/// predicates.is_fractional(1.0)
|
/// predicates.is_fractional(1.0)
|
||||||
/// |> should.equal(False)
|
/// |> should.equal(False)
|
||||||
/// }
|
/// }
|
||||||
|
@ -222,7 +220,7 @@ fn do_ceiling(a: Float) -> Float
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is a
|
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is a
|
||||||
/// power of another integer value \\(y \in \mathbb{Z}\\).
|
/// power of another integer value \\(y \in \mathbb{Z}\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
|
@ -262,9 +260,9 @@ pub fn is_power(x: Int, y: Int) -> Bool {
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A function that tests whether a given integer value \\(n \in \mathbb{Z}\\) is a
|
/// 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
|
/// perfect number. A number is perfect if it is equal to the sum of its proper
|
||||||
/// positive divisors.
|
/// positive divisors.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Details</summary>
|
/// <summary>Details</summary>
|
||||||
///
|
///
|
||||||
|
@ -314,7 +312,7 @@ fn do_sum(arr: List(Int)) -> Int {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is even.
|
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is even.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
|
@ -325,7 +323,7 @@ fn do_sum(arr: List(Int)) -> Int {
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// predicates.is_even(-3)
|
/// predicates.is_even(-3)
|
||||||
/// |> should.equal(False)
|
/// |> should.equal(False)
|
||||||
///
|
///
|
||||||
/// predicates.is_even(-4)
|
/// predicates.is_even(-4)
|
||||||
/// |> should.equal(True)
|
/// |> should.equal(True)
|
||||||
/// }
|
/// }
|
||||||
|
@ -347,7 +345,7 @@ pub fn is_even(x: Int) -> Bool {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is odd.
|
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is odd.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
|
@ -358,7 +356,7 @@ pub fn is_even(x: Int) -> Bool {
|
||||||
/// pub fn example() {
|
/// pub fn example() {
|
||||||
/// predicates.is_odd(-3)
|
/// predicates.is_odd(-3)
|
||||||
/// |> should.equal(True)
|
/// |> should.equal(True)
|
||||||
///
|
///
|
||||||
/// predicates.is_odd(-4)
|
/// predicates.is_odd(-4)
|
||||||
/// |> should.equal(False)
|
/// |> should.equal(False)
|
||||||
/// }
|
/// }
|
||||||
|
@ -380,24 +378,24 @@ pub fn is_odd(x: Int) -> Bool {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is a
|
/// 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
|
/// prime number. A prime number is a natural number greater than 1 that has no
|
||||||
/// positive divisors other than 1 and itself.
|
/// positive divisors other than 1 and itself.
|
||||||
///
|
///
|
||||||
/// The function uses the Miller-Rabin primality test to assess if \\(x\\) is prime.
|
/// 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
|
/// 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
|
/// as prime. However, the probability of such errors decreases with more testing
|
||||||
/// iterations (the function uses 64 iterations internally, which is typically
|
/// iterations (the function uses 64 iterations internally, which is typically
|
||||||
/// more than sufficient). The Miller-Rabin test is particularly useful for large
|
/// more than sufficient). The Miller-Rabin test is particularly useful for large
|
||||||
/// numbers.
|
/// numbers.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Details</summary>
|
/// <summary>Details</summary>
|
||||||
///
|
///
|
||||||
/// Examples of prime numbers:
|
/// Examples of prime numbers:
|
||||||
/// - \\(2\\) is a prime number since it has only two divisors: \\(1\\) and \\(2\\).
|
/// - \\(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\\).
|
/// - \\(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
|
/// - \\(4\\) is not a prime number since it has divisors other than \\(1\\) and itself, such
|
||||||
/// as \\(2\\).
|
/// as \\(2\\).
|
||||||
///
|
///
|
||||||
/// </details>
|
/// </details>
|
||||||
|
@ -414,7 +412,7 @@ pub fn is_odd(x: Int) -> Bool {
|
||||||
///
|
///
|
||||||
/// predicates.is_prime(4)
|
/// predicates.is_prime(4)
|
||||||
/// |> should.equal(False)
|
/// |> should.equal(False)
|
||||||
///
|
///
|
||||||
/// // Test the 2nd Carmichael number
|
/// // Test the 2nd Carmichael number
|
||||||
/// predicates.is_prime(1105)
|
/// predicates.is_prime(1105)
|
||||||
/// |> should.equal(False)
|
/// |> should.equal(False)
|
||||||
|
@ -512,9 +510,9 @@ pub fn is_between(x: Float, lower: Float, upper: Float) -> Bool {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A function that tests whether a given integer \\(n \in \mathbb{Z}\\) is divisible by another
|
/// A function that tests whether a given integer \\(n \in \mathbb{Z}\\) is divisible by another
|
||||||
/// integer \\(d \in \mathbb{Z}\\), such that \\(n \mod d = 0\\).
|
/// integer \\(d \in \mathbb{Z}\\), such that \\(n \mod d = 0\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Details</summary>
|
/// <summary>Details</summary>
|
||||||
///
|
///
|
||||||
|
@ -555,9 +553,9 @@ pub fn is_divisible(n: Int, d: Int) -> Bool {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// A function that tests whether a given integer \\(m \in \mathbb{Z}\\) is a multiple of another
|
/// 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}\\).
|
/// integer \\(k \in \mathbb{Z}\\), such that \\(m = k \times q\\), with \\(q \in \mathbb{Z}\\).
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Details</summary>
|
/// <summary>Details</summary>
|
||||||
///
|
///
|
||||||
|
|
|
@ -20,18 +20,18 @@
|
||||||
////<style>
|
////<style>
|
||||||
//// .katex { font-size: 1.1em; }
|
//// .katex { font-size: 1.1em; }
|
||||||
////</style>
|
////</style>
|
||||||
////
|
////
|
||||||
//// ---
|
//// ---
|
||||||
////
|
////
|
||||||
//// Sequences: A module containing functions for generating various types of
|
//// Sequences: A module containing functions for generating various types of
|
||||||
//// sequences, ranges and intervals.
|
//// sequences, ranges and intervals.
|
||||||
////
|
////
|
||||||
//// * **Ranges and intervals**
|
//// * **Ranges and intervals**
|
||||||
//// * [`arange`](#arange)
|
//// * [`arange`](#arange)
|
||||||
//// * [`linear_space`](#linear_space)
|
//// * [`linear_space`](#linear_space)
|
||||||
//// * [`logarithmic_space`](#logarithmic_space)
|
//// * [`logarithmic_space`](#logarithmic_space)
|
||||||
//// * [`geometric_space`](#geometric_space)
|
//// * [`geometric_space`](#geometric_space)
|
||||||
////
|
////
|
||||||
|
|
||||||
import gleam/iterator
|
import gleam/iterator
|
||||||
import gleam_community/maths/conversion
|
import gleam_community/maths/conversion
|
||||||
|
@ -47,7 +47,7 @@ import gleam_community/maths/piecewise
|
||||||
/// The function returns an iterator generating evenly spaced values within a given interval.
|
/// 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
|
/// 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.
|
/// by the step size provided. The function supports both positive and negative step values.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -59,13 +59,13 @@ import gleam_community/maths/piecewise
|
||||||
/// sequences.arange(1.0, 5.0, 1.0)
|
/// sequences.arange(1.0, 5.0, 1.0)
|
||||||
/// |> iterator.to_list()
|
/// |> iterator.to_list()
|
||||||
/// |> should.equal([1.0, 2.0, 3.0, 4.0])
|
/// |> should.equal([1.0, 2.0, 3.0, 4.0])
|
||||||
///
|
///
|
||||||
/// // No points returned since
|
/// // No points returned since
|
||||||
/// // start is smaller than stop and the step is positive
|
/// // start is smaller than stop and the step is positive
|
||||||
/// sequences.arange(5.0, 1.0, 1.0)
|
/// sequences.arange(5.0, 1.0, 1.0)
|
||||||
/// |> iterator.to_list()
|
/// |> iterator.to_list()
|
||||||
/// |> should.equal([])
|
/// |> should.equal([])
|
||||||
///
|
///
|
||||||
/// // Points returned since
|
/// // Points returned since
|
||||||
/// // start smaller than stop but negative step
|
/// // start smaller than stop but negative step
|
||||||
/// sequences.arange(5.0, 1.0, -1.0)
|
/// sequences.arange(5.0, 1.0, -1.0)
|
||||||
|
@ -115,10 +115,10 @@ pub fn arange(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function returns an iterator for generating linearly spaced points over a specified
|
/// 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
|
/// 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.
|
/// points and whether the endpoint is included determine the spacing between values.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -138,7 +138,7 @@ pub fn arange(
|
||||||
/// 0.0,
|
/// 0.0,
|
||||||
/// tol,
|
/// tol,
|
||||||
/// )
|
/// )
|
||||||
///
|
///
|
||||||
/// result
|
/// result
|
||||||
/// |> list.all(fn(x) { x == True })
|
/// |> list.all(fn(x) { x == True })
|
||||||
/// |> should.be_true()
|
/// |> should.be_true()
|
||||||
|
@ -160,7 +160,7 @@ pub fn linear_space(
|
||||||
stop: Float,
|
stop: Float,
|
||||||
num: Int,
|
num: Int,
|
||||||
endpoint: Bool,
|
endpoint: Bool,
|
||||||
) -> Result(iterator.Iterator(Float), String) {
|
) -> Result(iterator.Iterator(Float), Nil) {
|
||||||
let direction: Float = case start <=. stop {
|
let direction: Float = case start <=. stop {
|
||||||
True -> 1.0
|
True -> 1.0
|
||||||
False -> -1.0
|
False -> -1.0
|
||||||
|
@ -184,9 +184,7 @@ pub fn linear_space(
|
||||||
})
|
})
|
||||||
|> Ok
|
|> Ok
|
||||||
}
|
}
|
||||||
False ->
|
False -> Error(Nil)
|
||||||
"Invalid input: num < 1. Valid input is num >= 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,10 +194,10 @@ pub fn linear_space(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function returns an iterator of logarithmically spaced points over a specified interval.
|
/// 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,
|
/// 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.
|
/// and whether the endpoint is included determine the spacing between values.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
/// <summary>Example:</summary>
|
/// <summary>Example:</summary>
|
||||||
///
|
///
|
||||||
|
@ -241,7 +239,7 @@ pub fn logarithmic_space(
|
||||||
num: Int,
|
num: Int,
|
||||||
endpoint: Bool,
|
endpoint: Bool,
|
||||||
base: Float,
|
base: Float,
|
||||||
) -> Result(iterator.Iterator(Float), String) {
|
) -> Result(iterator.Iterator(Float), Nil) {
|
||||||
case num > 0 {
|
case num > 0 {
|
||||||
True -> {
|
True -> {
|
||||||
let assert Ok(linspace) = linear_space(start, stop, num, endpoint)
|
let assert Ok(linspace) = linear_space(start, stop, num, endpoint)
|
||||||
|
@ -252,9 +250,7 @@ pub fn logarithmic_space(
|
||||||
})
|
})
|
||||||
|> Ok
|
|> Ok
|
||||||
}
|
}
|
||||||
False ->
|
False -> Error(Nil)
|
||||||
"Invalid input: num < 1. Valid input is num >= 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,9 +260,9 @@ pub fn logarithmic_space(
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The function returns an iterator of numbers spaced evenly on a log scale (a geometric
|
/// 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
|
/// 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
|
/// similar to the [`logarithmic_space`](#logarithmic_space) function, but with endpoints
|
||||||
/// specified directly.
|
/// specified directly.
|
||||||
///
|
///
|
||||||
/// <details>
|
/// <details>
|
||||||
|
@ -295,7 +291,7 @@ pub fn logarithmic_space(
|
||||||
/// // Input (start and stop can't be equal to 0.0)
|
/// // Input (start and stop can't be equal to 0.0)
|
||||||
/// sequences.geometric_space(0.0, 1000.0, 3, False)
|
/// sequences.geometric_space(0.0, 1000.0, 3, False)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
/// sequences.geometric_space(-1000.0, 0.0, 3, False)
|
/// sequences.geometric_space(-1000.0, 0.0, 3, False)
|
||||||
/// |> should.be_error()
|
/// |> should.be_error()
|
||||||
///
|
///
|
||||||
|
@ -316,11 +312,9 @@ pub fn geometric_space(
|
||||||
stop: Float,
|
stop: Float,
|
||||||
num: Int,
|
num: Int,
|
||||||
endpoint: Bool,
|
endpoint: Bool,
|
||||||
) -> Result(iterator.Iterator(Float), String) {
|
) -> Result(iterator.Iterator(Float), Nil) {
|
||||||
case start == 0.0 || stop == 0.0 {
|
case start == 0.0 || stop == 0.0 {
|
||||||
True ->
|
True -> Error(Nil)
|
||||||
"Invalid input: Neither 'start' nor 'stop' can be zero, as they must be non-zero for logarithmic calculations."
|
|
||||||
|> Error
|
|
||||||
False ->
|
False ->
|
||||||
case num > 0 {
|
case num > 0 {
|
||||||
True -> {
|
True -> {
|
||||||
|
@ -328,9 +322,7 @@ pub fn geometric_space(
|
||||||
let assert Ok(log_stop) = elementary.logarithm_10(stop)
|
let assert Ok(log_stop) = elementary.logarithm_10(stop)
|
||||||
logarithmic_space(log_start, log_stop, num, endpoint, 10.0)
|
logarithmic_space(log_start, log_stop, num, endpoint, 10.0)
|
||||||
}
|
}
|
||||||
False ->
|
False -> Error(Nil)
|
||||||
"Invalid input: num < 1. Valid input is num >= 1."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,17 +20,17 @@
|
||||||
////<style>
|
////<style>
|
||||||
//// .katex { font-size: 1.1em; }
|
//// .katex { font-size: 1.1em; }
|
||||||
////</style>
|
////</style>
|
||||||
////
|
////
|
||||||
//// ---
|
//// ---
|
||||||
////
|
////
|
||||||
//// Special: A module containing special mathematical functions.
|
//// Special: A module containing special mathematical functions.
|
||||||
////
|
////
|
||||||
//// * **Special mathematical functions**
|
//// * **Special mathematical functions**
|
||||||
//// * [`beta`](#beta)
|
//// * [`beta`](#beta)
|
||||||
//// * [`erf`](#erf)
|
//// * [`erf`](#erf)
|
||||||
//// * [`gamma`](#gamma)
|
//// * [`gamma`](#gamma)
|
||||||
//// * [`incomplete_gamma`](#incomplete_gamma)
|
//// * [`incomplete_gamma`](#incomplete_gamma)
|
||||||
////
|
////
|
||||||
|
|
||||||
import gleam/list
|
import gleam/list
|
||||||
import gleam_community/maths/conversion
|
import gleam_community/maths/conversion
|
||||||
|
@ -100,7 +100,7 @@ pub fn erf(x: Float) -> Float {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
/// The gamma function over the real numbers. The function is essentially equal to
|
/// 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 factorial for any positive integer argument: \\(\Gamma(n) = (n - 1)!\\)
|
||||||
///
|
///
|
||||||
/// The implemented gamma function is approximated through Lanczos approximation
|
/// The implemented gamma function is approximated through Lanczos approximation
|
||||||
|
@ -163,7 +163,7 @@ fn gamma_lanczos(x: Float) -> Float {
|
||||||
/// </a>
|
/// </a>
|
||||||
/// </div>
|
/// </div>
|
||||||
///
|
///
|
||||||
pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, String) {
|
pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, Nil) {
|
||||||
case a >. 0.0 && x >=. 0.0 {
|
case a >. 0.0 && x >=. 0.0 {
|
||||||
True -> {
|
True -> {
|
||||||
let assert Ok(v) = elementary.power(x, a)
|
let assert Ok(v) = elementary.power(x, a)
|
||||||
|
@ -173,9 +173,7 @@ pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, String) {
|
||||||
|> Ok
|
|> Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
False ->
|
False -> Error(Nil)
|
||||||
"Invalid input argument: a <= 0 or x < 0. Valid input is a > 0 and x >= 0."
|
|
||||||
|> Error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub fn float_list_all_close_test() {
|
||||||
let rtol: Float = 0.01
|
let rtol: Float = 0.01
|
||||||
let atol: Float = 0.1
|
let atol: Float = 0.1
|
||||||
predicates.all_close(xarr, yarr, rtol, atol)
|
predicates.all_close(xarr, yarr, rtol, atol)
|
||||||
|> fn(zarr: Result(List(Bool), String)) -> Result(Bool, Nil) {
|
|> fn(zarr: Result(List(Bool), Nil)) -> Result(Bool, Nil) {
|
||||||
case zarr {
|
case zarr {
|
||||||
Ok(arr) ->
|
Ok(arr) ->
|
||||||
arr
|
arr
|
||||||
|
|
Loading…
Reference in a new issue