{-# LANGUAGE TypeFamilies #-}

-- | A monoid acted on by `Mat2x2`, an affine transformation target.
--
-- @since 1.1.0.0
module AtCoder.Extra.Monoid.V2
  ( -- * V2
    V2 (..),
    V2Repr,

    -- * Constructor
    new,
    unV2,
  )
where

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

-- | A monoid acted on by `Mat2x2`, an affine transformation target.
--
-- @since 1.1.0.0
newtype V2 a = V2 (V2Repr a)
  deriving newtype
    ( -- | @since 1.1.0.0
      V2 a -> V2 a -> Bool
(V2 a -> V2 a -> Bool) -> (V2 a -> V2 a -> Bool) -> Eq (V2 a)
forall a. Eq a => V2 a -> V2 a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => V2 a -> V2 a -> Bool
== :: V2 a -> V2 a -> Bool
$c/= :: forall a. Eq a => V2 a -> V2 a -> Bool
/= :: V2 a -> V2 a -> Bool
Eq,
      -- | @since 1.1.0.0
      Eq (V2 a)
Eq (V2 a) =>
(V2 a -> V2 a -> Ordering)
-> (V2 a -> V2 a -> Bool)
-> (V2 a -> V2 a -> Bool)
-> (V2 a -> V2 a -> Bool)
-> (V2 a -> V2 a -> Bool)
-> (V2 a -> V2 a -> V2 a)
-> (V2 a -> V2 a -> V2 a)
-> Ord (V2 a)
V2 a -> V2 a -> Bool
V2 a -> V2 a -> Ordering
V2 a -> V2 a -> V2 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 (V2 a)
forall a. Ord a => V2 a -> V2 a -> Bool
forall a. Ord a => V2 a -> V2 a -> Ordering
forall a. Ord a => V2 a -> V2 a -> V2 a
$ccompare :: forall a. Ord a => V2 a -> V2 a -> Ordering
compare :: V2 a -> V2 a -> Ordering
$c< :: forall a. Ord a => V2 a -> V2 a -> Bool
< :: V2 a -> V2 a -> Bool
$c<= :: forall a. Ord a => V2 a -> V2 a -> Bool
<= :: V2 a -> V2 a -> Bool
$c> :: forall a. Ord a => V2 a -> V2 a -> Bool
> :: V2 a -> V2 a -> Bool
$c>= :: forall a. Ord a => V2 a -> V2 a -> Bool
>= :: V2 a -> V2 a -> Bool
$cmax :: forall a. Ord a => V2 a -> V2 a -> V2 a
max :: V2 a -> V2 a -> V2 a
$cmin :: forall a. Ord a => V2 a -> V2 a -> V2 a
min :: V2 a -> V2 a -> V2 a
Ord,
      -- | @since 1.1.0.0
      Int -> V2 a -> ShowS
[V2 a] -> ShowS
V2 a -> String
(Int -> V2 a -> ShowS)
-> (V2 a -> String) -> ([V2 a] -> ShowS) -> Show (V2 a)
forall a. Show a => Int -> V2 a -> ShowS
forall a. Show a => [V2 a] -> ShowS
forall a. Show a => V2 a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> V2 a -> ShowS
showsPrec :: Int -> V2 a -> ShowS
$cshow :: forall a. Show a => V2 a -> String
show :: V2 a -> String
$cshowList :: forall a. Show a => [V2 a] -> ShowS
showList :: [V2 a] -> ShowS
Show
    )

-- | `V2` internal representation. Tuples are not the fastest representation, but it's easier
-- to implement `Data.Vector.Unboxed.Unbox`.
--
-- @since 1.1.0.0
type V2Repr a = (a, a)

-- | \(O(1)\) Creates `V2` of length \(1\).
--
-- @since 1.1.0.0
{-# INLINE new #-}
new :: (Num a) => a -> V2 a
new :: forall a. Num a => a -> V2 a
new !a
a = V2Repr a -> V2 a
forall a. V2Repr a -> V2 a
V2 (a
a, a
1)

-- | \(O(1)\) Retrieves the value of `V2`, discarding the length information.
--
-- @since 1.1.0.0
{-# INLINE unV2 #-}
unV2 :: V2 a -> a
unV2 :: forall a. V2 a -> a
unV2 (V2 (!a
a, !a
_)) = a
a

-- | @since 1.1.0.0
instance (Num a) => Semigroup (V2 a) where
  {-# INLINE (<>) #-}
  (V2 (!a
a1, !a
a2)) <> :: V2 a -> V2 a -> V2 a
<> (V2 (!a
b1, !a
b2)) = (a, a) -> V2 a
forall a. V2Repr a -> V2 a
V2 (a
a', a
b')
    where
      !a' :: a
a' = a
a1 a -> a -> a
forall a. Num a => a -> a -> a
+ a
b1
      !b' :: a
b' = a
a2 a -> a -> a
forall a. Num a => a -> a -> a
+ a
b2

-- | @since 1.1.0.0
instance (Num a) => Monoid (V2 a) where
  {-# INLINE mempty #-}
  mempty :: V2 a
mempty = V2Repr a -> V2 a
forall a. V2Repr a -> V2 a
V2 (a
0, a
0)

-- | @since 1.1.0.0
newtype instance VU.MVector s (V2 a) = MV_V2 (VU.MVector s (V2Repr a))

-- | @since 1.1.0.0
newtype instance VU.Vector (V2 a) = V_V2 (VU.Vector (V2Repr a))

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

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

-- | @since 1.1.0.0
instance (VU.Unbox a) => VU.Unbox (V2 a)