packages feed

factory 0.0.0.2 → 0.1.0.0

raw patch · 19 files changed

+625/−281 lines, 19 filesdep +randomdep ~toolshed

Dependencies added: random

Dependency ranges changed: toolshed

Files

changelog view
@@ -13,4 +13,11 @@ 	* Renamed 'Factory.Math.Precision.capPrecision' to 'Factory.Math.Precision.simplify'. 	* Removed module "Factory.Test.Performance.Exponential". 	* Removed function 'Factory.Math.Power.raise', which was no more efficient than ghc's implementation of '(^)'.-0.0.0.3+	* Uploaded to <http://hackage.haskell.org/packages/hackage.html>.+0.1.0.0+	* Amended 'factory.cabal' to more correctly specify the dependency on package 'toolshed'.+	* Added module "Factory.Math.Probability".+	* Renamed module "Factory.Data.Bounds" to "Factory.Data.Interval",+	and added functions; 'Factory.Data.Interval.precisely', 'Factory.Data.Interval.shift', 'Factory.Data.Interval.closedUnitInterval'.+	* Guarded 'eager-blackholing' flag in cabal file.+
factory.cabal view
@@ -1,6 +1,6 @@ --Package-properties Name:			factory-Version:		0.0.0.2+Version:		0.1.0.0 Cabal-Version:		>= 1.6 Copyright:		(C) 2011 Dr. Alistair Ward License:		GPL@@ -11,7 +11,7 @@ Build-Type:		Simple Description:		A library of number-theory functions, for; factorials, square-roots, Pi, primality-testing, prime-factorisation ... Category:		Math, Number Theory-Tested-With:		GHC == 6.12, GHC == 7.0+Tested-With:		GHC == 6.10, GHC == 6.12, GHC == 7.0 Homepage:		http://functionalley.eu Maintainer:		factory <at> functionalley <dot> eu Bug-reports:		factory <at> functionalley <dot> eu@@ -30,8 +30,8 @@     hs-source-dirs:	src      Exposed-modules:-        Factory.Data.Bounds         Factory.Data.Exponential+        Factory.Data.Interval         Factory.Data.MonicPolynomial         Factory.Data.Monomial         Factory.Data.Polynomial@@ -43,11 +43,6 @@         Factory.Math.Factorial         Factory.Math.Fibonacci         Factory.Math.Implementations.Factorial-        Factory.Math.Implementations.Primality-        Factory.Math.Implementations.PrimeFactorisation-        Factory.Math.Implementations.SquareRoot-        Factory.Math.MultiplicativeOrder-        Factory.Math.Pi         Factory.Math.Implementations.Pi.AGM.Algorithm         Factory.Math.Implementations.Pi.AGM.BrentSalamin         Factory.Math.Implementations.Pi.BBP.Algorithm@@ -69,10 +64,16 @@         Factory.Math.Implementations.Pi.Spigot.RabinowitzWagon         Factory.Math.Implementations.Pi.Spigot.Series         Factory.Math.Implementations.Pi.Spigot.Spigot+        Factory.Math.Implementations.Primality+        Factory.Math.Implementations.PrimeFactorisation+        Factory.Math.Implementations.SquareRoot+        Factory.Math.MultiplicativeOrder+        Factory.Math.Pi         Factory.Math.Power         Factory.Math.Precision         Factory.Math.Primality         Factory.Math.PrimeFactorisation+        Factory.Math.Probability         Factory.Math.Radix         Factory.Math.SquareRoot         Factory.Math.Statistics@@ -84,7 +85,8 @@         deepseq >= 1.1,         containers,         primes >= 0.1,-        toolshed == 0.11.*+        random,+        toolshed >= 0.12      if flag(threaded)         Build-depends:	parallel >= 3.0@@ -111,16 +113,17 @@         Factory.Test.Performance.SquareRoot         Factory.Test.Performance.Statistics         Factory.Test.QuickCheck.ArithmeticGeometricMean-        Factory.Test.QuickCheck.Bounds         Factory.Test.QuickCheck.Factorial+        Factory.Test.QuickCheck.Interval         Factory.Test.QuickCheck.MonicPolynomial         Factory.Test.QuickCheck.Pi         Factory.Test.QuickCheck.Polynomial         Factory.Test.QuickCheck.Power         Factory.Test.QuickCheck.Primality         Factory.Test.QuickCheck.PrimeFactorisation-        Factory.Test.QuickCheck.Radix+        Factory.Test.QuickCheck.Probability         Factory.Test.QuickCheck.QuickChecks+        Factory.Test.QuickCheck.Radix         Factory.Test.QuickCheck.SquareRoot         Factory.Test.QuickCheck.Statistics         Factory.Test.QuickCheck.Summation@@ -134,7 +137,10 @@     GHC-prof-options:	-prof -auto-all -caf-all      if flag(threaded)-        GHC-options:	-threaded -feager-blackholing+        GHC-options:	-threaded++        if impl(ghc >= 6.12)+            GHC-options:	-feager-blackholing      if impl(ghc >= 7.0)         GHC-options:	-rtsopts
makefile view
@@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program.  If not, see <http://www.gnu.org/licenses/>.  -.PHONY: all build clean configure copy haddock help hlint install prof sdist+.PHONY: all build check clean configure copy haddock help hlint install prof sdist  all: install @@ -45,8 +45,12 @@ sdist: configure 	runhaskell Setup.hs $@ +check: sdist+	cabal upload --check --verbose=3 dist/*.tar.gz;+ clean: 	runhaskell Setup.hs $@+	find src -type f \( -name '*.o' -o -name '*.hi' \) -delete  help: 	@grep '^[a-zA-Z].*:' makefile | sed -e 's/:.*//'
− src/Factory/Data/Bounds.hs
@@ -1,170 +0,0 @@-{-# LANGUAGE CPP #-}-{--	Copyright (C) 2011 Dr. Alistair Ward--	This program is free software: you can redistribute it and/or modify-	it under the terms of the GNU General Public License as published by-	the Free Software Foundation, either version 3 of the License, or-	(at your option) any later version.--	This program is distributed in the hope that it will be useful,-	but WITHOUT ANY WARRANTY; without even the implied warranty of-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-	GNU General Public License for more details.--	You should have received a copy of the GNU General Public License-	along with this program.  If not, see <http://www.gnu.org/licenses/>.--}-{- |- [@AUTHOR@]	Dr. Alistair Ward-- [@DESCRIPTION@]--	* Describes a /bounded/ range of, typically integral, quantities.--	* Operations have been defined, on the list of /consecutive/ quantities delimited by these two bounds.--	* The point is that if the list is composed from /consecutive/ quantities, the intermediate values can be inferred, rather than physically represented.-- [@CAVEATS@]--	* The API was driven top-down by its caller's requirements, rather than a bottom-up attempt to provide a complete interface.-	consequently there may be omissions from the view point of future callers.--}--module Factory.Data.Bounds (--- * Types--- ** Type-synonyms-	Bounds,--- * Functions---	divideAndConquer,-	elem',-	length',-	normalise,-	product',-	splitAt',-	toList,--- ** Accessors-	minBound',-	maxBound'--- ** Predicates---	isReversed-) where--import			Control.Arrow((***))-import qualified	Data.Monoid-import qualified	Data.Ratio--#if MIN_VERSION_parallel(3,0,0)-import qualified	Control.Parallel.Strategies-#endif--#if MIN_VERSION_base(4,3,0)-import	Data.Tuple(swap)-#else--- | Swap the components of a pair.-swap :: (a, b) -> (b, a)-swap (a, b)	= (b, a)-#endif---- | Defines a range of consecutive values, bracketed by /inclusive/ bounds.-type Bounds limit	= (limit, limit)---- | Accessor.-{-# INLINE minBound' #-}-minBound' :: Bounds a -> a-minBound'	= fst---- | Accessor.-{-# INLINE maxBound' #-}-maxBound' :: Bounds a -> a-maxBound'	= snd---- | 'True' if the specified value is within the inclusive 'Bounds'.-elem' :: Ord limit => limit -> Bounds limit -> Bool-elem' x	= uncurry (&&) . ((<= x) *** (x <=))---- | 'True' if /minBound'/ exceeds /maxBound'/ extent.-isReversed :: Ord limit => Bounds limit -> Bool-isReversed	= uncurry (>)---- | Swap the limits where they were originally reversed, but otherwise do nothing.-normalise :: Ord limit => Bounds limit -> Bounds limit-normalise b-	| isReversed b	= swap b-	| otherwise	= b---- | Bisect the bounds at the specified limit; which should be between the two existing limits.-splitAt' :: (Num limit, Ord limit) => limit -> Bounds limit -> (Bounds limit, Bounds limit)-splitAt' i bounds@(l, r)-	| any ($ i) [(< l), (>= r)]	= error $ "Factory.Data.Bounds.splitAt':\tunsuitable index=" ++ show i ++ " for bounds=" ++ show bounds ++ "."-	| otherwise			= ((l, i), (i + 1, r))---- | The length of 'toList'.-{-# INLINE length' #-}-length' :: (Num limit, Ord limit) => Bounds limit -> limit-length' (l, r)	= r + 1 - l---- | Converts 'Bounds' to a list by enumerating the values.-{-# INLINE toList #-}-toList :: Enum limit => Bounds limit -> [limit]-toList	= uncurry enumFromTo--{- |-	* Reduces 'Bounds' to a single integral value encapsulated in a 'Data.Monoid.Monoid',-	using a /divide-and-conquer/ strategy,-	bisecting the /bounds/ and recursively evaluating each part; <http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm>.--	* By choosing a 'ratio' other than @(1 % 2)@, the bisection can be made asymmetrical.-	The specified ratio represents the length of the left-hand portion over the original list-length;-	eg. @(1 % 3)@ results in the first part, half the length of the second.--	* This process of recursive bisection, is terminated beneath the specified minimum length,-	after which the 'Bounds' are expanded into the corresponding list, and the /monoid/'s binary operator is directly /folded/ over it.--	* One can view this as a <http://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>,-	in which 'Bounds' is exploded into a binary tree-structure-	(each leaf of which contains a list of up to 'minLength' integers, and each node of which contains an associative binary operator),-	and then collapsed to a scalar, by application of the operators.--}-divideAndConquer :: (Integral i, Data.Monoid.Monoid monoid)-	=> (i -> monoid)	-- ^ The monoid's constructor.-	-> Data.Ratio.Ratio i	-- ^ The ratio of the original span, at which to bisect the 'Bounds'.-	-> i			-- ^ For efficiency, the bounds will not be bisected, when it's length has been reduced to this value.-	-> Bounds i-	-> monoid		-- ^ The resulting scalar.-divideAndConquer monoidConstructor ratio minLength-	| any ($ ratio) [-		(< 0),-		(>= 1)-	]		= error $ "Factory.Data.Bounds.divideAndConquer:\tunsuitable ratio='" ++ show ratio ++ "'."-	| minLength < 1	= error $ "Factory.Data.Bounds.divideAndConquer:\tunsuitable minLength=" ++ show minLength ++ "."-	| otherwise	= slave-	where-		slave bounds@(l, r)-			| length' bounds <= minLength	= Data.Monoid.mconcat . map monoidConstructor $ toList bounds	--Fold the monoid's binary operator over the delimited list.-			| otherwise			= uncurry Data.Monoid.mappend .-#if MIN_VERSION_parallel(3,0,0)-			Control.Parallel.Strategies.withStrategy (-				Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rseq Control.Parallel.Strategies.rseq-			) .-#endif-			(slave *** slave) $ splitAt' (-				l + (r - l) * Data.Ratio.numerator ratio `div` Data.Ratio.denominator ratio	--Use the ratio to generate the split-index.-			) bounds	--Apply the monoid's binary operator to the two operands resulting from bisection.--{- |-	* Multiplies the consecutive sequence of integers within 'Bounds'.--	* Since the result can be large, 'divideAndConquer' is used to form operands of a similar order of magnitude,-	thus improving the efficiency of the big-number multiplication.--}-product' :: Integral i-	=> Data.Ratio.Ratio i	-- ^ The ratio at which to bisect the 'Bounds'.-	-> i			-- ^ For efficiency, the bounds will not be bisected, when it's length has been reduced to this value.-	-> Bounds i-	-> i			-- ^ The resulting product.-product' ratio minLength bounds-	| elem' 0 bounds	= 0-	| otherwise		= Data.Monoid.getProduct $ divideAndConquer Data.Monoid.Product ratio minLength bounds-
+ src/Factory/Data/Interval.hs view
@@ -0,0 +1,195 @@+{-# LANGUAGE CPP #-}+{-+	Copyright (C) 2011 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]++	* Describes a bounded set of, typically integral, quantities.++	* Operations have been defined, on the list of /consecutive/ quantities delimited by these endpoints.++	* The point is that if the list is composed from /consecutive/ quantities, the intermediate values can be inferred, rather than physically represented.++ [@CAVEATS@]++	* The API was driven top-down by its caller's requirements, rather than a bottom-up attempt to provide a complete interface.+	consequently there may be omissions from the view point of future callers.++	* Thought similar to the mathematical concept of an /interval/, the latter technically relates to /real/ numbers; <http://en.wikipedia.org/wiki/Interval_%28mathematics%29>.++	* No account has been made for /semi-closed/ or /open/ intervals.+-}++module Factory.Data.Interval(+-- * Types+-- ** Type-synonyms+	Interval,+-- * Constants+	closedUnitInterval,+-- * Functions+--	divideAndConquer,+	elem',+	getLength,+	normalise,+	product',+	shift,+	splitAt',+	toList,+-- ** Accessors+	getMinBound,+	getMaxBound,+-- ** Constructors+	precisely,+-- ** Predicates+	isReversed+) where++import			Control.Arrow((***), (&&&))+import qualified	Data.Monoid+import qualified	Data.Ratio+import qualified	ToolShed.Pair	as Pair++#if MIN_VERSION_parallel(3,0,0)+import qualified	Control.Parallel.Strategies+#endif++#if MIN_VERSION_base(4,3,0)+import	Data.Tuple(swap)+#else+-- | Swap the components of a pair.+swap :: (a, b) -> (b, a)+swap (a, b)	= (b, a)+#endif++-- | Defines a closed (inclusive) interval of consecutive values.+type Interval endPoint	= (endPoint, endPoint)++-- | Accessor.+{-# INLINE getMinBound #-}+getMinBound :: Interval endPoint -> endPoint+getMinBound	= fst++-- | Accessor.+{-# INLINE getMaxBound #-}+getMaxBound :: Interval endPoint -> endPoint+getMaxBound	= snd++-- | Construct the interval from a single value.+precisely :: endPoint -> Interval endPoint+precisely	= id &&& id++-- | Construct the /closed unit-interval/; <http://en.wikipedia.org/wiki/Unit_interval>.+closedUnitInterval :: Num n => Interval n+closedUnitInterval	= (0, 1)++-- | Shift of both /end-points/ of the /interval/ by the specified amount.+shift :: Num endPoint+	=> endPoint		-- ^ The magnitude of the require shift.+	-> Interval endPoint	-- ^ The interval to be shifted.+	-> Interval endPoint+shift i	= Pair.mirror (+ i)++-- | 'True' if the specified value is within the inclusive bounds of the /interval/.+elem' :: Ord endPoint => endPoint -> Interval endPoint -> Bool+elem' x	= Pair.both . ((<= x) *** (x <=))++-- | 'True' if 'getMinBound' exceeds 'getMaxBound' extent.+isReversed :: Ord endPoint => Interval endPoint -> Bool+isReversed	= uncurry (>)++-- | Swap the /end-points/ where they were originally reversed, but otherwise do nothing.+normalise :: Ord endPoint => Interval endPoint -> Interval endPoint+normalise b+	| isReversed b	= swap b+	| otherwise	= b++-- | Bisect the /interval/ at the specified /end-point/; which should be between the two existing /end-points/.+splitAt' :: (Num endPoint, Ord endPoint) => endPoint -> Interval endPoint -> (Interval endPoint, Interval endPoint)+splitAt' i interval@(l, r)+	| any ($ i) [(< l), (>= r)]	= error $ "Factory.Data.Interval.splitAt':\tunsuitable index=" ++ show i ++ " for interval=" ++ show interval ++ "."+	| otherwise			= ((l, i), (i + 1, r))++-- | The length of 'toList'.+{-# INLINE getLength #-}+getLength :: (Num endPoint, Ord endPoint) => Interval endPoint -> endPoint+getLength (l, r)	= r + 1 - l++-- | Converts 'Interval' to a list by enumerating the values.+{-# INLINE toList #-}+toList :: Enum endPoint => Interval endPoint -> [endPoint]+toList	= uncurry enumFromTo++{- |+	* Reduces 'Interval' to a single integral value encapsulated in a 'Data.Monoid.Monoid',+	using a /divide-and-conquer/ strategy,+	bisecting the /interval/ and recursively evaluating each part; <http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm>.++	* By choosing a 'ratio' other than @(1 % 2)@, the bisection can be made asymmetrical.+	The specified ratio represents the length of the left-hand portion over the original list-length;+	eg. @(1 % 3)@ results in the first part, half the length of the second.++	* This process of recursive bisection, is terminated beneath the specified minimum length,+	after which the 'Interval' are expanded into the corresponding list, and the /monoid/'s binary operator is directly /folded/ over it.++	* One can view this as a <http://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>,+	in which 'Interval' is exploded into a binary tree-structure+	(each leaf of which contains a list of up to 'minLength' integers, and each node of which contains an associative binary operator),+	and then collapsed to a scalar, by application of the operators.+-}+divideAndConquer :: (Integral i, Data.Monoid.Monoid monoid)+	=> (i -> monoid)	-- ^ The monoid's constructor.+	-> Data.Ratio.Ratio i	-- ^ The ratio of the original span, at which to bisect the 'Interval'.+	-> i			-- ^ For efficiency, the /interval/ will not be bisected, when it's length has been reduced to this value.+	-> Interval i+	-> monoid		-- ^ The resulting scalar.+divideAndConquer monoidConstructor ratio minLength+	| any ($ ratio) [+		(< 0),+		(>= 1)+	]		= error $ "Factory.Data.Interval.divideAndConquer:\tunsuitable ratio='" ++ show ratio ++ "'."+	| minLength < 1	= error $ "Factory.Data.Interval.divideAndConquer:\tunsuitable minLength=" ++ show minLength ++ "."+	| otherwise	= slave+	where+		slave interval@(l, r)+			| getLength interval <= minLength	= Data.Monoid.mconcat . map monoidConstructor $ toList interval	--Fold the monoid's binary operator over the delimited list.+			| otherwise			= uncurry Data.Monoid.mappend .+#if MIN_VERSION_parallel(3,0,0)+			Control.Parallel.Strategies.withStrategy (+				Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rseq Control.Parallel.Strategies.rseq+			) .+#endif+			Pair.mirror slave $ splitAt' (+				l + (r - l) * Data.Ratio.numerator ratio `div` Data.Ratio.denominator ratio	--Use the ratio to generate the split-index.+			) interval	--Apply the monoid's binary operator to the two operands resulting from bisection.++{- |+	* Multiplies the consecutive sequence of integers within 'Interval'.++	* Since the result can be large, 'divideAndConquer' is used to form operands of a similar order of magnitude,+	thus improving the efficiency of the big-number multiplication.+-}+product' :: Integral i+	=> Data.Ratio.Ratio i	-- ^ The ratio at which to bisect the 'Interval'.+	-> i			-- ^ For efficiency, the /interval/ will not be bisected, when it's length has been reduced to this value.+	-> Interval i+	-> i			-- ^ The resulting product.+product' ratio minLength interval+	| elem' 0 interval	= 0+	| otherwise		= Data.Monoid.getProduct $ divideAndConquer Data.Monoid.Product ratio minLength interval+
src/Factory/Data/MonicPolynomial.hs view
@@ -32,7 +32,6 @@ 	mkMonicPolynomial ) where -import			Control.Arrow((***)) import qualified	Control.Arrow import qualified	Factory.Data.Monomial		as Data.Monomial import			Factory.Data.Polynomial((*=))@@ -40,6 +39,7 @@ import qualified	Factory.Data.QuotientRing	as Data.QuotientRing import			Factory.Data.Ring((=*=), (=+=), (=-=)) import qualified	Factory.Data.Ring		as Data.Ring+import qualified	ToolShed.Pair			as Pair  -- | A type of 'Data.Polynomial.Polynomial', in which the /leading term/ is required to have a /coefficient/ of one. newtype MonicPolynomial c e	= MkMonicPolynomial {@@ -72,7 +72,7 @@  -- Since the /leading term/ of the /denominator/ is one, the /coefficient/ isn't required to implement 'Fractional'. instance (Num c, Num e, Ord e) => Data.QuotientRing.QuotientRing (MonicPolynomial c e)	where-	MkMonicPolynomial polynomialN `quotRem'` MkMonicPolynomial polynomialD	= (MkMonicPolynomial *** MkMonicPolynomial) $ longDivide polynomialN where+	MkMonicPolynomial polynomialN `quotRem'` MkMonicPolynomial polynomialD	= Pair.mirror MkMonicPolynomial $ longDivide polynomialN	where --		longDivide :: (Num c, Num e, Ord e) => Polynomial c e -> (Polynomial c e, Polynomial c e) 		longDivide numerator 			| Data.Polynomial.isZero numerator || Data.Monomial.getExponent quotient < 0	= (Data.Polynomial.zero, numerator)
src/Factory/Math/DivideAndConquer.hs view
@@ -25,7 +25,7 @@ 	* Implementations of this strategy have been provided for /addition/ and /multiplication/, 	though other associative binary operators, like 'gcd' or 'lcm' could also be used. -	* Where the contents of the list are consecutive, a more efficient implementation is available in /Factory.Data.Bounds/.+	* Where the contents of the list are consecutive, a more efficient implementation is available in /Factory.Data.Interval/. -}  module Factory.Math.DivideAndConquer(
src/Factory/Math/Implementations/Factorial.hs view
@@ -45,7 +45,7 @@ ) where  import qualified	Data.Numbers.Primes-import qualified	Factory.Data.Bounds		as Data.Bounds+import qualified	Factory.Data.Interval		as Data.Interval import qualified	Factory.Data.PrimeFactors	as Data.PrimeFactors import qualified	Factory.Math.Factorial		as Math.Factorial import qualified	ToolShed.Defaultable		as Defaultable@@ -54,7 +54,7 @@  -- | The algorithms by which /factorial/ has been implemented. data Algorithm	=-	Bisection		-- ^ The integers from which the /factorial/ is composed, are multiplied using @Data.Bounds.product'@.+	Bisection		-- ^ The integers from which the /factorial/ is composed, are multiplied using @Data.Interval.product'@. 	| PrimeFactorisation	-- ^ The /prime factors/ of the /factorial/ are extracted, then raised to the appropriate power, before multiplication. 	deriving (Eq, Read, Show) @@ -104,7 +104,7 @@ 	-> i	-- ^ The result. risingFactorial _ 0	= 1 risingFactorial 0 _	= 0-risingFactorial x n	= Data.Bounds.product' (recip 2) 64 $ Data.Bounds.normalise (x, (x + n) - 1)+risingFactorial x n	= Data.Interval.product' (recip 2) 64 $ Data.Interval.normalise (x, (x + n) - 1)  -- | Returns the /falling factorial/; <http://mathworld.wolfram.com/FallingFactorial.html> fallingFactorial :: Integral i@@ -113,7 +113,7 @@ 	-> i	-- ^ The result. fallingFactorial _ 0	= 1 fallingFactorial 0 _	= 0-fallingFactorial x n	= Data.Bounds.product' (recip 2) 64 $ Data.Bounds.normalise (x, (x - n) + 1)+fallingFactorial x n	= Data.Interval.product' (recip 2) 64 $ Data.Interval.normalise (x, (x - n) + 1)  {- | 	* Returns the ratio of two factorials.@@ -134,5 +134,5 @@ 	| denominator <= 1		= fromIntegral $ Math.Factorial.factorial (Defaultable.defaultValue :: Algorithm) numerator 	| numerator == denominator	= 1 	| numerator < denominator	= recip $ denominator !/! numerator	--Recurse.-	| otherwise			= fromIntegral $ Data.Bounds.product' (recip 2) 64 (succ denominator, numerator)+	| otherwise			= fromIntegral $ Data.Interval.product' (recip 2) 64 (succ denominator, numerator) 
src/Factory/Math/Implementations/Pi/Ramanujan/Classic.hs view
@@ -17,7 +17,7 @@ {- |  [@AUTHOR@]	Dr. Alistair Ward - [@DESCRIPTION@]	Defines the /Ramanujan/ series for /Pi/; <http://en.wikipedia.org/wiki/Srinivasa_Ramanujan>.+ [@DESCRIPTION@]	Defines the /Ramanujan/ series for /Pi/; <http://planetmath.org/encyclopedia/RamanujansFormulaForPi.html>. -}  module Factory.Math.Implementations.Pi.Ramanujan.Classic(
src/Factory/Math/Implementations/Pi/Spigot/Spigot.hs view
@@ -45,7 +45,6 @@ --	getRemainder ) where -import			Data.Ratio((%)) import qualified	Control.Arrow import qualified	Data.Char import qualified	Data.Ratio@@ -133,7 +132,7 @@ 	* Call 'processColumns'. -} mkRow :: Math.Implementations.Pi.Spigot.Series.Series I -> PreDigits -> Coefficients -> Pi-mkRow series preDigits	= processColumns series preDigits . zip (1 % decimal : Math.Implementations.Pi.Spigot.Series.bases series) . map (* decimal)+mkRow series preDigits	= processColumns series preDigits . zip (recip (fromIntegral decimal) : Math.Implementations.Pi.Spigot.Series.bases series) . map (* decimal)  {- | 	* Initialises a /spigot/-table with the row of 'Math.Implementations.Pi.Spigot.Series.coefficients'.
src/Factory/Math/Implementations/PrimeFactorisation.hs view
@@ -39,7 +39,7 @@ --	factoriseByTrialDivision ) where -import			Control.Arrow((&&&), (***))+import			Control.Arrow((&&&)) import qualified	Control.Arrow import qualified	Control.DeepSeq import qualified	Data.Maybe@@ -50,6 +50,7 @@ import qualified	Factory.Math.Power		as Math.Power import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation import qualified	ToolShed.Defaultable		as Defaultable+import qualified	ToolShed.Pair			as Pair  #if MIN_VERSION_parallel(3,0,0) import qualified	Control.Parallel.Strategies@@ -108,9 +109,7 @@ 		Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq	--CAVEAT: unproductive on the size of integers tested so far. 	) . #endif-	(-		factoriseByFermatsMethod *** factoriseByFermatsMethod	--Divide and conquer.-	) $ head factors+	Pair.mirror factoriseByFermatsMethod $ head factors 	where --		maybeSquareNumber :: Integral i => Maybe i 		maybeSquareNumber	= Math.Power.maybeSquareNumber i
+ src/Factory/Math/Probability.hs view
@@ -0,0 +1,181 @@+{-+	Copyright (C) 2011 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Miscellaneous functions for probability-distributions.+-}++module Factory.Math.Probability(+-- * Types+-- ** Data-types+	ContinuousDistribution(..),+	DiscreteDistribution(..),+-- * Functions+	boxMullerTransform,+--	minPositiveFloat,+--	reProfile,+	generateStandardizedNormalDistribution,+	generateContinuousPopulation,+	generatePoissonDistribution,+	generateDiscretePopulation+) where++import qualified	Control.Arrow+import			Control.Arrow((***), (&&&))+import qualified	Factory.Data.Interval	as Data.Interval+import qualified	System.Random+import qualified	ToolShed.ListPlus	as ListPlus+import qualified	ToolShed.Pair		as Pair+import qualified	ToolShed.SelfValidate	as SelfValidate++-- | Describes a /continuous probability-distribution/; <http://en.wikipedia.org/wiki/List_of_probability_distributions#Continuous_distributions>.+data ContinuousDistribution f+	= UniformDistribution (Data.Interval.Interval f)	-- ^ Defines a /Uniform/-distribution within a closed /interval/; <http://en.wikipedia.org/wiki/Uniform_distribution>.+	| NormalDistribution f f				-- ^ Defines a /Normal/-distribution with a particular /mean/ and /variance/; <http://en.wikipedia.org/wiki/Normal_distribution>.+	deriving (Eq, Read, Show)++instance (Num a, Ord a) => SelfValidate.SelfValidator (ContinuousDistribution a)	where+	isValid (UniformDistribution interval)	= not $ Data.Interval.isReversed interval+	isValid (NormalDistribution _ v)	= v >= 0++-- | Describes a /discrete probability-distribution/; <http://en.wikipedia.org/wiki/List_of_probability_distributions#Discrete_distributions>.+data DiscreteDistribution f	= PoissonDistribution f	deriving (Eq, Read, Show)++instance (Num f, Ord f) => SelfValidate.SelfValidator (DiscreteDistribution f)	where+	isValid (PoissonDistribution lambda)	= lambda >= 0++{- |+	* Converts a pair of independent /uniformly distributed/ random numbers, within the /semi-closed/ /unit interval/ /(0 .. 1]/,+	to a pair of independent /normally distributed/ random numbers, of standardized /mean/=0, and /variance/=1.++	* <http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform>.+-}+boxMullerTransform :: (Floating f, Ord f)+	=> (f, f)	-- ^ Independent, /uniformly distributed/ random numbers, which must be within the /semi-closed unit interval/, /(0, 1]/.+	-> (f, f)	-- ^ Independent, /normally distributed/ random numbers, with standardized /mean/=0 and /variance/=1.+boxMullerTransform cartesian+	| not . Pair.both $ Pair.mirror inSemiClosedUnitInterval cartesian	= error $ "Factory.Math.Probability.boxMullerTransform:\tspecified Cartesian coordinates, must be within semi-closed unit-interval (0, 1]; " ++ show cartesian+	| otherwise								= polarToCartesianTransform $ (sqrt . negate . (* 2) . log *** (* 2) . (* pi)) cartesian+	where+		inSemiClosedUnitInterval :: (Num n, Ord n) => n -> Bool+		inSemiClosedUnitInterval	= Pair.both . ((> 0) &&& (<= 1))++		polarToCartesianTransform :: Floating f => (f, f) -> (f, f)+		polarToCartesianTransform	= uncurry (*) . Control.Arrow.second cos &&& uncurry (*) . Control.Arrow.second sin++{- |+	* Determines the minimum positive floating-point number, which can be represented by using the parameter's type.++	* Only the type of the parameter is relevant, not its value.+-}+minPositiveFloat :: RealFloat a => a -> a+minPositiveFloat	= encodeFloat 1 . uncurry (-) . (fst . floatRange &&& floatDigits)++{- |+	* Uses the supplied random-number generator,+	to generate a conceptually infinite list, of /normally distributed/ random numbers, with standardized /mean/=0, and /variance/=1.++	* <http://en.wikipedia.org/wiki/Normal_distribution>, <http://mathworld.wolfram.com/NormalDistribution.html>.+-}+generateStandardizedNormalDistribution :: (System.Random.RandomGen g, RealFloat f, System.Random.Random f) => g -> [f]+generateStandardizedNormalDistribution	= ListPlus.linearise . uncurry (zipWith $ curry boxMullerTransform) . Pair.mirror (+	System.Random.randomRs (minPositiveFloat undefined, 1)+ ) . System.Random.split++-- | Stretches and shifts a /standardized normal distribution/ to achieve the required /mean/ and /standard-deviation/.+reProfile :: Num n => n -> n -> [n] -> [n]+reProfile mean standardDeviation = map ((+ mean) . (* standardDeviation))++{- |+	* Generates a random sample-population, with the specified continuous probability-distribution. ++	* When a /Normal distribution/ is requested,+	the generated population will only tend towards the requested /mean/ and /variance/ of, as the sample-size tends towards infinity.+	Whilst one could arrange for these criteria to be precisely met for any sample-size, the sample would lose a degree of randomness as a result.+-}+generateContinuousPopulation :: (RealFloat f, System.Random.Random f, System.Random.RandomGen g)+	=> Int	-- ^ number of items.+	-> ContinuousDistribution f+	-> g	-- ^ A generator of /uniformly distributed/ random numbers.+	-> [f]+generateContinuousPopulation 0 _ _				= []+generateContinuousPopulation populationSize probabilityDistribution randomGen+	| populationSize < 0					= error $ "Factory.Math.Probability.generateDiscretePopulation:\tinvalid population-size=" ++ show populationSize+	| not $ SelfValidate.isValid probabilityDistribution	= error $ "Factory.Math.Probability.generateContinuousPopulation:\tinvalid; '" ++ show probabilityDistribution ++ "'"+	| otherwise						= take populationSize $ (+		case probabilityDistribution of+			UniformDistribution interval				-> System.Random.randomRs interval+			NormalDistribution requiredMean requiredVariance	-> reProfile requiredMean (sqrt requiredVariance) . generateStandardizedNormalDistribution+	) randomGen++{- |+	* Uses the supplied random-number generator,+	to generate a conceptually infinite list, of random integers conforming to the /Poisson distribution/ (/mean/=lambda, /variance/=lambda).++	* <http://en.wikipedia.org/wiki/Poisson_distribution>.++	* CAVEAT:+		uses an algorithm by Knuth, which having a /linear time-complexity/ in /lambda/, can be intolerably slow;+		also, the term @exp $ negate lambda@, underflows for large /lambda/;+		so for large /lambda/, this implementation returns the appropriate 'NormalDistribution', which is similar for large /lambda/.+-}+generatePoissonDistribution :: (+	RealFloat		lambda,+	System.Random.Random	lambda,+	System.Random.RandomGen	g,+	Integral		events+ )+	=> lambda	-- ^ Defines the required approximate value of both /mean/ and /variance/.+	-> g+	-> [events]+generatePoissonDistribution lambda+	| lambda < 0	= error $ "Factory.Math.Probability.generatePoissonDistribution:\tinvalid lambda=" ++ show lambda+	| lambda > (+		negate . log $ minPositiveFloat lambda	--Guard against underflow, in the user-defined type for lambda.+	)		= filter (>= 0) . map round . reProfile lambda (sqrt lambda) . generateStandardizedNormalDistribution+	| otherwise	= generator+	where+		generator	= uncurry (:) . (+			fst . head . dropWhile (+				(> exp (negate lambda)) . snd	--CAVEAT: underflows if lambda > (103 :: Float, 745 :: Double).+			) . scanl (+				\accumulator random	-> succ *** (* random) $ accumulator+			) (negate 1, 1) . System.Random.randomRs (0, 1) *** generator {-recurse-}+		 ) . System.Random.split++-- | Generates a random sample-population, with the specified discrete probability-distribution. +generateDiscretePopulation :: (+	Ord			f,+	RealFloat		f,+	System.Random.Random	f,+	System.Random.RandomGen	g,+	Integral		events+ )+	=> Int	-- ^ number of items.+	-> DiscreteDistribution f+	-> g	-- ^ A generator of /uniformly distributed/ random numbers.+	-> [events]+generateDiscretePopulation 0 _ _				= []+generateDiscretePopulation populationSize probabilityDistribution randomGen+	| populationSize < 0					= error $ "Factory.Math.Probability.generateDiscretePopulation:\tinvalid populationSize=" ++ show populationSize+	| not $ SelfValidate.isValid probabilityDistribution	= error $ "Factory.Math.Probability.generateDiscretePopulation:\tinvalid; '" ++ show probabilityDistribution ++ "'"+	| otherwise						= take populationSize $ (+		case probabilityDistribution of+			PoissonDistribution lambda	-> generatePoissonDistribution lambda+	) randomGen+
src/Factory/Math/Statistics.hs view
@@ -22,7 +22,12 @@  module Factory.Math.Statistics( -- * Functions-	mean,+	getMean,+--	getDispersionFromMean,+	getVariance,+	getStandardDeviation,+	getAverageAbsoluteDeviation,+	getCoefficientOfVariance, 	nCr, 	nPr ) where@@ -30,21 +35,64 @@ import			Control.Arrow((***)) import			Control.Parallel(par, pseq) import qualified	Data.List---import qualified	Factory.Data.PrimeFactors		as Data.PrimeFactors---import		Factory.Data.PrimeFactors((>/<), (>*<))+import qualified	Data.Ratio import qualified	Factory.Math.Factorial			as Math.Factorial import qualified	Factory.Math.Implementations.Factorial	as Math.Implementations.Factorial+import qualified	Factory.Math.Power			as Math.Power --- | Determines the <http://en.wikipedia.org/wiki/Mean> of the supplied numbers.-mean :: (Real r, Fractional f) => [r] -> f-mean []	= error "Factory.Math.Statistics.mean:\tundefined result for specified null-list"-mean l	= uncurry (/) . (realToFrac *** fromIntegral) $ foldr (\s -> (+ s) *** succ) (0, 0 :: Int) l+{- |+	* Determines the /mean/ of the specified list of numbers; <http://en.wikipedia.org/wiki/Mean>. +	* Should the caller define the result-type as 'Data.Ratio.Rational', then it will be free from rounding-errors.+-}+getMean :: (Real r, Fractional result) => [r] -> result+getMean []	= error "Factory.Math.Statistics.getMean:\tundefined result for null-list."+getMean [x]	= realToFrac x	--Not necessary, but a shortcut for this special case.+getMean l	= uncurry (/) . (realToFrac *** fromIntegral) $ foldr (\s -> (+ s) *** succ) (0, 0 :: Int) l++{- |+	* Measures the dispersion of a population of results from the mean value; <http://en.wikipedia.org/wiki/Statistical_dispersion>.++	* Should the caller define the result-type as 'Data.Ratio.Rational', then it will be free from rounding-errors.+-}+getDispersionFromMean :: (Real r, Fractional result) => (Data.Ratio.Rational -> Data.Ratio.Rational) -> [r] -> result+getDispersionFromMean _ []	= error "Factory.Math.Statistics.getDispersionFromMean:\tundefined result for null-list."+getDispersionFromMean _ [_]	= 0	--Not necessary, but a shortcut for this special case.+getDispersionFromMean measure l	= getMean $ map (measure . (+ negate (getMean l :: Data.Ratio.Rational)) . realToFrac) l++{- |+	* Determines the exact /variance/ of the specified list of numbers; <http://en.wikipedia.org/wiki/Variance>.++	* Should the caller define the result-type as 'Data.Ratio.Rational', then it will be free from rounding-errors.+-}+getVariance :: (Real r, Fractional result) => [r] -> result+getVariance	= getDispersionFromMean Math.Power.square++-- | Determines the /standard-deviation/ of the specified list of numbers; <http://en.wikipedia.org/wiki/Standard_deviation>.+getStandardDeviation :: (Real r, Floating result) => [r] -> result+getStandardDeviation	= sqrt . getVariance++{- |+	* Determines the /average absolute deviation/ of the specified list of numbers; <http://en.wikipedia.org/wiki/Absolute_deviation#Average_absolute_deviation>.++	* Should the caller define the result-type as 'Data.Ratio.Rational', then it will be free from rounding-errors.+-}+getAverageAbsoluteDeviation :: (Real r, Fractional result) => [r] -> result+getAverageAbsoluteDeviation 	= getDispersionFromMean abs++-- | Determines the /coefficient-of-variance/ of the specified list of numbers; <http://en.wikipedia.org/wiki/Coefficient_of_variation>.+getCoefficientOfVariance :: (Real r, Floating result) => [r] -> result+getCoefficientOfVariance l+	| mean == 0	= error "Factory.Math.Statistics.getCoefficientOfVariance:\tundefined if mean is zero." +	| otherwise	= getStandardDeviation l / abs mean+	where+		mean	= getMean l+ -- | The number of unordered combinations of /r/ objects taken from /n/; <http://en.wikipedia.org/wiki/Combination>. nCr :: (Math.Factorial.Algorithm factorialAlgorithm, Integral i) 	=> factorialAlgorithm 	-> i	-- ^ The total number of items from which to select.-	-> i	-- ^ The number of iterms in a sample.+	-> i	-- ^ The number of items in a sample. 	-> i	-- ^ The number of combinations. nCr _ 0 _	= 1 nCr _ _ 0	= 1@@ -52,12 +100,6 @@ 	| n < 0		= error $ "Factory.Math.Statistics.nCr:\tinvalid n; " ++ show n 	| r < 0		= error $ "Factory.Math.Statistics.nCr:\tinvalid r; " ++ show r 	| n < r		= 0-{--	| otherwise	= uncurry div $ product' *** product' $ Math.Implementations.Factorial.primeFactors n >/< (-		Math.Implementations.Factorial.primeFactors r >*< Math.Implementations.Factorial.primeFactors (n - r)-	) where-		product'	= Data.PrimeFactors.product' (recip 2) 10--} 	| otherwise	= numerator `par` (denominator `pseq` numerator `div` denominator) 	where 		[smaller, bigger]	= Data.List.sort [r, n - r]
− src/Factory/Test/QuickCheck/Bounds.hs
@@ -1,43 +0,0 @@-{--	Copyright (C) 2011 Dr. Alistair Ward--	This program is free software: you can redistribute it and/or modify-	it under the terms of the GNU General Public License as published by-	the Free Software Foundation, either version 3 of the License, or-	(at your option) any later version.--	This program is distributed in the hope that it will be useful,-	but WITHOUT ANY WARRANTY; without even the implied warranty of-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-	GNU General Public License for more details.--	You should have received a copy of the GNU General Public License-	along with this program.  If not, see <http://www.gnu.org/licenses/>.--}-{- |- [@AUTHOR@]	Dr. Alistair Ward-- [@DESCRIPTION@]	Defines /QuickCheck/-properties for "Data.Bounds".--}--module Factory.Test.QuickCheck.Bounds(--- * Functions-	quickChecks-) where--import qualified	Data.Ratio-import qualified	Factory.Data.Bounds	as Data.Bounds-import qualified	Test.QuickCheck---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= Test.QuickCheck.quickCheckWith Test.QuickCheck.stdArgs {Test.QuickCheck.maxSuccess = 1000} prop_product	where-	prop_product :: Data.Ratio.Ratio Integer -> Integer -> Data.Bounds.Bounds Integer -> Test.QuickCheck.Property-	prop_product ratio minLength bounds	= Test.QuickCheck.label "prop_product" $ Data.Bounds.product' ratio' minLength' bounds' == product (Data.Bounds.toList bounds')	where-		bounds'		= Data.Bounds.normalise bounds-		minLength'	= 1 + minLength `mod` 1000-		ratio'		= if r > 1-			then recip r-			else r-			where-				r	= abs ratio
+ src/Factory/Test/QuickCheck/Interval.hs view
@@ -0,0 +1,43 @@+{-+	Copyright (C) 2011 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Defines /QuickCheck/-properties for "Data.Interval".+-}++module Factory.Test.QuickCheck.Interval(+-- * Functions+	quickChecks+) where++import qualified	Data.Ratio+import qualified	Factory.Data.Interval	as Data.Interval+import qualified	Test.QuickCheck++-- | Defines invariant properties.+quickChecks :: IO ()+quickChecks	= Test.QuickCheck.quickCheckWith Test.QuickCheck.stdArgs {Test.QuickCheck.maxSuccess = 1000} prop_product	where+	prop_product :: Data.Ratio.Ratio Integer -> Integer -> Data.Interval.Interval Integer -> Test.QuickCheck.Property+	prop_product ratio minLength interval	= Test.QuickCheck.label "prop_product" $ Data.Interval.product' ratio' minLength' interval' == product (Data.Interval.toList interval')	where+		interval'	= Data.Interval.normalise interval+		minLength'	= 1 + minLength `mod` 1000+		ratio'		= if r > 1+			then recip r+			else r+			where+				r	= abs ratio
+ src/Factory/Test/QuickCheck/Probability.hs view
@@ -0,0 +1,69 @@+{-+	Copyright (C) 2011 Dr. Alistair Ward++	This program is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Defines /QuickCheck/-properties for "Math.Probability".+-}++module Factory.Test.QuickCheck.Probability(+-- * Functions+	quickChecks+) where++import			Control.Arrow((&&&))+import qualified	Factory.Math.Probability		as Math.Probability+import qualified	Factory.Math.Statistics			as Math.Statistics+import			Factory.Test.QuickCheck.Factorial()+import qualified	ToolShed.Pair				as Pair+import qualified	System.Random+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++-- | Defines invariant properties.+quickChecks :: IO ()+quickChecks	= do+	randomGen	<- System.Random.getStdGen++	(+		Test.QuickCheck.quickCheck (prop_normalDistribution randomGen)+		>> Test.QuickCheck.quickCheck (prop_poissonDistribution randomGen)+	 ) where+		prop_normalDistribution :: System.Random.RandomGen g => g -> (Double, Double) -> Test.QuickCheck.Property+		prop_normalDistribution randomGen (mean, variance)	= variance' /= 0	==> Test.QuickCheck.label "prop_normalDistribution" . Pair.both . Pair.mirror (+			(< (0.05 :: Double)) . abs	--Tolerance.+		 ) . (+			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation+		 ) . map (+			(/ sqrt variance') . (+ negate mean)	--Standardize.+		 ) $ Math.Probability.generateContinuousPopulation 1000 (Math.Probability.NormalDistribution mean variance') randomGen	where+			variance'	= abs variance++		prop_poissonDistribution :: System.Random.RandomGen g => g -> Int -> Test.QuickCheck.Property+		prop_poissonDistribution randomGen lambda	= lambda' /= 0	==> Test.QuickCheck.label "prop_poissonDistribution" . Pair.both . Pair.mirror (+			(< (0.1 :: Double)) . abs	--Tolerance.+		 ) . (+			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation+		 ) $ map (+			(/ sqrt lambda') . (+ negate lambda') . fromIntegral	--Standardize.+		 ) (+			Math.Probability.generateDiscretePopulation 1000 (Math.Probability.PoissonDistribution lambda') randomGen :: [Int]+		 ) where+			lambda' :: Double+			lambda'	= fromIntegral $ lambda `mod` 1000++
src/Factory/Test/QuickCheck/QuickChecks.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {- 	Copyright (C) 2011 Dr. Alistair Ward @@ -27,14 +26,15 @@ ) where  import qualified	Factory.Test.QuickCheck.ArithmeticGeometricMean-import qualified	Factory.Test.QuickCheck.Bounds import qualified	Factory.Test.QuickCheck.Factorial+import qualified	Factory.Test.QuickCheck.Interval import qualified	Factory.Test.QuickCheck.MonicPolynomial import qualified	Factory.Test.QuickCheck.Pi import qualified	Factory.Test.QuickCheck.Polynomial import qualified	Factory.Test.QuickCheck.Power import qualified	Factory.Test.QuickCheck.Primality import qualified	Factory.Test.QuickCheck.PrimeFactorisation+import qualified	Factory.Test.QuickCheck.Probability import qualified	Factory.Test.QuickCheck.Radix import qualified	Factory.Test.QuickCheck.SquareRoot import qualified	Factory.Test.QuickCheck.Statistics@@ -43,14 +43,15 @@ -- | Run the /quickChecks/-functions for modules supporting this feature. run :: IO () run	= putStrLn "ArithmeticGeometricMean"	>> Factory.Test.QuickCheck.ArithmeticGeometricMean.quickChecks-	>> putStrLn "Bounds"			>> Factory.Test.QuickCheck.Bounds.quickChecks 	>> putStrLn "Factorial"			>> Factory.Test.QuickCheck.Factorial.quickChecks+	>> putStrLn "Interval"			>> Factory.Test.QuickCheck.Interval.quickChecks 	>> putStrLn "MonicPolynomial"		>> Factory.Test.QuickCheck.MonicPolynomial.quickChecks 	>> putStrLn "Pi"			>> Factory.Test.QuickCheck.Pi.quickChecks 	>> putStrLn "Polynomial"		>> Factory.Test.QuickCheck.Polynomial.quickChecks 	>> putStrLn "Power"			>> Factory.Test.QuickCheck.Power.quickChecks 	>> putStrLn "Primality"			>> Factory.Test.QuickCheck.Primality.quickChecks 	>> putStrLn "PrimeFactorisation"	>> Factory.Test.QuickCheck.PrimeFactorisation.quickChecks+	>> putStrLn "Probability"		>> Factory.Test.QuickCheck.Probability.quickChecks 	>> putStrLn "Radix"			>> Factory.Test.QuickCheck.Radix.quickChecks 	>> putStrLn "SquareRoot"		>> Factory.Test.QuickCheck.SquareRoot.quickChecks 	>> putStrLn "Statistics"		>> Factory.Test.QuickCheck.Statistics.quickChecks
src/Factory/Test/QuickCheck/Statistics.hs view
@@ -27,7 +27,9 @@  import qualified	Data.List import qualified	Data.Numbers.Primes+import qualified	Data.Ratio import qualified	Factory.Math.Implementations.Factorial	as Math.Implementations.Factorial+import qualified	Factory.Math.Power			as Math.Power import qualified	Factory.Math.Statistics			as Math.Statistics import			Factory.Test.QuickCheck.Factorial() import qualified	Test.QuickCheck@@ -35,34 +37,43 @@  -- | Defines invariant properties. quickChecks :: IO ()-quickChecks	=-	Test.QuickCheck.quickCheck `mapM_` [prop_nC0, prop_nC1, prop_sum]+quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_nC0, prop_nC1, prop_sum] 	>> Test.QuickCheck.quickCheck `mapM_` [prop_symmetry, prop_prime] 	>> Test.QuickCheck.quickCheck `mapM_` [prop_nP0, prop_nP1]-	>> Test.QuickCheck.quickCheck prop_balance	where-		prop_nC0, prop_nC1, prop_sum :: Math.Implementations.Factorial.Algorithm -> Integer -> Test.QuickCheck.Property-		prop_nC0 algorithm n	= Test.QuickCheck.label "prop_nC0" $ Math.Statistics.nCr algorithm (abs n) 0 == 1+	>> Test.QuickCheck.quickCheck `mapM_` [prop_zeroVariance, prop_zeroAverageAbsoluteDeviation]+	>> Test.QuickCheck.quickCheck `mapM_` [prop_balance, prop_varianceRelocated, prop_varianceScaled, prop_varianceOrder, prop_equivalence]+ where+	prop_nC0, prop_nC1, prop_sum :: Math.Implementations.Factorial.Algorithm -> Integer -> Test.QuickCheck.Property+	prop_nC0 algorithm n	= Test.QuickCheck.label "prop_nC0" $ Math.Statistics.nCr algorithm (abs n) 0 == 1 -		prop_nC1 algorithm i	= Test.QuickCheck.label "prop_nC1" $ Math.Statistics.nCr algorithm n 1 == n	where-			n	= 1 + abs i+	prop_nC1 algorithm i	= Test.QuickCheck.label "prop_nC1" $ Math.Statistics.nCr algorithm n 1 == n	where+		n	= 1 + abs i -		prop_sum algorithm i	= Test.QuickCheck.label "prop_sum" $ sum (Math.Statistics.nCr algorithm n `map` [0 .. n]) == 2 ^ n	where-			n	= 1 + abs i+	prop_sum algorithm i	= Test.QuickCheck.label "prop_sum" $ sum (Math.Statistics.nCr algorithm n `map` [0 .. n]) == 2 ^ n	where+		n	= 1 + abs i -		prop_symmetry, prop_prime :: Math.Implementations.Factorial.Algorithm -> (Integer, Integer) -> Test.QuickCheck.Property-		prop_symmetry algorithm (i, j)	= Test.QuickCheck.label "prop_symmetry" $ Math.Statistics.nCr algorithm n r == Math.Statistics.nCr algorithm n (n - r)	where-			[r, n]		= Data.List.sort $ map abs [i, j]+	prop_symmetry, prop_prime :: Math.Implementations.Factorial.Algorithm -> (Integer, Integer) -> Test.QuickCheck.Property+	prop_symmetry algorithm (i, j)	= Test.QuickCheck.label "prop_symmetry" $ Math.Statistics.nCr algorithm n r == Math.Statistics.nCr algorithm n (n - r)	where+		[r, n]		= Data.List.sort $ map abs [i, j] -		prop_prime algorithm (i, j)	= r `notElem` [0, n]	==> Test.QuickCheck.label "prop_prime" $ (Math.Statistics.nCr algorithm n r `mod` n) == 0	where-			n	= Data.Numbers.Primes.primes !! fromIntegral (i `mod` 500000)-			r	= j `mod` n	--Ensure r is smaller than n.+	prop_prime algorithm (i, j)	= r `notElem` [0, n]	==> Test.QuickCheck.label "prop_prime" $ (Math.Statistics.nCr algorithm n r `mod` n) == 0	where+		n	= Data.Numbers.Primes.primes !! fromIntegral (i `mod` 500000)+		r	= j `mod` n	--Ensure r is smaller than n. -		prop_nP0, prop_nP1 :: Integer -> Test.QuickCheck.Property-		prop_nP0 n	= Test.QuickCheck.label "prop_nP0" $ Math.Statistics.nPr (abs n) 0 == 1+	prop_nP0, prop_nP1 :: Integer -> Test.QuickCheck.Property+	prop_nP0 n	= Test.QuickCheck.label "prop_nP0" $ Math.Statistics.nPr (abs n) 0 == 1 -		prop_nP1 i	= Test.QuickCheck.label "prop_nP1" $ Math.Statistics.nPr n 1 == n	where-			n	= 1 + abs i+	prop_nP1 i	= Test.QuickCheck.label "prop_nP1" $ Math.Statistics.nPr n 1 == n	where+		n	= 1 + abs i -		prop_balance :: [Integer] -> Test.QuickCheck.Property-		prop_balance l	= not (null l)	==> Test.QuickCheck.label "prop_balance" . (< 1e-11 {-rounding errors-}) . abs . sum $ map (\i -> fromIntegral i - (Math.Statistics.mean l :: Double)) l+	prop_zeroVariance, prop_zeroAverageAbsoluteDeviation :: Data.Ratio.Rational -> Test.QuickCheck.Property+	prop_zeroVariance x			= Test.QuickCheck.label "prop_zeroVariance" $ Math.Statistics.getVariance (replicate 32 x) == (0 :: Data.Ratio.Rational)+	prop_zeroAverageAbsoluteDeviation x	= Test.QuickCheck.label "zeroAverageAbsoluteDeviation" $ Math.Statistics.getAverageAbsoluteDeviation (replicate 32 x) == (0 :: Data.Ratio.Rational)++	prop_balance, prop_varianceRelocated, prop_varianceScaled, prop_varianceOrder, prop_equivalence :: [Integer] -> Test.QuickCheck.Property+	prop_balance l			= not (null l)	==> Test.QuickCheck.label "prop_balance" . (== 0) . abs . sum $ map (\i -> fromIntegral i - (Math.Statistics.getMean l :: Data.Ratio.Rational)) l+	prop_varianceRelocated l	= not (null l)	==> Test.QuickCheck.label "prop_varianceRelocated" $ (Math.Statistics.getVariance l :: Data.Ratio.Rational) == Math.Statistics.getVariance (map succ l)+	prop_varianceScaled l		= not (null l)	==> Test.QuickCheck.label "prop_varianceScaled" $ (4 * Math.Statistics.getVariance l :: Data.Ratio.Rational) == Math.Statistics.getVariance (map (* 2) l)+	prop_varianceOrder l		= not (null l)	==> Test.QuickCheck.label "prop_varianceOrder" $ Math.Statistics.getVariance l == (Math.Statistics.getVariance (reverse l) :: Data.Ratio.Rational)+	prop_equivalence l		= not (null l)	==> Test.QuickCheck.label "prop_equivalence" $ Math.Statistics.getVariance l == Math.Statistics.getMean (map Math.Power.square l) - Math.Power.square (Math.Statistics.getMean l :: Data.Ratio.Rational) 
src/Main.hs view
@@ -98,7 +98,7 @@ 				packageIdentifier :: Distribution.Package.PackageIdentifier 				packageIdentifier	= Distribution.Package.PackageIdentifier { 					Distribution.Package.pkgName	= Distribution.Package.PackageName "factory",-					Distribution.Package.pkgVersion	= Distribution.Version.Version [0, 0, 0, 2] []+					Distribution.Package.pkgVersion	= Distribution.Version.Version [0, 0, 0, 3] [] 				}  			printUsage	= System.IO.hPutStrLn System.IO.stderr usage		>> System.exitWith System.ExitSuccess