gleam_community/maths
Functions
pub fn absolute_difference(a: Float, b: Float) -> Float
The absolute difference:
The function takes two inputs and and returns a positive float value which is the absolute difference of the inputs.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.absolute_difference(-10.0, 10.0)
|> should.equal(20.0)
maths.absolute_difference(0.0, -2.0)
|> should.equal(2.0)
}
pub fn acos(x: Float) -> Result(Float, Nil)
The inverse cosine function:
The function takes a number in its domain as input and returns a numeric value that lies in the range (an angle in radians). If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.acos(1.0)
|> should.equal(Ok(0.0))
maths.acos(1.1)
|> should.be_error()
maths.acos(-1.1)
|> should.be_error()
}
pub fn acosh(x: Float) -> Result(Float, Nil)
The inverse hyperbolic cosine function:
The function takes a number in its domain as input and returns a numeric value that lies in the range (an angle in radians). If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.acosh(1.0)
|> should.equal(Ok(0.0))
maths.acosh(0.0)
|> should.be_error()
}
pub fn all_close(
arr: List(#(Float, Float)),
rtol: Float,
atol: Float,
) -> List(Bool)
Determine if each value is close to or equivalent to its corresponding reference value , in a list of value pairs , based on supplied relative and absolute tolerance values. The equivalence of each pair is determined by the equation:
A list of Bool
values is returned, where each entry indicates if the corresponding pair
satisfies the condition. If all conditions are satisfied, the list will contain only True
values.
Example:
import gleam/list
import gleeunit/should
import gleam_community/maths
pub fn example () {
let value = 99.0
let reference_value = 100.0
let xarr = list.repeat(value, 42)
let yarr = list.repeat(reference_value, 42)
let arr = list.zip(xarr, yarr)
// We set 'absolute_tolerance' and 'relative_tolerance' such that
// the values are equivalent if 'value' is within 1 percent of
// 'reference_value' +/- 0.1
let relative_tolerance = 0.01
let absolute_tolerance = 0.1
let assert Ok(result) =
maths.all_close(arr, relative_tolerance, absolute_tolerance)
result
|> list.all(fn(x) { x == True })
|> should.be_true()
}
pub fn arg_maximum(
arr: List(a),
compare: fn(a, a) -> Order,
) -> Result(List(Int), Nil)
Returns the indices of the maximum values in a given list.
Example:
import gleam/float
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.arg_maximum(float.compare)
|> should.be_error()
[4.0, 4.0, 3.0, 2.0, 1.0]
|> maths.arg_maximum(float.compare)
|> should.equal(Ok([0, 1]))
}
pub fn arg_minimum(
arr: List(a),
compare: fn(a, a) -> Order,
) -> Result(List(Int), Nil)
Returns the indices of the minimum values in a given list.
Example:
import gleam/float
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.arg_minimum(float.compare)
|> should.be_error()
[4.0, 4.0, 3.0, 2.0, 1.0]
|> maths.arg_minimum(float.compare)
|> should.equal(Ok([4]))
}
pub fn asin(x: Float) -> Result(Float, Nil)
The inverse sine function:
The function takes a number in its domain as input and returns a numeric value that lies in the range (an angle in radians). If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.asin(0.0)
|> should.equal(Ok(0.0))
maths.asin(1.1)
|> should.be_error()
maths.asin(-1.1)
|> should.be_error()
}
pub fn asinh(x: Float) -> Float
The inverse hyperbolic sine function:
The function takes a number in its domain as input and returns a numeric value that lies in the range (an angle in radians).
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.asinh(0.0)
|> should.equal(0.0)
}
pub fn atan(x: Float) -> Float
The inverse tangent function:
The function takes a number in its domain as input and returns a numeric value that lies in the range (an angle in radians).
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.atan(0.0)
|> should.equal(0.0)
}
pub fn atan2(y: Float, x: Float) -> Float
The inverse 2-argument tangent function:
The function returns the angle in radians from the x-axis to the line containing the origin and a point given as input with coordinates . The numeric value returned by is in the range .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.atan2(0.0, 0.0)
|> should.equal(0.0)
}
pub fn atanh(x: Float) -> Result(Float, Nil)
The inverse hyperbolic tangent function:
The function takes a number in its domain as input and returns a numeric value that lies in the range (an angle in radians). If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.atanh(0.0)
|> should.equal(Ok(0.0))
maths.atanh(1.0)
|> should.be_error()
maths.atanh(-1.0)
|> should.be_error()
}
pub fn beta(x: Float, y: Float) -> Float
The beta function over the real numbers:
The beta function is evaluated through the use of the gamma function.
pub fn braycurtis_distance(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the Bray-Curtis distance between two lists:
In the formula, is the length of the two lists, and are the values in the respective input lists indexed by .
The Bray-Curtis distance is in the range if all entries are positive.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.braycurtis_distance([])
|> should.be_error()
maths.braycurtis_distance([#(1.0, 3.0), #(2.0, 4.0)])
|> should.equal(Ok(0.4))
}
pub fn braycurtis_distance_with_weights(
arr: List(#(Float, Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted Bray-Curtis distance between two lists:
In the formula, is the length of the two lists, and are the values in the respective input lists indexed by , while the are corresponding positive weights.
The Bray-Curtis distance is in the range if all entries are positive and .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.braycurtis_distance_with_weights([])
|> should.be_error()
maths.braycurtis_distance_with_weights([#(1.0, 3.0, 0.5), #(2.0, 4.0, 1.0)])
|> should.equal(Ok(0.375))
}
pub fn canberra_distance(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the Canberra distance between two lists:
In the formula, is the length of the two lists, and are the values in the respective input lists indexed by .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.canberra_distance([])
|> should.be_error()
maths.canberra_distance([#(1.0, -2.0), #(2.0, -1.0)])
|> should.equal(Ok(2.0))
}
pub fn canberra_distance_with_weights(
arr: List(#(Float, Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted Canberra distance between two lists:
In the formula, is the length of the two lists, and are the values in the respective input lists indexed by , while the are corresponding positive weights.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.canberra_distance_with_weights([])
|> should.be_error()
maths.canberra_distance_with_weights([#(1.0, -2.0, 0.5), #(2.0, -1.0, 1.0)])
|> should.equal(Ok(1.5))
}
pub fn cartesian_product(
xset: Set(a),
yset: Set(b),
) -> Set(#(a, b))
Generate a set containing all combinations of pairs of elements coming from two given sets.
Example:
import gleam/set
import gleeunit/should
import gleam_community/maths
pub fn example () {
set.from_list([])
|> maths.cartesian_product(set.from_list([]))
|> should.equal(set.from_list([]))
set.from_list([1.0, 10.0])
|> maths.cartesian_product(set.from_list([1.0, 2.0]))
|> should.equal(
set.from_list([#(1.0, 1.0), #(1.0, 2.0), #(10.0, 1.0), #(10.0, 2.0)]),
)
}
pub fn cartesian_to_polar(x: Float, y: Float) -> #(Float, Float)
Converts Cartesian coordinates to polar coordinates .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.cartesian_to_polar(1.0, 0.0)
|> should.equal((1.0, 0.0))
maths.cartesian_to_polar(0.0, 1.0)
|> should.equal((1.0, float.pi() /. 2.0))
}
pub fn chebyshev_distance(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the Chebyshev distance between two lists (representing vectors):
In the formula, is the length of the two lists and are the values in the respective input lists indexed by .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.chebyshev_distance([#(-5.0, -1.0), #(-10.0, -12.0), #(-3.0, -3.0)])
|> should.equal(Ok(4.0))
}
pub fn chebyshev_distance_with_weights(
arr: List(#(Float, Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted Chebyshev distance between two lists (representing vectors):
In the formula, is the length of the two lists and are the values in the respective input lists indexed by , while the are corresponding positive weights.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.chebyshev_distance_with_weights([
#(-5.0, -1.0, 0.5),
#(-10.0, -12.0, 1.0),
#(-3.0, -3.0, 1.0),
])
|> should.equal(Ok(2.0))
}
pub fn combination(n: Int, k: Int) -> Result(Int, Nil)
A combinatorial function for computing the number of -combinations of elements without repetitions:
Also known as “ choose ” or the binomial coefficient.
Details
A -combination without repetition is a sequence of elements selected from
elements where the order of selection does not matter and elements are not allowed to
repeat. For example, consider selecting 2 elements from a list of 3 elements:
["A", "B", "C"]
. In this case, possible selections are:
["A", "B"]
["A", "C"]
["B", "C"]
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.combination(-1, 1)
|> should.be_error()
maths.combination(4, 0)
|> should.equal(Ok(1))
maths.combination(4, 4)
|> should.equal(Ok(1))
maths.combination(13, 5)
|> should.equal(Ok(1287))
}
pub fn combination_with_repetitions(
n: Int,
k: Int,
) -> Result(Int, Nil)
A combinatorial function for computing the number of -combinations of elements with repetitions:
Also known as the “stars and bars” problem in maths. Furthermore, the implementation uses an efficient iterative multiplicative formula for computing the result.
Details
A -combination with repetitions is a sequence of elements selected from
elements where the order of selection does not matter and elements are allowed to
repeat. For example, consider selecting 2 elements from a list of 3 elements: ["A", "B", "C"]
.
In this case, possible selections are:
["A", "A"], ["A", "B"], ["A", "C"]
["B", "B"], ["B", "C"], ["C", "C"]
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.combination_with_repetitions(-1, 1)
|> should.be_error()
maths.combination_with_repetitions(2, 3)
|> should.equal(Ok(4))
maths.combination_with_repetitions(13, 5)
|> should.equal(Ok(6188))
}
pub fn copy_sign(x: Float, y: Float) -> Float
The function takes two arguments and returns such that it has the same sign as .
pub fn correlation(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate Pearson’s sample correlation coefficient to determine the linear relationship between the elements in two lists of equal length. The correlation coefficient is calculated as:
In the formula, is the sample size (the length of the input lists), , are the corresponding sample points indexed by and , are the sample means.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty lists returns an error
maths.correlation([], [])
|> should.be_error()
// Perfect positive correlation
let xarr =
list.range(0, 100)
|> list.map(fn(x) { int.to_float(x) })
let yarr =
list.range(0, 100)
|> list.map(fn(y) { int.to_float(y) })
list.zip(xarr, yarr)
|> maths.correlation()
|> should.equal(Ok(1.0))
// Perfect negative correlation
let xarr =
list.range(0, 100)
|> list.map(fn(x) { -1.0 *. int.to_float(x) })
let yarr =
list.range(0, 100)
|> list.map(fn(y) { int.to_float(y) })
list.zip(xarr, yarr)
|> maths.correlation()
|> should.equal(Ok(-1.0))
// No correlation (independent variables)
let xarr = [1.0, 2.0, 3.0, 4.0]
let yarr = [5.0, 5.0, 5.0, 5.0]
list.zip(xarr, yarr)
|> maths.correlation()
|> should.equal(Ok(0.0))
}
pub fn cos(x: Float) -> Float
The cosine function:
The function takes a number in its domain (an angle in radians) as input and returns a numeric value that lies in the range .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.cos(0.0)
|> should.equal(1.0)
maths.cos(maths.pi())
|> should.equal(-1.0)
}
pub fn cosh(x: Float) -> Float
The hyperbolic cosine function:
The function takes a number in its domain as input (an angle in radians) and returns a numeric value that lies in the range . If the input value is too large an overflow error might occur.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.cosh(0.0)
|> should.equal(0.0)
}
pub fn cosine_similarity(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the cosine similarity between two lists (representing vectors):
In the formula, is the length of the two lists and , are the values in the respective input lists indexed by .
The cosine similarity provides a value between -1 and 1, where 1 means the vectors are in the same direction, -1 means they are in exactly opposite directions, and 0 indicates orthogonality.
Example:
import gleam/option
import gleeunit/should
import gleam_community/maths
pub fn example() {
// Two orthogonal vectors
maths.cosine_similarity([#(-1.0, 1.0), #(1.0, 1.0), #(0.0, -1.0)])
|> should.equal(Ok(0.0))
// Two identical (parallel) vectors
maths.cosine_similarity([#(1.0, 1.0), #(2.0, 2.0), #(3.0, 3.0)])
|> should.equal(Ok(1.0))
// Two parallel, but oppositely oriented vectors
maths.cosine_similarity([#(-1.0, 1.0), #(-2.0, 2.0), #(-3.0, 3.0)])
|> should.equal(Ok(-1.0))
}
pub fn cosine_similarity_with_weights(
arr: List(#(Float, Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted cosine similarity between two lists (representing vectors):
In the formula, is the length of the two lists and , are the values in the respective input lists indexed by , while the are corresponding positive weights.
The cosine similarity provides a value between -1 and 1, where 1 means the vectors are in the same direction, -1 means they are in exactly opposite directions, and 0 indicates orthogonality.
Example:
import gleam/option
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) =
maths.cosine_similarity_with_weights([
#(1.0, 1.0, 2.0),
#(2.0, 2.0, 3.0),
#(3.0, 3.0, 4.0),
])
result
|> maths.is_close(1.0, 0.0, tolerance)
|> should.be_true()
let assert Ok(result) =
maths.cosine_similarity_with_weights([
#(-1.0, 1.0, 1.0),
#(-2.0, 2.0, 0.5),
#(-3.0, 3.0, 0.33),
])
result
|> maths.is_close(-1.0, 0.0, tolerance)
|> should.be_true()
}
pub fn cumulative_product(arr: List(Float)) -> List(Float)
Calculate the cumulative product of the elements in a list:
In the formula, is the ’th element in the cumulative product of elements. That is, is the length of the list and is the value in the input list indexed by . The value is thus the sum of the to first elements in the given list.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.cumulative_product()
|> should.equal([])
[1.0, 2.0, 3.0]
|> maths.cumulative_product()
|> should.equal([1.0, 2.0, 6.0])
}
pub fn cumulative_sum(arr: List(Float)) -> List(Float)
Calculate the cumulative sum of the elements in a list:
In the formula, is the ’th element in the cumulative sum of elements. That is, is the length of the list and is the value in the input list indexed by . The value is thus the sum of the to first elements in the given list.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.cumulative_sum()
|> should.equal([])
[1.0, 2.0, 3.0]
|> maths.cumulative_sum()
|> should.equal([1.0, 3.0, 6.0])
}
pub fn degrees_to_radians(x: Float) -> Float
Convert a value in degrees to a value measured in radians. That is, .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.degrees_to_radians(360.)
|> should.equal(2. *. maths.pi())
}
pub fn divisors(n: Int) -> List(Int)
The function returns all the positive divisors of an integer, including the number itself.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.divisors(4)
|> should.equal([1, 2, 4])
maths.divisors(6)
|> should.equal([1, 2, 3, 6])
maths.divisors(13)
|> should.equal([1, 13])
}
pub fn e() -> Float
Euler’s number .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(tolerance) = float.power(10.0, -6.0)
// Test that the constant is approximately equal to 2.7128...
maths.e()
|> maths.is_close(2.7182818284590452353602, 0.0, tolerance)
|> should.be_true()
}
pub fn euclidean_distance(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the Euclidean distance between two lists (representing vectors):
In the formula, is the length of the two lists and are the values in the respective input lists indexed by .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) = maths.euclidean_distance([#(1.0, 2.0), #(3.0, 4.0)])
result
|> maths.is_close(1.4142135623730951, 0.0, tolerance)
|> should.be_true()
}
pub fn euclidean_distance_with_weights(
arr: List(#(Float, Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted Euclidean distance between two lists (representing vectors):
In the formula, is the length of the two lists and are the values in the respective input lists indexed by , while the are corresponding positive weights.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) =
maths.euclidean_distance_with_weights([#(1.0, 2.0, 0.5), #(3.0, 4.0, 1.0)])
result
|> maths.is_close(1.224744871391589, 0.0, tolerance)
|> should.be_true()
}
pub fn euclidean_modulo(x: Int, y: Int) -> Int
Given two integers, (dividend) and (divisor), the Euclidean modulo of by , denoted as , is the remainder of the division of by , such that:
where is an integer that represents the quotient of the division.
Note that like the Gleam division operator /
this will return 0
if one of
the arguments is 0
.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.euclidean_modulo(15, 4)
|> should.equal(3)
maths.euclidean_modulo(-3, -2)
|> should.equal(1)
maths.euclidean_modulo(5, 0)
|> should.equal(0)
}
pub fn exponential(x: Float) -> Float
The exponential function:
where is Eulers’ number.
Note: If the input value is too large an overflow error might occur.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.exponential(0.0)
|> should.equal(1.0)
}
pub fn extrema(
arr: List(a),
compare: fn(a, a) -> Order,
) -> Result(#(a, a), Nil)
Returns a tuple consisting of the minimum and maximum values of a given list.
Example:
import gleam/float
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.extrema(float.compare)
|> should.be_error()
[4.0, 4.0, 3.0, 2.0, 1.0]
|> maths.extrema(float.compare)
|> should.equal(Ok(#(1.0, 4.0)))
}
pub fn factorial(n: Int) -> Result(Int, Nil)
A combinatorial function for computing the total number of combinations of elements, that is .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.factorial(-1)
|> should.be_error()
maths.factorial(0)
|> should.equal(Ok(1))
maths.factorial(3)
|> should.equal(Ok(6))
}
pub fn flip_sign(x: Float) -> Float
pub fn gamma(x: Float) -> Float
The gamma function over the real numbers. The function is essentially equal to the factorial for any positive integer argument:
The implemented gamma function is approximated through Lanczos approximation using the same coefficients used by the GNU Scientific Library.
pub fn gcd(x: Int, y: Int) -> Int
The function calculates the greatest common divisor of two integers . The greatest common divisor is the largest positive integer that is divisible by both and .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.gcd(1, 1)
|> should.equal(1)
maths.gcd(100, 10)
|> should.equal(10)
maths.gcd(-36, -17)
|> should.equal(1)
}
pub fn geometric_mean(arr: List(Float)) -> Result(Float, Nil)
Calculate the geometric mean of the elements in a list:
In the formula, is the sample size (the length of the list) and is the sample point in the input list indexed by . Note: The geometric mean is only defined for positive numbers.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
|> maths.geometric_mean()
|> should.be_error()
// List with negative numbers returns an error
[-1.0, -3.0, -6.0]
|> maths.geometric_mean()
|> should.be_error()
// Valid input returns a result
[1.0, 3.0, 9.0]
|> maths.geometric_mean()
|> should.equal(Ok(3.0))
}
pub fn geometric_space(
start: Float,
stop: Float,
steps: Int,
endpoint: Bool,
) -> Result(List(Float), Nil)
The function returns a list of a geometric progression between two specified
values, where each value is a constant multiple of the previous one. Unlike
logarithmic_space
, this function allows specifying the starting
and ending values (start
and stop
) directly, without requiring them to be transformed
into exponents.
Internally, the function computes the logarithms of start
and stop
and generates evenly
spaced points in the logarithmic domain (using base 10). These points are then transformed back
into their original scale to create a sequence of values that grow multiplicatively.
The start
and stop
values must be positive, as logarithms are undefined for non-positive
values. The number of points (steps
) must also be positive; specifying zero or a negative
value will result in an error.
Example:
import gleam/yielder
import gleeunit/should
import gleam_community/maths
pub fn example () {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(logspace) = maths.geometric_space(10.0, 1000.0, 3, True)
let pairs = logspace |> list.zip([10.0, 100.0, 1000.0])
let assert Ok(result) = maths.all_close(pairs, 0.0, tolerance)
result
|> list.all(fn(x) { x == True })
|> should.be_true()
// Input (start and stop can't be less than or equal to 0.0)
maths.geometric_space(0.0, 1000.0, 3, False)
|> should.be_error()
maths.geometric_space(-1000.0, 0.0, 3, False)
|> should.be_error()
// A negative number of points (-3) does not work
maths.geometric_space(10.0, 1000.0, -3, False)
|> should.be_error()
}
pub fn golden_ratio() -> Float
The golden ratio: .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.golden_ratio()
|> should.equal(1.618033988749895)
}
pub fn harmonic_mean(arr: List(Float)) -> Result(Float, Nil)
Calculate the harmonic mean of the elements in a list:
In the formula, is the sample size (the length of the list) and is the sample point in the input list indexed by . Note: The harmonic mean is only defined for positive numbers.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
|> maths.harmonic_mean()
|> should.be_error()
// List with negative numbers returns an error
[-1.0, -3.0, -6.0]
|> maths.harmonic_mean()
|> should.be_error()
// Valid input returns a result
[1.0, 3.0, 6.0]
|> maths.harmonic_mean()
|> should.equal(Ok(2.0))
}
pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, Nil)
The lower incomplete gamma function over the real numbers.
The implemented incomplete gamma function is evaluated through a power series expansion.
pub fn int_absolute_difference(a: Int, b: Int) -> Int
The absolute difference:
The function takes two inputs and and returns a positive integer value which is the absolute difference of the inputs.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.absolute_difference(-10, 10)
|> should.equal(20)
maths.absolute_difference(0, -2)
|> should.equal(2)
}
pub fn int_copy_sign(x: Int, y: Int) -> Int
The function takes two arguments and returns such that it has the same sign as .
pub fn int_cumulative_product(arr: List(Int)) -> List(Int)
Calculate the cumulative product of the elements in a list:
In the formula, is the ’th element in the cumulative product of elements. That is, is the length of the list and is the value in the input list indexed by . The value is thus the product of the to first elements in the given list.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.int_cumulative_product()
|> should.equal([])
[1, 2, 3]
|> maths.int_cumulative_product()
|> should.equal([1, 2, 6])
}
pub fn int_cumulative_sum(arr: List(Int)) -> List(Int)
Calculate the cumulative sum of the elements in a list:
In the formula, is the ’th element in the cumulative sum of elements. That is, is the length of the list and is the value in the input list indexed by . The value is thus the sum of the to first elements in the given list.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.int_cumulative_sum()
|> should.equal([])
[1, 2, 3]
|> maths.int_cumulative_sum()
|> should.equal([1, 3, 6])
}
pub fn int_flip_sign(x: Int) -> Int
pub fn int_sign(x: Int) -> Int
The function takes an input and returns the sign of the input, indicating whether it is positive (+1), negative (-1), or zero (0).
pub fn interquartile_range(
arr: List(Float),
) -> Result(Float, Nil)
Calculate the interquartile range (IQR) of the elements in a list.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
|> maths.interquartile_range()
|> should.be_error()
// Valid input returns a result
[1.0, 2.0, 3.0, 4.0, 5.0]
|> maths.interquartile_range()
|> should.equal(Ok(3.0))
}
pub fn is_between(x: Float, lower: Float, upper: Float) -> Bool
A function that tests whether a given real number is strictly between two other real numbers, , such that .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.is_between(5.5, 5.0, 6.0)
|> should.equal(True)
maths.is_between(5.0, 5.0, 6.0)
|> should.equal(False)
maths.is_between(6.0, 5.0, 6.0)
|> should.equal(False)
}
pub fn is_close(
x: Float,
y: Float,
rtol: Float,
atol: Float,
) -> Bool
Determine if a given value is close to or equivalent to a reference value based on supplied relative and absolute tolerance values. The equivalance of the two given values are then determined based on the equation:
True
is returned if the statement holds, otherwise False
is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example () {
let value = 99.
let reference_value = 100.
// We set 'absolute_tolerance' and 'relative_tolerance' such that the values are
// equivalent if 'value' is within 1 percent of 'reference_value' +/- 0.1
let relative_tolerance = 0.01
let absolute_tolerance = 0.10
maths.is_close(value, reference_value, relative_tolerance, absolute_tolerance)
|> should.be_true()
}
pub fn is_divisible(n: Int, d: Int) -> Bool
A function that tests whether a given integer is divisible by another integer , such that .
Details
For example:
- is divisible by because .
- is not divisible by because .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.is_divisible(10, 2)
|> should.equal(True)
maths.is_divisible(7, 3)
|> should.equal(False)
}
pub fn is_fractional(x: Float) -> Bool
Determine if a given value is fractional, i.e., if it contains a fractional part:
True
is returned if the given value is fractional (i.e., it has a non-zero decimal part),
otherwise False
is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example () {
maths.is_fractional(0.3333)
|> should.equal(True)
maths.is_fractional(1.0)
|> should.equal(False)
}
pub fn is_multiple(m: Int, k: Int) -> Bool
A function that tests whether a given integer is a multiple of another integer , such that , with .
Details
For example:
- is a multiple of because .
- is not a multiple of because does not yield an integer quotient.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.is_multiple(15, 5)
|> should.equal(True)
maths.is_multiple(14, 5)
|> should.equal(False)
}
pub fn is_perfect(n: Int) -> Bool
A function that tests whether a given integer value is a perfect number. A number is perfect if it is equal to the sum of its proper positive divisors.
Details
For example:
- is a perfect number since the divisors of 6 are .
- is a perfect number since the divisors of 28 are .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.is_perfect(6)
|> should.equal(True)
maths.is_perfect(28)
|> should.equal(True)
}
pub fn is_power(x: Int, y: Int) -> Bool
A function that determines if a given integer value is a power of another integer value , i.e., the function evaluates whether can be expressed as for some integer , by computing the base- logarithm of :
If is an integer (i.e., it has no fractional part), then is a power of
and True
is returned. Otherwise False
is returned.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
// Check if 4 is a power of 2 (it is)
maths.is_power(4, 2)
|> should.equal(True)
// Check if 5 is a power of 2 (it is not)
maths.is_power(5, 2)
|> should.equal(False)
}
pub fn is_prime(x: Int) -> Bool
A function that tests whether a given integer value is a prime number. A prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself.
The function uses the Miller-Rabin primality test to assess if is prime. It is a probabilistic test, so it can mistakenly identify a composite number as prime. However, the probability of such errors decreases with more testing iterations (the function uses 64 iterations internally, which is typically more than sufficient). The Miller-Rabin test is particularly useful for large numbers.
Details
Examples of prime numbers:
- is a prime number since it has only two divisors: and .
- is a prime number since it has only two divisors: and .
- is not a prime number since it has divisors other than and itself, such as .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.is_prime(2)
|> should.equal(True)
maths.is_prime(4)
|> should.equal(False)
// Test the 2nd Carmichael number
maths.is_prime(1105)
|> should.equal(False)
}
pub fn jaccard_index(xset: Set(a), yset: Set(a)) -> Float
The Jaccard index measures similarity between two sets of elements. Mathematically, the Jaccard index is defined as:
where:
- and are two sets being compared
- represents the size of the intersection of the two sets
- denotes the size of the union of the two sets
The value of the Jaccard index ranges from 0 to 1, where 0 indicates that the two sets share no elements and 1 indicates that the sets are identical. The Jaccard index is a special case of the Tversky index (with ).
Example:
import gleam/set
import gleeunit/should
import gleam_community/maths
pub fn example () {
let xset = set.from_list(["cat", "dog", "hippo", "monkey"])
let yset = set.from_list(["monkey", "rhino", "ostrich", "salmon"])
maths.jaccard_index(xset, yset)
|> should.equal(1.0 /. 7.0)
}
pub fn kurtosis(arr: List(Float)) -> Result(Float, Nil)
Calculate the sample kurtosis of a list of elements using the definition of Fisher.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
|> maths.kurtosis()
|> should.be_error()
// To calculate kurtosis at least four values are needed
[1.0, 2.0, 3.0]
|> maths.kurtosis()
|> should.be_error()
[1.0, 2.0, 3.0, 4.0]
|> maths.kurtosis()
|> should.equal(Ok(-1.36))
}
pub fn lcm(x: Int, y: Int) -> Int
The function calculates the least common multiple of two integers . The least common multiple is the smallest positive integer that has both and as factors.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.lcm(1, 1)
|> should.equal(1)
maths.lcm(100, 10)
|> should.equal(100)
maths.lcm(-36, -17)
|> should.equal(612)
}
pub fn linear_space(
start: Float,
stop: Float,
steps: Int,
endpoint: Bool,
) -> Result(List(Float), Nil)
The function returns a list of linearly spaced points over a specified interval. The endpoint of the interval can optionally be included/excluded. The number of points and whether the endpoint is included determine the spacing between values.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(linspace) = maths.linear_space(10.0, 20.0, 5, True)
let pairs = linspace |> list.zip([10.0, 12.5, 15.0, 17.5, 20.0])
let assert Ok(result) = maths.all_close(pairs, 0.0, tolerance)
result
|> list.all(fn(x) { x == True })
|> should.be_true()
// A negative number of points (-5) does not work
maths.linear_space(10.0, 50.0, -5, True)
|> should.be_error()
}
pub fn list_combination(
arr: List(a),
k: Int,
) -> Result(Yielder(List(a)), Nil)
Generates all possible combinations of elements selected from a given list of size . The function handles the case without repetitions, that is, repeated elements are not treated as distinct.
Example:
import gleam/yielder
import gleeunit/should
import gleam_community/maths
pub fn example () {
// All 2-combinations of [1, 2, 3] without repetition
let assert Ok(combinations) = maths.list_combination([1, 2, 3], 2)
combinations
|> yielder.to_list()
|> should.equal([[1, 2], [1, 3], [2, 3]])
}
pub fn list_combination_with_repetitions(
arr: List(a),
k: Int,
) -> Result(Yielder(List(a)), Nil)
Generates all possible combinations of elements selected from a given list of size . The function handles the case when the repetition of elements is allowed, that is, repeated elements are treated as distinct.
Example:
import gleam/yielder
import gleeunit/should
import gleam_community/maths
pub fn example () {
// All 2-combinations of [1, 2, 3] with repetition
let assert Ok(combinations) =
maths.list_combination_with_repetitions([1, 2, 3], 2)
combinations
|> yielder.to_list()
|> should.equal([[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]])
}
pub fn list_maximum(
arr: List(a),
compare: fn(a, a) -> Order,
) -> Result(a, Nil)
Returns the maximum value of a given list.
Example:
import gleam/float
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.list_maximum(float.compare)
|> should.be_error()
[4.0, 4.0, 3.0, 2.0, 1.0]
|> maths.list_maximum(float.compare)
|> should.equal(Ok(4.0))
}
pub fn list_minimum(
arr: List(a),
compare: fn(a, a) -> Order,
) -> Result(a, Nil)
Returns the minimum value of a given list.
Example:
import gleam/int
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.list_minimum(int.compare)
|> should.be_error()
[4, 4, 3, 2, 1]
|> maths.list_minimum(int.compare)
|> should.equal(Ok(1))
}
pub fn list_permutation(
arr: List(a),
k: Int,
) -> Result(Yielder(List(a)), Nil)
Generates all possible permutations of elements selected from a given list of size . The function handles the case without repetitions, that is, repeated elements are not treated as distinct.
Example:
import gleam/yielder
import gleeunit/should
import gleam_community/maths
pub fn example () {
// All 2-permutations of [1, 2] without repetition
let assert Ok(permutations) =
[1, 2]
|> maths.list_permutation(2)
permutations
|> yielder.to_list()
|> should.equal([[1, 2], [2, 1]])
}
pub fn list_permutation_with_repetitions(
arr: List(a),
k: Int,
) -> Result(Yielder(List(a)), Nil)
Generates all possible permutations of elements selected from a given list of size . The function handles the case when the repetition of elements is allowed, that is, repeated elements are treated as distinct.
Example:
import gleam/yielder
import gleeunit/should
import gleam_community/maths
pub fn example () {
// All 2-permutations of [1, 2] with repetition
let assert Ok(permutations) =
[1, 2]
|> maths.list_permutation_with_repetitions(2)
permutations
|> yielder.to_list()
|> set.from_list()
|> should.equal(set.from_list([[1, 1], [1, 2], [2, 2], [2, 1]]))
}
pub fn logarithm(x: Float, base: Float) -> Result(Float, Nil)
The base logarithm function (computed through the “change of base” formula):
The function takes a number in its domain and a base as input and returns a numeric value that lies in the range . If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example () {
maths.logarithm(1.0, 10.0)
|> should.equal(Ok(0.0))
maths.logarithm(maths.e(), maths.e())
|> should.equal(Ok(1.0))
maths.logarithm(-1.0, 2.0)
|> should.be_error()
}
pub fn logarithm_10(x: Float) -> Result(Float, Nil)
The base-10 logarithm function:
The function takes a number in its domain as input and returns a numeric value that lies in the range . If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example () {
maths.logarithm_10(1.0)
|> should.equal(Ok(0.0))
maths.logarithm_10(10.0)
|> should.equal(Ok(1.0))
maths.logarithm_10(-1.0)
|> should.be_error()
}
pub fn logarithm_2(x: Float) -> Result(Float, Nil)
The base-2 logarithm function:
The function takes a number in its domain as input and returns a numeric value that lies in the range . If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example () {
maths.logarithm_2(1.0)
|> should.equal(Ok(0.0))
maths.logarithm_2(2.0)
|> should.equal(Ok(1.0))
maths.logarithm_2(-1.0)
|> should.be_error()
}
pub fn logarithmic_space(
start: Float,
stop: Float,
steps: Int,
endpoint: Bool,
base: Float,
) -> Result(List(Float), Nil)
The function returns a list of logarithmically spaced points over a specified interval. The endpoint of the interval can optionally be included/excluded. The number of points, base, and whether the endpoint is included determine the spacing between values.
The values in the sequence are computed as powers of the given base, where
the exponents are evenly spaced between start
and stop
. The base
parameter must be positive, as negative bases lead to undefined behavior when
computing fractional exponents. Similarly, the number of points (steps
) must
be positive; specifying zero or a negative value will result in an error.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(logspace) = maths.logarithmic_space(1.0, 3.0, 3, True, 10.0)
let pairs = logspace |> list.zip([10.0, 100.0, 1000.0])
let assert Ok(result) = maths.all_close(pairs, 0.0, tolerance)
result
|> list.all(fn(x) { x == True })
|> should.be_true()
// A negative number of points (-3) does not work
maths.logarithmic_space(1.0, 3.0, -3, False, 10.0)
|> should.be_error()
}
pub fn manhattan_distance(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the Manhattan distance between two lists (representing vectors):
In the formula, is the length of the two lists and are the values in the respective input lists indexed by .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.manhattan_distance([#(1.0, 2.0), #(2.0, 3.0)])
|> should.equal(Ok(2.0))
}
pub fn manhattan_distance_with_weights(
arr: List(#(Float, Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted Manhattan distance between two lists (representing vectors):
In the formula, is the length of the two lists and are the values in the respective input lists indexed by , while the are corresponding positive weights.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.manhattan_distance_with_weights([#(1.0, 2.0, 0.5), #(2.0, 3.0, 1.0)])
|> should.equal(Ok(1.5))
}
pub fn mean(arr: List(Float)) -> Result(Float, Nil)
Calculate the arithmetic mean of the elements in a list:
In the formula, is the sample size (the length of the list) and is the sample point in the input list indexed by .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.mean()
|> should.be_error()
[1.0, 2.0, 3.0]
|> maths.mean()
|> should.equal(Ok(2.0))
}
pub fn median(arr: List(Float)) -> Result(Float, Nil)
Calculate the median of the elements in a list.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.median()
|> should.be_error()
[1.0, 2.0, 3.0]
|> maths.median()
|> should.equal(Ok(2.0))
[1.0, 2.0, 3.0, 4.0]
|> maths.median()
|> should.equal(Ok(2.5))
}
pub fn minkowski_distance(
arr: List(#(Float, Float)),
p: Float,
) -> Result(Float, Nil)
Calculate the Minkowski distance between two lists (representing vectors):
In the formula, is the order, is the length of the two lists and are the values in the respective input lists indexed by .
The Minkowski distance is a generalization of the Euclidean distance () and the Manhattan distance ().
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) =
maths.minkowski_distance([#(1.0, 2.0), #(3.0, 4.0), #(5.0, 6.0)], 4.0)
result
|> maths.is_close(1.3160740129524924, 0.0, tolerance)
|> should.be_true()
}
pub fn minkowski_distance_with_weights(
arr: List(#(Float, Float, Float)),
p: Float,
) -> Result(Float, Nil)
Calculate the weighted Minkowski distance between two lists (representing vectors):
In the formula, is the order, is the length of the two lists and are the values in the respective input lists indexed by . The are corresponding positive weights.
The Minkowski distance is a generalization of the Euclidean distance () and the Manhattan distance ().
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) =
maths.minkowski_distance_with_weights(
[#(1.0, 2.0, 0.5), #(3.0, 4.0, 1.0), #(5.0, 6.0, 1.0)],
4.0,
)
result
|> maths.is_close(1.2574334296829355, 0.0, tolerance)
|> should.be_true()
}
pub fn minmax(x: a, y: a, compare: fn(a, a) -> Order) -> #(a, a)
The minmax function takes two arguments along with a function for comparing . The function returns a tuple with the smallest value first and largest second.
Example
import gleam/float
import gleam/int
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.minmax(2.0, 1.5, float.compare)
|> should.equal(#(1.5, 2.0))
maths.minmax(1, 2, int.compare)
|> should.equal(#(1, 2))
}
pub fn moment(arr: List(Float), n: Int) -> Result(Float, Nil)
Calculate the n’th moment about the mean of a list of elements.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
|> maths.moment(0)
|> should.be_error()
// 0th moment about the mean is 1. per definition
[0.0, 1.0, 2.0, 3.0, 4.0]
|> maths.moment(0)
|> should.equal(Ok(1.0))
// 1st moment about the mean is 0. per definition
[0.0, 1.0, 2.0, 3.0, 4.0]
|> maths.moment(1)
|> should.equal(Ok(0.0))
// 2nd moment about the mean
[0.0, 1.0, 2.0, 3.0, 4.0]
|> maths.moment(2)
|> should.equal(Ok(2.0))
}
pub fn natural_logarithm(x: Float) -> Result(Float, Nil)
The natural logarithm function:
The function takes a number in its domain as input and returns a numeric value that lies in the range . If the input value is outside the domain of the function an error is returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example () {
maths.natural_logarithm(1.0)
|> should.equal(Ok(0.0))
maths.natural_logarithm(maths.e())
|> should.equal(Ok(1.0))
maths.natural_logarithm(-1.0)
|> should.be_error()
}
pub fn norm(arr: List(Float), p: Float) -> Result(Float, Nil)
Calculate the -norm of a list (representing a vector):
In the formula, is the length of the list and is the value in the input list indexed by .
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
[1.0, 1.0, 1.0]
|> maths.norm(1.0)
|> should.equal(Ok(3.0))
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) =
[1.0, 2.0, 3.0]
|> maths.norm(2.0)
result
|> maths.is_close(3.7416573867739413, 0.0, tolerance)
|> should.be_true()
}
pub fn norm_with_weights(
arr: List(#(Float, Float)),
p: Float,
) -> Result(Float, Nil)
Calculate the weighted -norm of a list (representing a vector):
In the formula, is the length of the list and is the value in the input list indexed by , while is a corresponding positive weight.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
[#(1.0, 0.5), #(1.0, 0.5), #(1.0, 0.5)]
|> maths.norm_with_weights(1.0)
|> should.equal(Ok(1.5))
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) =
[#(1.0, 0.5), #(2.0, 0.5), #(3.0, 0.5)]
|> maths.norm_with_weights(2.0)
result
|> maths.is_close(2.6457513110645907, 0.0, tolerance)
|> should.be_true()
}
pub fn nth_root(x: Float, n: Int) -> Result(Float, Nil)
The ’th root function: .
Note that the function is not defined if the input is negative (). An error will be returned as an imaginary number will otherwise have to be returned.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.nth_root(-1.0, 2)
|> should.be_error()
maths.nth_root(1.0, 2)
|> should.equal(Ok(1.0))
maths.nth_root(27.0, 3)
|> should.equal(Ok(3.0))
maths.nth_root(256.0, 4)
|> should.equal(Ok(4.0))
}
pub fn overlap_coefficient(xset: Set(a), yset: Set(a)) -> Float
The Overlap coefficient, also known as the Szymkiewicz–Simpson coefficient, is a measure of similarity between two sets that focuses on the size of the intersection relative to the smaller of the two sets. It is defined mathematically as:
where:
- and are the sets being compared
- is the size of the intersection of the sets
- is the size of the smaller set among and
The coefficient ranges from 0 to 1, where 0 indicates no overlap and 1 indicates that the smaller set is a suyset of the larger set. This measure is especially useful in situations where the similarity in terms of the proportion of overlap is more relevant than the difference in sizes between the two sets.
Example:
import gleam/set
import gleeunit/should
import gleam_community/maths
pub fn example () {
let set_a = set.from_list(["horse", "dog", "hippo", "monkey", "bird"])
let set_b = set.from_list(["monkey", "bird", "ostrich", "salmon"])
maths.overlap_coefficient(set_a, set_b)
|> should.equal(2.0 /. 4.0)
}
pub fn percentile(arr: List(Float), n: Int) -> Result(Float, Nil)
Calculate the n’th percentile of the elements in a list using linear interpolation between closest ranks.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
|> maths.percentile(40)
|> should.be_error()
// Calculate 40th percentile
[15.0, 20.0, 35.0, 40.0, 50.0]
|> maths.percentile(40)
|> should.equal(Ok(29.0))
}
pub fn permutation(n: Int, k: Int) -> Result(Int, Nil)
A combinatorial function for computing the number of -permutations without repetitions:
The implementation uses an efficient iterative multiplicative formula for computing the result.
Details
A -permutation without repetitions is a sequence of elements selected from
elements where the order of selection matters and elements are not allowed to repeat.
For example, consider selecting 2 elements from a list of 3 elements: ["A", "B", "C"]
. In
this case, possible selections are:
["A", "B"], ["B", "A"]
["A", "C"], ["C", "A"]
["B", "C"], ["C", "B"]
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.permutation(-1, 1)
|> should.be_error()
maths.permutation(4, 0)
|> should.equal(Ok(1))
maths.permutation(4, 2)
|> should.equal(Ok(12))
maths.permutation(13, 5)
|> should.equal(Ok(154_440))
}
pub fn permutation_with_repetitions(
n: Int,
k: Int,
) -> Result(Int, Nil)
A combinatorial function for computing the number of -permutations with repetitions:
Details
A -permutation with repetitions is a sequence of elements selected from
elements where the order of selection matters and elements are allowed to repeat. For example,
consider selecting 2 elements from a list of 3 elements: ["A", "B", "C"]
. In this case,
possible selections are:
["A", "A"], ["A", "B"], ["A", "C"]
["B", "A"], ["B", "B"], ["B", "C"]
["C", "A"], ["C", "B"], ["C", "C"]
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.permutation_with_repetitions(1, -1)
|> should.be_error()
maths.permutation_with_repetitions(2, 3)
|> should.equal(Ok(8))
maths.permutation_with_repetitions(4, 4)
|> should.equal(Ok(256))
maths.permutation_with_repetitions(6, 3)
|> should.equal(Ok(216))
}
pub fn polar_to_cartesian(
r: Float,
theta: Float,
) -> #(Float, Float)
Converts polar coordinates to Cartesian coordinates .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.polar_to_cartesian(1.0, 0.0)
|> should.equal(#(1.0, 0.0))
maths.polar_to_cartesian(1.0, float.pi() /. 2.0)
|> should.equal(#(0.0, 1.0))
}
pub fn proper_divisors(n: Int) -> List(Int)
The function returns all the positive divisors of an integer, excluding the number itself.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.proper_divisors(4)
|> should.equal([1, 2])
maths.proper_divisors(6)
|> should.equal([1, 2, 3])
maths.proper_divisors(13)
|> should.equal([1])
}
pub fn radians_to_degrees(x: Float) -> Float
Convert a value in degrees to a value measured in radians. That is, .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.radians_to_degrees(0.0)
|> should.equal(0.0)
maths.radians_to_degrees(2. *. maths.pi())
|> should.equal(360.)
}
pub fn round_down(x: Float, p: Int) -> Float
The function rounds a float to a specific number of digits (after the decimal place or before
if negative). In particular, the input is rounded to the nearest integer value (at the
specified digit) that is less than or equal to the input . This rounding behaviour is
similar to behaviour of the Gleam stdlib floor
function.
Details
The rounding mode rounds to:
- for 0 digits after the decimal point (
digits = 0
) - for 1 digits after the decimal point (
digits = 1
) - for 2 digits after the decimal point (
digits = 2
) - 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 1 digit before the decimal point (
digits = -1
) - for 2 digits before the decimal point (
digits = -2
) - for 3 digits before the decimal point (
digits = -3
)
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.round_down(12.0654, 2)
|> should.equal(12.06)
}
pub fn round_ties_away(x: Float, p: Int) -> Float
The function rounds a float to a specific number of digits (after the decimal place or before if negative). In particular, the input 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 behaviour).
Details
The rounding mode rounds to:
- for 0 digits after the decimal point (
digits = 0
) - for 1 digit after the decimal point (
digits = 1
) - for 2 digits after the decimal point (
digits = 2
) - 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 1 digit before the decimal point (
digits = -1
) - for 2 digits before the decimal point (
digits = -2
) - for 3 digits before the decimal point (
digits = -3
)
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.round_ties_away(12.0654, 2)
|> should.equal(12.07)
}
pub fn round_ties_up(x: Float, p: Int) -> Float
The function rounds a float to a specific number of digits (after the decimal place or before if negative). In particular, the input is rounded to the nearest integer value (at the specified digit) with ties (fractional values of 0.5) being rounded towards (Java/JavaScript rounding behaviour).
Details
The rounding mode rounds to:
- for 0 digits after the decimal point (
digits = 0
) - for 1 digits after the decimal point (
digits = 1
) - for 2 digits after the decimal point (
digits = 2
) - 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 1 digit before the decimal point (
digits = -1
) - for 2 digits before the decimal point (
digits = -2
) - for 3 digits before the decimal point (
digits = -3
)
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.round_ties_up(12.0654, 2)
|> should.equal(12.07)
}
pub fn round_to_nearest(x: Float, p: Int) -> Float
The function rounds a float to a specific number of digits (after the decimal place or before if negative). In particular, the input 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.
Details
The rounding mode rounds to:
- for 0 digits after the decimal point (
digits = 0
) - for 1 digit after the decimal point (
digits = 1
) - for 2 digits after the decimal point (
digits = 2
) - 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 1 digit before the decimal point (
digits = -1
) - for 2 digits before the decimal point (
digits = -2
) - for 3 digits before the decimal point (
digits = -3
)
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.round_to_nearest(12.0654, 2)
|> should.equal(12.07)
}
pub fn round_to_zero(x: Float, p: Int) -> Float
The function rounds a float to a specific number of digits (after the decimal place or before
if negative). In particular, the input is rounded to the nearest integer value (at the
specified digit) that is less than or equal to the absolute value of the input . This
rounding behaviour is similar to behaviour of the Gleam stdlib truncate
function.
Details
The rounding mode rounds to:
- for 0 digits after the decimal point (
digits = 0
) - for 1 digit after the decimal point (
digits = 1
) - for 2 digits after the decimal point (
digits = 2
) - 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 1 digit before the decimal point (
digits = -1
) - for 2 digits before the decimal point (
digits = -2
) - for 3 digits before the decimal point (
digits = -3
)
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.round_to_zero(12.0654, 2)
|> should.equal(12.06)
}
pub fn round_up(x: Float, p: Int) -> Float
The function rounds a float to a specific number of digits (after the decimal place or before
if negative). In particular, the input is rounded to the nearest integer value (at the
specified digit) that is larger than or equal to the input . This rounding behaviour is
similar to behaviour of the Gleam stdlib ceiling
function.
Details
The rounding mode rounds to:
- for 0 digits after the decimal point (
digits = 0
) - for 1 digit after the decimal point (
digits = 1
) - for 2 digits after the decimal point (
digits = 2
) - 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 1 digit places before the decimal point (
digit = -1
) - for 2 digits before the decimal point (
digits = -2
) - for 3 digits before the decimal point (
digits = -3
)
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.round_up(12.0654, 2)
|> should.equal(12.07)
}
pub fn sign(x: Float) -> Float
The function takes an input and returns the sign of the input, indicating whether it is positive (+1.0), negative (-1.0), or zero (0.0).
pub fn sin(x: Float) -> Float
The sine function:
The function takes a number in its domain (an angle in radians) as input and returns a numeric value that lies in the range .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.sin(0.0)
|> should.equal(0.0)
maths.sin(0.5 *. maths.pi())
|> should.equal(1.0)
}
pub fn sinh(x: Float) -> Float
The hyperbolic sine function:
The function takes a number in its domain as input (an angle in radians) and returns a numeric value that lies in the range . If the input value is too large an overflow error might occur.
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.sinh(0.0)
|> should.equal(0.0)
}
pub fn skewness(arr: List(Float)) -> Result(Float, Nil)
Calculate the sample skewness of a list of elements using the Fisher-Pearson coefficient of skewness.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
|> maths.skewness()
|> should.be_error()
// To calculate skewness at least three values are needed
[1.0, 2.0, 3.0]
|> maths.skewness()
|> should.equal(Ok(0.0))
[1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 4.0]
|> maths.skewness()
|> should.equal(Ok(0.6))
}
pub fn sorensen_dice_coefficient(
xset: Set(a),
yset: Set(a),
) -> Float
The Sørensen-Dice coefficient measures the similarity between two sets of elements. Mathematically, the coefficient is defined as:
where:
- and are two sets being compared
- is the size of the intersection of the two sets (i.e., the number of elements common to both sets)
- and are the sizes of the sets and , respectively
The coefficient ranges from 0 to 1, where 0 indicates no similarity (the sets share no elements) and 1 indicates perfect similarity (the sets are identical). The higher the coefficient, the greater the similarity between the two sets. The Sørensen-Dice coefficient is a special case of the Tversky index (with ).
Example:
import gleam/set
import gleeunit/should
import gleam_community/maths
pub fn example () {
let xset = set.from_list(["cat", "dog", "hippo", "monkey"])
let yset = set.from_list(["monkey", "rhino", "ostrich", "salmon", "spider"])
maths.sorensen_dice_coefficient(xset, yset)
|> should.equal(2.0 *. 1.0 /. { 4.0 +. 5.0 })
}
pub fn standard_deviation(
arr: List(Float),
ddof: Int,
) -> Result(Float, Nil)
Calculate the sample standard deviation of the elements in a list:
In the formula, is the sample size (the length of the list) and is the sample point in the input list indexed by . Furthermore, is the sample mean and is the “Delta Degrees of Freedom”, and is typically set to , which gives an unbiased estimate.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// Degrees of freedom
let ddof = 1
[]
|> maths.standard_deviation(ddof)
|> should.be_error()
[1.0, 2.0, 3.0]
|> maths.standard_deviation(ddof)
|> should.equal(Ok(1.0))
}
pub fn step_range(
start: Float,
stop: Float,
increment: Float,
) -> List(Float)
The function returns a list of evenly spaced values within a specified interval
[start, stop)
based on a given increment size.
Note that if increment > 0
, the sequence progresses from start
towards stop
, while if
increment < 0
, the sequence progresses from start
towards stop
in reverse.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
maths.step_range(1.0, 5.0, 1.0)
|> should.equal([1.0, 2.0, 3.0, 4.0])
// No points returned since
// start is smaller than stop and the step is positive
maths.step_range(5.0, 1.0, 1.0)
|> should.equal([])
// Points returned since
// start smaller than stop but negative step
maths.step_range(5.0, 1.0, -1.0)
|> should.equal([5.0, 4.0, 3.0, 2.0])
}
pub fn symmetric_space(
center: Float,
radius: Float,
steps: Int,
) -> Result(List(Float), Nil)
Generates evenly spaced points around a center value. The total span (around the center value)
is determined by the radius
argument of the function.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(symspace) = maths.symmetric_space(0.0, 5.0, 5)
symspace
|> should.equal([-5.0, -2.5, 0.0, 2.5, 5.0])
// A negative radius reverses the order of the values
let assert Ok(symspace) = maths.symmetric_space(0.0, -5.0, 5)
symspace
|> should.equal([5.0, 2.5, 0.0, -2.5, -5.0])
}
pub fn tan(x: Float) -> Float
The tangent function:
The function takes a number in its domain as input (an angle in radians) and returns a numeric value that lies in the range .
Example
import gleeunit/should
import gleam_community/maths
pub fn example() {
maths.tan(0.0)
|> should.equal(0.0)
}
pub fn tanh(x: Float) -> Float
The hyperbolic tangent function:
The function takes a number in its domain as input (an angle in radians) and returns a numeric value that lies in the range .
Example
import gleeunit/should
import gleam_community/maths
pub fn example () {
maths.tanh(0.0)
|> should.equal(0.0)
maths.tanh(25.0)
|> should.equal(1.0)
maths.tanh(-25.0)
|> should.equal(-1.0)
}
pub fn tau() -> Float
pub fn tversky_index(
xset: Set(a),
yset: Set(a),
alpha: Float,
beta: Float,
) -> Result(Float, Nil)
The Tversky index is a generalization of the Jaccard index and Sørensen-Dice coefficient, which adds flexibility in measuring similarity between two sets using two parameters, and . These parameters allow for asymmetric similarity measures between sets. The Tversky index is defined as:
where:
- and are the sets being compared
- and are the sizes of the relative complements of in and in , respectively,
- and are parameters that weight the relative importance of the elements unique to and
The Tversky index reduces to the Jaccard index when and to the Sørensen-Dice coefficient when . In general, the Tversky index can take on any non-negative value, including 0. The index equals 0 when there is no intersection between the two sets, indicating no similarity. The Tversky index does not have a strict upper limit of 1 when .
Example:
import gleam/set
import gleeunit/should
import gleam_community/maths
pub fn example () {
let yset = set.from_list(["cat", "dog", "hippo", "monkey"])
let xset = set.from_list(["monkey", "rhino", "ostrich", "salmon"])
// Test Jaccard index (alpha = beta = 1)
maths.tversky_index(xset, yset, 1.0, 1.0)
|> should.equal(Ok(1.0 /. 7.0))
}
pub fn variance(
arr: List(Float),
ddof: Int,
) -> Result(Float, Nil)
Calculate the sample variance of the elements in a list:
In the formula, is the sample size (the length of the list) and is the sample point in the input list indexed by . Furthermore, is the sample mean and is the “Delta Degrees of Freedom”. It is typically set to , which gives an unbiased estimate.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// Degrees of freedom
let ddof = 1
[]
|> maths.variance(ddof)
|> should.be_error()
[1.0, 2.0, 3.0]
|> maths.variance(ddof)
|> should.equal(Ok(1.0))
}
pub fn weighted_product(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted product of the elements in a list:
In the formula, is the length of the list and is the value in the input list indexed by , while the are corresponding positive weights.
Example:
import gleam/float
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.weighted_product()
|> should.equal(Ok(1.0))
[#(1.0, 1.0), #(2.0, 1.0), #(3.0, 1.0)]
|> maths.weighted_product()
|> should.equal(Ok(6.0))
let assert Ok(tolerance) = float.power(10.0, -6.0)
let assert Ok(result) =
[#(9.0, 0.5), #(10.0, 0.5), #(10.0, 0.5)]
|> maths.weighted_product()
result
|> maths.is_close(30.0, 0.0, tolerance)
|> should.be_true()
}
pub fn weighted_sum(
arr: List(#(Float, Float)),
) -> Result(Float, Nil)
Calculate the weighted sum of the elements in a list:
In the formula, is the length of the list and is the value in the input list indexed by , while the are corresponding positive weights.
Example:
import gleam/float
import gleeunit/should
import gleam_community/maths
pub fn example () {
[]
|> maths.weighted_sum()
|> should.equal(Ok(0.0))
[#(1.0, 1.0), #(2.0, 1.0), #(3.0, 1.0)]
|> maths.weighted_sum()
|> should.equal(Ok(6.0))
[#(9.0, 0.5), #(10.0, 0.5), #(10.0, 0.5)]
|> maths.weighted_sum()
|> should.equal(Ok(14.5))
}
pub fn yield_geometric_space(
start: Float,
stop: Float,
steps: Int,
endpoint: Bool,
) -> Result(Yielder(Float), Nil)
The function is similar to geometric_space
but instead returns a yielder
(lazily evaluated sequence of elements). This function can be used whenever there is a need
to generate a larger-than-usual sequence of elements.
Example:
import gleam/yielder.{Next, Done}
import gleeunit/should
import gleam_community/maths
pub fn example () {
let assert Ok(logspace) = maths.yield_geometric_space(10.0, 1000.0, 3, True)
let assert Next(element, rest) = yielder.step(logspace)
should.equal(element, 10.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 100.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 1000.0)
// We have generated 3 values, so the 4th will be 'Done'
should.equal(yielder.step(rest), Done)
}
pub fn yield_linear_space(
start: Float,
stop: Float,
steps: Int,
endpoint: Bool,
) -> Result(Yielder(Float), Nil)
The function is similar to linear_space
but instead returns a yielder
(lazily evaluated sequence of elements). This function can be used whenever there is a need
to generate a larger-than-usual sequence of elements.
Example:
import gleam/yielder.{Next, Done}
import gleeunit/should
import gleam_community/maths
pub fn example () {
let assert Ok(linspace) = maths.yield_linear_space(10.0, 20.0, 5, True)
let assert Next(element, rest) = yielder.step(linspace)
should.equal(element, 10.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 12.5)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 15.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 17.5)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 20.0)
// We have generated 5 values, so the 6th will be 'Done'
should.equal(yielder.step(rest), Done)
}
pub fn yield_logarithmic_space(
start: Float,
stop: Float,
steps: Int,
endpoint: Bool,
base: Float,
) -> Result(Yielder(Float), Nil)
The function is similar to logarithmic_space
but instead returns a yielder
(lazily evaluated sequence of elements). This function can be used whenever there is a need
to generate a larger-than-usual sequence of elements.
Example:
import gleam/yielder.{Next, Done}
import gleeunit/should
import gleam_community/maths
pub fn example () {
let assert Ok(logspace) =
maths.yield_logarithmic_space(1.0, 3.0, 3, True, 10.0)
let assert Next(element, rest) = yielder.step(logspace)
should.equal(element, 10.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 100.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 1000.0)
// We have generated 3 values, so the 4th will be 'Done'
should.equal(yielder.step(rest), Done)
}
pub fn yield_step_range(
start: Float,
stop: Float,
increment: Float,
) -> Yielder(Float)
The function is similar to step_range
but instead returns a yielder
(lazily evaluated sequence of elements). This function can be used whenever there is a need
to generate a larger-than-usual sequence of elements.
Example:
import gleam/yielder.{Next, Done}
import gleeunit/should
import gleam_community/maths
pub fn example () {
let range = maths.yield_step_range(1.0, 2.5, 0.5)
let assert Next(element, rest) = yielder.step(range)
should.equal(element, 1.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 1.5)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 2.0)
// We have generated 3 values over the interval [1.0, 2.5)
// in increments of 0.5, so the 4th will be 'Done'
should.equal(yielder.step(rest), Done)
}
pub fn yield_symmetric_space(
center: Float,
radius: Float,
steps: Int,
) -> Result(Yielder(Float), Nil)
The function is similar to symmetric_space
but instead returns a yielder
(lazily evaluated sequence of elements). This function can be used whenever there is a need
to generate a larger-than-usual sequence of elements.
Example:
import gleam/yielder.{Next, Done}
import gleeunit/should
import gleam_community/maths
pub fn example() {
let assert Ok(symspace) = maths.yield_symmetric_space(0.0, 5.0, 5)
let assert Next(element, rest) = yielder.step(symspace)
should.equal(element, -5.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, -2.5)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 0.0)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 2.5)
let assert Next(element, rest) = yielder.step(rest)
should.equal(element, 5.0)
// We have generated 5 values, so the 6th will be 'Done'
should.equal(yielder.step(rest), Done)
}
pub fn zscore(
arr: List(Float),
ddof: Int,
) -> Result(List(Float), Nil)
Calculate the z-score of each value in the list relative to the sample mean and standard deviation.
Example:
import gleeunit/should
import gleam_community/maths
pub fn example () {
// An empty list returns an error
[]
// Use degrees of freedom = 1
|> maths.zscore(1)
|> should.be_error()
[1.0, 2.0, 3.0]
// Use degrees of freedom = 1
|> maths.zscore(1)
|> should.equal(Ok([-1.0, 0.0, 1.0]))
}