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