{-# LANGUAGE TypeFamilies #-}

-- | `AtCoder.LazySegTree.SegAct` instance of range set action. It can set an interval \([l, r)\) to
-- the same monoid \(x\) such as @Sum Int@.
--
-- @since 1.0.0
module AtCoder.Extra.Monoid.RangeSet
  ( -- * RangeSet
    RangeSet (..),

    -- * Constructor
    new,

    -- * Action
    act,
  )
where

import AtCoder.Extra.Math qualified as ACEM
import AtCoder.LazySegTree (SegAct (..))
import Data.Bit (Bit (..))
import Data.Semigroup (stimes)
import Data.Vector.Generic qualified as VG
import Data.Vector.Generic.Mutable qualified as VGM
import Data.Vector.Unboxed qualified as VU
import Data.Vector.Unboxed.Mutable qualified as VUM

-- | `AtCoder.LazySegTree.SegAct` instance of range set action.
--
-- ==== Example
-- >>> import AtCoder.Extra.Monoid (SegAct(..), RangeSet(..))
-- >>> import AtCoder.LazySegTree qualified as LST
-- >>> import Data.Bit (Bit (..))
-- >>> import Data.Semigroup (Product(..))
-- >>> seg <- LST.build @_ @(RangeSet (Product Int)) @(Product Int) $ VU.generate 4 Product -- [0, 1, 2, 3]
-- >>> LST.applyIn seg 0 3 $ RangeSet (Bit True, Product 5) -- [5, 5, 5, 3]
-- >>> getProduct <$> LST.prod seg 0 4
-- 375
--
-- @since 1.0.0
newtype RangeSet a = RangeSet (RangeSetRepr a)
  deriving newtype
    ( -- | @since 1.0.0
      RangeSet a -> RangeSet a -> Bool
(RangeSet a -> RangeSet a -> Bool)
-> (RangeSet a -> RangeSet a -> Bool) -> Eq (RangeSet a)
forall a. Eq a => RangeSet a -> RangeSet a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => RangeSet a -> RangeSet a -> Bool
== :: RangeSet a -> RangeSet a -> Bool
$c/= :: forall a. Eq a => RangeSet a -> RangeSet a -> Bool
/= :: RangeSet a -> RangeSet a -> Bool
Eq,
      -- | @since 1.0.0
      Eq (RangeSet a)
Eq (RangeSet a) =>
(RangeSet a -> RangeSet a -> Ordering)
-> (RangeSet a -> RangeSet a -> Bool)
-> (RangeSet a -> RangeSet a -> Bool)
-> (RangeSet a -> RangeSet a -> Bool)
-> (RangeSet a -> RangeSet a -> Bool)
-> (RangeSet a -> RangeSet a -> RangeSet a)
-> (RangeSet a -> RangeSet a -> RangeSet a)
-> Ord (RangeSet a)
RangeSet a -> RangeSet a -> Bool
RangeSet a -> RangeSet a -> Ordering
RangeSet a -> RangeSet a -> RangeSet a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (RangeSet a)
forall a. Ord a => RangeSet a -> RangeSet a -> Bool
forall a. Ord a => RangeSet a -> RangeSet a -> Ordering
forall a. Ord a => RangeSet a -> RangeSet a -> RangeSet a
$ccompare :: forall a. Ord a => RangeSet a -> RangeSet a -> Ordering
compare :: RangeSet a -> RangeSet a -> Ordering
$c< :: forall a. Ord a => RangeSet a -> RangeSet a -> Bool
< :: RangeSet a -> RangeSet a -> Bool
$c<= :: forall a. Ord a => RangeSet a -> RangeSet a -> Bool
<= :: RangeSet a -> RangeSet a -> Bool
$c> :: forall a. Ord a => RangeSet a -> RangeSet a -> Bool
> :: RangeSet a -> RangeSet a -> Bool
$c>= :: forall a. Ord a => RangeSet a -> RangeSet a -> Bool
>= :: RangeSet a -> RangeSet a -> Bool
$cmax :: forall a. Ord a => RangeSet a -> RangeSet a -> RangeSet a
max :: RangeSet a -> RangeSet a -> RangeSet a
$cmin :: forall a. Ord a => RangeSet a -> RangeSet a -> RangeSet a
min :: RangeSet a -> RangeSet a -> RangeSet a
Ord,
      -- | @since 1.0.0
      Int -> RangeSet a -> ShowS
[RangeSet a] -> ShowS
RangeSet a -> String
(Int -> RangeSet a -> ShowS)
-> (RangeSet a -> String)
-> ([RangeSet a] -> ShowS)
-> Show (RangeSet a)
forall a. Show a => Int -> RangeSet a -> ShowS
forall a. Show a => [RangeSet a] -> ShowS
forall a. Show a => RangeSet a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> RangeSet a -> ShowS
showsPrec :: Int -> RangeSet a -> ShowS
$cshow :: forall a. Show a => RangeSet a -> String
show :: RangeSet a -> String
$cshowList :: forall a. Show a => [RangeSet a] -> ShowS
showList :: [RangeSet a] -> ShowS
Show
    )

-- | `RangeSet` internal representation. The first value represents if it is an identity action.
-- Tuples are not the fastest representation, but it's easier to implement
-- `Data.Vector.Unboxed.Unbox`.
--
-- @since 1.0.0
type RangeSetRepr a = (Bit, a)

-- | Creates a new `RangeSet` action.
--
-- @since 1.0.0
{-# INLINE new #-}
new :: a -> RangeSet a
new :: forall a. a -> RangeSet a
new = RangeSetRepr a -> RangeSet a
forall a. RangeSetRepr a -> RangeSet a
RangeSet (RangeSetRepr a -> RangeSet a)
-> (a -> RangeSetRepr a) -> a -> RangeSet a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Bit
Bit Bool
True,)

-- | Applies one-length range set: \(f: x \rightarrow y\).
--
-- @since 1.0.0
{-# INLINE act #-}
act :: RangeSet a -> a -> a
act :: forall a. RangeSet a -> a -> a
act (RangeSet (Bit Bool
True, !a
f)) a
_ = a
f
act (RangeSet (Bit Bool
False, !a
_)) a
x = a
x

-- | Acts on @a@ with length in terms of `SegAct`.
--
-- @since 1.0.0
{-# INLINE actWithLength #-}
actWithLength :: (Semigroup a) => Int -> RangeSet a -> a -> a
actWithLength :: forall a. Semigroup a => Int -> RangeSet a -> a -> a
actWithLength Int
len (RangeSet (Bit Bool
True, !a
f)) a
_ = (a -> a -> a) -> Int -> a -> a
forall a. (a -> a -> a) -> Int -> a -> a
ACEM.power a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>) Int
len a
f
actWithLength Int
_ (RangeSet (Bit Bool
False, !a
_)) a
x = a
x

-- | @since 1.0.0
instance Semigroup (RangeSet a) where
  {-# INLINE (<>) #-}
  RangeSet (Bit Bool
False, !a
_) <> :: RangeSet a -> RangeSet a -> RangeSet a
<> RangeSet a
old = RangeSet a
old
  RangeSet a
new_ <> RangeSet a
_ = RangeSet a
new_
  {-# INLINE stimes #-}
  stimes :: forall b. Integral b => b -> RangeSet a -> RangeSet a
stimes b
_ RangeSet a
x = RangeSet a
x

-- | @since 1.0.0
instance (Monoid a) => Monoid (RangeSet a) where
  {-# INLINE mempty #-}
  mempty :: RangeSet a
mempty = RangeSetRepr a -> RangeSet a
forall a. RangeSetRepr a -> RangeSet a
RangeSet (Bool -> Bit
Bit Bool
False, a
forall a. Monoid a => a
mempty)
  {-# INLINE mconcat #-}
  -- find the first non-mempty
  mconcat :: [RangeSet a] -> RangeSet a
mconcat [] = RangeSet a
forall a. Monoid a => a
mempty
  mconcat (RangeSet (Bit Bool
False, !a
_) : [RangeSet a]
as) = [RangeSet a] -> RangeSet a
forall a. Monoid a => [a] -> a
mconcat [RangeSet a]
as
  mconcat (RangeSet a
a : [RangeSet a]
_) = RangeSet a
a

-- | @since 1.0.0
instance (Monoid a) => SegAct (RangeSet a) a where
  {-# INLINE segActWithLength #-}
  segActWithLength :: Int -> RangeSet a -> a -> a
segActWithLength = Int -> RangeSet a -> a -> a
forall a. Semigroup a => Int -> RangeSet a -> a -> a
actWithLength

-- | @since 1.0.0
newtype instance VU.MVector s (RangeSet a) = MV_RangeSet (VU.MVector s (RangeSetRepr a))

-- | @since 1.0.0
newtype instance VU.Vector (RangeSet a) = V_RangeSet (VU.Vector (RangeSetRepr a))

-- | @since 1.0.0
deriving instance (VU.Unbox a) => VGM.MVector VUM.MVector (RangeSet a)

-- | @since 1.0.0
deriving instance (VU.Unbox a) => VG.Vector VU.Vector (RangeSet a)

-- | @since 1.0.0
instance (VU.Unbox a) => VU.Unbox (RangeSet a)