arithmoi 0.10.0.0 → 0.11.0.0
raw patch · 114 files changed
+3695/−3937 lines, 114 filesdep +chimeradep +integer-rootsdep +moddep −ghc-primdep ~basedep ~containersdep ~semiringssetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: chimera, integer-roots, mod, quickcheck-classes, tasty-rerun
Dependencies removed: ghc-prim
Dependency ranges changed: base, containers, semirings
API changes (from Hackage documentation)
- Math.NumberTheory.Moduli.Class: instance GHC.Classes.Eq (Math.NumberTheory.Moduli.Class.Mod m)
- Math.NumberTheory.Moduli.Class: instance GHC.Classes.Eq (Math.NumberTheory.Moduli.Class.MultMod m)
- Math.NumberTheory.Moduli.Class: instance GHC.Classes.Eq Math.NumberTheory.Moduli.Class.SomeMod
- Math.NumberTheory.Moduli.Class: instance GHC.Classes.Ord (Math.NumberTheory.Moduli.Class.Mod m)
- Math.NumberTheory.Moduli.Class: instance GHC.Classes.Ord (Math.NumberTheory.Moduli.Class.MultMod m)
- Math.NumberTheory.Moduli.Class: instance GHC.Classes.Ord Math.NumberTheory.Moduli.Class.SomeMod
- Math.NumberTheory.Moduli.Class: instance GHC.Enum.Enum (Math.NumberTheory.Moduli.Class.Mod m)
- Math.NumberTheory.Moduli.Class: instance GHC.Num.Num Math.NumberTheory.Moduli.Class.SomeMod
- Math.NumberTheory.Moduli.Class: instance GHC.Real.Fractional Math.NumberTheory.Moduli.Class.SomeMod
- Math.NumberTheory.Moduli.Class: instance GHC.Show.Show Math.NumberTheory.Moduli.Class.SomeMod
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Base.Monoid (Math.NumberTheory.Moduli.Class.MultMod m)
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Base.Semigroup (Math.NumberTheory.Moduli.Class.MultMod m)
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Enum.Bounded (Math.NumberTheory.Moduli.Class.Mod m)
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Enum.Bounded (Math.NumberTheory.Moduli.Class.MultMod m)
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Num.Num (Math.NumberTheory.Moduli.Class.Mod m)
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Real.Fractional (Math.NumberTheory.Moduli.Class.Mod m)
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Show.Show (Math.NumberTheory.Moduli.Class.Mod m)
- Math.NumberTheory.Moduli.Class: instance GHC.TypeNats.KnownNat m => GHC.Show.Show (Math.NumberTheory.Moduli.Class.MultMod m)
- Math.NumberTheory.Moduli.Jacobi: instance GHC.Base.Monoid Math.NumberTheory.Moduli.Jacobi.JacobiSymbol
- Math.NumberTheory.Moduli.Jacobi: instance GHC.Base.Semigroup Math.NumberTheory.Moduli.Jacobi.JacobiSymbol
- Math.NumberTheory.Moduli.Jacobi: instance GHC.Classes.Eq Math.NumberTheory.Moduli.Jacobi.JacobiSymbol
- Math.NumberTheory.Moduli.Jacobi: instance GHC.Classes.Ord Math.NumberTheory.Moduli.Jacobi.JacobiSymbol
- Math.NumberTheory.Moduli.Jacobi: instance GHC.Show.Show Math.NumberTheory.Moduli.Jacobi.JacobiSymbol
- Math.NumberTheory.Moduli.PrimitiveRoot: instance GHC.Classes.Eq (Math.NumberTheory.Moduli.PrimitiveRoot.PrimitiveRoot m)
- Math.NumberTheory.Moduli.PrimitiveRoot: instance GHC.TypeNats.KnownNat m => GHC.Show.Show (Math.NumberTheory.Moduli.PrimitiveRoot.PrimitiveRoot m)
- Math.NumberTheory.Primes.Counting: nthPrimeMaxArg :: Integer
- Math.NumberTheory.Primes.Factorisation: curveFactorisation :: forall g. Maybe Integer -> (Integer -> Bool) -> (Integer -> g -> (Integer, g)) -> g -> Maybe Int -> Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation: defaultStdGenFactorisation :: StdGen -> Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation: defaultStdGenFactorisation' :: StdGen -> Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation: factorise :: Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation: factorise' :: Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation: montgomeryFactorisation :: KnownNat n => Word -> Word -> Mod n -> Maybe Integer
- Math.NumberTheory.Primes.Factorisation: smallFactors :: Integer -> ([(Integer, Word)], Maybe Integer)
- Math.NumberTheory.Primes.Factorisation: stdGenFactorisation :: Maybe Integer -> StdGen -> Maybe Int -> Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation: stepFactorisation :: Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation: trialDivisionTo :: Integer -> Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation.Certified: certificateFactorisation :: Integer -> [((Integer, Word), PrimalityProof)]
- Math.NumberTheory.Primes.Factorisation.Certified: certifiedFactorisation :: Integer -> [(Integer, Word)]
- Math.NumberTheory.Primes.Factorisation.Certified: provenFactorisation :: Integer -> [((Integer, Word), PrimalityProof)]
- Math.NumberTheory.Primes.Sieve: data PrimeSieve
- Math.NumberTheory.Primes.Sieve: primeList :: forall a. Integral a => PrimeSieve -> [Prime a]
- Math.NumberTheory.Primes.Sieve: primeSieve :: Integer -> PrimeSieve
- Math.NumberTheory.Primes.Sieve: primes :: Integral a => [Prime a]
- Math.NumberTheory.Primes.Sieve: psieveFrom :: Integer -> [PrimeSieve]
- Math.NumberTheory.Primes.Sieve: psieveList :: [PrimeSieve]
- Math.NumberTheory.Primes.Sieve: sieveFrom :: Integer -> [Prime Integer]
- Math.NumberTheory.Primes.Small: smallPrimes :: Vector Word16
- Math.NumberTheory.Primes.Testing.Certificates: Assumption :: Integer -> PrimalityArgument
- Math.NumberTheory.Primes.Testing.Certificates: Belief :: Integer -> CompositenessArgument
- Math.NumberTheory.Primes.Testing.Certificates: Composite :: !CompositenessProof -> Certificate
- Math.NumberTheory.Primes.Testing.Certificates: Division :: Integer -> PrimalityArgument
- Math.NumberTheory.Primes.Testing.Certificates: Divisors :: Integer -> CompositenessArgument
- Math.NumberTheory.Primes.Testing.Certificates: Fermat :: Integer -> CompositenessArgument
- Math.NumberTheory.Primes.Testing.Certificates: Lucas :: Integer -> CompositenessArgument
- Math.NumberTheory.Primes.Testing.Certificates: Obvious :: Integer -> PrimalityArgument
- Math.NumberTheory.Primes.Testing.Certificates: Pock :: Integer -> Integer -> [(Integer, Word, Integer, PrimalityArgument)] -> PrimalityArgument
- Math.NumberTheory.Primes.Testing.Certificates: Prime :: !PrimalityProof -> Certificate
- Math.NumberTheory.Primes.Testing.Certificates: [aprime, alimit] :: PrimalityArgument -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: [aprime] :: PrimalityArgument -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: [compo, fermatBase] :: CompositenessArgument -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: [compo, firstDivisor, secondDivisor] :: CompositenessArgument -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: [compo] :: CompositenessArgument -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: [factorList] :: PrimalityArgument -> [(Integer, Word, Integer, PrimalityArgument)]
- Math.NumberTheory.Primes.Testing.Certificates: [largeFactor, smallFactor] :: PrimalityArgument -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: argueCertificate :: Certificate -> Either CompositenessArgument PrimalityArgument
- Math.NumberTheory.Primes.Testing.Certificates: argueCompositeness :: CompositenessProof -> CompositenessArgument
- Math.NumberTheory.Primes.Testing.Certificates: arguePrimality :: PrimalityProof -> PrimalityArgument
- Math.NumberTheory.Primes.Testing.Certificates: certify :: Integer -> Certificate
- Math.NumberTheory.Primes.Testing.Certificates: checkCertificate :: Certificate -> Bool
- Math.NumberTheory.Primes.Testing.Certificates: checkCompositenessProof :: CompositenessProof -> Bool
- Math.NumberTheory.Primes.Testing.Certificates: checkPrimalityProof :: PrimalityProof -> Bool
- Math.NumberTheory.Primes.Testing.Certificates: composite :: CompositenessProof -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: cprime :: PrimalityProof -> Integer
- Math.NumberTheory.Primes.Testing.Certificates: data Certificate
- Math.NumberTheory.Primes.Testing.Certificates: data CompositenessArgument
- Math.NumberTheory.Primes.Testing.Certificates: data CompositenessProof
- Math.NumberTheory.Primes.Testing.Certificates: data PrimalityArgument
- Math.NumberTheory.Primes.Testing.Certificates: data PrimalityProof
- Math.NumberTheory.Primes.Testing.Certificates: verifyCompositenessArgument :: CompositenessArgument -> Maybe CompositenessProof
- Math.NumberTheory.Primes.Testing.Certificates: verifyPrimalityArgument :: PrimalityArgument -> Maybe PrimalityProof
- Math.NumberTheory.SmoothNumbers: fromSet :: (Eq a, GcdDomain a) => Set a -> Maybe (SmoothBasis a)
- Math.NumberTheory.SmoothNumbers: fromSmoothUpperBound :: (Integral a, Enum (Prime a), Bits a, UniqueFactorisation a) => a -> Maybe (SmoothBasis a)
- Math.NumberTheory.SmoothNumbers: instance GHC.Classes.Eq a => GHC.Classes.Eq (Math.NumberTheory.SmoothNumbers.SmoothBasis a)
- Math.NumberTheory.SmoothNumbers: smoothOverInRange :: (Ord a, Num a) => SmoothBasis a -> a -> a -> [a]
- Math.NumberTheory.SmoothNumbers: smoothOverInRangeBF :: (Eq a, Enum a, GcdDomain a) => SmoothBasis a -> a -> a -> [a]
+ Math.NumberTheory.ArithmeticFunctions: divisorsTo :: (UniqueFactorisation n, Integral n) => n -> n -> Set n
+ Math.NumberTheory.ArithmeticFunctions: divisorsToA :: (UniqueFactorisation n, Integral n) => n -> ArithmeticFunction n (Set n)
+ Math.NumberTheory.ArithmeticFunctions.Inverse: inverseJordan :: (Semiring b, Integral a, Euclidean a, UniqueFactorisation a) => Word -> (a -> b) -> a -> b
+ Math.NumberTheory.ArithmeticFunctions.Inverse: inverseSigmaK :: (Semiring b, Euclidean a, UniqueFactorisation a, Integral a, Enum (Prime a), Bits a) => Word -> (a -> b) -> a -> b
+ Math.NumberTheory.DirichletCharacters: RootOfUnity :: Rational -> RootOfUnity
+ Math.NumberTheory.DirichletCharacters: [WithNat] :: KnownNat m => a m -> WithNat a
+ Math.NumberTheory.DirichletCharacters: [fromRootOfUnity] :: RootOfUnity -> Rational
+ Math.NumberTheory.DirichletCharacters: allChars :: forall n. KnownNat n => [DirichletCharacter n]
+ Math.NumberTheory.DirichletCharacters: characterNumber :: DirichletCharacter n -> Integer
+ Math.NumberTheory.DirichletCharacters: data DirichletCharacter (n :: Nat)
+ Math.NumberTheory.DirichletCharacters: data PrimitiveCharacter n
+ Math.NumberTheory.DirichletCharacters: data RealCharacter n
+ Math.NumberTheory.DirichletCharacters: data WithNat (a :: Nat -> Type)
+ Math.NumberTheory.DirichletCharacters: eval :: DirichletCharacter n -> MultMod n -> RootOfUnity
+ Math.NumberTheory.DirichletCharacters: evalAll :: forall n. KnownNat n => DirichletCharacter n -> Vector (OrZero RootOfUnity)
+ Math.NumberTheory.DirichletCharacters: evalGeneral :: KnownNat n => DirichletCharacter n -> Mod n -> OrZero RootOfUnity
+ Math.NumberTheory.DirichletCharacters: fromTable :: forall n. KnownNat n => Vector (OrZero RootOfUnity) -> Maybe (DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: getPrimitiveChar :: PrimitiveCharacter n -> DirichletCharacter n
+ Math.NumberTheory.DirichletCharacters: getRealChar :: RealCharacter n -> DirichletCharacter n
+ Math.NumberTheory.DirichletCharacters: indexToChar :: forall n. KnownNat n => Natural -> DirichletCharacter n
+ Math.NumberTheory.DirichletCharacters: indicesToChars :: forall n f. (KnownNat n, Functor f) => f Natural -> f (DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: induced :: forall n d. (KnownNat d, KnownNat n) => DirichletCharacter d -> Maybe (DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: instance GHC.Base.Semigroup (Math.NumberTheory.DirichletCharacters.DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: instance GHC.Classes.Eq (Math.NumberTheory.DirichletCharacters.DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: instance GHC.Classes.Eq (Math.NumberTheory.DirichletCharacters.PrimitiveCharacter n)
+ Math.NumberTheory.DirichletCharacters: instance GHC.Classes.Eq (Math.NumberTheory.DirichletCharacters.RealCharacter n)
+ Math.NumberTheory.DirichletCharacters: instance GHC.Classes.Eq Math.NumberTheory.DirichletCharacters.DirichletFactor
+ Math.NumberTheory.DirichletCharacters: instance GHC.TypeNats.KnownNat n => GHC.Base.Monoid (Math.NumberTheory.DirichletCharacters.DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: instance GHC.TypeNats.KnownNat n => GHC.Enum.Bounded (Math.NumberTheory.DirichletCharacters.DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: instance GHC.TypeNats.KnownNat n => GHC.Enum.Enum (Math.NumberTheory.DirichletCharacters.DirichletCharacter n)
+ Math.NumberTheory.DirichletCharacters: isPrimitive :: DirichletCharacter n -> Maybe (PrimitiveCharacter n)
+ Math.NumberTheory.DirichletCharacters: isPrincipal :: DirichletCharacter n -> Bool
+ Math.NumberTheory.DirichletCharacters: isRealCharacter :: DirichletCharacter n -> Maybe (RealCharacter n)
+ Math.NumberTheory.DirichletCharacters: jacobiCharacter :: forall n. KnownNat n => Maybe (RealCharacter n)
+ Math.NumberTheory.DirichletCharacters: makePrimitive :: DirichletCharacter n -> WithNat PrimitiveCharacter
+ Math.NumberTheory.DirichletCharacters: newtype RootOfUnity
+ Math.NumberTheory.DirichletCharacters: orZeroToNum :: Num a => (b -> a) -> OrZero b -> a
+ Math.NumberTheory.DirichletCharacters: orderChar :: DirichletCharacter n -> Integer
+ Math.NumberTheory.DirichletCharacters: pattern NonZero :: a -> OrZero a
+ Math.NumberTheory.DirichletCharacters: pattern Zero :: OrZero a
+ Math.NumberTheory.DirichletCharacters: principalChar :: KnownNat n => DirichletCharacter n
+ Math.NumberTheory.DirichletCharacters: toComplex :: Floating a => RootOfUnity -> Complex a
+ Math.NumberTheory.DirichletCharacters: toRealFunction :: KnownNat n => RealCharacter n -> Mod n -> Int
+ Math.NumberTheory.DirichletCharacters: toRootOfUnity :: Rational -> RootOfUnity
+ Math.NumberTheory.DirichletCharacters: type OrZero a = Ap Maybe a
+ Math.NumberTheory.DirichletCharacters: validChar :: forall n. KnownNat n => DirichletCharacter n -> Bool
+ Math.NumberTheory.Moduli.Jacobi: symbolToNum :: Num a => JacobiSymbol -> a
+ Math.NumberTheory.Moduli.Multiplicative: data MultMod m
+ Math.NumberTheory.Moduli.Multiplicative: data PrimitiveRoot m
+ Math.NumberTheory.Moduli.Multiplicative: discreteLogarithm :: CyclicGroup Integer m -> PrimitiveRoot m -> MultMod m -> Natural
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.Classes.Eq (Math.NumberTheory.Moduli.Multiplicative.MultMod m)
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.Classes.Eq (Math.NumberTheory.Moduli.Multiplicative.PrimitiveRoot m)
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.Classes.Ord (Math.NumberTheory.Moduli.Multiplicative.MultMod m)
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.TypeNats.KnownNat m => GHC.Base.Monoid (Math.NumberTheory.Moduli.Multiplicative.MultMod m)
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.TypeNats.KnownNat m => GHC.Base.Semigroup (Math.NumberTheory.Moduli.Multiplicative.MultMod m)
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.TypeNats.KnownNat m => GHC.Enum.Bounded (Math.NumberTheory.Moduli.Multiplicative.MultMod m)
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.TypeNats.KnownNat m => GHC.Show.Show (Math.NumberTheory.Moduli.Multiplicative.MultMod m)
+ Math.NumberTheory.Moduli.Multiplicative: instance GHC.TypeNats.KnownNat m => GHC.Show.Show (Math.NumberTheory.Moduli.Multiplicative.PrimitiveRoot m)
+ Math.NumberTheory.Moduli.Multiplicative: invertGroup :: KnownNat m => MultMod m -> MultMod m
+ Math.NumberTheory.Moduli.Multiplicative: isMultElement :: KnownNat m => Mod m -> Maybe (MultMod m)
+ Math.NumberTheory.Moduli.Multiplicative: isPrimitiveRoot :: (Integral a, UniqueFactorisation a) => CyclicGroup a m -> Mod m -> Maybe (PrimitiveRoot m)
+ Math.NumberTheory.Moduli.Multiplicative: multElement :: MultMod m -> Mod m
+ Math.NumberTheory.Moduli.Multiplicative: unPrimitiveRoot :: PrimitiveRoot m -> MultMod m
+ Math.NumberTheory.Moduli.Sqrt: MinusOne :: JacobiSymbol
+ Math.NumberTheory.Moduli.Sqrt: One :: JacobiSymbol
+ Math.NumberTheory.Moduli.Sqrt: Zero :: JacobiSymbol
+ Math.NumberTheory.Moduli.Sqrt: data JacobiSymbol
+ Math.NumberTheory.Moduli.Sqrt: jacobi :: (Integral a, Bits a) => a -> a -> JacobiSymbol
+ Math.NumberTheory.Moduli.Sqrt: symbolToNum :: Num a => JacobiSymbol -> a
+ Math.NumberTheory.Prefactored: instance GHC.Classes.Eq a => GHC.Classes.Eq (Math.NumberTheory.Prefactored.Prefactored a)
+ Math.NumberTheory.Primes: instance GHC.Enum.Bounded (Math.NumberTheory.Primes.Types.Prime GHC.Types.Int)
+ Math.NumberTheory.Primes: instance GHC.Enum.Bounded (Math.NumberTheory.Primes.Types.Prime GHC.Types.Word)
+ Math.NumberTheory.Recurrences.Bilinear: binomialDiagonal :: (Enum a, GcdDomain a) => a -> [a]
+ Math.NumberTheory.Recurrences.Bilinear: binomialFactors :: Word -> Word -> [(Prime Word, Word)]
+ Math.NumberTheory.Recurrences.Bilinear: binomialLine :: (Enum a, GcdDomain a) => a -> [a]
+ Math.NumberTheory.Recurrences.Bilinear: binomialRotated :: Semiring a => [[a]]
+ Math.NumberTheory.Recurrences.Linear: factorialFactors :: Word -> [(Prime Word, Word)]
+ Math.NumberTheory.SmoothNumbers: unSmoothBasis :: SmoothBasis a -> [a]
- Math.NumberTheory.ArithmeticFunctions: carmichaelA :: (UniqueFactorisation n, Integral n) => ArithmeticFunction n n
+ Math.NumberTheory.ArithmeticFunctions: carmichaelA :: Integral n => ArithmeticFunction n n
- Math.NumberTheory.ArithmeticFunctions: divisorsA :: (UniqueFactorisation n, Ord n) => ArithmeticFunction n (Set n)
+ Math.NumberTheory.ArithmeticFunctions: divisorsA :: (Ord n, Num n) => ArithmeticFunction n (Set n)
- Math.NumberTheory.ArithmeticFunctions: divisorsListA :: UniqueFactorisation n => ArithmeticFunction n [n]
+ Math.NumberTheory.ArithmeticFunctions: divisorsListA :: Num n => ArithmeticFunction n [n]
- Math.NumberTheory.ArithmeticFunctions: expMangoldtA :: UniqueFactorisation n => ArithmeticFunction n n
+ Math.NumberTheory.ArithmeticFunctions: expMangoldtA :: Num n => ArithmeticFunction n n
- Math.NumberTheory.ArithmeticFunctions: jordanA :: UniqueFactorisation n => Word -> ArithmeticFunction n n
+ Math.NumberTheory.ArithmeticFunctions: jordanA :: Num n => Word -> ArithmeticFunction n n
- Math.NumberTheory.ArithmeticFunctions: sigma :: (UniqueFactorisation n, Integral n) => Word -> n -> n
+ Math.NumberTheory.ArithmeticFunctions: sigma :: (UniqueFactorisation n, Integral n, Num a, GcdDomain a) => Word -> n -> a
- Math.NumberTheory.ArithmeticFunctions: sigmaA :: (UniqueFactorisation n, Integral n) => Word -> ArithmeticFunction n n
+ Math.NumberTheory.ArithmeticFunctions: sigmaA :: (Integral n, Num a, GcdDomain a) => Word -> ArithmeticFunction n a
- Math.NumberTheory.ArithmeticFunctions: totientA :: UniqueFactorisation n => ArithmeticFunction n n
+ Math.NumberTheory.ArithmeticFunctions: totientA :: Num n => ArithmeticFunction n n
- Math.NumberTheory.ArithmeticFunctions.Inverse: inverseTotient :: (Semiring b, Euclidean a, UniqueFactorisation a, Ord a) => (a -> b) -> a -> b
+ Math.NumberTheory.ArithmeticFunctions.Inverse: inverseTotient :: (Semiring b, Integral a, Euclidean a, UniqueFactorisation a) => (a -> b) -> a -> b
- Math.NumberTheory.Moduli.Chinese: chinese :: forall a. (Integral a, GcdDomain a, Euclidean a) => (a, a) -> (a, a) -> Maybe a
+ Math.NumberTheory.Moduli.Chinese: chinese :: forall a. (Eq a, Ring a, Euclidean a) => (a, a) -> (a, a) -> Maybe a
- Math.NumberTheory.Moduli.Chinese: chineseCoprime :: (Integral a, Euclidean a) => (a, a) -> (a, a) -> Maybe a
+ Math.NumberTheory.Moduli.Chinese: chineseCoprime :: (Eq a, Ring a, Euclidean a) => (a, a) -> (a, a) -> Maybe a
- Math.NumberTheory.Moduli.Singleton: data Some (a :: Nat -> *)
+ Math.NumberTheory.Moduli.Singleton: data Some (a :: Nat -> Type)
- Math.NumberTheory.Primes.Counting: nthPrime :: Integer -> Prime Integer
+ Math.NumberTheory.Primes.Counting: nthPrime :: Int -> Prime Integer
- Math.NumberTheory.Recurrences.Bilinear: binomial :: Integral a => [[a]]
+ Math.NumberTheory.Recurrences.Bilinear: binomial :: Semiring a => [[a]]
- Math.NumberTheory.Recurrences.Bilinear: faulhaberPoly :: Integral a => Int -> [Ratio a]
+ Math.NumberTheory.Recurrences.Bilinear: faulhaberPoly :: (GcdDomain a, Integral a) => Int -> [Ratio a]
- Math.NumberTheory.SmoothNumbers: fromList :: (Eq a, GcdDomain a) => [a] -> Maybe (SmoothBasis a)
+ Math.NumberTheory.SmoothNumbers: fromList :: (Eq a, GcdDomain a) => [a] -> SmoothBasis a
- Math.NumberTheory.SmoothNumbers: smoothOver :: (Ord a, Num a) => SmoothBasis a -> [a]
+ Math.NumberTheory.SmoothNumbers: smoothOver :: Integral a => SmoothBasis a -> [a]
- Math.NumberTheory.SmoothNumbers: smoothOver' :: forall a b. (Eq a, Num a, Ord b) => (a -> b) -> SmoothBasis a -> [a]
+ Math.NumberTheory.SmoothNumbers: smoothOver' :: (Eq a, Num a, Ord b) => (a -> b) -> SmoothBasis a -> [a]
Files
- Changes +0/−369
- GHC/TypeNats/Compat.hs +0/−34
- Math/NumberTheory/ArithmeticFunctions/Class.hs +4/−2
- Math/NumberTheory/ArithmeticFunctions/Inverse.hs +100/−21
- Math/NumberTheory/ArithmeticFunctions/Mertens.hs +1/−2
- Math/NumberTheory/ArithmeticFunctions/Moebius.hs +1/−1
- Math/NumberTheory/ArithmeticFunctions/NFreedom.hs +1/−1
- Math/NumberTheory/ArithmeticFunctions/SieveBlock.hs +12/−3
- Math/NumberTheory/ArithmeticFunctions/Standard.hs +58/−16
- Math/NumberTheory/Curves/Montgomery.hs +1/−1
- Math/NumberTheory/DirichletCharacters.hs +572/−0
- Math/NumberTheory/Euclidean.hs +2/−1
- Math/NumberTheory/Euclidean/Coprimes.hs +6/−3
- Math/NumberTheory/Moduli.hs +4/−6
- Math/NumberTheory/Moduli/Chinese.hs +37/−44
- Math/NumberTheory/Moduli/Class.hs +12/−316
- Math/NumberTheory/Moduli/DiscreteLogarithm.hs +3/−119
- Math/NumberTheory/Moduli/Equations.hs +8/−6
- Math/NumberTheory/Moduli/Internal.hs +126/−0
- Math/NumberTheory/Moduli/Jacobi.hs +4/−106
- Math/NumberTheory/Moduli/JacobiSymbol.hs +128/−0
- Math/NumberTheory/Moduli/Multiplicative.hs +121/−0
- Math/NumberTheory/Moduli/PrimitiveRoot.hs +4/−70
- Math/NumberTheory/Moduli/Singleton.hs +7/−4
- Math/NumberTheory/Moduli/SomeMod.hs +201/−0
- Math/NumberTheory/Moduli/Sqrt.hs +15/−6
- Math/NumberTheory/MoebiusInversion.hs +1/−1
- Math/NumberTheory/MoebiusInversion/Int.hs +0/−152
- Math/NumberTheory/Powers.hs +5/−0
- Math/NumberTheory/Powers/Cubes.hs +5/−54
- Math/NumberTheory/Powers/Fourth.hs +9/−13
- Math/NumberTheory/Powers/General.hs +12/−276
- Math/NumberTheory/Powers/Modular.hs +1/−1
- Math/NumberTheory/Powers/Squares.hs +7/−41
- Math/NumberTheory/Powers/Squares/Internal.hs +2/−0
- Math/NumberTheory/Prefactored.hs +2/−2
- Math/NumberTheory/Primes.hs +38/−13
- Math/NumberTheory/Primes/Counting.hs +0/−1
- Math/NumberTheory/Primes/Counting/Approximate.hs +0/−1
- Math/NumberTheory/Primes/Counting/Impl.hs +165/−70
- Math/NumberTheory/Primes/Factorisation.hs +0/−53
- Math/NumberTheory/Primes/Factorisation/Certified.hs +0/−169
- Math/NumberTheory/Primes/Factorisation/Montgomery.hs +128/−93
- Math/NumberTheory/Primes/Factorisation/TrialDivision.hs +4/−5
- Math/NumberTheory/Primes/Sieve.hs +0/−62
- Math/NumberTheory/Primes/Sieve/Eratosthenes.hs +7/−120
- Math/NumberTheory/Primes/Sieve/Indexing.hs +1/−4
- Math/NumberTheory/Primes/Small.hs +42/−6
- Math/NumberTheory/Primes/Testing.hs +0/−2
- Math/NumberTheory/Primes/Testing/Certificates.hs +0/−35
- Math/NumberTheory/Primes/Testing/Certificates/Internal.hs +0/−358
- Math/NumberTheory/Primes/Testing/Certified.hs +191/−3
- Math/NumberTheory/Primes/Testing/Probabilistic.hs +19/−18
- Math/NumberTheory/Quadratic/EisensteinIntegers.hs +16/−32
- Math/NumberTheory/Quadratic/GaussianIntegers.hs +11/−4
- Math/NumberTheory/Recurrences/Bilinear.hs +94/−16
- Math/NumberTheory/Recurrences/Linear.hs +26/−1
- Math/NumberTheory/Recurrences/Pentagonal.hs +13/−21
- Math/NumberTheory/RootsOfUnity.hs +69/−0
- Math/NumberTheory/SmoothNumbers.hs +63/−142
- Math/NumberTheory/Unsafe.hs +0/−69
- Math/NumberTheory/Utils.hs +9/−26
- Math/NumberTheory/Utils/DirichletSeries.hs +1/−2
- Math/NumberTheory/Utils/Hyperbola.hs +1/−1
- Math/NumberTheory/Zeta/Dirichlet.hs +0/−2
- Math/NumberTheory/Zeta/Hurwitz.hs +3/−6
- Math/NumberTheory/Zeta/Riemann.hs +0/−2
- Setup.hs +0/−5
- arithmoi.cabal +40/−44
- benchmark/Bench.hs +0/−4
- benchmark/Math/NumberTheory/DiscreteLogarithmBench.hs +5/−6
- benchmark/Math/NumberTheory/EuclideanBench.hs +0/−19
- benchmark/Math/NumberTheory/InverseBench.hs +2/−2
- benchmark/Math/NumberTheory/JacobiBench.hs +1/−1
- benchmark/Math/NumberTheory/PowersBench.hs +0/−31
- benchmark/Math/NumberTheory/PrimitiveRootsBench.hs +1/−1
- benchmark/Math/NumberTheory/RecurrencesBench.hs +9/−10
- benchmark/Math/NumberTheory/SequenceBench.hs +2/−10
- benchmark/Math/NumberTheory/SieveBlockBench.hs +0/−1
- benchmark/Math/NumberTheory/SmoothNumbersBench.hs +1/−2
- changelog.md +538/−0
- test-suite/Math/NumberTheory/ArithmeticFunctions/InverseTests.hs +151/−1
- test-suite/Math/NumberTheory/ArithmeticFunctionsTests.hs +11/−4
- test-suite/Math/NumberTheory/CurvesTests.hs +1/−1
- test-suite/Math/NumberTheory/DirichletCharactersTests.hs +248/−0
- test-suite/Math/NumberTheory/EisensteinIntegersTests.hs +19/−15
- test-suite/Math/NumberTheory/EuclideanTests.hs +3/−21
- test-suite/Math/NumberTheory/GaussianIntegersTests.hs +15/−10
- test-suite/Math/NumberTheory/Moduli/ChineseTests.hs +2/−25
- test-suite/Math/NumberTheory/Moduli/ClassTests.hs +1/−0
- test-suite/Math/NumberTheory/Moduli/DiscreteLogarithmTests.hs +2/−4
- test-suite/Math/NumberTheory/Moduli/EquationsTests.hs +3/−3
- test-suite/Math/NumberTheory/Moduli/JacobiTests.hs +1/−1
- test-suite/Math/NumberTheory/Moduli/PrimitiveRootTests.hs +7/−7
- test-suite/Math/NumberTheory/Moduli/SqrtTests.hs +0/−1
- test-suite/Math/NumberTheory/Powers/CubesTests.hs +0/−150
- test-suite/Math/NumberTheory/Powers/FourthTests.hs +0/−142
- test-suite/Math/NumberTheory/Powers/GeneralTests.hs +0/−127
- test-suite/Math/NumberTheory/Powers/ModularTests.hs +2/−2
- test-suite/Math/NumberTheory/Powers/SquaresTests.hs +0/−160
- test-suite/Math/NumberTheory/PrefactoredTests.hs +1/−1
- test-suite/Math/NumberTheory/Primes/CountingTests.hs +7/−10
- test-suite/Math/NumberTheory/Primes/FactorisationTests.hs +22/−5
- test-suite/Math/NumberTheory/Primes/SequenceTests.hs +28/−1
- test-suite/Math/NumberTheory/Primes/SieveTests.hs +11/−34
- test-suite/Math/NumberTheory/PrimesTests.hs +4/−6
- test-suite/Math/NumberTheory/Recurrences/BilinearTests.hs +64/−8
- test-suite/Math/NumberTheory/Recurrences/LinearTests.hs +18/−0
- test-suite/Math/NumberTheory/Recurrences/PentagonalTests.hs +2/−3
- test-suite/Math/NumberTheory/RootsOfUnityTests.hs +25/−0
- test-suite/Math/NumberTheory/SmoothNumbersTests.hs +33/−25
- test-suite/Math/NumberTheory/TestUtils.hs +32/−13
- test-suite/Math/NumberTheory/TestUtils/Wrappers.hs +1/−1
- test-suite/Test.hs +9/−12
− Changes
@@ -1,369 +0,0 @@-0.10.0.0- This release supports GHC 8.0, 8.2, 8.4, 8.6 and 8.8.-- Breaking changes:-- Move 'Euclidean' type class to 'semirings' package (#168).- Embrace the new 'Semiring' -> 'GcdDomain' -> 'Euclidean' hierarchy- of classes, refining 'Num' and 'Integral' constraints.-- Deprecate 'Math.NumberTheory.Primes.Factorisation', use- 'Math.NumberTheory.Primes.factorise' instead. Deprecate- 'Math.NumberTheory.Primes.Sieve', use 'Enum' instance instead.- Deprecate 'Math.NumberTheory.Primes.Factorisation.Certified' and- 'Math.NumberTheory.Primes.Testing.Certificates'.-- Remove deprecated earlier 'Math.NumberTheory.Recurrencies.*'- and 'Math.NumberTheory.UniqueFactorisation' modules.- Use 'Math.NumberTheory.Recurrences.*' and 'Math.NumberTheory.Primes'- instead.-- Remove deprecated earlier an old interface of 'Math.NumberTheory.Moduli.Sqrt'.-- Reshuffle exports from 'Math.NumberTheory.Zeta', do not advertise- its submodules as available to import.-- Add a proxy argument storing vector's flavor to- 'Math.NumberTheory.MoebiusInversion.{generalInversion,totientSum}'.- Deprecate 'Math.NumberTheory.MoebiusInversion.Int'.-- Deprecate 'Math.NumberTheory.SmoothNumbers.{fromSet,fromSmoothUpperBound}'.- Use 'Math.NumberTheory.SmoothNumbers.fromList' instead.- Deprecate 'Math.NumberTheory.SmoothNumbers.smoothOverInRange' in favor- of 'smoothOver' and 'Math.NumberTheory.SmoothNumbers.smoothOverInRange'- in favor of 'isSmooth'.-- 'solveQuadratic' and 'sqrtsMod' require an additional argument: a singleton- linking a type-level modulo with a term-level factorisation (#169).-- New features:-- The machinery of cyclic groups, primitive roots and discrete logarithms- has been completely overhauled and rewritten using singleton types (#169).-- There is also a new singleton type, linking a type-level modulo with- a term-level factorisation. It allows both to have a nicely-typed API- of `Mod m` and avoid repeating factorisations (#169).-- Refer to a brand new module 'Math.NumberTheory.Moduli.Singleton' for details.-- Add a new function 'factorBack'.-- Improvements:-- Add 'Ord SomeMod' instance (#165).-- Generalize 'sieveBlock' to handle any flavor of 'Vector' (#164).-- Add Semiring and Ring instances for Eisenstein and Gaussian integers.--0.9.0.0- This release supports GHC 8.0, 8.2, 8.4 and 8.6.-- Breaking changes:-- Remove 'Prime' type family and introduce 'Prime' newtype. This newtype- is now used extensively in public API:-- primes :: Integral a => [Prime a]- primeList :: Integral a => PrimeSieve -> [Prime a]- sieveFrom :: Integer -> [Prime Integer]- nthPrime :: Integer -> Prime Integer-- 'sbcFunctionOnPrimePower' now accepts 'Prime Word' instead of 'Word'.-- 'Math.NumberTheory.Primes.{Factorisation,Testing,Counting,Sieve}'- are no longer re-exported from 'Math.NumberTheory.Primes'.- Merge 'Math.NumberTheory.UniqueFactorisation' into- 'Math.NumberTheory.Primes' (#135, #153).-- From now on 'Math.NumberTheory.Primes.Factorisation.factorise'- and similar functions return [(Integer, Word)] instead of [(Integer, Int)].-- Remove deprecated 'Math.NumberTheory.GCD' and 'Math.NumberTheory.GCD.LowLevel'.-- Deprecate 'Math.NumberTheory.Recurrencies.*'.- Use 'Math.NumberTheory.Recurrences.*' instead (#146).-- New features:-- New functions 'nextPrime' and 'precPrime'. Implement an instance of 'Enum' for primes (#153):-- > [nextPrime 101 .. precPrime 130]- [Prime 101,Prime 103,Prime 107,Prime 109,Prime 113,Prime 127]-- Support Gaussian and Eisenstein integers in smooth numbers (#138).-- Add the Hurwitz zeta function on non-negative integer arguments (#126).-- Implement efficient tests of n-freeness: pointwise and in interval. See 'isNFree' and 'nFreesBlock' (#145).-- Generate preimages of the totient and the sum-of-divisors functions (#142):-- > inverseTotient 120 :: [Integer]- [155,310,183,366,225,450,175,350,231,462,143,286,244,372,396,308,248]-- Generate coefficients of Faulhaber polynomials 'faulhaberPoly' (#70).-- Improvements:-- Better precision for exact values of Riemann zeta and Dirichlet beta- functions (#123).-- Speed up certain cases of modular multiplication (#160).-- Extend Chinese theorem to non-coprime moduli (#71).--0.8.0.0- This release supports GHC 7.10, 8.0, 8.2, 8.4 and 8.6.-- Breaking changes:-- Stop reporting units (1, -1, i, -i) as a part of factorisation- for integers and Gaussian integers (#101). Now `factorise (-2)`- is `[(2, 1)]` and not `[(-1, 1), (2, 1)]`.-- Deprecate an old interface of 'Math.NumberTheory.Moduli.Sqrt'- and roll out a new one, more robust and type safe (#87).-- Deprecate 'Math.NumberTheory.GCD' and 'Math.NumberTheory.GCD.LowLevel' (#80).- Use 'Math.NumberTheory.Euclidean' instead (#128).- Move 'splitIntoCoprimes' to 'Math.NumberTheory.Euclidean.Coprimes'.-- Change types of 'splitIntoCoprimes', 'fromFactors' and 'prefFactors'- using newtype 'Coprimes' (#89).-- Redesign API to modular square roots (#108)-- Deprecate 'jacobi'' (#103).-- Sort Gaussian primes by norm (#124).-- Deprecate 'Math.NumberTheory.GaussianIntegers' in favor of- 'Math.NumberTheory.Quadratic.GaussianIntegers'.-- New features:-- Implement Ramanujan tau function (#112):-- > map ramanujan [1..10]- [1,-24,252,-1472,4830,-6048,-16744,84480,-113643,-115920]-- Implement partition function (#115):-- > take 10 partition- [1,1,2,3,5,7,11,15,22,30]-- Add the Dirichlet beta function on non-negative integer arguments (#120).- E. g.,-- > take 5 $ Math.NumberTheory.Zeta.Dirichlet.betas 1e-15- [0.5,0.7853981633974483,0.9159655941772191,0.9689461462593693,0.9889445517411055]-- Solve linear and quadratic congruences (#129).-- Support Eisenstein integers (#121).-- Implement discrete logarithm (#88).-- Improvements:-- Make return type of 'primes' and 'primeList' polymorphic instead of- being limited to 'Integer' only (#109).-- Speed up factorisation of Gaussian integers (#116).-- Speed up computation of primitive roots for prime powers (#127).--0.7.0.0- This release supports GHC 7.8, 7.10, 8.0, 8.2 and 8.4.-- Breaking changes:-- Remove 'Math.NumberTheory.Powers.Integer', deprecated in 0.5.0.0.-- Deprecate 'Math.NumberTheory.Primes.Heap'.- Use 'Math.NumberTheory.Primes.Sieve' instead.-- Deprecate 'FactorSieve', 'TotientSieve', 'CarmichaelSieve' and- accompanying functions. Use new general approach for bulk evaluation- of arithmetic functions instead (#77).-- Now 'moebius' returns not a number, but a value of 'Moebius' type (#90).-- New functions:-- A general framework for bulk evaluation of arithmetic functions (#77):-- > runFunctionOverBlock carmichaelA 1 10- [1,1,2,2,4,2,6,2,6,4]-- Implement a sublinear algorithm for Mertens function (#90):-- > map (mertens . (10 ^)) [0..9]- [1,-1,1,2,-23,-48,212,1037,1928,-222]-- Add basic support for cyclic groups and primitive roots (#86).-- Implement an efficient modular exponentiation (#86).-- Write routines for lazy generation of smooth numbers (#91).-- > smoothOverInRange (fromJust (fromList [3,5,7])) 1000 2000- [1029,1125,1215,1225,1323,1575,1701,1715,1875]-- Improvements:-- Now factorisation of large integers and Gaussian integers produces- factors as lazy as possible (#72, #76).--0.6.0.1:- Switch to smallcheck 1.1.3.--0.6.0.0:- This release supports GHC 7.8, 7.10, 8.0 and 8.2.-- Breaking changes:-- 'Math.NumberTheory.Moduli' was split into- 'Math.NumberTheory.Moduli.{Chinese,Class,Jacobi,Sqrt}'.-- Functions 'jacobi' and 'jacobi'' return 'JacobiSymbol'- instead of 'Int'.-- Functions 'invertMod', 'powerMod' and 'powerModInteger' were removed,- as well as their unchecked counterparts. Use new interface to- modular computations, provided by 'Math.NumberTheory.Moduli.Class'.-- New functions:-- Brand new 'Math.NumberTheory.Moduli.Class' (#56), providing- flexible and type safe modular arithmetic. Due to use of GMP built-ins- it is also significantly faster.-- New function 'divisorsList', which is lazier than 'divisors' and- does not require 'Ord' constraint (#64). Thus, it can be used- for 'GaussianInteger'.-- Improvements:-- Speed up factorisation over elliptic curve up to 15x (#65).-- Polymorphic 'fibonacci' and 'lucas' functions, which previously- were restricted to 'Integer' only (#63). This is especially useful- for modular computations, e. g., 'map fibonacci [1..10] :: [Mod 7]'.-- Make 'totientSum' more robust and idiomatic (#58).--0.5.0.1:- Switch to QuickCheck 2.10.--0.5.0.0:- This release supports GHC 7.8, 7.10 and 8.0. GHC 7.6 is no longer supported.-- Breaking changes:-- Remove deprecated interface to arithmetic functions (divisors, tau,- sigma, totient, jordan, moebius, liouville, smallOmega, bigOmega,- carmichael, expMangoldt). New interface is exposed via- Math.NumberTheory.ArithmeticFunctions (#30).-- Deprecate integerPower and integerWordPower from- Math.NumberTheory.Powers.Integer. Use (^) instead (#51).-- Math.NumberTheory.Logarithms has been moved to the separate package- integer-logarithms (#51).-- Rename Math.NumberTheory.Lucas to Math.NumberTheory.Recurrencies.Linear.-- New functions:-- Add basic combinatorial sequences: binomial coefficients, Stirling- numbers of both kinds, Eulerian numbers of both kinds, Bernoulli- numbers (#39). E. g.,-- > take 10 $ Math.NumberTheory.Recurrencies.Bilinear.bernoulli- [1 % 1,(-1) % 2,1 % 6,0 % 1,(-1) % 30,0 % 1,1 % 42,0 % 1,(-1) % 30,0 % 1]-- Add the Riemann zeta function on non-negative integer arguments (#44).- E. g.,-- > take 5 $ Math.NumberTheory.Zeta.zetas 1e-15- [-0.5,Infinity,1.6449340668482262,1.2020569031595945,1.0823232337111381]-- Improvements:-- Speed up isPrime twice; rework millerRabinV and isStrongFermatPP (#22, #25).--0.4.3.0:- This release supports GHC 7.6, 7.8, 7.10 and 8.0.-- Add Math.NumberTheory.ArithmeticFunctions with brand-new machinery- for arithmetic functions: divisors, tau, sigma, totient, jordan,- moebius, liouville, smallOmega, bigOmega, carmichael, expMangoldt (#30).- Old implementations (exposed via Math.NumberTheory.Primes.Factorisation- and Math.NumberTheory.Powers.Integer) are deprecated and will be removed- in the next major release.-- Add Karatsuba sqrt algorithm, improving performance on large integers (#6).-- Fix incorrect indexing of FactorSieve (#35).--0.4.2.0:- This release supports GHC 7.6, 7.8, 7.10 and 8.0.-- Add new cabal flag check-bounds, which replaces all unsafe array functions with safe ones.-- Add basic functions on Gaussian integers.- Add Möbius mu-function.-- Forbid non-positive moduli in Math.NumberTheory.Moduli.-- Fix out-of-bounds error in Math.NumberTheory.Primes.Heap, Math.NumberTheory.Primes.Sieve and Math.NumberTheory.MoebiusInversion.- Fix 32-bit build.- Fix binaryGCD on negative numbers.- Fix highestPower (various issues).--0.4.1.0:- Add integerLog10 variants at Bas van Dijk's request and expose- Math.NumberTheory.Powers.Integer, with an added integerWordPower.-0.4.0.4:- Update for GHC-7.8, the type of some primops changed, they return Int# now- instead of Bool.- Fixed bugs in modular square roots and factorisation.-0.4.0.3:- Relaxed dependencies on mtl and containers- Fixed warnings from GHC-7.5, Word(..) moved to GHC.Types- Removed SPECIALISE pragma from inline function (warning from 7.5, probably- pointless anyway)-0.4.0.2:- Sped up factor sieves. They need more space now, but the speedup is worth it, IMO.- Raised spec-constr limit in MoebiusInversion.Int-0.4.0.1:- Fixed Haddock bug-0.4.0.0:- Added generalised Möbius inversion, to be continued-0.3.0.0:- Added modular square roots and Chinese remainder theorem-0.2.0.6:- Performance tweaks for powerModInteger (~10%) and- invertMod (~25%).-0.2.0.5:- Fix bug in psieveFrom-0.2.0.4:- Fix bug in nthPrime-0.2.0.3:- Fix bug in powerMod-0.2.0.2:- Relax bounds on array dependency for 7.4.*-0.2.0.1:- Fix copy-pasto (only relevant for 7.3.*)- Fix imports for ghc >= 7.3-0.2.0.0:- Added certificates and certified testing/factorisation-0.1.0.2:- Fixed doc bugs-0.1.0.1:- Elaborate on overflow, work more on native Ints in Eratosthenes-0.1.0.0:- First release
− GHC/TypeNats/Compat.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE CPP #-}--{-# OPTIONS_HADDOCK hide #-}-#if MIN_VERSION_base(4,10,0)-module GHC.TypeNats.Compat- ( module GHC.TypeNats- ) where--#if MIN_VERSION_base(4,11,0)-import GHC.TypeNats hiding (Mod)-#else-import GHC.TypeNats-#endif-#else--module GHC.TypeNats.Compat- ( module GHC.TypeLits- , natVal- , someNatVal- ) where--import GHC.TypeLits hiding (natVal, someNatVal)-import qualified GHC.TypeLits as TL-import Numeric.Natural--natVal :: KnownNat n => proxy n -> Natural-natVal = fromInteger . TL.natVal--someNatVal :: Natural -> SomeNat-someNatVal n = case TL.someNatVal (toInteger n) of- Nothing -> error "someNatVal: impossible negative argument"- Just sn -> sn--#endif
Math/NumberTheory/ArithmeticFunctions/Class.hs view
@@ -11,8 +11,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} -{-# OPTIONS_HADDOCK hide #-}- module Math.NumberTheory.ArithmeticFunctions.Class ( ArithmeticFunction(..) , runFunction@@ -67,7 +65,11 @@ instance Monoid a => Monoid (ArithmeticFunction n a) where mempty = pure mempty+#if __GLASGOW_HASKELL__ < 803 mappend = liftA2 mappend+#else+ mappend = (<>)+#endif -- | Factorisation is expensive, so it is better to avoid doing it twice. -- Write 'runFunction (f + g) n' instead of 'runFunction f n + runFunction g n'.
Math/NumberTheory/ArithmeticFunctions/Inverse.hs view
@@ -16,7 +16,9 @@ module Math.NumberTheory.ArithmeticFunctions.Inverse ( inverseTotient+ , inverseJordan , inverseSigma+ , inverseSigmaK , -- * Wrappers MinWord(..) , MaxWord(..)@@ -28,7 +30,8 @@ import Prelude hiding (rem, quot) import Data.Bits (Bits)-import Data.List+import Data.Euclidean+import Data.List (foldl', partition, mapAccumL, sortOn) import Data.Map (Map) import qualified Data.Map as M import Data.Maybe@@ -42,9 +45,8 @@ import Numeric.Natural import Math.NumberTheory.ArithmeticFunctions-import Math.NumberTheory.Euclidean import Math.NumberTheory.Logarithms-import Math.NumberTheory.Powers+import Math.NumberTheory.Roots (exactRoot, integerRoot) import Math.NumberTheory.Primes import Math.NumberTheory.Utils.DirichletSeries (DirichletSeries) import qualified Math.NumberTheory.Utils.DirichletSeries as DS@@ -70,33 +72,37 @@ DS.fromDistinctAscList (map (\k -> (g (f p k), point (unPrime p ^ k))) ks) -- | See section 5.1 of the paper.-invTotient- :: forall a. (UniqueFactorisation a, Eq a)- => [(Prime a, Word)]+invJordan+ :: forall a. (Integral a, UniqueFactorisation a, Eq a)+ => Word+ -- ^ Value of k in 'jordan' k+ -> [(Prime a, Word)] -- ^ Factorisation of a value of the totient function -> [PrimePowers a] -- ^ Possible prime factors of an argument of the totient function-invTotient fs = map (\p -> PrimePowers p (doPrime p)) ps+invJordan k fs = map (\p -> PrimePowers p (doPrime p)) ps where divs :: [a] divs = runFunctionOnFactors divisorsListA fs ps :: [Prime a]- ps = mapMaybe (isPrime . (+ 1)) divs+ ps = mapMaybe (\d -> exactRoot k (d + 1) >>= isPrime) divs doPrime :: Prime a -> [Word] doPrime p = case lookup p fs of Nothing -> [1]- Just k -> [1 .. k+1]+ Just w -> [1 .. w+1] -- | See section 5.2 of the paper. invSigma :: forall a. (Euclidean a, Integral a, UniqueFactorisation a, Enum (Prime a), Bits a)- => [(Prime a, Word)]+ => Word+ -- ^ Value of k in 'sigma' k+ -> [(Prime a, Word)] -- ^ Factorisation of a value of the sum-of-divisors function -> [PrimePowers a] -- ^ Possible prime factors of an argument of the sum-of-divisors function-invSigma fs+invSigma k fs = map (\(x, ys) -> PrimePowers x (S.toList ys)) $ M.assocs $ M.unionWith (<>) pksSmall pksLarge@@ -108,7 +114,7 @@ divs = runFunctionOnFactors divisorsListA fs n :: a- n = product $ map (\(p, k) -> unPrime p ^ k) fs+ n = factorBack fs -- There are two possible strategies to find possible prime factors -- of an argument of the sum-of-divisors function.@@ -141,24 +147,24 @@ doPrime :: Prime a -> Set Word doPrime p' = let p = unPrime p' in S.fromDistinctAscList [ e- | e <- [1 .. intToWord (integerLogBase (toInteger p) (toInteger n))]- , n `rem` ((p ^ (e + 1) - 1) `quot` (p - 1)) == 0+ | e <- [1 .. intToWord (integerLogBase (toInteger (p ^ k)) (toInteger n))]+ , n `rem` ((p ^ (k * (e + 1)) - 1) `quot` (p ^ k - 1)) == 0 ] pksLarge :: Map (Prime a) (Set Word) pksLarge = M.unionsWith (<>) [ maybe mempty (flip M.singleton (S.singleton e)) (isPrime p) | d <- divs- , e <- [1 .. intToWord (integerLogBase (toInteger lim) (toInteger d))]- , let p = integerRoot e (d - 1)- , p ^ (e + 1) - 1 == d * (p - 1)+ , e <- [1 .. intToWord (quot (integerLogBase (toInteger lim) (toInteger d)) (wordToInt k)) ]+ , let p = integerRoot (e * k) (d - 1)+ , p ^ (k * (e + 1)) - 1 == d * (p ^ k - 1) ] -- | Instead of multiplying all atomic series and filtering out everything, -- which is not divisible by @n@, we'd rather split all atomic series into -- a couple of batches, each of which corresponds to a prime factor of @n@. -- This allows us to crop resulting Dirichlet series (see 'filter' calls--- in 'invertFunction' below) at the end of each batch, saving time and memory.+-- in @invertFunction@ below) at the end of each batch, saving time and memory. strategy :: forall a c. (GcdDomain c, Ord c) => ArithmeticFunction a c@@ -264,16 +270,54 @@ -- >>> unMaxWord (inverseTotient MaxWord 120) -- 462 inverseTotient- :: (Semiring b, Euclidean a, UniqueFactorisation a, Ord a)+ :: (Semiring b, Integral a, Euclidean a, UniqueFactorisation a) => (a -> b) -> a -> b-inverseTotient point = invertFunction point totientA invTotient+inverseTotient = inverseJordan 1 {-# SPECIALISE inverseTotient :: Semiring b => (Int -> b) -> Int -> b #-} {-# SPECIALISE inverseTotient :: Semiring b => (Word -> b) -> Word -> b #-} {-# SPECIALISE inverseTotient :: Semiring b => (Integer -> b) -> Integer -> b #-} {-# SPECIALISE inverseTotient :: Semiring b => (Natural -> b) -> Natural -> b #-} +-- | The inverse for 'jordan' function.+--+-- Generalizes the 'inverseTotient' function, which is 'inverseJordan' 1.+--+-- The return value is parameterized by a 'Semiring', which allows+-- various applications by providing different (multiplicative) embeddings.+-- E. g., list all preimages (see a helper 'asSetOfPreimages'):+--+-- >>> import qualified Data.Set as S+-- >>> import Data.Semigroup+-- >>> S.mapMonotonic getProduct (inverseJordan 2 (S.singleton . Product) 192)+-- fromList [15,16]+--+-- Similarly to 'inverseTotient', it is possible to count and sum preimages, or+-- get the maximum/minimum preimage.+--+-- Note: it is the __user's responsibility__ to use an appropriate type for+-- 'inverseSigmaK'. Even low values of k with 'Int' or 'Word' will return+-- invalid results due to over/underflow, or throw exceptions (i.e. division by+-- zero).+--+-- >>> asSetOfPreimages (inverseJordan 15) (jordan 15 19) :: S.Set Int+-- fromList []+--+-- >>> asSetOfPreimages (inverseJordan 15) (jordan 15 19) :: S.Set Integer+-- fromList [19]+inverseJordan+ :: (Semiring b, Integral a, Euclidean a, UniqueFactorisation a)+ => Word+ -> (a -> b)+ -> a+ -> b+inverseJordan k point = invertFunction point (jordanA k) (invJordan k)+{-# SPECIALISE inverseJordan :: Semiring b => Word -> (Int -> b) -> Int -> b #-}+{-# SPECIALISE inverseJordan :: Semiring b => Word -> (Word -> b) -> Word -> b #-}+{-# SPECIALISE inverseJordan :: Semiring b => Word -> (Integer -> b) -> Integer -> b #-}+{-# SPECIALISE inverseJordan :: Semiring b => Word -> (Natural -> b) -> Natural -> b #-}+ -- | The inverse for 'sigma' 1 function. -- -- The return value is parameterized by a 'Semiring', which allows@@ -306,11 +350,46 @@ => (a -> b) -> a -> b-inverseSigma point = invertFunction point (sigmaA 1) invSigma+inverseSigma = inverseSigmaK 1 {-# SPECIALISE inverseSigma :: Semiring b => (Int -> b) -> Int -> b #-} {-# SPECIALISE inverseSigma :: Semiring b => (Word -> b) -> Word -> b #-} {-# SPECIALISE inverseSigma :: Semiring b => (Integer -> b) -> Integer -> b #-} {-# SPECIALISE inverseSigma :: Semiring b => (Natural -> b) -> Natural -> b #-}++-- | The inverse for 'sigma' function.+--+-- Generalizes the 'inverseSigma' function, which is 'inverseSigmaK' 1.+--+-- The return value is parameterized by a 'Semiring', which allows+-- various applications by providing different (multiplicative) embeddings.+-- E. g., list all preimages (see a helper 'asSetOfPreimages'):+--+-- >>> import qualified Data.Set as S+-- >>> import Data.Semigroup+-- >>> S.mapMonotonic getProduct (inverseSigmaK 2 (S.singleton . Product) 850)+-- fromList [24, 26]+--+-- Similarly to 'inverseSigma', it is possible to count and sum preimages, or+-- get the maximum/minimum preimage.+--+-- Note: it is the __user's responsibility__ to use an appropriate type for+-- 'inverseSigmaK'. Even low values of k with 'Int' or 'Word' will return+-- invalid results due to over/underflow, or throw exceptions (i.e. division by+-- zero).+--+-- >>> asSetOfPreimages (inverseSigmaK 17) (sigma 17 13) :: S.Set Int+-- fromList *** Exception: divide by zero+inverseSigmaK+ :: (Semiring b, Euclidean a, UniqueFactorisation a, Integral a, Enum (Prime a), Bits a)+ => Word+ -> (a -> b)+ -> a+ -> b+inverseSigmaK k point = invertFunction point (sigmaA k) (invSigma k)+{-# SPECIALISE inverseSigmaK :: Semiring b => Word -> (Int -> b) -> Int -> b #-}+{-# SPECIALISE inverseSigmaK :: Semiring b => Word -> (Word -> b) -> Word -> b #-}+{-# SPECIALISE inverseSigmaK :: Semiring b => Word -> (Integer -> b) -> Integer -> b #-}+{-# SPECIALISE inverseSigmaK :: Semiring b => Word -> (Natural -> b) -> Natural -> b #-} -------------------------------------------------------------------------------- -- Wrappers
Math/NumberTheory/ArithmeticFunctions/Mertens.hs view
@@ -16,8 +16,7 @@ import qualified Data.Vector.Unboxed as U -import Math.NumberTheory.Powers.Cubes-import Math.NumberTheory.Powers.Squares+import Math.NumberTheory.Roots import Math.NumberTheory.ArithmeticFunctions.Moebius -- | Compute individual values of Mertens function in O(n^(2/3)) time and space.
Math/NumberTheory/ArithmeticFunctions/Moebius.hs view
@@ -36,7 +36,7 @@ import GHC.Integer.GMP.Internals import Unsafe.Coerce -import Math.NumberTheory.Powers.Squares (integerSquareRoot)+import Math.NumberTheory.Roots (integerSquareRoot) import Math.NumberTheory.Primes import Math.NumberTheory.Utils.FromIntegral (wordToInt)
Math/NumberTheory/ArithmeticFunctions/NFreedom.hs view
@@ -23,7 +23,7 @@ import qualified Data.Vector.Unboxed as U import qualified Data.Vector.Unboxed.Mutable as MU -import Math.NumberTheory.Powers.Squares (integerSquareRoot)+import Math.NumberTheory.Roots import Math.NumberTheory.Primes import Math.NumberTheory.Utils.FromIntegral (wordToInt)
Math/NumberTheory/ArithmeticFunctions/SieveBlock.hs view
@@ -39,8 +39,7 @@ import Math.NumberTheory.Logarithms (wordLog2, integerLogBase') import Math.NumberTheory.Primes import Math.NumberTheory.Primes.Types-import Math.NumberTheory.Powers.Squares (integerSquareRoot)-import Math.NumberTheory.Utils (splitOff)+import Math.NumberTheory.Roots (integerSquareRoot) import Math.NumberTheory.Utils.FromIntegral (wordToInt, intToWord) -- | A record, which specifies a function to evaluate over a block.@@ -172,7 +171,7 @@ MU.unsafeModify as (\x -> x * p') (I# ix#) MG.unsafeModify bs (\y -> y `append` f0) (I# ix#) else do- let (pow, _) = splitOff p q+ let pow = highestPowerDividing p q MU.unsafeModify as (\x -> x * p' ^ (pow + 2)) (I# ix#) MG.unsafeModify bs (\y -> y `append` V.unsafeIndex fs (wordToInt pow)) (I# ix#) @@ -185,6 +184,16 @@ MG.unsafeModify bs (\b -> b `append` f (Prime $ a' `quot` a) 1) k G.unsafeFreeze bs++-- This is a variant of 'Math.NumberTheory.Utils.splitOff',+-- specialized for better performance.+highestPowerDividing :: Int -> Int -> Word+highestPowerDividing !_ 0 = 0+highestPowerDividing p n = go 0 n+ where+ go !k m = case m `quotRem` p of+ (q, 0) -> go (k + 1) q+ _ -> k -- | This is 'sieveBlock' specialized to unboxed vectors. --
Math/NumberTheory/ArithmeticFunctions/Standard.hs view
@@ -10,11 +10,13 @@ {-# LANGUAGE ScopedTypeVariables #-} module Math.NumberTheory.ArithmeticFunctions.Standard- ( -- * Multiplicative functions- multiplicative- , divisors, divisorsA+ ( -- * List divisors+ divisors, divisorsA , divisorsList, divisorsListA , divisorsSmall, divisorsSmallA+ , divisorsTo, divisorsToA+ -- * Multiplicative functions+ , multiplicative , divisorCount, tau, tauA , sigma, sigmaA , totient, totientA@@ -33,8 +35,10 @@ ) where import Data.Coerce+import Data.Euclidean (GcdDomain(divide)) import Data.IntSet (IntSet) import qualified Data.IntSet as IS+import Data.Maybe import Data.Set (Set) import qualified Data.Set as S import Data.Semigroup@@ -58,7 +62,7 @@ {-# SPECIALIZE divisors :: Integer -> Set Integer #-} -- | The set of all (positive) divisors of an argument.-divisorsA :: (UniqueFactorisation n, Ord n) => ArithmeticFunction n (Set n)+divisorsA :: (Ord n, Num n) => ArithmeticFunction n (Set n) divisorsA = ArithmeticFunction (\p -> SetProduct . divisorsHelper (unPrime p)) (S.insert 1 . getSetProduct) divisorsHelper :: Num n => n -> Word -> Set n@@ -72,7 +76,7 @@ divisorsList = runFunction divisorsListA -- | The unsorted list of all (positive) divisors of an argument, produced in lazy fashion.-divisorsListA :: UniqueFactorisation n => ArithmeticFunction n [n]+divisorsListA :: Num n => ArithmeticFunction n [n] divisorsListA = ArithmeticFunction (\p -> ListProduct . divisorsListHelper (unPrime p)) ((1 :) . getListProduct) divisorsListHelper :: Num n => n -> Word -> [n]@@ -95,6 +99,23 @@ divisorsHelperSmall p a = IS.fromDistinctAscList $ p : p * p : map (p ^) [3 .. wordToInt a] {-# INLINE divisorsHelperSmall #-} +-- | See 'divisorsToA'.+divisorsTo :: (UniqueFactorisation n, Integral n) => n -> n -> Set n+divisorsTo to = runFunction (divisorsToA to)++-- | The set of all (positive) divisors up to an inclusive bound.+divisorsToA :: (UniqueFactorisation n, Integral n) => n -> ArithmeticFunction n (Set n)+divisorsToA to = ArithmeticFunction f unwrap+ where f p k = BoundedSetProduct (\bound -> divisorsToHelper bound (unPrime p) k)+ unwrap (BoundedSetProduct res) = if 1 <= to then S.insert 1 (res to) else res to++-- | Generate at most @a@ powers of @p@ up to an inclusive bound @b@.+divisorsToHelper :: (Ord n, Num n) => n -> n -> Word -> Set n+divisorsToHelper _ _ 0 = S.empty+divisorsToHelper b p 1 = if p <= b then S.singleton p else S.empty+divisorsToHelper b p a = S.fromDistinctAscList $ take (wordToInt a) $ takeWhile (<=b) $ iterate (p*) p+{-# INLINE divisorsToHelper #-}+ -- | Synonym for 'tau'. -- -- >>> map divisorCount [1..10]@@ -113,33 +134,37 @@ tauA = multiplicative $ const (fromIntegral . succ) -- | See 'sigmaA'.-sigma :: (UniqueFactorisation n, Integral n) => Word -> n -> n+sigma :: (UniqueFactorisation n, Integral n, Num a, GcdDomain a) => Word -> n -> a sigma = runFunction . sigmaA+{-# INLINABLE sigma #-} -- | The sum of the @k@-th powers of (positive) divisors of an argument. -- -- > sigmaA = multiplicative (\p k -> sum $ map (p ^) [0..k]) -- > sigmaA 0 = tauA-sigmaA :: (UniqueFactorisation n, Integral n) => Word -> ArithmeticFunction n n+sigmaA :: (Integral n, Num a, GcdDomain a) => Word -> ArithmeticFunction n a sigmaA 0 = tauA-sigmaA 1 = multiplicative $ sigmaHelper . unPrime-sigmaA a = multiplicative $ sigmaHelper . (^ wordToInt a) . unPrime+sigmaA 1 = multiplicative $ sigmaHelper . fromIntegral . unPrime+sigmaA a = multiplicative $ sigmaHelper . (^ wordToInt a) . fromIntegral . unPrime+{-# INLINABLE sigmaA #-} -sigmaHelper :: Integral n => n -> Word -> n+sigmaHelper :: (Num a, GcdDomain a) => a -> Word -> a sigmaHelper pa 1 = pa + 1 sigmaHelper pa 2 = pa * pa + pa + 1-sigmaHelper pa k = (pa ^ wordToInt (k + 1) - 1) `quot` (pa - 1)+sigmaHelper pa k = fromJust ((pa ^ wordToInt (k + 1) - 1) `divide` (pa - 1)) {-# INLINE sigmaHelper #-} -- | See 'totientA'. totient :: UniqueFactorisation n => n -> n totient = runFunction totientA+{-# INLINABLE totient #-} -- | Calculates the totient of a positive number @n@, i.e. -- the number of @k@ with @1 <= k <= n@ and @'gcd' n k == 1@, -- in other words, the order of the group of units in @ℤ/(n)@.-totientA :: UniqueFactorisation n => ArithmeticFunction n n+totientA :: Num n => ArithmeticFunction n n totientA = multiplicative $ jordanHelper . unPrime+{-# INLINABLE totientA #-} -- | See 'jordanA'. jordan :: UniqueFactorisation n => Word -> n -> n@@ -148,7 +173,7 @@ -- | Calculates the k-th Jordan function of an argument. -- -- > jordanA 1 = totientA-jordanA :: UniqueFactorisation n => Word -> ArithmeticFunction n n+jordanA :: Num n => Word -> ArithmeticFunction n n jordanA 0 = multiplicative $ \_ _ -> 0 jordanA 1 = totientA jordanA a = multiplicative $ jordanHelper . (^ wordToInt a) . unPrime@@ -211,7 +236,7 @@ -- | Calculates the Carmichael function for a positive integer, that is, -- the (smallest) exponent of the group of units in @ℤ/(n)@.-carmichaelA :: (UniqueFactorisation n, Integral n) => ArithmeticFunction n n+carmichaelA :: Integral n => ArithmeticFunction n n carmichaelA = ArithmeticFunction (\p -> LCM . f (unPrime p)) getLCM where f 2 1 = 1@@ -233,7 +258,7 @@ -- -- > smallOmegaA = additive (\_ _ -> 1) smallOmegaA :: Num a => ArithmeticFunction n a-smallOmegaA = additive (\_ _ -> 1)+smallOmegaA = additive $ const $ const 1 -- | See 'bigOmegaA'. bigOmega :: UniqueFactorisation n => n -> Word@@ -250,7 +275,7 @@ expMangoldt = runFunction expMangoldtA -- | The exponent of von Mangoldt function. Use @log expMangoldtA@ to recover von Mangoldt function itself.-expMangoldtA :: UniqueFactorisation n => ArithmeticFunction n n+expMangoldtA :: Num n => ArithmeticFunction n n expMangoldtA = ArithmeticFunction (const . MangoldtOne . unPrime) runMangoldt data Mangoldt a@@ -322,6 +347,23 @@ instance Num a => Monoid (ListProduct a) where mempty = ListProduct mempty+ mappend = (<>)++-- Represent as a Reader monad+newtype BoundedSetProduct a = BoundedSetProduct { _getBoundedSetProduct :: a -> Set a }++takeWhileLE :: Ord a => a -> Set a -> Set a+takeWhileLE b xs = if m then S.insert b ls else ls+ where (ls, m, _) = S.splitMember b xs++instance (Ord a, Num a) => Semigroup (BoundedSetProduct a) where+ BoundedSetProduct f1 <> BoundedSetProduct f2 = BoundedSetProduct f+ where f b = s1 <> s2 <> foldMap (\n -> takeWhileLE b $ S.mapMonotonic (* n) s2) s1+ where s1 = f1 b+ s2 = f2 b++instance (Ord a, Num a) => Monoid (BoundedSetProduct a) where+ mempty = BoundedSetProduct mempty mappend = (<>) newtype IntSetProduct = IntSetProduct { getIntSetProduct :: IntSet }
Math/NumberTheory/Curves/Montgomery.hs view
@@ -34,7 +34,7 @@ import Data.Proxy import GHC.Exts import GHC.Integer.Logarithms-import GHC.TypeNats.Compat+import GHC.TypeNats (KnownNat, SomeNat(..), Nat, natVal, someNatVal) import Math.NumberTheory.Utils (recipMod)
+ Math/NumberTheory/DirichletCharacters.hs view
@@ -0,0 +1,572 @@+-- |+-- Module: Math.NumberTheory.DirichletCharacters+-- Copyright: (c) 2018 Bhavik Mehta+-- Licence: MIT+-- Maintainer: Bhavik Mehta <bhavikmehta8@gmail.com>+--+-- Implementation and enumeration of Dirichlet characters.+--++{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-}++module Math.NumberTheory.DirichletCharacters+ (+ -- * An absorbing semigroup+ OrZero, pattern Zero, pattern NonZero+ , orZeroToNum+ -- * Dirichlet characters+ , DirichletCharacter+ -- ** Construction+ , indexToChar+ , indicesToChars+ , characterNumber+ , allChars+ , fromTable+ -- ** Evaluation+ , eval+ , evalGeneral+ , evalAll+ -- ** Special Dirichlet characters+ , principalChar+ , isPrincipal+ , orderChar+ -- ** Real Dirichlet characters+ , RealCharacter+ , isRealCharacter+ , getRealChar+ , toRealFunction+ , jacobiCharacter+ -- ** Primitive characters+ , PrimitiveCharacter+ , isPrimitive+ , getPrimitiveChar+ , induced+ , makePrimitive+ , WithNat(..)+ -- * Roots of unity+ , RootOfUnity(..)+ , toRootOfUnity+ , toComplex+ -- * Debugging+ , validChar+ ) where++#if !MIN_VERSION_base(4,12,0)+import Control.Applicative (liftA2)+#endif+import Data.Bits (Bits(..))+import Data.Foldable (for_)+import Data.Functor.Identity (Identity(..))+import Data.Kind+import Data.List (mapAccumL, foldl', sort, find, unfoldr)+import Data.Maybe (mapMaybe, fromJust, fromMaybe)+#if MIN_VERSION_base(4,12,0)+import Data.Monoid (Ap(..))+#endif+import Data.Proxy (Proxy(..))+import Data.Ratio ((%), numerator, denominator)+import Data.Semigroup (Semigroup(..),Product(..))+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV+import Data.Vector (Vector, (!))+import GHC.TypeNats (Nat, SomeNat(..), natVal, someNatVal)+import Numeric.Natural (Natural)++import Math.NumberTheory.ArithmeticFunctions (totient)+import Math.NumberTheory.Moduli.Chinese+import Math.NumberTheory.Moduli.Class (KnownNat, Mod, getVal)+import Math.NumberTheory.Moduli.Internal (isPrimitiveRoot', discreteLogarithmPP)+import Math.NumberTheory.Moduli.Multiplicative (MultMod(..), isMultElement)+import Math.NumberTheory.Moduli.Singleton (Some(..), cyclicGroupFromFactors)+import Math.NumberTheory.Powers.Modular (powMod)+import Math.NumberTheory.Primes (Prime(..), UniqueFactorisation, factorise, nextPrime)+import Math.NumberTheory.RootsOfUnity+import Math.NumberTheory.Utils.FromIntegral (wordToInt)+import Math.NumberTheory.Utils++-- | A Dirichlet character mod \(n\) is a group homomorphism from \((\mathbb{Z}/n\mathbb{Z})^*\)+-- to \(\mathbb{C}^*\), represented abstractly by `DirichletCharacter`. In particular, they take+-- values at roots of unity and can be evaluated using `eval`.+-- A Dirichlet character can be extended to a completely multiplicative function on \(\mathbb{Z}\)+-- by assigning the value 0 for \(a\) sharing a common factor with \(n\), using `evalGeneral`.+--+-- There are finitely many possible Dirichlet characters for a given modulus, in particular there+-- are \(\phi(n)\) characters modulo \(n\), where \(\phi\) refers to Euler's `totient` function.+-- This gives rise to `Enum` and `Bounded` instances.+newtype DirichletCharacter (n :: Nat) = Generated [DirichletFactor]++-- | The group (Z/nZ)^* decomposes to a product (Z/2^k0 Z)^* x (Z/p1^k1 Z)^* x ... x (Z/pi^ki Z)^*+-- where n = 2^k0 p1^k1 ... pi^ki, and the pj are odd primes, k0 possibly 0. Thus, a group+-- homomorphism from (Z/nZ)^* is characterised by group homomorphisms from each of these factor+-- groups. Furthermore, for odd p, we have (Z/p^k Z)^* isomorphic to Z / p^(k-1)*(p-1) Z, an+-- additive group, where an isomorphism is specified by a choice of primitive root.+-- Similarly, for k >= 2, (Z/2^k Z)^* is isomorphic to Z/2Z * (Z / 2^(k-2) Z) (and for k < 2+-- it is trivial). (See @lambda@ for this isomorphism).+-- Thus, to specify a Dirichlet character, it suffices to specify the value of generators+-- of each of these cyclic groups, when primitive roots are given. This data is given by a+-- DirichletFactor.+-- We have the invariant that the factors must be given in strictly increasing order, and the+-- generator is as given by @generator@, and are each non-trivial. These conditions are verified+-- using `validChar`.+data DirichletFactor = OddPrime { _getPrime :: Prime Natural+ , _getPower :: Word+ , _getGenerator :: Natural+ , _getValue :: RootOfUnity+ }+ | TwoPower { _getPower2 :: Int -- this ought to be Word, but many applications+ -- needed to use wordToInt, so Int is cleaner+ -- Required to be >= 2+ , _getFirstValue :: RootOfUnity+ , _getSecondValue :: RootOfUnity+ }+ | Two++instance Eq (DirichletCharacter n) where+ Generated a == Generated b = a == b++instance Eq DirichletFactor where+ TwoPower _ x1 x2 == TwoPower _ y1 y2 = x1 == y1 && x2 == y2+ OddPrime _ _ _ x == OddPrime _ _ _ y = x == y+ Two == Two = True+ _ == _ = False++-- | For primes, define the canonical primitive root as the smallest such. For prime powers \(p^k\),+-- either the smallest primitive root \(g\) mod \(p\) works, or \(g+p\) works.+generator :: (Integral a, UniqueFactorisation a) => Prime a -> Word -> a+generator p k+ | k == 1 = modP+ | otherwise = if powMod modP (p'-1) (p'*p') == 1 then modP + p' else modP+ where p' = unPrime p+ modP = case cyclicGroupFromFactors [(p,k)] of+ Just (Some cg) -> head $ filter (isPrimitiveRoot' cg) [2..p'-1]+ _ -> error "illegal"++-- | Implement the function \(\lambda\) from page 5 of+-- https://www2.eecs.berkeley.edu/Pubs/TechRpts/1984/CSD-84-186.pdf+lambda :: Integer -> Int -> Integer+lambda x e = ((powMod x (2*modulus) largeMod - 1) `shiftR` (e+1)) .&. (modulus - 1)+ where modulus = bit (e-2)+ largeMod = bit (2*e - 1)++-- | For elements of the multiplicative group \((\mathbb{Z}/n\mathbb{Z})^*\), a Dirichlet+-- character evaluates to a root of unity.+eval :: DirichletCharacter n -> MultMod n -> RootOfUnity+eval (Generated ds) m = foldMap (evalFactor m') ds+ where m' = getVal $ multElement m++-- | Evaluate each factor of the Dirichlet character.+evalFactor :: Integer -> DirichletFactor -> RootOfUnity+evalFactor m =+ \case+ OddPrime (toInteger . unPrime -> p) k (toInteger -> a) b ->+ discreteLogarithmPP p k a (m `rem` p^k) `stimes` b+ TwoPower k s b -> (if testBit m 1 then s else mempty)+ <> lambda (thingy k m) k `stimes` b+ Two -> mempty++thingy :: (Bits p, Num p) => Int -> p -> p+thingy k m = if testBit m 1+ then bit k - m'+ else m'+ where m' = m .&. (bit k - 1)++-- | A character can evaluate to a root of unity or zero: represented by @Nothing@.+evalGeneral :: KnownNat n => DirichletCharacter n -> Mod n -> OrZero RootOfUnity+evalGeneral chi t = case isMultElement t of+ Nothing -> Zero+ Just x -> NonZero $ eval chi x++-- | Give the principal character for this modulus: a principal character mod \(n\) is 1 for+-- \(a\) coprime to \(n\), and 0 otherwise.+principalChar :: KnownNat n => DirichletCharacter n+principalChar = minBound++mulChars :: DirichletCharacter n -> DirichletCharacter n -> DirichletCharacter n+mulChars (Generated x) (Generated y) = Generated (zipWith combine x y)+ where combine :: DirichletFactor -> DirichletFactor -> DirichletFactor+ combine Two Two = Two+ combine (OddPrime p k g n) (OddPrime _ _ _ m) =+ OddPrime p k g (n <> m)+ combine (TwoPower k a n) (TwoPower _ b m) =+ TwoPower k (a <> b) (n <> m)+ combine _ _ = error "internal error: malformed DirichletCharacter"++-- | This Semigroup is in fact a group, so @stimes@ can be called with a negative first argument.+instance Semigroup (DirichletCharacter n) where+ (<>) = mulChars+ stimes = stimesChar++instance KnownNat n => Monoid (DirichletCharacter n) where+ mempty = principalChar+ mappend = (<>)++stimesChar :: Integral a => a -> DirichletCharacter n -> DirichletCharacter n+stimesChar s (Generated xs) = Generated (map mult xs)+ where mult :: DirichletFactor -> DirichletFactor+ mult (OddPrime p k g n) = OddPrime p k g (s `stimes` n)+ mult (TwoPower k a b) = TwoPower k (s `stimes` a) (s `stimes` b)+ mult Two = Two++-- | We define `succ` and `pred` with more efficient implementations than+-- @`toEnum` . (+1) . `fromEnum`@.+instance KnownNat n => Enum (DirichletCharacter n) where+ toEnum = indexToChar . fromIntegral+ fromEnum = fromIntegral . characterNumber+ succ x = makeChar x (characterNumber x + 1)+ pred x = makeChar x (characterNumber x - 1)++ enumFromTo x y = bulkMakeChars x [fromEnum x..fromEnum y]+ enumFrom x = bulkMakeChars x [fromEnum x..]+ enumFromThenTo x y z = bulkMakeChars x [fromEnum x, fromEnum y..fromEnum z]+ enumFromThen x y = bulkMakeChars x [fromEnum x, fromEnum y..]++instance KnownNat n => Bounded (DirichletCharacter n) where+ minBound = indexToChar 0+ maxBound = indexToChar (totient n - 1)+ where n = natVal (Proxy :: Proxy n)++-- | We have a (non-canonical) enumeration of dirichlet characters.+characterNumber :: DirichletCharacter n -> Integer+characterNumber (Generated y) = foldl' go 0 y+ where go x (OddPrime p k _ a) = x * m + numerator (fromRootOfUnity a * fromIntegral m)+ where p' = fromIntegral (unPrime p)+ m = p'^(k-1)*(p'-1)+ go x (TwoPower k a b) = x' * 2 + numerator (fromRootOfUnity a * 2)+ where m = bit (k-2) :: Integer+ x' = x `shiftL` (k-2) + numerator (fromRootOfUnity b * fromIntegral m)+ go x Two = x++-- | Give the dirichlet character from its number.+-- Inverse of `characterNumber`.+indexToChar :: forall n. KnownNat n => Natural -> DirichletCharacter n+indexToChar = runIdentity . indicesToChars . Identity++-- | Give a collection of dirichlet characters from their numbers. This may be more efficient than+-- `indexToChar` for multiple characters, as it prevents some internal recalculations.+indicesToChars :: forall n f. (KnownNat n, Functor f) => f Natural -> f (DirichletCharacter n)+indicesToChars = fmap (Generated . unroll t . (`mod` m))+ where n = natVal (Proxy :: Proxy n)+ (Product m, t) = mkTemplate n++-- | List all characters for the modulus. This is preferred to using @[minBound..maxBound]@.+allChars :: forall n. KnownNat n => [DirichletCharacter n]+allChars = indicesToChars [0..m-1]+ where m = totient $ natVal (Proxy :: Proxy n)++-- | The same as `indexToChar`, but if we're given a character we can create others more efficiently.+makeChar :: Integral a => DirichletCharacter n -> a -> DirichletCharacter n+makeChar x = runIdentity . bulkMakeChars x . Identity++-- | Use one character to make many more: better than indicesToChars since it avoids recalculating+-- some primitive roots+bulkMakeChars :: (Integral a, Functor f) => DirichletCharacter n -> f a -> f (DirichletCharacter n)+bulkMakeChars x = fmap (Generated . unroll t . (`mod` m) . fromIntegral)+ where (Product m, t) = templateFromCharacter x++-- We assign each natural a unique Template, which can be decorated (eg in `unroll`) to+-- form a DirichletCharacter. A Template effectively holds the information carried around+-- in a DirichletFactor which depends only on the modulus of the character.+data Template = OddTemplate { _getPrime' :: Prime Natural+ , _getPower' :: Word+ , _getGenerator' :: !Natural+ , _getModulus' :: !Natural+ }+ | TwoPTemplate { _getPower2' :: Int+ , _getModulus' :: !Natural+ } -- the modulus is derivable from the other values, but calculation+ -- may be expensive, so we pre-calculate it+ -- morally getModulus should be a prefactored but seems to be+ -- pointless here+ | TwoTemplate++templateFromCharacter :: DirichletCharacter n -> (Product Natural, [Template])+templateFromCharacter (Generated t) = traverse go t+ where go (OddPrime p k g _) = (Product m, OddTemplate p k g m)+ where p' = unPrime p+ m = p'^(k-1)*(p'-1)+ go (TwoPower k _ _) = (Product (2*m), TwoPTemplate k m)+ where m = bit (k-2)+ go Two = (Product 1, TwoTemplate)++mkTemplate :: Natural -> (Product Natural, [Template])+mkTemplate = go . sort . factorise+ where go :: [(Prime Natural, Word)] -> (Product Natural, [Template])+ go ((unPrime -> 2, 1): xs) = (Product 1, [TwoTemplate]) <> traverse odds xs+ go ((unPrime -> 2, wordToInt -> k): xs) = (Product (2*m), [TwoPTemplate k m]) <> traverse odds xs+ where m = bit (k-2)+ go xs = traverse odds xs+ odds :: (Prime Natural, Word) -> (Product Natural, Template)+ odds (p, k) = (Product m, OddTemplate p k (generator p k) m)+ where p' = unPrime p+ m = p'^(k-1)*(p'-1)++-- the validity of the producted dirichletfactor list here requires the template to be valid+unroll :: [Template] -> Natural -> [DirichletFactor]+unroll t m = snd (mapAccumL func m t)+ where func :: Natural -> Template -> (Natural, DirichletFactor)+ func a (OddTemplate p k g n) = (a1, OddPrime p k g (toRootOfUnity $ (toInteger a2) % (toInteger n)))+ where (a1,a2) = quotRem a n+ func a (TwoPTemplate k n) = (b1, TwoPower k (toRootOfUnity $ (toInteger a2) % 2) (toRootOfUnity $ (toInteger b2) % (toInteger n)))+ where (a1,a2) = quotRem a 2+ (b1,b2) = quotRem a1 n+ func a TwoTemplate = (a, Two)++-- | Test if a given Dirichlet character is prinicpal for its modulus: a principal character mod+-- \(n\) is 1 for \(a\) coprime to \(n\), and 0 otherwise.+isPrincipal :: DirichletCharacter n -> Bool+isPrincipal chi = characterNumber chi == 0++-- | Induce a Dirichlet character to a higher modulus. If \(d \mid n\), then \(a \bmod{n}\) can be+-- reduced to \(a \bmod{d}\). Thus, the multiplicative function on \(\mathbb{Z}/d\mathbb{Z}\)+-- induces a multiplicative function on \(\mathbb{Z}/n\mathbb{Z}\).+--+-- >>> :set -XTypeApplications+-- >>> chi = indexToChar 5 :: DirichletCharacter 45+-- >>> chi2 = induced @135 chi+-- >>> :t chi2+-- Maybe (DirichletCharacter 135)+induced :: forall n d. (KnownNat d, KnownNat n) => DirichletCharacter d -> Maybe (DirichletCharacter n)+induced (Generated start) = if n `rem` d == 0+ then Just (Generated (combine (snd $ mkTemplate n) start))+ else Nothing+ where n = natVal (Proxy :: Proxy n)+ d = natVal (Proxy :: Proxy d)+ combine :: [Template] -> [DirichletFactor] -> [DirichletFactor]+ combine [] _ = []+ combine ts [] = map newFactor ts+ combine (t:xs) (y:ys) = case (t,y) of+ (TwoTemplate, Two) -> Two: combine xs ys+ (TwoTemplate, _) -> Two: combine xs (y:ys)+ (TwoPTemplate k _, Two) -> TwoPower k mempty mempty: combine xs ys+ (TwoPTemplate k _, TwoPower _ a b) -> TwoPower k a b: combine xs ys+ (TwoPTemplate k _, _) -> TwoPower k mempty mempty: combine xs (y:ys)+ (OddTemplate p k _ _, OddPrime q _ g a) | p == q -> OddPrime p k g a: combine xs ys+ (OddTemplate p k g _, OddPrime q _ _ _) | p < q -> OddPrime p k g mempty: combine xs (y:ys)+ _ -> error "internal error in induced: please report this as a bug"+ newFactor :: Template -> DirichletFactor+ newFactor TwoTemplate = Two+ newFactor (TwoPTemplate k _) = TwoPower k mempty mempty+ newFactor (OddTemplate p k g _) = OddPrime p k g mempty+ -- rest (p,k) = OddPrime p k (generator p k) mempty++-- | The <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol> gives a real Dirichlet+-- character for odd moduli.+jacobiCharacter :: forall n. KnownNat n => Maybe (RealCharacter n)+jacobiCharacter = if odd n+ then Just $ RealChar $ Generated $ map go $ snd $ mkTemplate n+ else Nothing+ where n = natVal (Proxy :: Proxy n)+ go :: Template -> DirichletFactor+ go (OddTemplate p k g _) = OddPrime p k g $ toRootOfUnity ((toInteger k) % 2)+ -- jacobi symbol of a primitive root mod p over p is always -1+ go _ = error "internal error in jacobiCharacter: please report this as a bug"+ -- every factor of n should be odd++-- | A Dirichlet character is real if it is real-valued.+newtype RealCharacter n = RealChar { -- | Extract the character itself from a `RealCharacter`.+ getRealChar :: DirichletCharacter n+ }+ deriving Eq++-- | Test if a given `DirichletCharacter` is real, and if so give a `RealCharacter`.+isRealCharacter :: DirichletCharacter n -> Maybe (RealCharacter n)+isRealCharacter t@(Generated xs) = if all real xs then Just (RealChar t) else Nothing+ where real :: DirichletFactor -> Bool+ real (OddPrime _ _ _ a) = a <> a == mempty+ real (TwoPower _ _ b) = b <> b == mempty+ real Two = True++-- TODO: it should be possible to calculate this without eval/evalGeneral+-- and thus avoid using discrete log calculations: consider the order of m+-- inside each of the factor groups?+-- | Evaluate a real Dirichlet character, which can only take values \(-1,0,1\).+toRealFunction :: KnownNat n => RealCharacter n -> Mod n -> Int+toRealFunction (RealChar chi) m = case evalGeneral chi m of+ Zero -> 0+ NonZero t | t == mempty -> 1+ NonZero t | t == RootOfUnity (1 % 2) -> -1+ _ -> error "internal error in toRealFunction: please report this as a bug"+ -- A real character should not be able to evaluate to+ -- anything other than {-1,0,1}, so should not reach this branch++-- | Test if the internal DirichletCharacter structure is valid.+validChar :: forall n. KnownNat n => DirichletCharacter n -> Bool+validChar (Generated xs) = correctDecomposition && all correctPrimitiveRoot xs && all validValued xs+ where correctDecomposition = sort (factorise n) == map getPP xs+ getPP (TwoPower k _ _) = (two, fromIntegral k)+ getPP (OddPrime p k _ _) = (p, k)+ getPP Two = (two,1)+ correctPrimitiveRoot (OddPrime p k g _) = g == generator p k+ correctPrimitiveRoot _ = True+ validValued (TwoPower k a b) = a <> a == mempty && (bit (k-2) :: Integer) `stimes` b == mempty+ validValued (OddPrime (unPrime -> p) k _ a) = (p^(k-1)*(p-1)) `stimes` a == mempty+ validValued Two = True+ n = natVal (Proxy :: Proxy n)+ two = nextPrime 2++-- | Get the order of the Dirichlet Character.+orderChar :: DirichletCharacter n -> Integer+orderChar (Generated xs) = foldl' lcm 1 $ map orderFactor xs+ where orderFactor (TwoPower _ (RootOfUnity a) (RootOfUnity b)) = denominator a `lcm` denominator b+ orderFactor (OddPrime _ _ _ (RootOfUnity a)) = denominator a+ orderFactor Two = 1++-- | Test if a Dirichlet character is <https://en.wikipedia.org/wiki/Dirichlet_character#Primitive_characters_and_conductor primitive>.+isPrimitive :: DirichletCharacter n -> Maybe (PrimitiveCharacter n)+isPrimitive t@(Generated xs) = if all primitive xs then Just (PrimitiveCharacter t) else Nothing+ where primitive :: DirichletFactor -> Bool+ primitive Two = False+ -- for odd p, we're testing if phi(p^(k-1)) `stimes` a is 1, since this means the+ -- character can come from some the smaller modulus p^(k-1)+ primitive (OddPrime _ 1 _ a) = a /= mempty+ primitive (OddPrime (unPrime -> p) k _ a) = (p^(k-2)*(p-1)) `stimes` a /= mempty+ primitive (TwoPower 2 a _) = a /= mempty+ primitive (TwoPower k _ b) = (bit (k-3) :: Integer) `stimes` b /= mempty++-- | A Dirichlet character is primitive if cannot be 'induced' from any character with+-- strictly smaller modulus.+newtype PrimitiveCharacter n = PrimitiveCharacter { -- | Extract the character itself from a `PrimitiveCharacter`.+ getPrimitiveChar :: DirichletCharacter n+ }+ deriving Eq++-- | Wrapper to hide an unknown type-level natural.+data WithNat (a :: Nat -> Type) where+ WithNat :: KnownNat m => a m -> WithNat a++-- | This function also provides access to the new modulus on type level, with a KnownNat instance+makePrimitive :: DirichletCharacter n -> WithNat PrimitiveCharacter+makePrimitive (Generated xs) =+ case someNatVal (product mods) of+ SomeNat (Proxy :: Proxy m) -> WithNat (PrimitiveCharacter (Generated ys) :: PrimitiveCharacter m)+ where (mods,ys) = unzip (mapMaybe prim xs)+ prim :: DirichletFactor -> Maybe (Natural, DirichletFactor)+ prim Two = Nothing+ prim (OddPrime p' k g a) = case find works options of+ Nothing -> error "invalid character"+ Just (0,_) -> Nothing+ Just (i,_) -> Just (p^i, OddPrime p' i g a)+ where options = (0,1): [(i,p^(i-1)*(p-1)) | i <- [1..k]]+ works (_,phi) = phi `stimes` a == mempty+ p = unPrime p'+ prim (TwoPower k a b) = case find worksb options of+ Nothing -> error "invalid character"+ Just (2,_) | a == mempty -> Nothing+ Just (i,_) -> Just (bit i :: Natural, TwoPower i a b)+ where options = [(i, bit (i-2) :: Natural) | i <- [2..k]]+ worksb (_,phi) = phi `stimes` b == mempty++#if !MIN_VERSION_base(4,12,0)+newtype Ap f a = Ap { getAp :: f a }+ deriving (Eq, Functor, Applicative, Monad)++instance (Applicative f, Semigroup a) => Semigroup (Ap f a) where+ (<>) = liftA2 (<>)++instance (Applicative f, Semigroup a, Monoid a) => Monoid (Ap f a) where+ mempty = pure mempty+ mappend = (<>)+#endif++-- | Similar to Maybe, but with different Semigroup and Monoid instances.+type OrZero a = Ap Maybe a++-- | 'Ap' 'Nothing'+pattern Zero :: OrZero a+pattern Zero = Ap Nothing++-- | 'Ap' ('Just' x)+pattern NonZero :: a -> OrZero a+pattern NonZero x = Ap (Just x)++{-# COMPLETE Zero, NonZero #-}++-- | Interpret an `OrZero` as a number, taking the `Zero` case to be 0.+orZeroToNum :: Num a => (b -> a) -> OrZero b -> a+orZeroToNum _ Zero = 0+orZeroToNum f (NonZero x) = f x++-- | In general, evaluating a DirichletCharacter at a point involves solving the discrete logarithm+-- problem, which can be hard: the implementations here are around O(sqrt n).+-- However, evaluating a dirichlet character at every point amounts to solving the discrete+-- logarithm problem at every point also, which can be done together in O(n) time, better than+-- using a complex algorithm at each point separately. Thus, if a large number of evaluations+-- of a dirichlet character are required, `evalAll` will be better than `evalGeneral`, since+-- computations can be shared.+evalAll :: forall n. KnownNat n => DirichletCharacter n -> Vector (OrZero RootOfUnity)+evalAll (Generated xs) = V.generate (fromIntegral n) func+ where n = natVal (Proxy :: Proxy n)+ vectors = map mkVector xs+ func :: Int -> OrZero RootOfUnity+ func m = foldMap go vectors+ where go :: (Int, Vector (OrZero RootOfUnity)) -> OrZero RootOfUnity+ go (modulus,v) = v ! (m `mod` modulus)+ mkVector :: DirichletFactor -> (Int, Vector (OrZero RootOfUnity))+ mkVector Two = (2, V.fromList [Zero, mempty])+ mkVector (OddPrime p k (fromIntegral -> g) a) = (modulus, w)+ where+ p' = unPrime p+ modulus = fromIntegral (p'^k) :: Int+ w = V.create $ do+ v <- MV.replicate modulus Zero+ -- TODO: we're in the ST monad here anyway, could be better to use STRefs to manage+ -- this loop, the current implementation probably doesn't fuse well+ let powers = iterateMaybe go (1,mempty)+ go (m,x) = if m' > 1+ then Just (m', x<>a)+ else Nothing+ where m' = m*g `mod` modulus+ for_ powers $ \(m,x) -> MV.unsafeWrite v m (NonZero x)+ -- don't bother with bounds check since m was reduced mod p^k+ return v+ -- for powers of two we use lambda directly instead, since the generators of the cyclic+ -- groups aren't obvious; it's possible to get them though:+ -- 5^(lambda(5)^{-1} mod 2^(p-2)) mod 2^p+ mkVector (TwoPower k a b) = (modulus, w)+ where+ modulus = bit k+ w = V.generate modulus f+ f m+ | even m = Zero+ | otherwise = NonZero ((if testBit m 1 then a else mempty) <> lambda (toInteger m'') k `stimes` b)+ where m'' = thingy k m++-- somewhere between unfoldr and iterate+iterateMaybe :: (a -> Maybe a) -> a -> [a]+iterateMaybe f x = unfoldr (fmap (\t -> (t, f t))) (Just x)++-- | Attempt to construct a character from its table of values.+-- An inverse to `evalAll`, defined only on its image.+fromTable :: forall n. KnownNat n => Vector (OrZero RootOfUnity) -> Maybe (DirichletCharacter n)+fromTable v = if length v == fromIntegral n+ then Generated <$> traverse makeFactor tmpl >>= check+ else Nothing+ where n = natVal (Proxy :: Proxy n)+ n' = fromIntegral n :: Integer+ tmpl = snd (mkTemplate n)+ check :: DirichletCharacter n -> Maybe (DirichletCharacter n)+ check chi = if evalAll chi == v then Just chi else Nothing+ makeFactor :: Template -> Maybe DirichletFactor+ makeFactor TwoTemplate = Just Two+ makeFactor (TwoPTemplate k _) = TwoPower k <$> getValue (-1,bit k) <*> getValue (exp4 k, bit k)+ makeFactor (OddTemplate p k g _) = OddPrime p k g <$> getValue (toInteger g, toInteger (unPrime p)^k)+ getValue :: (Integer,Integer) -> Maybe RootOfUnity+ getValue (g,m) = getAp (v ! fromInteger (fromJust (chinese (g,m) (1,n' `quot` m)) `mod` n'))++exp4terms :: [Rational]+exp4terms = [4^k % product [1..k] | k <- [0..]]++-- For reasons that aren't clear to me, `exp4` gives the inverse of 1 under lambda, so it gives the generator+-- This is the same as https://oeis.org/A320814+-- In particular, lambda (exp4 n) n == 1 (for n >= 3)+-- I've verified this for 3 <= n <= 2000, so the reasoning in fromTable should be accurate for moduli below 2^2000+exp4 :: Int -> Integer+exp4 n = (`mod` bit n) $ sum $ map (`mod` bit n) $ map (\q -> numerator q * fromMaybe (error "error in exp4") (recipMod (denominator q) (bit n))) $ take n $ exp4terms
Math/NumberTheory/Euclidean.hs view
@@ -3,6 +3,7 @@ -- Copyright: (c) 2018 Alexandre Rodrigues Baldé -- Licence: MIT -- Maintainer: Alexandre Rodrigues Baldé <alexandrer_b@outlook.com>+-- Description: Deprecated -- -- This module exports a class to represent Euclidean domains. --@@ -13,7 +14,7 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE ScopedTypeVariables #-} -module Math.NumberTheory.Euclidean+module Math.NumberTheory.Euclidean {-# DEPRECATED "Use Data.Euclidean instead" #-} ( GcdDomain(..) , Euclidean(..) , WrappedIntegral(..)
Math/NumberTheory/Euclidean/Coprimes.hs view
@@ -20,6 +20,7 @@ import Prelude hiding (gcd, quot, rem) import Data.Coerce+import Data.Euclidean import Data.List (tails, mapAccumL) import Data.Maybe #if __GLASGOW_HASKELL__ < 803@@ -27,8 +28,6 @@ #endif import Data.Semiring (Semiring(..), isZero) -import Math.NumberTheory.Euclidean- -- | A list of pairwise coprime numbers -- with their multiplicities. newtype Coprimes a b = Coprimes {@@ -41,6 +40,10 @@ Nothing -> error "violated prerequisite of unsafeDivide" Just z -> z +-- | Check whether an element is a unit of the ring.+isUnit :: (Eq a, GcdDomain a) => a -> Bool+isUnit x = not (isZero x) && isJust (one `divide` x)+ doPair :: (Eq a, GcdDomain a, Eq b, Num b) => a -> b -> a -> b -> (a, a, [(a, b)]) doPair x xm y ym | isUnit g = (x, y, [])@@ -52,7 +55,7 @@ xgs' = if isUnit g' then xgs else ((g', xm + ym) : xgs) (y', rests) = mapAccumL go (y `unsafeDivide` g) xgs'- go w (t, tm) = (w', if isUnit t' then acc else (t', tm) : acc)+ go w (t, tm) = (w', if isUnit t' || tm == 0 then acc else (t', tm) : acc) where (w', t', acc) = doPair w ym t tm
Math/NumberTheory/Moduli.hs view
@@ -10,15 +10,13 @@ module Math.NumberTheory.Moduli ( module Math.NumberTheory.Moduli.Class , module Math.NumberTheory.Moduli.Chinese- , module Math.NumberTheory.Moduli.DiscreteLogarithm- , module Math.NumberTheory.Moduli.Jacobi- , module Math.NumberTheory.Moduli.PrimitiveRoot+ , module Math.NumberTheory.Moduli.Multiplicative+ , module Math.NumberTheory.Moduli.Singleton , module Math.NumberTheory.Moduli.Sqrt ) where import Math.NumberTheory.Moduli.Chinese import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Moduli.DiscreteLogarithm-import Math.NumberTheory.Moduli.Jacobi-import Math.NumberTheory.Moduli.PrimitiveRoot+import Math.NumberTheory.Moduli.Multiplicative+import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.Moduli.Sqrt
Math/NumberTheory/Moduli/Chinese.hs view
@@ -31,18 +31,18 @@ , chineseRemainder2 ) where -import Prelude hiding (rem, quot, gcd, lcm)+import Prelude hiding ((^), (+), (-), (*), rem, mod, quot, gcd, lcm)+import qualified Prelude import Control.Monad (foldM)-import Data.Foldable+import Data.Euclidean+import Data.Mod import Data.Ratio-import GHC.TypeNats.Compat-import Numeric.Natural+import Data.Semiring (Semiring(..), (+), (-), (*), Ring)+import GHC.TypeNats (KnownNat, natVal) -import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Euclidean-import Math.NumberTheory.Euclidean.Coprimes-import Math.NumberTheory.Utils (recipMod, splitOff)+import Math.NumberTheory.Moduli.SomeMod+import Math.NumberTheory.Utils (recipMod) -- | 'chineseCoprime' @(n1, m1)@ @(n2, m2)@ returns @n@ such that -- @n \`mod\` m1 == n1@ and @n \`mod\` m2 == n2@.@@ -54,17 +54,14 @@ -- Just 5 -- >>> chineseCoprime (3, 4) (5, 6) -- Nothing -- moduli must be coprime-chineseCoprime :: (Integral a, Euclidean a) => (a, a) -> (a, a) -> Maybe a-chineseCoprime (n1, m1) (n2, m2) = case d of- 1 -> Just $ ((1 - u * m1) * n1 + (1 - v * m2) * n2) `mod` (m1 * m2)- _ -> Nothing+chineseCoprime :: (Eq a, Ring a, Euclidean a) => (a, a) -> (a, a) -> Maybe a+chineseCoprime (n1, m1) (n2, m2)+ | d == one+ = Just $ (v * m2 * n1 + u * m1 * n2) `rem` (m1 * m2)+ | otherwise = Nothing where (d, u, v) = extendedGCD m1 m2--{-# SPECIALISE chineseCoprime :: (Int, Int) -> (Int, Int) -> Maybe Int #-}-{-# SPECIALISE chineseCoprime :: (Word, Word) -> (Word, Word) -> Maybe Word #-}-{-# SPECIALISE chineseCoprime :: (Integer, Integer) -> (Integer, Integer) -> Maybe Integer #-}-{-# SPECIALISE chineseCoprime :: (Natural, Natural) -> (Natural, Natural) -> Maybe Natural #-}+{-# DEPRECATED chineseCoprime "Use 'chinese' instead" #-} -- | 'chinese' @(n1, m1)@ @(n2, m2)@ returns @n@ such that -- @n \`mod\` m1 == n1@ and @n \`mod\` m2 == n2@, if exists.@@ -76,36 +73,20 @@ -- Just 11 -- >>> chinese (3, 4) (2, 6) -- Nothing-chinese :: forall a. (Integral a, GcdDomain a, Euclidean a) => (a, a) -> (a, a) -> Maybe a+chinese :: forall a. (Eq a, Ring a, Euclidean a) => (a, a) -> (a, a) -> Maybe a chinese (n1, m1) (n2, m2)- | (n1 - n2) `rem` g == 0- = chineseCoprime (n1 `mod` m1', m1') (n2 `mod` m2', m2')+ | d == one+ = Just $ (v * m2 * n1 + u * m1 * n2) `rem` (m1 * m2)+ | (n1 - n2) `rem` d == zero+ = Just $ (v * (m2 `quot` d) * n1 + u * (m1 `quot` d) * n2) `rem` ((m1 `quot` d) * m2) | otherwise = Nothing where- g :: a- g = gcd m1 m2-- ms :: [(a, Word)]- ms = unCoprimes $ splitIntoCoprimes [(m1, 1), (m2 `quot` g, 1)]-- m1', m2' :: a- (m1', m2') = foldl' go (1, 1) $ map fst ms-- go :: (a, a) -> a -> (a, a)- go (t1, t2) p- | k1 <= k2- = (t1, t2 * p ^ k2)- | otherwise- = (t1 * p ^ k1, t2)- where- (k1, _) = splitOff p m1- (k2, _) = splitOff p m2+ (d, u, v) = extendedGCD m1 m2 {-# SPECIALISE chinese :: (Int, Int) -> (Int, Int) -> Maybe Int #-} {-# SPECIALISE chinese :: (Word, Word) -> (Word, Word) -> Maybe Word #-} {-# SPECIALISE chinese :: (Integer, Integer) -> (Integer, Integer) -> Maybe Integer #-}-{-# SPECIALISE chinese :: (Natural, Natural) -> (Natural, Natural) -> Maybe Natural #-} isCompatible :: KnownNat m => Mod m -> Rational -> Bool isCompatible n r = case invertMod (fromInteger (denominator r)) of@@ -119,10 +100,10 @@ -> SomeMod -> Maybe SomeMod chineseWrap f g (SomeMod n1) (SomeMod n2)- = fmap (`modulo` fromInteger (f m1 m2)) (g (getVal n1, m1) (getVal n2, m2))+ = fmap (`modulo` fromInteger (f m1 m2)) (g (toInteger $ unMod n1, m1) (toInteger $ unMod n2, m2)) where- m1 = getMod n1- m2 = getMod n2+ m1 = toInteger $ natVal n1+ m2 = toInteger $ natVal n2 chineseWrap _ _ (SomeMod n) (InfMod r) | isCompatible n r = Just $ InfMod r | otherwise = Nothing@@ -143,6 +124,7 @@ -- Nothing chineseCoprimeSomeMod :: SomeMod -> SomeMod -> Maybe SomeMod chineseCoprimeSomeMod = chineseWrap (*) chineseCoprime+{-# DEPRECATED chineseCoprimeSomeMod "Use 'chineseSomeMod' instead" #-} -- | Same as 'chinese', but operates on residues. --@@ -179,7 +161,8 @@ addRem acc (r,m) = do let cf = modulus `quot` m inv <- recipMod cf m- Just $! (acc + inv*cf*r) `mod` modulus+ Just $! (acc + inv*cf*r) `rem` modulus+{-# DEPRECATED chineseRemainder "Use 'chinese' instead" #-} -- | @chineseRemainder2 (r_1,m_1) (r_2,m_2)@ calculates the solution of --@@ -188,6 +171,16 @@ -- -- if @m_1@ and @m_2@ are coprime. chineseRemainder2 :: (Integer, Integer) -> (Integer, Integer) -> Integer-chineseRemainder2 (n1, m1) (n2, m2) = ((1 - u * m1) * n1 + (1 - v * m2) * n2) `mod` (m1 * m2)+chineseRemainder2 (n1, m1) (n2, m2) = ((1 - u * m1) * n1 + (1 - v * m2) * n2) `Prelude.mod` (m1 * m2) where (_, u, v) = extendedGCD m1 m2+{-# DEPRECATED chineseRemainder2 "Use 'chinese' instead" #-}++-------------------------------------------------------------------------------+-- Utils++extendedGCD :: (Eq a, Ring a, Euclidean a) => a -> a -> (a, a, a)+extendedGCD a b = (g, s, t)+ where+ (g, s) = gcdExt a b+ t = (g - a * s) `quot` b
Math/NumberTheory/Moduli/Class.hs view
@@ -43,94 +43,12 @@ , KnownNat ) where -import Data.Proxy-import Data.Ratio-import Data.Semigroup-import Data.Type.Equality-import GHC.Exts-import GHC.Integer.GMP.Internals-import GHC.Natural (Natural(..), powModNatural)-import GHC.TypeNats.Compat---- | Wrapper for residues modulo @m@.------ @Mod 3 :: Mod 10@ stands for the class of integers, congruent to 3 modulo 10 (…−17, −7, 3, 13, 23…).--- The modulo is stored on type level, so it is impossible, for example, to add up by mistake--- residues with different moduli.------ >>> :set -XDataKinds--- >>> (3 :: Mod 10) + (4 :: Mod 12)--- error: Couldn't match type ‘12’ with ‘10’...--- >>> (3 :: Mod 10) + 8--- (1 `modulo` 10)------ Note that modulo cannot be negative.-newtype Mod (m :: Nat) = Mod Natural- deriving (Eq, Ord, Enum)--instance KnownNat m => Show (Mod m) where- show m = "(" ++ show (getVal m) ++ " `modulo` " ++ show (getMod m) ++ ")"--instance KnownNat m => Bounded (Mod m) where- minBound = Mod 0- maxBound = let mx = Mod (getNatMod mx - 1) in mx--instance KnownNat m => Num (Mod m) where- mx@(Mod x) + Mod y =- Mod $ if xy >= m then xy - m else xy- where- xy = x + y- m = getNatMod mx- {-# INLINE (+) #-}- mx@(Mod x) - Mod y =- Mod $ if x >= y then x - y else m + x - y- where- m = getNatMod mx- {-# INLINE (-) #-}- negate mx@(Mod x) =- Mod $ if x == 0 then 0 else getNatMod mx - x- {-# INLINE negate #-}-- -- If modulo is small and fits into one machine word,- -- there is no need to use long arithmetic at all- -- and we can save some allocations.- mx@(Mod (NatS# x#)) * (Mod (NatS# y#)) = case getNatMod mx of- NatS# m# -> let !(# z1#, z2# #) = timesWord2# x# y# in- let !(# _, r# #) = quotRemWord2# z1# z2# m# in- Mod (NatS# r#)- NatJ# b# -> let !(# z1#, z2# #) = timesWord2# x# y# in- let r# = wordToBigNat2 z1# z2# `remBigNat` b# in- Mod $ if isTrue# (sizeofBigNat# r# ==# 1#)- then NatS# (bigNatToWord r#)- else NatJ# r#-- mx@(Mod !x) * (Mod !y) =- Mod $ x * y `rem` getNatMod mx- -- `rem` is slightly faster than `mod`- {-# INLINE (*) #-}-- abs = id- {-# INLINE abs #-}- signum = const $ Mod 1- {-# INLINE signum #-}- fromInteger x = mx- where- mx = Mod $ fromInteger $ x `mod` getMod mx- {-# INLINE fromInteger #-}+import Data.Mod+import GHC.Natural+import GHC.TypeNats (KnownNat, natVal) --- | Beware that division by residue, which is not coprime with the modulo,--- will result in runtime error. Consider using 'invertMod' instead.-instance KnownNat m => Fractional (Mod m) where- fromRational r = case denominator r of- 1 -> num- den -> num / fromInteger den- where- num = fromInteger (numerator r)- {-# INLINE fromRational #-}- recip mx = case invertMod mx of- Nothing -> error $ "recip{Mod}: residue is not coprime with modulo"- Just y -> y- {-# INLINE recip #-}+import Math.NumberTheory.Moduli.Multiplicative+import Math.NumberTheory.Moduli.SomeMod -- | Linking type and value levels: extract modulo @m@ as a value. getMod :: KnownNat m => Mod m -> Integer@@ -142,239 +60,17 @@ getNatMod = natVal {-# INLINE getNatMod #-} --- | The canonical representative of the residue class, always between 0 and @m-1@ inclusively.+-- | The canonical representative of the residue class, always between 0 and m-1 inclusively. getVal :: Mod m -> Integer-getVal (Mod x) = toInteger x+getVal = toInteger . unMod {-# INLINE getVal #-} --- | The canonical representative of the residue class, always between 0 and @m-1@ inclusively.+-- | The canonical representative of the residue class, always between 0 and m-1 inclusively. getNatVal :: Mod m -> Natural-getNatVal (Mod x) = x+getNatVal = unMod {-# INLINE getNatVal #-} --- | Computes the modular inverse, if the residue is coprime with the modulo.------ >>> :set -XDataKinds--- >>> invertMod (3 :: Mod 10)--- Just (7 `modulo` 10) -- because 3 * 7 = 1 :: Mod 10--- >>> invertMod (4 :: Mod 10)--- Nothing-invertMod :: KnownNat m => Mod m -> Maybe (Mod m)-invertMod mx- = if y <= 0- then Nothing- else Just $ Mod $ fromInteger y- where- -- first argument of recipModInteger is guaranteed to be positive- y = recipModInteger (getVal mx) (getMod mx)-{-# INLINABLE invertMod #-}---- | Drop-in replacement for 'Prelude.^', with much better performance.------ >>> :set -XDataKinds--- >>> powMod (3 :: Mod 10) 4--- (1 `modulo` 10)+-- | Synonym of '(^%)'. powMod :: (KnownNat m, Integral a) => Mod m -> a -> Mod m-powMod mx a- | a < 0 = error $ "^{Mod}: negative exponent"- | otherwise = Mod $ powModNatural (getNatVal mx) (fromIntegral a) (getNatMod mx)-{-# INLINABLE [1] powMod #-}--{-# SPECIALISE [1] powMod ::- KnownNat m => Mod m -> Integer -> Mod m,- KnownNat m => Mod m -> Natural -> Mod m,- KnownNat m => Mod m -> Int -> Mod m,- KnownNat m => Mod m -> Word -> Mod m #-}--{-# RULES-"powMod/2/Integer" forall x. powMod x (2 :: Integer) = let u = x in u*u-"powMod/3/Integer" forall x. powMod x (3 :: Integer) = let u = x in u*u*u-"powMod/2/Int" forall x. powMod x (2 :: Int) = let u = x in u*u-"powMod/3/Int" forall x. powMod x (3 :: Int) = let u = x in u*u*u-"powMod/2/Word" forall x. powMod x (2 :: Word) = let u = x in u*u-"powMod/3/Word" forall x. powMod x (3 :: Word) = let u = x in u*u*u-#-}---- | Infix synonym of 'powMod'.-(^%) :: (KnownNat m, Integral a) => Mod m -> a -> Mod m-(^%) = powMod-{-# INLINE (^%) #-}--infixr 8 ^%---- Unfortunately, such rule never fires due to technical details--- of type classes in Core.--- {-# RULES "^%Mod" forall (x :: KnownNat m => Mod m) p. x ^ p = x ^% p #-}---- | This type represents elements of the multiplicative group mod m, i.e.--- those elements which are coprime to m. Use @toMultElement@ to construct.-newtype MultMod m = MultMod {- multElement :: Mod m -- ^ Unwrap a residue.- } deriving (Eq, Ord, Show)--instance KnownNat m => Semigroup (MultMod m) where- MultMod a <> MultMod b = MultMod (a * b)- stimes k a@(MultMod a')- | k >= 0 = MultMod (powMod a' k)- | otherwise = invertGroup $ stimes (-k) a- -- ^ This Semigroup is in fact a group, so @stimes@ can be called with a negative first argument.--instance KnownNat m => Monoid (MultMod m) where- mempty = MultMod 1- mappend = (<>)--instance KnownNat m => Bounded (MultMod m) where- minBound = MultMod 1- maxBound = MultMod (-1)---- | Attempt to construct a multiplicative group element.-isMultElement :: KnownNat m => Mod m -> Maybe (MultMod m)-isMultElement a = if getNatVal a `gcd` getNatMod a == 1- then Just $ MultMod a- else Nothing---- | For elements of the multiplicative group, we can safely perform the inverse--- without needing to worry about failure.-invertGroup :: KnownNat m => MultMod m -> MultMod m-invertGroup (MultMod a) = case invertMod a of- Just b -> MultMod b- Nothing -> error "Math.NumberTheory.Moduli.invertGroup: failed to invert element"---- | This type represents residues with unknown modulo and rational numbers.--- One can freely combine them in arithmetic expressions, but each operation--- will spend time on modulo's recalculation:------ >>> 2 `modulo` 10 + 4 `modulo` 15--- (1 `modulo` 5)--- >>> (2 `modulo` 10) * (4 `modulo` 15)--- (3 `modulo` 5)--- >>> 2 `modulo` 10 + fromRational (3 % 7)--- (1 `modulo` 10)--- >>> 2 `modulo` 10 * fromRational (3 % 7)--- (8 `modulo` 10)------ If performance is crucial, it is recommended to extract @Mod m@ for further processing--- by pattern matching. E. g.,------ > case modulo n m of--- > SomeMod k -> process k -- Here k has type Mod m--- > InfMod{} -> error "impossible"-data SomeMod where- SomeMod :: KnownNat m => Mod m -> SomeMod- InfMod :: Rational -> SomeMod--instance Eq SomeMod where- SomeMod mx == SomeMod my =- getMod mx == getMod my && getVal mx == getVal my- InfMod rx == InfMod ry = rx == ry- _ == _ = False--instance Ord SomeMod where- SomeMod mx `compare` SomeMod my =- getMod mx `compare` getMod my <> getVal mx `compare` getVal my- SomeMod{} `compare` InfMod{} = LT- InfMod{} `compare` SomeMod{} = GT- InfMod rx `compare` InfMod ry = rx `compare` ry--instance Show SomeMod where- show = \case- SomeMod m -> show m- InfMod r -> show r---- | Create modular value by representative of residue class and modulo.--- One can use the result either directly (via functions from 'Num' and 'Fractional'),--- or deconstruct it by pattern matching. Note that 'modulo' never returns 'InfMod'.-modulo :: Integer -> Natural -> SomeMod-modulo n m = case someNatVal m of- SomeNat (_ :: Proxy t) -> SomeMod (fromInteger n :: Mod t)-{-# INLINABLE modulo #-}-infixl 7 `modulo`--liftUnOp- :: (forall k. KnownNat k => Mod k -> Mod k)- -> (Rational -> Rational)- -> SomeMod- -> SomeMod-liftUnOp fm fr = \case- SomeMod m -> SomeMod (fm m)- InfMod r -> InfMod (fr r)-{-# INLINEABLE liftUnOp #-}--liftBinOpMod- :: (KnownNat m, KnownNat n)- => (forall k. KnownNat k => Mod k -> Mod k -> Mod k)- -> Mod m- -> Mod n- -> SomeMod-liftBinOpMod f mx@(Mod x) my@(Mod y) = case someNatVal m of- SomeNat (_ :: Proxy t) -> SomeMod (Mod (x `mod` m) `f` Mod (y `mod` m) :: Mod t)- where- m = natVal mx `gcd` natVal my--liftBinOp- :: (forall k. KnownNat k => Mod k -> Mod k -> Mod k)- -> (Rational -> Rational -> Rational)- -> SomeMod- -> SomeMod- -> SomeMod-liftBinOp _ fr (InfMod rx) (InfMod ry) = InfMod (rx `fr` ry)-liftBinOp fm _ (InfMod rx) (SomeMod my) = SomeMod (fromRational rx `fm` my)-liftBinOp fm _ (SomeMod mx) (InfMod ry) = SomeMod (mx `fm` fromRational ry)-liftBinOp fm _ (SomeMod (mx :: Mod m)) (SomeMod (my :: Mod n))- = case (Proxy :: Proxy m) `sameNat` (Proxy :: Proxy n) of- Nothing -> liftBinOpMod fm mx my- Just Refl -> SomeMod (mx `fm` my)--instance Num SomeMod where- (+) = liftBinOp (+) (+)- (-) = liftBinOp (-) (+)- negate = liftUnOp negate negate- {-# INLINE negate #-}- (*) = liftBinOp (*) (*)- abs = id- {-# INLINE abs #-}- signum = const 1- {-# INLINE signum #-}- fromInteger = InfMod . fromInteger- {-# INLINE fromInteger #-}---- | Beware that division by residue, which is not coprime with the modulo,--- will result in runtime error. Consider using 'invertSomeMod' instead.-instance Fractional SomeMod where- fromRational = InfMod- {-# INLINE fromRational #-}- recip x = case invertSomeMod x of- Nothing -> error $ "recip{SomeMod}: residue is not coprime with modulo"- Just y -> y---- | Computes the inverse value, if it exists.------ >>> invertSomeMod (3 `modulo` 10)--- Just (7 `modulo` 10) -- because 3 * 7 = 1 :: Mod 10--- >>> invertSomeMod (4 `modulo` 10)--- Nothing--- >>> invertSomeMod (fromRational (2 % 5))--- Just 5 % 2-invertSomeMod :: SomeMod -> Maybe SomeMod-invertSomeMod = \case- SomeMod m -> fmap SomeMod (invertMod m)- InfMod r -> Just (InfMod (recip r))-{-# INLINABLE [1] invertSomeMod #-}--{-# SPECIALISE [1] powSomeMod ::- SomeMod -> Integer -> SomeMod,- SomeMod -> Natural -> SomeMod,- SomeMod -> Int -> SomeMod,- SomeMod -> Word -> SomeMod #-}---- | Drop-in replacement for 'Prelude.^', with much better performance.--- When -O is enabled, there is a rewrite rule, which specialises 'Prelude.^' to 'powSomeMod'.------ >>> powSomeMod (3 `modulo` 10) 4--- (1 `modulo` 10)-powSomeMod :: Integral a => SomeMod -> a -> SomeMod-powSomeMod (SomeMod m) a = SomeMod (m ^% a)-powSomeMod (InfMod r) a = InfMod (r ^ a)-{-# INLINABLE [1] powSomeMod #-}--{-# RULES "^%SomeMod" forall x p. x ^ p = powSomeMod x p #-}+powMod = (^%)+{-# INLINE powMod #-}
Math/NumberTheory/Moduli/DiscreteLogarithm.hs view
@@ -3,128 +3,12 @@ -- Copyright: (c) 2018 Bhavik Mehta -- License: MIT -- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+-- Description: Deprecated -- -{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ViewPatterns #-}--#if __GLASGOW_HASKELL__ < 801-{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}-#endif- module Math.NumberTheory.Moduli.DiscreteLogarithm+ {-# DEPRECATED "Use Math.NumberTheory.Moduli.Multiplicative instead" #-} ( discreteLogarithm ) where -import qualified Data.IntMap.Strict as M-import Data.Maybe (maybeToList)-import Data.Proxy-import Numeric.Natural (Natural)-import GHC.Integer.GMP.Internals (recipModInteger, powModInteger)-import GHC.TypeNats.Compat--import Math.NumberTheory.Moduli.Chinese (chineseRemainder2)-import Math.NumberTheory.Moduli.Class (MultMod(..), Mod, getVal)-import Math.NumberTheory.Moduli.Equations (solveLinear)-import Math.NumberTheory.Moduli.PrimitiveRoot (PrimitiveRoot(..))-import Math.NumberTheory.Moduli.Singleton-import Math.NumberTheory.Powers.Squares (integerSquareRoot)-import Math.NumberTheory.Primes (unPrime)---- | Computes the discrete logarithm. Currently uses a combination of the baby-step--- giant-step method and Pollard's rho algorithm, with Bach reduction.------ >>> :set -XDataKinds--- >>> import Data.Maybe--- >>> let cg = fromJust cyclicGroup :: CyclicGroup Integer 13--- >>> let rt = fromJust (isPrimitiveRoot cg 2)--- >>> let x = fromJust (isMultElement 11)--- >>> discreteLogarithm cg rt x--- 7-discreteLogarithm :: CyclicGroup Integer m -> PrimitiveRoot m -> MultMod m -> Natural-discreteLogarithm cg (multElement . unPrimitiveRoot -> a) (multElement -> b) = case cg of- CG2- -> 0- -- the only valid input was a=1, b=1- CG4- -> if getVal b == 1 then 0 else 1- -- the only possible input here is a=3 with b = 1 or 3- CGOddPrimePower (unPrime -> p) k- -> discreteLogarithmPP p k (getVal a) (getVal b)- CGDoubleOddPrimePower (unPrime -> p) k- -> discreteLogarithmPP p k (getVal a `rem` p^k) (getVal b `rem` p^k)- -- we have the isomorphism t -> t `rem` p^k from (Z/2p^kZ)* -> (Z/p^kZ)*---- Implementation of Bach reduction (https://www2.eecs.berkeley.edu/Pubs/TechRpts/1984/CSD-84-186.pdf)-{-# INLINE discreteLogarithmPP #-}-discreteLogarithmPP :: Integer -> Word -> Integer -> Integer -> Natural-discreteLogarithmPP p 1 a b = discreteLogarithmPrime p a b-discreteLogarithmPP p k a b = fromInteger result- where- baseSol = toInteger $ discreteLogarithmPrime p (a `rem` p) (b `rem` p)- thetaA = theta p pkMinusOne a- thetaB = theta p pkMinusOne b- pkMinusOne = p^(k-1)- c = (recipModInteger thetaA pkMinusOne * thetaB) `rem` pkMinusOne- result = chineseRemainder2 (baseSol, p-1) (c, pkMinusOne)---- compute the homomorphism theta given in https://math.stackexchange.com/a/1864495/418148-{-# INLINE theta #-}-theta :: Integer -> Integer -> Integer -> Integer-theta p pkMinusOne a = (numerator `quot` pk) `rem` pkMinusOne- where- pk = pkMinusOne * p- p2kMinusOne = pkMinusOne * pk- numerator = (powModInteger a (pk - pkMinusOne) p2kMinusOne - 1) `rem` p2kMinusOne---- TODO: Use Pollig-Hellman to reduce the problem further into groups of prime order.--- While Bach reduction simplifies the problem into groups of the form (Z/pZ)*, these--- have non-prime order, and the Pollig-Hellman algorithm can reduce the problem into--- smaller groups of prime order.--- In addition, the gcd check before solveLinear is applied in Pollard below will be--- made redundant, since n would be prime.-discreteLogarithmPrime :: Integer -> Integer -> Integer -> Natural-discreteLogarithmPrime p a b- | p < 100000000 = fromIntegral $ discreteLogarithmPrimeBSGS (fromInteger p) (fromInteger a) (fromInteger b)- | otherwise = discreteLogarithmPrimePollard p a b--discreteLogarithmPrimeBSGS :: Int -> Int -> Int -> Int-discreteLogarithmPrimeBSGS p a b = head [i*m + j | (v,i) <- zip giants [0..m-1], j <- maybeToList (M.lookup v table)]- where- m = integerSquareRoot (p - 2) + 1 -- simple way of ceiling (sqrt (p-1))- babies = iterate (.* a) 1- table = M.fromList (zip babies [0..m-1])- aInv = recipModInteger (toInteger a) (toInteger p)- bigGiant = fromInteger $ powModInteger aInv (toInteger m) (toInteger p)- giants = iterate (.* bigGiant) b- x .* y = x * y `rem` p---- TODO: Use more advanced walks, in order to reduce divisions, cf--- https://maths-people.anu.edu.au/~brent/pd/rpb231.pdf--- This will slightly improve the expected time to collision, and can reduce the--- number of divisions performed.-discreteLogarithmPrimePollard :: Integer -> Integer -> Integer -> Natural-discreteLogarithmPrimePollard p a b =- case concatMap runPollard [(x,y) | x <- [0..n], y <- [0..n]] of- (t:_) -> fromInteger t- [] -> error ("discreteLogarithm: pollard's rho failed, please report this as a bug. inputs " ++ show [p,a,b])- where- n = p-1 -- order of the cyclic group- halfN = n `quot` 2- mul2 m = if m < halfN then m * 2 else m * 2 - n- sqrtN = integerSquareRoot n- step (xi,!ai,!bi) = case xi `rem` 3 of- 0 -> (xi*xi `rem` p, mul2 ai, mul2 bi)- 1 -> ( a*xi `rem` p, ai+1, bi)- _ -> ( b*xi `rem` p, ai, bi+1)- initialise (x,y) = (powModInteger a x n * powModInteger b y n `rem` n, x, y)- begin t = go (step t) (step (step t))- check t = powModInteger a t p == b- go tort@(xi,ai,bi) hare@(x2i,a2i,b2i)- | xi == x2i, gcd (bi - b2i) n < sqrtN = case someNatVal (fromInteger n) of- SomeNat (Proxy :: Proxy n) -> map getVal $ solveLinear (fromInteger (bi - b2i) :: Mod n) (fromInteger (ai - a2i))- | xi == x2i = []- | otherwise = go (step tort) (step (step hare))- runPollard = filter check . begin . initialise+import Math.NumberTheory.Moduli.Multiplicative
Math/NumberTheory/Moduli/Equations.hs view
@@ -16,10 +16,12 @@ ) where import Data.Constraint+import Data.Maybe+import Data.Mod import GHC.Integer.GMP.Internals+import GHC.TypeNats (KnownNat, natVal) import Math.NumberTheory.Moduli.Chinese-import Math.NumberTheory.Moduli.Class import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.Moduli.Sqrt import Math.NumberTheory.Primes@@ -38,7 +40,7 @@ => Mod m -- ^ a -> Mod m -- ^ b -> [Mod m] -- ^ list of x-solveLinear a b = map fromInteger $ solveLinear' (getMod a) (getVal a) (getVal b)+solveLinear a b = map fromInteger $ solveLinear' (toInteger (natVal a)) (toInteger (unMod a)) (toInteger (unMod b)) solveLinear' :: Integer -> Integer -> Integer -> [Integer] solveLinear' m a b = case solveLinearCoprime m' (a `quot` d) (b `quot` d) of@@ -74,13 +76,13 @@ $ map (\(p, n) -> (solveQuadraticPrimePower a' b' c' p n, unPrime p ^ n)) $ unSFactors sm where- a' = getVal a- b' = getVal b- c' = getVal c+ a' = toInteger $ unMod a+ b' = toInteger $ unMod b+ c' = toInteger $ unMod c combine :: [([Integer], Integer)] -> ([Integer], Integer) combine = foldl- (\(xs, xm) (ys, ym) -> ([ chineseRemainder2 (x, xm) (y, ym) | x <- xs, y <- ys ], xm * ym))+ (\(xs, xm) (ys, ym) -> ([ fromJust $ chinese (x, xm) (y, ym) | x <- xs, y <- ys ], xm * ym)) ([0], 1) solveQuadraticPrimePower
+ Math/NumberTheory/Moduli/Internal.hs view
@@ -0,0 +1,126 @@+-- |+-- Module: Math.NumberTheory.Moduli.Internal+-- Copyright: (c) 2020 Bhavik Mehta+-- Licence: MIT+-- Maintainer: Bhavik Mehta <bhavikmehta8@gmail.com>+--+-- Multiplicative groups of integers modulo m.+--++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Math.NumberTheory.Moduli.Internal+ ( isPrimitiveRoot'+ , discreteLogarithmPP+ ) where++import qualified Data.Map as M+import Data.Maybe+import Data.Mod+import Data.Proxy+import GHC.TypeNats (SomeNat(..), someNatVal)+import GHC.Integer.GMP.Internals+import Numeric.Natural++import Math.NumberTheory.ArithmeticFunctions+import Math.NumberTheory.Moduli.Chinese+import Math.NumberTheory.Moduli.Equations+import Math.NumberTheory.Moduli.Singleton+import Math.NumberTheory.Primes+import Math.NumberTheory.Powers.Modular+import Math.NumberTheory.Roots++-- https://en.wikipedia.org/wiki/Primitive_root_modulo_n#Finding_primitive_roots+isPrimitiveRoot'+ :: (Integral a, UniqueFactorisation a)+ => CyclicGroup a m+ -> a+ -> Bool+isPrimitiveRoot' cg r =+ case cg of+ CG2 -> r == 1+ CG4 -> r == 3+ CGOddPrimePower p k -> oddPrimePowerTest (unPrime p) k r+ CGDoubleOddPrimePower p k -> doubleOddPrimePowerTest (unPrime p) k r+ where+ oddPrimeTest p g = let phi = totient p+ pows = map (\pk -> phi `quot` unPrime (fst pk)) (factorise phi)+ exps = map (\x -> powMod g x p) pows+ in g /= 0 && gcd g p == 1 && notElem 1 exps+ oddPrimePowerTest p 1 g = oddPrimeTest p (g `mod` p)+ oddPrimePowerTest p _ g = oddPrimeTest p (g `mod` p) && powMod g (p-1) (p*p) /= 1+ doubleOddPrimePowerTest p k g = odd g && oddPrimePowerTest p k g++-- Implementation of Bach reduction (https://www2.eecs.berkeley.edu/Pubs/TechRpts/1984/CSD-84-186.pdf)+{-# INLINE discreteLogarithmPP #-}+discreteLogarithmPP :: Integer -> Word -> Integer -> Integer -> Natural+discreteLogarithmPP p 1 a b = discreteLogarithmPrime p a b+discreteLogarithmPP p k a b = fromInteger $ if result < 0 then result + pkMinusPk1 else result+ where+ baseSol = toInteger $ discreteLogarithmPrime p (a `rem` p) (b `rem` p)+ thetaA = theta p pkMinusOne a+ thetaB = theta p pkMinusOne b+ pkMinusOne = p^(k-1)+ pkMinusPk1 = pkMinusOne * (p - 1)+ c = (recipModInteger thetaA pkMinusOne * thetaB) `rem` pkMinusOne+ result = fromJust $ chinese (baseSol, p-1) (c, pkMinusOne)++-- compute the homomorphism theta given in https://math.stackexchange.com/a/1864495/418148+{-# INLINE theta #-}+theta :: Integer -> Integer -> Integer -> Integer+theta p pkMinusOne a = (numerator `quot` pk) `rem` pkMinusOne+ where+ pk = pkMinusOne * p+ p2kMinusOne = pkMinusOne * pk+ numerator = (powModInteger a (pk - pkMinusOne) p2kMinusOne - 1) `rem` p2kMinusOne++-- TODO: Use Pollig-Hellman to reduce the problem further into groups of prime order.+-- While Bach reduction simplifies the problem into groups of the form (Z/pZ)*, these+-- have non-prime order, and the Pollig-Hellman algorithm can reduce the problem into+-- smaller groups of prime order.+-- In addition, the gcd check before solveLinear is applied in Pollard below will be+-- made redundant, since n would be prime.+discreteLogarithmPrime :: Integer -> Integer -> Integer -> Natural+discreteLogarithmPrime p a b+ | p < 100000000 = fromIntegral $ discreteLogarithmPrimeBSGS (fromInteger p) (fromInteger a) (fromInteger b)+ | otherwise = discreteLogarithmPrimePollard p a b++discreteLogarithmPrimeBSGS :: Int -> Int -> Int -> Int+discreteLogarithmPrimeBSGS p a b = head [i*m + j | (v,i) <- zip giants [0..m-1], j <- maybeToList (M.lookup v table)]+ where+ m = integerSquareRoot (p - 2) + 1 -- simple way of ceiling (sqrt (p-1))+ babies = iterate (.* a) 1+ table = M.fromList (zip babies [0..m-1])+ aInv = recipModInteger (toInteger a) (toInteger p)+ bigGiant = fromInteger $ powModInteger aInv (toInteger m) (toInteger p)+ giants = iterate (.* bigGiant) b+ x .* y = x * y `rem` p++-- TODO: Use more advanced walks, in order to reduce divisions, cf+-- https://maths-people.anu.edu.au/~brent/pd/rpb231.pdf+-- This will slightly improve the expected time to collision, and can reduce the+-- number of divisions performed.+discreteLogarithmPrimePollard :: Integer -> Integer -> Integer -> Natural+discreteLogarithmPrimePollard p a b =+ case concatMap runPollard [(x,y) | x <- [0..n], y <- [0..n]] of+ (t:_) -> fromInteger t+ [] -> error ("discreteLogarithm: pollard's rho failed, please report this as a bug. inputs " ++ show [p,a,b])+ where+ n = p-1 -- order of the cyclic group+ halfN = n `quot` 2+ mul2 m = if m < halfN then m * 2 else m * 2 - n+ sqrtN = integerSquareRoot n+ step (xi,!ai,!bi) = case xi `rem` 3 of+ 0 -> (xi*xi `rem` p, mul2 ai, mul2 bi)+ 1 -> ( a*xi `rem` p, ai+1, bi)+ _ -> ( b*xi `rem` p, ai, bi+1)+ initialise (x,y) = (powModInteger a x n * powModInteger b y n `rem` n, x, y)+ begin t = go (step t) (step (step t))+ check t = powModInteger a t p == b+ go tort@(xi,ai,bi) hare@(x2i,a2i,b2i)+ | xi == x2i, gcd (bi - b2i) n < sqrtN = case someNatVal (fromInteger n) of+ SomeNat (Proxy :: Proxy n) -> map (toInteger . unMod) $ solveLinear (fromInteger (bi - b2i) :: Mod n) (fromInteger (ai - a2i))+ | xi == x2i = []+ | otherwise = go (step tort) (step (step hare))+ runPollard = filter check . begin . initialise
Math/NumberTheory/Moduli/Jacobi.hs view
@@ -3,118 +3,16 @@ -- Copyright: (c) 2011 Daniel Fischer, 2017-2018 Andrew Lelechenko -- Licence: MIT -- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+-- Description: Deprecated -- -- <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol> -- is a generalization of the Legendre symbol, useful for primality -- testing and integer factorization. -- -{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE LambdaCase #-}--{-# OPTIONS_GHC -fno-warn-deprecations #-}- module Math.NumberTheory.Moduli.Jacobi- ( JacobiSymbol(..)- , jacobi+ {-# DEPRECATED "Use Math.NumberTheory.Moduli.Sqrt instead" #-}+ ( module Math.NumberTheory.Moduli.JacobiSymbol ) where -import Data.Bits-#if __GLASGOW_HASKELL__ < 803-import Data.Semigroup-#endif-import Numeric.Natural--import Math.NumberTheory.Utils---- | Represents three possible values of--- <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol>.-data JacobiSymbol = MinusOne | Zero | One- deriving (Eq, Ord, Show)--instance Semigroup JacobiSymbol where- (<>) = \case- MinusOne -> negJS- Zero -> const Zero- One -> id--instance Monoid JacobiSymbol where- mempty = One- mappend = (<>)--negJS :: JacobiSymbol -> JacobiSymbol-negJS = \case- MinusOne -> One- Zero -> Zero- One -> MinusOne---- | <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol> of two arguments.--- The lower argument (\"denominator\") must be odd and positive,--- this condition is checked.------ If arguments have a common factor, the result--- is 'Zero', otherwise it is 'MinusOne' or 'One'.------ >>> jacobi 1001 9911--- Zero -- arguments have a common factor 11--- >>> jacobi 1001 9907--- MinusOne-{-# SPECIALISE jacobi :: Integer -> Integer -> JacobiSymbol,- Natural -> Natural -> JacobiSymbol,- Int -> Int -> JacobiSymbol,- Word -> Word -> JacobiSymbol- #-}-jacobi :: (Integral a, Bits a) => a -> a -> JacobiSymbol-jacobi _ 1 = One-jacobi a b- | b < 0 = error "Math.NumberTheory.Moduli.jacobi: negative denominator"- | evenI b = error "Math.NumberTheory.Moduli.jacobi: even denominator"- | otherwise = jacobi' a b -- b odd, > 1--jacobi' :: (Integral a, Bits a) => a -> a -> JacobiSymbol-jacobi' 0 _ = Zero-jacobi' 1 _ = One-jacobi' a b- | a < 0 = let n = if rem4is3 b then MinusOne else One- (z, o) = shiftToOddCount (negate a)- s = if evenI z || rem8is1or7 b then n else negJS n- in s <> jacobi' o b- | a >= b = case a `rem` b of- 0 -> Zero- r -> jacPS One r b- | evenI a = case shiftToOddCount a of- (z, o) -> let r = if rem4is3 o && rem4is3 b then MinusOne else One- s = if evenI z || rem8is1or7 b then r else negJS r- in jacOL s b o- | otherwise = jacOL (if rem4is3 a && rem4is3 b then MinusOne else One) b a---- numerator positive and smaller than denominator-jacPS :: (Integral a, Bits a) => JacobiSymbol -> a -> a -> JacobiSymbol-jacPS !acc a b- | evenI a = case shiftToOddCount a of- (z, o)- | evenI z || rem8is1or7 b -> jacOL (if rem4is3 o && rem4is3 b then negJS acc else acc) b o- | otherwise -> jacOL (if rem4is3 o && rem4is3 b then acc else negJS acc) b o- | otherwise = jacOL (if rem4is3 a && rem4is3 b then negJS acc else acc) b a---- numerator odd, positive and larger than denominator-jacOL :: (Integral a, Bits a) => JacobiSymbol -> a -> a -> JacobiSymbol-jacOL !acc _ 1 = acc-jacOL !acc a b = case a `rem` b of- 0 -> Zero- r -> jacPS acc r b---- Utilities---- Sadly, GHC do not optimise `Prelude.even` to a bit test automatically.-evenI :: Bits a => a -> Bool-evenI n = not (n `testBit` 0)---- For an odd input @n@ test whether n `rem` 4 == 1-rem4is3 :: Bits a => a -> Bool-rem4is3 n = n `testBit` 1---- For an odd input @n@ test whether (n `rem` 8) `elem` [1, 7]-rem8is1or7 :: Bits a => a -> Bool-rem8is1or7 n = n `testBit` 1 == n `testBit` 2+import Math.NumberTheory.Moduli.JacobiSymbol
+ Math/NumberTheory/Moduli/JacobiSymbol.hs view
@@ -0,0 +1,128 @@+-- |+-- Module: Math.NumberTheory.Moduli.JacobiSymbol+-- Copyright: (c) 2011 Daniel Fischer, 2017-2018 Andrew Lelechenko+-- Licence: MIT+-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+-- Description: Deprecated+--+-- <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol>+-- is a generalization of the Legendre symbol, useful for primality+-- testing and integer factorization.+--++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}++module Math.NumberTheory.Moduli.JacobiSymbol+ ( JacobiSymbol(..)+ , jacobi+ , symbolToNum+ ) where++import Data.Bits+#if __GLASGOW_HASKELL__ < 803+import Data.Semigroup+#endif+import Numeric.Natural++import Math.NumberTheory.Utils++-- | Represents three possible values of+-- <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol>.+data JacobiSymbol = MinusOne | Zero | One+ deriving (Eq, Ord, Show)++instance Semigroup JacobiSymbol where+ (<>) = \case+ MinusOne -> negJS+ Zero -> const Zero+ One -> id++negJS :: JacobiSymbol -> JacobiSymbol+negJS = \case+ MinusOne -> One+ Zero -> Zero+ One -> MinusOne++{-# SPECIALISE symbolToNum :: JacobiSymbol -> Integer,+ JacobiSymbol -> Int,+ JacobiSymbol -> Word,+ JacobiSymbol -> Natural+ #-}+-- | Convenience function to convert out of a Jacobi symbol+symbolToNum :: Num a => JacobiSymbol -> a+symbolToNum = \case+ Zero -> 0+ One -> 1+ MinusOne -> -1++-- | <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol> of two arguments.+-- The lower argument (\"denominator\") must be odd and positive,+-- this condition is checked.+--+-- If arguments have a common factor, the result+-- is 'Zero', otherwise it is 'MinusOne' or 'One'.+--+-- >>> jacobi 1001 9911+-- Zero -- arguments have a common factor 11+-- >>> jacobi 1001 9907+-- MinusOne+{-# SPECIALISE jacobi :: Integer -> Integer -> JacobiSymbol,+ Natural -> Natural -> JacobiSymbol,+ Int -> Int -> JacobiSymbol,+ Word -> Word -> JacobiSymbol+ #-}+jacobi :: (Integral a, Bits a) => a -> a -> JacobiSymbol+jacobi _ 1 = One+jacobi a b+ | b < 0 = error "Math.NumberTheory.Moduli.jacobi: negative denominator"+ | evenI b = error "Math.NumberTheory.Moduli.jacobi: even denominator"+ | otherwise = jacobi' a b -- b odd, > 1++jacobi' :: (Integral a, Bits a) => a -> a -> JacobiSymbol+jacobi' 0 _ = Zero+jacobi' 1 _ = One+jacobi' a b+ | a < 0 = let n = if rem4is3 b then MinusOne else One+ (z, o) = shiftToOddCount (negate a)+ s = if evenI z || rem8is1or7 b then n else negJS n+ in s <> jacobi' o b+ | a >= b = case a `rem` b of+ 0 -> Zero+ r -> jacPS One r b+ | evenI a = case shiftToOddCount a of+ (z, o) -> let r = if rem4is3 o && rem4is3 b then MinusOne else One+ s = if evenI z || rem8is1or7 b then r else negJS r+ in jacOL s b o+ | otherwise = jacOL (if rem4is3 a && rem4is3 b then MinusOne else One) b a++-- numerator positive and smaller than denominator+jacPS :: (Integral a, Bits a) => JacobiSymbol -> a -> a -> JacobiSymbol+jacPS !acc a b+ | evenI a = case shiftToOddCount a of+ (z, o)+ | evenI z || rem8is1or7 b -> jacOL (if rem4is3 o && rem4is3 b then negJS acc else acc) b o+ | otherwise -> jacOL (if rem4is3 o && rem4is3 b then acc else negJS acc) b o+ | otherwise = jacOL (if rem4is3 a && rem4is3 b then negJS acc else acc) b a++-- numerator odd, positive and larger than denominator+jacOL :: (Integral a, Bits a) => JacobiSymbol -> a -> a -> JacobiSymbol+jacOL !acc _ 1 = acc+jacOL !acc a b = case a `rem` b of+ 0 -> Zero+ r -> jacPS acc r b++-- Utilities++-- Sadly, GHC do not optimise `Prelude.even` to a bit test automatically.+evenI :: Bits a => a -> Bool+evenI n = not (n `testBit` 0)++-- For an odd input @n@ test whether n `rem` 4 == 1+rem4is3 :: Bits a => a -> Bool+rem4is3 n = n `testBit` 1++-- For an odd input @n@ test whether (n `rem` 8) `elem` [1, 7]+rem8is1or7 :: Bits a => a -> Bool+rem8is1or7 n = n `testBit` 1 == n `testBit` 2
+ Math/NumberTheory/Moduli/Multiplicative.hs view
@@ -0,0 +1,121 @@+-- |+-- Module: Math.NumberTheory.Moduli.Multiplicative+-- Copyright: (c) 2017 Andrew Lelechenko+-- Licence: MIT+-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+--+-- Multiplicative groups of integers modulo m.+--++{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE PatternSynonyms #-}++module Math.NumberTheory.Moduli.Multiplicative+ ( -- * Multiplicative group+ MultMod+ , multElement+ , isMultElement+ , invertGroup+ -- * Primitive roots+ , PrimitiveRoot+ , unPrimitiveRoot+ , isPrimitiveRoot+ , discreteLogarithm+ ) where++import Control.Monad+import Data.Constraint+import Data.Mod+import Data.Semigroup+import GHC.TypeNats (KnownNat, natVal)+import Numeric.Natural++import Math.NumberTheory.Moduli.Internal+import Math.NumberTheory.Moduli.Singleton+import Math.NumberTheory.Primes++-- | This type represents elements of the multiplicative group mod m, i.e.+-- those elements which are coprime to m. Use @toMultElement@ to construct.+newtype MultMod m = MultMod {+ multElement :: Mod m -- ^ Unwrap a residue.+ } deriving (Eq, Ord, Show)++instance KnownNat m => Semigroup (MultMod m) where+ MultMod a <> MultMod b = MultMod (a * b)+ stimes k a@(MultMod a')+ | k >= 0 = MultMod (a' ^% k)+ | otherwise = invertGroup $ stimes (-k) a+ -- ^ This Semigroup is in fact a group, so @stimes@ can be called with a negative first argument.++instance KnownNat m => Monoid (MultMod m) where+ mempty = MultMod 1+ mappend = (<>)++instance KnownNat m => Bounded (MultMod m) where+ minBound = MultMod 1+ maxBound = MultMod (-1)++-- | Attempt to construct a multiplicative group element.+isMultElement :: KnownNat m => Mod m -> Maybe (MultMod m)+isMultElement a = if unMod a `gcd` natVal a == 1+ then Just $ MultMod a+ else Nothing++-- | For elements of the multiplicative group, we can safely perform the inverse+-- without needing to worry about failure.+invertGroup :: KnownNat m => MultMod m -> MultMod m+invertGroup (MultMod a) = case invertMod a of+ Just b -> MultMod b+ Nothing -> error "Math.NumberTheory.Moduli.invertGroup: failed to invert element"++-- | 'PrimitiveRoot' m is a type which is only inhabited+-- by <https://en.wikipedia.org/wiki/Primitive_root_modulo_n primitive roots> of m.+newtype PrimitiveRoot m = PrimitiveRoot+ { unPrimitiveRoot :: MultMod m -- ^ Extract primitive root value.+ }+ deriving (Eq, Show)++-- | Check whether a given modular residue is+-- a <https://en.wikipedia.org/wiki/Primitive_root_modulo_n primitive root>.+--+-- >>> :set -XDataKinds+-- >>> import Data.Maybe+-- >>> isPrimitiveRoot (fromJust cyclicGroup) (1 :: Mod 13)+-- Nothing+-- >>> isPrimitiveRoot (fromJust cyclicGroup) (2 :: Mod 13)+-- Just (PrimitiveRoot {unPrimitiveRoot = MultMod {multElement = (2 `modulo` 13)}})+isPrimitiveRoot+ :: (Integral a, UniqueFactorisation a)+ => CyclicGroup a m+ -> Mod m+ -> Maybe (PrimitiveRoot m)+isPrimitiveRoot cg r = case proofFromCyclicGroup cg of+ Sub Dict -> do+ r' <- isMultElement r+ guard $ isPrimitiveRoot' cg (fromIntegral (unMod r))+ return $ PrimitiveRoot r'++-- | Computes the discrete logarithm. Currently uses a combination of the baby-step+-- giant-step method and Pollard's rho algorithm, with Bach reduction.+--+-- >>> :set -XDataKinds+-- >>> import Data.Maybe+-- >>> let cg = fromJust cyclicGroup :: CyclicGroup Integer 13+-- >>> let rt = fromJust (isPrimitiveRoot cg 2)+-- >>> let x = fromJust (isMultElement 11)+-- >>> discreteLogarithm cg rt x+-- 7+discreteLogarithm :: CyclicGroup Integer m -> PrimitiveRoot m -> MultMod m -> Natural+discreteLogarithm cg (multElement . unPrimitiveRoot -> a) (multElement -> b) = case cg of+ CG2+ -> 0+ -- the only valid input was a=1, b=1+ CG4+ -> if unMod b == 1 then 0 else 1+ -- the only possible input here is a=3 with b = 1 or 3+ CGOddPrimePower (unPrime -> p) k+ -> discreteLogarithmPP p k (toInteger (unMod a)) (toInteger (unMod b))+ CGDoubleOddPrimePower (unPrime -> p) k+ -> discreteLogarithmPP p k (toInteger (unMod a) `rem` p^k) (toInteger (unMod b) `rem` p^k)+ -- we have the isomorphism t -> t `rem` p^k from (Z/2p^kZ)* -> (Z/p^kZ)*
Math/NumberTheory/Moduli/PrimitiveRoot.hs view
@@ -1,85 +1,19 @@ -- | -- Module: Math.NumberTheory.Moduli.PrimitiveRoot--- Copyright: (c) 2017 Andrew Lelechenko+-- Copyright: (c) 2017 Andrew Lelechenko, 2018 Bhavik Mehta -- Licence: MIT -- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+-- Description: Deprecated -- -- Primitive roots and cyclic groups. -- -{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}--#if __GLASGOW_HASKELL__ < 801-{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}-#endif- module Math.NumberTheory.Moduli.PrimitiveRoot+ {-# DEPRECATED "Use Math.NumberTheory.Moduli.Multiplicative instead" #-} ( -- * Primitive roots PrimitiveRoot , unPrimitiveRoot , isPrimitiveRoot ) where -import Math.NumberTheory.ArithmeticFunctions (totient)-import Math.NumberTheory.Moduli.Class hiding (powMod)-import Math.NumberTheory.Moduli.Singleton-import Math.NumberTheory.Powers.Modular-import Math.NumberTheory.Primes--import Control.Monad (guard)-import Data.Constraint---- | 'PrimitiveRoot' m is a type which is only inhabited--- by <https://en.wikipedia.org/wiki/Primitive_root_modulo_n primitive roots> of m.-newtype PrimitiveRoot m = PrimitiveRoot- { unPrimitiveRoot :: MultMod m -- ^ Extract primitive root value.- }- deriving (Eq, Show)---- https://en.wikipedia.org/wiki/Primitive_root_modulo_n#Finding_primitive_roots-isPrimitiveRoot'- :: (Integral a, UniqueFactorisation a)- => CyclicGroup a m- -> a- -> Bool-isPrimitiveRoot' cg r =- case cg of- CG2 -> r == 1- CG4 -> r == 3- CGOddPrimePower p k -> oddPrimePowerTest (unPrime p) k r- CGDoubleOddPrimePower p k -> doubleOddPrimePowerTest (unPrime p) k r- where- oddPrimeTest p g = let phi = totient p- pows = map (\pk -> phi `quot` unPrime (fst pk)) (factorise phi)- exps = map (\x -> powMod g x p) pows- in g /= 0 && gcd g p == 1 && all (/= 1) exps- oddPrimePowerTest p 1 g = oddPrimeTest p (g `mod` p)- oddPrimePowerTest p _ g = oddPrimeTest p (g `mod` p) && powMod g (p-1) (p*p) /= 1- doubleOddPrimePowerTest p k g = odd g && oddPrimePowerTest p k g---- | Check whether a given modular residue is--- a <https://en.wikipedia.org/wiki/Primitive_root_modulo_n primitive root>.------ >>> :set -XDataKinds--- >>> import Data.Maybe--- >>> isPrimitiveRoot (fromJust cyclicGroup) (1 :: Mod 13)--- Nothing--- >>> isPrimitiveRoot (fromJust cyclicGroup) (2 :: Mod 13)--- Just (PrimitiveRoot {unPrimitiveRoot = MultMod {multElement = (2 `modulo` 13)}})-isPrimitiveRoot- :: (Integral a, UniqueFactorisation a)- => CyclicGroup a m- -> Mod m- -> Maybe (PrimitiveRoot m)-isPrimitiveRoot cg r = case proofFromCyclicGroup cg of- Sub Dict -> do- r' <- isMultElement r- guard $ isPrimitiveRoot' cg (fromIntegral (getNatVal r))- return $ PrimitiveRoot r'+import Math.NumberTheory.Moduli.Multiplicative
Math/NumberTheory/Moduli/Singleton.hs view
@@ -49,23 +49,24 @@ import Control.DeepSeq import Data.Constraint-import Data.List+import Data.Kind+import Data.List (sort) import qualified Data.Map as M import Data.Proxy #if __GLASGOW_HASKELL__ < 803 import Data.Semigroup #endif import GHC.Generics-import GHC.TypeNats.Compat+import GHC.TypeNats (KnownNat, Nat, natVal) import Numeric.Natural import Unsafe.Coerce -import Math.NumberTheory.Powers+import Math.NumberTheory.Roots (highestPower) import Math.NumberTheory.Primes import Math.NumberTheory.Primes.Types -- | Wrapper to hide an unknown type-level natural.-data Some (a :: Nat -> *) where+data Some (a :: Nat -> Type) where Some :: a m -> Some a -- | From "Data.Constraint.Nat".@@ -211,6 +212,8 @@ where m = fromIntegral (natVal (Proxy :: Proxy m)) +-- | Create a singleton from factors.+-- Factors must be distinct, as in output of 'factorise'. cyclicGroupFromFactors :: (Eq a, Num a) => [(Prime a, Word)]
+ Math/NumberTheory/Moduli/SomeMod.hs view
@@ -0,0 +1,201 @@+-- |+-- Module: Math.NumberTheory.Moduli.SomeMod+-- Copyright: (c) 2017 Andrew Lelechenko+-- Licence: MIT+-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+--+-- Safe modular arithmetic with modulo on type level.+--++{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Math.NumberTheory.Moduli.SomeMod+ ( SomeMod(..)+ , modulo+ , invertSomeMod+ , powSomeMod+ ) where++import Data.Euclidean (GcdDomain(..), Euclidean(..), Field)+import Data.Mod+import Data.Proxy+#if __GLASGOW_HASKELL__ < 803+import Data.Semigroup+#endif+import Data.Semiring (Semiring(..), Ring(..))+import Data.Type.Equality+import GHC.TypeNats (KnownNat, SomeNat(..), sameNat, natVal, someNatVal)+import Numeric.Natural++-- | This type represents residues with unknown modulo and rational numbers.+-- One can freely combine them in arithmetic expressions, but each operation+-- will spend time on modulo's recalculation:+--+-- >>> 2 `modulo` 10 + 4 `modulo` 15+-- (1 `modulo` 5)+-- >>> (2 `modulo` 10) * (4 `modulo` 15)+-- (3 `modulo` 5)+-- >>> 2 `modulo` 10 + fromRational (3 % 7)+-- (1 `modulo` 10)+-- >>> 2 `modulo` 10 * fromRational (3 % 7)+-- (8 `modulo` 10)+--+-- If performance is crucial, it is recommended to extract @Mod m@ for further processing+-- by pattern matching. E. g.,+--+-- > case modulo n m of+-- > SomeMod k -> process k -- Here k has type Mod m+-- > InfMod{} -> error "impossible"+data SomeMod where+ SomeMod :: KnownNat m => Mod m -> SomeMod+ InfMod :: Rational -> SomeMod++instance Eq SomeMod where+ SomeMod mx == SomeMod my =+ natVal mx == natVal my && unMod mx == unMod my+ InfMod rx == InfMod ry = rx == ry+ _ == _ = False++instance Ord SomeMod where+ SomeMod mx `compare` SomeMod my =+ natVal mx `compare` natVal my <> unMod mx `compare` unMod my+ SomeMod{} `compare` InfMod{} = LT+ InfMod{} `compare` SomeMod{} = GT+ InfMod rx `compare` InfMod ry = rx `compare` ry++instance Show SomeMod where+ show = \case+ SomeMod m -> show m+ InfMod r -> show r++-- | Create modular value by representative of residue class and modulo.+-- One can use the result either directly (via functions from 'Num' and 'Fractional'),+-- or deconstruct it by pattern matching. Note that 'modulo' never returns 'InfMod'.+modulo :: Integer -> Natural -> SomeMod+modulo n m = case someNatVal m of+ SomeNat (_ :: Proxy t) -> SomeMod (fromInteger n :: Mod t)+{-# INLINABLE modulo #-}+infixl 7 `modulo`++liftUnOp+ :: (forall k. KnownNat k => Mod k -> Mod k)+ -> (Rational -> Rational)+ -> SomeMod+ -> SomeMod+liftUnOp fm fr = \case+ SomeMod m -> SomeMod (fm m)+ InfMod r -> InfMod (fr r)+{-# INLINEABLE liftUnOp #-}++liftBinOpMod+ :: (KnownNat m, KnownNat n)+ => (forall k. KnownNat k => Mod k -> Mod k -> Mod k)+ -> Mod m+ -> Mod n+ -> SomeMod+liftBinOpMod f mx my = case someNatVal m of+ SomeNat (_ :: Proxy t) ->+ SomeMod (fromIntegral (x `mod` m) `f` fromIntegral (y `mod` m) :: Mod t)+ where+ x = unMod mx+ y = unMod my+ m = natVal mx `Prelude.gcd` natVal my++liftBinOp+ :: (forall k. KnownNat k => Mod k -> Mod k -> Mod k)+ -> (Rational -> Rational -> Rational)+ -> SomeMod+ -> SomeMod+ -> SomeMod+liftBinOp _ fr (InfMod rx) (InfMod ry) = InfMod (rx `fr` ry)+liftBinOp fm _ (InfMod rx) (SomeMod my) = SomeMod (fromRational rx `fm` my)+liftBinOp fm _ (SomeMod mx) (InfMod ry) = SomeMod (mx `fm` fromRational ry)+liftBinOp fm _ (SomeMod (mx :: Mod m)) (SomeMod (my :: Mod n))+ = case (Proxy :: Proxy m) `sameNat` (Proxy :: Proxy n) of+ Nothing -> liftBinOpMod fm mx my+ Just Refl -> SomeMod (mx `fm` my)++instance Num SomeMod where+ (+) = liftBinOp (+) (+)+ (-) = liftBinOp (-) (-)+ negate = liftUnOp Prelude.negate Prelude.negate+ {-# INLINE negate #-}+ (*) = liftBinOp (*) (*)+ abs = id+ {-# INLINE abs #-}+ signum = const 1+ {-# INLINE signum #-}+ fromInteger = InfMod . fromInteger+ {-# INLINE fromInteger #-}++instance Semiring SomeMod where+ plus = (+)+ times = (*)+ zero = InfMod 0+ one = InfMod 1+ fromNatural = fromIntegral++instance Ring SomeMod where+ negate = Prelude.negate++-- | Beware that division by residue, which is not coprime with the modulo,+-- will result in runtime error. Consider using 'invertSomeMod' instead.+instance Fractional SomeMod where+ fromRational = InfMod+ {-# INLINE fromRational #-}+ recip x = case invertSomeMod x of+ Nothing -> error $ "recip{SomeMod}: residue is not coprime with modulo"+ Just y -> y++-- | See the warning about division above.+instance GcdDomain SomeMod where+ divide x y = Just (x / y)+ gcd = const $ const 1+ lcm = const $ const 1+ coprime = const $ const True++-- | See the warning about division above.+instance Euclidean SomeMod where+ degree = const 0+ quotRem x y = (x / y, 0)+ quot = (/)+ rem = const $ const 0++-- | See the warning about division above.+instance Field SomeMod++-- | Computes the inverse value, if it exists.+--+-- >>> invertSomeMod (3 `modulo` 10)+-- Just (7 `modulo` 10) -- because 3 * 7 = 1 :: Mod 10+-- >>> invertSomeMod (4 `modulo` 10)+-- Nothing+-- >>> invertSomeMod (fromRational (2 % 5))+-- Just 5 % 2+invertSomeMod :: SomeMod -> Maybe SomeMod+invertSomeMod = \case+ SomeMod m -> fmap SomeMod (invertMod m)+ InfMod r -> Just (InfMod (recip r))+{-# INLINABLE [1] invertSomeMod #-}++{-# SPECIALISE [1] powSomeMod ::+ SomeMod -> Integer -> SomeMod,+ SomeMod -> Natural -> SomeMod,+ SomeMod -> Int -> SomeMod,+ SomeMod -> Word -> SomeMod #-}++-- | Drop-in replacement for 'Prelude.^', with much better performance.+-- When -O is enabled, there is a rewrite rule, which specialises 'Prelude.^' to 'powSomeMod'.+--+-- >>> powSomeMod (3 `modulo` 10) 4+-- (1 `modulo` 10)+powSomeMod :: Integral a => SomeMod -> a -> SomeMod+powSomeMod (SomeMod m) a = SomeMod (m ^% a)+powSomeMod (InfMod r) a = InfMod (r ^ a)+{-# INLINABLE [1] powSomeMod #-}++{-# RULES "^%SomeMod" forall x p. x ^ p = powSomeMod x p #-}
Math/NumberTheory/Moduli/Sqrt.hs view
@@ -4,7 +4,8 @@ -- Licence: MIT -- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com> ----- Modular square roots.+-- Modular square roots and+-- <https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol>. -- {-# LANGUAGE BangPatterns #-}@@ -12,20 +13,25 @@ {-# LANGUAGE CPP #-} module Math.NumberTheory.Moduli.Sqrt- ( -- * New interface+ ( -- * Modular square roots sqrtsMod , sqrtsModFactorisation , sqrtsModPrimePower , sqrtsModPrime+ -- * Jacobi symbol+ , JacobiSymbol(..)+ , jacobi+ , symbolToNum ) where import Control.Monad (liftM2) import Data.Bits import Data.Constraint+import Data.Maybe+import Data.Mod import Math.NumberTheory.Moduli.Chinese-import Math.NumberTheory.Moduli.Class hiding (powMod)-import Math.NumberTheory.Moduli.Jacobi+import Math.NumberTheory.Moduli.JacobiSymbol import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.Powers.Modular (powMod) import Math.NumberTheory.Primes@@ -39,7 +45,7 @@ -- [(1 `modulo` 60),(49 `modulo` 60),(41 `modulo` 60),(29 `modulo` 60),(31 `modulo` 60),(19 `modulo` 60),(11 `modulo` 60),(59 `modulo` 60)] sqrtsMod :: SFactors Integer m -> Mod m -> [Mod m] sqrtsMod sm a = case proofFromSFactors sm of- Sub Dict -> map fromInteger $ sqrtsModFactorisation (getVal a) (unSFactors sm)+ Sub Dict -> map fromInteger $ sqrtsModFactorisation (toInteger (unMod a)) (unSFactors sm) -- | List all square roots modulo a number, the factorisation of which is -- passed as a second argument.@@ -59,7 +65,10 @@ cs :: [[(Integer, Integer)]] cs = zipWith (\l m -> map (\x -> (x, m)) l) rs ms - comb t1@(_, m1) t2@(_, m2) = (chineseRemainder2 t1 t2, m1 * m2)+ comb t1@(_, m1) t2@(_, m2) = (if ch < 0 then ch + m else ch, m)+ where+ ch = fromJust $ chinese t1 t2+ m = m1 * m2 -- | List all square roots modulo the power of a prime. --
Math/NumberTheory/MoebiusInversion.hs view
@@ -21,7 +21,7 @@ import qualified Data.Vector.Generic as G import qualified Data.Vector.Generic.Mutable as MG -import Math.NumberTheory.Powers.Squares+import Math.NumberTheory.Roots import Math.NumberTheory.Utils.FromIntegral -- | @totientSum n@ is, for @n > 0@, the sum of @[totient k | k <- [1 .. n]]@,
− Math/NumberTheory/MoebiusInversion/Int.hs
@@ -1,152 +0,0 @@--- |--- Module: Math.NumberTheory.MoebiusInversion--- Copyright: (c) 2012 Daniel Fischer--- Licence: MIT--- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>------ Generalised Möbius inversion for 'Int' valued functions.--{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}--{-# OPTIONS_HADDOCK hide #-}--module Math.NumberTheory.MoebiusInversion.Int {-# DEPRECATED "Use Math.NumberTheory.MoebiusInversion" #-}- ( generalInversion- , totientSum- ) where--import Control.Monad-import Control.Monad.ST-import qualified Data.Vector.Unboxed.Mutable as MV--import Math.NumberTheory.Powers.Squares---- | @totientSum n@ is, for @n > 0@, the sum of @[totient k | k <- [1 .. n]]@,--- computed via generalised Möbius inversion.--- See <http://mathworld.wolfram.com/TotientSummatoryFunction.html> for the--- formula used for @totientSum@.-totientSum :: Int -> Int-totientSum n- | n < 1 = 0- | otherwise = generalInversion (triangle . fromIntegral) n- where- triangle k = (k*(k+1)) `quot` 2---- | @generalInversion g n@ evaluates the generalised Möbius inversion of @g@--- at the argument @n@.------ The generalised Möbius inversion implemented here allows an efficient--- calculation of isolated values of the function @f : N -> Z@ if the function--- @g@ defined by------ >--- > g n = sum [f (n `quot` k) | k <- [1 .. n]]--- >------ can be cheaply computed. By the generalised Möbius inversion formula, then------ >--- > f n = sum [moebius k * g (n `quot` k) | k <- [1 .. n]]--- >------ which allows the computation in /O/(n) steps, if the values of the--- Möbius function are known. A slightly different formula, used here,--- does not need the values of the Möbius function and allows the--- computation in /O/(n^0.75) steps, using /O/(n^0.5) memory.------ An example of a pair of such functions where the inversion allows a--- more efficient computation than the direct approach is------ >--- > f n = number of reduced proper fractions with denominator <= n--- > g n = number of proper fractions with denominator <= n--- >------ (a /proper fraction/ is a fraction @0 < n/d < 1@). Then @f n@ is the--- cardinality of the Farey sequence of order @n@ (minus 1 or 2 if 0 and/or--- 1 are included in the Farey sequence), or the sum of the totients of--- the numbers @2 <= k <= n@. @f n@ is not easily directly computable,--- but then @g n = n*(n-1)/2@ is very easy to compute, and hence the inversion--- gives an efficient method of computing @f n@.------ For 'Int' valued functions, unboxed arrays can be used for greater efficiency.--- That bears the risk of overflow, however, so be sure to use it only when it's--- safe.------ The value @f n@ is then computed by @generalInversion g n@. Note that when--- many values of @f@ are needed, there are far more efficient methods, this--- method is only appropriate to compute isolated values of @f@.-generalInversion :: (Int -> Int) -> Int -> Int-generalInversion fun n- | n < 1 = error "Möbius inversion only defined on positive domain"- | n == 1 = fun 1- | n == 2 = fun 2 - fun 1- | n == 3 = fun 3 - 2*fun 1- | otherwise = fastInvert fun n--fastInvert :: (Int -> Int) -> Int -> Int-fastInvert fun n = runST (fastInvertST fun n)--fastInvertST :: forall s. (Int -> Int) -> Int -> ST s Int-fastInvertST fun n = do- let !k0 = integerSquareRoot (n `quot` 2)- !mk0 = n `quot` (2*k0+1)- kmax a m = (a `quot` m - 1) `quot` 2-- small <- MV.unsafeNew (mk0 + 1) :: ST s (MV.MVector s Int)- MV.unsafeWrite small 0 0- MV.unsafeWrite small 1 $! (fun 1)- when (mk0 >= 2) $- MV.unsafeWrite small 2 $! (fun 2 - fun 1)-- let calcit :: Int -> Int -> Int -> ST s (Int, Int)- calcit switch change i- | mk0 < i = return (switch,change)- | i == change = calcit (switch+1) (change + 4*switch+6) i- | otherwise = do- let mloop !acc k !m- | k < switch = kloop acc k- | otherwise = do- val <- MV.unsafeRead small m- let nxtk = kmax i (m+1)- mloop (acc - fromIntegral (k-nxtk)*val) nxtk (m+1)- kloop !acc k- | k == 0 = do- MV.unsafeWrite small i $! acc- calcit switch change (i+1)- | otherwise = do- val <- MV.unsafeRead small (i `quot` (2*k+1))- kloop (acc-val) (k-1)- mloop (fun i - fun (i `quot` 2)) ((i-1) `quot` 2) 1-- (sw, ch) <- calcit 1 8 3- large <- MV.unsafeNew k0 :: ST s (MV.MVector s Int)-- let calcbig :: Int -> Int -> Int -> ST s (MV.MVector s Int)- calcbig switch change j- | j == 0 = return large- | (2*j-1)*change <= n = calcbig (switch+1) (change + 4*switch+6) j- | otherwise = do- let i = n `quot` (2*j-1)- mloop !acc k m- | k < switch = kloop acc k- | otherwise = do- val <- MV.unsafeRead small m- let nxtk = kmax i (m+1)- mloop (acc - fromIntegral (k-nxtk)*val) nxtk (m+1)- kloop !acc k- | k == 0 = do- MV.unsafeWrite large (j-1) $! acc- calcbig switch change (j-1)- | otherwise = do- let m = i `quot` (2*k+1)- val <- if m <= mk0- then MV.unsafeRead small m- else MV.unsafeRead large (k*(2*j-1)+j-1)- kloop (acc-val) (k-1)- mloop (fun i - fun (i `quot` 2)) ((i-1) `quot` 2) 1-- mvec <- calcbig sw ch k0- MV.unsafeRead mvec 0
Math/NumberTheory/Powers.hs view
@@ -3,6 +3,7 @@ -- Copyright: (c) 2011 Daniel Fischer -- Licence: MIT -- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>+-- Description: Deprecated -- -- Calculating integer roots, modular powers and related things. -- This module reexports the most needed functions from the implementation@@ -10,7 +11,11 @@ -- in particular some unsafe functions which omit some tests for performance -- reasons. --++{-# OPTIONS_GHC -fno-warn-deprecations #-}+ module Math.NumberTheory.Powers+ {-# DEPRECATED "Use Math.NumberTheory.Roots or Math.NumberTheory.Powers.Modular" #-} ( -- * Integer Roots -- ** Square roots integerSquareRoot
Math/NumberTheory/Powers/Cubes.hs view
@@ -3,11 +3,15 @@ -- Copyright: (c) 2011 Daniel Fischer -- Licence: MIT -- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>+-- Description: Deprecated -- -- Functions dealing with cubes. Moderately efficient calculation of integer -- cube roots and testing for cubeness.+ {-# LANGUAGE MagicHash, BangPatterns, CPP, FlexibleContexts #-}+ module Math.NumberTheory.Powers.Cubes+ {-# DEPRECATED "Use Math.NumberTheory.Roots" #-} ( integerCubeRoot , integerCubeRoot' , exactCubeRoot@@ -30,25 +34,7 @@ import Numeric.Natural --- | Calculate the integer cube root of an integer @n@,--- that is the largest integer @r@ such that @r^3 <= n@.--- Note that this is not symmetric about @0@, for example--- @integerCubeRoot (-2) = (-2)@ while @integerCubeRoot 2 = 1@.-{-# SPECIALISE integerCubeRoot :: Int -> Int,- Word -> Word,- Integer -> Integer,- Natural -> Natural- #-}-integerCubeRoot :: Integral a => a -> a-integerCubeRoot 0 = 0-integerCubeRoot n- | n > 0 = integerCubeRoot' n- | otherwise =- let m = negate n- r = if m < 0- then negate . fromInteger $ integerCubeRoot' (negate $ fromIntegral n)- else negate (integerCubeRoot' m)- in if r*r*r == n then r else (r-1)+import Math.NumberTheory.Roots -- | Calculate the integer cube root of a nonnegative integer @n@, -- that is, the largest integer @r@ such that @r^3 <= n@.@@ -62,41 +48,6 @@ integerCubeRoot' :: Integral a => a -> a integerCubeRoot' 0 = 0 integerCubeRoot' n = newton3 n (approxCuRt n)---- | Returns @Nothing@ if the argument is not a cube,--- @Just r@ if @n == r^3@.-{-# SPECIALISE exactCubeRoot :: Int -> Maybe Int,- Word -> Maybe Word,- Integer -> Maybe Integer,- Natural -> Maybe Natural- #-}-exactCubeRoot :: Integral a => a -> Maybe a-exactCubeRoot 0 = Just 0-exactCubeRoot n- | n < 0 =- if m < 0- then fmap (negate . fromInteger) $ exactCubeRoot (negate $ fromIntegral n)- else fmap negate (exactCubeRoot m)- | isPossibleCube n && r*r*r == n = Just r- | otherwise = Nothing- where- m = negate n- r = integerCubeRoot' n---- | Test whether an integer is a cube.-{-# SPECIALISE isCube :: Int -> Bool,- Word -> Bool,- Integer -> Bool,- Natural -> Bool- #-}-isCube :: Integral a => a -> Bool-isCube 0 = True-isCube n- | n > 0 = isCube' n- | m > 0 = isCube' m- | otherwise = isCube' (negate (fromIntegral n) :: Integer)- where- m = negate n -- | Test whether a nonnegative integer is a cube. -- Before 'integerCubeRoot' is calculated, a few tests
Math/NumberTheory/Powers/Fourth.hs view
@@ -3,11 +3,15 @@ -- Copyright: (c) 2011 Daniel Fischer -- Licence: MIT -- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>+-- Description: Deprecated -- -- Functions dealing with fourth powers. Efficient calculation of integer fourth -- roots and efficient testing for being a square's square.+ {-# LANGUAGE MagicHash, CPP, FlexibleContexts #-}+ module Math.NumberTheory.Powers.Fourth+ {-# DEPRECATED "Use Math.NumberTheory.Roots" #-} ( integerFourthRoot , integerFourthRoot' , exactFourthRoot@@ -30,6 +34,8 @@ import Numeric.Natural +import Math.NumberTheory.Roots+ -- | Calculate the integer fourth root of a nonnegative number, -- that is, the largest integer @r@ with @r^4 <= n@. -- Throws an error on negaitve input.@@ -39,9 +45,7 @@ Natural -> Natural #-} integerFourthRoot :: Integral a => a -> a-integerFourthRoot n- | n < 0 = error "integerFourthRoot: negative argument"- | otherwise = integerFourthRoot' n+integerFourthRoot = integerRoot (4 :: Word) -- | Calculate the integer fourth root of a nonnegative number, -- that is, the largest integer @r@ with @r^4 <= n@.@@ -64,14 +68,7 @@ Natural -> Maybe Natural #-} exactFourthRoot :: Integral a => a -> Maybe a-exactFourthRoot 0 = Just 0-exactFourthRoot n- | n < 0 = Nothing- | isPossibleFourthPower n && r2*r2 == n = Just r- | otherwise = Nothing- where- r = integerFourthRoot' n- r2 = r*r+exactFourthRoot = exactRoot (4 :: Word) -- | Test whether an integer is a fourth power. -- First nonnegativity is checked, then the unchecked@@ -82,8 +79,7 @@ Natural -> Bool #-} isFourthPower :: Integral a => a -> Bool-isFourthPower 0 = True-isFourthPower n = n > 0 && isFourthPower' n+isFourthPower = isKthPower (4 :: Word) -- | Test whether a nonnegative number is a fourth power. -- The condition is /not/ checked. If a number passes the
Math/NumberTheory/Powers/General.hs view
@@ -3,13 +3,21 @@ -- Copyright: (c) 2011 Daniel Fischer -- Licence: MIT -- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>+-- Description: Deprecated -- -- Calculating integer roots and determining perfect powers. -- The algorithms are moderately efficient. ---{-# LANGUAGE MagicHash, BangPatterns, CPP #-}-{-# OPTIONS_GHC -O2 -fspec-constr-count=8 #-}++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}++{-# OPTIONS_GHC -fno-warn-deprecations #-}+ module Math.NumberTheory.Powers.General+ {-# DEPRECATED "Use Math.NumberTheory.Roots" #-} ( integerRoot , exactRoot , isKthPower@@ -20,162 +28,13 @@ #include "MachDeps.h" -import GHC.Base-import GHC.Integer-import GHC.Integer.GMP.Internals-import GHC.Integer.Logarithms (integerLog2#)--import Data.Bits-import Data.List (foldl')-import qualified Data.Set as Set-import Data.Vector.Unboxed (toList)--import Numeric.Natural- import Math.NumberTheory.Logarithms (integerLogBase')-import Math.NumberTheory.Utils (shiftToOddCount- , splitOff- ) import qualified Math.NumberTheory.Powers.Squares as P2 import qualified Math.NumberTheory.Powers.Cubes as P3 import qualified Math.NumberTheory.Powers.Fourth as P4-import Math.NumberTheory.Primes.Small-import Math.NumberTheory.Utils.FromIntegral (intToWord, wordToInt)---- | Calculate an integer root, @'integerRoot' k n@ computes the (floor of) the @k@-th--- root of @n@, where @k@ must be positive.--- @r = 'integerRoot' k n@ means @r^k <= n < (r+1)^k@ if that is possible at all.--- It is impossible if @k@ is even and @n \< 0@, since then @r^k >= 0@ for all @r@,--- then, and if @k <= 0@, @'integerRoot'@ raises an error. For @k < 5@, a specialised--- version is called which should be more efficient than the general algorithm.--- However, it is not guaranteed that the rewrite rules for those fire, so if @k@ is--- known in advance, it is safer to directly call the specialised versions.-{-# SPECIALISE integerRoot :: Int -> Int -> Int,- Int -> Word -> Word,- Int -> Integer -> Integer,- Int -> Natural -> Natural,- Word -> Int -> Int,- Word -> Word -> Word,- Word -> Integer -> Integer,- Word -> Natural -> Natural,- Integer -> Integer -> Integer,- Natural -> Natural -> Natural- #-}-integerRoot :: (Integral a, Integral b) => b -> a -> a-integerRoot 1 n = n-integerRoot 2 n = P2.integerSquareRoot n-integerRoot 3 n = P3.integerCubeRoot n-integerRoot 4 n = P4.integerFourthRoot n-integerRoot k n- | k < 1 = error "integerRoot: negative exponent or exponent 0"- | n < 0 && even k = error "integerRoot: negative radicand for even exponent"- | n < 0 =- let r = negate . fromInteger . integerRoot k . negate $ fromIntegral n- in if r^k == n then r else (r-1)- | n == 0 = 0- | n < 31 = 1- | kTooLarge = 1- | otherwise = newtonK k' n a- where- k' = fromIntegral k- a = approxKthRoot (fromIntegral k) n- kTooLarge = (toInteger k /= toInteger (fromIntegral k `asTypeOf` n)) -- k doesn't fit in n's type- || (toInteger k > toInteger (maxBound :: Int)) -- 2^k doesn't fit in Integer- || (I# (integerLog2# (toInteger n)) < fromIntegral k) -- n < 2^k---- | @'exactRoot' k n@ returns @'Nothing'@ if @n@ is not a @k@-th power,--- @'Just' r@ if @n == r^k@. If @k@ is divisible by @4, 3@ or @2@, a--- residue test is performed to avoid the expensive calculation if it--- can thus be determined that @n@ is not a @k@-th power.-exactRoot :: (Integral a, Integral b) => b -> a -> Maybe a-exactRoot 1 n = Just n-exactRoot 2 n = P2.exactSquareRoot n-exactRoot 3 n = P3.exactCubeRoot n-exactRoot 4 n = P4.exactFourthRoot n-exactRoot k n- | n == 1 = Just 1- | k < 1 = Nothing- | n < 0 && even k = Nothing- | n < 0 = fmap negate (exactRoot k (-n))- | n < 2 = Just n- | n < 31 = Nothing- | kTooLarge = Nothing- | otherwise = case k `rem` 12 of- 0 | c4 && c3 && ok -> Just r- | otherwise -> Nothing- 2 | c2 && ok -> Just r- | otherwise -> Nothing- 3 | c3 && ok -> Just r- | otherwise -> Nothing- 4 | c4 && ok -> Just r- | otherwise -> Nothing- 6 | c3 && c2 && ok -> Just r- | otherwise -> Nothing- 8 | c4 && ok -> Just r- | otherwise -> Nothing- 9 | c3 && ok -> Just r- | otherwise -> Nothing- 10 | c2 && ok -> Just r- | otherwise -> Nothing- _ | ok -> Just r- | otherwise -> Nothing-- where- k' :: Int- k' = fromIntegral k- r = integerRoot k' n- c2 = P2.isPossibleSquare n- c3 = P3.isPossibleCube n- c4 = P4.isPossibleFourthPower n- ok = r^k == n- kTooLarge = (toInteger k /= toInteger (fromIntegral k `asTypeOf` n)) -- k doesn't fit in n's type- || (toInteger k > toInteger (maxBound :: Int)) -- 2^k doesn't fit in Integer- || (I# (integerLog2# (toInteger n)) < fromIntegral k) -- n < 2^k---- | @'isKthPower' k n@ checks whether @n@ is a @k@-th power.-isKthPower :: (Integral a, Integral b) => b -> a -> Bool-isKthPower k n = case exactRoot k n of- Just _ -> True- Nothing -> False---- | @'isPerfectPower' n@ checks whether @n == r^k@ for some @k > 1@.-isPerfectPower :: Integral a => a -> Bool-isPerfectPower n- | n == 0 || n == 1 = True- | otherwise = k > 1- where- (_,k) = highestPower n---- | @'highestPower' n@ produces the pair @(b,k)@ with the largest--- exponent @k@ such that @n == b^k@, except for @'abs' n <= 1@,--- in which case arbitrarily large exponents exist, and by an--- arbitrary decision @(n,3)@ is returned.------ First, by trial division with small primes, the range of possible--- exponents is reduced (if @p^e@ exactly divides @n@, then @k@ must--- be a divisor of @e@, if several small primes divide @n@, @k@ must--- divide the greatest common divisor of their exponents, which mostly--- will be @1@, generally small; if none of the small primes divides--- @n@, the range of possible exponents is reduced since the base is--- necessarily large), if that has not yet determined the result, the--- remaining factor is examined by trying the divisors of the @gcd@--- of the prime exponents if some have been found, otherwise by trying--- prime exponents recursively.-highestPower :: Integral a => a -> (a, Word)-highestPower n'- | abs n <= 1 = (n', 3)- | n < 0 = case integerHighPower (negate n) of- (r,e) -> case shiftToOddCount e of- (k, o) -> (negate $ fromInteger (sqr k r), o)- | otherwise = case integerHighPower n of- (r,e) -> (fromInteger r, e)- where- n :: Integer- n = toInteger n'+import Math.NumberTheory.Utils.FromIntegral (intToWord) - sqr :: Word -> Integer -> Integer- sqr 0 m = m- sqr k m = sqr (k-1) (m*m)+import Math.NumberTheory.Roots -- | @'largePFPower' bd n@ produces the pair @(b,k)@ with the largest -- exponent @k@ such that @n == b^k@, where @bd > 1@ (it is expected@@ -195,96 +54,6 @@ -- Auxiliary functions -- ------------------------------------------------------------------------------------------ -{-# SPECIALISE newtonK :: Int -> Int -> Int -> Int,- Word -> Word -> Word -> Word,- Integer -> Integer -> Integer -> Integer,- Natural -> Natural -> Natural -> Natural- #-}-newtonK :: Integral a => a -> a -> a -> a-newtonK k n a = go (step a)- where- -- Beware integer overflow in m^(k-1)- step m = ((k-1)*m + fromInteger (toInteger n `quot` (toInteger m^(k-1)))) `quot` k- go m- | l < m = go l- | otherwise = m- where- l = step m--{-# SPECIALISE approxKthRoot :: Int -> Int -> Int,- Int -> Word -> Word,- Int -> Integer -> Integer,- Int -> Natural -> Natural- #-}-approxKthRoot :: Integral a => Int -> a -> a-approxKthRoot k = fromInteger . appKthRoot k . fromIntegral---- find an approximation to the k-th root--- here, k > 4 and n > 31-appKthRoot :: Int -> Integer -> Integer-appKthRoot (I# k#) (S# n#) = S# (double2Int# (int2Double# n# **## (1.0## /## int2Double# k#)))-appKthRoot k@(I# k#) n =- case integerLog2# n of- l# -> case l# `quotInt#` k# of- 0# -> 1- 1# -> 3- 2# -> 5- 3# -> 11- h# | isTrue# (h# <# 500#) ->- floor (scaleFloat (I# (h# -# 1#))- (fromInteger (n `shiftRInteger` (h# *# k# -# k#)) ** (1/fromIntegral k) :: Double))- | otherwise ->- floor (scaleFloat 400 (fromInteger (n `shiftRInteger` (h# *# k# -# k#)) ** (1/fromIntegral k) :: Double))- `shiftLInteger` (h# -# 401#)---- assumption: argument is > 1-integerHighPower :: Integer -> (Integer, Word)-integerHighPower n- | n < 4 = (n,1)- | otherwise = case shiftToOddCount n of- (e2,m) | m == 1 -> (2,e2)- | otherwise -> findHighPower e2 (if e2 == 0 then [] else [(2,e2)]) m r smallOddPrimes- where- r = P2.integerSquareRoot m--findHighPower :: Word -> [(Integer, Word)] -> Integer -> Integer -> [Integer] -> (Integer, Word)-findHighPower 1 pws m _ _ = (foldl' (*) m [p^e | (p,e) <- pws], 1)-findHighPower e pws 1 _ _ = (foldl' (*) 1 [p^(ex `quot` e) | (p,ex) <- pws], e)-findHighPower e pws m s (p:ps)- | s < p = findHighPower 1 pws m s []- | otherwise =- case splitOff p m of- (0,_) -> findHighPower e pws m s ps- (k,r) -> findHighPower (gcd k e) ((p,k):pws) r (P2.integerSquareRoot r) ps-findHighPower e pws m _ [] = finishPower e pws m--smallOddPrimes :: [Integer]-smallOddPrimes- = takeWhile (< spBound)- $ map fromIntegral- $ tail- $ toList smallPrimes--spBEx :: Word-spBEx = 14--spBound :: Integer-spBound = 2^spBEx---- n large, has no prime divisors < spBound-finishPower :: Word -> [(Integer, Word)] -> Integer -> (Integer, Word)-finishPower e pws n- | n < (1 `shiftL` wordToInt (2*spBEx)) = (foldl' (*) n [p^ex | (p,ex) <- pws], 1) -- n is prime- | e == 0 = rawPower maxExp n- | otherwise = go divs- where- maxExp = (W# (int2Word# (integerLog2# n))) `quot` spBEx- divs = divisorsTo maxExp e- go [] = (foldl' (*) n [p^ex | (p,ex) <- pws], 1)- go (d:ds) = case exactRoot d n of- Just r -> (foldl' (*) r [p^(ex `quot` d) | (p,ex) <- pws], d)- Nothing -> go ds- rawPower :: Word -> Integer -> (Integer, Word) rawPower mx n | mx < 2 = (n,1)@@ -318,36 +87,3 @@ Just r -> go (e*k) (b `quot` k) r (k:ks) Nothing -> go e b m ks go e _ m [] = (m,e)--divisorsTo :: Word -> Word -> [Word]-divisorsTo mx n = case shiftToOddCount n of- (k,o) | k == 0 -> go (Set.singleton 1) n iops- | otherwise -> go (Set.fromDistinctAscList $ takeWhile (<= mx) $ take (wordToInt k + 1) (iterate (*2) 1)) o iops- where- mset k st = fst (Set.split (mx+1) (Set.mapMonotonic (*k) st))- -- unP p m = (k, m / p ^ k), where k is as large as possible such that p ^ k still divides m- unP :: Word -> Word -> (Word, Word)- unP p m = goP 0 m- where- goP :: Word -> Word -> (Word, Word)- goP !i j = case j `quotRem` p of- (q,r) | r == 0 -> goP (i+1) q- | otherwise -> (i,j)- iops :: [Word]- iops = 3:5:prs- prs :: [Word]- prs = 7:filter prm (scanl (+) 11 $ cycle [2,4,2,4,6,2,6,4])- prm :: Word -> Bool- prm k = td prs- where- td (p:ps) = (p*p > k) || (k `rem` p /= 0 && td ps)- td [] = True- go !st m (p:ps)- | m == 1 = reverse $ Set.toAscList st- | m < p*p = reverse . Set.toAscList $ Set.union st (mset m st)- | otherwise =- case unP p m of- (0,_) -> go st m ps- -- iterate f x = [x, f x, f (f x)...]- (k,r) -> go (Set.unions (take (wordToInt k + 1) (iterate (mset p) st))) r ps- go st m [] = go st m [m+1]
Math/NumberTheory/Powers/Modular.hs view
@@ -80,7 +80,7 @@ -- | Specialised version of 'powMod', able to handle large moduli correctly. ----- >> powModInt 3 101 (2^60-1)+-- >>> powModInt 3 101 (2^60-1) -- 1018105167100379328 powModInt :: Int -> Int -> Int -> Int powModInt x y m
Math/NumberTheory/Powers/Squares.hs view
@@ -3,11 +3,17 @@ -- Copyright: (c) 2011 Daniel Fischer -- Licence: MIT -- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>+-- Description: Deprecated -- -- Functions dealing with squares. Efficient calculation of integer square roots -- and efficient testing for squareness.+ {-# LANGUAGE MagicHash, BangPatterns, PatternGuards, CPP, FlexibleContexts #-}++{-# OPTIONS_GHC -fno-warn-deprecations #-}+ module Math.NumberTheory.Powers.Squares+ {-# DEPRECATED "Use Math.NumberTheory.Roots" #-} ( -- * Square root calculation integerSquareRoot , integerSquareRoot'@@ -32,18 +38,7 @@ import Math.NumberTheory.Powers.Squares.Internal --- | Calculate the integer square root of a nonnegative number @n@,--- that is, the largest integer @r@ with @r*r <= n@.--- Throws an error on negative input.-{-# SPECIALISE integerSquareRoot :: Int -> Int,- Word -> Word,- Integer -> Integer,- Natural -> Natural- #-}-integerSquareRoot :: Integral a => a -> a-integerSquareRoot n- | n < 0 = error "integerSquareRoot: negative argument"- | otherwise = integerSquareRoot' n+import Math.NumberTheory.Roots -- | Calculate the integer square root of a nonnegative number @n@, -- that is, the largest integer @r@ with @r*r <= n@.@@ -83,35 +78,6 @@ integerSquareRootRem' n = (s, n - s * s) where s = integerSquareRoot' n---- | Returns 'Nothing' if the argument is not a square,--- @'Just' r@ if @r*r == n@ and @r >= 0@. Avoids the expensive calculation--- of the square root if @n@ is recognized as a non-square--- before, prevents repeated calculation of the square root--- if only the roots of perfect squares are needed.--- Checks for negativity and 'isPossibleSquare'.-{-# SPECIALISE exactSquareRoot :: Int -> Maybe Int,- Word -> Maybe Word,- Integer -> Maybe Integer,- Natural -> Maybe Natural- #-}-exactSquareRoot :: Integral a => a -> Maybe a-exactSquareRoot n- | n >= 0- , isPossibleSquare n- , (r, 0) <- integerSquareRootRem' n = Just r- | otherwise = Nothing---- | Test whether the argument is a square.--- After a number is found to be positive, first 'isPossibleSquare'--- is checked, if it is, the integer square root is calculated.-{-# SPECIALISE isSquare :: Int -> Bool,- Word -> Bool,- Integer -> Bool,- Natural -> Bool- #-}-isSquare :: Integral a => a -> Bool-isSquare n = n >= 0 && isSquare' n -- | Test whether the input (a nonnegative number) @n@ is a square. -- The same as 'isSquare', but without the negativity test.
Math/NumberTheory/Powers/Squares/Internal.hs view
@@ -3,6 +3,7 @@ -- Copyright: (c) 2016 Andrew Lelechenko -- Licence: MIT -- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+-- Description: Deprecated -- -- Internal functions dealing with square roots. End-users should not import this module. @@ -15,6 +16,7 @@ {-# OPTIONS_HADDOCK hide #-} module Math.NumberTheory.Powers.Squares.Internal+ {-# DEPRECATED "Use Math.NumberTheory.Roots" #-} ( karatsubaSqrt , isqrtA ) where
Math/NumberTheory/Prefactored.hs view
@@ -20,12 +20,12 @@ import Prelude hiding ((^), gcd) import Control.Arrow+import Data.Euclidean import Data.Semigroup import Data.Semiring (Semiring(..), Mul(..), (^)) import qualified Data.Semiring as Semiring import Unsafe.Coerce -import Math.NumberTheory.Euclidean import Math.NumberTheory.Euclidean.Coprimes import Math.NumberTheory.Primes import Math.NumberTheory.Primes.Types@@ -81,7 +81,7 @@ , prefFactors :: Coprimes a Word -- ^ List of pairwise coprime (but not neccesarily prime) factors, -- accompanied by their multiplicities.- } deriving (Show)+ } deriving (Eq, Show) -- | Create 'Prefactored' from a given number. --
Math/NumberTheory/Primes.hs view
@@ -10,7 +10,6 @@ {-# LANGUAGE LambdaCase #-} {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_GHC -fno-warn-deprecations #-} module Math.NumberTheory.Primes ( Prime@@ -23,21 +22,21 @@ primes ) where -import Control.Arrow import Data.Bits import Data.Coerce import Data.Maybe+import Data.Word+import Numeric.Natural import Math.NumberTheory.Primes.Counting (nthPrime, primeCount)-import qualified Math.NumberTheory.Primes.Factorisation as F (factorise)+import qualified Math.NumberTheory.Primes.Factorisation.Montgomery as F (factorise) import qualified Math.NumberTheory.Primes.Testing.Probabilistic as T (isPrime) import Math.NumberTheory.Primes.Sieve.Eratosthenes (primes, sieveRange, primeList, psieveFrom, primeSieve)+import Math.NumberTheory.Primes.Small import Math.NumberTheory.Primes.Types import Math.NumberTheory.Utils (toWheel30, fromWheel30) import Math.NumberTheory.Utils.FromIntegral -import Numeric.Natural- -- | A class for unique factorisation domains. class Num a => UniqueFactorisation a where -- | Factorise a number into a product of prime powers.@@ -84,11 +83,11 @@ isPrime :: a -> Maybe (Prime a) instance UniqueFactorisation Int where- factorise = map (Prime . integerToInt *** id) . F.factorise . intToInteger+ factorise = coerce . F.factorise isPrime n = if T.isPrime (toInteger n) then Just (Prime $ abs n) else Nothing instance UniqueFactorisation Word where- factorise = map (coerce integerToWord *** id) . F.factorise . wordToInteger+ factorise = coerce . F.factorise isPrime n = if T.isPrime (toInteger n) then Just (Prime n) else Nothing instance UniqueFactorisation Integer where@@ -96,9 +95,10 @@ isPrime n = if T.isPrime n then Just (Prime $ abs n) else Nothing instance UniqueFactorisation Natural where- factorise = map (coerce integerToNatural *** id) . F.factorise . naturalToInteger+ factorise = coerce . F.factorise isPrime n = if T.isPrime (toInteger n) then Just (Prime n) else Nothing +-- | Restore a number from its factorisation. factorBack :: Num a => [(Prime a, Word)] -> a factorBack = product . map (\(p, k) -> unPrime p ^ k) @@ -186,8 +186,25 @@ $ psieveFrom $ toInteger p' +smallPrimesLimit :: Integral a => a+smallPrimesLimit = fromIntegral (maxBound :: Word16)+ enumFromToGeneric :: (Bits a, Integral a, UniqueFactorisation a) => Prime a -> Prime a -> [Prime a]-enumFromToGeneric p@(Prime p') q@(Prime q') = takeWhile (<= q) $ dropWhile (< p) $+enumFromToGeneric p@(Prime p') q@(Prime q')+ | p' <= smallPrimesLimit, q' <= smallPrimesLimit+ = map (Prime . fromIntegral) $ smallPrimesFromTo (fromIntegral p') (fromIntegral q')+ | p' <= smallPrimesLimit+ = map (Prime . fromIntegral) (smallPrimesFromTo (fromIntegral p') smallPrimesLimit)+ ++ enumFromToGeneric' (nextPrime smallPrimesLimit) q+ | otherwise+ = enumFromToGeneric' p q++enumFromToGeneric'+ :: (Bits a, Integral a, UniqueFactorisation a)+ => Prime a+ -> Prime a+ -> [Prime a]+enumFromToGeneric' p@(Prime p') q@(Prime q') = takeWhile (<= q) $ dropWhile (< p) $ case chooseAlgorithm p' q' of IsPrime -> Prime 2 : Prime 3 : Prime 5 : mapMaybe isPrime (map fromWheel30 [toWheel30 p' .. toWheel30 q']) Sieve ->@@ -216,7 +233,7 @@ delta = p' - q' instance Enum (Prime Integer) where- toEnum = nthPrime . intToInteger+ toEnum = nthPrime fromEnum = integerToInt . primeCount . unPrime succ = succGeneric pred = predGeneric@@ -226,7 +243,7 @@ enumFromThenTo = enumFromThenToGeneric instance Enum (Prime Natural) where- toEnum = Prime . integerToNatural . unPrime . nthPrime . intToInteger+ toEnum = Prime . integerToNatural . unPrime . nthPrime fromEnum = integerToInt . primeCount . naturalToInteger . unPrime succ = succGeneric pred = predGeneric@@ -240,7 +257,7 @@ then error $ "Enum.toEnum{Prime}: " ++ show n ++ "th prime = " ++ show p ++ " is out of bounds of Int" else Prime (integerToInt p) where- Prime p = nthPrime (intToInteger n)+ Prime p = nthPrime n fromEnum = integerToInt . primeCount . intToInteger . unPrime succ = succGenericBounded pred = predGeneric@@ -249,12 +266,16 @@ enumFromThen = enumFromThenGeneric enumFromThenTo = enumFromThenToGeneric +instance Bounded (Prime Int) where+ minBound = Prime 2+ maxBound = precPrime maxBound+ instance Enum (Prime Word) where toEnum n = if p > wordToInteger maxBound then error $ "Enum.toEnum{Prime}: " ++ show n ++ "th prime = " ++ show p ++ " is out of bounds of Word" else Prime (integerToWord p) where- Prime p = nthPrime (intToInteger n)+ Prime p = nthPrime n fromEnum = integerToInt . primeCount . wordToInteger . unPrime succ = succGenericBounded pred = predGeneric@@ -262,3 +283,7 @@ enumFromTo = enumFromToGeneric enumFromThen = enumFromThenGeneric enumFromThenTo = enumFromThenToGeneric++instance Bounded (Prime Word) where+ minBound = Prime 2+ maxBound = precPrime maxBound
Math/NumberTheory/Primes/Counting.hs view
@@ -11,7 +11,6 @@ primeCount , primeCountMaxArg , nthPrime- , nthPrimeMaxArg -- * Approximations , approxPrimeCount , approxPrimeCountOverestimateLimit
Math/NumberTheory/Primes/Counting/Approximate.hs view
@@ -7,7 +7,6 @@ -- Approximations to the number of primes below a limit and the -- n-th prime. ---{-# OPTIONS_HADDOCK hide #-} module Math.NumberTheory.Primes.Counting.Approximate ( approxPrimeCount , approxPrimeCountOverestimateLimit
Math/NumberTheory/Primes/Counting/Impl.hs view
@@ -12,36 +12,27 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -fspec-constr-count=24 #-}-{-# OPTIONS_HADDOCK hide #-} module Math.NumberTheory.Primes.Counting.Impl ( primeCount , primeCountMaxArg , nthPrime- , nthPrimeMaxArg ) where #include "MachDeps.h" import Math.NumberTheory.Primes.Sieve.Eratosthenes- (PrimeSieve(..), primeList, primeSieve, psieveFrom, sieveTo, sieveBits, sieveRange, countFromTo, countToNth, countAll, nthPrimeCt)+ (PrimeSieve(..), primeList, primeSieve, psieveFrom, sieveTo, sieveBits, sieveRange) import Math.NumberTheory.Primes.Sieve.Indexing (toPrim, idxPr) import Math.NumberTheory.Primes.Counting.Approximate (nthPrimeApprox, approxPrimeCount) import Math.NumberTheory.Primes.Types-import Math.NumberTheory.Powers.Squares-import Math.NumberTheory.Powers.Cubes-import Math.NumberTheory.Logarithms-import Math.NumberTheory.Unsafe+import Math.NumberTheory.Roots -import Data.Array.ST import Control.Monad.ST+import Data.Array.Base+import Data.Array.ST import Data.Bits import Data.Int--#if SIZEOF_HSWORD < 8-#define COUNT_T Int64-#else-#define COUNT_T Int-#endif+import Unsafe.Coerce -- | Maximal allowed argument of 'primeCount'. Currently 8e18. primeCountMaxArg :: Integer@@ -69,34 +60,40 @@ return (fromIntegral $ ct+3) | otherwise = let !ub = cop $ fromInteger n- !sr = integerSquareRoot' ub- !cr = nxtEnd $ integerCubeRoot' ub + 15+ !sr = integerSquareRoot ub+ !cr = nxtEnd $ integerCubeRoot ub + 15 nxtEnd k = k - (k `rem` 30) + 31 !phn1 = calc ub cr !cs = cr+6 !pdf = sieveCount ub cs sr in phn1 - pdf --- | Maximal allowed argument of 'nthPrime'. Currently 1.5e17.-nthPrimeMaxArg :: Integer-nthPrimeMaxArg = 150000000000000000- -- | @'nthPrime' n@ calculates the @n@-th prime. Numbering of primes is -- @1@-based, so @'nthPrime' 1 == 2@. -- -- Requires @/O/((n*log n)^0.5)@ space, the time complexity is roughly @/O/((n*log n)^0.7@.--- The argument must be strictly positive, and must not exceed 'nthPrimeMaxArg'.-nthPrime :: Integer -> Prime Integer+-- The argument must be strictly positive.+nthPrime :: Int -> Prime Integer+nthPrime 1 = Prime 2+nthPrime 2 = Prime 3+nthPrime 3 = Prime 5+nthPrime 4 = Prime 7+nthPrime 5 = Prime 11+nthPrime 6 = Prime 13 nthPrime n- | n < 1 = error "Prime indexing starts at 1"- | n > nthPrimeMaxArg = error $ "nthPrime: can't handle index " ++ show n- | n < 200000 = Prime $ nthPrimeCt n- | ct0 < n = Prime $ tooLow n p0 (n-ct0) approxGap- | otherwise = Prime $ tooHigh n p0 (ct0-n) approxGap+ | n < 1+ = error "Prime indexing starts at 1"+ | n < 200000+ = Prime $ countToNth (n - 3) [primeSieve (p0 + p0 `quot` 32 + 37)]+ | p0 > toInteger (maxBound :: Int)+ = error $ "nthPrime: index " ++ show n ++ " is too large to handle"+ | miss > 0+ = Prime $ tooLow n (fromInteger p0) miss+ | otherwise+ = Prime $ tooHigh n (fromInteger p0) (negate miss) where- p0 = nthPrimeApprox n- approxGap = (7 * fromIntegral (integerLog2' p0)) `quot` 10- ct0 = primeCount p0+ p0 = nthPrimeApprox (toInteger n)+ miss = n - fromInteger (primeCount p0) -------------------------------------------------------------------------------- -- The Works --@@ -106,36 +103,43 @@ -- Not too pressing, since I think a) nthPrimeApprox always underestimates -- in the range we can handle, and b) it's always "goodEnough" -tooLow :: Integer -> Integer -> Integer -> Integer -> Integer-tooLow n a miss gap- | goodEnough = lowSieve a miss- | c1 < n = lowSieve p1 (n-c1)- | otherwise = lowSieve a miss -- a third count wouldn't make it faster, I think- where- est = miss*gap- p1 = a + (est * 19) `quot` 20- goodEnough = 3*est*est*est < 2*p1*p1 -- a second counting would be more work than sieving- c1 = primeCount p1+tooLow :: Int -> Int -> Int -> Integer+tooLow n p0 shortage+ | p1 > toInteger (maxBound :: Int)+ = error $ "nthPrime: index " ++ show n ++ " is too large to handle"+ | goodEnough+ = lowSieve p0 shortage+ | c1 < n+ = lowSieve (fromInteger p1) (n-c1)+ | otherwise+ = lowSieve p0 shortage -- a third count wouldn't make it faster, I think+ where+ gap = truncate (log (fromIntegral p0 :: Double))+ est = toInteger shortage * gap+ p1 = toInteger p0 + est+ goodEnough = 3*est*est*est < 2*p1*p1 -- a second counting would be more work than sieving+ c1 = fromInteger (primeCount p1) -tooHigh :: Integer -> Integer -> Integer -> Integer -> Integer-tooHigh n a surp gap- | c < n = lowSieve b (n-c)- | otherwise = tooHigh n b (c-n) gap- where- b = a - (surp * gap * 11) `quot` 10- c = primeCount b+tooHigh :: Int -> Int -> Int -> Integer+tooHigh n p0 surplus+ | c < n+ = lowSieve b (n-c)+ | otherwise+ = tooHigh n b (c-n)+ where+ gap = truncate (log (fromIntegral p0 :: Double))+ b = p0 - (surplus * gap * 11) `quot` 10+ c = fromInteger (primeCount (toInteger b)) -lowSieve :: Integer -> Integer -> Integer+lowSieve :: Int -> Int -> Integer lowSieve a miss = countToNth (miss+rep) psieves where- strt = if (fromInteger a .&. (1 :: Int)) == 1- then a+2- else a+1- psieves@(PS vO ba:_) = psieveFrom strt+ strt = a + 1 + (a .&. 1)+ psieves@(PS vO ba:_) = psieveFrom (toInteger strt) rep | o0 < 0 = 0 | otherwise = sum [1 | i <- [0 .. r2], ba `unsafeAt` i] where- o0 = strt - vO - 9 -- (strt - 2) - v0 - 7+ o0 = toInteger strt - vO - 9 -- (strt - 2) - v0 - 7 r0 = fromInteger o0 `rem` 30 r1 = r0 `quot` 3 r2 = min 7 (if r1 > 5 then r1-1 else r1)@@ -143,18 +147,18 @@ -- highSieve :: Integer -> Integer -> Integer -> Integer -- highSieve a surp gap = error "Oh shit" -sieveCount :: COUNT_T -> COUNT_T -> COUNT_T -> Integer+sieveCount :: Int64 -> Int64 -> Int64 -> Integer sieveCount ub cr sr = runST (sieveCountST ub cr sr) -sieveCountST :: forall s. COUNT_T -> COUNT_T -> COUNT_T -> ST s Integer+sieveCountST :: forall s. Int64 -> Int64 -> Int64 -> ST s Integer sieveCountST ub cr sr = do let psieves = psieveFrom (fromIntegral cr) pisr = approxPrimeCount sr picr = approxPrimeCount cr diff = pisr - picr size = fromIntegral (diff + diff `quot` 50) + 30- store <- unsafeNewArray_ (0,size-1) :: ST s (STUArray s Int COUNT_T)- let feed :: COUNT_T -> Int -> Int -> UArray Int Bool -> [PrimeSieve] -> ST s Integer+ store <- unsafeNewArray_ (0,size-1) :: ST s (STUArray s Int Int64)+ let feed :: Int64 -> Int -> Int -> UArray Int Bool -> [PrimeSieve] -> ST s Integer feed voff !wi !ri uar sves | ri == sieveBits = case sves of (PS vO ba : more) -> feed (fromInteger vO) wi 0 ba more@@ -168,7 +172,7 @@ | otherwise = feed voff wi (ri+1) uar sves where pval = voff + toPrim ri- eat :: Integer -> Integer -> COUNT_T -> Int -> Int -> STUArray s Int Bool -> [PrimeSieve] -> ST s Integer+ eat :: Integer -> Integer -> Int64 -> Int -> Int -> STUArray s Int Bool -> [PrimeSieve] -> ST s Integer eat !acc !btw voff !wi !si stu sves | si == sieveBits = case sves of@@ -197,7 +201,7 @@ let nbtw = btw + lac + 1 + fromIntegral new eat (acc+nbtw) nbtw (fromIntegral vO) (wi-1) (li+1) nstu more ctLoop lac s (ps : more) = do- !new <- countAll ps+ let !new = countAll ps ctLoop (lac + fromIntegral new) (s-1) more ctLoop _ _ [] = error "Primes ended" new <- countFromTo si (sieveBits-1) stu@@ -206,10 +210,10 @@ (PS vO ba : more) -> feed (fromInteger vO) 0 0 ba more _ -> error "No primes sieved" -calc :: COUNT_T -> COUNT_T -> Integer+calc :: Int64 -> Int64 -> Integer calc lim plim = runST (calcST lim plim) -calcST :: forall s. COUNT_T -> COUNT_T -> ST s Integer+calcST :: forall s. Int64 -> Int64 -> ST s Integer calcST lim plim = do !parr <- sieveTo (fromIntegral plim) (plo,phi) <- getBounds parr@@ -218,7 +222,7 @@ unsafeWrite ar1 0 lim unsafeWrite ar1 1 1 !ar2 <- unsafeNewArray_ (0,end-1)- let go :: Int -> Int -> STUArray s Int COUNT_T -> STUArray s Int COUNT_T -> ST s Integer+ let go :: Int -> Int -> STUArray s Int Int64 -> STUArray s Int Int64 -> ST s Integer go cap pix old new | pix == 2 = coll cap old | otherwise = do@@ -229,7 +233,7 @@ !ncap <- treat cap n old new go ncap (pix-1) new old else go cap (pix-1) old new- coll :: Int -> STUArray s Int COUNT_T -> ST s Integer+ coll :: Int -> STUArray s Int Int64 -> ST s Integer coll stop ar = let cgo !acc i | i < stop = do@@ -245,7 +249,7 @@ !size = fromIntegral $ (integerSquareRoot lim) `quot` 4 !end = 2*size -treat :: Int -> COUNT_T -> STUArray s Int COUNT_T -> STUArray s Int COUNT_T -> ST s Int+treat :: Int -> Int64 -> STUArray s Int Int64 -> STUArray s Int Int64 -> ST s Int treat end n old new = do qi0 <- locate n 0 (end `quot` 2 - 1) old let collect stop !acc ix@@ -284,7 +288,7 @@ -- Auxiliaries -- -------------------------------------------------------------------------------- -locate :: COUNT_T -> Int -> Int -> STUArray s Int COUNT_T -> ST s Int+locate :: Int64 -> Int -> Int -> STUArray s Int Int64 -> ST s Int locate p low high arr = do let go lo hi | lo < hi = do@@ -298,8 +302,8 @@ go low high {-# INLINE copyTo #-}-copyTo :: Int -> COUNT_T -> STUArray s Int COUNT_T -> Int- -> STUArray s Int COUNT_T -> Int -> ST s (Int,Int)+copyTo :: Int -> Int64 -> STUArray s Int Int64 -> Int+ -> STUArray s Int Int64 -> Int -> ST s (Int,Int) copyTo end lim old oi new ni = do let go ri wi | ri < end = do@@ -315,7 +319,7 @@ go oi ni {-# INLINE copyRem #-}-copyRem :: Int -> STUArray s Int COUNT_T -> Int -> STUArray s Int COUNT_T -> Int -> ST s Int+copyRem :: Int -> STUArray s Int Int64 -> Int -> STUArray s Int Int64 -> Int -> ST s Int copyRem end old oi new ni = do let go ri wi | ri < end = do@@ -325,13 +329,13 @@ go oi ni {-# INLINE cp6 #-}-cp6 :: COUNT_T -> Integer+cp6 :: Int64 -> Integer cp6 k = case k `quotRem` 30030 of (q,r) -> 5760*fromIntegral q + fromIntegral (cpCtAr `unsafeAt` fromIntegral r) -cop :: COUNT_T -> COUNT_T+cop :: Int64 -> Int64 cop m = m - fromIntegral (cpDfAr `unsafeAt` fromIntegral (m `rem` 30030)) @@ -406,3 +410,94 @@ note 26 13 accumulate 2 30027 +-------------------------------------------------------------------------------+-- Prime counting++#if SIZEOF_HSWORD == 8++#define RMASK 63+#define WSHFT 6+#define TOPB 32+#define TOPM 0xFFFFFFFF++#else++#define RMASK 31+#define WSHFT 5+#define TOPB 16+#define TOPM 0xFFFF++#endif++-- find the n-th set bit in a list of PrimeSieves,+-- aka find the (n+3)-rd prime+countToNth :: Int -> [PrimeSieve] -> Integer+countToNth !_ [] = error "countToNth: Prime stream ended prematurely"+countToNth !n (PS v0 bs : more) = go n 0+ where+ wa :: UArray Int Word+ wa = unsafeCoerce bs++ go !k i+ | i == snd (bounds wa)+ = countToNth k more+ | otherwise+ = let w = unsafeAt wa i+ bc = popCount w+ in if bc < k+ then go (k-bc) (i+1)+ else let j = bc - k+ px = top w j bc+ in v0 + toPrim (px + (i `shiftL` WSHFT))++-- count all set bits in a chunk, do it wordwise for speed.+countAll :: PrimeSieve -> Int+countAll (PS _ bs) = go 0 0+ where+ wa :: UArray Int Word+ wa = unsafeCoerce bs++ go !ct i+ | i == snd (bounds wa)+ = ct+ | otherwise+ = go (ct + popCount (unsafeAt wa i)) (i+1)++-- Find the j-th highest of bc set bits in the Word w.+top :: Word -> Int -> Int -> Int+top w j bc = go 0 TOPB TOPM bn w+ where+ !bn = bc-j+ go !_ _ !_ !_ 0 = error "Too few bits set"+ go bs 0 _ _ wd = if wd .&. 1 == 0 then error "Too few bits, shift 0" else bs+ go bs a msk ix wd =+ case popCount (wd .&. msk) of+ lc | lc < ix -> go (bs+a) a msk (ix-lc) (wd `unsafeShiftR` a)+ | otherwise ->+ let !na = a `shiftR` 1+ in go bs na (msk `unsafeShiftR` na) ix wd++-- count set bits between two indices (inclusive)+-- start and end must both be valid indices and start <= end+countFromTo :: Int -> Int -> STUArray s Int Bool -> ST s Int+countFromTo start end ba = do+ wa <- (castSTUArray :: STUArray s Int Bool -> ST s (STUArray s Int Word)) ba+ let !sb = start `shiftR` WSHFT+ !si = start .&. RMASK+ !eb = end `shiftR` WSHFT+ !ei = end .&. RMASK+ count !acc i+ | i == eb = do+ w <- unsafeRead wa i+ return (acc + popCount (w `shiftL` (RMASK - ei)))+ | otherwise = do+ w <- unsafeRead wa i+ count (acc + popCount w) (i+1)+ if sb < eb+ then do+ w <- unsafeRead wa sb+ count (popCount (w `shiftR` si)) (sb+1)+ else do+ w <- unsafeRead wa sb+ let !w1 = w `shiftR` si+ return (popCount (w1 `shiftL` (RMASK - ei + si)))
− Math/NumberTheory/Primes/Factorisation.hs
@@ -1,53 +0,0 @@--- |--- Module: Math.NumberTheory.Primes.Factorisation--- Description: Deprecated--- Copyright: (c) 2011 Daniel Fischer--- Licence: MIT--- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>------ Various functions related to prime factorisation.--- Many of these functions use the prime factorisation of an 'Integer'.--- If several of them are used on the same 'Integer', it would be inefficient--- to recalculate the factorisation, hence there are also functions working--- on the canonical factorisation, these require that the number be positive--- and in the case of the Carmichael function that the list of prime factors--- with their multiplicities is ascending.--module Math.NumberTheory.Primes.Factorisation {-# DEPRECATED "Use 'Math.NumberTheory.Primes.factorise' instead" #-}- ( -- * Factorisation functions- -- $algorithm- -- ** Complete factorisation- factorise- , defaultStdGenFactorisation- , stepFactorisation- , factorise'- , defaultStdGenFactorisation'- -- *** Trial division- , trialDivisionTo- -- ** Partial factorisation- , smallFactors- , stdGenFactorisation- , curveFactorisation- -- *** Single curve worker- , montgomeryFactorisation- ) where--import Math.NumberTheory.Primes.Factorisation.Montgomery-import Math.NumberTheory.Primes.Factorisation.TrialDivision---- $algorithm------ Factorisation of 'Integer's by the elliptic curve algorithm after Montgomery.--- The algorithm is explained at--- <http://programmingpraxis.com/2010/04/23/modern-elliptic-curve-factorization-part-1/>--- and--- <http://programmingpraxis.com/2010/04/27/modern-elliptic-curve-factorization-part-2/>------ The implementation is not very optimised, so it is not suitable for factorising numbers--- with several huge prime divisors. However, factors of 20-25 digits are normally found in--- acceptable time. The time taken depends, however, strongly on how lucky the curve-picking--- is. With luck, even large factors can be found in seconds; on the other hand, finding small--- factors (about 12-15 digits) can take minutes when the curve-picking is bad.------ Given enough time, the algorithm should be able to factor numbers of 100-120 digits, but it--- is best suited for numbers of up to 50-60 digits.
− Math/NumberTheory/Primes/Factorisation/Certified.hs
@@ -1,169 +0,0 @@--- |--- Module: Math.NumberTheory.Primes.Factorisation.Certified--- Description: Deprecated--- Copyright: (c) 2011 Daniel Fischer--- Licence: MIT--- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>------ Factorisation proving the primality of the found factors.------ For large numbers, this will be very slow in general.--- Use only if you're paranoid or must be /really/ sure.-{-# LANGUAGE BangPatterns, CPP #-}-module Math.NumberTheory.Primes.Factorisation.Certified {-# DEPRECATED "This module will be removed in the next release" #-}- ( certifiedFactorisation- , certificateFactorisation- , provenFactorisation- ) where--import System.Random-import Control.Monad.Trans.State.Strict-import Data.Maybe-import Data.Bits-import Data.Traversable--import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Primes.Factorisation.Montgomery-import Math.NumberTheory.Primes.Testing.Certificates.Internal-import Math.NumberTheory.Primes.Testing.Probabilistic---- | @'certifiedFactorisation' n@ produces the prime factorisation--- of @n@, proving the primality of the factors, but doesn't report the proofs.-certifiedFactorisation :: Integer -> [(Integer, Word)]-certifiedFactorisation = map fst . certificateFactorisation---- | @'certificateFactorisation' n@ produces a 'provenFactorisation'.-certificateFactorisation :: Integer -> [((Integer, Word),PrimalityProof)]-certificateFactorisation n = provenFactorisation n---- | @'provenFactorisation' n@ constructs a the prime factorisation of @n@--- (which must be positive) together with proofs of primality of the factors,--- using trial division up to 2^16 and elliptic curve factorisation for the--- remaining factors if necessary.------ Construction of primality proofs can take a /very/ long time, so this--- will usually be slow (but should be faster than using 'factorise' and--- proving the primality of the factors from scratch).-provenFactorisation :: Integer -> [((Integer, Word),PrimalityProof)]-provenFactorisation 1 = []-provenFactorisation n- | n < 2 = error "provenFactorisation: argument not positive"- | otherwise = let bd = 65536 in test $- case smallFactors n of- (sfs,mb) -> map (\t@(p,_) -> (t, smallCert p)) sfs- ++ case mb of- Nothing -> []- Just k -> certiFactorisation (Just $ bd*(bd+2)) primeCheck (randomR . (,) 6)- (mkStdGen $ fromIntegral n `xor` 0xdeadbeef) Nothing k---- | verify that we indeed have a correct primality proof-test :: [((Integer, Word),PrimalityProof)] -> [((Integer, Word),PrimalityProof)]-test (t@((p,_),prf):more)- | p == cprime prf && checkPrimalityProof prf = t : test more- | otherwise = error (invalid p prf)-test [] = []---- | produce a proof of primality for primes--- Only called for (not too small) numbers known to have no small prime factors,--- so we can directly use BPSW without trial division.-primeCheck :: Integer -> Maybe PrimalityProof-primeCheck n- | bailliePSW n = case certifyBPSW n of- proof@Pocklington{} -> Just proof- _ -> Nothing- | otherwise = Nothing---- | produce a certified factorisation--- Assumes all small prime factors have been stripped before.--- Since it is not exported, that is known to hold.--- This is a near duplicate of 'curveFactorisation', I should some time--- clean this up.-certiFactorisation :: Maybe Integer -- ^ Lower bound for composite divisors- -> (Integer -> Maybe PrimalityProof)- -- ^ A primality test- -> (Integer -> g -> (Integer,g)) -- ^ A PRNG- -> g -- ^ Initial PRNG state- -> Maybe Int -- ^ Estimated number of digits of the smallest prime factor- -> Integer -- ^ The number to factorise- -> [((Integer, Word),PrimalityProof)]- -- ^ List of prime factors, exponents and primality proofs-certiFactorisation primeBound primeTest prng seed mbdigs n- = case ptest n of- Just proof -> [((n,1),proof)]- Nothing -> evalState (fact n digits) seed- where- digits = fromMaybe 8 mbdigs- mult 1 xs = xs- mult j xs = [((p,j*k),c) | ((p,k),c) <- xs]- vdb xs = [(p,2*e) | (p,e) <- xs]- dbl (u,v) = (mult 2 u, vdb v)- ptest = case primeBound of- Just bd -> \k -> if k <= bd then (Just $ smallCert k) else primeTest k- Nothing -> primeTest- rndR k = state (\gen -> prng k gen)- fact m digs = do let (b1,b2,ct) = findParms digs- (pfs,cfs) <- repFact m b1 b2 ct- if null cfs- then return pfs- else do- nfs <- forM cfs $ \(k,j) ->- mult j <$> fact k (if null pfs then digs+4 else digs)- return (mergeAll $ pfs:nfs)- repFact m b1 b2 count- | count < 0 = return ([],[(m,1)])- | otherwise = do- s <- rndR m- case s `modulo` fromInteger m of- InfMod{} -> error "impossible case"- SomeMod sm -> case montgomeryFactorisation b1 b2 sm of- Nothing -> repFact m b1 b2 (count-1)- Just d -> do- let !cof = m `quot` d- case gcd cof d of- 1 -> do- (dp,dc) <- case ptest d of- Just proof -> return ([((d,1),proof)],[])- Nothing -> repFact d b1 b2 (count-1)- (cp,cc) <- case ptest cof of- Just proof -> return ([((cof,1),proof)],[])- Nothing -> repFact cof b1 b2 (count-1)- return (merge dp cp, dc ++ cc)- g -> do- let d' = d `quot` g- c' = cof `quot` g- (dp,dc) <- case ptest d' of- Just proof -> return ([((d',1),proof)],[])- Nothing -> repFact d' b1 b2 (count-1)- (cp,cc) <- case ptest c' of- Just proof -> return ([((c',1),proof)],[])- Nothing -> repFact c' b1 b2 (count-1)- (gp,gc) <- case ptest g of- Just proof -> return ([((g,2),proof)],[])- Nothing -> dbl <$> repFact g b1 b2 (count-1)- return (mergeAll [dp,cp,gp], dc ++ cc ++ gc)---- | merge two lists of factors, so that the result is strictly increasing (wrt the primes)-merge :: [((Integer, Word), PrimalityProof)] -> [((Integer, Word), PrimalityProof)] -> [((Integer, Word), PrimalityProof)]-merge xxs@(x@((p,e),c):xs) yys@(y@((q,d),_):ys)- = case compare p q of- LT -> x : merge xs yys- EQ -> ((p,e+d),c) : merge xs ys- GT -> y : merge xxs ys-merge [] ys = ys-merge xs _ = xs---- | merge a list of lists of factors so that the result is strictly increasing (wrt the primes)-mergeAll :: [[((Integer, Word), PrimalityProof)]] -> [((Integer, Word), PrimalityProof)]-mergeAll [] = []-mergeAll [xs] = xs-mergeAll (xs:ys:zss) = merge (merge xs ys) (mergeAll zss)---- | message for an invalid proof, should never be used-invalid :: Integer -> PrimalityProof -> String-invalid p prf = unlines- [ "\nInvalid primality proof constructed, please report this to the package maintainer!"- , "The supposed prime was:\n"- , show p- , "\nThe presumed proof was:\n"- , show prf- ]
Math/NumberTheory/Primes/Factorisation/Montgomery.hs view
@@ -10,70 +10,59 @@ -- and -- <http://programmingpraxis.com/2010/04/27/modern-elliptic-curve-factorization-part-2/> ----- The implementation is not very optimised, so it is not suitable for factorising numbers--- with only huge prime divisors. However, factors of 20-25 digits are normally found in--- acceptable time. The time taken depends, however, strongly on how lucky the curve-picking--- is. With luck, even large factors can be found in seconds; on the other hand, finding small--- factors (about 10 digits) can take minutes when the curve-picking is bad.------ Given enough time, the algorithm should be able to factor numbers of 100-120 digits, but it--- is best suited for numbers of up to 50-60 digits. {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-}-{-# OPTIONS_HADDOCK hide #-} module Math.NumberTheory.Primes.Factorisation.Montgomery ( -- * Complete factorisation functions -- ** Functions with input checking factorise- , defaultStdGenFactorisation- -- ** Functions without input checking- , factorise'- , stepFactorisation- , defaultStdGenFactorisation'- -- * Partial factorisation+ -- -- * Partial factorisation , smallFactors- , stdGenFactorisation- , curveFactorisation- -- ** Single curve worker+ -- -- ** Single curve worker , montgomeryFactorisation , findParms ) where import Control.Arrow import Control.Monad.Trans.State.Lazy-import System.Random+import Data.Array.Base (bounds, unsafeAt) import Data.Bits import Data.IntMap (IntMap) import qualified Data.IntMap as IM import Data.List (foldl') import Data.Maybe+import Data.Mod+import Data.Proxy #if __GLASGOW_HASKELL__ < 803 import Data.Semigroup #endif import Data.Traversable-import Data.Vector.Unboxed (toList)--import GHC.TypeNats.Compat+import GHC.Exts+import GHC.Integer.GMP.Internals hiding (integerToInt, wordToInteger)+import GHC.Natural+import GHC.TypeNats (KnownNat, SomeNat(..), natVal, someNatVal)+import System.Random import Math.NumberTheory.Curves.Montgomery import Math.NumberTheory.Euclidean.Coprimes (splitIntoCoprimes, unCoprimes)-import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Powers.General (highestPower, largePFPower)-import Math.NumberTheory.Powers.Squares (integerSquareRoot')+import Math.NumberTheory.Logarithms (integerLogBase')+import Math.NumberTheory.Roots import Math.NumberTheory.Primes.Sieve.Eratosthenes (PrimeSieve(..), psieveFrom) import Math.NumberTheory.Primes.Sieve.Indexing (toPrim) import Math.NumberTheory.Primes.Small import Math.NumberTheory.Primes.Testing.Probabilistic-import Math.NumberTheory.Unsafe-import Math.NumberTheory.Utils+import Math.NumberTheory.Utils hiding (splitOff)+import Math.NumberTheory.Utils.FromIntegral -- | @'factorise' n@ produces the prime factorisation of @n@. @'factorise' 0@ is -- an error and the factorisation of @1@ is empty. Uses a 'StdGen' produced in@@ -84,49 +73,16 @@ -- -- >>> factorise 10251562501 -- [(101701,1),(100801,1)]-factorise :: Integer -> [(Integer, Word)]-factorise n- | abs n == 1 = []- | n < 0 = factorise (-n)- | n == 0 = error "0 has no prime factorisation"- | otherwise = factorise' n---- | Like 'factorise', but without input checking, hence @n > 1@ is required.-factorise' :: Integer -> [(Integer, Word)]-factorise' n = defaultStdGenFactorisation' (mkStdGen $ fromInteger n `xor` 0xdeadbeef) n---- | @'stepFactorisation'@ is like 'factorise'', except that it doesn't use a--- pseudo random generator but steps through the curves in order.--- This strategy turns out to be surprisingly fast, on average it doesn't--- seem to be slower than the 'StdGen' based variant.-stepFactorisation :: Integer -> [(Integer, Word)]-stepFactorisation n- = let (sfs,mb) = smallFactors n- in sfs ++ case mb of- Nothing -> []- Just r -> curveFactorisation (Just $ 65536 * 65536) bailliePSW- (\m k -> (if k < (m-1) then k else error "Curves exhausted",k+1)) 6 Nothing r---- | @'defaultStdGenFactorisation'@ first strips off all small prime factors and then,--- if the factorisation is not complete, proceeds to curve factorisation.--- For negative numbers, a factor of @-1@ is included, the factorisation of @1@--- is empty. Since @0@ has no prime factorisation, a zero argument causes--- an error.-defaultStdGenFactorisation :: StdGen -> Integer -> [(Integer, Word)]-defaultStdGenFactorisation sg n- | n == 0 = error "0 has no prime factorisation"- | n < 0 = (-1,1) : defaultStdGenFactorisation sg (-n)- | n == 1 = []- | otherwise = defaultStdGenFactorisation' sg n---- | Like 'defaultStdGenFactorisation', but without input checking, so--- @n@ must be larger than @1@.-defaultStdGenFactorisation' :: StdGen -> Integer -> [(Integer, Word)]-defaultStdGenFactorisation' sg n- = let (sfs,mb) = smallFactors n- in sfs ++ case mb of- Nothing -> []- Just m -> stdGenFactorisation (Just $ 65536 * 65536) sg Nothing m+factorise :: Integral a => a -> [(a, Word)]+factorise 0 = error "0 has no prime factorisation"+factorise n' = map (first fromIntegral) sfs <> map (first fromInteger) rest+ where+ n = abs n'+ (sfs, mb) = smallFactors (fromIntegral n)+ sg = mkStdGen (fromIntegral n `xor` 0xdeadbeef)+ rest = case mb of+ Nothing -> []+ Just m -> stdGenFactorisation (Just $ 65536 * 65536) sg Nothing (toInteger m) ---------------------------------------------------------------------------------------------------- -- Factorisation wrappers --@@ -157,8 +113,7 @@ -- chances for a quick result by running several instances in parallel. -- -- 'curveFactorisation' @n@ requires that small (< 65536) prime factors of @n@--- have been stripped before. Otherwise it is likely to cycle forever. When in doubt,--- use 'defaultStdGenFactorisation'.+-- have been stripped before. Otherwise it is likely to cycle forever. -- -- 'curveFactorisation' is unlikely to succeed if @n@ has more than one (really) large prime factor. --@@ -186,7 +141,7 @@ rndR k = state (prng k) perfPw :: Integer -> (Integer, Word)- perfPw = maybe highestPower (largePFPower . integerSquareRoot') primeBound+ perfPw = maybe highestPower (largePFPower . integerSquareRoot) primeBound fact :: Integer -> Int -> State g [(Integer, Word)] fact 1 _ = return mempty@@ -218,9 +173,8 @@ workFact m _ _ 0 = return $ singleCompositeFactor m 1 workFact m b1 b2 count = do s <- rndR m- case s `modulo` fromInteger m of- InfMod{} -> error "impossible case"- SomeMod sm -> case montgomeryFactorisation b1 b2 sm of+ case someNatVal (fromInteger m) of+ SomeNat (_ :: Proxy t) -> case montgomeryFactorisation b1 b2 (fromInteger s :: Mod t) of Nothing -> workFact m b1 b2 (count - 1) Just d -> do let cs = unCoprimes $ splitIntoCoprimes [(d, 1), (m `quot` d, 1)]@@ -255,6 +209,52 @@ modifyPowers f (Factors pfs cfs) = Factors (map (second f) pfs) (map (second f) cfs) +-------------------------------------------------------------------------------+-- largePFPower++-- | @'largePFPower' bd n@ produces the pair @(b,k)@ with the largest+-- exponent @k@ such that @n == b^k@, where @bd > 1@ (it is expected+-- that @bd@ is much larger, at least @1000@ or so), @n > bd^2@ and @n@+-- has no prime factors @p <= bd@, skipping the trial division phase+-- of @'highestPower'@ when that is a priori known to be superfluous.+-- It is only present to avoid duplication of work in factorisation+-- and primality testing, it is not expected to be generally useful.+-- The assumptions are not checked, if they are not satisfied, wrong+-- results and wasted work may be the consequence.+largePFPower :: Integer -> Integer -> (Integer, Word)+largePFPower bd n = rawPower ln n+ where+ ln = intToWord (integerLogBase' (bd+1) n)++rawPower :: Word -> Integer -> (Integer, Word)+rawPower mx n = case exactRoot 4 n of+ Just r -> case rawPower (mx `quot` 4) r of+ (m,e) -> (m, 4*e)+ Nothing -> case exactSquareRoot n of+ Just r -> case rawOddPower (mx `quot` 2) r of+ (m,e) -> (m, 2*e)+ Nothing -> rawOddPower mx n++rawOddPower :: Word -> Integer -> (Integer, Word)+rawOddPower mx n+ | mx < 3 = (n,1)+rawOddPower mx n = case exactCubeRoot n of+ Just r -> case rawOddPower (mx `quot` 3) r of+ (m,e) -> (m, 3*e)+ Nothing -> badPower mx n++badPower :: Word -> Integer -> (Integer, Word)+badPower mx n+ | mx < 5 = (n,1)+ | otherwise = go 1 mx n (takeWhile (<= mx) $ scanl (+) 5 $ cycle [2,4])+ where+ go !e b m (k:ks)+ | b < k = (m,e)+ | otherwise = case exactRoot k m of+ Just r -> go (e*k) (b `quot` k) r (k:ks)+ Nothing -> go e b m ks+ go e _ m [] = (m,e)+ ---------------------------------------------------------------------------------------------------- -- The workhorse -- ----------------------------------------------------------------------------------------------------@@ -273,7 +273,7 @@ -- -- The result is maybe a nontrivial divisor of @n@. montgomeryFactorisation :: KnownNat n => Word -> Word -> Mod n -> Maybe Integer-montgomeryFactorisation b1 b2 s = case newPoint (getVal s) n of+montgomeryFactorisation b1 b2 s = case newPoint (toInteger (unMod s)) n of Nothing -> Nothing Just (SomePoint p0) -> do -- Small step: for each prime p <= b1@@ -281,14 +281,14 @@ let q = foldl (flip multiply) p0 smallPowers z = pointZ q - fromIntegral <$> case gcd n z of+ case gcd n z of -- If small step did not succeed, perform a big step. 1 -> case gcd n (bigStep q b1 b2) of 1 -> Nothing g -> Just g g -> Just g where- n = getMod s+ n = toInteger (natVal s) smallPowers = map findPower $ takeWhile (<= b1) (2 : 3 : 5 : list primeStore)@@ -350,22 +350,57 @@ -- | @'smallFactors' n@ finds all prime divisors of @n > 1@ up to 2^16 by trial division and returns the -- list of these together with their multiplicities, and a possible remaining factor which may be composite.-smallFactors :: Integer -> ([(Integer, Word)], Maybe Integer)-smallFactors n = case shiftToOddCount n of- (0,m) -> go m prms- (k,m) -> (2,k) <: if m == 1 then ([],Nothing) else go m prms+smallFactors :: Natural -> ([(Natural, Word)], Maybe Natural)+smallFactors = \case+ NatS# 0## -> error "0 has no prime factorisation"+ NatS# n# -> case shiftToOddCount# n# of+ (# 0##, m# #) -> goWord m# 1+ (# k#, m# #) -> (2, W# k#) <: goWord m# 1+ NatJ# n -> case shiftToOddCountBigNat n of+ (0, m) -> goBigNat m 1+ (k, m) -> (2, k) <: goBigNat m 1 where- prms = map fromIntegral $ toList smallPrimes x <: ~(l,b) = (x:l,b)- go m []- | m < 65536 * 65536 = ([(m, 1)], Nothing)- | otherwise = ([], Just m)- go m (p:ps)- | m < p*p = ([(m,1)], Nothing)- | otherwise = case splitOff p m of- (0,_) -> go m ps- (k,r) | r == 1 -> ([(p,k)], Nothing)- | otherwise -> (p,k) <: go r ps++ !(Ptr smallPrimesAddr#) = smallPrimesPtr++ goBigNat :: BigNat -> Int -> ([(Natural, Word)], Maybe Natural)+ goBigNat !m !i@(I# i#)+ | isTrue# (sizeofBigNat# m ==# 1#)+ = goWord (bigNatToWord m) i+ | i >= smallPrimesLength+ = ([], Just (NatJ# m))+ | otherwise+ = let p# = indexWord16OffAddr# smallPrimesAddr# i# in+ case m `quotRemBigNatWord` p# of+ (# mp, 0## #) ->+ let (# k, r #) = splitOff 1 mp in+ (NatS# p#, k) <: goBigNat r (i + 1)+ where+ splitOff !k x = case x `quotRemBigNatWord` p# of+ (# xp, 0## #) -> splitOff (k + 1) xp+ _ -> (# k, x #)+ _ -> goBigNat m (i + 1)++ goWord :: Word# -> Int -> ([(Natural, Word)], Maybe Natural)+ goWord 1## !_ = ([], Nothing)+ goWord m# !i+ | i >= smallPrimesLength+ = if isTrue# (m# `leWord#` 4294967295##) -- 65536 * 65536 - 1+ then ([(NatS# m#, 1)], Nothing)+ else ([], Just (NatS# m#))+ goWord m# !i@(I# i#) = let p# = indexWord16OffAddr# smallPrimesAddr# i# in+ if isTrue# (m# `ltWord#` (p# `timesWord#` p#))+ then ([(NatS# m#, 1)], Nothing)+ else case m# `quotRemWord#` p# of+ (# mp#, 0## #) ->+ let !(# k#, r# #) = splitOff 1## mp# in+ (NatS# p#, W# k#) <: goWord r# (i + 1)+ where+ splitOff k# x# = case x# `quotRemWord#` p# of+ (# xp#, 0## #) -> splitOff (k# `plusWord#` 1##) xp#+ _ -> (# k#, x# #)+ _ -> goWord m# (i + 1) -- | For a given estimated decimal length of the smallest prime factor -- ("tier") return parameters B1, B2 and the number of curves to try
Math/NumberTheory/Primes/Factorisation/TrialDivision.hs view
@@ -13,12 +13,11 @@ module Math.NumberTheory.Primes.Factorisation.TrialDivision ( trialDivisionWith , trialDivisionTo- , trialDivisionPrimeWith , trialDivisionPrimeTo ) where import Math.NumberTheory.Primes.Sieve.Eratosthenes (primeList, primeSieve, psieveList)-import Math.NumberTheory.Powers.Squares+import Math.NumberTheory.Roots import Math.NumberTheory.Primes.Types import Math.NumberTheory.Utils @@ -30,7 +29,7 @@ | n < 0 = trialDivisionWith prs (-n) | n == 0 = error "trialDivision of 0" | n == 1 = []- | otherwise = go n (integerSquareRoot' n) prs+ | otherwise = go n (integerSquareRoot n) prs where go !m !r (p:ps) | r < p = [(m,1)]@@ -39,7 +38,7 @@ (0,_) -> go m r ps (k,q) -> (p,k) : if q == 1 then []- else go q (integerSquareRoot' q) ps+ else go q (integerSquareRoot q) ps go m _ _ = [(m,1)] -- | @'trialDivisionTo' bound n@ produces a factorisation of @n@ using the@@ -58,7 +57,7 @@ trialDivisionPrimeWith prs n | n < 0 = trialDivisionPrimeWith prs (-n) | n < 2 = False- | otherwise = go n (integerSquareRoot' n) prs+ | otherwise = go n (integerSquareRoot n) prs where go !m !r (p:ps) = r < p || m `rem` p /= 0 && go m r ps go _ _ _ = True
− Math/NumberTheory/Primes/Sieve.hs
@@ -1,62 +0,0 @@--- |--- Module: Math.NumberTheory.Primes.Sieve--- Description: Deprecated--- Copyright: (c) 2011 Daniel Fischer--- Licence: MIT--- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>------ Prime generation using a sieve.--- Currently, an enhanced sieve of Eratosthenes is used, switching to an--- Atkin sieve is planned (if I get around to implementing it and it's not slower).------ The sieve used is segmented, with a chunk size chosen to give good (enough)--- cache locality while still getting something substantial done per chunk.--- However, that means we must store data for primes up to the square root of--- where sieving is done, thus sieving primes up to @n@ requires--- @/O/(sqrt n/log n)@ space.--module Math.NumberTheory.Primes.Sieve {-# DEPRECATED "Use 'Enum' instance of 'Math.NumberTheory.Primes.Prime' instead" #-}- ( -- * Limitations- -- $limits-- -- * Sieves and lists- primes- , sieveFrom- , PrimeSieve- , primeSieve- , psieveList- , psieveFrom- , primeList- ) where--import Math.NumberTheory.Primes.Sieve.Eratosthenes---- $limits------ There are three factors limiting the range of these sieves.------ (1) Memory------ (2) Overflow------ (3) The internal representation of the state------ An Eratosthenes type sieve needs to store the primes up to the square root of--- the currently sieved region, thus requires @/O/(sqrt n\/log n)@ space.We store @16@ bytes--- of information per prime, thus a Gigabyte of memory takes you to about @1.6*10^18@.--- The @log@ doesn't change much in that range, so as a first approximation, doubling--- the storage increases the sieve range by a factor of four.------ On a 64-bit system, this is (currently) the only limitation to be concerned with, but--- with more than four Terabyte of memory, the fact that the internal representation--- currently limits the sieve range to about @6.8*10^25@ could become relevant.--- Overflow in array indexing doesn't become a concern before memory and internal--- representation would allow to sieve past @10^37@.------ On a 32-bit system, the internal representation imposes no additional limits,--- but overflow has to be reckoned with. On the one hand, the fact that arrays are--- 'Int'-indexed restricts the size of the prime store, on the other hand, overflow--- in calculating the indices to cross off multiples is possible before running out--- of memory. The former limits the upper bound of the monolithic 'primeSieve' to--- shortly above @8*10^9@, the latter limits the range of the segmented sieves to--- about @1.7*10^18@.
Math/NumberTheory/Primes/Sieve/Eratosthenes.hs view
@@ -13,19 +13,13 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -fspec-constr-count=8 #-}-{-# OPTIONS_HADDOCK hide #-} module Math.NumberTheory.Primes.Sieve.Eratosthenes ( primes- , sieveFrom , psieveFrom , PrimeSieve(..) , psieveList , primeList , primeSieve- , nthPrimeCt- , countFromTo- , countAll- , countToNth , sieveBits , sieveRange , sieveTo@@ -33,24 +27,18 @@ #include "MachDeps.h" +import Control.Monad (when) import Control.Monad.ST+import Data.Array.Base import Data.Array.ST-import Data.Array.Unboxed+import Data.Bits import Data.Coerce import Data.Proxy-import Control.Monad (when)-import Data.Bits-#if WORD_SIZE_IN_BITS == 32 import Data.Word-#endif -import Math.NumberTheory.Powers.Squares (integerSquareRoot)-import Math.NumberTheory.Unsafe-import Math.NumberTheory.Utils-import Math.NumberTheory.Utils.FromIntegral-import Math.NumberTheory.Primes.Counting.Approximate import Math.NumberTheory.Primes.Sieve.Indexing import Math.NumberTheory.Primes.Types+import Math.NumberTheory.Roots #define IX_MASK 0xFFFFF #define IX_BITS 20@@ -78,17 +66,14 @@ sieveRange :: Int sieveRange = 30*sieveBytes -sieveWords :: Int-sieveWords = sieveBytes `quot` SIZEOF_HSWORD+type CacheWord = Word64 #if SIZEOF_HSWORD == 8-type CacheWord = Word #define RMASK 63 #define WSHFT 6 #define TOPB 32 #define TOPM 0xFFFFFFFF #else-type CacheWord = Word64 #define RMASK 31 #define WSHFT 5 #define TOPB 16@@ -191,7 +176,7 @@ then do let !i = indx .&. J_MASK k = indx `shiftR` J_BITS- strt1 = (k*(30*k + 2*rho i) + byte i) `shiftL` J_BITS + fromIntegral (idx i)+ strt1 = (k*(30*k + 2*rho i) + byte i) `shiftL` J_BITS + idx i !strt = fromIntegral (strt1 .&. IX_MASK) !skip = fromIntegral (strt1 `shiftR` IX_BITS) !ixes = fromIntegral indx `shiftL` IX_J_BITS + strt `shiftL` J_BITS + fromIntegral i@@ -341,39 +326,9 @@ | eb < i = return acc | otherwise = do w <- unsafeRead wa i- count (acc + bitCountWord w) (i+1)+ count (acc + popCount w) (i+1) count 0 sb --- count set bits between two indices (inclusive)--- start and end must both be valid indices and start <= end-countFromTo :: Int -> Int -> STUArray s Int Bool -> ST s Int-countFromTo start end ba = do- wa <- (castSTUArray :: STUArray s Int Bool -> ST s (STUArray s Int Word)) ba- let !sb = start `shiftR` WSHFT- !si = start .&. RMASK- !eb = end `shiftR` WSHFT- !ei = end .&. RMASK- count !acc i- | i == eb = do- w <- unsafeRead wa i- return (acc + bitCountWord (w `shiftL` (RMASK - ei)))- | otherwise = do- w <- unsafeRead wa i- count (acc + bitCountWord w) (i+1)- if sb < eb- then do- w <- unsafeRead wa sb- count (bitCountWord (w `shiftR` si)) (sb+1)- else do- w <- unsafeRead wa sb- let !w1 = w `shiftR` si- return (bitCountWord (w1 `shiftL` (RMASK - ei + si)))---- | @'sieveFrom' n@ creates the list of primes not less than @n@.-sieveFrom :: Integer -> [Prime Integer]-sieveFrom n = case psieveFrom n of- ps -> dropWhile ((< n) . unPrime) (ps >>= primeList)- -- | @'psieveFrom' n@ creates the list of 'PrimeSieve's starting roughly -- at @n@. Due to the organisation of the sieve, the list may contain -- a few primes less than @n@.@@ -435,74 +390,6 @@ else fill j (indx+1) fill 0 0 --- prime counting--nthPrimeCt :: Integer -> Integer-nthPrimeCt 1 = 2-nthPrimeCt 2 = 3-nthPrimeCt 3 = 5-nthPrimeCt 4 = 7-nthPrimeCt 5 = 11-nthPrimeCt 6 = 13-nthPrimeCt n- | n < 1 = error "nthPrimeCt: negative argument"- | n < 200000 = let bd0 = nthPrimeApprox n- bnd = bd0 + bd0 `quot` 32 + 37- !sv = primeSieve bnd- in countToNth (n-3) [sv]- | otherwise = countToNth (n-3) (psieveFrom (intToInteger $ fromInteger n .&. (7 :: Int)))---- find the n-th set bit in a list of PrimeSieves,--- aka find the (n+3)-rd prime-countToNth :: Integer -> [PrimeSieve] -> Integer-countToNth !n ps = runST (countDown n ps)--countDown :: Integer -> [PrimeSieve] -> ST s Integer-countDown !n (ps@(PS v0 bs) : more)- | n > 278734 || (v0 /= 0 && n > 253000) = do- ct <- countAll ps- countDown (n - fromIntegral ct) more- | otherwise = do- stu <- unsafeThaw bs- wa <- (castSTUArray :: STUArray s Int Bool -> ST s (STUArray s Int Word)) stu- let go !k i- | i == sieveWords = countDown k more- | otherwise = do- w <- unsafeRead wa i- let !bc = fromIntegral $ bitCountWord w- if bc < k- then go (k-bc) (i+1)- else let !j = fromIntegral (bc - k)- !px = top w j (fromIntegral bc)- in return (v0 + toPrim (px+(i `shiftL` WSHFT)))- go n 0-countDown _ [] = error "Prime stream ended prematurely"---- count all set bits in a chunk, do it wordwise for speed.-countAll :: PrimeSieve -> ST s Int-countAll (PS _ bs) = do- stu <- unsafeThaw bs- wa <- (castSTUArray :: STUArray s Int Bool -> ST s (STUArray s Int Word)) stu- let go !ct i- | i == sieveWords = return ct- | otherwise = do- w <- unsafeRead wa i- go (ct + bitCountWord w) (i+1)- go 0 0---- Find the j-th highest of bc set bits in the Word w.-top :: Word -> Int -> Int -> Int-top w j bc = go 0 TOPB TOPM bn w- where- !bn = bc-j- go !_ _ !_ !_ 0 = error "Too few bits set"- go bs 0 _ _ wd = if wd .&. 1 == 0 then error "Too few bits, shift 0" else bs- go bs a msk ix wd =- case bitCountWord (wd .&. msk) of- lc | lc < ix -> go (bs+a) a msk (ix-lc) (wd `uncheckedShiftR` a)- | otherwise ->- let !na = a `shiftR` 1- in go bs na (msk `uncheckedShiftR` na) ix wd {-# INLINE delta #-} delta :: Int -> Int
Math/NumberTheory/Primes/Sieve/Indexing.hs view
@@ -6,17 +6,14 @@ -- -- Auxiliary stuff, conversion between number and index, -- remainders modulo 30 and related things.-{-# OPTIONS_HADDOCK hide #-} module Math.NumberTheory.Primes.Sieve.Indexing ( idxPr , toPrim , rho ) where -import Data.Array.Unboxed+import Data.Array.Base import Data.Bits--import Math.NumberTheory.Unsafe {-# INLINE idxPr #-} idxPr :: Integral a => a -> (Int,Int)
Math/NumberTheory/Primes/Small.hs view
@@ -8,13 +8,49 @@ -- defining an array of precalculated primes < 2^16. -- +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+ module Math.NumberTheory.Primes.Small- ( smallPrimes+ ( smallPrimesPtr+ , smallPrimesLength+ , smallPrimesFromTo ) where -import Data.Vector.Unboxed (Vector, fromList)-import Data.Word+import GHC.Exts hiding (fromList)+import GHC.Word -smallPrimes :: Vector Word16-smallPrimes = fromList- [2,3,5,7,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,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733,9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857,9859,9871,9883,9887,9901,9907,9923,9929,9931,9941,9949,9967,9973,10007,10009,10037,10039,10061,10067,10069,10079,10091,10093,10099,10103,10111,10133,10139,10141,10151,10159,10163,10169,10177,10181,10193,10211,10223,10243,10247,10253,10259,10267,10271,10273,10289,10301,10303,10313,10321,10331,10333,10337,10343,10357,10369,10391,10399,10427,10429,10433,10453,10457,10459,10463,10477,10487,10499,10501,10513,10529,10531,10559,10567,10589,10597,10601,10607,10613,10627,10631,10639,10651,10657,10663,10667,10687,10691,10709,10711,10723,10729,10733,10739,10753,10771,10781,10789,10799,10831,10837,10847,10853,10859,10861,10867,10883,10889,10891,10903,10909,10937,10939,10949,10957,10973,10979,10987,10993,11003,11027,11047,11057,11059,11069,11071,11083,11087,11093,11113,11117,11119,11131,11149,11159,11161,11171,11173,11177,11197,11213,11239,11243,11251,11257,11261,11273,11279,11287,11299,11311,11317,11321,11329,11351,11353,11369,11383,11393,11399,11411,11423,11437,11443,11447,11467,11471,11483,11489,11491,11497,11503,11519,11527,11549,11551,11579,11587,11593,11597,11617,11621,11633,11657,11677,11681,11689,11699,11701,11717,11719,11731,11743,11777,11779,11783,11789,11801,11807,11813,11821,11827,11831,11833,11839,11863,11867,11887,11897,11903,11909,11923,11927,11933,11939,11941,11953,11959,11969,11971,11981,11987,12007,12011,12037,12041,12043,12049,12071,12073,12097,12101,12107,12109,12113,12119,12143,12149,12157,12161,12163,12197,12203,12211,12227,12239,12241,12251,12253,12263,12269,12277,12281,12289,12301,12323,12329,12343,12347,12373,12377,12379,12391,12401,12409,12413,12421,12433,12437,12451,12457,12473,12479,12487,12491,12497,12503,12511,12517,12527,12539,12541,12547,12553,12569,12577,12583,12589,12601,12611,12613,12619,12637,12641,12647,12653,12659,12671,12689,12697,12703,12713,12721,12739,12743,12757,12763,12781,12791,12799,12809,12821,12823,12829,12841,12853,12889,12893,12899,12907,12911,12917,12919,12923,12941,12953,12959,12967,12973,12979,12983,13001,13003,13007,13009,13033,13037,13043,13049,13063,13093,13099,13103,13109,13121,13127,13147,13151,13159,13163,13171,13177,13183,13187,13217,13219,13229,13241,13249,13259,13267,13291,13297,13309,13313,13327,13331,13337,13339,13367,13381,13397,13399,13411,13417,13421,13441,13451,13457,13463,13469,13477,13487,13499,13513,13523,13537,13553,13567,13577,13591,13597,13613,13619,13627,13633,13649,13669,13679,13681,13687,13691,13693,13697,13709,13711,13721,13723,13729,13751,13757,13759,13763,13781,13789,13799,13807,13829,13831,13841,13859,13873,13877,13879,13883,13901,13903,13907,13913,13921,13931,13933,13963,13967,13997,13999,14009,14011,14029,14033,14051,14057,14071,14081,14083,14087,14107,14143,14149,14153,14159,14173,14177,14197,14207,14221,14243,14249,14251,14281,14293,14303,14321,14323,14327,14341,14347,14369,14387,14389,14401,14407,14411,14419,14423,14431,14437,14447,14449,14461,14479,14489,14503,14519,14533,14537,14543,14549,14551,14557,14561,14563,14591,14593,14621,14627,14629,14633,14639,14653,14657,14669,14683,14699,14713,14717,14723,14731,14737,14741,14747,14753,14759,14767,14771,14779,14783,14797,14813,14821,14827,14831,14843,14851,14867,14869,14879,14887,14891,14897,14923,14929,14939,14947,14951,14957,14969,14983,15013,15017,15031,15053,15061,15073,15077,15083,15091,15101,15107,15121,15131,15137,15139,15149,15161,15173,15187,15193,15199,15217,15227,15233,15241,15259,15263,15269,15271,15277,15287,15289,15299,15307,15313,15319,15329,15331,15349,15359,15361,15373,15377,15383,15391,15401,15413,15427,15439,15443,15451,15461,15467,15473,15493,15497,15511,15527,15541,15551,15559,15569,15581,15583,15601,15607,15619,15629,15641,15643,15647,15649,15661,15667,15671,15679,15683,15727,15731,15733,15737,15739,15749,15761,15767,15773,15787,15791,15797,15803,15809,15817,15823,15859,15877,15881,15887,15889,15901,15907,15913,15919,15923,15937,15959,15971,15973,15991,16001,16007,16033,16057,16061,16063,16067,16069,16073,16087,16091,16097,16103,16111,16127,16139,16141,16183,16187,16189,16193,16217,16223,16229,16231,16249,16253,16267,16273,16301,16319,16333,16339,16349,16361,16363,16369,16381,16411,16417,16421,16427,16433,16447,16451,16453,16477,16481,16487,16493,16519,16529,16547,16553,16561,16567,16573,16603,16607,16619,16631,16633,16649,16651,16657,16661,16673,16691,16693,16699,16703,16729,16741,16747,16759,16763,16787,16811,16823,16829,16831,16843,16871,16879,16883,16889,16901,16903,16921,16927,16931,16937,16943,16963,16979,16981,16987,16993,17011,17021,17027,17029,17033,17041,17047,17053,17077,17093,17099,17107,17117,17123,17137,17159,17167,17183,17189,17191,17203,17207,17209,17231,17239,17257,17291,17293,17299,17317,17321,17327,17333,17341,17351,17359,17377,17383,17387,17389,17393,17401,17417,17419,17431,17443,17449,17467,17471,17477,17483,17489,17491,17497,17509,17519,17539,17551,17569,17573,17579,17581,17597,17599,17609,17623,17627,17657,17659,17669,17681,17683,17707,17713,17729,17737,17747,17749,17761,17783,17789,17791,17807,17827,17837,17839,17851,17863,17881,17891,17903,17909,17911,17921,17923,17929,17939,17957,17959,17971,17977,17981,17987,17989,18013,18041,18043,18047,18049,18059,18061,18077,18089,18097,18119,18121,18127,18131,18133,18143,18149,18169,18181,18191,18199,18211,18217,18223,18229,18233,18251,18253,18257,18269,18287,18289,18301,18307,18311,18313,18329,18341,18353,18367,18371,18379,18397,18401,18413,18427,18433,18439,18443,18451,18457,18461,18481,18493,18503,18517,18521,18523,18539,18541,18553,18583,18587,18593,18617,18637,18661,18671,18679,18691,18701,18713,18719,18731,18743,18749,18757,18773,18787,18793,18797,18803,18839,18859,18869,18899,18911,18913,18917,18919,18947,18959,18973,18979,19001,19009,19013,19031,19037,19051,19069,19073,19079,19081,19087,19121,19139,19141,19157,19163,19181,19183,19207,19211,19213,19219,19231,19237,19249,19259,19267,19273,19289,19301,19309,19319,19333,19373,19379,19381,19387,19391,19403,19417,19421,19423,19427,19429,19433,19441,19447,19457,19463,19469,19471,19477,19483,19489,19501,19507,19531,19541,19543,19553,19559,19571,19577,19583,19597,19603,19609,19661,19681,19687,19697,19699,19709,19717,19727,19739,19751,19753,19759,19763,19777,19793,19801,19813,19819,19841,19843,19853,19861,19867,19889,19891,19913,19919,19927,19937,19949,19961,19963,19973,19979,19991,19993,19997,20011,20021,20023,20029,20047,20051,20063,20071,20089,20101,20107,20113,20117,20123,20129,20143,20147,20149,20161,20173,20177,20183,20201,20219,20231,20233,20249,20261,20269,20287,20297,20323,20327,20333,20341,20347,20353,20357,20359,20369,20389,20393,20399,20407,20411,20431,20441,20443,20477,20479,20483,20507,20509,20521,20533,20543,20549,20551,20563,20593,20599,20611,20627,20639,20641,20663,20681,20693,20707,20717,20719,20731,20743,20747,20749,20753,20759,20771,20773,20789,20807,20809,20849,20857,20873,20879,20887,20897,20899,20903,20921,20929,20939,20947,20959,20963,20981,20983,21001,21011,21013,21017,21019,21023,21031,21059,21061,21067,21089,21101,21107,21121,21139,21143,21149,21157,21163,21169,21179,21187,21191,21193,21211,21221,21227,21247,21269,21277,21283,21313,21317,21319,21323,21341,21347,21377,21379,21383,21391,21397,21401,21407,21419,21433,21467,21481,21487,21491,21493,21499,21503,21517,21521,21523,21529,21557,21559,21563,21569,21577,21587,21589,21599,21601,21611,21613,21617,21647,21649,21661,21673,21683,21701,21713,21727,21737,21739,21751,21757,21767,21773,21787,21799,21803,21817,21821,21839,21841,21851,21859,21863,21871,21881,21893,21911,21929,21937,21943,21961,21977,21991,21997,22003,22013,22027,22031,22037,22039,22051,22063,22067,22073,22079,22091,22093,22109,22111,22123,22129,22133,22147,22153,22157,22159,22171,22189,22193,22229,22247,22259,22271,22273,22277,22279,22283,22291,22303,22307,22343,22349,22367,22369,22381,22391,22397,22409,22433,22441,22447,22453,22469,22481,22483,22501,22511,22531,22541,22543,22549,22567,22571,22573,22613,22619,22621,22637,22639,22643,22651,22669,22679,22691,22697,22699,22709,22717,22721,22727,22739,22741,22751,22769,22777,22783,22787,22807,22811,22817,22853,22859,22861,22871,22877,22901,22907,22921,22937,22943,22961,22963,22973,22993,23003,23011,23017,23021,23027,23029,23039,23041,23053,23057,23059,23063,23071,23081,23087,23099,23117,23131,23143,23159,23167,23173,23189,23197,23201,23203,23209,23227,23251,23269,23279,23291,23293,23297,23311,23321,23327,23333,23339,23357,23369,23371,23399,23417,23431,23447,23459,23473,23497,23509,23531,23537,23539,23549,23557,23561,23563,23567,23581,23593,23599,23603,23609,23623,23627,23629,23633,23663,23669,23671,23677,23687,23689,23719,23741,23743,23747,23753,23761,23767,23773,23789,23801,23813,23819,23827,23831,23833,23857,23869,23873,23879,23887,23893,23899,23909,23911,23917,23929,23957,23971,23977,23981,23993,24001,24007,24019,24023,24029,24043,24049,24061,24071,24077,24083,24091,24097,24103,24107,24109,24113,24121,24133,24137,24151,24169,24179,24181,24197,24203,24223,24229,24239,24247,24251,24281,24317,24329,24337,24359,24371,24373,24379,24391,24407,24413,24419,24421,24439,24443,24469,24473,24481,24499,24509,24517,24527,24533,24547,24551,24571,24593,24611,24623,24631,24659,24671,24677,24683,24691,24697,24709,24733,24749,24763,24767,24781,24793,24799,24809,24821,24841,24847,24851,24859,24877,24889,24907,24917,24919,24923,24943,24953,24967,24971,24977,24979,24989,25013,25031,25033,25037,25057,25073,25087,25097,25111,25117,25121,25127,25147,25153,25163,25169,25171,25183,25189,25219,25229,25237,25243,25247,25253,25261,25301,25303,25307,25309,25321,25339,25343,25349,25357,25367,25373,25391,25409,25411,25423,25439,25447,25453,25457,25463,25469,25471,25523,25537,25541,25561,25577,25579,25583,25589,25601,25603,25609,25621,25633,25639,25643,25657,25667,25673,25679,25693,25703,25717,25733,25741,25747,25759,25763,25771,25793,25799,25801,25819,25841,25847,25849,25867,25873,25889,25903,25913,25919,25931,25933,25939,25943,25951,25969,25981,25997,25999,26003,26017,26021,26029,26041,26053,26083,26099,26107,26111,26113,26119,26141,26153,26161,26171,26177,26183,26189,26203,26209,26227,26237,26249,26251,26261,26263,26267,26293,26297,26309,26317,26321,26339,26347,26357,26371,26387,26393,26399,26407,26417,26423,26431,26437,26449,26459,26479,26489,26497,26501,26513,26539,26557,26561,26573,26591,26597,26627,26633,26641,26647,26669,26681,26683,26687,26693,26699,26701,26711,26713,26717,26723,26729,26731,26737,26759,26777,26783,26801,26813,26821,26833,26839,26849,26861,26863,26879,26881,26891,26893,26903,26921,26927,26947,26951,26953,26959,26981,26987,26993,27011,27017,27031,27043,27059,27061,27067,27073,27077,27091,27103,27107,27109,27127,27143,27179,27191,27197,27211,27239,27241,27253,27259,27271,27277,27281,27283,27299,27329,27337,27361,27367,27397,27407,27409,27427,27431,27437,27449,27457,27479,27481,27487,27509,27527,27529,27539,27541,27551,27581,27583,27611,27617,27631,27647,27653,27673,27689,27691,27697,27701,27733,27737,27739,27743,27749,27751,27763,27767,27773,27779,27791,27793,27799,27803,27809,27817,27823,27827,27847,27851,27883,27893,27901,27917,27919,27941,27943,27947,27953,27961,27967,27983,27997,28001,28019,28027,28031,28051,28057,28069,28081,28087,28097,28099,28109,28111,28123,28151,28163,28181,28183,28201,28211,28219,28229,28277,28279,28283,28289,28297,28307,28309,28319,28349,28351,28387,28393,28403,28409,28411,28429,28433,28439,28447,28463,28477,28493,28499,28513,28517,28537,28541,28547,28549,28559,28571,28573,28579,28591,28597,28603,28607,28619,28621,28627,28631,28643,28649,28657,28661,28663,28669,28687,28697,28703,28711,28723,28729,28751,28753,28759,28771,28789,28793,28807,28813,28817,28837,28843,28859,28867,28871,28879,28901,28909,28921,28927,28933,28949,28961,28979,29009,29017,29021,29023,29027,29033,29059,29063,29077,29101,29123,29129,29131,29137,29147,29153,29167,29173,29179,29191,29201,29207,29209,29221,29231,29243,29251,29269,29287,29297,29303,29311,29327,29333,29339,29347,29363,29383,29387,29389,29399,29401,29411,29423,29429,29437,29443,29453,29473,29483,29501,29527,29531,29537,29567,29569,29573,29581,29587,29599,29611,29629,29633,29641,29663,29669,29671,29683,29717,29723,29741,29753,29759,29761,29789,29803,29819,29833,29837,29851,29863,29867,29873,29879,29881,29917,29921,29927,29947,29959,29983,29989,30011,30013,30029,30047,30059,30071,30089,30091,30097,30103,30109,30113,30119,30133,30137,30139,30161,30169,30181,30187,30197,30203,30211,30223,30241,30253,30259,30269,30271,30293,30307,30313,30319,30323,30341,30347,30367,30389,30391,30403,30427,30431,30449,30467,30469,30491,30493,30497,30509,30517,30529,30539,30553,30557,30559,30577,30593,30631,30637,30643,30649,30661,30671,30677,30689,30697,30703,30707,30713,30727,30757,30763,30773,30781,30803,30809,30817,30829,30839,30841,30851,30853,30859,30869,30871,30881,30893,30911,30931,30937,30941,30949,30971,30977,30983,31013,31019,31033,31039,31051,31063,31069,31079,31081,31091,31121,31123,31139,31147,31151,31153,31159,31177,31181,31183,31189,31193,31219,31223,31231,31237,31247,31249,31253,31259,31267,31271,31277,31307,31319,31321,31327,31333,31337,31357,31379,31387,31391,31393,31397,31469,31477,31481,31489,31511,31513,31517,31531,31541,31543,31547,31567,31573,31583,31601,31607,31627,31643,31649,31657,31663,31667,31687,31699,31721,31723,31727,31729,31741,31751,31769,31771,31793,31799,31817,31847,31849,31859,31873,31883,31891,31907,31957,31963,31973,31981,31991,32003,32009,32027,32029,32051,32057,32059,32063,32069,32077,32083,32089,32099,32117,32119,32141,32143,32159,32173,32183,32189,32191,32203,32213,32233,32237,32251,32257,32261,32297,32299,32303,32309,32321,32323,32327,32341,32353,32359,32363,32369,32371,32377,32381,32401,32411,32413,32423,32429,32441,32443,32467,32479,32491,32497,32503,32507,32531,32533,32537,32561,32563,32569,32573,32579,32587,32603,32609,32611,32621,32633,32647,32653,32687,32693,32707,32713,32717,32719,32749,32771,32779,32783,32789,32797,32801,32803,32831,32833,32839,32843,32869,32887,32909,32911,32917,32933,32939,32941,32957,32969,32971,32983,32987,32993,32999,33013,33023,33029,33037,33049,33053,33071,33073,33083,33091,33107,33113,33119,33149,33151,33161,33179,33181,33191,33199,33203,33211,33223,33247,33287,33289,33301,33311,33317,33329,33331,33343,33347,33349,33353,33359,33377,33391,33403,33409,33413,33427,33457,33461,33469,33479,33487,33493,33503,33521,33529,33533,33547,33563,33569,33577,33581,33587,33589,33599,33601,33613,33617,33619,33623,33629,33637,33641,33647,33679,33703,33713,33721,33739,33749,33751,33757,33767,33769,33773,33791,33797,33809,33811,33827,33829,33851,33857,33863,33871,33889,33893,33911,33923,33931,33937,33941,33961,33967,33997,34019,34031,34033,34039,34057,34061,34123,34127,34129,34141,34147,34157,34159,34171,34183,34211,34213,34217,34231,34253,34259,34261,34267,34273,34283,34297,34301,34303,34313,34319,34327,34337,34351,34361,34367,34369,34381,34403,34421,34429,34439,34457,34469,34471,34483,34487,34499,34501,34511,34513,34519,34537,34543,34549,34583,34589,34591,34603,34607,34613,34631,34649,34651,34667,34673,34679,34687,34693,34703,34721,34729,34739,34747,34757,34759,34763,34781,34807,34819,34841,34843,34847,34849,34871,34877,34883,34897,34913,34919,34939,34949,34961,34963,34981,35023,35027,35051,35053,35059,35069,35081,35083,35089,35099,35107,35111,35117,35129,35141,35149,35153,35159,35171,35201,35221,35227,35251,35257,35267,35279,35281,35291,35311,35317,35323,35327,35339,35353,35363,35381,35393,35401,35407,35419,35423,35437,35447,35449,35461,35491,35507,35509,35521,35527,35531,35533,35537,35543,35569,35573,35591,35593,35597,35603,35617,35671,35677,35729,35731,35747,35753,35759,35771,35797,35801,35803,35809,35831,35837,35839,35851,35863,35869,35879,35897,35899,35911,35923,35933,35951,35963,35969,35977,35983,35993,35999,36007,36011,36013,36017,36037,36061,36067,36073,36083,36097,36107,36109,36131,36137,36151,36161,36187,36191,36209,36217,36229,36241,36251,36263,36269,36277,36293,36299,36307,36313,36319,36341,36343,36353,36373,36383,36389,36433,36451,36457,36467,36469,36473,36479,36493,36497,36523,36527,36529,36541,36551,36559,36563,36571,36583,36587,36599,36607,36629,36637,36643,36653,36671,36677,36683,36691,36697,36709,36713,36721,36739,36749,36761,36767,36779,36781,36787,36791,36793,36809,36821,36833,36847,36857,36871,36877,36887,36899,36901,36913,36919,36923,36929,36931,36943,36947,36973,36979,36997,37003,37013,37019,37021,37039,37049,37057,37061,37087,37097,37117,37123,37139,37159,37171,37181,37189,37199,37201,37217,37223,37243,37253,37273,37277,37307,37309,37313,37321,37337,37339,37357,37361,37363,37369,37379,37397,37409,37423,37441,37447,37463,37483,37489,37493,37501,37507,37511,37517,37529,37537,37547,37549,37561,37567,37571,37573,37579,37589,37591,37607,37619,37633,37643,37649,37657,37663,37691,37693,37699,37717,37747,37781,37783,37799,37811,37813,37831,37847,37853,37861,37871,37879,37889,37897,37907,37951,37957,37963,37967,37987,37991,37993,37997,38011,38039,38047,38053,38069,38083,38113,38119,38149,38153,38167,38177,38183,38189,38197,38201,38219,38231,38237,38239,38261,38273,38281,38287,38299,38303,38317,38321,38327,38329,38333,38351,38371,38377,38393,38431,38447,38449,38453,38459,38461,38501,38543,38557,38561,38567,38569,38593,38603,38609,38611,38629,38639,38651,38653,38669,38671,38677,38693,38699,38707,38711,38713,38723,38729,38737,38747,38749,38767,38783,38791,38803,38821,38833,38839,38851,38861,38867,38873,38891,38903,38917,38921,38923,38933,38953,38959,38971,38977,38993,39019,39023,39041,39043,39047,39079,39089,39097,39103,39107,39113,39119,39133,39139,39157,39161,39163,39181,39191,39199,39209,39217,39227,39229,39233,39239,39241,39251,39293,39301,39313,39317,39323,39341,39343,39359,39367,39371,39373,39383,39397,39409,39419,39439,39443,39451,39461,39499,39503,39509,39511,39521,39541,39551,39563,39569,39581,39607,39619,39623,39631,39659,39667,39671,39679,39703,39709,39719,39727,39733,39749,39761,39769,39779,39791,39799,39821,39827,39829,39839,39841,39847,39857,39863,39869,39877,39883,39887,39901,39929,39937,39953,39971,39979,39983,39989,40009,40013,40031,40037,40039,40063,40087,40093,40099,40111,40123,40127,40129,40151,40153,40163,40169,40177,40189,40193,40213,40231,40237,40241,40253,40277,40283,40289,40343,40351,40357,40361,40387,40423,40427,40429,40433,40459,40471,40483,40487,40493,40499,40507,40519,40529,40531,40543,40559,40577,40583,40591,40597,40609,40627,40637,40639,40693,40697,40699,40709,40739,40751,40759,40763,40771,40787,40801,40813,40819,40823,40829,40841,40847,40849,40853,40867,40879,40883,40897,40903,40927,40933,40939,40949,40961,40973,40993,41011,41017,41023,41039,41047,41051,41057,41077,41081,41113,41117,41131,41141,41143,41149,41161,41177,41179,41183,41189,41201,41203,41213,41221,41227,41231,41233,41243,41257,41263,41269,41281,41299,41333,41341,41351,41357,41381,41387,41389,41399,41411,41413,41443,41453,41467,41479,41491,41507,41513,41519,41521,41539,41543,41549,41579,41593,41597,41603,41609,41611,41617,41621,41627,41641,41647,41651,41659,41669,41681,41687,41719,41729,41737,41759,41761,41771,41777,41801,41809,41813,41843,41849,41851,41863,41879,41887,41893,41897,41903,41911,41927,41941,41947,41953,41957,41959,41969,41981,41983,41999,42013,42017,42019,42023,42043,42061,42071,42073,42083,42089,42101,42131,42139,42157,42169,42179,42181,42187,42193,42197,42209,42221,42223,42227,42239,42257,42281,42283,42293,42299,42307,42323,42331,42337,42349,42359,42373,42379,42391,42397,42403,42407,42409,42433,42437,42443,42451,42457,42461,42463,42467,42473,42487,42491,42499,42509,42533,42557,42569,42571,42577,42589,42611,42641,42643,42649,42667,42677,42683,42689,42697,42701,42703,42709,42719,42727,42737,42743,42751,42767,42773,42787,42793,42797,42821,42829,42839,42841,42853,42859,42863,42899,42901,42923,42929,42937,42943,42953,42961,42967,42979,42989,43003,43013,43019,43037,43049,43051,43063,43067,43093,43103,43117,43133,43151,43159,43177,43189,43201,43207,43223,43237,43261,43271,43283,43291,43313,43319,43321,43331,43391,43397,43399,43403,43411,43427,43441,43451,43457,43481,43487,43499,43517,43541,43543,43573,43577,43579,43591,43597,43607,43609,43613,43627,43633,43649,43651,43661,43669,43691,43711,43717,43721,43753,43759,43777,43781,43783,43787,43789,43793,43801,43853,43867,43889,43891,43913,43933,43943,43951,43961,43963,43969,43973,43987,43991,43997,44017,44021,44027,44029,44041,44053,44059,44071,44087,44089,44101,44111,44119,44123,44129,44131,44159,44171,44179,44189,44201,44203,44207,44221,44249,44257,44263,44267,44269,44273,44279,44281,44293,44351,44357,44371,44381,44383,44389,44417,44449,44453,44483,44491,44497,44501,44507,44519,44531,44533,44537,44543,44549,44563,44579,44587,44617,44621,44623,44633,44641,44647,44651,44657,44683,44687,44699,44701,44711,44729,44741,44753,44771,44773,44777,44789,44797,44809,44819,44839,44843,44851,44867,44879,44887,44893,44909,44917,44927,44939,44953,44959,44963,44971,44983,44987,45007,45013,45053,45061,45077,45083,45119,45121,45127,45131,45137,45139,45161,45179,45181,45191,45197,45233,45247,45259,45263,45281,45289,45293,45307,45317,45319,45329,45337,45341,45343,45361,45377,45389,45403,45413,45427,45433,45439,45481,45491,45497,45503,45523,45533,45541,45553,45557,45569,45587,45589,45599,45613,45631,45641,45659,45667,45673,45677,45691,45697,45707,45737,45751,45757,45763,45767,45779,45817,45821,45823,45827,45833,45841,45853,45863,45869,45887,45893,45943,45949,45953,45959,45971,45979,45989,46021,46027,46049,46051,46061,46073,46091,46093,46099,46103,46133,46141,46147,46153,46171,46181,46183,46187,46199,46219,46229,46237,46261,46271,46273,46279,46301,46307,46309,46327,46337,46349,46351,46381,46399,46411,46439,46441,46447,46451,46457,46471,46477,46489,46499,46507,46511,46523,46549,46559,46567,46573,46589,46591,46601,46619,46633,46639,46643,46649,46663,46679,46681,46687,46691,46703,46723,46727,46747,46751,46757,46769,46771,46807,46811,46817,46819,46829,46831,46853,46861,46867,46877,46889,46901,46919,46933,46957,46993,46997,47017,47041,47051,47057,47059,47087,47093,47111,47119,47123,47129,47137,47143,47147,47149,47161,47189,47207,47221,47237,47251,47269,47279,47287,47293,47297,47303,47309,47317,47339,47351,47353,47363,47381,47387,47389,47407,47417,47419,47431,47441,47459,47491,47497,47501,47507,47513,47521,47527,47533,47543,47563,47569,47581,47591,47599,47609,47623,47629,47639,47653,47657,47659,47681,47699,47701,47711,47713,47717,47737,47741,47743,47777,47779,47791,47797,47807,47809,47819,47837,47843,47857,47869,47881,47903,47911,47917,47933,47939,47947,47951,47963,47969,47977,47981,48017,48023,48029,48049,48073,48079,48091,48109,48119,48121,48131,48157,48163,48179,48187,48193,48197,48221,48239,48247,48259,48271,48281,48299,48311,48313,48337,48341,48353,48371,48383,48397,48407,48409,48413,48437,48449,48463,48473,48479,48481,48487,48491,48497,48523,48527,48533,48539,48541,48563,48571,48589,48593,48611,48619,48623,48647,48649,48661,48673,48677,48679,48731,48733,48751,48757,48761,48767,48779,48781,48787,48799,48809,48817,48821,48823,48847,48857,48859,48869,48871,48883,48889,48907,48947,48953,48973,48989,48991,49003,49009,49019,49031,49033,49037,49043,49057,49069,49081,49103,49109,49117,49121,49123,49139,49157,49169,49171,49177,49193,49199,49201,49207,49211,49223,49253,49261,49277,49279,49297,49307,49331,49333,49339,49363,49367,49369,49391,49393,49409,49411,49417,49429,49433,49451,49459,49463,49477,49481,49499,49523,49529,49531,49537,49547,49549,49559,49597,49603,49613,49627,49633,49639,49663,49667,49669,49681,49697,49711,49727,49739,49741,49747,49757,49783,49787,49789,49801,49807,49811,49823,49831,49843,49853,49871,49877,49891,49919,49921,49927,49937,49939,49943,49957,49991,49993,49999,50021,50023,50033,50047,50051,50053,50069,50077,50087,50093,50101,50111,50119,50123,50129,50131,50147,50153,50159,50177,50207,50221,50227,50231,50261,50263,50273,50287,50291,50311,50321,50329,50333,50341,50359,50363,50377,50383,50387,50411,50417,50423,50441,50459,50461,50497,50503,50513,50527,50539,50543,50549,50551,50581,50587,50591,50593,50599,50627,50647,50651,50671,50683,50707,50723,50741,50753,50767,50773,50777,50789,50821,50833,50839,50849,50857,50867,50873,50891,50893,50909,50923,50929,50951,50957,50969,50971,50989,50993,51001,51031,51043,51047,51059,51061,51071,51109,51131,51133,51137,51151,51157,51169,51193,51197,51199,51203,51217,51229,51239,51241,51257,51263,51283,51287,51307,51329,51341,51343,51347,51349,51361,51383,51407,51413,51419,51421,51427,51431,51437,51439,51449,51461,51473,51479,51481,51487,51503,51511,51517,51521,51539,51551,51563,51577,51581,51593,51599,51607,51613,51631,51637,51647,51659,51673,51679,51683,51691,51713,51719,51721,51749,51767,51769,51787,51797,51803,51817,51827,51829,51839,51853,51859,51869,51871,51893,51899,51907,51913,51929,51941,51949,51971,51973,51977,51991,52009,52021,52027,52051,52057,52067,52069,52081,52103,52121,52127,52147,52153,52163,52177,52181,52183,52189,52201,52223,52237,52249,52253,52259,52267,52289,52291,52301,52313,52321,52361,52363,52369,52379,52387,52391,52433,52453,52457,52489,52501,52511,52517,52529,52541,52543,52553,52561,52567,52571,52579,52583,52609,52627,52631,52639,52667,52673,52691,52697,52709,52711,52721,52727,52733,52747,52757,52769,52783,52807,52813,52817,52837,52859,52861,52879,52883,52889,52901,52903,52919,52937,52951,52957,52963,52967,52973,52981,52999,53003,53017,53047,53051,53069,53077,53087,53089,53093,53101,53113,53117,53129,53147,53149,53161,53171,53173,53189,53197,53201,53231,53233,53239,53267,53269,53279,53281,53299,53309,53323,53327,53353,53359,53377,53381,53401,53407,53411,53419,53437,53441,53453,53479,53503,53507,53527,53549,53551,53569,53591,53593,53597,53609,53611,53617,53623,53629,53633,53639,53653,53657,53681,53693,53699,53717,53719,53731,53759,53773,53777,53783,53791,53813,53819,53831,53849,53857,53861,53881,53887,53891,53897,53899,53917,53923,53927,53939,53951,53959,53987,53993,54001,54011,54013,54037,54049,54059,54083,54091,54101,54121,54133,54139,54151,54163,54167,54181,54193,54217,54251,54269,54277,54287,54293,54311,54319,54323,54331,54347,54361,54367,54371,54377,54401,54403,54409,54413,54419,54421,54437,54443,54449,54469,54493,54497,54499,54503,54517,54521,54539,54541,54547,54559,54563,54577,54581,54583,54601,54617,54623,54629,54631,54647,54667,54673,54679,54709,54713,54721,54727,54751,54767,54773,54779,54787,54799,54829,54833,54851,54869,54877,54881,54907,54917,54919,54941,54949,54959,54973,54979,54983,55001,55009,55021,55049,55051,55057,55061,55073,55079,55103,55109,55117,55127,55147,55163,55171,55201,55207,55213,55217,55219,55229,55243,55249,55259,55291,55313,55331,55333,55337,55339,55343,55351,55373,55381,55399,55411,55439,55441,55457,55469,55487,55501,55511,55529,55541,55547,55579,55589,55603,55609,55619,55621,55631,55633,55639,55661,55663,55667,55673,55681,55691,55697,55711,55717,55721,55733,55763,55787,55793,55799,55807,55813,55817,55819,55823,55829,55837,55843,55849,55871,55889,55897,55901,55903,55921,55927,55931,55933,55949,55967,55987,55997,56003,56009,56039,56041,56053,56081,56087,56093,56099,56101,56113,56123,56131,56149,56167,56171,56179,56197,56207,56209,56237,56239,56249,56263,56267,56269,56299,56311,56333,56359,56369,56377,56383,56393,56401,56417,56431,56437,56443,56453,56467,56473,56477,56479,56489,56501,56503,56509,56519,56527,56531,56533,56543,56569,56591,56597,56599,56611,56629,56633,56659,56663,56671,56681,56687,56701,56711,56713,56731,56737,56747,56767,56773,56779,56783,56807,56809,56813,56821,56827,56843,56857,56873,56891,56893,56897,56909,56911,56921,56923,56929,56941,56951,56957,56963,56983,56989,56993,56999,57037,57041,57047,57059,57073,57077,57089,57097,57107,57119,57131,57139,57143,57149,57163,57173,57179,57191,57193,57203,57221,57223,57241,57251,57259,57269,57271,57283,57287,57301,57329,57331,57347,57349,57367,57373,57383,57389,57397,57413,57427,57457,57467,57487,57493,57503,57527,57529,57557,57559,57571,57587,57593,57601,57637,57641,57649,57653,57667,57679,57689,57697,57709,57713,57719,57727,57731,57737,57751,57773,57781,57787,57791,57793,57803,57809,57829,57839,57847,57853,57859,57881,57899,57901,57917,57923,57943,57947,57973,57977,57991,58013,58027,58031,58043,58049,58057,58061,58067,58073,58099,58109,58111,58129,58147,58151,58153,58169,58171,58189,58193,58199,58207,58211,58217,58229,58231,58237,58243,58271,58309,58313,58321,58337,58363,58367,58369,58379,58391,58393,58403,58411,58417,58427,58439,58441,58451,58453,58477,58481,58511,58537,58543,58549,58567,58573,58579,58601,58603,58613,58631,58657,58661,58679,58687,58693,58699,58711,58727,58733,58741,58757,58763,58771,58787,58789,58831,58889,58897,58901,58907,58909,58913,58921,58937,58943,58963,58967,58979,58991,58997,59009,59011,59021,59023,59029,59051,59053,59063,59069,59077,59083,59093,59107,59113,59119,59123,59141,59149,59159,59167,59183,59197,59207,59209,59219,59221,59233,59239,59243,59263,59273,59281,59333,59341,59351,59357,59359,59369,59377,59387,59393,59399,59407,59417,59419,59441,59443,59447,59453,59467,59471,59473,59497,59509,59513,59539,59557,59561,59567,59581,59611,59617,59621,59627,59629,59651,59659,59663,59669,59671,59693,59699,59707,59723,59729,59743,59747,59753,59771,59779,59791,59797,59809,59833,59863,59879,59887,59921,59929,59951,59957,59971,59981,59999,60013,60017,60029,60037,60041,60077,60083,60089,60091,60101,60103,60107,60127,60133,60139,60149,60161,60167,60169,60209,60217,60223,60251,60257,60259,60271,60289,60293,60317,60331,60337,60343,60353,60373,60383,60397,60413,60427,60443,60449,60457,60493,60497,60509,60521,60527,60539,60589,60601,60607,60611,60617,60623,60631,60637,60647,60649,60659,60661,60679,60689,60703,60719,60727,60733,60737,60757,60761,60763,60773,60779,60793,60811,60821,60859,60869,60887,60889,60899,60901,60913,60917,60919,60923,60937,60943,60953,60961,61001,61007,61027,61031,61043,61051,61057,61091,61099,61121,61129,61141,61151,61153,61169,61211,61223,61231,61253,61261,61283,61291,61297,61331,61333,61339,61343,61357,61363,61379,61381,61403,61409,61417,61441,61463,61469,61471,61483,61487,61493,61507,61511,61519,61543,61547,61553,61559,61561,61583,61603,61609,61613,61627,61631,61637,61643,61651,61657,61667,61673,61681,61687,61703,61717,61723,61729,61751,61757,61781,61813,61819,61837,61843,61861,61871,61879,61909,61927,61933,61949,61961,61967,61979,61981,61987,61991,62003,62011,62017,62039,62047,62053,62057,62071,62081,62099,62119,62129,62131,62137,62141,62143,62171,62189,62191,62201,62207,62213,62219,62233,62273,62297,62299,62303,62311,62323,62327,62347,62351,62383,62401,62417,62423,62459,62467,62473,62477,62483,62497,62501,62507,62533,62539,62549,62563,62581,62591,62597,62603,62617,62627,62633,62639,62653,62659,62683,62687,62701,62723,62731,62743,62753,62761,62773,62791,62801,62819,62827,62851,62861,62869,62873,62897,62903,62921,62927,62929,62939,62969,62971,62981,62983,62987,62989,63029,63031,63059,63067,63073,63079,63097,63103,63113,63127,63131,63149,63179,63197,63199,63211,63241,63247,63277,63281,63299,63311,63313,63317,63331,63337,63347,63353,63361,63367,63377,63389,63391,63397,63409,63419,63421,63439,63443,63463,63467,63473,63487,63493,63499,63521,63527,63533,63541,63559,63577,63587,63589,63599,63601,63607,63611,63617,63629,63647,63649,63659,63667,63671,63689,63691,63697,63703,63709,63719,63727,63737,63743,63761,63773,63781,63793,63799,63803,63809,63823,63839,63841,63853,63857,63863,63901,63907,63913,63929,63949,63977,63997,64007,64013,64019,64033,64037,64063,64067,64081,64091,64109,64123,64151,64153,64157,64171,64187,64189,64217,64223,64231,64237,64271,64279,64283,64301,64303,64319,64327,64333,64373,64381,64399,64403,64433,64439,64451,64453,64483,64489,64499,64513,64553,64567,64577,64579,64591,64601,64609,64613,64621,64627,64633,64661,64663,64667,64679,64693,64709,64717,64747,64763,64781,64783,64793,64811,64817,64849,64853,64871,64877,64879,64891,64901,64919,64921,64927,64937,64951,64969,64997,65003,65011,65027,65029,65033,65053,65063,65071,65089,65099,65101,65111,65119,65123,65129,65141,65147,65167,65171,65173,65179,65183,65203,65213,65239,65257,65267,65269,65287,65293,65309,65323,65327,65353,65357,65371,65381,65393,65407,65413,65419,65423,65437,65447,65449,65479,65497,65519,65521]+smallPrimesFromTo :: Word16 -> Word16 -> [Word16]+smallPrimesFromTo !(W16# from#) !(W16# to#) = go k0#+ where+ !(Ptr smallPrimesAddr#) = smallPrimesPtr+ fromD# = word2Double# from#+ k0#+ | isTrue# (from# `leWord#` 5##)+ = 0#+ | otherwise+ = double2Int# (fromD# /## logDouble# fromD#)++ go k#+ | I# k# >= smallPrimesLength+ = []+ | isTrue# (p# `gtWord#` to#)+ = []+ | isTrue# (p# `ltWord#` from#)+ = go (k# +# 1#)+ | otherwise+ = W16# p# : go (k# +# 1#)+ where+ p# = indexWord16OffAddr# smallPrimesAddr# k#++-- length smallPrimes+smallPrimesLength :: Int+smallPrimesLength = 6542++-- concatMap (\x -> map Data.Char.chr [x `mod` 256, x `quot` 256]) smallPrimes+smallPrimesPtr :: Ptr Word16+smallPrimesPtr = Ptr "\STX\NUL\ETX\NUL\ENQ\NUL\a\NUL\v\NUL\r\NUL\DC1\NUL\DC3\NUL\ETB\NUL\GS\NUL\US\NUL%\NUL)\NUL+\NUL/\NUL5\NUL;\NUL=\NULC\NULG\NULI\NULO\NULS\NULY\NULa\NULe\NULg\NULk\NULm\NULq\NUL\DEL\NUL\131\NUL\137\NUL\139\NUL\149\NUL\151\NUL\157\NUL\163\NUL\167\NUL\173\NUL\179\NUL\181\NUL\191\NUL\193\NUL\197\NUL\199\NUL\211\NUL\223\NUL\227\NUL\229\NUL\233\NUL\239\NUL\241\NUL\251\NUL\SOH\SOH\a\SOH\r\SOH\SI\SOH\NAK\SOH\EM\SOH\ESC\SOH%\SOH3\SOH7\SOH9\SOH=\SOHK\SOHQ\SOH[\SOH]\SOHa\SOHg\SOHo\SOHu\SOH{\SOH\DEL\SOH\133\SOH\141\SOH\145\SOH\153\SOH\163\SOH\165\SOH\175\SOH\177\SOH\183\SOH\187\SOH\193\SOH\201\SOH\205\SOH\207\SOH\211\SOH\223\SOH\231\SOH\235\SOH\243\SOH\247\SOH\253\SOH\t\STX\v\STX\GS\STX#\STX-\STX3\STX9\STX;\STXA\STXK\STXQ\STXW\STXY\STX_\STXe\STXi\STXk\STXw\STX\129\STX\131\STX\135\STX\141\STX\147\STX\149\STX\161\STX\165\STX\171\STX\179\STX\189\STX\197\STX\207\STX\215\STX\221\STX\227\STX\231\STX\239\STX\245\STX\249\STX\SOH\ETX\ENQ\ETX\DC3\ETX\GS\ETX)\ETX+\ETX5\ETX7\ETX;\ETX=\ETXG\ETXU\ETXY\ETX[\ETX_\ETXm\ETXq\ETXs\ETXw\ETX\139\ETX\143\ETX\151\ETX\161\ETX\169\ETX\173\ETX\179\ETX\185\ETX\199\ETX\203\ETX\209\ETX\215\ETX\223\ETX\229\ETX\241\ETX\245\ETX\251\ETX\253\ETX\a\EOT\t\EOT\SI\EOT\EM\EOT\ESC\EOT%\EOT'\EOT-\EOT?\EOTC\EOTE\EOTI\EOTO\EOTU\EOT]\EOTc\EOTi\EOT\DEL\EOT\129\EOT\139\EOT\147\EOT\157\EOT\163\EOT\169\EOT\177\EOT\189\EOT\193\EOT\199\EOT\205\EOT\207\EOT\213\EOT\225\EOT\235\EOT\253\EOT\255\EOT\ETX\ENQ\t\ENQ\v\ENQ\DC1\ENQ\NAK\ENQ\ETB\ENQ\ESC\ENQ'\ENQ)\ENQ/\ENQQ\ENQW\ENQ]\ENQe\ENQw\ENQ\129\ENQ\143\ENQ\147\ENQ\149\ENQ\153\ENQ\159\ENQ\167\ENQ\171\ENQ\173\ENQ\179\ENQ\191\ENQ\201\ENQ\203\ENQ\207\ENQ\209\ENQ\213\ENQ\219\ENQ\231\ENQ\243\ENQ\251\ENQ\a\ACK\r\ACK\DC1\ACK\ETB\ACK\US\ACK#\ACK+\ACK/\ACK=\ACKA\ACKG\ACKI\ACKM\ACKS\ACKU\ACK[\ACKe\ACKy\ACK\DEL\ACK\131\ACK\133\ACK\157\ACK\161\ACK\163\ACK\173\ACK\185\ACK\187\ACK\197\ACK\205\ACK\211\ACK\217\ACK\223\ACK\241\ACK\247\ACK\251\ACK\253\ACK\t\a\DC3\a\US\a'\a7\aE\aK\aO\aQ\aU\aW\aa\am\as\ay\a\139\a\141\a\157\a\159\a\181\a\187\a\195\a\201\a\205\a\207\a\211\a\219\a\225\a\235\a\237\a\247\a\ENQ\b\SI\b\NAK\b!\b#\b'\b)\b3\b?\bA\bQ\bS\bY\b]\b_\bi\bq\b\131\b\155\b\159\b\165\b\173\b\189\b\191\b\195\b\203\b\219\b\221\b\225\b\233\b\239\b\245\b\249\b\ENQ\t\a\t\GS\t#\t%\t+\t/\t5\tC\tI\tM\tO\tU\tY\t_\tk\tq\tw\t\133\t\137\t\143\t\155\t\163\t\169\t\173\t\199\t\217\t\227\t\235\t\239\t\245\t\247\t\253\t\DC3\n\US\n!\n1\n9\n=\nI\nW\na\nc\ng\no\nu\n{\n\DEL\n\129\n\133\n\139\n\147\n\151\n\153\n\159\n\169\n\171\n\181\n\189\n\193\n\207\n\217\n\229\n\231\n\237\n\241\n\243\n\ETX\v\DC1\v\NAK\v\ESC\v#\v)\v-\v?\vG\vQ\vW\v]\ve\vo\v{\v\137\v\141\v\147\v\153\v\155\v\183\v\185\v\195\v\203\v\207\v\221\v\225\v\233\v\245\v\251\v\a\f\v\f\DC1\f%\f/\f1\fA\f[\f_\fa\fm\fs\fw\f\131\f\137\f\145\f\149\f\157\f\179\f\181\f\185\f\187\f\199\f\227\f\229\f\235\f\241\f\247\f\251\f\SOH\r\ETX\r\SI\r\DC3\r\US\r!\r+\r-\r=\r?\rO\rU\ri\ry\r\129\r\133\r\135\r\139\r\141\r\163\r\171\r\183\r\189\r\199\r\201\r\205\r\211\r\213\r\219\r\229\r\231\r\243\r\253\r\255\r\t\SO\ETB\SO\GS\SO!\SO'\SO/\SO5\SO;\SOK\SOW\SOY\SO]\SOk\SOq\SOu\SO}\SO\135\SO\143\SO\149\SO\155\SO\177\SO\183\SO\185\SO\195\SO\209\SO\213\SO\219\SO\237\SO\239\SO\249\SO\a\SI\v\SI\r\SI\ETB\SI%\SI)\SI1\SIC\SIG\SIM\SIO\SIS\SIY\SI[\SIg\SIk\SI\DEL\SI\149\SI\161\SI\163\SI\167\SI\173\SI\179\SI\181\SI\187\SI\209\SI\211\SI\217\SI\233\SI\239\SI\251\SI\253\SI\ETX\DLE\SI\DLE\US\DLE!\DLE%\DLE+\DLE9\DLE=\DLE?\DLEQ\DLEi\DLEs\DLEy\DLE{\DLE\133\DLE\135\DLE\145\DLE\147\DLE\157\DLE\163\DLE\165\DLE\175\DLE\177\DLE\187\DLE\193\DLE\201\DLE\231\DLE\241\DLE\243\DLE\253\DLE\ENQ\DC1\v\DC1\NAK\DC1'\DC1-\DC19\DC1E\DC1G\DC1Y\DC1_\DC1c\DC1i\DC1o\DC1\129\DC1\131\DC1\141\DC1\155\DC1\161\DC1\165\DC1\167\DC1\171\DC1\195\DC1\197\DC1\209\DC1\215\DC1\231\DC1\239\DC1\245\DC1\251\DC1\r\DC2\GS\DC2\US\DC2#\DC2)\DC2+\DC21\DC27\DC2A\DC2G\DC2S\DC2_\DC2q\DC2s\DC2y\DC2}\DC2\143\DC2\151\DC2\175\DC2\179\DC2\181\DC2\185\DC2\191\DC2\193\DC2\205\DC2\209\DC2\223\DC2\253\DC2\a\DC3\r\DC3\EM\DC3'\DC3-\DC37\DC3C\DC3E\DC3I\DC3O\DC3W\DC3]\DC3g\DC3i\DC3m\DC3{\DC3\129\DC3\135\DC3\139\DC3\145\DC3\147\DC3\157\DC3\159\DC3\175\DC3\187\DC3\195\DC3\213\DC3\217\DC3\223\DC3\235\DC3\237\DC3\243\DC3\249\DC3\255\DC3\ESC\DC4!\DC4/\DC43\DC4;\DC4E\DC4M\DC4Y\DC4k\DC4o\DC4q\DC4u\DC4\141\DC4\153\DC4\159\DC4\161\DC4\177\DC4\183\DC4\189\DC4\203\DC4\213\DC4\227\DC4\231\DC4\ENQ\NAK\v\NAK\DC1\NAK\ETB\NAK\US\NAK%\NAK)\NAK+\NAK7\NAK=\NAKA\NAKC\NAKI\NAK_\NAKe\NAKg\NAKk\NAK}\NAK\DEL\NAK\131\NAK\143\NAK\145\NAK\151\NAK\155\NAK\181\NAK\187\NAK\193\NAK\197\NAK\205\NAK\215\NAK\247\NAK\a\SYN\t\SYN\SI\SYN\DC3\SYN\NAK\SYN\EM\SYN\ESC\SYN%\SYN3\SYN9\SYN=\SYNE\SYNO\SYNU\SYNi\SYNm\SYNo\SYNu\SYN\147\SYN\151\SYN\159\SYN\169\SYN\175\SYN\181\SYN\189\SYN\195\SYN\207\SYN\211\SYN\217\SYN\219\SYN\225\SYN\229\SYN\235\SYN\237\SYN\247\SYN\249\SYN\t\ETB\SI\ETB#\ETB'\ETB3\ETBA\ETB]\ETBc\ETBw\ETB{\ETB\141\ETB\149\ETB\155\ETB\159\ETB\165\ETB\179\ETB\185\ETB\191\ETB\201\ETB\203\ETB\213\ETB\225\ETB\233\ETB\243\ETB\245\ETB\255\ETB\a\CAN\DC3\CAN\GS\CAN5\CAN7\CAN;\CANC\CANI\CANM\CANU\CANg\CANq\CANw\CAN}\CAN\DEL\CAN\133\CAN\143\CAN\155\CAN\157\CAN\167\CAN\173\CAN\179\CAN\185\CAN\193\CAN\199\CAN\209\CAN\215\CAN\217\CAN\223\CAN\229\CAN\235\CAN\245\CAN\253\CAN\NAK\EM\ESC\EM1\EM3\EME\EMI\EMQ\EM[\EMy\EM\129\EM\147\EM\151\EM\153\EM\163\EM\169\EM\171\EM\177\EM\181\EM\199\EM\207\EM\219\EM\237\EM\253\EM\ETX\SUB\ENQ\SUB\DC1\SUB\ETB\SUB!\SUB#\SUB-\SUB/\SUB5\SUB?\SUBM\SUBQ\SUBi\SUBk\SUB{\SUB}\SUB\135\SUB\137\SUB\147\SUB\167\SUB\171\SUB\173\SUB\177\SUB\185\SUB\201\SUB\207\SUB\213\SUB\215\SUB\227\SUB\243\SUB\251\SUB\255\SUB\ENQ\ESC#\ESC%\ESC/\ESC1\ESC7\ESC;\ESCA\ESCG\ESCO\ESCU\ESCY\ESCe\ESCk\ESCs\ESC\DEL\ESC\131\ESC\145\ESC\157\ESC\167\ESC\191\ESC\197\ESC\209\ESC\215\ESC\217\ESC\239\ESC\247\ESC\t\FS\DC3\FS\EM\FS'\FS+\FS-\FS3\FS=\FSE\FSK\FSO\FSU\FSs\FS\129\FS\139\FS\141\FS\153\FS\163\FS\165\FS\181\FS\183\FS\201\FS\225\FS\243\FS\249\FS\t\GS\ESC\GS!\GS#\GS5\GS9\GS?\GSA\GSK\GSS\GS]\GSc\GSi\GSq\GSu\GS{\GS}\GS\135\GS\137\GS\149\GS\153\GS\159\GS\165\GS\167\GS\179\GS\183\GS\197\GS\215\GS\219\GS\225\GS\245\GS\249\GS\SOH\RS\a\RS\v\RS\DC3\RS\ETB\RS%\RS+\RS/\RS=\RSI\RSM\RSO\RSm\RSq\RS\137\RS\143\RS\149\RS\161\RS\173\RS\187\RS\193\RS\197\RS\199\RS\203\RS\221\RS\227\RS\239\RS\247\RS\253\RS\SOH\US\r\US\SI\US\ESC\US9\USI\USK\USQ\USg\USu\US{\US\133\US\145\US\151\US\153\US\157\US\165\US\175\US\181\US\187\US\211\US\225\US\231\US\235\US\243\US\255\US\DC1 \ESC \GS ' ) - 3 G M Q _ c e i w } \137 \161 \171 \177 \185 \195 \197 \227 \231 \237 \239 \251 \255 \r!\DC3!5!A!I!O!Y\ENQ)\DC1)!)#)?)G)])e)i)o)u)\131)\135)\143)\155)\161)\167)\171)\191)\195)\213)\215)\227)\233)\237)\243)\SOH*\DC3*\GS*%*/*O*U*_*e*k*m*s*\131*\137*\139*\151*\157*\185*\187*\197*\205*\221*\227*\235*\241*\251*\DC3+'+1+3+=+?+K+O+U+i+m+o+{+\141+\151+\153+\163+\165+\169+\189+\205+\231+\235+\243+\249+\253+\t,\SI,\ETB,#,/,5,9,A,W,Y,i,w,\129,\135,\147,\159,\173,\179,\183,\203,\207,\219,\225,\227,\233,\239,\255,\a-\GS-\US-;-C-I-M-a-e-q-\137-\157-\161-\169-\179-\181-\197-\199-\211-\223-\SOH.\ETX.\a.\r.\EM.\US.%.-.3.7.9.?.W.[.o.y.\DEL.\133.\147.\151.\157.\163.\165.\177.\183.\193.\195.\205.\211.\231.\235.\ENQ/\t/\v/\DC1/'/)/A/E/K/M/Q/W/o/u/}/\129/\131/\165/\171/\179/\195/\207/\209/\219/\221/\231/\237/\245/\249/\SOH0\r0#0)070;0U0Y0[0g0q0y0}0\133\&0\145\&0\149\&0\163\&0\169\&0\185\&0\191\&0\199\&0\203\&0\209\&0\215\&0\223\&0\229\&0\239\&0\251\&0\253\&0\ETX1\t1\EM1!1'1-191C1E1K1]1a1g1m1s1\DEL1\145\&1\153\&1\159\&1\169\&1\177\&1\195\&1\199\&1\213\&1\219\&1\237\&1\247\&1\255\&1\t2\NAK2\ETB2\GS2)252Y2]2c2k2o2u2w2{2\141\&2\153\&2\159\&2\167\&2\173\&2\179\&2\183\&2\201\&2\203\&2\207\&2\209\&2\233\&2\237\&2\243\&2\249\&2\a3%3+3/353A3G3[3_3g3k3s3y3\DEL3\131\&3\161\&3\163\&3\173\&3\185\&3\193\&3\203\&3\211\&3\235\&3\241\&3\253\&3\SOH4\SI4\DC34\EM4\ESC474E4U4W4c4i4m4\129\&4\139\&4\145\&4\151\&4\157\&4\165\&4\175\&4\187\&4\201\&4\211\&4\225\&4\241\&4\255\&4\t5\ETB5\GS5-535;5A5Q5e5o5q5w5{5}5\129\&5\141\&5\143\&5\153\&5\155\&5\161\&5\183\&5\189\&5\191\&5\195\&5\213\&5\221\&5\231\&5\239\&5\ENQ6\a6\DC16#6165676;6M6O6S6Y6a6k6m6\139\&6\143\&6\173\&6\175\&6\185\&6\187\&6\205\&6\209\&6\227\&6\233\&6\247\&6\SOH7\ETX7\a7\ESC7?7E7I7O7]7a7u7\DEL7\141\&7\163\&7\169\&7\171\&7\201\&7\213\&7\223\&7\241\&7\243\&7\247\&7\ENQ8\v8!83858A8G8K8S8W8_8e8o8q8}8\143\&8\153\&8\167\&8\183\&8\197\&8\201\&8\207\&8\213\&8\215\&8\221\&8\225\&8\227\&8\255\&8\SOH9\GS9#9%9)9/9=9A9M9[9k9y9}9\131\&9\139\&9\145\&9\149\&9\155\&9\161\&9\167\&9\175\&9\179\&9\187\&9\191\&9\205\&9\221\&9\229\&9\235\&9\239\&9\251\&9\ETX:\DC3:\NAK:\US:':+:1:K:Q:[:c:g:m:y:\135:\165:\169:\183:\205:\213:\225:\229:\235:\243:\253:\ETX;\DC1;\ESC;!;#;-;9;E;S;Y;_;q;{;\129;\137;\155;\159;\165;\167;\173;\183;\185;\195;\203;\209;\215;\225;\227;\245;\255;\SOH<\r<\DC1<\ETB<\US<)<5<C<O<S<[<e<k<q<\133<\137<\151<\167<\181<\191<\199<\209<\221<\223<\241<\247<\ETX=\r=\EM=\ESC=\US=!=-=3=7=?=C=o=s=u=y={=\133=\145=\151=\157=\171=\175=\181=\187=\193=\201=\207=\243=\ENQ>\t>\SI>\DC1>\GS>#>)>/>3>A>W>c>e>w>\129>\135>\161>\185>\189>\191>\195>\197>\201>\215>\219>\225>\231>\239>\255>\v?\r?7?;?=?A?Y?_?e?g?y?}?\139?\145?\173?\191?\205?\211?\221?\233?\235?\241?\253?\ESC@!@%@+@1@?@C@E@]@a@g@m@\135@\145@\163@\169@\177@\183@\189@\219@\223@\235@\247@\249@\tA\vA\DC1A\NAKA!A3A5A;A?AYAeAkAwA{A\147A\171A\183A\189A\191A\203A\231A\239A\243A\249A\ENQB\aB\EMB\USB#B)B/BCBSBUB[BaBsB}B\131B\133B\137B\145B\151B\157B\181B\197B\203B\211B\221B\227B\241B\aC\SIC\USC%C'C3C7C9COCWCiC\139C\141C\147C\165C\169C\175C\181C\189C\199C\207C\225C\231C\235C\237C\241C\249C\tD\vD\ETBD#D)D;D?DEDKDQDSDYDeDoD\131D\143D\161D\165D\171D\173D\189D\191D\201D\215D\219D\249D\251D\ENQE\DC1E\DC3E+E1EAEIESEUEaEwE}E\DELE\143E\163E\173E\175E\187E\199E\217E\227E\239E\245E\247E\SOHF\ETXF\tF\DC3F%F'F3F9F=FCFEF]FyF{F\DELF\129F\139F\141F\157F\169F\177F\199F\201F\207F\211F\213F\223F\229F\249F\ENQG\SIG\ETBG#G)G/G5G9GKGMGQG]GoGqG}G\131G\135G\137G\153G\165G\177G\191G\195G\203G\221G\225G\237G\251G\SOHH\aH\vH\DC3H\EMH\GSH1H=HGHUHYH[HkHmHyH\151H\155H\161H\185H\205H\229H\239H\247H\ETXI\rI\EMI\USI+I7I=IEIUIcIiImIsI\151I\171I\181I\211I\223I\225I\229I\231I\ETXJ\SIJ\GSJ#J9JAJEJWJ]JkJ}J\129J\135J\137J\143J\177J\195J\197J\213J\219J\237J\239J\aK\vK\rK\DC3K\USK%K1K;KCKIKYKeKmKwK\133K\173K\179K\181K\187K\191K\203K\217K\221K\223K\227K\229K\233K\241K\247K\SOHL\aL\rL\SIL\NAKL\ESCL!L-L3LKLULWLaLgLsLyL\DELL\141L\147L\153L\205L\225L\231L\241L\243L\253L\ENQM\SIM\ESCM'M)M/M3MAMQMYMeMkM\129M\131M\141M\149M\155M\177M\179M\201M\207M\215M\225M\237M\249M\251M\ENQN\vN\ETBN\EMN\GSN+N5N7N=NONSN_NgNyN\133N\139N\145N\149N\155N\161N\175N\179N\181N\193N\205N\209N\215N\233N\251N\aO\tO\EMO%O-O?OIOcOgOmOuO{O\129O\133O\135O\145O\165O\169O\175O\183O\187O\207O\217O\219O\253O\255O\ETXP\ESCP\GSP)P5P?PEPGPSPqPwP\131P\147P\159P\161P\183P\201P\213P\227P\237P\239P\251P\aQ\vQ\rQ\DC1Q\ETBQ#Q%Q5QGQIQqQyQ\137Q\143Q\151Q\161Q\163Q\167Q\185Q\193Q\203Q\211Q\223Q\227Q\245Q\247Q\tR\DC3R\NAKR\EMR\ESCR\USR'RCRERKRaRmRsR\129R\147R\151R\157R\165R\171R\177R\187R\195R\199R\201R\219R\229R\235R\255R\NAKS\GSS#SASESGSKS]ScS\129S\131S\135S\143S\149S\153S\159S\171S\185S\219S\233S\239S\243S\245S\251S\255S\rT\DC1T\DC3T\EMT5T7T;TATITSTUT_TaTkTmTqT\143T\145T\157T\169T\179T\197T\209T\223T\233T\235T\247T\253T\aU\rU\ESCU'U+U9U=UOUQU[UcUgUoUyU\133U\151U\169U\177U\183U\201U\217U\231U\237U\243U\253U\vV\SIV\NAKV\ETBV#V/V3V9V?VKVMV]V_VkVqVuV\131V\137V\141V\143V\155V\173V\177V\213V\231V\243V\255V\SOHW\ENQW\aW\vW\DC3W\USW#WGWMW_WaWmWwW}W\137W\161W\169W\175W\181W\197W\209W\211W\229W\239W\ETXX\rX\SIX\NAKX'X+X-XUX[X]XmXoXsX{X\141X\151X\163X\169X\171X\181X\189X\193X\199X\211X\213X\223X\241X\249X\255X\ETXY\ETBY\ESCY!YEYKYMYWY]YuY{Y\137Y\153Y\159Y\177Y\179Y\189Y\209Y\219Y\227Y\233Y\237Y\243Y\245Y\255Y\SOHZ\rZ\DC1Z\DC3Z\ETBZ\USZ)Z/Z;ZMZ[ZgZwZ\DELZ\133Z\149Z\157Z\161Z\163Z\169Z\187Z\211Z\229Z\239Z\251Z\253Z\SOH[\SI[\EM[\US[%[+[=[I[K[g[y[\135[\151[\163[\177[\201[\213[\235[\241[\243[\253[\ENQ\\\t\\\v\\\SI\\\GS\\)\\/\\3\\9\\G\\K\\M\\Q\\o\\u\\w\\}\\\135\\\137\\\167\\\189\\\191\\\195\\\201\\\209\\\215\\\221\\\237\\\249\\\ENQ]\v]\DC3]\ETB]\EM]1]=]A]G]O]U][]e]g]m]y]\149]\163]\169]\173]\185]\193]\199]\211]\215]\221]\235]\241]\253]\a^\r^\DC3^\ESC^!^'^+^-^1^9^E^I^W^i^s^u^\133^\139^\159^\165^\175^\183^\187^\217^\253^\t_\DC1_'_3_5_;_G_W_]_c_e_w_{_\149_\153_\161_\179_\189_\197_\207_\213_\227_\231_\251_\DC1`#`/`7`S`_`e`k`s`y`\133`\157`\173`\187`\191`\205`\217`\223`\233`\245`\ta\SIa\DC3a\ESCa-a9aKaUaWa[aoaya\135a\139a\145a\147a\157a\181a\199a\201a\205a\225a\241a\255a\tb\ETBb\GSb!b'b;bAbKbQbSb_beb\131b\141b\149b\155b\159b\165b\173b\213b\215b\219b\221b\233b\251b\255b\ENQc\rc\ETBc\GSc/cAcCcOc_cgcmcqcwc}c\DELc\179c\193c\197c\217c\233c\235c\239c\245c\SOHd\ETXd\td\NAKd!d'd+d9dCdIdOd]dgdud\133d\141d\147d\159d\163d\171d\193d\199d\201d\219d\241d\247d\249d\ve\DC1e!e/e9e?eKeMeSeWe_eqe}e\141e\143e\147e\161e\165e\173e\185e\197e\227e\243e\251e\255e\SOHf\af\GSf)f1f;fAfGfMf[fafsf}f\137f\139f\149f\151f\155f\181f\185f\197f\205f\209f\227f\235f\245f\ETXg\DC3g\EMg\USg'g1g7g?gEgQg[gogyg\129g\133g\145g\171g\189g\193g\205g\223g\229g\ETXh\th\DC1h\ETBh-h9h;h?hEhKhMhWhYh]hchihkhqh\135h\153h\159h\177h\189h\197h\209h\215h\225h\237h\239h\255h\SOHi\vi\ri\ETBi)i/iCiGiIiOieikiqi\131i\137i\151i\163i\179i\181i\187i\193i\197i\211i\223i\227i\229i\247i\aj+j7j=jKjgjijuj{j\135j\141j\145j\147j\163j\193j\201j\225j\231j\ENQk\SIk\DC1k#k'k-k9kAkWkYk_kuk\135k\137k\147k\149k\159k\189k\191k\219k\225k\239k\255k\ENQl\EMl)l+l1l5lUlYl[l_lelglslwl}l\131l\143l\145l\151l\155l\161l\169l\175l\179l\199l\203l\235l\245l\253l\rm\SIm%m'm+m1m9m?mOm]mamsm{m\DELm\147m\153m\165m\177m\183m\193m\195m\205m\207m\219m\247m\ETXn\NAKn\ETBn)n3n;nEnunwn{n\129n\137n\147n\149n\159n\189n\191n\227n\233n\243n\249n\251n\ro\DC1o\ETBo\USo/o=oMoSoaoeoyo}o\131o\133o\143o\155o\157o\163o\175o\181o\187o\191o\203o\205o\211o\215o\227o\233o\241o\245o\247o\253o\SIp\EMp\USp'p3p9pOpQpWpcpupyp\135p\141p\145p\165p\171p\187p\195p\199p\207p\229p\237p\249p\255p\ENQq\NAKq!q3qQqYq]q_qcqiq\131q\135q\149q\173q\195q\201q\203q\209q\219q\225q\239q\245q\251q\ar\DC1r\ETBr\EMr%r/r;rCrUrgrqrwr\DELr\143r\149r\155r\163r\179r\199r\203r\205r\215r\217r\227r\239r\245r\253r\ETXs\rs!s+s=sWs[sas\DELs\129s\133s\141s\147s\159s\171s\189s\193s\201s\223s\229s\231s\243s\NAKt\ESCt-t9t?tAt]tkt{t\137t\141t\155t\167t\171t\177t\183t\185t\221t\225t\231t\251t\au\USu%u;u=uMu_ukuwu\137u\139u\145u\151u\157u\161u\167u\181u\185u\187u\209u\217u\229u\235u\245u\251u\ETXv\SIv!v-v3v=v?vUvcvivovsv\133v\139v\159v\181v\183v\195v\219v\223v\241v\ETXw\ENQw\ESCw\GSw!w-w5wAwKwYw]w_wqw\129w\167w\173w\179w\185w\197w\207w\213w\225w\233w\239w\243w\249w\ax%x+x5x=xSxYxaxmxwxyx\131x\133x\139x\149x\151x\161x\173x\191x\211x\217x\221x\229x\251x\SOHy\ay%y+y9y?yKyWy]ygyiysy\145y\147y\163y\171y\175y\177y\183y\201y\205y\207y\213y\217y\243y\247y\255y\ENQz\SIz\DC1z\NAKz\ESCz#z'z-zKzWzYz_zeziz}z\147z\155z\159z\161z\165z\237z\245z\249z\SOH{\ETB{\EM{\GS{+{5{7{;{O{U{_{q{w{\139{\155{\161{\169{\175{\179{\199{\211{\233{\235{\239{\241{\253{\a|\EM|\ESC|1|7|I|g|i|s|\129|\139|\147|\163|\213|\219|\229|\237|\247|\ETX}\t}\ESC}\GS}3}9};}?}E}M}S}Y}c}u}w}\141}\143}\159}\173}\183}\189}\191}\203}\213}\233}\237}\251}\SOH~\ENQ~)~+~/~5~A~C~G~U~a~g~k~q~s~y~}~\145~\155~\157~\167~\173~\185~\187~\211~\223~\235~\241~\247~\251~\DC3\DEL\NAK\DEL\EM\DEL1\DEL3\DEL9\DEL=\DELC\DELK\DEL[\DELa\DELc\DELm\DELy\DEL\135\DEL\141\DEL\175\DEL\181\DEL\195\DEL\201\DEL\205\DEL\207\DEL\237\DEL\ETX\128\v\128\SI\128\NAK\128\GS\128!\128#\128?\128A\128G\128K\128e\128w\128\141\128\143\128\149\128\165\128\171\128\173\128\189\128\201\128\203\128\215\128\219\128\225\128\231\128\245\128\255\128\ENQ\129\r\129\EM\129\GS\129/\129\&1\129;\129C\129S\129Y\129_\129}\129\DEL\129\137\129\155\129\157\129\167\129\175\129\179\129\187\129\199\129\223\129\a\130\t\130\NAK\130\US\130%\130\&1\130\&3\130?\130C\130E\130I\130O\130a\130o\130{\130\129\130\133\130\147\130\177\130\181\130\189\130\199\130\207\130\213\130\223\130\241\130\249\130\253\130\v\131\ESC\131!\131)\131-\131\&3\131\&5\131?\131A\131M\131Q\131S\131W\131]\131e\131i\131o\131\143\131\167\131\177\131\185\131\203\131\213\131\215\131\221\131\231\131\233\131\237\131\255\131\ENQ\132\DC1\132\DC3\132#\132%\132;\132A\132G\132O\132a\132e\132w\132\131\132\139\132\145\132\149\132\169\132\175\132\205\132\227\132\239\132\241\132\247\132\t\133\r\133K\133O\133Q\133]\133c\133m\133o\133{\133\135\133\163\133\165\133\169\133\183\133\205\133\211\133\213\133\219\133\225\133\235\133\249\133\253\133\255\133\t\134\SI\134\ETB\134!\134/\134\&9\134?\134A\134M\134c\134u\134}\134\135\134\153\134\165\134\167\134\179\134\183\134\195\134\197\134\207\134\209\134\215\134\233\134\239\134\245\134\ETB\135\GS\135\US\135+\135/\135\&5\135G\135Y\135[\135k\135q\135w\135\DEL\135\133\135\143\135\161\135\169\135\179\135\187\135\197\135\199\135\203\135\221\135\247\135\ETX\136\EM\136\ESC\136\US\136!\136\&7\136=\136C\136Q\136a\136g\136{\136\133\136\145\136\147\136\165\136\207\136\211\136\235\136\237\136\243\136\253\136\t\137\v\137\DC1\137\ESC\137#\137'\137-\137\&9\137E\137M\137Q\137W\137c\137\129\137\149\137\155\137\179\137\185\137\195\137\207\137\209\137\219\137\239\137\245\137\251\137\255\137\v\138\EM\138#\138\&5\138A\138I\138O\138[\138_\138m\138w\138y\138\133\138\163\138\179\138\181\138\193\138\199\138\203\138\205\138\209\138\215\138\241\138\245\138\a\139\t\139\r\139\DC3\139!\139W\139]\139\145\139\147\139\163\139\169\139\175\139\187\139\213\139\217\139\219\139\225\139\247\139\253\139\255\139\v\140\ETB\140\GS\140'\140\&9\140;\140G\140S\140]\140o\140{\140\129\140\137\140\143\140\153\140\159\140\167\140\171\140\173\140\177\140\197\140\221\140\227\140\233\140\243\140\SOH\141\v\141\r\141#\141)\141\&7\141A\141[\141_\141q\141y\141\133\141\145\141\155\141\167\141\173\141\181\141\197\141\203\141\211\141\217\141\223\141\245\141\247\141\SOH\142\NAK\142\US\142%\142Q\142c\142i\142s\142u\142y\142\DEL\142\141\142\145\142\171\142\175\142\177\142\189\142\199\142\207\142\211\142\219\142\231\142\235\142\247\142\255\142\NAK\143\GS\143#\143-\143?\143E\143K\143S\143Y\143e\143i\143q\143\131\143\141\143\153\143\159\143\171\143\173\143\179\143\183\143\185\143\201\143\213\143\225\143\239\143\249\143\a\144\r\144\ETB\144#\144%\144\&1\144\&7\144;\144A\144C\144O\144S\144m\144s\144\133\144\139\144\149\144\155\144\157\144\175\144\185\144\193\144\197\144\223\144\233\144\253\144\ETX\145\DC3\145'\145\&3\145=\145E\145O\145Q\145a\145g\145{\145\133\145\153\145\157\145\187\145\189\145\193\145\201\145\217\145\219\145\237\145\241\145\243\145\249\145\ETX\146\NAK\146!\146/\146A\146G\146W\146k\146q\146u\146}\146\131\146\135\146\141\146\153\146\161\146\171\146\173\146\185\146\191\146\195\146\197\146\203\146\213\146\215\146\231\146\243\146\SOH\147\v\147\DC1\147\EM\147\US\147;\147=\147C\147U\147s\147\149\147\151\147\167\147\179\147\181\147\199\147\215\147\221\147\229\147\239\147\247\147\SOH\148\t\148\DC3\148?\148E\148K\148O\148c\148g\148i\148m\148{\148\151\148\159\148\165\148\181\148\195\148\225\148\231\148\ENQ\149\t\149\ETB\149!\149'\149-\149\&5\149\&9\149K\149W\149]\149_\149u\149\129\149\137\149\143\149\155\149\159\149\173\149\177\149\183\149\185\149\189\149\207\149\227\149\233\149\249\149\US\150/\150\&1\150\&5\150;\150=\150e\150\143\150\157\150\161\150\167\150\169\150\193\150\203\150\209\150\211\150\229\150\239\150\251\150\253\150\r\151\SI\151\NAK\151%\151+\151\&3\151\&7\151\&9\151C\151I\151Q\151[\151]\151o\151\DEL\151\135\151\147\151\165\151\177\151\183\151\195\151\205\151\211\151\217\151\235\151\247\151\ENQ\152\t\152\v\152\NAK\152)\152/\152;\152A\152Q\152k\152o\152\129\152\131\152\135\152\167\152\177\152\185\152\191\152\195\152\201\152\207\152\221\152\227\152\245\152\249\152\251\152\r\153\ETB\153\US\153)\153\&1\153;\153=\153A\153G\153I\153S\153}\153\133\153\145\153\149\153\155\153\173\153\175\153\191\153\199\153\203\153\205\153\215\153\229\153\241\153\251\153\SI\154\DC3\154\ESC\154%\154K\154O\154U\154W\154a\154u\154\DEL\154\139\154\145\154\157\154\183\154\195\154\199\154\207\154\235\154\243\154\247\154\255\154\ETB\155\GS\155'\155/\155\&5\155E\155Q\155Y\155c\155o\155w\155\141\155\147\155\149\155\159\155\161\155\167\155\177\155\183\155\189\155\197\155\203\155\207\155\221\155\249\155\SOH\156\DC1\156#\156+\156/\156\&5\156I\156M\156_\156e\156g\156\DEL\156\151\156\157\156\163\156\175\156\187\156\191\156\193\156\215\156\217\156\227\156\233\156\241\156\253\156\SOH\157\NAK\157'\157-\157\&1\157=\157U\157[\157a\157\151\157\159\157\165\157\169\157\195\157\231\157\235\157\237\157\241\157\v\158\ETB\158#\158'\158-\158\&3\158;\158G\158Q\158S\158_\158o\158\129\158\135\158\143\158\149\158\161\158\179\158\189\158\191\158\245\158\249\158\251\158\ENQ\159#\159/\159\&7\159;\159C\159S\159a\159m\159s\159w\159}\159\137\159\143\159\145\159\149\159\163\159\175\159\179\159\193\159\199\159\223\159\229\159\235\159\245\159\SOH\160\r\160!\160\&3\160\&9\160?\160O\160W\160[\160a\160u\160y\160\153\160\157\160\171\160\181\160\183\160\189\160\201\160\217\160\219\160\223\160\229\160\241\160\243\160\253\160\ENQ\161\v\161\SI\161\DC1\161\ESC\161)\161/\161\&5\161A\161S\161u\161}\161\135\161\141\161\165\161\171\161\173\161\183\161\195\161\197\161\227\161\237\161\251\161\a\162\DC3\162#\162)\162/\162\&1\162C\162G\162M\162k\162y\162}\162\131\162\137\162\139\162\145\162\149\162\155\162\169\162\175\162\179\162\187\162\197\162\209\162\215\162\247\162\SOH\163\t\163\US\163!\163+\163\&1\163I\163Q\163U\163s\163y\163{\163\135\163\151\163\159\163\165\163\169\163\175\163\183\163\199\163\213\163\219\163\225\163\229\163\231\163\241\163\253\163\255\163\SI\164\GS\164!\164#\164'\164;\164M\164W\164Y\164c\164i\164u\164\147\164\155\164\173\164\185\164\195\164\197\164\203\164\209\164\213\164\225\164\237\164\239\164\243\164\255\164\DC1\165)\165+\165\&5\165;\165C\165S\165[\165a\165m\165w\165\133\165\139\165\151\165\157\165\163\165\167\165\169\165\193\165\197\165\203\165\211\165\217\165\221\165\223\165\227\165\233\165\247\165\251\165\ETX\166\r\166%\166=\166I\166K\166Q\166]\166s\166\145\166\147\166\153\166\171\166\181\166\187\166\193\166\201\166\205\166\207\166\213\166\223\166\231\166\241\166\247\166\255\166\SI\167\NAK\167#\167)\167-\167E\167M\167W\167Y\167e\167k\167o\167\147\167\149\167\171\167\177\167\185\167\191\167\201\167\209\167\215\167\227\167\237\167\251\167\ENQ\168\v\168\GS\168)\168+\168\&7\168;\168U\168_\168m\168}\168\143\168\151\168\169\168\181\168\193\168\199\168\215\168\229\168\253\168\a\169\DC3\169\ESC\169\&1\169\&7\169\&9\169C\169\DEL\169\133\169\135\169\139\169\147\169\163\169\177\169\187\169\193\169\217\169\223\169\235\169\253\169\NAK\170\ETB\170\&5\170\&9\170;\170G\170M\170W\170Y\170]\170k\170q\170\129\170\131\170\141\170\149\170\171\170\191\170\197\170\201\170\233\170\239\170\SOH\171\ENQ\171\a\171\v\171\r\171\DC1\171\EM\171M\171[\171q\171s\171\137\171\157\171\167\171\175\171\185\171\187\171\193\171\197\171\211\171\215\171\221\171\241\171\245\171\251\171\253\171\t\172\NAK\172\ESC\172'\172\&7\172\&9\172E\172O\172W\172[\172a\172c\172\DEL\172\139\172\147\172\157\172\169\172\171\172\175\172\189\172\217\172\225\172\231\172\235\172\237\172\241\172\247\172\249\172\ENQ\173?\173E\173S\173]\173_\173e\173\129\173\161\173\165\173\195\173\203\173\209\173\213\173\219\173\231\173\243\173\245\173\249\173\255\173\ENQ\174\DC3\174#\174+\174I\174M\174O\174Y\174a\174g\174k\174q\174\139\174\143\174\155\174\157\174\167\174\185\174\197\174\209\174\227\174\229\174\233\174\245\174\253\174\t\175\DC3\175'\175+\175\&3\175C\175O\175W\175]\175m\175u\175\DEL\175\139\175\153\175\159\175\163\175\171\175\183\175\187\175\207\175\213\175\253\175\ENQ\176\NAK\176\ESC\176?\176A\176G\176K\176Q\176S\176i\176{\176}\176\135\176\141\176\177\176\191\176\203\176\207\176\225\176\233\176\237\176\251\176\ENQ\177\a\177\DC1\177\EM\177\GS\177\US\177\&1\177A\177M\177[\177e\177s\177y\177\DEL\177\169\177\179\177\185\177\191\177\211\177\221\177\229\177\241\177\245\177\SOH\178\DC3\178\NAK\178\US\178-\178?\178I\178[\178c\178i\178m\178{\178\129\178\139\178\169\178\183\178\189\178\195\178\199\178\211\178\249\178\253\178\255\178\ETX\179\t\179\DC1\179\GS\179'\179-\179?\179E\179w\179}\179\129\179\135\179\147\179\155\179\165\179\197\179\203\179\225\179\227\179\237\179\249\179\v\180\r\180\DC3\180\ETB\180\&5\180=\180C\180I\180[\180e\180g\180k\180w\180\139\180\149\180\157\180\181\180\191\180\193\180\199\180\221\180\227\180\229\180\247\180\SOH\181\r\181\SI\181-\181?\181K\181g\181i\181o\181s\181y\181\135\181\141\181\153\181\163\181\171\181\175\181\187\181\213\181\223\181\231\181\237\181\253\181\255\181\t\182\ESC\182)\182/\182\&3\182\&9\182G\182W\182Y\182_\182c\182o\182\131\182\135\182\155\182\159\182\165\182\177\182\179\182\215\182\219\182\225\182\227\182\237\182\239\182\ENQ\183\r\183\DC3\183\GS\183)\183\&5\183G\183U\183m\183\145\183\149\183\169\183\193\183\203\183\209\183\211\183\239\183\245\183\a\184\SI\184\DC3\184\EM\184!\184'\184+\184-\184\&9\184U\184g\184u\184\133\184\147\184\165\184\175\184\183\184\189\184\193\184\199\184\205\184\213\184\235\184\247\184\249\184\ETX\185\NAK\185\ESC\185\GS\185/\185\&9\185;\185G\185Q\185c\185\131\185\137\185\141\185\147\185\153\185\161\185\167\185\173\185\183\185\203\185\209\185\221\185\231\185\239\185\249\185\a\186\r\186\ETB\186%\186)\186+\186A\186S\186U\186_\186a\186e\186y\186}\186\DEL\186\161\186\163\186\175\186\181\186\191\186\193\186\203\186\221\186\227\186\241\186\253\186\t\187\US\187'\187-\187=\187C\187K\187O\187[\187a\187i\187m\187\145\187\151\187\157\187\177\187\201\187\207\187\219\187\237\187\247\187\249\187\ETX\188\GS\188#\188\&3\188;\188A\188E\188]\188o\188w\188\131\188\143\188\153\188\171\188\183\188\185\188\209\188\213\188\225\188\243\188\255\188\r\189\ETB\189\EM\189\GS\189\&5\189A\189O\189Y\189_\189a\189g\189k\189q\189\139\189\143\189\149\189\155\189\157\189\179\189\187\189\205\189\209\189\227\189\235\189\239\189\a\190\t\190\NAK\190!\190%\190'\190[\190]\190o\190u\190y\190\DEL\190\139\190\141\190\147\190\159\190\169\190\177\190\181\190\183\190\207\190\217\190\219\190\229\190\231\190\243\190\249\190\v\191\&3\191\&9\191M\191]\191_\191k\191q\191{\191\135\191\137\191\141\191\147\191\161\191\173\191\185\191\207\191\213\191\221\191\225\191\227\191\243\191\ENQ\192\DC1\192\DC3\192\EM\192)\192/\192\&1\192\&7\192;\192G\192e\192m\192}\192\DEL\192\145\192\155\192\179\192\181\192\187\192\211\192\215\192\217\192\239\192\241\192\SOH\193\ETX\193\t\193\NAK\193\EM\193+\193\&3\193\&7\193E\193I\193[\193s\193y\193{\193\129\193\139\193\141\193\151\193\189\193\195\193\205\193\219\193\225\193\231\193\255\193\ETX\194\ENQ\194\DC1\194!\194/\194?\194K\194M\194S\194]\194w\194{\194}\194\137\194\143\194\147\194\159\194\167\194\179\194\189\194\207\194\213\194\227\194\255\194\SOH\195\a\195\DC1\195\DC3\195\ETB\195%\195G\195I\195O\195e\195g\195q\195\DEL\195\131\195\133\195\149\195\157\195\167\195\173\195\181\195\191\195\199\195\203\195\209\195\211\195\227\195\233\195\239\195\SOH\196\US\196-\196\&3\196\&7\196U\196W\196a\196o\196s\196\135\196\145\196\153\196\157\196\165\196\183\196\187\196\201\196\207\196\211\196\235\196\241\196\247\196\t\197\ESC\197\GS\197A\197G\197Q\197_\197k\197o\197u\197w\197\149\197\155\197\159\197\161\197\167\197\195\197\215\197\219\197\239\197\251\197\DC3\198#\198\&5\198A\198O\198U\198Y\198e\198\133\198\145\198\151\198\161\198\169\198\179\198\185\198\203\198\205\198\221\198\235\198\241\198\a\199\r\199\EM\199\ESC\199-\199\&1\199\&9\199W\199c\199g\199s\199u\199\DEL\199\165\199\187\199\189\199\193\199\207\199\213\199\225\199\249\199\253\199\255\199\ETX\200\DC1\200\GS\200'\200)\200\&9\200?\200S\200W\200k\200\129\200\141\200\143\200\147\200\149\200\161\200\183\200\207\200\213\200\219\200\221\200\227\200\231\200\237\200\239\200\249\200\ENQ\201\DC1\201\ETB\201\EM\201\US\201/\201\&7\201=\201A\201S\201_\201k\201y\201}\201\137\201\143\201\151\201\157\201\175\201\181\201\191\201\203\201\217\201\223\201\227\201\235\201\SOH\202\a\202\t\202%\202\&7\202\&9\202K\202U\202[\202i\202s\202u\202\DEL\202\141\202\147\202\157\202\159\202\181\202\187\202\195\202\201\202\217\202\229\202\237\202\ETX\203\ENQ\203\t\203\ETB\203)\203\&5\203;\203S\203Y\203c\203e\203q\203\135\203\153\203\159\203\179\203\185\203\195\203\209\203\213\203\215\203\221\203\233\203\255\203\r\204\EM\204\GS\204#\204+\204A\204C\204M\204Y\204a\204\137\204\139\204\145\204\155\204\163\204\167\204\209\204\229\204\233\204\t\205\NAK\205\US\205%\205\&1\205=\205?\205I\205Q\205W\205[\205c\205g\205\129\205\147\205\151\205\159\205\187\205\193\205\211\205\217\205\229\205\231\205\241\205\247\205\253\205\v\206\NAK\206!\206/\206G\206M\206Q\206e\206{\206}\206\143\206\147\206\153\206\165\206\167\206\183\206\201\206\215\206\221\206\227\206\231\206\237\206\245\206\a\207\v\207\EM\207\&7\207;\207M\207U\207_\207a\207e\207m\207y\207}\207\137\207\155\207\157\207\169\207\179\207\181\207\197\207\205\207\209\207\239\207\241\207\247\207\DC3\208\NAK\208\US\208!\208\&3\208=\208K\208O\208i\208o\208\129\208\133\208\153\208\159\208\163\208\171\208\189\208\193\208\205\208\231\208\255\208\ETX\209\ETB\209-\209/\209A\209W\209Y\209]\209i\209k\209q\209w\209}\209\129\209\135\209\149\209\153\209\177\209\189\209\195\209\213\209\215\209\227\209\255\209\r\210\DC1\210\ETB\210\US\210\&5\210;\210G\210Y\210a\210e\210y\210\DEL\210\131\210\137\210\139\210\157\210\163\210\167\210\179\210\191\210\199\210\227\210\233\210\241\210\251\210\253\210\NAK\211!\211+\211C\211K\211U\211i\211u\211{\211\135\211\147\211\151\211\165\211\177\211\201\211\235\211\253\211\ENQ\212\SI\212\NAK\212'\212/\212\&3\212;\212K\212Y\212_\212c\212i\212\129\212\131\212\137\212\141\212\147\212\149\212\165\212\171\212\177\212\197\212\221\212\225\212\227\212\231\212\245\212\249\212\v\213\r\213\DC3\213\US\213#\213\&1\213\&5\213\&7\213I\213Y\213_\213e\213g\213w\213\139\213\145\213\151\213\181\213\185\213\193\213\199\213\223\213\239\213\245\213\251\213\ETX\214\SI\214-\214\&1\214C\214U\214]\214a\214{\214\133\214\135\214\157\214\165\214\175\214\189\214\195\214\199\214\217\214\225\214\237\214\t\215\v\215\DC1\215\NAK\215!\215'\215?\215E\215M\215W\215k\215{\215\131\215\161\215\167\215\173\215\177\215\179\215\189\215\203\215\209\215\219\215\251\215\DC1\216#\216%\216)\216+\216/\216\&7\216M\216U\216g\216s\216\143\216\145\216\161\216\173\216\191\216\205\216\215\216\233\216\245\216\251\216\ESC\217%\217\&3\217\&9\217C\217E\217O\217Q\217W\217m\217o\217s\217y\217\129\217\139\217\145\217\159\217\165\217\169\217\181\217\211\217\235\217\241\217\247\217\255\217\ENQ\218\t\218\v\218\SI\218\NAK\218\GS\218#\218)\218?\218Q\218Y\218]\218_\218q\218w\218{\218}\218\141\218\159\218\179\218\189\218\195\218\201\218\231\218\233\218\245\218\DC1\219\ETB\219\GS\219#\219%\219\&1\219;\219C\219U\219g\219k\219s\219\133\219\143\219\145\219\173\219\175\219\185\219\199\219\203\219\205\219\235\219\247\219\r\220'\220\&1\220\&9\220?\220I\220Q\220a\220o\220u\220{\220\133\220\147\220\153\220\157\220\159\220\169\220\181\220\183\220\189\220\199\220\207\220\211\220\213\220\223\220\249\220\SI\221\NAK\221\ETB\221#\221\&5\221\&9\221S\221W\221_\221i\221o\221}\221\135\221\137\221\155\221\161\221\171\221\191\221\197\221\203\221\207\221\231\221\233\221\237\221\245\221\251\221\v\222\EM\222)\222;\222=\222A\222M\222O\222Y\222[\222a\222m\222w\222}\222\131\222\151\222\157\222\161\222\167\222\205\222\209\222\215\222\227\222\241\222\245\222\SOH\223\t\223\DC3\223\US\223+\223\&3\223\&7\223=\223K\223U\223[\223g\223i\223s\223\133\223\135\223\153\223\163\223\171\223\181\223\183\223\195\223\199\223\213\223\241\223\243\223\ETX\224\ENQ\224\ETB\224\GS\224'\224-\224\&5\224E\224S\224q\224{\224\143\224\149\224\159\224\183\224\185\224\213\224\215\224\227\224\243\224\249\224\SOH\225%\225)\225\&1\225\&5\225C\225O\225Y\225a\225m\225q\225w\225\DEL\225\131\225\137\225\151\225\173\225\181\225\187\225\191\225\193\225\203\225\209\225\229\225\239\225\247\225\253\225\ETX\226\EM\226+\226-\226=\226C\226W\226[\226u\226y\226\135\226\157\226\171\226\175\226\187\226\193\226\201\226\205\226\211\226\217\226\243\226\253\226\255\226\DC1\227#\227'\227)\227\&9\227;\227M\227Q\227W\227_\227c\227i\227u\227w\227}\227\131\227\159\227\197\227\201\227\209\227\225\227\251\227\255\227\SOH\228\v\228\ETB\228\EM\228#\228+\228\&1\228;\228G\228I\228S\228U\228m\228q\228\143\228\169\228\175\228\181\228\199\228\205\228\211\228\233\228\235\228\245\228\a\229!\229%\229\&7\229?\229E\229K\229W\229g\229m\229u\229\133\229\139\229\147\229\163\229\165\229\207\229\t\230\DC1\230\NAK\230\ESC\230\GS\230!\230)\230\&9\230?\230S\230W\230c\230o\230u\230\129\230\131\230\141\230\143\230\149\230\171\230\173\230\183\230\189\230\197\230\203\230\213\230\227\230\233\230\239\230\243\230\ENQ\231\r\231\ETB\231\US\231/\231=\231G\231I\231S\231U\231a\231g\231k\231\DEL\231\137\231\145\231\197\231\205\231\215\231\221\231\223\231\233\231\241\231\251\231\SOH\232\a\232\SI\232\EM\232\ESC\232\&1\232\&3\232\&7\232=\232K\232O\232Q\232i\232u\232y\232\147\232\165\232\169\232\175\232\189\232\219\232\225\232\229\232\235\232\237\232\ETX\233\v\233\SI\233\NAK\233\ETB\233-\233\&3\233;\233K\233Q\233_\233c\233i\233{\233\131\233\143\233\149\233\161\233\185\233\215\233\231\233\239\233\DC1\234\EM\234/\234\&5\234C\234M\234_\234m\234q\234}\234\133\234\137\234\173\234\179\234\185\234\187\234\197\234\199\234\203\234\223\234\229\234\235\234\245\234\SOH\235\a\235\t\235\&1\235\&9\235?\235[\235a\235c\235o\235\129\235\133\235\157\235\171\235\177\235\183\235\193\235\213\235\223\235\237\235\253\235\v\236\ESC\236!\236)\236M\236Q\236]\236i\236o\236{\236\173\236\185\236\191\236\195\236\201\236\207\236\215\236\221\236\231\236\233\236\243\236\245\236\a\237\DC1\237\US\237/\237\&7\237=\237A\237U\237Y\237[\237e\237k\237y\237\139\237\149\237\187\237\197\237\215\237\217\237\227\237\229\237\241\237\245\237\247\237\251\237\t\238\SI\238\EM\238!\238I\238O\238c\238g\238s\238{\238\129\238\163\238\171\238\193\238\201\238\213\238\223\238\225\238\241\238\ESC\239'\239/\239E\239M\239c\239k\239q\239\147\239\149\239\155\239\159\239\173\239\179\239\195\239\197\239\219\239\225\239\233\239\SOH\240\ETB\240\GS\240\US\240+\240/\240\&5\240C\240G\240O\240g\240k\240q\240w\240y\240\143\240\163\240\169\240\173\240\187\240\191\240\197\240\203\240\211\240\217\240\227\240\233\240\241\240\247\240\a\241\NAK\241\ESC\241!\241\&7\241=\241U\241u\241{\241\141\241\147\241\165\241\175\241\183\241\213\241\231\241\237\241\253\241\t\242\SI\242\ESC\242\GS\242#\242'\242\&3\242;\242A\242W\242_\242e\242i\242w\242\129\242\147\242\167\242\177\242\179\242\185\242\189\242\191\242\219\242\237\242\239\242\249\242\255\242\ENQ\243\v\243\EM\243A\243Y\243[\243_\243g\243s\243w\243\139\243\143\243\175\243\193\243\209\243\215\243\251\243\ETX\244\t\244\r\244\DC3\244!\244%\244+\244E\244K\244U\244c\244u\244\DEL\244\133\244\139\244\153\244\163\244\169\244\175\244\189\244\195\244\219\244\223\244\237\244\ETX\245\v\245\ETB\245!\245)\245\&5\245G\245Q\245c\245k\245\131\245\141\245\149\245\153\245\177\245\183\245\201\245\207\245\209\245\219\245\249\245\251\245\ENQ\246\a\246\v\246\r\246\&5\246\&7\246S\246[\246a\246g\246y\246\DEL\246\137\246\151\246\155\246\173\246\203\246\221\246\223\246\235\246\t\247\SI\247-\247\&1\247C\247O\247Q\247U\247c\247i\247s\247y\247\129\247\135\247\145\247\157\247\159\247\165\247\177\247\187\247\189\247\207\247\211\247\231\247\235\247\241\247\255\247\ENQ\248\v\248!\248'\248-\248\&5\248G\248Y\248c\248e\248o\248q\248w\248{\248\129\248\141\248\159\248\161\248\171\248\179\248\183\248\201\248\203\248\209\248\215\248\221\248\231\248\239\248\249\248\255\248\DC1\249\GS\249%\249\&1\249\&7\249;\249A\249O\249_\249a\249m\249q\249w\249\157\249\163\249\169\249\185\249\205\249\233\249\253\249\a\250\r\250\DC3\250!\250%\250?\250C\250Q\250[\250m\250{\250\151\250\153\250\157\250\171\250\187\250\189\250\217\250\223\250\231\250\237\250\SI\251\ETB\251\ESC\251-\251/\251?\251G\251M\251u\251}\251\143\251\147\251\177\251\183\251\195\251\197\251\227\251\233\251\243\251\SOH\252)\252\&7\252A\252C\252O\252Y\252a\252e\252m\252s\252y\252\149\252\151\252\155\252\167\252\181\252\197\252\205\252\235\252\251\252\r\253\SI\253\EM\253+\253\&1\253Q\253U\253g\253m\253o\253{\253\133\253\151\253\153\253\159\253\169\253\183\253\201\253\229\253\235\253\243\253\ETX\254\ENQ\254\t\254\GS\254'\254/\254A\254K\254M\254W\254_\254c\254i\254u\254{\254\143\254\147\254\149\254\155\254\159\254\179\254\189\254\215\254\233\254\243\254\245\254\a\255\r\255\GS\255+\255/\255I\255M\255[\255e\255q\255\DEL\255\133\255\139\255\143\255\157\255\167\255\169\255\199\255\217\255\239\255\241\255"#++-- smallPrimes :: [Word16]+-- smallPrimes =+-- [2,3,5,7,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,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733,9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857,9859,9871,9883,9887,9901,9907,9923,9929,9931,9941,9949,9967,9973,10007,10009,10037,10039,10061,10067,10069,10079,10091,10093,10099,10103,10111,10133,10139,10141,10151,10159,10163,10169,10177,10181,10193,10211,10223,10243,10247,10253,10259,10267,10271,10273,10289,10301,10303,10313,10321,10331,10333,10337,10343,10357,10369,10391,10399,10427,10429,10433,10453,10457,10459,10463,10477,10487,10499,10501,10513,10529,10531,10559,10567,10589,10597,10601,10607,10613,10627,10631,10639,10651,10657,10663,10667,10687,10691,10709,10711,10723,10729,10733,10739,10753,10771,10781,10789,10799,10831,10837,10847,10853,10859,10861,10867,10883,10889,10891,10903,10909,10937,10939,10949,10957,10973,10979,10987,10993,11003,11027,11047,11057,11059,11069,11071,11083,11087,11093,11113,11117,11119,11131,11149,11159,11161,11171,11173,11177,11197,11213,11239,11243,11251,11257,11261,11273,11279,11287,11299,11311,11317,11321,11329,11351,11353,11369,11383,11393,11399,11411,11423,11437,11443,11447,11467,11471,11483,11489,11491,11497,11503,11519,11527,11549,11551,11579,11587,11593,11597,11617,11621,11633,11657,11677,11681,11689,11699,11701,11717,11719,11731,11743,11777,11779,11783,11789,11801,11807,11813,11821,11827,11831,11833,11839,11863,11867,11887,11897,11903,11909,11923,11927,11933,11939,11941,11953,11959,11969,11971,11981,11987,12007,12011,12037,12041,12043,12049,12071,12073,12097,12101,12107,12109,12113,12119,12143,12149,12157,12161,12163,12197,12203,12211,12227,12239,12241,12251,12253,12263,12269,12277,12281,12289,12301,12323,12329,12343,12347,12373,12377,12379,12391,12401,12409,12413,12421,12433,12437,12451,12457,12473,12479,12487,12491,12497,12503,12511,12517,12527,12539,12541,12547,12553,12569,12577,12583,12589,12601,12611,12613,12619,12637,12641,12647,12653,12659,12671,12689,12697,12703,12713,12721,12739,12743,12757,12763,12781,12791,12799,12809,12821,12823,12829,12841,12853,12889,12893,12899,12907,12911,12917,12919,12923,12941,12953,12959,12967,12973,12979,12983,13001,13003,13007,13009,13033,13037,13043,13049,13063,13093,13099,13103,13109,13121,13127,13147,13151,13159,13163,13171,13177,13183,13187,13217,13219,13229,13241,13249,13259,13267,13291,13297,13309,13313,13327,13331,13337,13339,13367,13381,13397,13399,13411,13417,13421,13441,13451,13457,13463,13469,13477,13487,13499,13513,13523,13537,13553,13567,13577,13591,13597,13613,13619,13627,13633,13649,13669,13679,13681,13687,13691,13693,13697,13709,13711,13721,13723,13729,13751,13757,13759,13763,13781,13789,13799,13807,13829,13831,13841,13859,13873,13877,13879,13883,13901,13903,13907,13913,13921,13931,13933,13963,13967,13997,13999,14009,14011,14029,14033,14051,14057,14071,14081,14083,14087,14107,14143,14149,14153,14159,14173,14177,14197,14207,14221,14243,14249,14251,14281,14293,14303,14321,14323,14327,14341,14347,14369,14387,14389,14401,14407,14411,14419,14423,14431,14437,14447,14449,14461,14479,14489,14503,14519,14533,14537,14543,14549,14551,14557,14561,14563,14591,14593,14621,14627,14629,14633,14639,14653,14657,14669,14683,14699,14713,14717,14723,14731,14737,14741,14747,14753,14759,14767,14771,14779,14783,14797,14813,14821,14827,14831,14843,14851,14867,14869,14879,14887,14891,14897,14923,14929,14939,14947,14951,14957,14969,14983,15013,15017,15031,15053,15061,15073,15077,15083,15091,15101,15107,15121,15131,15137,15139,15149,15161,15173,15187,15193,15199,15217,15227,15233,15241,15259,15263,15269,15271,15277,15287,15289,15299,15307,15313,15319,15329,15331,15349,15359,15361,15373,15377,15383,15391,15401,15413,15427,15439,15443,15451,15461,15467,15473,15493,15497,15511,15527,15541,15551,15559,15569,15581,15583,15601,15607,15619,15629,15641,15643,15647,15649,15661,15667,15671,15679,15683,15727,15731,15733,15737,15739,15749,15761,15767,15773,15787,15791,15797,15803,15809,15817,15823,15859,15877,15881,15887,15889,15901,15907,15913,15919,15923,15937,15959,15971,15973,15991,16001,16007,16033,16057,16061,16063,16067,16069,16073,16087,16091,16097,16103,16111,16127,16139,16141,16183,16187,16189,16193,16217,16223,16229,16231,16249,16253,16267,16273,16301,16319,16333,16339,16349,16361,16363,16369,16381,16411,16417,16421,16427,16433,16447,16451,16453,16477,16481,16487,16493,16519,16529,16547,16553,16561,16567,16573,16603,16607,16619,16631,16633,16649,16651,16657,16661,16673,16691,16693,16699,16703,16729,16741,16747,16759,16763,16787,16811,16823,16829,16831,16843,16871,16879,16883,16889,16901,16903,16921,16927,16931,16937,16943,16963,16979,16981,16987,16993,17011,17021,17027,17029,17033,17041,17047,17053,17077,17093,17099,17107,17117,17123,17137,17159,17167,17183,17189,17191,17203,17207,17209,17231,17239,17257,17291,17293,17299,17317,17321,17327,17333,17341,17351,17359,17377,17383,17387,17389,17393,17401,17417,17419,17431,17443,17449,17467,17471,17477,17483,17489,17491,17497,17509,17519,17539,17551,17569,17573,17579,17581,17597,17599,17609,17623,17627,17657,17659,17669,17681,17683,17707,17713,17729,17737,17747,17749,17761,17783,17789,17791,17807,17827,17837,17839,17851,17863,17881,17891,17903,17909,17911,17921,17923,17929,17939,17957,17959,17971,17977,17981,17987,17989,18013,18041,18043,18047,18049,18059,18061,18077,18089,18097,18119,18121,18127,18131,18133,18143,18149,18169,18181,18191,18199,18211,18217,18223,18229,18233,18251,18253,18257,18269,18287,18289,18301,18307,18311,18313,18329,18341,18353,18367,18371,18379,18397,18401,18413,18427,18433,18439,18443,18451,18457,18461,18481,18493,18503,18517,18521,18523,18539,18541,18553,18583,18587,18593,18617,18637,18661,18671,18679,18691,18701,18713,18719,18731,18743,18749,18757,18773,18787,18793,18797,18803,18839,18859,18869,18899,18911,18913,18917,18919,18947,18959,18973,18979,19001,19009,19013,19031,19037,19051,19069,19073,19079,19081,19087,19121,19139,19141,19157,19163,19181,19183,19207,19211,19213,19219,19231,19237,19249,19259,19267,19273,19289,19301,19309,19319,19333,19373,19379,19381,19387,19391,19403,19417,19421,19423,19427,19429,19433,19441,19447,19457,19463,19469,19471,19477,19483,19489,19501,19507,19531,19541,19543,19553,19559,19571,19577,19583,19597,19603,19609,19661,19681,19687,19697,19699,19709,19717,19727,19739,19751,19753,19759,19763,19777,19793,19801,19813,19819,19841,19843,19853,19861,19867,19889,19891,19913,19919,19927,19937,19949,19961,19963,19973,19979,19991,19993,19997,20011,20021,20023,20029,20047,20051,20063,20071,20089,20101,20107,20113,20117,20123,20129,20143,20147,20149,20161,20173,20177,20183,20201,20219,20231,20233,20249,20261,20269,20287,20297,20323,20327,20333,20341,20347,20353,20357,20359,20369,20389,20393,20399,20407,20411,20431,20441,20443,20477,20479,20483,20507,20509,20521,20533,20543,20549,20551,20563,20593,20599,20611,20627,20639,20641,20663,20681,20693,20707,20717,20719,20731,20743,20747,20749,20753,20759,20771,20773,20789,20807,20809,20849,20857,20873,20879,20887,20897,20899,20903,20921,20929,20939,20947,20959,20963,20981,20983,21001,21011,21013,21017,21019,21023,21031,21059,21061,21067,21089,21101,21107,21121,21139,21143,21149,21157,21163,21169,21179,21187,21191,21193,21211,21221,21227,21247,21269,21277,21283,21313,21317,21319,21323,21341,21347,21377,21379,21383,21391,21397,21401,21407,21419,21433,21467,21481,21487,21491,21493,21499,21503,21517,21521,21523,21529,21557,21559,21563,21569,21577,21587,21589,21599,21601,21611,21613,21617,21647,21649,21661,21673,21683,21701,21713,21727,21737,21739,21751,21757,21767,21773,21787,21799,21803,21817,21821,21839,21841,21851,21859,21863,21871,21881,21893,21911,21929,21937,21943,21961,21977,21991,21997,22003,22013,22027,22031,22037,22039,22051,22063,22067,22073,22079,22091,22093,22109,22111,22123,22129,22133,22147,22153,22157,22159,22171,22189,22193,22229,22247,22259,22271,22273,22277,22279,22283,22291,22303,22307,22343,22349,22367,22369,22381,22391,22397,22409,22433,22441,22447,22453,22469,22481,22483,22501,22511,22531,22541,22543,22549,22567,22571,22573,22613,22619,22621,22637,22639,22643,22651,22669,22679,22691,22697,22699,22709,22717,22721,22727,22739,22741,22751,22769,22777,22783,22787,22807,22811,22817,22853,22859,22861,22871,22877,22901,22907,22921,22937,22943,22961,22963,22973,22993,23003,23011,23017,23021,23027,23029,23039,23041,23053,23057,23059,23063,23071,23081,23087,23099,23117,23131,23143,23159,23167,23173,23189,23197,23201,23203,23209,23227,23251,23269,23279,23291,23293,23297,23311,23321,23327,23333,23339,23357,23369,23371,23399,23417,23431,23447,23459,23473,23497,23509,23531,23537,23539,23549,23557,23561,23563,23567,23581,23593,23599,23603,23609,23623,23627,23629,23633,23663,23669,23671,23677,23687,23689,23719,23741,23743,23747,23753,23761,23767,23773,23789,23801,23813,23819,23827,23831,23833,23857,23869,23873,23879,23887,23893,23899,23909,23911,23917,23929,23957,23971,23977,23981,23993,24001,24007,24019,24023,24029,24043,24049,24061,24071,24077,24083,24091,24097,24103,24107,24109,24113,24121,24133,24137,24151,24169,24179,24181,24197,24203,24223,24229,24239,24247,24251,24281,24317,24329,24337,24359,24371,24373,24379,24391,24407,24413,24419,24421,24439,24443,24469,24473,24481,24499,24509,24517,24527,24533,24547,24551,24571,24593,24611,24623,24631,24659,24671,24677,24683,24691,24697,24709,24733,24749,24763,24767,24781,24793,24799,24809,24821,24841,24847,24851,24859,24877,24889,24907,24917,24919,24923,24943,24953,24967,24971,24977,24979,24989,25013,25031,25033,25037,25057,25073,25087,25097,25111,25117,25121,25127,25147,25153,25163,25169,25171,25183,25189,25219,25229,25237,25243,25247,25253,25261,25301,25303,25307,25309,25321,25339,25343,25349,25357,25367,25373,25391,25409,25411,25423,25439,25447,25453,25457,25463,25469,25471,25523,25537,25541,25561,25577,25579,25583,25589,25601,25603,25609,25621,25633,25639,25643,25657,25667,25673,25679,25693,25703,25717,25733,25741,25747,25759,25763,25771,25793,25799,25801,25819,25841,25847,25849,25867,25873,25889,25903,25913,25919,25931,25933,25939,25943,25951,25969,25981,25997,25999,26003,26017,26021,26029,26041,26053,26083,26099,26107,26111,26113,26119,26141,26153,26161,26171,26177,26183,26189,26203,26209,26227,26237,26249,26251,26261,26263,26267,26293,26297,26309,26317,26321,26339,26347,26357,26371,26387,26393,26399,26407,26417,26423,26431,26437,26449,26459,26479,26489,26497,26501,26513,26539,26557,26561,26573,26591,26597,26627,26633,26641,26647,26669,26681,26683,26687,26693,26699,26701,26711,26713,26717,26723,26729,26731,26737,26759,26777,26783,26801,26813,26821,26833,26839,26849,26861,26863,26879,26881,26891,26893,26903,26921,26927,26947,26951,26953,26959,26981,26987,26993,27011,27017,27031,27043,27059,27061,27067,27073,27077,27091,27103,27107,27109,27127,27143,27179,27191,27197,27211,27239,27241,27253,27259,27271,27277,27281,27283,27299,27329,27337,27361,27367,27397,27407,27409,27427,27431,27437,27449,27457,27479,27481,27487,27509,27527,27529,27539,27541,27551,27581,27583,27611,27617,27631,27647,27653,27673,27689,27691,27697,27701,27733,27737,27739,27743,27749,27751,27763,27767,27773,27779,27791,27793,27799,27803,27809,27817,27823,27827,27847,27851,27883,27893,27901,27917,27919,27941,27943,27947,27953,27961,27967,27983,27997,28001,28019,28027,28031,28051,28057,28069,28081,28087,28097,28099,28109,28111,28123,28151,28163,28181,28183,28201,28211,28219,28229,28277,28279,28283,28289,28297,28307,28309,28319,28349,28351,28387,28393,28403,28409,28411,28429,28433,28439,28447,28463,28477,28493,28499,28513,28517,28537,28541,28547,28549,28559,28571,28573,28579,28591,28597,28603,28607,28619,28621,28627,28631,28643,28649,28657,28661,28663,28669,28687,28697,28703,28711,28723,28729,28751,28753,28759,28771,28789,28793,28807,28813,28817,28837,28843,28859,28867,28871,28879,28901,28909,28921,28927,28933,28949,28961,28979,29009,29017,29021,29023,29027,29033,29059,29063,29077,29101,29123,29129,29131,29137,29147,29153,29167,29173,29179,29191,29201,29207,29209,29221,29231,29243,29251,29269,29287,29297,29303,29311,29327,29333,29339,29347,29363,29383,29387,29389,29399,29401,29411,29423,29429,29437,29443,29453,29473,29483,29501,29527,29531,29537,29567,29569,29573,29581,29587,29599,29611,29629,29633,29641,29663,29669,29671,29683,29717,29723,29741,29753,29759,29761,29789,29803,29819,29833,29837,29851,29863,29867,29873,29879,29881,29917,29921,29927,29947,29959,29983,29989,30011,30013,30029,30047,30059,30071,30089,30091,30097,30103,30109,30113,30119,30133,30137,30139,30161,30169,30181,30187,30197,30203,30211,30223,30241,30253,30259,30269,30271,30293,30307,30313,30319,30323,30341,30347,30367,30389,30391,30403,30427,30431,30449,30467,30469,30491,30493,30497,30509,30517,30529,30539,30553,30557,30559,30577,30593,30631,30637,30643,30649,30661,30671,30677,30689,30697,30703,30707,30713,30727,30757,30763,30773,30781,30803,30809,30817,30829,30839,30841,30851,30853,30859,30869,30871,30881,30893,30911,30931,30937,30941,30949,30971,30977,30983,31013,31019,31033,31039,31051,31063,31069,31079,31081,31091,31121,31123,31139,31147,31151,31153,31159,31177,31181,31183,31189,31193,31219,31223,31231,31237,31247,31249,31253,31259,31267,31271,31277,31307,31319,31321,31327,31333,31337,31357,31379,31387,31391,31393,31397,31469,31477,31481,31489,31511,31513,31517,31531,31541,31543,31547,31567,31573,31583,31601,31607,31627,31643,31649,31657,31663,31667,31687,31699,31721,31723,31727,31729,31741,31751,31769,31771,31793,31799,31817,31847,31849,31859,31873,31883,31891,31907,31957,31963,31973,31981,31991,32003,32009,32027,32029,32051,32057,32059,32063,32069,32077,32083,32089,32099,32117,32119,32141,32143,32159,32173,32183,32189,32191,32203,32213,32233,32237,32251,32257,32261,32297,32299,32303,32309,32321,32323,32327,32341,32353,32359,32363,32369,32371,32377,32381,32401,32411,32413,32423,32429,32441,32443,32467,32479,32491,32497,32503,32507,32531,32533,32537,32561,32563,32569,32573,32579,32587,32603,32609,32611,32621,32633,32647,32653,32687,32693,32707,32713,32717,32719,32749,32771,32779,32783,32789,32797,32801,32803,32831,32833,32839,32843,32869,32887,32909,32911,32917,32933,32939,32941,32957,32969,32971,32983,32987,32993,32999,33013,33023,33029,33037,33049,33053,33071,33073,33083,33091,33107,33113,33119,33149,33151,33161,33179,33181,33191,33199,33203,33211,33223,33247,33287,33289,33301,33311,33317,33329,33331,33343,33347,33349,33353,33359,33377,33391,33403,33409,33413,33427,33457,33461,33469,33479,33487,33493,33503,33521,33529,33533,33547,33563,33569,33577,33581,33587,33589,33599,33601,33613,33617,33619,33623,33629,33637,33641,33647,33679,33703,33713,33721,33739,33749,33751,33757,33767,33769,33773,33791,33797,33809,33811,33827,33829,33851,33857,33863,33871,33889,33893,33911,33923,33931,33937,33941,33961,33967,33997,34019,34031,34033,34039,34057,34061,34123,34127,34129,34141,34147,34157,34159,34171,34183,34211,34213,34217,34231,34253,34259,34261,34267,34273,34283,34297,34301,34303,34313,34319,34327,34337,34351,34361,34367,34369,34381,34403,34421,34429,34439,34457,34469,34471,34483,34487,34499,34501,34511,34513,34519,34537,34543,34549,34583,34589,34591,34603,34607,34613,34631,34649,34651,34667,34673,34679,34687,34693,34703,34721,34729,34739,34747,34757,34759,34763,34781,34807,34819,34841,34843,34847,34849,34871,34877,34883,34897,34913,34919,34939,34949,34961,34963,34981,35023,35027,35051,35053,35059,35069,35081,35083,35089,35099,35107,35111,35117,35129,35141,35149,35153,35159,35171,35201,35221,35227,35251,35257,35267,35279,35281,35291,35311,35317,35323,35327,35339,35353,35363,35381,35393,35401,35407,35419,35423,35437,35447,35449,35461,35491,35507,35509,35521,35527,35531,35533,35537,35543,35569,35573,35591,35593,35597,35603,35617,35671,35677,35729,35731,35747,35753,35759,35771,35797,35801,35803,35809,35831,35837,35839,35851,35863,35869,35879,35897,35899,35911,35923,35933,35951,35963,35969,35977,35983,35993,35999,36007,36011,36013,36017,36037,36061,36067,36073,36083,36097,36107,36109,36131,36137,36151,36161,36187,36191,36209,36217,36229,36241,36251,36263,36269,36277,36293,36299,36307,36313,36319,36341,36343,36353,36373,36383,36389,36433,36451,36457,36467,36469,36473,36479,36493,36497,36523,36527,36529,36541,36551,36559,36563,36571,36583,36587,36599,36607,36629,36637,36643,36653,36671,36677,36683,36691,36697,36709,36713,36721,36739,36749,36761,36767,36779,36781,36787,36791,36793,36809,36821,36833,36847,36857,36871,36877,36887,36899,36901,36913,36919,36923,36929,36931,36943,36947,36973,36979,36997,37003,37013,37019,37021,37039,37049,37057,37061,37087,37097,37117,37123,37139,37159,37171,37181,37189,37199,37201,37217,37223,37243,37253,37273,37277,37307,37309,37313,37321,37337,37339,37357,37361,37363,37369,37379,37397,37409,37423,37441,37447,37463,37483,37489,37493,37501,37507,37511,37517,37529,37537,37547,37549,37561,37567,37571,37573,37579,37589,37591,37607,37619,37633,37643,37649,37657,37663,37691,37693,37699,37717,37747,37781,37783,37799,37811,37813,37831,37847,37853,37861,37871,37879,37889,37897,37907,37951,37957,37963,37967,37987,37991,37993,37997,38011,38039,38047,38053,38069,38083,38113,38119,38149,38153,38167,38177,38183,38189,38197,38201,38219,38231,38237,38239,38261,38273,38281,38287,38299,38303,38317,38321,38327,38329,38333,38351,38371,38377,38393,38431,38447,38449,38453,38459,38461,38501,38543,38557,38561,38567,38569,38593,38603,38609,38611,38629,38639,38651,38653,38669,38671,38677,38693,38699,38707,38711,38713,38723,38729,38737,38747,38749,38767,38783,38791,38803,38821,38833,38839,38851,38861,38867,38873,38891,38903,38917,38921,38923,38933,38953,38959,38971,38977,38993,39019,39023,39041,39043,39047,39079,39089,39097,39103,39107,39113,39119,39133,39139,39157,39161,39163,39181,39191,39199,39209,39217,39227,39229,39233,39239,39241,39251,39293,39301,39313,39317,39323,39341,39343,39359,39367,39371,39373,39383,39397,39409,39419,39439,39443,39451,39461,39499,39503,39509,39511,39521,39541,39551,39563,39569,39581,39607,39619,39623,39631,39659,39667,39671,39679,39703,39709,39719,39727,39733,39749,39761,39769,39779,39791,39799,39821,39827,39829,39839,39841,39847,39857,39863,39869,39877,39883,39887,39901,39929,39937,39953,39971,39979,39983,39989,40009,40013,40031,40037,40039,40063,40087,40093,40099,40111,40123,40127,40129,40151,40153,40163,40169,40177,40189,40193,40213,40231,40237,40241,40253,40277,40283,40289,40343,40351,40357,40361,40387,40423,40427,40429,40433,40459,40471,40483,40487,40493,40499,40507,40519,40529,40531,40543,40559,40577,40583,40591,40597,40609,40627,40637,40639,40693,40697,40699,40709,40739,40751,40759,40763,40771,40787,40801,40813,40819,40823,40829,40841,40847,40849,40853,40867,40879,40883,40897,40903,40927,40933,40939,40949,40961,40973,40993,41011,41017,41023,41039,41047,41051,41057,41077,41081,41113,41117,41131,41141,41143,41149,41161,41177,41179,41183,41189,41201,41203,41213,41221,41227,41231,41233,41243,41257,41263,41269,41281,41299,41333,41341,41351,41357,41381,41387,41389,41399,41411,41413,41443,41453,41467,41479,41491,41507,41513,41519,41521,41539,41543,41549,41579,41593,41597,41603,41609,41611,41617,41621,41627,41641,41647,41651,41659,41669,41681,41687,41719,41729,41737,41759,41761,41771,41777,41801,41809,41813,41843,41849,41851,41863,41879,41887,41893,41897,41903,41911,41927,41941,41947,41953,41957,41959,41969,41981,41983,41999,42013,42017,42019,42023,42043,42061,42071,42073,42083,42089,42101,42131,42139,42157,42169,42179,42181,42187,42193,42197,42209,42221,42223,42227,42239,42257,42281,42283,42293,42299,42307,42323,42331,42337,42349,42359,42373,42379,42391,42397,42403,42407,42409,42433,42437,42443,42451,42457,42461,42463,42467,42473,42487,42491,42499,42509,42533,42557,42569,42571,42577,42589,42611,42641,42643,42649,42667,42677,42683,42689,42697,42701,42703,42709,42719,42727,42737,42743,42751,42767,42773,42787,42793,42797,42821,42829,42839,42841,42853,42859,42863,42899,42901,42923,42929,42937,42943,42953,42961,42967,42979,42989,43003,43013,43019,43037,43049,43051,43063,43067,43093,43103,43117,43133,43151,43159,43177,43189,43201,43207,43223,43237,43261,43271,43283,43291,43313,43319,43321,43331,43391,43397,43399,43403,43411,43427,43441,43451,43457,43481,43487,43499,43517,43541,43543,43573,43577,43579,43591,43597,43607,43609,43613,43627,43633,43649,43651,43661,43669,43691,43711,43717,43721,43753,43759,43777,43781,43783,43787,43789,43793,43801,43853,43867,43889,43891,43913,43933,43943,43951,43961,43963,43969,43973,43987,43991,43997,44017,44021,44027,44029,44041,44053,44059,44071,44087,44089,44101,44111,44119,44123,44129,44131,44159,44171,44179,44189,44201,44203,44207,44221,44249,44257,44263,44267,44269,44273,44279,44281,44293,44351,44357,44371,44381,44383,44389,44417,44449,44453,44483,44491,44497,44501,44507,44519,44531,44533,44537,44543,44549,44563,44579,44587,44617,44621,44623,44633,44641,44647,44651,44657,44683,44687,44699,44701,44711,44729,44741,44753,44771,44773,44777,44789,44797,44809,44819,44839,44843,44851,44867,44879,44887,44893,44909,44917,44927,44939,44953,44959,44963,44971,44983,44987,45007,45013,45053,45061,45077,45083,45119,45121,45127,45131,45137,45139,45161,45179,45181,45191,45197,45233,45247,45259,45263,45281,45289,45293,45307,45317,45319,45329,45337,45341,45343,45361,45377,45389,45403,45413,45427,45433,45439,45481,45491,45497,45503,45523,45533,45541,45553,45557,45569,45587,45589,45599,45613,45631,45641,45659,45667,45673,45677,45691,45697,45707,45737,45751,45757,45763,45767,45779,45817,45821,45823,45827,45833,45841,45853,45863,45869,45887,45893,45943,45949,45953,45959,45971,45979,45989,46021,46027,46049,46051,46061,46073,46091,46093,46099,46103,46133,46141,46147,46153,46171,46181,46183,46187,46199,46219,46229,46237,46261,46271,46273,46279,46301,46307,46309,46327,46337,46349,46351,46381,46399,46411,46439,46441,46447,46451,46457,46471,46477,46489,46499,46507,46511,46523,46549,46559,46567,46573,46589,46591,46601,46619,46633,46639,46643,46649,46663,46679,46681,46687,46691,46703,46723,46727,46747,46751,46757,46769,46771,46807,46811,46817,46819,46829,46831,46853,46861,46867,46877,46889,46901,46919,46933,46957,46993,46997,47017,47041,47051,47057,47059,47087,47093,47111,47119,47123,47129,47137,47143,47147,47149,47161,47189,47207,47221,47237,47251,47269,47279,47287,47293,47297,47303,47309,47317,47339,47351,47353,47363,47381,47387,47389,47407,47417,47419,47431,47441,47459,47491,47497,47501,47507,47513,47521,47527,47533,47543,47563,47569,47581,47591,47599,47609,47623,47629,47639,47653,47657,47659,47681,47699,47701,47711,47713,47717,47737,47741,47743,47777,47779,47791,47797,47807,47809,47819,47837,47843,47857,47869,47881,47903,47911,47917,47933,47939,47947,47951,47963,47969,47977,47981,48017,48023,48029,48049,48073,48079,48091,48109,48119,48121,48131,48157,48163,48179,48187,48193,48197,48221,48239,48247,48259,48271,48281,48299,48311,48313,48337,48341,48353,48371,48383,48397,48407,48409,48413,48437,48449,48463,48473,48479,48481,48487,48491,48497,48523,48527,48533,48539,48541,48563,48571,48589,48593,48611,48619,48623,48647,48649,48661,48673,48677,48679,48731,48733,48751,48757,48761,48767,48779,48781,48787,48799,48809,48817,48821,48823,48847,48857,48859,48869,48871,48883,48889,48907,48947,48953,48973,48989,48991,49003,49009,49019,49031,49033,49037,49043,49057,49069,49081,49103,49109,49117,49121,49123,49139,49157,49169,49171,49177,49193,49199,49201,49207,49211,49223,49253,49261,49277,49279,49297,49307,49331,49333,49339,49363,49367,49369,49391,49393,49409,49411,49417,49429,49433,49451,49459,49463,49477,49481,49499,49523,49529,49531,49537,49547,49549,49559,49597,49603,49613,49627,49633,49639,49663,49667,49669,49681,49697,49711,49727,49739,49741,49747,49757,49783,49787,49789,49801,49807,49811,49823,49831,49843,49853,49871,49877,49891,49919,49921,49927,49937,49939,49943,49957,49991,49993,49999,50021,50023,50033,50047,50051,50053,50069,50077,50087,50093,50101,50111,50119,50123,50129,50131,50147,50153,50159,50177,50207,50221,50227,50231,50261,50263,50273,50287,50291,50311,50321,50329,50333,50341,50359,50363,50377,50383,50387,50411,50417,50423,50441,50459,50461,50497,50503,50513,50527,50539,50543,50549,50551,50581,50587,50591,50593,50599,50627,50647,50651,50671,50683,50707,50723,50741,50753,50767,50773,50777,50789,50821,50833,50839,50849,50857,50867,50873,50891,50893,50909,50923,50929,50951,50957,50969,50971,50989,50993,51001,51031,51043,51047,51059,51061,51071,51109,51131,51133,51137,51151,51157,51169,51193,51197,51199,51203,51217,51229,51239,51241,51257,51263,51283,51287,51307,51329,51341,51343,51347,51349,51361,51383,51407,51413,51419,51421,51427,51431,51437,51439,51449,51461,51473,51479,51481,51487,51503,51511,51517,51521,51539,51551,51563,51577,51581,51593,51599,51607,51613,51631,51637,51647,51659,51673,51679,51683,51691,51713,51719,51721,51749,51767,51769,51787,51797,51803,51817,51827,51829,51839,51853,51859,51869,51871,51893,51899,51907,51913,51929,51941,51949,51971,51973,51977,51991,52009,52021,52027,52051,52057,52067,52069,52081,52103,52121,52127,52147,52153,52163,52177,52181,52183,52189,52201,52223,52237,52249,52253,52259,52267,52289,52291,52301,52313,52321,52361,52363,52369,52379,52387,52391,52433,52453,52457,52489,52501,52511,52517,52529,52541,52543,52553,52561,52567,52571,52579,52583,52609,52627,52631,52639,52667,52673,52691,52697,52709,52711,52721,52727,52733,52747,52757,52769,52783,52807,52813,52817,52837,52859,52861,52879,52883,52889,52901,52903,52919,52937,52951,52957,52963,52967,52973,52981,52999,53003,53017,53047,53051,53069,53077,53087,53089,53093,53101,53113,53117,53129,53147,53149,53161,53171,53173,53189,53197,53201,53231,53233,53239,53267,53269,53279,53281,53299,53309,53323,53327,53353,53359,53377,53381,53401,53407,53411,53419,53437,53441,53453,53479,53503,53507,53527,53549,53551,53569,53591,53593,53597,53609,53611,53617,53623,53629,53633,53639,53653,53657,53681,53693,53699,53717,53719,53731,53759,53773,53777,53783,53791,53813,53819,53831,53849,53857,53861,53881,53887,53891,53897,53899,53917,53923,53927,53939,53951,53959,53987,53993,54001,54011,54013,54037,54049,54059,54083,54091,54101,54121,54133,54139,54151,54163,54167,54181,54193,54217,54251,54269,54277,54287,54293,54311,54319,54323,54331,54347,54361,54367,54371,54377,54401,54403,54409,54413,54419,54421,54437,54443,54449,54469,54493,54497,54499,54503,54517,54521,54539,54541,54547,54559,54563,54577,54581,54583,54601,54617,54623,54629,54631,54647,54667,54673,54679,54709,54713,54721,54727,54751,54767,54773,54779,54787,54799,54829,54833,54851,54869,54877,54881,54907,54917,54919,54941,54949,54959,54973,54979,54983,55001,55009,55021,55049,55051,55057,55061,55073,55079,55103,55109,55117,55127,55147,55163,55171,55201,55207,55213,55217,55219,55229,55243,55249,55259,55291,55313,55331,55333,55337,55339,55343,55351,55373,55381,55399,55411,55439,55441,55457,55469,55487,55501,55511,55529,55541,55547,55579,55589,55603,55609,55619,55621,55631,55633,55639,55661,55663,55667,55673,55681,55691,55697,55711,55717,55721,55733,55763,55787,55793,55799,55807,55813,55817,55819,55823,55829,55837,55843,55849,55871,55889,55897,55901,55903,55921,55927,55931,55933,55949,55967,55987,55997,56003,56009,56039,56041,56053,56081,56087,56093,56099,56101,56113,56123,56131,56149,56167,56171,56179,56197,56207,56209,56237,56239,56249,56263,56267,56269,56299,56311,56333,56359,56369,56377,56383,56393,56401,56417,56431,56437,56443,56453,56467,56473,56477,56479,56489,56501,56503,56509,56519,56527,56531,56533,56543,56569,56591,56597,56599,56611,56629,56633,56659,56663,56671,56681,56687,56701,56711,56713,56731,56737,56747,56767,56773,56779,56783,56807,56809,56813,56821,56827,56843,56857,56873,56891,56893,56897,56909,56911,56921,56923,56929,56941,56951,56957,56963,56983,56989,56993,56999,57037,57041,57047,57059,57073,57077,57089,57097,57107,57119,57131,57139,57143,57149,57163,57173,57179,57191,57193,57203,57221,57223,57241,57251,57259,57269,57271,57283,57287,57301,57329,57331,57347,57349,57367,57373,57383,57389,57397,57413,57427,57457,57467,57487,57493,57503,57527,57529,57557,57559,57571,57587,57593,57601,57637,57641,57649,57653,57667,57679,57689,57697,57709,57713,57719,57727,57731,57737,57751,57773,57781,57787,57791,57793,57803,57809,57829,57839,57847,57853,57859,57881,57899,57901,57917,57923,57943,57947,57973,57977,57991,58013,58027,58031,58043,58049,58057,58061,58067,58073,58099,58109,58111,58129,58147,58151,58153,58169,58171,58189,58193,58199,58207,58211,58217,58229,58231,58237,58243,58271,58309,58313,58321,58337,58363,58367,58369,58379,58391,58393,58403,58411,58417,58427,58439,58441,58451,58453,58477,58481,58511,58537,58543,58549,58567,58573,58579,58601,58603,58613,58631,58657,58661,58679,58687,58693,58699,58711,58727,58733,58741,58757,58763,58771,58787,58789,58831,58889,58897,58901,58907,58909,58913,58921,58937,58943,58963,58967,58979,58991,58997,59009,59011,59021,59023,59029,59051,59053,59063,59069,59077,59083,59093,59107,59113,59119,59123,59141,59149,59159,59167,59183,59197,59207,59209,59219,59221,59233,59239,59243,59263,59273,59281,59333,59341,59351,59357,59359,59369,59377,59387,59393,59399,59407,59417,59419,59441,59443,59447,59453,59467,59471,59473,59497,59509,59513,59539,59557,59561,59567,59581,59611,59617,59621,59627,59629,59651,59659,59663,59669,59671,59693,59699,59707,59723,59729,59743,59747,59753,59771,59779,59791,59797,59809,59833,59863,59879,59887,59921,59929,59951,59957,59971,59981,59999,60013,60017,60029,60037,60041,60077,60083,60089,60091,60101,60103,60107,60127,60133,60139,60149,60161,60167,60169,60209,60217,60223,60251,60257,60259,60271,60289,60293,60317,60331,60337,60343,60353,60373,60383,60397,60413,60427,60443,60449,60457,60493,60497,60509,60521,60527,60539,60589,60601,60607,60611,60617,60623,60631,60637,60647,60649,60659,60661,60679,60689,60703,60719,60727,60733,60737,60757,60761,60763,60773,60779,60793,60811,60821,60859,60869,60887,60889,60899,60901,60913,60917,60919,60923,60937,60943,60953,60961,61001,61007,61027,61031,61043,61051,61057,61091,61099,61121,61129,61141,61151,61153,61169,61211,61223,61231,61253,61261,61283,61291,61297,61331,61333,61339,61343,61357,61363,61379,61381,61403,61409,61417,61441,61463,61469,61471,61483,61487,61493,61507,61511,61519,61543,61547,61553,61559,61561,61583,61603,61609,61613,61627,61631,61637,61643,61651,61657,61667,61673,61681,61687,61703,61717,61723,61729,61751,61757,61781,61813,61819,61837,61843,61861,61871,61879,61909,61927,61933,61949,61961,61967,61979,61981,61987,61991,62003,62011,62017,62039,62047,62053,62057,62071,62081,62099,62119,62129,62131,62137,62141,62143,62171,62189,62191,62201,62207,62213,62219,62233,62273,62297,62299,62303,62311,62323,62327,62347,62351,62383,62401,62417,62423,62459,62467,62473,62477,62483,62497,62501,62507,62533,62539,62549,62563,62581,62591,62597,62603,62617,62627,62633,62639,62653,62659,62683,62687,62701,62723,62731,62743,62753,62761,62773,62791,62801,62819,62827,62851,62861,62869,62873,62897,62903,62921,62927,62929,62939,62969,62971,62981,62983,62987,62989,63029,63031,63059,63067,63073,63079,63097,63103,63113,63127,63131,63149,63179,63197,63199,63211,63241,63247,63277,63281,63299,63311,63313,63317,63331,63337,63347,63353,63361,63367,63377,63389,63391,63397,63409,63419,63421,63439,63443,63463,63467,63473,63487,63493,63499,63521,63527,63533,63541,63559,63577,63587,63589,63599,63601,63607,63611,63617,63629,63647,63649,63659,63667,63671,63689,63691,63697,63703,63709,63719,63727,63737,63743,63761,63773,63781,63793,63799,63803,63809,63823,63839,63841,63853,63857,63863,63901,63907,63913,63929,63949,63977,63997,64007,64013,64019,64033,64037,64063,64067,64081,64091,64109,64123,64151,64153,64157,64171,64187,64189,64217,64223,64231,64237,64271,64279,64283,64301,64303,64319,64327,64333,64373,64381,64399,64403,64433,64439,64451,64453,64483,64489,64499,64513,64553,64567,64577,64579,64591,64601,64609,64613,64621,64627,64633,64661,64663,64667,64679,64693,64709,64717,64747,64763,64781,64783,64793,64811,64817,64849,64853,64871,64877,64879,64891,64901,64919,64921,64927,64937,64951,64969,64997,65003,65011,65027,65029,65033,65053,65063,65071,65089,65099,65101,65111,65119,65123,65129,65141,65147,65167,65171,65173,65179,65183,65203,65213,65239,65257,65267,65269,65287,65293,65309,65323,65327,65353,65357,65371,65381,65393,65407,65413,65419,65423,65437,65447,65449,65479,65497,65519,65521]
Math/NumberTheory/Primes/Testing.hs view
@@ -6,8 +6,6 @@ -- -- Primality tests. -{-# OPTIONS_GHC -fno-warn-deprecations #-}- module Math.NumberTheory.Primes.Testing ( -- * Standard tests isPrime
− Math/NumberTheory/Primes/Testing/Certificates.hs
@@ -1,35 +0,0 @@--- |--- Module: Math.NumberTheory.Primes.Testing.Certificates--- Description: Deprecated--- Copyright: (c) 2011 Daniel Fischer--- Licence: MIT--- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>------ Certificates for primality or compositeness.-module Math.NumberTheory.Primes.Testing.Certificates {-# DEPRECATED "This module will be removed in the next release" #-}- ( -- * Certificates- Certificate(..)- , argueCertificate- , CompositenessProof- , composite- , PrimalityProof- , cprime- -- * Arguments- , CompositenessArgument(..)- , PrimalityArgument(..)- -- ** Weaken proofs to arguments- , arguePrimality- , argueCompositeness- -- ** Prove valid arguments- , verifyPrimalityArgument- , verifyCompositenessArgument- -- * Determine and prove whether a number is prime or composite- , certify- -- ** Checks for the paranoid- , checkCertificate- , checkCompositenessProof- , checkPrimalityProof- ) where--import Math.NumberTheory.Primes.Testing.Certificates.Internal-
− Math/NumberTheory/Primes/Testing/Certificates/Internal.hs
@@ -1,358 +0,0 @@--- |--- Module: Math.NumberTheory.Primes.Testing.Certificates.Internal--- Copyright: (c) 2011 Daniel Fischer--- Licence: MIT--- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com>------ Certificates for primality or compositeness.-{-# LANGUAGE CPP #-}-{-# OPTIONS_HADDOCK hide #-}-module Math.NumberTheory.Primes.Testing.Certificates.Internal- ( Certificate(..)- , CompositenessProof(..)- , PrimalityProof(..)- , CompositenessArgument(..)- , PrimalityArgument(..)- , checkCertificate- , checkCompositenessProof- , checkPrimalityProof- , certify- , trivial- , smallCert- , certifyBPSW- , argueCertificate- , arguePrimality- , argueCompositeness- , verifyPrimalityArgument- , verifyCompositenessArgument- ) where--import Data.List-import Data.Bits-import Data.Maybe-import GHC.Integer.GMP.Internals--import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Powers.Squares-import Math.NumberTheory.Primes (unPrime)-import Math.NumberTheory.Primes.Factorisation.TrialDivision-import Math.NumberTheory.Primes.Factorisation.Montgomery-import Math.NumberTheory.Primes.Testing.Probabilistic-import Math.NumberTheory.Primes.Sieve.Eratosthenes (primeList, primeSieve)-import Math.NumberTheory.Utils---- | A certificate of either compositeness or primality of an--- 'Integer'. Only numbers @> 1@ can be certified, trying to--- create a certificate for other numbers raises an error.-data Certificate- = Composite !CompositenessProof- | Prime !PrimalityProof- deriving Show---- | A proof of compositeness of a positive number. The type is--- abstract to ensure the validity of proofs.-data CompositenessProof- = Factors { composite :: !Integer -- ^ The number whose compositeness is proved.- , firstFactor- , secondFactor :: !Integer }- | StrongFermat { composite :: !Integer -- ^ The number whose compositeness is proved.- , witness :: !Integer }- | LucasSelfridge { composite :: !Integer -- ^ The number whose compositeness is proved.- }- deriving Show---- | An argument for compositeness of a number (which must be @> 1@).--- 'CompositenessProof's translate directly to 'CompositenessArgument's,--- correct arguments can be transformed into proofs. This type allows the--- manipulation of proofs while maintaining their correctness.--- The only way to access components of a 'CompositenessProof' except--- the composite is through this type.-data CompositenessArgument- = Divisors { compo, firstDivisor, secondDivisor :: Integer }- -- ^ @compo == firstDiv*secondDiv@, where all are @> 1@- | Fermat { compo, fermatBase :: Integer } -- ^ @compo@ fails the strong Fermat test for @fermatBase@- | Lucas { compo :: Integer } -- ^ @compo@ fails the Lucas-Selfridge test- | Belief { compo :: Integer } -- ^ No particular reason given- deriving (Show, Read, Eq, Ord)---- | A proof of primality of a positive number. The type is--- abstract to ensure the validity of proofs.-data PrimalityProof- = Pocklington { cprime :: !Integer -- ^ The number whose primality is proved.- , factorisedPart, cofactor :: !Integer- , knownFactors :: ![(Integer, Word, Integer, PrimalityProof)]- }- | TrialDivision { cprime :: !Integer -- ^ The number whose primality is proved.- , tdLimit :: !Integer }- | Trivial { cprime :: !Integer -- ^ The number whose primality is proved.- }- deriving Show---- | An argument for primality of a number (which must be @> 1@).--- 'PrimalityProof's translate directly to 'PrimalityArgument's,--- correct arguments can be transformed into proofs. This type allows the--- manipulation of proofs while maintaining their correctness.--- The only way to access components of a 'PrimalityProof' except--- the prime is through this type.-data PrimalityArgument- = Pock { aprime :: Integer- , largeFactor, smallFactor :: Integer- , factorList :: [(Integer, Word, Integer, PrimalityArgument)]- } -- ^ A suggested Pocklington certificate- | Division { aprime, alimit :: Integer } -- ^ Primality should be provable by trial division to @alimit@- | Obvious { aprime :: Integer } -- ^ @aprime@ is said to be obviously prime, that holds for primes @< 30@- | Assumption { aprime :: Integer } -- ^ Primality assumed- deriving (Show, Read, Eq, Ord)---- | Eliminate 'Certificate'.-argueCertificate :: Certificate -> Either CompositenessArgument PrimalityArgument-argueCertificate (Composite proof) = Left (argueCompositeness proof)-argueCertificate (Prime proof) = Right (arguePrimality proof)---- | @'arguePrimality'@ transforms a proof of primality into an argument for primality.-arguePrimality :: PrimalityProof -> PrimalityArgument-arguePrimality (TrialDivision p l) = Division p l-arguePrimality (Trivial p) = Obvious p-arguePrimality (Pocklington p a b fcts) = Pock p a b (map argue fcts)- where- argue (x,y,z,prf) = (x,y,z,arguePrimality prf)---- | @'verifyPrimalityArgument'@ checks the given argument and constructs a proof from--- it, if it is valid. For the explicit arguments, this is simple and resonably fast,--- for an 'Assumption', the verification uses 'certify' and hence may take a long time.-verifyPrimalityArgument :: PrimalityArgument -> Maybe PrimalityProof-verifyPrimalityArgument (Assumption p)- = case certify p of- Composite _ -> Nothing- Prime proof -> Just proof-verifyPrimalityArgument arg- | checkPrimalityProof prf = Just prf- | otherwise = Nothing- where- prf = primProof arg---- | not exported, this is the one place where invalid proofs can be constructed-primProof :: PrimalityArgument -> PrimalityProof-primProof (Division p l) = TrialDivision p l-primProof (Obvious p) = Trivial p-primProof (Assumption p) = case certify p of- Composite _ -> Trivial p -- we're faking to not raise an error- Prime proof -> proof-primProof (Pock p a b fcts) = Pocklington p a b (map prove fcts)- where- prove (x,y,z,arg) = (x,y,z,primProof arg)---- | @'argueCompositeness'@ transforms a proof of compositeness into an argument--- for compositeness.-argueCompositeness :: CompositenessProof -> CompositenessArgument-argueCompositeness (Factors c f s) = Divisors c f s-argueCompositeness (StrongFermat c b) = Fermat c b-argueCompositeness (LucasSelfridge c) = Lucas c---- | @'verifyCompositenessArgument'@ checks the given argument and constructs a proof from--- it, if it is valid. For the explicit arguments, this is simple and resonably fast,--- for a 'Belief', the verification uses 'certify' and hence may take a long time.-verifyCompositenessArgument :: CompositenessArgument -> Maybe CompositenessProof-verifyCompositenessArgument (Belief c)- = case certify c of- Composite proof -> Just proof- Prime _ -> Nothing-verifyCompositenessArgument arg- | checkCompositenessProof prf = Just prf- | otherwise = Nothing- where- prf = compProof arg---- | not exported, here is where invalid proofs can be constructed,--- they must not leak-compProof :: CompositenessArgument -> CompositenessProof-compProof (Divisors c f s) = Factors c f s-compProof (Fermat c b) = StrongFermat c b-compProof (Lucas c) = LucasSelfridge c-compProof (Belief _) = error "Trying to prove by belief"---- | Check the validity of a 'Certificate'. Since it should be impossible--- to construct invalid certificates by the public interface, this should--- never return 'False'.-checkCertificate :: Certificate -> Bool-checkCertificate (Composite cp) = checkCompositenessProof cp-checkCertificate (Prime pp) = checkPrimalityProof pp---- | Check the validity of a 'CompositenessProof'. Since it should be--- impossible to create invalid proofs by the public interface, this--- should never return 'False'.-checkCompositenessProof :: CompositenessProof -> Bool-checkCompositenessProof (Factors c a b) = a > 1 && b > 1 && a*b == c-checkCompositenessProof (StrongFermat c w) = w > 1 && c > w && not (isStrongFermatPP c w)-checkCompositenessProof (LucasSelfridge c) = c > 3 && fromIntegral c .&. (1 :: Int) == 1 && lucasTest c---- | Check the validity of a 'PrimalityProof'. Since it should be--- impossible to create invalid proofs by the public interface, this--- should never return 'False'.-checkPrimalityProof :: PrimalityProof -> Bool-checkPrimalityProof (Trivial n) = isTrivialPrime n-checkPrimalityProof (TrialDivision p b) = p <= b*b && trialDivisionPrimeTo b p-checkPrimalityProof (Pocklington p a b fcts) = b > 0 && a > b && a*b == pm1 && a == ppProd fcts && all verify fcts- where- pm1 = p-1- ppProd pps = product [pf^e | (pf,e,_,_) <- pps]- verify (pf,_,base,proof) = pf == cprime proof && crit pf base && checkPrimalityProof proof- crit pf base = gcd p (x-1) == 1 && y == 1- where- x = powModInteger base (pm1 `quot` pf) p- y = powModInteger x pf p---- | @'trivial'@ records a trivially known prime.--- If the argument is not one of them, an error is raised.-trivial :: Integer -> PrimalityProof-trivial n = fromMaybe oops $ maybeTrivial n- where- oops = error ("trivial: " ++ show n ++ " isn't a trivially known prime.")---- | @'maybeTrivial'@ finds out if its argument is a trivially known--- prime or not and returns the appropriate.-maybeTrivial :: Integer -> Maybe PrimalityProof-maybeTrivial n- | isTrivialPrime n = Just (Trivial n)- | otherwise = Nothing---- | @'isTrivialPrime'@ checks whether its argument is a trivially--- known prime.-isTrivialPrime :: Integer -> Bool-isTrivialPrime n = n `elem` trivialPrimes---- | List of trivially known primes.-trivialPrimes :: [Integer]-trivialPrimes = [2,3,5,7,11,13,17,19,23,29]---- | Certify a small number. This is not exposed and should only--- be used where correct. It is always checked after use, though,--- so it shouldn't be able to lie.-smallCert :: Integer -> PrimalityProof-smallCert n- | n < 30 = Trivial n- | otherwise = TrialDivision n (integerSquareRoot' n + 1)---- | @'certify' n@ constructs, for @n > 1@, a proof of either--- primality or compositeness of @n@. This may take a very long--- time if the number has no small(ish) prime divisors-certify :: Integer -> Certificate-certify n- | n < 2 = error "Only numbers larger than 1 can be certified"- | n < 31 = case trialDivisionWith trivialPrimes n of- ((p,_):_) | p < n -> Composite (Factors n p (n `quot` p))- | otherwise -> Prime (Trivial n)- _ -> error "Impossible"- | n < billi = let r2 = integerSquareRoot' n + 2 in- case trialDivisionTo r2 n of- ((p,_):_) | p < n -> Composite (Factors n p (n `quot` p))- | otherwise -> Prime (TrialDivision n r2)- _ -> error "Impossible"- | otherwise = case smallFactors n of- ([], Just _) | not (isStrongFermatPP n 2) -> Composite (StrongFermat n 2)- | not (lucasTest n) -> Composite (LucasSelfridge n)- | otherwise -> Prime (certifyBPSW n) -- if it isn't we error and ask for a report.- ((p,_):_, _) | p == n -> Prime (TrialDivision n (min 100000 n))- | otherwise -> Composite (Factors n p (n `quot` p))- _ -> error ("***Error factorising " ++ show n ++ "! Please report this to maintainer of arithmoi.")- where- billi = 1000000000000---- | Certify a number known to be not too small, having no small prime divisors and having--- passed the Baillie PSW test. So we assume it's prime, erroring if not.--- Since it's presumably a large number, we don't bother with trial division and--- construct a Pocklington certificate.-certifyBPSW :: Integer -> PrimalityProof-certifyBPSW n = Pocklington n a b kfcts- where- nm1 = n-1- h = nm1 `quot` 2- m3 = fromInteger n .&. (3 :: Int) == 3- (a,pp,b) = findDecomposition nm1- kfcts0 = map check pp- kfcts = foldl' force [] kfcts0- force xs t@(_,_,_,prf) = prf `seq` (t:xs)- check (p,e,byTD) = go 2- where- go bs- | bs > h = error (bpswMessage n)- | x == 1 = if m3 && (p == 2) then (p,e,n-bs,Trivial 2) else go (bs+1)- | g /= 1 = error (bpswMessage n ++ found g)- | y /= 1 = error (bpswMessage n ++ fermat bs)- | byTD = (p,e,bs, smallCert p)- | otherwise = case certify p of- Composite cpr -> error ("***Error in factorisation code: " ++ show p- ++ " was supposed to be prime but isn't.\n"- ++ "Please report this to the maintainer.\n\n"- ++ show cpr)- Prime ppr ->(p,e,bs,ppr)- where- q = nm1 `quot` p- x = powModInteger bs q n- y = powModInteger x p n- g = gcd n (x-1)---- | Find a decomposition of p-1 for the pocklington certificate.--- Usually bloody slow if p-1 has two (or more) /large/ prime divisors.-findDecomposition :: Integer -> (Integer, [(Integer, Word, Bool)], Integer)-findDecomposition n = go 1 n [] prms- where- sr = integerSquareRoot' n- pbd = min 1000000 (sr+20)- prms = map unPrime $ primeList (primeSieve $ pbd)- go a b afs (p:ps)- | a > b = (a,afs,b)- | otherwise = case splitOff p b of- (0,_) -> go a b afs ps- (e,q) -> go (a*p^e) q ((p,e,True):afs) ps- go a b afs []- | a > b = (a,afs,b)- | bailliePSW b = (b,[(b,1,False)],a) -- Until a Baillie PSW pseudoprime is found, I'm going with this- | e == 0 = error ("Error in factorisation, " ++ show p ++ " was found as a factor of " ++ show b ++ " but isn't.")- | otherwise = go (a*p^e) q ((p,e,False):afs) []- where- p = findFactor b 8 6- (e,q) = splitOff p b---- | Find a factor of a known composite with approximately digits digits,--- starting with curve s. Actually, this may loop infinitely, but the--- loop should not be entered before the heat death of the universe.-findFactor :: Integer -> Int -> Integer -> Integer-findFactor n digits s = case findLoop n lo hi count s of- Left t -> findFactor n (digits+5) t- Right f -> f- where- (lo,hi,count) = findParms digits---- | Find a factor or say with which curve to continue.-findLoop :: Integer -> Word -> Word -> Word -> Integer -> Either Integer Integer-findLoop _ _ _ 0 s = Left s-findLoop n lo hi ct s- | n <= s+2 = Left 6- | otherwise = case s `modulo` fromInteger n of- InfMod{} -> error "impossible case"- SomeMod sn -> case montgomeryFactorisation lo hi sn of- Nothing -> findLoop n lo hi (ct-1) (s+1)- Just fct- | bailliePSW fct -> Right fct- | otherwise -> Right (findFactor fct 8 (s+1))---- | Message in the unlikely case a Baillie PSW pseudoprime is found.-bpswMessage :: Integer -> String-bpswMessage n = unlines- [ "\n***Congratulations! You found a Baillie PSW pseudoprime!"- , "Please report this finding to the package maintainer,"- , "<daniel.is.fischer@googlemail.com>"- , "The number in question is:\n"- , show n- , "\nOther parties like wikipedia might also be interested."- , "\nSorry for aborting your programme, but this is a major discovery."- ]---- | Found a factor-found :: Integer -> String-found g = "\nA nontrivial divisor is:\n" ++ show g---- | Fermat failure-fermat :: Integer -> String-fermat b = "\nThe Fermat test fails for base\n" ++ show b
Math/NumberTheory/Primes/Testing/Certified.hs view
@@ -5,11 +5,29 @@ -- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com> -- -- Deterministic primality testing.-module Math.NumberTheory.Primes.Testing.Certified (isCertifiedPrime) where -import Math.NumberTheory.Primes.Testing.Probabilistic-import Math.NumberTheory.Primes.Testing.Certificates.Internal+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-} +module Math.NumberTheory.Primes.Testing.Certified+ ( isCertifiedPrime+ ) where++import Data.List (foldl')+import Data.Bits ((.&.))+import Data.Mod+import Data.Proxy+import GHC.Integer.GMP.Internals (powModInteger)+import GHC.TypeNats (SomeNat(..), someNatVal)++import Math.NumberTheory.Roots (integerSquareRoot)+import Math.NumberTheory.Primes (unPrime)+import Math.NumberTheory.Primes.Factorisation.TrialDivision (trialDivisionPrimeTo, trialDivisionTo, trialDivisionWith)+import Math.NumberTheory.Primes.Factorisation.Montgomery (montgomeryFactorisation, smallFactors, findParms)+import Math.NumberTheory.Primes.Testing.Probabilistic (bailliePSW, isPrime, isStrongFermatPP, lucasTest)+import Math.NumberTheory.Primes.Sieve.Eratosthenes (primeList, primeSieve)+import Math.NumberTheory.Utils (splitOff)+ -- | @'isCertifiedPrime' n@ tests primality of @n@, first trial division -- by small primes is performed, then a Baillie PSW test and finally a -- prime certificate is constructed and verified, provided no step before@@ -24,3 +42,173 @@ -- Although it is known that there are no Baillie PSW pseudoprimes below 2^64, -- use the verified bound 10^17, I don't know whether Gilchrist's result has been -- verified yet.++-- | A proof of primality of a positive number. The type is+-- abstract to ensure the validity of proofs.+data PrimalityProof+ = Pocklington { cprime :: !Integer -- ^ The number whose primality is proved.+ , _factorisedPart, _cofactor :: !Integer+ , _knownFactors :: ![(Integer, Word, Integer, PrimalityProof)]+ }+ | TrialDivision { cprime :: !Integer -- ^ The number whose primality is proved.+ , _tdLimit :: !Integer }+ | Trivial { cprime :: !Integer -- ^ The number whose primality is proved.+ }+ deriving Show++-- | Check the validity of a 'PrimalityProof'. Since it should be+-- impossible to create invalid proofs by the public interface, this+-- should never return 'False'.+checkPrimalityProof :: PrimalityProof -> Bool+checkPrimalityProof (Trivial n) = isTrivialPrime n+checkPrimalityProof (TrialDivision p b) = p <= b*b && trialDivisionPrimeTo b p+checkPrimalityProof (Pocklington p a b fcts) = b > 0 && a > b && a*b == pm1 && a == ppProd fcts && all verify fcts+ where+ pm1 = p-1+ ppProd pps = product [pf^e | (pf,e,_,_) <- pps]+ verify (pf,_,base,proof) = pf == cprime proof && crit pf base && checkPrimalityProof proof+ crit pf base = gcd p (x-1) == 1 && y == 1+ where+ x = powModInteger base (pm1 `quot` pf) p+ y = powModInteger x pf p++-- | @'isTrivialPrime'@ checks whether its argument is a trivially+-- known prime.+isTrivialPrime :: Integer -> Bool+isTrivialPrime n = n `elem` trivialPrimes++-- | List of trivially known primes.+trivialPrimes :: [Integer]+trivialPrimes = [2,3,5,7,11,13,17,19,23,29]++-- | Certify a small number. This is not exposed and should only+-- be used where correct. It is always checked after use, though,+-- so it shouldn't be able to lie.+smallCert :: Integer -> PrimalityProof+smallCert n+ | n < 30 = Trivial n+ | otherwise = TrialDivision n (integerSquareRoot n + 1)++-- | @'certify' n@ constructs, for @n > 1@, a proof of either+-- primality or compositeness of @n@. This may take a very long+-- time if the number has no small(ish) prime divisors+certify :: Integer -> Maybe PrimalityProof+certify n+ | n < 2 = error "Only numbers larger than 1 can be certified"+ | n < 31 = case trialDivisionWith trivialPrimes n of+ ((p,_):_) | p < n -> Nothing+ | otherwise -> Just (Trivial n)+ _ -> error "Impossible"+ | n < billi = let r2 = integerSquareRoot n + 2 in+ case trialDivisionTo r2 n of+ ((p,_):_) | p < n -> Nothing+ | otherwise -> Just (TrialDivision n r2)+ _ -> error "Impossible"+ | otherwise = case smallFactors (fromInteger (abs n)) of+ ([], Just _) | not (isStrongFermatPP n 2) -> Nothing+ | not (lucasTest n) -> Nothing+ | otherwise -> Just (certifyBPSW n) -- if it isn't we error and ask for a report.+ ((toInteger -> p,_):_, _)+ | p == n -> Just (TrialDivision n (min 100000 n))+ | otherwise -> Nothing+ _ -> error ("***Error factorising " ++ show n ++ "! Please report this to maintainer of arithmoi.")+ where+ billi = 1000000000000++-- | Certify a number known to be not too small, having no small prime divisors and having+-- passed the Baillie PSW test. So we assume it's prime, erroring if not.+-- Since it's presumably a large number, we don't bother with trial division and+-- construct a Pocklington certificate.+certifyBPSW :: Integer -> PrimalityProof+certifyBPSW n = Pocklington n a b kfcts+ where+ nm1 = n-1+ h = nm1 `quot` 2+ m3 = fromInteger n .&. (3 :: Int) == 3+ (a,pp,b) = findDecomposition nm1+ kfcts0 = map check pp+ kfcts = foldl' force [] kfcts0+ force xs t@(_,_,_,prf) = prf `seq` (t:xs)+ check (p,e,byTD) = go 2+ where+ go bs+ | bs > h = error (bpswMessage n)+ | x == 1 = if m3 && (p == 2) then (p,e,n-bs,Trivial 2) else go (bs+1)+ | g /= 1 = error (bpswMessage n ++ found g)+ | y /= 1 = error (bpswMessage n ++ fermat bs)+ | byTD = (p,e,bs, smallCert p)+ | otherwise = case certify p of+ Nothing -> error ("***Error in factorisation code: " ++ show p+ ++ " was supposed to be prime but isn't.\n"+ ++ "Please report this to the maintainer.\n\n")+ Just ppr ->(p,e,bs,ppr)+ where+ q = nm1 `quot` p+ x = powModInteger bs q n+ y = powModInteger x p n+ g = gcd n (x-1)++-- | Find a decomposition of p-1 for the pocklington certificate.+-- Usually bloody slow if p-1 has two (or more) /large/ prime divisors.+findDecomposition :: Integer -> (Integer, [(Integer, Word, Bool)], Integer)+findDecomposition n = go 1 n [] prms+ where+ sr = integerSquareRoot n+ pbd = min 1000000 (sr+20)+ prms = map unPrime $ primeList (primeSieve $ pbd)+ go a b afs (p:ps)+ | a > b = (a,afs,b)+ | otherwise = case splitOff p b of+ (0,_) -> go a b afs ps+ (e,q) -> go (a*p^e) q ((p,e,True):afs) ps+ go a b afs []+ | a > b = (a,afs,b)+ | bailliePSW b = (b,[(b,1,False)],a) -- Until a Baillie PSW pseudoprime is found, I'm going with this+ | e == 0 = error ("Error in factorisation, " ++ show p ++ " was found as a factor of " ++ show b ++ " but isn't.")+ | otherwise = go (a*p^e) q ((p,e,False):afs) []+ where+ p = findFactor b 8 6+ (e,q) = splitOff p b++-- | Find a factor of a known composite with approximately digits digits,+-- starting with curve s. Actually, this may loop infinitely, but the+-- loop should not be entered before the heat death of the universe.+findFactor :: Integer -> Int -> Integer -> Integer+findFactor n digits s = case findLoop n lo hi count s of+ Left t -> findFactor n (digits+5) t+ Right f -> f+ where+ (lo,hi,count) = findParms digits++-- | Find a factor or say with which curve to continue.+findLoop :: Integer -> Word -> Word -> Word -> Integer -> Either Integer Integer+findLoop _ _ _ 0 s = Left s+findLoop n lo hi ct s+ | n <= s+2 = Left 6+ | otherwise = case someNatVal (fromInteger n) of+ SomeNat (_ :: Proxy t) -> case montgomeryFactorisation lo hi (fromInteger s :: Mod t) of+ Nothing -> findLoop n lo hi (ct-1) (s+1)+ Just fct+ | bailliePSW fct -> Right fct+ | otherwise -> Right (findFactor fct 8 (s+1))++-- | Message in the unlikely case a Baillie PSW pseudoprime is found.+bpswMessage :: Integer -> String+bpswMessage n = unlines+ [ "\n***Congratulations! You found a Baillie PSW pseudoprime!"+ , "Please report this finding to the maintainers:"+ , "<daniel.is.fischer@googlemail.com>,"+ , "<andrew.lelechenko@gmail.com>"+ , "The number in question is:\n"+ , show n+ , "\nOther parties like wikipedia might also be interested."+ , "\nSorry for aborting your programm, but this is a major discovery."+ ]++-- | Found a factor+found :: Integer -> String+found g = "\nA nontrivial divisor is:\n" ++ show g++-- | Fermat failure+fermat :: Integer -> String+fermat b = "\nThe Fermat test fails for base\n" ++ show b
Math/NumberTheory/Primes/Testing/Probabilistic.hs view
@@ -5,8 +5,12 @@ -- Maintainer: Daniel Fischer <daniel.is.fischer@googlemail.com> -- -- Probabilistic primality tests, Miller-Rabin and Baillie-PSW.-{-# LANGUAGE CPP, MagicHash, BangPatterns #-}-{-# OPTIONS_HADDOCK hide #-}++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+ module Math.NumberTheory.Primes.Testing.Probabilistic ( isPrime , millerRabinV@@ -19,14 +23,15 @@ #include "MachDeps.h" import Data.Bits+import Data.Mod+import Data.Proxy import GHC.Base import GHC.Integer.GMP.Internals-import GHC.TypeNats.Compat+import GHC.TypeNats (KnownNat, SomeNat(..), someNatVal) -import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Moduli.Jacobi+import Math.NumberTheory.Moduli.JacobiSymbol import Math.NumberTheory.Utils-import Math.NumberTheory.Powers.Squares+import Math.NumberTheory.Roots -- | @isPrime n@ tests whether @n@ is a prime (negative or positive). -- It is a combination of trial division and Baillie-PSW test.@@ -83,15 +88,14 @@ | n < 0 = error "isStrongFermatPP: negative argument" | n <= 1 = False | n == 2 = True- | otherwise = case b `modulo` fromInteger n of- SomeMod b' -> isStrongFermatPPMod b'- InfMod{} -> True+ | otherwise = case someNatVal (fromInteger n) of+ SomeNat (_ :: Proxy t) -> isStrongFermatPPMod (fromInteger b :: Mod t) isStrongFermatPPMod :: KnownNat n => Mod n -> Bool isStrongFermatPPMod b = b == 0 || a == 1 || go t a where m = -1- (t, u) = shiftToOddCount $ getVal m+ (t, u) = shiftToOddCount $ unMod m a = b ^% u go 0 _ = False@@ -114,9 +118,8 @@ -- of prime bases is reasonable to find out whether it's worth the -- effort to undertake the prime factorisation). isFermatPP :: Integer -> Integer -> Bool-isFermatPP n b = case b `modulo` fromInteger n of- SomeMod b' -> b' ^% (n-1) == 1- InfMod{} -> True+isFermatPP n b = case someNatVal (fromInteger n) of+ SomeNat (_ :: Proxy t) -> (fromInteger b :: Mod t) ^% (n-1) == 1 -- | Primality test after Baillie, Pomerance, Selfridge and Wagstaff. -- The Baillie-PSW test consists of a strong Fermat probable primality@@ -147,12 +150,10 @@ -- the Fermat test. For package-internal use only. lucasTest :: Integer -> Bool lucasTest n- | square || d == 0 = False- | d == 1 = True- | otherwise = uo == 0 || go t vo qo+ | isSquare n || d == 0 = False+ | d == 1 = True+ | otherwise = uo == 0 || go t vo qo where- square = isPossibleSquare2 n && r*r == n- r = integerSquareRoot n d = find True 5 find !pos cd = case jacobi (n `rem` cd) cd of MinusOne -> if pos then cd else (-cd)
Math/NumberTheory/Quadratic/EisensteinIntegers.hs view
@@ -26,15 +26,16 @@ , primes ) where +import Prelude hiding (quot, quotRem, gcd) import Control.DeepSeq import Data.Coerce+import Data.Euclidean import Data.List (mapAccumL, partition) import Data.Maybe import Data.Ord (comparing) import qualified Data.Semiring as S import GHC.Generics (Generic) -import qualified Math.NumberTheory.Euclidean as ED import Math.NumberTheory.Moduli.Sqrt import Math.NumberTheory.Primes.Types import qualified Math.NumberTheory.Primes as U@@ -105,9 +106,9 @@ associates :: EisensteinInteger -> [EisensteinInteger] associates e = map (e *) ids -instance ED.GcdDomain EisensteinInteger+instance GcdDomain EisensteinInteger -instance ED.Euclidean EisensteinInteger where+instance Euclidean EisensteinInteger where degree = fromInteger . norm quotRem = divHelper @@ -164,35 +165,16 @@ (q2, r2) = divMod (a + b) 3 -- | Find an Eisenstein integer whose norm is the given prime number--- in the form @3k + 1@ using a modification of the--- <http://www.ams.org/journals/mcom/1972-26-120/S0025-5718-1972-0314745-6/S0025-5718-1972-0314745-6.pdf Hermite-Serret algorithm>.------ The maintainer <https://github.com/cartazio/arithmoi/pull/121#issuecomment-415010647 Andrew Lelechenko>--- derived the following:------ * Each prime of the form @3n + 1@ is actually of the form @6k + 1@.--- * One has @(z + 3k)^2 ≡ z^2 + 6kz + 9k^2 ≡ z^2 + (6k + 1)z - z + 9k^2 ≡ z^2 - z + 9k^2 (mod 6k + 1)@.------ The goal is to solve @z^2 - z + 1 ≡ 0 (mod 6k + 1)@. One has:------ 1. @z^2 - z + 1 ≡ 0 (mod 6k + 1)@--- 2. @z^2 - z ≡ -1 (mod 6k + 1)@--- 3. @z^2 - z + 9k^2 ≡ 9k^2 - 1 (mod 6k + 1)@--- 4. @(z + 3k)^2 ≡ 9k^2 - 1 (mod 6k + 1)@--- 5. @z + 3k = sqrtsModPrime(9k^2 - 1) (mod 6k + 1)@--- 6. @z = (sqrtsModPrime(9k^2 - 1) (mod 6k + 1)) - 3k@------ For example, let @p = 7@, then @k = 1@.--- Square root of @9*1^2-1 ≡ 1 (mod 7)@, and @z = 1 - 3*1 = -2 ≡ 5 (mod 7)@.+-- in the form @3k + 1@. ----- Truly, @norm (5 :+ 1) = 25 - 5 + 1 = 21 ≡ 0 (mod 7)@.+-- >>> findPrime (nextPrime 7)+-- Prime 3+2*ω findPrime :: Prime Integer -> U.Prime EisensteinInteger-findPrime p = case sqrtsModPrime (9*k*k - 1) p of- [] -> error "findPrime: argument must be prime p = 6k + 1"- z : _ -> Prime $ abs $ ED.gcd (unPrime p :+ 0) ((z - 3 * k) :+ 1)- where- k :: Integer- k = unPrime p `div` 6+findPrime p = case (r, sqrtsModPrime (9 * q * q - 1) p) of+ (1, z : _) -> Prime $ abs $ gcd (unPrime p :+ 0) ((z - 3 * q) :+ 1)+ _ -> error "findPrime: argument must be prime p = 6k + 1"+ where+ (q, r) = unPrime p `quotRem` 6 -- | An infinite list of Eisenstein primes. Uses primes in @Z@ to exhaustively -- generate all Eisenstein primes in order of ascending norm.@@ -200,6 +182,9 @@ -- * Every prime is in the first sextant, so the list contains no associates. -- * Eisenstein primes from the whole complex plane can be generated by -- applying 'associates' to each prime in this list.+--+-- >>> take 10 primes+-- [Prime 2+ω,Prime 2,Prime 3+2*ω,Prime 3+ω,Prime 4+3*ω,Prime 4+ω,Prime 5+3*ω,Prime 5+2*ω,Prime 5,Prime 6+5*ω] primes :: [Prime EisensteinInteger] primes = coerce $ (2 :+ 1) : mergeBy (comparing norm) l r where@@ -302,8 +287,7 @@ where (d1, z') = go1 c 0 z d2 = c - d1- z'' = head $ drop (wordToInt d2)- $ iterate (\g -> fromMaybe err $ (g * unPrime p) `quotEvenI` np) z'+ z'' = iterate (\g -> fromMaybe err $ (g * unPrime p) `quotEvenI` np) z' !! max 0 (wordToInt d2) go1 :: Word -> Word -> EisensteinInteger -> (Word, EisensteinInteger) go1 0 d z = (d, z)
Math/NumberTheory/Quadratic/GaussianIntegers.hs view
@@ -21,17 +21,18 @@ findPrime, ) where +import Prelude hiding (quot, quotRem) import Control.DeepSeq (NFData) import Data.Coerce+import Data.Euclidean import Data.List (mapAccumL, partition) import Data.Maybe import Data.Ord (comparing) import qualified Data.Semiring as S import GHC.Generics -import qualified Math.NumberTheory.Euclidean as ED import Math.NumberTheory.Moduli.Sqrt-import Math.NumberTheory.Powers (integerSquareRoot)+import Math.NumberTheory.Roots (integerSquareRoot) import Math.NumberTheory.Primes.Types import qualified Math.NumberTheory.Primes as U import Math.NumberTheory.Utils (mergeBy)@@ -86,9 +87,9 @@ | a < 0 && b <= 0 = ((-a) :+ (-b), -1) -- third quadrant: (-inf, 0) x (-inf, 0]i | otherwise = ((-b) :+ a, -ι) -- fourth quadrant: [0, inf) x (-inf, 0)i -instance ED.GcdDomain GaussianInteger+instance GcdDomain GaussianInteger -instance ED.Euclidean GaussianInteger where+instance Euclidean GaussianInteger where degree = fromInteger . norm quotRem = divHelper @@ -121,6 +122,9 @@ -- |An infinite list of the Gaussian primes. Uses primes in Z to exhaustively -- generate all Gaussian primes (up to associates), in order of ascending -- magnitude.+--+-- >>> take 10 primes+-- [Prime 1+ι,Prime 2+ι,Prime 1+2*ι,Prime 3,Prime 3+2*ι,Prime 2+3*ι,Prime 4+ι,Prime 1+4*ι,Prime 5+2*ι,Prime 2+5*ι] primes :: [U.Prime GaussianInteger] primes = coerce $ (1 :+ 1) : mergeBy (comparing norm) l r where@@ -133,6 +137,9 @@ -- |Find a Gaussian integer whose norm is the given prime number -- of form 4k + 1 using -- <http://www.ams.org/journals/mcom/1972-26-120/S0025-5718-1972-0314745-6/S0025-5718-1972-0314745-6.pdf Hermite-Serret algorithm>.+--+-- >>> findPrime (nextPrime 5)+-- Prime 2+ι findPrime :: Prime Integer -> U.Prime GaussianInteger findPrime p = case sqrtsModPrime (-1) p of [] -> error "findPrime: an argument must be prime p = 4k + 1"
Math/NumberTheory/Recurrences/Bilinear.hs view
@@ -30,11 +30,18 @@ -- 1 -- (0.01 secs, 391,152 bytes) +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ScopedTypeVariables #-} module Math.NumberTheory.Recurrences.Bilinear- ( binomial+ ( -- * Pascal triangle+ binomial+ , binomialRotated+ , binomialLine+ , binomialDiagonal+ , binomialFactors+ -- * Other recurrences , stirling1 , stirling2 , lah@@ -46,32 +53,103 @@ , faulhaberPoly ) where -import Data.List+import Data.Euclidean (GcdDomain(..))+import Data.List (scanl', zipWith4)+import Data.Maybe import Data.Ratio+import Data.Semiring (Semiring(..)) import Numeric.Natural import Math.NumberTheory.Recurrences.Linear (factorial)+import Math.NumberTheory.Primes --- | Infinite zero-based table of binomial coefficients (also known as Pascal triangle):--- @binomial !! n !! k == n! \/ k! \/ (n - k)!@.+-- | Infinite zero-based table of binomial coefficients (also known as Pascal triangle). ----- >>> take 5 (map (take 5) binomial)--- [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]+-- prop> binomial !! n !! k == n! / k! / (n - k)! ----- Complexity: @binomial !! n !! k@ is O(n) bits long, its computation--- takes O(k n) time and forces thunks @binomial !! n !! i@ for @0 <= i <= k@.--- Use the symmetry of Pascal triangle @binomial !! n !! k == binomial !! n !! (n - k)@ to speed up computations.+-- Note that 'binomial' !! n !! k is asymptotically slower+-- than 'binomialLine' n !! k,+-- but imposes only 'Semiring' constraint. ----- One could also consider 'Math.Combinat.Numbers.binomial' to compute stand-alone values.-binomial :: Integral a => [[a]]-binomial = map f [0..]- where- f n = scanl (\x k -> x * (n - k + 1) `div` k) 1 [1..n]+-- >>> take 6 binomial :: [[Int]]+-- [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1]]+binomial :: Semiring a => [[a]]+binomial = iterate (\l -> zipWith plus (l ++ [zero]) (zero : l)) [one] {-# SPECIALIZE binomial :: [[Int]] #-} {-# SPECIALIZE binomial :: [[Word]] #-} {-# SPECIALIZE binomial :: [[Integer]] #-} {-# SPECIALIZE binomial :: [[Natural]] #-} +-- | Pascal triangle, rotated by 45 degrees.+--+-- prop> binomialRotated !! n !! k == (n + k)! / n! / k! == binomial !! (n + k) !! k+--+-- Note that 'binomialRotated' !! n !! k is asymptotically slower+-- than 'binomialDiagonal' n !! k,+-- but imposes only 'Semiring' constraint.+--+-- >>> take 6 (map (take 6) binomialRotated) :: [[Int]]+-- [[1,1,1,1,1,1],[1,2,3,4,5,6],[1,3,6,10,15,21],[1,4,10,20,35,56],[1,5,15,35,70,126],[1,6,21,56,126,252]]+binomialRotated :: Semiring a => [[a]]+binomialRotated = iterate (tail . scanl' plus zero) (repeat one)+{-# SPECIALIZE binomialRotated :: [[Int]] #-}+{-# SPECIALIZE binomialRotated :: [[Word]] #-}+{-# SPECIALIZE binomialRotated :: [[Integer]] #-}+{-# SPECIALIZE binomialRotated :: [[Natural]] #-}++-- | The n-th (zero-based) line of 'binomial'+-- (and the n-th diagonal of 'binomialRotated').+--+-- >>> binomialLine 5+-- [1,5,10,10,5,1]+binomialLine :: (Enum a, GcdDomain a) => a -> [a]+binomialLine n = scanl'+ (\x (k, nk1) -> fromJust $ (x `times` nk1) `divide` k)+ one+ (zip [one..n] [n, pred n..one])+{-# SPECIALIZE binomialLine :: Int -> [Int] #-}+{-# SPECIALIZE binomialLine :: Word -> [Word] #-}+{-# SPECIALIZE binomialLine :: Integer -> [Integer] #-}+{-# SPECIALIZE binomialLine :: Natural -> [Natural] #-}++-- | The n-th (zero-based) diagonal of 'binomial'+-- (and the n-th line of 'binomialRotated').+--+-- >>> take 6 (binomialDiagonal 5)+-- [1,6,21,56,126,252]+binomialDiagonal :: (Enum a, GcdDomain a) => a -> [a]+binomialDiagonal n = scanl'+ (\x k -> fromJust $ (x `times` (n `plus` k) `divide` k))+ one+ [one..]+{-# SPECIALIZE binomialDiagonal :: Int -> [Int] #-}+{-# SPECIALIZE binomialDiagonal :: Word -> [Word] #-}+{-# SPECIALIZE binomialDiagonal :: Integer -> [Integer] #-}+{-# SPECIALIZE binomialDiagonal :: Natural -> [Natural] #-}++-- | Prime factors of a binomial coefficient.+--+-- prop> binomialFactors n k == factorise (binomial !! n !! k)+--+-- >>> binomialFactors 10 4+-- [(Prime 2,1),(Prime 3,1),(Prime 5,1),(Prime 7,1)]+binomialFactors :: Word -> Word -> [(Prime Word, Word)]+binomialFactors n k+ | n < 2+ = []+ | otherwise+ = filter ((/= 0) . snd)+ $ map (\p -> (p, mult (unPrime p) n - mult (unPrime p) (n - k) - mult (unPrime p) k))+ $ [minBound .. precPrime n]+ where+ mult :: Word -> Word -> Word+ mult p m = go mp mp+ where+ mp = m `quot` p+ go !acc !x+ | x >= p = let xp = x `quot` p in go (acc + xp) xp+ | otherwise = acc+ -- | Infinite zero-based table of <https://en.wikipedia.org/wiki/Stirling_numbers_of_the_first_kind Stirling numbers of the first kind>. -- -- >>> take 5 (map (take 5) stirling1)@@ -182,7 +260,7 @@ -- 959924142434241924250 -- >>> sum $ zipWith (*) (faulhaberPoly 10) (iterate (* 100) 1) -- 959924142434241924250 % 1-faulhaberPoly :: Integral a => Int -> [Ratio a]+faulhaberPoly :: (GcdDomain a, Integral a) => Int -> [Ratio a] -- Implementation by https://github.com/CarlEdman faulhaberPoly p = zipWith (*) ((0:)@@ -190,7 +268,7 @@ $ take (p+1) $ bernoulli) $ map (% (fromIntegral p+1)) $ zipWith (*) (iterate negate (if odd p then 1 else -1))- $ binomial !! (fromIntegral p+1)+ $ binomial !! (p+1) -- | Infinite zero-based list of <https://en.wikipedia.org/wiki/Euler_number Euler numbers>. -- The algorithm used was derived from <http://www.emis.ams.org/journals/JIS/VOL4/CHEN/AlgBE2.pdf Algorithms for Bernoulli numbers and Euler numbers>
Math/NumberTheory/Recurrences/Linear.hs view
@@ -6,9 +6,12 @@ -- -- Efficient calculation of linear recurrent sequences, including Fibonacci and Lucas sequences. -{-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+ module Math.NumberTheory.Recurrences.Linear ( factorial+ , factorialFactors , fibonacci , fibonacciPair , lucas@@ -20,6 +23,7 @@ import Data.Bits import Numeric.Natural+import Math.NumberTheory.Primes -- | Infinite zero-based table of factorials. --@@ -34,6 +38,27 @@ {-# SPECIALIZE factorial :: [Word] #-} {-# SPECIALIZE factorial :: [Integer] #-} {-# SPECIALIZE factorial :: [Natural] #-}++-- | Prime factors of a factorial.+--+-- prop> factorialFactors n == factorise (factorial !! n)+--+-- >>> factorialFactors 10+-- [(Prime 2,8),(Prime 3,4),(Prime 5,2),(Prime 7,1)]+factorialFactors :: Word -> [(Prime Word, Word)]+factorialFactors n+ | n < 2+ = []+ | otherwise+ = map (\p -> (p, mult (unPrime p))) [minBound .. precPrime n]+ where+ mult :: Word -> Word+ mult p = go np np+ where+ np = n `quot` p+ go !acc !x+ | x >= p = let xp = x `quot` p in go (acc + xp) xp+ | otherwise = acc -- | @'fibonacci' k@ calculates the @k@-th Fibonacci number in -- /O/(@log (abs k)@) steps. The index may be negative. This
Math/NumberTheory/Recurrences/Pentagonal.hs view
@@ -7,17 +7,15 @@ -- Values of <https://en.wikipedia.org/wiki/Partition_(number_theory)#Partition_function partition function>. -- -{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-} module Math.NumberTheory.Recurrences.Pentagonal ( partition- , pentagonalSigns- , pents ) where -import qualified Data.IntMap as IM-import Numeric.Natural (Natural)+import qualified Data.Chimera as Ch+import Data.Vector (Vector)+import Numeric.Natural (Natural) -- | Infinite list of generalized pentagonal numbers. -- Example:@@ -50,11 +48,11 @@ -- [Implementation notes for partition function] -- -- @p(n) = p(n-1) + p(n-2) - p(n-5) - p(n-7) + p(n-11) + ...@, where @p(0) = 1@--- and @p(k) = 0@ for a negative integer @k@. Uses a @Map@ from the--- @containers@ package to memoize previous results.+-- and @p(k) = 0@ for a negative integer @k@. Uses a @Chimera@ from the+-- @chimera@ package to memoize previous results. -- -- Example: calculating @partition !! 10@, assuming the memoization map is--- filled and called @dict :: Integral a => Map a a@.+-- filled and called @dict@. -- -- * @tail [0, 1, 2, 5, 7, 12 ,15, 22, 26, 35, ..] == [1, 2, 5, 7, 12 ,15, 22, 26, 35, 40, ..]@. -- * @takeWhile (\m -> 10 - m >= 0) [1, 2, 5, 7, 12 ,15, 22, 26, 35, 40, ..] == [1, 2, 5, 7]@.@@ -68,27 +66,21 @@ -- 2. Calculating @partition !! k@, where @k@ is any index equal or higher -- than @maxBound :: Int@ results in undefined behavior. +partitionF :: Num a => (Word -> a) -> Word -> a+partitionF _ 0 = 1+partitionF f n = sum $ pentagonalSigns $ map (f . (n -)) $ takeWhile (<= n) $ tail pents+ -- | Infinite zero-based table of <https://oeis.org/A000041 partition numbers>. -- -- >>> take 10 partition -- [1,1,2,3,5,7,11,15,22,30] -- -- >>> :set -XDataKinds--- >>> import Math.NumberTheory.Moduli.Class+-- >>> import Data.Mod -- >>> partition !! 1000 :: Mod 1000 -- (991 `modulo` 1000) partition :: Num a => [a]-partition = 1 : go (IM.singleton 0 1) 1- where- go :: Num a => IM.IntMap a -> Int -> [a]- go dict !n =- let n' = (sum .- pentagonalSigns .- map (\m -> dict IM.! (n - m)) .- takeWhile (\m -> n >= m) .- tail) (pents :: [Int])- dict' = IM.insert n n' dict- in n' : go dict' (n + 1)+partition = Ch.toList $ Ch.tabulateFix @Vector partitionF {-# SPECIALIZE partition :: [Int] #-} {-# SPECIALIZE partition :: [Word] #-} {-# SPECIALIZE partition :: [Integer] #-}
+ Math/NumberTheory/RootsOfUnity.hs view
@@ -0,0 +1,69 @@+-- |+-- Module: Math.NumberTheory.RootsOfUnity+-- Copyright: (c) 2018 Bhavik Mehta+-- Licence: MIT+-- Maintainer: Bhavik Mehta <bhavikmehta8@gmail.com>+--+-- Implementation of roots of unity+--+++module Math.NumberTheory.RootsOfUnity+( +-- * Roots of unity+ RootOfUnity (..)+-- ** Conversions+ , toRootOfUnity+ , toComplex )++where++import Data.Complex (Complex(..), cis)+import Data.Semigroup (Semigroup(..))+import Data.Ratio ((%), numerator, denominator)++-- | A representation of <https://en.wikipedia.org/wiki/Root_of_unity roots of unity>: complex+-- numbers \(z\) for which there is \(n\) such that \(z^n=1\).+newtype RootOfUnity =+ RootOfUnity { -- | Every root of unity can be expressed as \(e^{2 \pi i q}\) for some+ -- rational \(q\) satisfying \(0 \leq q < 1\), this function extracts it.+ fromRootOfUnity :: Rational }+ deriving (Eq)++instance Show RootOfUnity where+ show (RootOfUnity q)+ | n == 0 = "1"+ | d == 1 = "-1"+ | n == 1 = "e^(πi/" ++ show d ++ ")"+ | otherwise = "e^(" ++ show n ++ "πi/" ++ show d ++ ")"+ where n = numerator (2*q)+ d = denominator (2*q)++-- | Given a rational \(q\), produce the root of unity \(e^{2 \pi i q}\).+toRootOfUnity :: Rational -> RootOfUnity+toRootOfUnity q = RootOfUnity ((n `rem` d) % d)+ where n = numerator q+ d = denominator q+ -- effectively q `mod` 1+ -- This smart constructor ensures that the rational is always in the range 0 <= q < 1.++-- | This Semigroup is in fact a group, so @'stimes'@ can be called with a negative first argument.+instance Semigroup RootOfUnity where+ RootOfUnity q1 <> RootOfUnity q2 = toRootOfUnity (q1 + q2)+ stimes k (RootOfUnity q) = toRootOfUnity (q * fromIntegral k)++instance Monoid RootOfUnity where+ mappend = (<>)+ mempty = RootOfUnity 0++-- | Convert a root of unity into an inexact complex number. Due to floating point inaccuracies,+-- it is recommended to avoid use of this until the end of a calculation. Alternatively, with+-- the [cyclotomic](http://hackage.haskell.org/package/cyclotomic-0.5.1) package, one can use+-- @[polarRat](https://hackage.haskell.org/package/cyclotomic-0.5.1/docs/Data-Complex-Cyclotomic.html#v:polarRat)+-- 1 . @'fromRootOfUnity' to convert to a cyclotomic number.+toComplex :: Floating a => RootOfUnity -> Complex a+toComplex (RootOfUnity t)+ | t == 1/2 = (-1) :+ 0+ | t == 1/4 = 0 :+ 1+ | t == 3/4 = 0 :+ (-1)+ | otherwise = cis . (2*pi*) . fromRational $ t
Math/NumberTheory/SmoothNumbers.hs view
@@ -1,11 +1,11 @@ -- | -- Module: Math.NumberTheory.SmoothNumbers--- Copyright: (c) 2018 Frederick Schneider+-- Copyright: (c) 2018 Frederick Schneider, 2018-2019 Andrew Lelechenko -- Licence: MIT -- Maintainer: Frederick Schneider <frederick.schneider2011@gmail.com> -- -- A <https://en.wikipedia.org/wiki/Smooth_number smooth number>--- is an integer, which can be represented as a product of powers of elements+-- is an number, which can be represented as a product of powers of elements -- from a given set (smooth basis). E. g., 48 = 3 * 4 * 4 is smooth -- over a set {3, 4}, and 24 is not. --@@ -15,176 +15,97 @@ {-# LANGUAGE TypeApplications #-} module Math.NumberTheory.SmoothNumbers- ( -- * Create a smooth basis- SmoothBasis- , fromSet+ ( SmoothBasis+ , unSmoothBasis , fromList- , fromSmoothUpperBound- -- * Generate smooth numbers+ , isSmooth , smoothOver , smoothOver'- , smoothOverInRange- , smoothOverInRangeBF-- -- * Verify if a number is smooth- , isSmooth ) where import Prelude hiding (div, mod, gcd)-import Data.Bits (Bits)-import Data.Coerce+import Data.Euclidean import Data.List (nub)-import Data.Semiring (isZero)-import qualified Data.Set as S--import qualified Math.NumberTheory.Euclidean as E-import Math.NumberTheory.Primes+import Data.Maybe+import Data.Semiring -- | An abstract representation of a smooth basis.--- It consists of a set of numbers ≥2.-newtype SmoothBasis a = SmoothBasis { unSmoothBasis :: [a] } deriving (Eq, Show)---- | Build a 'SmoothBasis' from a set of numbers ≥2.------ >>> import qualified Data.Set as Set--- >>> fromSet (Set.fromList [2, 3])--- Just (SmoothBasis {unSmoothBasis = [2,3]})--- >>> fromSet (Set.fromList [2, 4])--- Just (SmoothBasis {unSmoothBasis = [2,4]})--- >>> fromSet (Set.fromList [1, 3]) -- should be >= 2--- Nothing-fromSet :: (Eq a, E.GcdDomain a) => S.Set a -> Maybe (SmoothBasis a)-fromSet s = if isValid l then Just (SmoothBasis l) else Nothing where l = S.elems s-{-# DEPRECATED fromSet "Use 'fromList' instead " #-}+newtype SmoothBasis a = SmoothBasis+ { unSmoothBasis :: [a]+ -- ^ Unwrap elements of a smooth basis.+ }+ deriving (Show) --- | Build a 'SmoothBasis' from a list of numbers ≥2.+-- | Build a 'SmoothBasis' from a list of numbers,+-- sanitizing it from duplicates, zeros and units. -- -- >>> fromList [2, 3]--- Just (SmoothBasis {unSmoothBasis = [2,3]})+-- SmoothBasis {unSmoothBasis = [2,3]} -- >>> fromList [2, 2]--- Just (SmoothBasis {unSmoothBasis = [2]})--- >>> fromList [2, 4]--- Just (SmoothBasis {unSmoothBasis = [2,4]})--- >>> fromList [1, 3] -- should be >= 2--- Nothing-fromList :: (Eq a, E.GcdDomain a) => [a] -> Maybe (SmoothBasis a)-fromList l = if isValid l' then Just (SmoothBasis l') else Nothing- where- l' = nub l+-- SmoothBasis {unSmoothBasis = [2]}+-- >>> fromList [1, 3]+-- SmoothBasis {unSmoothBasis = [3]}+fromList :: (Eq a, GcdDomain a) => [a] -> SmoothBasis a+fromList+ = SmoothBasis+ . filter (\x -> not (isZero x) && isNothing (one `divide` x))+ . nub --- | Build a 'SmoothBasis' from a list of primes below given bound.+-- | A generalization of 'smoothOver',+-- suitable for non-'Integral' domains.+-- The first argument must be an appropriate+-- <https://en.wikipedia.org/wiki/Ideal_norm Ideal norm> function,+-- like 'Math.NumberTheory.Quadratic.GaussianIntegers.norm'+-- or 'Math.NumberTheory.Quadratic.EisensteinIntegers.norm'. ----- >>> fromSmoothUpperBound 10--- Just (SmoothBasis {unSmoothBasis = [2,3,5,7]})--- >>> fromSmoothUpperBound 1--- Nothing-fromSmoothUpperBound- :: (Integral a, Enum (Prime a), Bits a, UniqueFactorisation a)- => a- -> Maybe (SmoothBasis a)-fromSmoothUpperBound n- | n < 2 = Nothing- | otherwise = Just $ SmoothBasis $ map unPrime [nextPrime 2 .. precPrime n]-{-# DEPRECATED fromSmoothUpperBound "Use 'fromList' with an appropriate list of primes instead " #-}---- | Helper used by @smoothOver@ (@Integral@ constraint) and @smoothOver'@--- (@Euclidean@ constraint) Since the typeclass constraint is just--- @Num@, it receives a @norm@ comparison function for the generated smooth--- numbers.--- This function relies on the fact that for any element of a smooth basis @p@--- and any @a@ it is true that @norm (a * p) > norm a@.--- This condition is not checked.+-- This routine is more efficient than filtering with 'isSmooth'.+--+-- >>> import Math.NumberTheory.Quadratic.GaussianIntegers+-- >>> take 10 (smoothOver' norm (fromList [1+ι,3]))+-- [1,1+ι,2,2+2*ι,3,4,3+3*ι,4+4*ι,6,8] smoothOver'- :: forall a b. (Eq a, Num a, Ord b)- => (a -> b)+ :: (Eq a, Num a, Ord b)+ => (a -> b) -- ^ <https://en.wikipedia.org/wiki/Ideal_norm Ideal norm> -> SmoothBasis a -> [a]-smoothOver' norm pl =- foldr- (\p l -> mergeListLists $ iterate (map (* p)) l)- [1]- (nub $ unSmoothBasis pl)+smoothOver' norm (SmoothBasis pl) =+ foldr+ (\p l -> foldr skipHead [] $ iterate (map (abs . (Prelude.* p))) l)+ [1]+ pl where- {-# INLINE mergeListLists #-}- mergeListLists :: [[a]] -> [a]- mergeListLists = foldr go1 []- where- go1 :: [a] -> [a] -> [a]- go1 [] b = b- go1 (h:t) b = h:(go2 t b)+ skipHead [] b = b+ skipHead (h : t) b = h : merge t b - go2 :: [a] -> [a] -> [a]- go2 a [] = a- go2 [] b = b- go2 a@(ah:at) b@(bh:bt)- | norm bh < norm ah = bh : (go2 a bt)- | abs ah == abs bh = ah : (go2 at bt)- | otherwise = ah : (go2 at b)+ merge a [] = a+ merge [] b = b+ merge a@(ah : at) b@(bh : bt)+ | norm bh < norm ah = bh : merge a bt+ | ah == bh = ah : merge at bt+ | otherwise = ah : merge at b -- | Generate an infinite ascending list of -- <https://en.wikipedia.org/wiki/Smooth_number smooth numbers> -- over a given smooth basis. ----- >>> import Data.Maybe--- >>> take 10 (smoothOver (fromJust (fromList [2, 5])))+-- This routine is more efficient than filtering with 'isSmooth'.+--+-- >>> take 10 (smoothOver (fromList [2, 5])) -- [1,2,4,5,8,10,16,20,25,32]-smoothOver :: (Ord a, Num a) => SmoothBasis a -> [a]+smoothOver :: Integral a => SmoothBasis a -> [a] smoothOver = smoothOver' abs --- | Generate an ascending list of--- <https://en.wikipedia.org/wiki/Smooth_number smooth numbers>--- over a given smooth basis in a given range.------ It may appear inefficient--- for short, but distant ranges;--- consider using 'smoothOverInRangeBF' in such cases.------ >>> import Data.Maybe--- >>> smoothOverInRange (fromJust (fromList [2, 5])) 100 200--- [100,125,128,160,200]-smoothOverInRange :: (Ord a, Num a) => SmoothBasis a -> a -> a -> [a]-smoothOverInRange s lo hi- = takeWhile (<= hi)- $ dropWhile (< lo)- $ smoothOver s-{-# DEPRECATED smoothOverInRange "Use 'smoothOver' instead" #-}---- | Generate an ascending list of--- <https://en.wikipedia.org/wiki/Smooth_number smooth numbers>--- over a given smooth basis in a given range.------ It is inefficient--- for large or starting near 0 ranges;--- consider using 'smoothOverInRange' in such cases.------ Suffix BF stands for the brute force algorithm, involving a lot of divisions.+-- | Check that a given number is smooth under a given 'SmoothBasis'. ----- >>> import Data.Maybe--- >>> smoothOverInRangeBF (fromJust (fromList [2, 5])) 100 200--- [100,125,128,160,200]-smoothOverInRangeBF- :: (Eq a, Enum a, E.GcdDomain a)- => SmoothBasis a- -> a- -> a- -> [a]-smoothOverInRangeBF prs lo hi- = coerce- $ filter (isSmooth prs)- $ coerce [lo..hi]-{-# DEPRECATED smoothOverInRangeBF "Use filtering by 'isSmooth' instead" #-}--isValid :: (Eq a, E.GcdDomain a) => [a] -> Bool-isValid [] = False-isValid xs = all (\x -> not (isZero x) && not (E.isUnit x)) xs---- | @isSmooth@ checks if a given number is smooth under a certain @SmoothBasis@.--- Does not check if the @SmoothBasis@ is valid.-isSmooth :: (Eq a, E.GcdDomain a) => SmoothBasis a -> a -> Bool+-- >>> isSmooth (fromList [2,3]) 12+-- True+-- >>> isSmooth (fromList [2,3]) 15+-- False+isSmooth :: (Eq a, GcdDomain a) => SmoothBasis a -> a -> Bool isSmooth prs x = not (isZero x) && go (unSmoothBasis prs) x where- go :: (Eq a, E.GcdDomain a) => [a] -> a -> Bool- go [] n = E.isUnit n- go pps@(p:ps) n = case n `E.divide` p of+ go :: (Eq a, GcdDomain a) => [a] -> a -> Bool+ go [] n = isJust (one `divide` n)+ go pps@(p:ps) n = case n `divide` p of Nothing -> go ps n Just q -> go pps q || go ps n
− Math/NumberTheory/Unsafe.hs
@@ -1,69 +0,0 @@--- |--- Module: Math.NumberTheory.Unsafe--- Copyright: (c) 2016 Andrew Lelechenko--- Licence: MIT--- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>------ Layer to switch between safe and unsafe arrays.-----{-# LANGUAGE CPP #-}--module Math.NumberTheory.Unsafe- ( UArray- , bounds- , castSTUArray- , unsafeAt- , unsafeFreeze- , unsafeNewArray_- , unsafeRead- , unsafeThaw- , unsafeWrite- ) where--#ifdef CheckBounds--import Data.Array.Base- ( UArray- , castSTUArray- )-import Data.Array.IArray- ( IArray- , bounds- , (!)- )-import Data.Array.MArray--unsafeAt :: (IArray a e, Ix i) => a i e -> i -> e-unsafeAt = (!)--unsafeFreeze :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)-unsafeFreeze = freeze--unsafeNewArray_ :: (Ix i, MArray a e m) => (i, i) -> m (a i e)-unsafeNewArray_ = newArray_--unsafeRead :: (MArray a e m, Ix i) => a i e -> i -> m e-unsafeRead = readArray--unsafeThaw :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)-unsafeThaw = thaw--unsafeWrite :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()-unsafeWrite = writeArray--#else--import Data.Array.Base- ( UArray- , bounds- , castSTUArray- , unsafeAt- , unsafeFreeze- , unsafeNewArray_- , unsafeRead- , unsafeThaw- , unsafeWrite- )--#endif
Math/NumberTheory/Utils.hs view
@@ -7,16 +7,12 @@ -- Some utilities, mostly for bit twiddling. -- {-# LANGUAGE CPP, MagicHash, UnboxedTuples, BangPatterns #-}-{-# OPTIONS_HADDOCK hide #-} module Math.NumberTheory.Utils ( shiftToOddCount , shiftToOdd , shiftToOdd# , shiftToOddCount#- , bitCountWord- , bitCountInt- , bitCountWord#- , uncheckedShiftR+ , shiftToOddCountBigNat , splitOff , splitOff# @@ -33,18 +29,13 @@ import Prelude hiding (mod, quotRem) import qualified Prelude as P +import Data.Bits+import Data.Euclidean+import Data.Semiring (Semiring(..), isZero) import GHC.Base- import GHC.Integer.GMP.Internals import GHC.Natural -import Data.Bits-import Data.Semiring (Semiring(..), isZero)-import Math.NumberTheory.Euclidean--uncheckedShiftR :: Word -> Int -> Word-uncheckedShiftR (W# w#) (I# i#) = W# (uncheckedShiftRL# w# i#)- -- | Remove factors of @2@ and count them. If -- @n = 2^k*m@ with @m@ odd, the result is @(k, m)@. -- Precondition: argument not @0@ (not checked).@@ -96,6 +87,11 @@ 0## -> (0, n) z# -> (W# z#, bigNatToNatural (bn# `shiftRBigNat` (word2Int# z#))) +shiftToOddCountBigNat :: BigNat -> (Word, BigNat)+shiftToOddCountBigNat bn# = case bigNatZeroCount bn# of+ 0## -> (0, bn#)+ z# -> (W# z#, bn# `shiftRBigNat` (word2Int# z#))+ -- | Count trailing zeros in a @'BigNat'@. -- Precondition: argument nonzero (not checked, Integer invariant). bigNatZeroCount :: BigNat -> Word#@@ -147,19 +143,6 @@ shiftToOddCount# :: Word# -> (# Word#, Word# #) shiftToOddCount# w# = case ctz# w# of k# -> (# k#, uncheckedShiftRL# w# (word2Int# k#) #)---- | Number of 1-bits in a @'Word#'@.-bitCountWord# :: Word# -> Int#-bitCountWord# w# = case bitCountWord (W# w#) of- I# i# -> i#---- | Number of 1-bits in a @'Word'@.-bitCountWord :: Word -> Int-bitCountWord = popCount---- | Number of 1-bits in an @'Int'@.-bitCountInt :: Int -> Int-bitCountInt = popCount splitOff :: (Eq a, GcdDomain a) => a -> a -> (Word, a) splitOff p n
Math/NumberTheory/Utils/DirichletSeries.hs view
@@ -25,13 +25,12 @@ import Prelude hiding (filter, last, rem, quot, snd, lookup) import Data.Coerce+import Data.Euclidean import Data.Map (Map) import qualified Data.Map.Strict as M import Data.Maybe import Data.Semiring (Semiring(..)) import Numeric.Natural--import Math.NumberTheory.Euclidean -- Sparse Dirichlet series are represented by an ascending list of pairs. -- For instance, [(a, b), (c, d)] stands for 1 + b/a^s + d/c^s.
Math/NumberTheory/Utils/Hyperbola.hs view
@@ -16,7 +16,7 @@ import Data.Bits -import Math.NumberTheory.Powers.Cubes+import Math.NumberTheory.Roots -- | Straightforward computation of -- [ n `quot` x | x <- [hi, hi - 1 .. lo] ].
Math/NumberTheory/Zeta/Dirichlet.hs view
@@ -8,8 +8,6 @@ {-# LANGUAGE ScopedTypeVariables #-} -{-# OPTIONS_HADDOCK hide #-}- module Math.NumberTheory.Zeta.Dirichlet ( betas , betasEven
Math/NumberTheory/Zeta/Hurwitz.hs view
@@ -8,8 +8,6 @@ {-# LANGUAGE ScopedTypeVariables #-} -{-# OPTIONS_HADDOCK hide #-}- module Math.NumberTheory.Zeta.Hurwitz ( zetaHurwitz ) where@@ -77,7 +75,7 @@ (\powOfA int -> powOfA * fromInteger int) powsOfAPlusN [-1, 0..]- in zipWith (/) (repeat aPlusN) denoms+ in map ((/) aPlusN) denoms -- [ 1 | ] -- [ ----------- | s <- [0 ..] ]@@ -111,9 +109,8 @@ (skipEvens powsOfAPlusN) fracs :: [a]- fracs = zipWith- (\sec pochh -> sum $ zipWith (\s p -> s * fromInteger p) sec pochh)- (repeat second)+ fracs = map+ (\pochh -> sum $ zipWith (\s p -> s * fromInteger p) second pochh) pochhammers -- Infinite list of @T@ values in 4.8.5 formula, for every @s@ in
Math/NumberTheory/Zeta/Riemann.hs view
@@ -8,8 +8,6 @@ {-# LANGUAGE ScopedTypeVariables #-} -{-# OPTIONS_HADDOCK hide #-}- module Math.NumberTheory.Zeta.Riemann ( zetas , zetasEven
− Setup.hs
@@ -1,5 +0,0 @@-module Main where--import Distribution.Simple--main = defaultMain
arithmoi.cabal view
@@ -1,13 +1,12 @@ name: arithmoi-version: 0.10.0.0+version: 0.11.0.0 cabal-version: >=1.10 build-type: Simple license: MIT license-file: LICENSE-copyright: (c) 2016-2019 Andrew Lelechenko, Carter Schonwald, 2011 Daniel Fischer+copyright: (c) 2016-2020 Andrew Lelechenko, 2016-2019 Carter Schonwald, 2011 Daniel Fischer maintainer: Andrew Lelechenko andrew dot lelechenko at gmail dot com, Carter Schonwald carter at wellposed dot com-stability: Provisional homepage: https://github.com/Bodigrim/arithmoi bug-reports: https://github.com/Bodigrim/arithmoi/issues synopsis: Efficient basic number-theoretic functions.@@ -19,37 +18,32 @@ powers (integer roots and tests, modular exponentiation). category: Math, Algorithms, Number Theory author: Andrew Lelechenko, Daniel Fischer-tested-with: GHC ==8.0.2 GHC ==8.2.2 GHC ==8.4.4 GHC ==8.6.5 GHC ==8.8.1+tested-with: GHC ==8.2.2 GHC ==8.4.4 GHC ==8.6.5 GHC ==8.8.3 GHC ==8.10.1 extra-source-files:- Changes+ changelog.md source-repository head type: git location: https://github.com/Bodigrim/arithmoi -flag check-bounds- description:- Replace unsafe array operations with safe ones- default: False- manual: True- library build-depends:- base >=4.9 && <5,+ base >=4.10 && <5, array >=0.5 && <0.6,- containers >=0.5 && <0.7,+ containers >=0.5.8 && <0.7,+ chimera >=0.3, constraints, deepseq, exact-pi >=0.5,- ghc-prim <0.6, integer-gmp <1.1, integer-logarithms >=1.0,+ integer-roots >=1.0,+ mod, random >=1.0 && <1.2, transformers >=0.4 && <0.6,- semirings >= 0.4.2,- vector >= 0.12+ semirings >=0.5.2,+ vector >=0.12 exposed-modules:- GHC.TypeNats.Compat Math.NumberTheory.ArithmeticFunctions Math.NumberTheory.ArithmeticFunctions.Inverse Math.NumberTheory.ArithmeticFunctions.Mertens@@ -57,6 +51,7 @@ Math.NumberTheory.ArithmeticFunctions.Moebius Math.NumberTheory.ArithmeticFunctions.SieveBlock Math.NumberTheory.Curves.Montgomery+ Math.NumberTheory.DirichletCharacters Math.NumberTheory.Euclidean Math.NumberTheory.Euclidean.Coprimes Math.NumberTheory.Moduli@@ -65,11 +60,11 @@ Math.NumberTheory.Moduli.DiscreteLogarithm Math.NumberTheory.Moduli.Equations Math.NumberTheory.Moduli.Jacobi+ Math.NumberTheory.Moduli.Multiplicative Math.NumberTheory.Moduli.PrimitiveRoot Math.NumberTheory.Moduli.Singleton Math.NumberTheory.Moduli.Sqrt Math.NumberTheory.MoebiusInversion- Math.NumberTheory.MoebiusInversion.Int Math.NumberTheory.Powers Math.NumberTheory.Powers.Cubes Math.NumberTheory.Powers.Fourth@@ -80,12 +75,7 @@ Math.NumberTheory.Prefactored Math.NumberTheory.Primes Math.NumberTheory.Primes.Counting- Math.NumberTheory.Primes.Factorisation- Math.NumberTheory.Primes.Factorisation.Certified- Math.NumberTheory.Primes.Sieve- Math.NumberTheory.Primes.Small Math.NumberTheory.Primes.Testing- Math.NumberTheory.Primes.Testing.Certificates Math.NumberTheory.Quadratic.GaussianIntegers Math.NumberTheory.Quadratic.EisensteinIntegers Math.NumberTheory.Recurrences@@ -93,47 +83,52 @@ Math.NumberTheory.Recurrences.Linear Math.NumberTheory.SmoothNumbers Math.NumberTheory.Zeta- Math.NumberTheory.Zeta.Dirichlet- Math.NumberTheory.Zeta.Hurwitz- Math.NumberTheory.Zeta.Riemann other-modules: Math.NumberTheory.ArithmeticFunctions.Class Math.NumberTheory.ArithmeticFunctions.Standard+ Math.NumberTheory.Moduli.Internal+ Math.NumberTheory.Moduli.JacobiSymbol+ Math.NumberTheory.Moduli.SomeMod Math.NumberTheory.Primes.Counting.Approximate Math.NumberTheory.Primes.Counting.Impl Math.NumberTheory.Primes.Factorisation.Montgomery Math.NumberTheory.Primes.Factorisation.TrialDivision Math.NumberTheory.Primes.Sieve.Eratosthenes Math.NumberTheory.Primes.Sieve.Indexing- Math.NumberTheory.Primes.Testing.Certificates.Internal+ Math.NumberTheory.Primes.Small Math.NumberTheory.Primes.Testing.Certified Math.NumberTheory.Primes.Testing.Probabilistic Math.NumberTheory.Primes.Types Math.NumberTheory.Recurrences.Pentagonal- Math.NumberTheory.Unsafe+ Math.NumberTheory.RootsOfUnity Math.NumberTheory.Utils Math.NumberTheory.Utils.DirichletSeries Math.NumberTheory.Utils.FromIntegral Math.NumberTheory.Utils.Hyperbola+ Math.NumberTheory.Zeta.Dirichlet+ Math.NumberTheory.Zeta.Hurwitz+ Math.NumberTheory.Zeta.Riemann Math.NumberTheory.Zeta.Utils default-language: Haskell2010- ghc-options: -O2 -Wall- if flag(check-bounds)- cpp-options: -DCheckBounds+ ghc-options: -Wall -Widentities -Wcompat -test-suite spec+test-suite arithmoi-tests build-depends:- base >=4.9 && <5,+ base >=4.10 && <5, arithmoi, containers, exact-pi >=0.4.1.1, integer-gmp <1.1,+ integer-roots >=1.0,+ mod, QuickCheck >=2.10,- semirings >= 0.2,+ quickcheck-classes >=0.6.3,+ semirings >=0.2, smallcheck >=1.1.3 && <1.2, tasty >=0.10, tasty-hunit >=0.9 && <0.11, tasty-quickcheck >=0.9 && <0.11,+ tasty-rerun >=1.1.17, tasty-smallcheck >=0.8 && <0.9, transformers >=0.5, vector@@ -143,6 +138,7 @@ Math.NumberTheory.ArithmeticFunctions.MertensTests Math.NumberTheory.ArithmeticFunctions.SieveBlockTests Math.NumberTheory.CurvesTests+ Math.NumberTheory.DirichletCharactersTests Math.NumberTheory.EisensteinIntegersTests Math.NumberTheory.GaussianIntegersTests Math.NumberTheory.EuclideanTests@@ -155,11 +151,7 @@ Math.NumberTheory.Moduli.SingletonTests Math.NumberTheory.Moduli.SqrtTests Math.NumberTheory.MoebiusInversionTests- Math.NumberTheory.Powers.CubesTests- Math.NumberTheory.Powers.FourthTests- Math.NumberTheory.Powers.GeneralTests Math.NumberTheory.Powers.ModularTests- Math.NumberTheory.Powers.SquaresTests Math.NumberTheory.PrefactoredTests Math.NumberTheory.Primes.CountingTests Math.NumberTheory.Primes.FactorisationTests@@ -170,6 +162,7 @@ Math.NumberTheory.Recurrences.PentagonalTests Math.NumberTheory.Recurrences.BilinearTests Math.NumberTheory.Recurrences.LinearTests+ Math.NumberTheory.RootsOfUnityTests Math.NumberTheory.SmoothNumbersTests Math.NumberTheory.TestUtils Math.NumberTheory.TestUtils.MyCompose@@ -181,9 +174,9 @@ main-is: Test.hs default-language: Haskell2010 hs-source-dirs: test-suite- ghc-options: -Wall+ ghc-options: -Wall -Widentities -Wcompat -benchmark criterion+benchmark arithmoi-gauge build-depends: base, arithmoi,@@ -193,18 +186,18 @@ deepseq, gauge, integer-logarithms,+ mod, random,+ semirings, vector other-modules: Math.NumberTheory.ArithmeticFunctionsBench Math.NumberTheory.DiscreteLogarithmBench Math.NumberTheory.EisensteinIntegersBench- Math.NumberTheory.EuclideanBench Math.NumberTheory.GaussianIntegersBench Math.NumberTheory.InverseBench Math.NumberTheory.JacobiBench Math.NumberTheory.MertensBench- Math.NumberTheory.PowersBench Math.NumberTheory.PrimesBench Math.NumberTheory.PrimitiveRootsBench Math.NumberTheory.RecurrencesBench@@ -216,14 +209,17 @@ main-is: Bench.hs default-language: Haskell2010 hs-source-dirs: benchmark+ ghc-options: -Wall -Widentities -Wcompat -executable sequence-model+benchmark arithmoi-sequence-model build-depends: base, arithmoi, containers, hmatrix-gsl buildable: False+ type: exitcode-stdio-1.0 main-is: SequenceModel.hs- hs-source-dirs: app default-language: Haskell2010+ hs-source-dirs: app+ ghc-options: -Wall -Widentities -Wcompat
benchmark/Bench.hs view
@@ -5,12 +5,10 @@ import Math.NumberTheory.ArithmeticFunctionsBench as ArithmeticFunctions import Math.NumberTheory.DiscreteLogarithmBench as DiscreteLogarithm import Math.NumberTheory.EisensteinIntegersBench as Eisenstein-import Math.NumberTheory.EuclideanBench as Euclidean import Math.NumberTheory.GaussianIntegersBench as Gaussian import Math.NumberTheory.InverseBench as Inverse import Math.NumberTheory.JacobiBench as Jacobi import Math.NumberTheory.MertensBench as Mertens-import Math.NumberTheory.PowersBench as Powers import Math.NumberTheory.PrimesBench as Primes import Math.NumberTheory.PrimitiveRootsBench as PrimitiveRoots import Math.NumberTheory.RecurrencesBench as Recurrences@@ -24,12 +22,10 @@ [ ArithmeticFunctions.benchSuite , DiscreteLogarithm.benchSuite , Eisenstein.benchSuite- , Euclidean.benchSuite , Gaussian.benchSuite , Inverse.benchSuite , Jacobi.benchSuite , Mertens.benchSuite- , Powers.benchSuite , Primes.benchSuite , PrimitiveRoots.benchSuite , Recurrences.benchSuite
benchmark/Math/NumberTheory/DiscreteLogarithmBench.hs view
@@ -14,21 +14,20 @@ import Gauge.Main import Control.Monad import Data.Maybe-import GHC.TypeNats.Compat+import Data.Mod+import GHC.TypeNats (KnownNat, SomeNat(..), someNatVal) import Data.Proxy import Numeric.Natural -import Math.NumberTheory.Moduli.Class (isMultElement, KnownNat, MultMod, multElement, getVal,Mod)-import Math.NumberTheory.Moduli.DiscreteLogarithm (discreteLogarithm)-import Math.NumberTheory.Moduli.PrimitiveRoot+import Math.NumberTheory.Moduli.Multiplicative import Math.NumberTheory.Moduli.Singleton data Case = forall m. KnownNat m => Case (PrimitiveRoot m) (MultMod m) String instance Show Case where- show (Case a b s) = concat [show (getVal a'), "ⁿ == ", show b', " mod ", s]+ show (Case a b s) = concat [show (unMod a'), "ⁿ == ", show b', " mod ", s] where a' = multElement $ unPrimitiveRoot a- b' = getVal $ multElement b+ b' = unMod $ multElement b makeCase :: (Integer, Integer, Natural, String) -> Maybe Case makeCase (a,b,n,s) =
− benchmark/Math/NumberTheory/EuclideanBench.hs
@@ -1,19 +0,0 @@-{-# OPTIONS_GHC -fno-warn-type-defaults #-}--module Math.NumberTheory.EuclideanBench- ( benchSuite- ) where--import Gauge.Main--import Math.NumberTheory.Euclidean--doBench :: Integral a => (a -> a -> (a, a, a)) -> a -> a-doBench func lim = sum [ let (a, b, c) = func x y in a + b + c | y <- [3, 5 .. lim], x <- [0..y] ]--benchSuite :: Benchmark-benchSuite = bgroup "Euclidean"- [ bench "extendedGCD/Int" $ nf (doBench extendedGCD :: Int -> Int) 1000- , bench "extendedGCD/Word" $ nf (doBench extendedGCD :: Word -> Word) 1000- , bench "extendedGCD/Integer" $ nf (doBench extendedGCD :: Integer -> Integer) 1000- ]
benchmark/Math/NumberTheory/InverseBench.hs view
@@ -9,10 +9,10 @@ import Gauge.Main import Data.Bits (Bits)+import Data.Euclidean import Numeric.Natural import Math.NumberTheory.ArithmeticFunctions.Inverse-import Math.NumberTheory.Euclidean import Math.NumberTheory.Primes fact :: (Enum a, Num a) => a@@ -21,7 +21,7 @@ tens :: Num a => a tens = 10 ^ 18 -countInverseTotient :: (Ord a, Euclidean a, UniqueFactorisation a) => a -> Word+countInverseTotient :: (Ord a, Integral a, Euclidean a, UniqueFactorisation a) => a -> Word countInverseTotient = inverseTotient (const 1) countInverseSigma :: (Integral a, Euclidean a, UniqueFactorisation a, Enum (Prime a), Bits a) => a -> Word
benchmark/Math/NumberTheory/JacobiBench.hs view
@@ -7,7 +7,7 @@ import Gauge.Main import Numeric.Natural -import Math.NumberTheory.Moduli.Jacobi+import Math.NumberTheory.Moduli.Sqrt doBench :: Integral a => (a -> a -> JacobiSymbol) -> a -> a doBench func lim = sum [ x + y | y <- [3, 5 .. lim], x <- [0..y], func x y == One ]
− benchmark/Math/NumberTheory/PowersBench.hs
@@ -1,31 +0,0 @@-{-# OPTIONS_GHC -fno-warn-type-defaults #-}--module Math.NumberTheory.PowersBench- ( benchSuite- ) where--import Gauge.Main-import System.Random--import Math.NumberTheory.Logarithms (integerLog2)-import Math.NumberTheory.Powers.Squares.Internal--genInteger :: Int -> Int -> Integer-genInteger salt bits- = head- . dropWhile ((< bits) . integerLog2)- . scanl (\a r -> a * 2^31 + abs r) 1- . randoms- . mkStdGen- $ salt + bits--compareRoots :: Int -> Benchmark-compareRoots bits = bgroup ("sqrt" ++ show bits)- [ bench "new" $ nf (fst . karatsubaSqrt) n- , bench "old" $ nf isqrtA n- ]- where- n = genInteger 0 bits--benchSuite :: Benchmark-benchSuite = bgroup "Powers" $ map compareRoots [2300, 2400 .. 2600]
benchmark/Math/NumberTheory/PrimitiveRootsBench.hs view
@@ -10,7 +10,7 @@ import Data.Constraint import Data.Maybe -import Math.NumberTheory.Moduli.PrimitiveRoot+import Math.NumberTheory.Moduli.Multiplicative import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.Primes
benchmark/Math/NumberTheory/RecurrencesBench.hs view
@@ -6,10 +6,10 @@ import Gauge.Main -import Math.NumberTheory.Recurrences (binomial, eulerian1, eulerian2,- stirling1, stirling2, partition)+import Data.Euclidean (GcdDomain)+import Math.NumberTheory.Recurrences -benchTriangle :: String -> (forall a. (Integral a) => [[a]]) -> Int -> Benchmark+benchTriangle :: String -> (forall a. (GcdDomain a, Integral a) => [[a]]) -> Int -> Benchmark benchTriangle name triangle n = bgroup name [ benchAt (10 * n) (1 * n) , benchAt (10 * n) (2 * n)@@ -31,18 +31,17 @@ benchSuite :: Benchmark benchSuite = bgroup "Recurrences"- [- bgroup "Bilinear"+ [ bgroup "Bilinear" [ benchTriangle "binomial" binomial 1000 , benchTriangle "stirling1" stirling1 100 , benchTriangle "stirling2" stirling2 100 , benchTriangle "eulerian1" eulerian1 100 , benchTriangle "eulerian2" eulerian2 100 ]- ,- bgroup "Pentagonal"- [ bgroup "Partition function"- [ benchPartition 1000- ]+ , benchPartition 1000+ , bgroup "factorialFactors"+ [ bench "10000" $ nf factorialFactors 10000+ , bench "20000" $ nf factorialFactors 20000+ , bench "40000" $ nf factorialFactors 40000 ] ]
benchmark/Math/NumberTheory/SequenceBench.hs view
@@ -1,5 +1,4 @@ {-# OPTIONS_GHC -fno-warn-type-defaults #-}-{-# OPTIONS_GHC -fno-warn-deprecations #-} module Math.NumberTheory.SequenceBench ( benchSuite@@ -7,21 +6,17 @@ import Gauge.Main -import Data.Array.IArray ((!)) import Data.Array.Unboxed import Data.Bits -import Math.NumberTheory.Primes (Prime(..))-import Math.NumberTheory.Primes.Sieve+import Math.NumberTheory.Primes (Prime(..), nextPrime, precPrime) import Math.NumberTheory.Primes.Testing filterIsPrime :: (Integer, Integer) -> Integer filterIsPrime (p, q) = sum $ takeWhile (<= q) $ dropWhile (< p) $ filter isPrime (map toPrim [toIdx p .. toIdx q]) eratosthenes :: (Integer, Integer) -> Integer-eratosthenes (p, q) = sum $ takeWhile (<= q) $ dropWhile (< p) $ map unPrime $ if q < toInteger sieveRange- then primeList $ primeSieve q- else concatMap primeList $ psieveFrom p+eratosthenes (p, q) = sum (map unPrime [nextPrime p .. precPrime q]) filterIsPrimeBench :: Benchmark filterIsPrimeBench = bgroup "filterIsPrime" $@@ -48,9 +43,6 @@ ------------------------------------------------------------------------------- -- Utils copypasted from internal modules--sieveRange :: Int-sieveRange = 30*128*1024 rho :: Int -> Int rho i = residues ! i
benchmark/Math/NumberTheory/SieveBlockBench.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} -{-# OPTIONS_GHC -fno-warn-deprecations #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Math.NumberTheory.SieveBlockBench
benchmark/Math/NumberTheory/SmoothNumbersBench.hs view
@@ -4,14 +4,13 @@ ( benchSuite ) where -import Data.Maybe import Gauge.Main import Math.NumberTheory.Primes import Math.NumberTheory.SmoothNumbers doBench :: Int -> Int-doBench lim = sum $ take lim $ smoothOver $ fromJust $ fromList $ map unPrime [nextPrime 2 .. precPrime lim]+doBench lim = sum $ take lim $ smoothOver $ fromList $ map unPrime [nextPrime 2 .. precPrime lim] benchSuite :: Benchmark benchSuite = bgroup "SmoothNumbers"
+ changelog.md view
@@ -0,0 +1,538 @@+# Changelog++## 0.11.0.0++### Added++* Brand new machinery to deal with Dirichlet characters ([#180](https://github.com/Bodigrim/arithmoi/pull/180)).++* Generate preimages of the Jordan and the sum-of-powers-of-divisors+ functions ([#148](https://github.com/Bodigrim/arithmoi/pull/148)).++* More flexible interface for Pascal triangle: in addition to `binomial`+ we now provide also `binomialRotated`, `binomialLine` and `binomialDiagonal`+ ([#151](https://github.com/Bodigrim/arithmoi/pull/151)). There are also `factoriseFactorial` and `factoriseBinomial` ([#152](https://github.com/Bodigrim/arithmoi/pull/152)).++* Add `Semiring` instance of `SomeMod` ([#174](https://github.com/Bodigrim/arithmoi/pull/174)).++* Generate divisors in range ([#183](https://github.com/Bodigrim/arithmoi/pull/183)).++### Changed++* Speed up `partition`, using better container for memoization ([#176](https://github.com/Bodigrim/arithmoi/pull/176)).++* Speed up `integerRoot`, using better starting approximation ([#177](https://github.com/Bodigrim/arithmoi/pull/177)).++### Deprecated++* Deprecate `Math.NumberTheory.Euclidean`, use `Data.Euclidean` instead.++* Deprecate `chineseRemainder`, `chineseRemainder2`, `chineseCoprime`,+ use `chinese` instead. Deprecate `chineseCoprimeSomeMod`, use `chineseSomeMod`.++* Deprecate `Math.NumberTheory.Powers` except `Math.NumberTheory.Powers.Modular`.+ Use `Math.NumberTheory.Roots` instead.++* Deprecate `Math.NumberTheory.Moduli.Jacobi`, use `Math.NumberTheory.Moduli.Sqrt`+ instead.++* Deprecate `Math.NumberTheory.Moduli.{DiscreteLogarithm,PrimitiveRoot}`,+ use `Math.NumberTheory.Moduli.Multiplicative` instead.++### Fixed++* Fix subtraction of `SomeMod` ([#174](https://github.com/Bodigrim/arithmoi/pull/174)).++## 0.10.0.0++### Added++* The machinery of cyclic groups, primitive roots and discrete logarithms+ has been completely overhauled and rewritten using singleton types ([#169](https://github.com/Bodigrim/arithmoi/pull/169)).++ There is also a new singleton type, linking a type-level modulo with+ a term-level factorisation. It allows both to have a nicely-typed API+ of `Mod m` and avoid repeating factorisations ([#169](https://github.com/Bodigrim/arithmoi/pull/169)).++ Refer to a brand new module `Math.NumberTheory.Moduli.Singleton` for details.++* Add a new function `factorBack`.++* Add `Ord SomeMod` instance ([#165](https://github.com/Bodigrim/arithmoi/pull/165)).++* Add `Semiring` and `Ring` instances for Eisenstein and Gaussian integers.++### Changed++* Embrace the new `Semiring -> GcdDomain -> Euclidean` hierarchy+ of classes, refining `Num` and `Integral` constraints.++* Reshuffle exports from `Math.NumberTheory.Zeta`, do not advertise+ its submodules as available to import.++* Add a proxy argument storing vector's flavor to+ `Math.NumberTheory.MoebiusInversion.{generalInversion,totientSum}`.++* `solveQuadratic` and `sqrtsMod` require an additional argument: a singleton+ linking a type-level modulo with a term-level factorisation ([#169](https://github.com/Bodigrim/arithmoi/pull/169)).++* Generalize `sieveBlock` to handle any flavor of `Vector` ([#164](https://github.com/Bodigrim/arithmoi/pull/164)).++### Deprecated++* Deprecate `Math.NumberTheory.Primes.Factorisation`, use+ `Math.NumberTheory.Primes.factorise` instead. Deprecate+ `Math.NumberTheory.Primes.Sieve`, use `Enum` instance instead.++* Deprecate `Math.NumberTheory.Primes.Factorisation.Certified` and+ `Math.NumberTheory.Primes.Testing.Certificates`.++* Deprecate `Math.NumberTheory.MoebiusInversion.Int`.++* Deprecate `Math.NumberTheory.SmoothNumbers.{fromSet,fromSmoothUpperBound}`.+ Use `Math.NumberTheory.SmoothNumbers.fromList` instead.++* Deprecate `Math.NumberTheory.SmoothNumbers.smoothOverInRange` in favor+ of `smoothOver` and `Math.NumberTheory.SmoothNumbers.smoothOverInRange`+ in favor of `isSmooth`.++### Removed++* Move `Euclidean` type class to `semirings` package ([#168](https://github.com/Bodigrim/arithmoi/pull/168)).++* Remove deprecated earlier `Math.NumberTheory.Recurrencies.*`+ and `Math.NumberTheory.UniqueFactorisation` modules.+ Use `Math.NumberTheory.Recurrences.*` and `Math.NumberTheory.Primes`+ instead.++* Remove deprecated earlier an old interface of `Math.NumberTheory.Moduli.Sqrt`.++## 0.9.0.0++### Added++* Introduce `Prime` newtype. This newtype+ is now used extensively in public API:++ ```haskell+ primes :: Integral a => [Prime a]+ primeList :: Integral a => PrimeSieve -> [Prime a]+ sieveFrom :: Integer -> [Prime Integer]+ nthPrime :: Integer -> Prime Integer+ ```++* New functions `nextPrime` and `precPrime`. Implement an instance of `Enum` for primes ([#153](https://github.com/Bodigrim/arithmoi/pull/153)):++ ```haskell+ > [nextPrime 101 .. precPrime 130]+ [Prime 101,Prime 103,Prime 107,Prime 109,Prime 113,Prime 127]+ ```+* Add the Hurwitz zeta function on non-negative integer arguments ([#126](https://github.com/Bodigrim/arithmoi/pull/126)).++* Implement efficient tests of n-freeness: pointwise and in interval. See `isNFree` and `nFreesBlock` ([#145](https://github.com/Bodigrim/arithmoi/pull/145)).++* Generate preimages of the totient and the sum-of-divisors functions ([#142](https://github.com/Bodigrim/arithmoi/pull/142)):++ ```haskell+ > inverseTotient 120 :: [Integer]+ [155,310,183,366,225,450,175,350,231,462,143,286,244,372,396,308,248]+ ```++* Generate coefficients of Faulhaber polynomials `faulhaberPoly` ([#70](https://github.com/Bodigrim/arithmoi/pull/70)).++### Changed++* Support Gaussian and Eisenstein integers in smooth numbers ([#138](https://github.com/Bodigrim/arithmoi/pull/138)).++* Change types of `primes`, `primeList`, `sieveFrom`, `nthPrime`, etc.,+ to use `Prime` newtype.++* `Math.NumberTheory.Primes.{Factorisation,Testing,Counting,Sieve}`+ are no longer re-exported from `Math.NumberTheory.Primes`.+ Merge `Math.NumberTheory.UniqueFactorisation` into+ `Math.NumberTheory.Primes` ([#135](https://github.com/Bodigrim/arithmoi/pull/135), [#153](https://github.com/Bodigrim/arithmoi/pull/153)).++* From now on `Math.NumberTheory.Primes.Factorisation.factorise`+ and similar functions return `[(Integer, Word)]` instead of `[(Integer, Int)]`.++* `sbcFunctionOnPrimePower` now accepts `Prime Word` instead of `Word`.++* Better precision for exact values of Riemann zeta and Dirichlet beta+ functions ([#123](https://github.com/Bodigrim/arithmoi/pull/123)).++* Speed up certain cases of modular multiplication ([#160](https://github.com/Bodigrim/arithmoi/pull/160)).++* Extend Chinese theorem to non-coprime moduli ([#71](https://github.com/Bodigrim/arithmoi/pull/71)).++### Deprecated++* Deprecate `Math.NumberTheory.Recurrencies.*`.+ Use `Math.NumberTheory.Recurrences.*` instead ([#146](https://github.com/Bodigrim/arithmoi/pull/146)).++### Removed++* Remove `Prime` type family.++* Remove deprecated `Math.NumberTheory.GCD` and `Math.NumberTheory.GCD.LowLevel`.++## 0.8.0.0++### Added++* A new interface for `Math.NumberTheory.Moduli.Sqrt`, more robust and type safe ([#87](https://github.com/Bodigrim/arithmoi/pull/87), [#108](https://github.com/Bodigrim/arithmoi/pull/108)).++* Implement Ramanujan tau function ([#112](https://github.com/Bodigrim/arithmoi/pull/112)):++ ```haskell+ > map ramanujan [1..10]+ [1,-24,252,-1472,4830,-6048,-16744,84480,-113643,-115920]+ ```++* Implement partition function ([#115](https://github.com/Bodigrim/arithmoi/pull/115)):++ ```haskell+ > take 10 partition+ [1,1,2,3,5,7,11,15,22,30]+ ```++* Add the Dirichlet beta function on non-negative integer arguments ([#120](https://github.com/Bodigrim/arithmoi/pull/120)).+ E. g.,++ ```haskell+ > take 5 $ Math.NumberTheory.Zeta.Dirichlet.betas 1e-15+ [0.5,0.7853981633974483,0.9159655941772191,0.9689461462593693,0.9889445517411055]+ ```++* Solve linear and quadratic congruences ([#129](https://github.com/Bodigrim/arithmoi/pull/129)).++* Support Eisenstein integers ([#121](https://github.com/Bodigrim/arithmoi/pull/121)).++* Implement discrete logarithm ([#88](https://github.com/Bodigrim/arithmoi/pull/88)).++### Changed++* Stop reporting units (1, -1, i, -i) as a part of factorisation+ for integers and Gaussian integers ([#101](https://github.com/Bodigrim/arithmoi/pull/101)). Now `factorise (-2)`+ is `[(2, 1)]` and not `[(-1, 1), (2, 1)]`.++* Move `splitIntoCoprimes` to `Math.NumberTheory.Euclidean.Coprimes`.++* Change types of `splitIntoCoprimes`, `fromFactors` and `prefFactors`+ using newtype `Coprimes` ([#89](https://github.com/Bodigrim/arithmoi/pull/89)).++* Sort Gaussian primes by norm ([#124](https://github.com/Bodigrim/arithmoi/pull/124)).++* Make return type of `primes` and `primeList` polymorphic instead of+ being limited to `Integer` only ([#109](https://github.com/Bodigrim/arithmoi/pull/109)).++* Speed up factorisation of Gaussian integers ([#116](https://github.com/Bodigrim/arithmoi/pull/116)).++* Speed up computation of primitive roots for prime powers ([#127](https://github.com/Bodigrim/arithmoi/pull/127)).++### Deprecated++* Deprecate an old interface of `Math.NumberTheory.Moduli.Sqrt`.++* Deprecate `Math.NumberTheory.GCD` and `Math.NumberTheory.GCD.LowLevel` ([#80](https://github.com/Bodigrim/arithmoi/pull/80)).+ Use `Math.NumberTheory.Euclidean` instead ([#128](https://github.com/Bodigrim/arithmoi/pull/128)).++* Deprecate `jacobi'` ([#103](https://github.com/Bodigrim/arithmoi/pull/103)).+++* Deprecate `Math.NumberTheory.GaussianIntegers` in favor of+ `Math.NumberTheory.Quadratic.GaussianIntegers`.++## 0.7.0.0++### Added++* A general framework for bulk evaluation of arithmetic functions ([#77](https://github.com/Bodigrim/arithmoi/pull/77)):++ ```haskell+ > runFunctionOverBlock carmichaelA 1 10+ [1,1,2,2,4,2,6,2,6,4]+ ```++* Implement a sublinear algorithm for Mertens function ([#90](https://github.com/Bodigrim/arithmoi/pull/90)):++ ```haskell+ > map (mertens . (10 ^)) [0..9]+ [1,-1,1,2,-23,-48,212,1037,1928,-222]+ ```++* Add basic support for cyclic groups and primitive roots ([#86](https://github.com/Bodigrim/arithmoi/pull/86)).++* Implement an efficient modular exponentiation ([#86](https://github.com/Bodigrim/arithmoi/pull/86)).++* Write routines for lazy generation of smooth numbers ([#91](https://github.com/Bodigrim/arithmoi/pull/91)).++ ```haskell+ > smoothOverInRange (fromJust (fromList [3,5,7])) 1000 2000+ [1029,1125,1215,1225,1323,1575,1701,1715,1875]+ ```++### Changed++* Now `moebius` returns not a number, but a value of `Moebius` type ([#90](https://github.com/Bodigrim/arithmoi/pull/90)).++* Now factorisation of large integers and Gaussian integers produces+ factors as lazy as possible ([#72](https://github.com/Bodigrim/arithmoi/pull/72), [#76](https://github.com/Bodigrim/arithmoi/pull/76)).++### Deprecated++* Deprecate `Math.NumberTheory.Primes.Heap`.+ Use `Math.NumberTheory.Primes.Sieve` instead.++* Deprecate `FactorSieve`, `TotientSieve`, `CarmichaelSieve` and+ accompanying functions. Use new general approach for bulk evaluation+ of arithmetic functions instead ([#77](https://github.com/Bodigrim/arithmoi/pull/77)).++### Removed++* Remove `Math.NumberTheory.Powers.Integer`, deprecated in 0.5.0.0.++## 0.6.0.1++### Changed++* Switch to `smallcheck-1.1.3`.++## 0.6.0.0++### Added++* Brand new `Math.NumberTheory.Moduli.Class` ([#56](https://github.com/Bodigrim/arithmoi/pull/56)), providing+ flexible and type safe modular arithmetic. Due to use of GMP built-ins+ it is also significantly faster.++* New function `divisorsList`, which is lazier than `divisors` and+ does not require `Ord` constraint ([#64](https://github.com/Bodigrim/arithmoi/pull/64)). Thus, it can be used+ for `GaussianInteger`.++### Changed++* `Math.NumberTheory.Moduli` was split into+ `Math.NumberTheory.Moduli.{Chinese,Class,Jacobi,Sqrt}`.++* Functions `jacobi` and `jacobi'` return `JacobiSymbol`+ instead of `Int`.++* Speed up factorisation over elliptic curve up to 15x ([#65](https://github.com/Bodigrim/arithmoi/pull/65)).++* Polymorphic `fibonacci` and `lucas` functions, which previously+ were restricted to `Integer` only ([#63](https://github.com/Bodigrim/arithmoi/pull/63)). This is especially useful+ for modular computations, e. g., `map fibonacci [1..10] :: [Mod 7]`.++* Make `totientSum` more robust and idiomatic ([#58](https://github.com/Bodigrim/arithmoi/pull/58)).++### Removed++* Functions `invertMod`, `powerMod` and `powerModInteger` were removed,+ as well as their unchecked counterparts. Use new interface to+ modular computations, provided by `Math.NumberTheory.Moduli.Class`.++## 0.5.0.1++### Changed++ Switch to `QuickCheck-2.10`.++## 0.5.0.0++### Added++* Add basic combinatorial sequences: binomial coefficients, Stirling+ numbers of both kinds, Eulerian numbers of both kinds, Bernoulli+ numbers ([#39](https://github.com/Bodigrim/arithmoi/pull/39)). E. g.,++ ```haskell+ > take 10 $ Math.NumberTheory.Recurrencies.Bilinear.bernoulli+ [1 % 1,(-1) % 2,1 % 6,0 % 1,(-1) % 30,0 % 1,1 % 42,0 % 1,(-1) % 30,0 % 1]+ ```++* Add the Riemann zeta function on non-negative integer arguments ([#44](https://github.com/Bodigrim/arithmoi/pull/44)).+ E. g.,++ ```haskell+ > take 5 $ Math.NumberTheory.Zeta.zetas 1e-15+ [-0.5,Infinity,1.6449340668482262,1.2020569031595945,1.0823232337111381]+ ```++### Changed++* Rename `Math.NumberTheory.Lucas` to `Math.NumberTheory.Recurrencies.Linear`.++* Speed up `isPrime` twice; rework `millerRabinV` and `isStrongFermatPP` ([#22](https://github.com/Bodigrim/arithmoi/pull/22), [#25](https://github.com/Bodigrim/arithmoi/pull/25)).++### Deprecated++* Deprecate `integerPower` and `integerWordPower` from+ `Math.NumberTheory.Powers.Integer`. Use `(^)` instead ([#51](https://github.com/Bodigrim/arithmoi/pull/51)).++### Removed++* Remove deprecated interface to arithmetic functions (`divisors`, `tau`,+ `sigma`, `totient`, `jordan`, `moebius`, `liouville`, `smallOmega`, `bigOmega`,+ `carmichael`, `expMangoldt`). New interface is exposed via+ `Math.NumberTheory.ArithmeticFunctions` ([#30](https://github.com/Bodigrim/arithmoi/pull/30)).++* `Math.NumberTheory.Logarithms` has been moved to the separate package+ `integer-logarithms` ([#51](https://github.com/Bodigrim/arithmoi/pull/51)).++## 0.4.3.0++### Added++* Add `Math.NumberTheory.ArithmeticFunctions` with brand-new machinery+ for arithmetic functions: `divisors`, `tau`, `sigma`, `totient`, `jordan`,+ `moebius`, `liouville`, `smallOmega`, `bigOmega`, `carmichael`, `expMangoldt` ([#30](https://github.com/Bodigrim/arithmoi/pull/30)).+ Old implementations (exposed via `Math.NumberTheory.Primes.Factorisation`+ and `Math.NumberTheory.Powers.Integer`) are deprecated and will be removed+ in the next major release.++* Add Karatsuba sqrt algorithm, improving performance on large integers ([#6](https://github.com/Bodigrim/arithmoi/pull/6)).++### Fixed++* Fix incorrect indexing of `FactorSieve` ([#35](https://github.com/Bodigrim/arithmoi/pull/35)).++## 0.4.2.0++### Added++* Add new cabal flag `check-bounds`, which replaces all unsafe array functions with safe ones.++* Add basic functions on Gaussian integers.++* Add Möbius mu-function.++### Changed++* Forbid non-positive moduli in `Math.NumberTheory.Moduli`.++### Fixed++* Fix out-of-bounds errors in `Math.NumberTheory.Primes.Heap`, `Math.NumberTheory.Primes.Sieve` and `Math.NumberTheory.MoebiusInversion`.++* Fix 32-bit build.++* Fix `binaryGCD` on negative numbers.++* Fix `highestPower` (various issues).++## 0.4.1.0++### Added++* Add `integerLog10` variants at Bas van Dijk's request and expose+ `Math.NumberTheory.Powers.Integer`, with an added `integerWordPower`.++## 0.4.0.4++### Fixed++* Update for GHC 7.8, the type of some primops changed, they return `Int#` now+ instead of `Bool`.++* Fixed bugs in modular square roots and factorisation.++## 0.4.0.3++### Changed++* Relaxed dependencies on mtl and containers.++### Fixed++* Fixed warnings from GHC 7.5, `Word(..)` moved to `GHC.Types`.++* Removed `SPECIALISE` pragma from inline function (warning from GHC 7.5, probably+ pointless anyway).++## 0.4.0.2++### Changed++* Sped up factor sieves. They need more space now, but the speedup is worth it, IMO.++* Raised spec-constr limit in `MoebiusInversion.Int`.++## 0.4.0.1++### Fixed++* Fixed Haddock bug.++## 0.4.0.0++### Added++* Added generalised Möbius inversion, to be continued.++## 0.3.0.0++### Added++* Added modular square roots and Chinese remainder theorem.++## 0.2.0.6++### Changed++* Performance tweaks for `powerModInteger` (~10%) and `invertMod` (~25%).++## 0.2.0.5++### Fixed++* Fix bug in `psieveFrom`.++## 0.2.0.4++### Fixed++* Fix bug in `nthPrime`.++## 0.2.0.3++### Fixed++* Fix bug in `powerMod`.++## 0.2.0.2++### Changed++* Relax bounds on `array` dependency for GHC 7.4.++## 0.2.0.1++### Fixed++* Fix copy-pasto (only relevant for GHC 7.3).++* Fix imports for GHC 7.3.++## 0.2.0.0++### Added++* Added certificates and certified testing/factorisation++## 0.1.0.2++### Fixed++* Fixed doc bugs++## 0.1.0.1++### Changed++* Elaborate on overflow, work more on native `Ints` in Eratosthenes.++## 0.1.0.0++### Added++* First release.
test-suite/Math/NumberTheory/ArithmeticFunctions/InverseTests.hs view
@@ -9,8 +9,11 @@ -- {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# OPTIONS_GHC -fconstraint-solver-iterations=0 #-}+ {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Math.NumberTheory.ArithmeticFunctions.InverseTests@@ -19,13 +22,17 @@ import Test.Tasty import Test.Tasty.HUnit+import Test.Tasty.SmallCheck as SC hiding (test)+import Test.Tasty.QuickCheck as QC hiding (Positive) import Data.Bits (Bits)+import Data.Euclidean+import Data.Semiring (Semiring) import qualified Data.Set as S+import Numeric.Natural (Natural) import Math.NumberTheory.ArithmeticFunctions import Math.NumberTheory.ArithmeticFunctions.Inverse-import Math.NumberTheory.Euclidean import Math.NumberTheory.Primes import Math.NumberTheory.Recurrences import Math.NumberTheory.TestUtils@@ -36,9 +43,28 @@ totientProperty1 :: forall a. (Euclidean a, Integral a, UniqueFactorisation a) => Positive a -> Bool totientProperty1 (Positive x) = x `S.member` asSetOfPreimages inverseTotient (totient x) +jordanProperty1+ :: (Euclidean a, Integral a, UniqueFactorisation a)+ => Power Word+ -> Positive a+ -> Bool+jordanProperty1 (Power k') (Positive x) =+ -- 'k' shouldn't be large to avoid slow tests.+ let k = 2 + k' `Prelude.mod` 20+ in x `S.member` asSetOfPreimages (inverseJordan k) (jordan k x)+ totientProperty2 :: (Euclidean a, Integral a, UniqueFactorisation a) => Positive a -> Bool totientProperty2 (Positive x) = all (== x) (S.map totient (asSetOfPreimages inverseTotient x)) +jordanProperty2+ :: (Euclidean a, Integral a, UniqueFactorisation a, Ord a)+ => Power Word+ -> Positive a+ -> Bool+jordanProperty2 (Power k') (Positive x) =+ let k = 2 + k' `Prelude.mod` 20+ in all (== x) (S.map (jordan k) (asSetOfPreimages (inverseJordan k) x))+ -- | http://oeis.org/A055506 totientCountFactorial :: [Word] totientCountFactorial =@@ -132,15 +158,74 @@ totientMax :: Word -> Word totientMax = unMaxWord . inverseTotient MaxWord +jordans5 :: [Word]+jordans5 =+ [ 1+ , 31+ , 242+ , 992+ , 3124+ , 7502+ , 16806+ , 31744+ , 58806+ , 96844+ , 161050+ , 240064+ , 371292+ , 520986+ , 756008+ , 1015808+ , 1419856+ , 1822986+ , 2476098+ , 3099008+ , 4067052+ , 4992550+ , 6436342+ , 7682048+ , 9762500+ , 11510052+ , 14289858+ , 16671552+ , 20511148+ ]++jordanSpecialCase1 :: [Assertion]+jordanSpecialCase1 = zipWith mkAssert ixs jordans5+ where+ mkAssert a b = assertEqual "should be equal" (S.singleton a) (asSetOfPreimages (inverseJordan 5) b)+ ixs = [1 .. 29]+ ------------------------------------------------------------------------------- -- Sigma sigmaProperty1 :: forall a. (Euclidean a, UniqueFactorisation a, Integral a, Enum (Prime a), Bits a) => Positive a -> Bool sigmaProperty1 (Positive x) = x `S.member` asSetOfPreimages inverseSigma (sigma 1 x) +sigmaKProperty1+ :: forall a+ . (Euclidean a, UniqueFactorisation a, Integral a, Enum (Prime a), Bits a)+ => Power Word+ -> Positive a+ -> Bool+sigmaKProperty1 (Power k') (Positive x) =+ -- 'k' shouldn't be large to avoid slow tests.+ let k = 2 + k' `Prelude.mod` 20+ in x `S.member` asSetOfPreimages (inverseSigmaK k) (sigma k x)+ sigmaProperty2 :: (Euclidean a, UniqueFactorisation a, Integral a, Enum (Prime a), Bits a) => Positive a -> Bool sigmaProperty2 (Positive x) = all (== x) (S.map (sigma 1) (asSetOfPreimages inverseSigma x)) +sigmaKProperty2+ :: (Euclidean a, UniqueFactorisation a, Integral a, Enum (Prime a), Bits a)+ => Power Word+ -> Positive a+ -> Bool+sigmaKProperty2 (Power k') (Positive x) =+ let k = 2 + k' `Prelude.mod` 20+ in all (== x) (S.map (sigma k) (asSetOfPreimages (inverseSigmaK k) x))+ -- | http://oeis.org/A055486 sigmaCountFactorial :: [Word] sigmaCountFactorial =@@ -234,9 +319,60 @@ sigmaSpecialCase4 = assertBool "200 should be in inverseSigma(sigma(200))" $ sigmaProperty1 $ Positive (200 :: Word) +sigmas5 :: [Word]+sigmas5 =+ [ 1+ , 33+ , 244+ , 1057+ , 3126+ , 8052+ , 16808+ , 33825+ , 59293+ , 103158+ , 161052+ , 257908+ , 371294+ , 554664+ , 762744+ , 1082401+ , 1419858+ , 1956669+ , 2476100+ , 3304182+ , 4101152+ , 5314716+ , 6436344+ , 8253300+ , 9768751+ , 12252702+ , 14408200+ , 17766056+ , 20511150+ ]++sigmaSpecialCase5 :: [Assertion]+sigmaSpecialCase5 = zipWith mkAssert ixs sigmas5+ where+ mkAssert a b = assertEqual "should be equal" (S.singleton a) (asSetOfPreimages (inverseSigmaK 5) b)+ ixs = [1 .. 29]+ ------------------------------------------------------------------------------- -- TestTree +-- Tests for 'Int', 'Word' are omitted because 'inverseSigmaK/inverseJordan'+-- tests would quickly oveflow in these types.+testIntegralPropertyNoLargeInverse+ :: forall bool. (SC.Testable IO bool, QC.Testable bool)+ => String -> (forall a. (Euclidean a, Semiring a, Integral a, Bits a, UniqueFactorisation a, Show a, Enum (Prime a)) => Power Word -> Positive a -> bool) -> TestTree+testIntegralPropertyNoLargeInverse name f = testGroup name+ [ SC.testProperty "smallcheck Integer" (f :: Power Word -> Positive Integer -> bool)+ , SC.testProperty "smallcheck Natural" (f :: Power Word -> Positive Natural -> bool)+ , QC.testProperty "quickcheck Integer" (f :: Power Word -> Positive Integer -> bool)+ , QC.testProperty "quickcheck Natural" (f :: Power Word -> Positive Natural -> bool)+ ]+ testSuite :: TestTree testSuite = testGroup "Inverse" [ testGroup "Totient"@@ -259,5 +395,19 @@ (zipWith (\i a -> testCase ("factorial " ++ show i) a) [1..] sigmaSpecialCases2) , testGroup "max" (zipWith (\i a -> testCase ("factorial " ++ show i) a) [1..] sigmaSpecialCases3)+ ]++ , testGroup "Jordan"+ [ testIntegralPropertyNoLargeInverse "forward" jordanProperty1+ , testIntegralPropertyNoLargeInverse "backward" jordanProperty2+ , testGroup "inverseJordan"+ (zipWith (\i test -> testCase ("inverseJordan 5" ++ show i) test) jordans5 jordanSpecialCase1)+ ]++ , testGroup "SigmaK"+ [ testIntegralPropertyNoLargeInverse "forward" sigmaKProperty1+ , testIntegralPropertyNoLargeInverse "backward" sigmaKProperty2+ , testGroup "inverseSigma"+ (zipWith (\i test -> testCase ("inverseSigma 5" ++ show i) test) sigmas5 sigmaSpecialCase5) ] ]
test-suite/Math/NumberTheory/ArithmeticFunctionsTests.hs view
@@ -9,7 +9,6 @@ {-# LANGUAGE CPP #-} -{-# OPTIONS_GHC -fno-warn-deprecations #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Math.NumberTheory.ArithmeticFunctionsTests@@ -56,6 +55,13 @@ divisorsProperty5 :: NonZero Int -> Bool divisorsProperty5 (NonZero n) = S.toAscList (runFunction divisorsA n) == sort (runFunction divisorsListA n) +-- | 'divisorsTo' matches 'divisorsA' with a filter+divisorsProperty6 :: Positive Int -> NonNegative Int -> Bool+divisorsProperty6 (Positive a) (NonNegative b) = runFunction (divisorsToA to) n == expected+ where to = a+ n = to + b+ expected = S.filter (<=to) (runFunction divisorsA n)+ -- | tau matches baseline from OEIS. tauOeis :: Assertion tauOeis = oeisAssertion "A000005" tauA@@ -68,7 +74,7 @@ -- | sigma_0 coincides with tau by definition sigmaProperty1 :: NonZero Natural -> Bool-sigmaProperty1 (NonZero n) = runFunction tauA n == runFunction (sigmaA 0) n+sigmaProperty1 (NonZero n) = runFunction tauA n == (runFunction (sigmaA 0) n :: Natural) -- | value of totient is bigger than argument sigmaProperty2 :: NonZero Natural -> Bool@@ -80,7 +86,7 @@ [ 1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24, 31, 18, 39, 20 , 42, 32, 36, 24, 60, 31, 42, 40, 56, 30, 72, 32, 63, 48, 54, 48, 91, 38 , 60, 56, 90, 42, 96, 44, 84, 78, 72, 48, 124, 57, 93, 72, 98, 54, 120- , 72, 120, 80, 90, 60, 168, 62, 96, 104, 127, 84, 144, 68, 126, 96, 144+ , 72, 120, 80, 90, 60, 168, 62, 96, 104, 127, 84, 144, 68, 126, 96, 144 :: Natural ] -- | sigma_2 matches baseline from OEIS.@@ -89,7 +95,7 @@ [ 1, 5, 10, 21, 26, 50, 50, 85, 91, 130, 122, 210, 170, 250, 260, 341, 290 , 455, 362, 546, 500, 610, 530, 850, 651, 850, 820, 1050, 842, 1300, 962 , 1365, 1220, 1450, 1300, 1911, 1370, 1810, 1700, 2210, 1682, 2500, 1850- , 2562, 2366, 2650, 2210, 3410, 2451, 3255+ , 2562, 2366, 2650, 2210, 3410, 2451, 3255 :: Natural ] -- | value of totient if even, except totient(1) and totient(2)@@ -320,6 +326,7 @@ , testSmallAndQuick "matches definition" divisorsProperty3 , testSmallAndQuick "divisors = divisorsSmall" divisorsProperty4 , testSmallAndQuick "divisors = divisorsList" divisorsProperty5+ , testSmallAndQuick "divisors = divisorsTo" divisorsProperty6 ] , testGroup "Tau" [ testCase "OEIS" tauOeis
test-suite/Math/NumberTheory/CurvesTests.hs view
@@ -16,7 +16,7 @@ import Test.Tasty import Test.Tasty.QuickCheck as QC hiding (Positive, NonNegative, generate, getNonNegative) -import GHC.TypeNats.Compat+import GHC.TypeNats (KnownNat) import Math.NumberTheory.Curves.Montgomery import Math.NumberTheory.TestUtils
+ test-suite/Math/NumberTheory/DirichletCharactersTests.hs view
@@ -0,0 +1,248 @@+-- |+-- Module: Math.NumberTheory.DirichletCharactersTests+-- Copyright: (c) 2018 Bhavik Mehta+-- License: MIT+-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+--+-- Tests for Math.NumberTheory.DirichletCharacters+--++{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}++module Math.NumberTheory.DirichletCharactersTests where++import Test.Tasty++import Data.Complex+import Data.List (genericLength)+import Data.Maybe (isJust, mapMaybe)+import Data.Proxy+import Data.Semigroup+import qualified Data.Vector as V+import Numeric.Natural++import GHC.TypeNats (SomeNat(..), someNatVal, KnownNat, natVal, sameNat)+import Data.Type.Equality++import Math.NumberTheory.ArithmeticFunctions (totient, divisorsList)+import Math.NumberTheory.DirichletCharacters+import qualified Math.NumberTheory.Moduli.Sqrt as J+import Math.NumberTheory.Moduli.Class (SomeMod(..), modulo)+import Math.NumberTheory.TestUtils (testSmallAndQuick, Positive(..))++-- | This tests property 6 from https://en.wikipedia.org/wiki/Dirichlet_character#Axiomatic_definition+dirCharOrder :: forall n. KnownNat n => DirichletCharacter n -> Bool+dirCharOrder chi = isPrincipal (totient n `stimes` chi)+ where n = natVal @n Proxy++-- | Tests wikipedia's property 3 (note 1,2,5 are essentially enforced by the type system).+testMultiplicative :: KnownNat n => DirichletCharacter n -> Natural -> Natural -> Bool+testMultiplicative chi (fromIntegral -> a) (fromIntegral -> b) = chiAB == chiAchiB+ where chi' = evalGeneral chi+ chiAB = chi' (a*b)+ chiAchiB = (<>) <$> chi' a <*> chi' b++-- | Test property 4 from wikipedia+testAtOne :: KnownNat n => DirichletCharacter n -> Bool+testAtOne chi = eval chi mempty == mempty++dirCharProperty :: (forall n. KnownNat n => DirichletCharacter n -> a) -> Positive Natural -> Natural -> a+dirCharProperty test (Positive n) i =+ case someNatVal n of+ SomeNat (Proxy :: Proxy n) -> test chi+ where chi = indexToChar @n (i `mod` totient n)++realCharProperty :: (forall n. KnownNat n => RealCharacter n -> a) -> Positive Natural -> Int -> a+realCharProperty test (Positive n) i =+ case someNatVal n of+ SomeNat (Proxy :: Proxy n) -> test chi+ where chi = chars !! (i `mod` length chars)+ chars = mapMaybe isRealCharacter [principalChar @n .. maxBound]++-- | There should be totient(n) characters+countCharacters :: Positive Natural -> Bool+countCharacters (Positive n) =+ case someNatVal n of+ SomeNat (Proxy :: Proxy n) ->+ genericLength (allChars @n) == totient n++-- | The principal character should be 1 if gcd k n is 1 and 0 otherwise+principalCase :: Positive Natural -> Positive Integer -> Bool+principalCase (Positive n) (Positive k) =+ case k `modulo` n of+ SomeMod a -> evalGeneral chi a == if gcd k (fromIntegral n) > 1+ then Zero+ else mempty+ where chi = principalChar+ InfMod{} -> False++-- | Test the orthogonality relations https://en.wikipedia.org/wiki/Dirichlet_character#Character_orthogonality+orthogonality1 :: forall n. KnownNat n => DirichletCharacter n -> Bool+orthogonality1 chi = magnitude (total - correct) < (1e-13 :: Double)+ where n = natVal @n Proxy+ total = sum [orZeroToNum toComplex (evalGeneral chi a) | a <- [0 .. maxBound]]+ correct = if isPrincipal chi+ then fromIntegral $ totient n+ else 0++orthogonality2 :: Positive Natural -> Integer -> Bool+orthogonality2 (Positive n) a =+ case a `modulo` n of+ SomeMod a' -> magnitude (total - correct) < (1e-13 :: Double)+ where total = sum [orZeroToNum toComplex (evalGeneral chi a') | chi <- allChars]+ correct = if a' == 1+ then fromIntegral $ totient n+ else 0+ InfMod {} -> False++-- | Manually confirm isRealCharacter is correct (in both directions)+realityCheck :: KnownNat n => DirichletCharacter n -> Bool+realityCheck chi = isJust (isRealCharacter chi) == isReal'+ where isReal' = and [real (evalGeneral chi t) | t <- [minBound..maxBound]]+ real Zero = True+ real (NonZero t) = t <> t == mempty++-- | Check real character evaluation matches normal evaluation+realEvalCheck :: KnownNat n => RealCharacter n -> Int -> Bool+realEvalCheck chi i' = fromIntegral (toRealFunction chi i) == (orZeroToNum toComplex (evalGeneral (getRealChar chi) i) :: Complex Double)+ where i = fromIntegral i'++-- | The jacobi character agrees with the jacobi symbol+jacobiCheck :: Positive Natural -> Bool+jacobiCheck (Positive n) =+ case someNatVal (2*n+1) of+ SomeNat (Proxy :: Proxy n) ->+ case jacobiCharacter @n of+ Just chi -> and [toRealFunction chi (fromIntegral j) == J.symbolToNum (J.jacobi j (2*n+1)) | j <- [0..2*n]]+ _ -> False++-- | Bulk evaluation agrees with pointwise evaluation+evalAllCheck :: forall n. KnownNat n => DirichletCharacter n -> Bool+evalAllCheck chi = V.generate (fromIntegral $ natVal @n Proxy) (evalGeneral chi . fromIntegral) == evalAll chi++-- | Induced characters agree with the original character.+-- (Except for when d=1, where chi(0) = 1, which is true for no other d)+inducedCheck :: forall d. KnownNat d => DirichletCharacter d -> Positive Natural -> Bool+inducedCheck chi (Positive k) =+ case someNatVal (d*k) of+ SomeNat (Proxy :: Proxy n) ->+ case induced @n chi of+ Just chi2 -> and (V.izipWith matchedValue (V.concat (replicate (fromIntegral k) (evalAll chi))) (evalAll chi2))+ Nothing -> False+ where d = natVal @d Proxy+ matchedValue i x1 x2 = if gcd (fromIntegral i) (d*k) > 1+ then x2 == Zero+ else x2 == x1++-- | Primitive checker is correct (in both directions)+primitiveCheck :: forall n. KnownNat n => DirichletCharacter n -> Bool+primitiveCheck chi = isJust (isPrimitive chi) == isPrimitive'+ where isPrimitive' = all testModulus possibleModuli+ n = fromIntegral (natVal @n Proxy) :: Int+ possibleModuli = init (divisorsList n)+ table = evalAll chi+ testModulus d = not $ null [a | a <- [1..n-1], gcd a n == 1, a `mod` d == 1 `mod` d, table V.! a /= mempty]++-- | Ensure that makePrimitive gives primitive characters+makePrimitiveCheck :: DirichletCharacter n -> Bool+makePrimitiveCheck chi = case makePrimitive chi of+ WithNat chi' -> isJust (isPrimitive (getPrimitiveChar chi'))++-- | sameNat also ensures the two new moduli are the same+makePrimitiveIdem :: DirichletCharacter n -> Bool+makePrimitiveIdem chi = case makePrimitive chi of+ WithNat (chi' :: PrimitiveCharacter n') ->+ case makePrimitive (getPrimitiveChar chi') of+ WithNat (chi'' :: PrimitiveCharacter n'') ->+ case sameNat (Proxy :: Proxy n') (Proxy :: Proxy n'') of+ Just Refl -> chi' == chi''+ Nothing -> False++orderCheck :: DirichletCharacter n -> Bool+orderCheck chi = isPrincipal (n `stimes` chi) && and [not (isPrincipal (i `stimes` chi)) | i <- [1..n-1]]+ where n = orderChar chi++fromTableCheck :: forall n. KnownNat n => DirichletCharacter n -> Bool+fromTableCheck chi = isJust (fromTable @n (evalAll chi))++-- A bunch of functions making sure that every function which can produce a character (in+-- particular by fiddling internal representation) produces a valid character+indexToCharValid :: KnownNat n => DirichletCharacter n -> Bool+indexToCharValid = validChar++principalCharValid :: Positive Natural -> Bool+principalCharValid (Positive n) =+ case someNatVal n of+ SomeNat (Proxy :: Proxy n) -> validChar (principalChar @n)++mulCharsValid :: KnownNat n => DirichletCharacter n -> DirichletCharacter n -> Bool+mulCharsValid chi1 chi2 = validChar (chi1 <> chi2)++mulCharsValid' :: Positive Natural -> Natural -> Natural -> Bool+mulCharsValid' (Positive n) i j =+ case someNatVal n of+ SomeNat (Proxy :: Proxy n) ->+ mulCharsValid (indexToChar @n (i `mod` totient n)) (indexToChar @n (j `mod` totient n))++stimesCharValid :: KnownNat n => DirichletCharacter n -> Int -> Bool+stimesCharValid chi n = validChar (n `stimes` chi)++succValid :: KnownNat n => DirichletCharacter n -> Bool+succValid = validChar . succ++inducedValid :: forall d. KnownNat d => DirichletCharacter d -> Positive Natural -> Bool+inducedValid chi (Positive k) =+ case someNatVal (d*k) of+ SomeNat (Proxy :: Proxy n) ->+ case induced @n chi of+ Just chi2 -> validChar chi2+ Nothing -> False+ where d = natVal @d Proxy++jacobiValid :: Positive Natural -> Bool+jacobiValid (Positive n) =+ case someNatVal (2*n+1) of+ SomeNat (Proxy :: Proxy n) ->+ case jacobiCharacter @n of+ Just chi -> validChar (getRealChar chi)+ _ -> False++makePrimitiveValid :: DirichletCharacter n -> Bool+makePrimitiveValid chi = case makePrimitive chi of+ WithNat chi' -> validChar (getPrimitiveChar chi')++testSuite :: TestTree+testSuite = testGroup "DirichletCharacters"+ [ testSmallAndQuick "Dirichlet characters divide the right order" (dirCharProperty dirCharOrder)+ , testSmallAndQuick "Dirichlet characters are multiplicative" (dirCharProperty testMultiplicative)+ , testSmallAndQuick "Dirichlet characters are 1 at 1" (dirCharProperty testAtOne)+ , testSmallAndQuick "Right number of Dirichlet characters" countCharacters+ , testSmallAndQuick "Principal character behaves as expected" principalCase+ , testSmallAndQuick "Orthogonality relation 1" (dirCharProperty orthogonality1)+ , testSmallAndQuick "Orthogonality relation 2" orthogonality2+ , testSmallAndQuick "Real character checking is correct" (dirCharProperty realityCheck)+ , testSmallAndQuick "Real character evaluation is accurate" (realCharProperty realEvalCheck)+ , testSmallAndQuick "Jacobi character matches symbol" jacobiCheck+ , testSmallAndQuick "Bulk evaluation matches pointwise" (dirCharProperty evalAllCheck)+ , testSmallAndQuick "Induced character is correct" (dirCharProperty inducedCheck)+ , testSmallAndQuick "Primitive character checking is correct" (dirCharProperty primitiveCheck)+ , testSmallAndQuick "makePrimitive produces primitive character" (dirCharProperty makePrimitiveCheck)+ , testSmallAndQuick "makePrimitive is idempotent" (dirCharProperty makePrimitiveIdem)+ , testSmallAndQuick "Calculates correct order" (dirCharProperty orderCheck)+ , testSmallAndQuick "Can construct from table" (dirCharProperty fromTableCheck)+ , testGroup "Creates valid characters"+ [ testSmallAndQuick "indexToChar" (dirCharProperty indexToCharValid)+ , testSmallAndQuick "principalChar" principalCharValid+ , testSmallAndQuick "mulChars" mulCharsValid'+ , testSmallAndQuick "stimesChar" (dirCharProperty stimesCharValid)+ , testSmallAndQuick "succ" (dirCharProperty succValid)+ , testSmallAndQuick "induced" (dirCharProperty inducedValid)+ , testSmallAndQuick "jacobi" jacobiValid+ , testSmallAndQuick "makePrimitive" (dirCharProperty makePrimitiveValid)+ ]+ ]
test-suite/Math/NumberTheory/EisensteinIntegersTests.hs view
@@ -1,5 +1,3 @@-{-# OPTIONS_GHC -fno-warn-type-defaults #-}- -- | -- Module: Math.NumberTheory.EisensteinIntegersTests -- Copyright: (c) 2018 Alexandre Rodrigues Baldé@@ -9,21 +7,25 @@ -- Tests for Math.NumberTheory.EisensteinIntegers -- +{-# OPTIONS_GHC -fno-warn-type-defaults #-}+ module Math.NumberTheory.EisensteinIntegersTests ( testSuite ) where +import Prelude hiding (gcd, rem, quot, quotRem)+import Data.Euclidean import Data.Maybe (fromJust, isJust)+import Data.Proxy+import Test.Tasty.QuickCheck as QC hiding (Positive, getPositive, NonNegative, generate, getNonNegative)+import Test.QuickCheck.Classes import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (Assertion, assertEqual, testCase)-import Test.Tasty.QuickCheck as QC hiding (Positive(..)) -import qualified Math.NumberTheory.Euclidean as ED import qualified Math.NumberTheory.Quadratic.EisensteinIntegers as E import Math.NumberTheory.Primes-import Math.NumberTheory.TestUtils (Positive (..),- testSmallAndQuick)+import Math.NumberTheory.TestUtils -- | Check that @signum@ and @abs@ satisfy @z == signum z * abs z@, where @z@ is -- an @EisensteinInteger@.@@ -46,40 +48,40 @@ -- | Verify that @rem@ produces a remainder smaller than the divisor with -- regards to the Euclidean domain's function. remProperty1 :: E.EisensteinInteger -> E.EisensteinInteger -> Bool-remProperty1 x y = (y == 0) || (E.norm $ x `ED.rem` y) < (E.norm y)+remProperty1 x y = (y == 0) || (E.norm $ x `rem` y) < (E.norm y) -- | Verify that @quot@ and @rem@ are what `quotRem` produces. quotRemProperty1 :: E.EisensteinInteger -> E.EisensteinInteger -> Bool quotRemProperty1 x y = (y == 0) || q == q' && r == r' where- (q, r) = ED.quotRem x y- q' = ED.quot x y- r' = ED.rem x y+ (q, r) = quotRem x y+ q' = quot x y+ r' = rem x y -- | Verify that @quotRemE@ produces the right quotient and remainder. quotRemProperty2 :: E.EisensteinInteger -> E.EisensteinInteger -> Bool-quotRemProperty2 x y = (y == 0) || (x `ED.quot` y) * y + (x `ED.rem` y) == x+quotRemProperty2 x y = (y == 0) || (x `quot` y) * y + (x `rem` y) == x -- | Verify that @gcd z1 z2@ always divides @z1@ and @z2@. gcdEProperty1 :: E.EisensteinInteger -> E.EisensteinInteger -> Bool gcdEProperty1 z1 z2 = z1 == 0 && z2 == 0- || z1 `ED.rem` z == 0 && z2 `ED.rem` z == 0+ || z1 `rem` z == 0 && z2 `rem` z == 0 where- z = ED.gcd z1 z2+ z = gcd z1 z2 -- | Verify that a common divisor of @z1, z2@ is a always divisor of @gcd z1 z2@. gcdEProperty2 :: E.EisensteinInteger -> E.EisensteinInteger -> E.EisensteinInteger -> Bool gcdEProperty2 z z1 z2 = z == 0- || (ED.gcd z1' z2') `ED.rem` z == 0+ || (gcd z1' z2') `rem` z == 0 where z1' = z * z1 z2' = z * z2 -- | A special case that tests rounding/truncating in GCD. gcdESpecialCase1 :: Assertion-gcdESpecialCase1 = assertEqual "gcd" (1 E.:+ 1) $ ED.gcd (12 E.:+ 23) (23 E.:+ 34)+gcdESpecialCase1 = assertEqual "gcd" (1 E.:+ 1) $ gcd (12 E.:+ 23) (23 E.:+ 34) findPrimesProperty1 :: Positive Int -> Bool findPrimesProperty1 (Positive index) =@@ -179,4 +181,6 @@ factoriseProperty3 , testCase "factorise 15:+12" factoriseSpecialCase1 ]+ , lawsToTest $ gcdDomainLaws (Proxy :: Proxy E.EisensteinInteger)+ , lawsToTest $ euclideanLaws (Proxy :: Proxy E.EisensteinInteger) ]
test-suite/Math/NumberTheory/EuclideanTests.hs view
@@ -4,7 +4,7 @@ -- Licence: MIT -- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com> ----- Tests for Math.NumberTheory.Euclidean+-- Tests for Math.NumberTheory.Euclidean.Coprimes -- {-# LANGUAGE CPP #-}@@ -13,7 +13,6 @@ {-# OPTIONS_GHC -fno-warn-type-defaults #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-}-{-# OPTIONS_GHC -fno-warn-deprecations #-} module Math.NumberTheory.EuclideanTests ( testSuite@@ -26,32 +25,16 @@ import Control.Arrow import Data.Bits+import Data.Euclidean import Data.Maybe import Data.Semigroup import Data.List (tails, sort) import Numeric.Natural -import Math.NumberTheory.Euclidean import Math.NumberTheory.Euclidean.Coprimes import Math.NumberTheory.Quadratic.GaussianIntegers import Math.NumberTheory.TestUtils --- | Check that 'extendedGCD' is consistent with documentation.-extendedGCDProperty :: forall a. (Bits a, Num a, GcdDomain a, Euclidean a, Ord a) => AnySign a -> AnySign a -> Bool-extendedGCDProperty (AnySign a) (AnySign b)- | isNatural a = True -- extendedGCD does not make sense for Natural- | otherwise =- u * a + v * b == d- && d == gcd a b- -- (-1) >= 0 is true for unsigned types- && (abs u < abs b || abs b <= 1 || (-1 :: a) >= 0)- && (abs v < abs a || abs a <= 1 || (-1 :: a) >= 0)- where- (d, u, v) = extendedGCD a b--isNatural :: Bits a => a -> Bool-isNatural a = isNothing (bitSizeMaybe a) && not (isSigned a)- -- | Check that numbers are coprime iff their gcd equals to 1. coprimeProperty :: (Eq a, Num a, GcdDomain a, Euclidean a) => AnySign a -> AnySign a -> Bool coprimeProperty (AnySign a) (AnySign b) = coprime a b == (gcd a b == 1)@@ -153,8 +136,7 @@ testSuite :: TestTree testSuite = testGroup "Euclidean"- [ testSameIntegralProperty "extendedGCD" extendedGCDProperty- , testSameIntegralProperty "coprime" coprimeProperty+ [ testSameIntegralProperty "coprime" coprimeProperty , testGroup "splitIntoCoprimes" [ testGroup "preserves product of factors" [ testSmallAndQuick "Natural" (splitIntoCoprimesProperty1 @Natural)
test-suite/Math/NumberTheory/GaussianIntegersTests.hs view
@@ -13,17 +13,20 @@ ( testSuite ) where +import Prelude hiding (gcd, rem) import Control.Monad (zipWithM_)+import Data.Euclidean import Data.List (groupBy, sort) import Data.Maybe (fromJust, mapMaybe)+import Data.Proxy+import Test.Tasty.QuickCheck as QC hiding (Positive, getPositive, NonNegative, generate, getNonNegative)+import Test.QuickCheck.Classes import Test.Tasty import Test.Tasty.HUnit-import Test.Tasty.QuickCheck as QC hiding (NonNegative(..), Positive(..)) -import qualified Math.NumberTheory.Euclidean as ED import Math.NumberTheory.Quadratic.GaussianIntegers import Math.NumberTheory.Moduli.Sqrt-import Math.NumberTheory.Powers (integerSquareRoot)+import Math.NumberTheory.Roots (integerSquareRoot) import Math.NumberTheory.Primes (Prime, unPrime, UniqueFactorisation(..)) import Math.NumberTheory.TestUtils @@ -132,29 +135,29 @@ -- | Verify that @rem@ produces a remainder smaller than the divisor with -- regards to the Euclidean domain's function. remProperty :: GaussianInteger -> GaussianInteger -> Bool-remProperty x y = (y == 0) || (norm $ x `ED.rem` y) < (norm y)+remProperty x y = (y == 0) || (norm $ x `rem` y) < (norm y) gcdGProperty1 :: GaussianInteger -> GaussianInteger -> Bool gcdGProperty1 z1 z2 = z1 == 0 && z2 == 0- || z1 `ED.rem` z == 0 && z2 `ED.rem` z == 0+ || z1 `rem` z == 0 && z2 `rem` z == 0 where- z = ED.gcd z1 z2+ z = gcd z1 z2 gcdGProperty2 :: GaussianInteger -> GaussianInteger -> GaussianInteger -> Bool gcdGProperty2 z z1 z2 = z == 0- || (ED.gcd z1' z2') `ED.rem` z == 0+ || (gcd z1' z2') `rem` z == 0 where z1' = z * z1 z2' = z * z2 -- | a special case that tests rounding/truncating in GCD. gcdGSpecialCase1 :: Assertion-gcdGSpecialCase1 = assertEqual "gcdG" (-1) $ ED.gcd (12 :+ 23) (23 :+ 34)+gcdGSpecialCase1 = assertEqual "gcdG" (-1) $ gcd (12 :+ 23) (23 :+ 34) gcdGSpecialCase2 :: Assertion-gcdGSpecialCase2 = assertEqual "gcdG" (0 :+ (-1)) $ ED.gcd (0 :+ 3) (2 :+ 2)+gcdGSpecialCase2 = assertEqual "gcdG" (0 :+ (-1)) $ gcd (0 :+ 3) (2 :+ 2) testSuite :: TestTree testSuite = testGroup "GaussianIntegers" $@@ -165,7 +168,7 @@ , testCase "factorise 63:+36" factoriseSpecialCase1 ] ++- map (\x -> testCase ("laziness " ++ show (fst x)) (factoriseSpecialCase2 x))+ map (\x -> testCase "laziness" (factoriseSpecialCase2 x)) lazyCases) , testSmallAndQuick "findPrime'" findPrimeProperty1@@ -184,4 +187,6 @@ , testCase "(12 :+ 23) (23 :+ 34)" gcdGSpecialCase1 , testCase "(0 :+ 3) (2 :+ 2)" gcdGSpecialCase2 ]+ , lawsToTest $ gcdDomainLaws (Proxy :: Proxy GaussianInteger)+ , lawsToTest $ euclideanLaws (Proxy :: Proxy GaussianInteger) ]
test-suite/Math/NumberTheory/Moduli/ChineseTests.hs view
@@ -10,6 +10,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE ViewPatterns #-} +{-# OPTIONS_GHC -fno-warn-deprecations #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Math.NumberTheory.Moduli.ChineseTests@@ -18,31 +19,9 @@ import Test.Tasty -import Control.Arrow-import Data.List (tails)- import Math.NumberTheory.Moduli hiding (invertMod) import Math.NumberTheory.TestUtils --- | Check that 'chineseRemainder' is defined iff modulos are coprime.--- Also check that the result is a solution of input modular equations.-chineseRemainderProperty :: [(Integer, Positive Integer)] -> Bool-chineseRemainderProperty rms' = case chineseRemainder rms of- Nothing -> not areCoprime- Just n -> areCoprime && map (n `mod`) ms == zipWith mod rs ms- where- rms = map (second getPositive) rms'- (rs, ms) = unzip rms- areCoprime = all (== 1) [ gcd m1 m2 | (m1 : m2s) <- tails ms, m2 <- m2s ]---- | Check that 'chineseRemainder' matches 'chineseRemainder2'.-chineseRemainder2Property :: Integer -> Positive Integer -> Integer -> Positive Integer -> Bool-chineseRemainder2Property r1 (Positive m1) r2 (Positive m2)- | gcd m1 m2 /= 1 = True- | otherwise = case chineseRemainder [(r1, m1), (r2, m2)] of- Nothing -> False- Just ch -> (ch - chineseRemainder2 (r1, m1) (r2, m2)) `rem` (m1 * m2) == 0- chineseCoprimeProperty :: Integer -> Positive Integer -> Integer -> Positive Integer -> Bool chineseCoprimeProperty n1 (Positive m1) n2 (Positive m2) = case gcd m1 m2 of 1 -> case chineseCoprime (n1, m1) (n2, m2) of@@ -67,8 +46,6 @@ testSuite :: TestTree testSuite = testGroup "Chinese"- [ testSmallAndQuick "chineseRemainder" chineseRemainderProperty- , testSmallAndQuick "chineseRemainder2" chineseRemainder2Property- , testSmallAndQuick "chineseCoprime" chineseCoprimeProperty+ [ testSmallAndQuick "chineseCoprime" chineseCoprimeProperty , testSmallAndQuick "chinese" chineseProperty ]
test-suite/Math/NumberTheory/Moduli/ClassTests.hs view
@@ -8,6 +8,7 @@ -- {-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-}
test-suite/Math/NumberTheory/Moduli/DiscreteLogarithmTests.hs view
@@ -11,12 +11,10 @@ import Test.Tasty import Data.Semigroup import Data.Proxy-import GHC.TypeNats.Compat+import GHC.TypeNats (SomeNat(..), someNatVal) import Math.NumberTheory.ArithmeticFunctions (totient)-import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Moduli.DiscreteLogarithm-import Math.NumberTheory.Moduli.PrimitiveRoot+import Math.NumberTheory.Moduli.Multiplicative import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.TestUtils
test-suite/Math/NumberTheory/Moduli/EquationsTests.hs view
@@ -13,12 +13,12 @@ import Test.Tasty -import Data.List+import Data.List (sort)+import Data.Mod import Data.Proxy-import GHC.TypeNats.Compat+import GHC.TypeNats (KnownNat, SomeNat(..), someNatVal) import Numeric.Natural -import Math.NumberTheory.Moduli.Class import Math.NumberTheory.Moduli.Equations import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.TestUtils
test-suite/Math/NumberTheory/Moduli/JacobiTests.hs view
@@ -23,7 +23,7 @@ import Data.Semigroup #endif -import Math.NumberTheory.Moduli hiding (invertMod)+import Math.NumberTheory.Moduli.Sqrt import Math.NumberTheory.TestUtils -- https://en.wikipedia.org/wiki/Jacobi_symbol#Properties, item 2
test-suite/Math/NumberTheory/Moduli/PrimitiveRootTests.hs view
@@ -20,17 +20,17 @@ import Test.Tasty import Test.Tasty.HUnit -import qualified Data.Set as S+import Data.Euclidean import Data.List (genericTake, genericLength) import Data.Maybe (isJust, isNothing, mapMaybe)-import Numeric.Natural+import Data.Mod import Data.Proxy-import GHC.TypeNats.Compat+import qualified Data.Set as S+import GHC.TypeNats (SomeNat(..), someNatVal)+import Numeric.Natural import Math.NumberTheory.ArithmeticFunctions (totient)-import Math.NumberTheory.Euclidean-import Math.NumberTheory.Moduli.Class-import Math.NumberTheory.Moduli.PrimitiveRoot+import Math.NumberTheory.Moduli.Multiplicative import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.Primes import Math.NumberTheory.TestUtils@@ -72,7 +72,7 @@ Nothing -> True Just cg -> case isPrimitiveRoot cg (fromIntegral n) of Nothing -> True- Just rt -> gcd (toInteger m) (getVal (multElement (unPrimitiveRoot rt))) == 1+ Just rt -> gcd m (unMod (multElement (unPrimitiveRoot rt))) == 1 isPrimitiveRootProperty1 :: AnySign Integer -> Positive Natural -> Bool isPrimitiveRootProperty1 (AnySign n) (Positive m) = case someNatVal m of
test-suite/Math/NumberTheory/Moduli/SqrtTests.hs view
@@ -25,7 +25,6 @@ import Numeric.Natural import Math.NumberTheory.Moduli hiding (invertMod)-import Math.NumberTheory.Moduli.Singleton import Math.NumberTheory.Primes (unPrime, isPrime, Prime) import Math.NumberTheory.TestUtils
− test-suite/Math/NumberTheory/Powers/CubesTests.hs
@@ -1,150 +0,0 @@--- |--- Module: Math.NumberTheory.Powers.CubesTests--- Copyright: (c) 2016 Andrew Lelechenko--- Licence: MIT--- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>------ Tests for Math.NumberTheory.Powers.Cubes-----{-# LANGUAGE CPP #-}--{-# OPTIONS_GHC -fno-warn-type-defaults #-}--module Math.NumberTheory.Powers.CubesTests- ( testSuite- ) where--import Test.Tasty-import Test.Tasty.HUnit--import Data.Maybe--import Math.NumberTheory.Powers.Cubes-import Math.NumberTheory.TestUtils--#include "MachDeps.h"---- | Check that 'integerCubeRoot' returns the largest integer @m@ with @m^3 <= n@.------ (m + 1) ^ 3 /= n && cond--- means--- (m + 1) ^ 3 > n--- but without overflow for bounded types-integerCubeRootProperty :: Integral a => AnySign a -> Bool-integerCubeRootProperty (AnySign n) = m ^ 3 <= n && (m + 1) ^ 3 /= n && cond- where- m = integerCubeRoot n- cond- | m < 0 && m == -1 = n == -1- | m < 0 = (m + 1) ^ 2 <= n `div` (m + 1)- | otherwise = (m + 1) ^ 2 >= n `div` (m + 1)---- | Specialized to trigger 'cubeRootInt''.-integerCubeRootProperty_Int :: AnySign Int -> Bool-integerCubeRootProperty_Int = integerCubeRootProperty---- | Specialized to trigger 'cubeRootWord'.-integerCubeRootProperty_Word :: AnySign Word -> Bool-integerCubeRootProperty_Word = integerCubeRootProperty---- | Specialized to trigger 'cubeRootIgr'.-integerCubeRootProperty_Integer :: AnySign Integer -> Bool-integerCubeRootProperty_Integer = integerCubeRootProperty---- | Check that 'integerCubeRoot' returns the largest integer @m@ with @m^3 <= n@, , where @n@ has form @k@^3-1.-integerCubeRootProperty2 :: Integral a => AnySign a -> Bool-integerCubeRootProperty2 (AnySign k) = k == 0 || (m ^ 3 <= n && (m + 1) ^ 3 /= n && cond)- where- n = k ^ 3 - 1- m = integerCubeRoot n- cond- | m < 0 && m == -1 = n == -1- | m < 0 = (m + 1) ^ 2 <= n `div` (m + 1)- | otherwise = (m + 1) ^ 2 >= n `div` (m + 1)---- | Specialized to trigger 'cubeRootInt''.-integerCubeRootProperty2_Int :: AnySign Int -> Bool-integerCubeRootProperty2_Int = integerCubeRootProperty2---- | Specialized to trigger 'cubeRootWord'.-integerCubeRootProperty2_Word :: AnySign Word -> Bool-integerCubeRootProperty2_Word = integerCubeRootProperty2--#if WORD_SIZE_IN_BITS == 64---- | Check that 'integerCubeRoot' of 2^63-1 is 2^21-1, not 2^21.-integerCubeRootSpecialCase1_Int :: Assertion-integerCubeRootSpecialCase1_Int =- assertEqual "integerCubeRoot" (integerCubeRoot (maxBound :: Int)) (2 ^ 21 - 1)---- | Check that 'integerCubeRoot' of 2^63-1 is 2^21-1, not 2^21.-integerCubeRootSpecialCase1_Word :: Assertion-integerCubeRootSpecialCase1_Word =- assertEqual "integerCubeRoot" (integerCubeRoot (maxBound `div` 2 :: Word)) (2 ^ 21 - 1)---- | Check that 'integerCubeRoot' of 2^64-1 is 2642245.-integerCubeRootSpecialCase2 :: Assertion-integerCubeRootSpecialCase2 =- assertEqual "integerCubeRoot" (integerCubeRoot (maxBound :: Word)) 2642245--#endif---- | Check that 'integerCubeRoot'' returns the largest integer @m@ with @m^3 <= n@.-integerCubeRoot'Property :: Integral a => NonNegative a -> Bool-integerCubeRoot'Property (NonNegative n) = m ^ 3 <= n && (m + 1) ^ 3 /= n && (m + 1) ^ 2 >= n `div` (m + 1)- where- m = integerCubeRoot' n---- | Check that the number 'isCube' iff its 'integerCubeRoot' is exact.-isCubeProperty :: Integral a => AnySign a -> Bool-isCubeProperty (AnySign n) = (n /= m ^ 3 && not t) || (n == m ^ 3 && t)- where- t = isCube n- m = integerCubeRoot n---- | Check that the number 'isCube'' iff its 'integerCubeRoot'' is exact.-isCube'Property :: Integral a => NonNegative a -> Bool-isCube'Property (NonNegative n) = (n /= m ^ 3 && not t) || (n == m ^ 3 && t)- where- t = isCube' n- m = integerCubeRoot' n---- | Check that 'exactCubeRoot' returns an exact integer cubic root--- and is consistent with 'isCube'.-exactCubeRootProperty :: Integral a => AnySign a -> Bool-exactCubeRootProperty (AnySign n) = case exactCubeRoot n of- Nothing -> not (isCube n)- Just m -> isCube n && n == m ^ 3---- | Check that 'isPossibleCube' is consistent with 'exactCubeRoot'.-isPossibleCubeProperty :: Integral a => NonNegative a -> Bool-isPossibleCubeProperty (NonNegative n) = t || not t && isNothing m- where- t = isPossibleCube n- m = exactCubeRoot n--testSuite :: TestTree-testSuite = testGroup "Cubes"- [ testGroup "integerCubeRoot"- [ testIntegralProperty "generic" integerCubeRootProperty- , testSmallAndQuick "generic Int" integerCubeRootProperty_Int- , testSmallAndQuick "generic Word" integerCubeRootProperty_Word- , testSmallAndQuick "generic Integer" integerCubeRootProperty_Integer-- , testIntegralProperty "almost cube" integerCubeRootProperty2- , testSmallAndQuick "almost cube Int" integerCubeRootProperty2_Int- , testSmallAndQuick "almost cube Word" integerCubeRootProperty2_Word--#if WORD_SIZE_IN_BITS == 64- , testCase "maxBound :: Int" integerCubeRootSpecialCase1_Int- , testCase "maxBound / 2 :: Word" integerCubeRootSpecialCase1_Word- , testCase "maxBound :: Word" integerCubeRootSpecialCase2-#endif- ]- , testIntegralProperty "integerCubeRoot'" integerCubeRoot'Property- , testIntegralProperty "isCube" isCubeProperty- , testIntegralProperty "isCube'" isCube'Property- , testIntegralProperty "exactCubeRoot" exactCubeRootProperty- , testIntegralProperty "isPossibleCube" isPossibleCubeProperty- ]
− test-suite/Math/NumberTheory/Powers/FourthTests.hs
@@ -1,142 +0,0 @@--- |--- Module: Math.NumberTheory.Powers.FourthTests--- Copyright: (c) 2016 Andrew Lelechenko--- Licence: MIT--- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>------ Tests for Math.NumberTheory.Powers.Fourth-----{-# LANGUAGE CPP #-}--{-# OPTIONS_GHC -fno-warn-type-defaults #-}--module Math.NumberTheory.Powers.FourthTests- ( testSuite- ) where--import Test.Tasty-import Test.Tasty.HUnit--import Data.Maybe--import Math.NumberTheory.Powers.Fourth-import Math.NumberTheory.TestUtils--#include "MachDeps.h"---- | Check that 'integerFourthRoot' returns the largest integer @m@ with @m^4 <= n@.------ (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)--- means--- (m + 1) ^ 4 > n--- but without overflow for bounded types-integerFourthRootProperty :: Integral a => NonNegative a -> Bool-integerFourthRootProperty (NonNegative n) = m >= 0 && m ^ 4 <= n && (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)- where- m = integerFourthRoot n---- | Specialized to trigger 'biSqrtInt'.-integerFourthRootProperty_Int :: NonNegative Int -> Bool-integerFourthRootProperty_Int = integerFourthRootProperty---- | Specialized to trigger 'biSqrtWord'.-integerFourthRootProperty_Word :: NonNegative Word -> Bool-integerFourthRootProperty_Word = integerFourthRootProperty---- | Specialized to trigger 'biSqrtIgr'.-integerFourthRootProperty_Integer :: NonNegative Integer -> Bool-integerFourthRootProperty_Integer = integerFourthRootProperty---- | Check that 'integerFourthRoot' returns the largest integer @m@ with @m^4 <= n@, , where @n@ has form @k@^4-1.-integerFourthRootProperty2 :: Integral a => Positive a -> Bool-integerFourthRootProperty2 (Positive k) = n < 0 || m >= 0 && m ^ 4 <= n && (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)- where- n = k ^ 4 - 1- m = integerFourthRoot n---- | Specialized to trigger 'biSqrtInt.-integerFourthRootProperty2_Int :: Positive Int -> Bool-integerFourthRootProperty2_Int = integerFourthRootProperty2---- | Specialized to trigger 'biSqrtWord'.-integerFourthRootProperty2_Word :: Positive Word -> Bool-integerFourthRootProperty2_Word = integerFourthRootProperty2--#if WORD_SIZE_IN_BITS == 64---- | Check that 'integerFourthRoot' of 2^60-1 is 2^15-1, not 2^15.-integerFourthRootSpecialCase1_Int :: Assertion-integerFourthRootSpecialCase1_Int =- assertEqual "integerFourthRoot" (integerFourthRoot (maxBound `div` 8 :: Int)) (2 ^ 15 - 1)---- | Check that 'integerFourthRoot' of 2^60-1 is 2^15-1, not 2^15.-integerFourthRootSpecialCase1_Word :: Assertion-integerFourthRootSpecialCase1_Word =- assertEqual "integerFourthRoot" (integerFourthRoot (maxBound `div` 16 :: Word)) (2 ^ 15 - 1)---- | Check that 'integerFourthRoot' of 2^64-1 is 2^16-1, not 2^16.-integerFourthRootSpecialCase2 :: Assertion-integerFourthRootSpecialCase2 =- assertEqual "integerFourthRoot" (integerFourthRoot (maxBound :: Word)) (2 ^ 16 - 1)--#endif---- | Check that 'integerFourthRoot'' returns the largest integer @m@ with @m^4 <= n@.-integerFourthRoot'Property :: Integral a => NonNegative a -> Bool-integerFourthRoot'Property (NonNegative n) = m >= 0 && m ^ 4 <= n && (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)- where- m = integerFourthRoot' n---- | Check that the number 'isFourthPower' iff its 'integerFourthRoot' is exact.-isFourthPowerProperty :: Integral a => AnySign a -> Bool-isFourthPowerProperty (AnySign n) = (n < 0 && not t) || (n /= m ^ 4 && not t) || (n == m ^ 4 && t)- where- t = isFourthPower n- m = integerFourthRoot n---- | Check that the number 'isFourthPower'' iff its 'integerFourthRoot'' is exact.-isFourthPower'Property :: Integral a => NonNegative a -> Bool-isFourthPower'Property (NonNegative n) = (n /= m ^ 4 && not t) || (n == m ^ 4 && t)- where- t = isFourthPower' n- m = integerFourthRoot' n---- | Check that 'exactFourthRoot' returns an exact integer root of fourth power--- and is consistent with 'isFourthPower'.-exactFourthRootProperty :: Integral a => AnySign a -> Bool-exactFourthRootProperty (AnySign n) = case exactFourthRoot n of- Nothing -> not (isFourthPower n)- Just m -> isFourthPower n && n == m ^ 4---- | Check that 'isPossibleFourthPower' is consistent with 'exactFourthRoot'.-isPossibleFourthPowerProperty :: Integral a => NonNegative a -> Bool-isPossibleFourthPowerProperty (NonNegative n) = t || not t && isNothing m- where- t = isPossibleFourthPower n- m = exactFourthRoot n--testSuite :: TestTree-testSuite = testGroup "Fourth"- [ testGroup "integerFourthRoot"- [ testIntegralProperty "generic" integerFourthRootProperty- , testSmallAndQuick "generic Int" integerFourthRootProperty_Int- , testSmallAndQuick "generic Word" integerFourthRootProperty_Word- , testSmallAndQuick "generic Integer" integerFourthRootProperty_Integer-- , testIntegralProperty "almost Fourth" integerFourthRootProperty2- , testSmallAndQuick "almost Fourth Int" integerFourthRootProperty2_Int- , testSmallAndQuick "almost Fourth Word" integerFourthRootProperty2_Word--#if WORD_SIZE_IN_BITS == 64- , testCase "maxBound / 8 :: Int" integerFourthRootSpecialCase1_Int- , testCase "maxBound / 16 :: Word" integerFourthRootSpecialCase1_Word- , testCase "maxBound :: Word" integerFourthRootSpecialCase2-#endif- ]- , testIntegralProperty "integerFourthRoot'" integerFourthRoot'Property- , testIntegralProperty "isFourthPower" isFourthPowerProperty- , testIntegralProperty "isFourthPower'" isFourthPower'Property- , testIntegralProperty "exactFourthRoot" exactFourthRootProperty- , testIntegralProperty "isPossibleFourthPower" isPossibleFourthPowerProperty- ]
− test-suite/Math/NumberTheory/Powers/GeneralTests.hs
@@ -1,127 +0,0 @@--- |--- Module: Math.NumberTheory.Powers.GeneralTests--- Copyright: (c) 2016 Andrew Lelechenko--- Licence: MIT--- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>------ Tests for Math.NumberTheory.Powers.General-----{-# LANGUAGE CPP #-}--{-# OPTIONS_GHC -fno-warn-type-defaults #-}--module Math.NumberTheory.Powers.GeneralTests- ( testSuite- ) where--import Test.Tasty-import Test.Tasty.HUnit--import Math.NumberTheory.Powers.General-import Math.NumberTheory.TestUtils---- | Check that 'integerRoot' @pow@ returns the largest integer @m@ with @m^pow <= n@.-integerRootProperty :: (Integral a, Integral b) => AnySign a -> Power b -> Bool-integerRootProperty (AnySign n) (Power pow) = (even pow && n < 0)- || (toInteger root ^ pow <= toInteger n && toInteger n < toInteger (root + 1) ^ pow)- where- root = integerRoot pow n---- | Check that the number 'isKthPower' iff its 'integerRoot' is exact.-isKthPowerProperty :: (Integral a, Integral b) => AnySign a -> Power b -> Bool-isKthPowerProperty (AnySign n) (Power pow) = (even pow && n < 0 && not t) || (n /= root ^ pow && not t) || (n == root ^ pow && t)- where- t = isKthPower pow n- root = integerRoot pow n---- | Check that 'exactRoot' returns an exact integer root--- and is consistent with 'isKthPower'.-exactRootProperty :: (Integral a, Integral b) => AnySign a -> Power b -> Bool-exactRootProperty (AnySign n) (Power pow) = case exactRoot pow n of- Nothing -> not (isKthPower pow n)- Just root -> isKthPower pow n && n == root ^ pow---- | Check that 'isPerfectPower' is consistent with 'highestPower'.-isPerfectPowerProperty :: Integral a => AnySign a -> Bool-isPerfectPowerProperty (AnySign n) = (k > 1 && t) || (k == 1 && not t)- where- t = isPerfectPower n- (_, k) = highestPower n---- | Check that the first component of 'highestPower' is square-free.-highestPowerProperty :: Integral a => AnySign a -> Bool-highestPowerProperty (AnySign n) = (n + 1 `elem` [0, 1, 2] && k == 3) || (b ^ k == n && b' == b && k' == 1)- where- (b, k) = highestPower n- (b', k') = highestPower b---- | Check that 'largePFPower' is consistent with documentation.-largePFPowerProperty :: Positive Integer -> Integer -> Bool-largePFPowerProperty (Positive bd) n = bd == 1 || b == 0 || d' /= 0 || n <= b * d * d || any (\p -> gcd n p > 1) [2..bd] || b ^ k == n- where- (b, k) = largePFPower bd n- (d, d') = bd `quotRem` b--highestPowerSpecialCases :: [Assertion]-highestPowerSpecialCases =- -- Freezes before d44a13b.- [ a ( 1013582159576576- , 1013582159576576- , 1)- -- Freezes before d44a13b.- , a ( 1013582159576576 ^ 7- , 1013582159576576- , 7)-- , a ( -2 ^ 63 :: Int- , -2 :: Int- , 63)-- , a ( (2 ^ 63 - 1) ^ 21- , 2 ^ 63 - 1- , 21)-- , a ( 576116746989720969230211509779286598589421531472851155101032940901763389787901933902294777750323196846498573545522289802689311975294763847414975335235584- , 576116746989720969230211509779286598589421531472851155101032940901763389787901933902294777750323196846498573545522289802689311975294763847414975335235584- , 1)-- , a ( -340282366920938463500268095579187314689- , -340282366920938463500268095579187314689- , 1)-- , a ( 268398749 :: Int- , 268398749 :: Int- , 1)-- , a ( 118372752099 :: Int- , 118372752099 :: Int- , 1)-- , a ( 1409777209 :: Int- , 37547 :: Int- , 2)-- , a ( -6277101735386680764856636523970481806547819498980467802113- , -18446744073709551617- , 3)-- , a ( -18446744073709551619 ^ 5- , -18446744073709551619- , 5)- ]- where- a (n, b, k) = assertEqual "highestPower" (b, k) (highestPower n)--testSuite :: TestTree-testSuite = testGroup "General"- [ testIntegral2Property "integerRoot" integerRootProperty- , testIntegral2Property "isKthPower" isKthPowerProperty- , testIntegral2Property "exactRoot" exactRootProperty- , testIntegralProperty "isPerfectPower" isPerfectPowerProperty- , testGroup "highestPower"- ( testIntegralProperty "highestPower" highestPowerProperty- : zipWith (\i a -> testCase ("special case " ++ show i) a) [1..] highestPowerSpecialCases- )- , testSmallAndQuick "largePFPower" largePFPowerProperty- ]
test-suite/Math/NumberTheory/Powers/ModularTests.hs view
@@ -53,11 +53,11 @@ -- | Specialized to trigger 'powModInteger'. powModProperty_Integer :: AnySign Integer -> NonNegative Integer -> Positive Integer -> Bool-powModProperty_Integer (AnySign b) (NonNegative e) (Positive m) = powMod b e m == fromInteger (powMod' (fromIntegral b) (fromIntegral e) (fromIntegral m))+powModProperty_Integer (AnySign b) (NonNegative e) (Positive m) = powMod b e m == fromInteger (powMod' b (fromIntegral e) m) -- | Specialized to trigger 'powModNatural'. powModProperty_Natural :: AnySign Natural -> NonNegative Natural -> Positive Natural -> Bool-powModProperty_Natural (AnySign b) (NonNegative e) (Positive m) = powMod b e m == fromInteger (powMod' (fromIntegral b) (fromIntegral e) (fromIntegral m))+powModProperty_Natural (AnySign b) (NonNegative e) (Positive m) = powMod b e m == fromInteger (powMod' (fromIntegral b) e (fromIntegral m)) #if WORD_SIZE_IN_BITS == 64 -- | Large modulo m such that m^2 overflows.
− test-suite/Math/NumberTheory/Powers/SquaresTests.hs
@@ -1,160 +0,0 @@--- |--- Module: Math.NumberTheory.Powers.SquaresTests--- Copyright: (c) 2016 Andrew Lelechenko--- Licence: MIT--- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>------ Tests for Math.NumberTheory.Powers.Squares-----{-# LANGUAGE CPP #-}--{-# OPTIONS_GHC -fno-warn-type-defaults #-}--module Math.NumberTheory.Powers.SquaresTests- ( testSuite- ) where--import Test.Tasty-import Test.Tasty.HUnit--import Data.Maybe--import Math.NumberTheory.Powers.Squares-import Math.NumberTheory.TestUtils--#include "MachDeps.h"---- | Check that 'integerSquareRoot' returns the largest integer @m@ with @m*m <= n@.------ (m + 1) ^ 2 /= n && m + 1 >= n `div` (m + 1)--- means--- (m + 1) ^ 2 > n--- but without overflow for bounded types-integerSquareRootProperty :: Integral a => NonNegative a -> Bool-integerSquareRootProperty (NonNegative n) = m >=0 && m * m <= n && (m + 1) ^ 2 /= n && m + 1 >= n `div` (m + 1)- where- m = integerSquareRoot n---- | Specialized to trigger 'isqrtInt''.-integerSquareRootProperty_Int :: NonNegative Int -> Bool-integerSquareRootProperty_Int = integerSquareRootProperty---- | Specialized to trigger 'isqrtWord'.-integerSquareRootProperty_Word :: NonNegative Word -> Bool-integerSquareRootProperty_Word = integerSquareRootProperty---- | Specialized to trigger 'isqrtInteger'.-integerSquareRootProperty_Integer :: NonNegative Integer -> Bool-integerSquareRootProperty_Integer = integerSquareRootProperty---- | Check that 'integerSquareRoot' returns the largest integer @m@ with @m*m <= n@, where @n@ has form @k@^2-1.-integerSquareRootProperty2 :: Integral a => Positive a -> Bool-integerSquareRootProperty2 (Positive k) = n < 0- || m >=0 && m * m <= n && (m + 1) ^ 2 /= n && m + 1 >= n `div` (m + 1)- where- n = k ^ 2 - 1- m = integerSquareRoot n---- | Specialized to trigger 'isqrtInt''.-integerSquareRootProperty2_Int :: Positive Int -> Bool-integerSquareRootProperty2_Int = integerSquareRootProperty2---- | Specialized to trigger 'isqrtWord'.-integerSquareRootProperty2_Word :: Positive Word -> Bool-integerSquareRootProperty2_Word = integerSquareRootProperty2---- | Specialized to trigger 'isqrtInteger'.-integerSquareRootProperty2_Integer :: Positive Integer -> Bool-integerSquareRootProperty2_Integer = integerSquareRootProperty2--#if WORD_SIZE_IN_BITS == 64---- | Check that 'integerSquareRoot' of 2^62-1 is 2^31-1, not 2^31.-integerSquareRootSpecialCase1_Int :: Assertion-integerSquareRootSpecialCase1_Int =- assertEqual "integerSquareRoot" (integerSquareRoot (maxBound `div` 2 :: Int)) (2 ^ 31 - 1)---- | Check that 'integerSquareRoot' of 2^62-1 is 2^31-1, not 2^31.-integerSquareRootSpecialCase1_Word :: Assertion-integerSquareRootSpecialCase1_Word =- assertEqual "integerSquareRoot" (integerSquareRoot (maxBound `div` 4 :: Word)) (2 ^ 31 - 1)---- | Check that 'integerSquareRoot' of 2^64-1 is 2^32-1, not 2^32.-integerSquareRootSpecialCase2 :: Assertion-integerSquareRootSpecialCase2 =- assertEqual "integerSquareRoot" (integerSquareRoot (maxBound :: Word)) (2 ^ 32 - 1)--#endif---- | Check that 'integerSquareRoot'' returns the largest integer @r@ with @r*r <= n@.-integerSquareRoot'Property :: Integral a => NonNegative a -> Bool-integerSquareRoot'Property (NonNegative n) = m >=0 && m * m <= n && (m + 1) ^ 2 /= n && m + 1 >= n `div` (m + 1)- where- m = integerSquareRoot' n---- | Check that the number 'isSquare' iff its 'integerSquareRoot' is exact.-isSquareProperty :: Integral a => AnySign a -> Bool-isSquareProperty (AnySign n) = (n < 0 && not t) || (n /= m * m && not t) || (n == m * m && t)- where- t = isSquare n- m = integerSquareRoot n---- | Check that the number 'isSquare'' iff its 'integerSquareRoot'' is exact.-isSquare'Property :: Integral a => NonNegative a -> Bool-isSquare'Property (NonNegative n) = (n /= m * m && not t) || (n == m * m && t)- where- t = isSquare' n- m = integerSquareRoot' n---- | Check that 'exactSquareRoot' returns an exact integer square root--- and is consistent with 'isSquare'.-exactSquareRootProperty :: Integral a => AnySign a -> Bool-exactSquareRootProperty (AnySign n) = case exactSquareRoot n of- Nothing -> not (isSquare n)- Just m -> isSquare n && n == m * m---- | Check that 'isPossibleSquare' is consistent with 'exactSquareRoot'--- and that 'isPossibleSquare2' is a refinement of 'isPossibleSquare'.-isPossibleSquareProperty :: Integral a => NonNegative a -> Bool-isPossibleSquareProperty (NonNegative n) = t || not t && not t2 && isNothing m- where- t = isPossibleSquare n- t2 = isPossibleSquare2 n- m = exactSquareRoot n---- | Check that 'isPossibleSquare2'' is consistent with 'exactSquareRoot'.-isPossibleSquare2Property :: Integral a => NonNegative a -> Bool-isPossibleSquare2Property (NonNegative n) = t || not t && isNothing m- where- t = isPossibleSquare2 n- m = exactSquareRoot n---testSuite :: TestTree-testSuite = testGroup "Squares"- [ testGroup "integerSquareRoot"- [ testIntegralProperty "generic" integerSquareRootProperty- , testSmallAndQuick "generic Int" integerSquareRootProperty_Int- , testSmallAndQuick "generic Word" integerSquareRootProperty_Word- , testSmallAndQuick "generic Integer" integerSquareRootProperty_Integer-- , testIntegralProperty "almost square" integerSquareRootProperty2- , testSmallAndQuick "almost square Int" integerSquareRootProperty2_Int- , testSmallAndQuick "almost square Word" integerSquareRootProperty2_Word- , testSmallAndQuick "almost square Integer" integerSquareRootProperty2_Integer--#if WORD_SIZE_IN_BITS == 64- , testCase "maxBound / 2 :: Int" integerSquareRootSpecialCase1_Int- , testCase "maxBound / 4 :: Word" integerSquareRootSpecialCase1_Word- , testCase "maxBound :: Word" integerSquareRootSpecialCase2-#endif- ]-- , testIntegralProperty "integerSquareRoot'" integerSquareRoot'Property- , testIntegralProperty "isSquare" isSquareProperty- , testIntegralProperty "isSquare'" isSquare'Property- , testIntegralProperty "exactSquareRoot" exactSquareRootProperty- , testIntegralProperty "isPossibleSquare" isPossibleSquareProperty- , testIntegralProperty "isPossibleSquare2" isPossibleSquare2Property- ]
test-suite/Math/NumberTheory/PrefactoredTests.hs view
@@ -18,10 +18,10 @@ import Test.Tasty import Control.Arrow (second)+import Data.Euclidean import Data.List (tails) import Numeric.Natural -import Math.NumberTheory.Euclidean import Math.NumberTheory.Euclidean.Coprimes import Math.NumberTheory.Prefactored import Math.NumberTheory.TestUtils
test-suite/Math/NumberTheory/Primes/CountingTests.hs view
@@ -77,30 +77,27 @@ -- | Check that values of 'nthPrime' are positive.-nthPrimeProperty1 :: Positive Integer -> Bool-nthPrimeProperty1 (Positive n) = n > nthPrimeMaxArg- || unPrime (nthPrime n) > 0+nthPrimeProperty1 :: Positive Int -> Bool+nthPrimeProperty1 (Positive n) = unPrime (nthPrime n) > 0 -- | Check that 'nthPrime' is monotonically increasing function.-nthPrimeProperty2 :: Positive Integer -> Positive Integer -> Bool+nthPrimeProperty2 :: Positive Int -> Positive Int -> Bool nthPrimeProperty2 (Positive n1) (Positive n2)- = n1 > nthPrimeMaxArg- || n2 > nthPrimeMaxArg- || n1 <= n2 && p1 <= p2+ = n1 <= n2 && p1 <= p2 || n1 > n2 && p1 >= p2 where p1 = nthPrime n1 p2 = nthPrime n2 -- | Check that values of 'nthPrime' are prime.-nthPrimeProperty3 :: Positive Integer -> Bool+nthPrimeProperty3 :: Positive Int -> Bool nthPrimeProperty3 (Positive n) = isPrime $ unPrime $ nthPrime n -- | Check tabulated values. nthPrimeSpecialCases :: [Assertion] nthPrimeSpecialCases = map a table where- a (n, m) = assertBool "nthPrime" $ n > unPrime (nthPrime m)+ a (n, m) = assertBool "nthPrime" $ n > unPrime (nthPrime (fromInteger m)) -- | Check that values of 'approxPrimeCount' are non-negative.@@ -120,7 +117,7 @@ -- | Check that 'nthPrimeApprox' is consistent with 'nthPrimeApproxUnderestimateLimit'. nthPrimeApproxProperty2 :: Positive Integer -> Bool nthPrimeApproxProperty2 (Positive a) = a >= nthPrimeApproxUnderestimateLimit- || toInteger (nthPrimeApprox a) <= unPrime (nthPrime (toInteger a))+ || nthPrimeApprox a <= unPrime (nthPrime (fromInteger a)) testSuite :: TestTree
test-suite/Math/NumberTheory/Primes/FactorisationTests.hs view
@@ -26,7 +26,16 @@ specialCases :: [(Integer, [(Integer, Word)])] specialCases =- [ (4181339589500970917,[(15034813,1),(278110515209,1)])+ [ (35,[(5,1),(7,1)])+ , (75,[(3,1),(5,2)])+ , (65521^2,[(65521,2)])+ , (65537^2,[(65537,2)])+ , (2147483647, [(2147483647, 1)])+ , (4294967291, [(4294967291, 1)])+ , (3 * 5^2 * 7^21, [(3,1), (5,2), (7, 21)])+ , (9223372036854775783, [(9223372036854775783, 1)])+ , (18446744073709551557, [(18446744073709551557, 1)])+ , (4181339589500970917,[(15034813,1),(278110515209,1)]) , (4181339589500970918,[(2,1),(3,2),(7,1),(2595773,1),(12784336241,1)]) , (2227144715990344929,[(3,1),(317,1),(17381911,1),(134731889,1)]) , (10489674846272137811130167281,[(1312601,1),(9555017,1),(836368815445393,1)])@@ -58,6 +67,14 @@ ) ] +shortenNumber :: Integer -> String+shortenNumber n+ | l <= 10 = xs+ | otherwise = take 5 xs ++ "..." ++ drop (l - 5) xs+ where+ xs = show n+ l = length xs+ factoriseProperty1 :: Assertion factoriseProperty1 = assertEqual "0" [] (factorise (1 :: Int)) @@ -68,7 +85,7 @@ factoriseProperty3 (Positive n) = all (isJust . isPrime . unPrime . fst) (factorise n) factoriseProperty4 :: Positive Integer -> Bool-factoriseProperty4 (Positive n) = bases == nub (sort bases)+factoriseProperty4 (Positive n) = sort bases == nub (sort bases) where bases = map fst $ factorise n @@ -87,10 +104,10 @@ [ testCase "0" factoriseProperty1 , testSmallAndQuick "negate" factoriseProperty2 , testSmallAndQuick "bases are prime" factoriseProperty3- , testSmallAndQuick "bases are ordered and distinct" factoriseProperty4+ , testSmallAndQuick "bases are distinct" factoriseProperty4 , testSmallAndQuick "factorback" factoriseProperty5 ] ++- map (\x -> testCase ("special case " ++ show (fst x)) (factoriseProperty6 x)) specialCases+ map (\x -> testCase ("special case " ++ shortenNumber (fst x)) (factoriseProperty6 x)) specialCases ++- map (\x -> testCase ("laziness " ++ show (fst x)) (factoriseProperty7 x)) lazyCases+ map (\x -> testCase ("laziness " ++ shortenNumber (fst x)) (factoriseProperty7 x)) lazyCases ]
test-suite/Math/NumberTheory/Primes/SequenceTests.hs view
@@ -7,6 +7,7 @@ ) where import Test.Tasty+import Test.Tasty.HUnit import Data.Bits import Data.Maybe@@ -35,7 +36,7 @@ => Proxy a -> Int -> Bool-toEnumProperty _ n = n <= 0 || unPrime (toEnum n :: Prime a) == fromInteger (unPrime (nthPrime (toInteger n)))+toEnumProperty _ n = n <= 0 || unPrime (toEnum n :: Prime a) == fromInteger (unPrime (nthPrime n)) fromEnumProperty :: (Enum (Prime a), Integral a)@@ -55,6 +56,29 @@ -> Bool predProperty p = unPrime p <= 2 || all (isNothing . isPrime) [unPrime (pred p) + 1 .. unPrime p - 1] +enumFrom2To2 :: Assertion+enumFrom2To2 = assertEqual "should be equal"+ [two]+ [two..two]+ where+ two = minBound :: Prime Word++enumFrom65500To65600 :: Assertion+enumFrom65500To65600 = assertEqual "should be equal"+ [65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, 65587, 65599]+ (map unPrime [low..high])+ where+ low = nextPrime (65500 :: Word)+ high = precPrime (65600 :: Word)++enumFrom2To100000 :: Assertion+enumFrom2To100000 = assertEqual "should be equal"+ (takeWhile (<= high) [low..])+ [low..high]+ where+ low = minBound :: Prime Word+ high = precPrime (100000 :: Word)+ enumFromProperty :: (Ord a, Enum (Prime a)) => Prime a@@ -119,6 +143,9 @@ , testSmallAndQuick "Integer" (predProperty @Integer) , testSmallAndQuick "Natural" (predProperty @Natural) ]+ , testCase "[2..2] == [2]" enumFrom2To2+ , testCase "[65500..65600]" enumFrom65500To65600+ , testCase "[2..100000]" enumFrom2To100000 , testGroup "enumFrom" [ testSmallAndQuick "Int" (enumFromProperty @Int) , testSmallAndQuick "Word" (enumFromProperty @Word)
test-suite/Math/NumberTheory/Primes/SieveTests.hs view
@@ -8,10 +8,10 @@ -- {-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-}-{-# OPTIONS_GHC -fno-warn-deprecations #-} module Math.NumberTheory.Primes.SieveTests ( testSuite@@ -22,13 +22,13 @@ import Test.Tasty import Test.Tasty.HUnit +import Data.Bits import Data.Int import Data.Proxy (Proxy(..)) import Data.Word import Numeric.Natural (Natural) -import Math.NumberTheory.Primes (Prime, unPrime)-import Math.NumberTheory.Primes.Sieve+import Math.NumberTheory.Primes (Prime, unPrime, primes, nextPrime, precPrime, UniqueFactorisation) import Math.NumberTheory.Primes.Testing import Math.NumberTheory.TestUtils @@ -38,9 +38,6 @@ lim2 :: Num a => a lim2 = 100000 -lim3 :: Num a => a-lim3 = 1000- -- | Check that 'primes' matches 'isPrime'. primesProperty1 :: forall a. (Integral a, Show a) => Proxy a -> Assertion primesProperty1 _ = assertEqual "primes matches isPrime"@@ -55,37 +52,21 @@ -- | Check that 'primeList' from 'primeSieve' matches truncated 'primes'. primeSieveProperty1 :: AnySign Integer -> Bool primeSieveProperty1 (AnySign highBound')- = primeList (primeSieve highBound)- == takeWhile ((<= (highBound `max` 7)) . unPrime) primes+ = [nextPrime 2 .. precPrime highBound]+ == takeWhile (\p -> unPrime p <= highBound) primes where- highBound = highBound' `rem` lim1+ highBound = max 2 (highBound' `rem` lim1) -- | Check that 'primeList' from 'psieveList' matches 'primes'.-psieveListProperty1 :: forall a. (Integral a, Show a) => Proxy a -> Assertion+psieveListProperty1 :: forall a. (Integral a, Show a, Enum (Prime a), Bits a, UniqueFactorisation a) => Proxy a -> Assertion psieveListProperty1 _ = assertEqual "primes == primeList . psieveList" (take lim2 primes :: [Prime a])- (take lim2 $ concatMap primeList psieveList)+ (take lim2 [nextPrime 1..]) -psieveListProperty2 :: forall a. (Integral a, Show a) => Proxy a -> Assertion+psieveListProperty2 :: forall a. (Integral a, Bounded a, Show a) => Proxy a -> Assertion psieveListProperty2 _ = assertEqual "primes == primeList . psieveList"- (primes :: [Prime a])- (concat $ takeWhile (not . null) $ map primeList psieveList)---- | Check that 'sieveFrom' matches 'primeList' of 'psieveFrom'.-sieveFromProperty1 :: AnySign Integer -> Bool-sieveFromProperty1 (AnySign lowBound')- = take lim3 (sieveFrom lowBound)- == take lim3 (filter ((>= lowBound) . unPrime) (concatMap primeList $ psieveFrom lowBound))- where- lowBound = lowBound' `rem` lim1---- | Check that 'sieveFrom' matches 'isPrime' near 0.-sieveFromProperty2 :: AnySign Integer -> Bool-sieveFromProperty2 (AnySign lowBound')- = take lim3 (map unPrime (sieveFrom lowBound))- == take lim3 (filter (isPrime . toInteger) [lowBound `max` 0 ..])- where- lowBound = lowBound' `rem` lim1+ (map unPrime primes :: [a])+ (filter (isPrime . toInteger) [0..maxBound]) testSuite :: TestTree testSuite = testGroup "Sieve"@@ -111,9 +92,5 @@ , testCase "Int16" (psieveListProperty2 (Proxy :: Proxy Int16)) , testCase "Word8" (psieveListProperty2 (Proxy :: Proxy Word8)) , testCase "Word16" (psieveListProperty2 (Proxy :: Proxy Word16))- ]- , testGroup "sieveFrom"- [ testSmallAndQuick "psieveFrom" sieveFromProperty1- , testSmallAndQuick "isPrime near 0" sieveFromProperty2 ] ]
test-suite/Math/NumberTheory/PrimesTests.hs view
@@ -7,7 +7,6 @@ -- Tests for Math.NumberTheory.Primes -- -{-# OPTIONS_GHC -fno-warn-deprecations #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Math.NumberTheory.PrimesTests@@ -16,18 +15,17 @@ import Test.Tasty -import Math.NumberTheory.Primes (unPrime)-import Math.NumberTheory.Primes.Sieve (primeSieve, primeList, primes)+import Math.NumberTheory.Primes (primes, unPrime, nextPrime, precPrime) import Math.NumberTheory.TestUtils primesSumWonk :: Int -> Int-primesSumWonk upto = sum . takeWhile (< upto) . map unPrime . primeList $ primeSieve (toInteger upto)+primesSumWonk upto = sum $ map unPrime [nextPrime 2 .. precPrime upto] primesSum :: Int -> Int-primesSum upto = sum . takeWhile (< upto) . map unPrime $ primes+primesSum upto = sum . takeWhile (<= upto) . map unPrime $ primes primesSumProperty :: NonNegative Int -> Bool-primesSumProperty (NonNegative n) = primesSumWonk n == primesSum n+primesSumProperty (NonNegative n) = n < 2 || primesSumWonk n == primesSum n testSuite :: TestTree
test-suite/Math/NumberTheory/Recurrences/BilinearTests.hs view
@@ -7,6 +7,8 @@ -- Tests for Math.NumberTheory.Recurrences.Bilinear -- +{-# LANGUAGE TypeApplications #-}+ {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Math.NumberTheory.Recurrences.BilinearTests@@ -16,30 +18,73 @@ import Test.Tasty import Test.Tasty.HUnit +import Control.Arrow+import Data.List (sort) import Data.Ratio -import Math.NumberTheory.Recurrences.Bilinear (bernoulli, binomial, euler,- eulerian1, eulerian2,- eulerPolyAt1, lah, stirling1,- stirling2)+import Math.NumberTheory.Primes+import Math.NumberTheory.Recurrences.Bilinear import Math.NumberTheory.TestUtils binomialProperty1 :: NonNegative Int -> Bool-binomialProperty1 (NonNegative i) = length (binomial !! i) == i + 1+binomialProperty1 (NonNegative i) = length (binomial @Integer !! i) == i + 1 binomialProperty2 :: NonNegative Int -> Bool-binomialProperty2 (NonNegative i) = binomial !! i !! 0 == 1+binomialProperty2 (NonNegative i) = binomial @Integer !! i !! 0 == 1 binomialProperty3 :: NonNegative Int -> Bool-binomialProperty3 (NonNegative i) = binomial !! i !! i == 1+binomialProperty3 (NonNegative i) = binomial @Integer !! i !! i == 1 binomialProperty4 :: Positive Int -> Positive Int -> Bool binomialProperty4 (Positive i) (Positive j) = j >= i- || binomial !! i !! j+ || binomial @Integer !! i !! j == binomial !! (i - 1) !! (j - 1) + binomial !! (i - 1) !! j +binomialProperty5 :: Word -> Word -> Bool+binomialProperty5 n m' = n > 100000 ||+ sort (map (first unPrime) (factorise (binomial !! fromIntegral n !! fromIntegral m))) ==+ sort (map (first (toInteger . unPrime)) (binomialFactors n m))+ where+ m = m' `mod` (n + 1)++binomialProperty6 :: Word -> Word -> Bool+binomialProperty6 n m' = n > 100000 ||+ binomial !! fromIntegral n !! fromIntegral m ==+ product (map (\(p, k) -> toInteger (unPrime p) ^ k) (binomialFactors n m))+ where+ m = m' `mod` (n + 1)++binomialRotatedProperty2 :: NonNegative Int -> Bool+binomialRotatedProperty2 (NonNegative i) = binomialRotated @Integer !! i !! 0 == 1++binomialRotatedProperty3 :: NonNegative Int -> Bool+binomialRotatedProperty3 (NonNegative i) = binomialRotated @Integer !! 0 !! i == 1++binomialRotatedProperty4 :: Positive Int -> Positive Int -> Bool+binomialRotatedProperty4 (Positive i) (Positive j)+ = binomialRotated @Integer !! i !! j+ == binomialRotated !! i !! (j - 1)+ + binomialRotated !! (i - 1) !! j++binomialLineProperty1 :: NonNegative Int -> NonNegative Int -> Bool+binomialLineProperty1 (NonNegative i) (NonNegative j)+ = j >= i+ || binomial @Integer !! i !! j == binomialLine (toInteger i) !! j++binomialLineProperty2 :: NonNegative Int -> NonNegative Int -> Bool+binomialLineProperty2 (NonNegative i) (NonNegative j)+ = binomialRotated @Integer !! i !! j == binomialLine (toInteger (i + j)) !! j++binomialDiagonalProperty1 :: NonNegative Int -> NonNegative Int -> Bool+binomialDiagonalProperty1 (NonNegative i) (NonNegative j)+ = binomialRotated @Integer !! i !! j == binomialDiagonal (toInteger i) !! j++binomialDiagonalProperty2 :: NonNegative Int -> NonNegative Int -> Bool+binomialDiagonalProperty2 (NonNegative i) (NonNegative j)+ = binomial @Integer !! (i + j) !! j == binomialDiagonal (toInteger i) !! j+ stirling1Property1 :: NonNegative Int -> Bool stirling1Property1 (NonNegative i) = length (stirling1 !! i) == i + 1 @@ -184,6 +229,17 @@ , testSmallAndQuick "left side" binomialProperty2 , testSmallAndQuick "right side" binomialProperty3 , testSmallAndQuick "recurrency" binomialProperty4+ , testSmallAndQuick "factorise . binomial = binomialFactors" binomialProperty5+ , testSmallAndQuick "binomial = factorBack . binomialFactors" binomialProperty6+ , testSmallAndQuick "line" binomialLineProperty1+ , testSmallAndQuick "diagonal" binomialDiagonalProperty2+ ]+ , testGroup "binomialRotated"+ [ testSmallAndQuick "left side" binomialRotatedProperty2+ , testSmallAndQuick "right side" binomialRotatedProperty3+ , testSmallAndQuick "recurrency" binomialRotatedProperty4+ , testSmallAndQuick "line" binomialLineProperty2+ , testSmallAndQuick "diagonal" binomialDiagonalProperty1 ] , testGroup "stirling1" [ testSmallAndQuick "shape" stirling1Property1
test-suite/Math/NumberTheory/Recurrences/LinearTests.hs view
@@ -18,6 +18,10 @@ import Test.Tasty import Test.Tasty.HUnit +import Control.Arrow+import Data.List (sort)++import Math.NumberTheory.Primes import Math.NumberTheory.Recurrences.Linear import Math.NumberTheory.TestUtils @@ -79,6 +83,16 @@ generalLucasProperty3 :: AnySign Integer -> AnySign Integer -> Bool generalLucasProperty3 (AnySign p) (AnySign q) = generalLucas p q 0 == (0, 1, 2, p) +factorialProperty1 :: Word -> Bool+factorialProperty1 n = n > 100000 ||+ sort (map (first unPrime) (factorise (factorial !! fromIntegral n))) ==+ sort (map (first (toInteger . unPrime)) (factorialFactors n))++factorialProperty2 :: Word -> Bool+factorialProperty2 n = n > 100000 ||+ factorial !! fromIntegral n ==+ product (map (\(p, k) -> toInteger (unPrime p) ^ k) (factorialFactors n))+ testSuite :: TestTree testSuite = testGroup "Linear" [ testGroup "fibonacci"@@ -99,5 +113,9 @@ [ testSmallAndQuick "matches definition" generalLucasProperty1 , testSmallAndQuick "generalLucas 1 (-1)" generalLucasProperty2 , testSmallAndQuick "generalLucas _ _ 0" generalLucasProperty3+ ]+ , testGroup "factorial"+ [ testSmallAndQuick "factorise . factorial = factorialFactors" factorialProperty1+ , testSmallAndQuick "factorial = factorBack . factorialFactors" factorialProperty2 ] ]
test-suite/Math/NumberTheory/Recurrences/PentagonalTests.hs view
@@ -19,7 +19,7 @@ import Data.Proxy (Proxy (..)) import GHC.Natural (Natural)-import GHC.TypeNats.Compat (SomeNat (..), someNatVal)+import GHC.TypeNats (SomeNat (..), someNatVal) import Math.NumberTheory.Moduli (Mod, getVal) import Math.NumberTheory.Recurrences (partition)@@ -92,8 +92,7 @@ testSuite = testGroup "Pentagonal" [ testGroup "partition" [ testSmallAndQuick "matches definition" partitionProperty1- , testSmallAndQuick "mapping residue modulus 'n' is the same as giving\- \'partition' type '[Mod n]'" partitionProperty2+ , testSmallAndQuick "mod n" partitionProperty2 , testCase "first 20 elements of partition are correct" partitionSpecialCase20 ]
+ test-suite/Math/NumberTheory/RootsOfUnityTests.hs view
@@ -0,0 +1,25 @@+-- |+-- Module: Math.NumberTheory.RootsOfUnityTests+-- Copyright: (c) 2018 Bhavik Mehta+-- License: MIT+-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+--+-- Tests for Math.NumberTheory.RootsOfUnity+--++module Math.NumberTheory.RootsOfUnityTests where++import Test.Tasty++import Data.Complex+import Data.Ratio+import Data.Semigroup++import Math.NumberTheory.DirichletCharacters (toRootOfUnity, toComplex)+import Math.NumberTheory.TestUtils (testSmallAndQuick, Positive(..))++rootOfUnityTest :: Integer -> Positive Integer -> Bool+rootOfUnityTest n (Positive d) = toComplex ((d `div` gcd n d) `stimes` toRootOfUnity (n % d)) == (1 :: Complex Double)++testSuite :: TestTree+testSuite = testSmallAndQuick "RootOfUnity contains roots of unity" rootOfUnityTest
test-suite/Math/NumberTheory/SmoothNumbersTests.hs view
@@ -7,6 +7,8 @@ -- Tests for Math.NumberTheory.SmoothNumbersTests -- +{-# LANGUAGE TypeApplications #-}+ {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Math.NumberTheory.SmoothNumbersTests@@ -18,21 +20,26 @@ import Test.Tasty.HUnit import Data.Coerce+import Data.Euclidean import Data.List (nub)-import Data.Maybe (fromJust) import Numeric.Natural -import Math.NumberTheory.Euclidean import Math.NumberTheory.Primes (Prime (..)) import qualified Math.NumberTheory.Quadratic.GaussianIntegers as G import qualified Math.NumberTheory.Quadratic.EisensteinIntegers as E import Math.NumberTheory.SmoothNumbers (SmoothBasis, fromList, isSmooth, smoothOver, smoothOver') import Math.NumberTheory.TestUtils -isSmoothPropertyHelper :: (Eq a, Num a, Euclidean a) => (a -> Integer) -> [a] -> Int -> Int -> Bool+isSmoothPropertyHelper+ :: (Eq a, Num a, Euclidean a)+ => (a -> Integer)+ -> [a]+ -> Int+ -> Int+ -> Bool isSmoothPropertyHelper norm primes' i1 i2 = let primes = take i1 primes'- basis = fromJust (fromList primes)+ basis = fromList primes in all (isSmooth basis) $ take i2 $ smoothOver' norm basis isSmoothProperty1 :: Positive Int -> Positive Int -> Bool@@ -43,7 +50,7 @@ isSmoothProperty2 (Positive i1) (Positive i2) = isSmoothPropertyHelper E.norm (map unPrime E.primes) i1 i2 -smoothOverInRange :: (Ord a, Num a) => SmoothBasis a -> a -> a -> [a]+smoothOverInRange :: Integral a => SmoothBasis a -> a -> a -> [a] smoothOverInRange s lo hi = takeWhile (<= hi) $ dropWhile (< lo)@@ -60,9 +67,12 @@ $ filter (isSmooth prs) $ coerce [lo..hi] -smoothOverInRangeProperty :: Integral a => SmoothBasis a -> Positive a -> Positive a -> Bool-smoothOverInRangeProperty s (Positive lo') (Positive diff')- = xs == ys+smoothOverInRangeProperty+ :: (Show a, Integral a)+ => (SmoothBasis a, Positive a, Positive a)+ -> ([a], [a])+smoothOverInRangeProperty (s, Positive lo', Positive diff') =+ (map unwrapIntegral xs, map unwrapIntegral ys) where lo = WrapIntegral lo' `rem` 2^18 diff = WrapIntegral diff' `rem` 2^18@@ -70,7 +80,11 @@ xs = smoothOverInRange (coerce s) lo hi ys = smoothOverInRangeBF (coerce s) lo hi -smoothNumbersAreUniqueProperty :: Integral a => SmoothBasis a -> Positive Int -> Bool+smoothNumbersAreUniqueProperty+ :: (Show a, Integral a)+ => SmoothBasis a+ -> Positive Int+ -> Bool smoothNumbersAreUniqueProperty s (Positive len) = nub l == l where@@ -79,35 +93,29 @@ isSmoothSpecialCase1 :: Assertion isSmoothSpecialCase1 = assertBool "should be distinct" $ nub l == l where- b = fromJust $ fromList [1+3*G.ι,6+8*G.ι]+ b = fromList [1+3*G.ι,6+8*G.ι] l = take 10 $ map abs $ smoothOver' G.norm b isSmoothSpecialCase2 :: Assertion isSmoothSpecialCase2 = assertBool "should be smooth" $ isSmooth b 6 where- b = fromJust $ fromList [4, 3, 6, 10, 7::Int]+ b = fromList [4, 3, 6, 10, 7::Int] testSuite :: TestTree testSuite = testGroup "SmoothNumbers" [ testGroup "smoothOverInRange == smoothOverInRangeBF"- [ testSmallAndQuick "Int"- (smoothOverInRangeProperty :: SmoothBasis Int -> Positive Int -> Positive Int -> Bool)- , testSmallAndQuick "Word"- (smoothOverInRangeProperty :: SmoothBasis Word -> Positive Word -> Positive Word -> Bool)- , testSmallAndQuick "Integer"- (smoothOverInRangeProperty :: SmoothBasis Integer -> Positive Integer -> Positive Integer -> Bool)- , testSmallAndQuick "Natural"- (smoothOverInRangeProperty :: SmoothBasis Natural -> Positive Natural -> Positive Natural -> Bool)+ [ testEqualSmallAndQuick "Int" (smoothOverInRangeProperty @Int)+ , testEqualSmallAndQuick "Word" (smoothOverInRangeProperty @Word)+ , testEqualSmallAndQuick "Integer" (smoothOverInRangeProperty @Integer)+ , testEqualSmallAndQuick "Natural" (smoothOverInRangeProperty @Natural) ] , testGroup "smoothOver generates a list without duplicates"- [ testSmallAndQuick "Integer"- (smoothNumbersAreUniqueProperty :: SmoothBasis Integer -> Positive Int -> Bool)- , testSmallAndQuick "Natural"- (smoothNumbersAreUniqueProperty :: SmoothBasis Natural -> Positive Int -> Bool)+ [ testSmallAndQuick "Integer" (smoothNumbersAreUniqueProperty @Integer)+ , testSmallAndQuick "Natural" (smoothNumbersAreUniqueProperty @Natural) ]- , testGroup "Quadratic rings (Gaussian/Eisenstein)"+ , testGroup "Quadratic rings" [ testGroup "smoothOver generates valid smooth numbers"- [ testSmallAndQuick "Gaussian" isSmoothProperty1+ [ testSmallAndQuick "Gaussian" isSmoothProperty1 , testSmallAndQuick "Eisenstein" isSmoothProperty2 ] , testCase "all distinct for base [1+3*i,6+8*i]" isSmoothSpecialCase1
test-suite/Math/NumberTheory/TestUtils.hs view
@@ -12,7 +12,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -38,25 +37,30 @@ , testSameIntegralProperty3 , testIntegral2Property , testSmallAndQuick+ , testEqualSmallAndQuick -- * Export for @Zeta@ tests , assertEqualUpToEps++ -- * Export for Inverse tests+ , TestableIntegral++ , lawsToTest ) where -import Test.SmallCheck.Series (cons2)+import Test.QuickCheck.Classes+import Test.SmallCheck.Series (Positive(..), NonNegative(..), Serial(..), Series, generate, (\/), cons2) import Test.Tasty import Test.Tasty.HUnit (Assertion, assertBool) import Test.Tasty.SmallCheck as SC import Test.Tasty.QuickCheck as QC hiding (Positive, getPositive, NonNegative, generate, getNonNegative) -import Test.SmallCheck.Series (Positive(..), NonNegative(..), Serial(..), Series, generate, (\/))- import Data.Bits+import Data.Euclidean+import Data.Kind import Data.Semiring (Semiring)-import GHC.Exts import Numeric.Natural -import Math.NumberTheory.Euclidean import qualified Math.NumberTheory.Quadratic.EisensteinIntegers as E (EisensteinInteger(..)) import Math.NumberTheory.Quadratic.GaussianIntegers (GaussianInteger(..)) import Math.NumberTheory.Primes (Prime, UniqueFactorisation)@@ -87,10 +91,11 @@ -- SmoothNumbers instance (Ord a, Num a, Euclidean a, Arbitrary a) => Arbitrary (SN.SmoothBasis a) where- arbitrary = (fmap getPositive <$> arbitrary) `suchThatMap` SN.fromList+ arbitrary = SN.fromList <$> arbitrary+ shrink xs = SN.fromList <$> shrink (SN.unSmoothBasis xs) instance (Ord a, Num a, Euclidean a, Serial m a) => Serial m (SN.SmoothBasis a) where- series = (fmap getPositive <$> series) `suchThatMapSerial` SN.fromList+ series = SN.fromList <$> series ------------------------------------------------------------------------------- @@ -99,12 +104,12 @@ class (f (g x)) => (f `Compose` g) x instance (f (g x)) => (f `Compose` g) x -type family ConcatMap (w :: * -> Constraint) (cs :: [*]) :: Constraint+type family ConcatMap (w :: Type -> Constraint) (cs :: [Type]) :: Constraint where ConcatMap w '[] = () ConcatMap w (c ': cs) = (w c, ConcatMap w cs) -type family Matrix (as :: [* -> Constraint]) (w :: * -> *) (bs :: [*]) :: Constraint+type family Matrix (as :: [Type -> Constraint]) (w :: Type -> Type) (bs :: [Type]) :: Constraint where Matrix '[] w bs = () Matrix (a ': as) w bs = (ConcatMap (a `Compose` w) bs, Matrix as w bs)@@ -243,17 +248,31 @@ ] testSmallAndQuick- :: SC.Testable IO a- => QC.Testable a- => String -> a -> TestTree+ :: (SC.Testable IO a, QC.Testable a)+ => String+ -> a+ -> TestTree testSmallAndQuick name f = testGroup name [ SC.testProperty "smallcheck" f , QC.testProperty "quickcheck" f ] +testEqualSmallAndQuick+ :: (Serial IO a, Arbitrary a, Show a, Eq b, Show b)+ => String+ -> (a -> (b, b))+ -> TestTree+testEqualSmallAndQuick name f = testGroup name+ [ SC.testProperty "smallcheck" (uncurry (==) . f)+ , QC.testProperty "quickcheck" (uncurry (===) . f)+ ] -- | Used in @Math.NumberTheory.Zeta.DirichletTests@ and -- @Math.NumberTheory.Zeta.RiemannTests@. assertEqualUpToEps :: String -> Double -> Double -> Double -> Assertion assertEqualUpToEps msg eps expected actual = assertBool msg (abs (expected - actual) < eps)++lawsToTest :: Laws -> TestTree+lawsToTest (Laws name props) =+ testGroup name $ map (uncurry QC.testProperty) props
test-suite/Math/NumberTheory/TestUtils/Wrappers.hs view
@@ -27,13 +27,13 @@ import Control.Applicative import Data.Coerce+import Data.Euclidean import Data.Functor.Classes import Data.Semiring (Semiring) import Test.Tasty.QuickCheck as QC hiding (Positive, NonNegative, generate, getNonNegative, getPositive) import Test.SmallCheck.Series (Positive(..), NonNegative(..), Serial(..), Series) -import Math.NumberTheory.Euclidean (GcdDomain, Euclidean) import Math.NumberTheory.Primes (Prime, UniqueFactorisation(..)) -------------------------------------------------------------------------------
test-suite/Test.hs view
@@ -1,4 +1,5 @@ import Test.Tasty+import Test.Tasty.Ingredients.Rerun import qualified Math.NumberTheory.EuclideanTests as Euclidean @@ -17,11 +18,7 @@ import qualified Math.NumberTheory.MoebiusInversionTests as MoebiusInversion -import qualified Math.NumberTheory.Powers.CubesTests as Cubes-import qualified Math.NumberTheory.Powers.FourthTests as Fourth-import qualified Math.NumberTheory.Powers.GeneralTests as General import qualified Math.NumberTheory.Powers.ModularTests as Modular-import qualified Math.NumberTheory.Powers.SquaresTests as Squares import qualified Math.NumberTheory.PrefactoredTests as Prefactored @@ -47,18 +44,16 @@ import qualified Math.NumberTheory.Zeta.RiemannTests as Riemann import qualified Math.NumberTheory.Zeta.DirichletTests as Dirichlet +import qualified Math.NumberTheory.DirichletCharactersTests as DirichletChar++import qualified Math.NumberTheory.RootsOfUnityTests as RootsOfUnity+ main :: IO ()-main = defaultMain tests+main = defaultMainWithRerun tests tests :: TestTree tests = testGroup "All"- [ testGroup "Powers"- [ Cubes.testSuite- , Fourth.testSuite- , General.testSuite- , Modular.testSuite- , Squares.testSuite- ]+ [ Modular.testSuite , Euclidean.testSuite , testGroup "Recurrences" [ RecurrencesPentagonal.testSuite@@ -101,4 +96,6 @@ [ Riemann.testSuite , Dirichlet.testSuite ]+ , DirichletChar.testSuite+ , RootsOfUnity.testSuite ]