diff --git a/Math/Sym.hs b/Math/Sym.hs
--- a/Math/Sym.hs
+++ b/Math/Sym.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE FlexibleInstances #-}
+
 -- |
 -- Module      : Math.Sym
 -- Copyright   : (c) Anders Claesson 2012
@@ -28,9 +30,9 @@
     , generalize      -- :: Perm a => (StPerm -> StPerm) -> a -> a
 
     -- * Generating permutations
-    , unrankPerm      -- :: Perm a => a -> Integer -> a
-    , randomPerm      -- :: Perm a => a -> IO a
-    , perms           -- :: Perm a => a -> [a]
+    , unrankPerm      -- :: Perm a => Int -> Integer -> a
+    , randomPerm      -- :: Perm a => Int -> IO a
+    , perms           -- :: Perm a => Int -> [a]
 
     -- * Sorting operators
     , stackSort       -- :: Perm a => a -> a
@@ -42,9 +44,11 @@
     , avoiders        -- :: Perm a => [StPerm] -> [a] -> [a]
     , av              -- :: [StPerm] -> Int -> [StPerm]
 
-    -- * Single point deletions
+    -- * Single point extensions and deletions
     , del             -- :: Perm a => Int -> a -> a
     , shadow          -- :: (Ord a, Perm a) => a -> [a]
+    , ext             -- :: Perm a => Int -> a -> a
+    , coshadow        -- :: (Ord a, Perm a) => a -> [a]
 
     -- * Simple permutations
     , simple          -- :: Perm a => a -> Bool
@@ -60,7 +64,10 @@
 import Data.Bits (Bits, bitSize, testBit, popCount, shiftL)
 import Data.List (sort, sortBy, group)
 import Data.Vector.Storable (Vector)
-import qualified Data.Vector.Storable as SV (Vector, toList, fromList, fromListN, empty, map, (++))
+import qualified Data.Vector.Storable as SV
+    ( Vector, toList, fromList, fromListN, empty, singleton
+    , length, map, concat, splitAt
+    )
 import qualified Math.Sym.Internal as I
 import Foreign.C.Types (CUInt(..))
 
@@ -82,7 +89,7 @@
 
 instance Monoid StPerm where
     mempty = fromVector SV.empty
-    mappend u v = fromVector $ (SV.++) u' v'
+    mappend u v = fromVector $ SV.concat [u', v']
         where
           u' = toVector u
           v' = SV.map ( + size u) $ toVector v
@@ -112,7 +119,7 @@
 -- | The /skew sum/ of two permutations. (A definition of the
 -- /direct sum/ is provided by 'mappend' of the 'Monoid' instance for 'StPerm'.)
 (/-/) :: StPerm -> StPerm -> StPerm
-u /-/ v = fromVector $ (SV.++) u' v'
+u /-/ v = fromVector $ SV.concat [u', v']
     where
       u' = SV.map ( + size v) $ toVector u
       v' = toVector v
@@ -136,9 +143,10 @@
 -- The permutation typeclass
 -- -------------------------
 
--- | The class of permutations. Minimal complete definition: 'st' and
--- 'act'. The default implementations of 'size' and 'idperm' can be
--- somewhat slow, so you may want to implement them as well.
+-- | The class of permutations. Minimal complete definition: 'st'
+-- 'act' and 'idperm'. The default implementations of 'size' and
+-- 'neutralize' can be somewhat slow, so you may want to implement
+-- them as well.
 class Perm a where
 
     -- | The standardization map. If there is an underlying linear
@@ -154,7 +162,7 @@
     -- | A (left) /group action/ of 'StPerm' on @a@. As for any group
     -- action it should hold that
     -- 
-    -- > (u `act` v) `act` w == u `act` (v `act` w)   &&   idperm u `act` v == v
+    -- > (u `act` v) `act` w == u `act` (v `act` w)   &&   neutralize u `act` v == v
     -- 
     act :: StPerm -> a -> a
 
