module Sym.Perm.Component
(
components
, skewComponents
, leftMaxima
, leftMinima
, rightMaxima
, rightMinima
) where
import Foreign
import System.IO.Unsafe
import Sym.Perm
import qualified Sym.Perm.D8 as D8
comps :: Perm -> [Int]
comps w = unsafePerformIO . 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'
components :: Perm -> [Perm]
components w =
let ds = 0 : map (+1) (comps w)
ks = zipWith () (tail ds) ds
ws = slices ks w
in zipWith (\d v -> imap (\_ x -> x fromIntegral d) v) ds ws
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
leftMaxima :: Perm -> [Int]
leftMaxima w = map fromIntegral . reverse $ records (<) (toList w)
leftMinima :: Perm -> [Int]
leftMinima w = map fromIntegral . reverse $ records (>) (toList w)
rightMaxima :: Perm -> [Int]
rightMaxima w = map fromIntegral $ records (<) (reverse (toList w))
rightMinima :: Perm -> [Int]
rightMinima w = map fromIntegral $ records (>) (reverse (toList w))