-- | Provides the 'MSemigroup' typeclass.
--
-- @since 0.1
module Numeric.Algebra.Multiplicative.MSemigroup
  ( MSemigroup (..),
  )
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 GHC.Natural (Natural)

-- | Defines a multiplicative semigroup.
--
-- @since 0.1
type MSemigroup :: Type -> Constraint
class MSemigroup s where
  -- | @since 0.1
  (.*.) :: s -> s -> s

infixl 7 .*.

-- | @since 0.1
instance MSemigroup Double where
  .*. :: Double -> Double -> Double
(.*.) = Double -> Double -> Double
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Float where
  .*. :: Float -> Float -> Float
(.*.) = Float -> Float -> Float
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Int where
  .*. :: Int -> Int -> Int
(.*.) = Int -> Int -> Int
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Int8 where
  .*. :: Int8 -> Int8 -> Int8
(.*.) = Int8 -> Int8 -> Int8
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Int16 where
  .*. :: Int16 -> Int16 -> Int16
(.*.) = Int16 -> Int16 -> Int16
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Int32 where
  .*. :: Int32 -> Int32 -> Int32
(.*.) = Int32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Int64 where
  .*. :: Int64 -> Int64 -> Int64
(.*.) = Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Integer where
  .*. :: Integer -> Integer -> Integer
(.*.) = Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Word where
  .*. :: Word -> Word -> Word
(.*.) = Word -> Word -> Word
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Word8 where
  .*. :: Word8 -> Word8 -> Word8
(.*.) = Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Word16 where
  .*. :: Word16 -> Word16 -> Word16
(.*.) = Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Word32 where
  .*. :: Word32 -> Word32 -> Word32
(.*.) = Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Word64 where
  .*. :: Word64 -> Word64 -> Word64
(.*.) = Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup Natural where
  .*. :: Natural -> Natural -> Natural
(.*.) = Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup (Ratio Integer) where
  .*. :: Ratio Integer -> Ratio Integer -> Ratio Integer
(.*.) = Ratio Integer -> Ratio Integer -> Ratio Integer
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

-- | @since 0.1
instance MSemigroup (Ratio Natural) where
  .*. :: Ratio Natural -> Ratio Natural -> Ratio Natural
(.*.) = Ratio Natural -> Ratio Natural -> Ratio Natural
forall a. Num a => a -> a -> a
(*)
  {-# INLINE (.*.) #-}

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