{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}
{-# OPTIONS_HADDOCK not-home #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  GHC.Ix
-- Copyright   :  (c) The University of Glasgow, 1994-2000
-- License     :  see libraries/base/LICENSE
--
-- Maintainer  :  [email protected]
-- Stability   :  internal
-- Portability :  non-portable (GHC extensions)
--
-- GHC\'s Ix typeclass implementation.
--
-----------------------------------------------------------------------------

module GHC.Ix (
        Ix(..)
    ) where

import GHC.Enum
import GHC.Num
import GHC.Base
import GHC.Real( fromIntegral )
import GHC.Show

-- | The 'Ix' class is used to map a contiguous subrange of values in
-- a type onto integers.  It is used primarily for array indexing
-- (see the array package).
--
-- The first argument @(l,u)@ of each of these operations is a pair
-- specifying the lower and upper bounds of a contiguous subrange of values.
--
-- An implementation is entitled to assume the following laws about these
-- operations:
--
-- * @'inRange' (l,u) i == 'elem' i ('range' (l,u))@ @ @
--
-- * @'range' (l,u) '!!' 'index' (l,u) i == i@, when @'inRange' (l,u) i@
--
-- * @'map' ('index' (l,u)) ('range' (l,u))) == [0..'rangeSize' (l,u)-1]@ @ @
--
-- * @'rangeSize' (l,u) == 'length' ('range' (l,u))@ @ @
--
class (Ord a) => Ix a where
    {-# MINIMAL range, (index | unsafeIndex), inRange #-}

    -- | The list of values in the subrange defined by a bounding pair.
    range               :: (a,a) -> [a]
    -- | The position of a subscript in the subrange.
    index               :: (a,a) -> a -> Int
    -- | Like 'index', but without checking that the value is in range.
    unsafeIndex         :: (a,a) -> a -> Int
    -- | Returns 'True' the given subscript lies in the range defined
    -- the bounding pair.
    inRange             :: (a,a) -> a -> Bool
    -- | The size of the subrange defined by a bounding pair.
    rangeSize           :: (a,a) -> Int
    -- | like 'rangeSize', but without checking that the upper bound is
    -- in range.
    unsafeRangeSize     :: (a,a) -> Int

        -- Must specify one of index, unsafeIndex

        -- 'index' is typically over-ridden in instances, with essentially
        -- the same code, but using indexError instead of hopelessIndexError
        -- Reason: we have 'Show' at the instances
    {-# INLINE index #-}  -- See Note [Inlining index]
    index (a, a)
b a
i | (a, a) -> a -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a, a)
b a
i = (a, a) -> a -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a, a)
b a
i
              | Bool
otherwise   = Int
hopelessIndexError

    unsafeIndex (a, a)
b a
i = (a, a) -> a -> Int
forall a. Ix a => (a, a) -> a -> Int
index (a, a)
b a
i

    rangeSize b :: (a, a)
b@(a
_l,a
h) | (a, a) -> a -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a, a)
b a
h = (a, a) -> a -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a, a)
b a
h Int -> Int -> Int
forall a. Num a => a -> a -> a
  Int
1
                       | Bool
otherwise   = Int
0        -- This case is only here to
                                                -- check for an empty range
        -- NB: replacing (inRange b h) by (l <= h) fails for
        --     tuples.  E.g.  (1,2) <= (2,1) but the range is empty

    unsafeRangeSize b :: (a, a)
b@(a
_l,a
h) = (a, a) -> a -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a, a)
b a
h Int -> Int -> Int
forall a. Num a => a -> a -> a
  Int
1