@@ -171,29 +179,31 @@
     size :: a -> Int
     size = size . st
 
-    -- | The identity permutation on the same underlying set as the
-    -- given permutation. It should hold that
-    -- 
-    -- > st (idperm u) == idperm (st u)
-    -- 
-    -- Group theoretically, it should also hold that @u . inverse u ==
-    -- idperm u@. In terms of the group action this means
+    -- | The identity permutation of the given size.
+    idperm :: Int -> a
+
+    -- | The permutation obtained by acting on the given permutation
+    -- with its own inverse; that is, the identity permutation on the
+    -- same underlying set as the given permutation. It should hold
+    -- that
     -- 
-    -- > idperm u == inverse (st u) `act` u
+    -- > st (neutralize u) == neutralize (st u)
+    -- > neutralize u == inverse (st u) `act` u
+    -- > neutralize u == idperm (size u)
     -- 
-    -- and this is the default implementation.
-    {-# INLINE idperm #-}
-    idperm :: a -> a
-    idperm u = inverse (st u) `act` u
+    -- The default implementation uses the last of these three equations.
+    {-# INLINE neutralize #-}
+    neutralize :: a -> a
+    neutralize = idperm . size
 
     -- | The group theoretical inverse. It should hold that
     -- 
-    -- > inverse u == inverse (st u) `act` idperm u
+    -- > inverse u == inverse (st u) `act` neutralize u
     -- 
     -- and this is the default implementation.
     {-# INLINE inverse #-}
     inverse :: a -> a
-    inverse u = inverse (st u) `act` idperm u
+    inverse u = inverse (st u) `act` neutralize u
 
     -- | Predicate determining if two permutations are
     -- order-isomorphic. The default implementation uses
@@ -202,7 +212,7 @@
     -- 
     -- Equivalently, one could use
     -- 
-    -- > u `ordiso` v  ==  inverse u `act` v == idperm v
+    -- > u `ordiso` v  ==  inverse u `act` v == neutralize v
     -- 
     {-# INLINE ordiso #-}
     ordiso :: StPerm -> a -> Bool
@@ -212,7 +222,7 @@
     st         = id
     act u v    = fromVector $ I.act (toVector u) (toVector v)
     size       = I.size . toVector
-    idperm     = fromVector . I.idperm . size
+    idperm     = fromVector . I.idperm
     inverse    = fromVector . I.inverse . toVector
     ordiso     = (==)
 
@@ -221,47 +231,60 @@
 act' :: Ord a => [a] -> [b] -> [b]
 act' u = map snd . sortBy (comparing fst) . zip u
 
-instance (Enum a, Ord a) => Perm [a] where
-    st         = fromVector . I.st . I.fromList . map fromEnum
-    act u      = act' $ toList (inverse u)
-    inverse v  = act' v (idperm v)
+stL :: Enum a => [a] -> StPerm
+stL = fromVector . I.st . I.fromList . map fromEnum
+
+actL :: StPerm -> [a] -> [a]
+actL u = act' $ toList (inverse u)
+
+instance Perm String where
+    st         = stL
+    act        = actL
+    inverse v  = act' v (neutralize v)
     size       = length
-    idperm     = sort
+    idperm n   = take n $ ['1'..'9'] ++ ['A'..'Z'] ++ ['a'..'z'] ++ ['{'..]
 
+instance Perm [Int] where
+    st         = stL
+    act        = actL
+    inverse v  = act' v (neutralize v)
+    size       = length
+    idperm n   = [1..n]
 
+
 -- Generalize
 -- ----------
 
 -- | Generalize a function on 'StPerm' to a function on any permutations:
 -- 
--- > generalize f v = f (st v) `act` idperm v
+-- > generalize f v = f (st v) `act` neutralize v
 -- 
 -- Note that this will only work as intended if @f@ is size preserving.
 generalize :: Perm a => (StPerm -> StPerm) -> a -> a
-generalize f v = f (st v) `act` idperm v
+generalize f v = f (st v) `act` neutralize v
 
 
 -- Generating permutations
 -- -----------------------
 
 -- | @unrankPerm u rank@ is the @rank@-th (Myrvold & Ruskey)
--- permutation of @u@. E.g.,
+-- permutation of size @n@. E.g.,
 -- 
--- > unrankPerm ['1'..'9'] 88888 == "561297843"
+-- > unrankPerm 9 88888 == "561297843"
 -- 
-unrankPerm :: Perm a => a -> Integer -> a
-unrankPerm u = (`act` u) . fromVector . I.unrankPerm (size u)
+unrankPerm :: Perm a => Int -> Integer -> a
+unrankPerm n = (`act` idperm n) . fromVector . I.unrankPerm n
 
--- | @randomPerm u@ is a random permutation of @u@.
-randomPerm :: Perm a => a -> IO a
-randomPerm u = ((`act` u) . fromVector . I.fromLehmercode) `liftM` I.randomLehmercode (size u)
+-- | @randomPerm n@ is a random permutation of size @n@.
+randomPerm :: Perm a => Int -> IO a
+randomPerm n = ((`act` idperm n) . fromVector . I.fromLehmercode) `liftM` I.randomLehmercode n
 
--- | All permutations of a given permutation. E.g.,
+-- | All permutations of a given size. E.g.,
 -- 
--- > perms "123" == ["123","213","321","132","231","312"]
+-- > perms 3 == ["123","213","321","132","231","312"]
 -- 
-perms :: Perm a => a -> [a]
-perms u = map (`act` u) $ sym (size u)
+perms :: Perm a => Int -> [a]
+perms n = map (`act` idperm n) $ sym n
 
 
 -- Sorting operators
@@ -309,16 +332,29 @@
 av ps = avoiders ps . sym
 
 
--- Single point deletions
--- ----------------------
+-- Single point extensions and deletions
+-- -------------------------------------
 
 -- | Delete the element at a given position
 del :: Perm a => Int -> a -> a
-del i = generalize $ fromVector . I.del i .toVector
+del i = generalize $ fromVector . I.del i . toVector
 
 -- | The list of all single point deletions
 shadow :: (Ord a, Perm a) => a -> [a]
 shadow w = map head . group $ sort [ del i w | i <- [0 .. size w - 1]]
+
+-- | Insert a new largest element at the given position
+ext :: Perm a => Int -> a -> a
+ext i = generalize' $ fromVector . ext0 . toVector
+    where
+      generalize' f w = f (st w) `act` idperm (1+size w)
+      ext0 w = SV.concat [u, SV.singleton (SV.length w), v]
+          where
+            (u,v) = SV.splitAt i w
+
+-- | The list of all single point extensions
+coshadow :: (Ord a, Perm a) => a -> [a]
+coshadow w = map head . group $ sort [ ext i w | i <- [0 .. size w]]
 
 
 -- Simple permutations
diff --git a/Math/Sym/Internal.hs b/Math/Sym/Internal.hs
--- a/Math/Sym/Internal.hs
+++ b/Math/Sym/Internal.hs
@@ -61,6 +61,7 @@
     , cyc     -- cycles
     , inv     -- inversions
     , maj     -- the major index
+    , comaj   -- the co-major index
     , peak    -- peaks
     , vall    -- valleys
     , dasc    -- double ascents
@@ -330,6 +331,9 @@
 foreign import ccall unsafe "stat.h maj" c_maj
     :: Ptr CLong -> CLong -> CLong
 
+foreign import ccall unsafe "stat.h comaj" c_comaj
+    :: Ptr CLong -> CLong -> CLong
+
 foreign import ccall unsafe "stat.h peak" c_peak
     :: Ptr CLong -> CLong -> CLong
 
@@ -414,6 +418,10 @@
 -- | The major index.
 maj :: Perm0 -> Int
 maj = stat c_maj
+
+-- | The co-major index.
+comaj :: Perm0 -> Int
+comaj = stat c_comaj
 
 -- | The number of peaks.
 peak :: Perm0 -> Int
diff --git a/Math/Sym/Stat.hs b/Math/Sym/Stat.hs
--- a/Math/Sym/Stat.hs
+++ b/Math/Sym/Stat.hs
@@ -26,6 +26,7 @@
     , cyc         -- cycles
     , inv         -- inversions
     , maj         -- the major index
+    , comaj       -- the co-major index
     , peak        -- peaks
     , vall        -- valleys
     , dasc        -- double ascents
@@ -53,7 +54,8 @@
 import Math.Sym (Perm, toVector, st)
 import Math.Sym.Internal (Perm0)
 import qualified Math.Sym.Internal as I 
-    ( asc, des, exc, fp, cyc, inv, maj, peak, vall, dasc, ddes, lmin, lmax, rmin, rmax
+    ( asc, des, exc, fp, cyc, inv, maj, comaj, peak, vall, dasc, ddes
+    , lmin, lmax, rmin, rmax
     , head, last, lir, ldr, rir, rdr, comp, ep, dim, asc0, des0
     , lminValues, lminIndices
     )
@@ -91,6 +93,10 @@
 -- | /The major index/ is the sum of descents.
 maj :: Perm a => a -> Int
 maj = generalize I.maj
+
+-- | /The co-major index/ is the sum of descents.
+comaj :: Perm a => a -> Int
+comaj = generalize I.comaj
 
 -- | The number of /peaks/: positions @i@ such that @w[i-1] \< w[i]@ and @w[i] \> w[i+1]@.
 peak :: Perm a => a -> Int
diff --git a/cbits/stat.c b/cbits/stat.c
--- a/cbits/stat.c
+++ b/cbits/stat.c
@@ -112,6 +112,19 @@
 	return sum;
 }
 
+/* The co-major index */
+long
+comaj(const long *w, long len)
+{
+	long i, sum = 0;
+
+	for (i = 1; i < len; i++, w++) {
+		if (*w > *(w+1))
+			sum += len - i;
+	}
+	return sum;
+}
+
 
 /* The number of peaks */
 long
diff --git a/include/stat.h b/include/stat.h
--- a/include/stat.h
+++ b/include/stat.h
@@ -2,8 +2,10 @@
 long des  (const long *, long); /* descents */
 long exc  (const long *, long); /* excedances */
 long fp   (const long *, long); /* fixed points */
+long cyc  (const long *, long); /* The number of cycles */
 long inv  (const long *, long); /* inversions */
 long maj  (const long *, long); /* major index */
+long comaj(const long *, long); /* co-major index */
 long peak (const long *, long); /* peaks */
 long vall (const long *, long); /* valleys */
 long dasc (const long *, long); /* double ascents */
@@ -14,6 +16,9 @@
 long ldr  (const long *, long); /* left-most decreasing run */
 long comp (const long *, long); /* components */
 long ep   (const long *, long); /* rank a la Elizalde & Pak */
+long dim  (const long *, long); /* dimension */
+long asc0 (const long *, long); /* small ascents */
+long des0 (const long *, long); /* small descents */
 
-long lmin_values  (long *, const long *, long);
-long lmin_indices (long *, const long *, long);
+long lmin_values  (long *, const long *, long); /* values of left-to-right minima */
+long lmin_indices (long *, const long *, long); /* indices of left-to-right minima */
diff --git a/sym.cabal b/sym.cabal
--- a/sym.cabal
+++ b/sym.cabal
@@ -1,5 +1,5 @@
 Name:                sym
-Version:             0.2.3
+Version:             0.3
 Synopsis:            Permutations, patterns, and statistics
 Description:         
   Definitions for permutations with an emphasis on permutation
diff --git a/tests/Properties.hs b/tests/Properties.hs
--- a/tests/Properties.hs
+++ b/tests/Properties.hs
@@ -34,15 +34,10 @@
               r2 <- rank n
               return (n, r1, r2)
 
-moreThan :: Int -> Gen Int
-moreThan x = (\d -> x + abs d) `liftM` choose (1, 100)
-
-vecFrom :: Int -> Int -> Gen [Int]
-vecFrom 0 _ = return []
-vecFrom n x = moreThan x >>= liftM (x:) . vecFrom (n-1)
-
-incVec :: Int -> Gen [Int]
-incVec n = arbitrary >>= vecFrom n
+lenRank3 :: Gen (Int, Integer, Integer, Integer)
+lenRank3 = do (n, r1, r2) <- lenRank2
+              r3 <- rank n
+              return (n, r1, r2, r3)
 
 -- The sub-permutation determined by a set of indices.
 subperm :: Sym.Set -> Sym.StPerm -> Sym.StPerm
@@ -55,20 +50,21 @@
     arbitrary = uncurry Sym.unrankStPerm `liftM` lenRank
     shrink w = nub $ [0 .. Sym.size w - 1] >>= \k -> subperms k w
 
+perm :: Gen [Int]
+perm = liftM (\w -> w `Sym.act` [1..Sym.size w]) arbitrary
+
 perm2 :: Gen (Sym.StPerm, [Int])
-perm2 = do u <- arbitrary
-           v <- incVec (Sym.size u)
-           return (u, v)
+perm2 = do (n,r1,r2) <- lenRank2
+           let u = Sym.unrankStPerm n r1
+           let v = Sym.unrankStPerm n r2
+           return (u, v `Sym.act` [1..n])
 
 perm3 :: Gen (Sym.StPerm, Sym.StPerm, [Int])
-perm3 = do (n,r1,r2) <- lenRank2
+perm3 = do (n,r1,r2,r3) <- lenRank3
            let u = Sym.unrankStPerm n r1
            let v = Sym.unrankStPerm n r2
-           w <- incVec n
-           return (u, v, w)
-
-perm :: Gen [Int]
-perm = liftM (uncurry Sym.act) perm2
+           let w = Sym.unrankStPerm n r3
+           return (u, v, w `Sym.act` [1..n])
 
 newtype Symmetry = Symmetry (Sym.StPerm -> Sym.StPerm, String)
 
@@ -124,7 +120,7 @@
       sym' n = map Sym.fromList $ Data.List.permutations [0..fromIntegral n - 1]
 
 prop_perm =
-    and [ sort (Sym.perms [1..n]) == sort (permutations [1..n]) | n<-[0..6] ]
+    and [ sort (Sym.perms n) == sort (permutations [1..n]) | n<-[0..6::Int] ]
 
 prop_st =
     forAll perm2 $ \(u,v) -> Sym.st (u `Sym.act` v) == u `Sym.act` Sym.st v
@@ -133,7 +129,7 @@
     forAll perm2 $ \(u,v) -> u `Sym.act` v == map (v!!) (Sym.toList u)
 
 prop_act_id =
-    forAll perm2 $ \(u,v) -> Sym.idperm u `Sym.act` v == v
+    forAll perm2 $ \(u,v) -> Sym.neutralize u `Sym.act` v == v
 
 prop_act_associative =
     forAll perm3 $ \(u,v,w) -> (u `Sym.act` v) `Sym.act` w == u `Sym.act` (v `Sym.act` w)
@@ -141,28 +137,37 @@
 prop_size =
     forAll perm $ \v -> Sym.size v == Sym.size (Sym.st v)
 
-prop_idperm =
-    forAll perm2 $ \(u,v) -> Sym.idperm u == Sym.inverse (Sym.st u) `Sym.act` u
+prop_neutralize =
+    forAll perm2 $ \(u,v) -> Sym.neutralize u == Sym.inverse (Sym.st u) `Sym.act` u
 
 prop_inverse =
-    forAll perm $ \v -> Sym.inverse v == Sym.inverse (Sym.st v) `Sym.act` Sym.idperm v
+    forAll perm $ \v -> Sym.inverse v == Sym.inverse (Sym.st v) `Sym.act` Sym.neutralize v
 
 prop_ordiso1 =
-    forAll perm2 $ \(u,v) -> u `Sym.ordiso` v  ==  (u == Sym.st v)
+    forAll perm2 $ \(u,v) -> u `Sym.ordiso` v == (u == Sym.st v)
 
 prop_ordiso2 =
-    forAll perm2 $ \(u,v) -> u `Sym.ordiso` v  ==  (Sym.inverse u `Sym.act` v == Sym.idperm v)
+    forAll perm2 $ \(u,v) -> u `Sym.ordiso` v == (Sym.inverse u `Sym.act` v == Sym.neutralize v)
 
 shadow :: Ord a => [a] -> [[a]]
 shadow w = nubSort . map normalize $ ptDeletions w
     where
-      normalize u = [ (sort w)!!i | i <- st u ]
+      w' = sort w
+      normalize u = [ w'!!i | i <- st u ]
       nubSort = map head . group . sort
       ptDeletions [] = []
       ptDeletions xs@(x:xt) = xt : map (x:) (ptDeletions xt)
 
-prop_shadow = forAll perm $ \w -> Sym.shadow w == shadow w
+prop_shadow = forAll (resize 30 perm) $ \w -> Sym.shadow w == shadow w
 
+coshadow :: (Enum a, Ord a) => [a] -> [[a]]
+coshadow w = sort $ ptExtensions (succ $ maximum (toEnum 0 : w)) w
+    where
+      ptExtensions n [] = [[n]]
+      ptExtensions n xs@(x:xt) = (n:xs) : map (x:) (ptExtensions n xt)
+
+prop_coshadow = forAll (resize 50 perm) $ \w -> Sym.coshadow w == coshadow w
+
 segments :: [a] -> [[a]]
 segments [] = [[]]
 segments (x:xs) = segments xs ++ map (x:) (inits xs)
@@ -182,24 +187,25 @@
 simple :: Ord a => [a] -> Bool
 simple = null . properIntervals
 
-prop_simple = forAll (resize 50 perm) $ \w -> Sym.simple w == simple w
+prop_simple = forAll (resize 40 perm) $ \w -> Sym.simple w == simple w
 
 prop_unrankPerm =
     forAll perm $ \w ->
-    forAll (choose (0, product [1..fromIntegral (length w) - 1])) $ \r ->
-        Sym.st (Sym.unrankPerm (sort w) r) == Sym.unrankStPerm (length w) r
+        let n = length w
+        in forAll (choose (0, product [1..fromIntegral n - 1])) $ \r ->
+            Sym.st (Sym.unrankPerm n r :: [Int]) == Sym.unrankStPerm n r
 
 prop_stackSort = forAll perm $ \v -> Sym.stackSort v == stack v
 
 prop_stackSort_231 =
     forAll perm $ \v ->
-        (Sym.stackSort v == Sym.idperm v) == (v `Sym.avoids` [Sym.st "231"])
+        (Sym.stackSort v == Sym.neutralize v) == (v `Sym.avoids` [Sym.st "231"])
 
 prop_bubbleSort = forAll perm $ \v -> Sym.bubbleSort v == bubble v
 
 prop_bubbleSort_231_321 =
     forAll perm $ \v ->
-        (Sym.bubbleSort v == Sym.idperm v) == (v `Sym.avoids` [Sym.st "231", Sym.st "321"])
+        (Sym.bubbleSort v == Sym.neutralize v) == (v `Sym.avoids` [Sym.st "231", Sym.st "321"])
 
 prop_subperm_copies p =
     forAll (resize 21 perm) $ \w -> and [ subperm m (Sym.st w) == p | m <- Sym.copiesOf p w ]
@@ -295,7 +301,7 @@
 prop_subsets_cardinality2 =
     forAll (choose (0,20)) $ \n ->
     forAll (choose (0,20)) $ \k ->
-        let cs = map (SV.length) (Sym.subsets n k) in ((k > n) && null cs) || ([k] == nub cs)
+        let cs = map SV.length (Sym.subsets n k) in ((k > n) && null cs) || ([k] == nub cs)
 
 testsPerm =
     [ ("monoid/mempty/1",                check prop_monoid_mempty1)
@@ -313,11 +319,12 @@
     , ("act/id",                         check prop_act_id)
     , ("act/associative",                check prop_act_associative)
     , ("size",                           check prop_size)
-    , ("idperm",                         check prop_idperm)
+    , ("neutralize",                     check prop_neutralize)
     , ("inverse",                        check prop_inverse)
     , ("ordiso/1",                       check prop_ordiso1)
     , ("ordiso/2",                       check prop_ordiso2)
     , ("shadow",                         check prop_shadow)
+    , ("coshadow",                       check prop_coshadow)
     , ("simple",                         check prop_simple)
     , ("unrankPerm",                     check prop_unrankPerm)
     , ("stackSort",                      check prop_stackSort)
@@ -480,10 +487,11 @@
 des, asc, inv, lmin, lmax, rmin, rmax, peak, vall :: [Int] -> Int
 dasc, ddes, maj, comp, ep, dim :: [Int] -> Int
 
-dim  w = maximum $ 0 : [ i | (i,x) <- zip [0..] (st w), i /= x ]
-maj  w = sum [ i | (i,x,y) <- zip3 [1..] w (tail w), x > y ]
-asc0 w = sum [ 1 | (x,y) <- ascents  $ st w, y-x == 1 ]
-des0 w = sum [ 1 | (x,y) <- descents $ st w, x-y == 1 ]
+dim   w = maximum $ 0 : [ i | (i,x) <- zip [0..] (st w), i /= x ]
+maj   w = sum [ i | (i,x,y) <- zip3 [1..] w (tail w), x > y ]
+comaj w = sum [ n-i | (i,x,y) <- zip3 [1..] w (tail w), x > y ] where n = length w
+asc0  w = sum [ 1 | (x,y) <- ascents  $ st w, y-x == 1 ]
+des0  w = sum [ 1 | (x,y) <- descents $ st w, x-y == 1 ]
 
 asc  = length . ascents
 des  = length . descents
@@ -497,42 +505,43 @@
 dasc = length . doubleAscents
 ddes = length . doubleDescents
 
-prop_asc  = forAll perm $ \w -> asc  w == S.asc  w
-prop_des  = forAll perm $ \w -> des  w == S.des  w
-prop_exc  = forAll perm $ \w -> exc  w == S.exc  w
-prop_fp   = forAll perm $ \w -> fp   w == S.fp   w
-prop_cyc  = forAll perm $ \w -> cyc  w == S.cyc  w
-prop_inv  = forAll perm $ \w -> inv  w == S.inv  w
-prop_maj  = forAll perm $ \w -> maj  w == S.maj  w
-prop_lmin = forAll perm $ \w -> lmin w == S.lmin w
-prop_lmax = forAll perm $ \w -> lmax w == S.lmax w
-prop_rmin = forAll perm $ \w -> rmin w == S.rmin w
-prop_rmax = forAll perm $ \w -> rmax w == S.rmax w
-prop_head = forAll perm $ \w -> not (null w) ==> head (st w) == S.head w
-prop_last = forAll perm $ \w -> not (null w) ==> last (st w) == S.last w
-prop_peak = forAll perm $ \w -> peak w == S.peak w
-prop_vall = forAll perm $ \w -> vall w == S.vall w
-prop_dasc = forAll perm $ \w -> dasc w == S.dasc w
-prop_ddes = forAll perm $ \w -> ddes w == S.ddes w
-prop_ep   = forAll perm $ \w -> ep   w == S.ep   w
-prop_lir  = forAll perm $ \w -> lir  w == S.lir  w
-prop_ldr  = forAll perm $ \w -> ldr  w == S.ldr  w
-prop_rir  = forAll perm $ \w -> rir  w == S.rir  w
-prop_rdr  = forAll perm $ \w -> rdr  w == S.rdr  w
-prop_comp = forAll perm $ \w -> comp w == S.comp w
-prop_dim  = forAll perm $ \w -> dim  w == S.dim  w
-prop_asc0 = forAll perm $ \w -> asc0 w == S.asc0 w
-prop_des0 = forAll perm $ \w -> des0 w == S.des0 w
+prop_asc   = forAll perm $ \w -> asc   w == S.asc   w
+prop_des   = forAll perm $ \w -> des   w == S.des   w
+prop_exc   = forAll perm $ \w -> exc   w == S.exc   w
+prop_fp    = forAll perm $ \w -> fp    w == S.fp    w
+prop_cyc   = forAll perm $ \w -> cyc   w == S.cyc   w
+prop_inv   = forAll perm $ \w -> inv   w == S.inv   w
+prop_maj   = forAll perm $ \w -> maj   w == S.maj   w
+prop_comaj = forAll perm $ \w -> comaj w == S.comaj w
+prop_lmin  = forAll perm $ \w -> lmin  w == S.lmin  w
+prop_lmax  = forAll perm $ \w -> lmax  w == S.lmax  w
+prop_rmin  = forAll perm $ \w -> rmin  w == S.rmin  w
+prop_rmax  = forAll perm $ \w -> rmax  w == S.rmax  w
+prop_head  = forAll perm $ \w -> not (null w) ==> head w == 1 + S.head w
+prop_last  = forAll perm $ \w -> not (null w) ==> last w == 1 + S.last w
+prop_peak  = forAll perm $ \w -> peak  w == S.peak  w
+prop_vall  = forAll perm $ \w -> vall  w == S.vall  w
+prop_dasc  = forAll perm $ \w -> dasc  w == S.dasc  w
+prop_ddes  = forAll perm $ \w -> ddes  w == S.ddes  w
+prop_ep    = forAll perm $ \w -> ep    w == S.ep    w
+prop_lir   = forAll perm $ \w -> lir   w == S.lir   w
+prop_ldr   = forAll perm $ \w -> ldr   w == S.ldr   w
+prop_rir   = forAll perm $ \w -> rir   w == S.rir   w
+prop_rdr   = forAll perm $ \w -> rdr   w == S.rdr   w
+prop_comp  = forAll perm $ \w -> comp  w == S.comp  w
+prop_dim   = forAll perm $ \w -> dim   w == S.dim   w
+prop_asc0  = forAll perm $ \w -> asc0  w == S.asc0  w
+prop_des0  = forAll perm $ \w -> des0  w == S.des0  w
 
 prop_inv_21 = forAll perm $ \w -> S.inv w == length (Sym.copiesOf (Sym.st "21") w)
 
 prop_lmin_values =
-    forAll perm $ \w -> lMinima (st w) == S.lminValues  w
+    forAll perm $ \w -> lMinima (st w) == S.lminValues w
 prop_lmin_indices =
-    forAll perm $ \w -> [ head $ elemIndices x w | x <- lMinima w ] == S.lminIndices  w
+    forAll perm $ \w -> [ head $ elemIndices x w | x <- lMinima w ] == S.lminIndices w
 prop_lmin_card =
-    forAll perm $ \w -> and [ S.lmin w == length (S.lminValues  w)
-                            , S.lmin w == length (S.lminIndices  w)
+    forAll perm $ \w -> and [ S.lmin w == length (S.lminValues w)
+                            , S.lmin w == length (S.lminIndices w)
                             ]
 
 testsStat =
@@ -543,6 +552,7 @@
     , ("cyc",          check prop_cyc)
     , ("inv",          check prop_inv)
     , ("maj",          check prop_maj)
+    , ("comaj",        check prop_comaj)
     , ("lmin",         check prop_lmin)
     , ("lmax",         check prop_lmax)
     , ("rmin",         check prop_rmin)
