{-# LANGUAGE TypeFamilies #-}

-- | Opinionated zero-based multidimensional index and their boundaries.
module AtCoder.Extra.Ix0 where

type Bounds0 i = i

class Ix0 i where
  -- | Returns the size of the boundary.
  rangeSize0 :: Bounds0 i -> Int

  -- | Returns zero-based index, **without** running boundary check.
  index0 :: Bounds0 i -> i -> Int

  -- | Returns whether an index is contained in a bounds.
  inRange0 :: Bounds0 i -> i -> Bool

instance Ix0 Int where
  {-# INLINE rangeSize0 #-}
  rangeSize0 :: Bounds0 Int -> Bounds0 Int
rangeSize0 Bounds0 Int
d1 = Bounds0 Int
d1
  {-# INLINE index0 #-}
  index0 :: Bounds0 Int -> Bounds0 Int -> Bounds0 Int
index0 Bounds0 Int
_ Bounds0 Int
x1 = Bounds0 Int
x1
  {-# INLINE inRange0 #-}
  inRange0 :: Bounds0 Int -> Bounds0 Int -> Bool
inRange0 Bounds0 Int
d1 Bounds0 Int
x1 = Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x1 Bool -> Bool -> Bool
&& Bounds0 Int
x1 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d1

instance Ix0 (Int, Int) where
  {-# INLINE rangeSize0 #-}
  rangeSize0 :: Bounds0 (Bounds0 Int, Bounds0 Int) -> Bounds0 Int
rangeSize0 (!Bounds0 Int
d2, !Bounds0 Int
d1) = Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1
  {-# INLINE index0 #-}
  index0 :: Bounds0 (Bounds0 Int, Bounds0 Int)
-> Bounds0 (Bounds0 Int, Bounds0 Int) -> Bounds0 Int
index0 (!Bounds0 Int
_, !Bounds0 Int
d1) (!Bounds0 Int
x2, !Bounds0 Int
x1) = Bounds0 Int
x2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x1
  {-# INLINE inRange0 #-}
  inRange0 :: Bounds0 (Bounds0 Int, Bounds0 Int)
-> Bounds0 (Bounds0 Int, Bounds0 Int) -> Bool
inRange0 (!Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x2, !Bounds0 Int
x1) = Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x2 Bool -> Bool -> Bool
&& Bounds0 Int
x2 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d2 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x1 Bool -> Bool -> Bool
&& Bounds0 Int
x1 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d1

instance Ix0 (Int, Int, Int) where
  {-# INLINE rangeSize0 #-}
  rangeSize0 :: Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int) -> Bounds0 Int
rangeSize0 (!Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) = Bounds0 Int
d3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1
  {-# INLINE index0 #-}
  index0 :: Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int) -> Bounds0 Int
index0 (!Bounds0 Int
_, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = (Bounds0 Int
x3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x2) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x1
  {-# INLINE inRange0 #-}
  inRange0 :: Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int) -> Bool
inRange0 (!Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x3 Bool -> Bool -> Bool
&& Bounds0 Int
x3 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d3 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x2 Bool -> Bool -> Bool
&& Bounds0 Int
x2 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d2 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x1 Bool -> Bool -> Bool
&& Bounds0 Int
x1 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d1

instance Ix0 (Int, Int, Int, Int) where
  {-# INLINE rangeSize0 #-}
  rangeSize0 :: Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 Int
rangeSize0 (!Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) = Bounds0 Int
d4 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1
  {-# INLINE index0 #-}
  index0 :: Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 Int
index0 (!Bounds0 Int
_, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x4, !Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = ((Bounds0 Int
x4 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x3) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x2) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x1
  {-# INLINE inRange0 #-}
  inRange0 :: Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bool
inRange0 (!Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x4, !Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x4 Bool -> Bool -> Bool
&& Bounds0 Int
x4 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d4 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x3 Bool -> Bool -> Bool
&& Bounds0 Int
x3 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d3 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x2 Bool -> Bool -> Bool
&& Bounds0 Int
x2 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d2 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x1 Bool -> Bool -> Bool
&& Bounds0 Int
x1 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d1

instance Ix0 (Int, Int, Int, Int, Int) where
  {-# INLINE rangeSize0 #-}
  rangeSize0 :: Bounds0
  (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 Int
rangeSize0 (!Bounds0 Int
d5, !Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) = Bounds0 Int
d5 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d4 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1
  {-# INLINE index0 #-}
  index0 :: Bounds0
  (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0
     (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0 Int
index0 (!Bounds0 Int
_, !Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x5, !Bounds0 Int
x4, !Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = (((Bounds0 Int
x5 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d4 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x4) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x3) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x2) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x1
  {-# INLINE inRange0 #-}
  inRange0 :: Bounds0
  (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bounds0
     (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int)
-> Bool
inRange0 (!Bounds0 Int
d5, !Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x5, !Bounds0 Int
x4, !Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x5 Bool -> Bool -> Bool
&& Bounds0 Int
x5 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d5 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x4 Bool -> Bool -> Bool
&& Bounds0 Int
x4 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d4 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x3 Bool -> Bool -> Bool
&& Bounds0 Int
x3 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d3 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x2 Bool -> Bool -> Bool
&& Bounds0 Int
x2 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d2 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x1 Bool -> Bool -> Bool
&& Bounds0 Int
x1 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d1

instance Ix0 (Int, Int, Int, Int, Int, Int) where
  {-# INLINE rangeSize0 #-}
  rangeSize0 :: Bounds0
  (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int,
   Bounds0 Int)
-> Bounds0 Int
rangeSize0 (!Bounds0 Int
d6, !Bounds0 Int
d5, !Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) = Bounds0 Int
d6 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
d5 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d4 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1
  {-# INLINE index0 #-}
  index0 :: Bounds0
  (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int,
   Bounds0 Int)
-> Bounds0
     (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int,
      Bounds0 Int)
-> Bounds0 Int
index0 (!Bounds0 Int
_, !Bounds0 Int
d5, !Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x6, !Bounds0 Int
x5, !Bounds0 Int
x4, !Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = ((((Bounds0 Int
x6 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d5 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x5) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d4 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x4) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d3 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x3) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d2 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x2) Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
* Bounds0 Int
d1 Bounds0 Int -> Bounds0 Int -> Bounds0 Int
forall a. Num a => a -> a -> a
+ Bounds0 Int
x1
  {-# INLINE inRange0 #-}
  inRange0 :: Bounds0
  (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int,
   Bounds0 Int)
-> Bounds0
     (Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int, Bounds0 Int,
      Bounds0 Int)
-> Bool
inRange0 (!Bounds0 Int
d6, !Bounds0 Int
d5, !Bounds0 Int
d4, !Bounds0 Int
d3, !Bounds0 Int
d2, !Bounds0 Int
d1) (!Bounds0 Int
x6, !Bounds0 Int
x5, !Bounds0 Int
x4, !Bounds0 Int
x3, !Bounds0 Int
x2, !Bounds0 Int
x1) = Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x6 Bool -> Bool -> Bool
&& Bounds0 Int
x6 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d6 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x5 Bool -> Bool -> Bool
&& Bounds0 Int
x5 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d5 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x4 Bool -> Bool -> Bool
&& Bounds0 Int
x4 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d4 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x3 Bool -> Bool -> Bool
&& Bounds0 Int
x3 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d3 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x2 Bool -> Bool -> Bool
&& Bounds0 Int
x2 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d2 Bool -> Bool -> Bool
&& Bounds0 Int
0 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Bounds0 Int
x1 Bool -> Bool -> Bool
&& Bounds0 Int
x1 Bounds0 Int -> Bounds0 Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bounds0 Int
d1