{-
Note that the following is NOT right
        rangeSize (l,h) | l <= h    = index b h   1
                        | otherwise = 0

Because it might be the case that l<h, but the range
is nevertheless empty.  Consider
        ((1,2),(2,1))
Here l<h, but the second index ranges from 2..1 and
hence is empty


Note [Inlining index]
~~~~~~~~~~~~~~~~~~~~~
We inline the 'index' operation,

 * Partly because it generates much faster code
   (although bigger); see #1216

 * Partly because it exposes the bounds checks to the simplifier which
   might help a big.

If you make a per-instance index method, you may consider inlining it.

Note [Double bounds-checking of index values]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When you index an array, a!x, there are two possible bounds checks we might make:

  (A) Check that (inRange (bounds a) x) holds.

      (A) is checked in the method for 'index'

  (B) Check that (index (bounds a) x) lies in the range 0..n,
      where n is the size of the underlying array

      (B) is checked in the top-level function (!), in safeIndex.

Of course it *should* be the case that (A) holds iff (B) holds, but that
is a property of the particular instances of index, bounds, and inRange,
so GHC cannot guarantee it.

 * If you do (A) and not (B), then you might get a seg-fault,
   by indexing at some bizarre location.  #1610

 * If you do (B) but not (A), you may get no complaint when you index
   an array out of its semantic bounds.  #2120

At various times we have had (A) and not (B), or (B) and not (A); both
led to complaints.  So now we implement *both* checks (#2669).

For 1-d, 2-d, and 3-d arrays of Int we have specialised instances to avoid this.

Note [Out-of-bounds error messages]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The default method for 'index' generates hoplelessIndexError, because
Ix doesn't have Show as a superclass.  For particular base types we
can do better, so we override the default method for index.
-}

-- Abstract these errors from the relevant index functions so that
-- the guts of the function will be small enough to inline.

{-# NOINLINE indexError #-}
indexError :: Show a => (a,a) -> a -> String -> b
indexError :: (a, a) -> a -> String -> b
indexError (a, a)
rng a
i String
tp
  = String -> b
forall a. String -> a
errorWithoutStackTrace (String -> ShowS
showString String
"Ix{" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
tp ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"}.index: Index " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
           Bool -> ShowS -> ShowS
showParen Bool
True (Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
0 a
i) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
           String -> ShowS
showString String
" out of range " ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
           Bool -> ShowS -> ShowS
showParen Bool
True (Int -> (a, a) -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
0 (a, a)
rng) String
"")

hopelessIndexError :: Int -- Try to use 'indexError' instead!
hopelessIndexError :: Int
hopelessIndexError = String -> Int
forall a. String -> a
errorWithoutStackTrace String
"Error in array index"

----------------------------------------------------------------------
-- | @since 2.01
instance  Ix Char  where
    {-# INLINE range #-}
    range :: (Char, Char) -> String
range (Char
m,Char
n) = [Char
m..Char
n]

    {-# INLINE unsafeIndex #-}
    unsafeIndex :: (Char, Char) -> Char -> Int
unsafeIndex (Char
m,Char
_n) Char
i = Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
m

    {-# INLINE index #-}  -- See Note [Out-of-bounds error messages]
                          -- and Note [Inlining index]
    index :: (Char, Char) -> Char -> Int
index (Char, Char)
b Char
i | (Char, Char) -> Char -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Char, Char)
b Char
i =  (Char, Char) -> Char -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (Char, Char)
b Char
i
              | Bool
otherwise   =  (Char, Char) -> Char -> String -> Int
forall a b. Show a => (a, a) -> a -> String -> b
indexError (Char, Char)
b Char
i String
"Char"

    inRange :: (Char, Char) -> Char -> Bool
inRange (Char
m,Char
n) Char
i     =  Char
m Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
i Bool -> Bool -> Bool
&& Char
i Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
n

----------------------------------------------------------------------
-- | @since 2.01
instance  Ix Int  where
    {-# INLINE range #-}
        -- The INLINE stops the build in the RHS from getting inlined,
        -- so that callers can fuse with the result of range
    range :: (Int, Int) -> [Int]
range (Int
m,Int
n) = [Int
m..Int
n]

    {-# INLINE unsafeIndex #-}
    unsafeIndex :: (Int, Int) -> Int -> Int
unsafeIndex (Int
m,Int
_n) Int
i = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
m

    {-# INLINE index #-}  -- See Note [Out-of-bounds error messages]
                          -- and Note [Inlining index]
    index :: (Int, Int) -> Int -> Int
index (Int, Int)
b Int
i | (Int, Int) -> Int -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Int, Int)
b Int
i =  (Int, Int) -> Int -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (Int, Int)
b Int
i
              | Bool
otherwise   =  (Int, Int) -> Int -> String -> Int
forall a b. Show a => (a, a) -> a -> String -> b
indexError (Int, Int)
b Int
i String
"Int"

    {-# INLINE inRange #-}
    inRange :: (Int, Int) -> Int -> Bool
inRange (I# Int#
m,I# Int#
n) (I# Int#
i) =  Int# -> Bool
isTrue# (Int#
m Int# -> Int# -> Int#
<=# Int#
i) Bool -> Bool -> Bool
&& Int# -> Bool
isTrue# (Int#
i Int# -> Int# -> Int#
<=# Int#
n)

-- | @since 4.6.0.0
instance Ix Word where
    range :: (Word, Word) -> [Word]
range (Word
m,Word
n)         = [Word
m..Word
n]
    unsafeIndex :: (Word, Word) -> Word -> Int
unsafeIndex (Word
m,Word
_) Word
i = Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word
i Word -> Word -> Word
forall a. Num a => a -> a -> a
- Word
m)
    inRange :: (Word, Word) -> Word -> Bool
inRange (Word
m,Word
n) Word
i     = Word
m Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Word
i Bool -> Bool -> Bool
&& Word
i Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Word
n

----------------------------------------------------------------------
-- | @since 2.01
instance  Ix Integer  where
    {-# INLINE range #-}
    range :: (Integer, Integer) -> [Integer]
range (Integer
m,Integer
n) = [Integer
m..Integer
n]

    {-# INLINE unsafeIndex #-}
    unsafeIndex :: (Integer, Integer) -> Integer -> Int
unsafeIndex (Integer
m,Integer
_n) Integer
i   = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
m)

    {-# INLINE index #-}  -- See Note [Out-of-bounds error messages]
                          -- and Note [Inlining index]
    index :: (Integer, Integer) -> Integer -> Int
index (Integer, Integer)
b Integer
i | (Integer, Integer) -> Integer -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Integer, Integer)
b Integer
i =  (Integer, Integer) -> Integer -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (Integer, Integer)
b Integer
i
              | Bool
otherwise   =  (Integer, Integer) -> Integer -> String -> Int
forall a b. Show a => (a, a) -> a -> String -> b
indexError (Integer, Integer)
b Integer
i String
"Integer"

    inRange :: (Integer, Integer) -> Integer -> Bool
inRange (Integer
m,Integer
n) Integer
i     =  Integer
m Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
i Bool -> Bool -> Bool
&& Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
n

----------------------------------------------------------------------
-- | @since 4.8.0.0
instance Ix Natural where
    range :: (Natural, Natural) -> [Natural]
range (Natural
m,Natural
n) = [Natural
m..Natural
n]
    inRange :: (Natural, Natural) -> Natural -> Bool
inRange (Natural
m,Natural
n) Natural
i = Natural
m Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
<= Natural
i Bool -> Bool -> Bool
&& Natural
i Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
<= Natural
n
    unsafeIndex :: (Natural, Natural) -> Natural -> Int
unsafeIndex (Natural
m,Natural
_) Natural
i = Natural -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Natural
iNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
-Natural
m)
    index :: (Natural, Natural) -> Natural -> Int
index (Natural, Natural)
b Natural
i | (Natural, Natural) -> Natural -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Natural, Natural)
b Natural
i = (Natural, Natural) -> Natural -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (Natural, Natural)
b Natural
i
              | Bool
otherwise   = (Natural, Natural) -> Natural -> String -> Int
forall a b. Show a => (a, a) -> a -> String -> b
indexError (Natural, Natural)
b Natural
i String
"Natural"

----------------------------------------------------------------------
-- | @since 2.01
instance Ix Bool where -- as derived
    {-# INLINE range #-}
    range :: (Bool, Bool) -> [Bool]
range (Bool
m,Bool
n) = [Bool
m..Bool
n]

    {-# INLINE unsafeIndex #-}
    unsafeIndex :: (Bool, Bool) -> Bool -> Int
unsafeIndex (Bool
l,Bool
_) Bool
i = Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
l

    {-# INLINE index #-}  -- See Note [Out-of-bounds error messages]
                          -- and Note [Inlining index]
    index :: (Bool, Bool) -> Bool -> Int
index (Bool, Bool)
b Bool
i | (Bool, Bool) -> Bool -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Bool, Bool)
b Bool
i =  (Bool, Bool) -> Bool -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (Bool, Bool)
b Bool
i
              | Bool
otherwise   =  (Bool, Bool) -> Bool -> String -> Int
forall a b. Show a => (a, a) -> a -> String -> b
indexError (Bool, Bool)
b Bool
i String
"Bool"

    inRange :: (Bool, Bool) -> Bool -> Bool
inRange (Bool
l,Bool
u) Bool
i = Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
l Bool -> Bool -> Bool
&& Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
u

----------------------------------------------------------------------
-- | @since 2.01
instance Ix Ordering where -- as derived
    {-# INLINE range #-}
    range :: (Ordering, Ordering) -> [Ordering]
range (Ordering
m,Ordering
n) = [Ordering
m..Ordering
n]

    {-# INLINE unsafeIndex #-}
    unsafeIndex :: (Ordering, Ordering) -> Ordering -> Int
unsafeIndex (Ordering
l,Ordering
_) Ordering
i = Ordering -> Int
forall a. Enum a => a -> Int
fromEnum Ordering
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Ordering -> Int
forall a. Enum a => a -> Int
fromEnum Ordering
l

    {-# INLINE index #-}  -- See Note [Out-of-bounds error messages]
                          -- and Note [Inlining index]
    index :: (Ordering, Ordering) -> Ordering -> Int
index (Ordering, Ordering)
b Ordering
i | (Ordering, Ordering) -> Ordering -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Ordering, Ordering)
b Ordering
i =  (Ordering, Ordering) -> Ordering -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (Ordering, Ordering)
b Ordering
i
              | Bool
otherwise   =  (Ordering, Ordering) -> Ordering -> String -> Int
forall a b. Show a => (a, a) -> a -> String -> b
indexError (Ordering, Ordering)
b Ordering
i String
"Ordering"

    inRange :: (Ordering, Ordering) -> Ordering -> Bool
inRange (Ordering
l,Ordering
u) Ordering
i = Ordering -> Int
forall a. Enum a => a -> Int
fromEnum Ordering
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Ordering -> Int
forall a. Enum a => a -> Int
fromEnum Ordering
l Bool -> Bool -> Bool
&& Ordering -> Int
forall a. Enum a => a -> Int
fromEnum Ordering
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Ordering -> Int
forall a. Enum a => a -> Int
fromEnum Ordering
u

----------------------------------------------------------------------
-- | @since 2.01
instance Ix () where
    {-# INLINE range #-}
    range :: ((), ()) -> [()]
range   ((), ())    = [()]
    {-# INLINE unsafeIndex #-}
    unsafeIndex :: ((), ()) -> () -> Int
unsafeIndex   ((), ()) () = Int
0
    {-# INLINE inRange #-}
    inRange :: ((), ()) -> () -> Bool
inRange ((), ()) () = Bool
True

    {-# INLINE index #-}  -- See Note [Inlining index]
    index :: ((), ()) -> () -> Int
index ((), ())
b ()
i = ((), ()) -> () -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex ((), ())
b ()
i

----------------------------------------------------------------------
-- | @since 2.01
instance (Ix a, Ix b) => Ix (a, b) where -- as derived
    {-# SPECIALISE instance Ix (Int,Int) #-}

    {-# INLINE range #-}
    range :: ((a, b), (a, b)) -> [(a, b)]
range ((a
l1,b
l2),(a
u1,b
u2)) =
      [ (a
i1,b
i2) | a
i1 <- (a, a) -> [a]
forall a. Ix a => (a, a) -> [a]
range (a
l1,a
u1), b
i2 <- (b, b) -> [b]
forall a. Ix a => (a, a) -> [a]
range (b
l2,b
u2) ]

    {-# INLINE unsafeIndex #-}
    unsafeIndex :: ((a, b), (a, b)) -> (a, b) -> Int
unsafeIndex ((a
l1,b
l2),(a
u1,b
u2)) (a
i1,b
i2) =
      (a, a) -> a -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a
l1,a
u1) a
i1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (b, b) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (b
l2,b
u2) Int -> Int -> Int
forall a. Num a => a -> a -> a
  (b, b) -> b -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (b
l2,b
u2) b
i2

    {-# INLINE inRange #-}
    inRange :: ((a, b), (a, b)) -> (a, b) -> Bool
inRange ((a
l1,b
l2),(a
u1,b
u2)) (a
i1,b
i2) =
      (a, a) -> a -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a
l1,a
u1) a
i1 Bool -> Bool -> Bool
&& (b, b) -> b -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (b
l2,b
u2) b
i2

    -- Default method for index

----------------------------------------------------------------------
-- | @since 2.01
instance  (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3)  where
    {-# SPECIALISE instance Ix (Int,Int,Int) #-}

    range :: ((a1, a2, a3), (a1, a2, a3)) -> [(a1, a2, a3)]
range ((a1
l1,a2
l2,a3
l3),(a1
u1,a2
u2,a3
u3)) =
        [(a1
i1,a2
i2,a3
i3) | a1
i1 <- (a1, a1) -> [a1]
forall a. Ix a => (a, a) -> [a]
range (a1
l1,a1
u1),
                      a2
i2 <- (a2, a2) -> [a2]
forall a. Ix a => (a, a) -> [a]
range (a2
l2,a2
u2),
                      a3
i3 <- (a3, a3) -> [a3]
forall a. Ix a => (a, a) -> [a]
range (a3
l3,a3
u3)]

    unsafeIndex :: ((a1, a2, a3), (a1, a2, a3)) -> (a1, a2, a3) -> Int
unsafeIndex ((a1
l1,a2
l2,a3
l3),(a1
u1,a2
u2,a3
u3)) (a1
i1,a2
i2,a3
i3) =
      (a3, a3) -> a3 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a3
l3,a3
u3) a3
i3 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a3, a3) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a3
l3,a3
u3) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a2, a2) -> a2 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a2
l2,a2
u2) a2
i2 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a2, a2) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a2
l2,a2
u2) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a1, a1) -> a1 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a1
l1,a1
u1) a1
i1))

    inRange :: ((a1, a2, a3), (a1, a2, a3)) -> (a1, a2, a3) -> Bool
inRange ((a1
l1,a2
l2,a3
l3),(a1
u1,a2
u2,a3
u3)) (a1
i1,a2
i2,a3
i3) =
      (a1, a1) -> a1 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a1
l1,a1
u1) a1
i1 Bool -> Bool -> Bool
&& (a2, a2) -> a2 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a2
l2,a2
u2) a2
i2 Bool -> Bool -> Bool
&&
      (a3, a3) -> a3 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a3
l3,a3
u3) a3
i3

    -- Default method for index

