packages feed

ac-library-hs-1.5.2.1: src/AtCoder/Internal/Assert.hs

-- | Runtime assertion utility.
--
-- ==== __Example__
-- >>> let !_ = runtimeAssert False "errorMessage"
-- *** Exception: errorMessage
-- ...
--
-- >>> let !_ = checkIndex "AtCoder.Internal.Assert.doctest" 0 3
-- >>> let !_ = checkIndex "AtCoder.Internal.Assert.doctest" (-1) 3
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid index `-1` over length `3`
-- ...
--
-- >>> let !_ = checkIndexBounded "AtCoder.Internal.Assert.doctest" 2 1 3
-- >>> let !_ = checkIndexBounded "AtCoder.Internal.Assert.doctest" (-1) 1 3
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid index `-1` over bounds `[1, 3)`
-- ...
--
-- >>> let !_ = checkVertex "AtCoder.Internal.Assert.doctest" 0 3
-- >>> let !_ = checkVertex "AtCoder.Internal.Assert.doctest" (-1) 3
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid vertex `-1` over the number of vertices `3`
-- ...
--
-- >>> let !_ = checkEdge "AtCoder.Internal.Assert.doctest" 0 3
-- >>> let !_ = checkEdge "AtCoder.Internal.Assert.doctest" (-1) 3
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid edge index `-1` over the number of edges `3`
-- ...
--
-- >>> let !_ = checkCustom "AtCoder.Internal.Assert.doctest" "index" 0 "set" 3
-- >>> let !_ = checkCustom "AtCoder.Internal.Assert.doctest" "index" (-1) "set" 3
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid index `-1` over set `3`
-- ...
--
-- >>> let !_ = checkInterval "AtCoder.Internal.Assert.doctest" 0 3 3
-- >>> let !_ = checkInterval "AtCoder.Internal.Assert.doctest" 0 4 3
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid interval `[0, 4)` over length `3`
-- ...
--
-- >>> let !_ = checkIntervalBounded "AtCoder.Internal.Assert.doctest"  2 4 0 5
-- >>> let !_ = checkIntervalBounded "AtCoder.Internal.Assert.doctest" (-1) 0 0 5
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid interval `[-1, 0)` over bounds `[0, 5)`
-- ...
--
-- >>> let !_ = checkPoint2d "AtCoder.Internal.Assert.doctest"  1 1 2 2
-- >>> let !_ = checkPoint2d "AtCoder.Internal.Assert.doctest" 4 4 2 2
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid point `(4, 4)` for rectangle `[0, 2) x [0, 2)`
-- ...
--
-- >>> let !_ = checkRect "AtCoder.Internal.Assert.doctest"  1 2 1 2 3 3
-- >>> let !_ = checkRect "AtCoder.Internal.Assert.doctest" 1 2 1 2 1 1
-- *** Exception: AtCoder.Internal.Assert.doctest: given invalid rectangle `[1, 2) x [1, 2)` for rectangle `[0, 1) x [0, 1)`
-- ...
--
-- @since 1.0.0.0
module AtCoder.Internal.Assert
  ( -- * Runtime assertion
    runtimeAssert,

    -- * Tests
    testIndex,
    testInterval,
    testIntervalBounded,
    testPoint2d,
    testRect,
    testRectShape,

    -- * Index assertions
    checkIndex,
    errorIndex,
    checkIndexBounded,
    errorIndexBounded,
    checkVertex,
    errorVertex,
    checkEdge,
    errorEdge,
    checkCustom,
    errorCustom,

    -- * Interval assertions
    checkInterval,
    errorInterval,
    checkIntervalBounded,
    errorIntervalBounded,

    -- * Two-dimensional index assertions
    checkPoint2d,
    errorPoint2d,
    checkRect,
    errorRect,
    checkRectShape,
    errorRectShape,
  )
where

import GHC.Stack (HasCallStack)

