packages feed

factory 0.2.1.1 → 0.2.1.2

raw patch · 176 files changed

+8316/−8232 lines, 176 filesdep +factorydep ~Cabaldep ~toolshedPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: factory

Dependency ranges changed: Cabal, toolshed

API changes (from Hackage documentation)

- Factory.Data.MonicPolynomial: instance (Eq c, Eq e) => Eq (MonicPolynomial c e)
- Factory.Data.MonicPolynomial: instance (Eq c, Num c, Num e, Ord e, Show c, Show e) => QuotientRing (MonicPolynomial c e)
- Factory.Data.MonicPolynomial: instance (Eq c, Num c, Num e, Ord e, Show c, Show e) => Ring (MonicPolynomial c e)
- Factory.Data.MonicPolynomial: instance (Show c, Show e) => Show (MonicPolynomial c e)
- Factory.Data.Polynomial: instance (Eq c, Fractional c, Num e, Ord e) => QuotientRing (Polynomial c e)
- Factory.Data.Polynomial: instance (Eq c, Num c, Num e, Ord e) => Ring (Polynomial c e)
- Factory.Data.Polynomial: instance (Eq coefficient, Eq exponent) => Eq (Polynomial coefficient exponent)
- Factory.Data.Polynomial: instance (Show coefficient, Show exponent) => Show (Polynomial coefficient exponent)
- Factory.Data.PrimeWheel: instance Show i => Show (PrimeWheel i)
- Factory.Data.Ring: instance Read p => Read (Product p)
- Factory.Data.Ring: instance Read s => Read (Sum s)
- Factory.Data.Ring: instance Ring r => Monoid (Product r)
- Factory.Data.Ring: instance Ring r => Monoid (Sum r)
- Factory.Data.Ring: instance Show p => Show (Product p)
- Factory.Data.Ring: instance Show s => Show (Sum s)
- Factory.Math.Implementations.Factorial: instance Algorithmic Algorithm
- Factory.Math.Implementations.Factorial: instance Defaultable Algorithm
- Factory.Math.Implementations.Factorial: instance Eq Algorithm
- Factory.Math.Implementations.Factorial: instance Read Algorithm
- Factory.Math.Implementations.Factorial: instance Show Algorithm
- Factory.Math.Implementations.Pi.AGM.Algorithm: instance Algorithmic squareRootAlgorithm => Algorithmic (Algorithm squareRootAlgorithm)
- Factory.Math.Implementations.Pi.AGM.Algorithm: instance Defaultable squareRootAlgorithm => Defaultable (Algorithm squareRootAlgorithm)
- Factory.Math.Implementations.Pi.AGM.Algorithm: instance Eq squareRootAlgorithm => Eq (Algorithm squareRootAlgorithm)
- Factory.Math.Implementations.Pi.AGM.Algorithm: instance Read squareRootAlgorithm => Read (Algorithm squareRootAlgorithm)
- Factory.Math.Implementations.Pi.AGM.Algorithm: instance Show squareRootAlgorithm => Show (Algorithm squareRootAlgorithm)
- Factory.Math.Implementations.Pi.BBP.Algorithm: instance Algorithmic Algorithm
- Factory.Math.Implementations.Pi.BBP.Algorithm: instance Defaultable Algorithm
- Factory.Math.Implementations.Pi.BBP.Algorithm: instance Eq Algorithm
- Factory.Math.Implementations.Pi.BBP.Algorithm: instance Read Algorithm
- Factory.Math.Implementations.Pi.BBP.Algorithm: instance Show Algorithm
- Factory.Math.Implementations.Pi.BBP.Series: base :: Series -> Integer
- Factory.Math.Implementations.Pi.BBP.Series: getDenominators :: Series -> Int -> [Integer]
- Factory.Math.Implementations.Pi.BBP.Series: numerators :: Series -> [Integer]
- Factory.Math.Implementations.Pi.BBP.Series: seriesScalingFactor :: Series -> Rational
- Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (Algorithmic squareRootAlgorithm, Algorithmic factorialAlgorithm) => Algorithmic (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (Defaultable squareRootAlgorithm, Defaultable factorialAlgorithm) => Defaultable (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (Eq squareRootAlgorithm, Eq factorialAlgorithm) => Eq (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (Read squareRootAlgorithm, Read factorialAlgorithm) => Read (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (Show squareRootAlgorithm, Show factorialAlgorithm) => Show (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Borwein.Series: convergenceRate :: Series squareRootAlgorithm factorialAlgorithm -> ConvergenceRate
- Factory.Math.Implementations.Pi.Borwein.Series: terms :: Series squareRootAlgorithm factorialAlgorithm -> squareRootAlgorithm -> factorialAlgorithm -> DecimalDigits -> (Rational, [Rational])
- Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (Algorithmic squareRootAlgorithm, Algorithmic factorialAlgorithm) => Algorithmic (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (Defaultable squareRootAlgorithm, Defaultable factorialAlgorithm) => Defaultable (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (Eq squareRootAlgorithm, Eq factorialAlgorithm) => Eq (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (Read squareRootAlgorithm, Read factorialAlgorithm) => Read (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (Show squareRootAlgorithm, Show factorialAlgorithm) => Show (Algorithm squareRootAlgorithm factorialAlgorithm)
- Factory.Math.Implementations.Pi.Ramanujan.Series: convergenceRate :: Series squareRootAlgorithm factorialAlgorithm -> ConvergenceRate
- Factory.Math.Implementations.Pi.Ramanujan.Series: getSeriesScalingFactor :: Series squareRootAlgorithm factorialAlgorithm -> squareRootAlgorithm -> DecimalDigits -> Rational
- Factory.Math.Implementations.Pi.Ramanujan.Series: terms :: Series squareRootAlgorithm factorialAlgorithm -> factorialAlgorithm -> [Rational]
- Factory.Math.Implementations.Pi.Spigot.Algorithm: instance Algorithmic Algorithm
- Factory.Math.Implementations.Pi.Spigot.Algorithm: instance Defaultable Algorithm
- Factory.Math.Implementations.Pi.Spigot.Algorithm: instance Eq Algorithm
- Factory.Math.Implementations.Pi.Spigot.Algorithm: instance Read Algorithm
- Factory.Math.Implementations.Pi.Spigot.Algorithm: instance Show Algorithm
- Factory.Math.Implementations.Pi.Spigot.Series: baseDenominators :: Series i -> [i]
- Factory.Math.Implementations.Pi.Spigot.Series: baseNumerators :: Series i -> [i]
- Factory.Math.Implementations.Pi.Spigot.Series: coefficients :: Series i -> [i]
- Factory.Math.Implementations.Pi.Spigot.Series: nTerms :: Series i -> DecimalDigits -> Int
- Factory.Math.Implementations.Primality: instance Algorithmic factorisationAlgorithm => Algorithmic (Algorithm factorisationAlgorithm)
- Factory.Math.Implementations.Primality: instance Defaultable (Algorithm factorisationAlgorithm)
- Factory.Math.Implementations.Primality: instance Eq factorisationAlgorithm => Eq (Algorithm factorisationAlgorithm)
- Factory.Math.Implementations.Primality: instance Read factorisationAlgorithm => Read (Algorithm factorisationAlgorithm)
- Factory.Math.Implementations.Primality: instance Show factorisationAlgorithm => Show (Algorithm factorisationAlgorithm)
- Factory.Math.Implementations.PrimeFactorisation: instance Algorithmic Algorithm
- Factory.Math.Implementations.PrimeFactorisation: instance Defaultable Algorithm
- Factory.Math.Implementations.PrimeFactorisation: instance Eq Algorithm
- Factory.Math.Implementations.PrimeFactorisation: instance Read Algorithm
- Factory.Math.Implementations.PrimeFactorisation: instance Show Algorithm
- Factory.Math.Implementations.Primes.Algorithm: instance Algorithmic Algorithm
- Factory.Math.Implementations.Primes.Algorithm: instance Defaultable Algorithm
- Factory.Math.Implementations.Primes.Algorithm: instance Eq Algorithm
- Factory.Math.Implementations.Primes.Algorithm: instance Read Algorithm
- Factory.Math.Implementations.Primes.Algorithm: instance Show Algorithm
- Factory.Math.Implementations.Primes.SieveOfAtkin: instance Eq PolynomialType
- Factory.Math.Implementations.SquareRoot: instance Algorithmic Algorithm
- Factory.Math.Implementations.SquareRoot: instance Defaultable Algorithm
- Factory.Math.Implementations.SquareRoot: instance Eq Algorithm
- Factory.Math.Implementations.SquareRoot: instance Iterator Algorithm
- Factory.Math.Implementations.SquareRoot: instance Read Algorithm
- Factory.Math.Implementations.SquareRoot: instance Show Algorithm
- Factory.Math.Pi: instance (Algorithmic agm, Algorithmic bbp, Algorithmic borwein, Algorithmic ramanujan, Algorithmic spigot) => Algorithmic (Category agm bbp borwein ramanujan spigot)
- Factory.Math.Pi: instance (Defaultable agm, Defaultable bbp, Defaultable borwein, Defaultable ramanujan, Defaultable spigot) => Defaultable (Category agm bbp borwein ramanujan spigot)
- Factory.Math.Pi: instance (Eq agm, Eq bbp, Eq borwein, Eq ramanujan, Eq spigot) => Eq (Category agm bbp borwein ramanujan spigot)
- Factory.Math.Pi: instance (Read agm, Read bbp, Read borwein, Read ramanujan, Read spigot) => Read (Category agm bbp borwein ramanujan spigot)
- Factory.Math.Pi: instance (Show agm, Show bbp, Show borwein, Show ramanujan, Show spigot) => Show (Category agm bbp borwein ramanujan spigot)
- Factory.Math.Probability: instance (Floating parameter, Ord parameter, Show parameter) => SelfValidator (ContinuousDistribution parameter)
- Factory.Math.Probability: instance (Num parameter, Ord parameter, Show parameter) => SelfValidator (DiscreteDistribution parameter)
- Factory.Math.Probability: instance (RealFloat parameter, Show parameter, Random parameter) => Distribution (ContinuousDistribution parameter)
- Factory.Math.Probability: instance (RealFloat parameter, Show parameter, Random parameter) => Distribution (DiscreteDistribution parameter)
- Factory.Math.Probability: instance Eq parameter => Eq (ContinuousDistribution parameter)
- Factory.Math.Probability: instance Eq parameter => Eq (DiscreteDistribution parameter)
- Factory.Math.Probability: instance Read parameter => Read (ContinuousDistribution parameter)
- Factory.Math.Probability: instance Read parameter => Read (DiscreteDistribution parameter)
- Factory.Math.Probability: instance Show parameter => Show (ContinuousDistribution parameter)
- Factory.Math.Probability: instance Show parameter => Show (DiscreteDistribution parameter)
+ Factory.Data.MonicPolynomial: instance (GHC.Classes.Eq c, GHC.Classes.Eq e) => GHC.Classes.Eq (Factory.Data.MonicPolynomial.MonicPolynomial c e)
+ Factory.Data.MonicPolynomial: instance (GHC.Classes.Eq c, GHC.Num.Num c, GHC.Num.Num e, GHC.Classes.Ord e, GHC.Show.Show c, GHC.Show.Show e) => Factory.Data.QuotientRing.QuotientRing (Factory.Data.MonicPolynomial.MonicPolynomial c e)
+ Factory.Data.MonicPolynomial: instance (GHC.Classes.Eq c, GHC.Num.Num c, GHC.Num.Num e, GHC.Classes.Ord e, GHC.Show.Show c, GHC.Show.Show e) => Factory.Data.Ring.Ring (Factory.Data.MonicPolynomial.MonicPolynomial c e)
+ Factory.Data.MonicPolynomial: instance (GHC.Show.Show c, GHC.Show.Show e) => GHC.Show.Show (Factory.Data.MonicPolynomial.MonicPolynomial c e)
+ Factory.Data.Polynomial: instance (GHC.Classes.Eq c, GHC.Num.Num c, GHC.Num.Num e, GHC.Classes.Ord e) => Factory.Data.Ring.Ring (Factory.Data.Polynomial.Polynomial c e)
+ Factory.Data.Polynomial: instance (GHC.Classes.Eq c, GHC.Real.Fractional c, GHC.Num.Num e, GHC.Classes.Ord e) => Factory.Data.QuotientRing.QuotientRing (Factory.Data.Polynomial.Polynomial c e)
+ Factory.Data.Polynomial: instance (GHC.Classes.Eq coefficient, GHC.Classes.Eq exponent) => GHC.Classes.Eq (Factory.Data.Polynomial.Polynomial coefficient exponent)
+ Factory.Data.Polynomial: instance (GHC.Show.Show coefficient, GHC.Show.Show exponent) => GHC.Show.Show (Factory.Data.Polynomial.Polynomial coefficient exponent)
+ Factory.Data.PrimeWheel: instance GHC.Show.Show i => GHC.Show.Show (Factory.Data.PrimeWheel.PrimeWheel i)
+ Factory.Data.Ring: instance Factory.Data.Ring.Ring r => GHC.Base.Monoid (Factory.Data.Ring.Product r)
+ Factory.Data.Ring: instance Factory.Data.Ring.Ring r => GHC.Base.Monoid (Factory.Data.Ring.Sum r)
+ Factory.Data.Ring: instance GHC.Read.Read p => GHC.Read.Read (Factory.Data.Ring.Product p)
+ Factory.Data.Ring: instance GHC.Read.Read s => GHC.Read.Read (Factory.Data.Ring.Sum s)
+ Factory.Data.Ring: instance GHC.Show.Show p => GHC.Show.Show (Factory.Data.Ring.Product p)
+ Factory.Data.Ring: instance GHC.Show.Show s => GHC.Show.Show (Factory.Data.Ring.Sum s)
+ Factory.Math.Implementations.Factorial: instance Factory.Math.Factorial.Algorithmic Factory.Math.Implementations.Factorial.Algorithm
+ Factory.Math.Implementations.Factorial: instance GHC.Classes.Eq Factory.Math.Implementations.Factorial.Algorithm
+ Factory.Math.Implementations.Factorial: instance GHC.Read.Read Factory.Math.Implementations.Factorial.Algorithm
+ Factory.Math.Implementations.Factorial: instance GHC.Show.Show Factory.Math.Implementations.Factorial.Algorithm
+ Factory.Math.Implementations.Factorial: instance ToolShed.Defaultable.Defaultable Factory.Math.Implementations.Factorial.Algorithm
+ Factory.Math.Implementations.Pi.AGM.Algorithm: instance Factory.Math.SquareRoot.Algorithmic squareRootAlgorithm => Factory.Math.Pi.Algorithmic (Factory.Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm)
+ Factory.Math.Implementations.Pi.AGM.Algorithm: instance GHC.Classes.Eq squareRootAlgorithm => GHC.Classes.Eq (Factory.Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm)
+ Factory.Math.Implementations.Pi.AGM.Algorithm: instance GHC.Read.Read squareRootAlgorithm => GHC.Read.Read (Factory.Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm)
+ Factory.Math.Implementations.Pi.AGM.Algorithm: instance GHC.Show.Show squareRootAlgorithm => GHC.Show.Show (Factory.Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm)
+ Factory.Math.Implementations.Pi.AGM.Algorithm: instance ToolShed.Defaultable.Defaultable squareRootAlgorithm => ToolShed.Defaultable.Defaultable (Factory.Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm)
+ Factory.Math.Implementations.Pi.BBP.Algorithm: instance Factory.Math.Pi.Algorithmic Factory.Math.Implementations.Pi.BBP.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.BBP.Algorithm: instance GHC.Classes.Eq Factory.Math.Implementations.Pi.BBP.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.BBP.Algorithm: instance GHC.Read.Read Factory.Math.Implementations.Pi.BBP.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.BBP.Algorithm: instance GHC.Show.Show Factory.Math.Implementations.Pi.BBP.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.BBP.Algorithm: instance ToolShed.Defaultable.Defaultable Factory.Math.Implementations.Pi.BBP.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.BBP.Series: [base] :: Series -> Integer
+ Factory.Math.Implementations.Pi.BBP.Series: [getDenominators] :: Series -> Int -> [Integer]
+ Factory.Math.Implementations.Pi.BBP.Series: [numerators] :: Series -> [Integer]
+ Factory.Math.Implementations.Pi.BBP.Series: [seriesScalingFactor] :: Series -> Rational
+ Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (Factory.Math.SquareRoot.Algorithmic squareRootAlgorithm, Factory.Math.Factorial.Algorithmic factorialAlgorithm) => Factory.Math.Pi.Algorithmic (Factory.Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (GHC.Classes.Eq squareRootAlgorithm, GHC.Classes.Eq factorialAlgorithm) => GHC.Classes.Eq (Factory.Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (GHC.Read.Read squareRootAlgorithm, GHC.Read.Read factorialAlgorithm) => GHC.Read.Read (Factory.Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (GHC.Show.Show squareRootAlgorithm, GHC.Show.Show factorialAlgorithm) => GHC.Show.Show (Factory.Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Borwein.Algorithm: instance (ToolShed.Defaultable.Defaultable squareRootAlgorithm, ToolShed.Defaultable.Defaultable factorialAlgorithm) => ToolShed.Defaultable.Defaultable (Factory.Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Borwein.Series: [convergenceRate] :: Series squareRootAlgorithm factorialAlgorithm -> ConvergenceRate
+ Factory.Math.Implementations.Pi.Borwein.Series: [terms] :: Series squareRootAlgorithm factorialAlgorithm -> squareRootAlgorithm -> factorialAlgorithm -> DecimalDigits -> (Rational, [Rational])
+ Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (Factory.Math.SquareRoot.Algorithmic squareRootAlgorithm, Factory.Math.Factorial.Algorithmic factorialAlgorithm) => Factory.Math.Pi.Algorithmic (Factory.Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (GHC.Classes.Eq squareRootAlgorithm, GHC.Classes.Eq factorialAlgorithm) => GHC.Classes.Eq (Factory.Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (GHC.Read.Read squareRootAlgorithm, GHC.Read.Read factorialAlgorithm) => GHC.Read.Read (Factory.Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (GHC.Show.Show squareRootAlgorithm, GHC.Show.Show factorialAlgorithm) => GHC.Show.Show (Factory.Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Ramanujan.Algorithm: instance (ToolShed.Defaultable.Defaultable squareRootAlgorithm, ToolShed.Defaultable.Defaultable factorialAlgorithm) => ToolShed.Defaultable.Defaultable (Factory.Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)
+ Factory.Math.Implementations.Pi.Ramanujan.Series: [convergenceRate] :: Series squareRootAlgorithm factorialAlgorithm -> ConvergenceRate
+ Factory.Math.Implementations.Pi.Ramanujan.Series: [getSeriesScalingFactor] :: Series squareRootAlgorithm factorialAlgorithm -> squareRootAlgorithm -> DecimalDigits -> Rational
+ Factory.Math.Implementations.Pi.Ramanujan.Series: [terms] :: Series squareRootAlgorithm factorialAlgorithm -> factorialAlgorithm -> [Rational]
+ Factory.Math.Implementations.Pi.Spigot.Algorithm: instance Factory.Math.Pi.Algorithmic Factory.Math.Implementations.Pi.Spigot.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.Spigot.Algorithm: instance GHC.Classes.Eq Factory.Math.Implementations.Pi.Spigot.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.Spigot.Algorithm: instance GHC.Read.Read Factory.Math.Implementations.Pi.Spigot.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.Spigot.Algorithm: instance GHC.Show.Show Factory.Math.Implementations.Pi.Spigot.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.Spigot.Algorithm: instance ToolShed.Defaultable.Defaultable Factory.Math.Implementations.Pi.Spigot.Algorithm.Algorithm
+ Factory.Math.Implementations.Pi.Spigot.Series: [baseDenominators] :: Series i -> [i]
+ Factory.Math.Implementations.Pi.Spigot.Series: [baseNumerators] :: Series i -> [i]
+ Factory.Math.Implementations.Pi.Spigot.Series: [coefficients] :: Series i -> [i]
+ Factory.Math.Implementations.Pi.Spigot.Series: [nTerms] :: Series i -> DecimalDigits -> Int
+ Factory.Math.Implementations.Primality: instance Factory.Math.PrimeFactorisation.Algorithmic factorisationAlgorithm => Factory.Math.Primality.Algorithmic (Factory.Math.Implementations.Primality.Algorithm factorisationAlgorithm)
+ Factory.Math.Implementations.Primality: instance GHC.Classes.Eq factorisationAlgorithm => GHC.Classes.Eq (Factory.Math.Implementations.Primality.Algorithm factorisationAlgorithm)
+ Factory.Math.Implementations.Primality: instance GHC.Read.Read factorisationAlgorithm => GHC.Read.Read (Factory.Math.Implementations.Primality.Algorithm factorisationAlgorithm)
+ Factory.Math.Implementations.Primality: instance GHC.Show.Show factorisationAlgorithm => GHC.Show.Show (Factory.Math.Implementations.Primality.Algorithm factorisationAlgorithm)
+ Factory.Math.Implementations.Primality: instance ToolShed.Defaultable.Defaultable (Factory.Math.Implementations.Primality.Algorithm factorisationAlgorithm)
+ Factory.Math.Implementations.PrimeFactorisation: instance Factory.Math.PrimeFactorisation.Algorithmic Factory.Math.Implementations.PrimeFactorisation.Algorithm
+ Factory.Math.Implementations.PrimeFactorisation: instance GHC.Classes.Eq Factory.Math.Implementations.PrimeFactorisation.Algorithm
+ Factory.Math.Implementations.PrimeFactorisation: instance GHC.Read.Read Factory.Math.Implementations.PrimeFactorisation.Algorithm
+ Factory.Math.Implementations.PrimeFactorisation: instance GHC.Show.Show Factory.Math.Implementations.PrimeFactorisation.Algorithm
+ Factory.Math.Implementations.PrimeFactorisation: instance ToolShed.Defaultable.Defaultable Factory.Math.Implementations.PrimeFactorisation.Algorithm
+ Factory.Math.Implementations.Primes.Algorithm: instance Factory.Math.Primes.Algorithmic Factory.Math.Implementations.Primes.Algorithm.Algorithm
+ Factory.Math.Implementations.Primes.Algorithm: instance GHC.Classes.Eq Factory.Math.Implementations.Primes.Algorithm.Algorithm
+ Factory.Math.Implementations.Primes.Algorithm: instance GHC.Read.Read Factory.Math.Implementations.Primes.Algorithm.Algorithm
+ Factory.Math.Implementations.Primes.Algorithm: instance GHC.Show.Show Factory.Math.Implementations.Primes.Algorithm.Algorithm
+ Factory.Math.Implementations.Primes.Algorithm: instance ToolShed.Defaultable.Defaultable Factory.Math.Implementations.Primes.Algorithm.Algorithm
+ Factory.Math.Implementations.Primes.SieveOfAtkin: instance GHC.Classes.Eq Factory.Math.Implementations.Primes.SieveOfAtkin.PolynomialType
+ Factory.Math.Implementations.SquareRoot: instance Factory.Math.SquareRoot.Algorithmic Factory.Math.Implementations.SquareRoot.Algorithm
+ Factory.Math.Implementations.SquareRoot: instance Factory.Math.SquareRoot.Iterator Factory.Math.Implementations.SquareRoot.Algorithm
+ Factory.Math.Implementations.SquareRoot: instance GHC.Classes.Eq Factory.Math.Implementations.SquareRoot.Algorithm
+ Factory.Math.Implementations.SquareRoot: instance GHC.Read.Read Factory.Math.Implementations.SquareRoot.Algorithm
+ Factory.Math.Implementations.SquareRoot: instance GHC.Show.Show Factory.Math.Implementations.SquareRoot.Algorithm
+ Factory.Math.Implementations.SquareRoot: instance ToolShed.Defaultable.Defaultable Factory.Math.Implementations.SquareRoot.Algorithm
+ Factory.Math.Pi: instance (Factory.Math.Pi.Algorithmic agm, Factory.Math.Pi.Algorithmic bbp, Factory.Math.Pi.Algorithmic borwein, Factory.Math.Pi.Algorithmic ramanujan, Factory.Math.Pi.Algorithmic spigot) => Factory.Math.Pi.Algorithmic (Factory.Math.Pi.Category agm bbp borwein ramanujan spigot)
+ Factory.Math.Pi: instance (GHC.Classes.Eq agm, GHC.Classes.Eq bbp, GHC.Classes.Eq borwein, GHC.Classes.Eq ramanujan, GHC.Classes.Eq spigot) => GHC.Classes.Eq (Factory.Math.Pi.Category agm bbp borwein ramanujan spigot)
+ Factory.Math.Pi: instance (GHC.Read.Read agm, GHC.Read.Read bbp, GHC.Read.Read borwein, GHC.Read.Read ramanujan, GHC.Read.Read spigot) => GHC.Read.Read (Factory.Math.Pi.Category agm bbp borwein ramanujan spigot)
+ Factory.Math.Pi: instance (GHC.Show.Show agm, GHC.Show.Show bbp, GHC.Show.Show borwein, GHC.Show.Show ramanujan, GHC.Show.Show spigot) => GHC.Show.Show (Factory.Math.Pi.Category agm bbp borwein ramanujan spigot)
+ Factory.Math.Pi: instance (ToolShed.Defaultable.Defaultable agm, ToolShed.Defaultable.Defaultable bbp, ToolShed.Defaultable.Defaultable borwein, ToolShed.Defaultable.Defaultable ramanujan, ToolShed.Defaultable.Defaultable spigot) => ToolShed.Defaultable.Defaultable (Factory.Math.Pi.Category agm bbp borwein ramanujan spigot)
+ Factory.Math.Probability: instance (GHC.Float.Floating parameter, GHC.Classes.Ord parameter, GHC.Show.Show parameter) => ToolShed.SelfValidate.SelfValidator (Factory.Math.Probability.ContinuousDistribution parameter)
+ Factory.Math.Probability: instance (GHC.Float.RealFloat parameter, GHC.Show.Show parameter, System.Random.Random parameter) => Factory.Math.Probability.Distribution (Factory.Math.Probability.ContinuousDistribution parameter)
+ Factory.Math.Probability: instance (GHC.Float.RealFloat parameter, GHC.Show.Show parameter, System.Random.Random parameter) => Factory.Math.Probability.Distribution (Factory.Math.Probability.DiscreteDistribution parameter)
+ Factory.Math.Probability: instance (GHC.Num.Num parameter, GHC.Classes.Ord parameter, GHC.Show.Show parameter) => ToolShed.SelfValidate.SelfValidator (Factory.Math.Probability.DiscreteDistribution parameter)
+ Factory.Math.Probability: instance GHC.Classes.Eq parameter => GHC.Classes.Eq (Factory.Math.Probability.ContinuousDistribution parameter)
+ Factory.Math.Probability: instance GHC.Classes.Eq parameter => GHC.Classes.Eq (Factory.Math.Probability.DiscreteDistribution parameter)
+ Factory.Math.Probability: instance GHC.Read.Read parameter => GHC.Read.Read (Factory.Math.Probability.ContinuousDistribution parameter)
+ Factory.Math.Probability: instance GHC.Read.Read parameter => GHC.Read.Read (Factory.Math.Probability.DiscreteDistribution parameter)
+ Factory.Math.Probability: instance GHC.Show.Show parameter => GHC.Show.Show (Factory.Math.Probability.ContinuousDistribution parameter)
+ Factory.Math.Probability: instance GHC.Show.Show parameter => GHC.Show.Show (Factory.Math.Probability.DiscreteDistribution parameter)

Files

+ README.markdown view
@@ -0,0 +1,23 @@+# **Factory**.++This is **Factory**, a library of number-theory functions.++## Installation++It can be built and installed using [Cabal](https://www.haskell.org/cabal/users-guide/installing-packages.html).++## Documentation++More information about this library can be found at [Factory](http://functionalley.eu/Factory/factory.html).++## License++For information on copying and distributing this package, see the file **LICENSE** in this directory.++## Bug-reporting++Bug-reports should be emailed to <factory *at* functionalley *dot* eu>.++## Author++This library is written and maintained by Dr. Alistair Ward.
− changelog
@@ -1,88 +0,0 @@-2011-03-01 Dr. Alistair Ward <factory at functionalley dot eu>--0.0.0.1-	* First version of the package.-0.0.0.2-	* Created the modules; "Factory.Test.QuickCheck.Bounds", "Factory.Math.Implementations.Pi.Borwein.*" and "Factory.Test.Performance.Statistics".-	* Created a new module "Factory.Data.PrimeFactors", and migrated definitions from both "Factory.Math.PrimeFactorisation" and "Factory.Math.Implementations.PrimeFactorisation".-	* Created the class 'Factory.Math.Factorial.Factorial' and a new module "Factory.Math.Implementations.Factorial".-	Moved existing implementation (Bisection) into the new module, with a new implementation (PrimeFactorisation).-	* Added the function 'Factory.Math.Summation.sumR'.-	* Added a parameter to the functions 'Factory.Math.DivideAndConquer.divideAndConquer' and 'Factory.Data.Bounds.divideAndConquer', to permit asymmetric bisection.-	* Added methods to class "Factory.Math.Pi.Algorithm" to permit the retrieval of /Pi/ as a 'Rational' or a 'String'.-	* Renamed the function 'Factory.Math.Precision.capPrecision' to 'Factory.Math.Precision.simplify'.-	* Removed the module "Factory.Test.Performance.Exponential".-	* Removed the function 'Factory.Math.Power.raise', which was no more efficient than ghc's implementation of '(^)'.-	* 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 the module "Factory.Math.Probability".-	* Renamed the module "Factory.Data.Bounds" to "Factory.Data.Interval",-	and added the functions; 'Factory.Data.Interval.precisely', 'Factory.Data.Interval.shift', 'Factory.Data.Interval.closedUnitInterval'.-	* Guarded 'eager-blackholing' flag in /cabal/ file.-0.1.0.1-	* Renamed classes "Factory.Math.[Primality, Pi, Factorial, SquareRoot, PrimeFactorisation].Algorithm" to "Factory.Math.[Primality, Pi, Factorial, SquareRoot, PrimeFactorisation].Algorithmic", to distinguish them from the data-types which implement them.-	* Added the modules "Factory.Math.Hyperoperation", "Factory.Test.QuickCheck.Hyperoperation" and "Factory.Test.Performance.Hyperoperation".-	* Added the modules "Factory.Math.Primes", "Factory.Math.Implementation.Primes", "Factory.Test.Performance.Primes", "Factory.Test.QuickCheck.Primes" and "Factory.Data.PrimeWheel".-	* Added the function 'Factory.Math.PrimeFactorisation.squareFree'.-	* Added rewrite-rules to specialise 'Factory.Math.Power.isPerfectPower' for type-parameter='Int'.-	* Recoded "Factory.Math.Radix" to the interface "Data.Array.IArray.IArray", rather than the data-type "Data.Array.Array".-0.1.0.2-	* Added 'Factory.Math.Primes.primorial'.-	* Altered 'Factory.Math.Implementations.Primes.trialDivision' to take an integer defining the size of a 'Factory.Data.PrimeWheel', from which candidates are extracted.-	* Removed the command-line option 'primesPerformanceGraph', which appears to memoise data from previous tests.-	* Uploaded to <http://hackage.haskell.org/packages/hackage.html>.-0.1.0.3-	* Qualified 'Factory.Math.Implementations.Primes.trialDivision' with /NOINLINE/ pragma, to block optimization which conflicts with rewrite-rule for 'Factory.Math.Implementations.Primes.sieveOfEratosthenes' !-	* Re-coded 'Factory.Data.PrimeWheel.coprimes' and 'Factory.Math.Implementations.Primes.sieveOfEratosthenes', to use a map of lists, rather than a map of lists of lists.-0.2.0.0-	* Separately coded the special-case of a 'Factory.Data.PrimeWheel' of size zero, in 'Factory.Math.Implementations.Primes.trialDivision', to achieve better space-complexity.-	* Added 'Factory.Data.PrimeWheel.estimateOptimalSize'.-	* Split "Factory.Math.Implementations.Primes" into; "Factory.Math.Implementations.Primes.SieveOfEratosthenes", "Factory.Math.Implementations.Primes.TurnersSieve", "Factory.Math.Implementations.Primes.TrialDivision", and added a new module "Factory.Math.Implementations.Primes.SieveOfAtkin". This makes the rewrite-rules less fragile.-	* Coded 'Factory.Math.Radix.digitalRoot' more concisely.-	* Split "Factory.Math.Power" into an additional module "Factory.Math.PerfectPower".-	* Replaced '(+ 1)' and '(- 1)' with the faster calls 'succ' and 'pred'.-	* Used 'Paths_factory.version' in 'Main', rather than hard-coding it.-0.2.0.1-	* Changed by Lennart Augustsson, to replace "System" with "System.Environment" and "System.Exit", and to remove dependency on "haskell98".-0.2.0.2-	* Reacted to new module-hierarchy and addition of method 'ToolShed.SelfValidate.getErrors', in 'toolshed-0.13.0.0'.-	* Made 'Factory.Data.Interval.getLength' private.-	* Added 'Factory.Data.Interval.mkBounded'.-	* Generalised "Factory.Math.Statistics" to accept any 'Data.Foldable.Foldable' 'Functor', rather than merely lists.-0.2.0.3-	* Added class 'Show' to some contexts in "Factory.Math.Radix", for migration to 'ghc-7.4'.-0.2.0.4-	* Added classes 'Eq' and 'Show' to many contexts, for migration to 'ghc-7.4'.-	* Minor re-formatting.-0.2.0.5-	* Minor clarification of 'Factory.Math.Implementations.Primality.witnessesCompositeness'.-	* Added details to any failure to parse the command-line arguments.-	* Defined package's name using program's name, in "Main.hs".-	* Added 'Factory.Math.Primes.mersenneNumbers'.-	* Replaced use of 'mod' on positive integers, with the faster 'rem', in 'Factory.Math.Implementations.Pi.Spigot.Spigot.processColumns', 'Factory.Math.Implementations.Primality.witnessesCompositeness', 'Factory.Math.Implementations.Primes.TrialDivision.isIndivisibleBy', 'Factory.Math.Implementations.Primes.SieveOfAtkin.polynomialTypeLookup', 'Factory.Math.Implementations.Primes.SieveOfAtkin.findPolynomialSolutions', 'Factory.Math.Implementations.Primes.TurnersSieve.turnersSieve', 'Factory.Math.PerfectPower.maybeSquareNumber'.-	* Replaced calls to 'realToFrac' with 'toRational' in; "Factory.Math.Implementations.SquareRoot", 'Factory.Math.Statistics.getDispersionFromMean', 'Factory.Math.SquareRoot.getDiscrepancy', 'Factory.Math.SquareRoot.getAccuracy', to more clearly represent the required operation.-0.2.1.0-	* Refactored 'Factory.Test.QuickCheck.QuickChecks'.-	* Remove redundant import of 'Data.Ratio' from many modules.-	* Refactored 'Factory.Math.Radix.encodes' to make use of 'Data.List.genericLength', & removed empty 'where'.-	* Explicitly closed standard-input in the executable.-	* Replaced calls to 'error' from inside the IO-monad, with 'Control.Monad.fail'.-	* Added function 'Factory.Math.Precision.roundTo'.-	* Trapped command-line arguments to which garbage has been appended.-	* Corrected the output of 'Main.main.optDescrList.printVersion'.-	* Removed the integral population-size parameter from 'Factory.Math.Probability.generateContinuousPopulation' & 'Factory.Math.Probability.generateDiscretePopulation', making the result conceptually infinite.-	* Created class 'Factory.Math.Probability.Distribution', to which data-types 'Factory.Math.Probability.ContinuousDistribution' & 'Factory.Math.Probability.DiscreteDistribution' conform.-	* Added data-constructors 'Factory.Math.Probability.ExponentialDistribution', 'Factory.Math.Probability.ShiftedGeometricDistribution' & 'Factory.Math.Probability.LogNormal'.-	* Added command-line option '--plotDiscreteDistribution' to "Main".-	* Removed Preprocessor-check on the version of package 'toolshed', in "Factory/Math/Summation" & "Factory/Data/PrimeFactors".-0.2.1.1-	* Added 'Factory.Test.QuickCheck.Probability.prop_logNormalDistributionEqual'.-	* Removed /INLINE/ pragma from 'Factory.Math.Implementations.Primes.TrialDivision.isIndivisibleBy', since to be effective it must be called with fully applied parameters (which it isn't).-	* Un eta-reduced 'Factory.Math.Power.square', since we want it to be inlined when called with one argument.-	* Tested with 'haskell-platform-2013.2.0.0'.-	* Replaced preprocessor-directives with 'build-depends' constraints in 'factory.cabal'.-	* Added function 'Factory.Math.Statistics.getWeightedMean' & corresponding tests in module "Factory.Test.QuickCheck.Statistics".-	* Since '(<$>)' is exported from the Prelude from 'base-4.8', imported "Prelude" hiding '(<*>)' into module "Factory.Data.Monomial", since this symbol is defined locally for other purposes.-	* Either replaced instances of '(<$>)' with 'fmap' to avoid ambiguity between "Control.Applicative" & "Prelude" which (from 'base-4.8') also exports this symbol, or hid the symbol when importing the "Prelude"..-
+ changelog.markdown view
@@ -0,0 +1,98 @@+# 2011-03-01 Dr. Alistair Ward <factory at functionalley dot eu>++## 0.0.0.1+	* First version of the package.+## 0.0.0.2+	* Created the modules; **Factory.Test.QuickCheck.Bounds**, **Factory.Math.Implementations.Pi.Borwein** & **Factory.Test.Performance.Statistics** .+	* Created a new module **Factory.Data.PrimeFactors**, and migrated definitions from both **Factory.Math.PrimeFactorisation** & **Factory.Math.Implementations.PrimeFactorisation**.+	* Created the class `Factory.Math.Factorial.Factorial` and a new module **Factory.Math.Implementations.Factorial**.+	Moved existing implementation (`Bisection`) into the new module, with a new implementation (`PrimeFactorisation`).+	* Added the function `Factory.Math.Summation.sumR`.+	* Added a parameter to the functions `Factory.Math.DivideAndConquer.divideAndConquer` and `Factory.Data.Bounds.divideAndConquer`, to permit asymmetric bisection.+	* Added methods to class `Factory.Math.Pi.Algorithm` to permit the retrieval of *Pi* as a `Rational` or a `String`.+	* Renamed the function `Factory.Math.Precision.capPrecision` to `Factory.Math.Precision.simplify`.+	* Removed the module **Factory.Test.Performance.Exponential**.+	* Removed the function `Factory.Math.Power.raise`, which was no more efficient than ghc's implementation of `(^)`.+	* Uploaded to [Hackage](http://hackage.haskell.org/packages/hackage.html).+## 0.1.0.0+	* Amended the *.cabal*-file to more correctly specify the dependency on package **toolshed**.+	* Added the module **Factory.Math.Probability**.+	* Renamed the module **Factory.Data.Bounds** to **Factory.Data.Interval**,+	and added the functions; `Factory.Data.Interval.precisely`, `Factory.Data.Interval.shift`, `Factory.Data.Interval.closedUnitInterval`.+	* Guarded **eager-blackholing** flag in the *cabal*-file.+## 0.1.0.1+	* Renamed classes *Factory.Math.[Primality, Pi, Factorial, SquareRoot, PrimeFactorisation].Algorithm* to *Factory.Math.[Primality, Pi, Factorial, SquareRoot, PrimeFactorisation].Algorithmic*, to distinguish them from the data-types which implement them.+	* Added the modules **Factory.Math.Hyperoperation**, **Factory.Test.QuickCheck.Hyperoperation** and **Factory.Test.Performance.Hyperoperation**.+	* Added the modules **Factory.Math.Primes**, **Factory.Math.Implementation.Primes**, **Factory.Test.Performance.Primes**, **Factory.Test.QuickCheck.Primes** and **Factory.Data.PrimeWheel**.+	* Added the function `Factory.Math.PrimeFactorisation.squareFree`.+	* Added rewrite-rules to specialise `Factory.Math.Power.isPerfectPower` for type-parameter=`Int`.+	* Recoded **Factory.Math.Radix** to the interface `Data.Array.IArray.IArray`, rather than the data-type `Data.Array.Array`.+## 0.1.0.2+	* Added `Factory.Math.Primes.primorial`.+	* Altered `Factory.Math.Implementations.Primes.trialDivision` to take an integer defining the size of a `Factory.Data.PrimeWheel`, from which candidates are extracted.+	* Removed the command-line option `primesPerformanceGraph`, which appears to memoise data from previous tests.+	* Uploaded to [Hackage](http://hackage.haskell.org/packages/hackage.html).+## 0.1.0.3+	* Qualified `Factory.Math.Implementations.Primes.trialDivision` with **NOINLINE**-pragma, to block optimization which conflicts with rewrite-rule for `Factory.Math.Implementations.Primes.sieveOfEratosthenes` !+	* Re-coded `Factory.Data.PrimeWheel.coprimes` and `Factory.Math.Implementations.Primes.sieveOfEratosthenes`, to use a map of lists, rather than a map of lists of lists.+## 0.2.0.0+	* Separately coded the special-case of a **Factory.Data.PrimeWheel** of size zero, in `Factory.Math.Implementations.Primes.trialDivision`, to achieve better space-complexity.+	* Added `Factory.Data.PrimeWheel.estimateOptimalSize`.+	* Split **Factory.Math.Implementations.Primes** into; **Factory.Math.Implementations.Primes.SieveOfEratosthenes**, **Factory.Math.Implementations.Primes.TurnersSieve**, **Factory.Math.Implementations.Primes.TrialDivision**, and added a new module **Factory.Math.Implementations.Primes.SieveOfAtkin**. This makes the rewrite-rules less fragile.+	* Coded `Factory.Math.Radix.digitalRoot` more concisely.+	* Split **Factory.Math.Power** into an additional module **Factory.Math.PerfectPower**.+	* Replaced `(+ 1)` and `(- 1)` with the faster calls `succ` and `pred`.+	* Used `Paths_factory.version` in **Main**, rather than hard-coding it.+## 0.2.0.1+	* Changed by Lennart Augustsson, to replace `System` with `System.Environment` and `System.Exit`, and to remove dependency on **haskell98**.+## 0.2.0.2+	* Reacted to new module-hierarchy and addition of method `ToolShed.SelfValidate.getErrors`, in **toolshed-0.13.0.0**.+	* Made `Factory.Data.Interval.getLength` private.+	* Added `Factory.Data.Interval.mkBounded`.+	* Generalised **Factory.Math.Statistics** to accept any `Data.Foldable.Foldable` *Functor*, rather than merely lists.+## 0.2.0.3+	* Added class `Show` to some contexts in **Factory.Math.Radix**, for migration to **ghc-7.4**.+## 0.2.0.4+	* Added classes `Eq` and `Show` to many contexts, for migration to **ghc-7.4**.+	* Minor re-formatting.+## 0.2.0.5+	* Minor clarification of `Factory.Math.Implementations.Primality.witnessesCompositeness`.+	* Added details to any failure to parse the command-line arguments.+	* Defined package's name using program's name, in **Main.hs**.+	* Added `Factory.Math.Primes.mersenneNumbers`.+	* Replaced use of `mod` on positive integers, with the faster `rem`, in `Factory.Math.Implementations.Pi.Spigot.Spigot.processColumns`, `Factory.Math.Implementations.Primality.witnessesCompositeness`, `Factory.Math.Implementations.Primes.TrialDivision.isIndivisibleBy`, `Factory.Math.Implementations.Primes.SieveOfAtkin.polynomialTypeLookup`, `Factory.Math.Implementations.Primes.SieveOfAtkin.findPolynomialSolutions`, `Factory.Math.Implementations.Primes.TurnersSieve.turnersSieve`, `Factory.Math.PerfectPower.maybeSquareNumber`.+	* Replaced calls to `realToFrac` with `toRational` in; **Factory.Math.Implementations.SquareRoot**, `Factory.Math.Statistics.getDispersionFromMean`, `Factory.Math.SquareRoot.getDiscrepancy`, `Factory.Math.SquareRoot.getAccuracy`, to more clearly represent the required operation.+## 0.2.1.0+	* Refactored **Factory.Test.QuickCheck.QuickChecks**.+	* Remove redundant import of `Data.Ratio` from many modules.+	* Refactored `Factory.Math.Radix.encodes` to make use of `Data.List.genericLength`, & removed empty `where`.+	* Explicitly closed standard-input in the executable.+	* Replaced calls to `error` from inside the IO-monad, with `Control.Monad.fail`.+	* Added function `Factory.Math.Precision.roundTo`.+	* Trapped command-line arguments to which garbage has been appended.+	* Corrected the output of `Main.main.optDescrList.printVersion`.+	* Removed the integral population-size parameter from `Factory.Math.Probability.generateContinuousPopulation` & `Factory.Math.Probability.generateDiscretePopulation`, making the result conceptually infinite.+	* Created class `Factory.Math.Probability.Distribution`, to which data-types `Factory.Math.Probability.ContinuousDistribution` & `Factory.Math.Probability.DiscreteDistribution` conform.+	* Added data-constructors `Factory.Math.Probability.ExponentialDistribution`, `Factory.Math.Probability.ShiftedGeometricDistribution` & `Factory.Math.Probability.LogNormal`.+	* Added command-line option **--plotDiscreteDistribution** to **Main**.+	* Removed Preprocessor-check on the version of package **toolshed**, in **Factory/Math/Summation** & **Factory/Data/PrimeFactors**.+## 0.2.1.1+	* Added `Factory.Test.QuickCheck.Probability.prop_logNormalDistributionEqual`.+	* Removed /INLINE/ pragma from `Factory.Math.Implementations.Primes.TrialDivision.isIndivisibleBy`, since to be effective it must be called with fully applied parameters (which it isn't).+	* Un eta-reduced `Factory.Math.Power.square`, since we want it to be inlined when called with one argument.+	* Tested with **haskell-platform-2013.2.0.0**.+	* Replaced preprocessor-directives with **build-depends** constraints in the *.cabal*-file.+	* Added function `Factory.Math.Statistics.getWeightedMean` & corresponding tests in module **Factory.Test.QuickCheck.Statistics**.+	* Since `(<$>)` is exported from the Prelude from **base-4.8**, imported **Prelude** hiding `(<*>)` into module **Factory.Data.Monomial**, since this symbol is defined locally for other purposes.+	* Either replaced instances of `(<$>)` with `fmap` to avoid ambiguity between **Control.Applicative** & **Prelude** which (from **base-4.8**) also exports this symbol, or hid the symbol when importing the **Prelude**..+## 0.2.1.2+	* Hid `(<$>)` when importing the **Prelude** into module **src/Factory/Test/QuickCheck/Pi**.+	* Added the compiler to the output returned for the command-line option **version**.+	* Changed flag **threaded** in the *.cabal*-file to **manual**.+	* Added **Default-language**-specification to the *.cabal*-file.+	* Added file **README.markdown**.+	* Converted this file to markdown-format.+	* Replaced `System.Exit.exitWith (System.Exit.ExitFailure 1)` with `System.Exit.exitFailure` & `System.Exit.exitWith System.Exit.ExitSuccess` with `System.Exit.exitSuccess`.+	* Moved the entry-point to the test-suite from **Main.hs** to **Test.hs**, both to integrate with **cabal** & to minimise the dependencies of the executable.+	* Partitioned the source-files into **src-lib**, **src-exe**, & **src-test** directories, & referenced them individually from the *.cabal*-file to avoid repeated compilation.+	* Used **CPP** to control the import of symbols from **Control.Applicative**.
@@ -5,7 +5,7 @@ 	Copyright (C) 2011-2013 Dr. Alistair Ward. All Rights Reserved.  Home-page:-	http://functionalley.eu+	http://functionalley.eu/Factory/factory.html  License: 	GNU GENERAL PUBLIC LICENSE Version 3; see '/usr/share/common-licenses/GPL-3' or '/usr/share/doc/licenses/gpl-3.0.txt' where available, or the local packaged file 'LICENSE'.
factory.cabal view
@@ -1,34 +1,56 @@--- Package-properties-Name:			factory-Version:		0.2.1.1-Cabal-Version:		>= 1.6-Copyright:		(C) 2011-2013 Dr. Alistair Ward-License:		GPL-License-file:		LICENSE-Author:			Dr. Alistair Ward-Stability:		Unstable interface, incomplete features.-Synopsis:		Rational arithmetic in an irrational world.-Build-Type:		Simple-Description:		A library of number-theory functions, for; factorials, square-roots, Pi and primes.-Category:		Math, Number Theory-Tested-With:		GHC == 7.4, GHC == 7.6, GHC == 7.10-Homepage:		http://functionalley.eu-Maintainer:		factory <at> functionalley <dot> eu-Bug-reports:		factory <at> functionalley <dot> eu-Extra-Source-Files:	changelog, copyright, makefile+-- This file is part of Factory.+--+-- Factory 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.+--+-- Factory 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 Factory.  If not, see <http://www.gnu.org/licenses/>. --- Turn on using: 'runhaskell ./Setup.hs configure -f llvm'.+Name:		factory+Version:	0.2.1.2+Cabal-version:	>= 1.10+Copyright:	(C) 2011-2015 Dr. Alistair Ward+License:	GPL+License-file:	LICENSE+Author:		Dr. Alistair Ward+Stability:	stable+Synopsis:	Rational arithmetic in an irrational world.+Build-type:	Simple+Description:	A library of number-theory functions, for; factorials, square-roots, Pi and primes.+Category:	Math, Number Theory+Tested-with:	GHC == 7.4, GHC == 7.6, GHC == 7.8, GHC == 7.10+Homepage:	http://functionalley.eu/Factory/factory.html+Maintainer:	mailto <colon> factory <at> functionalley <dot> eu+Bug-reports:	mailto <colon> factory <at> functionalley <dot> eu++-- None of these files are needed at run-time.+Extra-source-files:+    changelog.markdown+    copyright+    README.markdown++-- Enable using: 'cabal configure -f llvm'. flag llvm     Description:	Whether the 'llvm' compiler-backend has been installed and is required for code-generation.-    manual:		True-    default:		False+    Manual:		True+    Default:		False  flag threaded     Description:	Enable parallelized code.-    default:		True+    Manual:		True+    Default:		True  Library-    hs-source-dirs:	src+    Default-language:	Haskell2010+    GHC-options:	-Wall -O2 -fno-warn-tabs+    Hs-source-dirs:	src-lib      Exposed-modules:         Factory.Data.Exponential@@ -97,9 +119,7 @@         parallel >= 3.0,         primes >= 0.1,         random,-        toolshed >= 0.13--    GHC-options:	-Wall -O2 -fno-warn-tabs+        toolshed >= 0.16      if impl(ghc >= 7.4.1)         GHC-prof-options:	-prof -fprof-auto -fprof-cafs@@ -110,10 +130,13 @@         GHC-options:	-fllvm  Executable factory-    hs-source-dirs:	src--    Main-Is:		Main.hs+    Default-language:	Haskell2010+    GHC-options:	-Wall -O2 -fno-warn-tabs+    Hs-source-dirs:	src-exe+    Main-is:		Main.hs+    GHC-prof-options:	-prof -auto-all -caf-all +-- Unexposed modules must be referenced for 'cabal sdist'.     Other-modules:         Factory.Test.CommandOptions         Factory.Test.Performance.Factorial@@ -124,6 +147,35 @@         Factory.Test.Performance.Primes         Factory.Test.Performance.SquareRoot         Factory.Test.Performance.Statistics++    Build-depends:+        array,+        base >= 4.3 && < 5,+        Cabal >= 1.10,+        containers,+        deepseq >= 1.1,+        factory,+        random,+        toolshed >= 0.16++    if flag(threaded)+        GHC-options:	-threaded++    if impl(ghc >= 7.0)+        GHC-options:	-rtsopts++        if flag(llvm)+            GHC-options:	-fllvm++Test-Suite quickCheck+    Default-language:	Haskell2010+    GHC-options:	-Wall -fno-warn-tabs+    Hs-source-dirs:	src-test+    Main-is:		Main.hs+    Type:		exitcode-stdio-1.0++-- Required for 'cabal sdist'.+    Other-modules:         Factory.Test.QuickCheck.ArithmeticGeometricMean         Factory.Test.QuickCheck.Factorial         Factory.Test.QuickCheck.Hyperoperation@@ -137,25 +189,18 @@         Factory.Test.QuickCheck.PrimeFactorisation         Factory.Test.QuickCheck.Primes         Factory.Test.QuickCheck.Probability-        Factory.Test.QuickCheck.QuickChecks         Factory.Test.QuickCheck.Radix         Factory.Test.QuickCheck.SquareRoot         Factory.Test.QuickCheck.Statistics         Factory.Test.QuickCheck.Summation      Build-depends:-        Cabal >= 1.6 && < 2,-        QuickCheck >= 2.2--    GHC-options:	-Wall -O2 -fno-warn-tabs-    GHC-prof-options:	-prof -auto-all -caf-all--    if flag(threaded)-        GHC-options:	-threaded--    if impl(ghc >= 7.0)-        GHC-options:	-rtsopts--        if flag(llvm)-            GHC-options:	-fllvm-+        array,+        base >= 4.3 && < 5,+        containers,+        deepseq >= 1.1,+        factory,+        primes >= 0.1,+        QuickCheck >= 2.2,+        random,+        toolshed >= 0.16
− makefile
@@ -1,57 +0,0 @@-# Copyright (C) 2011-2104 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/>.--.PHONY: all build check clean configure copy haddock help hlint install prof sdist--all: install--install: build haddock-	@[ -z "$$CABAL_INSTALL_OPTIONS" ] || echo "INFO: CABAL_INSTALL_OPTIONS='$$CABAL_INSTALL_OPTIONS'"-	runhaskell Setup $@ $$CABAL_INSTALL_OPTIONS--prof:-	CABAL_CONFIGURE_OPTIONS="--enable-library-profiling --enable-executable-profiling $$CABAL_CONFIGURE_OPTIONS" make install--copy: build-	@[ -z "$$CABAL_COPY_OPTIONS" ] || echo "INFO: CABAL_COPY_OPTIONS='$$CABAL_COPY_OPTIONS'"-	runhaskell Setup $@ $$CABAL_COPY_OPTIONS--build: configure-	@[ -z "$$CABAL_BUILD_OPTIONS" ] || echo "INFO: CABAL_BUILD_OPTIONS='$$CABAL_BUILD_OPTIONS'"-	runhaskell Setup $@ $$CABAL_BUILD_OPTIONS--configure: factory.cabal Setup.hs-	@[ -z "$$CABAL_CONFIGURE_OPTIONS" ] || echo "INFO: CABAL_CONFIGURE_OPTIONS='$$CABAL_CONFIGURE_OPTIONS'"-	runhaskell Setup $@ $$CABAL_CONFIGURE_OPTIONS	#--user--haddock: configure-	PATH=~/.cabal/bin:$$PATH runhaskell Setup $@ --hyperlink-source	#Amend path to find 'HsColour', as required for 'hyperlink-source'.--hlint:-	@$@ -i 'Use &&' -i 'Reduce duplication' -i 'Redundant bracket' src/ +RTS -N--sdist:-	TAR_OPTIONS='--format=ustar' runhaskell Setup $@--check: sdist-	cabal upload --check --verbose=3 dist/*.tar.gz;--clean:-	runhaskell Setup $@-	find src -type f \( -name '*.hc' -o -name '*.hcr' -o -name '*.hi' -o -name '*.o' \) -delete--help:-	@grep '^[a-zA-Z].*:' makefile | sed -e 's/:.*//'-
+ src-exe/Factory/Test/CommandOptions.hs view
@@ -0,0 +1,48 @@+{-+	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 the available set of command-line options; of which there's currently only one.+-}++module Factory.Test.CommandOptions(+-- * Types+-- ** Data-types+	CommandOptions(..),+-- * Functions+-- ** Mutators+	setVerbose+) where++import qualified	ToolShed.Defaultable++-- | Declare a record used to contain command-line options.+data CommandOptions	= MkCommandOptions {+	verbose	:: Bool	-- ^ Whether additional informative output should be generated, where applicable.+}++instance ToolShed.Defaultable.Defaultable CommandOptions	where+	defaultValue	= MkCommandOptions { verbose = False }++-- | Mutator.+setVerbose :: CommandOptions -> CommandOptions+setVerbose commandOptions = commandOptions {+	verbose	= True+}++
+ src-exe/Factory/Test/Performance/Factorial.hs view
@@ -0,0 +1,73 @@+{-+	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@]	Times the methods exported from module "Math.Factorial".+-}++module Factory.Test.Performance.Factorial(+-- * Functions+	factorialPerformance,+	factorialPerformanceControl,+	factorialPerformanceGraph,+	factorialPerformanceGraphControl+) where++import qualified	Control.DeepSeq+import qualified	Data.List+import qualified	Factory.Math.Factorial	as Math.Factorial+import qualified	ToolShed.System.TimePure++-- | Measures the CPU-time required by 'Math.Factorial.factorial'.+factorialPerformance :: (+	Control.DeepSeq.NFData		i,+	Integral			i,+	Math.Factorial.Algorithmic	algorithm,+	Show				i+ ) => algorithm -> i -> IO (Double, i)+factorialPerformance algorithm	= ToolShed.System.TimePure.getCPUSeconds . Math.Factorial.factorial algorithm++-- | Measures the CPU-time required by a naive implementation.+factorialPerformanceControl :: (Control.DeepSeq.NFData i, Integral i) => i -> IO (Double, i)+-- factorialPerformanceControl i	= ToolShed.System.TimePure.getCPUSeconds $ product [1 .. i]	-- CAVEAT: too lazy.+factorialPerformanceControl i	= ToolShed.System.TimePure.getCPUSeconds $ Data.List.foldl' (*) 1 [2 .. i]++{- |+	* Measure the CPU-time required by 'Math.Factorial.factorial', against an exponentially increasing operand.++	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.+-}+factorialPerformanceGraph :: Math.Factorial.Algorithmic algorithm => Bool -> algorithm -> IO ()+factorialPerformanceGraph verbose algorithm	= mapM_ (+	\operand	-> factorialPerformance algorithm operand >>= putStrLn . shows operand . showChar '\t' . (+		if verbose+			then (`shows` "")+			else (`shows` "") . fst+	)+ ) $ iterate (* 2) (1 :: Integer)++-- | Graphs the CPU-time required by a naive implementation, against an exponentially increasing operand.+factorialPerformanceGraphControl :: Bool -> IO ()+factorialPerformanceGraphControl verbose	= mapM_ (+	\operand	-> factorialPerformanceControl operand >>= putStrLn . shows operand . showChar '\t' . (+		if verbose+			then (`shows` "")+			else (`shows` "") . fst+	)+ ) $ iterate (* 2) (1 :: Integer)+
+ src-exe/Factory/Test/Performance/Hyperoperation.hs view
@@ -0,0 +1,71 @@+{-+	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@]	Times functions exported from module "Math.Hyperoperation".+-}++module Factory.Test.Performance.Hyperoperation(+-- * Functions+	hyperoperationPerformance,+	hyperoperationPerformanceGraphRank,+	hyperoperationPerformanceGraphExponent+) where++import qualified	Factory.Math.Hyperoperation	as Math.Hyperoperation+import qualified	ToolShed.System.TimePure++-- | Measures the CPU-time required by 'Math.Hyperoperation.hyperoperation'.+hyperoperationPerformance :: (Integral rank, Show rank) => rank -> Math.Hyperoperation.Base -> Math.Hyperoperation.HyperExponent -> IO (Double, Integer)+hyperoperationPerformance rank base	= ToolShed.System.TimePure.getCPUSeconds . Math.Hyperoperation.hyperoperation rank base++{- |+	* Measure the CPU-time required by 'Math.Hyperoperation.hyperoperation', against a linearly increasing /rank/.++	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.+-}+hyperoperationPerformanceGraphRank+	:: Bool	-- ^ Verbose.+	-> Math.Hyperoperation.Base+	-> Math.Hyperoperation.HyperExponent+	-> IO ()+hyperoperationPerformanceGraphRank verbose base hyperExponent	= mapM_ (+	\rank	-> hyperoperationPerformance rank base hyperExponent >>= putStrLn . shows rank . showChar '\t' . (+		if verbose+			then (`shows` "")+			else (`shows` "") . fst+	)+ ) [0 :: Int ..]++{- |+	* Measure the CPU-time required by 'Math.Hyperoperation.hyperoperation', against a linearly increasing /hyper-exponent/.++	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.+-}+hyperoperationPerformanceGraphExponent :: (Integral rank, Show rank)+	=> Bool	-- ^ Verbose.+	-> rank+	-> Math.Hyperoperation.Base+	-> IO ()+hyperoperationPerformanceGraphExponent verbose rank base	= mapM_ (+	\hyperExponent	-> hyperoperationPerformance rank base hyperExponent >>= putStrLn . shows hyperExponent . showChar '\t' . (+		if verbose+			then (`shows` "")+			else (`shows` "") . fst+	)+ ) [0 ..]
+ src-exe/Factory/Test/Performance/Pi.hs view
@@ -0,0 +1,81 @@+{-+	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@]	Times the methods exported from module "Math.Pi".+-}++module Factory.Test.Performance.Pi(+-- * Types+-- ** Type-synonyms+	Category,+-- * Functions+	piPerformance,+	piPerformanceGraph+) where++import qualified	Factory.Math.Factorial					as Math.Factorial+import qualified	Factory.Math.Implementations.Pi.AGM.Algorithm		as Math.Implementations.Pi.AGM.Algorithm+import qualified	Factory.Math.Implementations.Pi.BBP.Algorithm		as Math.Implementations.Pi.BBP.Algorithm+import qualified	Factory.Math.Implementations.Pi.Borwein.Algorithm	as Math.Implementations.Pi.Borwein.Algorithm+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Algorithm	as Math.Implementations.Pi.Ramanujan.Algorithm+import qualified	Factory.Math.Implementations.Pi.Spigot.Algorithm	as Math.Implementations.Pi.Spigot.Algorithm+import qualified	Factory.Math.Pi						as Math.Pi+import qualified	Factory.Math.Precision					as Math.Precision+import qualified	Factory.Math.SquareRoot					as Math.SquareRoot+import qualified	ToolShed.System.TimePure++-- | The type of a /Pi/-algorithm, including where required, the algorithm for /square-root/s and /factorial/s.+type Category squareRootAlgorithm factorialAlgorithm = Math.Pi.Category (+	Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm+ ) Math.Implementations.Pi.BBP.Algorithm.Algorithm (+	Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm+ ) (+	Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm+ ) Math.Implementations.Pi.Spigot.Algorithm.Algorithm++-- | Measures the CPU-time required to find Pi to the required precision.+piPerformance :: (+	Math.SquareRoot.Algorithmic	squareRootAlgorithm,+	Math.Factorial.Algorithmic	factorialAlgorithm+ ) => Category squareRootAlgorithm factorialAlgorithm -> Math.Precision.DecimalDigits -> IO (Double, String)+piPerformance category = ToolShed.System.TimePure.getCPUSeconds . Math.Pi.openS category++{- |+	* Measures the CPU-time required to determine /Pi/ to an exponentially increasing precision-requirement.++	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.+-}+piPerformanceGraph :: (+	Math.SquareRoot.Algorithmic	squareRootAlgorithm,+	Show				squareRootAlgorithm,+	Math.Factorial.Algorithmic	factorialAlgorithm,+	Show				factorialAlgorithm+ ) => RealFrac i+	=> Category squareRootAlgorithm factorialAlgorithm	-- ^ The algorithm.+	-> i							-- ^ The factor by which the precision is increased on each iteration.+	-> Math.Precision.DecimalDigits				-- ^ The maximum precision required.+	-> Bool							-- ^ Whether to return the digits of /Pi/.+	-> IO ()+piPerformanceGraph category factor maxDecimalDigits verbose	= mapM_ (+	\decimalDigits	-> piPerformance category decimalDigits >>= putStrLn . shows decimalDigits . showChar '\t' . (+		if verbose+			then (`shows` "")+			else (`shows` "") . fst+	)+ ) . takeWhile (<= maxDecimalDigits) . map round $ iterate (* factor) 1
+ src-exe/Factory/Test/Performance/Primality.hs view
@@ -0,0 +1,54 @@+{-+	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@]	Times functions exported from module "Math.Primality".+-}++module Factory.Test.Performance.Primality(+-- * Functions+	carmichaelNumbersPerformance,+	isPrimePerformance,+	isPrimePerformanceGraph+) where++import qualified	Control.DeepSeq+import qualified	Factory.Math.Fibonacci	as Math.Fibonacci+import qualified	Factory.Math.Primality	as Math.Primality+import qualified	ToolShed.System.TimePure++-- | Measures the CPU-time required to find the specified number of /Carmichael/-numbers, which is returned together with the requested list.+carmichaelNumbersPerformance :: Math.Primality.Algorithmic primalityAlgorithm => primalityAlgorithm -> Int -> IO (Double, [Integer])+carmichaelNumbersPerformance primalityAlgorithm i+	| i < 0		= fail $ "Factory.Test.Performance.Primality.carmichaelNumbersPerformance:\tnegative number; " ++ show i+	| otherwise	= ToolShed.System.TimePure.getCPUSeconds . take i $ Math.Primality.carmichaelNumbers primalityAlgorithm++-- | Measures the CPU-time required to determine whether the specified integer is prime, which is returned together with the Boolean result.+isPrimePerformance :: (Control.DeepSeq.NFData i, Integral i, Show i) => Math.Primality.Algorithmic primalityAlgorithm => primalityAlgorithm -> i -> IO (Double, Bool)+isPrimePerformance primalityAlgorithm	= ToolShed.System.TimePure.getCPUSeconds . Math.Primality.isPrime primalityAlgorithm++{- |+	* Measures the CPU-time required to determine whether /prime-indexed Fibonacci-numbers/ are actually /prime/.++	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.+-}+isPrimePerformanceGraph :: Math.Primality.Algorithmic primalityAlgorithm => primalityAlgorithm -> IO ()+isPrimePerformanceGraph primalityAlgorithm	= mapM_ (+	\operand	-> isPrimePerformance primalityAlgorithm operand >>= putStrLn . shows operand . showChar '\t' . (`shows` "")+ ) (Math.Fibonacci.primeIndexedFibonacci :: [Integer])+
+ src-exe/Factory/Test/Performance/PrimeFactorisation.hs view
@@ -0,0 +1,50 @@+{-+	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@]	Times the methods exported by module "Math.PrimeFactorisation".+-}++module Factory.Test.Performance.PrimeFactorisation(+-- * Functions+	primeFactorsPerformance,+	primeFactorsPerformanceGraph+) where++import qualified	Factory.Data.PrimeFactors	as Data.PrimeFactors+import qualified	Factory.Math.Fibonacci		as Math.Fibonacci+import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation+import qualified	ToolShed.System.TimePure++-- | Measures the CPU-time required to prime-factorise the specified integer, which is returned together with the resulting list of factors.+primeFactorsPerformance :: Math.PrimeFactorisation.Algorithmic algorithm => algorithm -> Integer -> IO (Double, Data.PrimeFactors.Factors Integer Int)+primeFactorsPerformance algorithm	= ToolShed.System.TimePure.getCPUSeconds . Math.PrimeFactorisation.primeFactors algorithm++{- |+	* Measure the CPU-time required by 'Math.PrimeFactorisation.primeFactors',+	arbitrarily against the /Fibonacci/-numbers (which seemed to fit the requirements).++	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.+-}+primeFactorsPerformanceGraph :: Math.PrimeFactorisation.Algorithmic algorithm => algorithm -> Int -> IO ()+primeFactorsPerformanceGraph algorithm tests+	| tests < 0	= fail $ "Factory.Test.Performance.PrimeFactorisation.primeFactorsPerformanceGraph:\tnegative number; " ++ show tests+	| otherwise	= mapM_ (+		\operand	-> primeFactorsPerformance algorithm operand >>= putStrLn . shows operand . showChar '\t' . (`shows` "")+	) . take tests . dropWhile (< 2) $ Math.Fibonacci.fibonacci+
+ src-exe/Factory/Test/Performance/Primes.hs view
@@ -0,0 +1,47 @@+{-+	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@]	Measures the CPU-time required by "Math.Primes.primes".+-}++module Factory.Test.Performance.Primes(+-- * Functions+	primesPerformance,+	mersenneNumbersPerformance+) where++import qualified	Control.DeepSeq+import qualified	Data.Array.IArray+import qualified	Factory.Math.Primes	as Math.Primes+import qualified	ToolShed.System.TimePure++-- | Measures the CPU-time required by 'Math.Primes.primes', to find the specified prime.+primesPerformance :: (+	Control.DeepSeq.NFData	i,+	Data.Array.IArray.Ix	i,+	Math.Primes.Algorithmic	algorithm,+	Integral		i+ ) => algorithm -> Int -> IO (Double, i)+primesPerformance algorithm	= ToolShed.System.TimePure.getCPUSeconds . (Math.Primes.primes algorithm !!)++-- | Measures the CPU-time required to find the specified number of /Mersenne/-numbers, which is returned together with the requested list.+mersenneNumbersPerformance :: Math.Primes.Algorithmic algorithm => algorithm -> Int -> IO (Double, [Integer])+mersenneNumbersPerformance primalityAlgorithm i+	| i < 0		= fail $ "Factory.Test.Performance.Primes.mersenneNumbersPerformance:\tnegative number; " ++ show i+	| otherwise	= ToolShed.System.TimePure.getCPUSeconds . take i $ Math.Primes.mersenneNumbers primalityAlgorithm
+ src-exe/Factory/Test/Performance/SquareRoot.hs view
@@ -0,0 +1,59 @@+{-+	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@]	Measures the CPU-time required by the methods exported from module "Math.SquareRoot".+-}++module Factory.Test.Performance.SquareRoot(+-- * Functions+	squareRootPerformance,+	squareRootPerformanceGraph+) where++import qualified	Control.Arrow+import qualified	Factory.Math.Precision	as Math.Precision+import qualified	Factory.Math.SquareRoot	as Math.SquareRoot+import qualified	ToolShed.System.TimePure++-- | Measures the CPU-time required by 'Math.SquareRoot.squareRootFrom', which is returned together with the approximate rational result.+squareRootPerformance :: (+	Math.SquareRoot.Algorithmic	algorithm,+	Real				operand,+	Show				operand+ ) => algorithm -> operand -> Math.Precision.DecimalDigits -> IO (Double, Math.SquareRoot.Result)+squareRootPerformance algorithm operand requiredDecimalDigits = ToolShed.System.TimePure.getCPUSeconds $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand++{- |+	* Measures the CPU-time required by 'Math.SquareRoot.squareRootFrom', and the resulting accuracy,+	using the specified algorithm, to an exponentially increasing precision-requirement.++	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.+-}+squareRootPerformanceGraph :: (+	Math.SquareRoot.Algorithmic	algorithm,+	Math.SquareRoot.Iterator	algorithm,+	Real				operand,+	Show				algorithm,+	Show				operand+ ) => algorithm -> operand -> IO ()+squareRootPerformanceGraph algorithm operand	= mapM_ (+	\requiredDecimalDigits	-> putStrLn . (+		\(cpuSeconds, actualDecimalDigits)	-> shows algorithm . showChar '\t' . shows requiredDecimalDigits . showChar '\t' . shows actualDecimalDigits . showChar '\t' $ shows cpuSeconds ""+	) . Control.Arrow.second (Math.SquareRoot.getAccuracy operand) =<< squareRootPerformance algorithm operand requiredDecimalDigits+ ) $ iterate (* max 2 (Math.SquareRoot.convergenceOrder algorithm)) 16
+ src-exe/Factory/Test/Performance/Statistics.hs view
@@ -0,0 +1,45 @@+{-+	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@]	Times the functions exported from module "Math.Statistics".+-}++module Factory.Test.Performance.Statistics(+-- * Functions+	nCrPerformance+) where++import qualified	Control.DeepSeq+import qualified	Factory.Math.Factorial	as Math.Factorial+import qualified	Factory.Math.Statistics	as Math.Statistics+import qualified	ToolShed.System.TimePure++-- | Measures the CPU-time required by 'Math.Statistics.nCr'.+nCrPerformance :: (+	Control.DeepSeq.NFData		i,+	Integral			i,+	Math.Factorial.Algorithmic	factorialAlgorithm,+	Show				i+ )+	=> factorialAlgorithm+	-> i	-- ^ The total number from which to select.+	-> i	-- ^ The number of items in a sample.+	-> IO (Double, i)+nCrPerformance factorialAlgorithm n r	= ToolShed.System.TimePure.getCPUSeconds $ Math.Statistics.nCr factorialAlgorithm n r+
+ src-exe/Main.hs view
@@ -0,0 +1,241 @@+{-+	Copyright (C) 2011-2013 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@]++	* Contains the entry-point to the program.++	* Facilitates testing.+-}++module Main(main) where++import qualified	Data.Map+import qualified	Data.List+import qualified	Data.Version+import qualified	Distribution.Package+import qualified	Distribution.Text+import qualified	Distribution.Version+import qualified	Factory.Math.Hyperoperation			as Math.Hyperoperation+import qualified	Factory.Math.Implementations.Factorial		as Math.Implementations.Factorial+import qualified	Factory.Math.Implementations.Primality		as Math.Implementations.Primality+import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation+import qualified	Factory.Math.Implementations.Primes.Algorithm	as Math.Implementations.Primes.Algorithm+import qualified	Factory.Math.Implementations.SquareRoot		as Math.Implementations.SquareRoot+import qualified	Factory.Math.Probability			as Math.Probability+import qualified	Factory.Test.CommandOptions			as Test.CommandOptions+import qualified	Factory.Test.Performance.Factorial		as Test.Performance.Factorial+import qualified	Factory.Test.Performance.Hyperoperation		as Test.Performance.Hyperoperation+import qualified	Factory.Test.Performance.Pi			as Test.Performance.Pi+import qualified	Factory.Test.Performance.Primality		as Test.Performance.Primality+import qualified	Factory.Test.Performance.PrimeFactorisation	as Test.Performance.PrimeFactorisation+import qualified	Factory.Test.Performance.Primes			as Test.Performance.Primes+import qualified	Factory.Test.Performance.SquareRoot		as Test.Performance.SquareRoot+import qualified	Factory.Test.Performance.Statistics		as Test.Performance.Statistics+import qualified	Paths_factory					as Paths	-- Either local stub, or package-instance autogenerated by 'Setup.hs build'.+import qualified	System.Console.GetOpt				as G+import qualified	System.Environment+import qualified	System.Exit+import qualified	System.Info+import qualified	System.IO+import qualified	System.IO.Error+import qualified	System.Random+import qualified	ToolShed.Defaultable++-- Local convenience definitions.+type PrimalityAlgorithm		= Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm+type PiCategory			= Test.Performance.Pi.Category Math.Implementations.SquareRoot.Algorithm Math.Implementations.Factorial.Algorithm++-- | Used to thread user-defined command-line options, though the list of functions which implement them.+type CommandLineAction	= Test.CommandOptions.CommandOptions -> IO Test.CommandOptions.CommandOptions	-- Supplied as the type-argument to 'G.OptDescr'.++-- | On failure to parse the specified string, returns an explanatory error.+read' :: Read a => String -> String -> a+read' errorMessage s	= case reads s of+	[(x, "")]	-> x+	_		-> error $ errorMessage ++ show s++-- | On failure to parse a command-line argument, returns an explanatory error.+readCommandArg :: Read a => String -> a+readCommandArg	= read' "Failed to parse command-line argument "++-- | Parses the command-line arguments, to determine 'Test.CommandOptions.CommandOptions'.+main :: IO ()+main	= do+	System.IO.hClose System.IO.stdin	-- Nothing is read from standard input.++	progName	<- System.Environment.getProgName++	let+		usageMessage :: String+		usageMessage	= "Usage:\t" ++ G.usageInfo progName optDescrList++		optDescrList :: [G.OptDescr CommandLineAction]+		optDescrList	= [+--				 String	[String]					(G.ArgDescr CommandLineAction)												String+			G.Option "?"	["help"]					(G.NoArg $ const printUsage)												"Display this help-text & then exit.",+			G.Option ""	["verbose"]					(G.NoArg $ return {-to IO-monad-} . Test.CommandOptions.setVerbose)							("Provide additional information where available; default '" ++ show (Test.CommandOptions.verbose ToolShed.Defaultable.defaultValue) ++ "'."),+			G.Option ""	["version"]					(G.NoArg $ const printVersion)												"Print version-information & then exit.",+			G.Option ""	["carmichaelNumbersPerformance"]		(carmichaelNumbersPerformance `G.ReqArg` "(Math.Implementations.Primality.Algorithm, Int)")				"Test the performance of 'Math.Primality.carmichaelNumbers'.",+			G.Option ""	["factorialPerformance"]			(factorialPerformance `G.ReqArg` "(Math.Implementations.Factorial.Algorithm, Integer)")					"Test the performance of 'Math.Factorial.factorial'.",+			G.Option ""	["factorialPerformanceGraph"]			(factorialPerformanceGraph `G.ReqArg` "Math.Implementations.Factorial.Algorithm")					"Test the performance of 'Math.Factorial.factorial', with an exponentially increasing operand.",+			G.Option ""	["factorialPerformanceGraphControl"]		(G.NoArg factorialPerformanceGraphControl)										"Test the performance of a naive factorial-implementation, with an exponentially increasing operand.",+			G.Option ""	["hyperoperationPerformance"]			(hyperoperationPerformance `G.ReqArg` "(Integer, Math.Hyperoperation.Base, Math.Hyperoperation.HyperExponent)")		"Test the performance of 'Math.Hyperoperation.hyperoperation', against the specified rank, base and hyper-exponent.",+			G.Option ""	["hyperoperationPerformanceGraphRank"]		(hyperoperationPerformanceGraphRank `G.ReqArg` "(Math.Hyperoperation.Base, Math.Hyperoperation.HyperExponent)")		"Test the performance of 'Math.Hyperoperation.hyperoperation', for the specified base and hyper-exponent, and a linearly increasing rank.",+			G.Option ""	["hyperoperationPerformanceGraphExponent"]	(hyperoperationPerformanceGraphExponent `G.ReqArg` "(Integer, Math.Hyperoperation.Base)")				"Test the performance of 'Math.Hyperoperation.hyperoperation', for the specified rank and base, and a linearly increasing hyper-exponent.",+			G.Option ""	["isPrimePerformance"]				(isPrimePerformance `G.ReqArg` "(Math.Implementations.Primality.Algorithm, Integer)")					"Test the performance of 'Math.Primality.isPrime'.",+			G.Option ""	["isPrimePerformanceGraph"]			(isPrimePerformanceGraph `G.ReqArg` "Math.Implementations.Primality.Algorithm")						"Test the performance of 'Math.Primality.isPrime', against the prime-indexed Fibonacci-numbers.",+			G.Option ""	["mersenneNumbersPerformance"]			(mersenneNumbersPerformance `G.ReqArg` "(Math.Implementations.Primes.Algorithm.Algorithm, Int)")			"Test the performance of 'Math.Primes.mersenneNumbers'.",+			G.Option ""	["factorialPerformance"]			(factorialPerformance `G.ReqArg` "(Math.Implementations.Factorial.Algorithm, Integer)")					"Test the performance of 'Math.Factorial.factorial'.",+			G.Option ""	["nCrPerformance"]				(nCrPerformance `G.ReqArg` "(Math.Implementations.Factorial.Algorithm, Integer, Integer)")				"Test the performance of 'Math.Factorial.factorial'.",+			G.Option ""	["piPerformance"]				(piPerformance `G.ReqArg` "(Math.Pi.Category, Math.Precision.DecimalDigits)")						"Test the performance of 'Math.Pi.openI'.",+			G.Option ""	["piPerformanceGraph"]				(piPerformanceGraph `G.ReqArg` "(Math.Pi.Category, Double, Math.Precision.DecimalDigits)")				"Test the performance of 'Math.Pi.openI', with an exponential precision-requirement (of the specified exponent), up to the specified limit.",+			G.Option ""	["plotDiscreteDistribution"]			(plotDiscreteDistribution `G.ReqArg` "(Int, Math.Probability.DiscreteDistribution)")					"Plot the Probability Mass function for the specified discrete distribution.",+			G.Option ""	["primeFactorsPerformance"]			(primeFactorsPerformance `G.ReqArg` "(Math.Implementations.PrimeFactorisation.Algorithm, Integer)")			"Test the performance of 'Math.PrimeFactorisation.primeFactors'.",+			G.Option ""	["primeFactorsPerformanceGraph"]		(primeFactorsPerformanceGraph `G.ReqArg` "(Math.Implementations.PrimeFactorisation.Algorithm, Int)")			"Test the performance of 'Math.PrimeFactorisation.primeFactors', on the specified number of odd integers from the Fibonacci-sequence.",+			G.Option ""	["primesPerformance"]				(primesPerformance `G.ReqArg` "(Math.Implementations.Primes.Algorithm.Algorithm, Int)")					"Test the performance of 'Math.Primes.primes'.",+			G.Option ""	["squareRootPerformance"]			(squareRootPerformance `G.ReqArg` "(Math.Implementations.SquareRoot.Algorithm, Rational, DecimalDigits)")	"Test the performance of 'Math.SquareRoot.squareRoot'.",+			G.Option ""	["squareRootPerformanceGraph"]			(squareRootPerformanceGraph `G.ReqArg` "(Math.Implementations.SquareRoot.Algorithm, Rational)")		"Test the performance of 'Math.SquareRoot.squareRoot', with an exponentially increasing precision-requirement."+		 ] where+			printVersion, printUsage :: IO Test.CommandOptions.CommandOptions+			printVersion	= System.IO.hPutStrLn System.IO.stderr (+				Distribution.Text.display packageIdentifier ++ "\n\nCompiled by " ++ show compiler ++ ".\n\nCopyright (C) 2011-2015 " ++ author ++ ".\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it under certain conditions.\n\nWritten by " ++ author ++ "."+			 ) >> System.Exit.exitSuccess	where+				packageIdentifier :: Distribution.Package.PackageIdentifier+				packageIdentifier	= Distribution.Package.PackageIdentifier {+					Distribution.Package.pkgName	= Distribution.Package.PackageName progName,	-- CAVEAT: coincidentally.+					Distribution.Package.pkgVersion	= Distribution.Version.Version (Data.Version.versionBranch Paths.version) []+				}++				author, compiler :: String+				author		= "Dr. Alistair Ward"+				compiler	= System.Info.compilerName ++ "-" ++ Data.List.intercalate "." (map show $ Data.Version.versionBranch System.Info.compilerVersion)++			printUsage	= System.IO.hPutStrLn System.IO.stderr usageMessage	>> System.Exit.exitSuccess++			factorialPerformanceGraphControl :: Test.CommandOptions.CommandOptions -> IO Test.CommandOptions.CommandOptions+			factorialPerformanceGraphControl commandOptions	= Test.Performance.Factorial.factorialPerformanceGraphControl (Test.CommandOptions.verbose commandOptions)	>> System.Exit.exitFailure++			carmichaelNumbersPerformance, factorialPerformance, factorialPerformanceGraph, hyperoperationPerformance, hyperoperationPerformanceGraphRank, hyperoperationPerformanceGraphExponent, isPrimePerformance, isPrimePerformanceGraph, mersenneNumbersPerformance, piPerformance, piPerformanceGraph, plotDiscreteDistribution, primeFactorsPerformance, primesPerformance, squareRootPerformance, squareRootPerformanceGraph :: String -> CommandLineAction++			carmichaelNumbersPerformance arg _	= Test.Performance.Primality.carmichaelNumbersPerformance algorithm i >>= print >> System.Exit.exitSuccess	where+				algorithm :: PrimalityAlgorithm+				(algorithm, i)	= readCommandArg arg++			factorialPerformance arg _	= Test.Performance.Factorial.factorialPerformance algorithm i >>= print >> System.Exit.exitSuccess	where+				algorithm	:: Math.Implementations.Factorial.Algorithm+				i		:: Integer+				(algorithm, i)	= readCommandArg arg++			factorialPerformanceGraph arg commandOptions	= Test.Performance.Factorial.factorialPerformanceGraph (Test.CommandOptions.verbose commandOptions) (readCommandArg arg :: Math.Implementations.Factorial.Algorithm)	>> System.Exit.exitFailure++			hyperoperationPerformance arg _	= Test.Performance.Hyperoperation.hyperoperationPerformance rank base hyperExponent >>= print >> System.Exit.exitSuccess	where+				rank		:: Integer+				base		:: Math.Hyperoperation.Base+				hyperExponent	:: Math.Hyperoperation.HyperExponent+				(rank, base, hyperExponent)	= readCommandArg arg++			hyperoperationPerformanceGraphRank arg commandOptions	= Test.Performance.Hyperoperation.hyperoperationPerformanceGraphRank (Test.CommandOptions.verbose commandOptions) base hyperExponent >> System.Exit.exitFailure	where+				base		:: Math.Hyperoperation.Base+				hyperExponent	:: Math.Hyperoperation.HyperExponent+				(base, hyperExponent)	= readCommandArg arg++			hyperoperationPerformanceGraphExponent arg commandOptions	= Test.Performance.Hyperoperation.hyperoperationPerformanceGraphExponent (Test.CommandOptions.verbose commandOptions) rank base >> System.Exit.exitFailure	where+				rank	:: Integer+				base	:: Math.Hyperoperation.Base+				(rank, base)	= readCommandArg arg++			isPrimePerformance arg _	= Test.Performance.Primality.isPrimePerformance algorithm i >>= print >> System.Exit.exitSuccess	where+				algorithm	:: PrimalityAlgorithm+				i		:: Integer+				(algorithm, i)	= readCommandArg arg++			isPrimePerformanceGraph arg _	= Test.Performance.Primality.isPrimePerformanceGraph (readCommandArg arg :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm) >> System.Exit.exitFailure++			mersenneNumbersPerformance arg _	= Test.Performance.Primes.mersenneNumbersPerformance algorithm i >>= print >> System.Exit.exitSuccess	where+				algorithm :: Math.Implementations.Primes.Algorithm.Algorithm+				(algorithm, i)	= readCommandArg arg++			nCrPerformance arg _	= Test.Performance.Statistics.nCrPerformance algorithm n r >>= print >> System.Exit.exitSuccess	where+				algorithm	:: Math.Implementations.Factorial.Algorithm+				n, r		:: Integer+				(algorithm, n, r)	= readCommandArg arg++			piPerformance arg _	= Test.Performance.Pi.piPerformance category decimalDigits >>= print >> System.Exit.exitSuccess	where+				category :: PiCategory+				(category, decimalDigits)	= readCommandArg arg++			piPerformanceGraph arg commandOptions	= Test.Performance.Pi.piPerformanceGraph category factor maxDecimalDigits (Test.CommandOptions.verbose commandOptions) >> System.Exit.exitFailure	where+				category	:: PiCategory+				factor		:: Double+				(category, factor, maxDecimalDigits)	= readCommandArg arg++			plotDiscreteDistribution arg _	= let+				distribution :: Math.Probability.DiscreteDistribution Double+				(n, distribution)	= readCommandArg arg+			 in do+				System.Random.getStdGen >>= print . Data.Map.toList . Data.Map.map ((/ (fromIntegral n :: Double)) . fromInteger) . Data.Map.fromListWith (+) . (`zip` repeat 1) . (take n :: [Integer] -> [Integer]) . Math.Probability.generateDiscretePopulation distribution++				System.Exit.exitSuccess++			primeFactorsPerformance arg _	= Test.Performance.PrimeFactorisation.primeFactorsPerformance algorithm i >>= print >> System.Exit.exitSuccess	where+				algorithm :: Math.Implementations.PrimeFactorisation.Algorithm+				(algorithm, i)	= readCommandArg arg++			primeFactorsPerformanceGraph arg _	= Test.Performance.PrimeFactorisation.primeFactorsPerformanceGraph algorithm index >> System.Exit.exitFailure	where+				algorithm :: Math.Implementations.PrimeFactorisation.Algorithm+				(algorithm, index)	= readCommandArg arg++			primesPerformance arg _	= (+				(+{-+	Hard-code specific algorithms, so the simplifier triggers rewrite-rules in "Math.Implementations.Primes",+	ready for run-time definitions of 'algorithm' to exploit as appropriate.+	CAVEAT: fragile.+-}+					case algorithm of+						Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize	-> Test.Performance.Primes.primesPerformance $ Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize+						Math.Implementations.Primes.Algorithm.SieveOfAtkin maxPrime		-> Test.Performance.Primes.primesPerformance $ Math.Implementations.Primes.Algorithm.SieveOfAtkin maxPrime+						_									-> Test.Performance.Primes.primesPerformance algorithm+				) index :: IO (+					Double,+--					Integer+					Int	-- Exploits rewrite-rules in "Math.Implementations.Primes.*".+				)+			 ) >>= print >> System.Exit.exitSuccess	where+				algorithm :: Math.Implementations.Primes.Algorithm.Algorithm+				(algorithm, index)	= readCommandArg arg++			squareRootPerformance arg _	= Test.Performance.SquareRoot.squareRootPerformance algorithm operand decimalDigits >>= print >> System.Exit.exitSuccess	where+				algorithm	:: Math.Implementations.SquareRoot.Algorithm+				operand		:: Rational+				(algorithm, operand, decimalDigits)	= readCommandArg arg++			squareRootPerformanceGraph arg _	= Test.Performance.SquareRoot.squareRootPerformanceGraph algorithm operand >> System.Exit.exitFailure	where+				algorithm	:: Math.Implementations.SquareRoot.Algorithm+				operand		:: Rational+				(algorithm, operand)	= readCommandArg arg++	args	<- System.Environment.getArgs++--	G.getOpt :: G.ArgOrder CommandLineAction -> [G.OptDescr Action] -> [String] -> ([Action], [String], [String])+	case G.getOpt G.RequireOrder optDescrList args of+		(commandLineActions, _, [])	-> Data.List.foldl' (>>=) (return {-to IO-monad-} ToolShed.Defaultable.defaultValue) commandLineActions	>> System.Exit.exitSuccess+		(_, _, errors)			-> System.IO.Error.ioError . System.IO.Error.userError $ concat errors ++ usageMessage	-- Throw.+
+ src-lib/Factory/Data/Exponential.hs view
@@ -0,0 +1,89 @@+{-+	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 simple numeric type, designed to contain an /exponential/ number.++	* <http://en.wikipedia.org/wiki/Exponentiation>.+-}++module Factory.Data.Exponential(+-- * Types+-- ** Type-synonyms+	Exponential,+-- * Functions+	evaluate,+	invert,+-- ** Accessors+	getBase,+	getExponent,+-- ** Constructors+	rightIdentity,+-- ** Operators+	(<^),+	(=~)+) where++import qualified	Control.Arrow++infix 4 =~	-- Same as (==).+infixr 8 <^	-- Same as (^).++-- | Describes an /exponential/, in terms of its /base/ and /exponent/.+type Exponential base exponent	= (base, exponent)++-- | Accessor.+{-# INLINE getBase #-}+getBase :: Exponential base exponent -> base+getBase	= fst++-- | Accessor.+{-# INLINE getExponent #-}+getExponent :: Exponential base exponent -> exponent+getExponent	= snd++{- |+	* Construct an 'Exponential' merely raised to the 1st power.++	* The value of the resulting exponential is the same as specified 'base'; <http://en.wikipedia.org/wiki/Identity_element>.+-}+rightIdentity :: Num exponent => base -> Exponential base exponent+rightIdentity x	= (x, 1)++-- | Evaluate the specified 'Exponential', returning the resulting number.+{-# INLINE evaluate #-}+evaluate :: (Num base, Integral exponent) => Exponential base exponent -> base+evaluate	= uncurry (^)	-- CAVEAT: in this eta-reduced form, it'll only be inlined when called without arguments.++-- | True if the /bases/ are equal.+(=~) :: Eq base => Exponential base exponent -> Exponential base exponent -> Bool+(l, _) =~ (r, _)	= l == r++-- | Raise the specified 'Exponential' to a power.+(<^) :: Num exponent+	=> Exponential base exponent	-- ^ The operand.+	-> exponent			-- ^ The power to which the exponential is to be raised.+	-> Exponential base exponent	-- ^ The result.+(b, e) <^ power	= (b, e * power)++-- | Invert the value, by negating the exponent.+invert :: Num exponent => Exponential base exponent -> Exponential base exponent+invert	= Control.Arrow.second negate+
+ src-lib/Factory/Data/Interval.hs view
@@ -0,0 +1,201 @@+{-+	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,+	mkBounded,+-- * Functions+--	divideAndConquer,+	elem',+--	getLength,+	normalise,+	product',+	shift,+	splitAt',+	toList,+-- ** Accessors+	getMinBound,+	getMaxBound,+-- ** Constructors+	precisely,+-- ** Predicates+	isReversed+) where++import			Control.Arrow((***), (&&&))+import qualified	Control.Parallel.Strategies+import qualified	Data.Monoid+import qualified	Data.Ratio+import qualified	Data.Tuple+import qualified	ToolShed.Data.Pair++-- | 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 /unsigned closed unit-interval/; <http://en.wikipedia.org/wiki/Unit_interval>.+closedUnitInterval :: Num n => Interval n+closedUnitInterval	= (0, 1)++-- | Construct an /interval/ from a bounded type.+mkBounded :: Bounded endPoint => Interval endPoint+mkBounded	= (minBound, maxBound)++-- | Construct an /interval/ from a single value.+precisely :: endPoint -> Interval endPoint+precisely	= id &&& id++-- | 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	= ToolShed.Data.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	= uncurry (&&) . ((<= 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	= Data.Tuple.swap b+	| otherwise	= b++-- | Bisect the /interval/ at the specified /end-point/; which should be between the two existing /end-points/.+splitAt' :: (+	Enum	endPoint,+	Num	endPoint,+	Ord	endPoint,+	Show	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), (succ i, r))++{- |+	* The distance between the endpoints,+	which for 'Integral' quantities is the same as the number of items in closed interval; though the latter concept would return type 'Int'.++	* CAVEAT: the implementation accounts for the potential fence-post error, for closed intervals of integers,+	but this results in the opposite error when used with /Fractional/ quantities.+	So, though most of the module merely requires 'Enum', this function is further restricted to 'Integral'.+-}+{-# INLINE getLength #-}+getLength :: Integral endPoint => Interval endPoint -> endPoint+getLength (l, r)	= succ r - l++{- |+	* Converts 'Interval' to a list by enumerating the values.++	* CAVEAT: produces rather odd results for 'Fractional' types, but no stranger than considering such types Enumerable in the first place.+-}+{-# INLINE toList #-}+toList :: Enum endPoint => Interval endPoint -> [endPoint]+toList	= uncurry enumFromTo	-- CAVEAT: in this eta-reduced form, it'll only be inlined when called without arguments.++{- |+	* 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 :: (Data.Monoid.Monoid monoid, Integral i, Show i)+	=> (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 . Control.Parallel.Strategies.withStrategy (+				Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rseq Control.Parallel.Strategies.rseq+			) . ToolShed.Data.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, Show 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-lib/Factory/Data/MonicPolynomial.hs view
@@ -0,0 +1,98 @@+{-+	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 /monic polynomial; <http://en.wikipedia.org/wiki/Monic_polynomial#Classifications>;+	ie. in which the /coefficient/ of the /leading term/ is one.+-}++module Factory.Data.MonicPolynomial(+-- * Types+-- ** Data-types,+	MonicPolynomial(getPolynomial),	-- Hide the data-constructor.+-- * Functions+-- ** Constructors+	mkMonicPolynomial+) where++import qualified	Control.Arrow+import qualified	Factory.Data.Monomial		as Data.Monomial+import			Factory.Data.Polynomial((*=))+import qualified	Factory.Data.Polynomial		as Data.Polynomial+import qualified	Factory.Data.QuotientRing	as Data.QuotientRing+import			Factory.Data.Ring((=*=), (=+=), (=-=))+import qualified	Factory.Data.Ring		as Data.Ring+import qualified	ToolShed.Data.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 {+	getPolynomial	:: Data.Polynomial.Polynomial c e+} deriving (Eq, Show)++-- | Smart constructor. Constructs an arbitrary /monic polynomial/.+mkMonicPolynomial :: (+	Eq	c,+	Num	c,+	Ord	e,+	Show	c,+	Show	e+ ) => Data.Polynomial.Polynomial c e -> MonicPolynomial c e+mkMonicPolynomial polynomial+	| not $ Data.Polynomial.isMonic polynomial	= error $ "Factory.Data.MonicPolynomial.mkMonicPolynomial:\tnot monic; " ++ show polynomial+	| otherwise					= MkMonicPolynomial polynomial++{-+	* This instance-declaration merely delegates to the 'Data.Polynomial.Polynomial' payload.++	* CAVEAT: it's not strictly an instance of this class, since the result of some methods isn't /monic/.+-}+instance (+	Eq	c,+	Num	c,+	Num	e,+	Ord	e,+	Show	c,+	Show	e+ ) => Data.Ring.Ring (MonicPolynomial c e)	where+	MkMonicPolynomial l =*= MkMonicPolynomial r	= MkMonicPolynomial $ l =*= r+	MkMonicPolynomial l =+= MkMonicPolynomial r	= mkMonicPolynomial $ l =+= r	-- CAVEAT: potentially non-monic.+--	additiveInverse (MkMonicPolynomial p)		= MkMonicPolynomial $ Data.Ring.additiveInverse p	-- CAVEAT: not monic !+	additiveInverse _				= error "Factory.Data.MonicPolynomial.additiveInverse:\tresult isn't monic"+	multiplicativeIdentity				= MkMonicPolynomial Data.Ring.multiplicativeIdentity+	additiveIdentity				= MkMonicPolynomial Data.Ring.additiveIdentity	-- CAVEAT: not monic !++-- Since the /leading term/ of the /denominator/ is one, the /coefficient/ isn't required to implement 'Fractional'.+instance (+	Eq	c,+	Num	c,+	Num	e,+	Ord	e,+	Show	c,+	Show	e+ ) => Data.QuotientRing.QuotientRing (MonicPolynomial c e)	where+	MkMonicPolynomial polynomialN `quotRem'` MkMonicPolynomial polynomialD	= ToolShed.Data.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)+			| otherwise									= Control.Arrow.first (Data.Polynomial.lift (quotient :)) $ longDivide (numerator =-= polynomialD *= quotient)+			where+--				quotient :: Num e => Data.Monomial.Monomial c e+				quotient	= Data.Polynomial.getLeadingTerm numerator `Data.Monomial.shiftExponent` negate (Data.Monomial.getExponent $ Data.Polynomial.getLeadingTerm polynomialD)+
+ src-lib/Factory/Data/Monomial.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE CPP #-}+{-+	Copyright (C) 2011-2015 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 <http://en.wikipedia.org/wiki/Monomial> and operations on it.++	* A /monomial/ is merely a /polynomial/ with a single non-zero term; cf. /Binomial/.+-}++module Factory.Data.Monomial(+-- * Types+-- ** Type-synonyms+	Monomial,+-- * Functions+	double,+	mod',+	negateCoefficient,+	realCoefficientToFrac,+	shiftCoefficient,+	shiftExponent,+	square,+-- ** Accessors+	getExponent,+	getCoefficient,+-- ** Operators+	(<=>),+	(</>),+	(<*>),	-- CAVEAT: this clashes with the Prelude from 'base-4.8'.+	(=~),+-- ** Predicates+	isMonomial+) where++import qualified	Control.Arrow++#if MIN_VERSION_base(4,8,0)+import Prelude hiding ((<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.+#endif++infix 4 <=>	-- Same as (==).+infix 4 =~	-- Same as (==).+infixl 7 </>	-- Same as (/).+infixl 7 <*>	-- Same as (*).++{- |+	* The type of an arbitrary monomial.++	* CAVEAT: though a /monomial/ has an integral power, this contraint is only imposed at the function-level.+-}+type Monomial coefficient exponent	= (coefficient, exponent)++-- | Accessor.+{-# INLINE getCoefficient #-}+getCoefficient :: Monomial c e -> c+getCoefficient	= fst++-- | Accessor.+{-# INLINE getExponent #-}+getExponent :: Monomial c e -> e+getExponent	= snd++{- |+	* 'True' if the /exponent/ is both integral and non-/negative/.++	* CAVEAT: one can't even call this function unless the /exponent/ is integral.+-}+isMonomial :: Integral e => Monomial c e -> Bool+isMonomial	= (>= 0) . getExponent++-- | Compares the /exponents/ of the specified 'Monomial's.+{-# INLINE (<=>) #-}+(<=>) :: Ord e => Monomial c e -> Monomial c e -> Ordering+(_, l) <=> (_, r)	= l `compare` r++-- | True if the /exponents/ are equal.+(=~) :: Eq e => Monomial c e -> Monomial c e -> Bool+(_, l) =~ (_, r)	= l == r++-- | Multiply the two specified 'Monomial's.+{-# INLINE (<*>) #-}+(<*>) :: (Num c, Num e) => Monomial c e -> Monomial c e -> Monomial c e+(cL, eL) <*> (cR, eR)	= (cL * cR, eL + eR)++-- | Divide the two specified 'Monomial's.+(</>) :: (Eq c, Fractional c, Num e)+	=> Monomial c e	-- ^ Numerator.+	-> Monomial c e	-- ^ Denominator.+	-> Monomial c e+(cN, eN) </> (1, eD)	= (cN, eN - eD)+(cN, eN) </> (cD, eD)	= (cN / cD, eN - eD)++-- | Square the specified 'Monomial'.+square :: (Num c, Num e) => Monomial c e -> Monomial c e+square (c, e)	= (c ^ (2 :: Int), 2 * e)++-- | Double the specified 'Monomial'.+{-# INLINE double #-}+double :: Num c => Monomial c e -> Monomial c e+double (c, e)	= (2 * c, e)++-- | Shift the /coefficient/, by the specified amount.+{-# INLINE shiftCoefficient #-}+shiftCoefficient :: Num c+	=> Monomial c e+	-> c	-- ^ The magnitude of the shift.+	-> Monomial c e+-- m `shiftCoefficient` i	= Control.Arrow.first (+ i) m	-- CAVEAT: Too slow.+(c, e) `shiftCoefficient` i	= (c + i, e)++-- | Shift the /exponent/, by the specified amount.+{-# INLINE shiftExponent #-}+shiftExponent :: Num e+	=> Monomial c e+	-> e	-- ^ The magnitude of the shift.+	-> Monomial c e+-- m `shiftExponent` i	= Control.Arrow.second (+ i) m	-- CAVEAT: Too slow.+(c, e) `shiftExponent` i	= (c, e + i)++-- | Negate the coefficient.+negateCoefficient :: Num c => Monomial c e -> Monomial c e+negateCoefficient	= Control.Arrow.first negate++-- | Reduce the coefficient using /modular/ arithmetic.+{-# INLINE mod' #-}+mod' :: Integral c+	=> Monomial c e+	-> c	-- ^ Modulus.+	-> Monomial c e+monomial `mod'` modulus	= Control.Arrow.first (`mod` modulus) monomial++-- | Convert the type of the /coefficient/.+realCoefficientToFrac :: (Real r, Fractional f) => Monomial r e -> Monomial f e+realCoefficientToFrac	= Control.Arrow.first realToFrac+
+ src-lib/Factory/Data/Polynomial.hs view
@@ -0,0 +1,379 @@+{-# LANGUAGE CPP #-}+{-+	Copyright (C) 2011-2015 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 <http://en.wikipedia.org/wiki/Univariate> polynomial and operations on it.++	* <http://en.wikipedia.org/wiki/Polynomial>.++	* <http://mathworld.wolfram.com/Polynomial.html>.+-}++module Factory.Data.Polynomial(+-- * Types+-- ** Type-synonyms+--	MonomialList,+-- ** Data-types,+	Polynomial,+-- * Constants+	zero,+	one,+-- * Functions+	evaluate,+	getDegree,+	getLeadingTerm,+	lift,+	mod',+	normalise,+--	pruneCoefficients,+	raiseModulo,+	realCoefficientsToFrac,+	terms,+-- ** Constructors+	mkConstant,+	mkLinear,+	mkPolynomial,+-- ** Operators+	(*=),+-- ** Predicates+	areCongruentModulo,+	inAscendingOrder,+	inDescendingOrder,+--	inOrder,+	isMonic,+	isMonomial,+	isNormalised,+	isPolynomial,+--	isReduced,+	isZero+) where++import			Control.Arrow((&&&))+import qualified	Control.Arrow+import qualified	Data.List+import			Factory.Data.Monomial((<*>), (</>), (<=>), (=~))+import qualified	Factory.Data.Monomial		as Data.Monomial+import qualified	Factory.Data.QuotientRing	as Data.QuotientRing+import			Factory.Data.Ring((=*=), (=+=), (=-=))+import qualified	Factory.Data.Ring		as Data.Ring++#if MIN_VERSION_base(4,8,0)+import Prelude hiding ((<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.+#endif++infixl 7 *=	-- Same as (*).++-- | The guts of a 'Polynomial'.+type MonomialList coefficient exponent	= [Data.Monomial.Monomial coefficient exponent]++{- |+	* The type of an arbitrary /univariate/ polynomial;+	actually it's more general, since it permits negative powers (<http://en.wikipedia.org/wiki/Laurent_polynomial>s).+	It can't describe /multivariate/ polynomials, which would require a list of /exponents/.+	Rather than requiring the /exponent/ to implement the /type-class/ 'Integral', this is implemented at the function-level, as required.++	* The structure permits gaps between /exponents/,+	in which /coefficients/ are inferred to be zero, thus enabling efficient representation of sparse polynomials.++	* CAVEAT: the 'MonomialList' is required to;+	be ordered by /descending/ exponent (ie. reverse <http://en.wikipedia.org/wiki/Monomial_order>);+	have had zero coefficients removed;+	and to have had /like/ terms merged;+	so the raw data-constructor isn't exported.+-}+newtype {- Integral exponent => -} Polynomial coefficient exponent	= MkPolynomial {+	getMonomialList	:: MonomialList coefficient exponent	-- ^ Accessor.+} deriving (Eq, Show)++-- | Makes /Polynomial/ a 'Data.Ring.Ring', over the /field/ composed from all possible /coefficients/; <http://en.wikipedia.org/wiki/Polynomial_ring>.+instance (+	Eq	c,+	Num	c,+	Num	e,+	Ord	e+ ) => Data.Ring.Ring (Polynomial c e) where+	MkPolynomial [] =*= _	= zero+	_ =*= MkPolynomial []	= zero+	polynomialL =*= polynomialR+--		| polynomialL == one			= polynomialR	-- Counterproductive.+--		| polynomialR == one			= polynomialL	-- Counterproductive.+		| terms polynomialL > terms polynomialR	= polynomialL `times` polynomialR+		| otherwise				= polynomialR `times` polynomialL+		where+			l `times` r	= {-# SCC "times" #-} Data.Ring.sum' (recip 2) {-TODO-} 10 {-empirical-} . map (l *=) $ getMonomialList r++	MkPolynomial [] =+= p				= p+	p =+= MkPolynomial []				= p+	MkPolynomial listL =+= MkPolynomial listR	= {-# SCC "merge" #-} MkPolynomial $ merge listL listR	where+		merge [] r			= r+		merge l []			= l+		merge l@(lh : ls) r@(rh : rs)	= case lh <=> rh of+			GT	-> lh : merge ls r+			LT	-> rh : merge l rs+			_	-> case lh `Data.Monomial.shiftCoefficient` Data.Monomial.getCoefficient rh of+				(0, _)		-> merge ls rs+				monomial	-> monomial : merge ls rs++	additiveInverse		= lift (Data.Monomial.negateCoefficient `map`)+	multiplicativeIdentity	= one+	additiveIdentity	= zero++{-+	Override the default implementation,+	in order to take advantage of the symmetry under reflection about the main diagonal,+	in the square matrix of products formed from the multiplication of each term by each term.+	Eg:+		(ax^3 + bx^2 + cx + d)^2 = [+			(a^2x^6 + abx^5 + acx^4 + adx^3) ++			(bax^5 + b^2x^4 + bcx^3 + bdx^2) ++			(cax^4 + cbx^3 + c^2x^2 + cdx) ++			(dax^3 + dbx^2 + dcx + d^2)+		]++		= (a^2x^6 + b^2x^4 + c^2x^2 + d^2) + 2 * [ax^3 * (bx^2 + cx + d) + bx^2 * (cx + d) + cx * (d)]+-}+	square (MkPolynomial [])	= zero+	square p			= Data.Ring.sum' (recip 2) {-TODO-} 10 {-empirical-} $ diagonal : corners	where+		diagonal	= {-# SCC "diagonal" #-} map Data.Monomial.square `lift` p+		corners		= {-# SCC "corners" #-} uncurry (+			zipWith (*=)+		 ) $ map MkPolynomial . init {-remove terminal null-} . Data.List.tails . tail &&& map Data.Monomial.double $ getMonomialList p++-- | Defines the ability to divide /polynomials/.+instance (+	Eq		c,+	Fractional	c,+	Num		e,+	Ord		e+ ) => Data.QuotientRing.QuotientRing (Polynomial c e)	where+{-+	Uses /Euclidian division/.+	<http://en.wikipedia.org/wiki/Polynomial_long_division>.+	<http://demonstrations.wolfram.com/PolynomialLongDivision/>.+-}+	_ `quotRem'` MkPolynomial []		= error "Factory.Data.Polynomial.quotRem':\tzero denominator."+	polynomialN `quotRem'` polynomialD	= longDivide polynomialN	where+--		longDivide :: (Fractional c, Num e, Ord e) => Polynomial c e -> (Polynomial c e, Polynomial c e)+		longDivide (MkPolynomial [])	= (zero, zero)	-- Exactly divides.+		longDivide numerator+			| Data.Monomial.getExponent quotient < 0	= (zero, numerator)	-- Indivisible remainder.+			| otherwise					= Control.Arrow.first (lift (quotient :)) $ longDivide (numerator =-= polynomialD *= quotient )+			where+--				quotient :: (Fractional c, Num e) => Data.Monomial.Monomial c e+				quotient	= getLeadingTerm numerator </> getLeadingTerm polynomialD++{- |+	* Transforms the data behind the constructor.++	* CAVEAT: similar to 'Data.Functor.fmap', but 'Polynomial' isn't an instance of 'Data.Functor.Functor' since we may want to operate on both /type-parameters/.++	* CAVEAT: the caller is required to re-'normalise' the resulting polynomial depending on the nature of the transformation of the data.+-}+lift :: (MonomialList c1 e1 -> MonomialList c2 e2) -> Polynomial c1 e1 -> Polynomial c2 e2+lift transform	= MkPolynomial . transform . getMonomialList++-- | Returns the number of non-zero terms in the polynomial.+terms :: Polynomial c e -> Int+terms (MkPolynomial l)	= length l++-- | Return the highest-degree monomial.+getLeadingTerm :: Polynomial c e -> Data.Monomial.Monomial c e+getLeadingTerm (MkPolynomial [])	= error "Factory.Data.Polynomial.getLeadingTerm:\tzero polynomial has no leading term."+getLeadingTerm (MkPolynomial (m : _))	= m++-- | Removes terms with a /coefficient/ of zero.+pruneCoefficients :: (Eq c, Num c) => Polynomial c e -> Polynomial c e+pruneCoefficients (MkPolynomial [])	= zero+pruneCoefficients p			= filter ((/= 0) . Data.Monomial.getCoefficient) `lift` p++-- | Sorts into /descending order/ of exponents, groups /like/ exponents, and calls 'pruneCoefficients'.+normalise :: (Eq c, Num c, Ord e) => Polynomial c e -> Polynomial c e+normalise	= pruneCoefficients . lift (+	map (+		foldr ((+) . Data.Monomial.getCoefficient) 0 &&& Data.Monomial.getExponent . head+	) . Data.List.groupBy (=~) . Data.List.sortBy (flip (<=>))+ )++-- | Constructs an arbitrary /zeroeth-degree polynomial/, ie. independent of the /indeterminate/.+mkConstant :: (Eq c, Num c, Num e) => c -> Polynomial c e+mkConstant 0	= zero+mkConstant c	= MkPolynomial [(c, 0)]++-- | Constructs an arbitrary /first-degree polynomial/.+mkLinear :: (Eq c, Num c, Num e)+	=> c	-- ^ Gradient.+	-> c	-- ^ Constant.+	-> Polynomial c e+mkLinear m c	= pruneCoefficients $ MkPolynomial [(m, 1), (c, 0)]++-- | Smart constructor. Constructs an arbitrary /polynomial/.+mkPolynomial :: (Eq c, Num c, Ord e) => MonomialList c e -> Polynomial c e+mkPolynomial []	= zero+mkPolynomial l	= normalise $ MkPolynomial l++-- | Constructs a /polynomial/ with zero terms.+zero :: Polynomial c e+zero	= MkPolynomial []++-- | Constructs a constant /monomial/, independent of the /indeterminate/.+one :: (Eq c, Num c, Num e) => Polynomial c e+one	= mkConstant 1++-- | True if all /exponents/ are in the order defined by the specified comparator.+inOrder :: (e -> e -> Bool) -> Polynomial c e -> Bool+inOrder comparator p+	| any ($ p) [isZero, isMonomial]	= True+	| otherwise				= and . uncurry (zipWith comparator) . (init &&& tail) . map Data.Monomial.getExponent $ getMonomialList p++-- | True if the /exponents/ of successive terms are in /ascending/ order.+inAscendingOrder :: Ord e => Polynomial c e -> Bool+inAscendingOrder	= inOrder (<=)++-- | True if the /exponents/ of successive terms are in /descending/ order.+inDescendingOrder :: Ord e => Polynomial c e -> Bool+inDescendingOrder	= inOrder (>=)++-- | True if no term has a /coefficient/ of zero.+isReduced :: (Eq c, Num c) => Polynomial c e -> Bool+isReduced	= all ((/= 0) . Data.Monomial.getCoefficient) . getMonomialList++-- | True if no term has a /coefficient/ of zero and the /exponents/ of successive terms are in /descending/ order.+isNormalised :: (Eq c, Num c, Ord e) => Polynomial c e -> Bool+isNormalised polynomial	= all ($ polynomial) [isReduced, inDescendingOrder]++{- |+	* 'True' if the /leading coefficient/ is one.++	* <http://en.wikipedia.org/wiki/Monic_polynomial#Classifications>.+-}+isMonic :: (Eq c, Num c) => Polynomial c e -> Bool+isMonic (MkPolynomial [])	= False	-- All coefficients are zero, and have therefore been removed.+isMonic p			= (== 1) . Data.Monomial.getCoefficient $ getLeadingTerm p++-- | True if there are zero terms.+isZero :: Polynomial c e -> Bool+isZero (MkPolynomial [])	= True+isZero _			= False++-- | True if there's exactly one term.+isMonomial :: Polynomial c e -> Bool+isMonomial (MkPolynomial [])	= True+isMonomial _			= False++-- | True if all /exponents/ are /positive/ integers as required.+isPolynomial :: Integral e => Polynomial c e -> Bool+isPolynomial	= all Data.Monomial.isMonomial . getMonomialList++{- |+	* 'True' if the two specified /polynomials/ are /congruent/ in /modulo/-arithmetic.++	* <http://planetmath.org/encyclopedia/PolynomialCongruence.html>.+-}+areCongruentModulo :: (Integral c, Num e, Ord e)+	=> Polynomial c e	-- ^ LHS.+	-> Polynomial c e	-- ^ RHS.+	-> c			-- ^ Modulus.+	-> Bool+areCongruentModulo _ _ 0	= error "Factory.Data.Polynomial.areCongruentModulo:\tzero modulus."+areCongruentModulo _ _ 1	= True+areCongruentModulo l r	modulus+	| l == r	= True+	| otherwise	= all ((== 0) . (`mod` modulus) . Data.Monomial.getCoefficient) . getMonomialList $ l =-= r++{- |+	* Return the /degree/ (AKA /order/) of the /polynomial/.++	* <http://en.wikipedia.org/wiki/Degree_of_a_polynomial>.++	* <http://mathworld.wolfram.com/PolynomialDegree.html>.+-}+getDegree :: Num e => Polynomial c e -> e+getDegree (MkPolynomial [])	= -1	-- CAVEAT: debatable, but makes some operations more robust and consistent.+getDegree p			= Data.Monomial.getExponent $ getLeadingTerm p++{- |+	* Scale-up the specified /polynomial/ by a constant /monomial/ factor.++	* <http://en.wikipedia.org/wiki/Scalar_multiplication>.+-}+(*=) :: (Eq c, Num c, Num e) => Polynomial c e -> Data.Monomial.Monomial c e -> Polynomial c e+polynomial *= monomial+	| Data.Monomial.getCoefficient monomial == 1	= map (`Data.Monomial.shiftExponent` Data.Monomial.getExponent monomial) `lift` polynomial+	| otherwise					= map (monomial <*>) `lift` polynomial++{- |+	* Raise a /polynomial/ to the specified positive integral power, but using /modulo/-arithmetic.++	* Whilst one could naively implement this as @(x Data.Ring.=^ n) `mod` m@, this will result in arithmetic operatons on unnecessarily big integers.+-}+raiseModulo :: (Integral c, Integral power, Num e, Ord e, Show power)+	=> Polynomial c e	-- ^ The base.+	-> power		-- ^ The exponent to which the base should be raised.+	-> c			-- ^ The modulus.+	-> Polynomial c e	-- ^ The result.+raiseModulo _ _ 0			= error "Factory.Data.Polynomial.raiseModulo:\tzero modulus."+raiseModulo _ _ 1			= zero+raiseModulo _ 0 modulus			= mkConstant $ 1 `mod` modulus+raiseModulo polynomial power modulus+	| power < 0			= error $ "Factory.Data.Polynomial.raiseModulo:\tthe result isn't guaranteed to be a polynomial, for power=" ++ show power+	| first `elem` [zero, one]	= first	-- Eg 'raiseModulo (mkPolynomial [(3,1)]) 100 3' or 'raiseModulo (mkPolynomial [(3,1),(1,0)]) 100 3'.+	| otherwise			= slave power+	where+--		first :: Integral c => Polynomial c e+		first	= polynomial `mod'` modulus++--		slave :: (Integral c, Integral power, Num e, Ord e) => power -> Polynomial c e+		slave 1	= first+		slave n	= (`mod'` modulus) . (if r == 0 {-even-} then id else (polynomial =*=)) . Data.Ring.square $ slave q {-recurse-}	where+			(q, r)	= n `quotRem` 2++-- | Reduces all the coefficients using /modular/ arithmetic.+mod' :: Integral c+	=> Polynomial c e+	-> c	-- ^ Modulus.+	-> Polynomial c e+mod' p modulus	= pruneCoefficients $ map (`Data.Monomial.mod'` modulus) `lift` p++{- |+	* Evaluate the /polynomial/ at a specific /indeterminate/.++	* CAVEAT: requires positive exponents; but it wouldn't really be a /polynomial/ otherwise.++	* If the /polynomial/ is very sparse, this may be inefficient,+	since it /memoizes/ the complete sequence of powers up to the polynomial's /degree/.+-}+evaluate :: (Num n, Integral e, Show e)+	=> n	-- ^ The /indeterminate/.+	-> Polynomial n e+	-> n	-- ^ The Result.+evaluate x	= foldr ((+) . raise) 0 . getMonomialList	where+	powers	= iterate (* x) 1++	raise monomial+		| exponent' < 0	= error $ "Factory.Data.Polynomial.evaluate.raise:\tnegative exponent; " ++ show exponent'+		| otherwise	= Data.Monomial.getCoefficient monomial * Data.List.genericIndex powers exponent'+		where+			exponent'	= Data.Monomial.getExponent monomial++-- | Convert the type of the /coefficient/s.+realCoefficientsToFrac :: (Real r, Fractional f) => Polynomial r e -> Polynomial f e+realCoefficientsToFrac	= lift (Data.Monomial.realCoefficientToFrac `map`)+
+ src-lib/Factory/Data/PrimeFactors.hs view
@@ -0,0 +1,143 @@+{-+	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 list of /prime factors/.++	* The product of this list of prime-factors represents the /composite/ integer from which they were originally extracted.+-}++module Factory.Data.PrimeFactors(+-- * Types+-- ** Type-synonyms+	Factors,+-- * Functions+	insert',+--	invert,+	product',+	reduce,+--	reduceSorted,+--	sumExponents,+-- ** Operators+	(>*<),+	(>/<),+	(>^)+) where++import qualified	Control.Arrow+import			Control.Arrow((&&&))+import qualified	Data.List+import qualified	Data.Ord+import qualified	Factory.Math.DivideAndConquer	as Math.DivideAndConquer+import qualified	Factory.Data.Exponential	as Data.Exponential+import			Factory.Data.Exponential((<^), (=~))+import qualified	ToolShed.Data.List++infixl 7 >/<, >*<	-- Same as (/).+infixr 8 >^		-- Same as (^).++{- |+	* Each element of this list represents one /prime-factor/, expressed as an /exponential/ with a /prime/ base, of the original integer.++	* Whilst it only makes sense for both the /base/ and /exponent/ to be integral, these constrains are applied at the function-level as required.+-}+type Factors base exponent	= [Data.Exponential.Exponential base exponent]++{- |+	* Sorts a list representing a product of /prime factors/ by increasing /base/.++	* Multiplies 'Data.Exponential.Exponential's of similar /base/.+-}+reduce :: (Ord base, Num exponent, Ord exponent) => Factors base exponent -> Factors base exponent+reduce	= reduceSorted . Data.List.sort {-primarily by base-}++-- | Multiplies 'Data.Exponential.Exponential's of similar /base/.+reduceSorted :: (Eq base, Num exponent) => Factors base exponent -> Factors base exponent+-- reduceSorted	= map (Data.Exponential.getBase . head &&& sumExponents) . Data.List.groupBy (=~)	-- Slow+reduceSorted []	= []+reduceSorted (x : xs)+	| null matched	= x : reduceSorted remainder+	| otherwise	= Control.Arrow.second (+ sumExponents matched) x : reduceSorted remainder+	where+		(matched, remainder)	= span (=~ x) xs++{- |+	* Insert a 'Data.Exponential.Exponential', into a list representing a product of /prime factors/, multiplying with any incumbent of like /base/.++	* The list should be sorted by increasing /base/.++	* Preserves the sort-order.++	* CAVEAT: this is tolerably efficient for sporadic insertion; to insert a list, use '>*<'.+-}+insert' :: (Ord base, Num exponent) => Data.Exponential.Exponential base exponent -> Factors base exponent -> Factors base exponent+insert' e []		= [e]+insert' e l@(x : xs)	= case Data.Ord.comparing Data.Exponential.getBase e x of+	LT	-> e : l+	GT	-> x : insert' e xs	-- Recurse.+	_	-> Control.Arrow.second (+ Data.Exponential.getExponent e) x : xs	-- Multiply by adding exponents.++{- |+	* Multiplies two lists each representing a product of /prime factors/, and sorted by increasing /base/.++	* Preserves the sort-order.+-}+(>*<) :: (Ord base, Num exponent, Ord exponent) => Factors base exponent -> Factors base exponent -> Factors base exponent+l >*< r	= reduceSorted $ ToolShed.Data.List.merge l r++-- | Invert the product of a list /prime factors/, by negating each of the /exponents/.+invert :: Num exponent => Factors base exponent -> Factors base exponent+invert	= map Data.Exponential.invert++{- |+	* Divides two lists, each representing a product of /prime factors/, and sorted by increasing /base/.++	* Preserves the sort-order.+-}+(>/<) :: (Integral base, Integral exponent)+	=> Factors base exponent				-- ^ The list of /prime factors/ in the /numerator/.+	-> Factors base exponent				-- ^ The list of /prime factors/ in the /denominator/.+	-> (Factors base exponent, Factors base exponent)	-- ^ The ratio of /numerator/ and /denominator/, after like /prime factors/ are cancelled.+numerator >/< denominator	= filter (+	(> 0) . Data.Exponential.getExponent+ ) &&& invert . filter (+	(< 0) . Data.Exponential.getExponent+ ) $ numerator >*< invert denominator++{- |+	* Raise the product of a list /prime factors/ to the specified power.++	* CAVEAT: this merely involves raising each element to the specified power; cf. raising a /polynomial/ to a power.+-}+(>^) :: Num exponent => Factors base exponent -> exponent -> Factors base exponent+factors >^ power	= map (<^ power) factors++-- | Sum the /exponents/ of the specified list; as required to multiply exponentials with identical /base/.+sumExponents :: Num exponent => Factors base exponent -> exponent+sumExponents	= foldr ((+) . Data.Exponential.getExponent) 0++-- | Multiply a list of /prime factors/.+product' :: (Num base, Integral exponent)+	=> Math.DivideAndConquer.BisectionRatio+	-> Math.DivideAndConquer.MinLength+	-> Factors base exponent		-- ^ The list on which to operate.+	-> base					-- ^ The result.+product' bisectionRatio minLength	= Math.DivideAndConquer.product' bisectionRatio minLength . map Data.Exponential.evaluate+
+ src-lib/Factory/Data/PrimeWheel.hs view
@@ -0,0 +1,198 @@+{-+	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 a /prime-wheel/, for use in prime-number generation; <http://en.wikipedia.org/wiki/Wheel_factorization>.+-}++module Factory.Data.PrimeWheel(+-- * Types+-- ** Type-synonyms+	Distance,+	NPrimes,+	PrimeMultiples,+--	Repository,+-- ** Data-types+	PrimeWheel(getPrimeComponents, getSpokeGaps),+-- * Functions+	estimateOptimalSize,+--	findCoprimes,+	generateMultiples,+	roll,+	rotate,+-- ** Constructors+	mkPrimeWheel,+-- ** Query+	getCircumference,+	getSpokeCount+) where++import			Control.Arrow((&&&), (***))+import qualified	Data.IntMap+import qualified	Data.List++{- |+	* A conceptual /wheel/, with irregularly spaced spokes; <http://www.haskell.org/haskellwiki/Prime_numbers_miscellaneous#Prime_Wheels>.++	* On being rolled, the trace of the spokes, identifies candidates which are /coprime/ to those primes from which the /wheel/ was composed.++	* One can alternatively view this as a set of vertical nested rings, each with a /prime circumference/, and touching at its lowest point.+	Each has a single mark on its /circumference/, which when rolled identifies multiples of that /circumference/.+	When the complete set is rolled, from the state where all marks are coincident, all multiples of the set of primes, are traced.++	* CAVEAT: The distance required to return to this state (the wheel's /circumference/), grows rapidly with the number of primes:++>	zip [0 ..] . scanl (*) 1 $ [2,3,5,7,11,13,17,19,23,29,31]+>	[(0,1),(1,2),(2,6),(3,30),(4,210),(5,2310),(6,30030),(7,510510),(8,9699690),(9,223092870),(10,6469693230),(11,200560490130)]++	* The number of spokes also grows rapidly with the number of primes:++>	zip [0 ..] . scanl (*) 1 . map pred $ [2,3,5,7,11,13,17,19,23,29,31]+>	[(0,1),(1,1),(2,2),(3,8),(4,48),(5,480),(6,5760),(7,92160),(8,1658880),(9,36495360),(10,1021870080),(11,30656102400)]+-}+data PrimeWheel i	= MkPrimeWheel {+	getPrimeComponents	:: [i],	-- ^ Accessor: the ordered sequence of initial primes, from which the /wheel/ was composed.+	getSpokeGaps		:: [i]	-- ^ Accessor: the sequence of spoke-gaps, the sum of which equals its /circumference/.+} deriving Show++-- | The /circumference/ of the specified 'PrimeWheel'.+getCircumference :: Integral i => PrimeWheel i -> i+getCircumference	= product . getPrimeComponents++-- | The number of spokes in the specified 'PrimeWheel'.+getSpokeCount :: Integral i => PrimeWheel i -> i+getSpokeCount	= foldr ((*) . pred) 1 . getPrimeComponents++-- | An infinite increasing sequence, of the multiples of a specific prime.+type PrimeMultiples i	= [i]++-- | Defines a container for the 'PrimeMultiples'.+type Repository	= Data.IntMap.IntMap (PrimeMultiples Int)++-- | The size of the /wheel/, measured by the number of primes from which it is composed.+type NPrimes	= Int++{- |+	* Uses a /Sieve of Eratosthenes/ (<http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes>), to generate an initial sequence of primes.++	* Also generates an infinite sequence of candidate primes, each of which is /coprime/ to the primes just found, e.g.:+	@filter ((== 1) . (gcd (2 * 3 * 5 * 7))) [11 ..] = [11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,121 ..]@; NB /121/ isn't prime.++	* CAVEAT: the use, for efficiency, of "Data.IntMap", limits the maximum bound of this sequence, though not to a significant extent.+-}+findCoprimes :: NPrimes -> ([Int], [Int])+findCoprimes 0	= ([], [])+findCoprimes required+	| required < 0	= error $ "Factory.Data.PrimeWheel.findCoprimes: invalid number of coprimes; " ++ show required+	| otherwise	= splitAt required $ 2 : sieve 3 0 Data.IntMap.empty+	where+		sieve :: Int -> NPrimes -> Repository -> [Int]+		sieve candidate found repository	= case Data.IntMap.lookup candidate repository of+			Just primeMultiples	-> sieve' found . insertUniq primeMultiples $ Data.IntMap.delete candidate repository	-- Re-insert subsequent multiples.+			Nothing {-prime-}	-> let+				found'		= succ found+				(key : values)	= iterate (+ gap * candidate) $ candidate ^ (2 :: Int)	-- Generate a sequence of prime-multiples, starting from its square.+			 in candidate : sieve' found' (+				if found' >= required+					then repository+					else Data.IntMap.insert key values repository+			 )+			where+				gap :: Int+				gap	= 2	-- For efficiency, only sieve odd integers.++				sieve' :: NPrimes -> Repository -> [Int]+				sieve'	= sieve $ candidate + gap	-- Tail-recurse.++				insertUniq :: PrimeMultiples Int -> Repository -> Repository+				insertUniq l m	= insert $ dropWhile (`Data.IntMap.member` m) l	where+					insert :: PrimeMultiples Int -> Repository+					insert []		= error "Factory.Data.PrimeWheel.findCoprimes.sieve.insertUniq.insert:\tnull list"+					insert (key : values)	= Data.IntMap.insert key values m+{- |+	* The optimal number of low primes from which to build the /wheel/, grows with the number of primes required;+	the /circumference/ should be approximately the /square-root/ of the number of integers it will be required to sieve.++	* CAVEAT: one greater than this is returned, which empirically seems better.+-}+estimateOptimalSize :: Integral i => i -> NPrimes+estimateOptimalSize maxPrime	= succ . length . takeWhile (<= optimalCircumference) . scanl1 (*) {-circumference-} . map fromIntegral {-prevent overflow-} . fst {-primes-} $ findCoprimes 10 {-arbitrary maximum bound-}	where+	optimalCircumference :: Integer+	optimalCircumference	= round (sqrt $ fromIntegral maxPrime :: Double)++{- |+	Smart constructor for a /wheel/ from the specified number of low primes.++	* The optimal number of low primes from which to build the /wheel/, grows with the number of primes required;+	the /circumference/ should be approximately the /square-root/ of the number of integers it will be required to sieve.++	* The sequence of gaps between spokes on the /wheel/ is /symmetrical under reflection/;+	though two values lie /on/ the axis, that aren't part of this symmetry. Eg:++>	nPrimes	Gaps+>	======	====+>	0	[1]+>	1	[2]	-- The terminal gap for all subsequent wheels is '2'; [(succ circumference `mod` circumference) - (pred circumference `mod` circumference)].+>	2	[4,2]	-- Both points are on the axis, so the symmetry isn't yet clear.+>	3	[6,4,2,4,2,4,6,2]+>	4	[10,2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2]++	Exploitation of this property has proved counter-productive, probably because it requires /strict evaluation/,+	exposing the user to the full cost of inadvertently choosing a /wheel/, which in practice, is rotated less than once.+-}+mkPrimeWheel :: Integral i => NPrimes -> PrimeWheel i+mkPrimeWheel 0	= MkPrimeWheel [] [1]+mkPrimeWheel nPrimes+	| nPrimes < 0	= error $ "Factory.Data.PrimeWheel.mkPrimeWheel: unable to construct from " ++ show nPrimes ++ " primes"+	| otherwise	= primeWheel+	where+		(primeComponents, coprimeCandidates)	= (map fromIntegral *** map fromIntegral . Data.List.genericTake (getSpokeCount primeWheel)) $ findCoprimes nPrimes+		primeWheel				= MkPrimeWheel primeComponents $ zipWith (-) coprimeCandidates $ 1 : coprimeCandidates	-- Measure the gaps between candidate primes.++-- | Couples a candidate prime with a /rolling wheel/, to define the distance rolled.+type Distance i	= (i, [i])++-- | Generates a new candidate prime, from a /rolling wheel/, and the current candidate.+rotate :: Integral i => Distance i -> Distance i+rotate (candidate, rollingWheel)	= (candidate +) . head &&& tail $ rollingWheel++{-# INLINE rotate #-}++-- | Generate an infinite, increasing sequence of candidate primes, from the specified /wheel/.+roll :: Integral i => PrimeWheel i -> [Distance i]+roll primeWheel	= tail $ iterate rotate (1, cycle $ getSpokeGaps primeWheel)++{- |+	* Generates multiples of the specified prime, starting from its /square/,+	skipping those multiples of the low primes from which the specified 'PrimeWheel' was composed,+	and which therefore, the /wheel/ won't generate as candidates. Eg:++>	Prime	Rotating PrimeWheel 3	Output+>	=====	=====================	======+>	7	[4,2,4,2,4,6,2,6]	[49,77,91,119,133,161,203,217,259 ..]+>	11	[2,4,2,4,6,2,6,4]	[121,143,187,209,253,319,341,407 ..]+>	13	[4,2,4,6,2,6,4,2]	[169,221,247,299,377,403,481,533,559 ..]+-}+generateMultiples :: Integral i+	=> i	-- ^ The number to square and multiply+	-> [i]	-- ^ A /rolling wheel/, the track of which, delimits the gaps between /coprime/ candidates.+	-> [i]+generateMultiples i	= scanl (\accumulator -> (+ accumulator) . (* i)) (i ^ (2 :: Int))++{-# INLINE generateMultiples #-}+
+ src-lib/Factory/Data/QuotientRing.hs view
@@ -0,0 +1,79 @@+{-+	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 /Quotient Ring/; <http://en.wikipedia.org/wiki/Quotient_ring>.++	* This is a /ring/ composed from a residue-class resulting from /modular/ division.+-}++module Factory.Data.QuotientRing(+-- * Type-classes+	QuotientRing(..),+-- * Functions+	quot',+	rem',+-- ** Predicates+	areCongruentModulo,+	isDivisibleBy+) where++import			Factory.Data.Ring((=-=))+import qualified	Factory.Data.Ring	as Data.Ring++-- | Defines a sub-class of 'Data.Ring.Ring', in which division is implemented.+class Data.Ring.Ring q => QuotientRing q	where+	quotRem'	:: q -> q -> (q, q)	-- ^ Divides the first operand by the second, to yield a pair composed from the /quotient/ and the /remainder/.++-- | Returns the /quotient/, after division of the two specified 'QuotientRing's.+quot' :: QuotientRing q+	=> q	-- ^ Numerator.+	-> q	-- ^ Denominator.+	-> q+quot' numerator	= fst . quotRem' numerator++-- | Returns the /remainder/, after division of the two specified 'QuotientRing's.+rem' :: QuotientRing q+	=> q	-- ^ Numerator.+	-> q	-- ^ Denominator.+	-> q+rem' numerator	= snd . quotRem' numerator++{- |+	* 'True' if the two specified 'QuotientRing's are /congruent/ in /modulo/-arithmetic, where the /modulus/ is a third 'QuotientRing'.++	* <http://www.usna.edu/Users/math/wdj/book/node74.html>.+-}+areCongruentModulo :: (Eq q, QuotientRing q)+	=> q	-- ^ LHS.+	-> q	-- ^ RHS.+	-> q	-- ^ Modulus.+	-> Bool+areCongruentModulo l r modulus+	| l == r	= True	-- Only required for efficiency.+	| otherwise	= (l =-= r) `isDivisibleBy` modulus++-- | True if the second operand /divides/ the first.+isDivisibleBy :: (Eq q, QuotientRing q)+	=> q	-- ^ Numerator.+	-> q	-- ^ Denominator.+	-> Bool+numerator `isDivisibleBy` denominator	= rem' numerator denominator == Data.Ring.additiveIdentity+
+ src-lib/Factory/Data/Ring.hs view
@@ -0,0 +1,118 @@+{-+	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 /ring/ and operations on its members.++	* <http://en.wikipedia.org/wiki/Ring_%28mathematics%29>.++	* <http://www.numericana.com/answer/rings.htm>.+-}++module Factory.Data.Ring(+-- * Type-classes+	Ring(..),+-- * Types+-- ** Data.types+--	Product,+--	Sum,+-- * Functions+	product',+	sum',+-- ** Operators+	(=^)+) where++import qualified	Data.Monoid+import qualified	Factory.Math.DivideAndConquer	as Math.DivideAndConquer++infixl 6 =+=	-- Same as (+).+infixl 6 =-=	-- Same as (-).+infixl 7 =*=	-- Same as (*).+infixr 8 =^	-- Same as (^).++{- |+	* Define both the operations applicable to all members of the /ring/, and its mandatory members.++	* Minimal definition; '=+=', '=*=', 'additiveInverse', 'multiplicativeIdentity', 'additiveIdentity'.+-}+class Ring r	where+	(=+=)			:: r -> r -> r	-- ^ Addition of two members; required to be /commutative/; <http://en.wikipedia.org/wiki/Commutativity>.+	(=*=)			:: r -> r -> r	-- ^ Multiplication of two members.+	additiveInverse		:: r -> r	-- ^ The operand required to yield /zero/ under addition; <http://en.wikipedia.org/wiki/Additive_inverse>.+	multiplicativeIdentity	:: r		-- ^ The /identity/-member under multiplication; <http://mathworld.wolfram.com/MultiplicativeIdentity.html>.+	additiveIdentity	:: r		-- ^ The /identity/-member under addition (AKA /zero/); <http://en.wikipedia.org/wiki/Additive_identity>.++	(=-=) :: r -> r -> r			-- ^ Subtract the two specified /ring/-members.+	l =-= r	= l =+= additiveInverse r	-- Default implementation.++	square :: r -> r			-- ^ Square the ring.+	square r	= r =*= r		-- Default implementation; there may be a more efficient one.++{- |+	* Raise a /ring/-member to the specified positive integral power.++	* Exponentiation is implemented as a sequence of either squares of, or multiplications by, the /ring/-member;+	<http://en.wikipedia.org/wiki/Exponentiation_by_squaring>.+-}+(=^) :: (+	Eq		r,+	Integral	power,+	Ring		r,+	Show		power+ ) => r -> power -> r+_ =^ 0	= multiplicativeIdentity+ring =^ power+	| power < 0							= error $ "Factory.Data.Ring.(=^):\tthe result isn't guaranteed to be a ring-member, for power=" ++ show power+	| ring `elem` [additiveIdentity, multiplicativeIdentity]	= ring+	| otherwise							= slave power+	where+		slave 1	= ring+		slave n	= (if r == 0 {-even-} then id else (=*= ring)) . square $ slave q	where+			(q, r)	= n `quotRem` 2++-- | Does for 'Ring', what 'Data.Monoid.Product' does for type 'Num', in that it makes it an instance of 'Data.Monoid.Monoid' under multiplication.+newtype Product p	= MkProduct {+	getProduct :: p	-- ^ Access the polymorphic payload.+} deriving (Read, Show)++instance Ring r => Data.Monoid.Monoid (Product r)	where+	mempty					= MkProduct multiplicativeIdentity+	MkProduct x `mappend` MkProduct y	= MkProduct $ x =*= y++-- | Returns the /product/ of the list of /ring/-members.+product' :: Ring r => Math.DivideAndConquer.BisectionRatio -> Math.DivideAndConquer.MinLength -> [r] -> r+-- product' _ _			= getProduct . Data.Monoid.mconcat . map MkProduct+product' ratio minLength	= getProduct . Math.DivideAndConquer.divideAndConquer ratio minLength . map MkProduct++-- | Does for 'Ring', what 'Data.Monoid.Sum' does for type 'Num', in that it makes it an instance of 'Data.Monoid.Monoid' under addition.+newtype Sum s	= MkSum {+	getSum :: s	-- ^ Access the polymorphic payload.+} deriving (Read, Show)++instance Ring r => Data.Monoid.Monoid (Sum r)	where+	mempty				= MkSum additiveIdentity+	MkSum x `mappend` MkSum y	= MkSum $ x =+= y++-- | Returns the /sum/ of the list of /ring/-members.+sum' :: Ring r => Math.DivideAndConquer.BisectionRatio -> Math.DivideAndConquer.MinLength -> [r] -> r+-- sum' _ _		= getSum . Data.Monoid.mconcat . map MkSum+sum' ratio minLength	= getSum . Math.DivideAndConquer.divideAndConquer ratio minLength . map MkSum+
+ src-lib/Factory/Math/ArithmeticGeometricMean.hs view
@@ -0,0 +1,91 @@+{-+	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@]	Determines the /Arithmetic-geometric mean/; <http://en.wikipedia.org/wiki/Arithmetic-geometric_mean>.+-}++module Factory.Math.ArithmeticGeometricMean(+-- * Types+-- ** Type-synonyms+	ArithmeticMean,+	GeometricMean,+	AGM,+-- * Functions+	convergeToAGM,+	spread,+-- ** Accessors+	getArithmeticMean,+	getGeometricMean,+-- ** Predicates+	isValid+) where++import			Control.Arrow((&&&))+import qualified	Control.Parallel.Strategies+import qualified	Factory.Math.Precision	as Math.Precision+import qualified	Factory.Math.SquareRoot	as Math.SquareRoot++-- | The type of the /arithmetic mean/; <http://en.wikipedia.org/wiki/Arithmetic_mean>.+type ArithmeticMean	= Rational++-- | The type of the /geometric mean/; <http://en.wikipedia.org/wiki/Geometric_mean>.+type GeometricMean	= Rational++-- | Encapsulates both /arithmetic/ and /geometric/ means.+type AGM	= (ArithmeticMean, GeometricMean)++-- | Accessor.+{-# INLINE getArithmeticMean #-}+getArithmeticMean :: AGM -> ArithmeticMean+getArithmeticMean	= fst++-- | Accessor.+{-# INLINE getGeometricMean #-}+getGeometricMean :: AGM -> GeometricMean+getGeometricMean	= snd++-- | Returns an infinite list which converges on the /Arithmetic-geometric mean/.+convergeToAGM :: Math.SquareRoot.Algorithmic squareRootAlgorithm => squareRootAlgorithm -> Math.Precision.DecimalDigits -> AGM -> [AGM]+convergeToAGM squareRootAlgorithm decimalDigits agm+	| decimalDigits <= 0	= error $ "Factory.Math.ArithmeticGeometricMean.convergeToAGM:\tinvalid number of decimal digits; " ++ show decimalDigits+	| not $ isValid agm	= error $ "Factory.Math.ArithmeticGeometricMean.convergeToAGM:\tboth means must be positive for a real geometric mean; " ++ show agm+	| spread agm == 0	= repeat agm+	| otherwise		= let+		simplify :: Rational -> Rational+		simplify	= Math.Precision.simplify (pred decimalDigits {-ignore single integral digit-})	-- This makes a gigantic difference to performance.++		findArithmeticMean :: AGM -> ArithmeticMean+		findArithmeticMean	= (/ 2) . uncurry (+)++		findGeometricMean :: AGM -> GeometricMean+		findGeometricMean	= Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits . uncurry (*)+	in iterate (+		Control.Parallel.Strategies.withStrategy (+			Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq+		) . (simplify . findArithmeticMean &&& simplify . findGeometricMean)+	) agm++-- | Returns the bounds within which the 'AGM' has been constrained.+spread :: AGM -> Rational+spread	= uncurry (-)++-- | Checks that both /means/ are positive, as required for the /geometric mean/ to be consistently /real/.+isValid :: AGM -> Bool+isValid (a, g)	= all (>= 0) [a, g]+
+ src-lib/Factory/Math/DivideAndConquer.hs view
@@ -0,0 +1,122 @@+{-+	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@]++	* Provides a polymorphic algorithm, to /unfold/ a list into a tree, to which an /associative binary operator/ is then applied to re-/fold/ the tree to a /scalar/.++	* 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.Interval/.+-}++module Factory.Math.DivideAndConquer(+-- * Types+-- ** Type-synonyms+	BisectionRatio,+	MinLength,+-- * Functions+	divideAndConquer,+	product',+	sum'+) where++import			Control.Arrow((***))+import qualified	Control.Parallel.Strategies+import qualified	Data.Monoid+import qualified	Data.Ratio++{- |+	* The ratio of the original list-length at which to bisect.++	* CAVEAT: the value can overflow.+-}+type BisectionRatio	= Data.Ratio.Ratio Int++-- | The list-length beneath which to terminate bisection.+type MinLength	= Int++{- |+	* Reduces a list to a single scalar encapsulated in a 'Data.Monoid.Monoid',+	using a /divide-and-conquer/ strategy,+	bisecting the list and recursively evaluating each part; <http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm>.++	* By choosing a 'bisectionRatio' 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 list-length,+	after which the /monoid/'s binary operator is directly /folded/ over the list.++	* One can view this as a <http://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>,+	in which the list 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 :: Data.Monoid.Monoid monoid+	=> BisectionRatio	-- ^ The ratio of the original list-length at which to bisect.+	-> MinLength		-- ^ For efficiency, the list will not be bisected, when it's length has been reduced to this value.+	-> [monoid]		-- ^ The list on which to operate.+	-> monoid		-- ^ The resulting scalar.+divideAndConquer bisectionRatio minLength l+	| any ($ apportion minLength) [+		(< 1),			-- The left-hand list may be null.+		(> pred minLength)	-- The right-hand list may be null.+	]		= error $ "Factory.Math.DivideAndConquer.divideAndConquer:\tbisectionRatio='" ++ show bisectionRatio ++ "' is incompatible with minLength=" ++ show minLength ++ "."+	| otherwise	= slave (length l) l+	where+		apportion :: Int -> Int+		apportion list	= (list * Data.Ratio.numerator bisectionRatio) `div` Data.Ratio.denominator bisectionRatio++		slave len list+			| len <= minLength	= Data.Monoid.mconcat list	-- Fold the monoid's binary operator over the list.+			| otherwise		= uncurry Data.Monoid.mappend . Control.Parallel.Strategies.withStrategy (+				Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rseq Control.Parallel.Strategies.rseq+			) . (slave cut *** slave (len - cut)) $ splitAt cut list	where	-- Apply the monoid's binary operator to the two operands resulting from bisection.+				cut	= apportion len++{- |+	* Multiplies the specified list of numbers.++	* Since the result can be large, 'divideAndConquer' is used in an attempt to form operands of a similar order of magnitude,+	which creates scope for the use of more efficient multiplication-algorithms.+-}+product' :: Num n+	=> BisectionRatio	-- ^ The ratio of the original list-length at which to bisect.+	-> MinLength		-- ^ For efficiency, the list will not be bisected, when it's length has been reduced to this value.+	-> [n]			-- ^ The numbers whose product is required.+	-> n			-- ^ The resulting product.+product' bisectionRatio minLength	= Data.Monoid.getProduct . divideAndConquer bisectionRatio minLength . map Data.Monoid.Product++{- |+	* Sums the specified list of numbers.++	* Since the result can be large, 'divideAndConquer' is used in an attempt to form operands of a similar order of magnitude,+	which creates scope for the use of more efficient multiplication-algorithms.+	/Multiplication/ is required for the /addition/ of 'Rational' numbers by cross-multiplication;+	this function is unlikely to be useful for other numbers.+-}+sum' :: Num n+	=> BisectionRatio	-- ^ The ratio of the original list-length at which to bisect.+	-> MinLength		-- ^ For efficiency, the list will not be bisected, when it's length has been reduced to this value.+	-> [n]			-- ^ The numbers whose sum is required.+	-> n			-- ^ The resulting sum.+sum' bisectionRatio minLength	= Data.Monoid.getSum . divideAndConquer bisectionRatio minLength . map Data.Monoid.Sum+
+ src-lib/Factory/Math/Factorial.hs view
@@ -0,0 +1,37 @@+{-+	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@]++	* Whilst this particular function is the subject of many introductory examples to Haskell,+	the simple algorithms appropriate for that forum, leave a large margin for performance-improvement.+	This module provides the interface for alternative algorithms.++	* <http://mathworld.wolfram.com/Factorial.html>.+-}++module Factory.Math.Factorial(+-- * Type-classes+	Algorithmic(..)+) where++-- | Defines the methods expected of a /factorial/-algorithm.+class Algorithmic algorithm	where+	factorial	:: (Integral i, Show i) => algorithm -> i -> i+
+ src-lib/Factory/Math/Fibonacci.hs view
@@ -0,0 +1,42 @@+{-+	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@]	<http://en.wikipedia.org/wiki/Fibonacci_number>.+-}++module Factory.Math.Fibonacci(+-- * Constants+	fibonacci,+	primeIndexedFibonacci+) where++import qualified	Data.Numbers.Primes++-- | A constant ordered list of the /Fibonacci/-numbers.+fibonacci :: Integral i => [i]+fibonacci	= 0 : scanl (+) 1 fibonacci++{- |+	* The subset of 'fibonacci', /indexed/ by a /prime/-number.++	* <http://primes.utm.edu/glossary/page.php?sort=FibonacciPrime>.+-}+primeIndexedFibonacci :: Integral i => [i]+primeIndexedFibonacci	= map (fibonacci !!) Data.Numbers.Primes.primes+
+ src-lib/Factory/Math/Hyperoperation.hs view
@@ -0,0 +1,113 @@+{-+	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@]	Provides various /hyperoperations/; <http://en.wikipedia.org/wiki/Hyperoperation>.+-}++module Factory.Math.Hyperoperation(+-- * Types+-- ** Type-synonyms+	Base,+	HyperExponent,+-- * Constants+	succession,+	addition,+	multiplication,+	exponentiation,+	tetration,+	pentation,+	hexation,+-- * Functions+	hyperoperation,+	ackermannPeter,+	powerTower,+-- ** Predicates+	areCoincidental+) where++import qualified	Data.List++{- |+	* Merely to enhance self-documentation.++	* CAVEAT: whilst it may appear that 'Base' could be non-'Integral', the recursive definition for /hyper-exponents/ above 'tetration', prevents this.+-}+type Base	= Integer++{- |+	* Merely to enhance self-documentation.++	* CAVEAT: whilst 'Base' and 'HyperExponent' can be independent types for both 'exponentiation' and 'tetration', they interact for other /hyper-exponents/.+-}+type HyperExponent	= Base++succession, addition, multiplication, exponentiation, tetration, pentation, hexation :: Int	-- Arbitrarily.+(succession : addition : multiplication : exponentiation : tetration : pentation : hexation : _)	= [0 ..]++{- |+	* Returns the /power-tower/ of the specified /base/; <http://mathworld.wolfram.com/PowerTower.html>.++	* A synonym for /tetration/;+		<http://en.wikipedia.org/wiki/Tetration>,+		<http://www.tetration.org/Fractals/Atlas/index.html>.+-}+powerTower :: (Integral base, Integral hyperExponent, Show base) => base -> hyperExponent -> base+powerTower 0 hyperExponent+	| even hyperExponent	= 1+	| otherwise		= 0+powerTower _ (-1)	= 0	-- The only negative hyper-exponent for which there's a consistent result.+powerTower base hyperExponent+	| base < 0 && hyperExponent > 1	= error $ "Factory.Math.Hyperoperation.powerTower:\tundefined for negative base; " ++ show base+	| otherwise			= Data.List.genericIndex (iterate (base ^) 1) hyperExponent++-- | The /hyperoperation/-sequence; <http://en.wikipedia.org/wiki/Hyperoperation>.+hyperoperation :: (Integral rank, Show rank) => rank -> Base -> HyperExponent -> Base+hyperoperation rank base hyperExponent+	| rank < fromIntegral succession	= error $ "Factory.Math.Hyperoperation.hyperoperation:\tundefined for rank; " ++ show rank+	| hyperExponent < 0			= error $ "Factory.Math.Hyperoperation.hyperoperation:\tundefined for hyper-exponent; " ++ show hyperExponent+	| otherwise				= rank ^# hyperExponent+	where+		(^#) :: Integral rank => rank -> HyperExponent -> Base+		r ^# 0	= case r of+			1 {-addition-}		-> base+			2 {-multiplication-}	-> 0+			_			-> 1+		r ^# e	= case r of+			0 {-succession-}	-> succ {-fromIntegral-} e+			1 {-addition-}		-> base + {-fromIntegral-} e+			2 {-multiplication-}	-> base * {-fromIntegral-} e+			3 {-exponentiation-}	-> base ^ e+			4 {-tetration-}		-> base `powerTower` e+			_+				| e' == e	-> tetration ^# e'	-- To which it would otherwise be reduced by laborious recursion.+				| otherwise	-> pred r ^# e'+				where+					e'	= {-fromIntegral $-} r ^# pred e++-- | The /Ackermann-Peter/-function; <http://en.wikipedia.org/wiki/Ackermann_function#Ackermann_numbers>.+ackermannPeter :: (Integral rank, Show rank) => rank -> HyperExponent -> Base+ackermannPeter rank	= (+ negate 3) . hyperoperation rank 2 {-base-} . (+ 3)++-- | True if @hyperoperation base hyperExponent@ has the same value for each specified 'rank'.+areCoincidental :: (Integral rank, Show rank) => Base -> HyperExponent -> [rank] -> Bool+areCoincidental _ _ []				= True+areCoincidental _ _ [_]				= True+areCoincidental base hyperExponent ranks	= all (== h) hs	where+	(h : hs)	= map (\rank -> hyperoperation rank base hyperExponent) ranks+
+ src-lib/Factory/Math/Implementations/Factorial.hs view
@@ -0,0 +1,138 @@+{-+	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@]++	* Provides implementations of the class 'Math.Factorial.Algorithmic'.++	* Provides additional functions related to /factorials/, but which depends on a specific implementation,+	and which therefore can't be accessed throught the class-interface.++	* <http://en.wikipedia.org/wiki/Factorial>.++	* <http://mathworld.wolfram.com/Factorial.html>.++	* <http://www.luschny.de/math/factorial/FastFactorialFunctions.htm>.+-}++module Factory.Math.Implementations.Factorial(+-- * Types+-- ** Data-types+	Algorithm(..),+-- * Functions+	primeFactors,+--	primeMultiplicity,+	risingFactorial,+	fallingFactorial,+-- ** Operators+	(!/!)+) where++import qualified	Data.Numbers.Primes+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++infixl 7 !/!	-- Same as (/).++-- | The algorithms by which /factorial/ has been implemented.+data Algorithm	=+	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)++instance ToolShed.Defaultable.Defaultable Algorithm	where+	defaultValue	= Bisection++instance Math.Factorial.Algorithmic Algorithm	where+	factorial algorithm n+		| n < 2		= 1+		| otherwise	= case algorithm of+			Bisection		-> risingFactorial 2 $ pred n+			PrimeFactorisation	-> Data.PrimeFactors.product' (recip 5) {-empirical-} 10 {-empirical-} $ primeFactors n++{- |+	* Returns the /prime factors/, of the /factorial/ of the specifed integer.++	* Precisely all the primes less than or equal to the specified integer /n/, are included in /n!/;+	only the multiplicity of each of these known prime components need be determined.++	* <http://en.wikipedia.org/wiki/Factorial#Number_theory>.++	* CAVEAT: currently a hotspot.+-}+primeFactors :: Integral base+	=> base					-- ^ The number, whose /factorial/ is to be factorised.+	-> Data.PrimeFactors.Factors base base	-- ^ The /base/ and /exponent/ of each /prime factor/ in the /factorial/, ordered by increasing /base/ (and decreasing /exponent/).+primeFactors n	= takeWhile ((> 0) . snd) $ map (\prime -> (prime, primeMultiplicity prime n)) Data.Numbers.Primes.primes++{- |+	* The number of times a specific /prime/, can be factored from the /factorial/ of the specified integer.++	* General purpose /prime-factorisation/ has /exponential time-complexity/,+	so use /Legendre's Theorem/, which relates only to the /prime factors/ of /factorials/.++	* <http://www.proofwiki.org/wiki/Multiplicity_of_Prime_Factor_in_Factorial>.+-}+primeMultiplicity :: Integral i+	=> i	-- ^ A prime number.+	-> i	-- ^ The integer, the factorial of which the prime is a factor.+	-> i	-- ^ The number of times the prime occurs in the factorial.+primeMultiplicity prime	= sum . takeWhile (> 0) . tail . iterate (`div` prime)++-- | Returns the /rising factorial/; <http://mathworld.wolfram.com/RisingFactorial.html>+risingFactorial :: (Integral i, Show i)+	=> i	-- ^ The lower bound of the integer-range, whose product is returned.+	-> i	-- ^ The number of integers in the range above.+	-> i	-- ^ The result.+risingFactorial _ 0	= 1+risingFactorial 0 _	= 0+risingFactorial x n	= Data.Interval.product' (recip 2) 64 $ Data.Interval.normalise (x, pred $ x + n)++-- | Returns the /falling factorial/; <http://mathworld.wolfram.com/FallingFactorial.html>+fallingFactorial :: (Integral i, Show i)+	=> i	-- ^ The upper bound of the integer-range, whose product is returned.+	-> i	-- ^ The number of integers in the range beneath.+	-> i	-- ^ The result.+fallingFactorial _ 0	= 1+fallingFactorial 0 _	= 0+fallingFactorial x n	= Data.Interval.product' (recip 2) 64 $ Data.Interval.normalise (x, succ $ x - n)++{- |+	* Returns the ratio of two factorials.++	* It is more efficient than evaluating both factorials, and then dividing.++	* For more complex combinations of factorials, such as in the /Binomial coefficient/,+	extract the /prime factors/ using 'primeFactors'+	then manipulate them using the module "Data.PrimeFactors",+	and evaluate it using by /Data.PrimeFactors.product'/.+-}+(!/!) :: (Integral i, Fractional f, Show i)+	=> i	-- ^ The /numerator/.+	-> i	-- ^ The /denominator/.+	-> f	-- ^ The resulting fraction.+numerator !/! denominator+	| numerator <= 1		= recip . fromIntegral $ Math.Factorial.factorial (ToolShed.Defaultable.defaultValue :: Algorithm) denominator+	| denominator <= 1		= fromIntegral $ Math.Factorial.factorial (ToolShed.Defaultable.defaultValue :: Algorithm) numerator+	| numerator == denominator	= 1+	| numerator < denominator	= recip $ denominator !/! numerator	-- Recurse.+	| otherwise			= fromIntegral $ Data.Interval.product' (recip 2) 64 (succ denominator, numerator)+
+ src-lib/Factory/Math/Implementations/Pi/AGM/Algorithm.hs view
@@ -0,0 +1,42 @@+{-+	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 the set of /Arithmetic-geometric Mean/-type /Pi/-algorithms which have been implemented; currently just one.+-}++module Factory.Math.Implementations.Pi.AGM.Algorithm(+-- * Types+-- ** Data-types+	Algorithm(..)+) where++import qualified	Factory.Math.Implementations.Pi.AGM.BrentSalamin	as Math.Implementations.Pi.AGM.BrentSalamin+import qualified	Factory.Math.Pi						as Math.Pi+import qualified	Factory.Math.SquareRoot					as Math.SquareRoot+import qualified	ToolShed.Defaultable++-- | Defines the available algorithms.+data Algorithm squareRootAlgorithm	= BrentSalamin squareRootAlgorithm	deriving (Eq, Read, Show)++instance ToolShed.Defaultable.Defaultable squareRootAlgorithm => ToolShed.Defaultable.Defaultable (Algorithm squareRootAlgorithm)	where+	defaultValue	= BrentSalamin ToolShed.Defaultable.defaultValue++instance Math.SquareRoot.Algorithmic squareRootAlgorithm => Math.Pi.Algorithmic (Algorithm squareRootAlgorithm)	where+	openR (BrentSalamin squareRootAlgorithm)	= Math.Implementations.Pi.AGM.BrentSalamin.openR squareRootAlgorithm+
+ src-lib/Factory/Math/Implementations/Pi/AGM/BrentSalamin.hs view
@@ -0,0 +1,64 @@+{-+	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@]++	* Implements the /Brent-Salamin/ (AKA /Gauss-Legendre/) algorithm;+		<http://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm>,+		<http://mathworld.wolfram.com/Brent-SalaminFormula.html>,+		<http://www.pi314.net/eng/salamin.php>.++	* The precision of the result approximately doubles for each iteration.++ [@CAVEAT@]	Assumptions on the convergence-rate result in rounding-errors, when only a small number of digits are requested.+-}++module Factory.Math.Implementations.Pi.AGM.BrentSalamin(+-- * Functions+	openR+) where++import			Control.Arrow((&&&))+import qualified	Factory.Math.ArithmeticGeometricMean	as Math.ArithmeticGeometricMean+import qualified	Factory.Math.Power			as Math.Power+import qualified	Factory.Math.Precision			as Math.Precision+import qualified	Factory.Math.SquareRoot			as Math.SquareRoot++{- |+	* Returns /Pi/, accurate to the specified number of decimal digits.++	* This algorithm is based on the /arithmetic-geometric/ mean of @1@ and @(1 / sqrt 2)@,+	but there are many confusingly similar formulations.+	The algorithm I've used here, where @a@ is the /arithmetic mean/ and @g@ is the /geometric mean/, is equivalent to other common formulations:++>		pi = (a[N-1] + g[N-1])^2 / (1 - sum [2^n * (a[n] - g[n])^2])			where n = [0 .. N-1]+>		=> 4*a[N]^2 / (1 - sum [2^n * (a[n]^2 - 2*a[n]*g[n] + g[n]^2)])+>		=> 4*a[N]^2 / (1 - sum [2^n * (a[n]^2 + 2*a[n]*g[n] + g[n]^2 - 4*a[n]*g[n])])+>		=> 4*a[N]^2 / (1 - sum [2^n * ((a[n] + g[n])^2 - 4*a[n]*g[n])])+>		=> 4*a[N]^2 / (1 - sum [2^(n-1) * 4 * (a[n-1]^2 - g[n-1]^2)])			where n = [1 .. N]+>		=> 4*a[N]^2 / (1 - sum [2^(n+1) * (a[n-1]^2 - g[n-1]^2)])++-}+openR :: Math.SquareRoot.Algorithmic squareRootAlgorithm => squareRootAlgorithm -> Math.Precision.DecimalDigits -> Rational+openR squareRootAlgorithm decimalDigits	= uncurry (/) . (+	Math.Power.square . uncurry (+) . last &&& negate . pred . sum . zipWith (*) (iterate (* 2) 1) . map (Math.Power.square . Math.ArithmeticGeometricMean.spread)+ ) . take (+	Math.Precision.getIterationsRequired Math.Precision.quadraticConvergence 1 decimalDigits+ ) $ Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits (1, Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits (recip 2 :: Rational))+
+ src-lib/Factory/Math/Implementations/Pi/BBP/Algorithm.hs view
@@ -0,0 +1,47 @@+{-+	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 the set of /Bailey-Borwein-Plouffe/-type formulae which have been implemented.+-}++module Factory.Math.Implementations.Pi.BBP.Algorithm(+-- * Types+-- ** Data-types+	Algorithm(..)+) where++import qualified	Factory.Math.Implementations.Pi.BBP.Base65536		as Math.Implementations.Pi.BBP.Base65536+import qualified	Factory.Math.Implementations.Pi.BBP.Bellard		as Math.Implementations.Pi.BBP.Bellard+import qualified	Factory.Math.Implementations.Pi.BBP.Implementation	as Math.Implementations.Pi.BBP.Implementation+import qualified	Factory.Math.Pi						as Math.Pi+import qualified	ToolShed.Defaultable++-- | Defines those /BBP/-type series which have been implemented.+data Algorithm	=+	Base65536	-- ^ A /base/-@2^16@ version of the formula.+	| Bellard	-- ^ A /nega-base/ @2^10@ version of the formula.+	deriving (Eq, Read, Show)++instance ToolShed.Defaultable.Defaultable Algorithm	where+	defaultValue	= Base65536++instance Math.Pi.Algorithmic Algorithm	where+	openR Base65536	= Math.Implementations.Pi.BBP.Implementation.openR Math.Implementations.Pi.BBP.Base65536.series+	openR Bellard	= Math.Implementations.Pi.BBP.Implementation.openR Math.Implementations.Pi.BBP.Bellard.series+
+ src-lib/Factory/Math/Implementations/Pi/BBP/Base65536.hs view
@@ -0,0 +1,38 @@+{-+	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 a specific base-@2^16@ /BBP/-formula; <http://mathworld.wolfram.com/PiFormulas.html>++-}++module Factory.Math.Implementations.Pi.BBP.Base65536(+-- * Constants+	series+) where++import qualified	Factory.Math.Implementations.Pi.BBP.Series	as Math.Implementations.Pi.BBP.Series++-- | Defines the parameters of this specific series.+series :: Math.Implementations.Pi.BBP.Series.Series+series	= Math.Implementations.Pi.BBP.Series.MkSeries {+	Math.Implementations.Pi.BBP.Series.numerators		= zipWith ($) (cycle [id, id, id, negate]) $ map (2 ^) [15 :: Integer, 14, 14, 12, 11, 10, 10, 8, 7, 6, 6, 4, 3, 2, 2, 0],+	Math.Implementations.Pi.BBP.Series.getDenominators	= \i -> map (32 * fromIntegral i +) [2, 3, 4, 7, 10, 11, 12, 15, 18, 19, 20, 23, 26, 27, 28, 31],+	Math.Implementations.Pi.BBP.Series.seriesScalingFactor	= recip $ 2 ^ (13 :: Int),+	Math.Implementations.Pi.BBP.Series.base			= 2 ^ (16 :: Int)+}
+ src-lib/Factory/Math/Implementations/Pi/BBP/Bellard.hs view
@@ -0,0 +1,41 @@+{-+	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 /Bellard/'s nega-base-@2^10@ /BBP/-formula; <http://en.wikipedia.org/wiki/Bellard%27s_formula>+-}++module Factory.Math.Implementations.Pi.BBP.Bellard(+-- * Constants+	series+) where++import			Control.Arrow((&&&))+import qualified	Factory.Math.Implementations.Pi.BBP.Series	as Math.Implementations.Pi.BBP.Series++-- | Defines the parameters of this specific series.+series :: Math.Implementations.Pi.BBP.Series.Series+series	= Math.Implementations.Pi.BBP.Series.MkSeries {+	Math.Implementations.Pi.BBP.Series.numerators		= zipWith ($) [negate, negate, id, negate, negate, negate, id] $ map (2 ^) [5 :: Integer, 0, 8, 6, 2, 2, 0],+	Math.Implementations.Pi.BBP.Series.getDenominators	= \i -> let+		f, t :: Integer+		(f, t)	= (4 *) &&& (10 *) $ fromIntegral i+	in [f + 1, f + 3, t + 1, t + 3, t + 5, t + 7, t + 9],+	Math.Implementations.Pi.BBP.Series.seriesScalingFactor	= recip $ 2 ^ (6 :: Int),+	Math.Implementations.Pi.BBP.Series.base			= negate $ 2 ^ (10 :: Int)+}
+ src-lib/Factory/Math/Implementations/Pi/BBP/Implementation.hs view
@@ -0,0 +1,57 @@+{-+	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@]++	* Implements a /Bailey-Borwein-Plouffe/ formula; <http://mathworld.wolfram.com/PiFormulas.html>++	* Surprisingly, because of the huge size of the 'Rational' quantities,+	it is a /single/ call to @Factory.Math.Summation.sum'@, rather than the calculation of the many terms in the series, which is the performance-bottleneck.+-}++module Factory.Math.Implementations.Pi.BBP.Implementation(+-- * Functions+	openR+) where++import			Data.Ratio((%))+import qualified	Factory.Math.Implementations.Pi.BBP.Series	as Math.Implementations.Pi.BBP.Series+import qualified	Factory.Math.Precision				as Math.Precision+import qualified	Factory.Math.Summation				as Math.Summation++-- | Returns /Pi/, accurate to the specified number of decimal digits.+openR+	:: Math.Implementations.Pi.BBP.Series.Series	-- ^ This /Pi/-algorithm is parameterised by the type of other algorithms to use.+	-> Math.Precision.DecimalDigits			-- ^ The number of decimal digits required.+	-> Rational+openR Math.Implementations.Pi.BBP.Series.MkSeries {+	Math.Implementations.Pi.BBP.Series.numerators		= numerators,+	Math.Implementations.Pi.BBP.Series.getDenominators	= getDenominators,+	Math.Implementations.Pi.BBP.Series.seriesScalingFactor	= seriesScalingFactor,+	Math.Implementations.Pi.BBP.Series.base			= base+} decimalDigits		= (seriesScalingFactor *) . Math.Summation.sum' 8 . take (+	Math.Precision.getTermsRequired (+		recip . fromIntegral $ abs {-potentially negative-} base	-- The convergence-rate.+	) decimalDigits+ ) . zipWith (*) (+	iterate (/ fromIntegral base) 1	-- Generate the scaling-ratio, between successive terms.+ ) $ map (+	sum . zipWith (%) numerators . getDenominators+ ) [0 ..]+
+ src-lib/Factory/Math/Implementations/Pi/BBP/Series.hs view
@@ -0,0 +1,36 @@+{-+	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 a /Bailey-Borwein-Plouffe/ formula; <http://mathworld.wolfram.com/PiFormulas.html>+-}++module Factory.Math.Implementations.Pi.BBP.Series(+-- * Types+-- ** Data-types+	Series(..)+) where++-- | Defines a series corresponding to a specific /BBP/-formula.+data Series	= MkSeries {+	numerators		:: [Integer],		-- ^ The constant numerators from which each term in the series is composed.+	getDenominators		:: Int -> [Integer],	-- ^ Generates the term-dependent denominators from which each term in the series is composed.+	seriesScalingFactor	:: Rational,		-- ^ The ratio by which the sum to infinity of the series, must be scaled to result in /Pi/.+	base			:: Integer		-- ^ The geometric ratio, by which successive terms are scaled.+}+
+ src-lib/Factory/Math/Implementations/Pi/Borwein/Algorithm.hs view
@@ -0,0 +1,56 @@+{-+	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 the set of /Borwein/-type algorithms (currently only one) which have been implemented; <http://www.pi314.net/eng/borwein.php>.+-}++module Factory.Math.Implementations.Pi.Borwein.Algorithm(+-- * Types+-- ** Data-types+	Algorithm(..)+) where++import qualified	Factory.Math.Factorial					as Math.Factorial+import qualified	Factory.Math.Implementations.Pi.Borwein.Borwein1993	as Math.Implementations.Pi.Borwein.Borwein1993+import qualified	Factory.Math.Implementations.Pi.Borwein.Implementation	as Math.Implementations.Pi.Borwein.Implementation+import qualified	Factory.Math.Pi						as Math.Pi+import qualified	Factory.Math.SquareRoot					as Math.SquareRoot+import qualified	ToolShed.Defaultable++{- |+	* Define those /Borwein/-series which have been implemented.++	* Though currently there's only one, provision has been made for the addition of more.+-}+data Algorithm squareRootAlgorithm factorialAlgorithm	=+	Borwein1993 squareRootAlgorithm factorialAlgorithm	-- ^ <http://en.wikipedia.org/wiki/Borwein%27s_algorithm>.+	deriving (Eq, Read, Show)++instance (+	ToolShed.Defaultable.Defaultable	squareRootAlgorithm,+	ToolShed.Defaultable.Defaultable	factorialAlgorithm+ ) => ToolShed.Defaultable.Defaultable (Algorithm squareRootAlgorithm factorialAlgorithm)	where+	defaultValue	= Borwein1993 ToolShed.Defaultable.defaultValue ToolShed.Defaultable.defaultValue++instance (+	Math.SquareRoot.Algorithmic	squareRootAlgorithm,+	Math.Factorial.Algorithmic	factorialAlgorithm+ ) => Math.Pi.Algorithmic (Algorithm squareRootAlgorithm factorialAlgorithm)	where+	openR (Borwein1993 squareRootAlgorithm factorialAlgorithm)	= Math.Implementations.Pi.Borwein.Implementation.openR Math.Implementations.Pi.Borwein.Borwein1993.series squareRootAlgorithm factorialAlgorithm+
+ src-lib/Factory/Math/Implementations/Pi/Borwein/Borwein1993.hs view
@@ -0,0 +1,73 @@+{-+	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 the /Borwein/ series for /Pi/; <http://en.wikipedia.org/wiki/Borwein%27s_algorithm#Jonathan_Borwein_and_Peter_Borwein.27s_Version_.281993.29>+-}++module Factory.Math.Implementations.Pi.Borwein.Borwein1993(+-- * Constants+	series+) where++-- import		Control.Arrow((***))+import			Data.Ratio((%))+-- import		Factory.Data.PrimeFactors((>*<), (>/<), (>^))+-- import qualified	Factory.Data.PrimeFactors			as Data.PrimeFactors+import qualified	Factory.Math.Factorial				as Math.Factorial+import qualified	Factory.Math.Implementations.Factorial		as Math.Implementations.Factorial+import qualified	Factory.Math.Implementations.Pi.Borwein.Series	as Math.Implementations.Pi.Borwein.Series+import qualified	Factory.Math.Power				as Math.Power+import qualified	Factory.Math.Precision				as Math.Precision+import qualified	Factory.Math.SquareRoot				as Math.SquareRoot++-- | Defines the parameters of the /Borwein/ series.+series :: (Math.SquareRoot.Algorithmic squareRootAlgorithm, Math.Factorial.Algorithmic factorialAlgorithm) => Math.Implementations.Pi.Borwein.Series.Series squareRootAlgorithm factorialAlgorithm+series = Math.Implementations.Pi.Borwein.Series.MkSeries {+	Math.Implementations.Pi.Borwein.Series.terms			= \squareRootAlgorithm factorialAlgorithm decimalDigits -> let+		simplify, squareRoot :: Rational -> Rational+		simplify	= Math.Precision.simplify $ pred decimalDigits {-ignore single integral digit-}	-- This makes a gigantic difference to performance.+		squareRoot	= simplify . Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits++		sqrt5, a, b, c3 :: Rational+		sqrt5	= squareRoot 5++		a	= 63365028312971999585426220 + sqrt5 * (28337702140800842046825600 + 384 * squareRoot (10891728551171178200467436212395209160385656017 + 4870929086578810225077338534541688721351255040 * sqrt5))+		b	= 7849910453496627210289749000 + 3510586678260932028965606400 * sqrt5 + 2515968 * squareRoot (3110 * (6260208323789001636993322654444020882161 + 2799650273060444296577206890718825190235 * sqrt5))+		c3	= simplify . Math.Power.cube $ negate 214772995063512240 - sqrt5 * (96049403338648032 + 1296 * squareRoot (10985234579463550323713318473 + 4912746253692362754607395912 * sqrt5))+	in (+		squareRoot $ negate c3,	-- The factor into which the series must be divided, to yield Pi.+		zipWith (+{-+			\n power -> let+				product'	= Data.PrimeFactors.product' (recip 2) 10+			in uncurry (/) . (+				(* (a + b * fromIntegral n)) . fromIntegral . product' *** (* power) . fromIntegral . product'+			) $ Math.Implementations.Factorial.primeFactors (6 * n) >/< (+				Math.Implementations.Factorial.primeFactors (3 * n) >*< Math.Implementations.Factorial.primeFactors n >^ 3+			)+-}+			\n power -> (+				Math.Implementations.Factorial.risingFactorial (succ $ 3 * n) (3 * n) % Math.Power.cube (Math.Factorial.factorial factorialAlgorithm n)+			) * (+				(a + b * fromIntegral n) / power+			)+		) [0 :: Integer ..] $ iterate (* c3) 1+	),+	Math.Implementations.Pi.Borwein.Series.convergenceRate		= 10 ** negate 50	-- Empirical.+}
+ src-lib/Factory/Math/Implementations/Pi/Borwein/Implementation.hs view
@@ -0,0 +1,50 @@+{-+	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 /Borwein/ series for /Pi/; <http://en.wikipedia.org/wiki/Borwein%27s_algorithm>+-}++module Factory.Math.Implementations.Pi.Borwein.Implementation(+-- * Functions+	openR+) where++import qualified	Control.Arrow+import qualified	Control.Parallel.Strategies+import qualified	Factory.Math.Implementations.Pi.Borwein.Series	as Math.Implementations.Pi.Borwein.Series+import qualified	Factory.Math.Precision				as Math.Precision++-- | Returns /Pi/, accurate to the specified number of decimal digits.+openR+	:: Math.Implementations.Pi.Borwein.Series.Series squareRootAlgorithm factorialAlgorithm	-- ^ This /Pi/-algorithm is parameterised by the type of other algorithms to use.+	-> squareRootAlgorithm									-- ^ The specific /square-root/ algorithm to apply to the above series.+	-> factorialAlgorithm									-- ^ The specific /factorial/-algorithm to apply to the above series.+	-> Math.Precision.DecimalDigits								-- ^ The number of decimal digits required.+	-> Rational+openR Math.Implementations.Pi.Borwein.Series.MkSeries {+	Math.Implementations.Pi.Borwein.Series.terms		= terms,+	Math.Implementations.Pi.Borwein.Series.convergenceRate	= convergenceRate+} squareRootAlgorithm factorialAlgorithm decimalDigits	= uncurry (/) . Control.Parallel.Strategies.withStrategy (+		Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq+	) . Control.Arrow.second (+		sum . take (+			Math.Precision.getTermsRequired convergenceRate decimalDigits+		)+	) $ terms squareRootAlgorithm factorialAlgorithm decimalDigits+
+ src-lib/Factory/Math/Implementations/Pi/Borwein/Series.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 a <http://en.wikipedia.org/wiki/Srinivasa_Borwein>-type series for /Pi/.+-}++module Factory.Math.Implementations.Pi.Borwein.Series(+-- * Types+-- ** Data-types+	Series(..)+) where++import qualified	Factory.Math.Precision	as Math.Precision++-- | Defines a series corresponding to a specific /Borwein/-formula.+data Series squareRootAlgorithm factorialAlgorithm	= MkSeries {+	terms+		:: squareRootAlgorithm+		-> factorialAlgorithm+		-> Math.Precision.DecimalDigits+		-> (+			Rational,	-- The factor into which the sum to infinity of the sequence, must be divided to result in /Pi/+			[Rational]	-- The sequence of terms, the sum to infinity of which defines the series.+		),+	convergenceRate :: Math.Precision.ConvergenceRate	-- ^ The expected number of digits of /Pi/, per term in the series.+}+
+ src-lib/Factory/Math/Implementations/Pi/Ramanujan/Algorithm.hs view
@@ -0,0 +1,55 @@+{-+	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 the set of /Ramanujan/-type algorithms which have been implemented; <http://en.wikipedia.org/wiki/Pi>.+-}++module Factory.Math.Implementations.Pi.Ramanujan.Algorithm(+-- * Types+-- ** Data-types+	Algorithm(..)+) where++import qualified	Factory.Math.Factorial						as Math.Factorial+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Chudnovsky		as Math.Implementations.Pi.Ramanujan.Chudnovsky+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Classic		as Math.Implementations.Pi.Ramanujan.Classic+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Implementation	as Math.Implementations.Pi.Ramanujan.Implementation+import qualified	Factory.Math.Pi							as Math.Pi+import qualified	Factory.Math.SquareRoot						as Math.SquareRoot+import qualified	ToolShed.Defaultable++-- | Define those /Ramanujan/-series which have been implemented.+data Algorithm squareRootAlgorithm factorialAlgorithm	=+	Classic squareRootAlgorithm factorialAlgorithm		-- ^ The original version.+	| Chudnovsky squareRootAlgorithm factorialAlgorithm	-- ^ A variant found by the /Chudnovsky brothers/.+	deriving (Eq, Read, Show)++instance (+	ToolShed.Defaultable.Defaultable	squareRootAlgorithm,+	ToolShed.Defaultable.Defaultable	factorialAlgorithm+ ) => ToolShed.Defaultable.Defaultable (Algorithm squareRootAlgorithm factorialAlgorithm)	where+	defaultValue	= Chudnovsky ToolShed.Defaultable.defaultValue ToolShed.Defaultable.defaultValue++instance (+	Math.SquareRoot.Algorithmic	squareRootAlgorithm,+	Math.Factorial.Algorithmic	factorialAlgorithm+ ) => Math.Pi.Algorithmic (Algorithm squareRootAlgorithm factorialAlgorithm)	where+	openR (Classic squareRootAlgorithm factorialAlgorithm)		= Math.Implementations.Pi.Ramanujan.Implementation.openR Math.Implementations.Pi.Ramanujan.Classic.series squareRootAlgorithm factorialAlgorithm+	openR (Chudnovsky squareRootAlgorithm factorialAlgorithm)	= Math.Implementations.Pi.Ramanujan.Implementation.openR Math.Implementations.Pi.Ramanujan.Chudnovsky.series squareRootAlgorithm factorialAlgorithm+
+ src-lib/Factory/Math/Implementations/Pi/Ramanujan/Chudnovsky.hs view
@@ -0,0 +1,63 @@+{-+	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 the /Chudnovsky/ series for /Pi/; <http://en.wikipedia.org/wiki/Pi>.+-}++module Factory.Math.Implementations.Pi.Ramanujan.Chudnovsky(+-- * Constants+	series+) where++-- import		Control.Arrow((***))+import			Data.Ratio((%))+-- import		Factory.Data.PrimeFactors((>/<), (>*<), (>^))+-- import qualified	Factory.Data.PrimeFactors				as Data.PrimeFactors+import qualified	Factory.Math.Factorial					as Math.Factorial+import qualified	Factory.Math.Implementations.Factorial			as Math.Implementations.Factorial+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Series	as Math.Implementations.Pi.Ramanujan.Series+import qualified	Factory.Math.Power					as Math.Power+import qualified	Factory.Math.SquareRoot					as Math.SquareRoot++-- | Defines the parameters of the /Chudnovsky/ series.+series :: (+	Math.SquareRoot.Algorithmic	squareRootAlgorithm,+	Math.Factorial.Algorithmic	factorialAlgorithm+ ) => Math.Implementations.Pi.Ramanujan.Series.Series squareRootAlgorithm factorialAlgorithm+series = Math.Implementations.Pi.Ramanujan.Series.MkSeries {+	Math.Implementations.Pi.Ramanujan.Series.terms			= \factorialAlgorithm -> zipWith (+{-+		\n power -> let+			product'	= Data.PrimeFactors.product' (recip 2) 10+		in uncurry (%) . (+			(* (13591409 + 545140134 * n)) . product' *** (* power) . product'+		) $ Math.Implementations.Factorial.primeFactors (6 * n) >/< (+			Math.Implementations.Factorial.primeFactors (3 * n) >*< Math.Implementations.Factorial.primeFactors n >^ 3+		)+-}+		\n power -> (+			Math.Implementations.Factorial.risingFactorial (succ $ 3 * n) (3 * n) % Math.Power.cube (Math.Factorial.factorial factorialAlgorithm n)+		) * (+			(13591409 + 545140134 * n) % power+		) -- CAVEAT: the order in which these terms are evaluated radically affects performance.+	) [0 ..] $ iterate (* (Math.Power.cube $ negate 640320 :: Integer)) 1,+	Math.Implementations.Pi.Ramanujan.Series.getSeriesScalingFactor	= \squareRootAlgorithm decimalDigits -> 426880 * Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits (10005 :: Integer),+	Math.Implementations.Pi.Ramanujan.Series.convergenceRate	= 10 ** negate 14.0	-- Empirical.+}+
+ src-lib/Factory/Math/Implementations/Pi/Ramanujan/Classic.hs view
@@ -0,0 +1,60 @@+{-+	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 the /Ramanujan/ series for /Pi/; <http://planetmath.org/encyclopedia/RamanujansFormulaForPi.html>.+-}++module Factory.Math.Implementations.Pi.Ramanujan.Classic(+-- * Constants+	series+) where++-- import		Control.Arrow((***))+import			Data.Ratio((%))+-- import		Factory.Data.PrimeFactors((>/<), (>^))+-- import qualified	Factory.Data.PrimeFactors				as Data.PrimeFactors+import qualified	Factory.Math.Factorial					as Math.Factorial+import qualified	Factory.Math.Implementations.Factorial			as Math.Implementations.Factorial+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Series	as Math.Implementations.Pi.Ramanujan.Series+import qualified	Factory.Math.Power					as Math.Power+import qualified	Factory.Math.SquareRoot					as Math.SquareRoot++-- | Defines the parameters of the /Ramanujan/ series.+series :: (Math.SquareRoot.Algorithmic squareRootAlgorithm, Math.Factorial.Algorithmic factorialAlgorithm) => Math.Implementations.Pi.Ramanujan.Series.Series squareRootAlgorithm factorialAlgorithm+series = Math.Implementations.Pi.Ramanujan.Series.MkSeries {+	Math.Implementations.Pi.Ramanujan.Series.terms			= \factorialAlgorithm -> let+		toFourthPower	= (^ (4 :: Int))+	in zipWith (+{-+		\n power -> let+			product'	= Data.PrimeFactors.product' (recip 2) 10+		in uncurry (%) . (+			(* (1103 + 26390 * n)) . product' *** (* power) . product'+		) $ Math.Implementations.Factorial.primeFactors (4 * n) >/< Math.Implementations.Factorial.primeFactors n >^ 4+-}+		\n power -> (+			Math.Implementations.Factorial.risingFactorial (succ n) (3 * n) % Math.Power.cube (Math.Factorial.factorial factorialAlgorithm n)+		) * (+			(1103 + 26390 * n) % power+		) -- CAVEAT: the order in which these terms are evaluated radically affects performance.+	) [0 ..] $ iterate (* toFourthPower 396) 1,+	Math.Implementations.Pi.Ramanujan.Series.getSeriesScalingFactor	= \squareRootAlgorithm decimalDigits -> 9801 / Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits (8 :: Integer),+	Math.Implementations.Pi.Ramanujan.Series.convergenceRate	= 10 ** negate 7.9	-- Empirical.+}+
+ src-lib/Factory/Math/Implementations/Pi/Ramanujan/Implementation.hs view
@@ -0,0 +1,52 @@+{-+	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@]	Implements a /Ramanujan/-type series for /Pi/; <http://en.wikipedia.org/wiki/Srinivasa_Ramanujan>.+-}++module Factory.Math.Implementations.Pi.Ramanujan.Implementation(+-- * Functions+	openR+) where++import qualified	Control.Parallel.Strategies+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Series	as Math.Implementations.Pi.Ramanujan.Series+import qualified	Factory.Math.Precision					as Math.Precision+import qualified	Factory.Math.Summation					as Math.Summation++-- | Returns /Pi/, accurate to the specified number of decimal digits.+openR+	:: Math.Implementations.Pi.Ramanujan.Series.Series squareRootAlgorithm factorialAlgorithm	-- ^ This /Pi/-algorithm is parameterised by the type of other algorithms to use.+	-> squareRootAlgorithm										-- ^ The specific /square-root/ algorithm to apply to the above series.+	-> factorialAlgorithm										-- ^ The specific /factorial/-algorithm to apply to the above series.+	-> Math.Precision.DecimalDigits									-- ^ The number of decimal digits required.+	-> Rational+openR Math.Implementations.Pi.Ramanujan.Series.MkSeries {+	Math.Implementations.Pi.Ramanujan.Series.terms			= terms,+	Math.Implementations.Pi.Ramanujan.Series.getSeriesScalingFactor	= getSeriesScalingFactor,+	Math.Implementations.Pi.Ramanujan.Series.convergenceRate	= convergenceRate+} squareRootAlgorithm factorialAlgorithm decimalDigits	= uncurry (/) $ Control.Parallel.Strategies.withStrategy (+		Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq+	) (+		getSeriesScalingFactor squareRootAlgorithm decimalDigits,+		Math.Summation.sumR 64 . take (+			Math.Precision.getTermsRequired convergenceRate decimalDigits+		) $ terms factorialAlgorithm+	) -- Pair.+
+ src-lib/Factory/Math/Implementations/Pi/Ramanujan/Series.hs view
@@ -0,0 +1,37 @@+{-+	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 a <http://en.wikipedia.org/wiki/Srinivasa_Ramanujan>-type series for /Pi/.+-}++module Factory.Math.Implementations.Pi.Ramanujan.Series(+-- * Types+-- ** Data-types+	Series(..)+) where++import qualified	Factory.Math.Precision	as Math.Precision++-- | Defines a series corresponding to a specific /Ramanujan/-formula.+data Series squareRootAlgorithm factorialAlgorithm	= MkSeries {+	terms			:: factorialAlgorithm -> [Rational],					-- ^ The sequence of terms, the sum to infinity of which defines the series.+	getSeriesScalingFactor	:: squareRootAlgorithm -> Math.Precision.DecimalDigits -> Rational,	-- ^ The ratio by which the sum to infinity of the sequence, must be scaled to result in /Pi/.+	convergenceRate		:: Math.Precision.ConvergenceRate					-- ^ The expected number of digits of /Pi/, per term in the series.+}+
+ src-lib/Factory/Math/Implementations/Pi/Spigot/Algorithm.hs view
@@ -0,0 +1,50 @@+{-+	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 the set of /Spigot/-algorithms which have been implemented.+-}++module Factory.Math.Implementations.Pi.Spigot.Algorithm(+-- * Types+-- ** Data-types+	Algorithm(..)+) where++import			Data.Ratio((%))+import qualified	Factory.Math.Implementations.Pi.Spigot.Gosper		as Math.Implementations.Pi.Spigot.Gosper+import qualified	Factory.Math.Implementations.Pi.Spigot.RabinowitzWagon	as Math.Implementations.Pi.Spigot.RabinowitzWagon+import qualified	Factory.Math.Implementations.Pi.Spigot.Spigot		as Math.Implementations.Pi.Spigot.Spigot+import qualified	Factory.Math.Pi						as Math.Pi+import qualified	ToolShed.Defaultable++-- | Define those /Spigot/-algorithms which have been implemented.+data Algorithm	=+	Gosper			-- ^ A /continued fraction/ discovered by /Gosper/.+	| RabinowitzWagon	-- ^ A /continued fraction/ discovered by /Rabinowitz/ and /Wagon/.+	deriving (Eq, Read, Show)++instance ToolShed.Defaultable.Defaultable Algorithm	where+	defaultValue	= Gosper++instance Math.Pi.Algorithmic Algorithm	where+	openI Gosper			= Math.Implementations.Pi.Spigot.Spigot.openI Math.Implementations.Pi.Spigot.Gosper.series+	openI RabinowitzWagon		= Math.Implementations.Pi.Spigot.Spigot.openI Math.Implementations.Pi.Spigot.RabinowitzWagon.series++	openR algorithm decimalDigits	= Math.Pi.openI algorithm decimalDigits % (10 ^ pred decimalDigits)+
+ src-lib/Factory/Math/Implementations/Pi/Spigot/Gosper.hs view
@@ -0,0 +1,39 @@+{-+	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 the /Gosper/ series; <http://www.pi314.net/eng/goutte.php>+-}++module Factory.Math.Implementations.Pi.Spigot.Gosper(+-- * Constants+	series+) where++import qualified	Factory.Math.Implementations.Pi.Spigot.Series	as Math.Implementations.Pi.Spigot.Series+import qualified	Factory.Math.Precision				as Math.Precision++-- | Defines a series which converges to /Pi/.+series :: Integral i => Math.Implementations.Pi.Spigot.Series.Series i+series	= Math.Implementations.Pi.Spigot.Series.MkSeries {+	Math.Implementations.Pi.Spigot.Series.baseNumerators	= map (\i -> i * pred (2 * i)) [1 ..],+	Math.Implementations.Pi.Spigot.Series.baseDenominators	= map ((* 3) . (\i -> succ i * (i + 2))) [3, 6 ..],+	Math.Implementations.Pi.Spigot.Series.coefficients	= [3, 8 ..],	-- 5n - 2+	Math.Implementations.Pi.Spigot.Series.nTerms		= Math.Precision.getTermsRequired $ 1 / 13 {-empirical convergence-rate-}+}+
+ src-lib/Factory/Math/Implementations/Pi/Spigot/RabinowitzWagon.hs view
@@ -0,0 +1,40 @@+{-+	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 the /Rabinowitz-Wagon/ series;+	<http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/spigot.pdf>+	<http://www.mathpropress.com/stan/bibliography/spigot.pdf>.+-}++module Factory.Math.Implementations.Pi.Spigot.RabinowitzWagon(+-- * Constants+	series+) where++import qualified	Factory.Math.Implementations.Pi.Spigot.Series	as Math.Implementations.Pi.Spigot.Series+import qualified	Factory.Math.Precision				as Math.Precision++-- | Defines a series which converges to /Pi/.+series :: Integral i => Math.Implementations.Pi.Spigot.Series.Series i+series	= Math.Implementations.Pi.Spigot.Series.MkSeries {+	Math.Implementations.Pi.Spigot.Series.baseNumerators	= [1 ..],+	Math.Implementations.Pi.Spigot.Series.baseDenominators	= [3, 5 ..],+	Math.Implementations.Pi.Spigot.Series.coefficients	= repeat 2,+	Math.Implementations.Pi.Spigot.Series.nTerms		= Math.Precision.getTermsRequired $ 10 ** negate (3 / 10) {-convergence-rate-}+}
+ src-lib/Factory/Math/Implementations/Pi/Spigot/Series.hs view
@@ -0,0 +1,53 @@+{-+	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 the parameters of a series used in a /Spigot/-table to generate /Pi/.+-}++module Factory.Math.Implementations.Pi.Spigot.Series(+-- * Types+-- ** Data-types+	Series(..),+-- * Functions+	bases+) where++import			Data.Ratio((%))+import qualified	Data.Ratio+import qualified	Factory.Math.Precision	as Math.Precision++{- |+	* Defines a series composed from a sum of terms, each one of which is the product of a coefficient and a base.++	* The coefficents and bases of the series are described in /Horner form/; @Pi = c1 + (b1 * (c2 + b2 * (c3 + b3 * (...))))@.+-}+data Series i	= MkSeries {+	coefficients		:: [i],+	baseNumerators		:: [i],+	baseDenominators	:: [i],+	nTerms			:: Math.Precision.DecimalDigits -> Int	-- ^ The width of the spigot-table, required to accurately generate the requested number of digits.+}++-- | Combines 'baseNumerators' and 'baseDenominators', and as a side-effect, expresses the ratio in lowest terms.+bases :: Integral i => Series i -> [Data.Ratio.Ratio i]+bases MkSeries {+	baseNumerators		= n,+	baseDenominators	= d+} = zipWith (%) n d+
+ src-lib/Factory/Math/Implementations/Pi/Spigot/Spigot.hs view
@@ -0,0 +1,153 @@+{-+	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@]++	* Implements a /spigot/-algorithm; <http://en.wikipedia.org/wiki/Spigot_algorithm>.++	* Uses the traditional algorithm, rather than the /unbounded/ algorithm described by <http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf>.+-}++module Factory.Math.Implementations.Pi.Spigot.Spigot(+-- * Types+-- ** Type-synonyms+--	Base,+--	Coefficients,+--	I,+--	Pi,+--	PreDigits,+--	QuotRem,+-- * Constants+	decimal,+-- * Functions+--	carryAndDivide,+--	processColumns,+	openI,+-- ** Accessors+--	getQuotient,+--	getRemainder,+-- ** Constructors+--	mkRow+) where++import qualified	Control.Arrow+import qualified	Data.Char+import qualified	Data.Ratio+import qualified	Factory.Math.Implementations.Pi.Spigot.Series	as Math.Implementations.Pi.Spigot.Series+import qualified	Factory.Math.Precision				as Math.Precision++{- |+	* The type in which all arithmetic is performed.++	* A small dynamic range, 32 bits or more, is typically adequate.+-}+type I	= Int++-- | The constant base in which we want the resulting value of /Pi/ to be expressed.+decimal :: I+decimal	= 10++-- | Coerce the polymorphic type 'Data.Ratio.Ratio' to suit the base used in our series.+type Base	= Data.Ratio.Ratio I++-- | Coerce the polymorphic type returned by 'quotRem' to our specific requirements.+type QuotRem	= (I, I)++-- Accessors.+getQuotient, getRemainder :: QuotRem -> I+getQuotient	= fst+getRemainder	= snd++type PreDigits		= [I]+type Pi			= [I]+type Coefficients	= [I]++{- |+	* For a digit on one row of the spigot-table, add any numerator carried from the similar calculation one column to the right.++	* Divide the result of this summation, by the denominator of the base, to get the quotient and remainder.++	* Determine the quantity to carry to the similar calculation one column to the left, by multiplying the quotient by the numerator of the base.+-}+carryAndDivide :: (Base, I) -> QuotRem -> QuotRem+carryAndDivide (base, lhs) rhs+	| n < d		= (0, n)	-- In some degenerate cases, the result of the subsequent calculation can be more simply determined.+	| otherwise	= Control.Arrow.first (* Data.Ratio.numerator base) $ n `quotRem` d+	where+		d, n :: I+		d	= Data.Ratio.denominator base+		n	= lhs + getQuotient rhs	-- Carry numerator from the column to the right and add it to the current digit.++{- |+	* Fold 'carryAndDivide', from right to left, over the columns of a row in the spigot-table, continuously checking for overflow.++	* Release any previously withheld result-digits, after any adjustment for overflow in the current result-digit.++	* Withhold the current result-digit until the risk of overflow in subsequent result-digits has been assessed.++	* Call 'mkRow'.+-}+processColumns+	:: Math.Implementations.Pi.Spigot.Series.Series I+	-> PreDigits+	-> [(Base, I)]	-- ^ Data-row.+	-> Pi+processColumns series preDigits l+	| overflowMargin > 1	= preDigits ++ nextRow [digit]				-- There's neither overflow, nor risk of impact from subsequent overflow.+	| overflowMargin == 1	= nextRow $ preDigits ++ [digit]			-- There's no overflow, but risk of impact from subsequent overflow.+	| otherwise		= map ((`rem` decimal) . succ) preDigits ++ nextRow [0]	-- Overflow => propagate the excess to previously withheld preDigits.+	where+		results :: [QuotRem]+		results	= init $ scanr carryAndDivide (0, undefined) l++		digit :: I+		digit	= getQuotient $ head results++		overflowMargin :: I+		overflowMargin	= decimal - digit++		nextRow :: [I] -> [I]+		nextRow preDigits'	= mkRow series preDigits' $ map getRemainder results++{- |+	* Multiply the remainders from the previous row.++	* Zip them with the constant bases, with an addition one stuck on the front to perform the conversion to decimal, to create a new row of the spigot-table.++	* Call 'processColumns'.+-}+mkRow :: Math.Implementations.Pi.Spigot.Series.Series I -> PreDigits -> Coefficients -> Pi+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'.++	* Ensures that the row has suffient terms to accurately generate the required number of digits.++	* Extracts only those digits which are guaranteed to be accurate.++	* CAVEAT: the result is returned as an 'Integer', i.e. without any decimal point.+-}+openI :: Math.Implementations.Pi.Spigot.Series.Series I -> Math.Precision.DecimalDigits -> Integer+openI series decimalDigits	= read . map (+	Data.Char.intToDigit . fromIntegral+ ) . take decimalDigits . mkRow series [] . take (+	Math.Implementations.Pi.Spigot.Series.nTerms series decimalDigits+ ) $ Math.Implementations.Pi.Spigot.Series.coefficients series+
+ src-lib/Factory/Math/Implementations/Primality.hs view
@@ -0,0 +1,217 @@+{-+	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@]++	* Determines whether an integer is prime.++	* <http://en.wikipedia.org/wiki/Primality_test>.++	* <http://primes.utm.edu/index.html>++	* CAVEAT: it doesn't determine the prime-factors of composite numbers, just that they exist.+-}++module Factory.Math.Implementations.Primality(+-- * Types+-- ** Data-types+	Algorithm(..)+-- * Functions+-- ** Predicates+--	isPrimeByAKS,+--	isPrimeByMillerRabin,+--	witnessesCompositeness+) where++import			Control.Arrow((&&&))+import qualified	Control.DeepSeq+import qualified	Control.Parallel.Strategies+import qualified	Data.Numbers.Primes+import qualified	Factory.Data.MonicPolynomial		as Data.MonicPolynomial+import qualified	Factory.Data.Polynomial			as Data.Polynomial+import qualified	Factory.Data.QuotientRing		as Data.QuotientRing+import qualified	Factory.Math.MultiplicativeOrder	as Math.MultiplicativeOrder+import qualified	Factory.Math.PerfectPower		as Math.PerfectPower+import qualified	Factory.Math.Power			as Math.Power+import qualified	Factory.Math.Primality			as Math.Primality+import qualified	Factory.Math.PrimeFactorisation		as Math.PrimeFactorisation+import qualified	ToolShed.Defaultable++-- | The algorithms by which /primality/-testing has been implemented.+data Algorithm factorisationAlgorithm	=+	AKS factorisationAlgorithm	-- ^ <http://en.wikipedia.org/wiki/AKS_primality_test>.+	| MillerRabin			-- ^ <http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test>.+	deriving (Eq, Read, Show)++instance ToolShed.Defaultable.Defaultable (Algorithm factorisationAlgorithm)	where+	defaultValue	= MillerRabin++instance Math.PrimeFactorisation.Algorithmic factorisationAlgorithm => Math.Primality.Algorithmic (Algorithm factorisationAlgorithm)	where+	isPrime _ 2	= True	-- The only even prime.+	isPrime algorithm candidate+		| candidate < 2 || (+			any (+				(== 0) . (candidate `rem`)			-- The candidate has a small prime-factor, and is therefore composite.+			) . filter (+				(candidate >=) . (* 2)				-- The candidate must be at least double the small prime, for it to be a potential factor.+			) . take 5 {-arbitrarily-} $ Data.Numbers.Primes.primes	-- Excludes even numbers, provided at least the 1st prime is tested.+		)		= False+		| otherwise	= (+			case algorithm of+				AKS factorisationAlgorithm	-> isPrimeByAKS factorisationAlgorithm+				MillerRabin			-> isPrimeByMillerRabin+		) candidate++{- |+	* An implementation of the /Agrawal-Kayal-Saxena/ primality-test; <http://en.wikipedia.org/wiki/AKS_primality_test>,+	using the /Lenstra/ and /Pomerance/ algorithm.++	* CAVEAT: this deterministic algorithm has a theoretical time-complexity of @O(log^6)@,+	and therefore can't compete with the performance of probabilistic ones.++	* The /formal polynomials/ used in this algorithm, are conceptually different from /polynomial functions/;+	the /indeterminate/ and its powers, are merely used to name a sequence of pigeon-holes in which /coefficients/ are stored,+	and is never substituted for a specific value.+	This mind-shift, allows one to introduce concepts like /modular/ arithmetic on polynomials,+	which merely represent an operation on their coefficients and the pigeon-hole in which they're placed.++	[@Manindra Agrawal, Neeraj Kayal and Nitin Saxena@]	<http://www.cse.iitk.ac.in/users/manindra/algebra/primality_v6.pdf>.++	[@H. W. Lenstra, Jr. and Carl Pomerance@]		<http://www.math.dartmouth.edu/~carlp/PDF/complexity12.pdf>.++	[@Salembier and Southerington@]				<http://ece.gmu.edu/courses/ECE746/project/F06_Project_resources/Salembier_Southerington_AKS.pdf>,++	[@R. Crandall and J. Papadopoulos@]			<http://images.apple.com/acg/pdf/aks3.pdf>,++	[@Andreas Klappenecker@]				<http://faculty.cs.tamu.edu/klappi/629/aks.ps>,++	[@Vibhor Bhatt and G. K. Patra@]			<http://www.cmmacs.ernet.in/cmmacs/Publications/resch_rep/rrcm0307.pdf>,+-}+isPrimeByAKS :: (+	Control.DeepSeq.NFData			i,+	Integral				i,+	Math.PrimeFactorisation.Algorithmic	factorisationAlgorithm,+	Show					i+ ) => factorisationAlgorithm -> i -> Bool+isPrimeByAKS factorisationAlgorithm n	= and [+	not $ Math.PerfectPower.isPerfectPower n,	-- Step 1.+	Math.Primality.areCoprime n `all` filter (/= n) [2 .. r],	-- Step 3.+	and $ Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rdeepseq	{-Benefits from '+RTS -H100M', which reduces garbage-collections-} (+		\a	-> let+--			lhs, rhs :: Data.Polynomial.Polynomial i i+			lhs	= Data.Polynomial.raiseModulo (Data.Polynomial.mkLinear 1 a) n {-power-} n {-modulus-}+			rhs	= Data.Polynomial.mod' (Data.Polynomial.mkPolynomial [(1, n), (a, 0)]) n+		in Data.QuotientRing.areCongruentModulo (+			Data.MonicPolynomial.mkMonicPolynomial lhs+		) (+			Data.MonicPolynomial.mkMonicPolynomial rhs+		) (+			Data.MonicPolynomial.mkMonicPolynomial modulus+		) -- Because all these polynomials are /monic/, one can establish /congruence/ using /integer/-division.+	) [+		1 .. floor . (* lg) . sqrt $ fromIntegral r+	] -- Step 4; (x + a)^n ~ x^n + a mod (x^r - 1, n).+ ] where+	lg :: Double+	lg	= logBase 2 $ fromIntegral n++--	r :: i+	r	= fst . head . dropWhile (+		(<= floor (Math.Power.square lg)) . snd+	 ) . map (+		id &&& Math.MultiplicativeOrder.multiplicativeOrder factorisationAlgorithm n+	 ) $ Math.Primality.areCoprime n `filter` [2 ..]	-- Step 2.++--	modulus :: Data.Polynomial.Polynomial i i+	modulus	= Data.Polynomial.mkPolynomial [(1, r), (negate 1, 0)]++{- |+	* Uses the specified 'base' in an attempt to prove the /compositeness/ of an integer.++	* This is the opposite of the /Miller Test/; <http://mathworld.wolfram.com/MillersPrimalityTest.html>.++	* If the result is 'True', then the candidate is /composite/; regrettably the converse isn't true.+	Amongst the set of possible bases, over three-quarters are /witnesses/ to the compositeness of a /composite/ candidate,+	the remainder belong to the subset of /liars/.+	In consequence, many false results must be accumulated for different bases, to convincingly identify a prime.+-}+witnessesCompositeness :: (Integral i, Show i)+	=> i	-- ^ Candidate integer.+	-> i+	-> Int+	-> i	-- ^ Base.+	-> Bool+witnessesCompositeness candidate oddRemainder nPowersOfTwo base	= all (+	$ ((`rem` candidate) . Math.Power.square) `iterate` Math.Power.raiseModulo base oddRemainder candidate	-- Repeatedly modulo-square.+ ) [+	(/= 1) . head,					-- Check whether the zeroeth modulo-power is incongruent to one.+	notElem (pred candidate) . take nPowersOfTwo	-- Check whether any modulo-power is incongruent to -1.+ ]++{- |+	* Repeatedly calls 'witnessesCompositeness', to progressively increase the probability of detecting a /composite/ number,+	until ultimately the candidate integer is proven to be prime.++	* Should all bases be tested, then the test is deterministic, but at an efficiency /lower/ than performing prime-factorisation.++	* The test becomes deterministic, for any candidate integer, when the number of tests reaches the limit defined by /Eric Bach/.++	* A testing of smaller set of bases, is sufficient for candidates smaller than various thresholds; <http://primes.utm.edu/prove/prove2_3.html>.++	* <http://en.wikipedia.org/wiki/Miller-Rabin_primality_test>.++	* <http://mathworld.wolfram.com/Rabin-MillerStrongPseudoprimeTest.html>++	* <http://mathworld.wolfram.com/StrongPseudoprime.html>.++	* <http://oeis.org/A014233>, <http://oeis.org/A006945>.+-}+isPrimeByMillerRabin :: (Integral i, Show i) => i -> Bool+isPrimeByMillerRabin primeCandidate	= not $ witnessesCompositeness primeCandidate (+	fst $ last binaryFactors	-- Odd-remainder.+ ) (+	length binaryFactors	-- The number of times that 'two' can be factored-out from 'predecessor'.+ ) `any` testBases	where+	predecessor	= pred primeCandidate+	binaryFactors	= takeWhile ((== 0) . snd) . tail {-drop the original-} $ iterate ((`quotRem` 2) . fst) (predecessor, 0)	-- Factor-out powers of two.+	testBases+		| null fewestPrimeBases	= let+			millersTestSet	= floor . (* 2 {-Eric Bach-}) . Math.Power.square . toRational {-avoid premature rounding-} $ log (fromIntegral primeCandidate :: Double {-overflows at 10^851-})+		in [2 .. predecessor `min` millersTestSet]+		| otherwise		= head fewestPrimeBases `take` Data.Numbers.Primes.primes+		where+			fewestPrimeBases	= map fst $ dropWhile ((primeCandidate >=) . snd) [+				(0,	9),			-- All odd integers less this, are prime, and require no further verification.+				(1,	2047),+				(2,	1373653),+				(3,	25326001),+				(4,	3215031751),+				(5,	2152302898747),		-- Jaeschke ...+				(6,	3474749660383),+				(8,	341550071728321),+				(11,	3825123056546413051),	-- Zhang ...+				(12,	318665857834031151167461),+				(13,	3317044064679887385961981),+				(14,	6003094289670105800312596501),+				(15,	59276361075595573263446330101),+				(17,	564132928021909221014087501701),+				(19,	1543267864443420616877677640751301),+				(20,	10 ^ (36 :: Int))	-- At least.+			 ]+
+ src-lib/Factory/Math/Implementations/PrimeFactorisation.hs view
@@ -0,0 +1,145 @@+{-+	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@]++	* Implements several different prime-factorisation algorithms.++	* <http://www.tug.org/texinfohtml/coreutils.html#factor-invocation>.+-}++module Factory.Math.Implementations.PrimeFactorisation(+-- * Types+-- ** Data-types+	Algorithm(+--		DixonsMethod,+		FermatsMethod,+		TrialDivision+	)+-- * Functions+--	factoriseByDixonsMethod+--	factoriseByFermatsMethod+--	factoriseByTrialDivision+) where++import			Control.Arrow((&&&))+import qualified	Control.Arrow+import qualified	Control.DeepSeq+import qualified	Control.Parallel.Strategies+import qualified	Data.Maybe+import qualified	Data.Numbers.Primes+import qualified	Factory.Data.Exponential	as Data.Exponential+import			Factory.Data.Exponential((<^))+import qualified	Factory.Data.PrimeFactors	as Data.PrimeFactors+import qualified	Factory.Math.PerfectPower	as Math.PerfectPower+import qualified	Factory.Math.Power		as Math.Power+import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation+import qualified	ToolShed.Data.Pair+import qualified	ToolShed.Defaultable++-- | The algorithms by which prime-factorisation has been implemented.+data Algorithm+	= DixonsMethod	-- ^ <http://en.wikipedia.org/wiki/Dixon%27s_factorization_method>.+	| FermatsMethod	-- ^ <http://en.wikipedia.org/wiki/Fermat%27s_factorization_method>.+	| TrialDivision	-- ^ <http://en.wikipedia.org/wiki/Trial_division>.+	deriving (Eq, Read, Show)++instance ToolShed.Defaultable.Defaultable Algorithm	where+	defaultValue	= TrialDivision++instance Math.PrimeFactorisation.Algorithmic Algorithm	where+	primeFactors algorithm	= case algorithm of+		DixonsMethod	-> factoriseByDixonsMethod+		FermatsMethod	-> Data.PrimeFactors.reduce . factoriseByFermatsMethod+		TrialDivision	-> factoriseByTrialDivision++-- | <http://en.wikipedia.org/wiki/Dixon%27s_factorization_method>.+factoriseByDixonsMethod :: Integral base => base -> Data.PrimeFactors.Factors base exponent+factoriseByDixonsMethod	= undefined++{- |+	* <http://en.wikipedia.org/wiki/Fermat%27s_factorization_method>.++	* <http://mathworld.wolfram.com/FermatsFactorizationMethod.html>.++	* <http://en.wikipedia.org/wiki/Congruence_of_squares>.++	*	@i = f1 * f2@							Assume a non-trivial factorisation, ie. one in which both factors exceed one.+	=>	@i = (larger + smaller) * (larger - smaller)@			Represent the co-factors as a sum and difference.+	=>	@i = larger^2 - smaller^2@					Which has an integral solution if @i@ is neither /even/ nor a /perfect square/.+	=>	@sqrt (larger^2 - i) = smaller@					Search for /larger/, which results in an integral value for /smaller/.++	* Given that the smaller factor /f2/, can't be less than 3 (/i/ isn't /even/), then the larger /f1/, can't be greater than @(i `div` 3)@.+	So:	@(f2 >= 3) && (f1 <= i `div` 3)@				Two equations which can be used to solve for /larger/.+	=>	@(larger - smaller >= 3) && (larger + smaller <= i `div` 3)@	Add these to eliminate /smaller/.+	=>	@larger <= (i + 9) `div` 6@					The upper bound of the search-space.++	* This algorithm works best when there's a factor close to the /square-root/.+-}+factoriseByFermatsMethod :: (+	Control.DeepSeq.NFData	base,+	Control.DeepSeq.NFData	exponent,+	Integral		base,+	Num			exponent+ ) => base -> Data.PrimeFactors.Factors base exponent+factoriseByFermatsMethod i+	| i <= 3				= [Data.Exponential.rightIdentity i]+	| even i				= Data.Exponential.rightIdentity 2 : factoriseByFermatsMethod (i `div` 2) {-recurse-}+	| Data.Maybe.isJust maybeSquareNumber	= (<^ 2) `map` factoriseByFermatsMethod (Data.Maybe.fromJust maybeSquareNumber) {-recurse-}+	| null factors				= [Data.Exponential.rightIdentity i]	-- Prime.+	| otherwise				= uncurry (++) . Control.Parallel.Strategies.withStrategy (+		Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq	-- CAVEAT: unproductive on the size of integers tested so far.+	) . ToolShed.Data.Pair.mirror factoriseByFermatsMethod $ head factors+	where+--		maybeSquareNumber :: Integral i => Maybe i+		maybeSquareNumber	= Math.PerfectPower.maybeSquareNumber i++--		factors :: Integral i => [i]+		factors	= map (+			(+				uncurry (+) &&& uncurry (-)	-- Construct the co-factors as the sum and difference of /larger/ and /smaller/.+			) . Control.Arrow.second Data.Maybe.fromJust+		 ) . filter (+			Data.Maybe.isJust . snd	-- Search for a perfect square.+		 ) . map (+			Control.Arrow.second $ Math.PerfectPower.maybeSquareNumber {-hotspot-} . (+ negate i)	-- Associate the corresponding value of /smaller/.+		 ) . takeWhile (+			(<= (i + 9) `div` 6) . fst	-- Terminate the search at the maximum value of /larger/.+		 ) . Math.Power.squaresFrom {-hotspot-} . ceiling $ sqrt (fromIntegral i :: Double)	-- Start the search at the minimum value of /larger/.++{- |+	* Decomposes the specified integer, into a product of /prime/-factors,+	using <http://mathworld.wolfram.com/DirectSearchFactorization.html>, AKA <http://en.wikipedia.org/wiki/Trial_division>.++	* This works best when the factors are small.+-}+factoriseByTrialDivision :: (Integral base, Num exponent) => base -> Data.PrimeFactors.Factors base exponent+factoriseByTrialDivision	= slave Data.Numbers.Primes.primes where+	slave primes i+		| null primeCandidates	= [Data.Exponential.rightIdentity i]+		| otherwise		= Data.Exponential.rightIdentity lowestPrimeFactor `Data.PrimeFactors.insert'` slave primeCandidates (i `quot` lowestPrimeFactor)+		where+			primeCandidates	= dropWhile (+				(/= 0) . (i `rem`)+			 ) $ takeWhile (+				<= Math.PrimeFactorisation.maxBoundPrimeFactor i+			 ) primes++			lowestPrimeFactor	= head primeCandidates+
+ src-lib/Factory/Math/Implementations/Primes/Algorithm.hs view
@@ -0,0 +1,63 @@+{-+	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@]++	* Generates the constant list of /prime-numbers/, by a variety of different algorithms.++	* <http://www.haskell.org/haskellwiki/Prime_numbers>.++	* <http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.31.3936&rep=rep1&type=pdf>.++	* <http://larc.unt.edu/ian/pubs/sieve.pdf>.+-}++module Factory.Math.Implementations.Primes.Algorithm(+-- * Types+-- ** Data-types+	Algorithm(..)+) where++import qualified	Data.Numbers.Primes+import qualified	Factory.Data.PrimeWheel					as Data.PrimeWheel+import qualified	Factory.Math.Implementations.Primes.SieveOfAtkin	as Math.Implementations.Primes.SieveOfAtkin+import qualified	Factory.Math.Implementations.Primes.SieveOfEratosthenes	as Math.Implementations.Primes.SieveOfEratosthenes+import qualified	Factory.Math.Implementations.Primes.TrialDivision	as Math.Implementations.Primes.TrialDivision+import qualified	Factory.Math.Implementations.Primes.TurnersSieve	as Math.Implementations.Primes.TurnersSieve+import qualified	Factory.Math.Primes					as Math.Primes+import qualified	ToolShed.Defaultable++-- | The implemented methods by which the primes may be generated.+data Algorithm+	= SieveOfAtkin Integer					-- ^ The /Sieve of Atkin/, optimised using a 'Data.PrimeWheel.PrimeWheel' of optimal size, for primes up to the specified maximum bound; <http://en.wikipedia.org/wiki/Sieve_of_Atkin>.+	| SieveOfEratosthenes Data.PrimeWheel.NPrimes		-- ^ The /Sieve of Eratosthenes/ (<http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes>), optimised using a 'Data.PrimeWheel.PrimeWheel'.+	| TrialDivision Data.PrimeWheel.NPrimes			-- ^ For each candidate, confirm indivisibility, by all /primes/ smaller than its /square-root/, optimised using a 'Data.PrimeWheel.PrimeWheel'.+	| TurnersSieve						-- ^ For each /prime/, the infinite list of candidates greater than its /square/, is filtered for indivisibility; <http://www.haskell.org/haskellwiki/Prime_numbers#Turner.27s_sieve_-_Trial_division>.+	| WheelSieve Int					-- ^ 'Data.Numbers.Primes.wheelSieve'.+	deriving (Eq, Read, Show)++instance ToolShed.Defaultable.Defaultable Algorithm	where+	defaultValue	= SieveOfEratosthenes 7	-- Resulting in a wheel of circumference 510510.++instance Math.Primes.Algorithmic Algorithm	where+	primes (SieveOfAtkin maxPrime)		= Math.Implementations.Primes.SieveOfAtkin.sieveOfAtkin (Data.PrimeWheel.estimateOptimalSize maxPrime) $ fromIntegral maxPrime+	primes (SieveOfEratosthenes wheelSize)	= Math.Implementations.Primes.SieveOfEratosthenes.sieveOfEratosthenes wheelSize+	primes (TrialDivision wheelSize)	= Math.Implementations.Primes.TrialDivision.trialDivision wheelSize+	primes TurnersSieve			= Math.Implementations.Primes.TurnersSieve.turnersSieve+	primes (WheelSieve wheelSize)		= Data.Numbers.Primes.wheelSieve wheelSize	-- Has better space-complexity than 'SieveOfEratosthenes'.
+ src-lib/Factory/Math/Implementations/Primes/SieveOfAtkin.hs view
@@ -0,0 +1,242 @@+{-+	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@]++	* Generates the constant /bounded/ list of /prime-numbers/, using the /Sieve of Atkin/; <http://en.wikipedia.org/wiki/Sieve_of_Atkin>.++	* <cr.yp.to/papers/primesieves-19990826.pdf>.++	* The implementation;+		has been optimised using a /wheel/ of static, but parameterised, size;+		has been parallelized;+		is polymorphic, but with a specialisation for type 'Int'.++ [@CAVEAT@] The 'Int'-specialisation is implemented by a /rewrite-rule/, which is /very/ fragile.+-}++module Factory.Math.Implementations.Primes.SieveOfAtkin(+-- * Types+-- ** Data-types+--	PolynomialType,+-- * Constants+--	atkinsModulus,+--	inherentPrimes,+--	nInherentPrimes,+--	squares,+-- * Functions+--	polynomialTypeLookupPeriod,+--	polynomialTypeLookup,+--	findPolynomialSolutions,+--	filterOddRepetitions,+--	generateMultiplesOfSquareTo,+--	getPrefactoredPrimes,+	sieveOfAtkin,+--	sieveOfAtkinInt+) where++import qualified	Control.DeepSeq+import qualified	Control.Parallel.Strategies+import qualified	Data.Array.IArray+import			Data.Array.IArray((!))+import qualified	Data.IntSet+import qualified	Data.List+import qualified	Data.Set+import qualified	Factory.Data.PrimeWheel	as Data.PrimeWheel+import qualified	Factory.Math.Power	as Math.Power+import qualified	ToolShed.Data.List++-- | Defines the types of /quadratic/, available to test the potential primality of a candidate integer.+data PolynomialType+	= ModFour	-- ^ Suitable for primality-testing numbers meeting @(n `mod` 4 == 1)@.+	| ModSix	-- ^ Suitable for primality-testing numbers meeting @(n `mod` 6 == 1)@.+	| ModTwelve	-- ^ Suitable for primality-testing numbers meeting @(n `mod` 12 == 11)@.+	| None		-- ^ There's no polynomial which can assess primality, because the candidate is composite.+	deriving Eq++-- | The constant modulus used to select the appropriate quadratic for a prime candidate.+atkinsModulus :: Integral i => i+atkinsModulus	= foldr1 lcm [4, 6, 12]	-- Sure, this is always '12', but this is the reason why.++-- | The constant list of primes factored-out by the unoptimised algorithm.+inherentPrimes :: Integral i => [i]+inherentPrimes	= [2, 3]++-- | The constant number of primes factored-out by the unoptimised algorithm.+nInherentPrimes :: Int+nInherentPrimes	= length (inherentPrimes :: [Int])++-- | Typically the set of primes which have been built into the specified /wheel/, but never fewer than 'inherentPrimes'.+getPrefactoredPrimes :: Integral i => Data.PrimeWheel.PrimeWheel i -> [i]+getPrefactoredPrimes	= max inherentPrimes . Data.PrimeWheel.getPrimeComponents++-- | The period over which the data returned by 'polynomialTypeLookup' repeats.+polynomialTypeLookupPeriod :: Integral i => Data.PrimeWheel.PrimeWheel i -> i+polynomialTypeLookupPeriod	= lcm atkinsModulus . Data.PrimeWheel.getCircumference++{- |+	* Defines which, if any, of the three /quadratics/ is appropriate for the primality-test for each candidate.++	* Since this algorithm uses /modular arithmetic/, the /range/ of results repeat after a short /domain/ related to the /modulus/.+	Thus one need calculate at most one period of this cycle, but fewer if the maximum prime required falls within the first cycle of results.++	* Because the results are /bounded/, they're returned in a zero-indexed /array/, to provide efficient random access;+	the first few elements should never be required, but it makes query clearer.++	* <http://en.wikipedia.org/wiki/Sieve_of_Atkin>.+-}+polynomialTypeLookup :: (Data.Array.IArray.Ix i, Integral i)+	=> Data.PrimeWheel.PrimeWheel i+	-> i	-- ^ The maximum prime required.+	-> Data.Array.IArray.Array i PolynomialType+polynomialTypeLookup primeWheel maxPrime	= Data.Array.IArray.listArray (0, pred (polynomialTypeLookupPeriod primeWheel) `min` maxPrime) $ map select [0 ..]	where+--	select :: Integral i => i -> PolynomialType+	select n+		| any (+			(== 0) . (n `rem`)		-- Though this is merely /Trial Division/, it's only performed over a short bounded interval of numerators.+		) primeComponents	= None+		| r `elem` [1, 5]	= ModFour	-- We actually require @(n `mod` 4 == 1)@, but this is the equivalent modulo 12, with @(r == 9)@ removed because they're all divisible by /3/.+		| r == 7		= ModSix	-- We actually require @(n `mod` 6 == 1)@, but this is the equivalent modulo 12, where @(r == 1)@ has been accounted for above.+		| r == 11		= ModTwelve	-- We require @(n `mod` 12 == 11)@.+		| otherwise		= None+		where+			r		= n `rem` atkinsModulus+			primeComponents	= drop nInherentPrimes $ Data.PrimeWheel.getPrimeComponents primeWheel++-- | The constant, infinite list of the /squares/, of integers increasing from /1/.+squares :: Integral i => [i]+squares	= map snd $ Math.Power.squaresFrom 1++{- |+	* Returns the /ordered/ list of those values with an /odd/ number of occurrences in the specified /unordered/ list.++	* CAVEAT: this is expensive in both execution-time and space.+	The typical imperative-style implementation accumulates polynomial-solutions in a /mutable array/ indexed by the candidate integer.+	This doesn't translate seamlessly to the /pure functional/ domain where /arrays/ naturally immutable,+	so we /sort/ a /list/ of polynomial-solutions, then measure the length of the solution-spans, corresponding to viable candidates.+	Regrettably, 'Data.List.sort' (implemented in /GHC/ by /mergesort/) has a time-complexity /O(n*log n)/+	which is greater than the theoretical /O(n)/ of the whole /Sieve of Atkin/;+	/GHC/'s old /qsort/-implementation is even slower :(+-}+filterOddRepetitions :: Ord a => [a] -> [a]+-- filterOddRepetitions	= map head . filter (foldr (const not) False) . Data.List.group . Data.List.sort	-- Too slow.+filterOddRepetitions	= slave True . Data.List.sort where+	slave isOdd (one : remainder@(two : _))+		| one == two	= slave (not isOdd) remainder+		| isOdd		= one : beginSpan+		| otherwise	= beginSpan+		where+			beginSpan	= slave True remainder+	slave True [singleton]	= [singleton]+	slave _ _		= []++{- |+	* Returns the ordered list of solutions aggregated from each of three /bivariate quadratics/; @z = f(x, y)@.++	* For a candidate integer to be prime, it is necessary but insufficient, that there are an /odd/ number of solutions of value /candidate/.++	* At most one of these three polynomials is suitable for the validation of any specific candidate /z/, depending on 'lookupPolynomialType'.+	so the three sets of solutions are mutually exclusive.+	One coordinate @(x, y)@, can have solutions in more than one of the three polynomials.++	* This algorithm exhaustively traverses the domain @(x, y)@, for resulting /z/ of the required modulus.+	Whilst it tightly constrains the bounds of the search-space, it searches the domain methodically rather than intelligently.+-}+findPolynomialSolutions :: (Control.DeepSeq.NFData i, Data.Array.IArray.Ix i, Integral i)+	=> Data.PrimeWheel.PrimeWheel i+	-> i	-- ^ The maximum prime-number required.+	-> [i]+findPolynomialSolutions primeWheel maxPrime	= foldr1 ToolShed.Data.List.merge {-The lists were previously sorted, as a side-effect, by 'filterOddRepetitions'-} $ Control.Parallel.Strategies.withStrategy (+		Control.Parallel.Strategies.parList Control.Parallel.Strategies.rdeepseq+	 ) [+		{-# SCC "4x^2+y^2" #-} filterOddRepetitions [+			z |+				x'	<- takeWhile (<= pred maxPrime) $ map (* 4) squares,+				z	<- takeWhile (<= maxPrime) $ map (+ x') oddSquares,+				lookupPolynomialType z == ModFour+		], -- List-comprehension. Twice the length of the other two lists.+		{-# SCC "3x^2+y^2" #-} filterOddRepetitions [+			z |+				x'	<- takeWhile (<= pred maxPrime) $ map (* 3) squares,+				z	<- takeWhile (<= maxPrime) . map (+ x') $ if even x' then oddSelection else evenSelection,+				lookupPolynomialType z == ModSix+		], -- List-comprehension.+		{-# SCC "3x^2-y^2" #-} filterOddRepetitions [+			z |+				x2	<- takeWhile (<= maxPrime `div` 2) squares,+				z	<- dropWhile (> maxPrime) . map (3 * x2 -) . takeWhile (< x2) $ if even x2 then oddSelection else evenSelection,+				lookupPolynomialType z == ModTwelve+		] -- List-comprehension.+	] where+		(evenSquares, oddSquares)	= Data.List.partition even squares++--		evenSelection, oddSelection :: Integral i => [i]+		evenSelection	= selection110 evenSquares	where+			selection110 (x0 : x1 : _ : xs)	= x0 : x1 : selection110 xs	-- Effectively, those for meeting ((== 4) . (`mod` 6)).+			selection110 xs			= xs+		oddSelection	= selection101 oddSquares	where+			selection101 (x0 : _ : x2 : xs)	= x0 : x2 : selection101 xs	-- Effectively, those for meeting ((== 1) . (`mod` 6)).+			selection101 xs			= xs++--		lookupPolynomialType :: (Data.Array.IArray.Ix i, Integral i) => i -> PolynomialType+		lookupPolynomialType	= (polynomialTypeLookup primeWheel maxPrime !) . (`rem` polynomialTypeLookupPeriod primeWheel)++-- | Generates the /bounded/ list of multiples, of the /square/ of the specified prime, skipping those which aren't required.+generateMultiplesOfSquareTo :: Integral i+	=> Data.PrimeWheel.PrimeWheel i	-- ^ Used to generate the gaps between prime multiples of the square.+	-> i				-- ^ The /prime/.+	-> i				-- ^ The maximum bound.+	-> [i]+generateMultiplesOfSquareTo primeWheel prime max'	= takeWhile (<= max') . scanl (\accumulator -> (+ accumulator) . (* prime2)) prime2 . cycle $ Data.PrimeWheel.getSpokeGaps primeWheel	where+	prime2	= Math.Power.square prime++{- |+	* Generates the constant /bounded/ list of /prime-numbers/.++	* <http://cr.yp.to/papers/primesieves-19990826.pdf>+-}+sieveOfAtkin :: (Control.DeepSeq.NFData i, Data.Array.IArray.Ix i, Integral i)+	=> Data.PrimeWheel.NPrimes	-- ^ Other implementations effectively use a hard-coded value either /2/ or /3/, but /6/ seems better.+	-> i				-- ^ The maximum prime required.+	-> [i]				-- ^ The /bounded/ list of primes.+sieveOfAtkin wheelSize maxPrime	= (prefactoredPrimes ++) . filterSquareFree Data.Set.empty . dropWhile (<= maximum prefactoredPrimes) $ findPolynomialSolutions primeWheel maxPrime	where+	primeWheel		= Data.PrimeWheel.mkPrimeWheel wheelSize+	prefactoredPrimes	= getPrefactoredPrimes primeWheel++--	filterSquareFree :: Integral i => Data.Set.Set i -> [i] -> [i]+	filterSquareFree _ []	= []+	filterSquareFree primeMultiples (candidate : candidates)+		| Data.Set.member candidate primeMultiples	= {-# SCC "delete" #-} filterSquareFree (Data.Set.delete candidate primeMultiples) candidates	-- Tail-recurse.+		| otherwise					= {-# SCC "insert" #-} candidate : filterSquareFree (Data.Set.union primeMultiples . Data.Set.fromDistinctAscList $ generateMultiplesOfSquareTo primeWheel candidate maxPrime) candidates++{-# NOINLINE sieveOfAtkin #-}+{-# RULES "sieveOfAtkin/Int" sieveOfAtkin = sieveOfAtkinInt #-}	-- CAVEAT: doesn't fire when built with profiling enabled.++-- | A specialisation of 'sieveOfAtkin', which reduces both the execution-time and the space required.+sieveOfAtkinInt :: Data.PrimeWheel.NPrimes -> Int -> [Int]+sieveOfAtkinInt wheelSize maxPrime	= (prefactoredPrimes ++) . filterSquareFree Data.IntSet.empty . dropWhile (<= maximum prefactoredPrimes) $ findPolynomialSolutions primeWheel maxPrime	where+	primeWheel		= Data.PrimeWheel.mkPrimeWheel wheelSize+	prefactoredPrimes	= getPrefactoredPrimes primeWheel++	filterSquareFree :: Data.IntSet.IntSet -> [Int] -> [Int]+	filterSquareFree _ []	= []+	filterSquareFree primeMultiples (candidate : candidates)+		| Data.IntSet.member candidate primeMultiples	= filterSquareFree (Data.IntSet.delete candidate primeMultiples) candidates+		| otherwise					= candidate : filterSquareFree (Data.IntSet.union primeMultiples . Data.IntSet.fromDistinctAscList $ generateMultiplesOfSquareTo primeWheel candidate maxPrime) candidates+
+ src-lib/Factory/Math/Implementations/Primes/SieveOfEratosthenes.hs view
@@ -0,0 +1,162 @@+{-+	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@]++	* Generates the constant, conceptually infinite, list of /prime-numbers/, using the /Sieve of Eratosthenes/; <http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes>.++	* Based on <http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf>.++	* The implementation;+		has been optimised using a /wheel/ of static, but parameterised, size;+		is polymorphic, but with a specialisation for type 'Int'.++ [@CAVEAT@] The 'Int'-specialisation is implemented by a /rewrite-rule/, which is /very/ fragile.+-}++module Factory.Math.Implementations.Primes.SieveOfEratosthenes(+-- * Types+-- ** Type-synonyms+--	PrimeMultiplesQueue,+--	PrimeMultiplesMap,+--	Repository,+--	PrimeMultiplesMapInt,+--	RepositoryInt,+-- * Functions+--	head',+--	tail',+	sieveOfEratosthenes,+--	sieveOfEratosthenesInt+) where++import			Control.Arrow((&&&), (***))+import qualified	Control.Arrow+import qualified	Data.IntMap+import qualified	Data.Map+import			Data.Sequence((|>))+import qualified	Data.Sequence+import qualified	Factory.Data.PrimeWheel		as Data.PrimeWheel++-- | The 'Data.Sequence.Seq' counterpart to 'Data.List.head'.+head' :: Data.Sequence.Seq [a] -> [a]+head'	= (`Data.Sequence.index` 0)++{- |+	* The 'Data.Sequence.Seq' counterpart to 'Data.List.tail'.++	* CAVEAT: because @ Data.List.tail [] @ returns an error, whereas @ tail' Data.Sequence.empty @ returns 'Data.Sequence.empty',+	this function is for internal use only.+-}+tail' :: Data.Sequence.Seq [a] -> Data.Sequence.Seq [a]+tail'	= Data.Sequence.drop 1++-- | An ordered queue of the multiples of primes.+type PrimeMultiplesQueue i	= Data.Sequence.Seq (Data.PrimeWheel.PrimeMultiples i)++-- | A map of the multiples of primes.+type PrimeMultiplesMap i	= Data.Map.Map i (Data.PrimeWheel.PrimeMultiples i)++-- | Combine a /queue/, with a /map/, to form a repository to hold prime-multiples.+type Repository i	= (PrimeMultiplesQueue i, PrimeMultiplesMap i)++{- |+	* A refinement of the /Sieve Of Eratosthenes/, which pre-sieves candidates, selecting only those /coprime/ to the specified short sequence of low prime-numbers.++	* The short sequence of initial primes are represented by a 'Data.PrimeWheel.PrimeWheel',+	of parameterised, but static, size; <http://en.wikipedia.org/wiki/Wheel_factorization>.++	* The algorithm requires one to record multiples of previously discovered primes, allowing /composite/ candidates to be eliminated by comparison.++	* Because each /list/ of multiples, starts with the /square/ of the prime from which it was generated,+	the vast majority will be larger than the maximum prime ultimately demanded, and the effort of constructing and storing this list, is consequently wasted.+	Many implementations solve this, by requiring specification of the maximum prime required,+	thus allowing the construction of redundant lists of multiples to be avoided.++	* This implementation doesn't impose that constraint, leaving a requirement for /rapid/ storage,+	which is supported by /appending/ the /list/ of prime-multiples, to a /queue/.+	If a large enough candidate is ever generated, to match the /head/ of the /list/ of prime-multiples,+	at the /head/ of this /queue/, then the whole /list/ of prime-multiples is dropped from the /queue/,+	but the /tail/ of this /list/ of prime-multiples, for which there is now a high likelyhood of a subsequent match, must now be re-recorded.+	A /queue/ doesn't support efficient random /insertion/, so a 'Data.Map.Map' is used for these subsequent multiples.+	This solution is faster than just using a "Data.PQueue.Min".++	* CAVEAT: has linear /O(n)/ space-complexity.+-}+sieveOfEratosthenes :: Integral i+	=> Data.PrimeWheel.NPrimes+	-> [i]+sieveOfEratosthenes	= uncurry (++) . (Data.PrimeWheel.getPrimeComponents &&& start . Data.PrimeWheel.roll) . Data.PrimeWheel.mkPrimeWheel	where+	start :: Integral i => [Data.PrimeWheel.Distance i] -> [i]+	start ~((candidate, rollingWheel) : distances)	= candidate : sieve (head distances) (Data.Sequence.singleton $ Data.PrimeWheel.generateMultiples candidate rollingWheel, Data.Map.empty)++	sieve :: Integral i => Data.PrimeWheel.Distance i -> Repository i -> [i]+	sieve distance@(candidate, rollingWheel) repository@(primeSquares, squareFreePrimeMultiples)	= case Data.Map.lookup candidate squareFreePrimeMultiples of+		Just primeMultiples	-> sieve' $ Control.Arrow.second (insertUniq primeMultiples . Data.Map.delete candidate) repository	-- Re-insert subsequent multiples.+		Nothing -- Not a square-free composite.+			| candidate == smallestPrimeSquare	-> sieve' $ (tail' *** insertUniq subsequentPrimeMultiples) repository	-- Migrate subsequent prime-multiples, from 'primeSquares' to 'squareFreePrimeMultiples'.+			| otherwise {-prime-}			-> candidate : sieve' (Control.Arrow.first (|> Data.PrimeWheel.generateMultiples candidate rollingWheel) repository)+			where+				(smallestPrimeSquare : subsequentPrimeMultiples)	= head' primeSquares+		where+--			sieve' :: Repository i -> [i]+			sieve'	= sieve $ Data.PrimeWheel.rotate distance	-- Tail-recurse.++			insertUniq :: Ord i => Data.PrimeWheel.PrimeMultiples i -> PrimeMultiplesMap i -> PrimeMultiplesMap i+			insertUniq l m	= insert $ dropWhile (`Data.Map.member` m) l	where+--				insert :: Ord i => Data.PrimeWheel.PrimeMultiples i -> PrimeMultiplesMap i+				insert []		= error "Factory.Math.Implementations.Primes.SieveOfEratosthenes.sieveOfEratosthenes.sieve.insertUniq.insert:\tnull list"+				insert (key : values)	= Data.Map.insert key values m++{-# NOINLINE sieveOfEratosthenes #-}+{-# RULES "sieveOfEratosthenes/Int" sieveOfEratosthenes = sieveOfEratosthenesInt #-}	-- CAVEAT: doesn't fire when built with profiling enabled.++-- | A specialisation of 'PrimeMultiplesMap'.+type PrimeMultiplesMapInt	= Data.IntMap.IntMap (Data.PrimeWheel.PrimeMultiples Int)++-- | A specialisation of 'Repository'.+type RepositoryInt	= (PrimeMultiplesQueue Int, PrimeMultiplesMapInt)++{- |+	* A specialisation of 'sieveOfEratosthenes', which approximately /doubles/ the speed and reduces the space required.++	* CAVEAT: because the algorithm involves /squares/ of primes,+	this implementation will overflow when finding primes greater than @2^16@ on a /32-bit/ machine.+-}+sieveOfEratosthenesInt :: Data.PrimeWheel.NPrimes -> [Int]+sieveOfEratosthenesInt	= uncurry (++) . (Data.PrimeWheel.getPrimeComponents &&& start . Data.PrimeWheel.roll) . Data.PrimeWheel.mkPrimeWheel	where+	start :: [Data.PrimeWheel.Distance Int] -> [Int]+	start ~((candidate, rollingWheel) : distances)	= candidate : sieve (head distances) (Data.Sequence.singleton $ Data.PrimeWheel.generateMultiples candidate rollingWheel, Data.IntMap.empty)++	sieve :: Data.PrimeWheel.Distance Int -> RepositoryInt -> [Int]+	sieve distance@(candidate, rollingWheel) repository@(primeSquares, squareFreePrimeMultiples)	= case Data.IntMap.lookup candidate squareFreePrimeMultiples of+		Just primeMultiples	-> sieve' $ Control.Arrow.second (insertUniq primeMultiples . Data.IntMap.delete candidate) repository+		Nothing+			| candidate == smallestPrimeSquare	-> sieve' $ (tail' *** insertUniq subsequentPrimeMultiples) repository+			| otherwise				-> candidate : sieve' (Control.Arrow.first (|> Data.PrimeWheel.generateMultiples candidate rollingWheel) repository)+			where+				(smallestPrimeSquare : subsequentPrimeMultiples)	= head' primeSquares+		where+			sieve' :: RepositoryInt -> [Int]+			sieve'	= sieve $ Data.PrimeWheel.rotate distance++			insertUniq :: Data.PrimeWheel.PrimeMultiples Int -> PrimeMultiplesMapInt -> PrimeMultiplesMapInt+			insertUniq l m	= insert $ dropWhile (`Data.IntMap.member` m) l	where+				insert :: Data.PrimeWheel.PrimeMultiples Int -> PrimeMultiplesMapInt+				insert []		= error "Factory.Math.Implementations.Primes.SieveOfEratosthenes.sieveOfEratosthenesInt.sieve.insertUniq.insert:\tnull list"+				insert (key : values)	= Data.IntMap.insert key values m
+ src-lib/Factory/Math/Implementations/Primes/TrialDivision.hs view
@@ -0,0 +1,59 @@+{-+	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@]	Generates the constant, conceptually infinite, list of /prime-numbers/, using /Trial Division/.+-}++module Factory.Math.Implementations.Primes.TrialDivision(+-- * Functions+	trialDivision+-- ** Predicates+--	isIndivisibleBy+) where++import qualified	Control.Arrow+import qualified	Data.List+import qualified	Factory.Math.Power		as Math.Power+import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation+import qualified	Factory.Data.PrimeWheel		as Data.PrimeWheel++-- | Uses /Trial Division/, to determine whether the specified candidate is indivisible by all potential denominators from the specified list.+isIndivisibleBy :: Integral i+	=> i	-- ^ The numerator.+	-> [i]	-- ^ The denominators of which it must not be a multiple.+	-> Bool+isIndivisibleBy numerator	= all ((/= 0) . (numerator `rem`)) . takeWhile (<= Math.PrimeFactorisation.maxBoundPrimeFactor numerator)++{- |+	* For each candidate, confirm indivisibility, by all /primes/ smaller than its /square-root/.++	* The candidates to sieve, are generated by a 'Data.PrimeWheel.PrimeWheel',+	of parameterised, but static, size; <http://en.wikipedia.org/wiki/Wheel_factorization>.+-}+trialDivision :: Integral prime => Data.PrimeWheel.NPrimes -> [prime]+trialDivision 0	= [2, 3] ++ filter (`isIndivisibleBy` trialDivision 0 {-recurse-}) [5 ..]	-- No faster than using 'Data.PrimeWheel.mkPrimeWheel 0', but apparently better space-complexity ?!+trialDivision wheelSize	= Data.PrimeWheel.getPrimeComponents primeWheel ++ indivisible	where+	primeWheel	= Data.PrimeWheel.mkPrimeWheel wheelSize+	candidates	= map fst $ Data.PrimeWheel.roll primeWheel+	indivisible	= uncurry (++) . Control.Arrow.second (+		filter (`isIndivisibleBy` indivisible {-recurse-})+	 ) $ Data.List.span (+		< Math.Power.square (head candidates)	-- The first composite candidate, is the square of the next prime after the wheel's constituent ones.+	 ) candidates+
+ src-lib/Factory/Math/Implementations/Primes/TurnersSieve.hs view
@@ -0,0 +1,48 @@+{-+	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@] Generates the constant, conceptally infinite, list of /prime-numbers/, using /Turner's Sieve/; <http://www.haskell.org/haskellwiki/Prime_numbers#Turner.27s_sieve_-_Trial_division>.+-}++module Factory.Math.Implementations.Primes.TurnersSieve(+-- * Functions+	turnersSieve+) where++import qualified	Factory.Math.Power	as Math.Power++{- |+	* For each /prime/, the infinite list of candidates greater than its /square/,+	is filtered for indivisibility; <http://www.haskell.org/haskellwiki/Prime_numbers#Turner.27s_sieve_-_Trial_division>.++	* CAVEAT: though one can easily add a 'Data.PrimeWheel.PrimeWheel', it proved counterproductive.+-}+turnersSieve :: Integral prime => [prime]+turnersSieve	= 2 : sieve [3, 5 ..]	where+	sieve :: Integral i => [i] -> [i]+	sieve []			= []+	sieve (prime : candidates)	= prime : sieve (+		filter (+			\candidate	-> any ($ candidate) [+				(< Math.Power.square prime),	-- Unconditionally admit any candidate smaller than the square of the last prime.+				(/= 0) . (`rem` prime)		-- Ensure indivisibility, of all subsequent candidates, by the last prime discovered.+			]+		) candidates+	 )+
+ src-lib/Factory/Math/Implementations/SquareRoot.hs view
@@ -0,0 +1,192 @@+{-+	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@]	Implements 'Math.SquareRoot.Algorithmic' by a variety of methods.++ [@CAVEAT@]++	Caller may benefit from application of 'Math.Precision.simplify' before operating on the result;+	which though of the required accuracy, may not be the most concise rational number satisfying that criterion.+-}+module Factory.Math.Implementations.SquareRoot(+-- * Types+-- ** Type-synonyms+--	ProblemSpecification,+	Terms,+-- ** Data-types+	Algorithm(..)+-- * Functions+--	squareRootByContinuedFraction,+--	squareRootByIteration,+--	squareRootByTaylorSeries,+--	taylorSeriesCoefficients+) where++import			Control.Arrow((***))+import			Factory.Data.PrimeFactors((>/<), (>^))+import qualified	Factory.Data.PrimeFactors		as Data.PrimeFactors+import qualified	Factory.Math.Implementations.Factorial	as Math.Implementations.Factorial+import qualified	Factory.Math.Power			as Math.Power+import qualified	Factory.Math.Precision			as Math.Precision+import qualified	Factory.Math.SquareRoot			as Math.SquareRoot+import qualified	Factory.Math.Summation			as Math.Summation+import qualified	ToolShed.Defaultable++-- | The number of terms in a series.+type Terms	= Int++-- | The algorithms by which the /square-root/ has been implemented.+data Algorithm+	= BakhshaliApproximation	-- ^ <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Bakhshali_approximation>+	| ContinuedFraction		-- ^ <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Continued_fraction_expansion>.+	| HalleysMethod			-- ^ <http://en.wikipedia.org/wiki/Halley%27s_method>.+	| NewtonRaphsonIteration	-- ^ <http://en.wikipedia.org/wiki/Newton%27s_method>.+	| TaylorSeries Terms		-- ^ <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Taylor_series>.+	deriving (Eq, Read, Show)++instance ToolShed.Defaultable.Defaultable Algorithm	where+	defaultValue	= NewtonRaphsonIteration++-- | Returns an improved estimate for the /square-root/ of the specified value, to the required precision, using the supplied initial estimate..+type ProblemSpecification operand+	= Math.SquareRoot.Estimate+	-> Math.Precision.DecimalDigits	-- ^ The required precision.+	-> operand			-- ^ The value for which to find the /square-root/.+	-> Math.SquareRoot.Result++instance Math.SquareRoot.Algorithmic Algorithm	where+	squareRootFrom _ _ _ 0	= 0+	squareRootFrom _ _ _ 1	= 1+	squareRootFrom algorithm estimate@(x, decimalDigits) requiredDecimalDigits y+		| decimalDigits >= requiredDecimalDigits	= x+		| requiredDecimalDigits <= 0			= error $ "Factory.Math.Implementations.SquareRoot.squareRootFrom:\tinvalid number of required decimal digits; " ++ show requiredDecimalDigits+		| y < 0						= error $ "Factory.Math.Implementations.SquareRoot.squareRootFrom:\tthere's no real square-root of " ++ show y+		| otherwise					= (+			case algorithm of+				ContinuedFraction	-> squareRootByContinuedFraction+				_			-> squareRootByIteration algorithm+		) estimate requiredDecimalDigits y++instance Math.SquareRoot.Iterator Algorithm where+	step BakhshaliApproximation y x+		| dy == 0	= x		-- The estimate was precise.+		| otherwise	= x' - dx'	-- Correct the estimate.+		where+			dy, dydx, dx, x', dydx', dx' :: Math.SquareRoot.Result+			dy	= Math.SquareRoot.getDiscrepancy y x+			dydx	= 2 * x+			dx	= dy / dydx+			x'	= x + dx	-- Identical to Newton-Raphson iteration.+			dydx'	= 2 * x'+			dx'	= Math.Power.square dx / dydx'++{-+	* /Halley's/ method; <http://mathworld.wolfram.com/HalleysMethod.html>++>		X(n+1) = Xn - f(Xn) / [f'(Xn) - f''(Xn) * f(Xn) / 2 * f'(Xn)]+>			=> Xn - (Xn^2 - Y) / [2Xn - 2 * (Xn^2 - Y) / 2 * 2Xn] where Y = X^2, f(X) = X^2 - Y, f'(X) = 2X, f''(X) = 2+>			=> Xn - 1 / [2Xn / (Xn^2 - Y) - 1 / 2Xn]+-}+	step HalleysMethod y x+		| dy == 0	= x		-- The estimate was precise.+		| otherwise	= x - dx	-- Correct the estimate.+		where+			dy, dydx, dx :: Math.SquareRoot.Result+			dy	= negate $ Math.SquareRoot.getDiscrepancy y x	-- Use the estimate to determine the error in 'y'.+			dydx	= 2 * x						-- The gradient, at the estimated value 'x'.+			dx	= recip $ dydx / dy - recip dydx++--	step NewtonRaphsonIteration y x	= (x + toRational y / x) / 2		-- This is identical to the /Babylonian Method/.+--	step NewtonRaphsonIteration y x	= x / 2 + toRational y / (2 * x)	-- Faster.+	step NewtonRaphsonIteration y x	= x / 2 + (toRational y / 2) / x	-- Faster still.++	step (TaylorSeries terms) y x	= squareRootByTaylorSeries terms y x++	step algorithm _ _		= error $ "Factory.Math.Implementations.SquareRoot.step:\tinappropriate algorithm; " ++ show algorithm++	convergenceOrder BakhshaliApproximation	= Math.Precision.quarticConvergence+	convergenceOrder ContinuedFraction	= Math.Precision.linearConvergence+	convergenceOrder HalleysMethod		= Math.Precision.cubicConvergence+	convergenceOrder NewtonRaphsonIteration	= Math.Precision.quadraticConvergence+	convergenceOrder (TaylorSeries terms)	= terms	-- The order of convergence, per iteration, equals the number of terms in the series on each iteration.++{- |+	* Uses /continued-fractions/, to iterate towards the principal /square-root/ of the specified positive integer;+	<http://en.wikipedia.org/wiki/Solving_quadratic_equations_with_continued_fractions>,+	<http://en.wikipedia.org/wiki/Generalized_continued_fraction#Roots_of_positive_numbers>,+	<http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Continued_fraction_expansion>.+	<http://www.myreckonings.com/Dead_Reckoning/Online/Materials/General%20Method%20for%20Extracting%20Roots.pdf>++	* The convergence <http://en.wikipedia.org/wiki/Rate_of_convergence> of the /continued-fraction/ is merely /1st order/ (linear).+-}+squareRootByContinuedFraction :: Real operand => ProblemSpecification operand+squareRootByContinuedFraction (initialEstimate, initialDecimalDigits) requiredDecimalDigits y	= initialEstimate + (convergents initialEstimate !! Math.Precision.getTermsRequired (10 ^^ negate initialDecimalDigits) requiredDecimalDigits)	where+	convergents :: Math.SquareRoot.Result -> [Math.SquareRoot.Result]+	convergents x	= iterate ((Math.SquareRoot.getDiscrepancy y x /) . ((2 * x) +)) 0++{- |+	* The constant coefficients of the /Taylor-series/ for a /square-root/; <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Taylor_series>.++	* @ ((-1)^n * factorial(2*n)) / ((1 - 2*n) * 4^n * factorial(n^2)) @.+-}+taylorSeriesCoefficients :: Fractional f => [f]+taylorSeriesCoefficients	= zipWith (+	\powers n	-> let+		doubleN		= 2 * n+		product'	= Data.PrimeFactors.product' (recip 2) {-arbitrary-} 10 {-arbitrary-}+	in uncurry (/) . (+		fromIntegral . product' *** fromIntegral . (* ((1 - doubleN) * powers)) . product'+	) $ Math.Implementations.Factorial.primeFactors doubleN >/< Math.Implementations.Factorial.primeFactors n >^ 2+ ) (+	iterate (* negate 4) 1	-- (-4)^n+ ) [0 :: Integer ..]		-- n++{- |+	* Returns the /Taylor-series/ for the /square-root/ of the specified value, to any requested number of terms.++	* <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Taylor_series>.++	* The convergence of the series is merely /linear/,+	in that each term increases the precision, by a constant number of decimal places, equal to the those in the original estimate.++	* By feeding-back the improved estimate, to form a new series, the order of convergence, on each successive iteration,+	becomes proportional to the number of terms;++>		Terms		Convergence+>		=====		===========+>		2 terms		/quadratic/+>		3 terms		/cubic/+-}+squareRootByTaylorSeries :: Real operand+	=> Terms			-- ^ The number of terms of the infinite series, to evaluate.+	-> operand			-- ^ The value for which the /square-root/ is required.+	-> Math.SquareRoot.Result	-- ^ An initial estimate.+	-> Math.SquareRoot.Result+squareRootByTaylorSeries _ _ 0	= error "Factory.Math.Implementations.SquareRoot.squareRootByTaylorSeries:\talgorithm can't cope with estimated value of zero."+squareRootByTaylorSeries terms y x+	| terms < 2	= error $ "Factory.Math.Implementations.SquareRoot.squareRootByTaylorSeries:\tinvalid number of terms; " ++ show terms+	| otherwise	= Math.Summation.sumR' . take terms . zipWith (*) taylorSeriesCoefficients $ iterate (* relativeError) x+	where+		relativeError :: Math.SquareRoot.Result+		relativeError	= pred $ toRational y / Math.Power.square x	-- Pedantically, this is the error in y, which is twice the magnitude of the error in x.++-- | Iterates from the estimated value, towards the /square-root/, a sufficient number of times to achieve the required accuracy.+squareRootByIteration :: Real operand => Algorithm -> ProblemSpecification operand+squareRootByIteration algorithm (initialEstimate, initialDecimalDigits) requiredDecimalDigits y	= iterate (Math.SquareRoot.step algorithm y) initialEstimate !! Math.Precision.getIterationsRequired (Math.SquareRoot.convergenceOrder algorithm) initialDecimalDigits requiredDecimalDigits+
+ src-lib/Factory/Math/MultiplicativeOrder.hs view
@@ -0,0 +1,66 @@+{-+	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@]	Exports the /Multiplicative Order/ of an integer, in a specific /modular/ arithmetic.++-}++module Factory.Math.MultiplicativeOrder(+-- * Functions+	multiplicativeOrder+) where++import qualified	Control.DeepSeq+import qualified	Factory.Data.Exponential	as Data.Exponential+import qualified	Factory.Math.Power		as Math.Power+import qualified	Factory.Math.Primality		as Math.Primality+import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation++{- |+	* The smallest positive integral power to which the specified integral base must be raised,+	to be congruent with one, in the specified /modular/ arithmetic.++	* Based on <http://rosettacode.org/wiki/Multiplicative_order#Haskell>.++	* <http://en.wikipedia.org/wiki/Multiplicative_order>.++	* <http://mathworld.wolfram.com/MultiplicativeOrder.html>.+-}+multiplicativeOrder :: (Math.PrimeFactorisation.Algorithmic primeFactorisationAlgorithm, Control.DeepSeq.NFData i, Integral i, Show i)+	=> primeFactorisationAlgorithm+	-> i	-- ^ Base.+	-> i	-- ^ Modulus.+	-> i	-- ^ Result.+multiplicativeOrder primeFactorisationAlgorithm base modulus+	| modulus < 2					= error $ "Factory.Math.MultiplicativeOrder.multiplicativeOrder:\tinvalid modulus; " ++ show modulus+	| not $ Math.Primality.areCoprime base modulus	= error $ "Factory.Math.MultiplicativeOrder.multiplicativeOrder:\targuments aren't coprime; " ++ show (base, modulus)+	| otherwise					= foldr (lcm . multiplicativeOrder') 1 $ Math.PrimeFactorisation.primeFactors primeFactorisationAlgorithm modulus	-- Combine the /multiplicative order/ of the constituent /prime-factors/.+	where+--		multiplicativeOrder' :: (Control.DeepSeq.NFData i, Integral i) => Data.Exponential.Exponential i -> i+		multiplicativeOrder' e	= product . map (+			\e'	-> let+				d :: Int+				d	= length . takeWhile (/= 1) . iterate (+					\y	-> Math.Power.raiseModulo y (Data.Exponential.getBase e') pk+				 ) $ Math.Power.raiseModulo base (totient `div` Data.Exponential.evaluate e') pk+			in Data.Exponential.getBase e' ^ d+		 ) $ Math.PrimeFactorisation.primeFactors primeFactorisationAlgorithm totient	where+			pk	= Data.Exponential.evaluate e+			totient	= Math.PrimeFactorisation.primePowerTotient e+
+ src-lib/Factory/Math/PerfectPower.hs view
@@ -0,0 +1,100 @@+{-+	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@]	Exports functions related to /perfect powers/.+-}++module Factory.Math.PerfectPower(+-- * Functions+	maybeSquareNumber,+-- ** Predicates+	isPerfectPower+--	isPerfectPowerInt+) where++import qualified	Data.IntSet+import qualified	Data.Set+import qualified	Factory.Math.Power	as Math.Power++{- |+	* Returns @(Just . sqrt)@ if the specified integer is a /square number/ (AKA /perfect square/).++	* <http://en.wikipedia.org/wiki/Square_number>.++	* <http://mathworld.wolfram.com/SquareNumber.html>.++	* @(Math.Power.square . sqrt)@ is expensive, so the modulus of the operand is tested first, in an attempt to prove it isn't a /perfect square/.+	The set of tests, and the valid moduli within each test, are ordered to maximize the rate of failure-detection.+-}+maybeSquareNumber :: Integral i => i -> Maybe i+maybeSquareNumber i+--	| i < 0					= Nothing	-- This function is performance-sensitive, but this test is neither strictly nor frequently required.+	| all (\(modulus, valid) -> rem i modulus `elem` valid) [+--							-- Distribution of moduli amongst perfect squares	Cumulative failure-detection.+		(16,	[0,1,4,9]),			-- All moduli are equally likely.			75%+		(9,	[0,1,4,7]),			-- Zero occurs 33%, the others only 22%.			88%+		(17,	[1,2,4,8,9,13,15,16,0]),	-- Zero only occurs 5.8%, the others 11.8%.		94%+-- These additional tests, aren't always cost-effective.+		(13,	[1,3,4,9,10,12,0]),		-- Zero only occurs 7.7%, the others 15.4%.		97%+		(7,	[1,2,4,0]),			-- Zero only occurs 14.3%, the others 28.6%.		98%+		(5,	[1,4,0])			-- Zero only occurs 20%, the others 40%.			99%++--	] && fromIntegral iSqrt == sqrt'	= Just iSqrt	-- CAVEAT: erroneously True for 187598574531033120 (187598574531033121 is square).+	] && Math.Power.square iSqrt == i	= Just iSqrt+	| otherwise				= Nothing+	where+		sqrt' :: Double+		sqrt'	= sqrt $ fromIntegral i++		iSqrt	= round sqrt'++{- |+	* An integer @(> 1)@ which can be expressed as an integral power @(> 1)@ of a smaller /natural/ number.++	* CAVEAT: /zero/ and /one/ are normally excluded from this set.++	* <http://en.wikipedia.org/wiki/Perfect_power>.++	* <http://mathworld.wolfram.com/PerfectPower.html>.++	* A generalisation of the concept of /perfect squares/, in which only the exponent '2' is significant.+-}+isPerfectPower :: Integral i => i -> Bool+isPerfectPower i+	| i < Math.Power.square 2	= False+	| otherwise			= i `Data.Set.member` foldr (+		\n set	-> if n `Data.Set.member` set+			then set+--			else Data.Set.union set . Data.Set.fromDistinctAscList . takeWhile (<= i) . iterate (* n) $ Math.Power.square n+			else foldr Data.Set.insert set . takeWhile (<= i) . iterate (* n) $ Math.Power.square n	-- Faster.+	) Data.Set.empty [2 .. round $ sqrt (fromIntegral i :: Double)]++{-# NOINLINE isPerfectPower #-}+{-# RULES "isPerfectPower/Int" isPerfectPower = isPerfectPowerInt #-}++-- | A specialisation of 'isPerfectPower'.+isPerfectPowerInt :: Int -> Bool+isPerfectPowerInt i+	| i < Math.Power.square 2	= False+	| otherwise			= i `Data.IntSet.member` foldr (+		\n set	-> if n `Data.IntSet.member` set+			then set+			else foldr Data.IntSet.insert set . takeWhile (<= i) . iterate (* n) $ Math.Power.square n+	) Data.IntSet.empty [2 .. round $ sqrt (fromIntegral i :: Double)]+
+ src-lib/Factory/Math/Pi.hs view
@@ -0,0 +1,100 @@+{-+	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 the classes of /Pi/-algorithm which have been implemented.+-}++module Factory.Math.Pi(+-- * Type-classes+	Algorithmic(..),+-- * Types+-- ** Data-types+	Category(..)+) where++import qualified	Factory.Math.Precision	as Math.Precision+import qualified	ToolShed.Defaultable++{- |+	* Defines the methods expected of a /Pi/-algorithm.++	* Most of the implementations naturally return a 'Rational', but the spigot-algorithms naturally produce a @[Int]@;+	though representing /Pi/ as a big integer with the decimal point removed is clearly incorrect.++	* Since representing /Pi/ as either a 'Rational' or promoted to an 'Integer', is inconvenient, an alternative decimal 'String'-representation is provided.+-}+class Algorithmic algorithm where+	openR	:: algorithm -> Math.Precision.DecimalDigits -> Rational	-- ^ Returns the value of /Pi/ as a 'Rational'.++	openI	:: algorithm -> Math.Precision.DecimalDigits -> Integer	-- ^ Returns the value of /Pi/, promoted by the required precision to form an integer.+	openI _ 1	= 3+	openI algorithm decimalDigits+		| decimalDigits <= 0	= error $ "Factory.Math.Pi.openI:\tinsufficient decimalDigits=" ++ show decimalDigits+		| otherwise		= round . Math.Precision.promote (openR algorithm decimalDigits) $ pred decimalDigits++	openS	:: algorithm -> Math.Precision.DecimalDigits -> String	-- ^ Returns the value of /Pi/ as a decimal 'String'.+	openS _ 1	= "3"+	openS algorithm decimalDigits+		| decimalDigits <= 0	= ""+		| decimalDigits <= 16	= take (succ decimalDigits) $ show (pi :: Double)+		| otherwise		= "3." ++ tail (show $ openI algorithm decimalDigits)	-- Insert a decimal point.++-- | Categorises the various algorithms.+data Category agm bbp borwein ramanujan spigot+	= AGM agm		-- ^ Algorithms based on the /Arithmetic-geometric Mean/.+	| BBP bbp		-- ^ <http://en.wikipedia.org/wiki/Bailey%E2%80%93Borwein%E2%80%93Plouffe_formula>.+	| Borwein borwein	-- ^ <http://en.wikipedia.org/wiki/Borwein%27s_algorithm>.+	| Ramanujan ramanujan	-- ^ <http://www.pi314.net/eng/ramanujan.php>.+	| Spigot spigot		-- ^ Algorithms from which the digits of /Pi/ slowly drip, one by one.+	deriving (Eq, Read, Show)++instance (+	ToolShed.Defaultable.Defaultable agm,+	ToolShed.Defaultable.Defaultable bbp,+	ToolShed.Defaultable.Defaultable borwein,+	ToolShed.Defaultable.Defaultable ramanujan,+	ToolShed.Defaultable.Defaultable spigot+ )  => ToolShed.Defaultable.Defaultable (Category agm bbp borwein ramanujan spigot)	where+	defaultValue	= BBP ToolShed.Defaultable.defaultValue++instance (+	Algorithmic agm,+	Algorithmic bbp,+	Algorithmic borwein,+	Algorithmic ramanujan,+	Algorithmic spigot+ ) => Algorithmic (Category agm bbp borwein ramanujan spigot)	where+	openR algorithm decimalDigits+		| decimalDigits <= 0	= error $ "Factory.Math.Pi.openR:\tinsufficient decimalDigits=" ++ show decimalDigits+		| decimalDigits <= 16	= Math.Precision.simplify (pred decimalDigits) (pi :: Double)+		| otherwise		= (+			case algorithm of+				AGM agm			-> openR agm+				BBP bbp			-> openR bbp+				Borwein borwein		-> openR borwein+				Ramanujan ramanujan	-> openR ramanujan+				Spigot spigot		-> openR spigot+		) decimalDigits++	openI _ 1				= 3+	openI (Spigot spigot) decimalDigits	= openI spigot decimalDigits+	openI algorithm decimalDigits+		| decimalDigits <= 0	= error $ "Factory.Math.Pi.openI:\tinsufficient decimalDigits=" ++ show decimalDigits+		| otherwise		= round . Math.Precision.promote (openR algorithm decimalDigits) $ pred decimalDigits+
+ src-lib/Factory/Math/Power.hs view
@@ -0,0 +1,84 @@+{-+	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@]	Exports functions involving integral powers.+-}++module Factory.Math.Power(+-- * Functions+	square,+	squaresFrom,+	cube,+	cubeRoot,+	raiseModulo+) where++-- | Mainly for convenience.+square :: Num n => n -> n+square x	= x ^ (2 :: Int)	-- CAVEAT: this could be eta-reduced, but it won't then inline when called with a single argument.++{-# INLINE square #-}++-- | Just for convenience.+cube :: Num n => n -> n+cube	= (^ (3 :: Int))++{- |+	* Iteratively generate sequential /squares/, from the specified initial value,+	based on the fact that @(x + 1)^2 = x^2 + 2 * x + 1@.++	* The initial value doesn't need to be either positive or integral.+-}+squaresFrom :: (Enum n, Num n)+	=> n		-- ^ Lower bound.+	-> [(n, n)]	-- ^ @ [(n, n^2)] @.+squaresFrom from	= iterate (\(x, y) -> (succ x, succ $ y + 2 * x)) (from, square from)++-- | Just for convenience.+cubeRoot :: Double -> Double+cubeRoot	= (** recip 3)++{- |+	* Raise an arbitrary number to the specified positive integral power, using /modular/ arithmetic.++	* Implements exponentiation as a sequence of either /squares/ or multiplications by the base;+	<http://en.wikipedia.org/wiki/Exponentiation_by_squaring>.++	* <http://en.wikipedia.org/wiki/Modular_exponentiation>.+-}+raiseModulo :: (Integral i, Integral power, Show power)+	=> i	-- ^ Base.+	-> power+	-> i	-- ^ Modulus.+	-> i	-- ^ Result.+raiseModulo _ _ 0	= error "Factory.Math.Power.raiseModulo:\tzero modulus."+raiseModulo _ _ 1	= 0+raiseModulo _ 0 modulus	= 1 `mod` modulus+raiseModulo base power modulus+	| base < 0		= (`mod` modulus) . (if even power then id else negate) $ raiseModulo (negate base) power modulus	-- Recurse.+	| power < 0		= error $ "Factory.Math.Power.raiseModulo:\tnegative power; " ++ show power+	| first `elem` [0, 1]	= first+	| otherwise		= slave power+	where+		first	= base `mod` modulus++		slave 1	= first+		slave e	= (`mod` modulus) . (if r == 0 {-even-} then id else (* base)) . square $ slave q {-recurse-}	where+			(q, r)	= e `quotRem` 2+
+ src-lib/Factory/Math/Precision.hs view
@@ -0,0 +1,125 @@+{-+	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 the unit with which precision is measured, and operations on it.+-}+module Factory.Math.Precision(+-- * Types+-- ** Type-synonyms+	ConvergenceOrder,+	ConvergenceRate,+	DecimalDigits,+-- * Constants+	linearConvergence,+	quadraticConvergence,+	cubicConvergence,+	quarticConvergence,+-- * Functions+	getIterationsRequired,+	getTermsRequired,+	roundTo,+	promote,+	simplify+) where++import qualified	Data.Ratio++-- | The /order of convergence/; <http://en.wikipedia.org/wiki/Rate_of_convergence>.+type ConvergenceOrder	= Int++-- | The /rate of convergence/; <http://en.wikipedia.org/wiki/Rate_of_convergence>.+type ConvergenceRate	= Double++-- | A number of decimal digits; presumably positive.+type DecimalDigits	= Int++-- | /Linear/ convergence-rate; which may be qualified by the /rate of convergence/.+linearConvergence :: ConvergenceOrder+linearConvergence	= 1++-- | /Quadratic/ convergence-rate.+quadraticConvergence :: ConvergenceOrder+quadraticConvergence	= 2++-- | /Cubic/ convergence-rate.+cubicConvergence :: ConvergenceOrder+cubicConvergence	= 3++-- | /Quartic/ convergence-rate.+quarticConvergence :: ConvergenceOrder+quarticConvergence	= 4++-- | The predicted number of iterations, required to achieve a specific accuracy, at a given /order of convergence/.+getIterationsRequired :: Integral i+	=> ConvergenceOrder+	-> DecimalDigits	-- ^ The precision of the initial estimate.+	-> DecimalDigits	-- ^ The required precision.+	-> i+getIterationsRequired convergenceOrder initialDecimalDigits requiredDecimalDigits+	| initialDecimalDigits <= 0	= error $ "Factory.Math.Precision.getIterationsRequired:\tinsufficient 'initialDecimalDigits'; " ++ show initialDecimalDigits+	| precisionRatio <= 1		= 0+	| otherwise			= ceiling $ fromIntegral convergenceOrder `logBase` precisionRatio+	where+		precisionRatio :: Double+		precisionRatio	= fromIntegral requiredDecimalDigits / fromIntegral initialDecimalDigits++{- |+	* The predicted number of terms which must be extracted from a series,+	if it is to converge to the required accuracy,+	at the specified linear /convergence-rate/.++	* The /convergence-rate/ of a series, is the error in the series after summation of @(n+1)th@ terms,+	divided by the error after only @n@ terms, as the latter tends to infinity.+	As such, for a /convergent/ series (in which the error get smaller with successive terms), it's value lies in the range @0 .. 1@.++	* <http://en.wikipedia.org/wiki/Rate_of_convergence>.+-}+getTermsRequired :: Integral i+	=> ConvergenceRate+	-> DecimalDigits	-- ^ The additional number of correct decimal digits.+	-> i+getTermsRequired _ 0		= 0+getTermsRequired convergenceRate requiredDecimalDigits+	| convergenceRate <= 0 || convergenceRate >= 1	= error $ "Factory.Math.Precision.getTermsRequired:\t(0 < convergence-rate < 1); " ++ show convergenceRate+	| requiredDecimalDigits < 0			= error $ "Factory.Math.Precision.getTermsRequired:\t'requiredDecimalDigits' must be positive; " ++ show requiredDecimalDigits+	| otherwise					= ceiling $ fromIntegral requiredDecimalDigits / negate (logBase 10 convergenceRate)++-- | Rounds the specified number, to a positive number of 'DecimalDigits'.+roundTo :: (RealFrac a, Fractional f) => DecimalDigits -> a -> f+roundTo decimals = (/ fromInteger promotionFactor) . fromInteger . round . (* fromInteger promotionFactor)	where+	promotionFactor :: Integer+	promotionFactor	= 10 ^ decimals++-- | Promotes the specified number, by a positive number of 'DecimalDigits'.+promote :: Num n => n -> DecimalDigits -> n+promote x	= (* x) . (10 ^)++{- |+	* Reduces a 'Rational' to the minimal form required for the specified number of /fractional/ decimal places;+	irrespective of the number of integral decimal places.++	* A 'Rational' approximation to an irrational number, may be very long, and provide an unknown excess precision.+	Whilst this doesn't sound harmful, it costs in performance and memory-requirement, and being unpredictable isn't actually useful.+-}+simplify :: RealFrac operand+	=> DecimalDigits	-- ^ The number of places after the decimal point, which are required.+	-> operand+	-> Rational+simplify decimalDigits operand	= Data.Ratio.approxRational operand . recip $ 4 * 10 ^ succ decimalDigits	-- Tolerate any error less than half the least significant digit required.+
+ src-lib/Factory/Math/Primality.hs view
@@ -0,0 +1,102 @@+{-+	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@]++	* Exports a common interface for primality-implementations.++	* Provides utilities for these implementations.+-}++module Factory.Math.Primality(+-- * Type-classes+	Algorithmic(..),+-- * Functions+	carmichaelNumbers,+-- ** Predicates+	areCoprime,+	isFermatWitness,+	isCarmichaelNumber+) where++import qualified	Control.DeepSeq+import qualified	Factory.Math.Power	as Math.Power++-- | Defines the methods expected of a primality-testing algorithm.+class Algorithmic algorithm	where+	isPrime	:: (Control.DeepSeq.NFData i, Integral i, Show i) => algorithm -> i -> Bool++{- |+	'True' if the two specified integers are /relatively prime/,+	i.e. if they share no common positive factors except one.++	* @1@ and @-1@ are the only numbers which are /coprime/ to themself.++	* <http://en.wikipedia.org/wiki/Coprime>.++	* <http://mathworld.wolfram.com/RelativelyPrime.html>.+-}+areCoprime :: Integral i => i -> i -> Bool+areCoprime i	= (== 1) . gcd i++{- |+	* Tests /Fermat's Little Theorem/ for all applicable values, as a probabilistic primality-test.++	* <http://en.wikipedia.org/wiki/Fermat%27s_little_theorem>.++	* <http://en.wikipedia.org/wiki/Fermat_primality_test>.++	* <http://en.wikipedia.org/wiki/Fermat_pseudoprime>.++	* CAVEAT: this primality-test fails for the /Carmichael numbers/.++	* TODO: confirm that all values must be tested.+-}+isFermatWitness :: (Integral i, Show i) => i -> Bool+isFermatWitness i	= not . all isFermatPseudoPrime $ filter (areCoprime i) [2 .. pred i]	where+	isFermatPseudoPrime base	= Math.Power.raiseModulo base (pred i) i == 1	-- CAVEAT: a /Fermat Pseudo-prime/ must also be a /composite/ number.++{- |+	* A /Carmichael number/ is an /odd/ /composite/ number which satisfies /Fermat's little theorem/.++	* <http://en.wikipedia.org/wiki/Carmichael_number>.++	* <http://mathworld.wolfram.com/CarmichaelNumber.html>.+-}+isCarmichaelNumber :: (+	Algorithmic		algorithm,+	Control.DeepSeq.NFData	i,+	Integral		i,+	Show			i+ ) => algorithm -> i -> Bool+isCarmichaelNumber algorithm i	= not $ or [+	i <= 2,+	even i,+	isFermatWitness i,+	isPrime algorithm i+ ]++-- | An ordered list of the /Carmichael/ numbers; <http://en.wikipedia.org/wiki/Carmichael_number>.+carmichaelNumbers :: (+	Algorithmic		algorithm,+	Control.DeepSeq.NFData	i,+	Integral		i,+	Show			i+ ) => algorithm -> [i]+carmichaelNumbers algorithm	= isCarmichaelNumber algorithm `filter` [3, 5 ..]
+ src-lib/Factory/Math/PrimeFactorisation.hs view
@@ -0,0 +1,151 @@+{-+	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@]++	* <http://en.wikipedia.org/wiki/Integer_factorization>.++	* Exports a common interface to permit decomposition of positive integers,+	into the unique combination of /prime/-factors known to exist according to the /Fundamental Theorem of Arithmetic/; <http://en.wikipedia.org/wiki/Fundamental_theorem_of_arithmetic>.++	* Leveraging this abstract capability, it derives the /smoothness/, /power-smoothness/, /omega/-numbers and /square-free/ integers.++	* Filters the list of /regular-numbers/ from the list of /smoothness/.++	* CAVEAT: to avoid wasting time, it may be advantageous to check /Factory.Math.Primality.isPrime/ first.+-}++module Factory.Math.PrimeFactorisation(+-- * Type-classes+	Algorithmic(..),+-- * Functions+	maxBoundPrimeFactor,+	smoothness,+	powerSmoothness,+	regularNumbers,+	primePowerTotient,+	eulersTotient,+	omega,+	squareFree+) where++import qualified	Control.DeepSeq+import qualified	Data.List+import qualified	Factory.Data.Exponential	as Data.Exponential+import qualified	Factory.Data.PrimeFactors	as Data.PrimeFactors++-- | Defines the methods expected of a /factorisation/-algorithm.+class Algorithmic algorithm	where+	primeFactors	:: (Control.DeepSeq.NFData base, Integral base)+		=> algorithm+		-> base	-- ^ The operand+		-> Data.PrimeFactors.Factors base Int {-arbitrarily-}++{- |+	* The upper limit for a prime to be considered as a candidate factor of the specified number.++	* One might naively think that this limit is @(x `div` 2)@ for an even number,+	but though a prime-factor /greater/ than the /square-root/ of the number can exist,+	its smaller /cofactor/ decomposes to a prime which must be less than the /square-root/.++	* NB: rather then using @(primeFactor <= sqrt numerator)@ to filter the candidate prime-factors of a given numerator,+	one can alternatively use @(numerator >= primeFactor ^ 2)@ to filter what can potentially be factored by a given prime-factor.++	* CAVEAT: suffers from rounding-errors, though no consequence has been witnessed.+-}+maxBoundPrimeFactor :: Integral i => i -> i+maxBoundPrimeFactor	= floor . (sqrt :: Double -> Double) . fromIntegral++{- |+	* A constant, zero-indexed, conceptually infinite, list, of the /smooth/ness of all positive integers.++	* <http://en.wikipedia.org/wiki/Smooth_number>.++	* <http://mathworld.wolfram.com/SmoothNumber.html>.+-}+smoothness :: (Algorithmic algorithm, Control.DeepSeq.NFData base, Integral base) => algorithm -> [base]+smoothness algorithm	= 0 : map (Data.Exponential.getBase . last . primeFactors algorithm) [1 ..]++{- |+	* A constant, zero-indexed, conceptually infinite, list of the /power-smooth/ness of all positive integers.++	* <http://en.wikipedia.org/wiki/Smooth_number#Powersmooth_numbers>.+-}+powerSmoothness :: (Algorithmic algorithm, Control.DeepSeq.NFData base, Integral base) => algorithm -> [base]+powerSmoothness algorithm	= 0 : map (maximum . map Data.Exponential.evaluate . primeFactors algorithm) [1 ..]++{- |+	* Filters 'smoothness', to derive the constant list of /Hamming-numbers/.++	* <http://en.wikipedia.org/wiki/Regular_number>.+-}+regularNumbers :: (Algorithmic algorithm, Control.DeepSeq.NFData base, Integral base) => algorithm -> [base]+regularNumbers algorithm	= map fst . filter ((<= (5 :: Integer)) . snd) . zip [1 ..] . tail $ smoothness algorithm++{- |+	* /Euler's Totient/ for a /power/ of a /prime/-number.++	* By /Olofsson/; @(phi(n^k) = n^(k - 1) * phi(n))@+	and since @(phi(prime) = prime - 1)@++	* CAVEAT: checks neither the primality nor the bounds of the specified value; therefore for internal use only.+-}+primePowerTotient :: (Integral base, Integral exponent) => Data.Exponential.Exponential base exponent -> base+primePowerTotient (base, exponent')	= pred base * base ^ pred exponent'++{- |+	* The number of /coprimes/ less than or equal to the specified positive integer.++	* <http://en.wikipedia.org/wiki/Euler%27s_totient_function>.++	* <http://mathworld.wolfram.com/TotientFunction.html>.++	* AKA /EulerPhi/.+-}+eulersTotient :: (+	Algorithmic		algorithm,+	Control.DeepSeq.NFData	i,+	Integral		i,+	Show			i+ ) => algorithm -> i -> i+eulersTotient _ 1	= 1+eulersTotient algorithm i+	| i <= 0	= error $ "Factory.Math.PrimeFactorisation.eulersTotient:\tundefined for; " ++ show i+	| otherwise	= product . map primePowerTotient $ primeFactors algorithm i++{- |+	* A constant, zero-indexed, conceptually infinite, list of the /small omega/ numbers (i.e. the number of /distinct/ prime factors); cf. /big omega/.++	* <http://oeis.org/wiki/Omega%28n%29,_number_of_distinct_primes_dividing_n>.++	* <http://mathworld.wolfram.com/DistinctPrimeFactors.html>++	* <http://planetmath.org/encyclopedia/NumberOfDistinctPrimeFactorsFunction.html>.+-}+omega :: (Algorithmic algorithm, Control.DeepSeq.NFData i, Integral i) => algorithm -> [i]+omega algorithm	= map (Data.List.genericLength . primeFactors algorithm) [0 :: Integer ..]++{- |+	* A constant, conceptually infinite, list of the /square-free/ numbers, i.e. those which aren't divisible by any /perfect square/.++	* <http://en.wikipedia.org/wiki/Square-free_integer>.+-}+squareFree :: (Algorithmic algorithm, Control.DeepSeq.NFData i, Integral i) => algorithm -> [i]+squareFree algorithm	= filter (all (== 1) . map Data.Exponential.getExponent . primeFactors algorithm) [1 ..]+
+ src-lib/Factory/Math/Primes.hs view
@@ -0,0 +1,64 @@+{-+	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@]	Exports a common interface for implementations of /prime-number/ generators.+-}++module Factory.Math.Primes(+-- * Types-classes+	Algorithmic(..),+-- * Functions+	primorial,+	mersenneNumbers+) where++import qualified	Control.DeepSeq+import qualified	Data.Array.IArray++-- | Defines the methods expected of a /prime-number/ generator.+class Algorithmic algorithm	where+	primes	:: (Control.DeepSeq.NFData i, Data.Array.IArray.Ix i, Integral i) => algorithm -> [i]	-- ^ Returns the constant, infinite, list of primes.++{- |+	* Returns the constant list, defining the /Primorial/.++	* <http://en.wikipedia.org/wiki/Primorial>.++	* <http://mathworld.wolfram.com/Primorial.html>.+-}+primorial :: (+	Algorithmic		algorithm,+	Control.DeepSeq.NFData	i,+	Data.Array.IArray.Ix	i,+	Integral		i+ ) => algorithm -> [i]+primorial	= scanl (*) 1 . primes++{- |+	* Returns the constant ordered infinite list of /Mersenne numbers/.++	* Only the subset composed from a prime exponent is returned; which is a strict superset of the /Mersenne Primes/.++	* <http://en.wikipedia.org/wiki/Mersenne_prime>.++	* <http://mathworld.wolfram.com/MersenneNumber.html>+-}+mersenneNumbers :: (Algorithmic algorithm, Integral i) => algorithm -> [i]+mersenneNumbers algorithm	= map (pred . (2 ^)) (primes algorithm :: [Int])	-- Whilst the exponentiation could be parallelised, not all values are known to be required.+
+ src-lib/Factory/Math/Probability.hs view
@@ -0,0 +1,255 @@+{-+	Copyright (C) 2011-2013 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@]	Functions for probability-distributions.++ [@CAVEAT@]	Because data-constructors are exposed, 'ToolShed.SelfValidate.isValid' need not be called.+-}++module Factory.Math.Probability(+-- * Type-classes+	Distribution(..),+-- * Types+-- ** Data-types+	ContinuousDistribution(..),+	DiscreteDistribution(..),+-- * Functions+	maxPreciseInteger,+--	minPositiveFloat,+	boxMullerTransform,+--	reProfile,+	generateStandardizedNormalDistribution,+	generateContinuousPopulation,+--	generatePoissonDistribution,+	generateDiscretePopulation+) where++import qualified	Control.Arrow+import			Control.Arrow((***), (&&&))+import qualified	Factory.Data.Interval	as Data.Interval+import qualified	Factory.Math.Power	as Math.Power+import qualified	System.Random+import qualified	ToolShed.Data.List+import qualified	ToolShed.Data.Pair+import qualified	ToolShed.SelfValidate++-- | The maximum integer which can be accurately represented as a Double.+maxPreciseInteger  :: RealFloat a => a -> Integer+maxPreciseInteger	= (2 ^) . floatDigits++{- |+	* 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)++-- | Describes /continuous probability-distributions/; <http://en.wikipedia.org/wiki/List_of_probability_distributions#Continuous_distributions>.+data ContinuousDistribution parameter+	= ExponentialDistribution parameter {-lambda-}				-- ^ Defines an /Exponential/-distribution with a particular /lambda/; <http://en.wikipedia.org/wiki/Exponential_distribution>.+	| LogNormalDistribution parameter {-location-} parameter {-scale2-}	-- ^ Defines a distribution whose logarithm is normally distributed with a particular /mean/ & /variance/; <http://en.wikipedia.org/wiki/Lognormal>.+	| NormalDistribution parameter {-mean-} parameter {-variance-}		-- ^ Defines a /Normal/-distribution with a particular /mean/ & /variance/; <http://en.wikipedia.org/wiki/Normal_distribution>.+	| UniformDistribution (Data.Interval.Interval parameter)		-- ^ Defines a /Uniform/-distribution within a /closed interval/; <http://en.wikipedia.org/wiki/Uniform_distribution>.+	deriving (Eq, Read, Show)++instance (Floating parameter, Ord parameter, Show parameter) => ToolShed.SelfValidate.SelfValidator (ContinuousDistribution parameter)	where+	getErrors probabilityDistribution	= ToolShed.SelfValidate.extractErrors $ case probabilityDistribution of+		ExponentialDistribution lambda		-> [(lambda <= 0, "'lambda' must exceed zero; " ++ show probabilityDistribution ++ ".")]+		LogNormalDistribution location scale2	-> let+			maxParameter	= log . fromInteger $ maxPreciseInteger (undefined :: Double)+		 in [+			(scale2 <= 0,						"'scale' must exceed zero; " ++ show probabilityDistribution ++ "."),+			(location > maxParameter || scale2 > maxParameter,	"loss of precision will result from either 'location' or 'scale^2' exceeding '" ++ show maxParameter ++ "'; " ++ show probabilityDistribution ++ ".")+		 ]+		NormalDistribution _ variance		-> [(variance <= 0, "variance must exceed zero; " ++ show probabilityDistribution ++ ".")]+		UniformDistribution interval		-> [(Data.Interval.isReversed interval, "reversed interval='" ++ show probabilityDistribution ++ "'.")]++-- | Describes /discrete probability-distributions/; <http://en.wikipedia.org/wiki/List_of_probability_distributions#Discrete_distributions>.+data DiscreteDistribution parameter+	= PoissonDistribution parameter {-lambda-}			-- ^ Defines an /Poisson/-distribution with a particular /lambda/; <http://en.wikipedia.org/wiki/Poisson_distribution>.+	| ShiftedGeometricDistribution parameter {-probability-}	-- ^ Defines an /Geometric/-distribution with a particular probability of success; <http://en.wikipedia.org/wiki/Geometric_distribution>.+	deriving (Eq, Read, Show)++instance (Num parameter, Ord parameter, Show parameter) => ToolShed.SelfValidate.SelfValidator (DiscreteDistribution parameter)	where+	getErrors probabilityDistribution	= ToolShed.SelfValidate.extractErrors $ case probabilityDistribution of+		PoissonDistribution lambda			-> [(lambda <= 0, "'lambda' must exceed zero; " ++ show probabilityDistribution ++ ".")]+		ShiftedGeometricDistribution probability	-> [(any ($ probability) [(<= 0), (> 1)], "probability must be in the semi-closed unit-interval (0, 1]; " ++ show probabilityDistribution ++ ".")]++-- | Defines a common interface for probability-distributions.+class Distribution probabilityDistribution	where+	generatePopulation+		:: (Fractional sample, System.Random.RandomGen randomGen)+		=> probabilityDistribution+		-> randomGen	-- ^ A generator of /uniformly distributed/ random numbers.+		-> [sample]	-- ^ CAVEAT: the integers generated for discrete distributions are represented by a fractional type; use 'generateDiscretePopulation' if this is a problem.++	getMean :: Fractional mean => probabilityDistribution -> mean	-- ^ The theoretical mean.++	getStandardDeviation :: Floating standardDeviation => probabilityDistribution -> standardDeviation-- ^ The theoretical standard-deviation.+	getStandardDeviation	= sqrt . getVariance	-- Default implementation.++	getVariance :: Floating variance => probabilityDistribution -> variance	-- ^ The theoretical variance.+	getVariance	= Math.Power.square . getStandardDeviation	-- Default implementation.++instance (RealFloat parameter, Show parameter, System.Random.Random parameter) => Distribution (ContinuousDistribution parameter)	where+	generatePopulation probabilityDistribution	= map realToFrac {-parameter -> sample-} . generateContinuousPopulation probabilityDistribution++	getMean (ExponentialDistribution lambda)			= realToFrac $ recip lambda+	getMean (LogNormalDistribution location scale2)			= realToFrac . exp . (+ location) $ scale2 / 2+	getMean (NormalDistribution mean _)				= realToFrac mean+	getMean (UniformDistribution (minParameter, maxParameter))	= realToFrac $ (minParameter + maxParameter) / 2++	getVariance (ExponentialDistribution lambda)			= realToFrac . recip $ Math.Power.square lambda+	getVariance (LogNormalDistribution location scale2)		= realToFrac $ (exp scale2 - 1) * exp (2 * location + scale2)	-- NB: for standard-deviation == mean, use scale^2 == ln 2.+	getVariance (NormalDistribution _ variance)			= realToFrac variance+	getVariance (UniformDistribution (minParameter, maxParameter))	= realToFrac $ Math.Power.square (maxParameter - minParameter) / 12++instance (RealFloat parameter, Show parameter, System.Random.Random parameter) => Distribution (DiscreteDistribution parameter)	where+	generatePopulation probabilityDistribution		= map fromInteger . generateDiscretePopulation probabilityDistribution++	getMean (PoissonDistribution lambda)			= realToFrac lambda+	getMean (ShiftedGeometricDistribution probability)	= realToFrac $ recip probability++	getVariance (PoissonDistribution lambda)		= realToFrac lambda+	getVariance (ShiftedGeometricDistribution probability)	= realToFrac $ (1 - probability) / Math.Power.square probability++{- |+	* 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,+	Show		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 . uncurry (&&) $ ToolShed.Data.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	= uncurry (&&) . ((> 0) &&& (<= 1))++		polarToCartesianTransform :: Floating f => (f, f) -> (f, f)+		polarToCartesianTransform	= uncurry (*) . Control.Arrow.second cos &&& uncurry (*) . Control.Arrow.second sin++{- |+	* 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 :: (+	RealFloat		f,+	Show			f,+	System.Random.Random	f,+	System.Random.RandomGen	randomGen+ ) => randomGen -> [f]+generateStandardizedNormalDistribution	= ToolShed.Data.List.linearise . uncurry (zipWith $ curry boxMullerTransform) . ToolShed.Data.Pair.mirror (+	System.Random.randomRs (minPositiveFloat undefined, 1)+ ) . System.Random.split++-- | Stretches and shifts a /distribution/ to achieve the required /mean/ and /standard-deviation/.+reProfile :: (Distribution distribution, Floating n) => distribution -> [n] -> [n]+reProfile distribution	= map ((+ getMean distribution) . (* getStandardDeviation distribution))++-- | Uses the supplied random-number generator, to generate a conceptually infinite population, with the specified continuous probability-distribution.+generateContinuousPopulation :: (+	RealFloat		f,+	Show			f,+	System.Random.Random	f,+	System.Random.RandomGen	randomGen+ )+	=> ContinuousDistribution f+	-> randomGen	-- ^ A generator of /uniformly distributed/ random numbers.+	-> [f]+generateContinuousPopulation probabilityDistribution randomGen+	| not $ ToolShed.SelfValidate.isValid probabilityDistribution	= error $ "Factory.Math.Probability.generateContinuousPopulation:\t" ++ ToolShed.SelfValidate.getFirstError probabilityDistribution+	| otherwise							= (+		case probabilityDistribution of+			ExponentialDistribution lambda		-> let+				quantile	= (/ lambda) . negate . log . (1 -)	-- <http://en.wikipedia.org/wiki/Quantile_function>.+			 in map quantile . System.Random.randomRs (0, 1)+			LogNormalDistribution location scale2	-> map (+				exp . (+ location) . (* sqrt scale2)	-- Stretch the standard-deviation & re-locate the mean to that specified for the log-space, then return to the original coordinates.+			 ) . generateStandardizedNormalDistribution+			NormalDistribution _ _			-> reProfile probabilityDistribution . generateStandardizedNormalDistribution+			UniformDistribution interval		-> System.Random.randomRs interval+	) randomGen++{- |+	* Uses the supplied random-number generator,+	to generate a conceptually infinite population, of random integers conforming to the /Poisson distribution/; <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'.+-}+generatePoissonDistribution :: (+	Integral		sample,+	RealFloat		lambda,+	Show			lambda,+	System.Random.Random	lambda,+	System.Random.RandomGen	randomGen+ )+	=> lambda	-- ^ Defines the required approximate value of both /mean/ and /variance/.+	-> randomGen+	-> [sample]+generatePoissonDistribution lambda+	| lambda <= 0	= error $ "Factory.Math.Probability.generatePoissonDistribution:\tlambda must exceed zero " ++ show lambda+	| lambda > (+		negate . log $ minPositiveFloat lambda	-- Guard against underflow, in the user-defined type for lambda.+	)		= filter (>= 0) . map round . (reProfile (PoissonDistribution lambda) :: [Double] -> [Double]) . 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++-- | Uses the supplied random-number generator, to generate a conceptually infinite population, with the specified discrete probability-distribution.+generateDiscretePopulation :: (+	Integral		sample,+	Ord			parameter,+	RealFloat		parameter,+	Show			parameter,+	System.Random.Random	parameter,+	System.Random.RandomGen	randomGen+ )+	=> DiscreteDistribution parameter+	-> randomGen	-- ^ A generator of /uniformly distributed/ random numbers.+	-> [sample]+generateDiscretePopulation probabilityDistribution randomGen+	| not $ ToolShed.SelfValidate.isValid probabilityDistribution	= error $ "Factory.Math.Probability.generateDiscretePopulation:\t" ++ ToolShed.SelfValidate.getFirstError probabilityDistribution+	| otherwise							= (+		case probabilityDistribution of+			PoissonDistribution lambda	-> generatePoissonDistribution lambda+			ShiftedGeometricDistribution probability+				| probability == 1	-> const $ repeat 1	-- The first Bernoulli Trial is guaranteed to succeed.+				| otherwise		-> map ceiling {-minimum 1-} . (\x -> x :: [Rational]) . generatePopulation (ExponentialDistribution . negate $ log (1 - probability))	-- The geometric distribution is a discrete version of the exponential distribution.+	) randomGen+
+ src-lib/Factory/Math/Radix.hs view
@@ -0,0 +1,139 @@+{-+	Copyright (C) 2011-2015 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@]	Facilitates representation of 'Integral' values in alternative 'Integral' bases.+-}++module Factory.Math.Radix(+-- * Constants+--	decodes,+--	digits,+--	encodes,+-- * Functions+	digitSum,+	digitalRoot,+	fromBase,+	toBase+) where++import			Data.Array.IArray((!))+import qualified	Data.Array.IArray+import qualified	Data.Char+import qualified	Data.List+import qualified	Data.Maybe++-- | Characters used to represent the digits of numbers in @(-36 <= base <= 36)@.+digits :: String+digits	= ['0' .. '9'] ++ ['a' .. 'z']++-- | Constant random-access lookup for 'digits'.+encodes :: (Data.Array.IArray.Ix index, Integral index) => Data.Array.IArray.Array index Char+encodes	= Data.Array.IArray.listArray (0, pred $ Data.List.genericLength digits) digits++-- | Constant reverse-lookup for 'digits'.+decodes :: Integral i => [(Char, i)]+decodes	= zip digits [0 ..]++{- |+	* Convert the specified integral quantity, to an alternative base, and represent the result as a 'String'.++	* Both negative integers and negative bases are permissible.++	* The conversion to 'Char' can only succeed where printable and intelligible characters exist to represent all digits in the chosen base;+	which in practice means @(-36 <= base <= 36)@.+-}+toBase :: (+	Data.Array.IArray.Ix	decimal,+	Integral		base,+	Integral		decimal,+	Show			base,+	Show			decimal+ ) => base -> decimal -> String+toBase 10 decimal	= show decimal	-- Base unchanged.+toBase _ 0		= "0"		-- Zero has the same representation in any base.+toBase base decimal+	| abs base < 2					= error $ "Factory.Math.Radix.toBase:\tan arbitrary integer can't be represented in base " ++ show base+	| abs base > Data.List.genericLength digits	= error $ "Factory.Math.Radix.toBase:\tunable to clearly represent the complete set of digits in base " ++ show base+	| base > 0 && decimal < 0			= '-' : map toDigit (fromDecimal (negate decimal) [])+	| otherwise					= toDigit `map` fromDecimal decimal []+	where+		fromDecimal 0		= id+		fromDecimal n+			| remainder < 0	= fromDecimal (succ quotient) . ((remainder - fromIntegral base) :)	-- This can only occur when base is negative; cf. 'divMod'.+			| otherwise	= fromDecimal quotient . (remainder :)+			where+				(quotient, remainder)	= n `quotRem` fromIntegral base++		toDigit :: (Data.Array.IArray.Ix i, Integral i, Show i) => i -> Char+		toDigit n+			| n >&< encodes	= encodes ! n+			| otherwise	= error $ "Factory.Math.Radix.toBase.toDigit:\tno suitable character-representation for integer " ++ show n+			where+				(>&<) :: (Data.Array.IArray.Ix i, Integral i) => i -> Data.Array.IArray.Array i Char -> Bool+				index >&< array	= ($ index) `all` [(>= lower), (<= upper)]	where+					(lower, upper)	= Data.Array.IArray.bounds array++{- |+	* Convert the 'String'-representation of a number in the specified base, to an integer.++	* Both negative numbers and negative bases are permissible.+-}+fromBase :: (+	Integral	base,+	Integral	decimal,+	Read		decimal,+	Show		base+ ) => base -> String -> decimal+fromBase 10 s	= read s	-- Base unchanged.+fromBase _ "0"	= 0		-- Zero has the same representation in any base.+fromBase base s+	| abs base < 2					= error $ "Factory.Math.Radix.fromBase:\tan arbitrary integer can't be represented in base " ++ show base+	| abs base > Data.List.genericLength digits	= error $ "Factory.Math.Radix.fromBase:\tunable to clearly represent the complete set of digits in base " ++ show base+	| base > 0 && head s == '-'			= negate . fromBase base $ tail s	-- Recurse.+	| otherwise					= Data.List.foldl' (\l -> ((l * fromIntegral base) +) . fromDigit) 0 s	where+		fromDigit :: Integral i => Char -> i+		fromDigit c	= case c `lookup` decodes of+			Just i+				| i >= abs (fromIntegral base)	-> error $ "Factory.Math.Radix.fromBase.fromDigit:\tillegal char " ++ show c ++ ", for base " ++ show base+				| otherwise			-> i+			_					-> error $ "Factory.Math.Radix.fromBase.fromDigit:\tunrecognised char " ++ show c++{- |+	* <http://mathworld.wolfram.com/DigitSum.html>.++	* <http://en.wikipedia.org/wiki/Digit_sum>.+-}+digitSum :: (+	Data.Array.IArray.Ix	decimal,+	Integral		base,+	Integral		decimal,+	Show			base,+	Show			decimal+ ) => base -> decimal -> decimal+digitSum 10	= fromIntegral . foldr ((+) . Data.Char.digitToInt) 0 . show+digitSum base	= sum . Data.Maybe.mapMaybe (`lookup` decodes) . toBase base++-- | <http://en.wikipedia.org/wiki/Digital_root>.+digitalRoot :: (+	Data.Array.IArray.Ix	decimal,+	Integral		decimal,+	Show			decimal+ ) => decimal -> decimal+digitalRoot	= until (<= 9) (digitSum (10 :: Int))+
+ src-lib/Factory/Math/SquareRoot.hs view
@@ -0,0 +1,120 @@+{-+	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@]++	* Exports a common interface for /square-root/ implementations.++	* Provides utilities for these implementations.+-}++module Factory.Math.SquareRoot(+-- * Type-classes+	Algorithmic(..),+	Iterator(..),+-- * Types+-- ** Type-synonyms+	Result,+	Estimate,+-- * Functions+	getAccuracy,+	getDiscrepancy,+	getEstimate,+--	rSqrt,+-- ** Predicates+	isPrecise+) where++import qualified	Factory.Math.Power	as Math.Power+import qualified	Factory.Math.Precision	as Math.Precision++-- | The result-type; actually, only the concrete return-type of 'Math.Precision.simplify', stops it being a polymorphic instance of 'Fractional'.+type Result	= Rational++-- | Contains an estimate for the /square-root/ of a value, and its accuracy.+type Estimate	= (Result, Math.Precision.DecimalDigits)++-- | Defines the methods expected of a /square-root/ algorithm.+class Algorithmic algorithm	where+	squareRootFrom	:: (Real operand, Show operand)+		=> algorithm+		-> Estimate			-- ^ An initial estimate from which to start.+		-> Math.Precision.DecimalDigits	-- ^ The required precision.+		-> operand			-- ^ The value for which to find the /square-root/.+		-> Result			-- ^ Returns an improved estimate of the /square-root/, found using the specified algorithm, accurate to at least the required number of decimal digits.++	squareRoot	:: (Real operand, Show operand)+		=> algorithm+		-> Math.Precision.DecimalDigits	-- ^ The required precision.+		-> operand			-- ^ The value for which to find the /square-root/.+		-> Result			-- ^ Returns an estimate of the /square-root/, found using the specified algorithm, accurate to at least the required number of decimal digits.+	squareRoot algorithm decimalDigits operand	= squareRootFrom algorithm (getEstimate operand) decimalDigits operand	-- Default implementation++-- | The interface required to iterate, from an estimate of the required value, to the next approximation.+class Iterator algorithm where+	step :: Real operand+		=> algorithm+		-> operand	-- ^ The value for which the /square-root/ is required; @y@.+		-> Result	-- ^ The current estimate; @x(n)@.+		-> Result	-- ^ An improved estimate; @x(n+1)@.++	convergenceOrder :: algorithm -> Math.Precision.ConvergenceOrder	-- ^ The ultimate ratio of successive terms as the iteration converges.++-- | Generalise 'sqrt' to operate on any 'Real' operand.+rSqrt :: Real operand => operand -> Double+rSqrt	= sqrt . realToFrac++-- | Uses 'Double'-precision floating-point arithmetic, to obtain an initial estimate for the /square-root/, and its accuracy.+getEstimate :: (Real operand, Show operand) => operand -> Estimate+getEstimate y+	| y < 0		= error $ "Factory.Math.SquareRoot.getEstimate:\tthere's no real square-root of " ++ show y+	| otherwise	= (Math.Precision.simplify decimalDigits {-doubles performance by roughly length of the Rational representation-} . toRational $ rSqrt y, decimalDigits)+	where+		decimalDigits :: Math.Precision.DecimalDigits+		decimalDigits	= 16	-- <http://en.wikipedia.org/wiki/IEEE_floating_point>.++{- |+	* The signed difference between the /square/ of an estimate for the /square-root/ of a value, and that value.++	* Positive when the estimate is too low.++	* CAVEAT: the magnitude is twice the error in the /square-root/.+-}+getDiscrepancy :: Real operand => operand -> Result -> Result+getDiscrepancy y x	= toRational y - Math.Power.square x++-- | True if the specified estimate for the /square-root/, is precise.+isPrecise :: Real operand => operand -> Result -> Bool+isPrecise y x	= getDiscrepancy y x == 0++{- |+	* For a given value and an estimate of its /square-root/,+	returns the number of decimals digits to which the /square-root/ is accurate; including the integral digits.++	* CAVEAT: the result returned for an exact match has been bodged.+-}+getAccuracy :: Real operand => operand -> Result -> Math.Precision.DecimalDigits+getAccuracy y x+	| absoluteError == 0	= maxBound	-- Bodge.+--	| otherwise		= length . takeWhile (< 1) $ iterate (* 10) relativeError	-- CAVEAT: too slow.+	| otherwise		= length $ show (round $ toRational y / absoluteError :: Integer)+	where+		absoluteError :: Result+		absoluteError	= abs (getDiscrepancy y x) / 2	-- NB: the magnitude of the error in 'y', is twice the error in its square-root, 'x'.+
+ src-lib/Factory/Math/Statistics.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 statistics functions.+-}++module Factory.Math.Statistics(+-- * Functions+	getMean,+	getWeightedMean,+--	getDispersionFromMean,+	getVariance,+	getStandardDeviation,+	getAverageAbsoluteDeviation,+	getCoefficientOfVariance,+	nCr,+	nPr+) where++import			Control.Arrow((***))+import			Control.Parallel(par, pseq)+import qualified	Data.Foldable+import qualified	Data.List+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 /mean/ of the specified numbers; <http://en.wikipedia.org/wiki/Mean>.++	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.+-}+getMean :: (+	Data.Foldable.Foldable	foldable,+	Fractional		result,+	Real			value+ )+	=> foldable value+	-> result+getMean foldable+	| denominator == 0	= error "Factory.Math.Statistics.getMean:\tno data => undefined result."+	| otherwise		= realToFrac numerator / fromIntegral denominator+	where+		(numerator, denominator)	= Data.Foldable.foldr (\s -> (+ s) *** succ) (0, 0 :: Int) foldable++{- |+	* Determines the /weighted mean/ of the specified numbers; <http://en.wikipedia.org/wiki/Weighted_arithmetic_mean>.++	* The specified value is only evaluated if the corresponding weight is non-zero.++	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.+-}+getWeightedMean :: (+	Data.Foldable.Foldable	foldable,+	Fractional		result,+	Real			value,+	Real			weight+ )+	=> foldable (value, weight)	-- ^ Each pair consists of a value & the corresponding weight.+	-> result+getWeightedMean foldable+	| denominator == 0	= error "Factory.Math.Statistics.getWeightedMean:\tzero weight => undefined result."+	| otherwise		= numerator / realToFrac denominator+	where+		(numerator, denominator)	= Data.Foldable.foldr (+			\(value, weight)	-> if weight == 0+				then id	--Avoid unnecessarily evaluation.+				else (+ realToFrac value * realToFrac weight) *** (+ weight)+		 ) (0, 0) foldable++{- |+	* 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 'Rational', then it will be free from rounding-errors.+-}+getDispersionFromMean :: (+	Data.Foldable.Foldable	foldable,+	Fractional		result,+	Functor			foldable,+	Real			value+ ) => (Rational -> Rational) -> foldable value -> result+getDispersionFromMean weight foldable	= getMean $ fmap (weight . (+ negate mean) . toRational) foldable	where+	mean :: Rational+	mean	= getMean foldable++{- |+	* Determines the exact /variance/ of the specified numbers; <http://en.wikipedia.org/wiki/Variance>.++	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.+-}+getVariance :: (+	Data.Foldable.Foldable	foldable,+	Fractional		variance,+	Functor			foldable,+	Real			value+ ) => foldable value -> variance+getVariance	= getDispersionFromMean Math.Power.square++-- | Determines the /standard-deviation/ of the specified numbers; <http://en.wikipedia.org/wiki/Standard_deviation>.+getStandardDeviation :: (+	Data.Foldable.Foldable	foldable,+	Floating		result,+	Functor			foldable,+	Real			value+ ) => foldable value -> result+getStandardDeviation	= sqrt . getVariance++{- |+	* Determines the /average absolute deviation/ of the specified numbers; <http://en.wikipedia.org/wiki/Absolute_deviation#Average_absolute_deviation>.++	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.+-}+getAverageAbsoluteDeviation :: (+	Data.Foldable.Foldable	foldable,+	Fractional		result,+	Functor			foldable,+	Real			value+ ) => foldable value -> result+getAverageAbsoluteDeviation	= getDispersionFromMean abs++-- | Determines the /coefficient-of-variance/ of the specified numbers; <http://en.wikipedia.org/wiki/Coefficient_of_variation>.+getCoefficientOfVariance :: (+	Data.Foldable.Foldable	foldable,+	Eq			result,+	Floating		result,+	Functor			foldable,+	Real			value+ ) => foldable value -> 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.Algorithmic factorialAlgorithm, Integral i, Show i)+	=> factorialAlgorithm+	-> i	-- ^ The total number of items from which to select.+	-> i	-- ^ The number of items in a sample.+	-> i	-- ^ The number of combinations.+nCr _ 0 _	= 1+nCr _ _ 0	= 1+nCr factorialAlgorithm n r+	| 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	= numerator `par` (denominator `pseq` numerator `div` denominator)+	where+		[smaller, bigger]	= Data.List.sort [r, n - r]+		numerator		= Math.Implementations.Factorial.risingFactorial (succ bigger) (n - bigger)+		denominator		= Math.Factorial.factorial factorialAlgorithm smaller++-- | The number of /permutations/ of /r/ objects taken from /n/; <http://en.wikipedia.org/wiki/Permutations>.+nPr :: (Integral i, Show i)+	=> i	-- ^ The total number of items from which to select.+	-> i	-- ^ The number of items in a sample.+	-> i	-- ^ The number of permutations.+nPr 0 _	= 1+nPr _ 0	= 1+nPr n r+	| n < 0		= error $ "Factory.Math.Statistics.nPr:\tinvalid n; " ++ show n+	| r < 0		= error $ "Factory.Math.Statistics.nPr:\tinvalid r; " ++ show r+	| n < r		= 0+	| otherwise	= Math.Implementations.Factorial.fallingFactorial n r+
+ src-lib/Factory/Math/Summation.hs view
@@ -0,0 +1,91 @@+{-+	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@]	Provides an alternative algorithm for the summation of /rational/ numbers.+-}++module Factory.Math.Summation(+-- * Functions+	sum',+	sumR',+	sumR+) where++import qualified	Control.DeepSeq+import qualified	Control.Parallel.Strategies+import qualified	Data.List+import qualified	Data.Ratio+import			Data.Ratio((%))+import qualified	ToolShed.Data.List++{- |+	* Sums a list of numbers of arbitrary type.++	* Sparks the summation of @(list-length / chunk-size)@ chunks from the list, each of the specified size (thought the last chunk may be smaller),+	then recursively sums the list of results from each spark.++	* CAVEAT: unless the numbers are large, 'Rational' (requiring /cross-multiplication/), or the list long,+	'sum' is too light-weight for sparking to be productive,+	therefore it is more likely to be the parallelised deep /evaluation/ of list-elements which saves time.+-}+sum' :: (Num n, Control.DeepSeq.NFData n)+	=> ToolShed.Data.List.ChunkLength+	-> [n]+	-> n+sum' chunkLength+	| chunkLength <= 1	= error $ "Factory.Math.Summation.sum':\tinvalid chunk-size; " ++ show chunkLength+	| otherwise		= slave+	where+		slave :: (Num n, Control.DeepSeq.NFData n) => [n] -> n+		slave []	= 0+		slave [x]	= x+		slave l		= slave {-recurse-} . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rdeepseq sum $ ToolShed.Data.List.chunk chunkLength l++{- |+	* Sums a list of /rational/ type numbers.++	* CAVEAT: though faster than 'Data.List.sum', this algorithm has poor space-complexity, making it unsuitable for unrestricted use.+-}+{-# INLINE sumR' #-}	-- This makes a staggering difference.+sumR' :: Integral i => [Data.Ratio.Ratio i] -> Data.Ratio.Ratio i+sumR' l	= foldr (\ratio -> ((Data.Ratio.numerator ratio * (commonDenominator `div` Data.Ratio.denominator ratio)) +)) 0 l % commonDenominator	where+--	commonDenominator	= foldr (lcm . Data.Ratio.denominator) 1 l+	commonDenominator	= Data.List.foldl' (\multiple -> lcm multiple . Data.Ratio.denominator) 1 l	-- Slightly faster.++{- |+	* Sums a list of /rational/ numbers.++	* Sparks the summation of @(list-length / chunk-length)@ chunks from the list, each of the specified size (thought the last chunk may be smaller),+	then recursively sums the list of results from each spark.++	* CAVEAT: memory-use is proportional to chunk-size.+-}+{-# INLINE sumR #-}	-- This makes a staggering difference to calls from other modules.+sumR :: (Integral i, Control.DeepSeq.NFData i)+	=> ToolShed.Data.List.ChunkLength+	-> [Data.Ratio.Ratio i]+	-> Data.Ratio.Ratio i+sumR chunkLength+	| chunkLength <= 1	= error $ "Factory.Math.Summation.sumR:\tinvalid chunk-size; " ++ show chunkLength+	| otherwise		= slave+	where+		slave :: (Integral i, Control.DeepSeq.NFData i) => [Data.Ratio.Ratio i] -> Data.Ratio.Ratio i+		slave l+			| length l <= chunkLength	= sumR' l+			| otherwise			= slave {-recurse-} . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rdeepseq sumR' $ ToolShed.Data.List.chunk chunkLength l
+ src-test/Factory/Test/QuickCheck/ArithmeticGeometricMean.hs view
@@ -0,0 +1,57 @@+{-+	Copyright (C) 2011-2015 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.ArithmeticGeometricMean".+-}++module Factory.Test.QuickCheck.ArithmeticGeometricMean(+-- * Constants+	results,+-- * Types+-- ** Type-synonyms+--	Testable+) where++import qualified	Data.Tuple+import qualified	Factory.Math.ArithmeticGeometricMean	as Math.ArithmeticGeometricMean+import qualified	Factory.Math.Implementations.SquareRoot	as Math.Implementations.SquareRoot+import qualified	Factory.Math.Precision			as Math.Precision+import			Factory.Test.QuickCheck.SquareRoot()+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++type Testable	= Math.Implementations.SquareRoot.Algorithm -> Math.Precision.DecimalDigits -> Math.ArithmeticGeometricMean.AGM -> Int -> Test.QuickCheck.Property++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= mapM Test.QuickCheck.quickCheckResult [prop_symmetrical, prop_bounds]	where+	prop_symmetrical, prop_bounds :: Testable+	prop_symmetrical squareRootAlgorithm decimalDigits agm index	= Math.ArithmeticGeometricMean.isValid agm ==> Test.QuickCheck.label "prop_symmetrical" . and . tail . take index' $ zipWith (==) (+		Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits' agm+	 ) (+		Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits' $ Data.Tuple.swap agm+	 ) where+		decimalDigits'	= succ $ decimalDigits `mod` 64+		index'		= succ $ index `mod` 8++	prop_bounds squareRootAlgorithm decimalDigits agm index	= all ($ agm) [Math.ArithmeticGeometricMean.isValid, uncurry (/=)] ==> Test.QuickCheck.label "prop_bounds" . all (uncurry (>=)) . tail . take index' $ Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits' agm+		where+			decimalDigits'	= 33 {-test is sensitive to rounding-errors-} + (decimalDigits `mod` 96)+			index'		= succ $ index `mod` 5+
+ src-test/Factory/Test/QuickCheck/Factorial.hs view
@@ -0,0 +1,75 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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.Implementations.Factorial".+-}++module Factory.Test.QuickCheck.Factorial(+-- * Constants+	results,+-- * Types+-- ** Type-synonyms+--	Testable+) where++import			Data.Ratio((%))+import qualified	Factory.Math.Factorial			as Math.Factorial+import qualified	Factory.Math.Implementations.Factorial	as Math.Implementations.Factorial+import			Factory.Math.Implementations.Factorial((!/!))+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++instance Test.QuickCheck.Arbitrary Math.Implementations.Factorial.Algorithm	where+	arbitrary	= Test.QuickCheck.elements [Math.Implementations.Factorial.Bisection, Math.Implementations.Factorial.PrimeFactorisation]++type Testable	= Integer -> Integer -> Test.QuickCheck.Property++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_equivalence,+	Test.QuickCheck.quickCheckResult prop_symmetry,+	Test.QuickCheck.quickCheckResult prop_x0,+	Test.QuickCheck.quickCheckResult prop_0n,+	Test.QuickCheck.quickCheckResult prop_ratio,+	Test.QuickCheck.quickCheckResult prop_consistency+ ] where+	prop_equivalence, prop_symmetry, prop_x0, prop_0n :: Testable+	prop_equivalence x n	= Test.QuickCheck.label "prop_equivalence" $ Math.Implementations.Factorial.risingFactorial x n == sign * Math.Implementations.Factorial.fallingFactorial (negate x) n && Math.Implementations.Factorial.fallingFactorial x n == sign * Math.Implementations.Factorial.risingFactorial (negate x) n	where+		sign :: Integer+		sign+			| even n	= 1+			| otherwise	= negate 1++	prop_symmetry x n	= Test.QuickCheck.label "prop_symmetry" $ Math.Implementations.Factorial.risingFactorial x n == Math.Implementations.Factorial.fallingFactorial (pred $ x + n) n++	prop_x0 x _		= Test.QuickCheck.label "prop_x0" $ all (== 1) $ map ($ 0) [Math.Implementations.Factorial.risingFactorial x, Math.Implementations.Factorial.fallingFactorial x]++	prop_0n _ n		= Test.QuickCheck.label "prop_0n" $ all (== if n == 0 then 1 else 0) $ map ($ n) [Math.Implementations.Factorial.risingFactorial 0, Math.Implementations.Factorial.fallingFactorial 0]++	prop_ratio :: Math.Implementations.Factorial.Algorithm -> Integer -> Integer -> Test.QuickCheck.Property+	prop_ratio algorithm i j	= Test.QuickCheck.label "prop_ratio" $ n !/! d == Math.Factorial.factorial algorithm n % Math.Factorial.factorial algorithm d	where+		n	= pred $ i `mod` 100000+		d	= pred $ j `mod` 100000++	prop_consistency :: Math.Implementations.Factorial.Algorithm -> Math.Implementations.Factorial.Algorithm -> Integer -> Test.QuickCheck.Property+	prop_consistency l r i	= l /= r	==> Test.QuickCheck.label "prop_consistency" $ Math.Factorial.factorial l n == Math.Factorial.factorial r n	where+		n	= pred $ i `mod` 100000+
+ src-test/Factory/Test/QuickCheck/Hyperoperation.hs view
@@ -0,0 +1,79 @@+{-+	Copyright (C) 2011-2015 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.Hyperoperation".+-}++module Factory.Test.QuickCheck.Hyperoperation(+-- * Constants+	results+) where++import qualified	Factory.Math.Hyperoperation	as Math.Hyperoperation+import qualified	Test.QuickCheck++type Rank	= Int++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_rankCoincides,+	Test.QuickCheck.quickCheckResult prop_baseCoincides,+	Test.QuickCheck.quickCheckResult prop_hyperExponentCoincides,+	Test.QuickCheck.quickCheckResult prop_succ,+	Test.QuickCheck.quickCheckResult prop_addition,+	Test.QuickCheck.quickCheckResult prop_multiplication,+	Test.QuickCheck.quickCheckResult prop_exponentiation+ ] where+	prop_rankCoincides :: Rank -> Test.QuickCheck.Property+	prop_rankCoincides rank = Test.QuickCheck.label "prop_rankCoincides" $ Math.Hyperoperation.hyperoperation rank' 2 2 == 4	where+		rank' :: Rank+		rank'	= succ $ rank `mod` 1000++	prop_baseCoincides :: Rank -> Integer -> Test.QuickCheck.Property+	prop_baseCoincides rank base	= Test.QuickCheck.label "prop_baseCoincides" $ Math.Hyperoperation.hyperoperation rank' base 1 == base	where+		rank' :: Rank+		rank'	= 2 + (rank `mod` 1000)++	prop_hyperExponentCoincides :: Rank -> Integer -> Test.QuickCheck.Property+	prop_hyperExponentCoincides rank hyperExponent	= Test.QuickCheck.label "prop_hyperExponentCoincides" $ Math.Hyperoperation.hyperoperation rank' 1 hyperExponent' == 1	where+		rank' :: Rank+		rank'	= 3 + (rank `mod` 1000)++		hyperExponent' :: Math.Hyperoperation.HyperExponent+		hyperExponent'	= abs hyperExponent++	prop_succ, prop_addition, prop_multiplication, prop_exponentiation :: Integer -> Integer -> Test.QuickCheck.Property+	prop_succ base hyperExponent			= Test.QuickCheck.label "prop_succ" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.succession base hyperExponent' == succ (fromIntegral hyperExponent')	where+		hyperExponent' :: Math.Hyperoperation.HyperExponent+		hyperExponent'	= abs hyperExponent++	prop_addition base hyperExponent		= Test.QuickCheck.label "prop_addition" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.addition base hyperExponent' == base + fromIntegral hyperExponent'	where+		hyperExponent' :: Math.Hyperoperation.HyperExponent+		hyperExponent'	= abs hyperExponent++	prop_multiplication base hyperExponent		= Test.QuickCheck.label "prop_multiplication" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.multiplication base hyperExponent' == base * fromIntegral hyperExponent'	where+		hyperExponent' :: Math.Hyperoperation.HyperExponent+		hyperExponent'	= abs hyperExponent++	prop_exponentiation base hyperExponent		= Test.QuickCheck.label "prop_exponentiation" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.exponentiation base hyperExponent' == base ^ hyperExponent'	where+		hyperExponent' :: Math.Hyperoperation.HyperExponent+		hyperExponent'	= abs hyperExponent++
+ src-test/Factory/Test/QuickCheck/Interval.hs view
@@ -0,0 +1,43 @@+{-+	Copyright (C) 2011-2015 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(+-- * Constants+	results+) where++import qualified	Data.Ratio+import qualified	Factory.Data.Interval	as Data.Interval+import qualified	Test.QuickCheck++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 1000 } `mapM` [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'	= succ $ minLength `mod` 1000+		ratio'+			| r > 1		= recip r+			| otherwise	= r+			where+				r	= abs ratio
+ src-test/Factory/Test/QuickCheck/MonicPolynomial.hs view
@@ -0,0 +1,77 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Data.MonicPolynomial".+-}++module Factory.Test.QuickCheck.MonicPolynomial(+-- * Constants+	results,+-- * Types+-- ** Type-synonyms+--	P+) where++import			Factory.Data.Ring((=*=), (=+=), (=^))+import			Factory.Test.QuickCheck.Polynomial()+import qualified	Factory.Data.MonicPolynomial	as Data.MonicPolynomial+import qualified	Factory.Data.Polynomial		as Data.Polynomial+import qualified	Factory.Data.QuotientRing	as Data.QuotientRing+import qualified	Factory.Data.Ring		as Data.Ring+import qualified	Test.QuickCheck++instance (+	Integral			c,+	Integral			e,+	Test.QuickCheck.Arbitrary	c,+	Test.QuickCheck.Arbitrary	e,+	Show				c,+	Show				e+ ) => Test.QuickCheck.Arbitrary (Data.MonicPolynomial.MonicPolynomial c e)	where+	arbitrary	= do+		polynomial	<- Test.QuickCheck.arbitrary++		return {-to Gen-monad-} . Data.MonicPolynomial.mkMonicPolynomial $ ((1, succ $ Data.Polynomial.getDegree polynomial) :) `Data.Polynomial.lift` polynomial++type P	= Data.MonicPolynomial.MonicPolynomial Integer Integer++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_quotRem,+	Test.QuickCheck.quickCheckResult prop_quotientRingNormalised,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 50 } prop_perfectPower,+	Test.QuickCheck.quickCheckResult prop_isDivisibleBy+ ] where+	prop_quotRem, prop_quotientRingNormalised :: P -> P -> Test.QuickCheck.Property+	prop_quotRem numerator denominator	= Test.QuickCheck.label "prop_quotRem" $ numerator == denominator =*= quotient =+= remainder	where+		(quotient, remainder)	= numerator `Data.QuotientRing.quotRem'` denominator++	prop_quotientRingNormalised numerator denominator	= Test.QuickCheck.label "prop_quotientRingNormalised" $ all (Data.Polynomial.isNormalised . Data.MonicPolynomial.getPolynomial) [numerator `Data.QuotientRing.quot'` denominator, numerator `Data.QuotientRing.rem'` denominator]++	prop_perfectPower :: P -> Int -> Test.QuickCheck.Property+	prop_perfectPower polynomial power	= Test.QuickCheck.label "prop_perfectPower" $ iterate (`Data.QuotientRing.quot'` polynomial) (polynomial =^ power') !! pred power' == polynomial	where+		power' :: Int+		power'	= succ $ power `mod` 100++	prop_isDivisibleBy :: [P] -> Test.QuickCheck.Property+	prop_isDivisibleBy monicPolynomials	= Test.QuickCheck.label "prop_isDivisibleBy" $ all (Data.QuotientRing.isDivisibleBy (Data.Ring.product' (recip 2) {-TODO-} 10 monicPolynomials)) monicPolynomials++
+ src-test/Factory/Test/QuickCheck/PerfectPower.hs view
@@ -0,0 +1,55 @@+{-+	Copyright (C) 2011-2015 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.PerfectPower".+-}++module Factory.Test.QuickCheck.PerfectPower(+-- * Constants+	results+) where++import qualified	Data.Maybe+import qualified	Factory.Math.PerfectPower	as Math.PerfectPower+import qualified	Factory.Math.Power		as Math.Power+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_maybeSquareNumber,+	Test.QuickCheck.quickCheckResult prop_rewriteRule,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 10000 } prop_notSquare,+	Test.QuickCheck.quickCheckResult prop_isPerfectPower+ ] where+	prop_maybeSquareNumber, prop_notSquare, prop_rewriteRule :: Integer -> Test.QuickCheck.Property+	prop_maybeSquareNumber i	= Test.QuickCheck.label "prop_maybeSquareNumber" $ Math.PerfectPower.maybeSquareNumber (Math.Power.square i) == Just (abs i)++	prop_notSquare i	= abs i > 0	==> Test.QuickCheck.label "prop_notSquare" . Data.Maybe.isNothing $ Math.PerfectPower.maybeSquareNumber (succ $ i ^ (10 {-promote rounding-error using big number-} :: Int))++	prop_rewriteRule i	= Test.QuickCheck.label "prop_rewriteRule" $ Math.PerfectPower.isPerfectPower i' == Math.PerfectPower.isPerfectPower (fromIntegral i' :: Int)	where+		i'	= abs i++	prop_isPerfectPower :: Integer -> Integer -> Test.QuickCheck.Property+	prop_isPerfectPower b e	= Test.QuickCheck.label "prop_isPerfectPower" . Math.PerfectPower.isPerfectPower $ b' ^ e'	where+		b'	= 2 + (b `mod` 10)+		e'	= 2 + (e `mod` 8)++
+ src-test/Factory/Test/QuickCheck/Pi.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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.Pi".+-}++module Factory.Test.QuickCheck.Pi(+-- * Constants+	results,+-- * Types+-- ** Type-synonyms+--	Testable+) where++import			Factory.Test.QuickCheck.Factorial()+import			Factory.Test.QuickCheck.SquareRoot()+import qualified	Factory.Math.Factorial					as Math.Factorial+import qualified	Factory.Math.Implementations.Factorial			as Math.Implementations.Factorial+import qualified	Factory.Math.Implementations.Pi.AGM.Algorithm		as Math.Implementations.Pi.AGM.Algorithm+import qualified	Factory.Math.Implementations.Pi.BBP.Algorithm		as Math.Implementations.Pi.BBP.Algorithm+import qualified	Factory.Math.Implementations.Pi.Borwein.Algorithm	as Math.Implementations.Pi.Borwein.Algorithm+import qualified	Factory.Math.Implementations.Pi.Ramanujan.Algorithm	as Math.Implementations.Pi.Ramanujan.Algorithm+import qualified	Factory.Math.Implementations.Pi.Spigot.Algorithm	as Math.Implementations.Pi.Spigot.Algorithm+import qualified	Factory.Math.Implementations.SquareRoot			as Math.Implementations.SquareRoot+import qualified	Factory.Math.Pi						as Math.Pi+import qualified	Factory.Math.Precision					as Math.Precision+import qualified	Factory.Math.SquareRoot					as Math.SquareRoot+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++#if !MIN_VERSION_base(4,8,0)+import	Control.Applicative((<$>), (<*>))+#endif++instance (+	Test.QuickCheck.Arbitrary	squareRootAlgorithm,+	Math.SquareRoot.Algorithmic	squareRootAlgorithm+ ) => Test.QuickCheck.Arbitrary (Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm)	where+	arbitrary	= Math.Implementations.Pi.AGM.Algorithm.BrentSalamin <$> Test.QuickCheck.arbitrary++instance Test.QuickCheck.Arbitrary Math.Implementations.Pi.BBP.Algorithm.Algorithm	where+	arbitrary	= Test.QuickCheck.elements [Math.Implementations.Pi.BBP.Algorithm.Bellard, Math.Implementations.Pi.BBP.Algorithm.Base65536]++instance (+	Test.QuickCheck.Arbitrary	squareRootAlgorithm,+	Math.SquareRoot.Algorithmic	squareRootAlgorithm,+	Test.QuickCheck.Arbitrary	factorialAlgorithm,+	Math.Factorial.Algorithmic	factorialAlgorithm+ ) => Test.QuickCheck.Arbitrary (Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)	where+	arbitrary	= Test.QuickCheck.oneof [+		Math.Implementations.Pi.Borwein.Algorithm.Borwein1993 <$> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary+	 ]++instance (+	Test.QuickCheck.Arbitrary	squareRootAlgorithm,+	Math.SquareRoot.Algorithmic	squareRootAlgorithm,+	Test.QuickCheck.Arbitrary	factorialAlgorithm,+	Math.Factorial.Algorithmic	factorialAlgorithm+ ) => Test.QuickCheck.Arbitrary (Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)	where+	arbitrary	= Test.QuickCheck.oneof [+		Math.Implementations.Pi.Ramanujan.Algorithm.Classic <$> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary,+		Math.Implementations.Pi.Ramanujan.Algorithm.Chudnovsky <$> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary+	 ]++instance Test.QuickCheck.Arbitrary Math.Implementations.Pi.Spigot.Algorithm.Algorithm	where+	arbitrary	= Test.QuickCheck.elements [Math.Implementations.Pi.Spigot.Algorithm.RabinowitzWagon, Math.Implementations.Pi.Spigot.Algorithm.Gosper]++instance (+	Test.QuickCheck.Arbitrary agm,+	Test.QuickCheck.Arbitrary bbp,+	Test.QuickCheck.Arbitrary borwein,+	Test.QuickCheck.Arbitrary ramanujan,+	Test.QuickCheck.Arbitrary spigot+ ) => Test.QuickCheck.Arbitrary (Math.Pi.Category agm bbp borwein ramanujan spigot)	where+	arbitrary	= Test.QuickCheck.oneof [+		Math.Pi.AGM <$> Test.QuickCheck.arbitrary,+		Math.Pi.BBP <$> Test.QuickCheck.arbitrary,+		Math.Pi.Borwein <$> Test.QuickCheck.arbitrary,+		Math.Pi.Ramanujan <$> Test.QuickCheck.arbitrary,+		Math.Pi.Spigot <$> Test.QuickCheck.arbitrary+	 ]++type Category	= Math.Pi.Category (+	Math.Implementations.Pi.AGM.Algorithm.Algorithm Math.Implementations.SquareRoot.Algorithm+ ) Math.Implementations.Pi.BBP.Algorithm.Algorithm (+	Math.Implementations.Pi.Borwein.Algorithm.Algorithm Math.Implementations.SquareRoot.Algorithm Math.Implementations.Factorial.Algorithm+ ) (+	Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm Math.Implementations.SquareRoot.Algorithm Math.Implementations.Factorial.Algorithm+ ) Math.Implementations.Pi.Spigot.Algorithm.Algorithm++type Testable	= Category -> Category -> Math.Precision.DecimalDigits -> Test.QuickCheck.Property++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= mapM Test.QuickCheck.quickCheckResult [prop_consistency]	where+	prop_consistency :: Testable+	prop_consistency l r decimalDigits	= l /= r	==> Test.QuickCheck.label "prop_consistency" $ Math.Pi.openI l decimalDigits' - Math.Pi.openI r decimalDigits' <= 1 {-rounding error-}	where+		decimalDigits'	= succ $ decimalDigits `mod` 250+
+ src-test/Factory/Test/QuickCheck/Polynomial.hs view
@@ -0,0 +1,122 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Data.Polynomial".+-}++module Factory.Test.QuickCheck.Polynomial(+-- * Constants+	results+) where++import			Control.Arrow((***))+import			Factory.Data.Ring((=*=), (=+=), (=-=), (=^))+import qualified	Data.Numbers.Primes+import qualified	Factory.Data.Polynomial		as Data.Polynomial+import qualified	Factory.Data.QuotientRing	as Data.QuotientRing+import qualified	Factory.Data.Ring		as Data.Ring+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++instance (+	Test.QuickCheck.Arbitrary	c,+	Integral			c,+	Test.QuickCheck.Arbitrary	e,+	Integral			e+ ) => Test.QuickCheck.Arbitrary (Data.Polynomial.Polynomial c e)	where+	arbitrary	= (Data.Polynomial.mkPolynomial . map ((+ negate 4) . (`mod` 8) *** (`mod` 8))) `fmap` Test.QuickCheck.arbitrary++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_congruence,+	Test.QuickCheck.quickCheckResult prop_quotRem,+	Test.QuickCheck.quickCheckResult prop_degree,+	Test.QuickCheck.quickCheckResult prop_ringNormalised,+	Test.QuickCheck.quickCheckResult prop_quotientRingNormalised,+	Test.QuickCheck.quickCheckResult prop_power,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 50 } prop_perfectPower,+	Test.QuickCheck.quickCheckResult prop_normalised,+	Test.QuickCheck.quickCheckResult prop_raiseModuloNormalised,+	Test.QuickCheck.quickCheckResult prop_integralDomain,+	Test.QuickCheck.quickCheckResult prop_isDivisibleBy+ ] where+	prop_congruence :: Int -> Test.QuickCheck.Property+	prop_congruence i	= Test.QuickCheck.label "prop_congruence" $ Data.Polynomial.areCongruentModulo (Data.Polynomial.mkLinear 1 (negate 1) =^ prime) (Data.Polynomial.mkPolynomial [(1, prime), (negate 1, 0)]) prime	where+		prime :: Integer+		prime	= Data.Numbers.Primes.primes !! mod i 100++	prop_quotRem, prop_degree, prop_ringNormalised, prop_quotientRingNormalised :: Data.Polynomial.Polynomial Integer Integer -> Data.Polynomial.Polynomial Integer Integer -> Test.QuickCheck.Property+	prop_quotRem numerator denominator	= denominator' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_quotRem" $ numerator' == denominator' =*= quotient =+= remainder	where+		numerator', denominator' :: Data.Polynomial.Polynomial Rational Integer+		numerator'	= Data.Polynomial.realCoefficientsToFrac numerator+		denominator'	= Data.Polynomial.realCoefficientsToFrac denominator++		(quotient, remainder)	= numerator' `Data.QuotientRing.quotRem'` denominator'++	prop_degree numerator denominator	= denominator' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_degree" $ remainder == Data.Polynomial.zero || Data.Polynomial.getDegree remainder < Data.Polynomial.getDegree denominator'	where+		numerator', denominator' :: Data.Polynomial.Polynomial Rational Integer+		numerator'	= Data.Polynomial.realCoefficientsToFrac numerator+		denominator'	= Data.Polynomial.realCoefficientsToFrac denominator++		remainder	= numerator' `Data.QuotientRing.rem'` denominator'++	prop_ringNormalised l r	= Test.QuickCheck.label "prop_ringNormalised" $ all Data.Polynomial.isNormalised [l =*= r, l =+= r, l =-= r]++	prop_quotientRingNormalised numerator denominator	= denominator' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_quotientRingNormalised" $ all Data.Polynomial.isNormalised [numerator' `Data.QuotientRing.quot'` denominator', numerator' `Data.QuotientRing.rem'` denominator']	where+		numerator', denominator' :: Data.Polynomial.Polynomial Rational Integer+		numerator'	= Data.Polynomial.realCoefficientsToFrac numerator+		denominator'	= Data.Polynomial.realCoefficientsToFrac denominator++	prop_power, prop_perfectPower, prop_normalised :: Data.Polynomial.Polynomial Integer Integer -> Int -> Test.QuickCheck.Property+	prop_power polynomial power	= Test.QuickCheck.label "prop_power" $ polynomial =^ power' == iterate (=*= polynomial) polynomial !! pred power'	where+		power' :: Int+		power'	= succ $ power `mod` 100++	prop_perfectPower polynomial power	= polynomial' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_perfectPower" $ iterate (`Data.QuotientRing.quot'` polynomial') (polynomial' =^ power') !! pred power' == polynomial'	where+		polynomial' :: Data.Polynomial.Polynomial Rational Integer+		polynomial'	= Data.Polynomial.realCoefficientsToFrac polynomial++		power' :: Int+		power'	= succ $ power `mod` 100++	prop_normalised polynomial i	= Test.QuickCheck.label "prop_normalised" $ all Data.Polynomial.isNormalised [+		polynomial =^ power',+		polynomial `Data.Polynomial.mod'` modulus'+	 ] where+		power' :: Int+		power'	= succ $ i `mod` 100++		modulus' :: Integer+		modulus'	= succ $ fromIntegral i `mod` 100++	prop_raiseModuloNormalised :: Data.Polynomial.Polynomial Integer Integer -> Integer -> Integer -> Test.QuickCheck.Property+	prop_raiseModuloNormalised polynomial power modulus	= Test.QuickCheck.label "prop_raiseModuloNormalised" . Data.Polynomial.isNormalised $ Data.Polynomial.raiseModulo polynomial power' modulus'	where+		power', modulus' :: Integer+		power'		= succ $ power `mod` 100+		modulus'	= succ $ modulus `mod` 100++	prop_integralDomain, prop_isDivisibleBy :: [Data.Polynomial.Polynomial Integer Integer] -> Test.QuickCheck.Property+	prop_integralDomain polynomials	= Data.Polynomial.zero `notElem` polynomials	==> Test.QuickCheck.label "prop_integralDomain" $ Data.Ring.product' (recip 2) {-TODO-} 10 polynomials /= Data.Polynomial.zero++	prop_isDivisibleBy polynomials	= Test.QuickCheck.label "prop_isDivisibleBy" . all (Data.QuotientRing.isDivisibleBy (Data.Ring.product' (recip 2) {-TODO-} 10 polynomials')) $ filter (/= Data.Polynomial.zero) polynomials'	where+		polynomials' :: [Data.Polynomial.Polynomial Rational Integer]+		polynomials'	= map Data.Polynomial.realCoefficientsToFrac polynomials+
+ src-test/Factory/Test/QuickCheck/Power.hs view
@@ -0,0 +1,47 @@+{-+	Copyright (C) 2011-2015 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 "Math.Power".+-}++module Factory.Test.QuickCheck.Power(+-- * Constants+	results+) where++import qualified	Data.List+import qualified	Factory.Math.Power	as Math.Power+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_squaresFrom,+	Test.QuickCheck.quickCheckResult prop_raiseModulo+ ] where+	prop_squaresFrom :: Integer -> Integer -> Test.QuickCheck.Property+	prop_squaresFrom from l	= Test.QuickCheck.label "prop_squaresFrom" . (\(x, y) -> y == Math.Power.square x) . Data.List.genericIndex (Math.Power.squaresFrom from) $ abs l++	prop_raiseModulo :: Integer -> Integer -> Integer -> Test.QuickCheck.Property+	prop_raiseModulo b e m	= m /= 0	==> Test.QuickCheck.label "prop_raiseModulo" $ Math.Power.raiseModulo b e' m == (b ^ e') `mod` m	where+		e' :: Integer+		e'	= abs e++
+ src-test/Factory/Test/QuickCheck/Primality.hs view
@@ -0,0 +1,72 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.Implementations.Primality".+-}++module Factory.Test.QuickCheck.Primality(+-- * Constants+	results+) where++import			Factory.Test.QuickCheck.PrimeFactorisation()+import qualified	Data.List+import qualified	Data.Numbers.Primes+import qualified	Factory.Math.Implementations.Primality		as Math.Implementations.Primality+import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation+import qualified	Factory.Math.Primality				as Math.Primality+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++instance Test.QuickCheck.Arbitrary factorisationAlgorithm => Test.QuickCheck.Arbitrary (Math.Implementations.Primality.Algorithm factorisationAlgorithm)	where+	arbitrary	= Test.QuickCheck.oneof [+		Math.Implementations.Primality.AKS `fmap` Test.QuickCheck.arbitrary,+		return {-to Gen-monad-} Math.Implementations.Primality.MillerRabin+	 ]++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 50 } prop_prime,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 50 } prop_composite,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 50 } prop_consistency+ ] where+	prop_prime :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Test.QuickCheck.Property+	prop_prime primalityAlgorithm i	= Test.QuickCheck.label "prop_prime" $ Math.Primality.isPrime primalityAlgorithm prime	where+		normalise n+			| primalityAlgorithm == Math.Implementations.Primality.MillerRabin	= n `mod` 1000000	-- Limited by the efficiency of 'Data.Numbers.Primes.primes'.+			| otherwise								= n `mod` 59++		prime :: Integer+		prime	= Data.List.genericIndex Data.Numbers.Primes.primes $ normalise i++	prop_composite :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> [Integer] -> Test.QuickCheck.Property+	prop_composite primalityAlgorithm l	= length l > 1	==> Test.QuickCheck.label "prop_composite" . not $ Math.Primality.isPrime primalityAlgorithm composite	where+		normalise n+			| primalityAlgorithm == Math.Implementations.Primality.MillerRabin	= n `mod` 1000000+			| otherwise								= n `mod` 10++		composite :: Integer+		composite	= product . map (Data.List.genericIndex Data.Numbers.Primes.primes . normalise) $ take 8 l++	prop_consistency :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Test.QuickCheck.Property+	prop_consistency l r i	= l /= r	==> Test.QuickCheck.label "prop_consistency" $ Math.Primality.isPrime l i' == Math.Primality.isPrime r i'	where+		i'	= i `mod` 512+
+ src-test/Factory/Test/QuickCheck/PrimeFactorisation.hs view
@@ -0,0 +1,100 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.PrimeFactorisation".+-}++module Factory.Test.QuickCheck.PrimeFactorisation(+-- * Constants+	results+) where++import qualified	Data.List+import qualified	Data.Numbers.Primes+import qualified	Factory.Data.PrimeFactors			as Data.PrimeFactors+import qualified	Factory.Data.Exponential			as Data.Exponential+import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation+import qualified	Factory.Math.MultiplicativeOrder		as Math.MultiplicativeOrder+import qualified	Factory.Math.PrimeFactorisation			as Math.PrimeFactorisation+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++instance Test.QuickCheck.Arbitrary Math.Implementations.PrimeFactorisation.Algorithm	where+	arbitrary	= Test.QuickCheck.oneof [+		Test.QuickCheck.elements [+			Math.Implementations.PrimeFactorisation.TrialDivision,+			Math.Implementations.PrimeFactorisation.FermatsMethod+		]+	 ]++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_consistency,+	Test.QuickCheck.quickCheckResult prop_primeFactors,+	Test.QuickCheck.quickCheckResult prop_smoothness,+	Test.QuickCheck.quickCheckResult prop_eulersTotientP,+	Test.QuickCheck.quickCheckResult prop_eulersTotientInequality,+	Test.QuickCheck.quickCheckResult prop_eulersTotient,+	Test.QuickCheck.quickCheckResult prop_lagrange,+	Test.QuickCheck.quickCheckResult prop_multiplicativeOrder,+	Test.QuickCheck.quickCheckResult prop_perfectPower+ ] where+	prop_consistency :: Integer -> Test.QuickCheck.Property+	prop_consistency i	= Test.QuickCheck.label "prop_consistency" $ (Math.PrimeFactorisation.primeFactors Math.Implementations.PrimeFactorisation.TrialDivision i' :: Data.PrimeFactors.Factors Integer Int) == Math.PrimeFactorisation.primeFactors Math.Implementations.PrimeFactorisation.FermatsMethod i'	where+		i' :: Integer+		i'	= succ $ i `mod` 1000000++	prop_primeFactors, prop_smoothness, prop_eulersTotientP, prop_eulersTotientInequality :: Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Test.QuickCheck.Property+	prop_primeFactors algorithm i	= Test.QuickCheck.label "prop_primeFactors" $ Data.PrimeFactors.product' (recip 2) {-TODO-} 10 (Math.PrimeFactorisation.primeFactors algorithm i') == i'	where+		i' :: Integer+		i'	= succ $ i `mod` 1000000++	prop_smoothness algorithm i	= Test.QuickCheck.label "prop_smoothness" $ (Math.PrimeFactorisation.smoothness algorithm !! (2 ^ i')) <= (2 :: Integer)	where+		i' :: Integer+		i'	= i `mod` 20++	prop_eulersTotientP algorithm i	= Test.QuickCheck.label "prop_eulersTotientP" $ Math.PrimeFactorisation.eulersTotient algorithm prime == pred prime	where+		prime :: Integer+		prime	= Data.List.genericIndex Data.Numbers.Primes.primes (i `mod` 10000)++	prop_eulersTotientInequality algorithm i	= i `notElem` [2, 6]	==> Test.QuickCheck.label "prop_eulersTotientInequality" $ Math.PrimeFactorisation.eulersTotient algorithm i' >= floor (sqrt $ fromIntegral i' :: Double)	where+		i'	= succ $ i `mod` 100000++	prop_eulersTotient, prop_lagrange, prop_multiplicativeOrder, prop_perfectPower :: Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Integer -> Test.QuickCheck.Property+	prop_eulersTotient algorithm i power	= Test.QuickCheck.label "prop_eulersTotient" $ Math.PrimeFactorisation.eulersTotient algorithm (base ^ power') == (base ^ pred power') * pred base	where+		base :: Integer+		base	= Data.List.genericIndex Data.Numbers.Primes.primes (i `mod` 8)++		power'	= succ $ power `mod` 5++	prop_lagrange algorithm base modulus	= gcd base modulus' == 1	==> Test.QuickCheck.label "prop_lagrange" $ (Math.PrimeFactorisation.eulersTotient algorithm modulus' `rem` Math.MultiplicativeOrder.multiplicativeOrder algorithm base modulus') == 0	where+		modulus' :: Integer+		modulus'	= 2 + abs modulus++	prop_multiplicativeOrder algorithm base modulus	= gcd base modulus' == 1	==> Test.QuickCheck.label "prop_multiplicativeOrder" $ (+		base ^ Math.MultiplicativeOrder.multiplicativeOrder algorithm base modulus'+	 ) `mod` modulus' == 1	where+		modulus' :: Integer+		modulus'	= 2 + abs modulus++	prop_perfectPower algorithm b e	= Test.QuickCheck.label "prop_perfectPower" $ foldr1 gcd (+		map Data.Exponential.getExponent . Math.PrimeFactorisation.primeFactors algorithm $ (2 + b `mod` 10 :: Integer) ^ (2 + e `mod` 5)+	 ) > 1
+ src-test/Factory/Test/QuickCheck/Primes.hs view
@@ -0,0 +1,101 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.Implementations.Primes".+-}++module Factory.Test.QuickCheck.Primes(+-- * Constants+--	defaultAlgorithm,+	results,+-- * Functions+--	isPrime,+	upperBound+) where++import qualified	Control.DeepSeq+import qualified	Data.Set+import qualified	Factory.Data.PrimeWheel				as Data.PrimeWheel+import qualified	Factory.Math.Implementations.Primality		as Math.Implementations.Primality+import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation+import qualified	Factory.Math.Implementations.Primes.Algorithm	as Math.Implementations.Primes.Algorithm+import qualified	Factory.Math.Primality				as Math.Primality+import qualified	Factory.Math.Primes				as Math.Primes+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))+import qualified	ToolShed.Defaultable++instance Test.QuickCheck.Arbitrary Math.Implementations.Primes.Algorithm.Algorithm	where+	arbitrary	= Test.QuickCheck.oneof [+		return {-to Gen-monad-} Math.Implementations.Primes.Algorithm.TurnersSieve,+		(Math.Implementations.Primes.Algorithm.TrialDivision . (`mod` 10)) `fmap` Test.QuickCheck.arbitrary,+		(Math.Implementations.Primes.Algorithm.SieveOfEratosthenes . (`mod` 10)) `fmap` Test.QuickCheck.arbitrary+	 ]++isPrime :: (Control.DeepSeq.NFData i, Integral i, Show i) => i -> Bool+isPrime	= Math.Primality.isPrime primalityAlgorithm	where+	primalityAlgorithm :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm+	primalityAlgorithm	= ToolShed.Defaultable.defaultValue++upperBound :: Math.Implementations.Primes.Algorithm.Algorithm -> Int -> Int+upperBound algorithm i	= mod i $ if algorithm == Math.Implementations.Primes.Algorithm.TurnersSieve+	then 8192+	else 65536++defaultAlgorithm :: Math.Implementations.Primes.Algorithm.Algorithm+defaultAlgorithm	= ToolShed.Defaultable.defaultValue++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_isPrime,+	Test.QuickCheck.quickCheckResult prop_isComposite,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 50 } prop_consistency,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 25 } prop_rewriteRule,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 25 } prop_sieveOfAtkin,+	Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 25 } prop_sieveOfAtkinRewrite+ ] where+	prop_isPrime, prop_isComposite :: Math.Implementations.Primes.Algorithm.Algorithm -> Int -> Test.QuickCheck.Property+	prop_isPrime algorithm i	= Test.QuickCheck.label "prop_isPrime" . all isPrime . takeWhile (<= upperBound algorithm i) $ (Math.Primes.primes algorithm :: [Int])+	prop_isComposite algorithm i	= Test.QuickCheck.label "prop_isComposite" . not . any isPrime . Data.Set.toList . Data.Set.difference (+		Data.Set.fromList [2 .. upperBound algorithm i]+	 ) . Data.Set.fromList . takeWhile (<= upperBound algorithm i) $ Math.Primes.primes algorithm++	prop_consistency :: Math.Implementations.Primes.Algorithm.Algorithm -> Math.Implementations.Primes.Algorithm.Algorithm -> Int -> Test.QuickCheck.Property+	prop_consistency l r i = l /= r	==> Test.QuickCheck.label "prop_consistency" . and . take (i `mod` 4096) $ zipWith (==) (Math.Primes.primes l) (Math.Primes.primes r :: [Int])++	prop_rewriteRule :: Data.PrimeWheel.NPrimes -> Int -> Test.QuickCheck.Property+	prop_rewriteRule wheelSize i	= Test.QuickCheck.label "prop_rewriteRule" $ toInteger (Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize') !! index :: Int) == (Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize') !! index :: Integer)	where+		wheelSize'	= wheelSize `mod` 8+		index		= i `mod` 131072++	prop_sieveOfAtkin, prop_sieveOfAtkinRewrite :: Int -> Test.QuickCheck.Property+	prop_sieveOfAtkin i	= Test.QuickCheck.label "prop_sieveOfAtkin" $ Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfAtkin prime) !! index == prime	where+		index	= i `mod` 131072++		prime :: Integer+		prime	= Math.Primes.primes defaultAlgorithm !! index++	prop_sieveOfAtkinRewrite i	= Test.QuickCheck.label "prop_sieveOfAtkinRewrite" $ Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfAtkin $ fromIntegral prime) !! index == prime	where+		index	= i `mod` 131072++		prime :: Int+		prime	= Math.Primes.primes defaultAlgorithm !! index+
+ src-test/Factory/Test/QuickCheck/Probability.hs view
@@ -0,0 +1,161 @@+{-+	Copyright (C) 2011-2015 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(+-- * Constants+	results,+-- * Functions+--	normalise+) where++import			Control.Arrow((&&&))+import qualified	Data.List+import qualified	Factory.Math.Probability	as Math.Probability+import qualified	Factory.Math.Statistics		as Math.Statistics+import			Factory.Test.QuickCheck.Factorial()+import qualified	System.Random+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))+import qualified	ToolShed.Data.Pair++-- | Re-profile a distribution to achieve a standard mean & variance.+normalise :: (+	Eq				f,+	Floating			f,+	Math.Probability.Distribution	distribution+ ) => distribution -> [f] -> [f]+normalise distribution+	| variance == 0	= error "Factory.Test.Quick.Probability.normalise:\tzero variance => can't stretch to one."+	| otherwise	= map $ (/ sqrt variance) . (+ negate mean)+	where+		(mean, variance)	= Math.Probability.getMean &&& Math.Probability.getVariance $ distribution++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= let+	isWithinTolerance :: Double -> Double -> Bool+	isWithinTolerance i	= (< recip i) . abs++	prop_logNormalDistribution, prop_logNormalDistribution', prop_normalDistribution, prop_uniformDistribution :: System.Random.RandomGen randomGen => randomGen -> Double -> Double -> Test.QuickCheck.Property+	prop_logNormalDistribution randomGen location scale2	= scale2 /= 0 ==> Test.QuickCheck.label "prop_logNormalDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 1) . (+		Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.+	 ) . (+		normalise distribution :: [Double] -> [Double]+	 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where+		maxParameter	= log . fromInteger $ Math.Probability.maxPreciseInteger (undefined :: Double)+		location'+			| location >= 0	= maxParameter `min` location+			| otherwise	= negate maxParameter `max` location++		distribution	= Math.Probability.LogNormalDistribution location' . min maxParameter $ abs scale2++	prop_logNormalDistribution' randomGen location scale2	= scale2 /= 0 ==> Test.QuickCheck.label "prop_logNormalDistribution'" . all (+		>= (0 :: Double)+	 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.LogNormalDistribution location' . min maxParameter $ abs scale2) randomGen	where+		maxParameter	= log . fromInteger $ Math.Probability.maxPreciseInteger (undefined :: Double)++		location'+			| location >= 0	= maxParameter `min` location+			| otherwise	= negate maxParameter `max` location++-- The mean & standard-deviation are equal when scale^2 == ln 2, but this seems to break-down when the mean is close to zero.+	prop_logNormalDistributionEqual :: System.Random.RandomGen randomGen => randomGen -> Double -> Test.QuickCheck.Property+	prop_logNormalDistributionEqual randomGen location	= location' > 16 {-any lower & it seems to fail-} ==> Test.QuickCheck.label "prop_logNormalDistributionEqual" . (+		< (recip 1000000 :: Double)+	 ) . pred . abs . uncurry (/) . (+		Math.Statistics.getMean &&& Math.Statistics.getStandardDeviation+	 ) $ take 10000 (+		Math.Probability.generatePopulation (Math.Probability.LogNormalDistribution location' $ log 2) randomGen :: [Double]+	 ) where+		maxParameter	= log . fromInteger $ Math.Probability.maxPreciseInteger (undefined :: Double)++		location'+			| location >= 0	= maxParameter `min` location+			| otherwise	= negate maxParameter `max` location++	prop_normalDistribution randomGen mean variance	= variance /= 0 ==> Test.QuickCheck.label "prop_normalDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (+		Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.+	 ) . (+		normalise distribution :: [Double] -> [Double]+	 ) . take 1000 $ Math.Probability.generatePopulation distribution randomGen	where+		distribution	= Math.Probability.NormalDistribution mean $ abs variance++	prop_uniformDistribution randomGen min' max'	= min' /= max' ==> Test.QuickCheck.label "prop_uniformDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (+		Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.+	 ) . (+		normalise distribution :: [Double] -> [Double]+	 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where+		[min'', max'']	= Data.List.sort [min', max']+		distribution	= Math.Probability.UniformDistribution (min'', max'')++	prop_exponentialDistribution, prop_exponentialDistribution', prop_poissonDistribution, prop_poissonDistribution', prop_shiftedGeometricDistribution, prop_shiftedGeometricDistribution' :: System.Random.RandomGen randomGen => randomGen -> Double -> Test.QuickCheck.Property+	prop_exponentialDistribution randomGen lambda	= Test.QuickCheck.label "prop_exponentialDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (+		Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.+	 ) . (+		normalise distribution :: [Double] -> [Double]+	 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where+		distribution	= Math.Probability.ExponentialDistribution . succ {-exclude zero-} $ abs lambda `max` 10 {-cap-}++	prop_exponentialDistribution' randomGen lambda	= lambda /= 0 ==> Test.QuickCheck.label "prop_exponentialDistribution'" . all (+		>= (0 :: Double)+	 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.ExponentialDistribution $ abs lambda) randomGen++	prop_poissonDistribution randomGen lambda	= Test.QuickCheck.label "prop_poissonDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (+		Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.+	 ) . (+		normalise distribution :: [Double] -> [Double]+	 ) . take 1000 $ Math.Probability.generatePopulation distribution randomGen	where+		distribution	= Math.Probability.PoissonDistribution . succ {-exclude zero-} $ abs lambda `max` 10 {-cap-}++	prop_poissonDistribution' randomGen lambda	= lambda /= 0 ==> Test.QuickCheck.label "prop_poissonDistribution'" . all (+		>= (0 :: Double)+	 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.PoissonDistribution $ abs lambda) randomGen++	prop_shiftedGeometricDistribution randomGen probability	= probability' /= 1 ==> Test.QuickCheck.label "prop_shiftedGeometricDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (+		Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.+	 ) . (+		normalise distribution :: [Double] -> [Double]+	 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where+		probability'	= recip . succ $ abs probability	-- Semi-closed unit-interval (0, 1].+		distribution	= Math.Probability.ShiftedGeometricDistribution probability'++	prop_shiftedGeometricDistribution' randomGen probability	= Test.QuickCheck.label "prop_shiftedGeometricDistribution'" . all (+		>= (1 :: Double)+	 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.ShiftedGeometricDistribution probability') randomGen	where+		probability'	= recip . succ $ abs probability	-- Semi-closed unit-interval (0, 1].+ in do+	randomGen	<- System.Random.getStdGen++	sequence [+		Test.QuickCheck.quickCheckResult $ prop_logNormalDistributionEqual randomGen,	-- CAVEAT: known to fail occasionally.+		Test.QuickCheck.quickCheckResult $ prop_logNormalDistribution randomGen,+		Test.QuickCheck.quickCheckResult $ prop_logNormalDistribution' randomGen,+		Test.QuickCheck.quickCheckResult $ prop_normalDistribution randomGen,+		Test.QuickCheck.quickCheckResult $ prop_uniformDistribution randomGen,+		Test.QuickCheck.quickCheckResult $ prop_exponentialDistribution randomGen,+		Test.QuickCheck.quickCheckResult $ prop_exponentialDistribution' randomGen,+		Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 25 } $ prop_poissonDistribution randomGen,+		Test.QuickCheck.quickCheckResult $ prop_poissonDistribution' randomGen,+		Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 50 } $ prop_shiftedGeometricDistribution randomGen,+		Test.QuickCheck.quickCheckResult $ prop_shiftedGeometricDistribution' randomGen+	 ]+
+ src-test/Factory/Test/QuickCheck/Radix.hs view
@@ -0,0 +1,46 @@+{-+	Copyright (C) 2011-2015 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.Radix".+-}++module Factory.Test.QuickCheck.Radix(+-- * Constants+	results,+-- * Types+-- ** Type-synonyms+--	Testable+) where++import qualified	Factory.Math.Radix	as Math.Radix+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++type Testable	= (Int, Integer) -> Test.QuickCheck.Property++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= mapM Test.QuickCheck.quickCheckResult [prop_reversable, prop_digitalRoot]	where+	prop_reversable, prop_digitalRoot :: Testable+	prop_reversable (b, n)	= abs base > 1 ==> Test.QuickCheck.label "prop_reversable" $ Math.Radix.fromBase base (Math.Radix.toBase base n) == n	where+		base	= (b `mod` 73) - 36++	prop_digitalRoot (_, n)	= Test.QuickCheck.label "prop_digitalRoot" $ Math.Radix.digitalRoot n' == 9	where+		n'	= 9 * succ (abs n)+
+ src-test/Factory/Test/QuickCheck/SquareRoot.hs view
@@ -0,0 +1,85 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.Implementations.SquareRoot".+-}++module Factory.Test.QuickCheck.SquareRoot(+-- * Constants+	results+) where++import			Data.Ratio((%))+import qualified	Data.Ratio+import qualified	Factory.Math.Implementations.SquareRoot	as Math.Implementations.SquareRoot+import qualified	Factory.Math.Power			as Math.Power+import qualified	Factory.Math.Precision			as Math.Precision+import qualified	Factory.Math.SquareRoot			as Math.SquareRoot+import qualified	Test.QuickCheck++instance Test.QuickCheck.Arbitrary (Math.Implementations.SquareRoot.Algorithm)	where+	arbitrary	= Test.QuickCheck.oneof [+		Test.QuickCheck.elements [+			Math.Implementations.SquareRoot.BakhshaliApproximation,+			Math.Implementations.SquareRoot.ContinuedFraction,+			Math.Implementations.SquareRoot.HalleysMethod,+			Math.Implementations.SquareRoot.NewtonRaphsonIteration+		],+		Math.Implementations.SquareRoot.TaylorSeries `fmap` Test.QuickCheck.elements [2 .. 32]+	 ]++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= mapM Test.QuickCheck.quickCheckResult [+	prop_accuracy,+	prop_factorable+--	prop_perfectSquare	-- This occasionally fails.+ ] where+	prop_accuracy, prop_factorable, prop_perfectSquare :: (Math.Implementations.SquareRoot.Algorithm, Math.Precision.DecimalDigits, Rational) -> Test.QuickCheck.Property+	prop_accuracy (algorithm, decimalDigits, operand)	= Test.QuickCheck.label "prop_accuracy" . (>= requiredDecimalDigits) . Math.SquareRoot.getAccuracy operand' $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand'	where+		requiredDecimalDigits :: Math.Precision.DecimalDigits+		requiredDecimalDigits	= succ $ decimalDigits `mod` 1024++		operand' :: Rational+		operand'	= abs operand++	prop_factorable (algorithm, decimalDigits, operand)	= Test.QuickCheck.label "prop_factorable" . (<= 5) . (+		* 10 ^ requiredDecimalDigits	-- Promote the relative error.+	 ) . abs $ 1 - (+		Math.SquareRoot.squareRoot algorithm requiredDecimalDigits (+			toRational $ Data.Ratio.numerator operand'+		) / Math.SquareRoot.squareRoot algorithm requiredDecimalDigits (+			toRational $ Data.Ratio.denominator operand'+		)+	 ) / Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand' where+		requiredDecimalDigits :: Math.Precision.DecimalDigits+		requiredDecimalDigits	= succ $ decimalDigits `mod` 1024++		operand' :: Rational+		operand'	= succ $ abs operand++	prop_perfectSquare (algorithm, decimalDigits, operand)	= Test.QuickCheck.label "prop_perfectSquare" . Math.SquareRoot.isPrecise perfectSquare $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits perfectSquare	where+		requiredDecimalDigits :: Math.Precision.DecimalDigits+		requiredDecimalDigits	= succ $ decimalDigits `mod` 32768++		operand', perfectSquare :: Rational+		operand'	= (abs (Data.Ratio.numerator operand) `min` (2 ^ (32 :: Int))) % (abs (Data.Ratio.denominator operand) `min` (2 ^ (32 :: Int)))	-- Avoid floating-point rounding-errors in 'Math.SquareRoot.rSqrt'.+		perfectSquare	= Math.Power.square operand'+
+ src-test/Factory/Test/QuickCheck/Statistics.hs view
@@ -0,0 +1,125 @@+{-+	Copyright (C) 2011-2015 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.Statistics".+-}++module Factory.Test.QuickCheck.Statistics(+-- * Constants+	results+) where++import qualified	Data.Array+import qualified	Data.List+import qualified	Data.Map+import qualified	Data.Numbers.Primes+import qualified	Data.Set+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+import			Test.QuickCheck((==>))++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	Test.QuickCheck.quickCheckResult prop_nC0,+	Test.QuickCheck.quickCheckResult prop_nC1,+	Test.QuickCheck.quickCheckResult prop_sum,+	Test.QuickCheck.quickCheckResult prop_symmetry,+	Test.QuickCheck.quickCheckResult prop_prime,+	Test.QuickCheck.quickCheckResult prop_nP0,+	Test.QuickCheck.quickCheckResult prop_nP1,+	Test.QuickCheck.quickCheckResult prop_zeroVariance,+	Test.QuickCheck.quickCheckResult prop_zeroAverageAbsoluteDeviation,+	Test.QuickCheck.quickCheckResult prop_balance,+	Test.QuickCheck.quickCheckResult prop_varianceRelocated,+	Test.QuickCheck.quickCheckResult prop_varianceScaled,+	Test.QuickCheck.quickCheckResult prop_varianceOrder,+	Test.QuickCheck.quickCheckResult prop_equivalence,+	Test.QuickCheck.quickCheckResult prop_varianceOfArray,+	Test.QuickCheck.quickCheckResult prop_varianceOfMap,+	Test.QuickCheck.quickCheckResult prop_meanOfSet,+	Test.QuickCheck.quickCheckResult prop_weightedMeanRational,+	Test.QuickCheck.quickCheckResult prop_weightedMeanInteger,+	Test.QuickCheck.quickCheckResult prop_weightedMeanUniformDenominator+ ] 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	= succ $ abs i++	prop_sum algorithm i	= Test.QuickCheck.label "prop_sum" $ sum (Math.Statistics.nCr algorithm n `map` [0 .. n]) == 2 ^ n	where+		n	= succ $ 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_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_nP1 i	= Test.QuickCheck.label "prop_nP1" $ Math.Statistics.nPr n 1 == n	where+		n	= succ $ abs i++	prop_zeroVariance, prop_zeroAverageAbsoluteDeviation :: Rational -> Test.QuickCheck.Property+	prop_zeroVariance x			= Test.QuickCheck.label "prop_zeroVariance" $ Math.Statistics.getVariance (replicate 32 x) == (0 :: Rational)+	prop_zeroAverageAbsoluteDeviation x	= Test.QuickCheck.label "zeroAverageAbsoluteDeviation" $ Math.Statistics.getAverageAbsoluteDeviation (replicate 32 x) == (0 :: Rational)++	prop_balance, prop_varianceRelocated, prop_varianceScaled, prop_varianceOrder, prop_equivalence, prop_varianceOfMap, prop_meanOfSet, prop_varianceOfArray :: [Integer] -> Test.QuickCheck.Property+	prop_balance l			= not (null l)	==> Test.QuickCheck.label "prop_balance" . (== 0) . abs . sum $ map (\i -> toRational i - Math.Statistics.getMean l) l+	prop_varianceRelocated l	= not (null l)	==> Test.QuickCheck.label "prop_varianceRelocated" $ (Math.Statistics.getVariance l :: Rational) == Math.Statistics.getVariance (map succ l)+	prop_varianceScaled l		= not (null l)	==> Test.QuickCheck.label "prop_varianceScaled" $ (4 * Math.Statistics.getVariance l :: 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) :: 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 :: Rational)+	prop_varianceOfArray l		= not (null l)	==> Test.QuickCheck.label "prop_varianceOfArray" $ Math.Statistics.getVariance (Data.Array.array (1, length l) $ zip [1 ..] l) == (Math.Statistics.getVariance l :: Rational)+	prop_varianceOfMap l		= not (null l)	==> Test.QuickCheck.label "prop_varianceOfMap" $ Math.Statistics.getVariance (Data.Map.fromList $ zip [0 :: Int ..] l) == (Math.Statistics.getVariance l :: Rational)+	prop_meanOfSet l		= not (null l')	==> Test.QuickCheck.label "prop_meanOfSet" $ Math.Statistics.getMean (Data.Set.fromList l') == (Math.Statistics.getMean l' :: Rational)	where+		l'	= Data.List.nub l++	prop_weightedMeanRational :: [(Rational, Rational)] -> Test.QuickCheck.Property+	prop_weightedMeanRational assoc	= (denominator /= 0) ==> Test.QuickCheck.label "prop_weightedMeanRational" $ Math.Statistics.getWeightedMean assoc == (+		sum (map (uncurry (*)) assoc) / denominator+	 ) where+		denominator	= sum $ map snd assoc+++	prop_weightedMeanInteger :: [(Integer, Integer)] -> Test.QuickCheck.Property+	prop_weightedMeanInteger assoc	= (denominator /= 0) ==> Test.QuickCheck.label "prop_weightedMeanInteger" $ Math.Statistics.getWeightedMean assoc == (+		toRational (+			sum $ map (+				uncurry (*)+			) assoc+		) / toRational denominator+	 ) where+		denominator	= sum $ map snd assoc++	prop_weightedMeanUniformDenominator :: [Rational] -> Integer -> Test.QuickCheck.Property+	prop_weightedMeanUniformDenominator numerators i	= (not (null numerators) && i /= 0) ==> Test.QuickCheck.label "prop_weightedMeanUniformDenominator" $ Math.Statistics.getWeightedMean (+		zip numerators $ repeat i+	 ) == (+		Math.Statistics.getMean numerators :: Rational+	 )+
+ src-test/Factory/Test/QuickCheck/Summation.hs view
@@ -0,0 +1,42 @@+{-+	Copyright (C) 2011-2015 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.Summation".+-}++module Factory.Test.QuickCheck.Summation(+-- * Constants+	results+) where++import qualified	Factory.Math.Summation	as Math.Summation+import qualified	Test.QuickCheck+import			Test.QuickCheck((==>))++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= mapM Test.QuickCheck.quickCheckResult [prop_sum, prop_sumR]	where+	prop_sum, prop_sumR :: Int -> [Rational] -> Test.QuickCheck.Property+	prop_sum chunkSize l	= not (null l)	==> Test.QuickCheck.label "prop_sum" $ Math.Summation.sum' chunkSize' l == sum l	where+		chunkSize'	= 2 + (chunkSize `mod` length l)++	prop_sumR chunkSize l	= not (null l)	==> Test.QuickCheck.label "prop_sumR" $ Math.Summation.sumR chunkSize' l == sum l	where+		chunkSize'	= 2 + (chunkSize `mod` length l)++
+ src-test/Main.hs view
@@ -0,0 +1,76 @@+{-+	Copyright (C) 2015 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@]++	* The entry-point to the application's test-suite.+-}++module Main(main) where++import			Control.Arrow((***))+import qualified	Control.Monad+import qualified	Factory.Test.QuickCheck.ArithmeticGeometricMean	as Test.QuickCheck.ArithmeticGeometricMean+import qualified	Factory.Test.QuickCheck.Factorial		as Test.QuickCheck.Factorial+import qualified	Factory.Test.QuickCheck.Hyperoperation		as Test.QuickCheck.Hyperoperation+import qualified	Factory.Test.QuickCheck.Interval		as Test.QuickCheck.Interval+import qualified	Factory.Test.QuickCheck.MonicPolynomial		as Test.QuickCheck.MonicPolynomial+import qualified	Factory.Test.QuickCheck.PerfectPower		as Test.QuickCheck.PerfectPower+import qualified	Factory.Test.QuickCheck.Pi			as Test.QuickCheck.Pi+import qualified	Factory.Test.QuickCheck.Polynomial		as Test.QuickCheck.Polynomial+import qualified	Factory.Test.QuickCheck.Power			as Test.QuickCheck.Power+import qualified	Factory.Test.QuickCheck.Primality		as Test.QuickCheck.Primality+import qualified	Factory.Test.QuickCheck.PrimeFactorisation	as Test.QuickCheck.PrimeFactorisation+import qualified	Factory.Test.QuickCheck.Primes			as Test.QuickCheck.Primes+import qualified	Factory.Test.QuickCheck.Probability		as Test.QuickCheck.Probability+import qualified	Factory.Test.QuickCheck.Radix			as Test.QuickCheck.Radix+import qualified	Factory.Test.QuickCheck.SquareRoot		as Test.QuickCheck.SquareRoot+import qualified	Factory.Test.QuickCheck.Statistics		as Test.QuickCheck.Statistics+import qualified	Factory.Test.QuickCheck.Summation		as Test.QuickCheck.Summation+import qualified	System.Exit+import qualified	ToolShed.Test.QuickCheck.Result++-- | Entry-point.+main :: IO ()+main	= mapM_ (+	snd {-exit-status-} . (+		putStrLn . (++ ":") *** (+			>>= (`Control.Monad.unless` System.Exit.exitFailure) . all ToolShed.Test.QuickCheck.Result.isSuccessful+		)+	)+ ) [+	("ArithmeticGeometricMean",	Test.QuickCheck.ArithmeticGeometricMean.results),+	("Factorial",			Test.QuickCheck.Factorial.results),+	("Hyperoperation",		Test.QuickCheck.Hyperoperation.results),+	("Interval",			Test.QuickCheck.Interval.results),+	("MonicPolynomial",		Test.QuickCheck.MonicPolynomial.results),+	("PerfectPower",		Test.QuickCheck.PerfectPower.results),+	("Pi",				Test.QuickCheck.Pi.results),+	("Polynomial",			Test.QuickCheck.Polynomial.results),+	("Power",			Test.QuickCheck.Power.results),+	("Primality",			Test.QuickCheck.Primality.results),+	("PrimeFactorisation",		Test.QuickCheck.PrimeFactorisation.results),+	("Primes",			Test.QuickCheck.Primes.results),+	("Probability",			Test.QuickCheck.Probability.results),+	("Radix",			Test.QuickCheck.Radix.results),+	("SquareRoot",			Test.QuickCheck.SquareRoot.results),+	("Statistics",			Test.QuickCheck.Statistics.results),+	("Summation",			Test.QuickCheck.Summation.results)+ ]+
− src/Factory/Data/Exponential.hs
@@ -1,89 +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@]--	* Describes a simple numeric type, designed to contain an /exponential/ number.--	* <http://en.wikipedia.org/wiki/Exponentiation>.--}--module Factory.Data.Exponential(--- * Types--- ** Type-synonyms-	Exponential,--- * Functions-	evaluate,-	invert,--- ** Accessors-	getBase,-	getExponent,--- ** Constructors-	rightIdentity,--- ** Operators-	(<^),-	(=~)-) where--import qualified	Control.Arrow--infix 4 =~	-- Same as (==).-infixr 8 <^	-- Same as (^).---- | Describes an /exponential/, in terms of its /base/ and /exponent/.-type Exponential base exponent	= (base, exponent)---- | Accessor.-{-# INLINE getBase #-}-getBase :: Exponential base exponent -> base-getBase	= fst---- | Accessor.-{-# INLINE getExponent #-}-getExponent :: Exponential base exponent -> exponent-getExponent	= snd--{- |-	* Construct an 'Exponential' merely raised to the 1st power.--	* The value of the resulting exponential is the same as specified 'base'; <http://en.wikipedia.org/wiki/Identity_element>.--}-rightIdentity :: Num exponent => base -> Exponential base exponent-rightIdentity x	= (x, 1)---- | Evaluate the specified 'Exponential', returning the resulting number.-{-# INLINE evaluate #-}-evaluate :: (Num base, Integral exponent) => Exponential base exponent -> base-evaluate	= uncurry (^)	-- CAVEAT: in this eta-reduced form, it'll only be inlined when called without arguments.---- | True if the /bases/ are equal.-(=~) :: Eq base => Exponential base exponent -> Exponential base exponent -> Bool-(l, _) =~ (r, _)	= l == r---- | Raise the specified 'Exponential' to a power.-(<^) :: Num exponent-	=> Exponential base exponent	-- ^ The operand.-	-> exponent			-- ^ The power to which the exponential is to be raised.-	-> Exponential base exponent	-- ^ The result.-(b, e) <^ power	= (b, e * power)---- | Invert the value, by negating the exponent.-invert :: Num exponent => Exponential base exponent -> Exponential base exponent-invert	= Control.Arrow.second negate-
− src/Factory/Data/Interval.hs
@@ -1,201 +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@]--	* 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,-	mkBounded,--- * Functions---	divideAndConquer,-	elem',---	getLength,-	normalise,-	product',-	shift,-	splitAt',-	toList,--- ** Accessors-	getMinBound,-	getMaxBound,--- ** Constructors-	precisely,--- ** Predicates-	isReversed-) where--import			Control.Arrow((***), (&&&))-import qualified	Control.Parallel.Strategies-import qualified	Data.Monoid-import qualified	Data.Ratio-import qualified	Data.Tuple-import qualified	ToolShed.Data.Pair---- | 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 /unsigned closed unit-interval/; <http://en.wikipedia.org/wiki/Unit_interval>.-closedUnitInterval :: Num n => Interval n-closedUnitInterval	= (0, 1)---- | Construct an /interval/ from a bounded type.-mkBounded :: Bounded endPoint => Interval endPoint-mkBounded	= (minBound, maxBound)---- | Construct an /interval/ from a single value.-precisely :: endPoint -> Interval endPoint-precisely	= id &&& id---- | 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	= ToolShed.Data.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	= uncurry (&&) . ((<= 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	= Data.Tuple.swap b-	| otherwise	= b---- | Bisect the /interval/ at the specified /end-point/; which should be between the two existing /end-points/.-splitAt' :: (-	Enum	endPoint,-	Num	endPoint,-	Ord	endPoint,-	Show	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), (succ i, r))--{- |-	* The distance between the endpoints,-	which for 'Integral' quantities is the same as the number of items in closed interval; though the latter concept would return type 'Int'.--	* CAVEAT: the implementation accounts for the potential fence-post error, for closed intervals of integers,-	but this results in the opposite error when used with /Fractional/ quantities.-	So, though most of the module merely requires 'Enum', this function is further restricted to 'Integral'.--}-{-# INLINE getLength #-}-getLength :: Integral endPoint => Interval endPoint -> endPoint-getLength (l, r)	= succ r - l--{- |-	* Converts 'Interval' to a list by enumerating the values.--	* CAVEAT: produces rather odd results for 'Fractional' types, but no stranger than considering such types Enumerable in the first place.--}-{-# INLINE toList #-}-toList :: Enum endPoint => Interval endPoint -> [endPoint]-toList	= uncurry enumFromTo	-- CAVEAT: in this eta-reduced form, it'll only be inlined when called without arguments.--{- |-	* 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 :: (Data.Monoid.Monoid monoid, Integral i, Show i)-	=> (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 . Control.Parallel.Strategies.withStrategy (-				Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rseq Control.Parallel.Strategies.rseq-			) . ToolShed.Data.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, Show 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
@@ -1,98 +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@]--	* Describes a /monic polynomial; <http://en.wikipedia.org/wiki/Monic_polynomial#Classifications>;-	ie. in which the /coefficient/ of the /leading term/ is one.--}--module Factory.Data.MonicPolynomial(--- * Types--- ** Data-types,-	MonicPolynomial(getPolynomial),	-- Hide the data-constructor.--- * Functions--- ** Constructors-	mkMonicPolynomial-) where--import qualified	Control.Arrow-import qualified	Factory.Data.Monomial		as Data.Monomial-import			Factory.Data.Polynomial((*=))-import qualified	Factory.Data.Polynomial		as Data.Polynomial-import qualified	Factory.Data.QuotientRing	as Data.QuotientRing-import			Factory.Data.Ring((=*=), (=+=), (=-=))-import qualified	Factory.Data.Ring		as Data.Ring-import qualified	ToolShed.Data.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 {-	getPolynomial	:: Data.Polynomial.Polynomial c e-} deriving (Eq, Show)---- | Smart constructor. Constructs an arbitrary /monic polynomial/.-mkMonicPolynomial :: (-	Eq	c,-	Num	c,-	Ord	e,-	Show	c,-	Show	e- ) => Data.Polynomial.Polynomial c e -> MonicPolynomial c e-mkMonicPolynomial polynomial-	| not $ Data.Polynomial.isMonic polynomial	= error $ "Factory.Data.MonicPolynomial.mkMonicPolynomial:\tnot monic; " ++ show polynomial-	| otherwise					= MkMonicPolynomial polynomial--{--	* This instance-declaration merely delegates to the 'Data.Polynomial.Polynomial' payload.--	* CAVEAT: it's not strictly an instance of this class, since the result of some methods isn't /monic/.--}-instance (-	Eq	c,-	Num	c,-	Num	e,-	Ord	e,-	Show	c,-	Show	e- ) => Data.Ring.Ring (MonicPolynomial c e)	where-	MkMonicPolynomial l =*= MkMonicPolynomial r	= MkMonicPolynomial $ l =*= r-	MkMonicPolynomial l =+= MkMonicPolynomial r	= mkMonicPolynomial $ l =+= r	-- CAVEAT: potentially non-monic.---	additiveInverse (MkMonicPolynomial p)		= MkMonicPolynomial $ Data.Ring.additiveInverse p	-- CAVEAT: not monic !-	additiveInverse _				= error "Factory.Data.MonicPolynomial.additiveInverse:\tresult isn't monic"-	multiplicativeIdentity				= MkMonicPolynomial Data.Ring.multiplicativeIdentity-	additiveIdentity				= MkMonicPolynomial Data.Ring.additiveIdentity	-- CAVEAT: not monic !---- Since the /leading term/ of the /denominator/ is one, the /coefficient/ isn't required to implement 'Fractional'.-instance (-	Eq	c,-	Num	c,-	Num	e,-	Ord	e,-	Show	c,-	Show	e- ) => Data.QuotientRing.QuotientRing (MonicPolynomial c e)	where-	MkMonicPolynomial polynomialN `quotRem'` MkMonicPolynomial polynomialD	= ToolShed.Data.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)-			| otherwise									= Control.Arrow.first (Data.Polynomial.lift (quotient :)) $ longDivide (numerator =-= polynomialD *= quotient)-			where---				quotient :: Num e => Data.Monomial.Monomial c e-				quotient	= Data.Polynomial.getLeadingTerm numerator `Data.Monomial.shiftExponent` negate (Data.Monomial.getExponent $ Data.Polynomial.getLeadingTerm polynomialD)-
− src/Factory/Data/Monomial.hs
@@ -1,148 +0,0 @@-{--	Copyright (C) 2011-2015 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 <http://en.wikipedia.org/wiki/Monomial> and operations on it.--	* A /monomial/ is merely a /polynomial/ with a single non-zero term; cf. /Binomial/.--}--module Factory.Data.Monomial(--- * Types--- ** Type-synonyms-	Monomial,--- * Functions-	double,-	mod',-	negateCoefficient,-	realCoefficientToFrac,-	shiftCoefficient,-	shiftExponent,-	square,--- ** Accessors-	getExponent,-	getCoefficient,--- ** Operators-	(<=>),-	(</>),-	(<*>),-	(=~),--- ** Predicates-	isMonomial-) where--import Prelude hiding ((<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.-import qualified	Control.Arrow--infix 4 <=>	-- Same as (==).-infix 4 =~	-- Same as (==).-infixl 7 </>	-- Same as (/).-infixl 7 <*>	-- Same as (*).--{- |-	* The type of an arbitrary monomial.--	* CAVEAT: though a /monomial/ has an integral power, this contraint is only imposed at the function-level.--}-type Monomial coefficient exponent	= (coefficient, exponent)---- | Accessor.-{-# INLINE getCoefficient #-}-getCoefficient :: Monomial c e -> c-getCoefficient	= fst---- | Accessor.-{-# INLINE getExponent #-}-getExponent :: Monomial c e -> e-getExponent	= snd--{- |-	* 'True' if the /exponent/ is both integral and non-/negative/.--	* CAVEAT: one can't even call this function unless the /exponent/ is integral.--}-isMonomial :: Integral e => Monomial c e -> Bool-isMonomial	= (>= 0) . getExponent---- | Compares the /exponents/ of the specified 'Monomial's.-{-# INLINE (<=>) #-}-(<=>) :: Ord e => Monomial c e -> Monomial c e -> Ordering-(_, l) <=> (_, r)	= l `compare` r---- | True if the /exponents/ are equal.-(=~) :: Eq e => Monomial c e -> Monomial c e -> Bool-(_, l) =~ (_, r)	= l == r---- | Multiply the two specified 'Monomial's.-{-# INLINE (<*>) #-}-(<*>) :: (Num c, Num e) => Monomial c e -> Monomial c e -> Monomial c e-(cL, eL) <*> (cR, eR)	= (cL * cR, eL + eR)---- | Divide the two specified 'Monomial's.-(</>) :: (Eq c, Fractional c, Num e)-	=> Monomial c e	-- ^ Numerator.-	-> Monomial c e	-- ^ Denominator.-	-> Monomial c e-(cN, eN) </> (1, eD)	= (cN, eN - eD)-(cN, eN) </> (cD, eD)	= (cN / cD, eN - eD)---- | Square the specified 'Monomial'.-square :: (Num c, Num e) => Monomial c e -> Monomial c e-square (c, e)	= (c ^ (2 :: Int), 2 * e)---- | Double the specified 'Monomial'.-{-# INLINE double #-}-double :: Num c => Monomial c e -> Monomial c e-double (c, e)	= (2 * c, e)---- | Shift the /coefficient/, by the specified amount.-{-# INLINE shiftCoefficient #-}-shiftCoefficient :: Num c-	=> Monomial c e-	-> c	-- ^ The magnitude of the shift.-	-> Monomial c e--- m `shiftCoefficient` i	= Control.Arrow.first (+ i) m	-- CAVEAT: Too slow.-(c, e) `shiftCoefficient` i	= (c + i, e)---- | Shift the /exponent/, by the specified amount.-{-# INLINE shiftExponent #-}-shiftExponent :: Num e-	=> Monomial c e-	-> e	-- ^ The magnitude of the shift.-	-> Monomial c e--- m `shiftExponent` i	= Control.Arrow.second (+ i) m	-- CAVEAT: Too slow.-(c, e) `shiftExponent` i	= (c, e + i)---- | Negate the coefficient.-negateCoefficient :: Num c => Monomial c e -> Monomial c e-negateCoefficient	= Control.Arrow.first negate---- | Reduce the coefficient using /modular/ arithmetic.-{-# INLINE mod' #-}-mod' :: Integral c-	=> Monomial c e-	-> c	-- ^ Modulus.-	-> Monomial c e-monomial `mod'` modulus	= Control.Arrow.first (`mod` modulus) monomial---- | Convert the type of the /coefficient/.-realCoefficientToFrac :: (Real r, Fractional f) => Monomial r e -> Monomial f e-realCoefficientToFrac	= Control.Arrow.first realToFrac-
− src/Factory/Data/Polynomial.hs
@@ -1,375 +0,0 @@-{--	Copyright (C) 2011-2015 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 <http://en.wikipedia.org/wiki/Univariate> polynomial and operations on it.--	* <http://en.wikipedia.org/wiki/Polynomial>.--	* <http://mathworld.wolfram.com/Polynomial.html>.--}--module Factory.Data.Polynomial(--- * Types--- ** Type-synonyms---	MonomialList,--- ** Data-types,-	Polynomial,--- * Constants-	zero,-	one,--- * Functions-	evaluate,-	getDegree,-	getLeadingTerm,-	lift,-	mod',-	normalise,---	pruneCoefficients,-	raiseModulo,-	realCoefficientsToFrac,-	terms,--- ** Constructors-	mkConstant,-	mkLinear,-	mkPolynomial,--- ** Operators-	(*=),--- ** Predicates-	areCongruentModulo,-	inAscendingOrder,-	inDescendingOrder,---	inOrder,-	isMonic,-	isMonomial,-	isNormalised,-	isPolynomial,---	isReduced,-	isZero-) where--import Prelude hiding ((<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.-import			Control.Arrow((&&&))-import qualified	Control.Arrow-import qualified	Data.List-import			Factory.Data.Monomial((<*>), (</>), (<=>), (=~))-import qualified	Factory.Data.Monomial		as Data.Monomial-import qualified	Factory.Data.QuotientRing	as Data.QuotientRing-import			Factory.Data.Ring((=*=), (=+=), (=-=))-import qualified	Factory.Data.Ring		as Data.Ring--infixl 7 *=	-- Same as (*).---- | The guts of a 'Polynomial'.-type MonomialList coefficient exponent	= [Data.Monomial.Monomial coefficient exponent]--{- |-	* The type of an arbitrary /univariate/ polynomial;-	actually it's more general, since it permits negative powers (<http://en.wikipedia.org/wiki/Laurent_polynomial>s).-	It can't describe /multivariate/ polynomials, which would require a list of /exponents/.-	Rather than requiring the /exponent/ to implement the /type-class/ 'Integral', this is implemented at the function-level, as required.--	* The structure permits gaps between /exponents/,-	in which /coefficients/ are inferred to be zero, thus enabling efficient representation of sparse polynomials.--	* CAVEAT: the 'MonomialList' is required to;-	be ordered by /descending/ exponent (ie. reverse <http://en.wikipedia.org/wiki/Monomial_order>);-	have had zero coefficients removed;-	and to have had /like/ terms merged;-	so the raw data-constructor isn't exported.--}-newtype {- Integral exponent => -} Polynomial coefficient exponent	= MkPolynomial {-	getMonomialList	:: MonomialList coefficient exponent	-- ^ Accessor.-} deriving (Eq, Show)---- | Makes /Polynomial/ a 'Data.Ring.Ring', over the /field/ composed from all possible /coefficients/; <http://en.wikipedia.org/wiki/Polynomial_ring>.-instance (-	Eq	c,-	Num	c,-	Num	e,-	Ord	e- ) => Data.Ring.Ring (Polynomial c e) where-	MkPolynomial [] =*= _	= zero-	_ =*= MkPolynomial []	= zero-	polynomialL =*= polynomialR---		| polynomialL == one			= polynomialR	-- Counterproductive.---		| polynomialR == one			= polynomialL	-- Counterproductive.-		| terms polynomialL > terms polynomialR	= polynomialL `times` polynomialR-		| otherwise				= polynomialR `times` polynomialL-		where-			l `times` r	= {-# SCC "times" #-} Data.Ring.sum' (recip 2) {-TODO-} 10 {-empirical-} . map (l *=) $ getMonomialList r--	MkPolynomial [] =+= p				= p-	p =+= MkPolynomial []				= p-	MkPolynomial listL =+= MkPolynomial listR	= {-# SCC "merge" #-} MkPolynomial $ merge listL listR	where-		merge [] r			= r-		merge l []			= l-		merge l@(lh : ls) r@(rh : rs)	= case lh <=> rh of-			GT	-> lh : merge ls r-			LT	-> rh : merge l rs-			_	-> case lh `Data.Monomial.shiftCoefficient` Data.Monomial.getCoefficient rh of-				(0, _)		-> merge ls rs-				monomial	-> monomial : merge ls rs--	additiveInverse		= lift (Data.Monomial.negateCoefficient `map`)-	multiplicativeIdentity	= one-	additiveIdentity	= zero--{--	Override the default implementation,-	in order to take advantage of the symmetry under reflection about the main diagonal,-	in the square matrix of products formed from the multiplication of each term by each term.-	Eg:-		(ax^3 + bx^2 + cx + d)^2 = [-			(a^2x^6 + abx^5 + acx^4 + adx^3) +-			(bax^5 + b^2x^4 + bcx^3 + bdx^2) +-			(cax^4 + cbx^3 + c^2x^2 + cdx) +-			(dax^3 + dbx^2 + dcx + d^2)-		]--		= (a^2x^6 + b^2x^4 + c^2x^2 + d^2) + 2 * [ax^3 * (bx^2 + cx + d) + bx^2 * (cx + d) + cx * (d)]--}-	square (MkPolynomial [])	= zero-	square p			= Data.Ring.sum' (recip 2) {-TODO-} 10 {-empirical-} $ diagonal : corners	where-		diagonal	= {-# SCC "diagonal" #-} map Data.Monomial.square `lift` p-		corners		= {-# SCC "corners" #-} uncurry (-			zipWith (*=)-		 ) $ map MkPolynomial . init {-remove terminal null-} . Data.List.tails . tail &&& map Data.Monomial.double $ getMonomialList p---- | Defines the ability to divide /polynomials/.-instance (-	Eq		c,-	Fractional	c,-	Num		e,-	Ord		e- ) => Data.QuotientRing.QuotientRing (Polynomial c e)	where-{--	Uses /Euclidian division/.-	<http://en.wikipedia.org/wiki/Polynomial_long_division>.-	<http://demonstrations.wolfram.com/PolynomialLongDivision/>.--}-	_ `quotRem'` MkPolynomial []		= error "Factory.Data.Polynomial.quotRem':\tzero denominator."-	polynomialN `quotRem'` polynomialD	= longDivide polynomialN	where---		longDivide :: (Fractional c, Num e, Ord e) => Polynomial c e -> (Polynomial c e, Polynomial c e)-		longDivide (MkPolynomial [])	= (zero, zero)	-- Exactly divides.-		longDivide numerator-			| Data.Monomial.getExponent quotient < 0	= (zero, numerator)	-- Indivisible remainder.-			| otherwise					= Control.Arrow.first (lift (quotient :)) $ longDivide (numerator =-= polynomialD *= quotient )-			where---				quotient :: (Fractional c, Num e) => Data.Monomial.Monomial c e-				quotient	= getLeadingTerm numerator </> getLeadingTerm polynomialD--{- |-	* Transforms the data behind the constructor.--	* CAVEAT: similar to 'Data.Functor.fmap', but 'Polynomial' isn't an instance of 'Data.Functor.Functor' since we may want to operate on both /type-parameters/.--	* CAVEAT: the caller is required to re-'normalise' the resulting polynomial depending on the nature of the transformation of the data.--}-lift :: (MonomialList c1 e1 -> MonomialList c2 e2) -> Polynomial c1 e1 -> Polynomial c2 e2-lift transform	= MkPolynomial . transform . getMonomialList---- | Returns the number of non-zero terms in the polynomial.-terms :: Polynomial c e -> Int-terms (MkPolynomial l)	= length l---- | Return the highest-degree monomial.-getLeadingTerm :: Polynomial c e -> Data.Monomial.Monomial c e-getLeadingTerm (MkPolynomial [])	= error "Factory.Data.Polynomial.getLeadingTerm:\tzero polynomial has no leading term."-getLeadingTerm (MkPolynomial (m : _))	= m---- | Removes terms with a /coefficient/ of zero.-pruneCoefficients :: (Eq c, Num c) => Polynomial c e -> Polynomial c e-pruneCoefficients (MkPolynomial [])	= zero-pruneCoefficients p			= filter ((/= 0) . Data.Monomial.getCoefficient) `lift` p---- | Sorts into /descending order/ of exponents, groups /like/ exponents, and calls 'pruneCoefficients'.-normalise :: (Eq c, Num c, Ord e) => Polynomial c e -> Polynomial c e-normalise	= pruneCoefficients . lift (-	map (-		foldr ((+) . Data.Monomial.getCoefficient) 0 &&& Data.Monomial.getExponent . head-	) . Data.List.groupBy (=~) . Data.List.sortBy (flip (<=>))- )---- | Constructs an arbitrary /zeroeth-degree polynomial/, ie. independent of the /indeterminate/.-mkConstant :: (Eq c, Num c, Num e) => c -> Polynomial c e-mkConstant 0	= zero-mkConstant c	= MkPolynomial [(c, 0)]---- | Constructs an arbitrary /first-degree polynomial/.-mkLinear :: (Eq c, Num c, Num e)-	=> c	-- ^ Gradient.-	-> c	-- ^ Constant.-	-> Polynomial c e-mkLinear m c	= pruneCoefficients $ MkPolynomial [(m, 1), (c, 0)]---- | Smart constructor. Constructs an arbitrary /polynomial/.-mkPolynomial :: (Eq c, Num c, Ord e) => MonomialList c e -> Polynomial c e-mkPolynomial []	= zero-mkPolynomial l	= normalise $ MkPolynomial l---- | Constructs a /polynomial/ with zero terms.-zero :: Polynomial c e-zero	= MkPolynomial []---- | Constructs a constant /monomial/, independent of the /indeterminate/.-one :: (Eq c, Num c, Num e) => Polynomial c e-one	= mkConstant 1---- | True if all /exponents/ are in the order defined by the specified comparator.-inOrder :: (e -> e -> Bool) -> Polynomial c e -> Bool-inOrder comparator p-	| any ($ p) [isZero, isMonomial]	= True-	| otherwise				= and . uncurry (zipWith comparator) . (init &&& tail) . map Data.Monomial.getExponent $ getMonomialList p---- | True if the /exponents/ of successive terms are in /ascending/ order.-inAscendingOrder :: Ord e => Polynomial c e -> Bool-inAscendingOrder	= inOrder (<=)---- | True if the /exponents/ of successive terms are in /descending/ order.-inDescendingOrder :: Ord e => Polynomial c e -> Bool-inDescendingOrder	= inOrder (>=)---- | True if no term has a /coefficient/ of zero.-isReduced :: (Eq c, Num c) => Polynomial c e -> Bool-isReduced	= all ((/= 0) . Data.Monomial.getCoefficient) . getMonomialList---- | True if no term has a /coefficient/ of zero and the /exponents/ of successive terms are in /descending/ order.-isNormalised :: (Eq c, Num c, Ord e) => Polynomial c e -> Bool-isNormalised polynomial	= all ($ polynomial) [isReduced, inDescendingOrder]--{- |-	* 'True' if the /leading coefficient/ is one.--	* <http://en.wikipedia.org/wiki/Monic_polynomial#Classifications>.--}-isMonic :: (Eq c, Num c) => Polynomial c e -> Bool-isMonic (MkPolynomial [])	= False	-- All coefficients are zero, and have therefore been removed.-isMonic p			= (== 1) . Data.Monomial.getCoefficient $ getLeadingTerm p---- | True if there are zero terms.-isZero :: Polynomial c e -> Bool-isZero (MkPolynomial [])	= True-isZero _			= False---- | True if there's exactly one term.-isMonomial :: Polynomial c e -> Bool-isMonomial (MkPolynomial [])	= True-isMonomial _			= False---- | True if all /exponents/ are /positive/ integers as required.-isPolynomial :: Integral e => Polynomial c e -> Bool-isPolynomial	= all Data.Monomial.isMonomial . getMonomialList--{- |-	* 'True' if the two specified /polynomials/ are /congruent/ in /modulo/-arithmetic.--	* <http://planetmath.org/encyclopedia/PolynomialCongruence.html>.--}-areCongruentModulo :: (Integral c, Num e, Ord e)-	=> Polynomial c e	-- ^ LHS.-	-> Polynomial c e	-- ^ RHS.-	-> c			-- ^ Modulus.-	-> Bool-areCongruentModulo _ _ 0	= error "Factory.Data.Polynomial.areCongruentModulo:\tzero modulus."-areCongruentModulo _ _ 1	= True-areCongruentModulo l r	modulus-	| l == r	= True-	| otherwise	= all ((== 0) . (`mod` modulus) . Data.Monomial.getCoefficient) . getMonomialList $ l =-= r--{- |-	* Return the /degree/ (AKA /order/) of the /polynomial/.--	* <http://en.wikipedia.org/wiki/Degree_of_a_polynomial>.--	* <http://mathworld.wolfram.com/PolynomialDegree.html>.--}-getDegree :: Num e => Polynomial c e -> e-getDegree (MkPolynomial [])	= -1	-- CAVEAT: debatable, but makes some operations more robust and consistent.-getDegree p			= Data.Monomial.getExponent $ getLeadingTerm p--{- |-	* Scale-up the specified /polynomial/ by a constant /monomial/ factor.--	* <http://en.wikipedia.org/wiki/Scalar_multiplication>.--}-(*=) :: (Eq c, Num c, Num e) => Polynomial c e -> Data.Monomial.Monomial c e -> Polynomial c e-polynomial *= monomial-	| Data.Monomial.getCoefficient monomial == 1	= map (`Data.Monomial.shiftExponent` Data.Monomial.getExponent monomial) `lift` polynomial-	| otherwise					= map (monomial <*>) `lift` polynomial--{- |-	* Raise a /polynomial/ to the specified positive integral power, but using /modulo/-arithmetic.--	* Whilst one could naively implement this as @(x Data.Ring.=^ n) `mod` m@, this will result in arithmetic operatons on unnecessarily big integers.--}-raiseModulo :: (Integral c, Integral power, Num e, Ord e, Show power)-	=> Polynomial c e	-- ^ The base.-	-> power		-- ^ The exponent to which the base should be raised.-	-> c			-- ^ The modulus.-	-> Polynomial c e	-- ^ The result.-raiseModulo _ _ 0			= error "Factory.Data.Polynomial.raiseModulo:\tzero modulus."-raiseModulo _ _ 1			= zero-raiseModulo _ 0 modulus			= mkConstant $ 1 `mod` modulus-raiseModulo polynomial power modulus-	| power < 0			= error $ "Factory.Data.Polynomial.raiseModulo:\tthe result isn't guaranteed to be a polynomial, for power=" ++ show power-	| first `elem` [zero, one]	= first	-- Eg 'raiseModulo (mkPolynomial [(3,1)]) 100 3' or 'raiseModulo (mkPolynomial [(3,1),(1,0)]) 100 3'.-	| otherwise			= slave power-	where---		first :: Integral c => Polynomial c e-		first	= polynomial `mod'` modulus----		slave :: (Integral c, Integral power, Num e, Ord e) => power -> Polynomial c e-		slave 1	= first-		slave n	= (`mod'` modulus) . (if r == 0 {-even-} then id else (polynomial =*=)) . Data.Ring.square $ slave q {-recurse-}	where-			(q, r)	= n `quotRem` 2---- | Reduces all the coefficients using /modular/ arithmetic.-mod' :: Integral c-	=> Polynomial c e-	-> c	-- ^ Modulus.-	-> Polynomial c e-mod' p modulus	= pruneCoefficients $ map (`Data.Monomial.mod'` modulus) `lift` p--{- |-	* Evaluate the /polynomial/ at a specific /indeterminate/.--	* CAVEAT: requires positive exponents; but it wouldn't really be a /polynomial/ otherwise.--	* If the /polynomial/ is very sparse, this may be inefficient,-	since it /memoizes/ the complete sequence of powers up to the polynomial's /degree/.--}-evaluate :: (Num n, Integral e, Show e)-	=> n	-- ^ The /indeterminate/.-	-> Polynomial n e-	-> n	-- ^ The Result.-evaluate x	= foldr ((+) . raise) 0 . getMonomialList	where-	powers	= iterate (* x) 1--	raise monomial-		| exponent' < 0	= error $ "Factory.Data.Polynomial.evaluate.raise:\tnegative exponent; " ++ show exponent'-		| otherwise	= Data.Monomial.getCoefficient monomial * Data.List.genericIndex powers exponent'-		where-			exponent'	= Data.Monomial.getExponent monomial---- | Convert the type of the /coefficient/s.-realCoefficientsToFrac :: (Real r, Fractional f) => Polynomial r e -> Polynomial f e-realCoefficientsToFrac	= lift (Data.Monomial.realCoefficientToFrac `map`)-
− src/Factory/Data/PrimeFactors.hs
@@ -1,143 +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@]--	* Describes a list of /prime factors/.--	* The product of this list of prime-factors represents the /composite/ integer from which they were originally extracted.--}--module Factory.Data.PrimeFactors(--- * Types--- ** Type-synonyms-	Factors,--- * Functions-	insert',---	invert,-	product',-	reduce,---	reduceSorted,---	sumExponents,--- ** Operators-	(>*<),-	(>/<),-	(>^)-) where--import qualified	Control.Arrow-import			Control.Arrow((&&&))-import qualified	Data.List-import qualified	Data.Ord-import qualified	Factory.Math.DivideAndConquer	as Math.DivideAndConquer-import qualified	Factory.Data.Exponential	as Data.Exponential-import			Factory.Data.Exponential((<^), (=~))-import qualified	ToolShed.Data.List--infixl 7 >/<, >*<	-- Same as (/).-infixr 8 >^		-- Same as (^).--{- |-	* Each element of this list represents one /prime-factor/, expressed as an /exponential/ with a /prime/ base, of the original integer.--	* Whilst it only makes sense for both the /base/ and /exponent/ to be integral, these constrains are applied at the function-level as required.--}-type Factors base exponent	= [Data.Exponential.Exponential base exponent]--{- |-	* Sorts a list representing a product of /prime factors/ by increasing /base/.--	* Multiplies 'Data.Exponential.Exponential's of similar /base/.--}-reduce :: (Ord base, Num exponent, Ord exponent) => Factors base exponent -> Factors base exponent-reduce	= reduceSorted . Data.List.sort {-primarily by base-}---- | Multiplies 'Data.Exponential.Exponential's of similar /base/.-reduceSorted :: (Eq base, Num exponent) => Factors base exponent -> Factors base exponent--- reduceSorted	= map (Data.Exponential.getBase . head &&& sumExponents) . Data.List.groupBy (=~)	-- Slow-reduceSorted []	= []-reduceSorted (x : xs)-	| null matched	= x : reduceSorted remainder-	| otherwise	= Control.Arrow.second (+ sumExponents matched) x : reduceSorted remainder-	where-		(matched, remainder)	= span (=~ x) xs--{- |-	* Insert a 'Data.Exponential.Exponential', into a list representing a product of /prime factors/, multiplying with any incumbent of like /base/.--	* The list should be sorted by increasing /base/.--	* Preserves the sort-order.--	* CAVEAT: this is tolerably efficient for sporadic insertion; to insert a list, use '>*<'.--}-insert' :: (Ord base, Num exponent) => Data.Exponential.Exponential base exponent -> Factors base exponent -> Factors base exponent-insert' e []		= [e]-insert' e l@(x : xs)	= case Data.Ord.comparing Data.Exponential.getBase e x of-	LT	-> e : l-	GT	-> x : insert' e xs	-- Recurse.-	_	-> Control.Arrow.second (+ Data.Exponential.getExponent e) x : xs	-- Multiply by adding exponents.--{- |-	* Multiplies two lists each representing a product of /prime factors/, and sorted by increasing /base/.--	* Preserves the sort-order.--}-(>*<) :: (Ord base, Num exponent, Ord exponent) => Factors base exponent -> Factors base exponent -> Factors base exponent-l >*< r	= reduceSorted $ ToolShed.Data.List.merge l r---- | Invert the product of a list /prime factors/, by negating each of the /exponents/.-invert :: Num exponent => Factors base exponent -> Factors base exponent-invert	= map Data.Exponential.invert--{- |-	* Divides two lists, each representing a product of /prime factors/, and sorted by increasing /base/.--	* Preserves the sort-order.--}-(>/<) :: (Integral base, Integral exponent)-	=> Factors base exponent				-- ^ The list of /prime factors/ in the /numerator/.-	-> Factors base exponent				-- ^ The list of /prime factors/ in the /denominator/.-	-> (Factors base exponent, Factors base exponent)	-- ^ The ratio of /numerator/ and /denominator/, after like /prime factors/ are cancelled.-numerator >/< denominator	= filter (-	(> 0) . Data.Exponential.getExponent- ) &&& invert . filter (-	(< 0) . Data.Exponential.getExponent- ) $ numerator >*< invert denominator--{- |-	* Raise the product of a list /prime factors/ to the specified power.--	* CAVEAT: this merely involves raising each element to the specified power; cf. raising a /polynomial/ to a power.--}-(>^) :: Num exponent => Factors base exponent -> exponent -> Factors base exponent-factors >^ power	= map (<^ power) factors---- | Sum the /exponents/ of the specified list; as required to multiply exponentials with identical /base/.-sumExponents :: Num exponent => Factors base exponent -> exponent-sumExponents	= foldr ((+) . Data.Exponential.getExponent) 0---- | Multiply a list of /prime factors/.-product' :: (Num base, Integral exponent)-	=> Math.DivideAndConquer.BisectionRatio-	-> Math.DivideAndConquer.MinLength-	-> Factors base exponent		-- ^ The list on which to operate.-	-> base					-- ^ The result.-product' bisectionRatio minLength	= Math.DivideAndConquer.product' bisectionRatio minLength . map Data.Exponential.evaluate-
− src/Factory/Data/PrimeWheel.hs
@@ -1,198 +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 a /prime-wheel/, for use in prime-number generation; <http://en.wikipedia.org/wiki/Wheel_factorization>.--}--module Factory.Data.PrimeWheel(--- * Types--- ** Type-synonyms-	Distance,-	NPrimes,-	PrimeMultiples,---	Repository,--- ** Data-types-	PrimeWheel(getPrimeComponents, getSpokeGaps),--- * Functions-	estimateOptimalSize,---	findCoprimes,-	generateMultiples,-	roll,-	rotate,--- ** Constructors-	mkPrimeWheel,--- ** Query-	getCircumference,-	getSpokeCount-) where--import			Control.Arrow((&&&), (***))-import qualified	Data.IntMap-import qualified	Data.List--{- |-	* A conceptual /wheel/, with irregularly spaced spokes; <http://www.haskell.org/haskellwiki/Prime_numbers_miscellaneous#Prime_Wheels>.--	* On being rolled, the trace of the spokes, identifies candidates which are /coprime/ to those primes from which the /wheel/ was composed.--	* One can alternatively view this as a set of vertical nested rings, each with a /prime circumference/, and touching at its lowest point.-	Each has a single mark on its /circumference/, which when rolled identifies multiples of that /circumference/.-	When the complete set is rolled, from the state where all marks are coincident, all multiples of the set of primes, are traced.--	* CAVEAT: The distance required to return to this state (the wheel's /circumference/), grows rapidly with the number of primes:-->	zip [0 ..] . scanl (*) 1 $ [2,3,5,7,11,13,17,19,23,29,31]->	[(0,1),(1,2),(2,6),(3,30),(4,210),(5,2310),(6,30030),(7,510510),(8,9699690),(9,223092870),(10,6469693230),(11,200560490130)]--	* The number of spokes also grows rapidly with the number of primes:-->	zip [0 ..] . scanl (*) 1 . map pred $ [2,3,5,7,11,13,17,19,23,29,31]->	[(0,1),(1,1),(2,2),(3,8),(4,48),(5,480),(6,5760),(7,92160),(8,1658880),(9,36495360),(10,1021870080),(11,30656102400)]--}-data PrimeWheel i	= MkPrimeWheel {-	getPrimeComponents	:: [i],	-- ^ Accessor: the ordered sequence of initial primes, from which the /wheel/ was composed.-	getSpokeGaps		:: [i]	-- ^ Accessor: the sequence of spoke-gaps, the sum of which equals its /circumference/.-} deriving Show---- | The /circumference/ of the specified 'PrimeWheel'.-getCircumference :: Integral i => PrimeWheel i -> i-getCircumference	= product . getPrimeComponents---- | The number of spokes in the specified 'PrimeWheel'.-getSpokeCount :: Integral i => PrimeWheel i -> i-getSpokeCount	= foldr ((*) . pred) 1 . getPrimeComponents---- | An infinite increasing sequence, of the multiples of a specific prime.-type PrimeMultiples i	= [i]---- | Defines a container for the 'PrimeMultiples'.-type Repository	= Data.IntMap.IntMap (PrimeMultiples Int)---- | The size of the /wheel/, measured by the number of primes from which it is composed.-type NPrimes	= Int--{- |-	* Uses a /Sieve of Eratosthenes/ (<http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes>), to generate an initial sequence of primes.--	* Also generates an infinite sequence of candidate primes, each of which is /coprime/ to the primes just found, e.g.:-	@filter ((== 1) . (gcd (2 * 3 * 5 * 7))) [11 ..] = [11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,121 ..]@; NB /121/ isn't prime.--	* CAVEAT: the use, for efficiency, of "Data.IntMap", limits the maximum bound of this sequence, though not to a significant extent.--}-findCoprimes :: NPrimes -> ([Int], [Int])-findCoprimes 0	= ([], [])-findCoprimes required-	| required < 0	= error $ "Factory.Data.PrimeWheel.findCoprimes: invalid number of coprimes; " ++ show required-	| otherwise	= splitAt required $ 2 : sieve 3 0 Data.IntMap.empty-	where-		sieve :: Int -> NPrimes -> Repository -> [Int]-		sieve candidate found repository	= case Data.IntMap.lookup candidate repository of-			Just primeMultiples	-> sieve' found . insertUniq primeMultiples $ Data.IntMap.delete candidate repository	-- Re-insert subsequent multiples.-			Nothing {-prime-}	-> let-				found'		= succ found-				(key : values)	= iterate (+ gap * candidate) $ candidate ^ (2 :: Int)	-- Generate a sequence of prime-multiples, starting from its square.-			 in candidate : sieve' found' (-				if found' >= required-					then repository-					else Data.IntMap.insert key values repository-			 )-			where-				gap :: Int-				gap	= 2	-- For efficiency, only sieve odd integers.--				sieve' :: NPrimes -> Repository -> [Int]-				sieve'	= sieve $ candidate + gap	-- Tail-recurse.--				insertUniq :: PrimeMultiples Int -> Repository -> Repository-				insertUniq l m	= insert $ dropWhile (`Data.IntMap.member` m) l	where-					insert :: PrimeMultiples Int -> Repository-					insert []		= error "Factory.Data.PrimeWheel.findCoprimes.sieve.insertUniq.insert:\tnull list"-					insert (key : values)	= Data.IntMap.insert key values m-{- |-	* The optimal number of low primes from which to build the /wheel/, grows with the number of primes required;-	the /circumference/ should be approximately the /square-root/ of the number of integers it will be required to sieve.--	* CAVEAT: one greater than this is returned, which empirically seems better.--}-estimateOptimalSize :: Integral i => i -> NPrimes-estimateOptimalSize maxPrime	= succ . length . takeWhile (<= optimalCircumference) . scanl1 (*) {-circumference-} . map fromIntegral {-prevent overflow-} . fst {-primes-} $ findCoprimes 10 {-arbitrary maximum bound-}	where-	optimalCircumference :: Integer-	optimalCircumference	= round (sqrt $ fromIntegral maxPrime :: Double)--{- |-	Smart constructor for a /wheel/ from the specified number of low primes.--	* The optimal number of low primes from which to build the /wheel/, grows with the number of primes required;-	the /circumference/ should be approximately the /square-root/ of the number of integers it will be required to sieve.--	* The sequence of gaps between spokes on the /wheel/ is /symmetrical under reflection/;-	though two values lie /on/ the axis, that aren't part of this symmetry. Eg:-->	nPrimes	Gaps->	======	====->	0	[1]->	1	[2]	-- The terminal gap for all subsequent wheels is '2'; [(succ circumference `mod` circumference) - (pred circumference `mod` circumference)].->	2	[4,2]	-- Both points are on the axis, so the symmetry isn't yet clear.->	3	[6,4,2,4,2,4,6,2]->	4	[10,2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2]--	Exploitation of this property has proved counter-productive, probably because it requires /strict evaluation/,-	exposing the user to the full cost of inadvertently choosing a /wheel/, which in practice, is rotated less than once.--}-mkPrimeWheel :: Integral i => NPrimes -> PrimeWheel i-mkPrimeWheel 0	= MkPrimeWheel [] [1]-mkPrimeWheel nPrimes-	| nPrimes < 0	= error $ "Factory.Data.PrimeWheel.mkPrimeWheel: unable to construct from " ++ show nPrimes ++ " primes"-	| otherwise	= primeWheel-	where-		(primeComponents, coprimeCandidates)	= (map fromIntegral *** map fromIntegral . Data.List.genericTake (getSpokeCount primeWheel)) $ findCoprimes nPrimes-		primeWheel				= MkPrimeWheel primeComponents $ zipWith (-) coprimeCandidates $ 1 : coprimeCandidates	-- Measure the gaps between candidate primes.---- | Couples a candidate prime with a /rolling wheel/, to define the distance rolled.-type Distance i	= (i, [i])---- | Generates a new candidate prime, from a /rolling wheel/, and the current candidate.-rotate :: Integral i => Distance i -> Distance i-rotate (candidate, rollingWheel)	= (candidate +) . head &&& tail $ rollingWheel--{-# INLINE rotate #-}---- | Generate an infinite, increasing sequence of candidate primes, from the specified /wheel/.-roll :: Integral i => PrimeWheel i -> [Distance i]-roll primeWheel	= tail $ iterate rotate (1, cycle $ getSpokeGaps primeWheel)--{- |-	* Generates multiples of the specified prime, starting from its /square/,-	skipping those multiples of the low primes from which the specified 'PrimeWheel' was composed,-	and which therefore, the /wheel/ won't generate as candidates. Eg:-->	Prime	Rotating PrimeWheel 3	Output->	=====	=====================	======->	7	[4,2,4,2,4,6,2,6]	[49,77,91,119,133,161,203,217,259 ..]->	11	[2,4,2,4,6,2,6,4]	[121,143,187,209,253,319,341,407 ..]->	13	[4,2,4,6,2,6,4,2]	[169,221,247,299,377,403,481,533,559 ..]--}-generateMultiples :: Integral i-	=> i	-- ^ The number to square and multiply-	-> [i]	-- ^ A /rolling wheel/, the track of which, delimits the gaps between /coprime/ candidates.-	-> [i]-generateMultiples i	= scanl (\accumulator -> (+ accumulator) . (* i)) (i ^ (2 :: Int))--{-# INLINE generateMultiples #-}-
− src/Factory/Data/QuotientRing.hs
@@ -1,79 +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@]--	* Describes a /Quotient Ring/; <http://en.wikipedia.org/wiki/Quotient_ring>.--	* This is a /ring/ composed from a residue-class resulting from /modular/ division.--}--module Factory.Data.QuotientRing(--- * Type-classes-	QuotientRing(..),--- * Functions-	quot',-	rem',--- ** Predicates-	areCongruentModulo,-	isDivisibleBy-) where--import			Factory.Data.Ring((=-=))-import qualified	Factory.Data.Ring	as Data.Ring---- | Defines a sub-class of 'Data.Ring.Ring', in which division is implemented.-class Data.Ring.Ring q => QuotientRing q	where-	quotRem'	:: q -> q -> (q, q)	-- ^ Divides the first operand by the second, to yield a pair composed from the /quotient/ and the /remainder/.---- | Returns the /quotient/, after division of the two specified 'QuotientRing's.-quot' :: QuotientRing q-	=> q	-- ^ Numerator.-	-> q	-- ^ Denominator.-	-> q-quot' numerator	= fst . quotRem' numerator---- | Returns the /remainder/, after division of the two specified 'QuotientRing's.-rem' :: QuotientRing q-	=> q	-- ^ Numerator.-	-> q	-- ^ Denominator.-	-> q-rem' numerator	= snd . quotRem' numerator--{- |-	* 'True' if the two specified 'QuotientRing's are /congruent/ in /modulo/-arithmetic, where the /modulus/ is a third 'QuotientRing'.--	* <http://www.usna.edu/Users/math/wdj/book/node74.html>.--}-areCongruentModulo :: (Eq q, QuotientRing q)-	=> q	-- ^ LHS.-	-> q	-- ^ RHS.-	-> q	-- ^ Modulus.-	-> Bool-areCongruentModulo l r modulus-	| l == r	= True	-- Only required for efficiency.-	| otherwise	= (l =-= r) `isDivisibleBy` modulus---- | True if the second operand /divides/ the first.-isDivisibleBy :: (Eq q, QuotientRing q)-	=> q	-- ^ Numerator.-	-> q	-- ^ Denominator.-	-> Bool-numerator `isDivisibleBy` denominator	= rem' numerator denominator == Data.Ring.additiveIdentity-
− src/Factory/Data/Ring.hs
@@ -1,118 +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@]--	* Describes a /ring/ and operations on its members.--	* <http://en.wikipedia.org/wiki/Ring_%28mathematics%29>.--	* <http://www.numericana.com/answer/rings.htm>.--}--module Factory.Data.Ring(--- * Type-classes-	Ring(..),--- * Types--- ** Data.types---	Product,---	Sum,--- * Functions-	product',-	sum',--- ** Operators-	(=^)-) where--import qualified	Data.Monoid-import qualified	Factory.Math.DivideAndConquer	as Math.DivideAndConquer--infixl 6 =+=	-- Same as (+).-infixl 6 =-=	-- Same as (-).-infixl 7 =*=	-- Same as (*).-infixr 8 =^	-- Same as (^).--{- |-	* Define both the operations applicable to all members of the /ring/, and its mandatory members.--	* Minimal definition; '=+=', '=*=', 'additiveInverse', 'multiplicativeIdentity', 'additiveIdentity'.--}-class Ring r	where-	(=+=)			:: r -> r -> r	-- ^ Addition of two members; required to be /commutative/; <http://en.wikipedia.org/wiki/Commutativity>.-	(=*=)			:: r -> r -> r	-- ^ Multiplication of two members.-	additiveInverse		:: r -> r	-- ^ The operand required to yield /zero/ under addition; <http://en.wikipedia.org/wiki/Additive_inverse>.-	multiplicativeIdentity	:: r		-- ^ The /identity/-member under multiplication; <http://mathworld.wolfram.com/MultiplicativeIdentity.html>.-	additiveIdentity	:: r		-- ^ The /identity/-member under addition (AKA /zero/); <http://en.wikipedia.org/wiki/Additive_identity>.--	(=-=) :: r -> r -> r			-- ^ Subtract the two specified /ring/-members.-	l =-= r	= l =+= additiveInverse r	-- Default implementation.--	square :: r -> r			-- ^ Square the ring.-	square r	= r =*= r		-- Default implementation; there may be a more efficient one.--{- |-	* Raise a /ring/-member to the specified positive integral power.--	* Exponentiation is implemented as a sequence of either squares of, or multiplications by, the /ring/-member;-	<http://en.wikipedia.org/wiki/Exponentiation_by_squaring>.--}-(=^) :: (-	Eq		r,-	Integral	power,-	Ring		r,-	Show		power- ) => r -> power -> r-_ =^ 0	= multiplicativeIdentity-ring =^ power-	| power < 0							= error $ "Factory.Data.Ring.(=^):\tthe result isn't guaranteed to be a ring-member, for power=" ++ show power-	| ring `elem` [additiveIdentity, multiplicativeIdentity]	= ring-	| otherwise							= slave power-	where-		slave 1	= ring-		slave n	= (if r == 0 {-even-} then id else (=*= ring)) . square $ slave q	where-			(q, r)	= n `quotRem` 2---- | Does for 'Ring', what 'Data.Monoid.Product' does for type 'Num', in that it makes it an instance of 'Data.Monoid.Monoid' under multiplication.-newtype Product p	= MkProduct {-	getProduct :: p	-- ^ Access the polymorphic payload.-} deriving (Read, Show)--instance Ring r => Data.Monoid.Monoid (Product r)	where-	mempty					= MkProduct multiplicativeIdentity-	MkProduct x `mappend` MkProduct y	= MkProduct $ x =*= y---- | Returns the /product/ of the list of /ring/-members.-product' :: Ring r => Math.DivideAndConquer.BisectionRatio -> Math.DivideAndConquer.MinLength -> [r] -> r--- product' _ _			= getProduct . Data.Monoid.mconcat . map MkProduct-product' ratio minLength	= getProduct . Math.DivideAndConquer.divideAndConquer ratio minLength . map MkProduct---- | Does for 'Ring', what 'Data.Monoid.Sum' does for type 'Num', in that it makes it an instance of 'Data.Monoid.Monoid' under addition.-newtype Sum s	= MkSum {-	getSum :: s	-- ^ Access the polymorphic payload.-} deriving (Read, Show)--instance Ring r => Data.Monoid.Monoid (Sum r)	where-	mempty				= MkSum additiveIdentity-	MkSum x `mappend` MkSum y	= MkSum $ x =+= y---- | Returns the /sum/ of the list of /ring/-members.-sum' :: Ring r => Math.DivideAndConquer.BisectionRatio -> Math.DivideAndConquer.MinLength -> [r] -> r--- sum' _ _		= getSum . Data.Monoid.mconcat . map MkSum-sum' ratio minLength	= getSum . Math.DivideAndConquer.divideAndConquer ratio minLength . map MkSum-
− src/Factory/Math/ArithmeticGeometricMean.hs
@@ -1,91 +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@]	Determines the /Arithmetic-geometric mean/; <http://en.wikipedia.org/wiki/Arithmetic-geometric_mean>.--}--module Factory.Math.ArithmeticGeometricMean(--- * Types--- ** Type-synonyms-	ArithmeticMean,-	GeometricMean,-	AGM,--- * Functions-	convergeToAGM,-	spread,--- ** Accessors-	getArithmeticMean,-	getGeometricMean,--- ** Predicates-	isValid-) where--import			Control.Arrow((&&&))-import qualified	Control.Parallel.Strategies-import qualified	Factory.Math.Precision	as Math.Precision-import qualified	Factory.Math.SquareRoot	as Math.SquareRoot---- | The type of the /arithmetic mean/; <http://en.wikipedia.org/wiki/Arithmetic_mean>.-type ArithmeticMean	= Rational---- | The type of the /geometric mean/; <http://en.wikipedia.org/wiki/Geometric_mean>.-type GeometricMean	= Rational---- | Encapsulates both /arithmetic/ and /geometric/ means.-type AGM	= (ArithmeticMean, GeometricMean)---- | Accessor.-{-# INLINE getArithmeticMean #-}-getArithmeticMean :: AGM -> ArithmeticMean-getArithmeticMean	= fst---- | Accessor.-{-# INLINE getGeometricMean #-}-getGeometricMean :: AGM -> GeometricMean-getGeometricMean	= snd---- | Returns an infinite list which converges on the /Arithmetic-geometric mean/.-convergeToAGM :: Math.SquareRoot.Algorithmic squareRootAlgorithm => squareRootAlgorithm -> Math.Precision.DecimalDigits -> AGM -> [AGM]-convergeToAGM squareRootAlgorithm decimalDigits agm-	| decimalDigits <= 0	= error $ "Factory.Math.ArithmeticGeometricMean.convergeToAGM:\tinvalid number of decimal digits; " ++ show decimalDigits-	| not $ isValid agm	= error $ "Factory.Math.ArithmeticGeometricMean.convergeToAGM:\tboth means must be positive for a real geometric mean; " ++ show agm-	| spread agm == 0	= repeat agm-	| otherwise		= let-		simplify :: Rational -> Rational-		simplify	= Math.Precision.simplify (pred decimalDigits {-ignore single integral digit-})	-- This makes a gigantic difference to performance.--		findArithmeticMean :: AGM -> ArithmeticMean-		findArithmeticMean	= (/ 2) . uncurry (+)--		findGeometricMean :: AGM -> GeometricMean-		findGeometricMean	= Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits . uncurry (*)-	in iterate (-		Control.Parallel.Strategies.withStrategy (-			Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq-		) . (simplify . findArithmeticMean &&& simplify . findGeometricMean)-	) agm---- | Returns the bounds within which the 'AGM' has been constrained.-spread :: AGM -> Rational-spread	= uncurry (-)---- | Checks that both /means/ are positive, as required for the /geometric mean/ to be consistently /real/.-isValid :: AGM -> Bool-isValid (a, g)	= all (>= 0) [a, g]-
− src/Factory/Math/DivideAndConquer.hs
@@ -1,122 +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@]--	* Provides a polymorphic algorithm, to /unfold/ a list into a tree, to which an /associative binary operator/ is then applied to re-/fold/ the tree to a /scalar/.--	* 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.Interval/.--}--module Factory.Math.DivideAndConquer(--- * Types--- ** Type-synonyms-	BisectionRatio,-	MinLength,--- * Functions-	divideAndConquer,-	product',-	sum'-) where--import			Control.Arrow((***))-import qualified	Control.Parallel.Strategies-import qualified	Data.Monoid-import qualified	Data.Ratio--{- |-	* The ratio of the original list-length at which to bisect.--	* CAVEAT: the value can overflow.--}-type BisectionRatio	= Data.Ratio.Ratio Int---- | The list-length beneath which to terminate bisection.-type MinLength	= Int--{- |-	* Reduces a list to a single scalar encapsulated in a 'Data.Monoid.Monoid',-	using a /divide-and-conquer/ strategy,-	bisecting the list and recursively evaluating each part; <http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm>.--	* By choosing a 'bisectionRatio' 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 list-length,-	after which the /monoid/'s binary operator is directly /folded/ over the list.--	* One can view this as a <http://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>,-	in which the list 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 :: Data.Monoid.Monoid monoid-	=> BisectionRatio	-- ^ The ratio of the original list-length at which to bisect.-	-> MinLength		-- ^ For efficiency, the list will not be bisected, when it's length has been reduced to this value.-	-> [monoid]		-- ^ The list on which to operate.-	-> monoid		-- ^ The resulting scalar.-divideAndConquer bisectionRatio minLength l-	| any ($ apportion minLength) [-		(< 1),			-- The left-hand list may be null.-		(> pred minLength)	-- The right-hand list may be null.-	]		= error $ "Factory.Math.DivideAndConquer.divideAndConquer:\tbisectionRatio='" ++ show bisectionRatio ++ "' is incompatible with minLength=" ++ show minLength ++ "."-	| otherwise	= slave (length l) l-	where-		apportion :: Int -> Int-		apportion list	= (list * Data.Ratio.numerator bisectionRatio) `div` Data.Ratio.denominator bisectionRatio--		slave len list-			| len <= minLength	= Data.Monoid.mconcat list	-- Fold the monoid's binary operator over the list.-			| otherwise		= uncurry Data.Monoid.mappend . Control.Parallel.Strategies.withStrategy (-				Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rseq Control.Parallel.Strategies.rseq-			) . (slave cut *** slave (len - cut)) $ splitAt cut list	where	-- Apply the monoid's binary operator to the two operands resulting from bisection.-				cut	= apportion len--{- |-	* Multiplies the specified list of numbers.--	* Since the result can be large, 'divideAndConquer' is used in an attempt to form operands of a similar order of magnitude,-	which creates scope for the use of more efficient multiplication-algorithms.--}-product' :: Num n-	=> BisectionRatio	-- ^ The ratio of the original list-length at which to bisect.-	-> MinLength		-- ^ For efficiency, the list will not be bisected, when it's length has been reduced to this value.-	-> [n]			-- ^ The numbers whose product is required.-	-> n			-- ^ The resulting product.-product' bisectionRatio minLength	= Data.Monoid.getProduct . divideAndConquer bisectionRatio minLength . map Data.Monoid.Product--{- |-	* Sums the specified list of numbers.--	* Since the result can be large, 'divideAndConquer' is used in an attempt to form operands of a similar order of magnitude,-	which creates scope for the use of more efficient multiplication-algorithms.-	/Multiplication/ is required for the /addition/ of 'Rational' numbers by cross-multiplication;-	this function is unlikely to be useful for other numbers.--}-sum' :: Num n-	=> BisectionRatio	-- ^ The ratio of the original list-length at which to bisect.-	-> MinLength		-- ^ For efficiency, the list will not be bisected, when it's length has been reduced to this value.-	-> [n]			-- ^ The numbers whose sum is required.-	-> n			-- ^ The resulting sum.-sum' bisectionRatio minLength	= Data.Monoid.getSum . divideAndConquer bisectionRatio minLength . map Data.Monoid.Sum-
− src/Factory/Math/Factorial.hs
@@ -1,37 +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@]--	* Whilst this particular function is the subject of many introductory examples to Haskell,-	the simple algorithms appropriate for that forum, leave a large margin for performance-improvement.-	This module provides the interface for alternative algorithms.--	* <http://mathworld.wolfram.com/Factorial.html>.--}--module Factory.Math.Factorial(--- * Type-classes-	Algorithmic(..)-) where---- | Defines the methods expected of a /factorial/-algorithm.-class Algorithmic algorithm	where-	factorial	:: (Integral i, Show i) => algorithm -> i -> i-
− src/Factory/Math/Fibonacci.hs
@@ -1,42 +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@]	<http://en.wikipedia.org/wiki/Fibonacci_number>.--}--module Factory.Math.Fibonacci(--- * Constants-	fibonacci,-	primeIndexedFibonacci-) where--import qualified	Data.Numbers.Primes---- | A constant ordered list of the /Fibonacci/-numbers.-fibonacci :: Integral i => [i]-fibonacci	= 0 : scanl (+) 1 fibonacci--{- |-	* The subset of 'fibonacci', /indexed/ by a /prime/-number.--	* <http://primes.utm.edu/glossary/page.php?sort=FibonacciPrime>.--}-primeIndexedFibonacci :: Integral i => [i]-primeIndexedFibonacci	= map (fibonacci !!) Data.Numbers.Primes.primes-
− src/Factory/Math/Hyperoperation.hs
@@ -1,113 +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@]	Provides various /hyperoperations/; <http://en.wikipedia.org/wiki/Hyperoperation>.--}--module Factory.Math.Hyperoperation(--- * Types--- ** Type-synonyms-	Base,-	HyperExponent,--- * Constants-	succession,-	addition,-	multiplication,-	exponentiation,-	tetration,-	pentation,-	hexation,--- * Functions-	hyperoperation,-	ackermannPeter,-	powerTower,--- ** Predicates-	areCoincidental-) where--import qualified	Data.List--{- |-	* Merely to enhance self-documentation.--	* CAVEAT: whilst it may appear that 'Base' could be non-'Integral', the recursive definition for /hyper-exponents/ above 'tetration', prevents this.--}-type Base	= Integer--{- |-	* Merely to enhance self-documentation.--	* CAVEAT: whilst 'Base' and 'HyperExponent' can be independent types for both 'exponentiation' and 'tetration', they interact for other /hyper-exponents/.--}-type HyperExponent	= Base--succession, addition, multiplication, exponentiation, tetration, pentation, hexation :: Int	-- Arbitrarily.-(succession : addition : multiplication : exponentiation : tetration : pentation : hexation : _)	= [0 ..]--{- |-	* Returns the /power-tower/ of the specified /base/; <http://mathworld.wolfram.com/PowerTower.html>.--	* A synonym for /tetration/;-		<http://en.wikipedia.org/wiki/Tetration>,-		<http://www.tetration.org/Fractals/Atlas/index.html>.--}-powerTower :: (Integral base, Integral hyperExponent, Show base) => base -> hyperExponent -> base-powerTower 0 hyperExponent-	| even hyperExponent	= 1-	| otherwise		= 0-powerTower _ (-1)	= 0	-- The only negative hyper-exponent for which there's a consistent result.-powerTower base hyperExponent-	| base < 0 && hyperExponent > 1	= error $ "Factory.Math.Hyperoperation.powerTower:\tundefined for negative base; " ++ show base-	| otherwise			= Data.List.genericIndex (iterate (base ^) 1) hyperExponent---- | The /hyperoperation/-sequence; <http://en.wikipedia.org/wiki/Hyperoperation>.-hyperoperation :: (Integral rank, Show rank) => rank -> Base -> HyperExponent -> Base-hyperoperation rank base hyperExponent-	| rank < fromIntegral succession	= error $ "Factory.Math.Hyperoperation.hyperoperation:\tundefined for rank; " ++ show rank-	| hyperExponent < 0			= error $ "Factory.Math.Hyperoperation.hyperoperation:\tundefined for hyper-exponent; " ++ show hyperExponent-	| otherwise				= rank ^# hyperExponent-	where-		(^#) :: Integral rank => rank -> HyperExponent -> Base-		r ^# 0	= case r of-			1 {-addition-}		-> base-			2 {-multiplication-}	-> 0-			_			-> 1-		r ^# e	= case r of-			0 {-succession-}	-> succ {-fromIntegral-} e-			1 {-addition-}		-> base + {-fromIntegral-} e-			2 {-multiplication-}	-> base * {-fromIntegral-} e-			3 {-exponentiation-}	-> base ^ e-			4 {-tetration-}		-> base `powerTower` e-			_-				| e' == e	-> tetration ^# e'	-- To which it would otherwise be reduced by laborious recursion.-				| otherwise	-> pred r ^# e'-				where-					e'	= {-fromIntegral $-} r ^# pred e---- | The /Ackermann-Peter/-function; <http://en.wikipedia.org/wiki/Ackermann_function#Ackermann_numbers>.-ackermannPeter :: (Integral rank, Show rank) => rank -> HyperExponent -> Base-ackermannPeter rank	= (+ negate 3) . hyperoperation rank 2 {-base-} . (+ 3)---- | True if @hyperoperation base hyperExponent@ has the same value for each specified 'rank'.-areCoincidental :: (Integral rank, Show rank) => Base -> HyperExponent -> [rank] -> Bool-areCoincidental _ _ []				= True-areCoincidental _ _ [_]				= True-areCoincidental base hyperExponent ranks	= all (== h) hs	where-	(h : hs)	= map (\rank -> hyperoperation rank base hyperExponent) ranks-
− src/Factory/Math/Implementations/Factorial.hs
@@ -1,138 +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@]--	* Provides implementations of the class 'Math.Factorial.Algorithmic'.--	* Provides additional functions related to /factorials/, but which depends on a specific implementation,-	and which therefore can't be accessed throught the class-interface.--	* <http://en.wikipedia.org/wiki/Factorial>.--	* <http://mathworld.wolfram.com/Factorial.html>.--	* <http://www.luschny.de/math/factorial/FastFactorialFunctions.htm>.--}--module Factory.Math.Implementations.Factorial(--- * Types--- ** Data-types-	Algorithm(..),--- * Functions-	primeFactors,---	primeMultiplicity,-	risingFactorial,-	fallingFactorial,--- ** Operators-	(!/!)-) where--import qualified	Data.Numbers.Primes-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--infixl 7 !/!	-- Same as (/).---- | The algorithms by which /factorial/ has been implemented.-data Algorithm	=-	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)--instance ToolShed.Defaultable.Defaultable Algorithm	where-	defaultValue	= Bisection--instance Math.Factorial.Algorithmic Algorithm	where-	factorial algorithm n-		| n < 2		= 1-		| otherwise	= case algorithm of-			Bisection		-> risingFactorial 2 $ pred n-			PrimeFactorisation	-> Data.PrimeFactors.product' (recip 5) {-empirical-} 10 {-empirical-} $ primeFactors n--{- |-	* Returns the /prime factors/, of the /factorial/ of the specifed integer.--	* Precisely all the primes less than or equal to the specified integer /n/, are included in /n!/;-	only the multiplicity of each of these known prime components need be determined.--	* <http://en.wikipedia.org/wiki/Factorial#Number_theory>.--	* CAVEAT: currently a hotspot.--}-primeFactors :: Integral base-	=> base					-- ^ The number, whose /factorial/ is to be factorised.-	-> Data.PrimeFactors.Factors base base	-- ^ The /base/ and /exponent/ of each /prime factor/ in the /factorial/, ordered by increasing /base/ (and decreasing /exponent/).-primeFactors n	= takeWhile ((> 0) . snd) $ map (\prime -> (prime, primeMultiplicity prime n)) Data.Numbers.Primes.primes--{- |-	* The number of times a specific /prime/, can be factored from the /factorial/ of the specified integer.--	* General purpose /prime-factorisation/ has /exponential time-complexity/,-	so use /Legendre's Theorem/, which relates only to the /prime factors/ of /factorials/.--	* <http://www.proofwiki.org/wiki/Multiplicity_of_Prime_Factor_in_Factorial>.--}-primeMultiplicity :: Integral i-	=> i	-- ^ A prime number.-	-> i	-- ^ The integer, the factorial of which the prime is a factor.-	-> i	-- ^ The number of times the prime occurs in the factorial.-primeMultiplicity prime	= sum . takeWhile (> 0) . tail . iterate (`div` prime)---- | Returns the /rising factorial/; <http://mathworld.wolfram.com/RisingFactorial.html>-risingFactorial :: (Integral i, Show i)-	=> i	-- ^ The lower bound of the integer-range, whose product is returned.-	-> i	-- ^ The number of integers in the range above.-	-> i	-- ^ The result.-risingFactorial _ 0	= 1-risingFactorial 0 _	= 0-risingFactorial x n	= Data.Interval.product' (recip 2) 64 $ Data.Interval.normalise (x, pred $ x + n)---- | Returns the /falling factorial/; <http://mathworld.wolfram.com/FallingFactorial.html>-fallingFactorial :: (Integral i, Show i)-	=> i	-- ^ The upper bound of the integer-range, whose product is returned.-	-> i	-- ^ The number of integers in the range beneath.-	-> i	-- ^ The result.-fallingFactorial _ 0	= 1-fallingFactorial 0 _	= 0-fallingFactorial x n	= Data.Interval.product' (recip 2) 64 $ Data.Interval.normalise (x, succ $ x - n)--{- |-	* Returns the ratio of two factorials.--	* It is more efficient than evaluating both factorials, and then dividing.--	* For more complex combinations of factorials, such as in the /Binomial coefficient/,-	extract the /prime factors/ using 'primeFactors'-	then manipulate them using the module "Data.PrimeFactors",-	and evaluate it using by /Data.PrimeFactors.product'/.--}-(!/!) :: (Integral i, Fractional f, Show i)-	=> i	-- ^ The /numerator/.-	-> i	-- ^ The /denominator/.-	-> f	-- ^ The resulting fraction.-numerator !/! denominator-	| numerator <= 1		= recip . fromIntegral $ Math.Factorial.factorial (ToolShed.Defaultable.defaultValue :: Algorithm) denominator-	| denominator <= 1		= fromIntegral $ Math.Factorial.factorial (ToolShed.Defaultable.defaultValue :: Algorithm) numerator-	| numerator == denominator	= 1-	| numerator < denominator	= recip $ denominator !/! numerator	-- Recurse.-	| otherwise			= fromIntegral $ Data.Interval.product' (recip 2) 64 (succ denominator, numerator)-
− src/Factory/Math/Implementations/Pi/AGM/Algorithm.hs
@@ -1,42 +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 the set of /Arithmetic-geometric Mean/-type /Pi/-algorithms which have been implemented; currently just one.--}--module Factory.Math.Implementations.Pi.AGM.Algorithm(--- * Types--- ** Data-types-	Algorithm(..)-) where--import qualified	Factory.Math.Implementations.Pi.AGM.BrentSalamin	as Math.Implementations.Pi.AGM.BrentSalamin-import qualified	Factory.Math.Pi						as Math.Pi-import qualified	Factory.Math.SquareRoot					as Math.SquareRoot-import qualified	ToolShed.Defaultable---- | Defines the available algorithms.-data Algorithm squareRootAlgorithm	= BrentSalamin squareRootAlgorithm	deriving (Eq, Read, Show)--instance ToolShed.Defaultable.Defaultable squareRootAlgorithm => ToolShed.Defaultable.Defaultable (Algorithm squareRootAlgorithm)	where-	defaultValue	= BrentSalamin ToolShed.Defaultable.defaultValue--instance Math.SquareRoot.Algorithmic squareRootAlgorithm => Math.Pi.Algorithmic (Algorithm squareRootAlgorithm)	where-	openR (BrentSalamin squareRootAlgorithm)	= Math.Implementations.Pi.AGM.BrentSalamin.openR squareRootAlgorithm-
− src/Factory/Math/Implementations/Pi/AGM/BrentSalamin.hs
@@ -1,64 +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@]--	* Implements the /Brent-Salamin/ (AKA /Gauss-Legendre/) algorithm;-		<http://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm>,-		<http://mathworld.wolfram.com/Brent-SalaminFormula.html>,-		<http://www.pi314.net/eng/salamin.php>.--	* The precision of the result approximately doubles for each iteration.-- [@CAVEAT@]	Assumptions on the convergence-rate result in rounding-errors, when only a small number of digits are requested.--}--module Factory.Math.Implementations.Pi.AGM.BrentSalamin(--- * Functions-	openR-) where--import			Control.Arrow((&&&))-import qualified	Factory.Math.ArithmeticGeometricMean	as Math.ArithmeticGeometricMean-import qualified	Factory.Math.Power			as Math.Power-import qualified	Factory.Math.Precision			as Math.Precision-import qualified	Factory.Math.SquareRoot			as Math.SquareRoot--{- |-	* Returns /Pi/, accurate to the specified number of decimal digits.--	* This algorithm is based on the /arithmetic-geometric/ mean of @1@ and @(1 / sqrt 2)@,-	but there are many confusingly similar formulations.-	The algorithm I've used here, where @a@ is the /arithmetic mean/ and @g@ is the /geometric mean/, is equivalent to other common formulations:-->		pi = (a[N-1] + g[N-1])^2 / (1 - sum [2^n * (a[n] - g[n])^2])			where n = [0 .. N-1]->		=> 4*a[N]^2 / (1 - sum [2^n * (a[n]^2 - 2*a[n]*g[n] + g[n]^2)])->		=> 4*a[N]^2 / (1 - sum [2^n * (a[n]^2 + 2*a[n]*g[n] + g[n]^2 - 4*a[n]*g[n])])->		=> 4*a[N]^2 / (1 - sum [2^n * ((a[n] + g[n])^2 - 4*a[n]*g[n])])->		=> 4*a[N]^2 / (1 - sum [2^(n-1) * 4 * (a[n-1]^2 - g[n-1]^2)])			where n = [1 .. N]->		=> 4*a[N]^2 / (1 - sum [2^(n+1) * (a[n-1]^2 - g[n-1]^2)])---}-openR :: Math.SquareRoot.Algorithmic squareRootAlgorithm => squareRootAlgorithm -> Math.Precision.DecimalDigits -> Rational-openR squareRootAlgorithm decimalDigits	= uncurry (/) . (-	Math.Power.square . uncurry (+) . last &&& negate . pred . sum . zipWith (*) (iterate (* 2) 1) . map (Math.Power.square . Math.ArithmeticGeometricMean.spread)- ) . take (-	Math.Precision.getIterationsRequired Math.Precision.quadraticConvergence 1 decimalDigits- ) $ Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits (1, Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits (recip 2 :: Rational))-
− src/Factory/Math/Implementations/Pi/BBP/Algorithm.hs
@@ -1,47 +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 the set of /Bailey-Borwein-Plouffe/-type formulae which have been implemented.--}--module Factory.Math.Implementations.Pi.BBP.Algorithm(--- * Types--- ** Data-types-	Algorithm(..)-) where--import qualified	Factory.Math.Implementations.Pi.BBP.Base65536		as Math.Implementations.Pi.BBP.Base65536-import qualified	Factory.Math.Implementations.Pi.BBP.Bellard		as Math.Implementations.Pi.BBP.Bellard-import qualified	Factory.Math.Implementations.Pi.BBP.Implementation	as Math.Implementations.Pi.BBP.Implementation-import qualified	Factory.Math.Pi						as Math.Pi-import qualified	ToolShed.Defaultable---- | Defines those /BBP/-type series which have been implemented.-data Algorithm	=-	Base65536	-- ^ A /base/-@2^16@ version of the formula.-	| Bellard	-- ^ A /nega-base/ @2^10@ version of the formula.-	deriving (Eq, Read, Show)--instance ToolShed.Defaultable.Defaultable Algorithm	where-	defaultValue	= Base65536--instance Math.Pi.Algorithmic Algorithm	where-	openR Base65536	= Math.Implementations.Pi.BBP.Implementation.openR Math.Implementations.Pi.BBP.Base65536.series-	openR Bellard	= Math.Implementations.Pi.BBP.Implementation.openR Math.Implementations.Pi.BBP.Bellard.series-
− src/Factory/Math/Implementations/Pi/BBP/Base65536.hs
@@ -1,38 +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 a specific base-@2^16@ /BBP/-formula; <http://mathworld.wolfram.com/PiFormulas.html>---}--module Factory.Math.Implementations.Pi.BBP.Base65536(--- * Constants-	series-) where--import qualified	Factory.Math.Implementations.Pi.BBP.Series	as Math.Implementations.Pi.BBP.Series---- | Defines the parameters of this specific series.-series :: Math.Implementations.Pi.BBP.Series.Series-series	= Math.Implementations.Pi.BBP.Series.MkSeries {-	Math.Implementations.Pi.BBP.Series.numerators		= zipWith ($) (cycle [id, id, id, negate]) $ map (2 ^) [15 :: Integer, 14, 14, 12, 11, 10, 10, 8, 7, 6, 6, 4, 3, 2, 2, 0],-	Math.Implementations.Pi.BBP.Series.getDenominators	= \i -> map (32 * fromIntegral i +) [2, 3, 4, 7, 10, 11, 12, 15, 18, 19, 20, 23, 26, 27, 28, 31],-	Math.Implementations.Pi.BBP.Series.seriesScalingFactor	= recip $ 2 ^ (13 :: Int),-	Math.Implementations.Pi.BBP.Series.base			= 2 ^ (16 :: Int)-}
− src/Factory/Math/Implementations/Pi/BBP/Bellard.hs
@@ -1,41 +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 /Bellard/'s nega-base-@2^10@ /BBP/-formula; <http://en.wikipedia.org/wiki/Bellard%27s_formula>--}--module Factory.Math.Implementations.Pi.BBP.Bellard(--- * Constants-	series-) where--import			Control.Arrow((&&&))-import qualified	Factory.Math.Implementations.Pi.BBP.Series	as Math.Implementations.Pi.BBP.Series---- | Defines the parameters of this specific series.-series :: Math.Implementations.Pi.BBP.Series.Series-series	= Math.Implementations.Pi.BBP.Series.MkSeries {-	Math.Implementations.Pi.BBP.Series.numerators		= zipWith ($) [negate, negate, id, negate, negate, negate, id] $ map (2 ^) [5 :: Integer, 0, 8, 6, 2, 2, 0],-	Math.Implementations.Pi.BBP.Series.getDenominators	= \i -> let-		f, t :: Integer-		(f, t)	= (4 *) &&& (10 *) $ fromIntegral i-	in [f + 1, f + 3, t + 1, t + 3, t + 5, t + 7, t + 9],-	Math.Implementations.Pi.BBP.Series.seriesScalingFactor	= recip $ 2 ^ (6 :: Int),-	Math.Implementations.Pi.BBP.Series.base			= negate $ 2 ^ (10 :: Int)-}
− src/Factory/Math/Implementations/Pi/BBP/Implementation.hs
@@ -1,57 +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@]--	* Implements a /Bailey-Borwein-Plouffe/ formula; <http://mathworld.wolfram.com/PiFormulas.html>--	* Surprisingly, because of the huge size of the 'Rational' quantities,-	it is a /single/ call to @Factory.Math.Summation.sum'@, rather than the calculation of the many terms in the series, which is the performance-bottleneck.--}--module Factory.Math.Implementations.Pi.BBP.Implementation(--- * Functions-	openR-) where--import			Data.Ratio((%))-import qualified	Factory.Math.Implementations.Pi.BBP.Series	as Math.Implementations.Pi.BBP.Series-import qualified	Factory.Math.Precision				as Math.Precision-import qualified	Factory.Math.Summation				as Math.Summation---- | Returns /Pi/, accurate to the specified number of decimal digits.-openR-	:: Math.Implementations.Pi.BBP.Series.Series	-- ^ This /Pi/-algorithm is parameterised by the type of other algorithms to use.-	-> Math.Precision.DecimalDigits			-- ^ The number of decimal digits required.-	-> Rational-openR Math.Implementations.Pi.BBP.Series.MkSeries {-	Math.Implementations.Pi.BBP.Series.numerators		= numerators,-	Math.Implementations.Pi.BBP.Series.getDenominators	= getDenominators,-	Math.Implementations.Pi.BBP.Series.seriesScalingFactor	= seriesScalingFactor,-	Math.Implementations.Pi.BBP.Series.base			= base-} decimalDigits		= (seriesScalingFactor *) . Math.Summation.sum' 8 . take (-	Math.Precision.getTermsRequired (-		recip . fromIntegral $ abs {-potentially negative-} base	-- The convergence-rate.-	) decimalDigits- ) . zipWith (*) (-	iterate (/ fromIntegral base) 1	-- Generate the scaling-ratio, between successive terms.- ) $ map (-	sum . zipWith (%) numerators . getDenominators- ) [0 ..]-
− src/Factory/Math/Implementations/Pi/BBP/Series.hs
@@ -1,36 +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 a /Bailey-Borwein-Plouffe/ formula; <http://mathworld.wolfram.com/PiFormulas.html>--}--module Factory.Math.Implementations.Pi.BBP.Series(--- * Types--- ** Data-types-	Series(..)-) where---- | Defines a series corresponding to a specific /BBP/-formula.-data Series	= MkSeries {-	numerators		:: [Integer],		-- ^ The constant numerators from which each term in the series is composed.-	getDenominators		:: Int -> [Integer],	-- ^ Generates the term-dependent denominators from which each term in the series is composed.-	seriesScalingFactor	:: Rational,		-- ^ The ratio by which the sum to infinity of the series, must be scaled to result in /Pi/.-	base			:: Integer		-- ^ The geometric ratio, by which successive terms are scaled.-}-
− src/Factory/Math/Implementations/Pi/Borwein/Algorithm.hs
@@ -1,56 +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 the set of /Borwein/-type algorithms (currently only one) which have been implemented; <http://www.pi314.net/eng/borwein.php>.--}--module Factory.Math.Implementations.Pi.Borwein.Algorithm(--- * Types--- ** Data-types-	Algorithm(..)-) where--import qualified	Factory.Math.Factorial					as Math.Factorial-import qualified	Factory.Math.Implementations.Pi.Borwein.Borwein1993	as Math.Implementations.Pi.Borwein.Borwein1993-import qualified	Factory.Math.Implementations.Pi.Borwein.Implementation	as Math.Implementations.Pi.Borwein.Implementation-import qualified	Factory.Math.Pi						as Math.Pi-import qualified	Factory.Math.SquareRoot					as Math.SquareRoot-import qualified	ToolShed.Defaultable--{- |-	* Define those /Borwein/-series which have been implemented.--	* Though currently there's only one, provision has been made for the addition of more.--}-data Algorithm squareRootAlgorithm factorialAlgorithm	=-	Borwein1993 squareRootAlgorithm factorialAlgorithm	-- ^ <http://en.wikipedia.org/wiki/Borwein%27s_algorithm>.-	deriving (Eq, Read, Show)--instance (-	ToolShed.Defaultable.Defaultable	squareRootAlgorithm,-	ToolShed.Defaultable.Defaultable	factorialAlgorithm- ) => ToolShed.Defaultable.Defaultable (Algorithm squareRootAlgorithm factorialAlgorithm)	where-	defaultValue	= Borwein1993 ToolShed.Defaultable.defaultValue ToolShed.Defaultable.defaultValue--instance (-	Math.SquareRoot.Algorithmic	squareRootAlgorithm,-	Math.Factorial.Algorithmic	factorialAlgorithm- ) => Math.Pi.Algorithmic (Algorithm squareRootAlgorithm factorialAlgorithm)	where-	openR (Borwein1993 squareRootAlgorithm factorialAlgorithm)	= Math.Implementations.Pi.Borwein.Implementation.openR Math.Implementations.Pi.Borwein.Borwein1993.series squareRootAlgorithm factorialAlgorithm-
− src/Factory/Math/Implementations/Pi/Borwein/Borwein1993.hs
@@ -1,73 +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 the /Borwein/ series for /Pi/; <http://en.wikipedia.org/wiki/Borwein%27s_algorithm#Jonathan_Borwein_and_Peter_Borwein.27s_Version_.281993.29>--}--module Factory.Math.Implementations.Pi.Borwein.Borwein1993(--- * Constants-	series-) where---- import		Control.Arrow((***))-import			Data.Ratio((%))--- import		Factory.Data.PrimeFactors((>*<), (>/<), (>^))--- import qualified	Factory.Data.PrimeFactors			as Data.PrimeFactors-import qualified	Factory.Math.Factorial				as Math.Factorial-import qualified	Factory.Math.Implementations.Factorial		as Math.Implementations.Factorial-import qualified	Factory.Math.Implementations.Pi.Borwein.Series	as Math.Implementations.Pi.Borwein.Series-import qualified	Factory.Math.Power				as Math.Power-import qualified	Factory.Math.Precision				as Math.Precision-import qualified	Factory.Math.SquareRoot				as Math.SquareRoot---- | Defines the parameters of the /Borwein/ series.-series :: (Math.SquareRoot.Algorithmic squareRootAlgorithm, Math.Factorial.Algorithmic factorialAlgorithm) => Math.Implementations.Pi.Borwein.Series.Series squareRootAlgorithm factorialAlgorithm-series = Math.Implementations.Pi.Borwein.Series.MkSeries {-	Math.Implementations.Pi.Borwein.Series.terms			= \squareRootAlgorithm factorialAlgorithm decimalDigits -> let-		simplify, squareRoot :: Rational -> Rational-		simplify	= Math.Precision.simplify $ pred decimalDigits {-ignore single integral digit-}	-- This makes a gigantic difference to performance.-		squareRoot	= simplify . Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits--		sqrt5, a, b, c3 :: Rational-		sqrt5	= squareRoot 5--		a	= 63365028312971999585426220 + sqrt5 * (28337702140800842046825600 + 384 * squareRoot (10891728551171178200467436212395209160385656017 + 4870929086578810225077338534541688721351255040 * sqrt5))-		b	= 7849910453496627210289749000 + 3510586678260932028965606400 * sqrt5 + 2515968 * squareRoot (3110 * (6260208323789001636993322654444020882161 + 2799650273060444296577206890718825190235 * sqrt5))-		c3	= simplify . Math.Power.cube $ negate 214772995063512240 - sqrt5 * (96049403338648032 + 1296 * squareRoot (10985234579463550323713318473 + 4912746253692362754607395912 * sqrt5))-	in (-		squareRoot $ negate c3,	-- The factor into which the series must be divided, to yield Pi.-		zipWith (-{--			\n power -> let-				product'	= Data.PrimeFactors.product' (recip 2) 10-			in uncurry (/) . (-				(* (a + b * fromIntegral n)) . fromIntegral . product' *** (* power) . fromIntegral . product'-			) $ Math.Implementations.Factorial.primeFactors (6 * n) >/< (-				Math.Implementations.Factorial.primeFactors (3 * n) >*< Math.Implementations.Factorial.primeFactors n >^ 3-			)--}-			\n power -> (-				Math.Implementations.Factorial.risingFactorial (succ $ 3 * n) (3 * n) % Math.Power.cube (Math.Factorial.factorial factorialAlgorithm n)-			) * (-				(a + b * fromIntegral n) / power-			)-		) [0 :: Integer ..] $ iterate (* c3) 1-	),-	Math.Implementations.Pi.Borwein.Series.convergenceRate		= 10 ** negate 50	-- Empirical.-}
− src/Factory/Math/Implementations/Pi/Borwein/Implementation.hs
@@ -1,50 +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 /Borwein/ series for /Pi/; <http://en.wikipedia.org/wiki/Borwein%27s_algorithm>--}--module Factory.Math.Implementations.Pi.Borwein.Implementation(--- * Functions-	openR-) where--import qualified	Control.Arrow-import qualified	Control.Parallel.Strategies-import qualified	Factory.Math.Implementations.Pi.Borwein.Series	as Math.Implementations.Pi.Borwein.Series-import qualified	Factory.Math.Precision				as Math.Precision---- | Returns /Pi/, accurate to the specified number of decimal digits.-openR-	:: Math.Implementations.Pi.Borwein.Series.Series squareRootAlgorithm factorialAlgorithm	-- ^ This /Pi/-algorithm is parameterised by the type of other algorithms to use.-	-> squareRootAlgorithm									-- ^ The specific /square-root/ algorithm to apply to the above series.-	-> factorialAlgorithm									-- ^ The specific /factorial/-algorithm to apply to the above series.-	-> Math.Precision.DecimalDigits								-- ^ The number of decimal digits required.-	-> Rational-openR Math.Implementations.Pi.Borwein.Series.MkSeries {-	Math.Implementations.Pi.Borwein.Series.terms		= terms,-	Math.Implementations.Pi.Borwein.Series.convergenceRate	= convergenceRate-} squareRootAlgorithm factorialAlgorithm decimalDigits	= uncurry (/) . Control.Parallel.Strategies.withStrategy (-		Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq-	) . Control.Arrow.second (-		sum . take (-			Math.Precision.getTermsRequired convergenceRate decimalDigits-		)-	) $ terms squareRootAlgorithm factorialAlgorithm decimalDigits-
− src/Factory/Math/Implementations/Pi/Borwein/Series.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 a <http://en.wikipedia.org/wiki/Srinivasa_Borwein>-type series for /Pi/.--}--module Factory.Math.Implementations.Pi.Borwein.Series(--- * Types--- ** Data-types-	Series(..)-) where--import qualified	Factory.Math.Precision	as Math.Precision---- | Defines a series corresponding to a specific /Borwein/-formula.-data Series squareRootAlgorithm factorialAlgorithm	= MkSeries {-	terms-		:: squareRootAlgorithm-		-> factorialAlgorithm-		-> Math.Precision.DecimalDigits-		-> (-			Rational,	-- The factor into which the sum to infinity of the sequence, must be divided to result in /Pi/-			[Rational]	-- The sequence of terms, the sum to infinity of which defines the series.-		),-	convergenceRate :: Math.Precision.ConvergenceRate	-- ^ The expected number of digits of /Pi/, per term in the series.-}-
− src/Factory/Math/Implementations/Pi/Ramanujan/Algorithm.hs
@@ -1,55 +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 the set of /Ramanujan/-type algorithms which have been implemented; <http://en.wikipedia.org/wiki/Pi>.--}--module Factory.Math.Implementations.Pi.Ramanujan.Algorithm(--- * Types--- ** Data-types-	Algorithm(..)-) where--import qualified	Factory.Math.Factorial						as Math.Factorial-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Chudnovsky		as Math.Implementations.Pi.Ramanujan.Chudnovsky-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Classic		as Math.Implementations.Pi.Ramanujan.Classic-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Implementation	as Math.Implementations.Pi.Ramanujan.Implementation-import qualified	Factory.Math.Pi							as Math.Pi-import qualified	Factory.Math.SquareRoot						as Math.SquareRoot-import qualified	ToolShed.Defaultable---- | Define those /Ramanujan/-series which have been implemented.-data Algorithm squareRootAlgorithm factorialAlgorithm	=-	Classic squareRootAlgorithm factorialAlgorithm		-- ^ The original version.-	| Chudnovsky squareRootAlgorithm factorialAlgorithm	-- ^ A variant found by the /Chudnovsky brothers/.-	deriving (Eq, Read, Show)--instance (-	ToolShed.Defaultable.Defaultable	squareRootAlgorithm,-	ToolShed.Defaultable.Defaultable	factorialAlgorithm- ) => ToolShed.Defaultable.Defaultable (Algorithm squareRootAlgorithm factorialAlgorithm)	where-	defaultValue	= Chudnovsky ToolShed.Defaultable.defaultValue ToolShed.Defaultable.defaultValue--instance (-	Math.SquareRoot.Algorithmic	squareRootAlgorithm,-	Math.Factorial.Algorithmic	factorialAlgorithm- ) => Math.Pi.Algorithmic (Algorithm squareRootAlgorithm factorialAlgorithm)	where-	openR (Classic squareRootAlgorithm factorialAlgorithm)		= Math.Implementations.Pi.Ramanujan.Implementation.openR Math.Implementations.Pi.Ramanujan.Classic.series squareRootAlgorithm factorialAlgorithm-	openR (Chudnovsky squareRootAlgorithm factorialAlgorithm)	= Math.Implementations.Pi.Ramanujan.Implementation.openR Math.Implementations.Pi.Ramanujan.Chudnovsky.series squareRootAlgorithm factorialAlgorithm-
− src/Factory/Math/Implementations/Pi/Ramanujan/Chudnovsky.hs
@@ -1,63 +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 the /Chudnovsky/ series for /Pi/; <http://en.wikipedia.org/wiki/Pi>.--}--module Factory.Math.Implementations.Pi.Ramanujan.Chudnovsky(--- * Constants-	series-) where---- import		Control.Arrow((***))-import			Data.Ratio((%))--- import		Factory.Data.PrimeFactors((>/<), (>*<), (>^))--- import qualified	Factory.Data.PrimeFactors				as Data.PrimeFactors-import qualified	Factory.Math.Factorial					as Math.Factorial-import qualified	Factory.Math.Implementations.Factorial			as Math.Implementations.Factorial-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Series	as Math.Implementations.Pi.Ramanujan.Series-import qualified	Factory.Math.Power					as Math.Power-import qualified	Factory.Math.SquareRoot					as Math.SquareRoot---- | Defines the parameters of the /Chudnovsky/ series.-series :: (-	Math.SquareRoot.Algorithmic	squareRootAlgorithm,-	Math.Factorial.Algorithmic	factorialAlgorithm- ) => Math.Implementations.Pi.Ramanujan.Series.Series squareRootAlgorithm factorialAlgorithm-series = Math.Implementations.Pi.Ramanujan.Series.MkSeries {-	Math.Implementations.Pi.Ramanujan.Series.terms			= \factorialAlgorithm -> zipWith (-{--		\n power -> let-			product'	= Data.PrimeFactors.product' (recip 2) 10-		in uncurry (%) . (-			(* (13591409 + 545140134 * n)) . product' *** (* power) . product'-		) $ Math.Implementations.Factorial.primeFactors (6 * n) >/< (-			Math.Implementations.Factorial.primeFactors (3 * n) >*< Math.Implementations.Factorial.primeFactors n >^ 3-		)--}-		\n power -> (-			Math.Implementations.Factorial.risingFactorial (succ $ 3 * n) (3 * n) % Math.Power.cube (Math.Factorial.factorial factorialAlgorithm n)-		) * (-			(13591409 + 545140134 * n) % power-		) -- CAVEAT: the order in which these terms are evaluated radically affects performance.-	) [0 ..] $ iterate (* (Math.Power.cube $ negate 640320 :: Integer)) 1,-	Math.Implementations.Pi.Ramanujan.Series.getSeriesScalingFactor	= \squareRootAlgorithm decimalDigits -> 426880 * Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits (10005 :: Integer),-	Math.Implementations.Pi.Ramanujan.Series.convergenceRate	= 10 ** negate 14.0	-- Empirical.-}-
− src/Factory/Math/Implementations/Pi/Ramanujan/Classic.hs
@@ -1,60 +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 the /Ramanujan/ series for /Pi/; <http://planetmath.org/encyclopedia/RamanujansFormulaForPi.html>.--}--module Factory.Math.Implementations.Pi.Ramanujan.Classic(--- * Constants-	series-) where---- import		Control.Arrow((***))-import			Data.Ratio((%))--- import		Factory.Data.PrimeFactors((>/<), (>^))--- import qualified	Factory.Data.PrimeFactors				as Data.PrimeFactors-import qualified	Factory.Math.Factorial					as Math.Factorial-import qualified	Factory.Math.Implementations.Factorial			as Math.Implementations.Factorial-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Series	as Math.Implementations.Pi.Ramanujan.Series-import qualified	Factory.Math.Power					as Math.Power-import qualified	Factory.Math.SquareRoot					as Math.SquareRoot---- | Defines the parameters of the /Ramanujan/ series.-series :: (Math.SquareRoot.Algorithmic squareRootAlgorithm, Math.Factorial.Algorithmic factorialAlgorithm) => Math.Implementations.Pi.Ramanujan.Series.Series squareRootAlgorithm factorialAlgorithm-series = Math.Implementations.Pi.Ramanujan.Series.MkSeries {-	Math.Implementations.Pi.Ramanujan.Series.terms			= \factorialAlgorithm -> let-		toFourthPower	= (^ (4 :: Int))-	in zipWith (-{--		\n power -> let-			product'	= Data.PrimeFactors.product' (recip 2) 10-		in uncurry (%) . (-			(* (1103 + 26390 * n)) . product' *** (* power) . product'-		) $ Math.Implementations.Factorial.primeFactors (4 * n) >/< Math.Implementations.Factorial.primeFactors n >^ 4--}-		\n power -> (-			Math.Implementations.Factorial.risingFactorial (succ n) (3 * n) % Math.Power.cube (Math.Factorial.factorial factorialAlgorithm n)-		) * (-			(1103 + 26390 * n) % power-		) -- CAVEAT: the order in which these terms are evaluated radically affects performance.-	) [0 ..] $ iterate (* toFourthPower 396) 1,-	Math.Implementations.Pi.Ramanujan.Series.getSeriesScalingFactor	= \squareRootAlgorithm decimalDigits -> 9801 / Math.SquareRoot.squareRoot squareRootAlgorithm decimalDigits (8 :: Integer),-	Math.Implementations.Pi.Ramanujan.Series.convergenceRate	= 10 ** negate 7.9	-- Empirical.-}-
− src/Factory/Math/Implementations/Pi/Ramanujan/Implementation.hs
@@ -1,52 +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@]	Implements a /Ramanujan/-type series for /Pi/; <http://en.wikipedia.org/wiki/Srinivasa_Ramanujan>.--}--module Factory.Math.Implementations.Pi.Ramanujan.Implementation(--- * Functions-	openR-) where--import qualified	Control.Parallel.Strategies-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Series	as Math.Implementations.Pi.Ramanujan.Series-import qualified	Factory.Math.Precision					as Math.Precision-import qualified	Factory.Math.Summation					as Math.Summation---- | Returns /Pi/, accurate to the specified number of decimal digits.-openR-	:: Math.Implementations.Pi.Ramanujan.Series.Series squareRootAlgorithm factorialAlgorithm	-- ^ This /Pi/-algorithm is parameterised by the type of other algorithms to use.-	-> squareRootAlgorithm										-- ^ The specific /square-root/ algorithm to apply to the above series.-	-> factorialAlgorithm										-- ^ The specific /factorial/-algorithm to apply to the above series.-	-> Math.Precision.DecimalDigits									-- ^ The number of decimal digits required.-	-> Rational-openR Math.Implementations.Pi.Ramanujan.Series.MkSeries {-	Math.Implementations.Pi.Ramanujan.Series.terms			= terms,-	Math.Implementations.Pi.Ramanujan.Series.getSeriesScalingFactor	= getSeriesScalingFactor,-	Math.Implementations.Pi.Ramanujan.Series.convergenceRate	= convergenceRate-} squareRootAlgorithm factorialAlgorithm decimalDigits	= uncurry (/) $ Control.Parallel.Strategies.withStrategy (-		Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq-	) (-		getSeriesScalingFactor squareRootAlgorithm decimalDigits,-		Math.Summation.sumR 64 . take (-			Math.Precision.getTermsRequired convergenceRate decimalDigits-		) $ terms factorialAlgorithm-	) -- Pair.-
− src/Factory/Math/Implementations/Pi/Ramanujan/Series.hs
@@ -1,37 +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 a <http://en.wikipedia.org/wiki/Srinivasa_Ramanujan>-type series for /Pi/.--}--module Factory.Math.Implementations.Pi.Ramanujan.Series(--- * Types--- ** Data-types-	Series(..)-) where--import qualified	Factory.Math.Precision	as Math.Precision---- | Defines a series corresponding to a specific /Ramanujan/-formula.-data Series squareRootAlgorithm factorialAlgorithm	= MkSeries {-	terms			:: factorialAlgorithm -> [Rational],					-- ^ The sequence of terms, the sum to infinity of which defines the series.-	getSeriesScalingFactor	:: squareRootAlgorithm -> Math.Precision.DecimalDigits -> Rational,	-- ^ The ratio by which the sum to infinity of the sequence, must be scaled to result in /Pi/.-	convergenceRate		:: Math.Precision.ConvergenceRate					-- ^ The expected number of digits of /Pi/, per term in the series.-}-
− src/Factory/Math/Implementations/Pi/Spigot/Algorithm.hs
@@ -1,50 +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 the set of /Spigot/-algorithms which have been implemented.--}--module Factory.Math.Implementations.Pi.Spigot.Algorithm(--- * Types--- ** Data-types-	Algorithm(..)-) where--import			Data.Ratio((%))-import qualified	Factory.Math.Implementations.Pi.Spigot.Gosper		as Math.Implementations.Pi.Spigot.Gosper-import qualified	Factory.Math.Implementations.Pi.Spigot.RabinowitzWagon	as Math.Implementations.Pi.Spigot.RabinowitzWagon-import qualified	Factory.Math.Implementations.Pi.Spigot.Spigot		as Math.Implementations.Pi.Spigot.Spigot-import qualified	Factory.Math.Pi						as Math.Pi-import qualified	ToolShed.Defaultable---- | Define those /Spigot/-algorithms which have been implemented.-data Algorithm	=-	Gosper			-- ^ A /continued fraction/ discovered by /Gosper/.-	| RabinowitzWagon	-- ^ A /continued fraction/ discovered by /Rabinowitz/ and /Wagon/.-	deriving (Eq, Read, Show)--instance ToolShed.Defaultable.Defaultable Algorithm	where-	defaultValue	= Gosper--instance Math.Pi.Algorithmic Algorithm	where-	openI Gosper			= Math.Implementations.Pi.Spigot.Spigot.openI Math.Implementations.Pi.Spigot.Gosper.series-	openI RabinowitzWagon		= Math.Implementations.Pi.Spigot.Spigot.openI Math.Implementations.Pi.Spigot.RabinowitzWagon.series--	openR algorithm decimalDigits	= Math.Pi.openI algorithm decimalDigits % (10 ^ pred decimalDigits)-
− src/Factory/Math/Implementations/Pi/Spigot/Gosper.hs
@@ -1,39 +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 the /Gosper/ series; <http://www.pi314.net/eng/goutte.php>--}--module Factory.Math.Implementations.Pi.Spigot.Gosper(--- * Constants-	series-) where--import qualified	Factory.Math.Implementations.Pi.Spigot.Series	as Math.Implementations.Pi.Spigot.Series-import qualified	Factory.Math.Precision				as Math.Precision---- | Defines a series which converges to /Pi/.-series :: Integral i => Math.Implementations.Pi.Spigot.Series.Series i-series	= Math.Implementations.Pi.Spigot.Series.MkSeries {-	Math.Implementations.Pi.Spigot.Series.baseNumerators	= map (\i -> i * pred (2 * i)) [1 ..],-	Math.Implementations.Pi.Spigot.Series.baseDenominators	= map ((* 3) . (\i -> succ i * (i + 2))) [3, 6 ..],-	Math.Implementations.Pi.Spigot.Series.coefficients	= [3, 8 ..],	-- 5n - 2-	Math.Implementations.Pi.Spigot.Series.nTerms		= Math.Precision.getTermsRequired $ 1 / 13 {-empirical convergence-rate-}-}-
− src/Factory/Math/Implementations/Pi/Spigot/RabinowitzWagon.hs
@@ -1,40 +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 the /Rabinowitz-Wagon/ series;-	<http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/spigot.pdf>-	<http://www.mathpropress.com/stan/bibliography/spigot.pdf>.--}--module Factory.Math.Implementations.Pi.Spigot.RabinowitzWagon(--- * Constants-	series-) where--import qualified	Factory.Math.Implementations.Pi.Spigot.Series	as Math.Implementations.Pi.Spigot.Series-import qualified	Factory.Math.Precision				as Math.Precision---- | Defines a series which converges to /Pi/.-series :: Integral i => Math.Implementations.Pi.Spigot.Series.Series i-series	= Math.Implementations.Pi.Spigot.Series.MkSeries {-	Math.Implementations.Pi.Spigot.Series.baseNumerators	= [1 ..],-	Math.Implementations.Pi.Spigot.Series.baseDenominators	= [3, 5 ..],-	Math.Implementations.Pi.Spigot.Series.coefficients	= repeat 2,-	Math.Implementations.Pi.Spigot.Series.nTerms		= Math.Precision.getTermsRequired $ 10 ** negate (3 / 10) {-convergence-rate-}-}
− src/Factory/Math/Implementations/Pi/Spigot/Series.hs
@@ -1,53 +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 the parameters of a series used in a /Spigot/-table to generate /Pi/.--}--module Factory.Math.Implementations.Pi.Spigot.Series(--- * Types--- ** Data-types-	Series(..),--- * Functions-	bases-) where--import			Data.Ratio((%))-import qualified	Data.Ratio-import qualified	Factory.Math.Precision	as Math.Precision--{- |-	* Defines a series composed from a sum of terms, each one of which is the product of a coefficient and a base.--	* The coefficents and bases of the series are described in /Horner form/; @Pi = c1 + (b1 * (c2 + b2 * (c3 + b3 * (...))))@.--}-data Series i	= MkSeries {-	coefficients		:: [i],-	baseNumerators		:: [i],-	baseDenominators	:: [i],-	nTerms			:: Math.Precision.DecimalDigits -> Int	-- ^ The width of the spigot-table, required to accurately generate the requested number of digits.-}---- | Combines 'baseNumerators' and 'baseDenominators', and as a side-effect, expresses the ratio in lowest terms.-bases :: Integral i => Series i -> [Data.Ratio.Ratio i]-bases MkSeries {-	baseNumerators		= n,-	baseDenominators	= d-} = zipWith (%) n d-
− src/Factory/Math/Implementations/Pi/Spigot/Spigot.hs
@@ -1,153 +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@]--	* Implements a /spigot/-algorithm; <http://en.wikipedia.org/wiki/Spigot_algorithm>.--	* Uses the traditional algorithm, rather than the /unbounded/ algorithm described by <http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf>.--}--module Factory.Math.Implementations.Pi.Spigot.Spigot(--- * Types--- ** Type-synonyms---	Base,---	Coefficients,---	I,---	Pi,---	PreDigits,---	QuotRem,--- * Constants-	decimal,--- * Functions---	carryAndDivide,---	processColumns,-	openI,--- ** Accessors---	getQuotient,---	getRemainder,--- ** Constructors---	mkRow-) where--import qualified	Control.Arrow-import qualified	Data.Char-import qualified	Data.Ratio-import qualified	Factory.Math.Implementations.Pi.Spigot.Series	as Math.Implementations.Pi.Spigot.Series-import qualified	Factory.Math.Precision				as Math.Precision--{- |-	* The type in which all arithmetic is performed.--	* A small dynamic range, 32 bits or more, is typically adequate.--}-type I	= Int---- | The constant base in which we want the resulting value of /Pi/ to be expressed.-decimal :: I-decimal	= 10---- | Coerce the polymorphic type 'Data.Ratio.Ratio' to suit the base used in our series.-type Base	= Data.Ratio.Ratio I---- | Coerce the polymorphic type returned by 'quotRem' to our specific requirements.-type QuotRem	= (I, I)---- Accessors.-getQuotient, getRemainder :: QuotRem -> I-getQuotient	= fst-getRemainder	= snd--type PreDigits		= [I]-type Pi			= [I]-type Coefficients	= [I]--{- |-	* For a digit on one row of the spigot-table, add any numerator carried from the similar calculation one column to the right.--	* Divide the result of this summation, by the denominator of the base, to get the quotient and remainder.--	* Determine the quantity to carry to the similar calculation one column to the left, by multiplying the quotient by the numerator of the base.--}-carryAndDivide :: (Base, I) -> QuotRem -> QuotRem-carryAndDivide (base, lhs) rhs-	| n < d		= (0, n)	-- In some degenerate cases, the result of the subsequent calculation can be more simply determined.-	| otherwise	= Control.Arrow.first (* Data.Ratio.numerator base) $ n `quotRem` d-	where-		d, n :: I-		d	= Data.Ratio.denominator base-		n	= lhs + getQuotient rhs	-- Carry numerator from the column to the right and add it to the current digit.--{- |-	* Fold 'carryAndDivide', from right to left, over the columns of a row in the spigot-table, continuously checking for overflow.--	* Release any previously withheld result-digits, after any adjustment for overflow in the current result-digit.--	* Withhold the current result-digit until the risk of overflow in subsequent result-digits has been assessed.--	* Call 'mkRow'.--}-processColumns-	:: Math.Implementations.Pi.Spigot.Series.Series I-	-> PreDigits-	-> [(Base, I)]	-- ^ Data-row.-	-> Pi-processColumns series preDigits l-	| overflowMargin > 1	= preDigits ++ nextRow [digit]				-- There's neither overflow, nor risk of impact from subsequent overflow.-	| overflowMargin == 1	= nextRow $ preDigits ++ [digit]			-- There's no overflow, but risk of impact from subsequent overflow.-	| otherwise		= map ((`rem` decimal) . succ) preDigits ++ nextRow [0]	-- Overflow => propagate the excess to previously withheld preDigits.-	where-		results :: [QuotRem]-		results	= init $ scanr carryAndDivide (0, undefined) l--		digit :: I-		digit	= getQuotient $ head results--		overflowMargin :: I-		overflowMargin	= decimal - digit--		nextRow :: [I] -> [I]-		nextRow preDigits'	= mkRow series preDigits' $ map getRemainder results--{- |-	* Multiply the remainders from the previous row.--	* Zip them with the constant bases, with an addition one stuck on the front to perform the conversion to decimal, to create a new row of the spigot-table.--	* Call 'processColumns'.--}-mkRow :: Math.Implementations.Pi.Spigot.Series.Series I -> PreDigits -> Coefficients -> Pi-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'.--	* Ensures that the row has suffient terms to accurately generate the required number of digits.--	* Extracts only those digits which are guaranteed to be accurate.--	* CAVEAT: the result is returned as an 'Integer', i.e. without any decimal point.--}-openI :: Math.Implementations.Pi.Spigot.Series.Series I -> Math.Precision.DecimalDigits -> Integer-openI series decimalDigits	= read . map (-	Data.Char.intToDigit . fromIntegral- ) . take decimalDigits . mkRow series [] . take (-	Math.Implementations.Pi.Spigot.Series.nTerms series decimalDigits- ) $ Math.Implementations.Pi.Spigot.Series.coefficients series-
− src/Factory/Math/Implementations/Primality.hs
@@ -1,217 +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@]--	* Determines whether an integer is prime.--	* <http://en.wikipedia.org/wiki/Primality_test>.--	* <http://primes.utm.edu/index.html>--	* CAVEAT: it doesn't determine the prime-factors of composite numbers, just that they exist.--}--module Factory.Math.Implementations.Primality(--- * Types--- ** Data-types-	Algorithm(..)--- * Functions--- ** Predicates---	isPrimeByAKS,---	isPrimeByMillerRabin,---	witnessesCompositeness-) where--import			Control.Arrow((&&&))-import qualified	Control.DeepSeq-import qualified	Control.Parallel.Strategies-import qualified	Data.Numbers.Primes-import qualified	Factory.Data.MonicPolynomial		as Data.MonicPolynomial-import qualified	Factory.Data.Polynomial			as Data.Polynomial-import qualified	Factory.Data.QuotientRing		as Data.QuotientRing-import qualified	Factory.Math.MultiplicativeOrder	as Math.MultiplicativeOrder-import qualified	Factory.Math.PerfectPower		as Math.PerfectPower-import qualified	Factory.Math.Power			as Math.Power-import qualified	Factory.Math.Primality			as Math.Primality-import qualified	Factory.Math.PrimeFactorisation		as Math.PrimeFactorisation-import qualified	ToolShed.Defaultable---- | The algorithms by which /primality/-testing has been implemented.-data Algorithm factorisationAlgorithm	=-	AKS factorisationAlgorithm	-- ^ <http://en.wikipedia.org/wiki/AKS_primality_test>.-	| MillerRabin			-- ^ <http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test>.-	deriving (Eq, Read, Show)--instance ToolShed.Defaultable.Defaultable (Algorithm factorisationAlgorithm)	where-	defaultValue	= MillerRabin--instance Math.PrimeFactorisation.Algorithmic factorisationAlgorithm => Math.Primality.Algorithmic (Algorithm factorisationAlgorithm)	where-	isPrime _ 2	= True	-- The only even prime.-	isPrime algorithm candidate-		| candidate < 2 || (-			any (-				(== 0) . (candidate `rem`)			-- The candidate has a small prime-factor, and is therefore composite.-			) . filter (-				(candidate >=) . (* 2)				-- The candidate must be at least double the small prime, for it to be a potential factor.-			) . take 5 {-arbitrarily-} $ Data.Numbers.Primes.primes	-- Excludes even numbers, provided at least the 1st prime is tested.-		)		= False-		| otherwise	= (-			case algorithm of-				AKS factorisationAlgorithm	-> isPrimeByAKS factorisationAlgorithm-				MillerRabin			-> isPrimeByMillerRabin-		) candidate--{- |-	* An implementation of the /Agrawal-Kayal-Saxena/ primality-test; <http://en.wikipedia.org/wiki/AKS_primality_test>,-	using the /Lenstra/ and /Pomerance/ algorithm.--	* CAVEAT: this deterministic algorithm has a theoretical time-complexity of @O(log^6)@,-	and therefore can't compete with the performance of probabilistic ones.--	* The /formal polynomials/ used in this algorithm, are conceptually different from /polynomial functions/;-	the /indeterminate/ and its powers, are merely used to name a sequence of pigeon-holes in which /coefficients/ are stored,-	and is never substituted for a specific value.-	This mind-shift, allows one to introduce concepts like /modular/ arithmetic on polynomials,-	which merely represent an operation on their coefficients and the pigeon-hole in which they're placed.--	[@Manindra Agrawal, Neeraj Kayal and Nitin Saxena@]	<http://www.cse.iitk.ac.in/users/manindra/algebra/primality_v6.pdf>.--	[@H. W. Lenstra, Jr. and Carl Pomerance@]		<http://www.math.dartmouth.edu/~carlp/PDF/complexity12.pdf>.--	[@Salembier and Southerington@]				<http://ece.gmu.edu/courses/ECE746/project/F06_Project_resources/Salembier_Southerington_AKS.pdf>,--	[@R. Crandall and J. Papadopoulos@]			<http://images.apple.com/acg/pdf/aks3.pdf>,--	[@Andreas Klappenecker@]				<http://faculty.cs.tamu.edu/klappi/629/aks.ps>,--	[@Vibhor Bhatt and G. K. Patra@]			<http://www.cmmacs.ernet.in/cmmacs/Publications/resch_rep/rrcm0307.pdf>,--}-isPrimeByAKS :: (-	Control.DeepSeq.NFData			i,-	Integral				i,-	Math.PrimeFactorisation.Algorithmic	factorisationAlgorithm,-	Show					i- ) => factorisationAlgorithm -> i -> Bool-isPrimeByAKS factorisationAlgorithm n	= and [-	not $ Math.PerfectPower.isPerfectPower n,	-- Step 1.-	Math.Primality.areCoprime n `all` filter (/= n) [2 .. r],	-- Step 3.-	and $ Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rdeepseq	{-Benefits from '+RTS -H100M', which reduces garbage-collections-} (-		\a	-> let---			lhs, rhs :: Data.Polynomial.Polynomial i i-			lhs	= Data.Polynomial.raiseModulo (Data.Polynomial.mkLinear 1 a) n {-power-} n {-modulus-}-			rhs	= Data.Polynomial.mod' (Data.Polynomial.mkPolynomial [(1, n), (a, 0)]) n-		in Data.QuotientRing.areCongruentModulo (-			Data.MonicPolynomial.mkMonicPolynomial lhs-		) (-			Data.MonicPolynomial.mkMonicPolynomial rhs-		) (-			Data.MonicPolynomial.mkMonicPolynomial modulus-		) -- Because all these polynomials are /monic/, one can establish /congruence/ using /integer/-division.-	) [-		1 .. floor . (* lg) . sqrt $ fromIntegral r-	] -- Step 4; (x + a)^n ~ x^n + a mod (x^r - 1, n).- ] where-	lg :: Double-	lg	= logBase 2 $ fromIntegral n----	r :: i-	r	= fst . head . dropWhile (-		(<= floor (Math.Power.square lg)) . snd-	 ) . map (-		id &&& Math.MultiplicativeOrder.multiplicativeOrder factorisationAlgorithm n-	 ) $ Math.Primality.areCoprime n `filter` [2 ..]	-- Step 2.----	modulus :: Data.Polynomial.Polynomial i i-	modulus	= Data.Polynomial.mkPolynomial [(1, r), (negate 1, 0)]--{- |-	* Uses the specified 'base' in an attempt to prove the /compositeness/ of an integer.--	* This is the opposite of the /Miller Test/; <http://mathworld.wolfram.com/MillersPrimalityTest.html>.--	* If the result is 'True', then the candidate is /composite/; regrettably the converse isn't true.-	Amongst the set of possible bases, over three-quarters are /witnesses/ to the compositeness of a /composite/ candidate,-	the remainder belong to the subset of /liars/.-	In consequence, many false results must be accumulated for different bases, to convincingly identify a prime.--}-witnessesCompositeness :: (Integral i, Show i)-	=> i	-- ^ Candidate integer.-	-> i-	-> Int-	-> i	-- ^ Base.-	-> Bool-witnessesCompositeness candidate oddRemainder nPowersOfTwo base	= all (-	$ ((`rem` candidate) . Math.Power.square) `iterate` Math.Power.raiseModulo base oddRemainder candidate	-- Repeatedly modulo-square.- ) [-	(/= 1) . head,					-- Check whether the zeroeth modulo-power is incongruent to one.-	notElem (pred candidate) . take nPowersOfTwo	-- Check whether any modulo-power is incongruent to -1.- ]--{- |-	* Repeatedly calls 'witnessesCompositeness', to progressively increase the probability of detecting a /composite/ number,-	until ultimately the candidate integer is proven to be prime.--	* Should all bases be tested, then the test is deterministic, but at an efficiency /lower/ than performing prime-factorisation.--	* The test becomes deterministic, for any candidate integer, when the number of tests reaches the limit defined by /Eric Bach/.--	* A testing of smaller set of bases, is sufficient for candidates smaller than various thresholds; <http://primes.utm.edu/prove/prove2_3.html>.--	* <http://en.wikipedia.org/wiki/Miller-Rabin_primality_test>.--	* <http://mathworld.wolfram.com/Rabin-MillerStrongPseudoprimeTest.html>--	* <http://mathworld.wolfram.com/StrongPseudoprime.html>.--	* <http://oeis.org/A014233>, <http://oeis.org/A006945>.--}-isPrimeByMillerRabin :: (Integral i, Show i) => i -> Bool-isPrimeByMillerRabin primeCandidate	= not $ witnessesCompositeness primeCandidate (-	fst $ last binaryFactors	-- Odd-remainder.- ) (-	length binaryFactors	-- The number of times that 'two' can be factored-out from 'predecessor'.- ) `any` testBases	where-	predecessor	= pred primeCandidate-	binaryFactors	= takeWhile ((== 0) . snd) . tail {-drop the original-} $ iterate ((`quotRem` 2) . fst) (predecessor, 0)	-- Factor-out powers of two.-	testBases-		| null fewestPrimeBases	= let-			millersTestSet	= floor . (* 2 {-Eric Bach-}) . Math.Power.square . toRational {-avoid premature rounding-} $ log (fromIntegral primeCandidate :: Double {-overflows at 10^851-})-		in [2 .. predecessor `min` millersTestSet]-		| otherwise		= head fewestPrimeBases `take` Data.Numbers.Primes.primes-		where-			fewestPrimeBases	= map fst $ dropWhile ((primeCandidate >=) . snd) [-				(0,	9),			-- All odd integers less this, are prime, and require no further verification.-				(1,	2047),-				(2,	1373653),-				(3,	25326001),-				(4,	3215031751),-				(5,	2152302898747),		-- Jaeschke ...-				(6,	3474749660383),-				(8,	341550071728321),-				(11,	3825123056546413051),	-- Zhang ...-				(12,	318665857834031151167461),-				(13,	3317044064679887385961981),-				(14,	6003094289670105800312596501),-				(15,	59276361075595573263446330101),-				(17,	564132928021909221014087501701),-				(19,	1543267864443420616877677640751301),-				(20,	10 ^ (36 :: Int))	-- At least.-			 ]-
− src/Factory/Math/Implementations/PrimeFactorisation.hs
@@ -1,145 +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@]--	* Implements several different prime-factorisation algorithms.--	* <http://www.tug.org/texinfohtml/coreutils.html#factor-invocation>.--}--module Factory.Math.Implementations.PrimeFactorisation(--- * Types--- ** Data-types-	Algorithm(---		DixonsMethod,-		FermatsMethod,-		TrialDivision-	)--- * Functions---	factoriseByDixonsMethod---	factoriseByFermatsMethod---	factoriseByTrialDivision-) where--import			Control.Arrow((&&&))-import qualified	Control.Arrow-import qualified	Control.DeepSeq-import qualified	Control.Parallel.Strategies-import qualified	Data.Maybe-import qualified	Data.Numbers.Primes-import qualified	Factory.Data.Exponential	as Data.Exponential-import			Factory.Data.Exponential((<^))-import qualified	Factory.Data.PrimeFactors	as Data.PrimeFactors-import qualified	Factory.Math.PerfectPower	as Math.PerfectPower-import qualified	Factory.Math.Power		as Math.Power-import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation-import qualified	ToolShed.Data.Pair-import qualified	ToolShed.Defaultable---- | The algorithms by which prime-factorisation has been implemented.-data Algorithm-	= DixonsMethod	-- ^ <http://en.wikipedia.org/wiki/Dixon%27s_factorization_method>.-	| FermatsMethod	-- ^ <http://en.wikipedia.org/wiki/Fermat%27s_factorization_method>.-	| TrialDivision	-- ^ <http://en.wikipedia.org/wiki/Trial_division>.-	deriving (Eq, Read, Show)--instance ToolShed.Defaultable.Defaultable Algorithm	where-	defaultValue	= TrialDivision--instance Math.PrimeFactorisation.Algorithmic Algorithm	where-	primeFactors algorithm	= case algorithm of-		DixonsMethod	-> factoriseByDixonsMethod-		FermatsMethod	-> Data.PrimeFactors.reduce . factoriseByFermatsMethod-		TrialDivision	-> factoriseByTrialDivision---- | <http://en.wikipedia.org/wiki/Dixon%27s_factorization_method>.-factoriseByDixonsMethod :: Integral base => base -> Data.PrimeFactors.Factors base exponent-factoriseByDixonsMethod	= undefined--{- |-	* <http://en.wikipedia.org/wiki/Fermat%27s_factorization_method>.--	* <http://mathworld.wolfram.com/FermatsFactorizationMethod.html>.--	* <http://en.wikipedia.org/wiki/Congruence_of_squares>.--	*	@i = f1 * f2@							Assume a non-trivial factorisation, ie. one in which both factors exceed one.-	=>	@i = (larger + smaller) * (larger - smaller)@			Represent the co-factors as a sum and difference.-	=>	@i = larger^2 - smaller^2@					Which has an integral solution if @i@ is neither /even/ nor a /perfect square/.-	=>	@sqrt (larger^2 - i) = smaller@					Search for /larger/, which results in an integral value for /smaller/.--	* Given that the smaller factor /f2/, can't be less than 3 (/i/ isn't /even/), then the larger /f1/, can't be greater than @(i `div` 3)@.-	So:	@(f2 >= 3) && (f1 <= i `div` 3)@				Two equations which can be used to solve for /larger/.-	=>	@(larger - smaller >= 3) && (larger + smaller <= i `div` 3)@	Add these to eliminate /smaller/.-	=>	@larger <= (i + 9) `div` 6@					The upper bound of the search-space.--	* This algorithm works best when there's a factor close to the /square-root/.--}-factoriseByFermatsMethod :: (-	Control.DeepSeq.NFData	base,-	Control.DeepSeq.NFData	exponent,-	Integral		base,-	Num			exponent- ) => base -> Data.PrimeFactors.Factors base exponent-factoriseByFermatsMethod i-	| i <= 3				= [Data.Exponential.rightIdentity i]-	| even i				= Data.Exponential.rightIdentity 2 : factoriseByFermatsMethod (i `div` 2) {-recurse-}-	| Data.Maybe.isJust maybeSquareNumber	= (<^ 2) `map` factoriseByFermatsMethod (Data.Maybe.fromJust maybeSquareNumber) {-recurse-}-	| null factors				= [Data.Exponential.rightIdentity i]	-- Prime.-	| otherwise				= uncurry (++) . Control.Parallel.Strategies.withStrategy (-		Control.Parallel.Strategies.parTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.rdeepseq	-- CAVEAT: unproductive on the size of integers tested so far.-	) . ToolShed.Data.Pair.mirror factoriseByFermatsMethod $ head factors-	where---		maybeSquareNumber :: Integral i => Maybe i-		maybeSquareNumber	= Math.PerfectPower.maybeSquareNumber i----		factors :: Integral i => [i]-		factors	= map (-			(-				uncurry (+) &&& uncurry (-)	-- Construct the co-factors as the sum and difference of /larger/ and /smaller/.-			) . Control.Arrow.second Data.Maybe.fromJust-		 ) . filter (-			Data.Maybe.isJust . snd	-- Search for a perfect square.-		 ) . map (-			Control.Arrow.second $ Math.PerfectPower.maybeSquareNumber {-hotspot-} . (+ negate i)	-- Associate the corresponding value of /smaller/.-		 ) . takeWhile (-			(<= (i + 9) `div` 6) . fst	-- Terminate the search at the maximum value of /larger/.-		 ) . Math.Power.squaresFrom {-hotspot-} . ceiling $ sqrt (fromIntegral i :: Double)	-- Start the search at the minimum value of /larger/.--{- |-	* Decomposes the specified integer, into a product of /prime/-factors,-	using <http://mathworld.wolfram.com/DirectSearchFactorization.html>, AKA <http://en.wikipedia.org/wiki/Trial_division>.--	* This works best when the factors are small.--}-factoriseByTrialDivision :: (Integral base, Num exponent) => base -> Data.PrimeFactors.Factors base exponent-factoriseByTrialDivision	= slave Data.Numbers.Primes.primes where-	slave primes i-		| null primeCandidates	= [Data.Exponential.rightIdentity i]-		| otherwise		= Data.Exponential.rightIdentity lowestPrimeFactor `Data.PrimeFactors.insert'` slave primeCandidates (i `quot` lowestPrimeFactor)-		where-			primeCandidates	= dropWhile (-				(/= 0) . (i `rem`)-			 ) $ takeWhile (-				<= Math.PrimeFactorisation.maxBoundPrimeFactor i-			 ) primes--			lowestPrimeFactor	= head primeCandidates-
− src/Factory/Math/Implementations/Primes/Algorithm.hs
@@ -1,63 +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@]--	* Generates the constant list of /prime-numbers/, by a variety of different algorithms.--	* <http://www.haskell.org/haskellwiki/Prime_numbers>.--	* <http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.31.3936&rep=rep1&type=pdf>.--	* <http://larc.unt.edu/ian/pubs/sieve.pdf>.--}--module Factory.Math.Implementations.Primes.Algorithm(--- * Types--- ** Data-types-	Algorithm(..)-) where--import qualified	Data.Numbers.Primes-import qualified	Factory.Data.PrimeWheel					as Data.PrimeWheel-import qualified	Factory.Math.Implementations.Primes.SieveOfAtkin	as Math.Implementations.Primes.SieveOfAtkin-import qualified	Factory.Math.Implementations.Primes.SieveOfEratosthenes	as Math.Implementations.Primes.SieveOfEratosthenes-import qualified	Factory.Math.Implementations.Primes.TrialDivision	as Math.Implementations.Primes.TrialDivision-import qualified	Factory.Math.Implementations.Primes.TurnersSieve	as Math.Implementations.Primes.TurnersSieve-import qualified	Factory.Math.Primes					as Math.Primes-import qualified	ToolShed.Defaultable---- | The implemented methods by which the primes may be generated.-data Algorithm-	= SieveOfAtkin Integer					-- ^ The /Sieve of Atkin/, optimised using a 'Data.PrimeWheel.PrimeWheel' of optimal size, for primes up to the specified maximum bound; <http://en.wikipedia.org/wiki/Sieve_of_Atkin>.-	| SieveOfEratosthenes Data.PrimeWheel.NPrimes		-- ^ The /Sieve of Eratosthenes/ (<http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes>), optimised using a 'Data.PrimeWheel.PrimeWheel'.-	| TrialDivision Data.PrimeWheel.NPrimes			-- ^ For each candidate, confirm indivisibility, by all /primes/ smaller than its /square-root/, optimised using a 'Data.PrimeWheel.PrimeWheel'.-	| TurnersSieve						-- ^ For each /prime/, the infinite list of candidates greater than its /square/, is filtered for indivisibility; <http://www.haskell.org/haskellwiki/Prime_numbers#Turner.27s_sieve_-_Trial_division>.-	| WheelSieve Int					-- ^ 'Data.Numbers.Primes.wheelSieve'.-	deriving (Eq, Read, Show)--instance ToolShed.Defaultable.Defaultable Algorithm	where-	defaultValue	= SieveOfEratosthenes 7	-- Resulting in a wheel of circumference 510510.--instance Math.Primes.Algorithmic Algorithm	where-	primes (SieveOfAtkin maxPrime)		= Math.Implementations.Primes.SieveOfAtkin.sieveOfAtkin (Data.PrimeWheel.estimateOptimalSize maxPrime) $ fromIntegral maxPrime-	primes (SieveOfEratosthenes wheelSize)	= Math.Implementations.Primes.SieveOfEratosthenes.sieveOfEratosthenes wheelSize-	primes (TrialDivision wheelSize)	= Math.Implementations.Primes.TrialDivision.trialDivision wheelSize-	primes TurnersSieve			= Math.Implementations.Primes.TurnersSieve.turnersSieve-	primes (WheelSieve wheelSize)		= Data.Numbers.Primes.wheelSieve wheelSize	-- Has better space-complexity than 'SieveOfEratosthenes'.
− src/Factory/Math/Implementations/Primes/SieveOfAtkin.hs
@@ -1,242 +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@]--	* Generates the constant /bounded/ list of /prime-numbers/, using the /Sieve of Atkin/; <http://en.wikipedia.org/wiki/Sieve_of_Atkin>.--	* <cr.yp.to/papers/primesieves-19990826.pdf>.--	* The implementation;-		has been optimised using a /wheel/ of static, but parameterised, size;-		has been parallelized;-		is polymorphic, but with a specialisation for type 'Int'.-- [@CAVEAT@] The 'Int'-specialisation is implemented by a /rewrite-rule/, which is /very/ fragile.--}--module Factory.Math.Implementations.Primes.SieveOfAtkin(--- * Types--- ** Data-types---	PolynomialType,--- * Constants---	atkinsModulus,---	inherentPrimes,---	nInherentPrimes,---	squares,--- * Functions---	polynomialTypeLookupPeriod,---	polynomialTypeLookup,---	findPolynomialSolutions,---	filterOddRepetitions,---	generateMultiplesOfSquareTo,---	getPrefactoredPrimes,-	sieveOfAtkin,---	sieveOfAtkinInt-) where--import qualified	Control.DeepSeq-import qualified	Control.Parallel.Strategies-import qualified	Data.Array.IArray-import			Data.Array.IArray((!))-import qualified	Data.IntSet-import qualified	Data.List-import qualified	Data.Set-import qualified	Factory.Data.PrimeWheel	as Data.PrimeWheel-import qualified	Factory.Math.Power	as Math.Power-import qualified	ToolShed.Data.List---- | Defines the types of /quadratic/, available to test the potential primality of a candidate integer.-data PolynomialType-	= ModFour	-- ^ Suitable for primality-testing numbers meeting @(n `mod` 4 == 1)@.-	| ModSix	-- ^ Suitable for primality-testing numbers meeting @(n `mod` 6 == 1)@.-	| ModTwelve	-- ^ Suitable for primality-testing numbers meeting @(n `mod` 12 == 11)@.-	| None		-- ^ There's no polynomial which can assess primality, because the candidate is composite.-	deriving Eq---- | The constant modulus used to select the appropriate quadratic for a prime candidate.-atkinsModulus :: Integral i => i-atkinsModulus	= foldr1 lcm [4, 6, 12]	-- Sure, this is always '12', but this is the reason why.---- | The constant list of primes factored-out by the unoptimised algorithm.-inherentPrimes :: Integral i => [i]-inherentPrimes	= [2, 3]---- | The constant number of primes factored-out by the unoptimised algorithm.-nInherentPrimes :: Int-nInherentPrimes	= length (inherentPrimes :: [Int])---- | Typically the set of primes which have been built into the specified /wheel/, but never fewer than 'inherentPrimes'.-getPrefactoredPrimes :: Integral i => Data.PrimeWheel.PrimeWheel i -> [i]-getPrefactoredPrimes	= max inherentPrimes . Data.PrimeWheel.getPrimeComponents---- | The period over which the data returned by 'polynomialTypeLookup' repeats.-polynomialTypeLookupPeriod :: Integral i => Data.PrimeWheel.PrimeWheel i -> i-polynomialTypeLookupPeriod	= lcm atkinsModulus . Data.PrimeWheel.getCircumference--{- |-	* Defines which, if any, of the three /quadratics/ is appropriate for the primality-test for each candidate.--	* Since this algorithm uses /modular arithmetic/, the /range/ of results repeat after a short /domain/ related to the /modulus/.-	Thus one need calculate at most one period of this cycle, but fewer if the maximum prime required falls within the first cycle of results.--	* Because the results are /bounded/, they're returned in a zero-indexed /array/, to provide efficient random access;-	the first few elements should never be required, but it makes query clearer.--	* <http://en.wikipedia.org/wiki/Sieve_of_Atkin>.--}-polynomialTypeLookup :: (Data.Array.IArray.Ix i, Integral i)-	=> Data.PrimeWheel.PrimeWheel i-	-> i	-- ^ The maximum prime required.-	-> Data.Array.IArray.Array i PolynomialType-polynomialTypeLookup primeWheel maxPrime	= Data.Array.IArray.listArray (0, pred (polynomialTypeLookupPeriod primeWheel) `min` maxPrime) $ map select [0 ..]	where---	select :: Integral i => i -> PolynomialType-	select n-		| any (-			(== 0) . (n `rem`)		-- Though this is merely /Trial Division/, it's only performed over a short bounded interval of numerators.-		) primeComponents	= None-		| r `elem` [1, 5]	= ModFour	-- We actually require @(n `mod` 4 == 1)@, but this is the equivalent modulo 12, with @(r == 9)@ removed because they're all divisible by /3/.-		| r == 7		= ModSix	-- We actually require @(n `mod` 6 == 1)@, but this is the equivalent modulo 12, where @(r == 1)@ has been accounted for above.-		| r == 11		= ModTwelve	-- We require @(n `mod` 12 == 11)@.-		| otherwise		= None-		where-			r		= n `rem` atkinsModulus-			primeComponents	= drop nInherentPrimes $ Data.PrimeWheel.getPrimeComponents primeWheel---- | The constant, infinite list of the /squares/, of integers increasing from /1/.-squares :: Integral i => [i]-squares	= map snd $ Math.Power.squaresFrom 1--{- |-	* Returns the /ordered/ list of those values with an /odd/ number of occurrences in the specified /unordered/ list.--	* CAVEAT: this is expensive in both execution-time and space.-	The typical imperative-style implementation accumulates polynomial-solutions in a /mutable array/ indexed by the candidate integer.-	This doesn't translate seamlessly to the /pure functional/ domain where /arrays/ naturally immutable,-	so we /sort/ a /list/ of polynomial-solutions, then measure the length of the solution-spans, corresponding to viable candidates.-	Regrettably, 'Data.List.sort' (implemented in /GHC/ by /mergesort/) has a time-complexity /O(n*log n)/-	which is greater than the theoretical /O(n)/ of the whole /Sieve of Atkin/;-	/GHC/'s old /qsort/-implementation is even slower :(--}-filterOddRepetitions :: Ord a => [a] -> [a]--- filterOddRepetitions	= map head . filter (foldr (const not) False) . Data.List.group . Data.List.sort	-- Too slow.-filterOddRepetitions	= slave True . Data.List.sort where-	slave isOdd (one : remainder@(two : _))-		| one == two	= slave (not isOdd) remainder-		| isOdd		= one : beginSpan-		| otherwise	= beginSpan-		where-			beginSpan	= slave True remainder-	slave True [singleton]	= [singleton]-	slave _ _		= []--{- |-	* Returns the ordered list of solutions aggregated from each of three /bivariate quadratics/; @z = f(x, y)@.--	* For a candidate integer to be prime, it is necessary but insufficient, that there are an /odd/ number of solutions of value /candidate/.--	* At most one of these three polynomials is suitable for the validation of any specific candidate /z/, depending on 'lookupPolynomialType'.-	so the three sets of solutions are mutually exclusive.-	One coordinate @(x, y)@, can have solutions in more than one of the three polynomials.--	* This algorithm exhaustively traverses the domain @(x, y)@, for resulting /z/ of the required modulus.-	Whilst it tightly constrains the bounds of the search-space, it searches the domain methodically rather than intelligently.--}-findPolynomialSolutions :: (Control.DeepSeq.NFData i, Data.Array.IArray.Ix i, Integral i)-	=> Data.PrimeWheel.PrimeWheel i-	-> i	-- ^ The maximum prime-number required.-	-> [i]-findPolynomialSolutions primeWheel maxPrime	= foldr1 ToolShed.Data.List.merge {-The lists were previously sorted, as a side-effect, by 'filterOddRepetitions'-} $ Control.Parallel.Strategies.withStrategy (-		Control.Parallel.Strategies.parList Control.Parallel.Strategies.rdeepseq-	 ) [-		{-# SCC "4x^2+y^2" #-} filterOddRepetitions [-			z |-				x'	<- takeWhile (<= pred maxPrime) $ map (* 4) squares,-				z	<- takeWhile (<= maxPrime) $ map (+ x') oddSquares,-				lookupPolynomialType z == ModFour-		], -- List-comprehension. Twice the length of the other two lists.-		{-# SCC "3x^2+y^2" #-} filterOddRepetitions [-			z |-				x'	<- takeWhile (<= pred maxPrime) $ map (* 3) squares,-				z	<- takeWhile (<= maxPrime) . map (+ x') $ if even x' then oddSelection else evenSelection,-				lookupPolynomialType z == ModSix-		], -- List-comprehension.-		{-# SCC "3x^2-y^2" #-} filterOddRepetitions [-			z |-				x2	<- takeWhile (<= maxPrime `div` 2) squares,-				z	<- dropWhile (> maxPrime) . map (3 * x2 -) . takeWhile (< x2) $ if even x2 then oddSelection else evenSelection,-				lookupPolynomialType z == ModTwelve-		] -- List-comprehension.-	] where-		(evenSquares, oddSquares)	= Data.List.partition even squares----		evenSelection, oddSelection :: Integral i => [i]-		evenSelection	= selection110 evenSquares	where-			selection110 (x0 : x1 : _ : xs)	= x0 : x1 : selection110 xs	-- Effectively, those for meeting ((== 4) . (`mod` 6)).-			selection110 xs			= xs-		oddSelection	= selection101 oddSquares	where-			selection101 (x0 : _ : x2 : xs)	= x0 : x2 : selection101 xs	-- Effectively, those for meeting ((== 1) . (`mod` 6)).-			selection101 xs			= xs----		lookupPolynomialType :: (Data.Array.IArray.Ix i, Integral i) => i -> PolynomialType-		lookupPolynomialType	= (polynomialTypeLookup primeWheel maxPrime !) . (`rem` polynomialTypeLookupPeriod primeWheel)---- | Generates the /bounded/ list of multiples, of the /square/ of the specified prime, skipping those which aren't required.-generateMultiplesOfSquareTo :: Integral i-	=> Data.PrimeWheel.PrimeWheel i	-- ^ Used to generate the gaps between prime multiples of the square.-	-> i				-- ^ The /prime/.-	-> i				-- ^ The maximum bound.-	-> [i]-generateMultiplesOfSquareTo primeWheel prime max'	= takeWhile (<= max') . scanl (\accumulator -> (+ accumulator) . (* prime2)) prime2 . cycle $ Data.PrimeWheel.getSpokeGaps primeWheel	where-	prime2	= Math.Power.square prime--{- |-	* Generates the constant /bounded/ list of /prime-numbers/.--	* <http://cr.yp.to/papers/primesieves-19990826.pdf>--}-sieveOfAtkin :: (Control.DeepSeq.NFData i, Data.Array.IArray.Ix i, Integral i)-	=> Data.PrimeWheel.NPrimes	-- ^ Other implementations effectively use a hard-coded value either /2/ or /3/, but /6/ seems better.-	-> i				-- ^ The maximum prime required.-	-> [i]				-- ^ The /bounded/ list of primes.-sieveOfAtkin wheelSize maxPrime	= (prefactoredPrimes ++) . filterSquareFree Data.Set.empty . dropWhile (<= maximum prefactoredPrimes) $ findPolynomialSolutions primeWheel maxPrime	where-	primeWheel		= Data.PrimeWheel.mkPrimeWheel wheelSize-	prefactoredPrimes	= getPrefactoredPrimes primeWheel----	filterSquareFree :: Integral i => Data.Set.Set i -> [i] -> [i]-	filterSquareFree _ []	= []-	filterSquareFree primeMultiples (candidate : candidates)-		| Data.Set.member candidate primeMultiples	= {-# SCC "delete" #-} filterSquareFree (Data.Set.delete candidate primeMultiples) candidates	-- Tail-recurse.-		| otherwise					= {-# SCC "insert" #-} candidate : filterSquareFree (Data.Set.union primeMultiples . Data.Set.fromDistinctAscList $ generateMultiplesOfSquareTo primeWheel candidate maxPrime) candidates--{-# NOINLINE sieveOfAtkin #-}-{-# RULES "sieveOfAtkin/Int" sieveOfAtkin = sieveOfAtkinInt #-}	-- CAVEAT: doesn't fire when built with profiling enabled.---- | A specialisation of 'sieveOfAtkin', which reduces both the execution-time and the space required.-sieveOfAtkinInt :: Data.PrimeWheel.NPrimes -> Int -> [Int]-sieveOfAtkinInt wheelSize maxPrime	= (prefactoredPrimes ++) . filterSquareFree Data.IntSet.empty . dropWhile (<= maximum prefactoredPrimes) $ findPolynomialSolutions primeWheel maxPrime	where-	primeWheel		= Data.PrimeWheel.mkPrimeWheel wheelSize-	prefactoredPrimes	= getPrefactoredPrimes primeWheel--	filterSquareFree :: Data.IntSet.IntSet -> [Int] -> [Int]-	filterSquareFree _ []	= []-	filterSquareFree primeMultiples (candidate : candidates)-		| Data.IntSet.member candidate primeMultiples	= filterSquareFree (Data.IntSet.delete candidate primeMultiples) candidates-		| otherwise					= candidate : filterSquareFree (Data.IntSet.union primeMultiples . Data.IntSet.fromDistinctAscList $ generateMultiplesOfSquareTo primeWheel candidate maxPrime) candidates-
− src/Factory/Math/Implementations/Primes/SieveOfEratosthenes.hs
@@ -1,162 +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@]--	* Generates the constant, conceptually infinite, list of /prime-numbers/, using the /Sieve of Eratosthenes/; <http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes>.--	* Based on <http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf>.--	* The implementation;-		has been optimised using a /wheel/ of static, but parameterised, size;-		is polymorphic, but with a specialisation for type 'Int'.-- [@CAVEAT@] The 'Int'-specialisation is implemented by a /rewrite-rule/, which is /very/ fragile.--}--module Factory.Math.Implementations.Primes.SieveOfEratosthenes(--- * Types--- ** Type-synonyms---	PrimeMultiplesQueue,---	PrimeMultiplesMap,---	Repository,---	PrimeMultiplesMapInt,---	RepositoryInt,--- * Functions---	head',---	tail',-	sieveOfEratosthenes,---	sieveOfEratosthenesInt-) where--import			Control.Arrow((&&&), (***))-import qualified	Control.Arrow-import qualified	Data.IntMap-import qualified	Data.Map-import			Data.Sequence((|>))-import qualified	Data.Sequence-import qualified	Factory.Data.PrimeWheel		as Data.PrimeWheel---- | The 'Data.Sequence.Seq' counterpart to 'Data.List.head'.-head' :: Data.Sequence.Seq [a] -> [a]-head'	= (`Data.Sequence.index` 0)--{- |-	* The 'Data.Sequence.Seq' counterpart to 'Data.List.tail'.--	* CAVEAT: because @ Data.List.tail [] @ returns an error, whereas @ tail' Data.Sequence.empty @ returns 'Data.Sequence.empty',-	this function is for internal use only.--}-tail' :: Data.Sequence.Seq [a] -> Data.Sequence.Seq [a]-tail'	= Data.Sequence.drop 1---- | An ordered queue of the multiples of primes.-type PrimeMultiplesQueue i	= Data.Sequence.Seq (Data.PrimeWheel.PrimeMultiples i)---- | A map of the multiples of primes.-type PrimeMultiplesMap i	= Data.Map.Map i (Data.PrimeWheel.PrimeMultiples i)---- | Combine a /queue/, with a /map/, to form a repository to hold prime-multiples.-type Repository i	= (PrimeMultiplesQueue i, PrimeMultiplesMap i)--{- |-	* A refinement of the /Sieve Of Eratosthenes/, which pre-sieves candidates, selecting only those /coprime/ to the specified short sequence of low prime-numbers.--	* The short sequence of initial primes are represented by a 'Data.PrimeWheel.PrimeWheel',-	of parameterised, but static, size; <http://en.wikipedia.org/wiki/Wheel_factorization>.--	* The algorithm requires one to record multiples of previously discovered primes, allowing /composite/ candidates to be eliminated by comparison.--	* Because each /list/ of multiples, starts with the /square/ of the prime from which it was generated,-	the vast majority will be larger than the maximum prime ultimately demanded, and the effort of constructing and storing this list, is consequently wasted.-	Many implementations solve this, by requiring specification of the maximum prime required,-	thus allowing the construction of redundant lists of multiples to be avoided.--	* This implementation doesn't impose that constraint, leaving a requirement for /rapid/ storage,-	which is supported by /appending/ the /list/ of prime-multiples, to a /queue/.-	If a large enough candidate is ever generated, to match the /head/ of the /list/ of prime-multiples,-	at the /head/ of this /queue/, then the whole /list/ of prime-multiples is dropped from the /queue/,-	but the /tail/ of this /list/ of prime-multiples, for which there is now a high likelyhood of a subsequent match, must now be re-recorded.-	A /queue/ doesn't support efficient random /insertion/, so a 'Data.Map.Map' is used for these subsequent multiples.-	This solution is faster than just using a "Data.PQueue.Min".--	* CAVEAT: has linear /O(n)/ space-complexity.--}-sieveOfEratosthenes :: Integral i-	=> Data.PrimeWheel.NPrimes-	-> [i]-sieveOfEratosthenes	= uncurry (++) . (Data.PrimeWheel.getPrimeComponents &&& start . Data.PrimeWheel.roll) . Data.PrimeWheel.mkPrimeWheel	where-	start :: Integral i => [Data.PrimeWheel.Distance i] -> [i]-	start ~((candidate, rollingWheel) : distances)	= candidate : sieve (head distances) (Data.Sequence.singleton $ Data.PrimeWheel.generateMultiples candidate rollingWheel, Data.Map.empty)--	sieve :: Integral i => Data.PrimeWheel.Distance i -> Repository i -> [i]-	sieve distance@(candidate, rollingWheel) repository@(primeSquares, squareFreePrimeMultiples)	= case Data.Map.lookup candidate squareFreePrimeMultiples of-		Just primeMultiples	-> sieve' $ Control.Arrow.second (insertUniq primeMultiples . Data.Map.delete candidate) repository	-- Re-insert subsequent multiples.-		Nothing -- Not a square-free composite.-			| candidate == smallestPrimeSquare	-> sieve' $ (tail' *** insertUniq subsequentPrimeMultiples) repository	-- Migrate subsequent prime-multiples, from 'primeSquares' to 'squareFreePrimeMultiples'.-			| otherwise {-prime-}			-> candidate : sieve' (Control.Arrow.first (|> Data.PrimeWheel.generateMultiples candidate rollingWheel) repository)-			where-				(smallestPrimeSquare : subsequentPrimeMultiples)	= head' primeSquares-		where---			sieve' :: Repository i -> [i]-			sieve'	= sieve $ Data.PrimeWheel.rotate distance	-- Tail-recurse.--			insertUniq :: Ord i => Data.PrimeWheel.PrimeMultiples i -> PrimeMultiplesMap i -> PrimeMultiplesMap i-			insertUniq l m	= insert $ dropWhile (`Data.Map.member` m) l	where---				insert :: Ord i => Data.PrimeWheel.PrimeMultiples i -> PrimeMultiplesMap i-				insert []		= error "Factory.Math.Implementations.Primes.SieveOfEratosthenes.sieveOfEratosthenes.sieve.insertUniq.insert:\tnull list"-				insert (key : values)	= Data.Map.insert key values m--{-# NOINLINE sieveOfEratosthenes #-}-{-# RULES "sieveOfEratosthenes/Int" sieveOfEratosthenes = sieveOfEratosthenesInt #-}	-- CAVEAT: doesn't fire when built with profiling enabled.---- | A specialisation of 'PrimeMultiplesMap'.-type PrimeMultiplesMapInt	= Data.IntMap.IntMap (Data.PrimeWheel.PrimeMultiples Int)---- | A specialisation of 'Repository'.-type RepositoryInt	= (PrimeMultiplesQueue Int, PrimeMultiplesMapInt)--{- |-	* A specialisation of 'sieveOfEratosthenes', which approximately /doubles/ the speed and reduces the space required.--	* CAVEAT: because the algorithm involves /squares/ of primes,-	this implementation will overflow when finding primes greater than @2^16@ on a /32-bit/ machine.--}-sieveOfEratosthenesInt :: Data.PrimeWheel.NPrimes -> [Int]-sieveOfEratosthenesInt	= uncurry (++) . (Data.PrimeWheel.getPrimeComponents &&& start . Data.PrimeWheel.roll) . Data.PrimeWheel.mkPrimeWheel	where-	start :: [Data.PrimeWheel.Distance Int] -> [Int]-	start ~((candidate, rollingWheel) : distances)	= candidate : sieve (head distances) (Data.Sequence.singleton $ Data.PrimeWheel.generateMultiples candidate rollingWheel, Data.IntMap.empty)--	sieve :: Data.PrimeWheel.Distance Int -> RepositoryInt -> [Int]-	sieve distance@(candidate, rollingWheel) repository@(primeSquares, squareFreePrimeMultiples)	= case Data.IntMap.lookup candidate squareFreePrimeMultiples of-		Just primeMultiples	-> sieve' $ Control.Arrow.second (insertUniq primeMultiples . Data.IntMap.delete candidate) repository-		Nothing-			| candidate == smallestPrimeSquare	-> sieve' $ (tail' *** insertUniq subsequentPrimeMultiples) repository-			| otherwise				-> candidate : sieve' (Control.Arrow.first (|> Data.PrimeWheel.generateMultiples candidate rollingWheel) repository)-			where-				(smallestPrimeSquare : subsequentPrimeMultiples)	= head' primeSquares-		where-			sieve' :: RepositoryInt -> [Int]-			sieve'	= sieve $ Data.PrimeWheel.rotate distance--			insertUniq :: Data.PrimeWheel.PrimeMultiples Int -> PrimeMultiplesMapInt -> PrimeMultiplesMapInt-			insertUniq l m	= insert $ dropWhile (`Data.IntMap.member` m) l	where-				insert :: Data.PrimeWheel.PrimeMultiples Int -> PrimeMultiplesMapInt-				insert []		= error "Factory.Math.Implementations.Primes.SieveOfEratosthenes.sieveOfEratosthenesInt.sieve.insertUniq.insert:\tnull list"-				insert (key : values)	= Data.IntMap.insert key values m
− src/Factory/Math/Implementations/Primes/TrialDivision.hs
@@ -1,59 +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@]	Generates the constant, conceptually infinite, list of /prime-numbers/, using /Trial Division/.--}--module Factory.Math.Implementations.Primes.TrialDivision(--- * Functions-	trialDivision--- ** Predicates---	isIndivisibleBy-) where--import qualified	Control.Arrow-import qualified	Data.List-import qualified	Factory.Math.Power		as Math.Power-import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation-import qualified	Factory.Data.PrimeWheel		as Data.PrimeWheel---- | Uses /Trial Division/, to determine whether the specified candidate is indivisible by all potential denominators from the specified list.-isIndivisibleBy :: Integral i-	=> i	-- ^ The numerator.-	-> [i]	-- ^ The denominators of which it must not be a multiple.-	-> Bool-isIndivisibleBy numerator	= all ((/= 0) . (numerator `rem`)) . takeWhile (<= Math.PrimeFactorisation.maxBoundPrimeFactor numerator)--{- |-	* For each candidate, confirm indivisibility, by all /primes/ smaller than its /square-root/.--	* The candidates to sieve, are generated by a 'Data.PrimeWheel.PrimeWheel',-	of parameterised, but static, size; <http://en.wikipedia.org/wiki/Wheel_factorization>.--}-trialDivision :: Integral prime => Data.PrimeWheel.NPrimes -> [prime]-trialDivision 0	= [2, 3] ++ filter (`isIndivisibleBy` trialDivision 0 {-recurse-}) [5 ..]	-- No faster than using 'Data.PrimeWheel.mkPrimeWheel 0', but apparently better space-complexity ?!-trialDivision wheelSize	= Data.PrimeWheel.getPrimeComponents primeWheel ++ indivisible	where-	primeWheel	= Data.PrimeWheel.mkPrimeWheel wheelSize-	candidates	= map fst $ Data.PrimeWheel.roll primeWheel-	indivisible	= uncurry (++) . Control.Arrow.second (-		filter (`isIndivisibleBy` indivisible {-recurse-})-	 ) $ Data.List.span (-		< Math.Power.square (head candidates)	-- The first composite candidate, is the square of the next prime after the wheel's constituent ones.-	 ) candidates-
− src/Factory/Math/Implementations/Primes/TurnersSieve.hs
@@ -1,48 +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@] Generates the constant, conceptally infinite, list of /prime-numbers/, using /Turner's Sieve/; <http://www.haskell.org/haskellwiki/Prime_numbers#Turner.27s_sieve_-_Trial_division>.--}--module Factory.Math.Implementations.Primes.TurnersSieve(--- * Functions-	turnersSieve-) where--import qualified	Factory.Math.Power	as Math.Power--{- |-	* For each /prime/, the infinite list of candidates greater than its /square/,-	is filtered for indivisibility; <http://www.haskell.org/haskellwiki/Prime_numbers#Turner.27s_sieve_-_Trial_division>.--	* CAVEAT: though one can easily add a 'Data.PrimeWheel.PrimeWheel', it proved counterproductive.--}-turnersSieve :: Integral prime => [prime]-turnersSieve	= 2 : sieve [3, 5 ..]	where-	sieve :: Integral i => [i] -> [i]-	sieve []			= []-	sieve (prime : candidates)	= prime : sieve (-		filter (-			\candidate	-> any ($ candidate) [-				(< Math.Power.square prime),	-- Unconditionally admit any candidate smaller than the square of the last prime.-				(/= 0) . (`rem` prime)		-- Ensure indivisibility, of all subsequent candidates, by the last prime discovered.-			]-		) candidates-	 )-
− src/Factory/Math/Implementations/SquareRoot.hs
@@ -1,192 +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@]	Implements 'Math.SquareRoot.Algorithmic' by a variety of methods.-- [@CAVEAT@]--	Caller may benefit from application of 'Math.Precision.simplify' before operating on the result;-	which though of the required accuracy, may not be the most concise rational number satisfying that criterion.--}-module Factory.Math.Implementations.SquareRoot(--- * Types--- ** Type-synonyms---	ProblemSpecification,-	Terms,--- ** Data-types-	Algorithm(..)--- * Functions---	squareRootByContinuedFraction,---	squareRootByIteration,---	squareRootByTaylorSeries,---	taylorSeriesCoefficients-) where--import			Control.Arrow((***))-import			Factory.Data.PrimeFactors((>/<), (>^))-import qualified	Factory.Data.PrimeFactors		as Data.PrimeFactors-import qualified	Factory.Math.Implementations.Factorial	as Math.Implementations.Factorial-import qualified	Factory.Math.Power			as Math.Power-import qualified	Factory.Math.Precision			as Math.Precision-import qualified	Factory.Math.SquareRoot			as Math.SquareRoot-import qualified	Factory.Math.Summation			as Math.Summation-import qualified	ToolShed.Defaultable---- | The number of terms in a series.-type Terms	= Int---- | The algorithms by which the /square-root/ has been implemented.-data Algorithm-	= BakhshaliApproximation	-- ^ <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Bakhshali_approximation>-	| ContinuedFraction		-- ^ <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Continued_fraction_expansion>.-	| HalleysMethod			-- ^ <http://en.wikipedia.org/wiki/Halley%27s_method>.-	| NewtonRaphsonIteration	-- ^ <http://en.wikipedia.org/wiki/Newton%27s_method>.-	| TaylorSeries Terms		-- ^ <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Taylor_series>.-	deriving (Eq, Read, Show)--instance ToolShed.Defaultable.Defaultable Algorithm	where-	defaultValue	= NewtonRaphsonIteration---- | Returns an improved estimate for the /square-root/ of the specified value, to the required precision, using the supplied initial estimate..-type ProblemSpecification operand-	= Math.SquareRoot.Estimate-	-> Math.Precision.DecimalDigits	-- ^ The required precision.-	-> operand			-- ^ The value for which to find the /square-root/.-	-> Math.SquareRoot.Result--instance Math.SquareRoot.Algorithmic Algorithm	where-	squareRootFrom _ _ _ 0	= 0-	squareRootFrom _ _ _ 1	= 1-	squareRootFrom algorithm estimate@(x, decimalDigits) requiredDecimalDigits y-		| decimalDigits >= requiredDecimalDigits	= x-		| requiredDecimalDigits <= 0			= error $ "Factory.Math.Implementations.SquareRoot.squareRootFrom:\tinvalid number of required decimal digits; " ++ show requiredDecimalDigits-		| y < 0						= error $ "Factory.Math.Implementations.SquareRoot.squareRootFrom:\tthere's no real square-root of " ++ show y-		| otherwise					= (-			case algorithm of-				ContinuedFraction	-> squareRootByContinuedFraction-				_			-> squareRootByIteration algorithm-		) estimate requiredDecimalDigits y--instance Math.SquareRoot.Iterator Algorithm where-	step BakhshaliApproximation y x-		| dy == 0	= x		-- The estimate was precise.-		| otherwise	= x' - dx'	-- Correct the estimate.-		where-			dy, dydx, dx, x', dydx', dx' :: Math.SquareRoot.Result-			dy	= Math.SquareRoot.getDiscrepancy y x-			dydx	= 2 * x-			dx	= dy / dydx-			x'	= x + dx	-- Identical to Newton-Raphson iteration.-			dydx'	= 2 * x'-			dx'	= Math.Power.square dx / dydx'--{--	* /Halley's/ method; <http://mathworld.wolfram.com/HalleysMethod.html>-->		X(n+1) = Xn - f(Xn) / [f'(Xn) - f''(Xn) * f(Xn) / 2 * f'(Xn)]->			=> Xn - (Xn^2 - Y) / [2Xn - 2 * (Xn^2 - Y) / 2 * 2Xn] where Y = X^2, f(X) = X^2 - Y, f'(X) = 2X, f''(X) = 2->			=> Xn - 1 / [2Xn / (Xn^2 - Y) - 1 / 2Xn]--}-	step HalleysMethod y x-		| dy == 0	= x		-- The estimate was precise.-		| otherwise	= x - dx	-- Correct the estimate.-		where-			dy, dydx, dx :: Math.SquareRoot.Result-			dy	= negate $ Math.SquareRoot.getDiscrepancy y x	-- Use the estimate to determine the error in 'y'.-			dydx	= 2 * x						-- The gradient, at the estimated value 'x'.-			dx	= recip $ dydx / dy - recip dydx----	step NewtonRaphsonIteration y x	= (x + toRational y / x) / 2		-- This is identical to the /Babylonian Method/.---	step NewtonRaphsonIteration y x	= x / 2 + toRational y / (2 * x)	-- Faster.-	step NewtonRaphsonIteration y x	= x / 2 + (toRational y / 2) / x	-- Faster still.--	step (TaylorSeries terms) y x	= squareRootByTaylorSeries terms y x--	step algorithm _ _		= error $ "Factory.Math.Implementations.SquareRoot.step:\tinappropriate algorithm; " ++ show algorithm--	convergenceOrder BakhshaliApproximation	= Math.Precision.quarticConvergence-	convergenceOrder ContinuedFraction	= Math.Precision.linearConvergence-	convergenceOrder HalleysMethod		= Math.Precision.cubicConvergence-	convergenceOrder NewtonRaphsonIteration	= Math.Precision.quadraticConvergence-	convergenceOrder (TaylorSeries terms)	= terms	-- The order of convergence, per iteration, equals the number of terms in the series on each iteration.--{- |-	* Uses /continued-fractions/, to iterate towards the principal /square-root/ of the specified positive integer;-	<http://en.wikipedia.org/wiki/Solving_quadratic_equations_with_continued_fractions>,-	<http://en.wikipedia.org/wiki/Generalized_continued_fraction#Roots_of_positive_numbers>,-	<http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Continued_fraction_expansion>.-	<http://www.myreckonings.com/Dead_Reckoning/Online/Materials/General%20Method%20for%20Extracting%20Roots.pdf>--	* The convergence <http://en.wikipedia.org/wiki/Rate_of_convergence> of the /continued-fraction/ is merely /1st order/ (linear).--}-squareRootByContinuedFraction :: Real operand => ProblemSpecification operand-squareRootByContinuedFraction (initialEstimate, initialDecimalDigits) requiredDecimalDigits y	= initialEstimate + (convergents initialEstimate !! Math.Precision.getTermsRequired (10 ^^ negate initialDecimalDigits) requiredDecimalDigits)	where-	convergents :: Math.SquareRoot.Result -> [Math.SquareRoot.Result]-	convergents x	= iterate ((Math.SquareRoot.getDiscrepancy y x /) . ((2 * x) +)) 0--{- |-	* The constant coefficients of the /Taylor-series/ for a /square-root/; <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Taylor_series>.--	* @ ((-1)^n * factorial(2*n)) / ((1 - 2*n) * 4^n * factorial(n^2)) @.--}-taylorSeriesCoefficients :: Fractional f => [f]-taylorSeriesCoefficients	= zipWith (-	\powers n	-> let-		doubleN		= 2 * n-		product'	= Data.PrimeFactors.product' (recip 2) {-arbitrary-} 10 {-arbitrary-}-	in uncurry (/) . (-		fromIntegral . product' *** fromIntegral . (* ((1 - doubleN) * powers)) . product'-	) $ Math.Implementations.Factorial.primeFactors doubleN >/< Math.Implementations.Factorial.primeFactors n >^ 2- ) (-	iterate (* negate 4) 1	-- (-4)^n- ) [0 :: Integer ..]		-- n--{- |-	* Returns the /Taylor-series/ for the /square-root/ of the specified value, to any requested number of terms.--	* <http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Taylor_series>.--	* The convergence of the series is merely /linear/,-	in that each term increases the precision, by a constant number of decimal places, equal to the those in the original estimate.--	* By feeding-back the improved estimate, to form a new series, the order of convergence, on each successive iteration,-	becomes proportional to the number of terms;-->		Terms		Convergence->		=====		===========->		2 terms		/quadratic/->		3 terms		/cubic/--}-squareRootByTaylorSeries :: Real operand-	=> Terms			-- ^ The number of terms of the infinite series, to evaluate.-	-> operand			-- ^ The value for which the /square-root/ is required.-	-> Math.SquareRoot.Result	-- ^ An initial estimate.-	-> Math.SquareRoot.Result-squareRootByTaylorSeries _ _ 0	= error "Factory.Math.Implementations.SquareRoot.squareRootByTaylorSeries:\talgorithm can't cope with estimated value of zero."-squareRootByTaylorSeries terms y x-	| terms < 2	= error $ "Factory.Math.Implementations.SquareRoot.squareRootByTaylorSeries:\tinvalid number of terms; " ++ show terms-	| otherwise	= Math.Summation.sumR' . take terms . zipWith (*) taylorSeriesCoefficients $ iterate (* relativeError) x-	where-		relativeError :: Math.SquareRoot.Result-		relativeError	= pred $ toRational y / Math.Power.square x	-- Pedantically, this is the error in y, which is twice the magnitude of the error in x.---- | Iterates from the estimated value, towards the /square-root/, a sufficient number of times to achieve the required accuracy.-squareRootByIteration :: Real operand => Algorithm -> ProblemSpecification operand-squareRootByIteration algorithm (initialEstimate, initialDecimalDigits) requiredDecimalDigits y	= iterate (Math.SquareRoot.step algorithm y) initialEstimate !! Math.Precision.getIterationsRequired (Math.SquareRoot.convergenceOrder algorithm) initialDecimalDigits requiredDecimalDigits-
− src/Factory/Math/MultiplicativeOrder.hs
@@ -1,66 +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@]	Exports the /Multiplicative Order/ of an integer, in a specific /modular/ arithmetic.---}--module Factory.Math.MultiplicativeOrder(--- * Functions-	multiplicativeOrder-) where--import qualified	Control.DeepSeq-import qualified	Factory.Data.Exponential	as Data.Exponential-import qualified	Factory.Math.Power		as Math.Power-import qualified	Factory.Math.Primality		as Math.Primality-import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation--{- |-	* The smallest positive integral power to which the specified integral base must be raised,-	to be congruent with one, in the specified /modular/ arithmetic.--	* Based on <http://rosettacode.org/wiki/Multiplicative_order#Haskell>.--	* <http://en.wikipedia.org/wiki/Multiplicative_order>.--	* <http://mathworld.wolfram.com/MultiplicativeOrder.html>.--}-multiplicativeOrder :: (Math.PrimeFactorisation.Algorithmic primeFactorisationAlgorithm, Control.DeepSeq.NFData i, Integral i, Show i)-	=> primeFactorisationAlgorithm-	-> i	-- ^ Base.-	-> i	-- ^ Modulus.-	-> i	-- ^ Result.-multiplicativeOrder primeFactorisationAlgorithm base modulus-	| modulus < 2					= error $ "Factory.Math.MultiplicativeOrder.multiplicativeOrder:\tinvalid modulus; " ++ show modulus-	| not $ Math.Primality.areCoprime base modulus	= error $ "Factory.Math.MultiplicativeOrder.multiplicativeOrder:\targuments aren't coprime; " ++ show (base, modulus)-	| otherwise					= foldr (lcm . multiplicativeOrder') 1 $ Math.PrimeFactorisation.primeFactors primeFactorisationAlgorithm modulus	-- Combine the /multiplicative order/ of the constituent /prime-factors/.-	where---		multiplicativeOrder' :: (Control.DeepSeq.NFData i, Integral i) => Data.Exponential.Exponential i -> i-		multiplicativeOrder' e	= product . map (-			\e'	-> let-				d :: Int-				d	= length . takeWhile (/= 1) . iterate (-					\y	-> Math.Power.raiseModulo y (Data.Exponential.getBase e') pk-				 ) $ Math.Power.raiseModulo base (totient `div` Data.Exponential.evaluate e') pk-			in Data.Exponential.getBase e' ^ d-		 ) $ Math.PrimeFactorisation.primeFactors primeFactorisationAlgorithm totient	where-			pk	= Data.Exponential.evaluate e-			totient	= Math.PrimeFactorisation.primePowerTotient e-
− src/Factory/Math/PerfectPower.hs
@@ -1,100 +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@]	Exports functions related to /perfect powers/.--}--module Factory.Math.PerfectPower(--- * Functions-	maybeSquareNumber,--- ** Predicates-	isPerfectPower---	isPerfectPowerInt-) where--import qualified	Data.IntSet-import qualified	Data.Set-import qualified	Factory.Math.Power	as Math.Power--{- |-	* Returns @(Just . sqrt)@ if the specified integer is a /square number/ (AKA /perfect square/).--	* <http://en.wikipedia.org/wiki/Square_number>.--	* <http://mathworld.wolfram.com/SquareNumber.html>.--	* @(Math.Power.square . sqrt)@ is expensive, so the modulus of the operand is tested first, in an attempt to prove it isn't a /perfect square/.-	The set of tests, and the valid moduli within each test, are ordered to maximize the rate of failure-detection.--}-maybeSquareNumber :: Integral i => i -> Maybe i-maybeSquareNumber i---	| i < 0					= Nothing	-- This function is performance-sensitive, but this test is neither strictly nor frequently required.-	| all (\(modulus, valid) -> rem i modulus `elem` valid) [---							-- Distribution of moduli amongst perfect squares	Cumulative failure-detection.-		(16,	[0,1,4,9]),			-- All moduli are equally likely.			75%-		(9,	[0,1,4,7]),			-- Zero occurs 33%, the others only 22%.			88%-		(17,	[1,2,4,8,9,13,15,16,0]),	-- Zero only occurs 5.8%, the others 11.8%.		94%--- These additional tests, aren't always cost-effective.-		(13,	[1,3,4,9,10,12,0]),		-- Zero only occurs 7.7%, the others 15.4%.		97%-		(7,	[1,2,4,0]),			-- Zero only occurs 14.3%, the others 28.6%.		98%-		(5,	[1,4,0])			-- Zero only occurs 20%, the others 40%.			99%----	] && fromIntegral iSqrt == sqrt'	= Just iSqrt	-- CAVEAT: erroneously True for 187598574531033120 (187598574531033121 is square).-	] && Math.Power.square iSqrt == i	= Just iSqrt-	| otherwise				= Nothing-	where-		sqrt' :: Double-		sqrt'	= sqrt $ fromIntegral i--		iSqrt	= round sqrt'--{- |-	* An integer @(> 1)@ which can be expressed as an integral power @(> 1)@ of a smaller /natural/ number.--	* CAVEAT: /zero/ and /one/ are normally excluded from this set.--	* <http://en.wikipedia.org/wiki/Perfect_power>.--	* <http://mathworld.wolfram.com/PerfectPower.html>.--	* A generalisation of the concept of /perfect squares/, in which only the exponent '2' is significant.--}-isPerfectPower :: Integral i => i -> Bool-isPerfectPower i-	| i < Math.Power.square 2	= False-	| otherwise			= i `Data.Set.member` foldr (-		\n set	-> if n `Data.Set.member` set-			then set---			else Data.Set.union set . Data.Set.fromDistinctAscList . takeWhile (<= i) . iterate (* n) $ Math.Power.square n-			else foldr Data.Set.insert set . takeWhile (<= i) . iterate (* n) $ Math.Power.square n	-- Faster.-	) Data.Set.empty [2 .. round $ sqrt (fromIntegral i :: Double)]--{-# NOINLINE isPerfectPower #-}-{-# RULES "isPerfectPower/Int" isPerfectPower = isPerfectPowerInt #-}---- | A specialisation of 'isPerfectPower'.-isPerfectPowerInt :: Int -> Bool-isPerfectPowerInt i-	| i < Math.Power.square 2	= False-	| otherwise			= i `Data.IntSet.member` foldr (-		\n set	-> if n `Data.IntSet.member` set-			then set-			else foldr Data.IntSet.insert set . takeWhile (<= i) . iterate (* n) $ Math.Power.square n-	) Data.IntSet.empty [2 .. round $ sqrt (fromIntegral i :: Double)]-
− src/Factory/Math/Pi.hs
@@ -1,100 +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 the classes of /Pi/-algorithm which have been implemented.--}--module Factory.Math.Pi(--- * Type-classes-	Algorithmic(..),--- * Types--- ** Data-types-	Category(..)-) where--import qualified	Factory.Math.Precision	as Math.Precision-import qualified	ToolShed.Defaultable--{- |-	* Defines the methods expected of a /Pi/-algorithm.--	* Most of the implementations naturally return a 'Rational', but the spigot-algorithms naturally produce a @[Int]@;-	though representing /Pi/ as a big integer with the decimal point removed is clearly incorrect.--	* Since representing /Pi/ as either a 'Rational' or promoted to an 'Integer', is inconvenient, an alternative decimal 'String'-representation is provided.--}-class Algorithmic algorithm where-	openR	:: algorithm -> Math.Precision.DecimalDigits -> Rational	-- ^ Returns the value of /Pi/ as a 'Rational'.--	openI	:: algorithm -> Math.Precision.DecimalDigits -> Integer	-- ^ Returns the value of /Pi/, promoted by the required precision to form an integer.-	openI _ 1	= 3-	openI algorithm decimalDigits-		| decimalDigits <= 0	= error $ "Factory.Math.Pi.openI:\tinsufficient decimalDigits=" ++ show decimalDigits-		| otherwise		= round . Math.Precision.promote (openR algorithm decimalDigits) $ pred decimalDigits--	openS	:: algorithm -> Math.Precision.DecimalDigits -> String			-- ^ Returns the value of /Pi/ as a decimal 'String'.-	openS _ 1	= "3"-	openS algorithm decimalDigits-		| decimalDigits <= 0	= ""-		| decimalDigits <= 16	= take (succ decimalDigits) $ show (pi :: Double)-		| otherwise		= "3." ++ tail (show $ openI algorithm decimalDigits)	-- Insert a decimal point.---- | Categorises the various algorithms.-data Category agm bbp borwein ramanujan spigot-	= AGM agm		-- ^ Algorithms based on the /Arithmetic-geometric Mean/.-	| BBP bbp		-- ^ <http://en.wikipedia.org/wiki/Bailey%E2%80%93Borwein%E2%80%93Plouffe_formula>.-	| Borwein borwein	-- ^ <http://en.wikipedia.org/wiki/Borwein%27s_algorithm>.-	| Ramanujan ramanujan	-- ^ <http://www.pi314.net/eng/ramanujan.php>.-	| Spigot spigot		-- ^ Algorithms from which the digits of /Pi/ slowly drip, one by one.-	deriving (Eq, Read, Show)--instance (-	ToolShed.Defaultable.Defaultable agm,-	ToolShed.Defaultable.Defaultable bbp,-	ToolShed.Defaultable.Defaultable borwein,-	ToolShed.Defaultable.Defaultable ramanujan,-	ToolShed.Defaultable.Defaultable spigot- )  => ToolShed.Defaultable.Defaultable (Category agm bbp borwein ramanujan spigot)	where-	defaultValue	= BBP ToolShed.Defaultable.defaultValue--instance (-	Algorithmic agm,-	Algorithmic bbp,-	Algorithmic borwein,-	Algorithmic ramanujan,-	Algorithmic spigot- ) => Algorithmic (Category agm bbp borwein ramanujan spigot)	where-	openR algorithm decimalDigits-		| decimalDigits <= 0	= error $ "Factory.Math.Pi.openR:\tinsufficient decimalDigits=" ++ show decimalDigits-		| decimalDigits <= 16	= Math.Precision.simplify (pred decimalDigits) (pi :: Double)-		| otherwise		= (-			case algorithm of-				AGM agm			-> openR agm-				BBP bbp			-> openR bbp-				Borwein borwein		-> openR borwein-				Ramanujan ramanujan	-> openR ramanujan-				Spigot spigot		-> openR spigot-		) decimalDigits--	openI _ 1				= 3-	openI (Spigot spigot) decimalDigits	= openI spigot decimalDigits-	openI algorithm decimalDigits-		| decimalDigits <= 0	= error $ "Factory.Math.Pi.openI:\tinsufficient decimalDigits=" ++ show decimalDigits-		| otherwise		= round . Math.Precision.promote (openR algorithm decimalDigits) $ pred decimalDigits-
− src/Factory/Math/Power.hs
@@ -1,84 +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@]	Exports functions involving integral powers.--}--module Factory.Math.Power(--- * Functions-	square,-	squaresFrom,-	cube,-	cubeRoot,-	raiseModulo-) where---- | Mainly for convenience.-square :: Num n => n -> n-square x	= x ^ (2 :: Int)	-- CAVEAT: this could be eta-reduced, but it won't then inline when called with a single argument.--{-# INLINE square #-}---- | Just for convenience.-cube :: Num n => n -> n-cube	= (^ (3 :: Int))--{- |-	* Iteratively generate sequential /squares/, from the specified initial value,-	based on the fact that @(x + 1)^2 = x^2 + 2 * x + 1@.--	* The initial value doesn't need to be either positive or integral.--}-squaresFrom :: (Enum n, Num n)-	=> n		-- ^ Lower bound.-	-> [(n, n)]	-- ^ @ [(n, n^2)] @.-squaresFrom from	= iterate (\(x, y) -> (succ x, succ $ y + 2 * x)) (from, square from)---- | Just for convenience.-cubeRoot :: Double -> Double-cubeRoot	= (** recip 3)--{- |-	* Raise an arbitrary number to the specified positive integral power, using /modular/ arithmetic.--	* Implements exponentiation as a sequence of either /squares/ or multiplications by the base;-	<http://en.wikipedia.org/wiki/Exponentiation_by_squaring>.--	* <http://en.wikipedia.org/wiki/Modular_exponentiation>.--}-raiseModulo :: (Integral i, Integral power, Show power)-	=> i	-- ^ Base.-	-> power-	-> i	-- ^ Modulus.-	-> i	-- ^ Result.-raiseModulo _ _ 0	= error "Factory.Math.Power.raiseModulo:\tzero modulus."-raiseModulo _ _ 1	= 0-raiseModulo _ 0 modulus	= 1 `mod` modulus-raiseModulo base power modulus-	| base < 0		= (`mod` modulus) . (if even power then id else negate) $ raiseModulo (negate base) power modulus	-- Recurse.-	| power < 0		= error $ "Factory.Math.Power.raiseModulo:\tnegative power; " ++ show power-	| first `elem` [0, 1]	= first-	| otherwise		= slave power-	where-		first	= base `mod` modulus--		slave 1	= first-		slave e	= (`mod` modulus) . (if r == 0 {-even-} then id else (* base)) . square $ slave q {-recurse-}	where-			(q, r)	= e `quotRem` 2-
− src/Factory/Math/Precision.hs
@@ -1,125 +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 the unit with which precision is measured, and operations on it.--}-module Factory.Math.Precision(--- * Types--- ** Type-synonyms-	ConvergenceOrder,-	ConvergenceRate,-	DecimalDigits,--- * Constants-	linearConvergence,-	quadraticConvergence,-	cubicConvergence,-	quarticConvergence,--- * Functions-	getIterationsRequired,-	getTermsRequired,-	roundTo,-	promote,-	simplify-) where--import qualified	Data.Ratio---- | The /order of convergence/; <http://en.wikipedia.org/wiki/Rate_of_convergence>.-type ConvergenceOrder	= Int---- | The /rate of convergence/; <http://en.wikipedia.org/wiki/Rate_of_convergence>.-type ConvergenceRate	= Double---- | A number of decimal digits; presumably positive.-type DecimalDigits	= Int---- | /Linear/ convergence-rate; which may be qualified by the /rate of convergence/.-linearConvergence :: ConvergenceOrder-linearConvergence	= 1---- | /Quadratic/ convergence-rate.-quadraticConvergence :: ConvergenceOrder-quadraticConvergence	= 2---- | /Cubic/ convergence-rate.-cubicConvergence :: ConvergenceOrder-cubicConvergence	= 3---- | /Quartic/ convergence-rate.-quarticConvergence :: ConvergenceOrder-quarticConvergence	= 4---- | The predicted number of iterations, required to achieve a specific accuracy, at a given /order of convergence/.-getIterationsRequired :: Integral i-	=> ConvergenceOrder-	-> DecimalDigits	-- ^ The precision of the initial estimate.-	-> DecimalDigits	-- ^ The required precision.-	-> i-getIterationsRequired convergenceOrder initialDecimalDigits requiredDecimalDigits-	| initialDecimalDigits <= 0	= error $ "Factory.Math.Precision.getIterationsRequired:\tinsufficient 'initialDecimalDigits'; " ++ show initialDecimalDigits-	| precisionRatio <= 1		= 0-	| otherwise			= ceiling $ fromIntegral convergenceOrder `logBase` precisionRatio-	where-		precisionRatio :: Double-		precisionRatio	= fromIntegral requiredDecimalDigits / fromIntegral initialDecimalDigits--{- |-	* The predicted number of terms which must be extracted from a series,-	if it is to converge to the required accuracy,-	at the specified linear /convergence-rate/.--	* The /convergence-rate/ of a series, is the error in the series after summation of @(n+1)th@ terms,-	divided by the error after only @n@ terms, as the latter tends to infinity.-	As such, for a /convergent/ series (in which the error get smaller with successive terms), it's value lies in the range @0 .. 1@.--	* <http://en.wikipedia.org/wiki/Rate_of_convergence>.--}-getTermsRequired :: Integral i-	=> ConvergenceRate-	-> DecimalDigits	-- ^ The additional number of correct decimal digits.-	-> i-getTermsRequired _ 0		= 0-getTermsRequired convergenceRate requiredDecimalDigits-	| convergenceRate <= 0 || convergenceRate >= 1	= error $ "Factory.Math.Precision.getTermsRequired:\t(0 < convergence-rate < 1); " ++ show convergenceRate-	| requiredDecimalDigits < 0			= error $ "Factory.Math.Precision.getTermsRequired:\t'requiredDecimalDigits' must be positive; " ++ show requiredDecimalDigits-	| otherwise					= ceiling $ fromIntegral requiredDecimalDigits / negate (logBase 10 convergenceRate)---- | Rounds the specified number, to a positive number of 'DecimalDigits'.-roundTo :: (RealFrac a, Fractional f) => DecimalDigits -> a -> f-roundTo decimals = (/ fromInteger promotionFactor) . fromInteger . round . (* fromInteger promotionFactor)	where-	promotionFactor :: Integer-	promotionFactor	= 10 ^ decimals---- | Promotes the specified number, by a positive number of 'DecimalDigits'.-promote :: Num n => n -> DecimalDigits -> n-promote x	= (* x) . (10 ^)--{- |-	* Reduces a 'Rational' to the minimal form required for the specified number of /fractional/ decimal places;-	irrespective of the number of integral decimal places.--	* A 'Rational' approximation to an irrational number, may be very long, and provide an unknown excess precision.-	Whilst this doesn't sound harmful, it costs in performance and memory-requirement, and being unpredictable isn't actually useful.--}-simplify :: RealFrac operand-	=> DecimalDigits	-- ^ The number of places after the decimal point, which are required.-	-> operand-	-> Rational-simplify decimalDigits operand	= Data.Ratio.approxRational operand . recip $ 4 * 10 ^ succ decimalDigits	-- Tolerate any error less than half the least significant digit required.-
− src/Factory/Math/Primality.hs
@@ -1,102 +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@]--	* Exports a common interface for primality-implementations.--	* Provides utilities for these implementations.--}--module Factory.Math.Primality(--- * Type-classes-	Algorithmic(..),--- * Functions-	carmichaelNumbers,--- ** Predicates-	areCoprime,-	isFermatWitness,-	isCarmichaelNumber-) where--import qualified	Control.DeepSeq-import qualified	Factory.Math.Power	as Math.Power---- | Defines the methods expected of a primality-testing algorithm.-class Algorithmic algorithm	where-	isPrime	:: (Control.DeepSeq.NFData i, Integral i, Show i) => algorithm -> i -> Bool--{- |-	'True' if the two specified integers are /relatively prime/,-	i.e. if they share no common positive factors except one.--	* @1@ and @-1@ are the only numbers which are /coprime/ to themself.--	* <http://en.wikipedia.org/wiki/Coprime>.--	* <http://mathworld.wolfram.com/RelativelyPrime.html>.--}-areCoprime :: Integral i => i -> i -> Bool-areCoprime i	= (== 1) . gcd i--{- |-	* Tests /Fermat's Little Theorem/ for all applicable values, as a probabilistic primality-test.--	* <http://en.wikipedia.org/wiki/Fermat%27s_little_theorem>.--	* <http://en.wikipedia.org/wiki/Fermat_primality_test>.--	* <http://en.wikipedia.org/wiki/Fermat_pseudoprime>.--	* CAVEAT: this primality-test fails for the /Carmichael numbers/.--	* TODO: confirm that all values must be tested.--}-isFermatWitness :: (Integral i, Show i) => i -> Bool-isFermatWitness i	= not . all isFermatPseudoPrime $ filter (areCoprime i) [2 .. pred i]	where-	isFermatPseudoPrime base	= Math.Power.raiseModulo base (pred i) i == 1	-- CAVEAT: a /Fermat Pseudo-prime/ must also be a /composite/ number.--{- |-	* A /Carmichael number/ is an /odd/ /composite/ number which satisfies /Fermat's little theorem/.--	* <http://en.wikipedia.org/wiki/Carmichael_number>.--	* <http://mathworld.wolfram.com/CarmichaelNumber.html>.--}-isCarmichaelNumber :: (-	Algorithmic		algorithm,-	Control.DeepSeq.NFData	i,-	Integral		i,-	Show			i- ) => algorithm -> i -> Bool-isCarmichaelNumber algorithm i	= not $ or [-	i <= 2,-	even i,-	isFermatWitness i,-	isPrime algorithm i- ]---- | An ordered list of the /Carmichael/ numbers; <http://en.wikipedia.org/wiki/Carmichael_number>.-carmichaelNumbers :: (-	Algorithmic		algorithm,-	Control.DeepSeq.NFData	i,-	Integral		i,-	Show			i- ) => algorithm -> [i]-carmichaelNumbers algorithm	= isCarmichaelNumber algorithm `filter` [3, 5 ..]
− src/Factory/Math/PrimeFactorisation.hs
@@ -1,151 +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@]--	* <http://en.wikipedia.org/wiki/Integer_factorization>.--	* Exports a common interface to permit decomposition of positive integers,-	into the unique combination of /prime/-factors known to exist according to the /Fundamental Theorem of Arithmetic/; <http://en.wikipedia.org/wiki/Fundamental_theorem_of_arithmetic>.--	* Leveraging this abstract capability, it derives the /smoothness/, /power-smoothness/, /omega/-numbers and /square-free/ integers.--	* Filters the list of /regular-numbers/ from the list of /smoothness/.--	* CAVEAT: to avoid wasting time, it may be advantageous to check /Factory.Math.Primality.isPrime/ first.--}--module Factory.Math.PrimeFactorisation(--- * Type-classes-	Algorithmic(..),--- * Functions-	maxBoundPrimeFactor,-	smoothness,-	powerSmoothness,-	regularNumbers,-	primePowerTotient,-	eulersTotient,-	omega,-	squareFree-) where--import qualified	Control.DeepSeq-import qualified	Data.List-import qualified	Factory.Data.Exponential	as Data.Exponential-import qualified	Factory.Data.PrimeFactors	as Data.PrimeFactors---- | Defines the methods expected of a /factorisation/-algorithm.-class Algorithmic algorithm	where-	primeFactors	:: (Control.DeepSeq.NFData base, Integral base)-		=> algorithm-		-> base	-- ^ The operand-		-> Data.PrimeFactors.Factors base Int {-arbitrarily-}--{- |-	* The upper limit for a prime to be considered as a candidate factor of the specified number.--	* One might naively think that this limit is @(x `div` 2)@ for an even number,-	but though a prime-factor /greater/ than the /square-root/ of the number can exist,-	its smaller /cofactor/ decomposes to a prime which must be less than the /square-root/.--	* NB: rather then using @(primeFactor <= sqrt numerator)@ to filter the candidate prime-factors of a given numerator,-	one can alternatively use @(numerator >= primeFactor ^ 2)@ to filter what can potentially be factored by a given prime-factor.--	* CAVEAT: suffers from rounding-errors, though no consequence has been witnessed.--}-maxBoundPrimeFactor :: Integral i => i -> i-maxBoundPrimeFactor	= floor . (sqrt :: Double -> Double) . fromIntegral--{- |-	* A constant, zero-indexed, conceptually infinite, list, of the /smooth/ness of all positive integers.--	* <http://en.wikipedia.org/wiki/Smooth_number>.--	* <http://mathworld.wolfram.com/SmoothNumber.html>.--}-smoothness :: (Algorithmic algorithm, Control.DeepSeq.NFData base, Integral base) => algorithm -> [base]-smoothness algorithm	= 0 : map (Data.Exponential.getBase . last . primeFactors algorithm) [1 ..]--{- |-	* A constant, zero-indexed, conceptually infinite, list of the /power-smooth/ness of all positive integers.--	* <http://en.wikipedia.org/wiki/Smooth_number#Powersmooth_numbers>.--}-powerSmoothness :: (Algorithmic algorithm, Control.DeepSeq.NFData base, Integral base) => algorithm -> [base]-powerSmoothness algorithm	= 0 : map (maximum . map Data.Exponential.evaluate . primeFactors algorithm) [1 ..]--{- |-	* Filters 'smoothness', to derive the constant list of /Hamming-numbers/.--	* <http://en.wikipedia.org/wiki/Regular_number>.--}-regularNumbers :: (Algorithmic algorithm, Control.DeepSeq.NFData base, Integral base) => algorithm -> [base]-regularNumbers algorithm	= map fst . filter ((<= (5 :: Integer)) . snd) . zip [1 ..] . tail $ smoothness algorithm--{- |-	* /Euler's Totient/ for a /power/ of a /prime/-number.--	* By /Olofsson/; @(phi(n^k) = n^(k - 1) * phi(n))@-	and since @(phi(prime) = prime - 1)@--	* CAVEAT: checks neither the primality nor the bounds of the specified value; therefore for internal use only.--}-primePowerTotient :: (Integral base, Integral exponent) => Data.Exponential.Exponential base exponent -> base-primePowerTotient (base, exponent')	= pred base * base ^ pred exponent'--{- |-	* The number of /coprimes/ less than or equal to the specified positive integer.--	* <http://en.wikipedia.org/wiki/Euler%27s_totient_function>.--	* <http://mathworld.wolfram.com/TotientFunction.html>.--	* AKA /EulerPhi/.--}-eulersTotient :: (-	Algorithmic		algorithm,-	Control.DeepSeq.NFData	i,-	Integral		i,-	Show			i- ) => algorithm -> i -> i-eulersTotient _ 1	= 1-eulersTotient algorithm i-	| i <= 0	= error $ "Factory.Math.PrimeFactorisation.eulersTotient:\tundefined for; " ++ show i-	| otherwise	= product . map primePowerTotient $ primeFactors algorithm i--{- |-	* A constant, zero-indexed, conceptually infinite, list of the /small omega/ numbers (i.e. the number of /distinct/ prime factors); cf. /big omega/.--	* <http://oeis.org/wiki/Omega%28n%29,_number_of_distinct_primes_dividing_n>.--	* <http://mathworld.wolfram.com/DistinctPrimeFactors.html>--	* <http://planetmath.org/encyclopedia/NumberOfDistinctPrimeFactorsFunction.html>.--}-omega :: (Algorithmic algorithm, Control.DeepSeq.NFData i, Integral i) => algorithm -> [i]-omega algorithm	= map (Data.List.genericLength . primeFactors algorithm) [0 :: Integer ..]--{- |-	* A constant, conceptually infinite, list of the /square-free/ numbers, i.e. those which aren't divisible by any /perfect square/.--	* <http://en.wikipedia.org/wiki/Square-free_integer>.--}-squareFree :: (Algorithmic algorithm, Control.DeepSeq.NFData i, Integral i) => algorithm -> [i]-squareFree algorithm	= filter (all (== 1) . map Data.Exponential.getExponent . primeFactors algorithm) [1 ..]-
− src/Factory/Math/Primes.hs
@@ -1,64 +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@]	Exports a common interface for implementations of /prime-number/ generators.--}--module Factory.Math.Primes(--- * Types-classes-	Algorithmic(..),--- * Functions-	primorial,-	mersenneNumbers-) where--import qualified	Control.DeepSeq-import qualified	Data.Array.IArray---- | Defines the methods expected of a /prime-number/ generator.-class Algorithmic algorithm	where-	primes	:: (Control.DeepSeq.NFData i, Data.Array.IArray.Ix i, Integral i) => algorithm -> [i]	-- ^ Returns the constant, infinite, list of primes.--{- |-	* Returns the constant list, defining the /Primorial/.--	* <http://en.wikipedia.org/wiki/Primorial>.--	* <http://mathworld.wolfram.com/Primorial.html>.--}-primorial :: (-	Algorithmic		algorithm,-	Control.DeepSeq.NFData	i,-	Data.Array.IArray.Ix	i,-	Integral		i- ) => algorithm -> [i]-primorial	= scanl (*) 1 . primes--{- |-	* Returns the constant ordered infinite list of /Mersenne numbers/.--	* Only the subset composed from a prime exponent is returned; which is a strict superset of the /Mersenne Primes/.--	* <http://en.wikipedia.org/wiki/Mersenne_prime>.--	* <http://mathworld.wolfram.com/MersenneNumber.html>--}-mersenneNumbers :: (Algorithmic algorithm, Integral i) => algorithm -> [i]-mersenneNumbers algorithm	= map (pred . (2 ^)) (primes algorithm :: [Int])	-- Whilst the exponentiation could be parallelised, not all values are known to be required.-
− src/Factory/Math/Probability.hs
@@ -1,255 +0,0 @@-{--	Copyright (C) 2011-2013 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@]	Functions for probability-distributions.-- [@CAVEAT@]	Because data-constructors are exposed, 'ToolShed.SelfValidate.isValid' need not be called.--}--module Factory.Math.Probability(--- * Type-classes-	Distribution(..),--- * Types--- ** Data-types-	ContinuousDistribution(..),-	DiscreteDistribution(..),--- * Functions-	maxPreciseInteger,---	minPositiveFloat,-	boxMullerTransform,---	reProfile,-	generateStandardizedNormalDistribution,-	generateContinuousPopulation,---	generatePoissonDistribution,-	generateDiscretePopulation-) where--import qualified	Control.Arrow-import			Control.Arrow((***), (&&&))-import qualified	Factory.Data.Interval	as Data.Interval-import qualified	Factory.Math.Power	as Math.Power-import qualified	System.Random-import qualified	ToolShed.Data.List-import qualified	ToolShed.Data.Pair-import qualified	ToolShed.SelfValidate---- | The maximum integer which can be accurately represented as a Double.-maxPreciseInteger  :: RealFloat a => a -> Integer-maxPreciseInteger	= (2 ^) . floatDigits--{- |-	* 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)---- | Describes /continuous probability-distributions/; <http://en.wikipedia.org/wiki/List_of_probability_distributions#Continuous_distributions>.-data ContinuousDistribution parameter-	= ExponentialDistribution parameter {-lambda-}				-- ^ Defines an /Exponential/-distribution with a particular /lambda/; <http://en.wikipedia.org/wiki/Exponential_distribution>.-	| LogNormalDistribution parameter {-location-} parameter {-scale2-}	-- ^ Defines a distribution whose logarithm is normally distributed with a particular /mean/ & /variance/; <http://en.wikipedia.org/wiki/Lognormal>.-	| NormalDistribution parameter {-mean-} parameter {-variance-}		-- ^ Defines a /Normal/-distribution with a particular /mean/ & /variance/; <http://en.wikipedia.org/wiki/Normal_distribution>.-	| UniformDistribution (Data.Interval.Interval parameter)		-- ^ Defines a /Uniform/-distribution within a /closed interval/; <http://en.wikipedia.org/wiki/Uniform_distribution>.-	deriving (Eq, Read, Show)--instance (Floating parameter, Ord parameter, Show parameter) => ToolShed.SelfValidate.SelfValidator (ContinuousDistribution parameter)	where-	getErrors probabilityDistribution	= ToolShed.SelfValidate.extractErrors $ case probabilityDistribution of-		ExponentialDistribution lambda		-> [(lambda <= 0, "'lambda' must exceed zero; " ++ show probabilityDistribution ++ ".")]-		LogNormalDistribution location scale2	-> let-			maxParameter	= log . fromInteger $ maxPreciseInteger (undefined :: Double)-		 in [-			(scale2 <= 0,						"'scale' must exceed zero; " ++ show probabilityDistribution ++ "."),-			(location > maxParameter || scale2 > maxParameter,	"loss of precision will result from either 'location' or 'scale^2' exceeding '" ++ show maxParameter ++ "'; " ++ show probabilityDistribution ++ ".")-		 ]-		NormalDistribution _ variance		-> [(variance <= 0, "variance must exceed zero; " ++ show probabilityDistribution ++ ".")]-		UniformDistribution interval		-> [(Data.Interval.isReversed interval, "reversed interval='" ++ show probabilityDistribution ++ "'.")]---- | Describes /discrete probability-distributions/; <http://en.wikipedia.org/wiki/List_of_probability_distributions#Discrete_distributions>.-data DiscreteDistribution parameter-	= PoissonDistribution parameter {-lambda-}			-- ^ Defines an /Poisson/-distribution with a particular /lambda/; <http://en.wikipedia.org/wiki/Poisson_distribution>.-	| ShiftedGeometricDistribution parameter {-probability-}	-- ^ Defines an /Geometric/-distribution with a particular probability of success; <http://en.wikipedia.org/wiki/Geometric_distribution>.-	deriving (Eq, Read, Show)--instance (Num parameter, Ord parameter, Show parameter) => ToolShed.SelfValidate.SelfValidator (DiscreteDistribution parameter)	where-	getErrors probabilityDistribution	= ToolShed.SelfValidate.extractErrors $ case probabilityDistribution of-		PoissonDistribution lambda			-> [(lambda <= 0, "'lambda' must exceed zero; " ++ show probabilityDistribution ++ ".")]-		ShiftedGeometricDistribution probability	-> [(any ($ probability) [(<= 0), (> 1)], "probability must be in the semi-closed unit-interval (0, 1]; " ++ show probabilityDistribution ++ ".")]---- | Defines a common interface for probability-distributions.-class Distribution probabilityDistribution	where-	generatePopulation-		:: (Fractional sample, System.Random.RandomGen randomGen)-		=> probabilityDistribution-		-> randomGen	-- ^ A generator of /uniformly distributed/ random numbers.-		-> [sample]	-- ^ CAVEAT: the integers generated for discrete distributions are represented by a fractional type; use 'generateDiscretePopulation' if this is a problem.--	getMean :: Fractional mean => probabilityDistribution -> mean	-- ^ The theoretical mean.--	getStandardDeviation :: Floating standardDeviation => probabilityDistribution -> standardDeviation-- ^ The theoretical standard-deviation.-	getStandardDeviation	= sqrt . getVariance	-- Default implementation.--	getVariance :: Floating variance => probabilityDistribution -> variance	-- ^ The theoretical variance.-	getVariance	= Math.Power.square . getStandardDeviation	-- Default implementation.--instance (RealFloat parameter, Show parameter, System.Random.Random parameter) => Distribution (ContinuousDistribution parameter)	where-	generatePopulation probabilityDistribution	= map realToFrac {-parameter -> sample-} . generateContinuousPopulation probabilityDistribution--	getMean (ExponentialDistribution lambda)			= realToFrac $ recip lambda-	getMean (LogNormalDistribution location scale2)			= realToFrac . exp . (+ location) $ scale2 / 2-	getMean (NormalDistribution mean _)				= realToFrac mean-	getMean (UniformDistribution (minParameter, maxParameter))	= realToFrac $ (minParameter + maxParameter) / 2--	getVariance (ExponentialDistribution lambda)			= realToFrac . recip $ Math.Power.square lambda-	getVariance (LogNormalDistribution location scale2)		= realToFrac $ (exp scale2 - 1) * exp (2 * location + scale2)	-- NB: for standard-deviation == mean, use scale^2 == ln 2.-	getVariance (NormalDistribution _ variance)			= realToFrac variance-	getVariance (UniformDistribution (minParameter, maxParameter))	= realToFrac $ Math.Power.square (maxParameter - minParameter) / 12--instance (RealFloat parameter, Show parameter, System.Random.Random parameter) => Distribution (DiscreteDistribution parameter)	where-	generatePopulation probabilityDistribution		= map fromInteger . generateDiscretePopulation probabilityDistribution--	getMean (PoissonDistribution lambda)			= realToFrac lambda-	getMean (ShiftedGeometricDistribution probability)	= realToFrac $ recip probability--	getVariance (PoissonDistribution lambda)		= realToFrac lambda-	getVariance (ShiftedGeometricDistribution probability)	= realToFrac $ (1 - probability) / Math.Power.square probability--{- |-	* 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,-	Show		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 . uncurry (&&) $ ToolShed.Data.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	= uncurry (&&) . ((> 0) &&& (<= 1))--		polarToCartesianTransform :: Floating f => (f, f) -> (f, f)-		polarToCartesianTransform	= uncurry (*) . Control.Arrow.second cos &&& uncurry (*) . Control.Arrow.second sin--{- |-	* 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 :: (-	RealFloat		f,-	Show			f,-	System.Random.Random	f,-	System.Random.RandomGen	randomGen- ) => randomGen -> [f]-generateStandardizedNormalDistribution	= ToolShed.Data.List.linearise . uncurry (zipWith $ curry boxMullerTransform) . ToolShed.Data.Pair.mirror (-	System.Random.randomRs (minPositiveFloat undefined, 1)- ) . System.Random.split---- | Stretches and shifts a /distribution/ to achieve the required /mean/ and /standard-deviation/.-reProfile :: (Distribution distribution, Floating n) => distribution -> [n] -> [n]-reProfile distribution	= map ((+ getMean distribution) . (* getStandardDeviation distribution))---- | Uses the supplied random-number generator, to generate a conceptually infinite population, with the specified continuous probability-distribution.-generateContinuousPopulation :: (-	RealFloat		f,-	Show			f,-	System.Random.Random	f,-	System.Random.RandomGen	randomGen- )-	=> ContinuousDistribution f-	-> randomGen	-- ^ A generator of /uniformly distributed/ random numbers.-	-> [f]-generateContinuousPopulation probabilityDistribution randomGen-	| not $ ToolShed.SelfValidate.isValid probabilityDistribution	= error $ "Factory.Math.Probability.generateContinuousPopulation:\t" ++ ToolShed.SelfValidate.getFirstError probabilityDistribution-	| otherwise							= (-		case probabilityDistribution of-			ExponentialDistribution lambda		-> let-				quantile	= (/ lambda) . negate . log . (1 -)	-- <http://en.wikipedia.org/wiki/Quantile_function>.-			 in map quantile . System.Random.randomRs (0, 1)-			LogNormalDistribution location scale2	-> map (-				exp . (+ location) . (* sqrt scale2)	-- Stretch the standard-deviation & re-locate the mean to that specified for the log-space, then return to the original coordinates.-			 ) . generateStandardizedNormalDistribution-			NormalDistribution _ _			-> reProfile probabilityDistribution . generateStandardizedNormalDistribution-			UniformDistribution interval		-> System.Random.randomRs interval-	) randomGen--{- |-	* Uses the supplied random-number generator,-	to generate a conceptually infinite population, of random integers conforming to the /Poisson distribution/; <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'.--}-generatePoissonDistribution :: (-	Integral		sample,-	RealFloat		lambda,-	Show			lambda,-	System.Random.Random	lambda,-	System.Random.RandomGen	randomGen- )-	=> lambda	-- ^ Defines the required approximate value of both /mean/ and /variance/.-	-> randomGen-	-> [sample]-generatePoissonDistribution lambda-	| lambda <= 0	= error $ "Factory.Math.Probability.generatePoissonDistribution:\tlambda must exceed zero " ++ show lambda-	| lambda > (-		negate . log $ minPositiveFloat lambda	-- Guard against underflow, in the user-defined type for lambda.-	)		= filter (>= 0) . map round . (reProfile (PoissonDistribution lambda) :: [Double] -> [Double]) . 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---- | Uses the supplied random-number generator, to generate a conceptually infinite population, with the specified discrete probability-distribution.-generateDiscretePopulation :: (-	Integral		sample,-	Ord			parameter,-	RealFloat		parameter,-	Show			parameter,-	System.Random.Random	parameter,-	System.Random.RandomGen	randomGen- )-	=> DiscreteDistribution parameter-	-> randomGen	-- ^ A generator of /uniformly distributed/ random numbers.-	-> [sample]-generateDiscretePopulation probabilityDistribution randomGen-	| not $ ToolShed.SelfValidate.isValid probabilityDistribution	= error $ "Factory.Math.Probability.generateDiscretePopulation:\t" ++ ToolShed.SelfValidate.getFirstError probabilityDistribution-	| otherwise							= (-		case probabilityDistribution of-			PoissonDistribution lambda	-> generatePoissonDistribution lambda-			ShiftedGeometricDistribution probability-				| probability == 1	-> const $ repeat 1	-- The first Bernoulli Trial is guaranteed to succeed.-				| otherwise		-> map ceiling {-minimum 1-} . (\x -> x :: [Rational]) . generatePopulation (ExponentialDistribution . negate $ log (1 - probability))	-- The geometric distribution is a discrete version of the exponential distribution.-	) randomGen-
− src/Factory/Math/Radix.hs
@@ -1,139 +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@]	Facilitates representation of 'Integral' values in alternative 'Integral' bases.--}--module Factory.Math.Radix(--- * Constants---	decodes,---	digits,---	encodes,--- * Functions-	digitSum,-	digitalRoot,-	fromBase,-	toBase-) where--import			Data.Array.IArray((!))-import qualified	Data.Array.IArray-import qualified	Data.Char-import qualified	Data.List-import qualified	Data.Maybe---- | Characters used to represent the digits of numbers in @(-36 <= base <= 36)@.-digits :: String-digits	= ['0' .. '9'] ++ ['a' .. 'z']---- | Constant random-access lookup for 'digits'.-encodes :: (Data.Array.IArray.Ix index, Integral index) => Data.Array.IArray.Array index Char-encodes	= Data.Array.IArray.listArray (0, pred $ Data.List.genericLength digits) digits---- | Constant reverse-lookup for 'digits'.-decodes :: Integral i => [(Char, i)]-decodes	= zip digits [0 ..]--{- |-	* Convert the specified integral decimal quantity, to an alternative base, and represent the result as a 'String'.--	* Both negative decimals and negative bases are permissible.--	* The conversion to 'Char' can only succeed where printable and intelligible characters exist to represent all digits in the chosen base;-	which in practice means @(-36 <= base <= 36)@.--}-toBase :: (-	Data.Array.IArray.Ix	decimal,-	Integral		base,-	Integral		decimal,-	Show			base,-	Show			decimal- ) => base -> decimal -> String-toBase 10 decimal	= show decimal	-- Base unchanged.-toBase _ 0		= "0"		-- Zero has the same representation in any base.-toBase base decimal-	| abs base < 2					= error $ "Factory.Math.Radix.toBase:\tan arbitrary integer can't be represented in base " ++ show base-	| abs base > Data.List.genericLength digits	= error $ "Factory.Math.Radix.toBase:\tunable to clearly represent the complete set of digits in base " ++ show base-	| base > 0 && decimal < 0			= '-' : map toDigit (fromDecimal (negate decimal) [])-	| otherwise					= toDigit `map` fromDecimal decimal []-	where-		fromDecimal 0		= id-		fromDecimal n-			| remainder < 0	= fromDecimal (succ quotient) . ((remainder - fromIntegral base) :)	-- This can only occur when base is negative; cf. 'divMod'.-			| otherwise	= fromDecimal quotient . (remainder :)-			where-				(quotient, remainder)	= n `quotRem` fromIntegral base--		toDigit :: (Data.Array.IArray.Ix i, Integral i, Show i) => i -> Char-		toDigit n-			| n >&< encodes	= encodes ! n-			| otherwise	= error $ "Factory.Math.Radix.toBase.toDigit:\tno suitable character-representation for integer " ++ show n-			where-				(>&<) :: (Data.Array.IArray.Ix i, Integral i) => i -> Data.Array.IArray.Array i Char -> Bool-				index >&< array	= ($ index) `all` [(>= lower), (<= upper)]	where-					(lower, upper)	= Data.Array.IArray.bounds array--{- |-	* Convert the 'String'-representation of a number in the specified base, to a decimal integer.--	* Both negative numbers and negative bases are permissible.--}-fromBase :: (-	Integral	base,-	Integral	decimal,-	Read		decimal,-	Show		base- ) => base -> String -> decimal-fromBase 10 s	= read s	-- Base unchanged.-fromBase _ "0"	= 0		-- Zero has the same representation in any base.-fromBase base s-	| abs base < 2					= error $ "Factory.Math.Radix.fromBase:\tan arbitrary integer can't be represented in base " ++ show base-	| abs base > Data.List.genericLength digits	= error $ "Factory.Math.Radix.fromBase:\tunable to clearly represent the complete set of digits in base " ++ show base-	| base > 0 && head s == '-'			= negate . fromBase base $ tail s	-- Recurse.-	| otherwise					= Data.List.foldl' (\l -> ((l * fromIntegral base) +) . fromDigit) 0 s	where-		fromDigit :: Integral i => Char -> i-		fromDigit c	= case c `lookup` decodes of-			Just i-				| i >= abs (fromIntegral base)	-> error $ "Factory.Math.Radix.fromBase.fromDigit:\tillegal char " ++ show c ++ ", for base " ++ show base-				| otherwise			-> i-			_					-> error $ "Factory.Math.Radix.fromBase.fromDigit:\tunrecognised char " ++ show c--{- |-	* <http://mathworld.wolfram.com/DigitSum.html>.--	* <http://en.wikipedia.org/wiki/Digit_sum>.--}-digitSum :: (-	Data.Array.IArray.Ix	decimal,-	Integral		base,-	Integral		decimal,-	Show			base,-	Show			decimal- ) => base -> decimal -> decimal-digitSum 10	= fromIntegral . foldr ((+) . Data.Char.digitToInt) 0 . show-digitSum base	= sum . Data.Maybe.mapMaybe (`lookup` decodes) . toBase base---- | <http://en.wikipedia.org/wiki/Digital_root>.-digitalRoot :: (-	Data.Array.IArray.Ix	decimal,-	Integral		decimal,-	Show			decimal- ) => decimal -> decimal-digitalRoot	= until (<= 9) (digitSum (10 :: Int))-
− src/Factory/Math/SquareRoot.hs
@@ -1,120 +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@]--	* Exports a common interface for /square-root/ implementations.--	* Provides utilities for these implementations.--}--module Factory.Math.SquareRoot(--- * Type-classes-	Algorithmic(..),-	Iterator(..),--- * Types--- ** Type-synonyms-	Result,-	Estimate,--- * Functions-	getAccuracy,-	getDiscrepancy,-	getEstimate,---	rSqrt,--- ** Predicates-	isPrecise-) where--import qualified	Factory.Math.Power	as Math.Power-import qualified	Factory.Math.Precision	as Math.Precision---- | The result-type; actually, only the concrete return-type of 'Math.Precision.simplify', stops it being a polymorphic instance of 'Fractional'.-type Result	= Rational---- | Contains an estimate for the /square-root/ of a value, and its accuracy.-type Estimate	= (Result, Math.Precision.DecimalDigits)---- | Defines the methods expected of a /square-root/ algorithm.-class Algorithmic algorithm	where-	squareRootFrom	:: (Real operand, Show operand)-		=> algorithm-		-> Estimate			-- ^ An initial estimate from which to start.-		-> Math.Precision.DecimalDigits	-- ^ The required precision.-		-> operand			-- ^ The value for which to find the /square-root/.-		-> Result			-- ^ Returns an improved estimate of the /square-root/, found using the specified algorithm, accurate to at least the required number of decimal digits.--	squareRoot	:: (Real operand, Show operand)-		=> algorithm-		-> Math.Precision.DecimalDigits	-- ^ The required precision.-		-> operand			-- ^ The value for which to find the /square-root/.-		-> Result			-- ^ Returns an estimate of the /square-root/, found using the specified algorithm, accurate to at least the required number of decimal digits.-	squareRoot algorithm decimalDigits operand	= squareRootFrom algorithm (getEstimate operand) decimalDigits operand	-- Default implementation---- | The interface required to iterate, from an estimate of the required value, to the next approximation.-class Iterator algorithm where-	step :: Real operand-		=> algorithm-		-> operand	-- ^ The value for which the /square-root/ is required; @y@.-		-> Result	-- ^ The current estimate; @x(n)@.-		-> Result	-- ^ An improved estimate; @x(n+1)@.--	convergenceOrder :: algorithm -> Math.Precision.ConvergenceOrder	-- ^ The ultimate ratio of successive terms as the iteration converges.---- | Generalise 'sqrt' to operate on any 'Real' operand.-rSqrt :: Real operand => operand -> Double-rSqrt	= sqrt . realToFrac---- | Uses 'Double'-precision floating-point arithmetic, to obtain an initial estimate for the /square-root/, and its accuracy.-getEstimate :: (Real operand, Show operand) => operand -> Estimate-getEstimate y-	| y < 0		= error $ "Factory.Math.SquareRoot.getEstimate:\tthere's no real square-root of " ++ show y-	| otherwise	= (Math.Precision.simplify decimalDigits {-doubles performance by roughly length of the Rational representation-} . toRational $ rSqrt y, decimalDigits)-	where-		decimalDigits :: Math.Precision.DecimalDigits-		decimalDigits	= 16	-- <http://en.wikipedia.org/wiki/IEEE_floating_point>.--{- |-	* The signed difference between the /square/ of an estimate for the /square-root/ of a value, and that value.--	* Positive when the estimate is too low.--	* CAVEAT: the magnitude is twice the error in the /square-root/.--}-getDiscrepancy :: Real operand => operand -> Result -> Result-getDiscrepancy y x	= toRational y - Math.Power.square x---- | True if the specified estimate for the /square-root/, is precise.-isPrecise :: Real operand => operand -> Result -> Bool-isPrecise y x	= getDiscrepancy y x == 0--{- |-	* For a given value and an estimate of its /square-root/,-	returns the number of decimals digits to which the /square-root/ is accurate; including the integral digits.--	* CAVEAT: the result returned for an exact match has been bodged.--}-getAccuracy :: Real operand => operand -> Result -> Math.Precision.DecimalDigits-getAccuracy y x-	| absoluteError == 0	= maxBound	-- Bodge.---	| otherwise		= length . takeWhile (< 1) $ iterate (* 10) relativeError	-- CAVEAT: too slow.-	| otherwise		= length $ show (round $ toRational y / absoluteError :: Integer)-	where-		absoluteError :: Result-		absoluteError	= abs (getDiscrepancy y x) / 2	-- NB: the magnitude of the error in 'y', is twice the error in its square-root, 'x'.-
− src/Factory/Math/Statistics.hs
@@ -1,181 +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@]	Miscellaneous statistics functions.--}--module Factory.Math.Statistics(--- * Functions-	getMean,-	getWeightedMean,---	getDispersionFromMean,-	getVariance,-	getStandardDeviation,-	getAverageAbsoluteDeviation,-	getCoefficientOfVariance,-	nCr,-	nPr-) where--import			Control.Arrow((***))-import			Control.Parallel(par, pseq)-import qualified	Data.Foldable-import qualified	Data.List-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 /mean/ of the specified numbers; <http://en.wikipedia.org/wiki/Mean>.--	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.--}-getMean :: (-	Data.Foldable.Foldable	foldable,-	Fractional		result,-	Real			value- )-	=> foldable value-	-> result-getMean foldable-	| denominator == 0	= error "Factory.Math.Statistics.getMean:\tno data => undefined result."-	| otherwise		= realToFrac numerator / fromIntegral denominator-	where-		(numerator, denominator)	= Data.Foldable.foldr (\s -> (+ s) *** succ) (0, 0 :: Int) foldable--{- |-	* Determines the /weighted mean/ of the specified numbers; <http://en.wikipedia.org/wiki/Weighted_arithmetic_mean>.--	* The specified value is only evaluated if the corresponding weight is non-zero.--	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.--}-getWeightedMean :: (-	Data.Foldable.Foldable	foldable,-	Fractional		result,-	Real			value,-	Real			weight- )-	=> foldable (value, weight)	-- ^ Each pair consists of a value & the corresponding weight.-	-> result-getWeightedMean foldable-	| denominator == 0	= error "Factory.Math.Statistics.getWeightedMean:\tzero weight => undefined result."-	| otherwise		= numerator / realToFrac denominator-	where-		(numerator, denominator)	= Data.Foldable.foldr (-			\(value, weight)	-> if weight == 0-				then id	--Avoid unnecessarily evaluation.-				else (+ realToFrac value * realToFrac weight) *** (+ weight)-		 ) (0, 0) foldable--{- |-	* 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 'Rational', then it will be free from rounding-errors.--}-getDispersionFromMean :: (-	Data.Foldable.Foldable	foldable,-	Fractional		result,-	Functor			foldable,-	Real			value- ) => (Rational -> Rational) -> foldable value -> result-getDispersionFromMean weight foldable	= getMean $ fmap (weight . (+ negate mean) . toRational) foldable	where-	mean :: Rational-	mean	= getMean foldable--{- |-	* Determines the exact /variance/ of the specified numbers; <http://en.wikipedia.org/wiki/Variance>.--	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.--}-getVariance :: (-	Data.Foldable.Foldable	foldable,-	Fractional		variance,-	Functor			foldable,-	Real			value- ) => foldable value -> variance-getVariance	= getDispersionFromMean Math.Power.square---- | Determines the /standard-deviation/ of the specified numbers; <http://en.wikipedia.org/wiki/Standard_deviation>.-getStandardDeviation :: (-	Data.Foldable.Foldable	foldable,-	Floating		result,-	Functor			foldable,-	Real			value- ) => foldable value -> result-getStandardDeviation	= sqrt . getVariance--{- |-	* Determines the /average absolute deviation/ of the specified numbers; <http://en.wikipedia.org/wiki/Absolute_deviation#Average_absolute_deviation>.--	* Should the caller define the result-type as 'Rational', then it will be free from rounding-errors.--}-getAverageAbsoluteDeviation :: (-	Data.Foldable.Foldable	foldable,-	Fractional		result,-	Functor			foldable,-	Real			value- ) => foldable value -> result-getAverageAbsoluteDeviation	= getDispersionFromMean abs---- | Determines the /coefficient-of-variance/ of the specified numbers; <http://en.wikipedia.org/wiki/Coefficient_of_variation>.-getCoefficientOfVariance :: (-	Data.Foldable.Foldable	foldable,-	Eq			result,-	Floating		result,-	Functor			foldable,-	Real			value- ) => foldable value -> 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.Algorithmic factorialAlgorithm, Integral i, Show i)-	=> factorialAlgorithm-	-> i	-- ^ The total number of items from which to select.-	-> i	-- ^ The number of items in a sample.-	-> i	-- ^ The number of combinations.-nCr _ 0 _	= 1-nCr _ _ 0	= 1-nCr factorialAlgorithm n r-	| 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	= numerator `par` (denominator `pseq` numerator `div` denominator)-	where-		[smaller, bigger]	= Data.List.sort [r, n - r]-		numerator		= Math.Implementations.Factorial.risingFactorial (succ bigger) (n - bigger)-		denominator		= Math.Factorial.factorial factorialAlgorithm smaller---- | The number of /permutations/ of /r/ objects taken from /n/; <http://en.wikipedia.org/wiki/Permutations>.-nPr :: (Integral i, Show i)-	=> i	-- ^ The total number of items from which to select.-	-> i	-- ^ The number of items in a sample.-	-> i	-- ^ The number of permutations.-nPr 0 _	= 1-nPr _ 0	= 1-nPr n r-	| n < 0		= error $ "Factory.Math.Statistics.nPr:\tinvalid n; " ++ show n-	| r < 0		= error $ "Factory.Math.Statistics.nPr:\tinvalid r; " ++ show r-	| n < r		= 0-	| otherwise	= Math.Implementations.Factorial.fallingFactorial n r-
− src/Factory/Math/Summation.hs
@@ -1,91 +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@]	Provides an alternative algorithm for the summation of /rational/ numbers.--}--module Factory.Math.Summation(--- * Functions-	sum',-	sumR',-	sumR-) where--import qualified	Control.DeepSeq-import qualified	Control.Parallel.Strategies-import qualified	Data.List-import qualified	Data.Ratio-import			Data.Ratio((%))-import qualified	ToolShed.Data.List--{- |-	* Sums a list of numbers of arbitrary type.--	* Sparks the summation of @(list-length / chunk-size)@ chunks from the list, each of the specified size (thought the last chunk may be smaller),-	then recursively sums the list of results from each spark.--	* CAVEAT: unless the numbers are large, 'Rational' (requiring /cross-multiplication/), or the list long,-	'sum' is too light-weight for sparking to be productive,-	therefore it is more likely to be the parallelised deep /evaluation/ of list-elements which saves time.--}-sum' :: (Num n, Control.DeepSeq.NFData n)-	=> ToolShed.Data.List.ChunkLength-	-> [n]-	-> n-sum' chunkLength-	| chunkLength <= 1	= error $ "Factory.Math.Summation.sum':\tinvalid chunk-size; " ++ show chunkLength-	| otherwise		= slave-	where-		slave :: (Num n, Control.DeepSeq.NFData n) => [n] -> n-		slave []	= 0-		slave [x]	= x-		slave l		= slave {-recurse-} . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rdeepseq sum $ ToolShed.Data.List.chunk chunkLength l--{- |-	* Sums a list of /rational/ type numbers.--	* CAVEAT: though faster than 'Data.List.sum', this algorithm has poor space-complexity, making it unsuitable for unrestricted use.--}-{-# INLINE sumR' #-}	-- This makes a staggering difference.-sumR' :: Integral i => [Data.Ratio.Ratio i] -> Data.Ratio.Ratio i-sumR' l	= foldr (\ratio -> ((Data.Ratio.numerator ratio * (commonDenominator `div` Data.Ratio.denominator ratio)) +)) 0 l % commonDenominator	where---	commonDenominator	= foldr (lcm . Data.Ratio.denominator) 1 l-	commonDenominator	= Data.List.foldl' (\multiple -> lcm multiple . Data.Ratio.denominator) 1 l	-- Slightly faster.--{- |-	* Sums a list of /rational/ numbers.--	* Sparks the summation of @(list-length / chunk-length)@ chunks from the list, each of the specified size (thought the last chunk may be smaller),-	then recursively sums the list of results from each spark.--	* CAVEAT: memory-use is proportional to chunk-size.--}-{-# INLINE sumR #-}	-- This makes a staggering difference to calls from other modules.-sumR :: (Integral i, Control.DeepSeq.NFData i)-	=> ToolShed.Data.List.ChunkLength-	-> [Data.Ratio.Ratio i]-	-> Data.Ratio.Ratio i-sumR chunkLength-	| chunkLength <= 1	= error $ "Factory.Math.Summation.sumR:\tinvalid chunk-size; " ++ show chunkLength-	| otherwise		= slave-	where-		slave :: (Integral i, Control.DeepSeq.NFData i) => [Data.Ratio.Ratio i] -> Data.Ratio.Ratio i-		slave l-			| length l <= chunkLength	= sumR' l-			| otherwise			= slave {-recurse-} . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rdeepseq sumR' $ ToolShed.Data.List.chunk chunkLength l
− src/Factory/Test/CommandOptions.hs
@@ -1,48 +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 the available set of command-line options; of which there's currently only one.--}--module Factory.Test.CommandOptions(--- * Types--- ** Data-types-	CommandOptions(..),--- * Functions--- ** Mutators-	setVerbose-) where--import qualified	ToolShed.Defaultable---- | Declare a record used to contain command-line options.-data CommandOptions	= MkCommandOptions {-	verbose	:: Bool	-- ^ Whether additional informative output should be generated, where applicable.-}--instance ToolShed.Defaultable.Defaultable CommandOptions	where-	defaultValue	= MkCommandOptions { verbose = False }---- | Mutator.-setVerbose :: CommandOptions -> CommandOptions-setVerbose commandOptions = commandOptions {-	verbose	= True-}--
− src/Factory/Test/Performance/Factorial.hs
@@ -1,73 +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@]	Times the methods exported from module "Math.Factorial".--}--module Factory.Test.Performance.Factorial(--- * Functions-	factorialPerformance,-	factorialPerformanceControl,-	factorialPerformanceGraph,-	factorialPerformanceGraphControl-) where--import qualified	Control.DeepSeq-import qualified	Data.List-import qualified	Factory.Math.Factorial	as Math.Factorial-import qualified	ToolShed.System.TimePure---- | Measures the CPU-time required by 'Math.Factorial.factorial'.-factorialPerformance :: (-	Control.DeepSeq.NFData		i,-	Integral			i,-	Math.Factorial.Algorithmic	algorithm,-	Show				i- ) => algorithm -> i -> IO (Double, i)-factorialPerformance algorithm	= ToolShed.System.TimePure.getCPUSeconds . Math.Factorial.factorial algorithm---- | Measures the CPU-time required by a naive implementation.-factorialPerformanceControl :: (Control.DeepSeq.NFData i, Integral i) => i -> IO (Double, i)--- factorialPerformanceControl i	= ToolShed.System.TimePure.getCPUSeconds $ product [1 .. i]	-- CAVEAT: too lazy.-factorialPerformanceControl i	= ToolShed.System.TimePure.getCPUSeconds $ Data.List.foldl' (*) 1 [2 .. i]--{- |-	* Measure the CPU-time required by 'Math.Factorial.factorial', against an exponentially increasing operand.--	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.--}-factorialPerformanceGraph :: Math.Factorial.Algorithmic algorithm => Bool -> algorithm -> IO ()-factorialPerformanceGraph verbose algorithm	= mapM_ (-	\operand	-> factorialPerformance algorithm operand >>= putStrLn . shows operand . showChar '\t' . (-		if verbose-			then (`shows` "")-			else (`shows` "") . fst-	)- ) $ iterate (* 2) (1 :: Integer)---- | Graphs the CPU-time required by a naive implementation, against an exponentially increasing operand.-factorialPerformanceGraphControl :: Bool -> IO ()-factorialPerformanceGraphControl verbose	= mapM_ (-	\operand	-> factorialPerformanceControl operand >>= putStrLn . shows operand . showChar '\t' . (-		if verbose-			then (`shows` "")-			else (`shows` "") . fst-	)- ) $ iterate (* 2) (1 :: Integer)-
− src/Factory/Test/Performance/Hyperoperation.hs
@@ -1,71 +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@]	Times functions exported from module "Math.Hyperoperation".--}--module Factory.Test.Performance.Hyperoperation(--- * Functions-	hyperoperationPerformance,-	hyperoperationPerformanceGraphRank,-	hyperoperationPerformanceGraphExponent-) where--import qualified	Factory.Math.Hyperoperation	as Math.Hyperoperation-import qualified	ToolShed.System.TimePure---- | Measures the CPU-time required by 'Math.Hyperoperation.hyperoperation'.-hyperoperationPerformance :: (Integral rank, Show rank) => rank -> Math.Hyperoperation.Base -> Math.Hyperoperation.HyperExponent -> IO (Double, Integer)-hyperoperationPerformance rank base	= ToolShed.System.TimePure.getCPUSeconds . Math.Hyperoperation.hyperoperation rank base--{- |-	* Measure the CPU-time required by 'Math.Hyperoperation.hyperoperation', against a linearly increasing /rank/.--	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.--}-hyperoperationPerformanceGraphRank-	:: Bool	-- ^ Verbose.-	-> Math.Hyperoperation.Base-	-> Math.Hyperoperation.HyperExponent-	-> IO ()-hyperoperationPerformanceGraphRank verbose base hyperExponent	= mapM_ (-	\rank	-> hyperoperationPerformance rank base hyperExponent >>= putStrLn . shows rank . showChar '\t' . (-		if verbose-			then (`shows` "")-			else (`shows` "") . fst-	)- ) [0 :: Int ..]--{- |-	* Measure the CPU-time required by 'Math.Hyperoperation.hyperoperation', against a linearly increasing /hyper-exponent/.--	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.--}-hyperoperationPerformanceGraphExponent :: (Integral rank, Show rank)-	=> Bool	-- ^ Verbose.-	-> rank-	-> Math.Hyperoperation.Base-	-> IO ()-hyperoperationPerformanceGraphExponent verbose rank base	= mapM_ (-	\hyperExponent	-> hyperoperationPerformance rank base hyperExponent >>= putStrLn . shows hyperExponent . showChar '\t' . (-		if verbose-			then (`shows` "")-			else (`shows` "") . fst-	)- ) [0 ..]
− src/Factory/Test/Performance/Pi.hs
@@ -1,81 +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@]	Times the methods exported from module "Math.Pi".--}--module Factory.Test.Performance.Pi(--- * Types--- ** Type-synonyms-	Category,--- * Functions-	piPerformance,-	piPerformanceGraph-) where--import qualified	Factory.Math.Factorial					as Math.Factorial-import qualified	Factory.Math.Implementations.Pi.AGM.Algorithm		as Math.Implementations.Pi.AGM.Algorithm-import qualified	Factory.Math.Implementations.Pi.BBP.Algorithm		as Math.Implementations.Pi.BBP.Algorithm-import qualified	Factory.Math.Implementations.Pi.Borwein.Algorithm	as Math.Implementations.Pi.Borwein.Algorithm-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Algorithm	as Math.Implementations.Pi.Ramanujan.Algorithm-import qualified	Factory.Math.Implementations.Pi.Spigot.Algorithm	as Math.Implementations.Pi.Spigot.Algorithm-import qualified	Factory.Math.Pi						as Math.Pi-import qualified	Factory.Math.Precision					as Math.Precision-import qualified	Factory.Math.SquareRoot					as Math.SquareRoot-import qualified	ToolShed.System.TimePure---- | The type of a /Pi/-algorithm, including where required, the algorithm for /square-root/s and /factorial/s.-type Category squareRootAlgorithm factorialAlgorithm = Math.Pi.Category (-	Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm- ) Math.Implementations.Pi.BBP.Algorithm.Algorithm (-	Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm- ) (-	Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm- ) Math.Implementations.Pi.Spigot.Algorithm.Algorithm---- | Measures the CPU-time required to find Pi to the required precision.-piPerformance :: (-	Math.SquareRoot.Algorithmic	squareRootAlgorithm,-	Math.Factorial.Algorithmic	factorialAlgorithm- ) => Category squareRootAlgorithm factorialAlgorithm -> Math.Precision.DecimalDigits -> IO (Double, String)-piPerformance category = ToolShed.System.TimePure.getCPUSeconds . Math.Pi.openS category--{- |-	* Measures the CPU-time required to determine /Pi/ to an exponentially increasing precision-requirement.--	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.--}-piPerformanceGraph :: (-	Math.SquareRoot.Algorithmic	squareRootAlgorithm,-	Show				squareRootAlgorithm,-	Math.Factorial.Algorithmic	factorialAlgorithm,-	Show				factorialAlgorithm- ) => RealFrac i-	=> Category squareRootAlgorithm factorialAlgorithm	-- ^ The algorithm.-	-> i							-- ^ The factor by which the precision is increased on each iteration.-	-> Math.Precision.DecimalDigits				-- ^ The maximum precision required.-	-> Bool							-- ^ Whether to return the digits of /Pi/.-	-> IO ()-piPerformanceGraph category factor maxDecimalDigits verbose	= mapM_ (-	\decimalDigits	-> piPerformance category decimalDigits >>= putStrLn . shows decimalDigits . showChar '\t' . (-		if verbose-			then (`shows` "")-			else (`shows` "") . fst-	)- ) . takeWhile (<= maxDecimalDigits) . map round $ iterate (* factor) 1
− src/Factory/Test/Performance/Primality.hs
@@ -1,54 +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@]	Times functions exported from module "Math.Primality".--}--module Factory.Test.Performance.Primality(--- * Functions-	carmichaelNumbersPerformance,-	isPrimePerformance,-	isPrimePerformanceGraph-) where--import qualified	Control.DeepSeq-import qualified	Factory.Math.Fibonacci	as Math.Fibonacci-import qualified	Factory.Math.Primality	as Math.Primality-import qualified	ToolShed.System.TimePure---- | Measures the CPU-time required to find the specified number of /Carmichael/-numbers, which is returned together with the requested list.-carmichaelNumbersPerformance :: Math.Primality.Algorithmic primalityAlgorithm => primalityAlgorithm -> Int -> IO (Double, [Integer])-carmichaelNumbersPerformance primalityAlgorithm i-	| i < 0		= fail $ "Factory.Test.Performance.Primality.carmichaelNumbersPerformance:\tnegative number; " ++ show i-	| otherwise	= ToolShed.System.TimePure.getCPUSeconds . take i $ Math.Primality.carmichaelNumbers primalityAlgorithm---- | Measures the CPU-time required to determine whether the specified integer is prime, which is returned together with the Boolean result.-isPrimePerformance :: (Control.DeepSeq.NFData i, Integral i, Show i) => Math.Primality.Algorithmic primalityAlgorithm => primalityAlgorithm -> i -> IO (Double, Bool)-isPrimePerformance primalityAlgorithm	= ToolShed.System.TimePure.getCPUSeconds . Math.Primality.isPrime primalityAlgorithm--{- |-	* Measures the CPU-time required to determine whether /prime-indexed Fibonacci-numbers/ are actually /prime/.--	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.--}-isPrimePerformanceGraph :: Math.Primality.Algorithmic primalityAlgorithm => primalityAlgorithm -> IO ()-isPrimePerformanceGraph primalityAlgorithm	= mapM_ (-	\operand	-> isPrimePerformance primalityAlgorithm operand >>= putStrLn . shows operand . showChar '\t' . (`shows` "")- ) (Math.Fibonacci.primeIndexedFibonacci :: [Integer])-
− src/Factory/Test/Performance/PrimeFactorisation.hs
@@ -1,50 +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@]	Times the methods exported by module "Math.PrimeFactorisation".--}--module Factory.Test.Performance.PrimeFactorisation(--- * Functions-	primeFactorsPerformance,-	primeFactorsPerformanceGraph-) where--import qualified	Factory.Data.PrimeFactors	as Data.PrimeFactors-import qualified	Factory.Math.Fibonacci		as Math.Fibonacci-import qualified	Factory.Math.PrimeFactorisation	as Math.PrimeFactorisation-import qualified	ToolShed.System.TimePure---- | Measures the CPU-time required to prime-factorise the specified integer, which is returned together with the resulting list of factors.-primeFactorsPerformance :: Math.PrimeFactorisation.Algorithmic algorithm => algorithm -> Integer -> IO (Double, Data.PrimeFactors.Factors Integer Int)-primeFactorsPerformance algorithm	= ToolShed.System.TimePure.getCPUSeconds . Math.PrimeFactorisation.primeFactors algorithm--{- |-	* Measure the CPU-time required by 'Math.PrimeFactorisation.primeFactors',-	arbitrarily against the /Fibonacci/-numbers (which seemed to fit the requirements).--	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.--}-primeFactorsPerformanceGraph :: Math.PrimeFactorisation.Algorithmic algorithm => algorithm -> Int -> IO ()-primeFactorsPerformanceGraph algorithm tests-	| tests < 0	= fail $ "Factory.Test.Performance.PrimeFactorisation.primeFactorsPerformanceGraph:\tnegative number; " ++ show tests-	| otherwise	= mapM_ (-		\operand	-> primeFactorsPerformance algorithm operand >>= putStrLn . shows operand . showChar '\t' . (`shows` "")-	) . take tests . dropWhile (< 2) $ Math.Fibonacci.fibonacci-
− src/Factory/Test/Performance/Primes.hs
@@ -1,47 +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@]	Measures the CPU-time required by "Math.Primes.primes".--}--module Factory.Test.Performance.Primes(--- * Functions-	primesPerformance,-	mersenneNumbersPerformance-) where--import qualified	Control.DeepSeq-import qualified	Data.Array.IArray-import qualified	Factory.Math.Primes	as Math.Primes-import qualified	ToolShed.System.TimePure---- | Measures the CPU-time required by 'Math.Primes.primes', to find the specified prime.-primesPerformance :: (-	Control.DeepSeq.NFData	i,-	Data.Array.IArray.Ix	i,-	Math.Primes.Algorithmic	algorithm,-	Integral		i- ) => algorithm -> Int -> IO (Double, i)-primesPerformance algorithm	= ToolShed.System.TimePure.getCPUSeconds . (Math.Primes.primes algorithm !!)---- | Measures the CPU-time required to find the specified number of /Mersenne/-numbers, which is returned together with the requested list.-mersenneNumbersPerformance :: Math.Primes.Algorithmic algorithm => algorithm -> Int -> IO (Double, [Integer])-mersenneNumbersPerformance primalityAlgorithm i-	| i < 0		= fail $ "Factory.Test.Performance.Primes.mersenneNumbersPerformance:\tnegative number; " ++ show i-	| otherwise	= ToolShed.System.TimePure.getCPUSeconds . take i $ Math.Primes.mersenneNumbers primalityAlgorithm
− src/Factory/Test/Performance/SquareRoot.hs
@@ -1,59 +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@]	Measures the CPU-time required by the methods exported from module "Math.SquareRoot".--}--module Factory.Test.Performance.SquareRoot(--- * Functions-	squareRootPerformance,-	squareRootPerformanceGraph-) where--import qualified	Control.Arrow-import qualified	Factory.Math.Precision	as Math.Precision-import qualified	Factory.Math.SquareRoot	as Math.SquareRoot-import qualified	ToolShed.System.TimePure---- | Measures the CPU-time required by 'Math.SquareRoot.squareRootFrom', which is returned together with the approximate rational result.-squareRootPerformance :: (-	Math.SquareRoot.Algorithmic	algorithm,-	Real				operand,-	Show				operand- ) => algorithm -> operand -> Math.Precision.DecimalDigits -> IO (Double, Math.SquareRoot.Result)-squareRootPerformance algorithm operand requiredDecimalDigits = ToolShed.System.TimePure.getCPUSeconds $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand--{- |-	* Measures the CPU-time required by 'Math.SquareRoot.squareRootFrom', and the resulting accuracy,-	using the specified algorithm, to an exponentially increasing precision-requirement.--	* CAVEAT: nothing is returned, since the result is printed ... and it never terminates.--}-squareRootPerformanceGraph :: (-	Math.SquareRoot.Algorithmic	algorithm,-	Math.SquareRoot.Iterator	algorithm,-	Real				operand,-	Show				algorithm,-	Show				operand- ) => algorithm -> operand -> IO ()-squareRootPerformanceGraph algorithm operand	= mapM_ (-	\requiredDecimalDigits	-> putStrLn . (-		\(cpuSeconds, actualDecimalDigits)	-> shows algorithm . showChar '\t' . shows requiredDecimalDigits . showChar '\t' . shows actualDecimalDigits . showChar '\t' $ shows cpuSeconds ""-	) . Control.Arrow.second (Math.SquareRoot.getAccuracy operand) =<< squareRootPerformance algorithm operand requiredDecimalDigits- ) $ iterate (* max 2 (Math.SquareRoot.convergenceOrder algorithm)) 16
− src/Factory/Test/Performance/Statistics.hs
@@ -1,45 +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@]	Times the functions exported from module "Math.Statistics".--}--module Factory.Test.Performance.Statistics(--- * Functions-	nCrPerformance-) where--import qualified	Control.DeepSeq-import qualified	Factory.Math.Factorial	as Math.Factorial-import qualified	Factory.Math.Statistics	as Math.Statistics-import qualified	ToolShed.System.TimePure---- | Measures the CPU-time required by 'Math.Statistics.nCr'.-nCrPerformance :: (-	Control.DeepSeq.NFData		i,-	Integral			i,-	Math.Factorial.Algorithmic	factorialAlgorithm,-	Show				i- )-	=> factorialAlgorithm-	-> i	-- ^ The total number from which to select.-	-> i	-- ^ The number of items in a sample.-	-> IO (Double, i)-nCrPerformance factorialAlgorithm n r	= ToolShed.System.TimePure.getCPUSeconds $ Math.Statistics.nCr factorialAlgorithm n r-
− src/Factory/Test/QuickCheck/ArithmeticGeometricMean.hs
@@ -1,57 +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 "Math.ArithmeticGeometricMean".--}--module Factory.Test.QuickCheck.ArithmeticGeometricMean(--- * Types--- ** Type-synonyms---	Testable,--- * Functions-	quickChecks-) where--import qualified	Data.Tuple-import qualified	Factory.Math.ArithmeticGeometricMean	as Math.ArithmeticGeometricMean-import qualified	Factory.Math.Implementations.SquareRoot	as Math.Implementations.SquareRoot-import qualified	Factory.Math.Precision			as Math.Precision-import			Factory.Test.QuickCheck.SquareRoot()-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))--type Testable	= Math.Implementations.SquareRoot.Algorithm -> Math.Precision.DecimalDigits -> Math.ArithmeticGeometricMean.AGM -> Int -> Test.QuickCheck.Property---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_symmetrical, prop_bounds]	where-	prop_symmetrical, prop_bounds :: Testable-	prop_symmetrical squareRootAlgorithm decimalDigits agm index	= Math.ArithmeticGeometricMean.isValid agm ==> Test.QuickCheck.label "prop_symmetrical" . and . tail . take index' $ zipWith (==) (-		Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits' agm-	 ) (-		Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits' $ Data.Tuple.swap agm-	 ) where-		decimalDigits'	= succ $ decimalDigits `mod` 64-		index'		= succ $ index `mod` 8--	prop_bounds squareRootAlgorithm decimalDigits agm index	= all ($ agm) [Math.ArithmeticGeometricMean.isValid, uncurry (/=)] ==> Test.QuickCheck.label "prop_bounds" . all (uncurry (>=)) . tail . take index' $ Math.ArithmeticGeometricMean.convergeToAGM squareRootAlgorithm decimalDigits' agm-		where-			decimalDigits'	= 33 {-test is sensitive to rounding-errors-} + (decimalDigits `mod` 96)-			index'		= succ $ index `mod` 5-
− src/Factory/Test/QuickCheck/Factorial.hs
@@ -1,68 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	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.Implementations.Factorial".--}--module Factory.Test.QuickCheck.Factorial(--- * Types--- ** Type-synonyms---	Testable,--- * Functions-	quickChecks-) where--import			Data.Ratio((%))-import qualified	Factory.Math.Factorial			as Math.Factorial-import qualified	Factory.Math.Implementations.Factorial	as Math.Implementations.Factorial-import			Factory.Math.Implementations.Factorial((!/!))-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))--instance Test.QuickCheck.Arbitrary Math.Implementations.Factorial.Algorithm	where-	arbitrary	= Test.QuickCheck.elements [Math.Implementations.Factorial.Bisection, Math.Implementations.Factorial.PrimeFactorisation]--type Testable	= Integer -> Integer -> Test.QuickCheck.Property---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_equivalence, prop_symmetry, prop_x0, prop_0n] >> Test.QuickCheck.quickCheck prop_ratio >> Test.QuickCheck.quickCheck prop_consistency	where-	prop_equivalence, prop_symmetry, prop_x0, prop_0n :: Testable-	prop_equivalence x n	= Test.QuickCheck.label "prop_equivalence" $ Math.Implementations.Factorial.risingFactorial x n == sign * Math.Implementations.Factorial.fallingFactorial (negate x) n && Math.Implementations.Factorial.fallingFactorial x n == sign * Math.Implementations.Factorial.risingFactorial (negate x) n	where-		sign :: Integer-		sign-			| even n	= 1-			| otherwise	= negate 1--	prop_symmetry x n	= Test.QuickCheck.label "prop_symmetry" $ Math.Implementations.Factorial.risingFactorial x n == Math.Implementations.Factorial.fallingFactorial (pred $ x + n) n--	prop_x0 x _		= Test.QuickCheck.label "prop_x0" $ all (== 1) $ map ($ 0) [Math.Implementations.Factorial.risingFactorial x, Math.Implementations.Factorial.fallingFactorial x]--	prop_0n _ n		= Test.QuickCheck.label "prop_0n" $ all (== if n == 0 then 1 else 0) $ map ($ n) [Math.Implementations.Factorial.risingFactorial 0, Math.Implementations.Factorial.fallingFactorial 0]--	prop_ratio :: Math.Implementations.Factorial.Algorithm -> Integer -> Integer -> Test.QuickCheck.Property-	prop_ratio algorithm i j	= Test.QuickCheck.label "prop_ratio" $ n !/! d == Math.Factorial.factorial algorithm n % Math.Factorial.factorial algorithm d	where-		n	= pred $ i `mod` 100000-		d	= pred $ j `mod` 100000--	prop_consistency :: Math.Implementations.Factorial.Algorithm -> Math.Implementations.Factorial.Algorithm -> Integer -> Test.QuickCheck.Property-	prop_consistency l r i	= l /= r	==> Test.QuickCheck.label "prop_consistency" $ Math.Factorial.factorial l n == Math.Factorial.factorial r n	where-		n	= pred $ i `mod` 100000-
− src/Factory/Test/QuickCheck/Hyperoperation.hs
@@ -1,75 +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 "Math.Hyperoperation".--}--module Factory.Test.QuickCheck.Hyperoperation(--- * Functions-	quickChecks-) where--import qualified	Factory.Math.Hyperoperation	as Math.Hyperoperation-import qualified	Test.QuickCheck--type Rank	= Int---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	=-	Test.QuickCheck.quickCheck prop_rankCoincides-	>> Test.QuickCheck.quickCheck prop_baseCoincides-	>> Test.QuickCheck.quickCheck prop_hyperExponentCoincides-	>> Test.QuickCheck.quickCheck `mapM_` [prop_succ, prop_addition, prop_multiplication, prop_exponentiation] where-		prop_rankCoincides :: Rank -> Test.QuickCheck.Property-		prop_rankCoincides rank = Test.QuickCheck.label "prop_rankCoincides" $ Math.Hyperoperation.hyperoperation rank' 2 2 == 4	where-			rank' :: Rank-			rank'	= succ $ rank `mod` 1000--		prop_baseCoincides :: Rank -> Integer -> Test.QuickCheck.Property-		prop_baseCoincides rank base	= Test.QuickCheck.label "prop_baseCoincides" $ Math.Hyperoperation.hyperoperation rank' base 1 == base	where-			rank' :: Rank-			rank'	= 2 + (rank `mod` 1000)--		prop_hyperExponentCoincides :: Rank -> Integer -> Test.QuickCheck.Property-		prop_hyperExponentCoincides rank hyperExponent	= Test.QuickCheck.label "prop_hyperExponentCoincides" $ Math.Hyperoperation.hyperoperation rank' 1 hyperExponent' == 1	where-			rank' :: Rank-			rank'	= 3 + (rank `mod` 1000)--			hyperExponent' :: Math.Hyperoperation.HyperExponent-			hyperExponent'	= abs hyperExponent--		prop_succ, prop_addition, prop_multiplication, prop_exponentiation :: Integer -> Integer -> Test.QuickCheck.Property-		prop_succ base hyperExponent			= Test.QuickCheck.label "prop_succ" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.succession base hyperExponent' == succ (fromIntegral hyperExponent')	where-			hyperExponent' :: Math.Hyperoperation.HyperExponent-			hyperExponent'	= abs hyperExponent--		prop_addition base hyperExponent		= Test.QuickCheck.label "prop_addition" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.addition base hyperExponent' == base + fromIntegral hyperExponent'	where-			hyperExponent' :: Math.Hyperoperation.HyperExponent-			hyperExponent'	= abs hyperExponent--		prop_multiplication base hyperExponent		= Test.QuickCheck.label "prop_multiplication" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.multiplication base hyperExponent' == base * fromIntegral hyperExponent'	where-			hyperExponent' :: Math.Hyperoperation.HyperExponent-			hyperExponent'	= abs hyperExponent--		prop_exponentiation base hyperExponent		= Test.QuickCheck.label "prop_exponentiation" $ Math.Hyperoperation.hyperoperation Math.Hyperoperation.exponentiation base hyperExponent' == base ^ hyperExponent'	where-			hyperExponent' :: Math.Hyperoperation.HyperExponent-			hyperExponent'	= abs hyperExponent--
− src/Factory/Test/QuickCheck/Interval.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.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'	= succ $ minLength `mod` 1000-		ratio'-			| r > 1		= recip r-			| otherwise	= r-			where-				r	= abs ratio
− src/Factory/Test/QuickCheck/MonicPolynomial.hs
@@ -1,72 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Data.MonicPolynomial".--}--module Factory.Test.QuickCheck.MonicPolynomial(--- * Types--- ** Type-synonyms---	P--- * Functions-	quickChecks-) where--import			Factory.Data.Ring((=*=), (=+=), (=^))-import			Factory.Test.QuickCheck.Polynomial()-import qualified	Factory.Data.MonicPolynomial	as Data.MonicPolynomial-import qualified	Factory.Data.Polynomial		as Data.Polynomial-import qualified	Factory.Data.QuotientRing	as Data.QuotientRing-import qualified	Factory.Data.Ring		as Data.Ring-import qualified	Test.QuickCheck--instance (-	Integral			c,-	Integral			e,-	Test.QuickCheck.Arbitrary	c,-	Test.QuickCheck.Arbitrary	e,-	Show				c,-	Show				e- ) => Test.QuickCheck.Arbitrary (Data.MonicPolynomial.MonicPolynomial c e)	where-	arbitrary	= do-		polynomial	<- Test.QuickCheck.arbitrary--		return {-to Gen-monad-} . Data.MonicPolynomial.mkMonicPolynomial $ ((1, succ $ Data.Polynomial.getDegree polynomial) :) `Data.Polynomial.lift` polynomial--type P	= Data.MonicPolynomial.MonicPolynomial Integer Integer---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_quotRem, prop_quotientRingNormalised] >> Test.QuickCheck.quickCheck prop_perfectPower >> Test.QuickCheck.quickCheck prop_isDivisibleBy where-	prop_quotRem, prop_quotientRingNormalised :: P -> P -> Test.QuickCheck.Property-	prop_quotRem numerator denominator	= Test.QuickCheck.label "prop_quotRem" $ numerator == denominator =*= quotient =+= remainder	where-		(quotient, remainder)	= numerator `Data.QuotientRing.quotRem'` denominator--	prop_quotientRingNormalised numerator denominator	= Test.QuickCheck.label "prop_quotientRingNormalised" $ all (Data.Polynomial.isNormalised . Data.MonicPolynomial.getPolynomial) [numerator `Data.QuotientRing.quot'` denominator, numerator `Data.QuotientRing.rem'` denominator]--	prop_perfectPower :: P -> Int -> Test.QuickCheck.Property-	prop_perfectPower polynomial power	= Test.QuickCheck.label "prop_perfectPower" $ iterate (`Data.QuotientRing.quot'` polynomial) (polynomial =^ power') !! pred power' == polynomial	where-		power' :: Int-		power'	= succ $ power `mod` 100--	prop_isDivisibleBy :: [P] -> Test.QuickCheck.Property-	prop_isDivisibleBy monicPolynomials	= Test.QuickCheck.label "prop_isDivisibleBy" $ all (Data.QuotientRing.isDivisibleBy (Data.Ring.product' (recip 2) {-TODO-} 10 monicPolynomials)) monicPolynomials--
− src/Factory/Test/QuickCheck/PerfectPower.hs
@@ -1,54 +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 "Math.PerfectPower".--}--module Factory.Test.QuickCheck.PerfectPower(--- * Functions-	quickChecks-) where--import qualified	Data.Maybe-import qualified	Factory.Math.PerfectPower	as Math.PerfectPower-import qualified	Factory.Math.Power		as Math.Power-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks =-	Test.QuickCheck.quickCheck `mapM_` [prop_maybeSquareNumber, prop_rewriteRule]-	>> Test.QuickCheck.quickCheckWith Test.QuickCheck.stdArgs {Test.QuickCheck.maxSuccess = 10000} prop_notSquare-	>> Test.QuickCheck.quickCheck prop_isPerfectPower-	where-		prop_maybeSquareNumber, prop_notSquare, prop_rewriteRule :: Integer -> Test.QuickCheck.Property-		prop_maybeSquareNumber i	= Test.QuickCheck.label "prop_maybeSquareNumber" $ Math.PerfectPower.maybeSquareNumber (Math.Power.square i) == Just (abs i)--		prop_notSquare i	= abs i > 0	==> Test.QuickCheck.label "prop_notSquare" . Data.Maybe.isNothing $ Math.PerfectPower.maybeSquareNumber (succ $ i ^ (10 {-promote rounding-error using big number-} :: Int))--		prop_rewriteRule i	= Test.QuickCheck.label "prop_rewriteRule" $ Math.PerfectPower.isPerfectPower i' == Math.PerfectPower.isPerfectPower (fromIntegral i' :: Int)	where-			i'	= abs i--		prop_isPerfectPower :: Integer -> Integer -> Test.QuickCheck.Property-		prop_isPerfectPower b e	= Test.QuickCheck.label "prop_isPerfectPower" . Math.PerfectPower.isPerfectPower $ b' ^ e'	where-			b'	= 2 + (b `mod` 10)-			e'	= 2 + (e `mod` 8)--
− src/Factory/Test/QuickCheck/Pi.hs
@@ -1,114 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	Copyright (C) 2011-2015 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.Pi".--}--module Factory.Test.QuickCheck.Pi(--- * Types--- ** Type-synonyms---	Testable,--- * Functions-	quickChecks-) where--import Prelude hiding ((<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.-import			Control.Applicative((<$>), (<*>))-import			Factory.Test.QuickCheck.Factorial()-import			Factory.Test.QuickCheck.SquareRoot()-import qualified	Factory.Math.Factorial					as Math.Factorial-import qualified	Factory.Math.Implementations.Factorial			as Math.Implementations.Factorial-import qualified	Factory.Math.Implementations.Pi.AGM.Algorithm		as Math.Implementations.Pi.AGM.Algorithm-import qualified	Factory.Math.Implementations.Pi.BBP.Algorithm		as Math.Implementations.Pi.BBP.Algorithm-import qualified	Factory.Math.Implementations.Pi.Borwein.Algorithm	as Math.Implementations.Pi.Borwein.Algorithm-import qualified	Factory.Math.Implementations.Pi.Ramanujan.Algorithm	as Math.Implementations.Pi.Ramanujan.Algorithm-import qualified	Factory.Math.Implementations.Pi.Spigot.Algorithm	as Math.Implementations.Pi.Spigot.Algorithm-import qualified	Factory.Math.Implementations.SquareRoot			as Math.Implementations.SquareRoot-import qualified	Factory.Math.Pi						as Math.Pi-import qualified	Factory.Math.Precision					as Math.Precision-import qualified	Factory.Math.SquareRoot					as Math.SquareRoot-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))--instance (-	Test.QuickCheck.Arbitrary	squareRootAlgorithm,-	Math.SquareRoot.Algorithmic	squareRootAlgorithm- ) => Test.QuickCheck.Arbitrary (Math.Implementations.Pi.AGM.Algorithm.Algorithm squareRootAlgorithm)	where-	arbitrary	= Math.Implementations.Pi.AGM.Algorithm.BrentSalamin <$> Test.QuickCheck.arbitrary--instance Test.QuickCheck.Arbitrary Math.Implementations.Pi.BBP.Algorithm.Algorithm	where-	arbitrary	= Test.QuickCheck.elements [Math.Implementations.Pi.BBP.Algorithm.Bellard, Math.Implementations.Pi.BBP.Algorithm.Base65536]--instance (-	Test.QuickCheck.Arbitrary	squareRootAlgorithm,-	Math.SquareRoot.Algorithmic	squareRootAlgorithm,-	Test.QuickCheck.Arbitrary	factorialAlgorithm,-	Math.Factorial.Algorithmic	factorialAlgorithm- ) => Test.QuickCheck.Arbitrary (Math.Implementations.Pi.Borwein.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)	where-	arbitrary	= Test.QuickCheck.oneof [-		Math.Implementations.Pi.Borwein.Algorithm.Borwein1993 <$> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary-	 ]--instance (-	Test.QuickCheck.Arbitrary	squareRootAlgorithm,-	Math.SquareRoot.Algorithmic	squareRootAlgorithm,-	Test.QuickCheck.Arbitrary	factorialAlgorithm,-	Math.Factorial.Algorithmic	factorialAlgorithm- ) => Test.QuickCheck.Arbitrary (Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm squareRootAlgorithm factorialAlgorithm)	where-	arbitrary	= Test.QuickCheck.oneof [-		Math.Implementations.Pi.Ramanujan.Algorithm.Classic <$> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary,-		Math.Implementations.Pi.Ramanujan.Algorithm.Chudnovsky <$> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary-	 ]--instance Test.QuickCheck.Arbitrary Math.Implementations.Pi.Spigot.Algorithm.Algorithm	where-	arbitrary	= Test.QuickCheck.elements [Math.Implementations.Pi.Spigot.Algorithm.RabinowitzWagon, Math.Implementations.Pi.Spigot.Algorithm.Gosper]--instance (-	Test.QuickCheck.Arbitrary agm,-	Test.QuickCheck.Arbitrary bbp,-	Test.QuickCheck.Arbitrary borwein,-	Test.QuickCheck.Arbitrary ramanujan,-	Test.QuickCheck.Arbitrary spigot- ) => Test.QuickCheck.Arbitrary (Math.Pi.Category agm bbp borwein ramanujan spigot)	where-	arbitrary	= Test.QuickCheck.oneof [-		Math.Pi.AGM <$> Test.QuickCheck.arbitrary,-		Math.Pi.BBP <$> Test.QuickCheck.arbitrary,-		Math.Pi.Borwein <$> Test.QuickCheck.arbitrary,-		Math.Pi.Ramanujan <$> Test.QuickCheck.arbitrary,-		Math.Pi.Spigot <$> Test.QuickCheck.arbitrary-	 ]--type Category	= Math.Pi.Category (-	Math.Implementations.Pi.AGM.Algorithm.Algorithm Math.Implementations.SquareRoot.Algorithm- ) Math.Implementations.Pi.BBP.Algorithm.Algorithm (-	Math.Implementations.Pi.Borwein.Algorithm.Algorithm Math.Implementations.SquareRoot.Algorithm Math.Implementations.Factorial.Algorithm- ) (-	Math.Implementations.Pi.Ramanujan.Algorithm.Algorithm Math.Implementations.SquareRoot.Algorithm Math.Implementations.Factorial.Algorithm- ) Math.Implementations.Pi.Spigot.Algorithm.Algorithm--type Testable	= Category -> Category -> Math.Precision.DecimalDigits -> Test.QuickCheck.Property---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks = Test.QuickCheck.quickCheck prop_consistency	where-	prop_consistency :: Testable-	prop_consistency l r decimalDigits	= l /= r	==> Test.QuickCheck.label "prop_consistency" $ Math.Pi.openI l decimalDigits' - Math.Pi.openI r decimalDigits' <= 1 {-rounding error-}	where-		decimalDigits'	= succ $ decimalDigits `mod` 250-
− src/Factory/Test/QuickCheck/Polynomial.hs
@@ -1,116 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Data.Polynomial".--}--module Factory.Test.QuickCheck.Polynomial(--- * Functions-	quickChecks-) where--import			Control.Arrow((***))-import			Factory.Data.Ring((=*=), (=+=), (=-=), (=^))-import qualified	Data.Numbers.Primes-import qualified	Factory.Data.Polynomial		as Data.Polynomial-import qualified	Factory.Data.QuotientRing	as Data.QuotientRing-import qualified	Factory.Data.Ring		as Data.Ring-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))--instance (-	Test.QuickCheck.Arbitrary	c,-	Integral			c,-	Test.QuickCheck.Arbitrary	e,-	Integral			e- ) => Test.QuickCheck.Arbitrary (Data.Polynomial.Polynomial c e)	where-	arbitrary	= (Data.Polynomial.mkPolynomial . map ((+ negate 4) . (`mod` 8) *** (`mod` 8))) `fmap` Test.QuickCheck.arbitrary---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks-	= Test.QuickCheck.quickCheck prop_congruence-	>> Test.QuickCheck.quickCheck `mapM_` [prop_quotRem, prop_degree, prop_ringNormalised, prop_quotientRingNormalised]-	>> Test.QuickCheck.quickCheck `mapM_` [prop_power, prop_perfectPower, prop_normalised]-	>> Test.QuickCheck.quickCheck prop_raiseModuloNormalised-	>> Test.QuickCheck.quickCheck `mapM_` [prop_integralDomain, prop_isDivisibleBy]-	where-		prop_congruence :: Int -> Test.QuickCheck.Property-		prop_congruence i	= Test.QuickCheck.label "prop_congruence" $ Data.Polynomial.areCongruentModulo (Data.Polynomial.mkLinear 1 (negate 1) =^ prime) (Data.Polynomial.mkPolynomial [(1, prime), (negate 1, 0)]) prime	where-			prime :: Integer-			prime	= Data.Numbers.Primes.primes !! mod i 100--		prop_quotRem, prop_degree, prop_ringNormalised, prop_quotientRingNormalised :: Data.Polynomial.Polynomial Integer Integer -> Data.Polynomial.Polynomial Integer Integer -> Test.QuickCheck.Property-		prop_quotRem numerator denominator	= denominator' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_quotRem" $ numerator' == denominator' =*= quotient =+= remainder	where-			numerator', denominator' :: Data.Polynomial.Polynomial Rational Integer-			numerator'	= Data.Polynomial.realCoefficientsToFrac numerator-			denominator'	= Data.Polynomial.realCoefficientsToFrac denominator--			(quotient, remainder)	= numerator' `Data.QuotientRing.quotRem'` denominator'--		prop_degree numerator denominator	= denominator' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_degree" $ remainder == Data.Polynomial.zero || Data.Polynomial.getDegree remainder < Data.Polynomial.getDegree denominator'	where-			numerator', denominator' :: Data.Polynomial.Polynomial Rational Integer-			numerator'	= Data.Polynomial.realCoefficientsToFrac numerator-			denominator'	= Data.Polynomial.realCoefficientsToFrac denominator--			remainder	= numerator' `Data.QuotientRing.rem'` denominator'--		prop_ringNormalised l r	= Test.QuickCheck.label "prop_ringNormalised" $ all Data.Polynomial.isNormalised [l =*= r, l =+= r, l =-= r]--		prop_quotientRingNormalised numerator denominator	= denominator' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_quotientRingNormalised" $ all Data.Polynomial.isNormalised [numerator' `Data.QuotientRing.quot'` denominator', numerator' `Data.QuotientRing.rem'` denominator']	where-			numerator', denominator' :: Data.Polynomial.Polynomial Rational Integer-			numerator'	= Data.Polynomial.realCoefficientsToFrac numerator-			denominator'	= Data.Polynomial.realCoefficientsToFrac denominator--		prop_power, prop_perfectPower, prop_normalised :: Data.Polynomial.Polynomial Integer Integer -> Int -> Test.QuickCheck.Property-		prop_power polynomial power	= Test.QuickCheck.label "prop_power" $ polynomial =^ power' == iterate (=*= polynomial) polynomial !! pred power'	where-			power' :: Int-			power'	= succ $ power `mod` 100--		prop_perfectPower polynomial power	= polynomial' /= Data.Polynomial.zero	==> Test.QuickCheck.label "prop_perfectPower" $ iterate (`Data.QuotientRing.quot'` polynomial') (polynomial' =^ power') !! pred power' == polynomial'	where-			polynomial' :: Data.Polynomial.Polynomial Rational Integer-			polynomial'	= Data.Polynomial.realCoefficientsToFrac polynomial--			power' :: Int-			power'	= succ $ power `mod` 100--		prop_normalised polynomial i	= Test.QuickCheck.label "prop_normalised" $ all Data.Polynomial.isNormalised [-			polynomial =^ power',-			polynomial `Data.Polynomial.mod'` modulus'-		 ] where-			power' :: Int-			power'	= succ $ i `mod` 100--			modulus' :: Integer-			modulus'	= succ $ fromIntegral i `mod` 100--		prop_raiseModuloNormalised :: Data.Polynomial.Polynomial Integer Integer -> Integer -> Integer -> Test.QuickCheck.Property-		prop_raiseModuloNormalised polynomial power modulus	= Test.QuickCheck.label "prop_raiseModuloNormalised" . Data.Polynomial.isNormalised $ Data.Polynomial.raiseModulo polynomial power' modulus'	where-			power', modulus' :: Integer-			power'		= succ $ power `mod` 100-			modulus'	= succ $ modulus `mod` 100--		prop_integralDomain, prop_isDivisibleBy :: [Data.Polynomial.Polynomial Integer Integer] -> Test.QuickCheck.Property-		prop_integralDomain polynomials	= Data.Polynomial.zero `notElem` polynomials	==> Test.QuickCheck.label "prop_integralDomain" $ Data.Ring.product' (recip 2) {-TODO-} 10 polynomials /= Data.Polynomial.zero--		prop_isDivisibleBy polynomials	= Test.QuickCheck.label "prop_isDivisibleBy" . all (Data.QuotientRing.isDivisibleBy (Data.Ring.product' (recip 2) {-TODO-} 10 polynomials')) $ filter (/= Data.Polynomial.zero) polynomials'	where-			polynomials' :: [Data.Polynomial.Polynomial Rational Integer]-			polynomials'	= map Data.Polynomial.realCoefficientsToFrac polynomials-
− src/Factory/Test/QuickCheck/Power.hs
@@ -1,45 +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 "Math.Power".--}--module Factory.Test.QuickCheck.Power(--- * Functions-	quickChecks-) where--import qualified	Data.List-import qualified	Factory.Math.Power	as Math.Power-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks = Test.QuickCheck.quickCheck prop_squaresFrom >> Test.QuickCheck.quickCheck prop_raiseModulo-	where-		prop_squaresFrom :: Integer -> Integer -> Test.QuickCheck.Property-		prop_squaresFrom from l	= Test.QuickCheck.label "prop_squaresFrom" . (\(x, y) -> y == Math.Power.square x) . Data.List.genericIndex (Math.Power.squaresFrom from) $ abs l--		prop_raiseModulo :: Integer -> Integer -> Integer -> Test.QuickCheck.Property-		prop_raiseModulo b e m	= m /= 0	==> Test.QuickCheck.label "prop_raiseModulo" $ Math.Power.raiseModulo b e' m == (b ^ e') `mod` m	where-			e' :: Integer-			e'	= abs e--
− src/Factory/Test/QuickCheck/Primality.hs
@@ -1,72 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.Implementations.Primality".--}--module Factory.Test.QuickCheck.Primality(--- * Functions-	quickChecks-) where--import			Factory.Test.QuickCheck.PrimeFactorisation()-import qualified	Data.List-import qualified	Data.Numbers.Primes-import qualified	Factory.Math.Implementations.Primality		as Math.Implementations.Primality-import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation-import qualified	Factory.Math.Primality				as Math.Primality-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))--instance Test.QuickCheck.Arbitrary factorisationAlgorithm => Test.QuickCheck.Arbitrary (Math.Implementations.Primality.Algorithm factorisationAlgorithm)	where-	arbitrary	= Test.QuickCheck.oneof [-		Math.Implementations.Primality.AKS `fmap` Test.QuickCheck.arbitrary,-		return {-to Gen-monad-} Math.Implementations.Primality.MillerRabin-	 ]---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks-	= Test.QuickCheck.quickCheck prop_prime-	>> Test.QuickCheck.quickCheck prop_composite-	>> Test.QuickCheck.quickCheck prop_consistency-	where-		prop_prime :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Test.QuickCheck.Property-		prop_prime primalityAlgorithm i	= Test.QuickCheck.label "prop_prime" $ Math.Primality.isPrime primalityAlgorithm prime	where-			normalise n-				| primalityAlgorithm == Math.Implementations.Primality.MillerRabin	= n `mod` 1000000	-- Limited by the efficiency of 'Data.Numbers.Primes.primes'.-				| otherwise								= n `mod` 59--			prime :: Integer-			prime	= Data.List.genericIndex Data.Numbers.Primes.primes $ normalise i--		prop_composite :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> [Integer] -> Test.QuickCheck.Property-		prop_composite primalityAlgorithm l	= length l > 1	==> Test.QuickCheck.label "prop_composite" . not $ Math.Primality.isPrime primalityAlgorithm composite	where-			normalise n-				| primalityAlgorithm == Math.Implementations.Primality.MillerRabin	= n `mod` 1000000-				| otherwise								= n `mod` 10--			composite :: Integer-			composite	= product . map (Data.List.genericIndex Data.Numbers.Primes.primes . normalise) $ take 8 l--		prop_consistency :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Test.QuickCheck.Property-		prop_consistency l r i	= l /= r	==> Test.QuickCheck.label "prop_consistency" $ Math.Primality.isPrime l i' == Math.Primality.isPrime r i'	where-			i'	= i `mod` 512-
− src/Factory/Test/QuickCheck/PrimeFactorisation.hs
@@ -1,94 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.PrimeFactorisation".--}--module Factory.Test.QuickCheck.PrimeFactorisation(--- * Functions-	quickChecks-) where--import qualified	Data.List-import qualified	Data.Numbers.Primes-import qualified	Factory.Data.PrimeFactors			as Data.PrimeFactors-import qualified	Factory.Data.Exponential			as Data.Exponential-import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation-import qualified	Factory.Math.MultiplicativeOrder		as Math.MultiplicativeOrder-import qualified	Factory.Math.PrimeFactorisation			as Math.PrimeFactorisation-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))--instance Test.QuickCheck.Arbitrary Math.Implementations.PrimeFactorisation.Algorithm	where-	arbitrary	= Test.QuickCheck.oneof [-		Test.QuickCheck.elements [-			Math.Implementations.PrimeFactorisation.TrialDivision,-			Math.Implementations.PrimeFactorisation.FermatsMethod-		]-	 ]---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	=-	Test.QuickCheck.quickCheck prop_consistency-	>> Test.QuickCheck.quickCheck `mapM_` [prop_primeFactors, prop_smoothness, prop_eulersTotientP, prop_eulersTotientInequality]-	>> Test.QuickCheck.quickCheck `mapM_` [prop_eulersTotient, prop_lagrange, prop_multiplicativeOrder, prop_perfectPower]-	where-		prop_consistency :: Integer -> Test.QuickCheck.Property-		prop_consistency i	= Test.QuickCheck.label "prop_consistency" $ (Math.PrimeFactorisation.primeFactors Math.Implementations.PrimeFactorisation.TrialDivision i' :: Data.PrimeFactors.Factors Integer Int) == Math.PrimeFactorisation.primeFactors Math.Implementations.PrimeFactorisation.FermatsMethod i'	where-			i' :: Integer-			i'	= succ $ i `mod` 1000000--		prop_primeFactors, prop_smoothness, prop_eulersTotientP, prop_eulersTotientInequality :: Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Test.QuickCheck.Property-		prop_primeFactors algorithm i	= Test.QuickCheck.label "prop_primeFactors" $ Data.PrimeFactors.product' (recip 2) {-TODO-} 10 (Math.PrimeFactorisation.primeFactors algorithm i') == i'	where-			i' :: Integer-			i'	= succ $ i `mod` 1000000--		prop_smoothness algorithm i	= Test.QuickCheck.label "prop_smoothness" $ (Math.PrimeFactorisation.smoothness algorithm !! (2 ^ i')) <= (2 :: Integer)	where-			i' :: Integer-			i'	= i `mod` 20--		prop_eulersTotientP algorithm i	= Test.QuickCheck.label "prop_eulersTotientP" $ Math.PrimeFactorisation.eulersTotient algorithm prime == pred prime	where-			prime :: Integer-			prime	= Data.List.genericIndex Data.Numbers.Primes.primes (i `mod` 10000)--		prop_eulersTotientInequality algorithm i	= i `notElem` [2, 6]	==> Test.QuickCheck.label "prop_eulersTotientInequality" $ Math.PrimeFactorisation.eulersTotient algorithm i' >= floor (sqrt $ fromIntegral i' :: Double)	where-			i'	= succ $ i `mod` 100000--		prop_eulersTotient, prop_lagrange, prop_multiplicativeOrder, prop_perfectPower :: Math.Implementations.PrimeFactorisation.Algorithm -> Integer -> Integer -> Test.QuickCheck.Property-		prop_eulersTotient algorithm i power	= Test.QuickCheck.label "prop_eulersTotient" $ Math.PrimeFactorisation.eulersTotient algorithm (base ^ power') == (base ^ pred power') * pred base	where-			base :: Integer-			base	= Data.List.genericIndex Data.Numbers.Primes.primes (i `mod` 8)--			power'	= succ $ power `mod` 5--		prop_lagrange algorithm base modulus	= gcd base modulus' == 1	==> Test.QuickCheck.label "prop_lagrange" $ (Math.PrimeFactorisation.eulersTotient algorithm modulus' `rem` Math.MultiplicativeOrder.multiplicativeOrder algorithm base modulus') == 0	where-			modulus' :: Integer-			modulus'	= 2 + abs modulus--		prop_multiplicativeOrder algorithm base modulus	= gcd base modulus' == 1	==> Test.QuickCheck.label "prop_multiplicativeOrder" $ (-			base ^ Math.MultiplicativeOrder.multiplicativeOrder algorithm base modulus'-		 ) `mod` modulus' == 1	where-			modulus' :: Integer-			modulus'	= 2 + abs modulus--		prop_perfectPower algorithm b e	= Test.QuickCheck.label "prop_perfectPower" $ foldr1 gcd (-			map Data.Exponential.getExponent . Math.PrimeFactorisation.primeFactors algorithm $ (2 + b `mod` 10 :: Integer) ^ (2 + e `mod` 5)-		 ) > 1
− src/Factory/Test/QuickCheck/Primes.hs
@@ -1,99 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.Implementations.Primes".--}--module Factory.Test.QuickCheck.Primes(--- * Constants---	defaultAlgorithm,--- * Functions-	quickChecks,---	isPrime,-	upperBound-) where--import qualified	Control.DeepSeq-import qualified	Data.Set-import qualified	Factory.Data.PrimeWheel				as Data.PrimeWheel-import qualified	Factory.Math.Implementations.Primality		as Math.Implementations.Primality-import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation-import qualified	Factory.Math.Implementations.Primes.Algorithm	as Math.Implementations.Primes.Algorithm-import qualified	Factory.Math.Primality				as Math.Primality-import qualified	Factory.Math.Primes				as Math.Primes-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))-import qualified	ToolShed.Defaultable--instance Test.QuickCheck.Arbitrary Math.Implementations.Primes.Algorithm.Algorithm	where-	arbitrary	= Test.QuickCheck.oneof [-		return {-to Gen-monad-} Math.Implementations.Primes.Algorithm.TurnersSieve,-		(Math.Implementations.Primes.Algorithm.TrialDivision . (`mod` 10)) `fmap` Test.QuickCheck.arbitrary,-		(Math.Implementations.Primes.Algorithm.SieveOfEratosthenes . (`mod` 10)) `fmap` Test.QuickCheck.arbitrary-	 ]--isPrime :: (Control.DeepSeq.NFData i, Integral i, Show i) => i -> Bool-isPrime	= Math.Primality.isPrime primalityAlgorithm	where-	primalityAlgorithm :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm-	primalityAlgorithm	= ToolShed.Defaultable.defaultValue--upperBound :: Math.Implementations.Primes.Algorithm.Algorithm -> Int -> Int-upperBound algorithm i	= mod i $ if algorithm == Math.Implementations.Primes.Algorithm.TurnersSieve-	then 8192-	else 65536--defaultAlgorithm :: Math.Implementations.Primes.Algorithm.Algorithm-defaultAlgorithm	= ToolShed.Defaultable.defaultValue---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks =-	Test.QuickCheck.quickCheck `mapM_` [prop_isPrime, prop_isComposite]-	>> Test.QuickCheck.quickCheck prop_consistency-	>> Test.QuickCheck.quickCheck prop_rewriteRule-	>> Test.QuickCheck.quickCheck `mapM_` [prop_sieveOfAtkin, prop_sieveOfAtkinRewrite]-	where-		prop_isPrime, prop_isComposite :: Math.Implementations.Primes.Algorithm.Algorithm -> Int -> Test.QuickCheck.Property-		prop_isPrime algorithm i	= Test.QuickCheck.label "prop_isPrime" . all isPrime . takeWhile (<= upperBound algorithm i) $ (Math.Primes.primes algorithm :: [Int])-		prop_isComposite algorithm i	= Test.QuickCheck.label "prop_isComposite" . not . any isPrime . Data.Set.toList . Data.Set.difference (-			Data.Set.fromList [2 .. upperBound algorithm i]-		 ) . Data.Set.fromList . takeWhile (<= upperBound algorithm i) $ Math.Primes.primes algorithm--		prop_consistency :: Math.Implementations.Primes.Algorithm.Algorithm -> Math.Implementations.Primes.Algorithm.Algorithm -> Int -> Test.QuickCheck.Property-		prop_consistency l r i = l /= r	==> Test.QuickCheck.label "prop_consistency" . and . take (i `mod` 4096) $ zipWith (==) (Math.Primes.primes l) (Math.Primes.primes r :: [Int])--		prop_rewriteRule :: Data.PrimeWheel.NPrimes -> Int -> Test.QuickCheck.Property-		prop_rewriteRule wheelSize i	= Test.QuickCheck.label "prop_rewriteRule" $ toInteger (Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize') !! index :: Int) == (Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize') !! index :: Integer)	where-			wheelSize'	= wheelSize `mod` 8-			index		= i `mod` 131072--		prop_sieveOfAtkin, prop_sieveOfAtkinRewrite :: Int -> Test.QuickCheck.Property-		prop_sieveOfAtkin i	= Test.QuickCheck.label "prop_sieveOfAtkin" $ Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfAtkin prime) !! index == prime	where-			index	= i `mod` 131072--			prime :: Integer-			prime	= Math.Primes.primes defaultAlgorithm !! index--		prop_sieveOfAtkinRewrite i	= Test.QuickCheck.label "prop_sieveOfAtkin'" $ Math.Primes.primes (Math.Implementations.Primes.Algorithm.SieveOfAtkin $ fromIntegral prime) !! index == prime	where-			index	= i `mod` 131072--			prime :: Int-			prime	= Math.Primes.primes defaultAlgorithm !! index-
− src/Factory/Test/QuickCheck/Probability.hs
@@ -1,160 +0,0 @@-{--	Copyright (C) 2011-2013 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---	normalise,-	quickChecks-) where--import			Control.Arrow((&&&))-import qualified	Data.List-import qualified	Factory.Math.Probability	as Math.Probability-import qualified	Factory.Math.Statistics		as Math.Statistics-import			Factory.Test.QuickCheck.Factorial()-import qualified	System.Random-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))-import qualified	ToolShed.Data.Pair---- | Re-profile a distribution to achieve a standard mean & variance.-normalise :: (-	Eq				f,-	Floating			f,-	Math.Probability.Distribution	distribution- ) => distribution -> [f] -> [f]-normalise distribution-	| variance == 0	= error "Factory.Test.Quick.Probability.normalise:\tzero variance => can't stretch to one."-	| otherwise	= map $ (/ sqrt variance) . (+ negate mean)-	where-		(mean, variance)	= Math.Probability.getMean &&& Math.Probability.getVariance $ distribution---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= do-	randomGen	<- System.Random.getStdGen--	Test.QuickCheck.quickCheck (prop_logNormalDistributionEqual randomGen) >> (Test.QuickCheck.quickCheck . ($ randomGen)) `mapM_` [-		prop_logNormalDistribution,-		prop_logNormalDistribution',-		prop_normalDistribution,-		prop_uniformDistribution-	 ] >> (Test.QuickCheck.quickCheck . ($ randomGen)) `mapM_` [-		prop_exponentialDistribution,-		prop_exponentialDistribution',-		prop_poissonDistribution,-		prop_poissonDistribution',-		prop_shiftedGeometricDistribution,-		prop_shiftedGeometricDistribution'-	 ]-	where-		isWithinTolerance :: Double -> Double -> Bool-		isWithinTolerance i	= (< recip i) . abs--		prop_logNormalDistribution, prop_logNormalDistribution', prop_normalDistribution, prop_uniformDistribution :: System.Random.RandomGen randomGen => randomGen -> Double -> Double -> Test.QuickCheck.Property-		prop_logNormalDistribution randomGen location scale2	= scale2 /= 0 ==> Test.QuickCheck.label "prop_logNormalDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 1) . (-			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.-		 ) . (-			normalise distribution :: [Double] -> [Double]-		 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where-			maxParameter	= log . fromInteger $ Math.Probability.maxPreciseInteger (undefined :: Double)-			location'-				| location >= 0	= maxParameter `min` location-				| otherwise	= negate maxParameter `max` location--			distribution	= Math.Probability.LogNormalDistribution location' . min maxParameter $ abs scale2--		prop_logNormalDistribution' randomGen location scale2	= scale2 /= 0 ==> Test.QuickCheck.label "prop_logNormalDistribution'" . all (-			>= (0 :: Double)-		 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.LogNormalDistribution location' . min maxParameter $ abs scale2) randomGen	where-			maxParameter	= log . fromInteger $ Math.Probability.maxPreciseInteger (undefined :: Double)--			location'-				| location >= 0	= maxParameter `min` location-				| otherwise	= negate maxParameter `max` location---- The mean & standard-deviation are equal when scale^2 == ln 2, but this seems to break-down when the mean is close to zero.-		prop_logNormalDistributionEqual :: System.Random.RandomGen randomGen => randomGen -> Double -> Test.QuickCheck.Property-		prop_logNormalDistributionEqual randomGen location	= location' > 1 ==> Test.QuickCheck.label "prop_logNormalDistributionEqual" . (-			< (recip 1000000 :: Double)-		 ) . pred . abs . uncurry (/) . (-			Math.Statistics.getMean &&& Math.Statistics.getStandardDeviation-		 ) $ take 10000 (-			Math.Probability.generatePopulation (Math.Probability.LogNormalDistribution location' $ log 2) randomGen :: [Double]-		 ) where-			maxParameter	= log . fromInteger $ Math.Probability.maxPreciseInteger (undefined :: Double)--			location'-				| location >= 0	= maxParameter `min` location-				| otherwise	= negate maxParameter `max` location--		prop_normalDistribution randomGen mean variance	= variance /= 0 ==> Test.QuickCheck.label "prop_normalDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (-			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.-		 ) . (-			normalise distribution :: [Double] -> [Double]-		 ) . take 1000 $ Math.Probability.generatePopulation distribution randomGen	where-			distribution	= Math.Probability.NormalDistribution mean $ abs variance--		prop_uniformDistribution randomGen min' max'	= min' /= max' ==> Test.QuickCheck.label "prop_uniformDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (-			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.-		 ) . (-			normalise distribution :: [Double] -> [Double]-		 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where-			[min'', max'']	= Data.List.sort [min', max']-			distribution	= Math.Probability.UniformDistribution (min'', max'')--		prop_exponentialDistribution, prop_exponentialDistribution', prop_poissonDistribution, prop_poissonDistribution', prop_shiftedGeometricDistribution, prop_shiftedGeometricDistribution' :: System.Random.RandomGen randomGen => randomGen -> Double -> Test.QuickCheck.Property-		prop_exponentialDistribution randomGen lambda	= Test.QuickCheck.label "prop_exponentialDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (-			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.-		 ) . (-			normalise distribution :: [Double] -> [Double]-		 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where-			distribution	= Math.Probability.ExponentialDistribution . succ {-exclude zero-} $ abs lambda `max` 10 {-cap-}--		prop_exponentialDistribution' randomGen lambda	= lambda /= 0 ==> Test.QuickCheck.label "prop_exponentialDistribution'" . all (-			>= (0 :: Double)-		 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.ExponentialDistribution $ abs lambda) randomGen--		prop_poissonDistribution randomGen lambda	= Test.QuickCheck.label "prop_poissonDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (-			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.-		 ) . (-			normalise distribution :: [Double] -> [Double]-		 ) . take 1000 $ Math.Probability.generatePopulation distribution randomGen	where-			distribution	= Math.Probability.PoissonDistribution . succ {-exclude zero-} $ abs lambda `max` 10 {-cap-}--		prop_poissonDistribution' randomGen lambda	= lambda /= 0 ==> Test.QuickCheck.label "prop_poissonDistribution'" . all (-			>= (0 :: Double)-		 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.PoissonDistribution $ abs lambda) randomGen--		prop_shiftedGeometricDistribution randomGen probability	= probability' /= 1 ==> Test.QuickCheck.label "prop_shiftedGeometricDistribution" . uncurry (&&) . ToolShed.Data.Pair.mirror (isWithinTolerance 10) . (-			Math.Statistics.getMean &&& pred . Math.Statistics.getStandardDeviation	-- Both of which, having been normalised, should be zero.-		 ) . (-			normalise distribution :: [Double] -> [Double]-		 ) . take 10000 $ Math.Probability.generatePopulation distribution randomGen	where-			probability'	= recip . succ $ abs probability	-- Semi-closed unit-interval (0, 1].-			distribution	= Math.Probability.ShiftedGeometricDistribution probability'--		prop_shiftedGeometricDistribution' randomGen probability	= Test.QuickCheck.label "prop_shiftedGeometricDistribution'" . all (-			>= (1 :: Double)-		 ) . take 10 $ Math.Probability.generatePopulation (Math.Probability.ShiftedGeometricDistribution probability') randomGen	where-			probability'	= recip . succ $ abs probability	-- Semi-closed unit-interval (0, 1].-
− src/Factory/Test/QuickCheck/QuickChecks.hs
@@ -1,70 +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@]	Calls the /quickChecks/-functions for modules supporting this feature.--}--module Factory.Test.QuickCheck.QuickChecks(--- * Functions-	run-) where--import qualified	Control.Arrow-import qualified	Factory.Test.QuickCheck.ArithmeticGeometricMean-import qualified	Factory.Test.QuickCheck.Factorial-import qualified	Factory.Test.QuickCheck.Hyperoperation-import qualified	Factory.Test.QuickCheck.Interval-import qualified	Factory.Test.QuickCheck.MonicPolynomial-import qualified	Factory.Test.QuickCheck.PerfectPower-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.Primes-import qualified	Factory.Test.QuickCheck.Probability-import qualified	Factory.Test.QuickCheck.Radix-import qualified	Factory.Test.QuickCheck.SquareRoot-import qualified	Factory.Test.QuickCheck.Statistics-import qualified	Factory.Test.QuickCheck.Summation---- | Run the /quickChecks/-functions for modules supporting this feature.-run :: IO ()-run	= mapM_ (-	uncurry (>>) . Control.Arrow.first putStrLn- ) [-	("ArithmeticGeometricMean",	Factory.Test.QuickCheck.ArithmeticGeometricMean.quickChecks),-	("Factorial",			Factory.Test.QuickCheck.Factorial.quickChecks),-	("Hyperoperation",		Factory.Test.QuickCheck.Hyperoperation.quickChecks),-	("Interval",			Factory.Test.QuickCheck.Interval.quickChecks),-	("MonicPolynomial",		Factory.Test.QuickCheck.MonicPolynomial.quickChecks),-	("PerfectPower",		Factory.Test.QuickCheck.PerfectPower.quickChecks),-	("Pi",				Factory.Test.QuickCheck.Pi.quickChecks),-	("Polynomial",			Factory.Test.QuickCheck.Polynomial.quickChecks),-	("Power",			Factory.Test.QuickCheck.Power.quickChecks),-	("Primality",			Factory.Test.QuickCheck.Primality.quickChecks),-	("PrimeFactorisation",		Factory.Test.QuickCheck.PrimeFactorisation.quickChecks),-	("Primes",			Factory.Test.QuickCheck.Primes.quickChecks),-	("Probability",			Factory.Test.QuickCheck.Probability.quickChecks),-	("Radix",			Factory.Test.QuickCheck.Radix.quickChecks),-	("SquareRoot",			Factory.Test.QuickCheck.SquareRoot.quickChecks),-	("Statistics",			Factory.Test.QuickCheck.Statistics.quickChecks),-	("Summation",			Factory.Test.QuickCheck.Summation.quickChecks)- ]-
− src/Factory/Test/QuickCheck/Radix.hs
@@ -1,46 +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 "Math.Radix".--}--module Factory.Test.QuickCheck.Radix(--- * Types--- ** Type-synonyms---	Testable,--- * Functions-	quickChecks-) where--import qualified	Factory.Math.Radix	as Math.Radix-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))--type Testable	= (Int, Integer) -> Test.QuickCheck.Property---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_reversable, prop_digitalRoot]	where-	prop_reversable, prop_digitalRoot :: Testable-	prop_reversable (b, n)	= abs base > 1 ==> Test.QuickCheck.label "prop_reversable" $ Math.Radix.fromBase base (Math.Radix.toBase base n) == n	where-		base	= (b `mod` 73) - 36--	prop_digitalRoot (_, n)	= Test.QuickCheck.label "prop_digitalRoot" $ Math.Radix.digitalRoot n' == 9	where-		n'	= 9 * succ (abs n)-
− src/Factory/Test/QuickCheck/SquareRoot.hs
@@ -1,86 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{--	Copyright (C) 2011-2015 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@]	Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.Implementations.SquareRoot".--}--module Factory.Test.QuickCheck.SquareRoot(--- * Types--- ** Type-synonyms---	Testable,--- * Functions-	quickChecks-) where--import			Data.Ratio((%))-import qualified	Data.Ratio-import qualified	Factory.Math.Implementations.SquareRoot	as Math.Implementations.SquareRoot-import qualified	Factory.Math.Power			as Math.Power-import qualified	Factory.Math.Precision			as Math.Precision-import qualified	Factory.Math.SquareRoot			as Math.SquareRoot-import qualified	Test.QuickCheck--instance Test.QuickCheck.Arbitrary (Math.Implementations.SquareRoot.Algorithm)	where-	arbitrary	= Test.QuickCheck.oneof [-		Test.QuickCheck.elements [-			Math.Implementations.SquareRoot.BakhshaliApproximation,-			Math.Implementations.SquareRoot.ContinuedFraction,-			Math.Implementations.SquareRoot.HalleysMethod,-			Math.Implementations.SquareRoot.NewtonRaphsonIteration-		],-		Math.Implementations.SquareRoot.TaylorSeries `fmap` Test.QuickCheck.elements [2 .. 32]-	 ]--type Testable	= (Math.Implementations.SquareRoot.Algorithm, Math.Precision.DecimalDigits, Rational) -> Test.QuickCheck.Property---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_accuracy, prop_factorable, prop_perfectSquare]	where-	prop_accuracy, prop_factorable, prop_perfectSquare :: Testable-	prop_accuracy (algorithm, decimalDigits, operand)	= Test.QuickCheck.label "prop_accuracy" . (>= requiredDecimalDigits) . Math.SquareRoot.getAccuracy operand' $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand'	where-		requiredDecimalDigits :: Math.Precision.DecimalDigits-		requiredDecimalDigits	= succ $ decimalDigits `mod` 1024--		operand' :: Rational-		operand'	= abs operand--	prop_factorable (algorithm, decimalDigits, operand)	= Test.QuickCheck.label "prop_factorable" . (<= 5) . (-		* 10 ^ requiredDecimalDigits	-- Promote the relative error.-	 ) . abs $ 1 - (-		Math.SquareRoot.squareRoot algorithm requiredDecimalDigits (-			toRational $ Data.Ratio.numerator operand'-		) / Math.SquareRoot.squareRoot algorithm requiredDecimalDigits (-			toRational $ Data.Ratio.denominator operand'-		)-	 ) / Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand' where-		requiredDecimalDigits :: Math.Precision.DecimalDigits-		requiredDecimalDigits	= succ $ decimalDigits `mod` 1024--		operand' :: Rational-		operand'	= succ $ abs operand--	prop_perfectSquare (algorithm, decimalDigits, operand)	= Test.QuickCheck.label "prop_perfectSquare" . Math.SquareRoot.isPrecise perfectSquare $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits perfectSquare	where-		requiredDecimalDigits :: Math.Precision.DecimalDigits-		requiredDecimalDigits	= succ $ decimalDigits `mod` 32768--		operand', perfectSquare :: Rational-		operand'	= (abs (Data.Ratio.numerator operand) `min` (2 ^ (32 :: Int))) % (abs (Data.Ratio.denominator operand) `min` (2 ^ (32 :: Int)))	-- Avoid floating-point rounding-errors in 'Math.SquareRoot.rSqrt'.-		perfectSquare	= Math.Power.square operand'-
− src/Factory/Test/QuickCheck/Statistics.hs
@@ -1,112 +0,0 @@-{--	Copyright (C) 2011-2014 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.Statistics".--}--module Factory.Test.QuickCheck.Statistics(--- * Functions-	quickChecks-) where--import qualified	Data.Array-import qualified	Data.List-import qualified	Data.Map-import qualified	Data.Numbers.Primes-import qualified	Data.Set-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-import			Test.QuickCheck((==>))---- | Defines invariant properties.-quickChecks :: IO ()-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 `mapM_` [prop_zeroVariance, prop_zeroAverageAbsoluteDeviation]-	>> Test.QuickCheck.quickCheck `mapM_` [prop_balance, prop_varianceRelocated, prop_varianceScaled, prop_varianceOrder, prop_equivalence, prop_varianceOfArray, prop_varianceOfMap, prop_meanOfSet]-	>> Test.QuickCheck.quickCheck prop_weightedMeanRational-	>> Test.QuickCheck.quickCheck prop_weightedMeanInteger-	>> Test.QuickCheck.quickCheck prop_weightedMeanUniformDenominator- 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	= succ $ abs i--	prop_sum algorithm i	= Test.QuickCheck.label "prop_sum" $ sum (Math.Statistics.nCr algorithm n `map` [0 .. n]) == 2 ^ n	where-		n	= succ $ 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_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_nP1 i	= Test.QuickCheck.label "prop_nP1" $ Math.Statistics.nPr n 1 == n	where-		n	= succ $ abs i--	prop_zeroVariance, prop_zeroAverageAbsoluteDeviation :: Rational -> Test.QuickCheck.Property-	prop_zeroVariance x			= Test.QuickCheck.label "prop_zeroVariance" $ Math.Statistics.getVariance (replicate 32 x) == (0 :: Rational)-	prop_zeroAverageAbsoluteDeviation x	= Test.QuickCheck.label "zeroAverageAbsoluteDeviation" $ Math.Statistics.getAverageAbsoluteDeviation (replicate 32 x) == (0 :: Rational)--	prop_balance, prop_varianceRelocated, prop_varianceScaled, prop_varianceOrder, prop_equivalence, prop_varianceOfMap, prop_meanOfSet, prop_varianceOfArray :: [Integer] -> Test.QuickCheck.Property-	prop_balance l			= not (null l)	==> Test.QuickCheck.label "prop_balance" . (== 0) . abs . sum $ map (\i -> toRational i - Math.Statistics.getMean l) l-	prop_varianceRelocated l	= not (null l)	==> Test.QuickCheck.label "prop_varianceRelocated" $ (Math.Statistics.getVariance l :: Rational) == Math.Statistics.getVariance (map succ l)-	prop_varianceScaled l		= not (null l)	==> Test.QuickCheck.label "prop_varianceScaled" $ (4 * Math.Statistics.getVariance l :: 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) :: 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 :: Rational)-	prop_varianceOfArray l		= not (null l)	==> Test.QuickCheck.label "prop_varianceOfArray" $ Math.Statistics.getVariance (Data.Array.array (1, length l) $ zip [1 ..] l) == (Math.Statistics.getVariance l :: Rational)-	prop_varianceOfMap l		= not (null l)	==> Test.QuickCheck.label "prop_varianceOfMap" $ Math.Statistics.getVariance (Data.Map.fromList $ zip [0 :: Int ..] l) == (Math.Statistics.getVariance l :: Rational)-	prop_meanOfSet l		= not (null l')	==> Test.QuickCheck.label "prop_meanOfSet" $ Math.Statistics.getMean (Data.Set.fromList l') == (Math.Statistics.getMean l' :: Rational)	where-		l'	= Data.List.nub l--	prop_weightedMeanRational :: [(Rational, Rational)] -> Test.QuickCheck.Property-	prop_weightedMeanRational assoc	= (denominator /= 0) ==> Test.QuickCheck.label "prop_weightedMeanRational" $ Math.Statistics.getWeightedMean assoc == (-		sum (map (uncurry (*)) assoc) / denominator-	 ) where-		denominator	= sum $ map snd assoc---	prop_weightedMeanInteger :: [(Integer, Integer)] -> Test.QuickCheck.Property-	prop_weightedMeanInteger assoc	= (denominator /= 0) ==> Test.QuickCheck.label "prop_weightedMeanInteger" $ Math.Statistics.getWeightedMean assoc == (-		toRational (-			sum $ map (-				uncurry (*)-			) assoc-		) / toRational denominator-	 ) where-		denominator	= sum $ map snd assoc--	prop_weightedMeanUniformDenominator :: [Rational] -> Integer -> Test.QuickCheck.Property-	prop_weightedMeanUniformDenominator numerators i	= (not (null numerators) && i /= 0) ==> Test.QuickCheck.label "prop_weightedMeanUniformDenominator" $ Math.Statistics.getWeightedMean (-		zip numerators $ repeat i-	 ) == (-		Math.Statistics.getMean numerators :: Rational-	 )-
− src/Factory/Test/QuickCheck/Summation.hs
@@ -1,42 +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 "Math.Summation".--}--module Factory.Test.QuickCheck.Summation(--- * Functions-	quickChecks-) where--import qualified	Factory.Math.Summation	as Math.Summation-import qualified	Test.QuickCheck-import			Test.QuickCheck((==>))---- | Defines invariant properties.-quickChecks :: IO ()-quickChecks	= Test.QuickCheck.quickCheck `mapM_` [prop_sum, prop_sumR]	where-	prop_sum, prop_sumR :: Int -> [Rational] -> Test.QuickCheck.Property-	prop_sum chunkSize l	= not (null l)	==> Test.QuickCheck.label "prop_sum" $ Math.Summation.sum' chunkSize' l == sum l	where-		chunkSize'	= 2 + (chunkSize `mod` length l)--	prop_sumR chunkSize l	= not (null l)	==> Test.QuickCheck.label "prop_sumR" $ Math.Summation.sumR chunkSize' l == sum l	where-		chunkSize'	= 2 + (chunkSize `mod` length l)--
− src/Main.hs
@@ -1,241 +0,0 @@-{--	Copyright (C) 2011-2013 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@]--	* Contains the entry-point to the program.--	* Facilitates testing.--}--module Main(main) where--import qualified	Data.Map-import qualified	Data.List-import qualified	Data.Version-import qualified	Distribution.Package-import qualified	Distribution.Text-import qualified	Distribution.Version-import qualified	Factory.Math.Hyperoperation			as Math.Hyperoperation-import qualified	Factory.Math.Implementations.Factorial		as Math.Implementations.Factorial-import qualified	Factory.Math.Implementations.Primality		as Math.Implementations.Primality-import qualified	Factory.Math.Implementations.PrimeFactorisation	as Math.Implementations.PrimeFactorisation-import qualified	Factory.Math.Implementations.Primes.Algorithm	as Math.Implementations.Primes.Algorithm-import qualified	Factory.Math.Implementations.SquareRoot		as Math.Implementations.SquareRoot-import qualified	Factory.Math.Probability			as Math.Probability-import qualified	Factory.Test.CommandOptions			as Test.CommandOptions-import qualified	Factory.Test.Performance.Factorial		as Test.Performance.Factorial-import qualified	Factory.Test.Performance.Hyperoperation		as Test.Performance.Hyperoperation-import qualified	Factory.Test.Performance.Pi			as Test.Performance.Pi-import qualified	Factory.Test.Performance.Primality		as Test.Performance.Primality-import qualified	Factory.Test.Performance.PrimeFactorisation	as Test.Performance.PrimeFactorisation-import qualified	Factory.Test.Performance.Primes			as Test.Performance.Primes-import qualified	Factory.Test.Performance.SquareRoot		as Test.Performance.SquareRoot-import qualified	Factory.Test.Performance.Statistics		as Test.Performance.Statistics-import qualified	Factory.Test.QuickCheck.QuickChecks		as Test.QuickCheck.QuickChecks-import qualified	Paths_factory					as Paths	-- Either local stub, or package-instance autogenerated by 'Setup.hs build'.-import qualified	System.Console.GetOpt				as G-import qualified	System.Environment-import qualified	System.Exit-import qualified	System.IO-import qualified	System.IO.Error-import qualified	System.Random-import qualified	ToolShed.Defaultable---- Local convenience definitions.-type PrimalityAlgorithm		= Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm-type PiCategory			= Test.Performance.Pi.Category Math.Implementations.SquareRoot.Algorithm Math.Implementations.Factorial.Algorithm---- | Used to thread user-defined command-line options, though the list of functions which implement them.-type CommandLineAction	= Test.CommandOptions.CommandOptions -> IO Test.CommandOptions.CommandOptions	-- Supplied as the type-argument to 'G.OptDescr'.---- | On failure to parse the specified string, returns an explanatory error.-read' :: Read a => String -> String -> a-read' errorMessage s	= case reads s of-	[(x, "")]	-> x-	_		-> error $ errorMessage ++ show s---- | On failure to parse a command-line argument, returns an explanatory error.-readCommandArg :: Read a => String -> a-readCommandArg	= read' "Failed to parse command-line argument "---- | Parses the command-line arguments, to determine 'Test.CommandOptions.CommandOptions'.-main :: IO ()-main	= do-	System.IO.hClose System.IO.stdin	-- Nothing is read from standard input.--	progName	<- System.Environment.getProgName--	let-		usageMessage :: String-		usageMessage	= "Usage:\t" ++ G.usageInfo progName optDescrList--		optDescrList :: [G.OptDescr CommandLineAction]-		optDescrList	= [---				 String	[String]					(G.ArgDescr CommandLineAction)												String-			G.Option "?"	["help"]					(G.NoArg $ const printUsage)												"Display this help-text & then exit.",-			G.Option ""	["verbose"]					(G.NoArg $ return {-to IO-monad-} . Test.CommandOptions.setVerbose)							("Provide additional information where available; default '" ++ show (Test.CommandOptions.verbose ToolShed.Defaultable.defaultValue) ++ "'."),-			G.Option ""	["version"]					(G.NoArg $ const printVersion)												"Print version-information & then exit.",-			G.Option "q"	["runQuickChecks"]				(G.NoArg $ const runQuickChecks)											"Run Quick-checks using arbitrary data & then exit.",-			G.Option ""	["carmichaelNumbersPerformance"]		(carmichaelNumbersPerformance `G.ReqArg` "(Math.Implementations.Primality.Algorithm, Int)")				"Test the performance of 'Math.Primality.carmichaelNumbers'.",-			G.Option ""	["factorialPerformance"]			(factorialPerformance `G.ReqArg` "(Math.Implementations.Factorial.Algorithm, Integer)")					"Test the performance of 'Math.Factorial.factorial'.",-			G.Option ""	["factorialPerformanceGraph"]			(factorialPerformanceGraph `G.ReqArg` "Math.Implementations.Factorial.Algorithm")					"Test the performance of 'Math.Factorial.factorial', with an exponentially increasing operand.",-			G.Option ""	["factorialPerformanceGraphControl"]		(G.NoArg factorialPerformanceGraphControl)										"Test the performance of a naive factorial-implementation, with an exponentially increasing operand.",-			G.Option ""	["hyperoperationPerformance"]			(hyperoperationPerformance `G.ReqArg` "(Integer, Math.Hyperoperation.Base, Math.Hyperoperation.HyperExponent)")		"Test the performance of 'Math.Hyperoperation.hyperoperation', against the specified rank, base and hyper-exponent.",-			G.Option ""	["hyperoperationPerformanceGraphRank"]		(hyperoperationPerformanceGraphRank `G.ReqArg` "(Math.Hyperoperation.Base, Math.Hyperoperation.HyperExponent)")		"Test the performance of 'Math.Hyperoperation.hyperoperation', for the specified base and hyper-exponent, and a linearly increasing rank.",-			G.Option ""	["hyperoperationPerformanceGraphExponent"]	(hyperoperationPerformanceGraphExponent `G.ReqArg` "(Integer, Math.Hyperoperation.Base)")				"Test the performance of 'Math.Hyperoperation.hyperoperation', for the specified rank and base, and a linearly increasing hyper-exponent.",-			G.Option ""	["isPrimePerformance"]				(isPrimePerformance `G.ReqArg` "(Math.Implementations.Primality.Algorithm, Integer)")					"Test the performance of 'Math.Primality.isPrime'.",-			G.Option ""	["isPrimePerformanceGraph"]			(isPrimePerformanceGraph `G.ReqArg` "Math.Implementations.Primality.Algorithm")						"Test the performance of 'Math.Primality.isPrime', against the prime-indexed Fibonacci-numbers.",-			G.Option ""	["mersenneNumbersPerformance"]			(mersenneNumbersPerformance `G.ReqArg` "(Math.Implementations.Primes.Algorithm.Algorithm, Int)")			"Test the performance of 'Math.Primes.mersenneNumbers'.",-			G.Option ""	["factorialPerformance"]			(factorialPerformance `G.ReqArg` "(Math.Implementations.Factorial.Algorithm, Integer)")					"Test the performance of 'Math.Factorial.factorial'.",-			G.Option ""	["nCrPerformance"]				(nCrPerformance `G.ReqArg` "(Math.Implementations.Factorial.Algorithm, Integer, Integer)")				"Test the performance of 'Math.Factorial.factorial'.",-			G.Option ""	["piPerformance"]				(piPerformance `G.ReqArg` "(Math.Pi.Category, Math.Precision.DecimalDigits)")						"Test the performance of 'Math.Pi.openI'.",-			G.Option ""	["piPerformanceGraph"]				(piPerformanceGraph `G.ReqArg` "(Math.Pi.Category, Double, Math.Precision.DecimalDigits)")				"Test the performance of 'Math.Pi.openI', with an exponential precision-requirement (of the specified exponent), up to the specified limit.",-			G.Option ""	["plotDiscreteDistribution"]			(plotDiscreteDistribution `G.ReqArg` "(Int, Math.Probability.DiscreteDistribution)")					"Plot the Probability Mass function for the specified discrete distribution.",-			G.Option ""	["primeFactorsPerformance"]			(primeFactorsPerformance `G.ReqArg` "(Math.Implementations.PrimeFactorisation.Algorithm, Integer)")			"Test the performance of 'Math.PrimeFactorisation.primeFactors'.",-			G.Option ""	["primeFactorsPerformanceGraph"]		(primeFactorsPerformanceGraph `G.ReqArg` "(Math.Implementations.PrimeFactorisation.Algorithm, Int)")			"Test the performance of 'Math.PrimeFactorisation.primeFactors', on the specified number of odd integers from the Fibonacci-sequence.",-			G.Option ""	["primesPerformance"]				(primesPerformance `G.ReqArg` "(Math.Implementations.Primes.Algorithm.Algorithm, Int)")					"Test the performance of 'Math.Primes.primes'.",-			G.Option ""	["squareRootPerformance"]			(squareRootPerformance `G.ReqArg` "(Math.Implementations.SquareRoot.Algorithm, Rational, DecimalDigits)")	"Test the performance of 'Math.SquareRoot.squareRoot'.",-			G.Option ""	["squareRootPerformanceGraph"]			(squareRootPerformanceGraph `G.ReqArg` "(Math.Implementations.SquareRoot.Algorithm, Rational)")		"Test the performance of 'Math.SquareRoot.squareRoot', with an exponentially increasing precision-requirement."-		 ] where-			printVersion, printUsage, runQuickChecks :: IO Test.CommandOptions.CommandOptions-			printVersion	= System.IO.hPutStrLn System.IO.stderr (Distribution.Text.display packageIdentifier ++ "\n\nCopyright (C) 2011-2015 " ++ author ++ ".\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it under certain conditions.\n\nWritten by " ++ author ++ ".")	>> System.Exit.exitWith System.Exit.ExitSuccess	where-				packageIdentifier :: Distribution.Package.PackageIdentifier-				packageIdentifier	= Distribution.Package.PackageIdentifier {-					Distribution.Package.pkgName	= Distribution.Package.PackageName progName,	-- CAVEAT: coincidentally.-					Distribution.Package.pkgVersion	= Distribution.Version.Version (Data.Version.versionBranch Paths.version) []-				}--				author :: String-				author	= "Dr. Alistair Ward"--			printUsage	= System.IO.hPutStrLn System.IO.stderr usageMessage	>> System.Exit.exitWith System.Exit.ExitSuccess--			runQuickChecks	= Test.QuickCheck.QuickChecks.run			>> System.Exit.exitWith System.Exit.ExitSuccess--			factorialPerformanceGraphControl :: Test.CommandOptions.CommandOptions -> IO Test.CommandOptions.CommandOptions-			factorialPerformanceGraphControl commandOptions	= Test.Performance.Factorial.factorialPerformanceGraphControl (Test.CommandOptions.verbose commandOptions)	>> System.Exit.exitWith (System.Exit.ExitFailure 1)--			carmichaelNumbersPerformance, factorialPerformance, factorialPerformanceGraph, hyperoperationPerformance, hyperoperationPerformanceGraphRank, hyperoperationPerformanceGraphExponent, isPrimePerformance, isPrimePerformanceGraph, mersenneNumbersPerformance, piPerformance, piPerformanceGraph, plotDiscreteDistribution, primeFactorsPerformance, primesPerformance, squareRootPerformance, squareRootPerformanceGraph :: String -> CommandLineAction--			carmichaelNumbersPerformance arg _	= Test.Performance.Primality.carmichaelNumbersPerformance algorithm i >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm :: PrimalityAlgorithm-				(algorithm, i)	= readCommandArg arg--			factorialPerformance arg _	= Test.Performance.Factorial.factorialPerformance algorithm i >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm	:: Math.Implementations.Factorial.Algorithm-				i		:: Integer-				(algorithm, i)	= readCommandArg arg--			factorialPerformanceGraph arg commandOptions	= Test.Performance.Factorial.factorialPerformanceGraph (Test.CommandOptions.verbose commandOptions) (readCommandArg arg :: Math.Implementations.Factorial.Algorithm)	>> System.Exit.exitWith (System.Exit.ExitFailure 1)--			hyperoperationPerformance arg _	= Test.Performance.Hyperoperation.hyperoperationPerformance rank base hyperExponent >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				rank		:: Integer-				base		:: Math.Hyperoperation.Base-				hyperExponent	:: Math.Hyperoperation.HyperExponent-				(rank, base, hyperExponent)	= readCommandArg arg--			hyperoperationPerformanceGraphRank arg commandOptions	= Test.Performance.Hyperoperation.hyperoperationPerformanceGraphRank (Test.CommandOptions.verbose commandOptions) base hyperExponent >> System.Exit.exitWith (System.Exit.ExitFailure 1)	where-				base		:: Math.Hyperoperation.Base-				hyperExponent	:: Math.Hyperoperation.HyperExponent-				(base, hyperExponent)	= readCommandArg arg--			hyperoperationPerformanceGraphExponent arg commandOptions	= Test.Performance.Hyperoperation.hyperoperationPerformanceGraphExponent (Test.CommandOptions.verbose commandOptions) rank base >> System.Exit.exitWith (System.Exit.ExitFailure 1)	where-				rank	:: Integer-				base	:: Math.Hyperoperation.Base-				(rank, base)	= readCommandArg arg--			isPrimePerformance arg _	= Test.Performance.Primality.isPrimePerformance algorithm i >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm	:: PrimalityAlgorithm-				i		:: Integer-				(algorithm, i)	= readCommandArg arg--			isPrimePerformanceGraph arg _	= Test.Performance.Primality.isPrimePerformanceGraph (readCommandArg arg :: Math.Implementations.Primality.Algorithm Math.Implementations.PrimeFactorisation.Algorithm) >> System.Exit.exitWith (System.Exit.ExitFailure 1)--			mersenneNumbersPerformance arg _	= Test.Performance.Primes.mersenneNumbersPerformance algorithm i >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm :: Math.Implementations.Primes.Algorithm.Algorithm-				(algorithm, i)	= readCommandArg arg--			nCrPerformance arg _	= Test.Performance.Statistics.nCrPerformance algorithm n r >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm	:: Math.Implementations.Factorial.Algorithm-				n, r		:: Integer-				(algorithm, n, r)	= readCommandArg arg--			piPerformance arg _	= Test.Performance.Pi.piPerformance category decimalDigits >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				category :: PiCategory-				(category, decimalDigits)	= readCommandArg arg--			piPerformanceGraph arg commandOptions	= Test.Performance.Pi.piPerformanceGraph category factor maxDecimalDigits (Test.CommandOptions.verbose commandOptions) >> System.Exit.exitWith (System.Exit.ExitFailure 1)	where-				category	:: PiCategory-				factor		:: Double-				(category, factor, maxDecimalDigits)	= readCommandArg arg--			plotDiscreteDistribution arg _	= let-				distribution :: Math.Probability.DiscreteDistribution Double-				(n, distribution)	= readCommandArg arg-			 in do-				System.Random.getStdGen >>= print . Data.Map.toList . Data.Map.map ((/ (fromIntegral n :: Double)) . fromInteger) . Data.Map.fromListWith (+) . (`zip` repeat 1) . (take n :: [Integer] -> [Integer]) . Math.Probability.generateDiscretePopulation distribution--				System.Exit.exitWith System.Exit.ExitSuccess--			primeFactorsPerformance arg _	= Test.Performance.PrimeFactorisation.primeFactorsPerformance algorithm i >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm :: Math.Implementations.PrimeFactorisation.Algorithm-				(algorithm, i)	= readCommandArg arg--			primeFactorsPerformanceGraph arg _	= Test.Performance.PrimeFactorisation.primeFactorsPerformanceGraph algorithm index >> System.Exit.exitWith (System.Exit.ExitFailure 1)	where-				algorithm :: Math.Implementations.PrimeFactorisation.Algorithm-				(algorithm, index)	= readCommandArg arg--			primesPerformance arg _	= (-				(-{--	Hard-code specific algorithms, so the simplifier triggers rewrite-rules in "Math.Implementations.Primes",-	ready for run-time definitions of 'algorithm' to exploit as appropriate.-	CAVEAT: fragile.--}-					case algorithm of-						Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize	-> Test.Performance.Primes.primesPerformance $ Math.Implementations.Primes.Algorithm.SieveOfEratosthenes wheelSize-						Math.Implementations.Primes.Algorithm.SieveOfAtkin maxPrime		-> Test.Performance.Primes.primesPerformance $ Math.Implementations.Primes.Algorithm.SieveOfAtkin maxPrime-						_									-> Test.Performance.Primes.primesPerformance algorithm-				) index :: IO (-					Double,---					Integer-					Int	-- Exploits rewrite-rules in "Math.Implementations.Primes.*".-				)-			 ) >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm :: Math.Implementations.Primes.Algorithm.Algorithm-				(algorithm, index)	= readCommandArg arg--			squareRootPerformance arg _	= Test.Performance.SquareRoot.squareRootPerformance algorithm operand decimalDigits >>= print >> System.Exit.exitWith System.Exit.ExitSuccess	where-				algorithm	:: Math.Implementations.SquareRoot.Algorithm-				operand		:: Rational-				(algorithm, operand, decimalDigits)	= readCommandArg arg--			squareRootPerformanceGraph arg _	= Test.Performance.SquareRoot.squareRootPerformanceGraph algorithm operand >> System.Exit.exitWith (System.Exit.ExitFailure 1)	where-				algorithm	:: Math.Implementations.SquareRoot.Algorithm-				operand		:: Rational-				(algorithm, operand)	= readCommandArg arg--	args	<- System.Environment.getArgs----	G.getOpt :: G.ArgOrder CommandLineAction -> [G.OptDescr Action] -> [String] -> ([Action], [String], [String])-	case G.getOpt G.RequireOrder optDescrList args of-		(commandLineActions, _, [])	-> Data.List.foldl' (>>=) (return {-to IO-monad-} ToolShed.Defaultable.defaultValue) commandLineActions	>> System.Exit.exitWith System.Exit.ExitSuccess-		(_, _, errors)			-> System.IO.Error.ioError . System.IO.Error.userError $ concat errors ++ usageMessage	-- Throw.-