----------------------------------------------------------------------
-- | @since 2.01
instance  (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4)  where
    range :: ((a1, a2, a3, a4), (a1, a2, a3, a4)) -> [(a1, a2, a3, a4)]
range ((a1
l1,a2
l2,a3
l3,a4
l4),(a1
u1,a2
u2,a3
u3,a4
u4)) =
      [(a1
i1,a2
i2,a3
i3,a4
i4) | a1
i1 <- (a1, a1) -> [a1]
forall a. Ix a => (a, a) -> [a]
range (a1
l1,a1
u1),
                       a2
i2 <- (a2, a2) -> [a2]
forall a. Ix a => (a, a) -> [a]
range (a2
l2,a2
u2),
                       a3
i3 <- (a3, a3) -> [a3]
forall a. Ix a => (a, a) -> [a]
range (a3
l3,a3
u3),
                       a4
i4 <- (a4, a4) -> [a4]
forall a. Ix a => (a, a) -> [a]
range (a4
l4,a4
u4)]

    unsafeIndex :: ((a1, a2, a3, a4), (a1, a2, a3, a4)) -> (a1, a2, a3, a4) -> Int
unsafeIndex ((a1
l1,a2
l2,a3
l3,a4
l4),(a1
u1,a2
u2,a3
u3,a4
u4)) (a1
i1,a2
i2,a3
i3,a4
i4) =
      (a4, a4) -> a4 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a4
