[project @ 1999-01-14 18:12:47 by sof]
[ghc-hetmet.git] / ghc / lib / std / Ix.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1999
3 %
4
5 \section[Ix]{Module @Ix@}
6
7 \begin{code}
8 {-# OPTIONS -fno-implicit-prelude #-}
9
10 module Ix 
11     (
12         Ix
13           ( range       -- :: (Ix a) => (a,a) -> [a]
14           , index       -- :: (Ix a) => (a,a) -> a   -> Int
15           , inRange     -- :: (Ix a) => (a,a) -> a   -> Bool
16           )
17     ,   rangeSize       -- :: (Ix a) => (a,a) -> Int
18     -- Ix instances:
19     --
20     --  Ix Char
21     --  Ix Int
22     --  Ix Integer
23     --  Ix Bool
24     --  Ix Ordering
25     --  Ix ()
26     --  (Ix a, Ix b) => Ix (a, b)
27     --  ...
28
29     -- Implementation checked wrt. Haskell 98 lib report, 1/99.
30     ) where
31
32 import {-# SOURCE #-} PrelErr ( error )
33 import PrelTup
34 import PrelBase
35 \end{code}
36
37 %*********************************************************
38 %*                                                      *
39 \subsection{The @Ix@ class}
40 %*                                                      *
41 %*********************************************************
42
43 \begin{code}
44 class  ({-Show a,-} Ord a) => Ix a  where
45     range               :: (a,a) -> [a]
46     index               :: (a,a) -> a -> Int
47     inRange             :: (a,a) -> a -> Bool
48 \end{code}
49
50
51 %*********************************************************
52 %*                                                      *
53 \subsection{Instances of @Ix@}
54 %*                                                      *
55 %*********************************************************
56
57 \begin{code}
58 instance  Ix Char  where
59     range (c,c')        =  [c..c']
60     index b@(c,_) ci
61         | inRange b ci  =  fromEnum ci - fromEnum c
62         | otherwise     =  indexError ci b "Char"
63     inRange (m,n) i     =  m <= i && i <= n
64
65 instance  Ix Int  where
66     range (m,n)         =  [m..n]
67     index b@(m,_) i
68         | inRange b i   =  i - m
69         | otherwise     =  indexError i b "Int"
70     inRange (m,n) i     =  m <= i && i <= n
71
72 -- abstract these errors from the relevant index functions so that
73 -- the guts of the function will be small enough to inline.
74
75 {-# NOINLINE indexError #-}
76 indexError :: Show a => a -> (a,a) -> String -> b
77 indexError i rng tp
78   = error (showString "Ix{" . showString tp . showString "}.index: Index " .
79            showParen True (showsPrec 0 i) .
80            showString " out of range " $
81            showParen True (showsPrec 0 rng) "")
82
83 -- Integer instance is in PrelNum
84
85 ----------------------------------------------------------------------
86 instance Ix Bool where -- as derived
87     range   (l,u)   = map toEnum [fromEnum l .. fromEnum u]
88     index   (l,_) i = fromEnum i - fromEnum l
89     inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
90
91 ----------------------------------------------------------------------
92 instance Ix Ordering where -- as derived
93     range   (l,u)   = map toEnum [fromEnum l .. fromEnum u]
94     index   (l,_) i = fromEnum i - fromEnum l
95     inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
96
97 ----------------------------------------------------------------------
98 instance Ix () where
99     {-# INLINE range #-}
100     range   ((), ())    = [()]
101     {-# INLINE index #-}
102     index   ((), ()) () = 0
103     {-# INLINE inRange #-}
104     inRange ((), ()) () = True
105
106 ----------------------------------------------------------------------
107 instance (Ix a, Ix b) => Ix (a, b) where -- as derived
108     {- INLINE range #-}
109     range ((l1,l2),(u1,u2)) =
110       [ (i1,i2) | i1 <- range (l1,u1), i2 <- range (l2,u2) ]
111
112     {- INLINE index #-}
113     index ((l1,l2),(u1,u2)) (i1,i2) =
114       index (l1,u1) i1 * rangeSize (l2,u2) + index (l2,u2) i2
115
116     {- INLINE inRange #-}
117     inRange ((l1,l2),(u1,u2)) (i1,i2) =
118       inRange (l1,u1) i1 && inRange (l2,u2) i2
119
120 instance  (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3)  where
121     range ((l1,l2,l3),(u1,u2,u3)) =
122         [(i1,i2,i3) | i1 <- range (l1,u1),
123                       i2 <- range (l2,u2),
124                       i3 <- range (l3,u3)]
125
126     index ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
127       index (l3,u3) i3 + rangeSize (l3,u3) * (
128       index (l2,u2) i2 + rangeSize (l2,u2) * (
129       index (l1,u1) i1))
130
131     inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
132       inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
133       inRange (l3,u3) i3
134
135 instance  (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4)  where
136     range ((l1,l2,l3,l4),(u1,u2,u3,u4)) =
137       [(i1,i2,i3,i4) | i1 <- range (l1,u1),
138                        i2 <- range (l2,u2),
139                        i3 <- range (l3,u3),
140                        i4 <- range (l4,u4)]
141
142     index ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
143       index (l4,u4) i4 + rangeSize (l4,u4) * (
144       index (l3,u3) i3 + rangeSize (l3,u3) * (
145       index (l2,u2) i2 + rangeSize (l2,u2) * (
146       index (l1,u1) i1)))
147
148     inRange ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
149       inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
150       inRange (l3,u3) i3 && inRange (l4,u4) i4
151
152 instance  (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5)  where
153     range ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) =
154       [(i1,i2,i3,i4,i5) | i1 <- range (l1,u1),
155                           i2 <- range (l2,u2),
156                           i3 <- range (l3,u3),
157                           i4 <- range (l4,u4),
158                           i5 <- range (l5,u5)]
159
160     index ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
161       index (l5,u5) i5 + rangeSize (l5,u5) * (
162       index (l4,u4) i4 + rangeSize (l4,u4) * (
163       index (l3,u3) i3 + rangeSize (l3,u3) * (
164       index (l2,u2) i2 + rangeSize (l2,u2) * (
165       index (l1,u1) i1))))
166
167     inRange ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
168       inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
169       inRange (l3,u3) i3 && inRange (l4,u4) i4 && 
170       inRange (l5,u5) i5
171 \end{code}
172
173 %********************************************************
174 %*                                                      *
175 \subsection{Size of @Ix@ interval}
176 %*                                                      *
177 %********************************************************
178
179 The @rangeSize@ operator returns the number of elements
180 in the range for an @Ix@ pair:
181
182 \begin{code}
183 {-# SPECIALISE rangeSize :: (Int,Int) -> Int #-}
184 rangeSize :: (Ix a) => (a,a) -> Int
185 rangeSize b@(l,h)
186  | l > h     = 0
187  | otherwise = index b h + 1
188
189 \end{code}