mirror of
https://github.com/sigmasternchen/gleam-community-maths
synced 2025-03-15 07:59:01 +00:00
Merge pull request #28 from gleam-community/refactor/nil-errors
♻️ Replace `String` errors with `Nil`
This commit is contained in:
commit
77e13b9254
9 changed files with 178 additions and 353 deletions
|
@ -442,7 +442,7 @@ pub fn int_sum(arr: List(Int)) -> Int {
|
|||
pub fn float_product(
|
||||
arr: List(Float),
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
case arr, weights {
|
||||
[], _ ->
|
||||
1.0
|
||||
|
@ -452,22 +452,16 @@ pub fn float_product(
|
|||
|> list.fold(1.0, fn(acc, a) { a *. acc })
|
||||
|> Ok
|
||||
_, option.Some(warr) -> {
|
||||
let results =
|
||||
list.zip(arr, warr)
|
||||
|> list.map(fn(a) {
|
||||
pair.first(a)
|
||||
|> elementary.power(pair.second(a))
|
||||
})
|
||||
|> result.all
|
||||
case results {
|
||||
Ok(prods) ->
|
||||
prods
|
||||
|> list.fold(1.0, fn(acc, a) { a *. acc })
|
||||
|> Ok
|
||||
Error(msg) ->
|
||||
msg
|
||||
|> Error
|
||||
}
|
||||
list.zip(arr, warr)
|
||||
|> list.map(fn(a: #(Float, Float)) -> Result(Float, Nil) {
|
||||
pair.first(a)
|
||||
|> elementary.power(pair.second(a))
|
||||
})
|
||||
|> result.all
|
||||
|> result.map(fn(prods) {
|
||||
prods
|
||||
|> list.fold(1.0, fn(acc: Float, a: Float) -> Float { a *. acc })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,12 +130,10 @@ pub fn combination(
|
|||
n: Int,
|
||||
k: Int,
|
||||
mode: option.Option(CombinatoricsMode),
|
||||
) -> Result(Int, String) {
|
||||
) -> Result(Int, Nil) {
|
||||
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
|
||||
_, _ if n < 0 -> Error(Nil)
|
||||
_, _ if k < 0 -> Error(Nil)
|
||||
_, _ -> {
|
||||
case mode {
|
||||
option.Some(WithRepetitions) -> combination_with_repetitions(n, k)
|
||||
|
@ -145,12 +143,11 @@ pub fn combination(
|
|||
}
|
||||
}
|
||||
|
||||
fn combination_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||
{ n + k - 1 }
|
||||
|> combination_without_repetitions(k)
|
||||
fn combination_with_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||
combination_without_repetitions(n + k - 1, k)
|
||||
}
|
||||
|
||||
fn combination_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||
fn combination_without_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||
case n, k {
|
||||
_, _ if k == 0 || k == n -> {
|
||||
1 |> Ok
|
||||
|
@ -202,17 +199,11 @@ fn combination_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn factorial(n) -> Result(Int, String) {
|
||||
pub fn factorial(n) -> Result(Int, Nil) {
|
||||
case n {
|
||||
_ if n < 0 ->
|
||||
"Invalid input argument: n < 0. Valid input is n >= 0."
|
||||
|> Error
|
||||
0 ->
|
||||
1
|
||||
|> Ok
|
||||
1 ->
|
||||
1
|
||||
|> Ok
|
||||
_ if n < 0 -> Error(Nil)
|
||||
0 -> Ok(1)
|
||||
1 -> Ok(1)
|
||||
_ ->
|
||||
list.range(1, n)
|
||||
|> list.fold(1, fn(acc, x) { acc * x })
|
||||
|
@ -300,22 +291,16 @@ 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)
|
||||
}
|
||||
}
|
||||
) -> Result(Int, Nil) {
|
||||
case n, k, mode {
|
||||
_, _, _ if n < 0 -> Error(Nil)
|
||||
_, _, _ if k < 0 -> Error(Nil)
|
||||
_, _, option.Some(WithRepetitions) -> permutation_with_repetitions(n, k)
|
||||
_, _, _ -> permutation_without_repetitions(n, k)
|
||||
}
|
||||
}
|
||||
|
||||
fn permutation_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||
fn permutation_without_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||
case n, k {
|
||||
_, _ if k < 0 || k > n -> {
|
||||
0 |> Ok
|
||||
|
@ -330,7 +315,7 @@ fn permutation_without_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
|||
}
|
||||
}
|
||||
|
||||
fn permutation_with_repetitions(n: Int, k: Int) -> Result(Int, String) {
|
||||
fn permutation_with_repetitions(n: Int, k: Int) -> Result(Int, Nil) {
|
||||
let n_float = conversion.int_to_float(n)
|
||||
let k_float = conversion.int_to_float(k)
|
||||
// 'n' ank 'k' are positive integers, so no errors here...
|
||||
|
@ -388,29 +373,20 @@ 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
|
||||
_ ->
|
||||
case mode {
|
||||
option.Some(WithRepetitions) ->
|
||||
list_combination_with_repetitions(arr, k)
|
||||
_ -> list_combination_without_repetitions(arr, k)
|
||||
}
|
||||
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||
case k, mode {
|
||||
_, _ if k < 0 -> Error(Nil)
|
||||
_, 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) {
|
||||
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||
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
|
||||
}
|
||||
_, arr_length if k > arr_length -> Error(Nil)
|
||||
// Special case: When k = n, then the entire list is the only valid combination
|
||||
_, arr_length if k == arr_length -> {
|
||||
iterator.single(arr) |> Ok
|
||||
|
@ -446,7 +422,7 @@ fn do_list_combination_without_repetitions(
|
|||
fn list_combination_with_repetitions(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||
Ok(do_list_combination_with_repetitions(iterator.from_list(arr), k, []))
|
||||
}
|
||||
|
||||
|
@ -528,17 +504,12 @@ 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)
|
||||
}
|
||||
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||
case k, mode {
|
||||
_, _ if k < 0 -> Error(Nil)
|
||||
_, option.Some(WithRepetitions) ->
|
||||
Ok(list_permutation_with_repetitions(arr, k))
|
||||
_, _ -> list_permutation_without_repetitions(arr, k)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,12 +529,9 @@ fn remove_first_by_index(
|
|||
fn list_permutation_without_repetitions(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
) -> Result(iterator.Iterator(List(a)), Nil) {
|
||||
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
|
||||
}
|
||||
_, arr_length if k > arr_length -> Error(Nil)
|
||||
_, _ -> {
|
||||
let indexed_arr = list.index_map(arr, fn(x, i) { #(i, x) })
|
||||
Ok(do_list_permutation_without_repetitions(
|
||||
|
@ -594,9 +562,9 @@ fn do_list_permutation_without_repetitions(
|
|||
fn list_permutation_with_repetitions(
|
||||
arr: List(a),
|
||||
k: Int,
|
||||
) -> Result(iterator.Iterator(List(a)), String) {
|
||||
) -> iterator.Iterator(List(a)) {
|
||||
let indexed_arr = list.index_map(arr, fn(x, i) { #(i, x) })
|
||||
Ok(do_list_permutation_with_repetitions(indexed_arr, k))
|
||||
do_list_permutation_with_repetitions(indexed_arr, k)
|
||||
}
|
||||
|
||||
fn do_list_permutation_with_repetitions(
|
||||
|
|
|
@ -98,14 +98,10 @@ import gleam/option
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn acos(x: Float) -> Result(Float, String) {
|
||||
pub fn acos(x: Float) -> Result(Float, Nil) {
|
||||
case x >=. -1.0 && x <=. 1.0 {
|
||||
True ->
|
||||
do_acos(x)
|
||||
|> Ok
|
||||
False ->
|
||||
"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."
|
||||
|> Error
|
||||
True -> Ok(do_acos(x))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,14 +146,10 @@ fn do_acos(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn acosh(x: Float) -> Result(Float, String) {
|
||||
pub fn acosh(x: Float) -> Result(Float, Nil) {
|
||||
case x >=. 1.0 {
|
||||
True ->
|
||||
do_acosh(x)
|
||||
|> Ok
|
||||
False ->
|
||||
"Invalid input argument: x < 1. Valid input is x >= 1."
|
||||
|> Error
|
||||
True -> Ok(do_acosh(x))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,14 +197,10 @@ fn do_acosh(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn asin(x: Float) -> Result(Float, String) {
|
||||
pub fn asin(x: Float) -> Result(Float, Nil) {
|
||||
case x >=. -1.0 && x <=. 1.0 {
|
||||
True ->
|
||||
do_asin(x)
|
||||
|> Ok
|
||||
False ->
|
||||
"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."
|
||||
|> Error
|
||||
True -> Ok(do_asin(x))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,14 +382,10 @@ fn do_atan2(a: Float, b: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn atanh(x: Float) -> Result(Float, String) {
|
||||
pub fn atanh(x: Float) -> Result(Float, Nil) {
|
||||
case x >. -1.0 && x <. 1.0 {
|
||||
True ->
|
||||
do_atanh(x)
|
||||
|> Ok
|
||||
False ->
|
||||
"Invalid input argument: x > -1 or x < 1. Valid input is -1. < x < 1."
|
||||
|> Error
|
||||
True -> Ok(do_atanh(x))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -753,14 +737,10 @@ fn do_exponential(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn natural_logarithm(x: Float) -> Result(Float, String) {
|
||||
pub fn natural_logarithm(x: Float) -> Result(Float, Nil) {
|
||||
case x >. 0.0 {
|
||||
True ->
|
||||
do_natural_logarithm(x)
|
||||
|> Ok
|
||||
False ->
|
||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
||||
|> Error
|
||||
True -> Ok(do_natural_logarithm(x))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -810,30 +790,19 @@ fn do_natural_logarithm(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String) {
|
||||
case x >. 0.0 {
|
||||
True ->
|
||||
case base {
|
||||
option.Some(a) ->
|
||||
case a >. 0.0 && a != 1.0 {
|
||||
True -> {
|
||||
// Apply the "change of base formula"
|
||||
let assert Ok(numerator) = logarithm_10(x)
|
||||
let assert Ok(denominator) = logarithm_10(a)
|
||||
numerator /. denominator
|
||||
|> Ok
|
||||
}
|
||||
False ->
|
||||
"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."
|
||||
|> Error
|
||||
}
|
||||
_ ->
|
||||
"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."
|
||||
|> Error
|
||||
pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, Nil) {
|
||||
case x >. 0.0, base {
|
||||
True, option.Some(a) ->
|
||||
case a >. 0.0 && a != 1.0 {
|
||||
False -> Error(Nil)
|
||||
True -> {
|
||||
// Apply the "change of base formula"
|
||||
let assert Ok(numerator) = logarithm_10(x)
|
||||
let assert Ok(denominator) = logarithm_10(a)
|
||||
Ok(numerator /. denominator)
|
||||
}
|
||||
}
|
||||
_ ->
|
||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
||||
|> Error
|
||||
_, _ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -877,14 +846,10 @@ pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String)
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn logarithm_2(x: Float) -> Result(Float, String) {
|
||||
pub fn logarithm_2(x: Float) -> Result(Float, Nil) {
|
||||
case x >. 0.0 {
|
||||
True ->
|
||||
do_logarithm_2(x)
|
||||
|> Ok
|
||||
False ->
|
||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
||||
|> Error
|
||||
True -> Ok(do_logarithm_2(x))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -932,14 +897,10 @@ fn do_logarithm_2(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn logarithm_10(x: Float) -> Result(Float, String) {
|
||||
pub fn logarithm_10(x: Float) -> Result(Float, Nil) {
|
||||
case x >. 0.0 {
|
||||
True ->
|
||||
do_logarithm_10(x)
|
||||
|> Ok
|
||||
False ->
|
||||
"Invalid input argument: x <= 0. Valid input is x > 0."
|
||||
|> Error
|
||||
True -> Ok(do_logarithm_10(x))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -993,7 +954,7 @@ fn do_logarithm_10(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn power(x: Float, y: Float) -> Result(Float, String) {
|
||||
pub fn power(x: Float, y: Float) -> Result(Float, Nil) {
|
||||
let fractional = do_ceiling(y) -. y >. 0.0
|
||||
// In the following check:
|
||||
// 1. If the base (x) is negative and the exponent (y) is fractional
|
||||
|
@ -1002,9 +963,7 @@ pub fn power(x: Float, y: Float) -> Result(Float, String) {
|
|||
// expression is equivalent to the exponent (y) divided by 0 and an
|
||||
// error should be returned
|
||||
case { x <. 0.0 && fractional } || { x == 0.0 && y <. 0.0 } {
|
||||
True ->
|
||||
"Invalid input argument: x < 0 and y is fractional or x = 0 and y < 0."
|
||||
|> Error
|
||||
True -> Error(Nil)
|
||||
False ->
|
||||
do_power(x, y)
|
||||
|> Ok
|
||||
|
@ -1055,19 +1014,13 @@ fn do_ceiling(a: Float) -> Float
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn square_root(x: Float) -> Result(Float, String) {
|
||||
pub fn square_root(x: Float) -> Result(Float, Nil) {
|
||||
// In the following check:
|
||||
// 1. If x is negative then return an error as it will otherwise be an
|
||||
// imaginary number
|
||||
case x <. 0.0 {
|
||||
True ->
|
||||
"Invalid input argument: x < 0."
|
||||
|> Error
|
||||
False -> {
|
||||
let assert Ok(result) = power(x, 1.0 /. 2.0)
|
||||
result
|
||||
|> Ok
|
||||
}
|
||||
True -> Error(Nil)
|
||||
False -> power(x, 1.0 /. 2.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1107,19 +1060,13 @@ pub fn square_root(x: Float) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn cube_root(x: Float) -> Result(Float, String) {
|
||||
pub fn cube_root(x: Float) -> Result(Float, Nil) {
|
||||
// In the following check:
|
||||
// 1. If x is negative then return an error as it will otherwise be an
|
||||
// imaginary number
|
||||
case x <. 0.0 {
|
||||
True ->
|
||||
"Invalid input argument: x < 0."
|
||||
|> Error
|
||||
False -> {
|
||||
let assert Ok(result) = power(x, 1.0 /. 3.0)
|
||||
result
|
||||
|> Ok
|
||||
}
|
||||
True -> Error(Nil)
|
||||
False -> power(x, 1.0 /. 3.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1162,25 +1109,13 @@ pub fn cube_root(x: Float) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn nth_root(x: Float, n: Int) -> Result(Float, String) {
|
||||
pub fn nth_root(x: Float, n: Int) -> Result(Float, Nil) {
|
||||
// In the following check:
|
||||
// 1. If x is negative then return an error as it will otherwise be an
|
||||
// imaginary number
|
||||
case x <. 0.0 {
|
||||
True ->
|
||||
"Invalid input argument: x < 0. Valid input is x > 0"
|
||||
|> Error
|
||||
False ->
|
||||
case n >= 1 {
|
||||
True -> {
|
||||
let assert Ok(result) = power(x, 1.0 /. int.to_float(n))
|
||||
result
|
||||
|> Ok
|
||||
}
|
||||
False ->
|
||||
"Invalid input argument: n < 1. Valid input is n >= 2."
|
||||
|> Error
|
||||
}
|
||||
case x >=. 0.0 && n >= 1 {
|
||||
True -> power(x, 1.0 /. int.to_float(n))
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ import gleam/int
|
|||
import gleam/list
|
||||
import gleam/option
|
||||
import gleam/pair
|
||||
import gleam/result
|
||||
import gleam/set
|
||||
import gleam_community/maths/arithmetics
|
||||
import gleam_community/maths/conversion
|
||||
|
@ -72,21 +73,15 @@ fn validate_lists(
|
|||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Bool, String) {
|
||||
) -> Result(Bool, Nil) {
|
||||
case xarr, yarr {
|
||||
[], _ ->
|
||||
"Invalid input argument: The list xarr is empty."
|
||||
|> Error
|
||||
_, [] ->
|
||||
"Invalid input argument: The list yarr is empty."
|
||||
|> Error
|
||||
[], _ -> Error(Nil)
|
||||
_, [] -> Error(Nil)
|
||||
_, _ -> {
|
||||
let xarr_length = list.length(xarr)
|
||||
let yarr_length = list.length(yarr)
|
||||
case xarr_length == yarr_length, weights {
|
||||
False, _ ->
|
||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
||||
|> Error
|
||||
False, _ -> Error(Nil)
|
||||
True, option.None -> {
|
||||
True
|
||||
|> Ok
|
||||
|
@ -97,9 +92,7 @@ fn validate_lists(
|
|||
True -> {
|
||||
validate_weights(warr)
|
||||
}
|
||||
False ->
|
||||
"Invalid input argument: length(weights) != length(xarr) and length(weights) != length(yarr). Valid input is when length(weights) == length(xarr) == length(yarr)."
|
||||
|> Error
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,16 +100,12 @@ fn validate_lists(
|
|||
}
|
||||
}
|
||||
|
||||
fn validate_weights(warr: List(Float)) -> Result(Bool, String) {
|
||||
fn validate_weights(warr: List(Float)) -> Result(Bool, Nil) {
|
||||
// Check that all the given weights are positive
|
||||
let assert Ok(minimum) = piecewise.list_minimum(warr, float.compare)
|
||||
case minimum >=. 0.0 {
|
||||
False ->
|
||||
"Invalid input argument: One or more weights are negative. Valid input is when all weights are >= 0."
|
||||
|> Error
|
||||
True ->
|
||||
True
|
||||
|> Ok
|
||||
False -> Error(Nil)
|
||||
True -> Ok(True)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +163,7 @@ pub fn norm(
|
|||
arr: List(Float),
|
||||
p: Float,
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
case arr, weights {
|
||||
[], _ ->
|
||||
0.0
|
||||
|
@ -221,10 +210,7 @@ pub fn norm(
|
|||
|> Error
|
||||
}
|
||||
}
|
||||
False -> {
|
||||
"Invalid input argument: length(weights) != length(arr). Valid input is when length(weights) == length(arr)."
|
||||
|> Error
|
||||
}
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,7 +272,7 @@ pub fn manhattan_distance(
|
|||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
minkowski_distance(xarr, yarr, 1.0, weights)
|
||||
}
|
||||
|
||||
|
@ -354,26 +340,17 @@ pub fn minkowski_distance(
|
|||
yarr: List(Float),
|
||||
p: Float,
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
case validate_lists(xarr, yarr, weights) {
|
||||
Error(msg) ->
|
||||
msg
|
||||
|> Error
|
||||
Ok(_) -> {
|
||||
case p <. 1.0 {
|
||||
True ->
|
||||
"Invalid input argument: p < 1. Valid input is p >= 1."
|
||||
|> Error
|
||||
False -> {
|
||||
let differences =
|
||||
list.zip(xarr, yarr)
|
||||
|> list.map(fn(tuple) { pair.first(tuple) -. pair.second(tuple) })
|
||||
|
||||
let assert Ok(result) = norm(differences, p, weights)
|
||||
result
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
) -> Result(Float, Nil) {
|
||||
use _ <- result.try(validate_lists(xarr, yarr, weights))
|
||||
case p <. 1.0 {
|
||||
True -> Error(Nil)
|
||||
False -> {
|
||||
let differences: List(Float) =
|
||||
list.zip(xarr, yarr)
|
||||
|> list.map(fn(tuple: #(Float, Float)) -> Float {
|
||||
pair.first(tuple) -. pair.second(tuple)
|
||||
})
|
||||
norm(differences, p, weights)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -434,7 +411,7 @@ pub fn euclidean_distance(
|
|||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
minkowski_distance(xarr, yarr, 2.0, weights)
|
||||
}
|
||||
|
||||
|
@ -484,7 +461,7 @@ pub fn euclidean_distance(
|
|||
pub fn chebyshev_distance(
|
||||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
case validate_lists(xarr, yarr, option.None) {
|
||||
Error(msg) ->
|
||||
msg
|
||||
|
@ -540,11 +517,9 @@ pub fn chebyshev_distance(
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn mean(arr: List(Float)) -> Result(Float, String) {
|
||||
pub fn mean(arr: List(Float)) -> Result(Float, Nil) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
[] -> Error(Nil)
|
||||
_ ->
|
||||
arr
|
||||
|> arithmetics.float_sum(option.None)
|
||||
|
@ -664,34 +639,27 @@ fn do_median(
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
_ ->
|
||||
case ddof < 0 {
|
||||
True ->
|
||||
"Invalid input argument: ddof < 0. Valid input is ddof >= 0."
|
||||
|> Error
|
||||
False -> {
|
||||
let assert Ok(mean) = mean(arr)
|
||||
arr
|
||||
|> list.map(fn(a) {
|
||||
let assert Ok(result) = elementary.power(a -. mean, 2.0)
|
||||
result
|
||||
})
|
||||
|> arithmetics.float_sum(option.None)
|
||||
|> fn(a) {
|
||||
a
|
||||
/. {
|
||||
conversion.int_to_float(list.length(arr))
|
||||
-. conversion.int_to_float(ddof)
|
||||
}
|
||||
}
|
||||
|> Ok
|
||||
pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, Nil) {
|
||||
case arr, ddof {
|
||||
[], _ -> Error(Nil)
|
||||
_, _ if ddof < 0 -> Error(Nil)
|
||||
_, _ -> {
|
||||
let assert Ok(mean) = mean(arr)
|
||||
arr
|
||||
|> list.map(fn(a: Float) -> Float {
|
||||
let assert Ok(result) = elementary.power(a -. mean, 2.0)
|
||||
result
|
||||
})
|
||||
|> arithmetics.float_sum(option.None)
|
||||
|> fn(a: Float) -> Float {
|
||||
a
|
||||
/. {
|
||||
conversion.int_to_float(list.length(arr))
|
||||
-. conversion.int_to_float(ddof)
|
||||
}
|
||||
}
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -741,25 +709,18 @@ pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn standard_deviation(arr: List(Float), ddof: Int) -> Result(Float, String) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
_ ->
|
||||
case ddof < 0 {
|
||||
True ->
|
||||
"Invalid input argument: ddof < 0. Valid input is ddof >= 0."
|
||||
|> Error
|
||||
False -> {
|
||||
let assert Ok(variance) = variance(arr, ddof)
|
||||
// The computed variance will always be positive
|
||||
// So an error should never be returned
|
||||
let assert Ok(stdev) = elementary.square_root(variance)
|
||||
stdev
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
pub fn standard_deviation(arr: List(Float), ddof: Int) -> Result(Float, Nil) {
|
||||
case arr, ddof {
|
||||
[], _ -> Error(Nil)
|
||||
_, _ if ddof < 0 -> Error(Nil)
|
||||
_, _ -> {
|
||||
let assert Ok(variance) = variance(arr, ddof)
|
||||
// The computed variance will always be positive
|
||||
// So an error should never be returned
|
||||
let assert Ok(stdev) = elementary.square_root(variance)
|
||||
stdev
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -924,7 +885,7 @@ pub fn tversky_index(
|
|||
yset: set.Set(a),
|
||||
alpha: Float,
|
||||
beta: Float,
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
case alpha >=. 0.0, beta >=. 0.0 {
|
||||
True, True -> {
|
||||
let intersection =
|
||||
|
@ -943,18 +904,7 @@ pub fn tversky_index(
|
|||
/. { intersection +. alpha *. difference1 +. beta *. difference2 }
|
||||
|> Ok
|
||||
}
|
||||
False, True -> {
|
||||
"Invalid input argument: alpha < 0. Valid input is alpha >= 0."
|
||||
|> Error
|
||||
}
|
||||
True, False -> {
|
||||
"Invalid input argument: beta < 0. Valid input is beta >= 0."
|
||||
|> Error
|
||||
}
|
||||
_, _ -> {
|
||||
"Invalid input argument: alpha < 0 and beta < 0. Valid input is alpha >= 0 and beta >= 0."
|
||||
|> Error
|
||||
}
|
||||
_, _ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1077,7 +1027,7 @@ pub fn cosine_similarity(
|
|||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
case validate_lists(xarr, yarr, weights) {
|
||||
Error(msg) ->
|
||||
msg
|
||||
|
@ -1173,7 +1123,7 @@ pub fn canberra_distance(
|
|||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
case validate_lists(xarr, yarr, weights) {
|
||||
Error(msg) ->
|
||||
msg
|
||||
|
@ -1266,7 +1216,7 @@ pub fn braycurtis_distance(
|
|||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
weights: option.Option(List(Float)),
|
||||
) -> Result(Float, String) {
|
||||
) -> Result(Float, Nil) {
|
||||
case validate_lists(xarr, yarr, weights) {
|
||||
Error(msg) ->
|
||||
msg
|
||||
|
|
|
@ -949,11 +949,9 @@ pub fn minmax(x: a, y: a, compare: fn(a, a) -> order.Order) {
|
|||
pub fn list_minimum(
|
||||
arr: List(a),
|
||||
compare: fn(a, a) -> order.Order,
|
||||
) -> Result(a, String) {
|
||||
) -> Result(a, Nil) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
[] -> Error(Nil)
|
||||
[x, ..rest] ->
|
||||
Ok(
|
||||
list.fold(rest, x, fn(acc, element) {
|
||||
|
@ -1003,11 +1001,9 @@ pub fn list_minimum(
|
|||
pub fn list_maximum(
|
||||
arr: List(a),
|
||||
compare: fn(a, a) -> order.Order,
|
||||
) -> Result(a, String) {
|
||||
) -> Result(a, Nil) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
[] -> Error(Nil)
|
||||
[x, ..rest] ->
|
||||
Ok(
|
||||
list.fold(rest, x, fn(acc, element) {
|
||||
|
@ -1063,11 +1059,9 @@ pub fn list_maximum(
|
|||
pub fn arg_minimum(
|
||||
arr: List(a),
|
||||
compare: fn(a, a) -> order.Order,
|
||||
) -> Result(List(Int), String) {
|
||||
) -> Result(List(Int), Nil) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
[] -> Error(Nil)
|
||||
_ -> {
|
||||
let assert Ok(min) =
|
||||
arr
|
||||
|
@ -1133,11 +1127,9 @@ pub fn arg_minimum(
|
|||
pub fn arg_maximum(
|
||||
arr: List(a),
|
||||
compare: fn(a, a) -> order.Order,
|
||||
) -> Result(List(Int), String) {
|
||||
) -> Result(List(Int), Nil) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
[] -> Error(Nil)
|
||||
_ -> {
|
||||
let assert Ok(max) =
|
||||
arr
|
||||
|
@ -1203,11 +1195,9 @@ pub fn arg_maximum(
|
|||
pub fn extrema(
|
||||
arr: List(a),
|
||||
compare: fn(a, a) -> order.Order,
|
||||
) -> Result(#(a, a), String) {
|
||||
) -> Result(#(a, a), Nil) {
|
||||
case arr {
|
||||
[] ->
|
||||
"Invalid input argument: The list is empty."
|
||||
|> Error
|
||||
[] -> Error(Nil)
|
||||
[x, ..rest] ->
|
||||
Ok(
|
||||
list.fold(rest, #(x, x), fn(acc, element) {
|
||||
|
|
|
@ -135,7 +135,7 @@ fn float_absolute_difference(a: Float, b: Float) -> Float {
|
|||
/// let rtol = 0.01
|
||||
/// let atol = 0.10
|
||||
/// predicates.all_close(xarr, yarr, rtol, atol)
|
||||
/// |> fn(zarr), String)) {
|
||||
/// |> fn(zarr: Result(List(Bool), Nil)) -> Result(Bool, Nil) {
|
||||
/// case zarr {
|
||||
/// Ok(arr) ->
|
||||
/// arr
|
||||
|
@ -159,13 +159,11 @@ pub fn all_close(
|
|||
yarr: List(Float),
|
||||
rtol: Float,
|
||||
atol: Float,
|
||||
) -> Result(List(Bool), String) {
|
||||
) -> Result(List(Bool), Nil) {
|
||||
let xlen = list.length(xarr)
|
||||
let ylen = list.length(yarr)
|
||||
case xlen == ylen {
|
||||
False ->
|
||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
||||
|> Error
|
||||
False -> Error(Nil)
|
||||
True ->
|
||||
list.zip(xarr, yarr)
|
||||
|> list.map(fn(z) { is_close(pair.first(z), pair.second(z), rtol, atol) })
|
||||
|
|
|
@ -160,7 +160,7 @@ pub fn linear_space(
|
|||
stop: Float,
|
||||
num: Int,
|
||||
endpoint: Bool,
|
||||
) -> Result(iterator.Iterator(Float), String) {
|
||||
) -> Result(iterator.Iterator(Float), Nil) {
|
||||
let direction = case start <=. stop {
|
||||
True -> 1.0
|
||||
False -> -1.0
|
||||
|
@ -184,9 +184,7 @@ pub fn linear_space(
|
|||
})
|
||||
|> Ok
|
||||
}
|
||||
False ->
|
||||
"Invalid input: num < 1. Valid input is num >= 1."
|
||||
|> Error
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,7 +239,7 @@ pub fn logarithmic_space(
|
|||
num: Int,
|
||||
endpoint: Bool,
|
||||
base: Float,
|
||||
) -> Result(iterator.Iterator(Float), String) {
|
||||
) -> Result(iterator.Iterator(Float), Nil) {
|
||||
case num > 0 {
|
||||
True -> {
|
||||
let assert Ok(linspace) = linear_space(start, stop, num, endpoint)
|
||||
|
@ -252,9 +250,7 @@ pub fn logarithmic_space(
|
|||
})
|
||||
|> Ok
|
||||
}
|
||||
False ->
|
||||
"Invalid input: num < 1. Valid input is num >= 1."
|
||||
|> Error
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,11 +312,9 @@ pub fn geometric_space(
|
|||
stop: Float,
|
||||
num: Int,
|
||||
endpoint: Bool,
|
||||
) -> Result(iterator.Iterator(Float), String) {
|
||||
) -> Result(iterator.Iterator(Float), Nil) {
|
||||
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."
|
||||
|> Error
|
||||
True -> Error(Nil)
|
||||
False ->
|
||||
case num > 0 {
|
||||
True -> {
|
||||
|
@ -328,9 +322,7 @@ pub fn geometric_space(
|
|||
let assert Ok(log_stop) = elementary.logarithm_10(stop)
|
||||
logarithmic_space(log_start, log_stop, num, endpoint, 10.0)
|
||||
}
|
||||
False ->
|
||||
"Invalid input: num < 1. Valid input is num >= 1."
|
||||
|> Error
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ fn gamma_lanczos(x: Float) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, String) {
|
||||
pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, Nil) {
|
||||
case a >. 0.0 && x >=. 0.0 {
|
||||
True -> {
|
||||
let assert Ok(v) = elementary.power(x, a)
|
||||
|
@ -173,9 +173,7 @@ pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, String) {
|
|||
|> Ok
|
||||
}
|
||||
|
||||
False ->
|
||||
"Invalid input argument: a <= 0 or x < 0. Valid input is a > 0 and x >= 0."
|
||||
|> Error
|
||||
False -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ pub fn float_list_all_close_test() {
|
|||
let rtol = 0.01
|
||||
let atol = 0.1
|
||||
predicates.all_close(xarr, yarr, rtol, atol)
|
||||
|> fn(zarr) {
|
||||
|> fn(zarr: Result(List(Bool), Nil)) -> Result(Bool, Nil) {
|
||||
case zarr {
|
||||
Ok(arr) ->
|
||||
arr
|
||||
|
|
Loading…
Reference in a new issue