diff --git a/src/Data/Quantity/Math.purs b/src/Data/Quantity/Math.purs index 4df1f1a..8dfc1c9 100644 --- a/src/Data/Quantity/Math.purs +++ b/src/Data/Quantity/Math.purs @@ -38,6 +38,7 @@ module Data.Quantity.Math , min2 , min , mean + , geomean , modulo , round , gamma @@ -55,8 +56,8 @@ import Data.Foldable (foldM) import Data.Decimal (Decimal) import Data.Either (Either) import Data.Quantity (Quantity, ConversionError, derivedUnit, asValueIn', - scalar', quantity', toScalar', (⊘), (⊕), (.*)) - + scalar', quantity', toScalar', (⊗), (⊘), (⊕), (.*), pow) +import Data.Int (toNumber) type Result = Either ConversionError Quantity lift ∷ (Decimal → Decimal) → Quantity → Result @@ -178,6 +179,11 @@ mean xs = (_ ⊘ n) <$> foldM (⊕) (head xs) (tail xs) where n = scalar' (Decimal.fromInt (length xs)) +geomean ∷ NonEmptyList Quantity → Result +geomean xs = (_ `pow` (Decimal.fromInt 1 / n)) <$> foldM (⊗) (head xs) (tail xs) + where + n = Decimal.fromInt (length xs) + modulo ∷ Quantity → Quantity → Result modulo = lift2 Decimal.modulo diff --git a/src/Quantities.purs b/src/Quantities.purs index 15fc95b..d3ea318 100644 --- a/src/Quantities.purs +++ b/src/Quantities.purs @@ -26,7 +26,7 @@ import Data.Quantity (ConversionError(..), Quantity, abs, approximatelyEqual, as sqrt, toScalar, toScalar', toStandard, (.*), (⊕), (⊖), (⊗), (⊘)) as DQ import Data.Quantity.Math (acos, acosh, acot, acoth, acsc, acsch, asec, asech, asin, asinh, atan, atan2, atanh, ceil, cos, cosh, cot, coth, csc, csch, e, exp, factorial, - floor, gamma, ln, log10, max, max2, mean, min, min2, modulo, pi, round, + floor, gamma, ln, log10, max, max2, mean, geomean, min, min2, modulo, pi, round, sec, sech, sin, sinh, tan, tanh, tau, phi) as DQM import Data.Quantity.Physics (avogadroConstant, electronCharge, electronMass, g0, gravitationalConstant, kB, planckConstant, protonMass, diff --git a/test/Main.purs b/test/Main.purs index bfaa95c..cd47c85 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -36,7 +36,7 @@ import Data.Quantity (Quantity, (.*), prettyPrint, (⊕), (⊖), (⊗), (⊘), errorMessage, showResult, qNegate, isFinite, ConversionError(..)) import Data.Quantity as Q -import Data.Quantity.Math (sin, asin, pi, modulo, max, min, mean, atan2) +import Data.Quantity.Math (sin, asin, pi, modulo, max, min, mean, geomean, atan2) import Effect (Effect) @@ -511,6 +511,7 @@ main = runTest do : (-1.0 .* inch) : Nil let qs3 = NonEmptyList $ (4.2 .* second) :| Nil + let qs4 = NonEmptyList $ scalar (3.0) :| scalar 4.0 : scalar 2.0 : Nil test "max" do equal (Right $ scalar 4.0) (max qs1) @@ -526,7 +527,11 @@ main = runTest do equal (Right $ scalar 1.0) (mean qs1) equal (Right $ 1.0 .* meter) (mean qs2) equal (Right $ 4.2 .* second) (mean qs3) + test "geomean" do + + equal (Right $ 4.2 .* second) (geomean qs3) + equal (Right $ scalar 2.9) (geomean qs4) suite "Consistency checks" do test "Data.Units.SI.Derived" do -- See: https://en.wikipedia.org/wiki/International_System_of_Units#Derived_units