l4,a4
u4) a4
i4 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a4, a4) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a4
l4,a4
u4) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a3, a3) -> a3 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a3
l3,a3
u3) a3
i3 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a3, a3) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a3
l3,a3
u3) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a2, a2) -> a2 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a2
l2,a2
u2) a2
i2 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a2, a2) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a2
l2,a2
u2) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a1, a1) -> a1 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a1
l1,a1
u1) a1
i1)))

    inRange :: ((a1, a2, a3, a4), (a1, a2, a3, a4)) -> (a1, a2, a3, a4) -> Bool
inRange ((a1
l1,a2
l2,a3
l3,a4
l4),(a1
u1,a2
u2,a3
u3,a4
u4)) (a1
i1,a2
i2,a3
i3,a4
i4) =
      (a1, a1) -> a1 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a1
l1,a1
u1) a1
i1 Bool -> Bool -> Bool
&& (a2, a2) -> a2 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a2
l2,a2
u2) a2
i2 Bool -> Bool -> Bool
&&
      (a3, a3) -> a3 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a3
l3,a3
u3) a3
i3 Bool -> Bool -> Bool
&& (a4, a4) -> a4 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a4
l4,a4
u4) a4
i4

    -- Default method for index
-- | @since 2.01
instance  (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5)  where
    range :: ((a1, a2, a3, a4, a5), (a1, a2, a3, a4, a5))
