packages feed

combinat 0.2.9.0 → 0.2.10.0

raw patch · 22 files changed

+1230/−767 lines, 22 filesdep +compact-word-vectorsdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: compact-word-vectors

Dependency ranges changed: base

API changes (from Hackage documentation)

- Math.Combinat.Partitions.Integer.Compact: Medium1 :: {-# UNPACK #-} !Word64 -> Partition
- Math.Combinat.Partitions.Integer.Compact: Medium2 :: {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> Partition
- Math.Combinat.Partitions.Integer.Compact: Medium3 :: {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> Partition
- Math.Combinat.Partitions.Integer.Compact: Medium4 :: {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> Partition
- Math.Combinat.Partitions.Integer.Compact: Nibble :: {-# UNPACK #-} !Word64 -> Partition
- Math.Combinat.Partitions.Integer.Compact: WordList :: {-# UNPACK #-} !Int -> ![Word64] -> Partition
- Math.Combinat.Partitions.Integer.Compact: c_dual_nibble :: Word64 -> Word64
- Math.Combinat.Partitions.Integer.Compact: cmp :: Partition -> Partition -> Ordering
- Math.Combinat.Partitions.Integer.Compact: data Partition
- Math.Combinat.Partitions.Integer.Compact: makeMedium :: Int -> [Int] -> Partition
- Math.Combinat.Partitions.Integer.Compact: makeMedium1 :: Int -> [Int] -> Partition
- Math.Combinat.Partitions.Integer.Compact: makeMedium2 :: Int -> [Int] -> Partition
- Math.Combinat.Partitions.Integer.Compact: makeMedium3 :: Int -> [Int] -> Partition
- Math.Combinat.Partitions.Integer.Compact: makeMedium4 :: Int -> [Int] -> Partition
- Math.Combinat.Partitions.Integer.Compact: makeNibble :: Int -> [Int] -> Partition
- Math.Combinat.Partitions.Integer.Compact: makeWordList :: Int -> [Int] -> Partition
- Math.Combinat.Partitions.Integer.Compact: partitionPrefixChar :: Partition -> Char
- Math.Combinat.Partitions.Integer.Compact: pieriRuleSingleBox :: Partition -> [Partition]
- Math.Combinat.Partitions.Integer.Compact: toOne :: Int -> [Int]
- Math.Combinat.Partitions.Integer.Compact: toZero :: Int -> [Int]
- Math.Combinat.Permutations: identity :: Int -> Permutation
- Math.Combinat.Permutations: inverse :: Permutation -> Permutation
- Math.Combinat.Permutations: multiply :: Permutation -> Permutation -> Permutation
- Math.Combinat.Permutations: multiplyMany :: [Permutation] -> Permutation
- Math.Combinat.Permutations: multiplyMany' :: Int -> [Permutation] -> Permutation
- Math.Combinat.Permutations: permute :: IArray arr b => Permutation -> arr Int b -> arr Int b
- Math.Combinat.Permutations: permuteLeft :: IArray arr b => Permutation -> arr Int b -> arr Int b
- Math.Combinat.Permutations: permuteLeftList :: forall a. Permutation -> [a] -> [a]
- Math.Combinat.Permutations: permuteRight :: IArray arr b => Permutation -> arr Int b -> arr Int b
- Math.Combinat.Permutations: permuteRightList :: forall a. Permutation -> [a] -> [a]
- Math.Combinat.Tableaux.GelfandTsetlin.Cone: instance GHC.Arr.Ix Math.Combinat.Tableaux.GelfandTsetlin.Cone.Tri
- Math.Combinat.TypeLevel: data Proxy (t :: k) :: forall k. () => k -> *
+ Math.Combinat.Groups.Thompson.F: pattern Br :: Tree a -> Tree a -> Tree a
+ Math.Combinat.Groups.Thompson.F: pattern Ct :: Tree ()
+ Math.Combinat.Groups.Thompson.F: pattern Lf :: Tree ()
+ Math.Combinat.Groups.Thompson.F: pattern X0 :: TDiag
+ Math.Combinat.Groups.Thompson.F: pattern X1 :: TDiag
+ Math.Combinat.Helper: evens :: [a] -> [a]
+ Math.Combinat.Helper: odds :: [a] -> [a]
+ Math.Combinat.Helper: productFromTo :: Integral a => a -> a -> Integer
+ Math.Combinat.Helper: productFromToStride2 :: Integral a => a -> a -> Integer
+ Math.Combinat.Helper: productInterleaved :: [Integer] -> Integer
+ Math.Combinat.Numbers.Primes: divides :: Integer -> Integer -> Bool
+ Math.Combinat.Numbers.Primes: divisorSum :: Integer -> Integer
+ Math.Combinat.Numbers.Primes: divisorSum' :: Int -> Integer -> Integer
+ Math.Combinat.Numbers.Primes: divisors :: Integer -> [Integer]
+ Math.Combinat.Numbers.Primes: eulerTotient :: Integer -> Integer
+ Math.Combinat.Numbers.Primes: factorize :: Integer -> [(Integer, Int)]
+ Math.Combinat.Numbers.Primes: factorizeNaive :: Integer -> [(Integer, Int)]
+ Math.Combinat.Numbers.Primes: liouvilleLambda :: (Integral a, Num b) => a -> b
+ Math.Combinat.Numbers.Primes: moebiusMu :: (Integral a, Num b) => a -> b
+ Math.Combinat.Numbers.Primes: productOfFactors :: [(Integer, Int)] -> Integer
+ Math.Combinat.Numbers.Primes: squareFreeDivisors :: Integer -> [(Integer, Sign)]
+ Math.Combinat.Numbers.Primes: squareFreeDivisors_ :: Integer -> [Integer]
+ Math.Combinat.Numbers.Sequences: binomialNaive :: Integral a => a -> a -> Integer
+ Math.Combinat.Numbers.Sequences: binomialSplit :: Integral a => a -> a -> Integer
+ Math.Combinat.Numbers.Sequences: doubleFactorialNaive :: Integral a => a -> Integer
+ Math.Combinat.Numbers.Sequences: doubleFactorialSplit :: Integral a => a -> Integer
+ Math.Combinat.Numbers.Sequences: factorialNaive :: Integral a => a -> Integer
+ Math.Combinat.Numbers.Sequences: factorialPrimeExponents :: Int -> [(Integer, Int)]
+ Math.Combinat.Numbers.Sequences: factorialPrimeExponentsNaive :: forall a. Integral a => a -> [(Integer, Int)]
+ Math.Combinat.Numbers.Sequences: factorialPrimeExponents_ :: Int -> [Int]
+ Math.Combinat.Numbers.Sequences: factorialSplit :: Integral a => a -> Integer
+ Math.Combinat.Numbers.Sequences: factorialSwing :: Integral a => a -> Integer
+ Math.Combinat.Numbers.Sequences: swingFactorialExponents_ :: Int -> [Int]
+ Math.Combinat.Partitions.Integer: ConjLex :: Partition -> ConjLex
+ Math.Combinat.Partitions.Integer: conjugateLexicographicCompare :: Partition -> Partition -> Ordering
+ Math.Combinat.Partitions.Integer: dominanceCompare :: Partition -> Partition -> Maybe Ordering
+ Math.Combinat.Partitions.Integer: dropTailingZeros :: [Int] -> [Int]
+ Math.Combinat.Partitions.Integer: fromConjLex :: ConjLex -> Partition
+ Math.Combinat.Partitions.Integer: fromExponentVector :: [Int] -> Partition
+ Math.Combinat.Partitions.Integer: instance GHC.Classes.Eq Math.Combinat.Partitions.Integer.ConjLex
+ Math.Combinat.Partitions.Integer: instance GHC.Classes.Ord Math.Combinat.Partitions.Integer.ConjLex
+ Math.Combinat.Partitions.Integer: instance GHC.Show.Show Math.Combinat.Partitions.Integer.ConjLex
+ Math.Combinat.Partitions.Integer: newtype ConjLex
+ Math.Combinat.Partitions.Integer: toExponentVector :: Partition -> [Int]
+ Math.Combinat.Partitions.Integer.Compact: Partition :: WordVec -> Partition
+ Math.Combinat.Partitions.Integer.Compact: cmpLexico :: Partition -> Partition -> Ordering
+ Math.Combinat.Partitions.Integer.Compact: descendToOne :: Int -> [Int]
+ Math.Combinat.Partitions.Integer.Compact: descendToZero :: Int -> [Int]
+ Math.Combinat.Partitions.Integer.Compact: newtype Partition
+ Math.Combinat.Partitions.Integer.Compact: pattern Cons :: Int -> Partition -> Partition
+ Math.Combinat.Partitions.Integer.Compact: pattern Head :: Int -> Partition
+ Math.Combinat.Partitions.Integer.Compact: pattern Length :: Int -> Partition
+ Math.Combinat.Partitions.Integer.Compact: pattern Nil :: Partition
+ Math.Combinat.Partitions.Integer.Compact: pattern Partition_ :: [Int] -> Partition
+ Math.Combinat.Partitions.Integer.Compact: pattern Tail :: Partition -> Partition
+ Math.Combinat.Partitions.Integer.Compact: showsPrecPartition :: Int -> Partition -> ShowS
+ Math.Combinat.Partitions.Integer.Naive: fromList :: [Int] -> Partition
+ Math.Combinat.Partitions.Integer.Naive: fromListUnsafe :: [Int] -> Partition
+ Math.Combinat.Partitions.Integer.Naive: pattern Cons :: Int -> Partition -> Partition
+ Math.Combinat.Partitions.Integer.Naive: pattern Head :: Int -> Partition
+ Math.Combinat.Partitions.Integer.Naive: pattern Length :: Int -> Partition
+ Math.Combinat.Partitions.Integer.Naive: pattern Nil :: Partition
+ Math.Combinat.Partitions.Integer.Naive: pattern Partition_ :: [Int] -> Partition
+ Math.Combinat.Partitions.Integer.Naive: pattern Tail :: Partition -> Partition
+ Math.Combinat.Partitions.Integer.Naive: toList :: Partition -> [Int]
+ Math.Combinat.Permutations: (!!!) :: Permutation -> Int -> Int
+ Math.Combinat.Permutations: identityPermutation :: Int -> Permutation
+ Math.Combinat.Permutations: inversePermutation :: Permutation -> Permutation
+ Math.Combinat.Permutations: lookupPermutation :: Permutation -> Int -> Int
+ Math.Combinat.Permutations: multiplyPermutation :: Permutation -> Permutation -> Permutation
+ Math.Combinat.Permutations: permuteArray :: IArray arr b => Permutation -> arr Int b -> arr Int b
+ Math.Combinat.Permutations: permuteArrayLeft :: IArray arr b => Permutation -> arr Int b -> arr Int b
+ Math.Combinat.Permutations: permuteArrayRight :: IArray arr b => Permutation -> arr Int b -> arr Int b
+ Math.Combinat.Permutations: permuteListLeft :: forall a. Permutation -> [a] -> [a]
+ Math.Combinat.Permutations: permuteListRight :: forall a. Permutation -> [a] -> [a]
+ Math.Combinat.Permutations: productOfPermutations :: [Permutation] -> Permutation
+ Math.Combinat.Permutations: productOfPermutations' :: Int -> [Permutation] -> Permutation
+ Math.Combinat.Permutations: toPermutationUnsafeN :: Int -> [Int] -> Permutation
+ Math.Combinat.RootSystems: A :: !Int -> Dynkin
+ Math.Combinat.RootSystems: B :: !Int -> Dynkin
+ Math.Combinat.RootSystems: C :: !Int -> Dynkin
+ Math.Combinat.RootSystems: D :: !Int -> Dynkin
+ Math.Combinat.RootSystems: E6 :: Dynkin
+ Math.Combinat.RootSystems: E7 :: Dynkin
+ Math.Combinat.RootSystems: E8 :: Dynkin
+ Math.Combinat.RootSystems: F4 :: Dynkin
+ Math.Combinat.RootSystems: G2 :: Dynkin
+ Math.Combinat.RootSystems: HalfInt :: Int -> HalfInt
+ Math.Combinat.RootSystems: allRootsOf :: Dynkin -> Set HalfVec
+ Math.Combinat.RootSystems: ambientDim :: Dynkin -> Int
+ Math.Combinat.RootSystems: basisOfPositives :: Set HalfVec -> [HalfVec]
+ Math.Combinat.RootSystems: bracket :: HalfVec -> HalfVec -> HalfInt
+ Math.Combinat.RootSystems: cartanMatrix :: [HalfVec] -> Array (Int, Int) Int
+ Math.Combinat.RootSystems: data Dynkin
+ Math.Combinat.RootSystems: divByTwo :: Int -> HalfInt
+ Math.Combinat.RootSystems: findPositiveHyperplane :: [HalfVec] -> [Double]
+ Math.Combinat.RootSystems: half :: HalfInt
+ Math.Combinat.RootSystems: instance GHC.Classes.Eq Math.Combinat.RootSystems.Dynkin
+ Math.Combinat.RootSystems: instance GHC.Classes.Eq Math.Combinat.RootSystems.HalfInt
+ Math.Combinat.RootSystems: instance GHC.Classes.Ord Math.Combinat.RootSystems.HalfInt
+ Math.Combinat.RootSystems: instance GHC.Num.Num Math.Combinat.RootSystems.HalfInt
+ Math.Combinat.RootSystems: instance GHC.Num.Num Math.Combinat.RootSystems.HalfVec
+ Math.Combinat.RootSystems: instance GHC.Show.Show Math.Combinat.RootSystems.Dynkin
+ Math.Combinat.RootSystems: instance GHC.Show.Show Math.Combinat.RootSystems.HalfInt
+ Math.Combinat.RootSystems: mirror :: HalfVec -> HalfVec -> HalfVec
+ Math.Combinat.RootSystems: mirrorClosure :: [HalfVec] -> Set HalfVec
+ Math.Combinat.RootSystems: mirrorStep :: Set HalfVec -> Set HalfVec
+ Math.Combinat.RootSystems: mulByTwo :: HalfInt -> Int
+ Math.Combinat.RootSystems: negateVec :: HalfVec -> HalfVec
+ Math.Combinat.RootSystems: negativeRootsOf :: Dynkin -> Set HalfVec
+ Math.Combinat.RootSystems: newtype HalfInt
+ Math.Combinat.RootSystems: positiveRoots :: [HalfVec] -> Set HalfVec
+ Math.Combinat.RootSystems: positiveRootsOf :: Dynkin -> Set HalfVec
+ Math.Combinat.RootSystems: printMatrix :: Show a => Array (Int, Int) a -> IO ()
+ Math.Combinat.RootSystems: safeZip :: (a -> b -> c) -> [a] -> [b] -> [c]
+ Math.Combinat.RootSystems: scaleBy :: Int -> HalfInt -> HalfInt
+ Math.Combinat.RootSystems: scaleVec :: Int -> HalfVec -> HalfVec
+ Math.Combinat.RootSystems: simpleRootsE6_123 :: [HalfVec]
+ Math.Combinat.RootSystems: simpleRootsE7_12 :: [HalfVec]
+ Math.Combinat.RootSystems: simpleRootsE7_diag :: [HalfVec]
+ Math.Combinat.RootSystems: simpleRootsE8_even :: [HalfVec]
+ Math.Combinat.RootSystems: simpleRootsE8_odd :: [HalfVec]
+ Math.Combinat.RootSystems: simpleRootsOf :: Dynkin -> [HalfVec]
+ Math.Combinat.RootSystems: type HalfVec = [HalfInt]
+ Math.Combinat.Tableaux.GelfandTsetlin.Cone: instance GHC.Ix.Ix Math.Combinat.Tableaux.GelfandTsetlin.Cone.Tri
+ Math.Combinat.TypeLevel: data Proxy (t :: k)
- Math.Combinat.Groups.Braid: Braid :: [BrGen] -> Braid
+ Math.Combinat.Groups.Braid: Braid :: [BrGen] -> Braid (n :: Nat)
- Math.Combinat.Groups.Braid: SomeBraid :: (Braid n) -> SomeBraid
+ Math.Combinat.Groups.Braid: SomeBraid :: Braid n -> SomeBraid
- Math.Combinat.Groups.Braid: _randomBraidWord :: (RandomGen g) => Int -> Int -> g -> ([BrGen], g)
+ Math.Combinat.Groups.Braid: _randomBraidWord :: RandomGen g => Int -> Int -> g -> ([BrGen], g)
- Math.Combinat.Groups.Braid: _randomPositiveBraidWord :: (RandomGen g) => Int -> Int -> g -> ([BrGen], g)
+ Math.Combinat.Groups.Braid: _randomPositiveBraidWord :: RandomGen g => Int -> Int -> g -> ([BrGen], g)
- Math.Combinat.Groups.Braid: extend :: (n1 <= n2) => Braid n1 -> Braid n2
+ Math.Combinat.Groups.Braid: extend :: n1 <= n2 => Braid n1 -> Braid n2
- Math.Combinat.Groups.Braid.NF: BraidNF :: !Int -> [Permutation] -> BraidNF
+ Math.Combinat.Groups.Braid.NF: BraidNF :: !Int -> [Permutation] -> BraidNF (n :: Nat)
- Math.Combinat.Groups.Braid.NF: [_nfDeltaExp] :: BraidNF -> !Int
+ Math.Combinat.Groups.Braid.NF: [_nfDeltaExp] :: BraidNF (n :: Nat) -> !Int
- Math.Combinat.Groups.Braid.NF: [_nfPerms] :: BraidNF -> [Permutation]
+ Math.Combinat.Groups.Braid.NF: [_nfPerms] :: BraidNF (n :: Nat) -> [Permutation]
- Math.Combinat.Groups.Thompson.F: Branch :: !(Tree a) -> !(Tree a) -> Tree a
+ Math.Combinat.Groups.Thompson.F: Branch :: !Tree a -> !Tree a -> Tree a
- Math.Combinat.Helper: RandT :: (StateT g m a) -> RandT g m a
+ Math.Combinat.Helper: RandT :: StateT g m a -> RandT g m a
- Math.Combinat.Partitions.Integer.Compact: i2w :: Int -> Word64
+ Math.Combinat.Partitions.Integer.Compact: i2w :: Int -> Word
- Math.Combinat.Partitions.Integer.Compact: sum' :: [Word64] -> Word64
+ Math.Combinat.Partitions.Integer.Compact: sum' :: [Word] -> Word
- Math.Combinat.Partitions.Integer.Compact: w2i :: Word64 -> Int
+ Math.Combinat.Partitions.Integer.Compact: w2i :: Word -> Int
- Math.Combinat.Partitions.Integer.Count: makeTableOfIntegers :: ((Int -> Integer) -> (Int -> Integer)) -> TableOfIntegers
+ Math.Combinat.Partitions.Integer.Count: makeTableOfIntegers :: ((Int -> Integer) -> Int -> Integer) -> TableOfIntegers
- Math.Combinat.Permutations: Permutation :: (UArray Int Int) -> Permutation
+ Math.Combinat.Permutations: Permutation :: WordVec -> Permutation
- Math.Combinat.Permutations: infixr 7 `multiply`
+ Math.Combinat.Permutations: infixr 7 `multiplyPermutation`
- Math.Combinat.Trees.Binary: Branch :: (BinTree a) -> (BinTree a) -> BinTree a
+ Math.Combinat.Trees.Binary: Branch :: BinTree a -> BinTree a -> BinTree a
- Math.Combinat.Trees.Binary: Branch' :: (BinTree' a b) -> b -> (BinTree' a b) -> BinTree' a b
+ Math.Combinat.Trees.Binary: Branch' :: BinTree' a b -> b -> BinTree' a b -> BinTree' a b
- Math.Combinat.TypeLevel: Proxy :: Proxy
+ Math.Combinat.TypeLevel: Proxy :: Proxy (t :: k)
- Math.Combinat.TypeLevel: Some :: (f n) -> Some f
+ Math.Combinat.TypeLevel: Some :: f n -> Some f
- Math.Combinat.TypeLevel: asProxyTypeOf :: () => a -> proxy a -> a
+ Math.Combinat.TypeLevel: asProxyTypeOf :: a -> proxy a -> a

Files

Math/Combinat/Groups/Braid.hs view
@@ -48,7 +48,7 @@ import Math.Combinat.TypeLevel import Math.Combinat.Numbers.Series -import Math.Combinat.Permutations ( Permutation(..) )+import Math.Combinat.Permutations ( Permutation(..) , (!!!) ) import qualified Math.Combinat.Permutations as P  --------------------------------------------------------------------------------@@ -233,8 +233,8 @@ -- | The involution @tau@ on permutations (permutation braids) -- tauPerm :: Permutation -> Permutation-tauPerm (Permutation arr) = Permutation $ listArray (1,n) [ (n+1) - arr!(n-i) | i<-[0..n-1] ] where-  (1,n) = bounds arr+tauPerm perm = P.toPermutationUnsafeN n [ (n+1) - perm !!! (n-i) | i<-[0..n-1] ] where+  n = P.permutationSize perm  -------------------------------------------------------------------------------- -- * Group operations@@ -265,7 +265,7 @@  -- | A braid is pure if its permutation is trivial isPureBraid :: KnownNat n => Braid n -> Bool-isPureBraid braid = (braidPermutation braid == P.identity n) where+isPureBraid braid = (braidPermutation braid == P.identityPermutation n) where   n = numberOfStrands braid  -- | Returns the left-to-right permutation associated to the braid. @@ -282,13 +282,13 @@ -- we got the two-line notation of the permutation. -- braidPermutation :: KnownNat n => Braid n -> Permutation-braidPermutation braid@ (Braid gens) = perm where+braidPermutation braid@(Braid gens) = perm where   n    = numberOfStrands braid   perm = _braidPermutation n (map brGenIdx gens)  -- | This is an untyped version of 'braidPermutation' _braidPermutation :: Int -> [Int] -> Permutation-_braidPermutation n idxs = Permutation (runSTUArray action) where+_braidPermutation n idxs = P.uarrayToPermutationUnsafe (runSTUArray action) where    action :: forall s. ST s (STUArray s Int Int)    action = do @@ -358,8 +358,8 @@ -- | Returns the individual \"phases\" of the a permutation braid realizing the -- given permutation. _permutationBraid' :: Permutation -> [[Int]]-_permutationBraid' perm@(Permutation arr) = runST action where-  (1,n) = bounds arr+_permutationBraid' perm = runST action where+  n = P.permutationSize perm    action :: forall s. ST s [[Int]]   action = do@@ -388,7 +388,7 @@     let worker phase           | phase >= n  = return []           | otherwise   = do-              let tgt = (arr ! phase)+              let tgt = P.lookupPermutation perm phase  -- (arr ! phase)               src <- readArray cfwd tgt               let this = [src-1,src-2..phase]               mapM_ doSwap $ this 
Math/Combinat/Groups/Braid/NF.hs view
@@ -53,7 +53,7 @@ import Math.Combinat.Helper import Math.Combinat.Sign -import Math.Combinat.Permutations ( Permutation(..) , isIdentityPermutation , isReversePermutation )+import Math.Combinat.Permutations ( Permutation(..) , (!!!) , isIdentityPermutation , isReversePermutation ) import qualified Math.Combinat.Permutations as P  import Math.Combinat.Groups.Braid@@ -128,7 +128,7 @@     facs = leftGreedyFactors n $ map brGenIdx gs      replaceFac idxs = XDelta (-1) : map XSigma (_permutationBraid perm) where-    perm = (P.reversePermutation n) `P.multiply` (P.adjacentTranspositions n idxs)+    perm = (P.reversePermutation n) `P.multiplyPermutation` (P.adjacentTranspositions n idxs)   -- | Replaces @sigma_i^-1@ generators by @(Delta^-1 * L_i)@.@@ -259,13 +259,13 @@ -- | The permutation @posL k :: Braid n@ is realizing posLPerm :: Int -> Int -> Permutation posLPerm n k -  | k>0 && k<n  = (P.reversePermutation n `P.multiply` P.adjacentTransposition n k)+  | k>0 && k<n  = (P.reversePermutation n `P.multiplyPermutation` P.adjacentTransposition n k)   | otherwise   = error "posLPerm: index out of range"  -- | The permutation @posR k :: Braid n@ is realizing posRPerm :: Int -> Int -> Permutation posRPerm n k -  | k>0 && k<n  = (P.adjacentTransposition n k `P.multiply` P.reversePermutation n )+  | k>0 && k<n  = (P.adjacentTransposition n k `P.multiplyPermutation` P.reversePermutation n )   | otherwise   = error "posRPerm: index out of range"  --------------------------------------------------------------------------------@@ -333,15 +333,15 @@ -- > permutationStartingSet p == permWordStartingSet n (_permutationBraid p) -- permutationStartingSet :: Permutation -> [Int]-permutationStartingSet = permutationFinishingSet . P.inverse+permutationStartingSet = permutationFinishingSet . P.inversePermutation  -- | This satisfies --  -- > permutationFinishingSet p == permWordFinishingSet n (_permutationBraid p) -- permutationFinishingSet :: Permutation -> [Int]-permutationFinishingSet (Permutation arr) -  = [ i | i<-[1..n-1] , arr ! i > arr ! (i+1) ] where (1,n) = bounds arr+permutationFinishingSet perm+  = [ i | i<-[1..n-1] , perm !!! i > perm !!! (i+1) ] where n = P.permutationSize perm  -- | Returns the list of permutations failing Lemma 2.5 in [2]  -- (so an empty list means the implementaton is correct)@@ -417,8 +417,8 @@           []    -> let (e',rs) = worker' eq 0 e rest in (e', preal : rs)           (j:_) -> worker' (-e) (-e) e (p':q':rest') where                       s  = P.adjacentTransposition n j-                     p' = P.multiply s preal-                     q' = P.multiply qreal s+                     p' = P.multiplyPermutation s preal+                     q' = P.multiplyPermutation qreal s         where           preal = oddTau (e+ep) p       -- the "real" p           qreal = oddTau (e+eq) q       -- the "real" q
Math/Combinat/Helper.hs view
@@ -1,5 +1,5 @@ --- | Miscellaneous helper functions+-- | Miscellaneous helper functions used internally  {-# LANGUAGE BangPatterns, PolyKinds, GeneralizedNewtypeDeriving #-} module Math.Combinat.Helper where@@ -57,6 +57,46 @@ interleave [x]    []     = x : [] interleave []     []     = [] interleave _      _      = error "interleave: shouldn't happen"++evens, odds :: [a] -> [a] +evens (x:xs) = x : odds xs+evens [] = []+odds (x:xs) = evens xs+odds [] = []++--------------------------------------------------------------------------------+-- * multiplication++-- | Product of list of integers, but in interleaved order (for a list of big numbers,+-- it should be faster than the linear order)+productInterleaved :: [Integer] -> Integer+productInterleaved = go where+  go []    = 1+  go [x]   = x+  go [x,y] = x*y+  go list  = go (evens list) * go (odds list)++-- | Faster implementation of @product [ i | i <- [a+1..b] ]@+productFromTo :: Integral a => a -> a -> Integer+productFromTo = go where+  go !a !b +    | dif < 1     = 1+    | dif < 5     = product [ fromIntegral i | i<-[a+1..b] ]+    | otherwise   = go a half * go half b+    where+      dif  = b - a+      half = div (a+b+1) 2++-- | Faster implementation of product @[ i | i <- [a+1,a+3,..b] ]@+productFromToStride2 :: Integral a => a -> a -> Integer+productFromToStride2 = go where+  go !a !b +    | dif < 1     = 1+    | dif < 9     = product [ fromIntegral i | i<-[a+1,a+3..b] ]+    | otherwise   = go a half * go half b+    where+      dif  = b - a+      half = a + 2*(div dif 4)  -------------------------------------------------------------------------------- -- * equality and ordering 
Math/Combinat/Numbers.hs view
@@ -1,9 +1,12 @@  module Math.Combinat.Numbers -  ( module Math.Combinat.Numbers.Sequences-  , module Math.Combinat.Numbers.Integers+  ( module Math.Combinat.Numbers.Integers+  , module Math.Combinat.Numbers.Primes+  , module Math.Combinat.Numbers.Sequences   )    where -import Math.Combinat.Numbers.Sequences import Math.Combinat.Numbers.Integers+import Math.Combinat.Numbers.Primes+import Math.Combinat.Numbers.Sequences+
Math/Combinat/Numbers/Primes.hs view
@@ -2,13 +2,20 @@ -- | Prime numbers and related number theoretical stuff.  module Math.Combinat.Numbers.Primes -  ( -- * List of prime numbers-    primes+  ( -- * Elementary number theory+    divides+  , divisors, squareFreeDivisors, squareFreeDivisors_  +  , divisorSum , divisorSum'+  , moebiusMu , eulerTotient , liouvilleLambda+    -- * List of prime numbers+  , primes   , primesSimple   , primesTMWE     -- * Prime factorization-  , groupIntegerFactors+  , factorize, factorizeNaive+  , productOfFactors   , integerFactorsTrialDivision+  , groupIntegerFactors     -- * Modulo @m@ arithmetic   , powerMod     -- * Prime testing@@ -20,14 +27,93 @@  -------------------------------------------------------------------------------- +import Data.List ( group , sort , foldl' )++import Math.Combinat.Sign+import Math.Combinat.Helper import Math.Combinat.Numbers.Integers -import Data.List ( group , sort )+-- import Math.Combinat.Sets   ( sublists )       -- cyclic dependency...+import Math.Combinat.Tuples ( tuples'  )+ import Data.Bits  import System.Random  --------------------------------------------------------------------------------++-- | @d `divides` n@+divides :: Integer -> Integer -> Bool+divides d n = (mod n d == 0)++{-# SPECIALIZE moebiusMu :: Int     -> Int     #-}+{-# SPECIALIZE moebiusMu :: Integer -> Integer #-}+-- | The Moebius mu function+moebiusMu :: (Integral a, Num b) => a -> b+moebiusMu n +  | any (>1) expos       =  0+  | even (length primes) =  1+  | otherwise            = -1+  where+    factors = groupIntegerFactors $ integerFactorsTrialDivision $ fromIntegral n+    (primes,expos) = unzip factors++{-# SPECIALIZE liouvilleLambda :: Int     -> Int     #-}+{-# SPECIALIZE liouvilleLambda :: Integer -> Integer #-}+-- | The Liouville lambda function+liouvilleLambda :: (Integral a, Num b) => a -> b+liouvilleLambda n = +  if odd (foldl' (+) 0 $ map snd grps)+    then -1+    else  1+  where+    grps = groupIntegerFactors $ integerFactorsTrialDivision $ fromIntegral n++-- | Sum ofthe of the divisors+divisorSum :: Integer -> Integer+divisorSum n = foldl' (+) 0 [ d | d <- divisors n]++-- | Sum of @k@-th powers of the divisors+divisorSum' :: Int -> Integer -> Integer+divisorSum' k n = foldl' (+) 0 [ d^k | d <- divisors n]++-- | Euler's totient function+eulerTotient :: Integer -> Integer+eulerTotient n = div n prodp * prodp1 where+  grps   = groupIntegerFactors $ integerFactorsTrialDivision n+  ps     = map fst grps+  prodp  = foldl' (*) 1 [ p   | p <- ps ] +  prodp1 = foldl' (*) 1 [ p-1 | p <- ps ] ++-- | Divisors of @n@ (note: the result is /not/ ordered!)+divisors :: Integer -> [Integer]+divisors n = [ f tup | tup <- tuples' expos ] where+  grps = groupIntegerFactors $ integerFactorsTrialDivision n+  (ps,expos) = unzip grps+  f es = foldl' (*) 1 $ zipWith (^) ps es++-- | List of square-free divisors together with their Mobius mu value+-- (note: the result is /not/ ordered!)+squareFreeDivisors :: Integer -> [(Integer,Sign)]+squareFreeDivisors n = map f (sublists primes) where+  grps = groupIntegerFactors $ integerFactorsTrialDivision n+  primes = map fst grps+  f ps = ( foldl' (*) 1 ps , if even (length ps) then Plus else Minus)++-- | List of square-free divisors +-- (note: the result is /not/ ordered!)+squareFreeDivisors_ :: Integer -> [Integer]+squareFreeDivisors_ n = map f (sublists primes) where+  grps = groupIntegerFactors $ integerFactorsTrialDivision n+  primes = map fst grps+  f ps = foldl' (*) 1 ps++-- | To avoid cyclic dependencies, I made a local copy of this...+sublists :: [a] -> [[a]]+sublists [] = [[]]+sublists (x:xs) = sublists xs ++ map (x:) (sublists xs)  ++-------------------------------------------------------------------------------- -- List of prime numbers   -- | Infinite list of primes, using the TMWE algorithm.@@ -54,10 +140,10 @@   pairs ((x:xs):ys:t) = (x : union xs ys) : pairs t    wheel = 2:4:2:4:6:2:6:4:2:4:6:6:2:6:4:2:6:4:6:8:4:2:4:2:             4:8:6:4:6:2:4:6:2:6:6:4:2:4:6:2:6:4:2:4:2:10:2:10:wheel -  gaps k ws@(w:t) cs@ ~(c:u) +  gaps k ws@(w:t) cs@(~(c:u))     | k==c  = gaps (k+w) t u                   | True  = k : gaps (k+w) t cs  -  roll k ws@(w:t) ps@ ~(p:u) +  roll k ws@(w:t) ps@(~(p:u))      | k==p  = scanl (\c d->c+p*d) (p*p) ws : roll (k+w) t u                   | True  = roll (k+w) t ps    @@ -77,6 +163,22 @@  -------------------------------------------------------------------------------- -- Prime factorization++factorize :: Integer -> [(Integer,Int)]+factorize = factorizeNaive++factorizeNaive :: Integer -> [(Integer,Int)]+factorizeNaive = groupIntegerFactors . integerFactorsTrialDivision++productOfFactors :: [(Integer,Int)] -> Integer+productOfFactors = productInterleaved . map (uncurry pow) where+  pow _ 0 = 1+  pow p 1 = p+  pow 2 n = shiftL 1 n+  pow p 2 = p*p+  pow p n = if even n+              then     (pow p (shiftR n 1))^2+              else p * (pow p (shiftR n 1))^2   -- | Groups integer factors. Example: from [2,2,2,3,3,5] we produce [(2,3),(3,2),(5,1)]   groupIntegerFactors :: [Integer] -> [(Integer,Int)]
Math/Combinat/Numbers/Sequences.hs view
@@ -4,39 +4,148 @@ -- See the \"On-Line Encyclopedia of Integer Sequences\", -- <https://oeis.org> . +{-# LANGUAGE BangPatterns, ScopedTypeVariables #-} module Math.Combinat.Numbers.Sequences where  --------------------------------------------------------------------------------  import Data.Array+import Data.Bits ( shiftL , shiftR , (.&.) ) -import Math.Combinat.Helper ( sum' )+import Math.Combinat.Helper  import Math.Combinat.Sign +import Math.Combinat.Numbers.Primes ( primes , factorize , productOfFactors )++import qualified Data.Map.Strict as Map   -- used for factorialPrimeExponentsNaive+ -------------------------------------------------------------------------------- -- * Factorial --- | A000142.+-- | The factorial function (A000142). factorial :: Integral a => a -> Integer-factorial n-  | n <  0    = error "factorial: input should be nonnegative"+factorial = factorialSplit++-- | Faster implementation of the factorial function+factorialSplit :: Integral a => a -> Integer+factorialSplit n = productFromTo 1 n++-- | Naive implementation of factorial+factorialNaive :: Integral a => a -> Integer+factorialNaive n+  | n <  0    = error "factorialNaive: input should be nonnegative"   | n == 0    = 1   | otherwise = product [1..fromIntegral n] --- | A006882.+-- | \"Swing factorial\" algorithm+factorialSwing :: Integral a => a -> Integer+factorialSwing n = productOfFactors (factorialPrimeExponents $ fromIntegral n) where++--------------------------------------------------------------------------------++-- | Prime factorization of the factorial (using the \"swing factorial\" algorithm)+factorialPrimeExponents :: Int -> [(Integer,Int)]+factorialPrimeExponents n = filter cond $ zip primes (factorialPrimeExponents_ n) where+  cond (_,!e) = e > 0++factorialPrimeExponentsNaive :: forall a. Integral a => a -> [(Integer,Int)]+factorialPrimeExponentsNaive n = result where+  fi = fromIntegral :: a -> Integer+  result = Map.toList +         $ Map.unionsWith (+) +         $ map Map.fromList +         $ map factorize +         $ map fi [1..n] ++factorialPrimeExponents_ :: Int -> [Int]+factorialPrimeExponents_ = go where+  go  0 = []+  go  1 = []+  go  2 = [1]+  go !n = longAdd half swing where+    half  = map (flip shiftL 1) $ go (shiftR n 1)+    swing = swingFactorialExponents_ n++  longAdd :: [Int] -> [Int] -> [Int]+  longAdd xs [] = xs+  longAdd [] ys = ys+  longAdd (!x:xs) (!y:ys) = (x+y) : longAdd xs ys++-- | Prime factorizaiton of the \"swing factorial\" function)+swingFactorialExponents_ :: Int -> [Int]+swingFactorialExponents_ = go where+  go 0 = []+  go 1 = []+  go 2 = [1]+  go n = expo2 : map expo (tail ps) where++    nn = fromIntegral n :: Integer++    ps :: [Integer]+    ps = takeWhile (<=nn) primes ++    expo2 :: Int+    expo2 = go 0 (shiftR n 1) where+      go :: Int -> Int -> Int+      go !acc !r  +        | r < 1     = acc+        | otherwise = go acc' r' +        where+          acc' = acc + (r .&. 1)+          r'   = shiftR r 1++    expo :: Integer -> Int+    expo pp = go 0 (div n p) where+      p = fromInteger pp :: Int+      go :: Int -> Int -> Int+      go !acc !r  +        | r < 1     = acc+        | otherwise = go acc' r' +        where+          acc' = acc + (r .&. 1)+          r'   = div r p++--------------------------------------------------------------------------------++-- | The double factorial doubleFactorial :: Integral a => a -> Integer-doubleFactorial n-  | n <  0    = error "doubleFactorial: input should be nonnegative"+doubleFactorial = doubleFactorialSplit++-- | Faster implementation of the double factorial function+doubleFactorialSplit :: Integral a => a -> Integer+doubleFactorialSplit n+  | n <  0    = error "doubleFactorialSplit: input should be nonnegative"   | n == 0    = 1+  | odd n     = productFromToStride2 2 n+  | otherwise = let halfn = div n 2 +                in  shiftL (factorialSplit halfn) (fromIntegral halfn)++-- | Naive implementation of the double factorial (A006882).+doubleFactorialNaive :: Integral a => a -> Integer+doubleFactorialNaive n+  | n <  0    = error "doubleFactorialNaive: input should be nonnegative"+  | n == 0    = 1   | odd n     = product [1,3..fromIntegral n]   | otherwise = product [2,4..fromIntegral n]  -------------------------------------------------------------------------------- -- * Binomial and multinomial --- | A007318. Note: This is zero for @n<0@ or @k<0@; see also 'signedBinomial' below.+-- | Binomial numbers (A007318). Note: This is zero for @n<0@ or @k<0@; see also 'signedBinomial' below. binomial :: Integral a => a -> a -> Integer-binomial n k +binomial = binomialSplit++-- | Faster implementation of binomial+binomialSplit :: Integral a => a -> a -> Integer+binomialSplit n k +  | k > n = 0+  | k < 0 = 0+  | k > (n `div` 2) = binomialSplit n (n-k)+  | otherwise = (productFromTo (n-k) n) `div` (productFromTo 1 k)++-- | A007318. Note: This is zero for @n<0@ or @k<0@; see also 'signedBinomial' below.+binomialNaive :: Integral a => a -> a -> Integer+binomialNaive n k    | k > n = 0   | k < 0 = 0   | k > (n `div` 2) = binomial n (n-k)
Math/Combinat/Partitions/Integer.hs view
@@ -29,6 +29,10 @@   , toPartition    , toPartitionUnsafe    , isPartition +    -- * Conversion to\/from exponent vectors+  , toExponentVector+  , fromExponentVector+  , dropTailingZeros     -- * Union and sum   , unionOfPartitions   , sumOfPartitions@@ -49,8 +53,12 @@   , randomPartition   , randomPartitions     -- * Dominating \/ dominated partitions+  , dominanceCompare   , dominatedPartitions    , dominatingPartitions +    -- * Conjugate lexicographic ordering+  , conjugateLexicographicCompare +  , ConjLex (..) , fromConjLex      -- * Partitions with given number of parts   , partitionsWithKParts     -- * Partitions with only odd\/distinct parts@@ -83,7 +91,7 @@ import Data.Array import System.Random -import Math.Combinat.Partitions.Integer.Naive+import Math.Combinat.Partitions.Integer.Naive hiding ()    -- this is for haddock! import Math.Combinat.Partitions.Integer.IntList import Math.Combinat.Partitions.Integer.Count @@ -116,6 +124,41 @@ isPartition (x:xs@(y:_)) = (x >= y) && isPartition xs  --------------------------------------------------------------------------------+-- * Conversion to\/from exponent vectors+     +-- | Converts a partition to an exponent vector.+--+-- For example, +--+-- > toExponentVector (Partition [4,4,2,2,2,1]) == [1,3,0,2]+--+-- meaning @(1^1,2^3,3^0,4^2)@.+--+toExponentVector :: Partition -> [Int]+toExponentVector part = fun 1 $ reverse $ group (fromPartition part) where+  fun _  [] = []+  fun !k gs@(this@(i:_):rest) +    | k < i      = replicate (i-k) 0 ++ fun i gs+    | otherwise  = length this : fun (k+1) rest++fromExponentVector :: [Int] -> Partition+fromExponentVector expos = Partition $ concat $ reverse $ zipWith f [1..] expos where+  f !i !e = replicate e i++dropTailingZeros :: [Int] -> [Int]+dropTailingZeros = reverse . dropWhile (==0) . reverse++{-+-- alternative implementation+toExponentialVector2 :: Partition -> [Int]+toExponentialVector2 p = go 1 (toExponentialForm p) where+  go _  []              = []+  go !i ef@((j,e):rest) = if i<j +    then 0 : go (i+1) ef+    else e : go (i+1) rest+-}++-------------------------------------------------------------------------------- -- * Union and sum  -- | This is simply the union of parts. For example @@ -232,6 +275,14 @@ -------------------------------------------------------------------------------- -- * Dominating \/ dominated partitions +-- | Dominance partial ordering as a partial ordering.+dominanceCompare :: Partition -> Partition -> Maybe Ordering+dominanceCompare p q  +  | p==q             = Just EQ+  | p `dominates` q  = Just GT+  | q `dominates` p  = Just LT+  | otherwise        = Nothing+ -- | Lists all partitions of the same weight as @lambda@ and also dominated by @lambda@ -- (that is, all partial sums are less or equal): --@@ -247,6 +298,28 @@ --  dominatingPartitions :: Partition -> [Partition]     dominatingPartitions (Partition_ mu) = map Partition_ (_dominatingPartitions mu)++--------------------------------------------------------------------------------+-- * Conjugate lexicographic ordering++conjugateLexicographicCompare :: Partition -> Partition -> Ordering+conjugateLexicographicCompare p q = compare (dualPartition q) (dualPartition p) ++newtype ConjLex = ConjLex Partition deriving (Eq,Show)++fromConjLex :: ConjLex -> Partition+fromConjLex (ConjLex p) = p++instance Ord ConjLex where+  compare (ConjLex p) (ConjLex q) = conjugateLexicographicCompare p q++-- {- CONJUGATE LEXICOGRAPHIC ordering is a refinement of dominance partial ordering -}+-- let test n = [ ConjLex p >= ConjLex q | p <- partitions n , q <-partitions n ,  p `dominates` q ]+-- and (test 20)++-- {- LEXICOGRAPHIC ordering is a refinement of dominance partial ordering -}+-- let test n = [ p >= q | p <- partitions n , q <-partitions n ,  p `dominates` q ]+-- and (test 20)  -------------------------------------------------------------------------------- -- * Partitions with given number of parts
Math/Combinat/Partitions/Integer/Compact.hs view
@@ -3,25 +3,17 @@  Partitions are conceptually nonincreasing sequences of /positive/ integers. -When the partition fits into a 15x15 rectangle, we encode the parts as nibbles in a single 64-bit word.-The most significant nibble is the first element, and the least significant nibble is used to encode-the length. This way equality and comparison of 64-bit words is the same as the corresponding operations-for partitions (lexicographic ordering).--This will make working with small partitions much more memory efficient (very helpful when-building tables indexed by partitions, for example!) and hopefully quite a bit faster, too.--When they do not fit into a 15x15 rectangle, but fit into 255x7, 255x15, 255x23 or 255x31, respectively,-then we extend the above to use the bytes of 1, 2, 3 or 4 64-bit words.--In the general case, we encode the partition as a list of 64-bit words, each encoding 4 16-bit parts.--Partitions with elements bigger than 65535 are not supported.+This implementation uses the @compact-word-vectors@ library internally to provide+a much more memory-efficient Partition type that the naive lists of integer.+This is very helpful when building large tables indexed by partitions, for example; +and hopefully quite a bit faster, too.  Note: This is an internal module, you are not supposed to import it directly.+It is also not fully ready to be used yet...+ -} -{-# LANGUAGE BangPatterns, PatternSynonyms, ViewPatterns, ForeignFunctionInterface #-}+{-# LANGUAGE BangPatterns, PatternSynonyms, ViewPatterns #-} module Math.Combinat.Partitions.Integer.Compact where  --------------------------------------------------------------------------------@@ -31,41 +23,30 @@ import Data.Ord import Data.List ( intercalate , group , sort , sortBy , foldl' , scanl' )  -import Math.Combinat.Compositions ( compositions' )+import Data.Vector.Compact.WordVec ( WordVec , Shape(..) )+import qualified Data.Vector.Compact.WordVec as V +import Math.Combinat.Compositions ( compositions' )  -------------------------------------------------------------------------------- -- * The compact partition data type -data Partition-  = Nibble   {-# UNPACK #-} !Word64-  | Medium1  {-# UNPACK #-} !Word64-  | Medium2  {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64-  | Medium3  {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64-  | Medium4  {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64-  | WordList {-# UNPACK #-} !Int ![Word64]-  deriving (Eq,Show)-----------------------------------------------------------------------------------  --- | for debugging-partitionPrefixChar :: Partition -> Char-partitionPrefixChar p = case p of-  Nibble   {} -> 'N'-  Medium1  {} -> '1'-  Medium2  {} -> '2' -  Medium3  {} -> '3' -  Medium4  {} -> '4' -  WordList {} -> 'L'+newtype Partition +  = Partition WordVec +  deriving Eq -{-  instance Show Partition where-  show compact = partitionPrefixChar compact -               : '<' : intercalate "," (map show $ toList compact) ++ ">"--}+  showsPrec = showsPrecPartition +showsPrecPartition :: Int -> Partition -> ShowS+showsPrecPartition prec (Partition vec)+  = showParen (prec > 10) +  $ showString "Partition"+  . showChar ' ' +  . shows (V.toList vec)+ instance Ord Partition where-  compare = cmp+  compare = cmpLexico                 -------------------------------------------------------------------------------- -- * Pattern synonyms @@ -97,200 +78,60 @@ -- * Lexicographic comparison  -- | The lexicographic ordering-cmp :: Partition -> Partition -> Ordering-cmp (Nibble  a)           (Nibble  b)           = compare  a             b-cmp (Medium1 a1)          (Medium1 b1)          = compare  a1            b1-cmp (Medium2 a1 a2)       (Medium2 b1 b2)       = compare (a1,a2)       (b1,b2)-cmp (Medium3 a1 a2 a3)    (Medium3 b1 b2 b3)    = compare (a1,a2,a3)    (b1,b2,b3)-cmp (Medium4 a1 a2 a3 a4) (Medium4 b1 b2 b3 b4) = compare (a1,a2,a3,a4) (b1,b2,b3,b4)-cmp (WordList _ as)       (WordList _ bs)       = compare  as            bs-cmp p                     q                     = compare (toList p)    (toList q)-  +cmpLexico :: Partition -> Partition -> Ordering+cmpLexico (Partition vec1) (Partition vec2) = compare (V.toList vec1) (V.toList vec2)+ -------------------------------------------------------------------------------- -- * Basic (de)constructrion  empty :: Partition-empty = Nibble 0+empty = Partition (V.empty)  isEmpty :: Partition -> Bool-isEmpty compact = case compact of-  Nibble x -> (x == 0)-  _        -> False+isEmpty (Partition vec) = V.null vec  --------------------------------------------------------------------------------  singleton :: Int -> Partition-singleton x-  | x == 0      = Nibble 0-  | x <= 15     = Nibble     $ shiftL (i2w x) 60 + 1-  | x <= 255    = Medium1    $ shiftL (i2w x) 56 + 1-  | x <= 65535  = WordList 1 [ shiftL (i2w x) 48 ]-  | otherwise   = error "singleton: partitions with elements bigger than 65535 are not supported"+singleton x +  | x >  0     = Partition (V.singleton $ i2w x)+  | x == 0     = empty+  | otherwise  = error "Parittion/singleton: negative input"  --------------------------------------------------------------------------------  uncons :: Partition -> Maybe (Int,Partition)-uncons compact = case compact of-  Nibble  0           -> Nothing-  Nibble  w           -> Just ( w2i (shiftR w  60) , Nibble $ shiftL (w .&. 0x0ffffffffffffff0) 4 + ((w .&. 15) - 1) )-  Medium1 w1          -> Just ( w2i (shiftR w1 56) , partitionTail compact )-  Medium2 w1 w2       -> Just ( w2i (shiftR w1 56) , partitionTail compact )-  Medium3 w1 w2 w3    -> Just ( w2i (shiftR w1 56) , partitionTail compact )-  Medium4 w1 w2 w3 w4 -> Just ( w2i (shiftR w1 56) , partitionTail compact )-  WordList n (w:rest) -> Just ( w2i (shiftR w  48) , partitionTail compact )----------------------------------------------------------------------------------+uncons (Partition vec) = case V.uncons vec of+  Nothing     -> Nothing+  Just (h,tl) -> Just (w2i h, Partition tl)  -- | @partitionTail p == snd (uncons p)@ partitionTail :: Partition -> Partition-partitionTail compact = case compact of--  Nibble  0 -> Nibble 0-  Nibble  w -> Nibble $ shiftL (w .&. 0x0ffffffffffffff0) 4 + ((w .&. 15) - 1) --  Medium1 w1 ->-    let !y = (shiftR w1 48) .&. 255     -- next element-        !n = w1 .&. 15-    in  if y <= 15 -          then makeNibble (w2i $ n-1) $ safeTail $ toList compact-          else Medium1    $ shiftL (w1 .&. 0x00ffffffffffff00) 8 + (n-1) --  Medium2 w1 w2 ->      -    let !y = (shiftR w1 48) .&. 255-        !n = w2 .&. 255-    in  if y <= 15 -          then makeNibble (w2i $ n-1) $ safeTail $ toList compact-          else if n <= 8-            then Medium1 $ shiftL (w1 .&. 0x00ffffffffffffff) 8 + shiftL (shiftR w2 56) 8 + (n-1) --            else Medium2 ( shiftL  w1 8 + shiftR w2 56 ) -                         ( shiftL (w2 .&. 0x00ffffffffffff00) 8 + (n-1) )--  Medium3 w1 w2 w3 ->   -    let !y = (shiftR w1 48) .&. 255-        !n = w3 .&. 255-    in  if y <= 15 && n <= 16-          then makeNibble (w2i $ n-1) $ safeTail $ toList compact-          else if n <= 16-            then Medium2 ( shiftL  w1 8 + shiftR w2 56 ) -                         ( shiftL  w2 8 + shiftR w3 56 + shiftL (shiftR w3 56) 8 + (n-1) )- -            else Medium3 ( shiftL  w1 8 + shiftR w2 56 ) -                         ( shiftL  w2 8 + shiftR w3 56 ) -                         ( shiftL (w3 .&. 0x00ffffffffffff00) 8 + (n-1) )- -  _ -> -    let n = width compact-    in  fromDescList' (n-1) $ safeTail $ toList compact +partitionTail (Partition vec) = Partition (V.tail vec) ---------------------------------------------------------------------------------+-------------------------------------------------------------------------------  -- | We assume that @x >= partitionHeight p@! cons :: Int -> Partition -> Partition-cons !x !compact = case compact of--  Nibble 0                -> singleton x-  -  Nibble word-    | x <= 15  && n < 15  -> Nibble $ shiftR word 4 + shiftL xw 60 + (n+1)-    | x <= 255            -> makeMedium   (w2i $ n+1) (x : toList compact)-    | otherwise           -> makeWordList (w2i $ n+1) (x : toList compact)-    where  -      n  = word .&. 15-      xw = i2w x-      -  Medium1 w1-    | x <= 255 && n < 7   -> Medium1 (shiftR w1 8 + shiftL xw 56 + (n+1))-    | x <= 255            -> Medium2 (shiftR w1 8 + shiftL xw 56        ) 8-    | otherwise           -> makeWordList (w2i $ n+1) (x : toList compact)-    where  -      n  = w1 .&. 255-      xw = i2w x--  Medium2 w1 w2-    | x <= 255 && n < 15  -> Medium2 (shiftR w1 8 + shiftL xw 56) (shiftR w2 8 + shiftL (w1 .&. 255) 56 + (n+1))-    | x <= 255            -> Medium3 (shiftR w1 8 + shiftL xw 56) (shiftR w2 8 + shiftL (w1 .&. 255) 56        ) 16-    | otherwise           -> makeWordList (w2i $ n+1) (x : toList compact)-    where  -      n  = w2 .&. 255-      xw = i2w x--  Medium3 w1 w2 w3-    | x <= 255 && n < 23  -> Medium3 (shiftR w1 8 + shiftL xw 56) (shiftR w2 8 + shiftL (w1 .&. 255) 56) (shiftR w3 8 + shiftL (w2 .&. 255) 56 + (n+1))-    | x <= 255            -> Medium4 (shiftR w1 8 + shiftL xw 56) (shiftR w2 8 + shiftL (w1 .&. 255) 56) (shiftR w3 8 + shiftL (w2 .&. 255) 56        ) 24-    | otherwise           -> makeWordList (w2i $ n+1) (x : toList compact)-    where  -      n  = w3 .&. 255-      xw = i2w x--  Medium4 w1 w2 w3 w4-    | x <= 255 && n < 31  -> Medium4 (shiftR w1 8 + shiftL  xw          56) -                                     (shiftR w2 8 + shiftL (w1 .&. 255) 56) -                                     (shiftR w3 8 + shiftL (w2 .&. 255) 56) -                                     (shiftR w4 8 + shiftL (w3 .&. 255) 56 + (n+1))-    | otherwise           -> makeWordList (w2i $ n+1) (x : toList compact)-    where  -      n = w4 .&. 255-      xw = i2w x-      -  _ -> -    let n = width compact-    in  fromDescList' (n+1) (x : toList compact)+cons !x (Partition !vec) +  | V.null vec = Partition (if x > 0 then V.singleton y else V.empty) +  | y >= h     = Partition (V.cons y vec)+  | otherwise  = error "Partition/cons: invalid element to cons"+  where  +    y = i2w x+    h = V.head vec  --------------------------------------------------------------------------------  -- | We assume that the element is not bigger than the last element! snoc :: Partition -> Int -> Partition-snoc !compact  0 = compact-snoc !compact !x = case compact of--  Nibble 0 -> singleton x--  Nibble word-    | n < 15    -> Nibble $ (word + 1) .|. shiftL (i2w x) ((15-n)*4)-    | otherwise -> makeMedium (n+1) (toList compact ++ [x])-    where  -      n = w2i (word .&. 15)-      -  Medium1 w1-    | n < 7     -> Medium1 $ (w1 + 1) .|. shiftL (i2w x) ((7-n)*8)-    | otherwise -> Medium2 ((w1 .&. 0xffffffffffffff00) + i2w x) 8-    where  -      n = w2i (w1 .&. 255)--  Medium2 w1 w2-    | n < 15    -> Medium2 w1 $ (w2 + 1) .|. shiftL (i2w x) ((15-n)*8)-    | otherwise -> Medium3 w1 ((w2 .&. 0xffffffffffffff00) + i2w x) 16-    where  -      n = w2i (w2 .&. 255)--  Medium3 w1 w2 w3-    | n < 23    -> Medium3 w1 w2 $ (w3 + 1) .|. shiftL (i2w x) ((23-n)*8)-    | otherwise -> Medium4 w1 w2 ((w3 .&. 0xffffffffffffff00) + i2w x) 24-    where  -      n = w2i (w3 .&. 255)--  Medium4 w1 w2 w3 w4-    | n < 31    -> Medium4 w1 w2 w3 $ (w4 + 1) .|. shiftL (i2w x) ((31-n)*8)-    | otherwise -> makeWordList (n + 1) (toList compact ++ [x])-    where  -      n = w2i (w4 .&. 255)-  -  WordList n list -> WordList (n+1) (go list) where-    go :: [Word64] -> [Word64]-    go (w:[]) = case mod n 4 of-                  0 -> w : shiftL (i2w x) 48 : []-                  1 -> w + shiftL (i2w x) 32 : []-                  2 -> w + shiftL (i2w x) 16 : []-                  3 -> w +        (i2w x)    : []-    go (w:ws) = w : go ws-    go []     = shiftL (i2w x) 48 : []- -{-   -  _ -> -    let n = width compact-    in  makeWordList (n+1) (toList compact ++ [x])--}+snoc (Partition !vec) !x+  | x == 0           = Partition vec+  | V.null vec       = Partition (V.singleton y)+  | y <= V.last vec  = Partition (V.snoc vec y)+  | otherwise        = error "Partition/snoc: invalid element to snoc"+  where+    y = i2w x  -------------------------------------------------------------------------------- -- * exponential form@@ -308,33 +149,15 @@  -- | Width, or the number of parts width :: Partition -> Int-width compact = case compact of-  Nibble        word -> w2i (word .&.  15)-  Medium1       word -> w2i (word .&. 255)-  Medium2 _     word -> w2i (word .&. 255)-  Medium3 _ _   word -> w2i (word .&. 255)-  Medium4 _ _ _ word -> w2i (word .&. 255)-  WordList n    _    -> n+width (Partition vec) = V.vecLen vec  -- | Height, or the first (that is, the largest) element height :: Partition -> Int-height compact = case compact of-  Nibble  word        -> w2i (shiftR word 60)-  Medium1 word        -> w2i (shiftR word 56)-  Medium2 word _      -> w2i (shiftR word 56)-  Medium3 word _ _    -> w2i (shiftR word 56)-  Medium4 word _ _ _  -> w2i (shiftR word 56)-  WordList _ (word:_) -> w2i (shiftR word 48)+height (Partition vec) = w2i (V.head vec)  -- | Width and height  widthHeight :: Partition -> (Int,Int)-widthHeight compact = case compact of -  Nibble  word            -> ( w2i (word  .&.  15) , w2i (shiftR word  60) )-  Medium1 word            -> ( w2i (word  .&. 255) , w2i (shiftR word  56) )-  Medium2 word1     word2 -> ( w2i (word2 .&. 255) , w2i (shiftR word1 56) )-  Medium3 word1 _   word3 -> ( w2i (word3 .&. 255) , w2i (shiftR word1 56) )-  Medium4 word1 _ _ word4 -> ( w2i (word4 .&. 255) , w2i (shiftR word1 56) )-  WordList n (word:_)     -> ( n                   , w2i (shiftR word  48) )+widthHeight (Partition vec) = (V.vecLen vec , w2i (V.head vec))  -------------------------------------------------------------------------------- -- * Differential sequence@@ -342,132 +165,35 @@ -- | From a non-increasing sequence @[a1,a2,..,an]@ this computes the sequence of differences -- @[a1-a2,a2-a3,...,an-0]@ diffSequence :: Partition -> [Int]-diffSequence compact = case compact of--  Nibble 0 -> []--  Nibble w -> -    let !nw = (w .&. 15) -        !w' = w - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w (60 - i*4) - shiftR w' (56 - i*4)) .&. 15 | i<-[0..n-1] ]--  Medium1 w -> -    let !nw = (w .&. 255) -        !w' = w - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w (56 - i*8) - shiftR w' (48 - i*8)) .&. 255 | i<-[0..n-1] ]--  Medium2 w1 w2 -> -    let !nw = (w2 .&. 255) -        !w2' = w2 - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w1 (56 - i*8) - shiftR w1  (48 - i*8)) .&. 255 | i<-[0..6]   ] ++ -        ( w2i $ (       w1            - shiftR w2   56       ) .&. 255               ) : -        [ w2i $ (shiftR w2 (56 - i*8) - shiftR w2' (48 - i*8)) .&. 255 | i<-[0..n-9] ] --  Medium3 w1 w2 w3 -> -    let !nw = (w3 .&. 255) -        !w3' = w3 - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w1 (56 - i*8) - shiftR w1  (48 - i*8)) .&. 255 | i<-[0..6]    ] ++ -        ( w2i $ (       w1            - shiftR w2   56       ) .&. 255                ) : -        [ w2i $ (shiftR w2 (56 - i*8) - shiftR w2  (48 - i*8)) .&. 255 | i<-[0..6]    ] ++-        ( w2i $ (       w2            - shiftR w3   56       ) .&. 255                ) : -        [ w2i $ (shiftR w3 (56 - i*8) - shiftR w3' (48 - i*8)) .&. 255 | i<-[0..n-17] ] --  Medium4 w1 w2 w3 w4 -> -    let !nw = (w4 .&. 255) -        !w4' = w4 - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w1 (56 - i*8) - shiftR w1  (48 - i*8)) .&. 255 | i<-[0..6]    ] ++ -        ( w2i $ (       w1            - shiftR w2   56       ) .&. 255                ) : -        [ w2i $ (shiftR w2 (56 - i*8) - shiftR w2  (48 - i*8)) .&. 255 | i<-[0..6]    ] ++-        ( w2i $ (       w2            - shiftR w3   56       ) .&. 255                ) : -        [ w2i $ (shiftR w3 (56 - i*8) - shiftR w3  (48 - i*8)) .&. 255 | i<-[0..6]    ] ++-        ( w2i $ (       w3            - shiftR w4   56       ) .&. 255                ) : -        [ w2i $ (shiftR w4 (56 - i*8) - shiftR w4' (48 - i*8)) .&. 255 | i<-[0..n-25] ] --  WordList {} -> go (toList compact) where-    go (x:ys@(y:_)) = (x-y) : go ys -    go [x] = [x]-    go []  = []+diffSequence = go . toDescList where+  go (x:ys@(y:_)) = (x-y) : go ys +  go [x] = [x]+  go []  = []  ----------------------------------------  -- | From a non-increasing sequence @[a1,a2,..,an]@ this computes the reversed sequence of differences -- @[ a[n]-0 , a[n-1]-a[n] , ... , a[2]-a[3] , a[1]-a[2] ] @ reverseDiffSequence :: Partition -> [Int]-reverseDiffSequence compact = case compact of--  Nibble 0 -> []--  Nibble w -> -    let !nw = (w .&. 15) -        !w' = w - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w (60 - i*4) - shiftR w' (56 - i*4)) .&. 15 | i<-toZero (n-1) ]--  Medium1 w -> -    let !nw = (w .&. 255) -        !w' = w - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w (56 - i*8) - shiftR w' (48 - i*8)) .&. 255 | i<-toZero (n-1) ]--  Medium2 w1 w2 -> -    let !nw = (w2 .&. 255) -        !w2' = w2 - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w2 (56 - i*8) - shiftR w2' (48 - i*8)) .&. 255 | i<-toZero (n-9) ] ++-        ( w2i $ (       w1            - shiftR w2   56       ) .&. 255                   ) : -        [ w2i $ (shiftR w1 (56 - i*8) - shiftR w1  (48 - i*8)) .&. 255 | i<-toZero 6     ]  -        -  Medium3 w1 w2 w3 -> -    let !nw = (w3 .&. 255) -        !w3' = w3 - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w3 (56 - i*8) - shiftR w3' (48 - i*8)) .&. 255 | i<-toZero (n-17) ] ++-        ( w2i $ (       w2            - shiftR w3   56       ) .&. 255                    ) : -        [ w2i $ (shiftR w2 (56 - i*8) - shiftR w2  (48 - i*8)) .&. 255 | i<-toZero 6      ] ++-        ( w2i $ (       w1            - shiftR w2   56       ) .&. 255                    ) : -        [ w2i $ (shiftR w1 (56 - i*8) - shiftR w1  (48 - i*8)) .&. 255 | i<-toZero 6      ] --  Medium4 w1 w2 w3 w4 -> -    let !nw = (w4 .&. 255) -        !w4' = w4 - nw-        !n  = w2i nw-    in  [ w2i $ (shiftR w4 (56 - i*8) - shiftR w4' (48 - i*8)) .&. 255 | i<-toZero (n-25) ] ++-        ( w2i $ (       w3            - shiftR w4   56       ) .&. 255                    ) : -        [ w2i $ (shiftR w3 (56 - i*8) - shiftR w3  (48 - i*8)) .&. 255 | i<-toZero 6      ] ++-        ( w2i $ (       w2            - shiftR w3   56       ) .&. 255                    ) : -        [ w2i $ (shiftR w2 (56 - i*8) - shiftR w2  (48 - i*8)) .&. 255 | i<-toZero 6      ] ++-        ( w2i $ (       w1            - shiftR w2   56       ) .&. 255                    ) : -        [ w2i $ (shiftR w1 (56 - i*8) - shiftR w1  (48 - i*8)) .&. 255 | i<-toZero 6      ] --  WordList {} -> (h : go asclist) where-    asclist@(h:_) = toAscList compact-    go (x:ys@(y:_)) = (y-x) : go ys -    go [_] = []-    go []  = []+reverseDiffSequence p = go (0 : toAscList p) where+  go (x:ys@(y:_)) = (y-x) : go ys +  go [x] = []+  go []  = []  -------------------------------------------------------------------------------- -- *  Dual partition -foreign import ccall unsafe "c_dual_nibble" c_dual_nibble :: Word64 -> Word64- dualPartition :: Partition -> Partition-dualPartition compact = case compact of--  Nibble 0 -> Nibble 0-  Nibble w -> Nibble (c_dual_nibble w)  -  _        -> if (w <= 255 && h <= 31)-                then makeMedium   h dualList-                else makeWordList h dualList+dualPartition compact@(Partition vec) +  | V.null vec  = Partition V.empty+  | otherwise   = Partition (V.fromList' shape $ map i2w dual)   where-    (w,h) = widthHeight compact-    dualList = concat+    height = V.head   vec+    len    = V.vecLen vec+    shape  = Shape (w2i height) (V.bitsNeededFor $ i2w len)+    dual   = concat       [ replicate d j-      | (j,d) <- zip (toOne w) (reverseDiffSequence compact)+      | (j,d) <- zip (descendToOne len) (reverseDiffSequence compact)       ]  --------------------------------------------------------------------------------@@ -478,106 +204,11 @@  -- | returns a descending (non-increasing) list toDescList :: Partition -> [Int]-toDescList compact = case compact of--  Nibble 0 -> []--  Nibble word -> -    let !n = w2i (word .&. 15) -    in  [ w2i (shiftR word  (60 - i*4) .&. 15 ) | i<-[0..n-1] ]--  Medium1 word1 -> -    let !n = w2i (word1 .&. 255)-    in  [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-[0..n-1] ]--  Medium2 word1 word2 -> -    let !n = w2i (word2 .&. 255) -    in  [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-[0..7]   ] ++-        [ w2i (shiftR word2 (56 - i*8) .&. 255) | i<-[0..n-9] ] --  Medium3 word1 word2 word3 -> -    let !n = w2i (word3 .&. 255) -    in  [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-[0..7]    ] ++-        [ w2i (shiftR word2 (56 - i*8) .&. 255) | i<-[0..7]    ] ++-        [ w2i (shiftR word3 (56 - i*8) .&. 255) | i<-[0..n-17] ] --  Medium4 word1 word2 word3 word4 -> -    let !n = w2i (word4 .&. 255) -    in  [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-[0..7]    ] ++-        [ w2i (shiftR word2 (56 - i*8) .&. 255) | i<-[0..7]    ] ++-        [ w2i (shiftR word3 (56 - i*8) .&. 255) | i<-[0..7]    ] ++-        [ w2i (shiftR word4 (56 - i*8) .&. 255) | i<-[0..n-25] ] --  WordList _ list -> go list where-    go :: [Word64] -> [Int]-    go !wlist = case wlist of-      (!w):(!ws) -> case ws of -        (_:_)      -> w2i (shiftR w 48          ) :-                      w2i (shiftR w 32 .&. 65535) :-                      w2i (shiftR w 16 .&. 65535) :-                      w2i (       w    .&. 65535) : go ws-        []         -> takeWhile (/=0) (fromWord w)-      []         -> []--    fromWord :: Word64 -> [Int]-    fromWord !word = -      [ w2i (shiftR word 48          )-      , w2i (shiftR word 32 .&. 65535)-      , w2i (shiftR word 16 .&. 65535)-      , w2i (       word    .&. 65535)-      ]------------------------------------------+toDescList (Partition vec) = map w2i (V.toList vec)  -- | Returns a reversed (ascending; non-decreasing) list toAscList :: Partition -> [Int]-toAscList compact = case compact of--  Nibble 0 -> []--  Nibble word -> -    let !n = w2i (word .&. 15) -    in  [ w2i (shiftR word  (60 - i*4) .&. 15 ) | i<-toZero (n-1) ]--  Medium1 word1 -> -    let !n = w2i (word1 .&. 255)-    in  [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-toZero (n-1) ]--  Medium2 word1 word2 -> -    let !n = w2i (word2 .&. 255) -    in  [ w2i (shiftR word2 (56 - i*8) .&. 255) | i<-toZero (n-9) ] ++-        [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-toZero 7     ] --  Medium3 word1 word2 word3 -> -    let !n = w2i (word3 .&. 255) -    in  [ w2i (shiftR word3 (56 - i*8) .&. 255) | i<-toZero (n-17) ] ++-        [ w2i (shiftR word2 (56 - i*8) .&. 255) | i<-toZero 7      ] ++-        [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-toZero 7      ]-        -  Medium4 word1 word2 word3 word4 -> -    let !n = w2i (word4 .&. 255) -    in  [ w2i (shiftR word4 (56 - i*8) .&. 255) | i<-toZero (n-25) ] ++-        [ w2i (shiftR word3 (56 - i*8) .&. 255) | i<-toZero 7      ] ++-        [ w2i (shiftR word2 (56 - i*8) .&. 255) | i<-toZero 7      ] ++-        [ w2i (shiftR word1 (56 - i*8) .&. 255) | i<-toZero 7      ]--  WordList _ list -> dropWhile (==0) $ go (reverse list) where-    go :: [Word64] -> [Int]-    go !wlist = case wlist of-      (!w):ws -> w2i (       w    .&. 65535) : -                 w2i (shiftR w 16 .&. 65535) :-                 w2i (shiftR w 32 .&. 65535) :-                 w2i (shiftR w 48          ) : go ws-      [] -> []--{--    go :: [Word64] -> [Int]-    go (w:[]) = fromWord w-    go (w:ws) = fromWord w ++ go ws-    go []     = []-    fromWord :: Word64 -> [Int]-    fromWord word = [ w2i (shiftR word (48 - i*16) .&. 65535) | i<-toZero 3 ] --}+toAscList (Partition vec) = map w2i (V.toRevList vec)  -------------------------------------------------------------------------------- -- * Conversion from list@@ -590,129 +221,33 @@   :: Int          -- ^ length   -> [Int]        -- ^ the list   -> Partition-fromDescList' !n !list =-  case list of-    []                           -> empty-    (h:_) | h <= 0               -> empty-          | h <= 15 && n <= 15   -> makeNibble   n list-          | h >  65535           -> error "partitions with elements bigger than 65535 are not supported"-          | h >  255 || n > 31   -> makeWordList n list-          | otherwise            -> makeMedium   n list--makeNibble :: Int -> [Int] -> Partition-makeNibble !n list = Nibble $ go (i2w n) 60 list where-  go !acc !k (x:xs) = go (acc + shiftL (i2w x) k) (k-4) xs-  go !acc _  []     = acc-{-   -makeNibble :: Int -> [Int] -> Partition-makeNibble !n list = Nibble -  $ sum' [ shiftL (i2w x) (60 - 4*i) | (i,x) <- zip [0..] list ] -  + i2w n--}--makeMedium :: Int -> [Int] -> Partition-makeMedium !n list -  | n <= 7   = makeMedium1 n list-  | n <= 15  = makeMedium2 n list-  | n <= 23  = makeMedium3 n list-  | n <= 31  = makeMedium4 n list-  | otherwise = error "makeMedium: input list too big (should be smaller than 32)"--makeMedium1 :: Int -> [Int] -> Partition-makeMedium1 !n list = Medium1 -  $ sum' [ shiftL (fromIntegral x) (56 - 8*i) | (i,x) <- zip [0..] list ] -  + fromIntegral n--makeMedium2 :: Int -> [Int] -> Partition-makeMedium2 !n list = Medium2 word1 word2 where-  (list1,list2) = splitAt 8 list-  word1 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list1 ] -  word2 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list2 ] -        + fromIntegral n--makeMedium3 :: Int -> [Int] -> Partition-makeMedium3 !n list = Medium3 word1 word2 word3 where-  (list1,tmp  ) = splitAt 8 list-  (list2,list3) = splitAt 8 tmp-  word1 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list1 ] -  word2 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list2 ] -  word3 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list3 ] -        + i2w n--makeMedium4 :: Int -> [Int] -> Partition-makeMedium4 !n list = Medium4 word1 word2 word3 word4 where-  (list1,tmp1 ) = splitAt 8 list-  (list2,tmp2 ) = splitAt 8 tmp1-  (list3,list4) = splitAt 8 tmp2-  word1 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list1 ] -  word2 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list2 ] -  word3 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list3 ] -  word4 = sum' [ shiftL (i2w x) (56 - 8*i) | (i,x) <- zip [0..] list4 ] -        + i2w n-    -makeWordList :: Int -> [Int] -> Partition-makeWordList !n list = WordList n (go list) where   -  go :: [Int] -> [Word64]-  go !xs = case xs of-    (x:y:z:w:rest) -> makeWord x y z w : go rest-    (x:y:z:  []  ) -> makeWord x y z 0 : []-    (x:y:    []  ) -> makeWord x y 0 0 : []-    (x:      []  ) -> makeWord x 0 0 0 : []-    []             -> []-  makeWord !x !y !z !w = shiftL (i2w x) 48  -                       + shiftL (i2w y) 32  -                       + shiftL (i2w z) 16 -                       +        (i2w w)-{--  go [] = []-  go xs = case splitAt 4 xs of-    (this,rest) -> case rest of-      [] -> makeWord (take 4 $ this ++ repeat 0) : []-      _  -> makeWord this : go rest-  makeWord [x,y,z,w] = shiftL (i2w x) 48  -                     + shiftL (i2w y) 32  -                     + shiftL (i2w z) 16 -                     +        (i2w w)--}+fromDescList' !len !list = Partition (V.fromList' (Shape len bits) $ map i2w list) where+  bits = case list of+    []     -> 4+    (x:xs) -> V.bitsNeededFor (i2w x)  -------------------------------------------------------------------------------- -- * Partial orderings +-- @ |p `isSubPartitionOf` q@ isSubPartitionOf :: Partition -> Partition -> Bool-isSubPartitionOf p q = case (p,q) of--  (Nibble 0 , _       ) -> True-  -  (Nibble u , Nibble v) -> let !n = w2i (u .&. 15) -                           in  and [    (shiftR u (60 - i*4) .&. 15)-                                     <= (shiftR v (60 - i*4) .&. 15) -                                   | i<-[0..n-1] -                                   ]--  _                     -> and $ zipWith (<=) (toList p) (toList q ++ repeat 0)+isSubPartitionOf p q = and $ zipWith (<=) (toList p) (toList q ++ repeat 0) +-- | @q `dominates` p@ dominates :: Partition -> Partition -> Bool-dominates q p = case (q,p) of--  (_        , Nibble 0 ) -> True--  (Nibble v , Nibble u ) -> go 60 0 0 where-                              n = u .&. 15                              -                              klimit = w2i (4*(15-n))-                              go !k !b !a = if k <= klimit -                                then True-                                else let !b' = b + (shiftR v k .&. 15)-                                         !a' = a + (shiftR u k .&. 15)-                                     in  if b' < a' -                                           then False -                                           else go (k-4) b' a'--  _                      -> and $ zipWith (>=) (sums $ toList q ++ repeat 0) (sums $ toList p) where-                              sums = tail . scanl' (+) 0+dominates (Partition vec_q) (Partition vec_p) = and $ zipWith (>=) (sums (qs ++ repeat 0)) (sums ps) where +  sums = tail . scanl' (+) 0+  ps = V.toList vec_p+  qs = V.toList vec_q  -------------------------------------------------------------------------------- -- * Pieri rule +-- | Expands to product @s[lambda]*h[k]@ as a sum of @s[mu]@-s. See <https://en.wikipedia.org/wiki/Pieri's_formula>+pieriRule :: Partition -> Int -> [Partition]+pieriRule = error "Partitions/Integer/Compact: pieriRule not implemented yet"++{- -- | Expands to product @s[lambda]*h[1] = s[lambda]*e[1]@ as a sum of @s[mu]@-s. See <https://en.wikipedia.org/wiki/Pieri's_formula> pieriRuleSingleBox :: Partition -> [Partition] pieriRuleSingleBox !compact = case compact of@@ -780,37 +315,38 @@       go !k [c]    = if c==0 then 0 else shiftL (i2w c) k + 1       go !k (c:cs) = shiftL (i2w c) k + go (k-4) cs       go !k []     = error "Compact/pieriRule/encode: shouldn't happen"+-}  -------------------------------------------------------------------------------- -- * local (internally used) utility functions  {-# INLINE i2w #-}-i2w :: Int -> Word64+i2w :: Int -> Word i2w = fromIntegral  {-# INLINE w2i #-}-w2i :: Word64 -> Int+w2i :: Word -> Int w2i = fromIntegral  {-# INLINE sum' #-}-sum' :: [Word64] -> Word64+sum' :: [Word] -> Word sum' = foldl' (+) 0  {-# INLINE safeTail #-} safeTail :: [Int] -> [Int] safeTail xs = case xs of { [] -> [] ; _ -> tail xs } -{-# INLINE toZero #-}-toZero :: Int -> [Int]-toZero !n-  | n >  0  = n : toZero (n-1) +{-# INLINE descendToZero #-}+descendToZero :: Int -> [Int]+descendToZero !n+  | n >  0  = n : descendToZero (n-1)    | n == 0  = [0]   | n <  0  = [] -{-# INLINE toOne #-}-toOne :: Int -> [Int]-toOne !n-  | n >  1  = n : toOne (n-1) +{-# INLINE descendToOne #-}+descendToOne :: Int -> [Int]+descendToOne !n+  | n >  1  = n : descendToOne (n-1)    | n == 1  = [1]   | n <  1  = [] 
Math/Combinat/Partitions/Integer/Naive.hs view
@@ -41,6 +41,18 @@  --------------------------------------------------------------------------------- +toList :: Partition -> [Int]+toList (Partition xs) = xs++fromList :: [Int] -> Partition +fromList = mkPartition where+  mkPartition xs = Partition $ sortBy (reverseCompare) $ filter (>0) xs++fromListUnsafe :: [Int] -> Partition+fromListUnsafe = Partition++---------------------------------------------------------------------------------+ isEmptyPartition :: Partition -> Bool isEmptyPartition (Partition p) = null p 
Math/Combinat/Permutations.hs view
@@ -13,6 +13,7 @@   ( -- * The Permutation type     Permutation (..)   , fromPermutation+  , lookupPermutation , (!!!)   , permutationArray   , permutationUArray   , uarrayToPermutationUnsafe@@ -20,6 +21,7 @@   , maybePermutation   , toPermutation   , toPermutationUnsafe+  , toPermutationUnsafeN   , permutationSize     -- * Disjoint cycles   , DisjointCycles (..)@@ -54,16 +56,16 @@   , bubbleSort2   , bubbleSort     -- * Permutation groups-  , identity-  , inverse-  , multiply-  , multiplyMany -  , multiplyMany'+  , identityPermutation+  , inversePermutation+  , multiplyPermutation+  , productOfPermutations+  , productOfPermutations'     -- * Action of the permutation group-  , permute +  , permuteArray    , permuteList-  , permuteLeft , permuteRight-  , permuteLeftList , permuteRightList+  , permuteArrayLeft , permuteArrayRight+  , permuteListLeft  , permuteListRight     -- * Sorting   , sortingPermutationAsc    , sortingPermutationDesc@@ -108,6 +110,9 @@ import Data.Array.MArray import Data.Array.Unsafe +import Data.Vector.Compact.WordVec ( WordVec )+import qualified Data.Vector.Compact.WordVec as V+ import Math.Combinat.ASCII import Math.Combinat.Classes import Math.Combinat.Helper@@ -117,10 +122,58 @@ import System.Random  --------------------------------------------------------------------------------+-- WordVec helpers++toUArray :: WordVec -> UArray Int Int+toUArray vec = listArray (1,n) (map fromIntegral $ V.toList vec) where n = V.vecLen vec++fromUArray :: UArray Int Int -> WordVec+fromUArray arr = fromPermListN n (map fromIntegral $ elems arr) where+  (1,n) = bounds arr++-- | maximum = length+fromPermListN :: Int -> [Int] -> WordVec+fromPermListN n perm = V.fromList' shape (map fromIntegral perm) where+  shape = V.Shape n bits+  bits  = V.bitsNeededFor (fromIntegral n :: Word)++fromPermList :: [Int] -> WordVec+fromPermList perm = V.fromList (map fromIntegral perm)++(.!) :: WordVec -> Int -> Int+(.!) vec idx = fromIntegral (V.unsafeIndex (idx-1) vec)++_elems :: WordVec -> [Int]+_elems = map fromIntegral . V.toList++_assocs :: WordVec -> [(Int,Int)]+_assocs vec = zip [1..] (_elems vec)++_bound :: WordVec -> Int+_bound = V.vecLen++{- +-- the old internal representation (UArray Int Int)++_elems :: UArray Int Int -> [Int]+_elems = elems++_assocs :: UArray Int Int -> [(Int,Int)]+_assocs = elems++_bound :: UArray Int Int -> Int+_bound = snd . bounds+-}+++toPermN :: Int -> [Int] -> Permutation+toPermN n xs = Permutation (fromPermListN n xs)++-------------------------------------------------------------------------------- -- * Types --- | A permutation. Internally it is an (unboxed) array of the integers @[1..n]@, with --- indexing range also being @(1,n)@. +-- | A permutation. Internally it is an (compact) vector +-- of the integers @[1..n]@. -- -- If this array of integers is @[p1,p2,...,pn]@, then in two-line  -- notations, that represents the permutation@@ -136,12 +189,12 @@ -- -- (NOTE: this changed at version 0.2.8.0!) ---newtype Permutation = Permutation (UArray Int Int) deriving (Eq,Ord) -- ,Show,Read)+newtype Permutation = Permutation WordVec deriving (Eq,Ord) -- ,Show,Read)  instance Show Permutation where   showsPrec d (Permutation arr)      = showParen (d > 10)  -    $ showString "toPermutation " . showsPrec 11 (elems arr)       -- app_prec = 10+    $ showString "toPermutation " . showsPrec 11 (_elems arr)       -- app_prec = 10  instance Read Permutation where   readsPrec d r = readParen (d > 10) fun r where@@ -164,25 +217,26 @@ newtype DisjointCycles = DisjointCycles [[Int]] deriving (Eq,Ord,Show,Read)  fromPermutation :: Permutation -> [Int]-fromPermutation (Permutation ar) = elems ar+fromPermutation (Permutation ar) = _elems ar  permutationUArray :: Permutation -> UArray Int Int-permutationUArray (Permutation ar) = ar+permutationUArray (Permutation ar) = toUArray ar --- | Note: this is slower than 'permutationUArray' permutationArray :: Permutation -> Array Int Int-permutationArray (Permutation ar) = listArray (1,n) (elems ar) where-  (1,n) = bounds ar+permutationArray (Permutation ar) = listArray (1,n) (_elems ar) where+  n = _bound ar  -- | Assumes that the input is a permutation of the numbers @[1..n]@. toPermutationUnsafe :: [Int] -> Permutation-toPermutationUnsafe xs = Permutation perm where-  n    = length xs-  perm = listArray (1,n) xs+toPermutationUnsafe xs = Permutation (fromPermList xs)  +-- | This is faster than 'toPermutationUnsafe', but you need to supply @n@.+toPermutationUnsafeN :: Int -> [Int] -> Permutation+toPermutationUnsafeN n xs = Permutation (fromPermListN n xs) + -- | Note: Indexing starts from 1. uarrayToPermutationUnsafe :: UArray Int Int -> Permutation-uarrayToPermutationUnsafe = Permutation+uarrayToPermutationUnsafe = Permutation . fromUArray  -- | Checks whether the input is a permutation of the numbers @[1..n]@. isPermutation :: [Int] -> Bool@@ -200,7 +254,7 @@   action :: forall s. ST s (Maybe Permutation)   action = do     ar <- newArray (1,n) 0 :: ST s (STUArray s Int Int)-    let go []     = return $ Just (Permutation $ listArray (1,n) input)+    let go []     = return $ Just (toPermutationUnsafe input)         go (j:js) = if j<1 || j>n            then return Nothing           else do@@ -218,15 +272,27 @@  -- | Returns @n@, where the input is a permutation of the numbers @[1..n]@ permutationSize :: Permutation -> Int-permutationSize (Permutation ar) = snd $ bounds ar+permutationSize (Permutation ar) = _bound ar +-- | Returns the image @sigma(k)@ of @k@ under the permutation @sigma@.+-- +-- Note: we don't check the bounds! It may even crash if you index out of bounds!+lookupPermutation :: Permutation -> Int -> Int+lookupPermutation (Permutation ar) idx = ar .! idx++-- infix 8 !!!++-- | Infix version of 'lookupPermutation'+(!!!) :: Permutation -> Int -> Int+(!!!) (Permutation ar) idx = ar .! idx+ instance HasWidth Permutation where   width = permutationSize  -- | Checks whether the permutation is the identity permutation isIdentityPermutation :: Permutation -> Bool-isIdentityPermutation (Permutation ar) = (elems ar == [1..n]) where-  (1,n) = bounds ar+isIdentityPermutation (Permutation ar) = (_elems ar == [1..n]) where+  n = _bound ar  -- | Given a permutation of @n@ and a permutation of @m@, we return -- a permutation of @n+m@ resulting by putting them next to each other.@@ -255,18 +321,18 @@ -- | The standard two-line notation, moving the element indexed by the top row into -- the place indexed by the corresponding element in the bottom row. twoLineNotation :: Permutation -> ASCII-twoLineNotation (Permutation arr) = genericTwoLineNotation $ zip [1..] (elems arr)+twoLineNotation (Permutation arr) = genericTwoLineNotation $ zip [1..] (_elems arr)  -- | The inverse two-line notation, where the it\'s the bottom line  -- which is in standard order. The columns of this are a permutation -- of the columns 'twoLineNotation'. -- -- Remark: the top row of @inverseTwoLineNotation perm@ is the same --- as the bottom row of @twoLineNotation (inverse perm)@.+-- as the bottom row of @twoLineNotation (inversePermutation perm)@. -- inverseTwoLineNotation :: Permutation -> ASCII inverseTwoLineNotation (Permutation arr) =-  genericTwoLineNotation $ sortBy (comparing snd) $ zip [1..] (elems arr) +  genericTwoLineNotation $ sortBy (comparing snd) $ zip [1..] (_elems arr)   -- | Two-line notation for any set of numbers genericTwoLineNotation :: [(Int,Int)] -> ASCII@@ -301,7 +367,7 @@   numberOfCycles = numberOfCycles . permutationToDisjointCycles    disjointCyclesToPermutation :: Int -> DisjointCycles -> Permutation-disjointCyclesToPermutation n (DisjointCycles cycles) = Permutation perm where+disjointCyclesToPermutation n (DisjointCycles cycles) = Permutation $ fromUArray perm where    pairs :: [Int] -> [(Int,Int)]   pairs xs@(x:_) = worker (xs++[x]) where@@ -329,7 +395,7 @@ permutationToDisjointCycles :: Permutation -> DisjointCycles permutationToDisjointCycles (Permutation perm) = res where -  (1,n) = bounds perm+  n = _bound perm    -- we don't want trivial cycles   f :: [Int] -> Bool@@ -357,7 +423,7 @@   worker :: STUArray s Int Bool -> Int -> Int -> [Int] -> ST s [Int]   worker tag k l cyc = do     writeArray tag l True-    let m = perm ! l+    let m = perm .! l     if m == k        then return cyc       else worker tag k m (m:cyc)      @@ -365,7 +431,7 @@ isEvenPermutation :: Permutation -> Bool isEvenPermutation (Permutation perm) = res where -  (1,n) = bounds perm+  n = _bound perm   res = runST $ do     tag <- newArray (1,n) False      cycles <- unfoldM (step tag) 1 @@ -387,7 +453,7 @@   worker :: STUArray s Int Bool -> Int -> Int -> Int -> ST s Int   worker tag k l cyclen = do     writeArray tag l True-    let m = perm ! l+    let m = perm .! l     if m == k        then return cyclen       else worker tag k m (1+cyclen)      @@ -426,8 +492,8 @@ -- inversions :: Permutation -> [(Int,Int)] inversions (Permutation arr) = list where-  (_,n) = bounds arr-  list = [ (i,j) | i<-[1..n-1], j<-[i+1..n], arr!i > arr!j ]+  n =  _bound arr+  list = [ (i,j) | i<-[1..n-1], j<-[i+1..n], arr.!i > arr.!j ]  -- | Returns the number of inversions: --@@ -442,8 +508,8 @@ -- This should be @O(n*log(n))@ -- numberOfInversionsMerge :: Permutation -> Int-numberOfInversionsMerge (Permutation arr) = fst (sortCnt n $ elems arr) where-  (_,n) = bounds arr+numberOfInversionsMerge (Permutation arr) = fst (sortCnt n $ _elems arr) where+  n = _bound arr                                            -- | First argument is length of the list.   -- Returns also the inversion count.@@ -471,8 +537,8 @@ -- numberOfInversionsNaive :: Permutation -> Int numberOfInversionsNaive (Permutation arr) = length list where-  (_,n) = bounds arr-  list = [ (0::Int) | i<-[1..n-1], j<-[i+1..n], arr!i > arr!j ]+  n    = _bound arr+  list = [ (0::Int) | i<-[1..n-1], j<-[i+1..n], arr.!i > arr.!j ]  -- | Bubble sorts breaks a permutation into the product of adjacent transpositions: --@@ -491,7 +557,7 @@ -- bubbleSort :: Permutation -> [Int] bubbleSort perm@(Permutation tgt) = runST action where-  (_,n)           = bounds tgt+  n = _bound tgt    action :: forall s. ST s [Int]   action = do@@ -502,7 +568,7 @@      list <- forM [1..n] $ \x -> do -      let k = tgt ! x        -- we take the number which will be at the @x@-th position at the end+      let k = tgt .! x       -- we take the number which will be at the @x@-th position at the end       i <- readArray inv k   -- number @k@ is at the moment at position @i@       let j = x              -- but the final place is at @x@       @@ -534,11 +600,11 @@  -- | The permutation @[n,n-1,n-2,...,2,1]@. Note that it is the inverse of itself. reversePermutation :: Int -> Permutation-reversePermutation n = Permutation $ listArray (1,n) [n,n-1..1]+reversePermutation n = Permutation $ fromPermListN n [n,n-1..1]  -- | Checks whether the permutation is the reverse permutation @[n,n-1,n-2,...,2,1]. isReversePermutation :: Permutation -> Bool-isReversePermutation (Permutation arr) = elems arr == [n,n-1..1] where (1,n) = bounds arr+isReversePermutation (Permutation arr) = _elems arr == [n,n-1..1] where n = _bound arr  -- | A transposition (swapping two elements).  --@@ -547,7 +613,7 @@ transposition :: Int -> (Int,Int) -> Permutation transposition n (i,j) =    if i>=1 && j>=1 && i<=n && j<=n -    then Permutation $ listArray (1,n) [ f k | k<-[1..n] ]+    then Permutation $ fromPermListN n [ f k | k<-[1..n] ]     else error "transposition: index out of range"   where     f k | k == i    = j@@ -559,7 +625,7 @@ -- > transpositions n list == multiplyMany [ transposition n pair | pair <- list ] -- transpositions :: Int -> [(Int,Int)] -> Permutation-transpositions n list = Permutation (runSTUArray action) where+transpositions n list = Permutation (fromUArray $ runSTUArray action) where    action :: ST s (STUArray s Int Int)   action = do@@ -584,7 +650,7 @@ -- > adjacentTranspositions n list == multiplyMany [ adjacentTransposition n idx | idx <- list ] -- adjacentTranspositions :: Int -> [Int] -> Permutation-adjacentTranspositions n list = Permutation (runSTUArray action) where+adjacentTranspositions n list = Permutation (fromUArray $ runSTUArray action) where    action :: ST s (STUArray s Int Int)   action = do@@ -610,7 +676,7 @@ -- > ( 2 3 4 5 1 ) --  cycleLeft :: Int -> Permutation-cycleLeft n = Permutation $ listArray (1,n) $ [2..n] ++ [1]+cycleLeft n = Permutation $ fromPermListN n ([2..n] ++ [1])  -- | The permutation which cycles a list right by one step: -- @@ -622,52 +688,52 @@ -- > ( 5 1 2 3 4 ) --  cycleRight :: Int -> Permutation-cycleRight n = Permutation $ listArray (1,n) $ n : [1..n-1]+cycleRight n = Permutation $ fromPermListN n (n : [1..n-1])     -------------------------------------------------------------------------------- -- * Permutation groups --- | Multiplies two permutations together: @p `multiply` q@+-- | Multiplies two permutations together: @p `multiplyPermutation` q@ -- means the permutation when we first apply @p@, and then @q@ -- (that is, the natural action is the /right/ action) ----- See also 'permute' for our conventions.  +-- See also 'permuteArray' for our conventions.   ---multiply :: Permutation -> Permutation -> Permutation-multiply pi1@(Permutation perm1) pi2@(Permutation perm2) = +multiplyPermutation :: Permutation -> Permutation -> Permutation+multiplyPermutation pi1@(Permutation perm1) pi2@(Permutation perm2) =    if (n==m) -    then Permutation result-    else error "multiply: permutations of different sets"  +    then Permutation $ fromUArray result+    else error "multiplyPermutation: permutations of different sets"     where-    (_,n) = bounds perm1-    (_,m) = bounds perm2    -    result = permute pi2 perm1+    n = _bound perm1+    m = _bound perm2    +    result = permuteArray pi2 (toUArray perm1)   -infixr 7 `multiply`  +infixr 7 `multiplyPermutation`    -- | The inverse permutation.-inverse :: Permutation -> Permutation    -inverse (Permutation perm1) = Permutation result+inversePermutation :: Permutation -> Permutation    +inversePermutation (Permutation perm1) = Permutation $ fromUArray result   where-    result = array (1,n) $ map swap $ assocs perm1-    (_,n) = bounds perm1+    result = array (1,n) $ map swap $ _assocs perm1+    n = _bound perm1      -- | The identity (or trivial) permutation.-identity :: Int -> Permutation -identity n = Permutation $ listArray (1,n) [1..n]+identityPermutation :: Int -> Permutation +identityPermutation n = Permutation $ fromPermListN n [1..n]  -- | Multiply together a /non-empty/ list of permutations (the reason for requiring the list to -- be non-empty is that we don\'t know the size of the result). See also 'multiplyMany''.-multiplyMany :: [Permutation] -> Permutation -multiplyMany [] = error "multiplyMany: empty list, we don't know size of the result"-multiplyMany ps = foldl1' multiply ps    +productOfPermutations :: [Permutation] -> Permutation +productOfPermutations [] = error "productOfPermutations: empty list, we don't know size of the result"+productOfPermutations ps = foldl1' multiplyPermutation ps      -- | Multiply together a (possibly empty) list of permutations, all of which has size @n@-multiplyMany' :: Int -> [Permutation] -> Permutation -multiplyMany' n []       = identity n-multiplyMany' n ps@(p:_) = if n == permutationSize p -  then foldl1' multiply ps    -  else error "multiplyMany': incompatible permutation size(s)"+productOfPermutations' :: Int -> [Permutation] -> Permutation +productOfPermutations' n []       = identityPermutation n+productOfPermutations' n ps@(p:_) = if n == permutationSize p +  then foldl1' multiplyPermutation ps    +  else error "productOfPermutations': incompatible permutation size(s)"  -------------------------------------------------------------------------------- -- * Action of the permutation group@@ -682,75 +748,75 @@ -- We adopt the convention that permutations act /on the right/  -- (as in Knuth): ----- > permute pi2 (permute pi1 set) == permute (pi1 `multiply` pi2) set+-- > permuteArray pi2 (permuteArray pi1 set) == permuteArray (pi1 `multiplyPermutation` pi2) set ----- Synonym to 'permuteRight'+-- Synonym to 'permuteArrayRight' ---{-# SPECIALIZE permute :: Permutation -> Array  Int b   -> Array  Int b   #-}-{-# SPECIALIZE permute :: Permutation -> UArray Int Int -> UArray Int Int #-}-permute :: IArray arr b => Permutation -> arr Int b -> arr Int b    -permute = permuteRight+{-# SPECIALIZE permuteArray :: Permutation -> Array  Int b   -> Array  Int b   #-}+{-# SPECIALIZE permuteArray :: Permutation -> UArray Int Int -> UArray Int Int #-}+permuteArray :: IArray arr b => Permutation -> arr Int b -> arr Int b    +permuteArray = permuteArrayRight  -- | Right action on lists. Synonym to 'permuteListRight' -- permuteList :: Permutation -> [a] -> [a]-permuteList = permuteRightList+permuteList = permuteListRight      -- | The right (standard) action of permutations on sets.  -- --- > permuteRight pi2 (permuteRight pi1 set) == permuteRight (pi1 `multiply` pi2) set+-- > permuteArrayRight pi2 (permuteArrayRight pi1 set) == permuteArrayRight (pi1 `multiplyPermutation` pi2) set --    -- The second argument should be an array with bounds @(1,n)@. -- The function checks the array bounds. ---{-# SPECIALIZE permuteRight :: Permutation -> Array  Int b   -> Array  Int b   #-}-{-# SPECIALIZE permuteRight :: Permutation -> UArray Int Int -> UArray Int Int #-}-permuteRight :: IArray arr b => Permutation -> arr Int b -> arr Int b    -permuteRight pi@(Permutation perm) ar = +{-# SPECIALIZE permuteArrayRight :: Permutation -> Array  Int b   -> Array  Int b   #-}+{-# SPECIALIZE permuteArrayRight :: Permutation -> UArray Int Int -> UArray Int Int #-}+permuteArrayRight :: IArray arr b => Permutation -> arr Int b -> arr Int b    +permuteArrayRight pi@(Permutation perm) ar =    if (a==1) && (b==n) -    then listArray (1,n) [ ar!(perm!i) | i <- [1..n] ] -    else error "permuteRight: array bounds do not match"+    then listArray (1,n) [ ar!(perm.!i) | i <- [1..n] ] +    else error "permuteArrayRight: array bounds do not match"   where-    (_,n) = bounds perm  +    n     = _bound perm     (a,b) = bounds ar     -- | The right (standard) action on a list. The list should be of length @n@. ----- > fromPermutation perm == permuteRightList perm [1..n]+-- > fromPermutation perm == permuteListRight perm [1..n] -- -permuteRightList :: forall a . Permutation -> [a] -> [a]    -permuteRightList perm xs = elems $ permuteRight perm $ arr where+permuteListRight :: forall a . Permutation -> [a] -> [a]    +permuteListRight perm xs = elems $ permuteArrayRight perm $ arr where   arr = listArray (1,n) xs :: Array Int a   n   = permutationSize perm  -- | The left (opposite) action of the permutation group. ----- > permuteLeft pi2 (permuteLeft pi1 set) == permuteLeft (pi2 `multiply` pi1) set+-- > permuteArrayLeft pi2 (permuteArrayLeft pi1 set) == permuteArrayLeft (pi2 `multiplyPermutation` pi1) set ----- It is related to 'permuteLeft' via:+-- It is related to 'permuteLeftArray' via: ----- > permuteLeft  pi arr == permuteRight (inverse pi) arr--- > permuteRight pi arr == permuteLeft  (inverse pi) arr+-- > permuteArrayLeft  pi arr == permuteArrayRight (inversePermutation pi) arr+-- > permuteArrayRight pi arr == permuteArrayLeft  (inversePermutation pi) arr ---{-# SPECIALIZE permuteLeft :: Permutation -> Array  Int b   -> Array  Int b   #-}-{-# SPECIALIZE permuteLeft :: Permutation -> UArray Int Int -> UArray Int Int #-}-permuteLeft :: IArray arr b => Permutation -> arr Int b -> arr Int b    -permuteLeft pi@(Permutation perm) ar =    +{-# SPECIALIZE permuteArrayLeft :: Permutation -> Array  Int b   -> Array  Int b   #-}+{-# SPECIALIZE permuteArrayLeft :: Permutation -> UArray Int Int -> UArray Int Int #-}+permuteArrayLeft :: IArray arr b => Permutation -> arr Int b -> arr Int b    +permuteArrayLeft pi@(Permutation perm) ar =       -- permuteRight (inverse pi) ar   if (a==1) && (b==n) -    then array (1,n) [ ( perm!i , ar!i ) | i <- [1..n] ] -    else error "permuteLeft: array bounds do not match"+    then array (1,n) [ ( perm.!i , ar!i ) | i <- [1..n] ] +    else error "permuteArrayLeft: array bounds do not match"   where-    (_,n) = bounds perm  +    n     = _bound perm     (a,b) = bounds ar     -- | The left (opposite) action on a list. The list should be of length @n@. ----- > permuteLeftList perm set == permuteList (inverse perm) set--- > fromPermutation (inverse perm) == permuteLeftList perm [1..n]+-- > permuteListLeft perm set == permuteList (inversePermutation perm) set+-- > fromPermutation (inversePermutation perm) == permuteListLeft perm [1..n] ---permuteLeftList :: forall a. Permutation -> [a] -> [a]    -permuteLeftList perm xs = elems $ permuteLeft perm $ arr where+permuteListLeft :: forall a. Permutation -> [a] -> [a]    +permuteListLeft perm xs = elems $ permuteArrayLeft perm $ arr where   arr = listArray (1,n) xs :: Array Int a   n   = permutationSize perm @@ -843,7 +909,7 @@     forM_ [1..n] $ \i -> writeArray ar i i     rnd' <- worker n (if isSattolo then n-1 else n) rnd ar      perm <- Data.Array.Unsafe.unsafeFreeze ar-    return (Permutation perm, rnd')+    return (Permutation (fromUArray perm), rnd')   worker :: RandomGen g => Int -> Int -> g -> STUArray s Int Int -> ST s g    worker n m rnd ar =      if n==1 
+ Math/Combinat/RootSystems.hs view
@@ -0,0 +1,319 @@+
+-- | Naive (very inefficient) algorithm to generate the irreducible (Dynkin) root systems
+--
+-- Based on <https://en.wikipedia.org/wiki/Root_system>
+
+{-# LANGUAGE BangPatterns, FlexibleInstances, TypeSynonymInstances, FlexibleContexts #-}
+module Math.Combinat.RootSystems where
+
+--------------------------------------------------------------------------------
+
+import Control.Monad
+
+import Data.Array
+
+import Data.Set (Set)
+import qualified Data.Set as Set
+
+import Data.List
+import Data.Ord
+
+import Math.Combinat.Numbers.Primes
+import Math.Combinat.Sets
+
+--------------------------------------------------------------------------------
+-- * Half-integers
+
+-- | The type of half-integers (internally represented by their double)
+--
+-- TODO: refactor this into its own module
+newtype HalfInt 
+  = HalfInt Int  
+  deriving (Eq,Ord)
+
+half :: HalfInt
+half = HalfInt 1
+
+divByTwo :: Int -> HalfInt
+divByTwo n = HalfInt n
+
+mulByTwo :: HalfInt -> Int
+mulByTwo (HalfInt n) = n
+
+scaleBy :: Int -> HalfInt -> HalfInt
+scaleBy k (HalfInt n) = HalfInt (k*n)
+
+instance Show HalfInt where
+  show (HalfInt n) = case divMod n 2 of
+    (k,0) -> show k
+    (_,1) -> show n ++ "/2"
+
+instance Num HalfInt where
+  fromInteger = HalfInt . (*2) . fromInteger
+  a + b = divByTwo $ mulByTwo a + mulByTwo b
+  a - b = divByTwo $ mulByTwo a - mulByTwo b
+  a * b = case divMod (mulByTwo a * mulByTwo b) 4 of
+            (k,0) -> HalfInt (2*k)
+            (k,2) -> HalfInt (2*k+1)
+            _     -> error "the result of multiplication is not a half-integer"
+  negate = divByTwo . negate . mulByTwo
+  signum = divByTwo . signum . mulByTwo
+  abs    = divByTwo . abs    . mulByTwo
+
+--------------------------------------------------------------------------------
+-- * Vectors of half-integers
+
+type HalfVec = [HalfInt]
+
+instance Num HalfVec where
+  fromInteger = error "HalfVec/fromInteger"
+  (+) = safeZip (+)
+  (-) = safeZip (-)
+  (*) = safeZip (*)
+  negate = map negate
+  abs    = map abs
+  signum = map signum
+
+scaleVec :: Int -> HalfVec -> HalfVec  
+scaleVec k = map (scaleBy k)
+
+negateVec :: HalfVec -> HalfVec
+negateVec = map negate
+
+-- dotProd :: HalfVec -> HalfVec
+-- dotProd xs ys = foldl' (+) 0 $ safeZip (*) xs ys
+
+safeZip :: (a -> b -> c) -> [a] -> [b] -> [c]
+safeZip f = go where
+  go (x:xs) (y:ys) = f x y : go xs ys
+  go []     []     = []
+  go _      _      = error "safeZip: the lists do not have equal length"
+
+--------------------------------------------------------------------------------
+-- * Dynkin diagrams
+
+data Dynkin
+  = A !Int
+  | B !Int
+  | C !Int
+  | D !Int
+  | E6 | E7 | E8
+  | F4
+  | G2
+  deriving (Eq,Show)
+
+--------------------------------------------------------------------------------
+-- * The roots of root systems
+
+-- | The ambient dimension of (our representation of the) system (length of the vector)
+ambientDim :: Dynkin -> Int
+ambientDim d = case d of
+  A n -> n+1   -- it's an n dimensional subspace of (n+1) dimensions
+  B n -> n
+  C n -> n
+  D n -> n
+  E6  -> 6
+  E7  -> 8     -- sublattice of E8 ?
+  E8  -> 8
+  F4  -> 4
+  G2  -> 3     -- it's a 2 dimensional subspace of 3 dimensions
+
+simpleRootsOf :: Dynkin -> [HalfVec]
+simpleRootsOf d = 
+
+  case d of
+
+    A n -> [ e i - e (i+1) | i <- [1..n]   ]
+
+    B n -> [ e i - e (i+1) | i <- [1..n-1] ] ++ [e n]
+
+    C n -> [ e i - e (i+1) | i <- [1..n-1] ] ++ [scaleVec 2 (e n)]
+
+    D n -> [ e i - e (i+1) | i <- [1..n-1] ] ++ [e (n-1) + e n]
+
+    E6  -> simpleRootsE6_123
+    E7  -> simpleRootsE7_12
+    E8  -> simpleRootsE8_even 
+
+    F4  -> [ [ 1,-1, 0, 0]
+           , [ 0, 1,-1, 0]
+           , [ 0, 0, 1, 0]
+           , [-h,-h,-h,-h]
+           ]
+
+    G2  -> [ [ 1,-1, 0]
+           , [-1, 2,-1]
+           ]
+
+  where
+    h = half
+    n = ambientDim d
+
+    e :: Int -> HalfVec
+    e i = replicate (i-1) 0 ++ [1] ++ replicate (n-i) 0
+
+positiveRootsOf :: Dynkin -> Set HalfVec
+positiveRootsOf = positiveRoots . simpleRootsOf
+
+negativeRootsOf :: Dynkin -> Set HalfVec
+negativeRootsOf = Set.map negate . positiveRootsOf
+
+allRootsOf :: Dynkin -> Set HalfVec
+allRootsOf dynkin = Set.unions [  pos , neg ] where
+  simple = simpleRootsOf dynkin
+  pos   = positiveRoots simple
+  neg   = Set.map negate pos
+
+--------------------------------------------------------------------------------
+-- * Positive roots
+
+-- | Finds a vector, which is hopefully not orthognal to any root
+-- (generated by the given simple roots), and has positive dot product with each of them.
+findPositiveHyperplane :: [HalfVec] -> [Double]
+findPositiveHyperplane vs = w where
+  n  = length (head vs)
+  w0 = map (fromIntegral . mulByTwo) (foldl1 (+) vs) :: [Double]
+  w  = zipWith (+) w0 perturb
+  perturb = map small $ map fromIntegral $ take n primes
+  small :: Double -> Double
+  small x = x / (10**10) 
+
+positiveRoots :: [HalfVec] -> Set HalfVec
+positiveRoots simples = Set.fromList pos where
+  roots = mirrorClosure simples
+  w     = findPositiveHyperplane simples
+  pos   = [ r | r <- Set.toList roots , dot4 r > 0 ] where
+
+  dot4 :: HalfVec -> Double
+  dot4 a = foldl' (+) 0 $ safeZip (*) w $ map (fromIntegral . mulByTwo) a
+
+basisOfPositives :: Set HalfVec -> [HalfVec]
+basisOfPositives set = Set.toList (Set.difference set set2) where
+  set2 = Set.fromList [ a + b | [a,b] <- choose 2 (Set.toList set) ]
+
+
+--------------------------------------------------------------------------------
+-- * Operations on half-integer vectors
+
+-- | bracket b a = (a,b)/(a,a) 
+bracket :: HalfVec -> HalfVec -> HalfInt
+bracket b a = 
+  case divMod (2*a_dot_b) (a_dot_a) of
+    (n,0) -> divByTwo n
+    _     -> error "bracket: result is not a half-integer"
+  where
+    a_dot_b = foldl' (+) 0 $ safeZip (*) (map mulByTwo a) (map mulByTwo b)
+    a_dot_a = foldl' (+) 0 $ safeZip (*) (map mulByTwo a) (map mulByTwo a)
+
+-- | mirror b a = b - 2*(a,b)/(a,a) * a
+mirror :: HalfVec -> HalfVec -> HalfVec
+mirror b a = b - scaleVec (mulByTwo $ bracket b a) a
+
+-- | Cartan matrix of a list of (simple) roots
+cartanMatrix :: [HalfVec] -> Array (Int,Int) Int
+cartanMatrix list = array ((1,1),(n,n)) [ ((i,j), f i j) | i<-[1..n] , j<-[1..n] ] where
+  n   = length list
+  arr = listArray (1,n) list
+  f !i !j = mulByTwo $ bracket (arr!j) (arr!i)
+
+printMatrix :: Show a => Array (Int,Int) a -> IO ()
+printMatrix arr = do
+  let ((1,1),(n,m)) = bounds arr
+      arr' = fmap show arr
+  let ks   = [ 1 + maximum [ length (arr'!(i,j)) | i<-[1..n] ] | j<-[1..m] ]
+  forM_ [1..n] $ \i -> do
+    putStrLn $ flip concatMap [1..m] $ \j -> extendTo (ks!!(j-1)) $ arr' ! (i,j)
+  where
+    extendTo n s = replicate (n-length s) ' ' ++ s
+
+--------------------------------------------------------------------------------
+-- * Mirroring 
+
+-- | We mirror stuff until there is no more things happening
+-- (very naive algorithm, but seems to work)
+mirrorClosure :: [HalfVec] -> Set HalfVec
+mirrorClosure = go . Set.fromList where 
+  
+  go set 
+    | n'  > n   = go set'
+    | n'' > n   = go set''
+    | otherwise = set
+    where
+      n   = Set.size set
+      n'  = Set.size set'
+      n'' = Set.size set''
+      set'  = mirrorStep set
+      set'' = Set.union set (Set.map negateVec set) 
+
+mirrorStep :: Set HalfVec -> Set HalfVec
+mirrorStep old = Set.union old new where
+  new = Set.fromList [ mirror b a | [a,b] <- choose 2 $ Set.toList old ] 
+
+--------------------------------------------------------------------------------
+-- * E6, E7 and E8
+
+-- | This is a basis of E6 as the subset of the even E8 root system
+-- where the first three coordinates agree (they are consolidated 
+-- into the first coordinate here)
+simpleRootsE6_123:: [HalfVec]
+simpleRootsE6_123 = roots where
+  h = half
+  roots =
+    [ [-h,-h,-h,-h,-h,-h,-h,-h]
+    , [ h, h, h, h, h, h,-h,-h]
+    , [ 0, 0, 0, 0,-1, 0, 1, 0]
+    , [ 0, 0, 0, 0, 0, 0,-1, 1]
+    , [-h,-h,-h, h, h, h, h,-h]
+    , [ 0, 0, 0,-1, 1, 0, 0, 0]
+    ]
+
+-- | This is a basis of E8 as the subset of the even E8 root system
+-- where the first two coordinates agree (they are consolidated 
+-- into the first coordinate here)
+simpleRootsE7_12:: [HalfVec]
+simpleRootsE7_12 = roots where
+  h = half
+  roots =
+    [ [-h,-h,-h,-h,-h,-h,-h,-h]
+    , [ h, h, h, h, h, h,-h,-h]
+    , [ h, h,-h,-h,-h,-h, h, h]
+    , [-h,-h, h, h,-h, h, h,-h]
+    , [ 0, 0, 0,-1, 1, 0, 0, 0]
+    , [ 0, 0,-1, 1, 0, 0, 0, 0]
+    , [ 0, 0, 0, 0, 0, 0,-1, 1]
+    ]
+
+-- | This is a basis of E7 as the subset of the even E8 root system
+-- for which the sum of coordinates sum to zero
+simpleRootsE7_diag :: [HalfVec]
+simpleRootsE7_diag = roots where
+  roots = [ e i - e (i+1) | i <-[2..7] ] ++ [[h,h,h,h,-h,-h,-h,-h]]
+  h = half
+  n = 8
+
+  e :: Int -> HalfVec
+  e i = replicate (i-1) 0 ++ [1] ++ replicate (n-i) 0 
+
+simpleRootsE8_even :: [HalfVec]
+simpleRootsE8_even = roots where
+  roots = [v1,v2,v3,v4,v5,v7,v8,v6]
+
+  [v1,v2,v3,v4,v5,v6,v7,v8] = roots0
+  roots0 = [ e i - e (i+1) | i <-[1..6] ] ++ [ e 6 + e 7 , replicate 8 (-h)  ]
+    
+  h = half
+  n = 8
+
+  e :: Int -> HalfVec
+  e i = replicate (i-1) 0 ++ [1] ++ replicate (n-i) 0
+
+simpleRootsE8_odd :: [HalfVec]
+simpleRootsE8_odd = roots where
+  roots = [ e i - e (i+1) | i <-[1..7] ] ++ [[-h,-h,-h,-h,-h , h,h,h]]
+  h = half
+  n = 8
+
+  e :: Int -> HalfVec
+  e i = replicate (i-1) 0 ++ [1] ++ replicate (n-i) 0 
+
+--------------------------------------------------------------------------------
Math/Combinat/Tableaux/LittlewoodRichardson.hs view
@@ -212,8 +212,8 @@ lrScalar lambdaMu alphaBeta = _lrScalar (fromSkewPartition lambdaMu) (fromSkewPartition alphaBeta)  _lrScalar :: (Partition,Partition) -> (Partition,Partition) -> Int-_lrScalar (plam  @(Partition lam  ) , pmu  @(Partition mu0)  ) -         (palpha@(Partition alpha) , pbeta@(Partition beta)) = +_lrScalar ( plam@(  Partition lam  ) , pmu@(  Partition mu0 ) ) +          ( palpha@(Partition alpha) , pbeta@(Partition beta) ) =    if    not (pmu   `isSubPartitionOf` plam  )       || not (pbeta `isSubPartitionOf` palpha)       || (sum' lam + sum' beta) /= (sum' alpha + sum' mu0)     -- equivalent to (lambda-mu) /= (alpha-beta)
− cbits/c_compact_partition.c
@@ -1,24 +0,0 @@--#include <stdint.h>--// -------------------------------------------------------------------------------uint64_t c_dual_nibble(uint64_t word)-{-  uint64_t n    = (word & 15);    // length-  uint64_t h    = (word >> 60);   // height-  uint64_t dual = h;              // length of dual = height of original-  uint64_t w    = word - n;       // zero out the low nibble--  uint64_t o = 60;-  for(uint64_t i=0; i<n; i++)-  { uint64_t k = ( (w >> (64-4*(n-i))) -                 - (w >> (60-4*(n-i))) ) & 15 ;   // diff-    for(uint64_t j=0;j<k;j++) { dual |= (n-i) << o ; o -= 4 ; } -  }--  return dual;-}--// ------------------------------------------------------------------------------
combinat.cabal view
@@ -1,5 +1,5 @@ Name:                combinat-Version:             0.2.9.0+Version:             0.2.10.0 Synopsis:            Generate and manipulate various combinatorial objects. Description:         A collection of functions to generate, count, manipulate                      and visualize all kinds of combinatorial objects like @@ -8,12 +8,12 @@ License:             BSD3 License-file:        LICENSE Author:              Balazs Komuves-Copyright:           (c) 2008-2018 Balazs Komuves+Copyright:           (c) 2008-2021 Balazs Komuves Maintainer:          bkomuves (plus) hackage (at) gmail (dot) com Homepage:            http://moire.be/haskell/ Stability:           Experimental Category:            Math-Tested-With:         GHC == 8.0.2+Tested-With:         GHC == 8.6.5 Cabal-Version:       1.24 Build-Type:          Simple @@ -24,13 +24,15 @@  source-repository head   type:                darcs -  location:            http://moire.be/haskell/projects/combinat/+  location:            https://hub.darcs.net/bkomuves/combinat  --------------------------------------------------------------------------------  Library -  Build-Depends:       base >= 4 && < 5, array >= 0.5, containers, random, transformers+  Build-Depends:       base >= 4 && < 5, +                       array >= 0.5, containers, random, transformers,+                       compact-word-vectors >= 0.2.0.2    Exposed-Modules:     Math.Combinat                        Math.Combinat.Classes@@ -72,6 +74,7 @@                        Math.Combinat.Trees.Nary                        Math.Combinat.Trees.Graphviz                        Math.Combinat.LatticePaths+                       Math.Combinat.RootSystems                        Math.Combinat.ASCII                        Math.Combinat.Helper                        Math.Combinat.TypeLevel@@ -85,8 +88,6 @@    Hs-Source-Dirs:      . -  C-Sources:           cbits/c_compact_partition.c-   ghc-options:         -fwarn-tabs -fno-warn-unused-matches -fno-warn-name-shadowing -fno-warn-unused-imports      @@ -106,12 +107,14 @@                        Tests.SkewTableaux                        Tests.Thompson                        Tests.Partitions.Integer-                       Tests.Partitions.Compact+                       Tests.Partitions.Compact                          Tests.Partitions.Skew                        Tests.Partitions.Ribbon-+                       Tests.Numbers.Primes   +                       Tests.Numbers.Sequences+                          build-depends:       base >= 4 && < 5, array >= 0.5, containers >= 0.5, random, transformers,-                       combinat,+                       combinat, compact-word-vectors >= 0.2.0.2,                        test-framework,                         test-framework-quickcheck2, QuickCheck >= 2,                        tasty, tasty-quickcheck, tasty-hunit
test/TestSuite.hs view
@@ -22,6 +22,17 @@ main :: IO () main = defaultMain tests +{- ++----- missing (because tasty, not test-framework): -----++Partitions.Compact+Numbers.Primes+Numbers.Sequences++-}++ tests :: [Test] tests =    [ testgroup_Permutations
test/Tests/Braid.hs view
@@ -226,7 +226,7 @@ prop_braidPerm_comp :: TwoBraids -> Bool prop_braidPerm_comp (TwoBraids b1 b2) = (p == q) where   p = braidPermutation (compose b1 b2) -  q = braidPermutation b1 `P.multiply` braidPermutation b2+  q = braidPermutation b1 `P.multiplyPermutation` braidPermutation b2  prop_link_positive :: PositiveBraid -> Bool prop_link_positive (PositiveB braid) = all (>=0) $ elems $ linkingMatrix braid
+ test/Tests/Numbers/Primes.hs view
@@ -0,0 +1,106 @@+++-- | Tests for number theory+--++{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, DataKinds, KindSignatures #-}+module Tests.Numbers.Primes where++--------------------------------------------------------------------------------++{-+import Test.Framework+import Test.Framework.Providers.QuickCheck2+import Test.QuickCheck+-}++import Test.Tasty+import Test.Tasty.HUnit      as U+import Test.Tasty.QuickCheck as Q ++import System.Random++import Data.List+import Data.Ratio++import GHC.TypeLits+import Data.Proxy++import Math.Combinat.Sign+import Math.Combinat.Numbers+import Math.Combinat.Numbers.Primes+import Math.Combinat.Helper++--------------------------------------------------------------------------------++prop_primes_sum_100    =  sum (take    100 primes)  @=?       24133 +prop_primes_sum_1000   =  sum (take   1000 primes)  @=?     3682913+prop_primes_sum_10000  =  sum (take  10000 primes)  @=?   496165411+prop_primes_sum_100000 =  sum (take 100000 primes)  @=? 62260698721++prop_divisorsigma1_sum_1000   =  sum [ divisorSum    n | n <- [1..1000] ]  @=?  823081+prop_divisorsigma1_sum_1000_b =  sum [ divisorSum' 1 n | n <- [1..1000] ]  @=?  823081+prop_divisorsigma2_sum_1000   =  sum [ divisorSum' 2 n | n <- [1..1000] ]  @=?  401382971+prop_divisorsigma3_sum_1000   =  sum [ divisorSum' 3 n | n <- [1..1000] ]  @=?  271161435595++prop_divisors_def n  =  sort (divisors n) == [ d | d<-[1..n] , d `divides` n ]++prop_moebius_inversion n   =  sum [ moebiusMu d | d <- divisors n ] == (if n==1 then 1 else 0)++prop_totient_divisorsum n  =  n == sum [ eulerTotient d | d <- divisors n ]++prop_totient_mobius_inv n  =  eulerTotient n == sum [ moebiusMu d * div n d | d <- divisors n ]++prop_Liouville_squaredivs n =  liouvilleLambda n == rhs where+  rhs = sum [ moebiusMu (div n d2) +            | d <- divisors n , let d2 = d*d , d2 <= n , d2 `divides` n+            ] ++prop_Liouville_sum n = sum [ liouvilleLambda d | d <- divisors n ] == (if isSquare n then 1 else 0) ++--------------------------------------------------------------------------------++prop_product_of_factors n  =  productOfFactors (factorize n) == n+prop_factorize_vs_naive n  =  factorize n == factorizeNaive n++--------------------------------------------------------------------------------++main = defaultMain tests++tests :: TestTree+tests = testGroup "Tests" [{-properties,-} unitTests]++unitTests :: TestTree+unitTests = testGroup "Primes module"+  [ unitTests1+  , unitTests2+  ]++unitTests1 :: TestTree+unitTests1 = testGroup "Elementary number theory unit tests "+  [ testCase "sum first 100 primes"         $ prop_primes_sum_100+  , testCase "sum first 1000 primes"        $ prop_primes_sum_1000+  , testCase "sum first 10000 primes"       $ prop_primes_sum_10000+  , testCase "sum first 100000 primes"      $ prop_primes_sum_100000+  , testCase "divisor set"                  $ allTrue [ prop_divisors_def n | n<-[1..1000] ]+  , testCase "sum 1000 divisor sigma_1"     $ prop_divisorsigma1_sum_1000+  , testCase "sum 1000 divisor sigma_1 /b"  $ prop_divisorsigma1_sum_1000_b+  , testCase "sum 1000 divisor sigma_2"     $ prop_divisorsigma2_sum_1000+  , testCase "sum 1000 divisor sigma_3"     $ prop_divisorsigma3_sum_1000+  , testCase "moebius inversion"            $ allTrue [ prop_moebius_inversion    n | n<-[1..1000] ]+  , testCase "totient divisor sum"          $ allTrue [ prop_totient_divisorsum   n | n<-[1..1000] ]+  , testCase "totient moebius inversion"    $ allTrue [ prop_totient_mobius_inv   n | n<-[1..1000] ]+  , testCase "Liouville square divs sumn"   $ allTrue [ prop_Liouville_squaredivs n | n<-[1..1000] ]+  , testCase "Liouville divisor sum"        $ allTrue [ prop_Liouville_sum        n | n<-[1..1000] ]+  ]++unitTests2 :: TestTree+unitTests2 = testGroup "Integer factorization"+  [ testCase "productOfFactors . factorize = id" $ allTrue [ prop_product_of_factors n | n<-[1..1000] ]+  , testCase "factorize vs. factorizeNaive"      $ allTrue [ prop_factorize_vs_naive n | n<-[1..1000] ]+  ]++allTrue :: [Bool] -> Assertion+allTrue bools = (and bools @=? True)++--------------------------------------------------------------------------------
+ test/Tests/Numbers/Sequences.hs view
@@ -0,0 +1,66 @@+++-- | Tests for integer sequences+--++{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, DataKinds, KindSignatures #-}+module Tests.Numbers.Sequences where++--------------------------------------------------------------------------------++{-+import Test.Framework+import Test.Framework.Providers.QuickCheck2+import Test.QuickCheck+-}++import Test.Tasty+import Test.Tasty.HUnit      as U+import Test.Tasty.QuickCheck as Q ++import System.Random++import Data.List+import Data.Ratio++import GHC.TypeLits+import Data.Proxy++import Math.Combinat.Sign+import Math.Combinat.Numbers.Sequences+import Math.Combinat.Numbers.Primes+import Math.Combinat.Helper++--------------------------------------------------------------------------------++prop_factorial_naive_vs_split n = factorialNaive n == factorialSplit n+prop_factorial_split_vs_swing n = factorialSplit n == factorialSwing n++prop_fac_exponents_vs_naive n  = factorialPrimeExponents n == factorialPrimeExponentsNaive n+prop_factorial_vs_fac_expos n  = productOfFactors (factorialPrimeExponents n) == factorial n++prop_double_factorial_naive_vs_split n = doubleFactorialNaive n == doubleFactorialSplit n++prop_binomial_naive_vs_split n k = binomialNaive n k == binomialSplit n k++--------------------------------------------------------------------------------++main = defaultMain tests++tests :: TestTree+tests = testGroup "Tests" [{-properties,-} unitTests]++unitTests :: TestTree+unitTests = testGroup "Numbers.Sequences module"+  [ testCase "naive vs. split factorial"          $ allTrue [ prop_factorial_naive_vs_split n | n<-[1..1000] ]+  , testCase "split vs. swing factorial"          $ allTrue [ prop_factorial_split_vs_swing n | n<-[1..1000] ]+  , testCase "naive vs. fast factorial expos"     $ allTrue [ prop_fac_exponents_vs_naive   n | n<-[1..1000] ]+  , testCase "factorial vs. fac exponents"        $ allTrue [ prop_factorial_vs_fac_expos   n | n<-[1..1000] ]+  , testCase "naive vs. split double factorial"   $ allTrue [ prop_double_factorial_naive_vs_split n | n<-[1..1000]  ]+  , testCase "naive vs. split binomial"           $ allTrue [ prop_binomial_naive_vs_split n k | n<-[1..100] , k<-[-3..n+3] ]+  ]++allTrue :: [Bool] -> Assertion+allTrue bools = (and bools @=? True)++--------------------------------------------------------------------------------
test/Tests/Partitions/Compact.hs view
@@ -3,16 +3,18 @@  -------------------------------------------------------------------------------- -import Data.List hiding ( uncons )+import Data.List hiding ( uncons , singleton ) import Data.Ord  import Test.Tasty import Test.Tasty.HUnit      as U import Test.Tasty.QuickCheck as Q  +import qualified Data.Vector.Compact.WordVec as Vec+ import Math.Combinat.Partitions.Integer.Compact-import Math.Combinat.Partitions.Integer as P--- import qualified Math.Combinat.Parititions.Integer.IntList as P +-- import qualified Math.Combinat.Partitions.Integer as P+import qualified Math.Combinat.Partitions.Integer.IntList as P   -------------------------------------------------------------------------------- @@ -23,6 +25,11 @@  -------------------------------------------------------------------------------- +cmp :: Partition -> Partition -> Ordering+cmp (Partition x) (Partition y) = Vec.cmpExtZero x y++--------------------------------------------------------------------------------+ unitTests :: TestTree unitTests = testGroup "Unit tests"   [ testCase "toList . fromList == id /1" $ allTrue [ xs == toList (fromDescList xs) | xs <- _testPartitions ]@@ -80,7 +87,7 @@   , testCase "dominates/15"            $ allTrue [ P._dominates xs1 xs2 == dominates p1 p2 | xs1 <- _parts    15 , xs2 <- _parts    15 , let p1 = fromDescList xs1 , let p2 = fromDescList xs2 ]   , testCase "dominates/16"            $ allTrue [ P._dominates xs1 xs2 == dominates p1 p2 | xs1 <- _parts    16 , xs2 <- _parts    16 , let p1 = fromDescList xs1 , let p2 = fromDescList xs2 ]   , testCase "dominates/17"            $ allTrue [ P._dominates xs1 xs2 == dominates p1 p2 | xs1 <- _parts    17 , xs2 <- _parts    17 , let p1 = fromDescList xs1 , let p2 = fromDescList xs2 ]-  , testCase "pieriRuleSingleBox"      $ allTrue [ pieriRuleSingleBox p =%%= map fromDescList (P._pieriRule xs 1) | xs <- _testPartitions      , let p = fromDescList xs ] +--  , testCase "pieriRuleSingleBox"      $ allTrue [ pieriRuleSingleBox p =%%= map fromDescList (P._pieriRule xs 1) | xs <- _testPartitions      , let p = fromDescList xs ]    , testCase "pieriRule"               $ allTrue [ pieriRule p k        =%%= map fromDescList (P._pieriRule xs k) | xs <- every10th _testPartitionsSmall , let p = fromDescList xs , k <- [1..2] ]    ] @@ -122,7 +129,7 @@   , prop "fromExpo . toExpo == id" $ \p -> fromExponentialForm (toExponentialForm p) == p   , prop "isSubPartitionOf"        $ \p q -> isSubPartitionOf p q == P._isSubPartitionOf (toList p) (toList q)   , prop "dominates"               $ \p q -> dominates p q == P._dominates (toList p) (toList q)-  , prop "pieriRuleSingleBox"      $ \p -> map toList (pieriRuleSingleBox p) =%%= P._pieriRule (toList p) 1 +--  , prop "pieriRuleSingleBox"      $ \p -> map toList (pieriRuleSingleBox p) =%%= P._pieriRule (toList p) 1     , localOption (QuickCheckTests 100)    $ prop "pieriRule /1"            $ \p (PieriK k) -> map toList (pieriRule p k) =%%= P._pieriRule (toList p) k 
test/Tests/Partitions/Integer.hs view
@@ -48,13 +48,20 @@     n <- choose (0, fromInteger (natVal (Proxy :: Proxy n)))     myMkGen' Part (randomPartition n) +newtype Expo = Expo [Int] deriving (Eq,Show)++instance Arbitrary Expo where+  arbitrary = do+    n  <- choose (0, 10)+    es <- replicateM n $ choose (0,4)+    return $ Expo es+ -------------------------------------------------------------------------------- -- * Types and instances  newtype PartitionWeight     = PartitionWeight     Int              deriving (Eq,Show) data    PartitionWeightPair = PartitionWeightPair Int Int          deriving (Eq,Show) data    PartitionIntPair    = PartitionIntPair    Partition Int    deriving (Eq,Show)- maxPartitionSize :: Int maxPartitionSize = 44 @@ -79,6 +86,16 @@     return (PartitionIntPair part k)  --------------------------------------------------------------------------------++-- {- CONJUGATE LEXICOGRAPHIC ordering is a refinement of dominance partial ordering -}+-- let test n = [ ConjLex p >= ConjLex q | p <- partitions n , q <-partitions n ,  p `dominates` q ]+-- and (test 20)++-- {- LEXICOGRAPHIC ordering is a refinement of dominance partial ordering -}+-- let test n = [ p >= q | p <- partitions n , q <-partitions n ,  p `dominates` q ]+-- and (test 20)++-------------------------------------------------------------------------------- -- * test group  testgroup_IntegerPartitions :: Test@@ -94,6 +111,11 @@   , testProperty "dominating partitions"           prop_dominating_list   , testProperty "counting partitions"             prop_countParts   , testProperty "union/sum duality"               prop_union_sum_duality+    --+  , testProperty "to/from expo vector"             prop_to_from_expo_vector+  , testProperty "to/from expo form"               prop_to_from_expo_form+  , testProperty "from/to expo vector"             prop_from_to_expo_vector+  , testProperty "from/to expo form"               prop_from_to_expo_form   ]  --------------------------------------------------------------------------------@@ -133,3 +155,12 @@  -------------------------------------------------------------------------------- +prop_to_from_expo_vector p  =  fromExponentVector  (toExponentVector  p) == p+prop_to_from_expo_form   p  =  fromExponentialForm (toExponentialForm p) == p++prop_from_to_expo_vector (Expo es) = toExponentVector (fromExponentVector es) == dropTailingZeros es++prop_from_to_expo_form   p  =  let ef = toExponentialForm p+                               in  toExponentialForm (fromExponentialForm ef) == ef++--------------------------------------------------------------------------------
test/Tests/Permutations.hs view
@@ -2,7 +2,7 @@ -- | Tests for permutations.  -- -{-# LANGUAGE CPP, ScopedTypeVariables, GeneralizedNewtypeDeriving, FlexibleContexts #-}+{-# LANGUAGE CPP, BangPatterns, ScopedTypeVariables, GeneralizedNewtypeDeriving, FlexibleContexts #-} module Tests.Permutations where  --------------------------------------------------------------------------------@@ -46,7 +46,7 @@   n = permutationSize perm  permInternalSet :: Permutation -> Array Int Elem-permInternalSet perm@(Permutation arr) = listArray (1,n) [ Elem (arr!i) | i<-[1..n] ] where+permInternalSet perm@(Permutation arr) = listArray (1,n) [ Elem (perm !!! i) | i<-[1..n] ] where   n = permutationSize perm  sameSize :: Permutation ->  Permutation -> Bool@@ -134,6 +134,7 @@    , testProperty "sign of permutation is multiplicative"     prop_mulSign         , testProperty "inverse is compatible with multiplication" prop_invMul+  , testProperty "sign of permutation is parity of inversions"  prop_sign_inversions    , testProperty "parity of cyclic permutaiton" prop_cyclSign   , testProperty "random permutation is valid"  prop_permIsPerm@@ -178,38 +179,40 @@  prop_randCyclic cycl = ( isCyclicPermutation (fromCyclic cycl) ) -prop_inverse perm = ( perm == inverse (inverse perm) ) +prop_inverse perm = ( perm == inversePermutation (inversePermutation perm) )   prop_mulPerm (SameSize perm1 perm2) = -    ( permute perm2 (permute perm1 set) == permute (perm1 `multiply` perm2) set ) +    ( permuteArray perm2 (permuteArray perm1 set) == permuteArray (perm1 `multiplyPermutation` perm2) set )    where      set = naturalSet perm1  prop_mulPermRight (SameSize perm1 perm2) = -    ( permuteRight perm2 (permuteRight perm1 set) == permuteRight (perm1 `multiply` perm2) set ) +    ( permuteArrayRight perm2 (permuteArrayRight perm1 set) == permuteArrayRight (perm1 `multiplyPermutation` perm2) set )    where      set = naturalSet perm1  prop_mulPermLeft (SameSize perm1 perm2) = -    ( permuteLeft perm2 (permuteLeft perm1 set) == permuteLeft (perm2 `multiply` perm1) set ) +    ( permuteArrayLeft perm2 (permuteArrayLeft perm1 set) == permuteArrayLeft (perm2 `multiplyPermutation` perm1) set )    where      set = naturalSet perm1 -prop_perm          perm = permute perm (naturalSet perm) == permInternalSet perm-prop_permLeft      perm = permuteLeft  perm (permInternalSet perm) == naturalSet perm-prop_permRight     perm = permuteRight perm (naturalSet perm) == permInternalSet perm-prop_permLeftRight perm = permuteLeft (inverse perm) (naturalSet perm) == permuteRight (perm) (naturalSet perm) +prop_perm          perm = permuteArray      perm (naturalSet perm) == permInternalSet perm+prop_permLeft      perm = permuteArrayLeft  perm (permInternalSet perm) == naturalSet perm+prop_permRight     perm = permuteArrayRight perm (naturalSet perm) == permInternalSet perm+prop_permLeftRight perm = permuteArrayLeft (inversePermutation perm) (naturalSet perm) == permuteArrayRight (perm) (naturalSet perm)   prop_cycleLeft  = permuteList (cycleLeft  5) "abcde" == "bcdea" prop_cycleRight = permuteList (cycleRight 5) "abcde" == "eabcd"  prop_mulSign (SameSize perm1 perm2) = -    ( sgn perm1 * sgn perm2 == sgn (perm1 `multiply` perm2) ) +    ( sgn perm1 * sgn perm2 == sgn (perm1 `multiplyPermutation` perm2) )    where      sgn = signValue . signOfPermutation :: Permutation -> Int +prop_sign_inversions perm = signOfPermutation perm == paritySign (numberOfInversions perm)+ prop_invMul (SameSize perm1 perm2) =   -  ( inverse perm2 `multiply` inverse perm1 == inverse (perm1 `multiply` perm2) ) +  ( inversePermutation perm2 `multiplyPermutation` inversePermutation perm1 == inversePermutation (perm1 `multiplyPermutation` perm2) )   prop_cyclSign cycl = ( isEvenPermutation perm == odd n ) where   perm = fromCyclic cycl@@ -221,17 +224,17 @@   isEvenAlternative p =      even $ sum $ map (\x->x-1) $ map length $ fromDisjointCycles $ permutationToDisjointCycles p -prop_bubbleSort perm = multiplyMany' n (map (adjacentTransposition n) $ bubbleSort perm) == perm where+prop_bubbleSort perm = productOfPermutations' n (map (adjacentTransposition n) $ bubbleSort perm) == perm where   n = permutationSize perm -prop_bubbleSort2 perm = multiplyMany' n (map (transposition n) $ bubbleSort2 perm) == perm where+prop_bubbleSort2 perm = productOfPermutations' n (map (transposition n) $ bubbleSort2 perm) == perm where   n = permutationSize perm  prop_bubble_inversions perm = length (bubbleSort perm) == numberOfInversions perm  prop_number_inversions perm = length (inversions perm) == numberOfInversions perm -prop_ninversions_inverse perm = numberOfInversions perm == numberOfInversions (inverse perm)+prop_ninversions_inverse perm = numberOfInversions perm == numberOfInversions (inversePermutation perm)  prop_merge_inversions perm = (numberOfInversionsMerge perm == numberOfInversionsNaive perm) 
test/Tests/Series.hs view
@@ -159,7 +159,7 @@ newtype NZRat  = NZRat  { fromNZRat  :: Rational } deriving (Eq,Ord,Show,Num,Fractional)  -- type parameter is for controlling the size (length), because some tests are too slow-newtype Ser  (n :: Nat) = Ser  { fromSer'  :: [Integer] } deriving (Eq,Ord,Show)+newtype Ser  (n :: Nat) = Ser  { fromSer'  :: [Integer]  } deriving (Eq,Ord,Show) newtype SerR (n :: Nat) = SerR { fromSerR' :: [Rational] } deriving (Eq,Ord,Show)  newtype Exp  = Exp  { fromExp  ::  Int  } deriving (Eq,Ord,Show,Num,Random)@@ -371,7 +371,7 @@ prop_diff_integrate ser = (xs =!= differentiateSeries (integrateSeries xs)) where   xs = fromSerR ser -prop_integrate_diff ser = (0 : tail xs =!= integrateSeries (differentiateSeries xs)) where+prop_integrate_diff ser = (null xs) || (0 : tail xs =!= integrateSeries (differentiateSeries xs)) where   xs = fromSerR ser  prop_cos_vs_cos2 = (cosSeries =!= (cosSeries2 :: [Rational]))