mirror of
https://github.com/sigmasternchen/gleam-community-maths
synced 2025-03-15 07:59:01 +00:00
Work on float_list dist funcs
This commit is contained in:
parent
82ad10b7e6
commit
62f4015ee4
4 changed files with 245 additions and 122 deletions
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
@ -24,4 +24,6 @@ jobs:
|
|||
|
||||
- run: gleam format --check
|
||||
|
||||
- run: gleam test
|
||||
- run: gleam test --target=erlang
|
||||
|
||||
- run: gleam test --target=javscript
|
|
@ -1587,14 +1587,14 @@ pub fn nth_root(x: Float, n: Int) -> Result(Float, String) {
|
|||
"Invalid input argument: x < 0. Valid input is x > 0"
|
||||
|> Error
|
||||
False ->
|
||||
case n >= 2 {
|
||||
case n >= 1 {
|
||||
True -> {
|
||||
assert Ok(result) = power(x, 1.0 /. int.to_float(n))
|
||||
result
|
||||
|> Ok
|
||||
}
|
||||
False ->
|
||||
"Invalid input argyment: n < 2. Valid input is n >= 2."
|
||||
"Invalid input argument: n < 1. Valid input is n >= 2."
|
||||
|> Error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,9 @@
|
|||
//// * [`sum`](#sum)
|
||||
//// * [`product`](#product)
|
||||
//// * [`norm`](#norm)
|
||||
//// * [`minkowski`](#minkowski)
|
||||
//// * [`euclidean`](#euclidean)
|
||||
//// * [`manhatten`](#manhatten)
|
||||
//// * [`root_mean_squared_error`](#root_mean_squared_error)
|
||||
//// * [`mean_squared_error`](#mean_squared_error)
|
||||
//// * [`minkowski_distance`](#minkowski_distance)
|
||||
//// * [`euclidean_distance`](#euclidean_distance)
|
||||
//// * [`manhatten_distance`](#manhatten_distance)
|
||||
//// * [`cumulative_sum`](#cumulative_sum)
|
||||
//// * [`cumulative_product`](#cumulative_product)
|
||||
//// * **Ranges and intervals**
|
||||
|
@ -53,6 +51,8 @@ import gleam/float
|
|||
import gleam/pair
|
||||
import gleam/option
|
||||
import gleam_community/maths/float as floatx
|
||||
import gleam_community/maths/int as intx
|
||||
import gleam/io
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
|
@ -60,6 +60,77 @@ import gleam_community/maths/float as floatx
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the $$p$$-norm of a list (representing a vector):
|
||||
///
|
||||
/// \\[
|
||||
/// \left( \sum_{i=1}^n \left|x_i\right|^{p} \right)^{\frac{1}{p}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the list and $$x_i$$ is the value in the input list indexed by $$i$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float as floatx
|
||||
/// import gleam_community/maths/float_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
/// assert Ok(tol) = floatx.power(-10.0, -6.0)
|
||||
///
|
||||
/// [1.0, 1.0, 1.0]
|
||||
/// |> float_list.norm(1.0)
|
||||
/// |> floatx.is_close(3.0, 0.0, tol)
|
||||
/// |> should.be_true()
|
||||
///
|
||||
/// [1.0, 1.0, 1.0]
|
||||
/// |> float_list.norm(-1.0)
|
||||
/// |> floatx.is_close(0.3333333333333333, 0.0, tol)
|
||||
/// |> should.be_true()
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn norm(arr: List(Float), p: Float) -> Float {
|
||||
case arr {
|
||||
[] -> 0.0
|
||||
_ -> {
|
||||
let agg: Float =
|
||||
arr
|
||||
|> list.fold(
|
||||
0.0,
|
||||
fn(acc: Float, a: Float) -> Float {
|
||||
assert Ok(result) = floatx.power(float.absolute_value(a), p)
|
||||
result +. acc
|
||||
},
|
||||
)
|
||||
assert Ok(result) = floatx.power(agg, 1.0 /. p)
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the Minkowski distance between two lists (representing vectors):
|
||||
///
|
||||
/// \\[
|
||||
/// \left( \sum_{i=1}^n \left|x_i - x_j \right|^{p} \right)^{\frac{1}{p}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$.
|
||||
///
|
||||
/// The Minkowski distance is a generalization of both the Euclidean distance ($$p=2$$) and the Manhattan distance ($$p = 1$$).
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
|
@ -77,8 +148,69 @@ import gleam_community/maths/float as floatx
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn norm(xarr: List(Float), p: Int) -> Float {
|
||||
todo
|
||||
pub fn minkowski_distance(
|
||||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
p: Float,
|
||||
) -> Result(Float, String) {
|
||||
let xlen: Int = list.length(xarr)
|
||||
let ylen: Int = list.length(yarr)
|
||||
case xlen == ylen {
|
||||
False ->
|
||||
"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."
|
||||
|> Error
|
||||
True ->
|
||||
case p <. 1.0 {
|
||||
True ->
|
||||
"Invalid input argument: p < 1. Valid input is p >= 1."
|
||||
|> Error
|
||||
False ->
|
||||
list.zip(xarr, yarr)
|
||||
|> list.map(fn(tuple: #(Float, Float)) -> Float {
|
||||
pair.first(tuple) -. pair.second(tuple)
|
||||
})
|
||||
|> norm(p)
|
||||
|> Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// Calculcate the Euclidean distance between two lists (representing vectors):
|
||||
///
|
||||
/// \\[
|
||||
/// \left( \sum_{i=1}^n \left|x_i - x_j \right|^{p} \right)^{\frac{1}{p}}
|
||||
/// \\]
|
||||
///
|
||||
/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$.
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
///
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn euclidean_distance(
|
||||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
) -> Result(Float, String) {
|
||||
minkowski_distance(xarr, yarr, 2.0)
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
|
@ -104,116 +236,11 @@ pub fn norm(xarr: List(Float), p: Int) -> Float {
|
|||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn minkowski(xarr: List(Float), yarr: List(Float), p: Int) -> Float {
|
||||
todo
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
///
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn euclidean(xarr: List(Float), yarr: List(Float)) -> Float {
|
||||
todo
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
///
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn manhatten(xarr: List(Float), yarr: List(Float)) -> Float {
|
||||
todo
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
///
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn mean_squared_error(xarr: List(Float), yarr: List(Float)) -> Float {
|
||||
todo
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="https://github.com/gleam-community/maths/issues">
|
||||
/// <small>Spot a typo? Open an issue!</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
/// <details>
|
||||
/// <summary>Example:</summary>
|
||||
///
|
||||
/// import gleeunit/should
|
||||
/// import gleam_community/maths/float_list
|
||||
///
|
||||
/// pub fn example () {
|
||||
///
|
||||
/// }
|
||||
/// </details>
|
||||
///
|
||||
/// <div style="text-align: right;">
|
||||
/// <a href="#">
|
||||
/// <small>Back to top ↑</small>
|
||||
/// </a>
|
||||
/// </div>
|
||||
///
|
||||
pub fn root_mean_squared_error(xarr: List(Float), yarr: List(Float)) -> Float {
|
||||
todo
|
||||
pub fn manhatten_distance(
|
||||
xarr: List(Float),
|
||||
yarr: List(Float),
|
||||
) -> Result(Float, String) {
|
||||
minkowski_distance(xarr, yarr, 1.0)
|
||||
}
|
||||
|
||||
/// <div style="text-align: right;">
|
||||
|
@ -659,7 +686,7 @@ pub fn arg_maximum(arr: List(Float)) -> Result(List(Int), String) {
|
|||
arr
|
||||
|> list.index_map(fn(index: Int, a: Float) -> Int {
|
||||
case a -. max {
|
||||
0. -> index
|
||||
0.0 -> index
|
||||
_ -> -1
|
||||
}
|
||||
})
|
||||
|
@ -719,7 +746,7 @@ pub fn arg_minimum(arr: List(Float)) -> Result(List(Int), String) {
|
|||
arr
|
||||
|> list.index_map(fn(index: Int, a: Float) -> Int {
|
||||
case a -. min {
|
||||
0. -> index
|
||||
0.0 -> index
|
||||
_ -> -1
|
||||
}
|
||||
})
|
||||
|
|
|
@ -2,8 +2,10 @@ import gleam/int
|
|||
import gleam/list
|
||||
import gleam/pair
|
||||
import gleam_community/maths/float_list
|
||||
import gleam_community/maths/float as floatx
|
||||
import gleeunit
|
||||
import gleeunit/should
|
||||
import gleam/io
|
||||
|
||||
pub fn main() {
|
||||
gleeunit.main()
|
||||
|
@ -33,6 +35,98 @@ pub fn float_list_all_close_test() {
|
|||
|> should.equal(Ok(True))
|
||||
}
|
||||
|
||||
pub fn float_list_norm_test() {
|
||||
assert Ok(tol) = floatx.power(-10.0, -6.0)
|
||||
|
||||
// An empty lists returns 0.0
|
||||
[]
|
||||
|> float_list.norm(1.0)
|
||||
|> should.equal(0.0)
|
||||
|
||||
// Check that the function agrees, at some arbitrary input
|
||||
// points, with known function values
|
||||
[1.0, 1.0, 1.0]
|
||||
|> float_list.norm(1.0)
|
||||
|> floatx.is_close(3.0, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
[1.0, 1.0, 1.0]
|
||||
|> float_list.norm(-1.0)
|
||||
|> floatx.is_close(0.3333333333333333, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
[-1.0, -1.0, -1.0]
|
||||
|> float_list.norm(-1.0)
|
||||
|> floatx.is_close(0.3333333333333333, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
[-1.0, -1.0, -1.0]
|
||||
|> float_list.norm(1.0)
|
||||
|> floatx.is_close(3.0, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
[-1.0, -2.0, -3.0]
|
||||
|> float_list.norm(-10.0)
|
||||
|> floatx.is_close(0.9999007044905545, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
[-1.0, -2.0, -3.0]
|
||||
|> float_list.norm(-100.0)
|
||||
|> floatx.is_close(1.0, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
[-1.0, -2.0, -3.0]
|
||||
|> float_list.norm(2.0)
|
||||
|> floatx.is_close(3.7416573867739413, 0.0, tol)
|
||||
|> should.be_true()
|
||||
}
|
||||
|
||||
pub fn float_list_minkowski_test() {
|
||||
assert Ok(tol) = floatx.power(-10.0, -6.0)
|
||||
|
||||
// Empty lists returns 0.0
|
||||
float_list.minkowski_distance([], [], 1.0)
|
||||
|> should.equal(Ok(0.0))
|
||||
|
||||
// Differing lenghths returns error
|
||||
float_list.minkowski_distance([], [1.0], 1.0)
|
||||
|> should.be_error()
|
||||
|
||||
// Test order < 1
|
||||
float_list.minkowski_distance([0.0, 0.0], [0.0, 0.0], -1.0)
|
||||
|> should.be_error()
|
||||
|
||||
// Check that the function agrees, at some arbitrary input
|
||||
// points, with known function values
|
||||
assert Ok(result) = float_list.minkowski_distance([1.0, 1.0], [1.0, 1.0], 1.0)
|
||||
result
|
||||
|> floatx.is_close(0.0, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
assert Ok(result) =
|
||||
float_list.minkowski_distance([0.0, 0.0], [1.0, 1.0], 10.0)
|
||||
result
|
||||
|> floatx.is_close(1.0717734625362931, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
assert Ok(result) =
|
||||
float_list.minkowski_distance([0.0, 0.0], [1.0, 1.0], 100.0)
|
||||
result
|
||||
|> floatx.is_close(1.0069555500567189, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
assert Ok(result) =
|
||||
float_list.minkowski_distance([0.0, 0.0], [1.0, 1.0], 10.0)
|
||||
result
|
||||
|> floatx.is_close(1.0717734625362931, 0.0, tol)
|
||||
|> should.be_true()
|
||||
|
||||
assert Ok(result) = float_list.minkowski_distance([0.0, 0.0], [1.0, 2.0], 2.0)
|
||||
result
|
||||
|> floatx.is_close(2.23606797749979, 0.0, tol)
|
||||
|> should.be_true()
|
||||
}
|
||||
|
||||
pub fn float_list_maximum_test() {
|
||||
// An empty lists returns an error
|
||||
[]
|
||||
|
|
Loading…
Reference in a new issue