-- | \(O(1)\) Assertion that is never erased at compile time.
--
-- @since 1.0.0.0
{-# INLINE runtimeAssert #-}
runtimeAssert :: (HasCallStack) => Bool -> String -> ()
runtimeAssert p s
  | p = ()
  | otherwise = error s

-- | \(O(1)\) Tests \(0 \le i \lt n\).
--
-- @since 1.0.0.0
{-# INLINE testIndex #-}
testIndex ::
  (HasCallStack) =>
  -- | \(i\)
  Int ->
  -- | \(n\)
  Int ->
  -- | \(0 \le i \lt n\)
  Bool
testIndex i n = 0 <= i && i < n

-- | \(O(1)\) Tests \(0 \le l \le r \le n\).
--
-- @since 1.0.0.0
{-# INLINE testInterval #-}
testInterval ::
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(n\)
  Int ->
  -- | \(0 \le l \le r \le n\).
  Bool
testInterval l r n = 0 <= l && l <= r && r <= n

-- | \(O(1)\) Tests \(l_0 \le l \le r \le r_0\).
--
-- @since 1.2.1.0
{-# INLINE testIntervalBounded #-}
testIntervalBounded ::
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(l_0\)
  Int ->
  -- | \(r_0\)
  Int ->
  -- | \(l_0 \le l \le r \le r_0\)
  Bool
testIntervalBounded l r l0 r0 = l0 <= l && l <= r && r <= r0

-- | \(O(1)\) Tests \((x, y) \in [0, w) \times [0, h)\).
--
-- @since 1.2.3.0
{-# INLINE testPoint2d #-}
testPoint2d ::
  (HasCallStack) =>
  -- | \(x\)
  Int ->
  -- | \(y\)
  Int ->
  -- | \(w\)
  Int ->
  -- | \(h\)
  Int ->
  -- | \((x, y) \in [0, w) \times [0, h)\)
  Bool
testPoint2d x y w h = 0 <= x && x < w && 0 <= y && y < h

-- | \(O(1)\) Tests \([x_1, x_2) \times [y_1, y_2) \in [0, w) \times [0, h)\).
--
-- @since 1.2.3.0
{-# INLINE testRect #-}
testRect ::
  (HasCallStack) =>
  -- | \(x_1\)
  Int ->
  -- | \(x_2\)
  Int ->
  -- | \(y_1\)
  Int ->
  -- | \(y_2\)
  Int ->
  -- | \(w\)
  Int ->
  -- | \(h\)
  Int ->
  -- | \([x_1, x_2) \times [y_1, y_2) \in [0, w) \times [0, h)\).
  Bool
testRect x1 x2 y1 y2 w h = 0 <= x1 && x1 <= x2 && x2 <= w && 0 <= y1 && y1 <= y2 && y2 <= h

-- | \(O(1)\) Tests \(x_1 \le x_2 \land y_1 \le y_2\).
--
-- @since 1.2.3.0
{-# INLINE testRectShape #-}
testRectShape ::
  (HasCallStack) =>
  -- | \(x_1\)
  Int ->
  -- | \(x_2\)
  Int ->
  -- | \(y_1\)
  Int ->
  -- | \(y_2\)
  Int ->
  -- | \(x_1 \le x_2 \land y_1 \le y_2\).
  Bool
testRectShape x1 x2 y1 y2 = x1 <= x2 && y1 <= y2

-- | \(O(1)\) Asserts \(0 \leq i \lt n\) for an array index \(i\).
--
-- @since 1.0.0.0
{-# INLINE checkIndex #-}
checkIndex :: (HasCallStack) => String -> Int -> Int -> ()
checkIndex funcName i n
  | 0 <= i && i < n = ()
  | otherwise = errorIndex funcName i n

-- | \(O(1)\) Emits index boundary error.
--
-- @since 1.0.0.0
{-# INLINE errorIndex #-}
errorIndex :: (HasCallStack) => String -> Int -> Int -> a
errorIndex funcName i n =
  error $ funcName ++ ": given invalid index `" ++ show i ++ "` over length `" ++ show n ++ "`"

-- | \(O(1)\) Asserts \(l_0 \leq i \lt r_0\) for an array index \(i\).
--
-- @since 1.2.1.0
{-# INLINE checkIndexBounded #-}
checkIndexBounded :: (HasCallStack) => String -> Int -> Int -> Int -> ()
checkIndexBounded funcName i l r
  | l <= i && i < r = ()
  | otherwise = errorIndexBounded funcName i l r

-- | \(O(1)\) Emits index boundary error.
--
-- @since 1.2.1.0
{-# INLINE errorIndexBounded #-}
errorIndexBounded :: (HasCallStack) => String -> Int -> Int -> Int -> a
errorIndexBounded funcName i l r =
  error $ funcName ++ ": given invalid index `" ++ show i ++ "` over bounds `[" ++ show l ++ ", " ++ show r ++ ")`"

-- | \(O(1)\) Asserts \(0 \leq i \lt n\) for a graph vertex \(i\).
--
-- @since 1.0.0.0
{-# INLINE checkVertex #-}
checkVertex :: (HasCallStack) => String -> Int -> Int -> ()
checkVertex funcName i n
  | 0 <= i && i < n = ()
  | otherwise = errorVertex funcName i n

-- | \(O(1)\) Emits vertex boundary error.
--
-- @since 1.0.0.0
{-# INLINE errorVertex #-}
errorVertex :: (HasCallStack) => String -> Int -> Int -> a
errorVertex funcName i n =
  error $ funcName ++ ": given invalid vertex `" ++ show i ++ "` over the number of vertices `" ++ show n ++ "`"

-- | \(O(1)\) Asserts \(0 \leq i \lt m\) for an edge index \(i\).
--
-- @since 1.0.0.0
{-# INLINE checkEdge #-}
checkEdge :: (HasCallStack) => String -> Int -> Int -> ()
checkEdge funcName i n
  | 0 <= i && i < n = ()
  | otherwise = errorEdge funcName i n

-- | \(O(1)\) Emits edge index boundary error.
--
-- @since 1.0.0.0
{-# INLINE errorEdge #-}
errorEdge :: (HasCallStack) => String -> Int -> Int -> a
errorEdge funcName i n =
  error $ funcName ++ ": given invalid edge index `" ++ show i ++ "` over the number of edges `" ++ show n ++ "`"

-- | \(O(1)\) Asserts index boundary with custom message.
--
-- @since 1.0.0.0
{-# INLINE checkCustom #-}
checkCustom :: (HasCallStack) => String -> String -> Int -> String -> Int -> ()
checkCustom funcName indexName i setName n
  | testIndex i n = ()
  | otherwise = errorCustom funcName indexName i setName n

-- | \(O(1)\) Emits custom index error.
--
-- @since 1.0.0.0
{-# INLINE errorCustom #-}
errorCustom :: (HasCallStack) => String -> String -> Int -> String -> Int -> a
errorCustom funcName indexName i setName n = error $ funcName ++ ": given invalid " ++ indexName ++ " `" ++ show i ++ "` over " ++ setName ++ " `" ++ show n ++ "`"

-- | \(O(1)\) Asserts \(0 \leq l \leq r \leq n\) for a half-open interval \([l, r)\).
--
-- @since 1.0.0.0
{-# INLINE checkInterval #-}
checkInterval :: (HasCallStack) => String -> Int -> Int -> Int -> ()
checkInterval funcName l r n
  | testInterval l r n = ()
  | otherwise = errorInterval funcName l r n

-- | \(O(1)\) Emits interval boundary error.
--
-- @since 1.0.0.0
{-# INLINE errorInterval #-}
errorInterval :: (HasCallStack) => String -> Int -> Int -> Int -> a
errorInterval funcName l r n = error $ funcName ++ ": given invalid interval `[" ++ show l ++ ", " ++ show r ++ ")` over length `" ++ show n ++ "`"

-- | \(O(1)\) Asserts \(0 \leq l \leq r \leq n\) for a half-open interval \([l, r)\).
--
-- @since 1.2.1.0
{-# INLINE checkIntervalBounded #-}
checkIntervalBounded :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> ()
checkIntervalBounded funcName l r l0 r0
  | testIntervalBounded l r l0 r0 = ()
  | otherwise = errorIntervalBounded funcName l r l0 r0

-- | \(O(1)\) Emits interval boundary error.
--
-- @since 1.2.1.0
{-# INLINE errorIntervalBounded #-}
errorIntervalBounded :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> a
errorIntervalBounded funcName l r l0 r0 = error $ funcName ++ ": given invalid interval `[" ++ show l ++ ", " ++ show r ++ ")` over bounds `[" ++ show l0 ++ ", " ++ show r0 ++ ")`"

-- | \(O(1)\) Asserts \(0 \leq i \lt n\) for a graph vertex \(i\).
--
-- @since 1.2.3.0
{-# INLINE checkPoint2d #-}
checkPoint2d :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> ()
checkPoint2d funcName x y w h
  | testPoint2d x y w h = ()
  | otherwise = errorPoint2d funcName x y w h

-- | \(O(1)\) Emits point boundary error.
--
-- @since 1.2.3.0
{-# INLINE errorPoint2d #-}
errorPoint2d :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> a
errorPoint2d funcName x y w h =
  error $ funcName ++ ": given invalid point `(" ++ show x ++ ", " ++ show y ++ ")` for rectangle `[0, " ++ show w ++ ") x [0, " ++ show h ++ ")`"

-- | \(O(1)\) Asserts \([x_1, x_2) \times [y_1, y_2) \in [0, w) \times [0, h)\).
--
-- @since 1.2.3.0
{-# INLINE checkRect #-}
checkRect :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> Int -> Int -> ()
checkRect funcName x1 x2 y1 y2 w h
  | testRect x1 x2 y1 y2 w h = ()
  | otherwise = errorRect funcName x1 x2 y1 y2 w h

-- | \(O(1)\) Asserts rectangle boundary error.
--
-- @since 1.2.3.0
{-# INLINE errorRect #-}
errorRect :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> Int -> Int -> a
errorRect funcName x1 x2 y1 y2 w h =
  error $ funcName ++ ": given invalid rectangle `[" ++ show x1 ++ ", " ++ show x2 ++ ") x [" ++ show y1 ++ ", " ++ show y2 ++ ")` for rectangle `[0, " ++ show w ++ ") x [0, " ++ show h ++ ")`"

-- | \(O(1)\) Asserts \(x_1 \le x_2\) and \(y_1 \le y_2\).
--
-- @since 1.2.3.0
{-# INLINE checkRectShape #-}
checkRectShape :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> ()
checkRectShape funcName x1 x2 y1 y2
  | testRectShape x1 x2 y1 y2 = ()
  | otherwise = errorRectShape funcName x1 x2 y1 y2

-- | \(O(1)\) Asserts rectangle boundary error.
--
-- @since 1.2.3.0
{-# INLINE errorRectShape #-}
errorRectShape :: (HasCallStack) => String -> Int -> Int -> Int -> Int -> a
errorRectShape funcName x1 x2 y1 y2 =
  error $ funcName ++ ": given invalid rectangle `[" ++ show x1 ++ ", " ++ show x2 ++ ") x [" ++ show y1 ++ ", " ++ show y2 ++ ")`"