-- | Provides the 'AGroup' typeclass.
--
-- @since 0.1
module Numeric.Algebra.Additive.AGroup
  ( AGroup (..),
  )
where

import Data.Complex (Complex)
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Kind (Constraint, Type)
import Data.Ratio (Ratio)
import Data.Word (Word16, Word32, Word64, Word8)
import Numeric.Algebra.Additive.AMonoid (AMonoid)

-- | Defines an additive group.
--
-- @since 0.1
type AGroup :: Type -> Constraint
class (AMonoid g) => AGroup g where
  -- | @since 0.1
  (.-.) :: g -> g -> g

infixl 6 .-.

-- | @since 0.1
instance AGroup Double where
  .-. :: Double -> Double -> Double
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Float where
  .-. :: Float -> Float -> Float
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Int where
  .-. :: Int -> Int -> Int
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Int8 where
  .-. :: Int8 -> Int8 -> Int8
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Int16 where
  .-. :: Int16 -> Int16 -> Int16
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Int32 where
  .-. :: Int32 -> Int32 -> Int32
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Int64 where
  .-. :: Int64 -> Int64 -> Int64
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Integer where
  .-. :: Integer -> Integer -> Integer
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Word where
  .-. :: Word -> Word -> Word
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Word8 where
  .-. :: Word8 -> Word8 -> Word8
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Word16 where
  .-. :: Word16 -> Word16 -> Word16
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Word32 where
  .-. :: Word32 -> Word32 -> Word32
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup Word64 where
  .-. :: Word64 -> Word64 -> Word64
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance AGroup (Ratio Integer) where
  .-. :: Ratio Integer -> Ratio Integer -> Ratio Integer
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (RealFloat a) => AGroup (Complex a) where
  .-. :: Complex a -> Complex a -> Complex a
(.-.) = (-)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a) where
  (a
x1, a
x2) .-. :: (a, a) -> (a, a) -> (a, a)
.-. (a
y1, a
y2) = (a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1, a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a, a) where
  (a
x1, a
x2, a
x3) .-. :: (a, a, a) -> (a, a, a) -> (a, a, a)
.-. (a
y1, a
y2, a
y3) = (a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1, a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2, a
x3 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y3)
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a, a, a) where
  (a
x1, a
x2, a
x3, a
x4) .-. :: (a, a, a, a) -> (a, a, a, a) -> (a, a, a, a)
.-. (a
y1, a
y2, a
y3, a
y4) =
    ( a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1,
      a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2,
      a
x3 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y3,
      a
x4 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y4
    )
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a, a, a, a) where
  (a
x1, a
x2, a
x3, a
x4, a
x5) .-. :: (a, a, a, a, a) -> (a, a, a, a, a) -> (a, a, a, a, a)
.-. (a
y1, a
y2, a
y3, a
y4, a
y5) =
    ( a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1,
      a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2,
      a
x3 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y3,
      a
x4 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y4,
      a
x5 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y5
    )
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a, a, a, a, a) where
  (a
x1, a
x2, a
x3, a
x4, a
x5, a
x6) .-. :: (a, a, a, a, a, a) -> (a, a, a, a, a, a) -> (a, a, a, a, a, a)
.-. (a
y1, a
y2, a
y3, a
y4, a
y5, a
y6) =
    ( a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1,
      a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2,
      a
x3 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y3,
      a
x4 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y4,
      a
x5 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y5,
      a
x6 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y6
    )
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a, a, a, a, a, a) where
  (a
x1, a
x2, a
x3, a
x4, a
x5, a
x6, a
x7) .-. :: (a, a, a, a, a, a, a)
-> (a, a, a, a, a, a, a) -> (a, a, a, a, a, a, a)
.-. (a
y1, a
y2, a
y3, a
y4, a
y5, a
y6, a
y7) =
    ( a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1,
      a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2,
      a
x3 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y3,
      a
x4 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y4,
      a
x5 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y5,
      a
x6 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y6,
      a
x7 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y7
    )
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a, a, a, a, a, a, a) where
  (a
x1, a
x2, a
x3, a
x4, a
x5, a
x6, a
x7, a
x8) .-. :: (a, a, a, a, a, a, a, a)
-> (a, a, a, a, a, a, a, a) -> (a, a, a, a, a, a, a, a)
.-. (a
y1, a
y2, a
y3, a
y4, a
y5, a
y6, a
y7, a
y8) =
    ( a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1,
      a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2,
      a
x3 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y3,
      a
x4 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y4,
      a
x5 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y5,
      a
x6 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y6,
      a
x7 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y7,
      a
x8 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y8
    )
  {-# INLINE (.-.) #-}

-- | @since 0.1
instance (AGroup a) => AGroup (a, a, a, a, a, a, a, a, a) where
  (a
x1, a
x2, a
x3, a
x4, a
x5, a
x6, a
x7, a
x8, a
x9) .-. :: (a, a, a, a, a, a, a, a, a)
-> (a, a, a, a, a, a, a, a, a) -> (a, a, a, a, a, a, a, a, a)
.-. (a
y1, a
y2, a
y3, a
y4, a
y5, a
y6, a
y7, a
y8, a
y9) =
    ( a
x1 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y1,
      a
x2 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y2,
      a
x3 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y3,
      a
x4 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y4,
      a
x5 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y5,
      a
x6 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y6,
      a
x7 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y7,
      a
x8 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y8,
      a
x9 a -> a -> a
forall g. AGroup g => g -> g -> g
.-. a
y9
    )
  {-# INLINE (.-.) #-}