mirror of
https://github.com/sigmasternchen/gleam-community-maths
synced 2025-03-15 07:59:01 +00:00
Work on all modules
This commit is contained in:
parent
0358fd0b92
commit
35863afec3
10 changed files with 875 additions and 791 deletions
|
@ -19,8 +19,7 @@
|
|||
//// .katex { font-size: 1.1em; }
|
||||
////</style>
|
||||
////
|
||||
//// A module containing several different kinds of mathematical functions and constants
|
||||
//// that apply to real numbers (floats).
|
||||
//// A module containing mathematical functions and constants that apply to real numbers (floats).
|
||||
////
|
||||
//// ---
|
||||
////
|
||||
|
@ -92,35 +91,42 @@ import gleam/option
|
|||
/// </div>
|
||||
///
|
||||
/// The ceiling function rounds a given input value $$x \in \mathbb{R}$$ towards $$+\infty$$ at a specified number of digits.
|
||||
/// For example, $$12.0654$$ is rounded to:
|
||||
/// - $$1000.0$$ at the 3rd digit before the decimal point (`digit = -3`)
|
||||
/// - $$100.0$$ at the 2nd digit before the decimal point (`digit = -2`)
|
||||
/// - $$20.0$$ the 1st digit before the decimal point (`digit = -1`)
|
||||
/// - $$13.0$ at the 0th digit before the decimal point (`digit = 0`)
|
||||
/// - $$12.1$$ at the 1st digit after the decimal point (`digit = 1`)
|
||||
/// - $$12.07$$ at the 2nd digit after the decimal point (`digit = 2`)
|
||||
/// - $$12.066$$ at the 3rd digit after the decimal point (`digit = 3`)
|
||||
///
|
||||
/// See also the concrete code example below.
|
||||
///
|
||||
/// Note: The ceiling function is used as an alias for the rounding function `round` with rounding mode `"Up"`.
|
||||
/// Note: The ceiling function is used as an alias for the rounding function [`round`](#round) with rounding mode `"Up"`.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <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`)
|
||||
///
|
||||
/// 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`)
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam/option
|
||||
/// import gleam_community/maths/float as floatx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// floatx.ceiling(12.0654, option.Some(3))
|
||||
/// |> should.equal(12.066)
|
||||
/// floatx.ceiling(12.0654, option.Some(1))
|
||||
/// |> should.equal(Ok(12.1))
|
||||
///
|
||||
/// floatx.ceiling(12.0654, option.Some(2))
|
||||
/// |> should.equal(12.07)
|
||||
/// |> should.equal(Ok(12.07))
|
||||
///
|
||||
/// floatx.ceiling(12.0654, option.Some(1))
|
||||
/// |> should.equal(12.1)
|
||||
/// floatx.ceiling(12.0654, option.Some(3))
|
||||
/// |> should.equal(Ok(12.066))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -141,35 +147,41 @@ pub fn ceiling(x: Float, digits: option.Option(Int)) -> Result(Float, String) {
|
|||
/// </div>
|
||||
///
|
||||
/// The floor function rounds a given input value $$x \in \mathbb{R}$$ towards $$-\infty$$ at a specified number of digits.
|
||||
/// For example, $$12.0654$$ is rounded to:
|
||||
/// - $$0.0$$ at the 3rd digit before the decimal point (`digit = -3`)
|
||||
/// - $$0.0$$ at the 2nd digit before the decimal point (`digit = -2`)
|
||||
/// - $$10.0$$ the 1st digit before the decimal point (`digit = -1`)
|
||||
/// - $$12.0$ at the 0th digit before the decimal point (`digit = 0`)
|
||||
/// - $$12.0$$ at the 1st digit after the decimal point (`digit = 1`)
|
||||
/// - $$12.06$$ at the 2nd digit after the decimal point (`digit = 2`)
|
||||
/// - $$12.065$$ at the 3rd digit after the decimal point (`digit = 3`)
|
||||
///
|
||||
/// See also the concrete code example below.
|
||||
///
|
||||
/// Note: The floor function is used as an alias for the rounding function `round` with rounding mode `"Down"`.
|
||||
/// Note: The floor function is used as an alias for the rounding function [`round`](#round) with rounding mode `"Down"`.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <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`)
|
||||
///
|
||||
/// 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>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam/option
|
||||
/// import gleam_community/maths/float as floatx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// floatx.ceiling(12.0654, option.Some(3))
|
||||
/// |> should.equal(12.065)
|
||||
/// floatx.floor(12.0654, option.Some(1))
|
||||
/// |> should.equal(Ok(12.0))
|
||||
///
|
||||
/// floatx.ceiling(12.0654, option.Some(2))
|
||||
/// |> should.equal(12.06)
|
||||
/// floatx.floor(12.0654, option.Some(2))
|
||||
/// |> should.equal(Ok(12.06))
|
||||
///
|
||||
/// floatx.ceiling(12.0654, option.Some(1))
|
||||
/// |> should.equal(12.0)
|
||||
/// floatx.floor(12.0654, option.Some(3))
|
||||
/// |> should.equal(Ok(12.065))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -189,26 +201,42 @@ pub fn floor(x: Float, digits: option.Option(Int)) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The truncate function rounds a given input value $$x \in \mathbb{R}$$ towards $$0$$ at a specified number of digits.
|
||||
///
|
||||
/// Note: The truncate function is used as an alias for the rounding function [`round`](#round) with rounding mode `"ToZero"`.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <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`)
|
||||
///
|
||||
/// 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>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam/option
|
||||
/// import gleam_community/maths/float as floatx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// floatx.round(0.4444, 2)
|
||||
/// |> should.equal(0.44)
|
||||
/// floatx.truncate(12.0654, option.Some(1))
|
||||
/// |> should.equal(Ok(12.0))
|
||||
///
|
||||
/// floatx.round(0.4445, 2)
|
||||
/// |> should.equal(0.44)
|
||||
/// floatx.truncate(12.0654, option.Some(2))
|
||||
/// |> should.equal(Ok(12.0))
|
||||
///
|
||||
/// floatx.round(0.4455, 2)
|
||||
/// |> should.equal(0.45)
|
||||
///
|
||||
/// floatx.round(0.4555, 2)
|
||||
/// |> should.equal(0.46)
|
||||
/// floatx.truncate(12.0654, option.Some(3))
|
||||
/// |> should.equal(Ok(12.0))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -218,8 +246,8 @@ pub fn floor(x: Float, digits: option.Option(Int)) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn truncate(x: Float, digits: Int) -> Result(Float, String) {
|
||||
round(x, option.Some(digits), option.Some("ToZero"))
|
||||
pub fn truncate(x: Float, digits: option.Option(Int)) -> Result(Float, String) {
|
||||
round(x, digits, option.Some("ToZero"))
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
|
@ -228,49 +256,125 @@ pub fn truncate(x: Float, digits: Int) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function rounds a floating point number to a specific number of digits using a given 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:
|
||||
/// - `Nearest` (default): If the last digit is equal to 5, then the previous digit is rounded to nearest even integer value.
|
||||
/// - `TiesAway`: If the last digit is equal to 5, then the previous digit is rounded away from zero (C/C++ rounding behavior).
|
||||
/// - `TiesUp`: If the last digit is equal to 5, then the previous digit is rounded towards $$+\infty$$ (Java/JavaScript rounding behaviour).
|
||||
/// - `ToZero`: The last digit is rounded towards $$0$$.
|
||||
/// - An alias for this rounding mode is [`truncate`](#truncate)
|
||||
/// - `Down`: If the last digit larger than 0, then the previous digit is rounded towards $$-\infty$$.
|
||||
/// - An alias for this rounding mode is [`floor`](#floor)
|
||||
/// - `Up`: If the last digit is larger than 0, then the previous digit is rounded towards $$+\infty$$.
|
||||
/// - An alias for this rounding mode is [`ceiling`](#ceiling)
|
||||
///
|
||||
/// Valid rounding modes include:
|
||||
/// - `Nearest` (default): The specified digit is rounded to nearest even integer value if the following digit + 1 is equal to 5.
|
||||
/// - `TiesAway`: The specified digit is rounded away from zero (C/C++ rounding behavior) if the following digit + 1 is equal to 5.
|
||||
/// - `TiesUp`: The specified digit is rounded towards $$+\infty$$ (Java/JavaScript rounding behaviour) if the following digit + 1 is equal to 5.
|
||||
/// - `ToZero`: The input value is truncated at the specified digit.
|
||||
/// - An alias for this rounding mode is [`truncate`](#truncate)
|
||||
/// - `Down`: The specified digit is rounded towards $$-\infty$$ if the following digit + 1 is larger than 0.
|
||||
/// - An alias for this rounding mode is [`floor`](#floor)
|
||||
/// - `Up`: The specified digit is rounded towards $$+\infty$$ if the following digit + 1 is larger than 0.
|
||||
/// - An alias for this rounding mode is [`ceiling`](#ceiling)
|
||||
/// - `"Nearest"` (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.
|
||||
/// - `"TiesAway"`: 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).
|
||||
/// - `"TiesUp"`: 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).
|
||||
/// - `"ToZero"`: 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).
|
||||
/// - `"Down"`: 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).
|
||||
/// - `"Up"`: 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>Example:</summary>
|
||||
/// <summary>Details</summary>
|
||||
///
|
||||
/// The `"Nearest"` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `"TiesAway"` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `"TiesUp"` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.1$$ for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `"ToZero"` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.0$$ for 1 digit after the decimal point (`digits = 1`)
|
||||
/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `"Down"` rounding mode, rounds $$12.0654$$ to:
|
||||
/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`)
|
||||
/// - $$12.0$$ for 1 digits after the decimal point (`digits = 1`)
|
||||
/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`)
|
||||
/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`)
|
||||
///
|
||||
/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point.
|
||||
/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`)
|
||||
/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`)
|
||||
/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`)
|
||||
///
|
||||
/// The `"Up"` 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`)
|
||||
///
|
||||
/// </details>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam/option
|
||||
/// import gleam_community/maths/float as floatx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// floatx.round(0.4444, 2)
|
||||
/// |> should.equal(0.44)
|
||||
/// // The default number of digits is 0 if None is provided
|
||||
/// floatx.round(12.0654, option.None, option.Some("Nearest"))
|
||||
/// |> should.equal(Ok(12.0))
|
||||
///
|
||||
/// floatx.round(0.4445, 2)
|
||||
/// |> should.equal(0.44)
|
||||
/// // The default rounding mode is "Nearest" if None is provided
|
||||
/// floatx.round(12.0654, option.None, option.None)
|
||||
/// |> should.equal(Ok(12.0))
|
||||
///
|
||||
/// floatx.round(0.4455, 2)
|
||||
/// |> should.equal(0.45)
|
||||
/// // We get an error if an invalid rounding mode is provided
|
||||
/// floatx.round(12.0654, option.None, option.Some("XYZ"))
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// floatx.round(0.4555, 2)
|
||||
/// |> should.equal(0.46)
|
||||
/// // Try different rounding modes
|
||||
/// floatx.round(12.0654, option.Some(2), option.Some("Nearest"))
|
||||
/// |> should.equal(Ok(12.07))
|
||||
///
|
||||
/// floatx.round(12.0654, option.Some(2), option.Some("TiesAway"))
|
||||
/// |> should.equal(Ok(12.07))
|
||||
///
|
||||
/// floatx.round(12.0654, option.Some(2), option.Some("TiesUp"))
|
||||
/// |> should.equal(Ok(12.07)
|
||||
///
|
||||
/// floatx.round(12.0654, option.Some(2), option.Some("ToZero"))
|
||||
/// |> should.equal(Ok(12.06))
|
||||
///
|
||||
/// floatx.round(12.0654, option.Some(2), option.Some("Down"))
|
||||
/// |> should.equal(Ok(12.06))
|
||||
///
|
||||
/// floatx.round(12.0654, option.Some(2), option.Some("Up"))
|
||||
/// |> should.equal(Ok(12.07))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -288,82 +392,78 @@ pub fn round(
|
|||
case digits {
|
||||
option.Some(a) -> {
|
||||
assert Ok(p) = power(10.0, int.to_float(a))
|
||||
case mode {
|
||||
// Rounding mode choices
|
||||
option.Some("Nearest") ->
|
||||
round_nearest(p, x)
|
||||
|> Ok
|
||||
option.Some("TiesAway") ->
|
||||
round_ties_away(p, x)
|
||||
|> Ok
|
||||
option.Some("TiesUp") ->
|
||||
round_ties_up(p, x)
|
||||
|> Ok
|
||||
option.Some("ToZero") ->
|
||||
round_to_zero(p, x)
|
||||
|> Ok
|
||||
option.Some("Down") ->
|
||||
round_down(p, x)
|
||||
|> Ok
|
||||
option.Some("Up") ->
|
||||
round_up(p, x)
|
||||
|> Ok
|
||||
// Default rounding mode
|
||||
option.None ->
|
||||
round_nearest(p, x)
|
||||
|> Ok
|
||||
_ ->
|
||||
"Invalid Rounding Mode!"
|
||||
|> Error
|
||||
}
|
||||
do_round(p, x, mode)
|
||||
}
|
||||
option.None -> do_round(1.0, x, mode)
|
||||
}
|
||||
}
|
||||
|
||||
fn do_round(
|
||||
p: Float,
|
||||
x: Float,
|
||||
mode: option.Option(String),
|
||||
) -> Result(Float, String) {
|
||||
case mode {
|
||||
// Rounding mode choices
|
||||
option.Some("Nearest") ->
|
||||
round_nearest(p, x)
|
||||
|> Ok
|
||||
option.Some("TiesAway") ->
|
||||
round_ties_away(p, x)
|
||||
|> Ok
|
||||
option.Some("TiesUp") ->
|
||||
round_ties_up(p, x)
|
||||
|> Ok
|
||||
option.Some("ToZero") ->
|
||||
round_to_zero(p, x)
|
||||
|> Ok
|
||||
option.Some("Down") ->
|
||||
round_down(p, x)
|
||||
|> Ok
|
||||
option.Some("Up") ->
|
||||
round_up(p, x)
|
||||
|> Ok
|
||||
// Default rounding mode. The default is "Nearest"
|
||||
option.None ->
|
||||
round_nearest(p, x)
|
||||
|> Ok
|
||||
_ ->
|
||||
"Invalid!"
|
||||
"Invalid rounding mode. Valid input is 'Nearest', 'TiesAway', 'TiesUp', 'ToZero', 'Down', 'Up'."
|
||||
|> Error
|
||||
}
|
||||
}
|
||||
|
||||
fn round_nearest(p: Float, x: Float) -> Float {
|
||||
let positive = x >. 0.0
|
||||
let xabs = float.absolute_value(x)
|
||||
let geq_tie = xabs -. truncate_float(xabs) >=. 0.5
|
||||
assert Ok(is_even) = int.modulo(to_int(xabs), 2)
|
||||
io.debug(is_even)
|
||||
case geq_tie {
|
||||
True ->
|
||||
let xabs = float.absolute_value(x) *. p
|
||||
let rem = xabs -. truncate_float(xabs)
|
||||
case rem {
|
||||
_ if rem >. 0.5 -> sign(x) *. truncate_float(xabs +. 1.0) /. p
|
||||
_ if rem == 0.5 -> {
|
||||
assert Ok(is_even) = int.modulo(to_int(xabs), 2)
|
||||
case is_even == 0 {
|
||||
True -> sign(x) *. truncate_float({ xabs +. 0.0 } *. p) /. p
|
||||
False -> sign(x) *. truncate_float({ xabs +. 1.0 } *. p) /. p
|
||||
True -> sign(x) *. truncate_float(xabs) /. p
|
||||
False -> sign(x) *. truncate_float(xabs +. 1.0) /. p
|
||||
}
|
||||
False -> sign(x) *. truncate_float({ xabs +. 0.0 } *. p) /. p
|
||||
}
|
||||
_ -> sign(x) *. truncate_float(xabs) /. p
|
||||
}
|
||||
}
|
||||
|
||||
fn round_ties_away(p: Float, x: Float) -> Float {
|
||||
let positive = x >. 0.0
|
||||
let xabs = float.absolute_value(x)
|
||||
let g_tie = xabs -. truncate_float(xabs) >=. 0.5
|
||||
case g_tie {
|
||||
True -> sign(x) *. truncate_float({ xabs +. 1.0 } *. p) /. p
|
||||
False -> truncate_float(x *. p) /. p
|
||||
let xabs = float.absolute_value(x) *. p
|
||||
let rem = xabs -. truncate_float(xabs)
|
||||
case rem {
|
||||
_ if rem >=. 0.5 -> sign(x) *. truncate_float(xabs +. 1.0) /. p
|
||||
_ -> sign(x) *. truncate_float(xabs) /. p
|
||||
}
|
||||
}
|
||||
|
||||
fn round_ties_up(p: Float, x: Float) -> Float {
|
||||
let positive = x >. 0.0
|
||||
let xabs = float.absolute_value(x)
|
||||
let geq_tie = xabs -. truncate_float(xabs) >=. 0.5
|
||||
case geq_tie {
|
||||
True ->
|
||||
case positive {
|
||||
True -> sign(x) *. truncate_float({ xabs +. 1.0 } *. p) /. p
|
||||
False -> sign(x) *. truncate_float({ xabs +. 0.0 } *. p) /. p
|
||||
}
|
||||
False ->
|
||||
case positive {
|
||||
True -> sign(x) *. truncate_float({ xabs +. 0.0 } *. p) /. p
|
||||
False -> sign(x) *. truncate_float({ xabs +. 0.0 } *. p) /. p
|
||||
}
|
||||
let xabs = float.absolute_value(x) *. p
|
||||
let rem = xabs -. truncate_float(xabs)
|
||||
case rem {
|
||||
_ if rem >=. 0.5 && x >=. 0.0 -> sign(x) *. truncate_float(xabs +. 1.0) /. p
|
||||
_ -> sign(x) *. truncate_float(xabs) /. p
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -434,7 +534,7 @@ if erlang {
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -495,7 +595,7 @@ if javascript {
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -553,7 +653,7 @@ if javascript {
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -613,7 +713,7 @@ if javascript {
|
|||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, +\infty\)$$ (an angle in radians).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -660,7 +760,7 @@ if javascript {
|
|||
/// a numeric value $$y$$ that lies in the range $$\[-\frac{\pi}{2}, \frac{\pi}{2}\]$$ (an angle in radians).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -716,7 +816,7 @@ if javascript {
|
|||
/// returned by $$\text{atan2}(y, x)$$ is in the range $$\[-\pi, \pi\]$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -764,7 +864,7 @@ if javascript {
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -824,7 +924,7 @@ if javascript {
|
|||
/// as input and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -875,7 +975,7 @@ if javascript {
|
|||
/// If the input value is too large an overflow error might occur.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -923,7 +1023,7 @@ if javascript {
|
|||
/// Note: If the input value $$x$$ is too large an overflow error might occur.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -971,7 +1071,7 @@ if javascript {
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam/option
|
||||
|
@ -1040,7 +1140,7 @@ pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String)
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1102,7 +1202,7 @@ if javascript {
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1163,7 +1263,7 @@ if javascript {
|
|||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1207,61 +1307,6 @@ if javascript {
|
|||
"../floatx.mjs" "log2"
|
||||
}
|
||||
|
||||
// pub fn logb(x: Float, b: Float) -> Result(Float, String) {
|
||||
// case x >. 0.0 {
|
||||
// True ->
|
||||
// case b >. 0.0 && b != 1.0 {
|
||||
// True -> {
|
||||
// // Apply the change of base formula
|
||||
// assert Ok(numerator) = log10(x)
|
||||
// assert Ok(denominator) = log10(b)
|
||||
// numerator /. denominator
|
||||
// |> Ok
|
||||
// }
|
||||
// False ->
|
||||
// "Invalid input argument: b <= 0 or b == 1. Valid input is b > 0 and b != 1."
|
||||
// |> Error
|
||||
// }
|
||||
// False ->
|
||||
// "Invalid input argument: x <= 0. Valid input is x > 0."
|
||||
// |> Error
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The The base-2 logarithm function:
|
||||
///
|
||||
/// \\[
|
||||
/// \forall x \in \(0, \infty), \\; \log_{2}{(x)} = y \in \(-\infty, +\infty\)
|
||||
/// \\]
|
||||
///
|
||||
/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ as input and returns
|
||||
/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$.
|
||||
/// If the input value is outside the domain of the function an error is returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// floatx.logarithm_2(1.0)
|
||||
/// |> should.equal(Ok(0.0))
|
||||
///
|
||||
/// floatx.logarithm_2(2.0)
|
||||
/// |> should.equal(Ok(1.0))
|
||||
///
|
||||
/// floatx.logarithm_2(-1.0)
|
||||
/// |> should.be_error()
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
|
@ -1285,7 +1330,7 @@ if javascript {
|
|||
/// error will have to be returned as the expression is otherwise undefined.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1309,9 +1354,6 @@ if javascript {
|
|||
/// </div>
|
||||
///
|
||||
pub fn power(x: Float, y: Float) -> Result(Float, String) {
|
||||
// assert Ok(y_ceiling) = ceiling(y, option.Some(0))
|
||||
// io.debug(y_ceiling)
|
||||
// let fractional: Bool = y_ceiling -. y >. 0.0
|
||||
let fractional: Bool = do_ceiling(y) -. y >. 0.0
|
||||
// In the following check:
|
||||
// 1. If the base (x) is negative and the exponent (y) is fractional
|
||||
|
@ -1352,7 +1394,7 @@ if javascript {
|
|||
/// as an imaginary number will otherwise have to be returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1404,7 +1446,7 @@ pub fn square_root(x: Float) -> Result(Float, String) {
|
|||
/// as an imaginary number will otherwise have to be returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1456,7 +1498,7 @@ pub fn cube_root(x: Float) -> Result(Float, String) {
|
|||
/// as an imaginary number will otherwise have to be returned.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1517,7 +1559,7 @@ pub fn nth_root(x: Float, n: Int) -> Result(Float, String) {
|
|||
/// Naive (unfused) and corrected (unfused) in [https://arxiv.org/pdf/1904.09481.pdf]("An Improved Algorithm for Hypot(A, B)" by Borges, C. F)
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1556,7 +1598,7 @@ pub fn hypotenuse(x: Float, y: Float) -> Float {
|
|||
/// as input and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1608,7 +1650,7 @@ if javascript {
|
|||
/// occur.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1656,7 +1698,7 @@ if javascript {
|
|||
/// $$\(-\infty, +\infty\)$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1703,7 +1745,7 @@ if javascript {
|
|||
/// and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1750,7 +1792,7 @@ if javascript {
|
|||
/// That is, $$1 \text{ radians } = \frac{180}{\pi} \text{ degrees }$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1784,7 +1826,7 @@ pub fn to_degree(x: Float) -> Float {
|
|||
/// That is, $$1 \text{ degrees } = \frac{\pi}{180} \text{ radians }$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1814,7 +1856,7 @@ pub fn to_radian(x: Float) -> Float {
|
|||
/// The min function.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1850,7 +1892,7 @@ pub fn minimum(x: Float, y: Float) -> Float {
|
|||
/// The min function.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1886,7 +1928,7 @@ pub fn maximum(x: Float, y: Float) -> Float {
|
|||
/// The minmax function.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -1916,8 +1958,7 @@ pub fn minmax(x: Float, y: Float) -> #(Float, Float) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The sign function which returns the sign of the input, indicating
|
||||
/// whether it is positive, negative, or zero.
|
||||
/// The sign function which returns the sign of the input, indicating whether it is positive, negative, or zero.
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -1953,7 +1994,7 @@ if javascript {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function returns $$x$$ such that it has the same sign as $$y$$.
|
||||
/// The function takes two arguments $$x$$ and $$y$$ and returns $$x$$ such that it has the same sign as $$y$$.
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -1962,18 +2003,14 @@ if javascript {
|
|||
/// </div>
|
||||
///
|
||||
pub fn copy_sign(x: Float, y: Float) -> Float {
|
||||
// let signx: Float = sign(x)
|
||||
// let signy: Float = sign(y)
|
||||
// case signx == signy {
|
||||
// True -> y
|
||||
// False -> {
|
||||
// case signx >. signy {
|
||||
// True ->
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
todo
|
||||
case sign(x) == sign(y) {
|
||||
// x and y have the same sign, just return x
|
||||
True -> x
|
||||
// x and y have different signs:
|
||||
// - x is positive and y is negative, then flip sign of x
|
||||
// - x is negative and y is positive, then flip sign of x
|
||||
False -> flip_sign(x)
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
|
@ -1982,6 +2019,7 @@ pub fn copy_sign(x: Float, y: Float) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function flips the sign of a given input value.
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
|
@ -2212,7 +2250,7 @@ pub fn tau() -> Float {
|
|||
/// Note: If the input value $$x$$ is too large an overflow error might occur.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -2250,7 +2288,7 @@ pub fn e() -> Float {
|
|||
/// value which is the the absolute difference of the inputs.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
|
@ -2291,10 +2329,10 @@ pub fn absolute_difference(a: Float, b: Float) -> Float {
|
|||
///
|
||||
/// `True` is returned if statement holds, otherwise `False` is returned.
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
/// <summary>Example</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/stats
|
||||
/// import gleam_community/maths/float as floatx
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// let val: Float = 99.
|
||||
|
@ -2303,7 +2341,7 @@ pub fn absolute_difference(a: Float, b: Float) -> Float {
|
|||
/// // if 'val' is within 1 percent of 'ref_val' +/- 0.1
|
||||
/// let rtol: Float = 0.01
|
||||
/// let atol: Float = 0.10
|
||||
/// stats.is_close(val, ref_val, rtol, atol)
|
||||
/// floatx.is_close(val, ref_val, rtol, atol)
|
||||
/// |> should.be_true()
|
||||
/// }
|
||||
/// </details>
|
||||
|
|
|
@ -40,12 +40,10 @@
|
|||
//// * [`maximum`](#maximum)
|
||||
//// * [`minimum`](#minimum)
|
||||
//// * [`extrema`](#extrema)
|
||||
//// * [`argmax`](#arg_maximum)
|
||||
//// * [`argmin`](#arg_minimum)
|
||||
//// * [`arg_maximum`](#arg_maximum)
|
||||
//// * [`arg_minimum`](#arg_minimum)
|
||||
//// * **Tests**
|
||||
//// * [`all_close`](#all_close)
|
||||
//// * **Misc. functions**
|
||||
//// * [`trim`](#trim)
|
||||
|
||||
import gleam/list
|
||||
import gleam/int
|
||||
|
@ -173,8 +171,7 @@ pub fn geometric_space(
|
|||
/// \sum_{i=1}^n x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and
|
||||
/// $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -222,8 +219,7 @@ pub fn sum(arr: List(Float)) -> Float {
|
|||
/// \prod_{i=1}^n x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and
|
||||
/// $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -271,8 +267,7 @@ pub fn product(arr: List(Float)) -> Float {
|
|||
/// \sum_{i=1}^n x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and
|
||||
/// $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -314,8 +309,7 @@ pub fn cumulative_sum(arr: List(Float)) -> List(Float) {
|
|||
/// \prod_{i=1}^n x_i
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and
|
||||
/// $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
|
@ -395,9 +389,9 @@ pub fn norm(xarr: List(Float), yarr: List(Float), p: Int) -> List(Float) {
|
|||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// [4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
/// |> float_list.maximum()
|
||||
/// |> should.equal(Ok(4.))
|
||||
/// |> should.equal(Ok(4.0))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -450,9 +444,9 @@ pub fn maximum(arr: List(Float)) -> Result(Float, String) {
|
|||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// [4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
/// |> float_list.minimum()
|
||||
/// |> should.equal(Ok(1.))
|
||||
/// |> should.equal(Ok(1.0))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -505,7 +499,7 @@ pub fn minimum(arr: List(Float)) -> Result(Float, String) {
|
|||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// [4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
/// |> float_list.arg_maximum()
|
||||
/// |> should.equal(Ok([0, 1]))
|
||||
/// }
|
||||
|
@ -565,7 +559,7 @@ pub fn arg_maximum(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// [4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
/// |> float_list.arg_minimum()
|
||||
/// |> should.equal(Ok([4]))
|
||||
/// }
|
||||
|
@ -577,7 +571,7 @@ pub fn arg_maximum(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn arg_mininmum(arr: List(Float)) -> Result(List(Int), String) {
|
||||
pub fn arg_minimum(arr: List(Float)) -> Result(List(Int), String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|
@ -625,9 +619,9 @@ pub fn arg_mininmum(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// [4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
/// |> float_list.extrema()
|
||||
/// |> should.equal(Ok(1.))
|
||||
/// |> should.equal(Ok(#(1.0, 4.0)))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -638,7 +632,30 @@ pub fn arg_mininmum(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// </div>
|
||||
///
|
||||
pub fn extrema(arr: List(Float)) -> Result(#(Float, Float), String) {
|
||||
todo
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
_ -> {
|
||||
assert Ok(val_max) = list.at(arr, 0)
|
||||
assert Ok(val_min) = list.at(arr, 0)
|
||||
arr
|
||||
|> list.fold(
|
||||
#(val_min, val_max),
|
||||
fn(acc: #(Float, Float), a: Float) {
|
||||
let first: Float = pair.first(acc)
|
||||
let second: Float = pair.second(acc)
|
||||
case a <. first, a >. second {
|
||||
True, True -> #(a, a)
|
||||
True, False -> #(a, second)
|
||||
False, True -> #(first, a)
|
||||
False, False -> #(first, second)
|
||||
}
|
||||
},
|
||||
)
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
//// .katex { font-size: 1.1em; }
|
||||
////</style>
|
||||
////
|
||||
//// A module containing several different kinds of mathematical functions
|
||||
//// applying to integer numbers.
|
||||
//// A module containing mathematical functions applying to integer (int) numbers.
|
||||
////
|
||||
//// ---
|
||||
////
|
||||
|
@ -77,13 +76,13 @@ import gleam_community/maths/float as floatx
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// math.minimum(2.0, 1.5)
|
||||
/// intx.minimum(2.0, 1.5)
|
||||
/// |> should.equal(1.5)
|
||||
///
|
||||
/// math.minimum(1.5, 2.0)
|
||||
/// intx.minimum(1.5, 2.0)
|
||||
/// |> should.equal(1.5)
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -113,13 +112,13 @@ pub fn minimum(x: Int, y: Int) -> Int {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// math.maximum(2.0, 1.5)
|
||||
/// intx.maximum(2.0, 1.5)
|
||||
/// |> should.equal(1.5)
|
||||
///
|
||||
/// math.maximum(1.5, 2.0)
|
||||
/// intx.maximum(1.5, 2.0)
|
||||
/// |> should.equal(1.5)
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -149,13 +148,13 @@ pub fn maximum(x: Int, y: Int) -> Int {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// math.minmax(2.0, 1.5)
|
||||
/// intx.minmax(2.0, 1.5)
|
||||
/// |> should.equal(#(1.5, 2.0))
|
||||
///
|
||||
/// math.minmax(1.5, 2.0)
|
||||
/// intx.minmax(1.5, 2.0)
|
||||
/// |> should.equal(#(1.5, 2.0))
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -204,7 +203,7 @@ if erlang {
|
|||
|
||||
if javascript {
|
||||
external fn do_sign(Int) -> Int =
|
||||
"../math.mjs" "sign"
|
||||
"../intx.mjs" "sign"
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
|
@ -224,6 +223,31 @@ pub fn flip_sign(x: Int) -> Int {
|
|||
-1 * x
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// The function takes two arguments $$x$$ and $$y$$ and returns $$x$$ such that it has the same sign as $$y$$.
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn copy_sign(x: Int, y: Int) -> Int {
|
||||
case sign(x) == sign(y) {
|
||||
// x and y have the same sign, just return x
|
||||
True -> x
|
||||
// x and y have different signs:
|
||||
// - x is positive and y is negative, then flip sign of x
|
||||
// - x is negative and y is positive, then flip sign of x
|
||||
False -> flip_sign(x)
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
|
@ -243,22 +267,22 @@ pub fn flip_sign(x: Int) -> Int {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// // Invalid input gives an error
|
||||
/// // Error on: n = -1 < 0
|
||||
/// math.combination(-1, 1)
|
||||
/// intx.combination(-1, 1)
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// math.combination(4, 0)
|
||||
/// intx.combination(4, 0)
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// math.combination(4, 4)
|
||||
/// intx.combination(4, 4)
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// math.combination(4, 2)
|
||||
/// intx.combination(4, 2)
|
||||
/// |> should.equal(Ok(6))
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -314,23 +338,23 @@ pub fn combination(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// // Invalid input gives an error
|
||||
/// math.factorial(-1)
|
||||
/// intx.factorial(-1)
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// math.factorial(0)
|
||||
/// intx.factorial(0)
|
||||
/// |> should.equal(Ok(1))
|
||||
/// math.factorial(1)
|
||||
/// intx.factorial(1)
|
||||
/// |> should.equal(Ok(1))
|
||||
/// math.factorial(2)
|
||||
/// intx.factorial(2)
|
||||
/// |> should.equal(Ok(2))
|
||||
/// math.factorial(3)
|
||||
/// intx.factorial(3)
|
||||
/// |> should.equal(Ok(6))
|
||||
/// math.factorial(4)
|
||||
/// intx.factorial(4)
|
||||
/// |> should.equal(Ok(24))
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -379,22 +403,22 @@ pub fn factorial(n) -> Result(Int, String) {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// // Invalid input gives an error
|
||||
/// // Error on: n = -1 < 0
|
||||
/// math.permutation(-1, 1)
|
||||
/// intx.permutation(-1, 1)
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// math.permutation(4, 0)
|
||||
/// intx.permutation(4, 0)
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// math.permutation(4, 4)
|
||||
/// intx.permutation(4, 4)
|
||||
/// |> should.equal(Ok(1))
|
||||
///
|
||||
/// math.permutation(4, 2)
|
||||
/// intx.permutation(4, 2)
|
||||
/// |> should.equal(Ok(12))
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -450,13 +474,13 @@ pub fn permutation(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
/// math.absolute_difference(-10.0, 10.0)
|
||||
/// intx.absolute_difference(-10.0, 10.0)
|
||||
/// |> should.equal(20.0)
|
||||
///
|
||||
/// math.absolute_difference(0.0, -2.0)
|
||||
/// intx.absolute_difference(0.0, -2.0)
|
||||
/// |> should.equal(2.0)
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -482,7 +506,7 @@ pub fn absolute_difference(a: Int, b: Int) -> Int {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/math
|
||||
/// import gleam_community/maths/int as intx
|
||||
///
|
||||
/// pub fn example() {
|
||||
///
|
||||
|
@ -498,7 +522,7 @@ pub fn absolute_difference(a: Int, b: Int) -> Int {
|
|||
pub fn is_power(x: Int, y: Int) -> Bool {
|
||||
assert Ok(value) =
|
||||
floatx.logarithm(int.to_float(x), option.Some(int.to_float(y)))
|
||||
assert Ok(truncated) = floatx.truncate(value, 0)
|
||||
assert Ok(truncated) = floatx.truncate(value, option.Some(0))
|
||||
let rem = value -. truncated
|
||||
rem == 0.0
|
||||
}
|
||||
|
|
|
@ -26,11 +26,18 @@
|
|||
////
|
||||
//// ---
|
||||
////
|
||||
//// * **Miscellaneous functions**
|
||||
//// * [`amax`](#amax)
|
||||
//// * [`amin`](#amin)
|
||||
//// * [`argmax`](#argmax)
|
||||
//// * [`argmin`](#argmin)
|
||||
//// * **Distances, sums and products**
|
||||
//// * [`sum`](#sum)
|
||||
//// * [`product`](#product)
|
||||
//// * [`norm`](#norm)
|
||||
//// * [`cumulative_sum`](#cumulative_sum)
|
||||
//// * [`cumulative_product`](#cumulative_product)
|
||||
//// * **Misc. mathematical functions**
|
||||
//// * [`maximum`](#maximum)
|
||||
//// * [`minimum`](#minimum)
|
||||
//// * [`extrema`](#extrema)
|
||||
//// * [`arg_maximum`](#arg_maximum)
|
||||
//// * [`arg_minimum`](#arg_minimum)
|
||||
|
||||
import gleam/list
|
||||
import gleam/int
|
||||
|
@ -50,17 +57,17 @@ import gleam_community/maths/int as intx
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/stats
|
||||
/// import gleam_community/maths/int_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// // An empty lists returns an error
|
||||
/// []
|
||||
/// |> stats.argmin()
|
||||
/// |> int_list.arg_minimum()
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// |> stats.argmin()
|
||||
/// [4, 4, 3, 2, 1]
|
||||
/// |> stats.arg_minimum()
|
||||
/// |> should.equal(Ok([4]))
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -71,7 +78,7 @@ import gleam_community/maths/int as intx
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn argmin(arr: List(Float)) -> Result(List(Int), String) {
|
||||
pub fn arg_minimum(arr: List(Int)) -> Result(List(Int), String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|
@ -79,11 +86,11 @@ pub fn argmin(arr: List(Float)) -> Result(List(Int), String) {
|
|||
_ -> {
|
||||
assert Ok(min) =
|
||||
arr
|
||||
|> amin()
|
||||
|> minimum()
|
||||
arr
|
||||
|> list.index_map(fn(index: Int, a: Float) -> Int {
|
||||
case a -. min {
|
||||
0. -> index
|
||||
|> list.index_map(fn(index: Int, a: Int) -> Int {
|
||||
case a - min {
|
||||
0 -> index
|
||||
_ -> -1
|
||||
}
|
||||
})
|
||||
|
@ -110,17 +117,17 @@ pub fn argmin(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/stats
|
||||
/// import gleam_community/maths/int_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// // An empty lists returns an error
|
||||
/// []
|
||||
/// |> stats.argmax()
|
||||
/// |> int_list.arg_maximum()
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// |> stats.argmax()
|
||||
/// [4, 4, 3, 2, 1]
|
||||
/// |> int_list.arg_maximum()
|
||||
/// |> should.equal(Ok([0, 1]))
|
||||
/// }
|
||||
/// </details>
|
||||
|
@ -131,7 +138,7 @@ pub fn argmin(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn argmax(arr: List(Float)) -> Result(List(Int), String) {
|
||||
pub fn arg_maximum(arr: List(Int)) -> Result(List(Int), String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|
@ -139,11 +146,11 @@ pub fn argmax(arr: List(Float)) -> Result(List(Int), String) {
|
|||
_ -> {
|
||||
assert Ok(max) =
|
||||
arr
|
||||
|> amax()
|
||||
|> maximum()
|
||||
arr
|
||||
|> list.index_map(fn(index: Int, a: Float) -> Int {
|
||||
case a -. max {
|
||||
0. -> index
|
||||
|> list.index_map(fn(index: Int, a: Int) -> Int {
|
||||
case a - max {
|
||||
0 -> index
|
||||
_ -> -1
|
||||
}
|
||||
})
|
||||
|
@ -170,18 +177,18 @@ pub fn argmax(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/stats
|
||||
/// import gleam_community/maths/int_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// // An empty lists returns an error
|
||||
/// []
|
||||
/// |> stats.amax()
|
||||
/// |> int_list.maximum()
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// |> stats.amax()
|
||||
/// |> should.equal(Ok(4.))
|
||||
/// [4, 4, 3, 2, 1]
|
||||
/// |> int_list.maximum()
|
||||
/// |> should.equal(Ok(4))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -191,7 +198,7 @@ pub fn argmax(arr: List(Float)) -> Result(List(Int), String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn amax(arr: List(Float)) -> Result(Float, String) {
|
||||
pub fn maximum(arr: List(Int)) -> Result(Int, String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|
@ -201,8 +208,8 @@ pub fn amax(arr: List(Float)) -> Result(Float, String) {
|
|||
arr
|
||||
|> list.fold(
|
||||
val0,
|
||||
fn(acc: Float, a: Float) {
|
||||
case a >. acc {
|
||||
fn(acc: Int, a: Int) {
|
||||
case a > acc {
|
||||
True -> a
|
||||
False -> acc
|
||||
}
|
||||
|
@ -225,18 +232,18 @@ pub fn amax(arr: List(Float)) -> Result(Float, String) {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/stats
|
||||
/// import gleam_community/maths/int_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// // An empty lists returns an error
|
||||
/// []
|
||||
/// |> stats.amin()
|
||||
/// |> int_list.minimum()
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// |> stats.amin()
|
||||
/// |> should.equal(Ok(1.))
|
||||
/// [4, 4, 3, 2, 1]
|
||||
/// |> int_list.minimum()
|
||||
/// |> should.equal(Ok(1))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -246,7 +253,7 @@ pub fn amax(arr: List(Float)) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn amin(arr: List(Float)) -> Result(Float, String) {
|
||||
pub fn minimum(arr: List(Int)) -> Result(Int, String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|
@ -256,8 +263,8 @@ pub fn amin(arr: List(Float)) -> Result(Float, String) {
|
|||
arr
|
||||
|> list.fold(
|
||||
val0,
|
||||
fn(acc: Float, a: Float) {
|
||||
case a <. acc {
|
||||
fn(acc: Int, a: Int) {
|
||||
case a < acc {
|
||||
True -> a
|
||||
False -> acc
|
||||
}
|
||||
|
@ -279,18 +286,18 @@ pub fn amin(arr: List(Float)) -> Result(Float, String) {
|
|||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/stats
|
||||
/// import gleam_community/maths/int_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// // An empty lists returns an error
|
||||
/// []
|
||||
/// |> stats.amin()
|
||||
/// |> int_list.extrema()
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Valid input returns a result
|
||||
/// [4., 4., 3., 2., 1.]
|
||||
/// |> stats.amin()
|
||||
/// |> should.equal(Ok(1.))
|
||||
/// [4, 4, 3, 2, 1]
|
||||
/// |> int_list.extrema()
|
||||
/// |> should.equal(Ok(#(1, 4)))
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
|
@ -300,6 +307,29 @@ pub fn amin(arr: List(Float)) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn extrema(arr: List(Float)) -> Result(#(Float, Float), String) {
|
||||
todo
|
||||
pub fn extrema(arr: List(Int)) -> Result(#(Int, Int), String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
_ -> {
|
||||
assert Ok(val_max) = list.at(arr, 0)
|
||||
assert Ok(val_min) = list.at(arr, 0)
|
||||
arr
|
||||
|> list.fold(
|
||||
#(val_min, val_max),
|
||||
fn(acc: #(Int, Int), a: Int) {
|
||||
let first: Int = pair.first(acc)
|
||||
let second: Int = pair.second(acc)
|
||||
case a < first, a > second {
|
||||
True, True -> #(a, a)
|
||||
True, False -> #(a, second)
|
||||
False, True -> #(first, a)
|
||||
False, False -> #(first, second)
|
||||
}
|
||||
},
|
||||
)
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,8 @@
|
|||
//// .katex { font-size: 1.1em; }
|
||||
////</style>
|
||||
////
|
||||
//// A module containing several different kinds of mathematical functions
|
||||
//// applying to lists of real numbers.
|
||||
//// A module containing general utility functions applying to lists.
|
||||
////
|
||||
//// Function naming has been adopted from <a href="https://en.wikipedia.org/wiki/C_mathematical_functions"> C mathematical function</a>.
|
||||
////
|
||||
//// ---
|
||||
////
|
||||
//// * **Miscellaneous functions**
|
||||
|
@ -39,24 +36,23 @@ import gleam/float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Trim a list to a certain size given min/max indices. The min/max indices
|
||||
/// are inclusive.
|
||||
/// Trim a list to a certain size given min/max indices. The min/max indices are inclusive.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_stats/stats
|
||||
/// import gleam_community/maths/list as listx
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// // An empty lists returns an error
|
||||
/// []
|
||||
/// |> stats.trim(0, 0)
|
||||
/// |> listx.trim(0, 0)
|
||||
/// |> should.be_error()
|
||||
///
|
||||
/// // Trim the list to only the middle part of list
|
||||
/// [1., 2., 3., 4., 5., 6.]
|
||||
/// |> stats.trim(1, 4)
|
||||
/// |> listx.trim(1, 4)
|
||||
/// |> should.equal(Ok([2., 3., 4., 5.]))
|
||||
/// }
|
||||
/// </details>
|
||||
|
|
410
temp.gleam
410
temp.gleam
|
@ -1,410 +0,0 @@
|
|||
//// Small examples ALSO used in the docs...
|
||||
|
||||
import gleam/int
|
||||
import gleam/list
|
||||
import gleam/pair
|
||||
import gleam_stats/stats
|
||||
import gleeunit
|
||||
import gleeunit/should
|
||||
|
||||
pub fn main() {
|
||||
gleeunit.main()
|
||||
}
|
||||
|
||||
pub fn example_sum_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.sum()
|
||||
|> should.equal(0.)
|
||||
|
||||
// Valid input returns a result
|
||||
[1., 2., 3.]
|
||||
|> stats.sum()
|
||||
|> should.equal(6.)
|
||||
}
|
||||
|
||||
pub fn example_mean_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.mean()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[1., 2., 3.]
|
||||
|> stats.mean()
|
||||
|> should.equal(Ok(2.))
|
||||
}
|
||||
|
||||
pub fn example_median_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.median()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[1., 2., 3.]
|
||||
|> stats.median()
|
||||
|> should.equal(Ok(2.))
|
||||
|
||||
[1., 2., 3., 4.]
|
||||
|> stats.median()
|
||||
|> should.equal(Ok(2.5))
|
||||
}
|
||||
|
||||
pub fn example_hmean_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.hmean()
|
||||
|> should.be_error()
|
||||
|
||||
// List with negative numbers returns an error
|
||||
[-1., -3., -6.]
|
||||
|> stats.hmean()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[1., 3., 6.]
|
||||
|> stats.hmean()
|
||||
|> should.equal(Ok(2.))
|
||||
}
|
||||
|
||||
pub fn example_gmean_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.gmean()
|
||||
|> should.be_error()
|
||||
// List with negative numbers returns an error
|
||||
[-1., -3., -6.]
|
||||
|> stats.gmean()
|
||||
|> should.be_error()
|
||||
// Valid input returns a result
|
||||
[1., 3., 9.]
|
||||
|> stats.gmean()
|
||||
|> should.equal(Ok(3.))
|
||||
}
|
||||
|
||||
pub fn example_var_test() {
|
||||
// Degrees of freedom
|
||||
let ddof: Int = 1
|
||||
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.var(ddof)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[1., 2., 3.]
|
||||
|> stats.var(ddof)
|
||||
|> should.equal(Ok(1.))
|
||||
}
|
||||
|
||||
pub fn example_std_test() {
|
||||
// Degrees of freedom
|
||||
let ddof: Int = 1
|
||||
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.std(ddof)
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[1., 2., 3.]
|
||||
|> stats.std(ddof)
|
||||
|> should.equal(Ok(1.))
|
||||
}
|
||||
|
||||
pub fn example_moment_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.moment(0)
|
||||
|> should.be_error()
|
||||
|
||||
// 0th moment about the mean is 1. per definition
|
||||
[0., 1., 2., 3., 4.]
|
||||
|> stats.moment(0)
|
||||
|> should.equal(Ok(1.))
|
||||
|
||||
// 1st moment about the mean is 0. per definition
|
||||
[0., 1., 2., 3., 4.]
|
||||
|> stats.moment(1)
|
||||
|> should.equal(Ok(0.))
|
||||
|
||||
// 2nd moment about the mean
|
||||
[0., 1., 2., 3., 4.]
|
||||
|> stats.moment(2)
|
||||
|> should.equal(Ok(2.))
|
||||
}
|
||||
|
||||
pub fn example_skewness_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.skewness()
|
||||
|> should.be_error()
|
||||
|
||||
// No skewness
|
||||
// -> Zero skewness
|
||||
[1., 2., 3., 4.]
|
||||
|> stats.skewness()
|
||||
|> should.equal(Ok(0.))
|
||||
|
||||
// Right-skewed distribution
|
||||
// -> Positive skewness
|
||||
[1., 1., 1., 2.]
|
||||
|> stats.skewness()
|
||||
|> fn(x: Result(Float, String)) -> Bool {
|
||||
case x {
|
||||
Ok(x) -> x >. 0.
|
||||
_ -> False
|
||||
}
|
||||
}
|
||||
|> should.be_true()
|
||||
}
|
||||
|
||||
pub fn example_kurtosis_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.skewness()
|
||||
|> should.be_error()
|
||||
|
||||
// No tail
|
||||
// -> Fisher's definition gives kurtosis -3
|
||||
[1., 1., 1., 1.]
|
||||
|> stats.kurtosis()
|
||||
|> should.equal(Ok(-3.))
|
||||
|
||||
// Distribution with a tail
|
||||
// -> Higher kurtosis
|
||||
[1., 1., 1., 2.]
|
||||
|> stats.kurtosis()
|
||||
|> fn(x: Result(Float, String)) -> Bool {
|
||||
case x {
|
||||
Ok(x) -> x >. -3.
|
||||
_ -> False
|
||||
}
|
||||
}
|
||||
|> should.be_true()
|
||||
}
|
||||
|
||||
pub fn example_zscore_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
// Use degrees of freedom = 1
|
||||
|> stats.zscore(1)
|
||||
|> should.be_error()
|
||||
|
||||
[1., 2., 3.]
|
||||
// Use degrees of freedom = 1
|
||||
|> stats.zscore(1)
|
||||
|> should.equal(Ok([-1., 0., 1.]))
|
||||
}
|
||||
|
||||
pub fn example_percentile_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.percentile(40)
|
||||
|> should.be_error()
|
||||
|
||||
// Calculate 40th percentile
|
||||
[15., 20., 35., 40., 50.]
|
||||
|> stats.percentile(40)
|
||||
|> should.equal(Ok(29.))
|
||||
}
|
||||
|
||||
pub fn example_iqr_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.iqr()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[1., 2., 3., 4., 5.]
|
||||
|> stats.iqr()
|
||||
|> should.equal(Ok(3.))
|
||||
}
|
||||
|
||||
pub fn example_freedman_diaconis_rule_test() {
|
||||
// An empty list returns an error
|
||||
[]
|
||||
|> stats.freedman_diaconis_rule()
|
||||
|> should.be_error()
|
||||
|
||||
// Calculate histogram bin widths
|
||||
list.range(0, 1000)
|
||||
|> list.map(fn(x: Int) -> Float { int.to_float(x) })
|
||||
|> stats.freedman_diaconis_rule()
|
||||
|> should.equal(Ok(10.))
|
||||
}
|
||||
|
||||
pub fn example_range_test() {
|
||||
// Create a range
|
||||
let range = stats.Range(0., 1.)
|
||||
// Retrieve min and max values
|
||||
let stats.Range(min, max) = range
|
||||
min
|
||||
|> should.equal(0.)
|
||||
max
|
||||
|> should.equal(1.)
|
||||
}
|
||||
|
||||
pub fn example_bin_test() {
|
||||
// Create a bin
|
||||
let bin: stats.Bin = #(stats.Range(0., 1.), 999)
|
||||
// Retrieve min and max values
|
||||
let stats.Range(min, max) = pair.first(bin)
|
||||
min
|
||||
|> should.equal(0.)
|
||||
max
|
||||
|> should.equal(1.)
|
||||
// Retrieve count
|
||||
let count = pair.second(bin)
|
||||
count
|
||||
|> should.equal(999)
|
||||
}
|
||||
|
||||
pub fn example_histogram_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> stats.histogram(1.)
|
||||
|> should.be_error()
|
||||
// Create the bins of a histogram given a list of values
|
||||
list.range(0, 100)
|
||||
|> list.map(fn(x: Int) -> Float { int.to_float(x) })
|
||||
// Below 25. is the bin width
|
||||
// The Freedman-Diaconis’s Rule can be used to determine a decent value
|
||||
|> stats.histogram(25.)
|
||||
|> should.equal(Ok([
|
||||
#(stats.Range(0., 25.), 25),
|
||||
#(stats.Range(25., 50.), 25),
|
||||
#(stats.Range(50., 75.), 25),
|
||||
#(stats.Range(75., 100.), 25),
|
||||
]))
|
||||
}
|
||||
|
||||
pub fn example_correlation_test() {
|
||||
// An empty lists returns an error
|
||||
stats.correlation([], [])
|
||||
|> should.be_error()
|
||||
|
||||
// Lists with fewer than 2 elements return an error
|
||||
stats.correlation([1.0], [1.0])
|
||||
|> should.be_error()
|
||||
|
||||
// Lists of uneqal length return an error
|
||||
stats.correlation([1.0, 2.0, 3.0], [1.0, 2.0])
|
||||
|> should.be_error()
|
||||
|
||||
// Perfect positive correlation
|
||||
let xarr0: List(Float) =
|
||||
list.range(0, 100)
|
||||
|> list.map(fn(x: Int) -> Float { int.to_float(x) })
|
||||
let yarr0: List(Float) =
|
||||
list.range(0, 100)
|
||||
|> list.map(fn(x: Int) -> Float { int.to_float(x) })
|
||||
stats.correlation(xarr0, yarr0)
|
||||
|> should.equal(Ok(1.))
|
||||
|
||||
// Perfect negative correlation
|
||||
let xarr0: List(Float) =
|
||||
list.range(0, 100)
|
||||
|> list.map(fn(x: Int) -> Float { -1. *. int.to_float(x) })
|
||||
let yarr0: List(Float) =
|
||||
list.range(0, 100)
|
||||
|> list.map(fn(x: Int) -> Float { int.to_float(x) })
|
||||
stats.correlation(xarr0, yarr0)
|
||||
|> should.equal(Ok(-1.))
|
||||
}
|
||||
|
||||
pub fn example_trim_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> stats.trim(0, 0)
|
||||
|> should.be_error()
|
||||
|
||||
// Trim the list to only the middle part of list
|
||||
[1., 2., 3., 4., 5., 6.]
|
||||
|> stats.trim(1, 4)
|
||||
|> should.equal(Ok([2., 3., 4., 5.]))
|
||||
}
|
||||
|
||||
pub fn example_isclose_test() {
|
||||
let val: Float = 99.
|
||||
let ref_val: Float = 100.
|
||||
// We set 'atol' and 'rtol' such that the values are equivalent
|
||||
// if 'val' is within 1 percent of 'ref_val' +/- 0.1
|
||||
let rtol: Float = 0.01
|
||||
let atol: Float = 0.10
|
||||
stats.isclose(val, ref_val, rtol, atol)
|
||||
|> should.be_true()
|
||||
}
|
||||
|
||||
pub fn example_allclose_test() {
|
||||
let val: Float = 99.
|
||||
let ref_val: Float = 100.
|
||||
let xarr: List(Float) = list.repeat(val, 42)
|
||||
let yarr: List(Float) = list.repeat(ref_val, 42)
|
||||
// We set 'atol' and 'rtol' such that the values are equivalent
|
||||
// if 'val' is within 1 percent of 'ref_val' +/- 0.1
|
||||
let rtol: Float = 0.01
|
||||
let atol: Float = 0.10
|
||||
stats.allclose(xarr, yarr, rtol, atol)
|
||||
|> fn(zarr: Result(List(Bool), String)) -> Result(Bool, Nil) {
|
||||
case zarr {
|
||||
Ok(arr) ->
|
||||
arr
|
||||
|> list.all(fn(a: Bool) -> Bool { a })
|
||||
|> Ok
|
||||
_ ->
|
||||
Nil
|
||||
|> Error
|
||||
}
|
||||
}
|
||||
|> should.equal(Ok(True))
|
||||
}
|
||||
|
||||
pub fn example_amax_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> stats.amax()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4., 4., 3., 2., 1.]
|
||||
|> stats.amax()
|
||||
|> should.equal(Ok(4.))
|
||||
}
|
||||
|
||||
pub fn example_amin_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> stats.amin()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4., 4., 3., 2., 1.]
|
||||
|> stats.amin()
|
||||
|> should.equal(Ok(1.))
|
||||
}
|
||||
|
||||
pub fn example_argmax_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> stats.argmax()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4., 4., 3., 2., 1.]
|
||||
|> stats.argmax()
|
||||
|> should.equal(Ok([0, 1]))
|
||||
}
|
||||
|
||||
pub fn example_argmin_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> stats.argmin()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4., 4., 3., 2., 1.]
|
||||
|> stats.argmin()
|
||||
|> should.equal(Ok([4]))
|
||||
}
|
94
test/gleam/gleam_community_maths_float_list_test.gleam
Normal file
94
test/gleam/gleam_community_maths_float_list_test.gleam
Normal file
|
@ -0,0 +1,94 @@
|
|||
import gleam/int
|
||||
import gleam/list
|
||||
import gleam/pair
|
||||
import gleam_community/maths/float_list
|
||||
import gleeunit
|
||||
import gleeunit/should
|
||||
|
||||
pub fn main() {
|
||||
gleeunit.main()
|
||||
}
|
||||
|
||||
pub fn float_list_all_close_test() {
|
||||
let val: Float = 99.0
|
||||
let ref_val: Float = 100.0
|
||||
let xarr: List(Float) = list.repeat(val, 42)
|
||||
let yarr: List(Float) = list.repeat(ref_val, 42)
|
||||
// We set 'atol' and 'rtol' such that the values are equivalent
|
||||
// if 'val' is within 1 percent of 'ref_val' +/- 0.1
|
||||
let rtol: Float = 0.01
|
||||
let atol: Float = 0.10
|
||||
float_list.all_close(xarr, yarr, rtol, atol)
|
||||
|> fn(zarr: Result(List(Bool), String)) -> Result(Bool, Nil) {
|
||||
case zarr {
|
||||
Ok(arr) ->
|
||||
arr
|
||||
|> list.all(fn(a: Bool) -> Bool { a })
|
||||
|> Ok
|
||||
_ ->
|
||||
Nil
|
||||
|> Error
|
||||
}
|
||||
}
|
||||
|> should.equal(Ok(True))
|
||||
}
|
||||
|
||||
pub fn float_list_maximum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> float_list.maximum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
|> float_list.maximum()
|
||||
|> should.equal(Ok(4.0))
|
||||
}
|
||||
|
||||
pub fn float_list_minimum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> float_list.minimum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
|> float_list.minimum()
|
||||
|> should.equal(Ok(1.0))
|
||||
}
|
||||
|
||||
pub fn float_list_arg_maximum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> float_list.arg_maximum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
|> float_list.arg_maximum()
|
||||
|> should.equal(Ok([0, 1]))
|
||||
}
|
||||
|
||||
pub fn float_list_arg_minimum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> float_list.arg_minimum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
|> float_list.arg_minimum()
|
||||
|> should.equal(Ok([4]))
|
||||
}
|
||||
|
||||
pub fn float_list_extrema_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> float_list.extrema()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4.0, 4.0, 3.0, 2.0, 1.0]
|
||||
|> float_list.extrema()
|
||||
|> should.equal(Ok(#(1.0, 4.0)))
|
||||
}
|
|
@ -513,65 +513,95 @@ pub fn float_to_radian_test() {
|
|||
}
|
||||
|
||||
pub fn float_ceiling_test() {
|
||||
// Round based on 3. digit AFTER decimal point
|
||||
// Round 3. digit AFTER decimal point
|
||||
floatx.ceiling(12.0654, option.Some(3))
|
||||
|> should.equal(Ok(12.066))
|
||||
|
||||
// Round based on 2. digit AFTER decimal point
|
||||
// Round 2. digit AFTER decimal point
|
||||
floatx.ceiling(12.0654, option.Some(2))
|
||||
|> should.equal(Ok(12.07))
|
||||
|
||||
// Round based on 1. digit AFTER decimal point
|
||||
// Round 1. digit AFTER decimal point
|
||||
floatx.ceiling(12.0654, option.Some(1))
|
||||
|> should.equal(Ok(12.1))
|
||||
|
||||
// Round based on 0. digit BEFORE decimal point
|
||||
// Round 0. digit BEFORE decimal point
|
||||
floatx.ceiling(12.0654, option.Some(0))
|
||||
|> should.equal(Ok(13.0))
|
||||
|
||||
// Round based on 1. digit BEFORE decimal point
|
||||
// Round 1. digit BEFORE decimal point
|
||||
floatx.ceiling(12.0654, option.Some(-1))
|
||||
|> should.equal(Ok(20.0))
|
||||
|
||||
// Round based on 2. digit BEFORE decimal point
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.ceiling(12.0654, option.Some(-2))
|
||||
|> should.equal(Ok(100.0))
|
||||
|
||||
// Round based on 3. digit BEFORE decimal point
|
||||
// Round 3. digit BEFORE decimal point
|
||||
floatx.ceiling(12.0654, option.Some(-3))
|
||||
|> should.equal(Ok(1000.0))
|
||||
}
|
||||
|
||||
pub fn float_floor_test() {
|
||||
// Round based on 3. digit AFTER decimal point
|
||||
// Round 3. digit AFTER decimal point
|
||||
floatx.floor(12.0654, option.Some(3))
|
||||
|> should.equal(Ok(12.065))
|
||||
|
||||
// Round based on 2. digit AFTER decimal point
|
||||
// Round 2. digit AFTER decimal point
|
||||
floatx.floor(12.0654, option.Some(2))
|
||||
|> should.equal(Ok(12.06))
|
||||
|
||||
// Round based on 1. digit AFTER decimal point
|
||||
// Round 1. digit AFTER decimal point
|
||||
floatx.floor(12.0654, option.Some(1))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Round based on 0. digit BEFORE decimal point
|
||||
// Round 0. digit BEFORE decimal point
|
||||
floatx.floor(12.0654, option.Some(0))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Round based on 1. digit BEFORE decimal point
|
||||
// Round 1. digit BEFORE decimal point
|
||||
floatx.floor(12.0654, option.Some(-1))
|
||||
|> should.equal(Ok(10.0))
|
||||
|
||||
// Round based on 2. digit BEFORE decimal point
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.floor(12.0654, option.Some(-2))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
// Round based on 2. digit BEFORE decimal point
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.floor(12.0654, option.Some(-3))
|
||||
|> should.equal(Ok(0.0))
|
||||
}
|
||||
|
||||
pub fn float_truncate_test() {
|
||||
// Round 3. digit AFTER decimal point
|
||||
floatx.truncate(12.0654, option.Some(3))
|
||||
|> should.equal(Ok(12.065))
|
||||
|
||||
// Round 2. digit AFTER decimal point
|
||||
floatx.truncate(12.0654, option.Some(2))
|
||||
|> should.equal(Ok(12.06))
|
||||
|
||||
// Round 1. digit AFTER decimal point
|
||||
floatx.truncate(12.0654, option.Some(1))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Round 0. digit BEFORE decimal point
|
||||
floatx.truncate(12.0654, option.Some(0))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Round 1. digit BEFORE decimal point
|
||||
floatx.truncate(12.0654, option.Some(-1))
|
||||
|> should.equal(Ok(10.0))
|
||||
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.truncate(12.0654, option.Some(-2))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.truncate(12.0654, option.Some(-3))
|
||||
|> should.equal(Ok(0.0))
|
||||
}
|
||||
|
||||
pub fn float_minimum_test() {
|
||||
floatx.minimum(0.75, 0.5)
|
||||
|> should.equal(0.5)
|
||||
|
@ -636,6 +666,20 @@ pub fn float_flip_sign_test() {
|
|||
|> should.equal(100.0)
|
||||
}
|
||||
|
||||
pub fn float_copy_sign_test() {
|
||||
floatx.copy_sign(100.0, 10.0)
|
||||
|> should.equal(100.0)
|
||||
|
||||
floatx.copy_sign(-100.0, 10.0)
|
||||
|> should.equal(100.0)
|
||||
|
||||
floatx.copy_sign(100.0, -10.0)
|
||||
|> should.equal(-100.0)
|
||||
|
||||
floatx.copy_sign(-100.0, -10.0)
|
||||
|> should.equal(-100.0)
|
||||
}
|
||||
|
||||
pub fn float_beta_function_test() {
|
||||
io.debug("TODO: Implement tests for 'float.beta'.")
|
||||
}
|
||||
|
@ -649,6 +693,7 @@ pub fn float_gamma_function_test() {
|
|||
}
|
||||
|
||||
pub fn math_round_to_nearest_test() {
|
||||
// Try with positive values
|
||||
floatx.round(1.50, option.Some(0), option.Some("Nearest"))
|
||||
|> should.equal(Ok(2.0))
|
||||
|
||||
|
@ -664,14 +709,45 @@ pub fn math_round_to_nearest_test() {
|
|||
floatx.round(4.50, option.Some(0), option.Some("Nearest"))
|
||||
|> should.equal(Ok(4.0))
|
||||
|
||||
// Try with negative values
|
||||
floatx.round(-3.50, option.Some(0), option.Some("Nearest"))
|
||||
|> should.equal(Ok(-4.0))
|
||||
|
||||
floatx.round(-4.50, option.Some(0), option.Some("Nearest"))
|
||||
|> should.equal(Ok(-4.0))
|
||||
|
||||
// Round 3. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(3), option.Some("Nearest"))
|
||||
|> should.equal(Ok(12.065))
|
||||
|
||||
// Round 2. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(2), option.Some("Nearest"))
|
||||
|> should.equal(Ok(12.07))
|
||||
|
||||
// Round 1. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(1), option.Some("Nearest"))
|
||||
|> should.equal(Ok(12.1))
|
||||
|
||||
// Round 0. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(0), option.Some("Nearest"))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Round 1. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-1), option.Some("Nearest"))
|
||||
|> should.equal(Ok(10.0))
|
||||
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-2), option.Some("Nearest"))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
// Round 3. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-3), option.Some("Nearest"))
|
||||
|> should.equal(Ok(0.0))
|
||||
}
|
||||
|
||||
pub fn math_round_up_test() {
|
||||
// Note: Rounding mode "Up" is an alias for the ceiling function
|
||||
// Try with positive values
|
||||
floatx.round(0.45, option.Some(0), option.Some("Up"))
|
||||
|> should.equal(Ok(1.0))
|
||||
|
||||
|
@ -689,9 +765,29 @@ pub fn math_round_up_test() {
|
|||
|
||||
floatx.round(0.505, option.Some(2), option.Some("Up"))
|
||||
|> should.equal(Ok(0.51))
|
||||
|
||||
// Try with negative values
|
||||
floatx.round(-0.45, option.Some(0), option.Some("Up"))
|
||||
|> should.equal(Ok(-0.0))
|
||||
|
||||
floatx.round(-0.50, option.Some(0), option.Some("Up"))
|
||||
|> should.equal(Ok(-0.0))
|
||||
|
||||
floatx.round(-0.45, option.Some(1), option.Some("Up"))
|
||||
|> should.equal(Ok(-0.4))
|
||||
|
||||
floatx.round(-0.50, option.Some(1), option.Some("Up"))
|
||||
|> should.equal(Ok(-0.5))
|
||||
|
||||
floatx.round(-0.4550, option.Some(2), option.Some("Up"))
|
||||
|> should.equal(Ok(-0.45))
|
||||
|
||||
floatx.round(-0.5050, option.Some(2), option.Some("Up"))
|
||||
|> should.equal(Ok(-0.5))
|
||||
}
|
||||
|
||||
pub fn math_round_down_test() {
|
||||
// Note: Rounding mode "Down" is an alias for the floor function
|
||||
// Try with positive values
|
||||
floatx.round(0.45, option.Some(0), option.Some("Down"))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
@ -732,6 +828,8 @@ pub fn math_round_down_test() {
|
|||
}
|
||||
|
||||
pub fn math_round_to_zero_test() {
|
||||
// Note: Rounding mode "ToZero" is an alias for the truncate function
|
||||
// Try with positive values
|
||||
floatx.round(0.50, option.Some(0), option.Some("ToZero"))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
|
@ -749,9 +847,39 @@ pub fn math_round_to_zero_test() {
|
|||
|
||||
floatx.round(0.5075, option.Some(2), option.Some("ToZero"))
|
||||
|> should.equal(Ok(0.50))
|
||||
|
||||
// Try with negative values
|
||||
floatx.round(-0.50, option.Some(0), option.Some("ToZero"))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
floatx.round(-0.75, option.Some(0), option.Some("ToZero"))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
floatx.round(-0.45, option.Some(1), option.Some("ToZero"))
|
||||
|> should.equal(Ok(-0.4))
|
||||
|
||||
floatx.round(-0.57, option.Some(1), option.Some("ToZero"))
|
||||
|> should.equal(Ok(-0.50))
|
||||
|
||||
floatx.round(-0.4575, option.Some(2), option.Some("ToZero"))
|
||||
|> should.equal(Ok(-0.45))
|
||||
|
||||
floatx.round(-0.5075, option.Some(2), option.Some("ToZero"))
|
||||
|> should.equal(Ok(-0.50))
|
||||
}
|
||||
|
||||
pub fn math_round_ties_away_test() {
|
||||
// Try with positive values
|
||||
floatx.round(1.40, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(1.0))
|
||||
|
||||
floatx.round(1.50, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(2.0))
|
||||
|
||||
floatx.round(2.50, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(3.0))
|
||||
|
||||
// Try with negative values
|
||||
floatx.round(-1.40, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(-1.0))
|
||||
|
||||
|
@ -764,17 +892,47 @@ pub fn math_round_ties_away_test() {
|
|||
floatx.round(-2.50, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(-3.0))
|
||||
|
||||
floatx.round(1.40, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(1.0))
|
||||
// Round 3. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(3), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(12.065))
|
||||
|
||||
floatx.round(1.50, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(2.0))
|
||||
// Round 2. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(2), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(12.07))
|
||||
|
||||
floatx.round(2.50, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(3.0))
|
||||
// Round 1. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(1), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(12.1))
|
||||
|
||||
// Round 0. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(0), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Round 1. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-1), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(10.0))
|
||||
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-2), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-3), option.Some("TiesAway"))
|
||||
|> should.equal(Ok(0.0))
|
||||
}
|
||||
|
||||
pub fn math_round_ties_up_test() {
|
||||
// Try with positive values
|
||||
floatx.round(1.40, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(1.0))
|
||||
|
||||
floatx.round(1.50, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(2.0))
|
||||
|
||||
floatx.round(2.50, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(3.0))
|
||||
|
||||
// Try with negative values
|
||||
floatx.round(-1.40, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(-1.0))
|
||||
|
||||
|
@ -787,14 +945,56 @@ pub fn math_round_ties_up_test() {
|
|||
floatx.round(-2.50, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(-2.0))
|
||||
|
||||
floatx.round(1.40, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(1.0))
|
||||
// Round 3. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(3), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(12.065))
|
||||
|
||||
floatx.round(1.50, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(2.0))
|
||||
// Round 2. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(2), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(12.07))
|
||||
|
||||
floatx.round(2.50, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(3.0))
|
||||
// Round 1. digit AFTER decimal point
|
||||
floatx.round(12.0654, option.Some(1), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(12.1))
|
||||
|
||||
// Round 0. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(0), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Round 1. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-1), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(10.0))
|
||||
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-2), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
// Round 2. digit BEFORE decimal point
|
||||
floatx.round(12.0654, option.Some(-3), option.Some("TiesUp"))
|
||||
|> should.equal(Ok(0.0))
|
||||
}
|
||||
|
||||
pub fn math_round_error_test() {
|
||||
// Test invalid rounding mode
|
||||
floatx.round(-1.50, option.Some(0), option.Some("XYZ"))
|
||||
|> should.be_error()
|
||||
}
|
||||
|
||||
pub fn math_round_edge_cases_test() {
|
||||
// The default number of digits is 0 if None is provided
|
||||
floatx.round(12.0654, option.None, option.Some("Nearest"))
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// The default rounding mode is "Nearest" if None is provided
|
||||
floatx.round(12.0654, option.None, option.None)
|
||||
|> should.equal(Ok(12.0))
|
||||
|
||||
// Test invalid rounding mode
|
||||
floatx.round(12.0654, option.None, option.Some("XYZ"))
|
||||
|> should.be_error()
|
||||
|
||||
floatx.round(-1.50, option.Some(0), option.Some("XYZ"))
|
||||
|> should.be_error()
|
||||
}
|
||||
|
||||
pub fn float_incomplete_gamma_function_test() {
|
||||
|
@ -865,3 +1065,14 @@ pub fn float_constants_test() {
|
|||
|> floatx.is_close(3.14159, 0.0, 0.00001)
|
||||
|> should.be_true()
|
||||
}
|
||||
|
||||
pub fn float_is_close_test() {
|
||||
let val: Float = 99.0
|
||||
let ref_val: Float = 100.0
|
||||
// We set 'atol' and 'rtol' such that the values are equivalent
|
||||
// if 'val' is within 1 percent of 'ref_val' +/- 0.1
|
||||
let rtol: Float = 0.01
|
||||
let atol: Float = 0.10
|
||||
floatx.is_close(val, ref_val, rtol, atol)
|
||||
|> should.be_true()
|
||||
}
|
||||
|
|
70
test/gleam/gleam_community_maths_int_list_test.gleam
Normal file
70
test/gleam/gleam_community_maths_int_list_test.gleam
Normal file
|
@ -0,0 +1,70 @@
|
|||
import gleam/int
|
||||
import gleam/list
|
||||
import gleam/pair
|
||||
import gleam_community/maths/int_list
|
||||
import gleeunit
|
||||
import gleeunit/should
|
||||
|
||||
pub fn main() {
|
||||
gleeunit.main()
|
||||
}
|
||||
|
||||
pub fn int_list_maximum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> int_list.maximum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4, 4, 3, 2, 1]
|
||||
|> int_list.maximum()
|
||||
|> should.equal(Ok(4))
|
||||
}
|
||||
|
||||
pub fn int_list_minimum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> int_list.minimum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4, 4, 3, 2, 1]
|
||||
|> int_list.minimum()
|
||||
|> should.equal(Ok(1))
|
||||
}
|
||||
|
||||
pub fn int_list_arg_maximum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> int_list.arg_maximum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4, 4, 3, 2, 1]
|
||||
|> int_list.arg_maximum()
|
||||
|> should.equal(Ok([0, 1]))
|
||||
}
|
||||
|
||||
pub fn int_list_arg_minimum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> int_list.arg_minimum()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4, 4, 3, 2, 1]
|
||||
|> int_list.arg_minimum()
|
||||
|> should.equal(Ok([4]))
|
||||
}
|
||||
|
||||
pub fn int_list_extrema_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|> int_list.extrema()
|
||||
|> should.be_error()
|
||||
|
||||
// Valid input returns a result
|
||||
[4, 4, 3, 2, 1]
|
||||
|> int_list.extrema()
|
||||
|> should.equal(Ok(#(1, 4)))
|
||||
}
|
|
@ -156,6 +156,20 @@ pub fn int_flip_sign_test() {
|
|||
|> should.equal(100)
|
||||
}
|
||||
|
||||
pub fn int_copy_sign_test() {
|
||||
intx.copy_sign(100, 10)
|
||||
|> should.equal(100)
|
||||
|
||||
intx.copy_sign(-100, 10)
|
||||
|> should.equal(100)
|
||||
|
||||
intx.copy_sign(100, -10)
|
||||
|> should.equal(-100)
|
||||
|
||||
intx.copy_sign(-100, -10)
|
||||
|> should.equal(-100)
|
||||
}
|
||||
|
||||
pub fn int_is_power_test() {
|
||||
intx.is_power(10, 10)
|
||||
|> should.equal(True)
|
||||
|
|
Loading…
Reference in a new issue