diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0bbd977..3ce4599 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,8 +13,8 @@ jobs: - uses: erlef/setup-beam@v1 with: - otp-version: "26.1" - gleam-version: "0.33.0" + otp-version: "26.2" + gleam-version: "1.0.0" - uses: actions/setup-node@v3 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f0046b..98c5e59 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,8 +19,8 @@ jobs: - uses: erlef/setup-beam@v1 with: - otp-version: "26.1" - gleam-version: "0.33.0" + otp-version: "26.2" + gleam-version: "1.0.0" - uses: actions/setup-node@v3 with: diff --git a/README.md b/README.md index c912757..716b910 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ import gleam_community/maths/elementary import gleam_community/maths/piecewise import gleam_community/maths/predicates import gleam/float +import gleam/int pub fn main() { // Evaluate the sine function @@ -31,7 +32,7 @@ pub fn main() { // Returns Tuple: Ok(#(3.0, 50.0)) // Find the list indices of the smallest value - piecewise.arg_minimum([10, 3, 50, 20, 3], float.compare) + piecewise.arg_minimum([10, 3, 50, 20, 3], int.compare) // Returns List: Ok([1, 4]) // Determine if a number is fractional @@ -46,7 +47,6 @@ pub fn main() { combinatorics.list_combination([1, 2], 1) // Returns List: Ok([[1], [2]]) } - ``` ## Installation diff --git a/gleam.toml b/gleam.toml index a849b65..ff28f07 100644 --- a/gleam.toml +++ b/gleam.toml @@ -1,10 +1,10 @@ name = "gleam_community_maths" -version = "1.0.2" +version = "1.1.0" licences = ["Apache-2.0"] description = "A basic maths library" repository = { type = "github", user = "gleam-community", repo = "maths" } -gleam = ">= 0.33.0" +gleam = ">= 0.32.0" [dependencies] gleam_stdlib = "~> 0.34" diff --git a/manifest.toml b/manifest.toml index 7445d63..6c5a157 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,8 +2,8 @@ # You typically do not need to edit this file packages = [ - { name = "gleam_stdlib", version = "0.34.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1FB8454D2991E9B4C0C804544D8A9AD0F6184725E20D63C3155F0AEB4230B016" }, - { name = "gleeunit", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "4E75DCF846D653848094169304743DFFB386E3AECCCF611F99ADB735FF4D4DD9" }, + { name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" }, + { name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" }, ] [requirements] diff --git a/src/gleam_community/maths/arithmetics.gleam b/src/gleam_community/maths/arithmetics.gleam index acb0fd1..a238abc 100644 --- a/src/gleam_community/maths/arithmetics.gleam +++ b/src/gleam_community/maths/arithmetics.gleam @@ -30,6 +30,7 @@ //// * [`lcm`](#lcm) //// * [`divisors`](#divisors) //// * [`proper_divisors`](#proper_divisors) +//// * [`int_euclidean_modulo`](#int_euclidean_modulo) //// * **Sums and products** //// * [`float_sum`](#float_sum) //// * [`int_sum`](#int_sum) @@ -102,15 +103,23 @@ fn do_gcd(x: Int, y: Int) -> Int { /// /// /// -/// The function calculates the Euclidian modulo of two numbers -/// The Euclidian_modulo is the modulo that most often is used in maths -/// rather than the normal truncating modulo operation that is used most -/// often in programming through the % operator -/// In contrast to the % operator this function will always return a positive -/// result +/// +/// Given two integers, $$x$$ (dividend) and $$y$$ (divisor), the Euclidean modulo of $$x$$ by $$y$$, +/// denoted as $$x \mod y$$, is the remainder $$r$$ of the division of $$x$$ by $$y$$, such that: +/// +/// \\[ +/// x = q \cdot y + r \quad \text{and} \quad 0 \leq r < |y|, +/// \\] +/// +/// where $$q$$ is an integer that represents the quotient of the division. /// -/// Like the gleam division operator / this will return 0 if one of the -/// parameters are 0 as this is not defined in mathematics +/// The Euclidean modulo function of two numbers, is the remainder operation most commonly utilized in +/// mathematics. This differs from the standard truncating modulo operation frequently employed in +/// programming via the `%` operator. Unlike the `%` operator, which may return negative results +/// depending on the divisor's sign, the Euclidean modulo function is designed to +/// always yield a positive outcome, ensuring consistency with mathematical conventions. +/// +/// Note that like the Gleam division operator `/` this will return `0` if one of the arguments is `0`. /// /// ///
@@ -120,13 +129,13 @@ fn do_gcd(x: Int, y: Int) -> Int { /// import gleam_community/maths/arithmetics /// /// pub fn example() { -/// arithmetics.euclidian_modulo(15, 4) +/// arithmetics.euclidean_modulo(15, 4) /// |> should.equal(3) /// -/// arithmetics.euclidian_modulo(-3, -2) +/// arithmetics.euclidean_modulo(-3, -2) /// |> should.equal(1) /// -/// arithmetics.euclidian_modulo(5, 0) +/// arithmetics.euclidean_modulo(5, 0) /// |> should.equal(0) /// } ///
@@ -137,7 +146,7 @@ fn do_gcd(x: Int, y: Int) -> Int { /// /// /// -pub fn euclidian_modulo(x: Int, y: Int) -> Int { +pub fn int_euclidean_modulo(x: Int, y: Int) -> Int { case x % y, x, y { _, 0, _ -> 0 _, _, 0 -> 0 diff --git a/src/gleam_community/maths/combinatorics.gleam b/src/gleam_community/maths/combinatorics.gleam index dcdeab1..b16d0ad 100644 --- a/src/gleam_community/maths/combinatorics.gleam +++ b/src/gleam_community/maths/combinatorics.gleam @@ -239,8 +239,7 @@ pub fn permutation(n: Int, k: Int) -> Result(Int, String) { False -> { let assert Ok(v1) = factorial(n) let assert Ok(v2) = factorial(n - k) - v1 - / v2 + v1 / v2 |> Ok } } @@ -416,14 +415,17 @@ pub fn cartesian_product(xarr: List(a), yarr: List(a)) -> List(#(a, a)) { yarr |> set.from_list() xset - |> set.fold(set.new(), fn(accumulator0: set.Set(#(a, a)), member0: a) -> set.Set( - #(a, a), - ) { - set.fold(yset, accumulator0, fn(accumulator1: set.Set(#(a, a)), member1: a) -> set.Set( - #(a, a), - ) { - set.insert(accumulator1, #(member0, member1)) - }) - }) + |> set.fold( + set.new(), + fn(accumulator0: set.Set(#(a, a)), member0: a) -> set.Set(#(a, a)) { + set.fold( + yset, + accumulator0, + fn(accumulator1: set.Set(#(a, a)), member1: a) -> set.Set(#(a, a)) { + set.insert(accumulator1, #(member0, member1)) + }, + ) + }, + ) |> set.to_list() } diff --git a/src/gleam_community/maths/elementary.gleam b/src/gleam_community/maths/elementary.gleam index 673cd23..1b518a4 100644 --- a/src/gleam_community/maths/elementary.gleam +++ b/src/gleam_community/maths/elementary.gleam @@ -819,8 +819,7 @@ pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String) // Apply the "change of base formula" let assert Ok(numerator) = logarithm_10(x) let assert Ok(denominator) = logarithm_10(a) - numerator - /. denominator + numerator /. denominator |> Ok } False -> diff --git a/src/gleam_community/maths/piecewise.gleam b/src/gleam_community/maths/piecewise.gleam index 6299489..c8492da 100644 --- a/src/gleam_community/maths/piecewise.gleam +++ b/src/gleam_community/maths/piecewise.gleam @@ -445,8 +445,7 @@ fn round_ties_up(p: Float, x: Float) -> Float { let remainder: Float = xabs -. xabs_truncated case remainder { _ if remainder >=. 0.5 && x >=. 0.0 -> - float_sign(x) *. truncate_float(xabs +. 1.0) - /. p + float_sign(x) *. truncate_float(xabs +. 1.0) /. p _ -> float_sign(x) *. xabs_truncated /. p } } @@ -577,8 +576,7 @@ pub fn int_absolute_value(x: Int) -> Int { /// /// pub fn float_absolute_difference(a: Float, b: Float) -> Float { - a - -. b + a -. b |> float_absolute_value() } @@ -618,8 +616,7 @@ pub fn float_absolute_difference(a: Float, b: Float) -> Float { /// /// pub fn int_absolute_difference(a: Int, b: Int) -> Int { - a - - b + a - b |> int_absolute_value() } diff --git a/src/gleam_community/maths/predicates.gleam b/src/gleam_community/maths/predicates.gleam index 8348e9c..f8d357c 100644 --- a/src/gleam_community/maths/predicates.gleam +++ b/src/gleam_community/maths/predicates.gleam @@ -98,8 +98,7 @@ fn float_absolute_value(x: Float) -> Float { } fn float_absolute_difference(a: Float, b: Float) -> Float { - a - -. b + a -. b |> float_absolute_value() } diff --git a/test/gleam_community/maths/arithmetics_test.gleam b/test/gleam_community/maths/arithmetics_test.gleam index 104cb4d..aa694b7 100644 --- a/test/gleam_community/maths/arithmetics_test.gleam +++ b/test/gleam_community/maths/arithmetics_test.gleam @@ -21,14 +21,31 @@ pub fn int_gcd_test() { |> should.equal(6) } -pub fn euclidian_modulo_test() { - arithmetics.euclidian_modulo(15, 4) +pub fn int_euclidean_modulo_test() { + // Base Case: Positive x, Positive y + // Note that the truncated, floored, and euclidean + // definitions should agree for this base case + arithmetics.int_euclidean_modulo(15, 4) |> should.equal(3) - arithmetics.euclidian_modulo(-3, -2) + // Case: Positive x, Negative y + arithmetics.int_euclidean_modulo(15, -4) + |> should.equal(3) + + // Case: Negative x, Positive y + arithmetics.int_euclidean_modulo(-15, 4) |> should.equal(1) - arithmetics.euclidian_modulo(5, 0) + // Case: Negative x, Negative y + arithmetics.int_euclidean_modulo(-15, -4) + |> should.equal(1) + + // Case: Positive x, Zero y + arithmetics.int_euclidean_modulo(5, 0) + |> should.equal(0) + + // Case: Zero x, Negative y + arithmetics.int_euclidean_modulo(0, 5) |> should.equal(0) } diff --git a/test/gleam_community/maths/piecewise_test.gleam b/test/gleam_community/maths/piecewise_test.gleam index 46d97a4..de1df0e 100644 --- a/test/gleam_community/maths/piecewise_test.gleam +++ b/test/gleam_community/maths/piecewise_test.gleam @@ -311,17 +311,26 @@ pub fn math_round_ties_away_test() { |> should.equal(Ok(12.0)) // Round 1. digit BEFORE decimal point - piecewise.round(12.0654, option.Some(-1), option.Some(piecewise.RoundTiesAway), + piecewise.round( + 12.0654, + option.Some(-1), + option.Some(piecewise.RoundTiesAway), ) |> should.equal(Ok(10.0)) // Round 2. digit BEFORE decimal point - piecewise.round(12.0654, option.Some(-2), option.Some(piecewise.RoundTiesAway), + piecewise.round( + 12.0654, + option.Some(-2), + option.Some(piecewise.RoundTiesAway), ) |> should.equal(Ok(0.0)) // Round 2. digit BEFORE decimal point - piecewise.round(12.0654, option.Some(-3), option.Some(piecewise.RoundTiesAway), + piecewise.round( + 12.0654, + option.Some(-3), + option.Some(piecewise.RoundTiesAway), ) |> should.equal(Ok(0.0)) }