mirror of
https://github.com/sigmasternchen/gleam-community-maths
synced 2025-03-15 07:59:01 +00:00
Merge pull request #26 from NicklasXYZ/main
Update the combinatorics and sequences module
This commit is contained in:
commit
7fd4d74b2c
12 changed files with 1630 additions and 714 deletions
46
README.md
46
README.md
|
@ -10,43 +10,49 @@ The library supports both targets: Erlang and JavaScript.
|
|||
## Quickstart
|
||||
|
||||
```gleam
|
||||
import gleam/float
|
||||
import gleam/iterator
|
||||
import gleam/option.{Some}
|
||||
import gleam_community/maths/arithmetics
|
||||
import gleam_community/maths/combinatorics
|
||||
import gleam_community/maths/combinatorics.{WithoutRepetitions}
|
||||
import gleam_community/maths/elementary
|
||||
import gleam_community/maths/piecewise
|
||||
import gleam_community/maths/predicates
|
||||
import gleam/float
|
||||
import gleam/int
|
||||
import gleeunit/should
|
||||
|
||||
pub fn main() {
|
||||
pub fn example() {
|
||||
// Evaluate the sine function
|
||||
elementary.sin(elementary.pi())
|
||||
// Returns Float: 0.0
|
||||
let result = elementary.sin(elementary.pi())
|
||||
|
||||
// Set the relative and absolute tolerance
|
||||
let assert Ok(absolute_tol) = elementary.power(10.0, -6.0)
|
||||
let relative_tol = 0.0
|
||||
|
||||
// Check that the value is very close to 0.0
|
||||
// That is, if 'result' is within +/- 10^(-6)
|
||||
predicates.is_close(result, 0.0, relative_tol, absolute_tol)
|
||||
|> should.be_true()
|
||||
|
||||
// Find the greatest common divisor
|
||||
arithmetics.gcd(54, 24)
|
||||
// Returns Int: 6
|
||||
|> should.equal(6)
|
||||
|
||||
// Find the minimum and maximum of a list
|
||||
piecewise.extrema([10.0, 3.0, 50.0, 20.0, 3.0], float.compare)
|
||||
// Returns Tuple: Ok(#(3.0, 50.0))
|
||||
|
||||
// Find the list indices of the smallest value
|
||||
piecewise.arg_minimum([10, 3, 50, 20, 3], int.compare)
|
||||
// Returns List: Ok([1, 4])
|
||||
|> should.equal(Ok(#(3.0, 50.0)))
|
||||
|
||||
// Determine if a number is fractional
|
||||
predicates.is_fractional(0.3333)
|
||||
// Returns Bool: True
|
||||
|> should.equal(True)
|
||||
|
||||
// Determine if 28 is a power of 3
|
||||
predicates.is_power(28, 3)
|
||||
// Returns Bool: False
|
||||
|
||||
// Generate all k = 1 combinations of [1, 2]
|
||||
combinatorics.list_combination([1, 2], 1)
|
||||
// Returns List: Ok([[1], [2]])
|
||||
// Generate all k = 2 combinations of [1, 2, 3]
|
||||
let assert Ok(combinations) =
|
||||
combinatorics.list_combination([1, 2, 3], 2, Some(WithoutRepetitions))
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1, 2], [1, 3], [2, 3]])
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -58,8 +58,8 @@ import gleam_community/maths/piecewise
|
|||
/// </div>
|
||||
///
|
||||
/// The function calculates the greatest common divisor of two integers
|
||||
/// $$x, y \in \mathbb{Z}$$. The greatest common divisor is the largest positive
|
||||
/// integer that is divisible by both $$x$$ and $$y$$.
|
||||
/// \\(x, y \in \mathbb{Z}\\). The greatest common divisor is the largest positive
|
||||
/// integer that is divisible by both \\(x\\) and \\(y\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -108,15 +108,15 @@ fn do_gcd(x: Int, y: Int) -> Int {
|
|||
/// </div>
|
||||
///
|
||||
///
|
||||
/// Given two integers, $$x$$ (dividend) and $$y$$ (divisor), the Euclidean modulo
|
||||
/// of $$x$$ by $$y$$, denoted as $$x \mod y$$, is the remainder $$r$$ of the
|
||||
/// division of $$x$$ by $$y$$, such that:
|
||||
/// Given two integers, \\(x\\) (dividend) and \\(y\\) (divisor), the Euclidean modulo
|
||||
/// of \\(x\\) by \\(y\\), denoted as \\(x \mod y\\), is the remainder \\(r\\) of the
|
||||
/// division of \\(x\\) by \\(y\\), such that:
|
||||
///
|
||||
/// \\[
|
||||
/// x = q \cdot y + r \quad \text{and} \quad 0 \leq r < |y|,
|
||||
/// \\]
|
||||
///
|
||||
/// where $$q$$ is an integer that represents the quotient of the division.
|
||||
/// where \\(q\\) is an integer that represents the quotient of the division.
|
||||
///
|
||||
/// The Euclidean modulo function of two numbers, is the remainder operation most
|
||||
/// commonly utilized in mathematics. This differs from the standard truncating
|
||||
|
@ -169,8 +169,8 @@ pub fn int_euclidean_modulo(x: Int, y: Int) -> Int {
|
|||
/// </div>
|
||||
///
|
||||
/// The function calculates the least common multiple of two integers
|
||||
/// $$x, y \in \mathbb{Z}$$. The least common multiple is the smallest positive
|
||||
/// integer that has both $$x$$ and $$y$$ as factors.
|
||||
/// \\(x, y \in \mathbb{Z}\\). The least common multiple is the smallest positive
|
||||
/// integer that has both \\(x\\) and \\(y\\) as factors.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -305,9 +305,9 @@ pub fn proper_divisors(n: Int) -> List(Int) {
|
|||
/// \sum_{i=1}^n w_i x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{R}$$ is
|
||||
/// the value in the input list indexed by $$i$$, while the $$w_i \in \mathbb{R}$$
|
||||
/// are corresponding weights ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\) is
|
||||
/// the value in the input list indexed by \\(i\\), while the \\(w_i \in \mathbb{R}\\)
|
||||
/// are corresponding weights (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -362,8 +362,8 @@ pub fn float_sum(arr: List(Float), weights: option.Option(List(Float))) -> Float
|
|||
/// \sum_{i=1}^n x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{Z}$$ is
|
||||
/// the value in the input list indexed by $$i$$.
|
||||
/// 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\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -411,9 +411,9 @@ pub fn int_sum(arr: List(Int)) -> Int {
|
|||
/// \prod_{i=1}^n x_i^{w_i}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{R}$$ is
|
||||
/// the value in the input list indexed by $$i$$, while the $$w_i \in \mathbb{R}$$
|
||||
/// are corresponding weights ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\) is
|
||||
/// the value in the input list indexed by \\(i\\), while the \\(w_i \in \mathbb{R}\\)
|
||||
/// are corresponding weights (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -486,8 +486,8 @@ pub fn float_product(
|
|||
/// \prod_{i=1}^n x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{Z}$$ is
|
||||
/// the value in the input list indexed by $$i$$.
|
||||
/// 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\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -535,10 +535,10 @@ pub fn int_product(arr: List(Int)) -> Int {
|
|||
/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative sum of $$n$$
|
||||
/// elements. That is, $$n$$ is the length of the list and $$x_i \in \mathbb{R}$$
|
||||
/// is the value in the input list indexed by $$i$$. The value $$v_j$$ is thus the
|
||||
/// sum of the $$1$$ to $$j$$ first elements in the given list.
|
||||
/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(n\\)
|
||||
/// elements. That is, \\(n\\) is the length of the list and \\(x_i \in \mathbb{R}\\)
|
||||
/// is the value in the input list indexed by \\(i\\). The value \\(v_j\\) is thus the
|
||||
/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -585,10 +585,10 @@ pub fn float_cumulative_sum(arr: List(Float)) -> List(Float) {
|
|||
/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative sum of $$n$$
|
||||
/// elements. That is, $$n$$ is the length of the list and $$x_i \in \mathbb{Z}$$
|
||||
/// is the value in the input list indexed by $$i$$. The value $$v_j$$ is thus the
|
||||
/// sum of the $$1$$ to $$j$$ first elements in the given list.
|
||||
/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative sum of \\(n\\)
|
||||
/// elements. That is, \\(n\\) is the length of the list and \\(x_i \in \mathbb{Z}\\)
|
||||
/// is the value in the input list indexed by \\(i\\). The value \\(v_j\\) is thus the
|
||||
/// sum of the \\(1\\) to \\(j\\) first elements in the given list.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -635,10 +635,10 @@ pub fn int_cumulative_sum(arr: List(Int)) -> List(Int) {
|
|||
/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative product of
|
||||
/// $$n$$ elements. That is, $$n$$ is the length of the list and
|
||||
/// $$x_i \in \mathbb{R}$$ is the value in the input list indexed by $$i$$. The
|
||||
/// value $$v_j$$ is thus the sum of the $$1$$ to $$j$$ first elements in the
|
||||
/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative product of
|
||||
/// \\(n\\) elements. That is, \\(n\\) is the length of the list and
|
||||
/// \\(x_i \in \mathbb{R}\\) is the value in the input list indexed by \\(i\\). The
|
||||
/// value \\(v_j\\) is thus the sum of the \\(1\\) to \\(j\\) first elements in the
|
||||
/// given list.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -687,10 +687,10 @@ pub fn float_cumulative_product(arr: List(Float)) -> List(Float) {
|
|||
/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative product of
|
||||
/// $$n$$ elements. That is, $$n$$ is the length of the list and
|
||||
/// $$x_i \in \mathbb{Z}$$ is the value in the input list indexed by $$i$$. The
|
||||
/// value $$v_j$$ is thus the product of the $$1$$ to $$j$$ first elements in the
|
||||
/// In the formula, \\(v_j\\) is the \\(j\\)'th element in the cumulative product of
|
||||
/// \\(n\\) elements. That is, \\(n\\) is the length of the list and
|
||||
/// \\(x_i \in \mathbb{Z}\\) is the value in the input list indexed by \\(i\\). The
|
||||
/// value \\(v_j\\) is thus the product of the \\(1\\) to \\(j\\) first elements in the
|
||||
/// given list.
|
||||
///
|
||||
/// <details>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -23,7 +23,8 @@
|
|||
////
|
||||
//// ---
|
||||
////
|
||||
//// Combinatorics: A module that offers mathematical functions related to counting, arrangements, and combinations.
|
||||
//// Combinatorics: A module that offers mathematical functions related to counting, arrangements,
|
||||
//// and permutations/combinations.
|
||||
////
|
||||
//// * **Combinatorial functions**
|
||||
//// * [`combination`](#combination)
|
||||
|
@ -34,8 +35,17 @@
|
|||
//// * [`cartesian_product`](#cartesian_product)
|
||||
////
|
||||
|
||||
import gleam/iterator
|
||||
import gleam/list
|
||||
import gleam/option
|
||||
import gleam/set
|
||||
import gleam_community/maths/conversion
|
||||
import gleam_community/maths/elementary
|
||||
|
||||
pub type CombinatoricsMode {
|
||||
WithRepetitions
|
||||
WithoutRepetitions
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
|
@ -43,37 +53,71 @@ import gleam/set
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// A combinatorial function for computing the number of a $$k$$-combinations of $$n$$ elements:
|
||||
/// A combinatorial function for computing the number of \\(k\\)-combinations of \\(n\\) elements.
|
||||
///
|
||||
/// **Without Repetitions:**
|
||||
///
|
||||
/// \\[
|
||||
/// C(n, k) = \binom{n}{k} = \frac{n!}{k! (n-k)!}
|
||||
/// \\]
|
||||
/// Also known as "$$n$$ choose $$k$$" or the binomial coefficient.
|
||||
/// Also known as "\\(n\\) choose \\(k\\)" or the binomial coefficient.
|
||||
///
|
||||
/// The implementation uses the effecient iterative multiplicative formula for the computation.
|
||||
/// **With Repetitions:**
|
||||
///
|
||||
/// \\[
|
||||
/// C^*(n, k) = \binom{n + k - 1}{k} = \frac{(n + k - 1)!}{k! (n - 1)!}
|
||||
/// \\]
|
||||
/// Also known as the "stars and bars" problem in combinatorics.
|
||||
///
|
||||
/// The implementation uses an efficient iterative multiplicative formula for computing the result.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// A \\(k\\)-combination is a sequence of \\(k\\) elements selected from \\(n\\) elements where
|
||||
/// the order of selection does not matter. For example, consider selecting 2 elements from a list
|
||||
/// of 3 elements: `["A", "B", "C"]`:
|
||||
///
|
||||
/// - For \\(k\\)-combinations (without repetitions), where order does not matter, the possible
|
||||
/// selections are:
|
||||
/// - `["A", "B"]`
|
||||
/// - `["A", "C"]`
|
||||
/// - `["B", "C"]`
|
||||
///
|
||||
/// - For \\(k\\)-combinations (with repetitions), where order does not matter but elements can
|
||||
/// repeat, the possible selections are:
|
||||
/// - `["A", "A"], ["A", "B"], ["A", "C"]`
|
||||
/// - `["B", "B"], ["B", "C"], ["C", "C"]`
|
||||
///
|
||||
/// - On the contrary, for \\(k\\)-permutations (without repetitions), the order matters, so the
|
||||
/// possible selections are:
|
||||
/// - `["A", "B"], ["B", "A"]`
|
||||
/// - `["A", "C"], ["C", "A"]`
|
||||
/// - `["B", "C"], ["C", "B"]`
|
||||
/// </details>
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleam/option
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/combinatorics
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// // Invalid input gives an error
|
||||
/// // Error on: n = -1 < 0
|
||||
/// combinatorics.combination(-1, 1)
|
||||
/// combinatorics.combination(-1, 1, option.None)
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// combinatorics.combination(4, 0)
|
||||
/// // Valid input: n = 4 and k = 0
|
||||
/// combinatorics.combination(4, 0, option.Some(combinatorics.WithoutRepetitions))
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// combinatorics.combination(4, 4)
|
||||
/// // Valid input: k = n (n = 4, k = 4)
|
||||
/// combinatorics.combination(4, 4, option.Some(combinatorics.WithoutRepetitions))
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// combinatorics.combination(4, 2)
|
||||
/// |> should.equal(Ok(6))
|
||||
/// }
|
||||
/// // Valid input: combinations with repetition (n = 2, k = 3)
|
||||
/// combinatorics.combination(2, 3, option.Some(combinatorics.WithRepetitions))
|
||||
/// |> should.equal(Ok(4))
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
|
@ -82,36 +126,46 @@ import gleam/set
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn combination(n: Int, k: Int) -> Result(Int, String) {
|
||||
case n < 0 {
|
||||
True ->
|
||||
"Invalid input argument: n < 0. Valid input is n > 0."
|
||||
|> Error
|
||||
False ->
|
||||
case k < 0 || k > n {
|
||||
True ->
|
||||
0
|
||||
|> Ok
|
||||
False ->
|
||||
case k == 0 || k == n {
|
||||
True ->
|
||||
1
|
||||
|> Ok
|
||||
False -> {
|
||||
pub fn combination(
|
||||
n: Int,
|
||||
k: Int,
|
||||
mode: option.Option(CombinatoricsMode),
|
||||
) -> Result(Int, String) {
|
||||
case n, k {
|
||||
_, _ if n < 0 ->
|
||||
"Invalid input argument: n < 0. Valid input is n >= 0." |> Error
|
||||
_, _ if k < 0 ->
|
||||
"Invalid input argument: k < 0. Valid input is k >= 0." |> Error
|
||||
_, _ -> {
|
||||
case mode {
|
||||
option.Some(WithRepetitions) -> combination_with_repetitions(n, k)
|
||||
_ -> combination_without_repetitions(n, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn combination_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||
{ n + k - 1 }
|
||||
|> combination_without_repetitions(k)
|
||||
}
|
||||
|
||||
fn combination_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||
case n, k {
|
||||
_, _ if k == 0 || k == n -> {
|
||||
1 |> Ok
|
||||
}
|
||||
_, _ -> {
|
||||
let min = case k < n - k {
|
||||
True -> k
|
||||
False -> n - k
|
||||
}
|
||||
list.range(1, min)
|
||||
|> list.fold(1, fn(acc: Int, x: Int) -> Int {
|
||||
acc * { n + 1 - x } / x
|
||||
})
|
||||
|> list.fold(1, fn(acc: Int, x: Int) -> Int { acc * { n + 1 - x } / x })
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
|
@ -119,8 +173,8 @@ pub fn combination(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// A combinatorial function for computing the total number of combinations of $$n$$
|
||||
/// elements, that is $$n!$$.
|
||||
/// A combinatorial function for computing the total number of combinations of \\(n\\)
|
||||
/// elements, that is \\(n!\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -133,21 +187,12 @@ pub fn combination(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// combinatorics.factorial(-1)
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// // Valid input returns a result (n = 0)
|
||||
/// combinatorics.factorial(0)
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// combinatorics.factorial(1)
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// combinatorics.factorial(2)
|
||||
/// |> should.equal(Ok(2))
|
||||
///
|
||||
/// combinatorics.factorial(3)
|
||||
/// |> should.equal(Ok(6))
|
||||
///
|
||||
/// combinatorics.factorial(4)
|
||||
/// |> should.equal(Ok(24))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -158,12 +203,10 @@ pub fn combination(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// </div>
|
||||
///
|
||||
pub fn factorial(n) -> Result(Int, String) {
|
||||
case n < 0 {
|
||||
True ->
|
||||
"Invalid input argument: n < 0. Valid input is n > 0."
|
||||
|> Error
|
||||
False ->
|
||||
case n {
|
||||
_ if n < 0 ->
|
||||
"Invalid input argument: n < 0. Valid input is n >= 0."
|
||||
|> Error
|
||||
0 ->
|
||||
1
|
||||
|> Ok
|
||||
|
@ -172,11 +215,10 @@ pub fn factorial(n) -> Result(Int, String) {
|
|||
|> Ok
|
||||
_ ->
|
||||
list.range(1, n)
|
||||
|> list.fold(1, fn(acc: Int, x: Int) { acc * x })
|
||||
|> list.fold(1, fn(acc: Int, x: Int) -> Int { acc * x })
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
|
@ -184,33 +226,66 @@ pub fn factorial(n) -> Result(Int, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// A combinatorial function for computing the number of $$k$$-permuations (without repetitions)
|
||||
/// of $$n$$ elements:
|
||||
/// A combinatorial function for computing the number of \\(k\\)-permutations.
|
||||
///
|
||||
/// **Without** repetitions:
|
||||
///
|
||||
/// \\[
|
||||
/// P(n, k) = \frac{n!}{(n - k)!}
|
||||
/// P(n, k) = \binom{n}{k} \cdot k! = \frac{n!}{(n - k)!}
|
||||
/// \\]
|
||||
///
|
||||
/// **With** repetitions:
|
||||
///
|
||||
/// \\[
|
||||
/// P^*(n, k) = n^k
|
||||
/// \\]
|
||||
///
|
||||
/// The implementation uses an efficient iterative multiplicative formula for computing the result.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// A \\(k\\)-permutation (without repetitions) is a sequence of \\(k\\) elements selected from \
|
||||
/// \\(n\\) elements where the order of selection matters. For example, consider selecting 2
|
||||
/// elements from a list of 3 elements: `["A", "B", "C"]`:
|
||||
///
|
||||
/// - For \\(k\\)-permutations (without repetitions), the order matters, so the possible selections
|
||||
/// are:
|
||||
/// - `["A", "B"], ["B", "A"]`
|
||||
/// - `["A", "C"], ["C", "A"]`
|
||||
/// - `["B", "C"], ["C", "B"]`
|
||||
///
|
||||
/// - For \\(k\\)-permutations (with repetitions), the order also matters, but we have repeated
|
||||
/// selections:
|
||||
/// - `["A", "A"], ["A", "B"], ["A", "C"]`
|
||||
/// - `["B", "A"], ["B", "B"], ["B", "C"]`
|
||||
/// - `["C", "A"], ["C", "B"], ["C", "C"]`
|
||||
///
|
||||
/// - On the contrary, for \\(k\\)-combinations (without repetitions), where order does not matter,
|
||||
/// the possible selections are:
|
||||
/// - `["A", "B"]`
|
||||
/// - `["A", "C"]`
|
||||
/// - `["B", "C"]`
|
||||
/// </details>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleam/option
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/combinatorics
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// // Invalid input gives an error
|
||||
/// // Error on: n = -1 < 0
|
||||
/// combinatorics.permutation(-1, 1)
|
||||
/// combinatorics.permutation(-1, 1, option.None)
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// combinatorics.permutation(4, 0)
|
||||
/// // Valid input returns a result (n = 4, k = 0)
|
||||
/// combinatorics.permutation(4, 0, option.Some(combinatorics.WithoutRepetitions))
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// combinatorics.permutation(4, 4)
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// combinatorics.permutation(4, 2)
|
||||
/// // Valid input returns the correct number of permutations (n = 4, k = 2)
|
||||
/// combinatorics.permutation(4, 2, option.Some(combinatorics.WithoutRepetitions))
|
||||
/// |> should.equal(Ok(12))
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -221,30 +296,48 @@ pub fn factorial(n) -> Result(Int, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn permutation(n: Int, k: Int) -> Result(Int, String) {
|
||||
case n < 0 {
|
||||
True ->
|
||||
"Invalid input argument: n < 0. Valid input is n > 0."
|
||||
|> Error
|
||||
False ->
|
||||
case k < 0 || k > n {
|
||||
True ->
|
||||
0
|
||||
|> Ok
|
||||
False ->
|
||||
case k == n {
|
||||
True ->
|
||||
1
|
||||
|> Ok
|
||||
False -> {
|
||||
let assert Ok(v1) = factorial(n)
|
||||
let assert Ok(v2) = factorial(n - k)
|
||||
v1 / v2
|
||||
pub fn permutation(
|
||||
n: Int,
|
||||
k: Int,
|
||||
mode: option.Option(CombinatoricsMode),
|
||||
) -> Result(Int, String) {
|
||||
case n, k {
|
||||
_, _ if n < 0 ->
|
||||
"Invalid input argument: n < 0. Valid input is n >= 0." |> Error
|
||||
_, _ if k < 0 ->
|
||||
"Invalid input argument: k < 0. Valid input is k >= 0." |> Error
|
||||
_, _ -> {
|
||||
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) {
|
||||
case n, k {
|
||||
_, _ if k < 0 || k > n -> {
|
||||
0 |> Ok
|
||||
}
|
||||
_, _ if k == 0 -> {
|
||||
1 |> Ok
|
||||
}
|
||||
_, _ ->
|
||||
list.range(0, k - 1)
|
||||
|> list.fold(1, fn(acc: Int, x: Int) -> Int { acc * { n - x } })
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn permutation_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||
let n_float = conversion.int_to_float(n)
|
||||
let k_float = conversion.int_to_float(k)
|
||||
// 'n' ank 'k' are positive integers, so no errors here...
|
||||
let assert Ok(result) = elementary.power(n_float, k_float)
|
||||
result
|
||||
|> conversion.float_to_int()
|
||||
|> Ok
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
|
@ -253,18 +346,33 @@ pub fn permutation(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Generate all $$k$$-combinations based on a given list.
|
||||
/// Generates all possible combinations of \\(k\\) elements selected from a given list of size
|
||||
/// \\(n\\).
|
||||
///
|
||||
/// The function can handle cases with and without repetitions
|
||||
/// (see more details [here](#combination)). Also, note that repeated elements are treated as
|
||||
/// distinct.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam/set
|
||||
/// import gleam/option
|
||||
/// import gleam/iterator
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/combinatorics
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// let assert Ok(result) = combinatorics.list_combination([1, 2, 3, 4], 3)
|
||||
/// // Generate all 3-combinations without repetition
|
||||
/// let assert Ok(result) =
|
||||
/// combinatorics.list_combination(
|
||||
/// [1, 2, 3, 4],
|
||||
/// 3,
|
||||
/// option.Some(combinatorics.WithoutRepetitions),
|
||||
/// )
|
||||
///
|
||||
/// result
|
||||
/// |> iterator.to_list()
|
||||
/// |> set.from_list()
|
||||
/// |> should.equal(set.from_list([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]))
|
||||
/// }
|
||||
|
@ -276,35 +384,87 @@ pub fn permutation(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn list_combination(arr: List(a), k: Int) -> Result(List(List(a)), String) {
|
||||
case k < 0 {
|
||||
True ->
|
||||
"Invalid input argument: k < 0. Valid input is k > 0."
|
||||
pub fn list_combination(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
mode: option.Option(CombinatoricsMode),
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
case k {
|
||||
_ if k < 0 ->
|
||||
"Invalid input argument: k < 0. Valid input is k >= 0."
|
||||
|> Error
|
||||
False -> {
|
||||
case k > list.length(arr) {
|
||||
True ->
|
||||
"Invalid input argument: k > length(arr). Valid input is 0 < k <= length(arr)."
|
||||
|> Error
|
||||
False -> {
|
||||
do_list_combination(arr, k, [])
|
||||
|> Ok
|
||||
_ ->
|
||||
case mode {
|
||||
option.Some(WithRepetitions) ->
|
||||
list_combination_with_repetitions(arr, k)
|
||||
_ -> list_combination_without_repetitions(arr, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn list_combination_without_repetitions(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
case k, list.length(arr) {
|
||||
_, arr_length if k > arr_length -> {
|
||||
"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
|
||||
_, arr_length if k == arr_length -> {
|
||||
iterator.single(arr) |> Ok
|
||||
}
|
||||
_, _ -> {
|
||||
Ok(
|
||||
do_list_combination_without_repetitions(iterator.from_list(arr), k, []),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_list_combination_without_repetitions(
|
||||
arr: iterator.Iterator(a),
|
||||
k: Int,
|
||||
prefix: List(a),
|
||||
) -> iterator.Iterator(List(a)) {
|
||||
case k {
|
||||
0 -> iterator.single(list.reverse(prefix))
|
||||
_ ->
|
||||
case arr |> iterator.step {
|
||||
iterator.Done -> iterator.empty()
|
||||
iterator.Next(x, xs) -> {
|
||||
let with_x =
|
||||
do_list_combination_without_repetitions(xs, k - 1, [x, ..prefix])
|
||||
let without_x = do_list_combination_without_repetitions(xs, k, prefix)
|
||||
iterator.concat([with_x, without_x])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_list_combination(arr: List(a), k: Int, prefix: List(a)) -> List(List(a)) {
|
||||
fn list_combination_with_repetitions(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
Ok(do_list_combination_with_repetitions(iterator.from_list(arr), k, []))
|
||||
}
|
||||
|
||||
fn do_list_combination_with_repetitions(
|
||||
arr: iterator.Iterator(a),
|
||||
k: Int,
|
||||
prefix: List(a),
|
||||
) -> iterator.Iterator(List(a)) {
|
||||
case k {
|
||||
0 -> [list.reverse(prefix)]
|
||||
0 -> iterator.single(list.reverse(prefix))
|
||||
_ ->
|
||||
case arr {
|
||||
[] -> []
|
||||
[x, ..xs] -> {
|
||||
let with_x = do_list_combination(xs, k - 1, [x, ..prefix])
|
||||
let without_x = do_list_combination(xs, k, prefix)
|
||||
list.append(with_x, without_x)
|
||||
case arr |> iterator.step {
|
||||
iterator.Done -> iterator.empty()
|
||||
iterator.Next(x, xs) -> {
|
||||
let with_x =
|
||||
do_list_combination_with_repetitions(arr, k - 1, [x, ..prefix])
|
||||
let without_x = do_list_combination_with_repetitions(xs, k, prefix)
|
||||
iterator.concat([with_x, without_x])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,43 +476,44 @@ fn do_list_combination(arr: List(a), k: Int, prefix: List(a)) -> List(List(a)) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Generate all permutations of a given list.
|
||||
/// Generates all possible permutations of \\(k\\) elements selected from a given list of size
|
||||
/// \\(n\\).
|
||||
///
|
||||
/// Repeated elements are treated as distinct for the
|
||||
/// purpose of permutations, so two identical elements
|
||||
/// for example will appear "both ways round". This
|
||||
/// means lists with repeated elements return the same
|
||||
/// number of permutations as ones without.
|
||||
///
|
||||
/// N.B. The output of this function is a list of size
|
||||
/// factorial in the size of the input list. Caution is
|
||||
/// advised on input lists longer than ~11 elements, which
|
||||
/// may cause the VM to use unholy amounts of memory for
|
||||
/// the output.
|
||||
/// The function can handle cases with and without repetitions
|
||||
/// (see more details [here](#permutation)). Also, note that repeated elements are treated as
|
||||
/// distinct.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam/set
|
||||
/// import gleam/option
|
||||
/// import gleam/iterator
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/combinatorics
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// [1, 2, 3]
|
||||
/// |> combinatorics.list_permutation()
|
||||
/// // Generate all 3-permutations without repetition
|
||||
/// let assert Ok(result) =
|
||||
/// combinatorics.list_permutation(
|
||||
/// [1, 2, 3],
|
||||
/// 3,
|
||||
/// option.Some(combinatorics.WithoutRepetitions),
|
||||
/// )
|
||||
///
|
||||
/// result
|
||||
/// |> iterator.to_list()
|
||||
/// |> set.from_list()
|
||||
/// |> should.equal(set.from_list([
|
||||
/// |> should.equal(
|
||||
/// set.from_list([
|
||||
/// [1, 2, 3],
|
||||
/// [2, 1, 3],
|
||||
/// [3, 1, 2],
|
||||
/// [1, 3, 2],
|
||||
/// [2, 3, 1],
|
||||
/// [3, 2, 1],
|
||||
/// ]))
|
||||
///
|
||||
/// [1.0, 1.0]
|
||||
/// |> combinatorics.list_permutation()
|
||||
/// |> should.equal([[1.0, 1.0], [1.0, 1.0]])
|
||||
/// ]),
|
||||
/// )
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -362,19 +523,99 @@ fn do_list_combination(arr: List(a), k: Int, prefix: List(a)) -> List(List(a)) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn list_permutation(arr: List(a)) -> List(List(a)) {
|
||||
case arr {
|
||||
[] -> [[]]
|
||||
_ -> {
|
||||
use x <- list.flat_map(arr)
|
||||
// `x` is drawn from the list `arr` above,
|
||||
// so Ok(...) can be safely asserted as the result of `list.pop` below
|
||||
let assert Ok(#(_, remaining)) = list.pop(arr, fn(y) { x == y })
|
||||
list.map(list_permutation(remaining), fn(perm) { [x, ..perm] })
|
||||
///
|
||||
pub fn list_permutation(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
mode: option.Option(CombinatoricsMode),
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
case k {
|
||||
_ if k < 0 ->
|
||||
"Invalid input argument: k < 0. Valid input is k >= 0."
|
||||
|> Error
|
||||
_ ->
|
||||
case mode {
|
||||
option.Some(WithRepetitions) ->
|
||||
list_permutation_with_repetitions(arr, k)
|
||||
_ -> list_permutation_without_repetitions(arr, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_first_by_index(
|
||||
arr: iterator.Iterator(#(Int, a)),
|
||||
index_to_remove: Int,
|
||||
) -> iterator.Iterator(#(Int, a)) {
|
||||
iterator.flat_map(arr, fn(arg) {
|
||||
let #(index, element) = arg
|
||||
case index == index_to_remove {
|
||||
True -> iterator.empty()
|
||||
False -> iterator.single(#(index, element))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn list_permutation_without_repetitions(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
case k, list.length(arr) {
|
||||
_, arr_length if k > arr_length -> {
|
||||
"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) })
|
||||
Ok(do_list_permutation_without_repetitions(
|
||||
iterator.from_list(indexed_arr),
|
||||
k,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_list_permutation_without_repetitions(
|
||||
arr: iterator.Iterator(#(Int, a)),
|
||||
k: Int,
|
||||
) -> iterator.Iterator(List(a)) {
|
||||
case k {
|
||||
0 -> iterator.single([])
|
||||
_ ->
|
||||
iterator.flat_map(arr, fn(arg) {
|
||||
let #(index, element) = arg
|
||||
let remaining = remove_first_by_index(arr, index)
|
||||
let permutations =
|
||||
do_list_permutation_without_repetitions(remaining, k - 1)
|
||||
iterator.map(permutations, fn(permutation) { [element, ..permutation] })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn list_permutation_with_repetitions(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
let indexed_arr = list.index_map(arr, fn(x, i) { #(i, x) })
|
||||
Ok(do_list_permutation_with_repetitions(indexed_arr, k))
|
||||
}
|
||||
|
||||
fn do_list_permutation_with_repetitions(
|
||||
arr: List(#(Int, a)),
|
||||
k: Int,
|
||||
) -> iterator.Iterator(List(a)) {
|
||||
case k {
|
||||
0 -> iterator.single([])
|
||||
_ ->
|
||||
iterator.flat_map(arr |> iterator.from_list, fn(arg) {
|
||||
let #(_, element) = arg
|
||||
// Allow the same element (by index) to be reused in future recursive calls
|
||||
let permutations = do_list_permutation_with_repetitions(arr, k - 1)
|
||||
// Prepend the current element to each generated permutation
|
||||
iterator.map(permutations, fn(permutation) { [element, ..permutation] })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
|
@ -386,18 +627,22 @@ pub fn list_permutation(arr: List(a)) -> List(List(a)) {
|
|||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleam/set
|
||||
/// import gleeunit/should
|
||||
/// import gleam/list
|
||||
/// import gleam_community/maths/combinatorics
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// []
|
||||
/// |> combinatorics.cartesian_product([])
|
||||
/// |> should.equal([])
|
||||
/// // Cartesian product of two empty sets
|
||||
/// set.from_list([])
|
||||
/// |> combinatorics.cartesian_product(set.from_list([]))
|
||||
/// |> should.equal(set.from_list([]))
|
||||
///
|
||||
/// [1.0, 10.0]
|
||||
/// |> combinatorics.cartesian_product([1.0, 2.0])
|
||||
/// |> should.equal([#(1.0, 1.0), #(1.0, 2.0), #(10.0, 1.0), #(10.0, 2.0)])
|
||||
/// // Cartesian product of two sets with numeric values
|
||||
/// set.from_list([1.0, 10.0])
|
||||
/// |> combinatorics.cartesian_product(set.from_list([1.0, 2.0]))
|
||||
/// |> should.equal(
|
||||
/// set.from_list([#(1.0, 1.0), #(1.0, 2.0), #(10.0, 1.0), #(10.0, 2.0)]),
|
||||
/// )
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -407,13 +652,7 @@ pub fn list_permutation(arr: List(a)) -> List(List(a)) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn cartesian_product(xarr: List(a), yarr: List(a)) -> List(#(a, a)) {
|
||||
let xset: set.Set(a) =
|
||||
xarr
|
||||
|> set.from_list()
|
||||
let yset: set.Set(a) =
|
||||
yarr
|
||||
|> set.from_list()
|
||||
pub fn cartesian_product(xset: set.Set(a), yset: set.Set(a)) -> set.Set(#(a, a)) {
|
||||
xset
|
||||
|> set.fold(
|
||||
set.new(),
|
||||
|
@ -427,5 +666,4 @@ pub fn cartesian_product(xarr: List(a), yarr: List(a)) -> List(#(a, a)) {
|
|||
)
|
||||
},
|
||||
)
|
||||
|> set.to_list()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -76,7 +76,8 @@ pub fn int_to_float(x: Int) -> Float {
|
|||
/// </div>
|
||||
///
|
||||
/// The function returns the integral part of a given floating point value.
|
||||
/// That is, everything after the decimal point of a given floating point value is discarded and only the integer value before the decimal point is returned.
|
||||
/// That is, everything after the decimal point of a given floating point value is discarded
|
||||
/// and only the integer value before the decimal point is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -119,7 +120,7 @@ fn do_to_int(a: Float) -> Int
|
|||
/// </div>
|
||||
///
|
||||
/// Convert a value in degrees to a value measured in radians.
|
||||
/// That is, $$1 \text{ degrees } = \frac{\pi}{180} \text{ radians }$$.
|
||||
/// That is, \\(1 \text{ degrees } = \frac{\pi}{180} \text{ radians }\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -151,7 +152,7 @@ pub fn degrees_to_radians(x: Float) -> Float {
|
|||
/// </div>
|
||||
///
|
||||
/// Convert a value in degrees to a value measured in radians.
|
||||
/// That is, $$1 \text{ radians } = \frac{180}{\pi} \text{ degrees }$$.
|
||||
/// That is, \\(1 \text{ radians } = \frac{180}{\pi} \text{ degrees }\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -70,8 +70,8 @@ import gleam/option
|
|||
/// \forall x \in \[-1, 1\], \\; \cos^{-1}{(x)} = y \in \[0, \pi \]
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\[-1, 1\]$$ as input and returns a
|
||||
/// numeric value $$y$$ that lies in the range $$\[0, \pi \]$$ (an angle in radians).
|
||||
/// The function takes a number \\(x\\) in its domain \\(\[-1, 1\]\\) as input and returns a
|
||||
/// numeric value \\(y\\) that lies in the range \\(\[0, \pi \]\\) (an angle in radians).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -125,8 +125,8 @@ fn do_acos(a: Float) -> Float
|
|||
/// \forall x \in [1, +\infty\), \\; \cosh^{-1}{(x)} = y \in \[0, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\[1, +\infty\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\[0, +\infty\)$$ (an angle in radians).
|
||||
/// The function takes a number \\(x\\) in its domain \\(\[1, +\infty\)\\) as input and returns
|
||||
/// a numeric value \\(y\\) that lies in the range \\(\[0, +\infty\)\\) (an angle in radians).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -177,9 +177,9 @@ fn do_acosh(a: Float) -> Float
|
|||
/// \forall x \in \[-1, 1\], \\; \sin^{-1}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\[-1, 1\]$$ as input and returns a numeric
|
||||
/// value $$y$$ that lies in the range $$\[-\frac{\pi}{2}, \frac{\pi}{2}\]$$ (an angle in radians).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\[-1, 1\]\\) as input and returns a numeric
|
||||
/// value \\(y\\) that lies in the range \\(\[-\frac{\pi}{2}, \frac{\pi}{2}\]\\) (an angle in
|
||||
/// radians). If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -232,8 +232,9 @@ fn do_asin(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, \infty\), \\; \sinh^{-1}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, +\infty\)$$ (an angle in radians).
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input and
|
||||
/// returns a numeric value \\(y\\) that lies in the range \\(\(-\infty, +\infty\)\\) (an angle in
|
||||
/// radians).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -273,8 +274,9 @@ fn do_asinh(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, \infty\), \\; \tan^{-1}{(x)} = y \in \[-\frac{\pi}{2}, \frac{\pi}{2}\]
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\[-\frac{\pi}{2}, \frac{\pi}{2}\]$$ (an angle in radians).
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input and
|
||||
/// returns a numeric value \\(y\\) that lies in the range \\(\[-\frac{\pi}{2}, \frac{\pi}{2}\]\\)
|
||||
/// (an angle in radians).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -323,8 +325,8 @@ fn do_atan(a: Float) -> Float
|
|||
/// \\]
|
||||
///
|
||||
/// The function returns the angle in radians from the x-axis to the line containing the
|
||||
/// origin $$\(0, 0\)$$ and a point given as input with coordinates $$\(x, y\)$$. The numeric value
|
||||
/// returned by $$\text{atan2}(y, x)$$ is in the range $$\[-\pi, \pi\]$$.
|
||||
/// origin \\(\(0, 0\)\\) and a point given as input with coordinates \\(\(x, y\)\\). The numeric
|
||||
/// value returned by \\(\text{atan2}(y, x)\\) is in the range \\(\[-\pi, \pi\]\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -364,8 +366,8 @@ fn do_atan2(a: Float, b: Float) -> Float
|
|||
/// \forall x \in \(-1, 1\), \\; \tanh^{-1}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-1, 1\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$ (an angle in radians).
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(-1, 1\)\\) as input and returns
|
||||
/// a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\) (an angle in radians).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -419,8 +421,8 @@ fn do_atanh(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, +\infty\), \\; \cos{(x)} = y \in \[-1, 1\]
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ (an angle in radians)
|
||||
/// as input and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$.
|
||||
/// 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\]\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -463,9 +465,9 @@ fn do_cos(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, \infty\), \\; \cosh{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ as input (an angle in radians)
|
||||
/// and returns a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$.
|
||||
/// If the input value is too large an overflow error might occur.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) as input (an angle
|
||||
/// in radians) and returns a numeric value \\(y\\) that lies in the range
|
||||
/// \\(\(-\infty, \infty\)\\). If the input value is too large an overflow error might occur.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -505,8 +507,8 @@ fn do_cosh(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, +\infty\), \\; \sin{(x)} = y \in \[-1, 1\]
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ (an angle in radians)
|
||||
/// as input and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$.
|
||||
/// 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\]\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -549,10 +551,9 @@ fn do_sin(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, +\infty\), \\; \sinh{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input
|
||||
/// (an angle in radians) and returns a numeric value $$y$$ that lies in the range
|
||||
/// $$\(-\infty, +\infty\)$$. If the input value is too large an overflow error might
|
||||
/// occur.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input
|
||||
/// (an angle in radians) and returns a numeric value \\(y\\) that lies in the range
|
||||
/// \\(\(-\infty, +\infty\)\\). If the input value is too large an overflow error might occur.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -592,9 +593,9 @@ fn do_sinh(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, +\infty\), \\; \tan{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input
|
||||
/// (an angle in radians) and returns a numeric value $$y$$ that lies in the range
|
||||
/// $$\(-\infty, +\infty\)$$.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(-\infty, +\infty\)\\) as input
|
||||
/// (an angle in radians) and returns a numeric value \\(y\\) that lies in the range
|
||||
/// \\(\(-\infty, +\infty\)\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -634,8 +635,8 @@ fn do_tan(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, \infty\), \\; \tanh{(x)} = y \in \[-1, 1\]
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ as input (an angle in radians)
|
||||
/// and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(-\infty, \infty\)\\) as input (an angle
|
||||
/// in radians) and returns a numeric value \\(y\\) that lies in the range \\(\[-1, 1\]\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -681,9 +682,9 @@ fn do_tanh(a: Float) -> Float
|
|||
/// \forall x \in \(-\infty, \infty\), \\; e^{(x)} = y \in \(0, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// $$e \approx 2.71828\dots$$ is Eulers' number.
|
||||
/// \\(e \approx 2.71828\dots\\) is Eulers' number.
|
||||
///
|
||||
/// Note: If the input value $$x$$ is too large an overflow error might occur.
|
||||
/// Note: If the input value \\(x\\) is too large an overflow error might occur.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
@ -723,8 +724,8 @@ fn do_exponential(a: Float) -> Float
|
|||
/// \forall x \in \(0, \infty\), \\; \log_{e}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns
|
||||
/// a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -773,14 +774,14 @@ fn do_natural_logarithm(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The base $$b$$ logarithm function (computed through the "change of base" formula):
|
||||
/// The base \\(b\\) logarithm function (computed through the "change of base" formula):
|
||||
///
|
||||
/// \\[
|
||||
/// \forall x \in \(0, \infty\) \textnormal{ and } b > 1, \\; \log_{b}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ and a base $$b > 1$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) and a base \\(b > 1\\)
|
||||
/// as input and returns a numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -848,8 +849,8 @@ pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String)
|
|||
/// \forall x \in \(0, \infty), \\; \log_{2}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns a
|
||||
/// numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -903,8 +904,8 @@ fn do_logarithm_2(a: Float) -> Float
|
|||
/// \forall x \in \(0, \infty), \\; \log_{10}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$.
|
||||
/// The function takes a number \\(x\\) in its domain \\(\(0, \infty\)\\) as input and returns a
|
||||
/// numeric value \\(y\\) that lies in the range \\(\(-\infty, \infty\)\\).
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -958,14 +959,14 @@ fn do_logarithm_10(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The exponentiation function: $$y = x^{a}$$.
|
||||
/// The exponentiation function: \\(y = x^{a}\\).
|
||||
///
|
||||
/// Note that the function is not defined if:
|
||||
/// 1. The base is negative ($$x < 0$$) and the exponent is fractional
|
||||
/// ($$a = \frac{n}{m}$$ is an irrreducible fraction). An error will be returned
|
||||
/// 1. The base is negative (\\(x < 0\\)) and the exponent is fractional
|
||||
/// (\\(a = \frac{n}{m}\\) is an irrreducible fraction). An error will be returned
|
||||
/// as an imaginary number will otherwise have to be returned.
|
||||
/// 2. The base is zero ($$x = 0$$) and the exponent is negative ($$a < 0$$) then the
|
||||
/// expression is equivalent to the exponent $$y$$ divided by $$0$$ and an
|
||||
/// 2. The base is zero (\\(x = 0\\)) and the exponent is negative (\\(a < 0\\)) then the
|
||||
/// expression is equivalent to the exponent \\(y\\) divided by \\(0\\) and an
|
||||
/// error will have to be returned as the expression is otherwise undefined.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -1024,10 +1025,10 @@ fn do_ceiling(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The square root function: $$y = \sqrt[2]{x} = x^{\frac{1}{2}}$$.
|
||||
/// The square root function: \\(y = \sqrt[2]{x} = x^{\frac{1}{2}}\\).
|
||||
///
|
||||
/// Note that the function is not defined if:
|
||||
/// 1. The input is negative ($$x < 0$$). An error will be returned
|
||||
/// 1. The input is negative (\\(x < 0\\)). An error will be returned
|
||||
/// as an imaginary number will otherwise have to be returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -1076,10 +1077,10 @@ pub fn square_root(x: Float) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The cube root function: $$y = \sqrt[3]{x} = x^{\frac{1}{3}}$$.
|
||||
/// The cube root function: \\(y = \sqrt[3]{x} = x^{\frac{1}{3}}\\).
|
||||
///
|
||||
/// Note that the function is not defined if:
|
||||
/// 1. The input is negative ($$x < 0$$). An error will be returned
|
||||
/// 1. The input is negative (\\(x < 0\\)). An error will be returned
|
||||
/// as an imaginary number will otherwise have to be returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -1128,10 +1129,10 @@ pub fn cube_root(x: Float) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The $$n$$'th root function: $$y = \sqrt[n]{x} = x^{\frac{1}{n}}$$.
|
||||
/// The \\(n\\)'th root function: \\(y = \sqrt[n]{x} = x^{\frac{1}{n}}\\).
|
||||
///
|
||||
/// Note that the function is not defined if:
|
||||
/// 1. The input is negative ($$x < 0$$). An error will be returned
|
||||
/// 1. The input is negative (\\(x < 0\\)). An error will be returned
|
||||
/// as an imaginary number will otherwise have to be returned.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -1189,7 +1190,7 @@ pub fn nth_root(x: Float, n: Int) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The mathematical constant pi: $$\pi \approx 3.1415\dots$$
|
||||
/// The mathematical constant pi: \\(\pi \approx 3.1415\dots\\)
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -1211,7 +1212,7 @@ fn do_pi() -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The mathematical constant tau: $$\tau = 2 \cdot \pi \approx 6.283\dots$$
|
||||
/// The mathematical constant tau: \\(\tau = 2 \cdot \pi \approx 6.283\dots\\)
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -1229,7 +1230,7 @@ pub fn tau() -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Euler's number $$e \approx 2.71828\dots$$.
|
||||
/// Euler's number \\(e \approx 2.71828\dots\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -126,15 +126,15 @@ fn validate_weights(warr: List(Float)) -> Result(Bool, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculate the (weighted) $$p$$-norm of a list (representing a vector):
|
||||
/// Calculate the (weighted) \\(p\\)-norm of a list (representing a vector):
|
||||
///
|
||||
/// \\[
|
||||
/// \left( \sum_{i=1}^n w_{i} \left|x_{i}\right|^{p} \right)^{\frac{1}{p}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i$$ is the value in
|
||||
/// the input list indexed by $$i$$, while $$w_i \in \mathbb{R}_{+}$$ is
|
||||
/// a corresponding positive weight ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the list and \\(x_i\\) is the value in
|
||||
/// the input list indexed by \\(i\\), while \\(w_i \in \mathbb{R}_{+}\\) is
|
||||
/// a corresponding positive weight (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -246,10 +246,10 @@ pub fn norm(
|
|||
/// \sum_{i=1}^n w_{i} \left|x_i - y_i \right|
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the
|
||||
/// values in the respective input lists indexed by $$i$$, while the
|
||||
/// $$w_i \in \mathbb{R}_{+}$$ are corresponding positive weights
|
||||
/// ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the two lists and \\(x_i, y_i\\) are the
|
||||
/// values in the respective input lists indexed by \\(i\\), while the
|
||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -306,13 +306,13 @@ pub fn manhattan_distance(
|
|||
/// \left( \sum_{i=1}^n w_{i} \left|x_i - y_i \right|^{p} \right)^{\frac{1}{p}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$p >= 1$$ is the order, $$n$$ is the length of the two lists
|
||||
/// and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i$$.
|
||||
/// The $$w_i \in \mathbb{R}_{+}$$ are corresponding positive weights
|
||||
/// ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(p >= 1\\) is the order, \\(n\\) is the length of the two lists
|
||||
/// and \\(x_i, y_i\\) are the values in the respective input lists indexed by \\(i\\).
|
||||
/// The \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// 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>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -396,10 +396,10 @@ pub fn minkowski_distance(
|
|||
/// \left( \sum_{i=1}^n w_{i} \left|x_i - y_i \right|^{2} \right)^{\frac{1}{2}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the
|
||||
/// values in the respective input lists indexed by $$i$$, while the
|
||||
/// $$w_i \in \mathbb{R}_{+}$$ are corresponding positive weights
|
||||
/// ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the two lists and \\(x_i, y_i\\) are the
|
||||
/// values in the respective input lists indexed by \\(i\\), while the
|
||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -455,8 +455,8 @@ pub fn euclidean_distance(
|
|||
/// \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
|
||||
/// values in the respective input lists indexed by $$i$$.
|
||||
/// 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\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -517,8 +517,8 @@ pub fn chebyshev_distance(
|
|||
/// \bar{x} = \frac{1}{n}\sum_{i=1}^n x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the sample size (the length of the list) and $$x_i$$
|
||||
/// is the sample point in the input list indexed by $$i$$.
|
||||
/// 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\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -637,11 +637,11 @@ fn do_median(
|
|||
/// s^{2} = \frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the sample size (the length of the list) and $$x_i$$
|
||||
/// is the sample point in the input list indexed by $$i$$.
|
||||
/// Furthermore, $$\bar{x}$$ is the sample mean and $$d$$ is the "Delta
|
||||
/// Degrees of Freedom", and is by default set to $$d = 0$$, which gives a biased
|
||||
/// estimate of the sample variance. Setting $$d = 1$$ gives an unbiased estimate.
|
||||
/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
|
||||
/// is the sample point in the input list indexed by \\(i\\).
|
||||
/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
|
||||
/// Degrees of Freedom", and is by default set to \\(d = 0\\), which gives a biased
|
||||
/// estimate of the sample variance. Setting \\(d = 1\\) gives an unbiased estimate.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -713,11 +713,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}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the sample size (the length of the list) and $$x_i$$
|
||||
/// is the sample point in the input list indexed by $$i$$.
|
||||
/// Furthermore, $$\bar{x}$$ is the sample mean and $$d$$ is the "Delta
|
||||
/// Degrees of Freedom", and is by default set to $$d = 0$$, which gives a biased
|
||||
/// estimate of the sample standard deviation. Setting $$d = 1$$ gives an unbiased
|
||||
/// In the formula, \\(n\\) is the sample size (the length of the list) and \\(x_i\\)
|
||||
/// is the sample point in the input list indexed by \\(i\\).
|
||||
/// Furthermore, \\(\bar{x}\\) is the sample mean and \\(d\\) is the "Delta
|
||||
/// Degrees of Freedom", and is by default set to \\(d = 0\\), which gives a biased
|
||||
/// estimate of the sample standard deviation. Setting \\(d = 1\\) gives an unbiased
|
||||
/// estimate.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -785,14 +785,14 @@ pub fn standard_deviation(arr: List(Float), ddof: Int) -> Result(Float, String)
|
|||
///
|
||||
/// where:
|
||||
///
|
||||
/// - $$X$$ and $$Y$$ are two sets being compared,
|
||||
/// - $$|X \cap Y|$$ represents the size of the intersection of the two sets
|
||||
/// - $$|X \cup Y|$$ denotes the size of the union of the two sets
|
||||
/// - \\(X\\) and \\(Y\\) are two sets being compared,
|
||||
/// - \\(|X \cap Y|\\) represents the size of the intersection of the two sets
|
||||
/// - \\(|X \cup Y|\\) denotes the size of the union of the two sets
|
||||
///
|
||||
/// The value of the Jaccard index ranges from 0 to 1, where 0 indicates that the
|
||||
/// two sets share no elements and 1 indicates that the sets are identical. The
|
||||
/// Jaccard index is a special case of the [Tversky index](#tversky_index) (with
|
||||
/// $$\alpha=\beta=1$$).
|
||||
/// \\(\alpha=\beta=1\\)).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -835,16 +835,16 @@ pub fn jaccard_index(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
|||
/// \\]
|
||||
///
|
||||
/// where:
|
||||
/// - $$X$$ and $$Y$$ are two sets being compared
|
||||
/// - $$|X \cap Y|$$ is the size of the intersection of the two sets (i.e., the
|
||||
/// - \\(X\\) and \\(Y\\) are two sets being compared
|
||||
/// - \\(|X \cap Y|\\) is the size of the intersection of the two sets (i.e., the
|
||||
/// number of elements common to both sets)
|
||||
/// - $$|X|$$ and $$|Y|$$ are the sizes of the sets $$X$$ and $$Y$$, respectively
|
||||
/// - \\(|X|\\) and \\(|Y|\\) are the sizes of the sets \\(X\\) and \\(Y\\), respectively
|
||||
///
|
||||
/// The coefficient ranges from 0 to 1, where 0 indicates no similarity (the sets
|
||||
/// share no elements) and 1 indicates perfect similarity (the sets are identical).
|
||||
/// The higher the coefficient, the greater the similarity between the two sets.
|
||||
/// The Sørensen-Dice coefficient is a special case of the
|
||||
/// [Tversky index](#tversky_index) (with $$\alpha=\beta=0.5$$).
|
||||
/// [Tversky index](#tversky_index) (with \\(\alpha=\beta=0.5\\)).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -880,8 +880,8 @@ pub fn sorensen_dice_coefficient(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
|||
/// </div>
|
||||
///
|
||||
/// The Tversky index is a generalization of the Jaccard index and Sørensen-Dice
|
||||
/// coefficient, which adds flexibility through two parameters, $$\alpha$$ and
|
||||
/// $$\beta$$, allowing for asymmetric similarity measures between sets. The
|
||||
/// coefficient, which adds flexibility through two parameters, \\(\alpha\\) and
|
||||
/// \\(\beta\\), allowing for asymmetric similarity measures between sets. The
|
||||
/// Tversky index is defined as:
|
||||
///
|
||||
/// \\[
|
||||
|
@ -890,18 +890,18 @@ pub fn sorensen_dice_coefficient(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
|||
///
|
||||
/// where:
|
||||
///
|
||||
/// - $$X$$ and $$Y$$ are the sets being compared
|
||||
/// - $$|X - Y|$$ and $$|Y - X|$$ are the sizes of the relative complements of
|
||||
/// $$Y$$ in $$X$$ and $$X$$ in $$Y$$, respectively,
|
||||
/// - $$\alpha$$ and $$\beta$$ are parameters that weigh the relative importance
|
||||
/// of the elements unique to $$X$$ and $$Y$$
|
||||
/// - \\(X\\) and \\(Y\\) are the sets being compared
|
||||
/// - \\(|X - Y|\\) and \\(|Y - X|\\) are the sizes of the relative complements of
|
||||
/// \\(Y\\) in \\(X\\) and \\(X\\) in \\(Y\\), respectively,
|
||||
/// - \\(\alpha\\) and \\(\beta\\) are parameters that weigh the relative importance
|
||||
/// of the elements unique to \\(X\\) and \\(Y\\)
|
||||
///
|
||||
/// The Tversky index reduces to the Jaccard index when $$\alpha = \beta = 1$$ and
|
||||
/// to the Sørensen-Dice coefficient when $$\alpha = \beta = 0.5$$. In general, the
|
||||
/// The Tversky index reduces to the Jaccard index when \\(\alpha = \beta = 1\\) and
|
||||
/// to the Sørensen-Dice coefficient when \\(\alpha = \beta = 0.5\\). In general, the
|
||||
/// Tversky index can take on any non-negative value, including 0. The index equals
|
||||
/// 0 when there is no intersection between the two sets, indicating no similarity.
|
||||
/// However, unlike similarity measures bounded strictly between 0 and 1, the
|
||||
/// Tversky index does not have a strict upper limit of 1 when $$\alpha \neq \beta$$.
|
||||
/// Tversky index does not have a strict upper limit of 1 when \\(\alpha \neq \beta\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -982,9 +982,9 @@ pub fn tversky_index(
|
|||
///
|
||||
/// where:
|
||||
///
|
||||
/// - $$X$$ and $$Y$$ are the sets being compared
|
||||
/// - $$|X \cap Y|$$ is the size of the intersection of the sets
|
||||
/// - $$\min(|X|, |Y|)$$ is the size of the smaller set among $$X$$ and $$Y$$
|
||||
/// - \\(X\\) and \\(Y\\) are the sets being compared
|
||||
/// - \\(|X \cap Y|\\) is the size of the intersection of the sets
|
||||
/// - \\(\min(|X|, |Y|)\\) is the size of the smaller set among \\(X\\) and \\(Y\\)
|
||||
///
|
||||
/// The coefficient ranges from 0 to 1, where 0 indicates no overlap and 1
|
||||
/// indicates that the smaller set is a suyset of the larger set. This
|
||||
|
@ -1043,10 +1043,10 @@ pub fn overlap_coefficient(xset: set.Set(a), yset: set.Set(a)) -> Float {
|
|||
/// \\; \in \\; \left[-1, 1\right]
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i$$, $$y_i$$ are
|
||||
/// the values in the respective input lists indexed by $$i$$, while the
|
||||
/// $$w_i \in \mathbb{R}_{+}$$ are corresponding positive weights
|
||||
/// ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the two lists and \\(x_i\\), \\(y_i\\) are
|
||||
/// the values in the respective input lists indexed by \\(i\\), while the
|
||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// The cosine similarity provides a value between -1 and 1, where 1 means the
|
||||
/// vectors are in the same direction, -1 means they are in exactly opposite
|
||||
|
@ -1143,10 +1143,10 @@ pub fn cosine_similarity(
|
|||
/// {\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
|
||||
/// values in the respective input lists indexed by $$i$$, while the
|
||||
/// $$w_i \in \mathbb{R}_{+}$$ are corresponding positive weights
|
||||
/// ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the two lists, and \\(x_i, y_i\\) are the
|
||||
/// values in the respective input lists indexed by \\(i\\), while the
|
||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -1231,12 +1231,12 @@ fn canberra_distance_helper(tuple: #(Float, Float)) -> Float {
|
|||
/// {\sum_{i=1}^n w_{i}\left| x_i + y_i \right|}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists, and $$x_i, y_i$$ are the values
|
||||
/// in the respective input lists indexed by $$i$$, while the
|
||||
/// $$w_i \in \mathbb{R}_{+}$$ are corresponding positive weights
|
||||
/// ($$w_i = 1.0\\;\forall i=1...n$$ by default).
|
||||
/// In the formula, \\(n\\) is the length of the two lists, and \\(x_i, y_i\\) are the values
|
||||
/// in the respective input lists indexed by \\(i\\), while the
|
||||
/// \\(w_i \in \mathbb{R}_{+}\\) are corresponding positive weights
|
||||
/// (\\(w_i = 1.0\\;\forall i=1...n\\) by default).
|
||||
///
|
||||
/// The 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.
|
||||
///
|
||||
/// <details>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css" integrity="sha384-wcIxkf4k558AjM3Yz3BBFQUbk/zgIYC2R0QpeeYb+TwlBVMrlgLqwRjRtGZiK7ww" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js" integrity="sha384-hIoBPJpTUs74ddyc4bFZSM1TVlQDA60VBbJS0oA934VSz82sBx1X7kSx2ATBDIyd" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -66,24 +66,26 @@ import gleam_community/maths/elementary
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// 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$$.
|
||||
/// The ceiling function rounds a given input value \\(x \in \mathbb{R}\\) to the nearest integer
|
||||
/// value (at the specified digit) that is larger than or equal to the input \\(x\\).
|
||||
///
|
||||
/// Note: The ceiling function is used as an alias for the rounding function [`round`](#round) with rounding mode `RoundUp`.
|
||||
/// Note: The ceiling function is used as an alias for the rounding function [`round`](#round)
|
||||
/// with rounding mode `RoundUp`.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// For example, $$12.0654$$ is rounded to:
|
||||
/// - $$13.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.066$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// For example, \\(12.0654\\) is rounded to:
|
||||
/// - \\(13.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.066\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// For example, $$12.0654$$ is rounded to:
|
||||
/// - $$20.0$$ for 1 digit places before the decimal point (`digit = -1`)
|
||||
/// - $$100.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$1000.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// For example, \\(12.0654\\) is rounded to:
|
||||
/// - \\(20.0\\) for 1 digit places before the decimal point (`digit = -1`)
|
||||
/// - \\(100.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(1000.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -122,23 +124,26 @@ pub fn ceiling(x: Float, digits: option.Option(Int)) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// 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$$.
|
||||
/// The floor function rounds input \\(x \in \mathbb{R}\\) to the nearest integer value (at the
|
||||
/// specified digit) that is less than or equal to the input \\(x\\).
|
||||
///
|
||||
/// Note: The floor function is used as an alias for the rounding function [`round`](#round) with rounding mode `RoundDown`.
|
||||
/// Note: The floor function is used as an alias for the rounding function [`round`](#round)
|
||||
/// with rounding mode `RoundDown`.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// For example, $$12.0654$$ is rounded to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.0$$ for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// For example, \\(12.0654\\) is rounded to:
|
||||
/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.0\\) for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -177,23 +182,27 @@ pub fn floor(x: Float, digits: option.Option(Int)) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The truncate function rounds a given input $$x \in \mathbb{R}$$ to the nearest integer value (at the specified digit) that is less than or equal to the absolute value of the input $$x$$.
|
||||
/// The truncate function rounds a given input \\(x \in \mathbb{R}\\) to the nearest integer
|
||||
/// value (at the specified digit) that is less than or equal to the absolute value of the
|
||||
/// input \\(x\\).
|
||||
///
|
||||
/// Note: The truncate function is used as an alias for the rounding function [`round`](#round) with rounding mode `RoundToZero`.
|
||||
/// Note: The truncate function is used as an alias for the rounding function [`round`](#round)
|
||||
/// with rounding mode `RoundToZero`.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// For example, $$12.0654$$ is rounded to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.0$$ for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// For example, \\(12.0654\\) is rounded to:
|
||||
/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.0\\) for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -232,84 +241,103 @@ pub fn truncate(x: Float, digits: option.Option(Int)) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function rounds a float to a specific number of digits (after the decimal place or before if negative) using a specified rounding mode.
|
||||
/// The function rounds a float to a specific number of digits (after the decimal place or before
|
||||
/// if negative) using a specified rounding mode.
|
||||
///
|
||||
/// Valid rounding modes include:
|
||||
/// - `RoundNearest` (default): The input $$x$$ is rounded to the nearest integer value (at the specified digit) with ties (fractional values of 0.5) being rounded to the nearest even integer.
|
||||
/// - `RoundTiesAway`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) with ties (fractional values of 0.5) being rounded away from zero (C/C++ rounding behavior).
|
||||
/// - `RoundTiesUp`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) with ties (fractional values of 0.5) being rounded towards $$+\infty$$ (Java/JavaScript rounding behaviour).
|
||||
/// - `RoundToZero`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) that is less than or equal to the absolute value of the input $$x$$. An alias for this rounding mode is [`truncate`](#truncate).
|
||||
/// - `RoundDown`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) that is less than or equal to the input $$x$$. An alias for this rounding mode is [`floor`](#floor).
|
||||
/// - `RoundUp`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) that is larger than or equal to the input $$x$$. An alias for this rounding mode is [`ceiling`](#ceiling).
|
||||
/// - `RoundNearest` (default): The input \\(x\\) is rounded to the nearest integer value (at the
|
||||
/// specified digit) with ties (fractional values of 0.5) being rounded to the nearest even
|
||||
/// integer.
|
||||
/// - `RoundTiesAway`: The input \\(x\\) is rounded to the nearest integer value (at the
|
||||
/// specified digit) with ties (fractional values of 0.5) being rounded away from zero (C/C++
|
||||
/// rounding behavior).
|
||||
/// - `RoundTiesUp`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
||||
/// digit) with ties (fractional values of 0.5) being rounded towards \\(+\infty\\)
|
||||
/// (Java/JavaScript rounding behaviour).
|
||||
/// - `RoundToZero`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
||||
/// digit) that is less than or equal to the absolute value of the input \\(x\\). An alias for
|
||||
/// this rounding mode is [`truncate`](#truncate).
|
||||
/// - `RoundDown`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
||||
/// digit) that is less than or equal to the input \\(x\\). An alias for this rounding mode is
|
||||
/// [`floor`](#floor).
|
||||
/// - `RoundUp`: The input \\(x\\) is rounded to the nearest integer value (at the specified
|
||||
/// digit) that is larger than or equal to the input \\(x\\). An alias for this rounding mode
|
||||
/// is [`ceiling`](#ceiling).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// The `RoundNearest` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// The `RoundNearest` rounding mode, rounds \\(12.0654\\) to:
|
||||
/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `RoundTiesAway` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// The `RoundTiesAway` rounding mode, rounds \\(12.0654\\) to:
|
||||
/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `RoundTiesUp` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// The `RoundTiesUp` rounding mode, rounds \\(12.0654\\) to:
|
||||
/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.1\\) for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `RoundToZero` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.0$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// The `RoundToZero` rounding mode, rounds \\(12.0654\\) to:
|
||||
/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.0\\) for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `RoundDown` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.0$$ for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// The `RoundDown` rounding mode, rounds \\(12.0654\\) to:
|
||||
/// - \\(12.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.0\\) for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - \\(12.06\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.065\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(10.0\\) for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - \\(0.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(0.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `RoundUp` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$13.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.066$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
/// The `RoundUp` rounding mode, rounds \\(12.0654\\) to:
|
||||
/// - \\(13.0\\) for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - \\(12.1\\) for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - \\(12.07\\) for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - \\(12.066\\) for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$20.0$$ for 1 digit places before the decimal point (`digit = -1`)
|
||||
/// - $$100.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$1000.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative
|
||||
/// number refers to the digits before the decimal point.
|
||||
/// - \\(20.0\\) for 1 digit places before the decimal point (`digit = -1`)
|
||||
/// - \\(100.0\\) for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - \\(1000.0\\) for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -475,7 +503,7 @@ fn do_ceiling(a: Float) -> Float
|
|||
/// \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.
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -504,7 +532,7 @@ pub fn float_absolute_value(x: Float) -> Float {
|
|||
/// \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.
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -533,7 +561,7 @@ pub fn int_absolute_value(x: Int) -> Int {
|
|||
/// \forall x, y \in \mathbb{R}, \\; |x - y| \in \mathbb{R}_{+}.
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes two inputs $$x$$ and $$y$$ and returns a positive float
|
||||
/// The function takes two inputs \\(x\\) and \\(y\\) and returns a positive float
|
||||
/// value which is the the absolute difference of the inputs.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -574,7 +602,7 @@ pub fn float_absolute_difference(a: Float, b: Float) -> Float {
|
|||
/// \forall x, y \in \mathbb{Z}, \\; |x - y| \in \mathbb{Z}_{+}.
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes two inputs $$x$$ and $$y$$ and returns a positive integer
|
||||
/// The function takes two inputs \\(x\\) and \\(y\\) and returns a positive integer
|
||||
/// value which is the the absolute difference of the inputs.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -609,7 +637,7 @@ pub fn int_absolute_difference(a: Int, b: Int) -> Int {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function takes an input $$x \in \mathbb{R}$$ and returns the sign of
|
||||
/// The function takes an input \\(x \in \mathbb{R}\\) and returns the sign of
|
||||
/// the input, indicating whether it is positive (+1.0), negative (-1.0), or
|
||||
/// zero (0.0).
|
||||
///
|
||||
|
@ -645,7 +673,7 @@ fn do_float_sign(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function takes an input $$x \in \mathbb{Z}$$ and returns the sign of
|
||||
/// The function takes an input \\(x \in \mathbb{Z}\\) and returns the sign of
|
||||
/// the input, indicating whether it is positive (+1), negative (-1), or zero
|
||||
/// (0).
|
||||
///
|
||||
|
@ -681,8 +709,8 @@ fn do_int_sign(a: Int) -> Int
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function takes two arguments $$x, y \in \mathbb{R}$$ and returns $$x$$
|
||||
/// such that it has the same sign as $$y$$.
|
||||
/// The function takes two arguments \\(x, y \in \mathbb{R}\\) and returns \\(x\\)
|
||||
/// such that it has the same sign as \\(y\\).
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -707,8 +735,8 @@ pub fn float_copy_sign(x: Float, y: Float) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function takes two arguments $$x, y \in \mathbb{Z}$$ and returns $$x$$
|
||||
/// such that it has the same sign as $$y$$.
|
||||
/// The function takes two arguments \\(x, y \in \mathbb{Z}\\) and returns \\(x\\)
|
||||
/// such that it has the same sign as \\(y\\).
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -733,7 +761,7 @@ pub fn int_copy_sign(x: Int, y: Int) -> Int {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function flips the sign of a given input value $$x \in \mathbb{R}$$.
|
||||
/// The function flips the sign of a given input value \\(x \in \mathbb{R}\\).
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -751,7 +779,7 @@ pub fn float_flip_sign(x: Float) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function flips the sign of a given input value $$x \in \mathbb{Z}$$.
|
||||
/// The function flips the sign of a given input value \\(x \in \mathbb{Z}\\).
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -769,8 +797,8 @@ pub fn int_flip_sign(x: Int) -> Int {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The minimum function takes two arguments $$x, y$$ along with a function
|
||||
/// for comparing $$x, y$$. The function returns the smallest of the two given
|
||||
/// The minimum function takes two arguments \\(x, y\\) along with a function
|
||||
/// for comparing \\(x, y\\). The function returns the smallest of the two given
|
||||
/// values.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -815,8 +843,8 @@ pub fn minimum(x: a, y: a, compare: fn(a, a) -> order.Order) -> a {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The maximum function takes two arguments $$x, y$$ along with a function
|
||||
/// for comparing $$x, y$$. The function returns the largest of the two given
|
||||
/// The maximum function takes two arguments \\(x, y\\) along with a function
|
||||
/// for comparing \\(x, y\\). The function returns the largest of the two given
|
||||
/// values.
|
||||
///
|
||||
/// <details>
|
||||
|
@ -855,8 +883,8 @@ pub fn maximum(x: a, y: a, compare: fn(a, a) -> order.Order) -> a {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The minmax function takes two arguments $$x, y$$ along with a function
|
||||
/// for comparing $$x, y$$. The function returns a tuple with the smallest
|
||||
/// The minmax function takes two arguments \\(x, y\\) along with a function
|
||||
/// for comparing \\(x, y\\). The function returns a tuple with the smallest
|
||||
/// value first and largest second.
|
||||
///
|
||||
/// <details>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -54,8 +54,8 @@ import gleam_community/maths/piecewise
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// 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
|
||||
/// Determine if a given value \\(a\\) is close to or equivalent to a reference value
|
||||
/// \\(b\\) based on supplied relative \\(r_{tol}\\) and absolute \\(a_{tol}\\) tolerance
|
||||
/// values. The equivalance of the two given values are then determined based on
|
||||
/// the equation:
|
||||
///
|
||||
|
@ -221,8 +221,8 @@ fn do_ceiling(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// A function that tests whether a given integer value $$x \in \mathbb{Z}$$ is a
|
||||
/// power of another integer value $$y \in \mathbb{Z}$$.
|
||||
/// A function that tests whether a given integer value \\(x \in \mathbb{Z}\\) is a
|
||||
/// power of another integer value \\(y \in \mathbb{Z}\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -261,7 +261,7 @@ pub fn is_power(x: Int, y: Int) -> Bool {
|
|||
/// </a>
|
||||
/// </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
|
||||
/// positive divisors.
|
||||
///
|
||||
|
@ -269,8 +269,8 @@ pub fn is_power(x: Int, y: Int) -> Bool {
|
|||
/// <summary>Details</summary>
|
||||
///
|
||||
/// For example:
|
||||
/// - $$6$$ is a perfect number since the divisors of 6 are $$1 + 2 + 3 = 6$$.
|
||||
/// - $$28$$ is a perfect number since the divisors of 28 are $$1 + 2 + 4 + 7 + 14 = 28$$
|
||||
/// - \\(6\\) is a perfect number since the divisors of 6 are \\(1 + 2 + 3 = 6\\).
|
||||
/// - \\(28\\) is a perfect number since the divisors of 28 are \\(1 + 2 + 4 + 7 + 14 = 28\\).
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -314,7 +314,7 @@ fn do_sum(arr: List(Int)) -> Int {
|
|||
/// </a>
|
||||
/// </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>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -347,7 +347,7 @@ pub fn is_even(x: Int) -> Bool {
|
|||
/// </a>
|
||||
/// </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>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -380,11 +380,11 @@ pub fn is_odd(x: Int) -> Bool {
|
|||
/// </a>
|
||||
/// </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
|
||||
/// 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
|
||||
/// as prime. However, the probability of such errors decreases with more testing
|
||||
/// iterations (the function uses 64 iterations internally, which is typically
|
||||
|
@ -395,9 +395,10 @@ pub fn is_odd(x: Int) -> Bool {
|
|||
/// <summary>Details</summary>
|
||||
///
|
||||
/// Examples of prime numbers:
|
||||
/// - $$2$$ is a prime number since it has only two divisors: $$1$$ and $$2$$.
|
||||
/// - $$7$$ is a prime number since it has only two divisors: $$1$$ and $$7$$.
|
||||
/// - $$4$$ is not a prime number since it has divisors other than $$1$$ and itself, such as $$2$$.
|
||||
/// - \\(2\\) is a prime number since it has only two divisors: \\(1\\) and \\(2\\).
|
||||
/// - \\(7\\) is a prime number since it has only two divisors: \\(1\\) and \\(7\\).
|
||||
/// - \\(4\\) is not a prime number since it has divisors other than \\(1\\) and itself, such
|
||||
/// as \\(2\\).
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -474,8 +475,8 @@ fn powmod_with_check(base: Int, exponent: Int, modulus: Int) -> Int {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// A function that tests whether a given real number $$x \in \mathbb{R}$$ is strictly
|
||||
/// between two other real numbers, $$a,b \in \mathbb{R}$$, such that $$a < x < b$$.
|
||||
/// A function that tests whether a given real number \\(x \in \mathbb{R}\\) is strictly
|
||||
/// between two other real numbers, \\(a,b \in \mathbb{R}\\), such that \\(a < x < b\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -511,15 +512,15 @@ pub fn is_between(x: Float, lower: Float, upper: Float) -> Bool {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// 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$$.
|
||||
/// 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\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// For example:
|
||||
/// - $$n = 10$$ is divisible by $$d = 2$$ because $$10 \mod 2 = 0$$.
|
||||
/// - $$n = 7$$ is not divisible by $$d = 3$$ because $$7 \mod 3 \neq 0$$.
|
||||
/// - \\(n = 10\\) is divisible by \\(d = 2\\) because \\(10 \mod 2 = 0\\).
|
||||
/// - \\(n = 7\\) is not divisible by \\(d = 3\\) because \\(7 \mod 3 \neq 0\\).
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
@ -554,15 +555,16 @@ pub fn is_divisible(n: Int, d: Int) -> Bool {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// 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 \quad q \in \mathbb{Z}$$.
|
||||
/// A function that tests whether a given integer \\(m \in \mathbb{Z}\\) is a multiple of another
|
||||
/// integer \\(k \in \mathbb{Z}\\), such that \\(m = k \times q\\), with \\(q \in \mathbb{Z}\\).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// For example:
|
||||
/// - $$m = 15$$ is a multiple of $$k = 5$$ because $$15 = 5 \times 3$$.
|
||||
/// - $$m = 14$$ is not a multiple of $$k = 5$$ because $$14 \div 5$$ does not yield an integer quotient.
|
||||
/// - \\(m = 15\\) is a multiple of \\(k = 5\\) because \\(15 = 5 \times 3\\).
|
||||
/// - \\(m = 14\\) is not a multiple of \\(k = 5\\) because \\(14 \div 5\\) does not yield an
|
||||
/// integer quotient.
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -33,7 +33,7 @@
|
|||
//// * [`geometric_space`](#geometric_space)
|
||||
////
|
||||
|
||||
import gleam/list
|
||||
import gleam/iterator
|
||||
import gleam_community/maths/conversion
|
||||
import gleam_community/maths/elementary
|
||||
import gleam_community/maths/piecewise
|
||||
|
@ -44,29 +44,32 @@ import gleam_community/maths/piecewise
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function returns a list with evenly spaced values within a given interval
|
||||
/// based on a start, stop value and a given increment (step-length) between
|
||||
/// consecutive values. The list returned includes the given start value but
|
||||
/// excludes the stop value.
|
||||
/// The function returns an iterator generating evenly spaced values within a given interval.
|
||||
/// based on a start value but excludes the stop value. The spacing between values is determined
|
||||
/// by the step size provided. The function supports both positive and negative step values.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleam/iterator
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/sequences
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// sequences.arange(1.0, 5.0, 1.0)
|
||||
/// |> iterator.to_list()
|
||||
/// |> should.equal([1.0, 2.0, 3.0, 4.0])
|
||||
///
|
||||
/// // No points returned since
|
||||
/// // start smaller than stop and positive step
|
||||
/// // start is smaller than stop and the step is positive
|
||||
/// sequences.arange(5.0, 1.0, 1.0)
|
||||
/// |> iterator.to_list()
|
||||
/// |> should.equal([])
|
||||
///
|
||||
/// // Points returned since
|
||||
/// // start smaller than stop but negative step
|
||||
/// sequences.arange(5.0, 1.0, -1.0)
|
||||
/// |> iterator.to_list()
|
||||
/// |> should.equal([5.0, 4.0, 3.0, 2.0])
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -77,19 +80,29 @@ import gleam_community/maths/piecewise
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn arange(start: Float, stop: Float, step: Float) -> List(Float) {
|
||||
pub fn arange(
|
||||
start: Float,
|
||||
stop: Float,
|
||||
step: Float,
|
||||
) -> iterator.Iterator(Float) {
|
||||
case start >=. stop && step >. 0.0 || start <=. stop && step <. 0.0 {
|
||||
True -> []
|
||||
True -> iterator.empty()
|
||||
False -> {
|
||||
let direction: Float = case start <=. stop {
|
||||
True -> 1.0
|
||||
False -> -1.0
|
||||
let direction = case start <=. stop {
|
||||
True -> {
|
||||
1.0
|
||||
}
|
||||
let step_abs: Float = piecewise.float_absolute_value(step)
|
||||
let num: Float = piecewise.float_absolute_value(start -. stop) /. step_abs
|
||||
False -> {
|
||||
-1.0
|
||||
}
|
||||
}
|
||||
let step_abs = piecewise.float_absolute_value(step)
|
||||
let num =
|
||||
piecewise.float_absolute_value(start -. stop) /. step_abs
|
||||
|> conversion.float_to_int()
|
||||
|
||||
list.range(0, conversion.float_to_int(num) - 1)
|
||||
|> list.map(fn(i: Int) -> Float {
|
||||
iterator.range(0, num - 1)
|
||||
|> iterator.map(fn(i: Int) {
|
||||
start +. conversion.int_to_float(i) *. step_abs *. direction
|
||||
})
|
||||
}
|
||||
|
@ -102,22 +115,30 @@ pub fn arange(start: Float, stop: Float, step: Float) -> List(Float) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Generate a linearly spaced list of points over a specified interval. The
|
||||
/// endpoint of the interval can optionally be included/excluded.
|
||||
/// The function returns an iterator for generating linearly spaced points over a specified
|
||||
/// interval. The endpoint of the interval can optionally be included/excluded. The number of
|
||||
/// points and whether the endpoint is included determine the spacing between values.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleam/iterator
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/elementary
|
||||
/// import gleam_community/maths/sequences
|
||||
/// import gleam_community/maths/predicates
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||
/// let assert Ok(linspace) = sequences.linear_space(10.0, 50.0, 5, True)
|
||||
/// let assert Ok(tol) = elementary.power(10.0, -6.0)
|
||||
/// let assert Ok(linspace) = sequences.linear_space(10.0, 20.0, 5, True)
|
||||
/// let assert Ok(result) =
|
||||
/// predicates.all_close(linspace, [10.0, 20.0, 30.0, 40.0, 50.0], 0.0, tol)
|
||||
/// predicates.all_close(
|
||||
/// linspace |> iterator.to_list(),
|
||||
/// [10.0, 12.5, 15.0, 17.5, 20.0],
|
||||
/// 0.0,
|
||||
/// tol,
|
||||
/// )
|
||||
///
|
||||
/// result
|
||||
/// |> list.all(fn(x) { x == True })
|
||||
/// |> should.be_true()
|
||||
|
@ -139,38 +160,32 @@ pub fn linear_space(
|
|||
stop: Float,
|
||||
num: Int,
|
||||
endpoint: Bool,
|
||||
) -> Result(List(Float), String) {
|
||||
) -> Result(iterator.Iterator(Float), String) {
|
||||
let direction: Float = case start <=. stop {
|
||||
True -> 1.0
|
||||
False -> -1.0
|
||||
}
|
||||
case num > 0 {
|
||||
True ->
|
||||
case endpoint {
|
||||
|
||||
let increment = case endpoint {
|
||||
True -> {
|
||||
let increment: Float =
|
||||
piecewise.float_absolute_value(start -. stop)
|
||||
/. conversion.int_to_float(num - 1)
|
||||
list.range(0, num - 1)
|
||||
|> list.map(fn(i: Int) -> Float {
|
||||
start +. conversion.int_to_float(i) *. increment *. direction
|
||||
})
|
||||
|> Ok
|
||||
}
|
||||
False -> {
|
||||
let increment: Float =
|
||||
piecewise.float_absolute_value(start -. stop)
|
||||
/. conversion.int_to_float(num)
|
||||
list.range(0, num - 1)
|
||||
|> list.map(fn(i: Int) -> Float {
|
||||
}
|
||||
}
|
||||
case num > 0 {
|
||||
True -> {
|
||||
iterator.range(0, num - 1)
|
||||
|> iterator.map(fn(i: Int) -> Float {
|
||||
start +. conversion.int_to_float(i) *. increment *. direction
|
||||
})
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
|
||||
False ->
|
||||
"Invalid input: num < 0. Valid input is num > 0."
|
||||
"Invalid input: num < 1. Valid input is num >= 1."
|
||||
|> Error
|
||||
}
|
||||
}
|
||||
|
@ -181,22 +196,29 @@ pub fn linear_space(
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Generate a logarithmically spaced list of points over a specified interval. The
|
||||
/// endpoint of the interval can optionally be included/excluded.
|
||||
/// The function returns an iterator of logarithmically spaced points over a specified interval.
|
||||
/// The endpoint of the interval can optionally be included/excluded. The number of points, base,
|
||||
/// and whether the endpoint is included determine the spacing between values.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleam/iterator
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/elementary
|
||||
/// import gleam_community/maths/sequences
|
||||
/// import gleam_community/maths/predicates
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||
/// let assert Ok(tol) = elementary.power(10.0, -6.0)
|
||||
/// let assert Ok(logspace) = sequences.logarithmic_space(1.0, 3.0, 3, True, 10.0)
|
||||
/// let assert Ok(result) =
|
||||
/// predicates.all_close(logspace, [10.0, 100.0, 1000.0], 0.0, tol)
|
||||
/// predicates.all_close(
|
||||
/// logspace |> iterator.to_list(),
|
||||
/// [10.0, 100.0, 1000.0],
|
||||
/// 0.0,
|
||||
/// tol,
|
||||
/// )
|
||||
/// result
|
||||
/// |> list.all(fn(x) { x == True })
|
||||
/// |> should.be_true()
|
||||
|
@ -219,19 +241,19 @@ pub fn logarithmic_space(
|
|||
num: Int,
|
||||
endpoint: Bool,
|
||||
base: Float,
|
||||
) -> Result(List(Float), String) {
|
||||
) -> Result(iterator.Iterator(Float), String) {
|
||||
case num > 0 {
|
||||
True -> {
|
||||
let assert Ok(linspace) = linear_space(start, stop, num, endpoint)
|
||||
linspace
|
||||
|> list.map(fn(i: Float) -> Float {
|
||||
|> iterator.map(fn(i: Float) -> Float {
|
||||
let assert Ok(result) = elementary.power(base, i)
|
||||
result
|
||||
})
|
||||
|> Ok
|
||||
}
|
||||
False ->
|
||||
"Invalid input: num < 0. Valid input is num > 0."
|
||||
"Invalid input: num < 1. Valid input is num >= 1."
|
||||
|> Error
|
||||
}
|
||||
}
|
||||
|
@ -242,25 +264,30 @@ pub fn logarithmic_space(
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function returns a list of numbers spaced evenly on a log scale (a
|
||||
/// geometric progression). Each point in the list is a constant multiple of the
|
||||
/// previous. The function is similar to the
|
||||
/// [`logarithmic_space`](#logarithmic_space) function, but with endpoints
|
||||
/// The function returns an iterator of numbers spaced evenly on a log scale (a geometric
|
||||
/// progression). Each point in the list is a constant multiple of the previous. The function is
|
||||
/// similar to the [`logarithmic_space`](#logarithmic_space) function, but with endpoints
|
||||
/// specified directly.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleam/iterator
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/elementary
|
||||
/// import gleam_community/maths/sequences
|
||||
/// import gleam_community/maths/predicates
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// let assert Ok(tol) = elementary.power(-10.0, -6.0)
|
||||
/// let assert Ok(tol) = elementary.power(10.0, -6.0)
|
||||
/// let assert Ok(logspace) = sequences.geometric_space(10.0, 1000.0, 3, True)
|
||||
/// let assert Ok(result) =
|
||||
/// predicates.all_close(logspace, [10.0, 100.0, 1000.0], 0.0, tol)
|
||||
/// predicates.all_close(
|
||||
/// logspace |> iterator.to_list(),
|
||||
/// [10.0, 100.0, 1000.0],
|
||||
/// 0.0,
|
||||
/// tol,
|
||||
/// )
|
||||
/// result
|
||||
/// |> list.all(fn(x) { x == True })
|
||||
/// |> should.be_true()
|
||||
|
@ -289,7 +316,7 @@ pub fn geometric_space(
|
|||
stop: Float,
|
||||
num: Int,
|
||||
endpoint: Bool,
|
||||
) -> Result(List(Float), String) {
|
||||
) -> Result(iterator.Iterator(Float), String) {
|
||||
case start == 0.0 || stop == 0.0 {
|
||||
True ->
|
||||
"Invalid input: Neither 'start' nor 'stop' can be zero, as they must be non-zero for logarithmic calculations."
|
||||
|
@ -302,7 +329,7 @@ pub fn geometric_space(
|
|||
logarithmic_space(log_start, log_stop, num, endpoint, 10.0)
|
||||
}
|
||||
False ->
|
||||
"Invalid input: num < 0. Valid input is num > 0."
|
||||
"Invalid input: num < 1. Valid input is num >= 1."
|
||||
|> Error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script>
|
||||
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous"></script>
|
||||
////<script>
|
||||
//// document.addEventListener("DOMContentLoaded", function() {
|
||||
//// renderMathInElement(document.body, {
|
||||
|
@ -8,12 +8,12 @@
|
|||
//// // • auto-render specific keys, e.g.:
|
||||
//// delimiters: [
|
||||
//// {left: '$$', right: '$$', display: false},
|
||||
//// // {left: '$', right: '$', display: false},
|
||||
//// // {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '$', right: '$', display: false},
|
||||
//// {left: '\\(', right: '\\)', display: false},
|
||||
//// {left: '\\[', right: '\\]', display: true}
|
||||
//// ],
|
||||
//// // • rendering keys, e.g.:
|
||||
//// throwOnError : false
|
||||
//// throwOnError : true
|
||||
//// });
|
||||
//// });
|
||||
////</script>
|
||||
|
@ -101,7 +101,7 @@ pub fn erf(x: Float) -> Float {
|
|||
/// </div>
|
||||
///
|
||||
/// 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
|
||||
/// using the same coefficients used by the GNU Scientific Library.
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import gleam/iterator
|
||||
import gleam/list
|
||||
import gleam/option
|
||||
import gleam/set
|
||||
import gleam_community/maths/combinatorics
|
||||
import gleeunit/should
|
||||
|
||||
pub fn int_factorial_test() {
|
||||
// Invalid input gives an error
|
||||
// Invalid input gives an error (factorial of negative number)
|
||||
combinatorics.factorial(-1)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
// Valid inputs for factorial of small numbers
|
||||
combinatorics.factorial(0)
|
||||
|> should.equal(Ok(1))
|
||||
|
||||
|
@ -26,56 +28,120 @@ pub fn int_factorial_test() {
|
|||
}
|
||||
|
||||
pub fn int_combination_test() {
|
||||
// Invalid input gives an error
|
||||
// Error on: n = -1 < 0
|
||||
combinatorics.combination(-1, 1)
|
||||
// Invalid input: k < 0 should return an error
|
||||
combinatorics.combination(1, -1, option.None)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
combinatorics.combination(4, 0)
|
||||
// Invalid input: n < 0 should return an error
|
||||
combinatorics.combination(-1, 1, option.None)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input: k > n without repetition gives 0 combinations
|
||||
combinatorics.combination(2, 3, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(0))
|
||||
|
||||
// Valid input: k > n with repetition allowed
|
||||
combinatorics.combination(2, 3, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(4))
|
||||
|
||||
// Valid input: zero combinations (k=0) should always yield 1 combination
|
||||
combinatorics.combination(4, 0, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(1))
|
||||
|
||||
combinatorics.combination(4, 4)
|
||||
combinatorics.combination(4, 0, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(1))
|
||||
|
||||
combinatorics.combination(4, 2)
|
||||
// Valid input: k = n without repetition gives 1 combination
|
||||
combinatorics.combination(4, 4, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(1))
|
||||
|
||||
// Valid input: k = n with repetition allows more combinations
|
||||
combinatorics.combination(4, 4, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(35))
|
||||
|
||||
// Valid input: k < n without and with repetition
|
||||
combinatorics.combination(4, 2, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(6))
|
||||
|
||||
combinatorics.combination(7, 5)
|
||||
combinatorics.combination(4, 2, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(10))
|
||||
|
||||
// Valid input with larger values of n and k
|
||||
combinatorics.combination(7, 5, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(21))
|
||||
// NOTE: Tests with the 'combination' function that produce values that
|
||||
// exceed precision of the JavaScript 'Number' primitive will result in
|
||||
// errors
|
||||
|
||||
combinatorics.combination(7, 5, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(462))
|
||||
// NOTE: Tests with the 'combination' function that produce values that exceed
|
||||
// precision of the JavaScript 'Number' primitive will result in errors
|
||||
}
|
||||
|
||||
pub fn math_permutation_test() {
|
||||
// Invalid input gives an error
|
||||
// Error on: n = -1 < 0
|
||||
combinatorics.permutation(-1, 1)
|
||||
// Invalid input: k < 0 should return an error
|
||||
combinatorics.permutation(1, -1, option.None)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
combinatorics.permutation(4, 0)
|
||||
// Invalid input: n < 0 should return an error
|
||||
combinatorics.permutation(-1, 1, option.None)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input: k > n without repetition gives 0 permutations
|
||||
combinatorics.permutation(2, 3, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(0))
|
||||
|
||||
// Valid input: k > n with repetition allowed gives non-zero permutations
|
||||
combinatorics.permutation(2, 3, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(8))
|
||||
|
||||
// Valid input: k = 0 should always yield 1 permutation
|
||||
combinatorics.permutation(4, 0, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(1))
|
||||
|
||||
combinatorics.permutation(4, 4)
|
||||
combinatorics.permutation(4, 0, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(1))
|
||||
|
||||
combinatorics.permutation(4, 2)
|
||||
// Valid input: k = n permutations without repetition
|
||||
combinatorics.permutation(4, 4, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(24))
|
||||
|
||||
// Valid input: k = n permutations with repetition
|
||||
combinatorics.permutation(4, 4, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(256))
|
||||
|
||||
// Valid input: k < n permutations without and with repetition
|
||||
combinatorics.permutation(4, 2, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(12))
|
||||
|
||||
combinatorics.permutation(4, 2, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(16))
|
||||
|
||||
// Valid input with larger values of n and k
|
||||
combinatorics.permutation(6, 2, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(30))
|
||||
|
||||
combinatorics.permutation(6, 2, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(36))
|
||||
|
||||
combinatorics.permutation(6, 3, option.Some(combinatorics.WithoutRepetitions))
|
||||
|> should.equal(Ok(120))
|
||||
|
||||
combinatorics.permutation(6, 3, option.Some(combinatorics.WithRepetitions))
|
||||
|> should.equal(Ok(216))
|
||||
}
|
||||
|
||||
pub fn list_cartesian_product_test() {
|
||||
// An empty lists returns an empty list
|
||||
[]
|
||||
|> combinatorics.cartesian_product([])
|
||||
|> should.equal([])
|
||||
// An empty list returns an empty list as the Cartesian product
|
||||
let xset = set.from_list([])
|
||||
let yset = set.from_list([])
|
||||
let expected_result = set.from_list([])
|
||||
xset
|
||||
|> combinatorics.cartesian_product(yset)
|
||||
|> should.equal(expected_result)
|
||||
|
||||
// Test with some arbitrary inputs
|
||||
[1, 2, 3]
|
||||
|> combinatorics.cartesian_product([1, 2, 3])
|
||||
|> set.from_list()
|
||||
|> should.equal(
|
||||
// Cartesian product of two sets with the same elements
|
||||
let xset = set.from_list([1, 2, 3])
|
||||
let yset = set.from_list([1, 2, 3])
|
||||
let expected_result =
|
||||
set.from_list([
|
||||
#(1, 1),
|
||||
#(1, 2),
|
||||
|
@ -86,38 +152,140 @@ pub fn list_cartesian_product_test() {
|
|||
#(3, 1),
|
||||
#(3, 2),
|
||||
#(3, 3),
|
||||
]),
|
||||
)
|
||||
])
|
||||
xset
|
||||
|> combinatorics.cartesian_product(yset)
|
||||
|> should.equal(expected_result)
|
||||
|
||||
[1.0, 10.0]
|
||||
|> combinatorics.cartesian_product([1.0, 2.0])
|
||||
|> set.from_list()
|
||||
|> should.equal(
|
||||
set.from_list([#(1.0, 1.0), #(1.0, 2.0), #(10.0, 1.0), #(10.0, 2.0)]),
|
||||
)
|
||||
// Cartesian product with floating-point numbers
|
||||
let xset = set.from_list([1.0, 10.0])
|
||||
let yset = set.from_list([1.0, 2.0])
|
||||
let expected_result =
|
||||
set.from_list([#(1.0, 1.0), #(1.0, 2.0), #(10.0, 1.0), #(10.0, 2.0)])
|
||||
xset
|
||||
|> combinatorics.cartesian_product(yset)
|
||||
|> should.equal(expected_result)
|
||||
|
||||
// Cartesian product of sets with different sizes
|
||||
let xset = set.from_list([1.0, 10.0, 100.0])
|
||||
let yset = set.from_list([1.0, 2.0])
|
||||
let expected_result =
|
||||
set.from_list([
|
||||
#(1.0, 1.0),
|
||||
#(1.0, 2.0),
|
||||
#(10.0, 1.0),
|
||||
#(10.0, 2.0),
|
||||
#(100.0, 1.0),
|
||||
#(100.0, 2.0),
|
||||
])
|
||||
xset
|
||||
|> combinatorics.cartesian_product(yset)
|
||||
|> should.equal(expected_result)
|
||||
|
||||
// Cartesian product with different types (strings)
|
||||
let xset = set.from_list(["a", "y", "z"])
|
||||
let yset = set.from_list(["a", "x"])
|
||||
let expected_result =
|
||||
set.from_list([
|
||||
#("a", "a"),
|
||||
#("a", "x"),
|
||||
#("y", "a"),
|
||||
#("y", "x"),
|
||||
#("z", "a"),
|
||||
#("z", "x"),
|
||||
])
|
||||
xset
|
||||
|> combinatorics.cartesian_product(yset)
|
||||
|> should.equal(expected_result)
|
||||
}
|
||||
|
||||
pub fn list_permutation_test() {
|
||||
// An empty lists returns one (empty) permutation
|
||||
// Invalid input: k < 0 should return an error for an empty list
|
||||
[]
|
||||
|> combinatorics.list_permutation()
|
||||
|> combinatorics.list_permutation(-1, option.None)
|
||||
|> should.be_error()
|
||||
|
||||
// Invalid input: k > n should return an error without repetition
|
||||
[1, 2]
|
||||
|> combinatorics.list_permutation(
|
||||
3,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input: An empty list returns a single empty permutation
|
||||
let assert Ok(permutations) =
|
||||
[]
|
||||
|> combinatorics.list_permutation(0, option.None)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[]])
|
||||
|
||||
// Singleton returns one (singleton) permutation
|
||||
// Also works regardless of type of list elements
|
||||
// Singleton list returns a single permutation regardless of repetition settings
|
||||
let assert Ok(permutations) =
|
||||
["a"]
|
||||
|> combinatorics.list_permutation()
|
||||
|> combinatorics.list_permutation(
|
||||
1,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([["a"]])
|
||||
|
||||
// Test with some arbitrary inputs
|
||||
let assert Ok(permutations) =
|
||||
["a"]
|
||||
|> combinatorics.list_permutation(
|
||||
1,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([["a"]])
|
||||
|
||||
// 4-permutations of a single element repeats it 4 times
|
||||
let assert Ok(permutations) =
|
||||
["a"]
|
||||
|> combinatorics.list_permutation(
|
||||
4,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([["a", "a", "a", "a"]])
|
||||
|
||||
// 2-permutations of [1, 2] without repetition
|
||||
let assert Ok(permutations) =
|
||||
[1, 2]
|
||||
|> combinatorics.list_permutation()
|
||||
|> combinatorics.list_permutation(
|
||||
2,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(set.from_list([[1, 2], [2, 1]]))
|
||||
|
||||
// Test with some arbitrary inputs
|
||||
// 2-permutations of [1, 2] with repetition
|
||||
let assert Ok(permutations) =
|
||||
[1, 2]
|
||||
|> combinatorics.list_permutation(
|
||||
2,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(set.from_list([[1, 1], [1, 2], [2, 2], [2, 1]]))
|
||||
|
||||
// 3-permutations of [1, 2, 3] without repetition
|
||||
let assert Ok(permutations) =
|
||||
[1, 2, 3]
|
||||
|> combinatorics.list_permutation()
|
||||
|> combinatorics.list_permutation(
|
||||
3,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(
|
||||
set.from_list([
|
||||
|
@ -130,57 +298,403 @@ pub fn list_permutation_test() {
|
|||
]),
|
||||
)
|
||||
|
||||
// Repeated elements are treated as distinct for the
|
||||
// purpose of permutations, so two identical elements
|
||||
// will appear "both ways round"
|
||||
// 3-permutations of [1, 2, 3] with repetition
|
||||
let assert Ok(permutations) =
|
||||
[1, 2, 3]
|
||||
|> combinatorics.list_permutation(
|
||||
3,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(
|
||||
set.from_list([
|
||||
[1, 1, 1],
|
||||
[1, 1, 2],
|
||||
[1, 1, 3],
|
||||
[1, 2, 1],
|
||||
[1, 2, 2],
|
||||
[1, 2, 3],
|
||||
[1, 3, 1],
|
||||
[1, 3, 2],
|
||||
[1, 3, 3],
|
||||
[2, 1, 1],
|
||||
[2, 1, 2],
|
||||
[2, 1, 3],
|
||||
[2, 2, 1],
|
||||
[2, 2, 2],
|
||||
[2, 2, 3],
|
||||
[2, 3, 1],
|
||||
[2, 3, 2],
|
||||
[2, 3, 3],
|
||||
[3, 1, 1],
|
||||
[3, 1, 2],
|
||||
[3, 1, 3],
|
||||
[3, 2, 1],
|
||||
[3, 2, 2],
|
||||
[3, 2, 3],
|
||||
[3, 3, 1],
|
||||
[3, 3, 2],
|
||||
[3, 3, 3],
|
||||
]),
|
||||
)
|
||||
|
||||
// Repeated elements are treated as distinct in permutations without repetition
|
||||
let assert Ok(permutations) =
|
||||
[1.0, 1.0]
|
||||
|> combinatorics.list_permutation()
|
||||
|> combinatorics.list_permutation(
|
||||
2,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1.0, 1.0], [1.0, 1.0]])
|
||||
|
||||
// This means lists with repeated elements return the
|
||||
// same number of permutations as ones without
|
||||
["l", "e", "t", "t", "e", "r", "s"]
|
||||
|> combinatorics.list_permutation()
|
||||
// Repeated elements allow more possibilities when repetition is allowed
|
||||
let assert Ok(permutations) =
|
||||
[1.0, 1.0]
|
||||
|> combinatorics.list_permutation(
|
||||
2,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])
|
||||
|
||||
// Large inputs: Ensure the correct number of permutations is generated
|
||||
let assert Ok(permutations) =
|
||||
["a", "b", "c", "d", "e"]
|
||||
|> combinatorics.list_permutation(
|
||||
5,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(5040)
|
||||
|> should.equal(120)
|
||||
|
||||
let assert Ok(permutations) =
|
||||
["a", "b", "c", "d", "e"]
|
||||
|> combinatorics.list_permutation(
|
||||
5,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(3125)
|
||||
}
|
||||
|
||||
pub fn permutation_alignment_test() {
|
||||
// Test: Number of generated permutations should match the expected count
|
||||
// Without repetitions
|
||||
let arr = ["a", "b", "c", "d", "e", "f"]
|
||||
let length = list.length(arr)
|
||||
|
||||
let assert Ok(number_of_permutations) =
|
||||
combinatorics.permutation(
|
||||
length,
|
||||
length,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
let assert Ok(permutations) =
|
||||
arr
|
||||
|> combinatorics.list_permutation(
|
||||
length,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(number_of_permutations)
|
||||
|
||||
// With repetitions
|
||||
let arr = ["a", "b", "c", "d", "e", "f"]
|
||||
let length = list.length(arr)
|
||||
|
||||
let assert Ok(number_of_permutations) =
|
||||
combinatorics.permutation(
|
||||
length,
|
||||
length,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
let assert Ok(permutations) =
|
||||
arr
|
||||
|> combinatorics.list_permutation(
|
||||
length,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
permutations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(number_of_permutations)
|
||||
}
|
||||
|
||||
pub fn list_combination_test() {
|
||||
// A negative number returns an error
|
||||
// Invalid input: k < 0 should return an error for an empty list
|
||||
[]
|
||||
|> combinatorics.list_combination(-1)
|
||||
|> combinatorics.list_combination(-1, option.None)
|
||||
|> should.be_error()
|
||||
|
||||
// k is larger than given input list returns an error
|
||||
// Invalid input: k > n should return an error without repetition
|
||||
[1, 2]
|
||||
|> combinatorics.list_combination(3)
|
||||
|> combinatorics.list_combination(
|
||||
3,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
|> should.be_error()
|
||||
// An empty lists returns an empty list
|
||||
|
||||
// Valid input: k > n with repetition allowed
|
||||
let assert Ok(combinations) =
|
||||
[1, 2]
|
||||
|> combinatorics.list_combination(
|
||||
3,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 2, 2]])
|
||||
|
||||
// Valid input: Empty list should return a single empty combination
|
||||
let assert Ok(combinations) =
|
||||
[]
|
||||
|> combinatorics.list_combination(0)
|
||||
|> should.equal(Ok([[]]))
|
||||
|> combinatorics.list_combination(
|
||||
0,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[]])
|
||||
|
||||
// Test with some arbitrary inputs
|
||||
let assert Ok(combinations) =
|
||||
[]
|
||||
|> combinatorics.list_combination(
|
||||
0,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[]])
|
||||
|
||||
// 1-combination of [1, 2] without and with repetition
|
||||
let assert Ok(combinations) =
|
||||
[1, 2]
|
||||
|> combinatorics.list_combination(1)
|
||||
|> should.equal(Ok([[1], [2]]))
|
||||
|> combinatorics.list_combination(
|
||||
1,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1], [2]])
|
||||
|
||||
// Test with some arbitrary inputs
|
||||
let assert Ok(combinations) =
|
||||
[1, 2]
|
||||
|> combinatorics.list_combination(2)
|
||||
|> should.equal(Ok([[1, 2]]))
|
||||
|> combinatorics.list_combination(
|
||||
1,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1], [2]])
|
||||
|
||||
// Test with some arbitrary inputs
|
||||
let assert Ok(result) = combinatorics.list_combination([1, 2, 3, 4], 2)
|
||||
result
|
||||
// 2-combination of [1, 2] without and with repetition
|
||||
let assert Ok(combinations) =
|
||||
[1, 2]
|
||||
|> combinatorics.list_combination(
|
||||
2,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1, 2]])
|
||||
|
||||
let assert Ok(combinations) =
|
||||
[1, 2]
|
||||
|> combinatorics.list_combination(
|
||||
2,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1, 1], [1, 2], [2, 2]])
|
||||
|
||||
// 2-combination of [1, 2, 3, 4] without and with repetition
|
||||
let assert Ok(combinations) =
|
||||
[1, 2, 3, 4]
|
||||
|> combinatorics.list_combination(
|
||||
2,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(
|
||||
set.from_list([[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]),
|
||||
)
|
||||
|
||||
// Test with some arbitrary inputs
|
||||
let assert Ok(result) = combinatorics.list_combination([1, 2, 3, 4], 3)
|
||||
result
|
||||
let assert Ok(combinations) =
|
||||
[1, 2, 3, 4]
|
||||
|> combinatorics.list_combination(
|
||||
2,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(
|
||||
set.from_list([
|
||||
[1, 1],
|
||||
[1, 2],
|
||||
[1, 3],
|
||||
[1, 4],
|
||||
[2, 2],
|
||||
[2, 3],
|
||||
[2, 4],
|
||||
[3, 3],
|
||||
[3, 4],
|
||||
[4, 4],
|
||||
]),
|
||||
)
|
||||
|
||||
// 3-combination of [1, 2, 3, 4] without repetition
|
||||
let assert Ok(combinations) =
|
||||
[1, 2, 3, 4]
|
||||
|> combinatorics.list_combination(
|
||||
3,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(set.from_list([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]))
|
||||
|
||||
// 3-combination of [1, 2, 3] with repetition
|
||||
let assert Ok(combinations) =
|
||||
[1, 2, 3]
|
||||
|> combinatorics.list_combination(
|
||||
3,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> set.from_list()
|
||||
|> should.equal(
|
||||
set.from_list([
|
||||
[1, 1, 1],
|
||||
[1, 1, 2],
|
||||
[1, 1, 3],
|
||||
[1, 2, 2],
|
||||
[1, 2, 3],
|
||||
[1, 3, 3],
|
||||
[2, 2, 2],
|
||||
[2, 2, 3],
|
||||
[2, 3, 3],
|
||||
[3, 3, 3],
|
||||
]),
|
||||
)
|
||||
|
||||
// Combinations treat repeated elements as distinct in certain scenarios
|
||||
let assert Ok(combinations) =
|
||||
[1.0, 1.0]
|
||||
|> combinatorics.list_combination(
|
||||
2,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1.0, 1.0]])
|
||||
|
||||
// Repetition creates more possibilities even with identical elements
|
||||
let assert Ok(combinations) =
|
||||
[1.0, 1.0]
|
||||
|> combinatorics.list_combination(
|
||||
2,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> should.equal([[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]])
|
||||
|
||||
// Large input: Ensure correct number of combinations is generated
|
||||
let assert Ok(combinations) =
|
||||
["a", "b", "c", "d", "e"]
|
||||
|> combinatorics.list_combination(
|
||||
5,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(1)
|
||||
|
||||
let assert Ok(combinations) =
|
||||
["a", "b", "c", "d", "e"]
|
||||
|> combinatorics.list_combination(
|
||||
5,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(126)
|
||||
}
|
||||
|
||||
pub fn combination_alignment_test() {
|
||||
// Test: Number of generated combinations should match the expected count
|
||||
// Without repetitions
|
||||
let arr = ["a", "b", "c", "d", "e", "f"]
|
||||
let length = list.length(arr)
|
||||
|
||||
let assert Ok(number_of_combinations) =
|
||||
combinatorics.combination(
|
||||
length,
|
||||
length,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
let assert Ok(combinations) =
|
||||
arr
|
||||
|> combinatorics.list_combination(
|
||||
length,
|
||||
option.Some(combinatorics.WithoutRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(number_of_combinations)
|
||||
|
||||
// With repetitions
|
||||
let arr = ["a", "b", "c", "d", "e", "f"]
|
||||
let length = list.length(arr)
|
||||
|
||||
let assert Ok(number_of_combinations) =
|
||||
combinatorics.combination(
|
||||
length,
|
||||
length,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
let assert Ok(combinations) =
|
||||
arr
|
||||
|> combinatorics.list_combination(
|
||||
length,
|
||||
option.Some(combinatorics.WithRepetitions),
|
||||
)
|
||||
combinations
|
||||
|> iterator.to_list()
|
||||
|> list.length()
|
||||
|> should.equal(number_of_combinations)
|
||||
}
|
||||
|
||||
pub fn example_test() {
|
||||
// Cartesian product of two empty sets
|
||||
set.from_list([])
|
||||
|> combinatorics.cartesian_product(set.from_list([]))
|
||||
|> should.equal(set.from_list([]))
|
||||
|
||||
// Cartesian product of two sets with numeric values
|
||||
set.from_list([1.0, 10.0])
|
||||
|> combinatorics.cartesian_product(set.from_list([1.0, 2.0]))
|
||||
|> should.equal(
|
||||
set.from_list([#(1.0, 1.0), #(1.0, 2.0), #(10.0, 1.0), #(10.0, 2.0)]),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import gleam/iterator
|
||||
import gleam/list
|
||||
import gleam_community/maths/elementary
|
||||
import gleam_community/maths/predicates
|
||||
|
@ -12,14 +13,24 @@ pub fn float_list_linear_space_test() {
|
|||
// ---> With endpoint included
|
||||
let assert Ok(linspace) = sequences.linear_space(10.0, 50.0, 5, True)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [10.0, 20.0, 30.0, 40.0, 50.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[10.0, 20.0, 30.0, 40.0, 50.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
||||
let assert Ok(linspace) = sequences.linear_space(10.0, 20.0, 5, True)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [10.0, 12.5, 15.0, 17.5, 20.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[10.0, 12.5, 15.0, 17.5, 20.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|
@ -29,7 +40,12 @@ pub fn float_list_linear_space_test() {
|
|||
// ----> Without endpoint included
|
||||
let assert Ok(linspace) = sequences.linear_space(10.0, 50.0, 5, False)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [10.0, 18.0, 26.0, 34.0, 42.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[10.0, 18.0, 26.0, 34.0, 42.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|
@ -37,7 +53,12 @@ pub fn float_list_linear_space_test() {
|
|||
|
||||
let assert Ok(linspace) = sequences.linear_space(10.0, 20.0, 5, False)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [10.0, 12.0, 14.0, 16.0, 18.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[10.0, 12.0, 14.0, 16.0, 18.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|
@ -46,7 +67,12 @@ pub fn float_list_linear_space_test() {
|
|||
// Try with negative stop
|
||||
let assert Ok(linspace) = sequences.linear_space(10.0, -50.0, 5, False)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [10.0, -2.0, -14.0, -26.0, -38.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[10.0, -2.0, -14.0, -26.0, -38.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|
@ -54,7 +80,12 @@ pub fn float_list_linear_space_test() {
|
|||
|
||||
let assert Ok(linspace) = sequences.linear_space(10.0, -20.0, 5, True)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [10.0, 2.5, -5.0, -12.5, -20.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[10.0, 2.5, -5.0, -12.5, -20.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|
@ -63,7 +94,12 @@ pub fn float_list_linear_space_test() {
|
|||
// Try with negative start
|
||||
let assert Ok(linspace) = sequences.linear_space(-10.0, 50.0, 5, False)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [-10.0, 2.0, 14.0, 26.0, 38.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[-10.0, 2.0, 14.0, 26.0, 38.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|
@ -71,7 +107,12 @@ pub fn float_list_linear_space_test() {
|
|||
|
||||
let assert Ok(linspace) = sequences.linear_space(-10.0, 20.0, 5, True)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(linspace, [-10.0, -2.5, 5.0, 12.5, 20.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
linspace |> iterator.to_list(),
|
||||
[-10.0, -2.5, 5.0, 12.5, 20.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|
@ -90,7 +131,12 @@ pub fn float_list_logarithmic_space_test() {
|
|||
// - Positive start, stop, base
|
||||
let assert Ok(logspace) = sequences.logarithmic_space(1.0, 3.0, 3, True, 10.0)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [10.0, 100.0, 1000.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[10.0, 100.0, 1000.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -99,7 +145,12 @@ pub fn float_list_logarithmic_space_test() {
|
|||
let assert Ok(logspace) =
|
||||
sequences.logarithmic_space(1.0, 3.0, 3, True, -10.0)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [-10.0, 100.0, -1000.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[-10.0, 100.0, -1000.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -108,7 +159,12 @@ pub fn float_list_logarithmic_space_test() {
|
|||
let assert Ok(logspace) =
|
||||
sequences.logarithmic_space(1.0, -3.0, 3, True, -10.0)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [-10.0, -0.1, -0.001], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[-10.0, -0.1, -0.001],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -117,7 +173,12 @@ pub fn float_list_logarithmic_space_test() {
|
|||
let assert Ok(logspace) =
|
||||
sequences.logarithmic_space(1.0, -3.0, 3, True, 10.0)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [10.0, 0.1, 0.001], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[10.0, 0.1, 0.001],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -126,7 +187,12 @@ pub fn float_list_logarithmic_space_test() {
|
|||
let assert Ok(logspace) =
|
||||
sequences.logarithmic_space(-1.0, 3.0, 3, True, 10.0)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [0.1, 10.0, 1000.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[0.1, 10.0, 1000.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -136,7 +202,12 @@ pub fn float_list_logarithmic_space_test() {
|
|||
let assert Ok(logspace) =
|
||||
sequences.logarithmic_space(1.0, 3.0, 3, False, 10.0)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [10.0, 46.41588834, 215.443469], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[10.0, 46.41588834, 215.443469],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -154,7 +225,12 @@ pub fn float_list_geometric_space_test() {
|
|||
// - Positive start, stop
|
||||
let assert Ok(logspace) = sequences.geometric_space(10.0, 1000.0, 3, True)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [10.0, 100.0, 1000.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[10.0, 100.0, 1000.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -162,7 +238,12 @@ pub fn float_list_geometric_space_test() {
|
|||
// - Positive start, negative stop
|
||||
let assert Ok(logspace) = sequences.geometric_space(10.0, 0.001, 3, True)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [10.0, 0.1, 0.001], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[10.0, 0.1, 0.001],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -170,7 +251,12 @@ pub fn float_list_geometric_space_test() {
|
|||
// - Positive stop, negative start
|
||||
let assert Ok(logspace) = sequences.geometric_space(0.1, 1000.0, 3, True)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [0.1, 10.0, 1000.0], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[0.1, 10.0, 1000.0],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -179,7 +265,12 @@ pub fn float_list_geometric_space_test() {
|
|||
// - Positive start, stop
|
||||
let assert Ok(logspace) = sequences.geometric_space(10.0, 1000.0, 3, False)
|
||||
let assert Ok(result) =
|
||||
predicates.all_close(logspace, [10.0, 46.41588834, 215.443469], 0.0, tol)
|
||||
predicates.all_close(
|
||||
logspace |> iterator.to_list(),
|
||||
[10.0, 46.41588834, 215.443469],
|
||||
0.0,
|
||||
tol,
|
||||
)
|
||||
result
|
||||
|> list.all(fn(x) { x == True })
|
||||
|> should.be_true()
|
||||
|
@ -199,31 +290,39 @@ pub fn float_list_geometric_space_test() {
|
|||
pub fn float_list_arange_test() {
|
||||
// Positive start, stop, step
|
||||
sequences.arange(1.0, 5.0, 1.0)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([1.0, 2.0, 3.0, 4.0])
|
||||
|
||||
sequences.arange(1.0, 5.0, 0.5)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5])
|
||||
|
||||
sequences.arange(1.0, 2.0, 0.25)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([1.0, 1.25, 1.5, 1.75])
|
||||
|
||||
// Reverse (switch start/stop largest/smallest value)
|
||||
sequences.arange(5.0, 1.0, 1.0)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([])
|
||||
|
||||
// Reverse negative step
|
||||
sequences.arange(5.0, 1.0, -1.0)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([5.0, 4.0, 3.0, 2.0])
|
||||
|
||||
// Positive start, negative stop, step
|
||||
sequences.arange(5.0, -1.0, -1.0)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([5.0, 4.0, 3.0, 2.0, 1.0, 0.0])
|
||||
|
||||
// Negative start, stop, step
|
||||
sequences.arange(-5.0, -1.0, -1.0)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([])
|
||||
|
||||
// Negative start, stop, positive step
|
||||
sequences.arange(-5.0, -1.0, 1.0)
|
||||
|> iterator.to_list()
|
||||
|> should.equal([-5.0, -4.0, -3.0, -2.0])
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue