ix-shapable-0.1.0: Data/Ix/Shapable.hs
{-# LANGUAGE FlexibleInstances #-}
module Data.Ix.Shapable
( Shapable(..)
, rank
, shape
, shapeToStride
, size
) where
import Data.Array.Base (numElements)
import Data.Array.IArray
-- | Determine the rank of an array.
rank :: (Shapable i, Ix i, IArray a e) => a i e -> Int
rank = sRank . fst . bounds
-- | Canonical representation of the shape.
-- The following properties hold:
-- 'length . shape = rank'
-- 'product . shape = size'
shape :: (Shapable i, Ix i, IArray a e) => a i e -> [Int]
shape = uncurry sShape . bounds
-- | How much the offset changes when you move one element in the given
-- direction. Since arrays are in row-major order, 'last . shapeToStride = const 1'
shapeToStride :: [Int] -> [Int]
shapeToStride = scanr (*) 1 . tail
-- | Number of elements in the Array.
size :: (Ix i, IArray a e) => a i e -> Int
size = numElements
-- | We need this type class to distinguish between different tuples of Ix.
-- There are Shapable instances for homogenous Int tuples, but may Haddock
-- doesn't see them.
class Shapable i where
sRank :: i -> Int
sShape :: i -> i -> [Int]
sBounds :: [Int] -> (i,i)
instance Shapable Int where
sRank _ = 1
sShape a a' = [rangeSize (a,a')]
sBounds [a] = (0,a-1)
sBounds _ = error "sBounds expected list length 1"
instance Shapable (Int,Int) where
sRank _ = 2
sShape (a,b) (a',b') = [rangeSize (a,a'), rangeSize (b,b')]
sBounds [a,b] = ((0,0),(a-1,b-1))
sBounds _ = error "sBounds expected list length 2"
instance Shapable (Int,Int,Int) where
sRank _ = 3
sShape (a,b,c) (a',b',c') =
[rangeSize (a,a'), rangeSize (b,b'), rangeSize (c,c')]
sBounds [a,b,c] = ((0,0,0),(a-1,b-1,c-1))
sBounds _ = error "sBounds expected list length 3"
instance Shapable (Int,Int,Int,Int) where
sRank _ = 4
sShape (a,b,c,d) (a',b',c',d') =
[rangeSize (a,a'), rangeSize (b,b'), rangeSize (c,c'), rangeSize (d,d')]
sBounds [a,b,c,d] = ((0,0,0,0),(a-1,b-1,c-1,d-1))
sBounds _ = error "sBounds expected list length 4"
instance Shapable (Int,Int,Int,Int,Int) where
sRank _ = 5
sShape (a,b,c,d,e) (a',b',c',d',e') =
[rangeSize (a,a'), rangeSize (b,b'), rangeSize (c,c'), rangeSize (d,d')
, rangeSize (e,e')]
sBounds [a,b,c,d,e] = ((0,0,0,0,0),(a-1,b-1,c-1,d-1,e-1))
sBounds _ = error "sBounds expected list length 5"
instance Shapable (Int,Int,Int,Int,Int,Int) where
sRank _ = 6
sShape (a,b,c,d,e,f) (a',b',c',d',e',f') =
[rangeSize (a,a'), rangeSize (b,b'), rangeSize (c,c'), rangeSize (d,d')
, rangeSize (e,e'), rangeSize (f,f')]
sBounds [a,b,c,d,e,f] = ((0,0,0,0,0,0),(a-1,b-1,c-1,d-1,e-1,f-1))
sBounds _ = error "sBounds expected list length 6"
instance Shapable (Int,Int,Int,Int,Int,Int,Int) where
sRank _ = 7
sShape (a,b,c,d,e,f,g) (a',b',c',d',e',f',g') =
[rangeSize (a,a'), rangeSize (b,b'), rangeSize (c,c'), rangeSize (d,d')
, rangeSize (e,e'), rangeSize (f,f'), rangeSize (g,g')]
sBounds [a,b,c,d,e,f,g] = ((0,0,0,0,0,0,0),(a-1,b-1,c-1,d-1,e-1,f-1,g-1))
sBounds _ = error "sBounds expected list length 7"
instance Shapable (Int,Int,Int,Int,Int,Int,Int,Int) where
sRank _ = 8
sShape (a,b,c,d,e,f,g,h) (a',b',c',d',e',f',g',h') =
[rangeSize (a,a'), rangeSize (b,b'), rangeSize (c,c'), rangeSize (d,d')
, rangeSize (e,e'), rangeSize (f,f'), rangeSize (g,g'), rangeSize (h,h')]
sBounds [a,b,c,d,e,f,g,h] = ((0,0,0,0,0,0,0,0),(a-1,b-1,c-1,d-1,e-1,f-1,g-1,h-1))
sBounds _ = error "sBounds expected list length 8"
instance Shapable (Int,Int,Int,Int,Int,Int,Int,Int,Int) where
sRank _ = 9
sShape (a,b,c,d,e,f,g,h,i) (a',b',c',d',e',f',g',h',i') =
[rangeSize (a,a'), rangeSize (b,b'), rangeSize (c,c'), rangeSize (d,d')
, rangeSize (e,e'), rangeSize (f,f'), rangeSize (g,g'), rangeSize (h,h')
, rangeSize (i,i')]
sBounds [a,b,c,d,e,f,g,h,i] = ((0,0,0,0,0,0,0,0,0)
,(a-1,b-1,c-1,d-1,e-1,f-1,g-1,h-1,i-1))
sBounds _ = error "sBounds expected list length 9"