-- | -- Copyright : Anders Claesson 2013 -- Maintainer : Anders Claesson -- -- Components of permutations. -- module Math.Perm.Component ( components , skewComponents , leftMaxima , leftMinima , rightMaxima , rightMinima ) where import Foreign import System.IO.Unsafe import Data.Perm import qualified Math.Perm.D8 as D8 -- Positions /i/ such that /max{ w[j] : j <= i } = i/. These positions -- mark the boundaries of components. comps :: Perm -> [Int] comps w = unsafeDupablePerformIO . unsafeWith w $ go [] 0 0 where n = size w go ks m i p | i >= n = return (reverse ks) | otherwise = do y <- fromIntegral `fmap` peek p let p' = advancePtr p 1 let i' = i+1 let m' = if y > m then y else m let ks' = if m' == i then i:ks else ks go ks' m' i' p' -- | The list of (plus) components. components :: Perm -> [Perm] components w = let ds = 0 : map (+1) (comps w) ks = zipWith (-) (tail ds) ds ws = unsafeSlice ks w in zipWith (\d v -> imap (\_ x -> x - fromIntegral d) v) ds ws -- | The list of skew components, also called minus components. skewComponents :: Perm -> [Perm] skewComponents = map D8.complement . components . D8.complement records :: (a -> a -> Bool) -> [a] -> [a] records _ [] = [] records f (x:xs) = recs [x] xs where recs rs@(r:_) (y:ys) = recs ((if f r y then y else r):rs) ys recs rs _ = rs -- | For each position, left-to-right, records the largest value seen -- thus far. leftMaxima :: Perm -> [Int] leftMaxima w = reverse $ records (<) (toList w) -- | For each position, left-to-right, records the smallest value seen -- thus far. leftMinima :: Perm -> [Int] leftMinima w = reverse $ records (>) (toList w) -- | For each position, /right-to-left/, records the largest value seen -- thus far. rightMaxima :: Perm -> [Int] rightMaxima w = records (<) (reverse (toList w)) -- | For each position, /right-to-left/, records the smallest value seen -- thus far. rightMinima :: Perm -> [Int] rightMinima w = records (>) (reverse (toList w))