-> [(a1, a2, a3, a4, a5)]
range ((a1
l1,a2
l2,a3
l3,a4
l4,a5
l5),(a1
u1,a2
u2,a3
u3,a4
u4,a5
u5)) =
      [(a1
i1,a2
i2,a3
i3,a4
i4,a5
i5) | a1
i1 <- (a1, a1) -> [a1]
forall a. Ix a => (a, a) -> [a]
range (a1
l1,a1
u1),
                          a2
i2 <- (a2, a2) -> [a2]
forall a. Ix a => (a, a) -> [a]
range (a2
l2,a2
u2),
                          a3
i3 <- (a3, a3) -> [a3]
forall a. Ix a => (a, a) -> [a]
range (a3
l3,a3
u3),
                          a4
i4 <- (a4, a4) -> [a4]
forall a. Ix a => (a, a) -> [a]
range (a4
l4,a4
u4),
                          a5
i5 <- (a5, a5) -> [a5]
forall a. Ix a => (a, a) -> [a]
range (a5
l5,a5
u5)]

    unsafeIndex :: ((a1, a2, a3, a4, a5), (a1, a2, a3, a4, a5))
-> (a1, a2, a3, a4, a5) -> Int
unsafeIndex ((a1
l1,a2
l2,a3
l3,a4
l4,a5
l5),(a1
u1,a2
u2,a3
u3,a4
u4,a5
u5)) (a1
i1,a2
i2,a3
i3,a4
i4,a5
i5) =
      (a5, a5) -> a5 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a5
