2 % (c) The AQUA Project, Glasgow University, 1994-1999
5 \section[Ix]{Module @Ix@}
8 {-# OPTIONS -fno-implicit-prelude #-}
13 ( range -- :: (Ix a) => (a,a) -> [a]
14 , index -- :: (Ix a) => (a,a) -> a -> Int
15 , inRange -- :: (Ix a) => (a,a) -> a -> Bool
17 , rangeSize -- :: (Ix a) => (a,a) -> Int
26 -- (Ix a, Ix b) => Ix (a, b)
29 -- Implementation checked wrt. Haskell 98 lib report, 1/99.
32 import {-# SOURCE #-} PrelErr ( error )
35 import PrelList( null )
41 %*********************************************************
43 \subsection{The @Ix@ class}
45 %*********************************************************
48 class (Ord a) => Ix a where
50 index, unsafeIndex :: (a,a) -> a -> Int
51 inRange :: (a,a) -> a -> Bool
53 -- Must specify one of index, unsafeIndex
54 index b i | inRange b i = unsafeIndex b i
55 | otherwise = error "Error in array index"
56 unsafeIndex b i = index b i
59 %*********************************************************
61 \subsection{Instances of @Ix@}
63 %*********************************************************
66 -- abstract these errors from the relevant index functions so that
67 -- the guts of the function will be small enough to inline.
69 {-# NOINLINE indexError #-}
70 indexError :: Show a => (a,a) -> a -> String -> b
72 = error (showString "Ix{" . showString tp . showString "}.index: Index " .
73 showParen True (showsPrec 0 i) .
74 showString " out of range " $
75 showParen True (showsPrec 0 rng) "")
77 ----------------------------------------------------------------------
78 instance Ix Char where
83 unsafeIndex (m,n) i = fromEnum i - fromEnum m
85 index b i | inRange b i = unsafeIndex b i
86 | otherwise = indexError b i "Char"
88 inRange (m,n) i = m <= i && i <= n
90 ----------------------------------------------------------------------
96 unsafeIndex (m,n) i = i - m
98 index b i | inRange b i = unsafeIndex b i
99 | otherwise = indexError b i "Int"
101 inRange (m,n) i = m <= i && i <= n
104 ----------------------------------------------------------------------
105 instance Ix Integer where
110 unsafeIndex (m,n) i = fromInteger (i - m)
112 index b i | inRange b i = unsafeIndex b i
113 | otherwise = indexError b i "Integer"
115 inRange (m,n) i = m <= i && i <= n
118 ----------------------------------------------------------------------
119 instance Ix Bool where -- as derived
121 | l <= u = map toEnum [fromEnum l .. fromEnum u]
124 unsafeIndex (l,_) i = fromEnum i - fromEnum l
126 index b i | inRange b i = unsafeIndex b i
127 | otherwise = indexError b i "Bool"
129 inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
131 ----------------------------------------------------------------------
132 instance Ix Ordering where -- as derived
134 | l <= u = map toEnum [fromEnum l .. fromEnum u]
136 unsafeIndex (l,_) i = fromEnum i - fromEnum l
137 index b i | inRange b i = unsafeIndex b i
138 | otherwise = indexError b i "Ordering"
139 inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
141 ----------------------------------------------------------------------
144 range ((), ()) = [()]
145 {-# INLINE unsafeIndex #-}
146 unsafeIndex ((), ()) () = 0
147 {-# INLINE inRange #-}
148 inRange ((), ()) () = True
150 index b i = unsafeIndex b i
153 ----------------------------------------------------------------------
154 instance (Ix a, Ix b) => Ix (a, b) where -- as derived
155 {-# SPECIALISE instance Ix (Int,Int) #-}
158 range ((l1,l2),(u1,u2)) =
159 [ (i1,i2) | i1 <- range (l1,u1), i2 <- range (l2,u2) ]
161 {- INLINE unsafeIndex #-}
162 unsafeIndex ((l1,l2),(u1,u2)) (i1,i2) =
163 unsafeIndex (l1,u1) i1 * unsafeRangeSize (l2,u2) + unsafeIndex (l2,u2) i2
165 {- INLINE inRange #-}
166 inRange ((l1,l2),(u1,u2)) (i1,i2) =
167 inRange (l1,u1) i1 && inRange (l2,u2) i2
169 -- Default method for index
171 ----------------------------------------------------------------------
172 instance (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3) where
173 {-# SPECIALISE instance Ix (Int,Int,Int) #-}
175 range ((l1,l2,l3),(u1,u2,u3)) =
176 [(i1,i2,i3) | i1 <- range (l1,u1),
180 unsafeIndex ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
181 unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
182 unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
183 unsafeIndex (l1,u1) i1))
185 inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
186 inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
189 -- Default method for index
191 ----------------------------------------------------------------------
192 instance (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4) where
193 range ((l1,l2,l3,l4),(u1,u2,u3,u4)) =
194 [(i1,i2,i3,i4) | i1 <- range (l1,u1),
199 unsafeIndex ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
200 unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
201 unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
202 unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
203 unsafeIndex (l1,u1) i1)))
205 inRange ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
206 inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
207 inRange (l3,u3) i3 && inRange (l4,u4) i4
209 -- Default method for index
211 instance (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5) where
212 range ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) =
213 [(i1,i2,i3,i4,i5) | i1 <- range (l1,u1),
219 unsafeIndex ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
220 unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (
221 unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
222 unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
223 unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
224 unsafeIndex (l1,u1) i1))))
226 inRange ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
227 inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
228 inRange (l3,u3) i3 && inRange (l4,u4) i4 &&
231 -- Default method for index
234 %********************************************************
236 \subsection{Size of @Ix@ interval}
238 %********************************************************
240 The @rangeSize@ operator returns the number of elements
241 in the range for an @Ix@ pair.
244 {-# SPECIALISE unsafeRangeSize :: (Int,Int) -> Int #-}
245 {-# SPECIALISE unsafeRangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
246 unsafeRangeSize :: (Ix a) => (a,a) -> Int
247 unsafeRangeSize b@(l,h) = unsafeIndex b h + 1
249 {-# SPECIALISE rangeSize :: (Int,Int) -> Int #-}
250 {-# SPECIALISE rangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
251 rangeSize :: (Ix a) => (a,a) -> Int
252 rangeSize b@(l,h) | inRange b h = unsafeIndex b h + 1
255 -- Note that the following is NOT right
256 -- rangeSize (l,h) | l <= h = index b h + 1
259 -- Because it might be the case that l<h, but the range
260 -- is nevertheless empty. Consider
262 -- Here l<h, but the second index ranges from 2..1 and