diff --git a/subprojects/bahaghari/lib/math.nix b/subprojects/bahaghari/lib/math.nix index 80c3ffa9..538264f2 100644 --- a/subprojects/bahaghari/lib/math.nix +++ b/subprojects/bahaghari/lib/math.nix @@ -123,6 +123,67 @@ rec { in expR * (pow 2 k); + /** + Given a list of numbers, return the arithmetic mean. + + # Arguments + + list + : A list of numbers. + + # Type + + ``` + arithmeticMean :: [ Number ] -> Number + ``` + + # Example + + ``` + arithmeticMean (lib.range 1 10) + => 5.5 + ``` + */ + arithmeticMean = list: + summate list / (self.toFloat (lib.length list)); + + /** + Given a pair of numbers, return the arithmetic-geometric mean (typically + written as M(x, y)). + + # Arguments + + x, y + : The pair of values to be applied. + + # Type + + ``` + agm :: Number -> Number -> Number + ``` + + # Example + + ``` + agm 24 6 + => 13.4581714817256 + + agm 1 5 + => 2.6040081905309407 + ``` + */ + agm = x: y: + assert lib.assertMsg (x >= 0 && y >= 0) + "bahaghariLib.math.agm: both numbers should be positive"; + let + x' = (x + y) / 2; + y' = sqrt (x * y); + in + if abs (x' - y') > constants.epsilon then + agm x' y' + else + x; + /* Given a number, find its square root. This method is implemented using Newton's method. diff --git a/subprojects/bahaghari/tests/lib/math.nix b/subprojects/bahaghari/tests/lib/math.nix index 380176a7..a1d237c8 100644 --- a/subprojects/bahaghari/tests/lib/math.nix +++ b/subprojects/bahaghari/tests/lib/math.nix @@ -377,6 +377,25 @@ lib.runTests { expected = 1; }; + testMathAGM = { + expr = round' (self.math.agm 24 6); + expected = round' 13.4581714817256; + }; + + testMathAGM2 = let + round' = self.math.round' (-9); + in { + expr = round' (self.math.agm 1 5); + expected = round' 2.6040081905309407; + }; + + testMathAGM3 = let + round' = self.math.round' (-4); + in { + expr = round' (self.math.agm 1123.0 576.756); + expected = round' 827.1835522818762; + }; + testDegreesToRadians = { expr = self.math.degreesToRadians 180; expected = self.math.constants.pi; @@ -495,4 +514,14 @@ lib.runTests { expr = round' (self.math.tan (-152)); expected = round' (-2.5994579438382797); }; + + testMathArithmeticMean = { + expr = self.math.arithmeticMean (lib.range 1 10); + expected = 5.5; + }; + + testMathArithmeticMean2 = { + expr = self.math.arithmeticMean (lib.range 1 20); + expected = 10.5; + }; }