From 5f07c5b0fce1b52238e45a09ffb4f9c543fbfddc Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Sat, 1 Jun 2024 13:21:30 +0800 Subject: [PATCH] bahaghari/lib: add math.sqrt function --- subprojects/bahaghari/lib/default.nix | 2 +- subprojects/bahaghari/lib/math.nix | 35 ++++++++++++++++++++++++ subprojects/bahaghari/tests/lib/math.nix | 24 +++++++++++++++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/subprojects/bahaghari/lib/default.nix b/subprojects/bahaghari/lib/default.nix index 52afc540..f247b026 100644 --- a/subprojects/bahaghari/lib/default.nix +++ b/subprojects/bahaghari/lib/default.nix @@ -49,5 +49,5 @@ pkgs.lib.makeExtensible inherit (self.hex) isHexString; inherit (self.math) abs pow percentage factorial floor ceil round round' - summate product; + summate product sqrt; }) diff --git a/subprojects/bahaghari/lib/math.nix b/subprojects/bahaghari/lib/math.nix index 63689b1f..1e774ae5 100644 --- a/subprojects/bahaghari/lib/math.nix +++ b/subprojects/bahaghari/lib/math.nix @@ -48,6 +48,41 @@ rec { in if exponent < 0 then (1 / value) else value; + /* Given a number, find its square root. This method is implemented using + Newton's method. + + Type: sqrt :: Number -> Number + + Example: + sqrt 4 + => 2 + + sqrt 169 + => 13 + + sqrt 12 + => 3.464101615 + */ + sqrt = number: + assert lib.assertMsg (number >= 0) + "bahaghariLib.math.sqrt: Only positive numbers are allowed"; + let + # Changing this value can change the result drastically. A value of + # 10^-13 for tolerance seems to be the most balanced so far since we are + # dealing with floats and should be enough for most cases. + tolerance = pow 10 (-13); + + iter = value: + let + root = 0.5 * (value + (number / value)); + in + if (abs (root - value) > tolerance) then + iter root + else + value; + in + iter number; + /* Implements the factorial function with the given value. Type: factorial :: Number -> Number diff --git a/subprojects/bahaghari/tests/lib/math.nix b/subprojects/bahaghari/tests/lib/math.nix index 5205a848..ebd224c5 100644 --- a/subprojects/bahaghari/tests/lib/math.nix +++ b/subprojects/bahaghari/tests/lib/math.nix @@ -166,7 +166,7 @@ lib.runTests { expected = 10; }; - testMathSummate22 = { + testMathSummate2 = { expr = self.math.summate [ 1 2 3 4.5 5.6 6.7 ]; expected = 22.8; }; @@ -180,4 +180,26 @@ lib.runTests { expr = self.math.product [ 1.5 2 3 4.6 ]; expected = 41.4; }; + + # All of the answers here should be sourced from another tool such as a + # calculator. + testMathSqrt = { + expr = self.math.sqrt 4; + expected = 2; + }; + + testMathSqrt2 = { + expr = self.math.sqrt 169; + expected = 13; + }; + + testMathSqrt3 = { + expr = self.math.round' (-9) (self.math.sqrt 12); + expected = 3.464101615; + }; + + testMathSqrt4 = { + expr = self.math.round' (-10) (self.math.sqrt 2); + expected = 1.4142135624; + }; }