Initial commit

This commit is contained in:
Hugo Mårdbrink 2025-11-30 15:44:22 +01:00
commit a6272848f9
379 changed files with 74829 additions and 0 deletions

View file

@ -0,0 +1,553 @@
import { Ok, Error, Empty as $Empty, divideFloat } from "../gleam.mjs";
import * as $order from "../gleam/order.mjs";
import {
parse_float as parse,
float_to_string as to_string,
ceiling,
floor,
round as js_round,
truncate,
identity as do_to_float,
power as do_power,
random_uniform as random,
log as do_log,
exp as exponential,
} from "../gleam_stdlib.mjs";
export { ceiling, exponential, floor, parse, random, to_string, truncate };
/**
* Compares two `Float`s, returning an `Order`:
* `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.
*
* ## Examples
*
* ```gleam
* compare(2.0, 2.3)
* // -> Lt
* ```
*
* To handle
* [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems)
* you may use [`loosely_compare`](#loosely_compare) instead.
*/
export function compare(a, b) {
let $ = a === b;
if ($) {
return new $order.Eq();
} else {
let $1 = a < b;
if ($1) {
return new $order.Lt();
} else {
return new $order.Gt();
}
}
}
/**
* Compares two `Float`s, returning the smaller of the two.
*
* ## Examples
*
* ```gleam
* min(2.0, 2.3)
* // -> 2.0
* ```
*/
export function min(a, b) {
let $ = a < b;
if ($) {
return a;
} else {
return b;
}
}
/**
* Compares two `Float`s, returning the larger of the two.
*
* ## Examples
*
* ```gleam
* max(2.0, 2.3)
* // -> 2.3
* ```
*/
export function max(a, b) {
let $ = a > b;
if ($) {
return a;
} else {
return b;
}
}
/**
* Restricts a `Float` between a lower and upper bound.
*
* ## Examples
*
* ```gleam
* clamp(1.2, min: 1.4, max: 1.6)
* // -> 1.4
* ```
*/
export function clamp(x, min_bound, max_bound) {
let _pipe = x;
let _pipe$1 = min(_pipe, max_bound);
return max(_pipe$1, min_bound);
}
/**
* Returns the absolute value of the input as a `Float`.
*
* ## Examples
*
* ```gleam
* absolute_value(-12.5)
* // -> 12.5
* ```
*
* ```gleam
* absolute_value(10.2)
* // -> 10.2
* ```
*/
export function absolute_value(x) {
let $ = x >= 0.0;
if ($) {
return x;
} else {
return 0.0 - x;
}
}
/**
* Compares two `Float`s within a tolerance, returning an `Order`:
* `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.
*
* This function allows Float comparison while handling
* [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).
*
* Notice: For `Float`s the tolerance won't be exact:
* `5.3 - 5.0` is not exactly `0.3`.
*
* ## Examples
*
* ```gleam
* loosely_compare(5.0, with: 5.3, tolerating: 0.5)
* // -> Eq
* ```
*
* If you want to check only for equality you may use
* [`loosely_equals`](#loosely_equals) instead.
*/
export function loosely_compare(a, b, tolerance) {
let difference = absolute_value(a - b);
let $ = difference <= tolerance;
if ($) {
return new $order.Eq();
} else {
return compare(a, b);
}
}
/**
* Checks for equality of two `Float`s within a tolerance,
* returning an `Bool`.
*
* This function allows Float comparison while handling
* [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).
*
* Notice: For `Float`s the tolerance won't be exact:
* `5.3 - 5.0` is not exactly `0.3`.
*
* ## Examples
*
* ```gleam
* loosely_equals(5.0, with: 5.3, tolerating: 0.5)
* // -> True
* ```
*
* ```gleam
* loosely_equals(5.0, with: 5.1, tolerating: 0.1)
* // -> False
* ```
*/
export function loosely_equals(a, b, tolerance) {
let difference = absolute_value(a - b);
return difference <= tolerance;
}
/**
* Returns the results of the base being raised to the power of the
* exponent, as a `Float`.
*
* ## Examples
*
* ```gleam
* power(2.0, -1.0)
* // -> Ok(0.5)
* ```
*
* ```gleam
* power(2.0, 2.0)
* // -> Ok(4.0)
* ```
*
* ```gleam
* power(8.0, 1.5)
* // -> Ok(22.627416997969522)
* ```
*
* ```gleam
* 4.0 |> power(of: 2.0)
* // -> Ok(16.0)
* ```
*
* ```gleam
* power(-1.0, 0.5)
* // -> Error(Nil)
* ```
*/
export function power(base, exponent) {
let fractional = (ceiling(exponent) - exponent) > 0.0;
let $ = ((base < 0.0) && fractional) || ((base === 0.0) && (exponent < 0.0));
if ($) {
return new Error(undefined);
} else {
return new Ok(do_power(base, exponent));
}
}
/**
* Returns the square root of the input as a `Float`.
*
* ## Examples
*
* ```gleam
* square_root(4.0)
* // -> Ok(2.0)
* ```
*
* ```gleam
* square_root(-16.0)
* // -> Error(Nil)
* ```
*/
export function square_root(x) {
return power(x, 0.5);
}
/**
* Returns the negative of the value provided.
*
* ## Examples
*
* ```gleam
* negate(1.0)
* // -> -1.0
* ```
*/
export function negate(x) {
return -1.0 * x;
}
/**
* Rounds the value to the nearest whole number as an `Int`.
*
* ## Examples
*
* ```gleam
* round(2.3)
* // -> 2
* ```
*
* ```gleam
* round(2.5)
* // -> 3
* ```
*/
export function round(x) {
let $ = x >= 0.0;
if ($) {
return js_round(x);
} else {
return 0 - js_round(negate(x));
}
}
/**
* Converts the value to a given precision as a `Float`.
* The precision is the number of allowed decimal places.
* Negative precisions are allowed and force rounding
* to the nearest tenth, hundredth, thousandth etc.
*
* ## Examples
*
* ```gleam
* to_precision(2.43434348473, precision: 2)
* // -> 2.43
* ```
*
* ```gleam
* to_precision(547890.453444, precision: -3)
* // -> 548000.0
* ```
*/
export function to_precision(x, precision) {
let $ = precision <= 0;
if ($) {
let factor = do_power(10.0, do_to_float(- precision));
return do_to_float(round(divideFloat(x, factor))) * factor;
} else {
let factor = do_power(10.0, do_to_float(precision));
return divideFloat(do_to_float(round(x * factor)), factor);
}
}
function sum_loop(loop$numbers, loop$initial) {
while (true) {
let numbers = loop$numbers;
let initial = loop$initial;
if (numbers instanceof $Empty) {
return initial;
} else {
let first = numbers.head;
let rest = numbers.tail;
loop$numbers = rest;
loop$initial = first + initial;
}
}
}
/**
* Sums a list of `Float`s.
*
* ## Example
*
* ```gleam
* sum([1.0, 2.2, 3.3])
* // -> 6.5
* ```
*/
export function sum(numbers) {
return sum_loop(numbers, 0.0);
}
function product_loop(loop$numbers, loop$initial) {
while (true) {
let numbers = loop$numbers;
let initial = loop$initial;
if (numbers instanceof $Empty) {
return initial;
} else {
let first = numbers.head;
let rest = numbers.tail;
loop$numbers = rest;
loop$initial = first * initial;
}
}
}
/**
* Multiplies a list of `Float`s and returns the product.
*
* ## Example
*
* ```gleam
* product([2.5, 3.2, 4.2])
* // -> 33.6
* ```
*/
export function product(numbers) {
return product_loop(numbers, 1.0);
}
/**
* Computes the modulo of an float division of inputs as a `Result`.
*
* Returns division of the inputs as a `Result`: If the given divisor equals
* `0`, this function returns an `Error`.
*
* ## Examples
*
* ```gleam
* modulo(13.3, by: 3.3)
* // -> Ok(0.1)
* ```
*
* ```gleam
* modulo(-13.3, by: 3.3)
* // -> Ok(3.2)
* ```
*
* ```gleam
* modulo(13.3, by: -3.3)
* // -> Ok(-3.2)
* ```
*
* ```gleam
* modulo(-13.3, by: -3.3)
* // -> Ok(-0.1)
* ```
*/
export function modulo(dividend, divisor) {
if (divisor === 0.0) {
return new Error(undefined);
} else {
return new Ok(dividend - (floor(divideFloat(dividend, divisor)) * divisor));
}
}
/**
* Returns division of the inputs as a `Result`.
*
* ## Examples
*
* ```gleam
* divide(0.0, 1.0)
* // -> Ok(0.0)
* ```
*
* ```gleam
* divide(1.0, 0.0)
* // -> Error(Nil)
* ```
*/
export function divide(a, b) {
if (b === 0.0) {
return new Error(undefined);
} else {
let b$1 = b;
return new Ok(divideFloat(a, b$1));
}
}
/**
* Adds two floats together.
*
* It's the function equivalent of the `+.` operator.
* This function is useful in higher order functions or pipes.
*
* ## Examples
*
* ```gleam
* add(1.0, 2.0)
* // -> 3.0
* ```
*
* ```gleam
* import gleam/list
*
* list.fold([1.0, 2.0, 3.0], 0.0, add)
* // -> 6.0
* ```
*
* ```gleam
* 3.0 |> add(2.0)
* // -> 5.0
* ```
*/
export function add(a, b) {
return a + b;
}
/**
* Multiplies two floats together.
*
* It's the function equivalent of the `*.` operator.
* This function is useful in higher order functions or pipes.
*
* ## Examples
*
* ```gleam
* multiply(2.0, 4.0)
* // -> 8.0
* ```
*
* ```gleam
* import gleam/list
*
* list.fold([2.0, 3.0, 4.0], 1.0, multiply)
* // -> 24.0
* ```
*
* ```gleam
* 3.0 |> multiply(2.0)
* // -> 6.0
* ```
*/
export function multiply(a, b) {
return a * b;
}
/**
* Subtracts one float from another.
*
* It's the function equivalent of the `-.` operator.
* This function is useful in higher order functions or pipes.
*
* ## Examples
*
* ```gleam
* subtract(3.0, 1.0)
* // -> 2.0
* ```
*
* ```gleam
* import gleam/list
*
* list.fold([1.0, 2.0, 3.0], 10.0, subtract)
* // -> 4.0
* ```
*
* ```gleam
* 3.0 |> subtract(_, 2.0)
* // -> 1.0
* ```
*
* ```gleam
* 3.0 |> subtract(2.0, _)
* // -> -1.0
* ```
*/
export function subtract(a, b) {
return a - b;
}
/**
* Returns the natural logarithm (base e) of the given as a `Result`. If the
* input is less than or equal to 0, returns `Error(Nil)`.
*
* ## Examples
*
* ```gleam
* logarithm(1.0)
* // -> Ok(0.0)
* ```
*
* ```gleam
* logarithm(2.718281828459045) // e
* // -> Ok(1.0)
* ```
*
* ```gleam
* logarithm(0.0)
* // -> Error(Nil)
* ```
*
* ```gleam
* logarithm(-1.0)
* // -> Error(Nil)
* ```
*/
export function logarithm(x) {
let $ = x <= 0.0;
if ($) {
return new Error(undefined);
} else {
return new Ok(do_log(x));
}
}