l5,a5
u5) a5
i5 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a5, a5) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a5
l5,a5
u5) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a4, a4) -> a4 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a4
l4,a4
u4) a4
i4 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a4, a4) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a4
l4,a4
u4) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a3, a3) -> a3 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a3
l3,a3
u3) a3
i3 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a3, a3) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a3
l3,a3
u3) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a2, a2) -> a2 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a2
l2,a2
u2) a2
i2 Int -> Int -> Int
forall a. Num a => a -> a -> a
  (a2, a2) -> Int
forall a. Ix a => (a, a) -> Int
unsafeRangeSize (a2
l2,a2
u2) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (
      (a1, a1) -> a1 -> Int
forall a. Ix a => (a, a) -> a -> Int
unsafeIndex (a1
l1,a1
u1) a1
i1))))

    inRange :: ((a1, a2, a3, a4, a5), (a1, a2, a3, a4, a5))
-> (a1, a2, a3, a4, a5) -> Bool
inRange ((a1
l1,a2
l2,a3
l3,a4
l4,a5
l5),(a1
u1,a2
u2,a3
u3,a4
u4,a5
u5)) (a1
i1,a2
i2,a3
i3,a4
i4,a5
i5) =
      (a1, a1) -> a1 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a1
l1,a1
u1) a1
i1 Bool -> Bool -> Bool
&& (a2, a2) -> a2 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a2
l2,a2
u2) a2
i2 Bool -> Bool -> Bool
&&
      (a3, a3) -> a3 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a3
l3,a3
u3) a3
i3 Bool -> Bool -> Bool
&& (a4, a4) -> a4 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a4
l4,a4
u4) a4
i4 Bool -> Bool -> Bool
&&
      (a5, a5) -> a5 -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a5
l5,a5
u5) a5
i5

    -- Default method for index