{-# LANGUAGE ConstraintKinds        #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# OPTIONS_GHC -fno-omit-interface-pragmas #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module PlutusTx.Numeric (
  
  AdditiveSemigroup (..),
  AdditiveMonoid (..),
  AdditiveGroup (..),
  MultiplicativeSemigroup (..),
  MultiplicativeMonoid (..),
  Semiring,
  Ring,
  Module (..),
  
  Additive (..),
  Multiplicative (..),
  
  negate,
  divMod,
  quotRem,
  abs,
  ) where
import Data.Semigroup (Product (Product), Sum (Sum))
import PlutusTx.Bool (Bool (False, True), (&&), (||))
import PlutusTx.Builtins (Integer, addInteger, divideInteger, modInteger, multiplyInteger, quotientInteger,
                          remainderInteger, subtractInteger)
import PlutusTx.Monoid (Group, Monoid (mempty), gsub)
import PlutusTx.Ord (Ord ((<)))
import PlutusTx.Semigroup (Semigroup ((<>)))
infixl 7 *
infixl 6 +, -
class AdditiveSemigroup a where
    (+) :: a -> a -> a
class AdditiveSemigroup a => AdditiveMonoid a where
    zero :: a
class AdditiveMonoid a => AdditiveGroup a where
    (-) :: a -> a -> a
{-# INLINABLE negate #-}
negate :: AdditiveGroup a => a -> a
negate :: a -> a
negate a
x = a
forall a. AdditiveMonoid a => a
zero a -> a -> a
forall a. AdditiveGroup a => a -> a -> a
- a
x
newtype Additive a = Additive a
instance Semigroup a => AdditiveSemigroup (Additive a) where
    {-# INLINABLE (+) #-}
    Additive a
x + :: Additive a -> Additive a -> Additive a
+ Additive a
y = a -> Additive a
forall a. a -> Additive a
Additive (a
x a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
y)
instance Monoid a => AdditiveMonoid (Additive a) where
    {-# INLINABLE zero #-}
    zero :: Additive a
zero = a -> Additive a
forall a. a -> Additive a
Additive a
forall a. Monoid a => a
mempty
instance Group a => AdditiveGroup (Additive a) where
    {-# INLINABLE (-) #-}
    Additive a
x - :: Additive a -> Additive a -> Additive a
- Additive a
y = a -> Additive a
forall a. a -> Additive a
Additive (a
x a -> a -> a
forall a. Group a => a -> a -> a
`gsub` a
y)
class MultiplicativeSemigroup a where
    (*) :: a -> a -> a
class MultiplicativeSemigroup a => MultiplicativeMonoid a where
    one :: a
newtype Multiplicative a = Multiplicative a
instance Semigroup a => MultiplicativeSemigroup (Multiplicative a) where
    {-# INLINABLE (*) #-}
    Multiplicative a
x * :: Multiplicative a -> Multiplicative a -> Multiplicative a
* Multiplicative a
y = a -> Multiplicative a
forall a. a -> Multiplicative a
Multiplicative (a
x a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
y)
instance Monoid a => MultiplicativeMonoid (Multiplicative a) where
    {-# INLINABLE one #-}
    one :: Multiplicative a
one = a -> Multiplicative a
forall a. a -> Multiplicative a
Multiplicative a
forall a. Monoid a => a
mempty
type Semiring a = (AdditiveMonoid a, MultiplicativeMonoid a)
type Ring a = (AdditiveGroup a, MultiplicativeMonoid a)
instance AdditiveSemigroup Integer where
    {-# INLINABLE (+) #-}
    + :: Integer -> Integer -> Integer
(+) = Integer -> Integer -> Integer
addInteger
instance AdditiveMonoid Integer where
    {-# INLINABLE zero #-}
    zero :: Integer
zero = Integer
0
instance AdditiveGroup Integer where
    {-# INLINABLE (-) #-}
    (-) = Integer -> Integer -> Integer
subtractInteger
instance MultiplicativeSemigroup Integer where
    {-# INLINABLE (*) #-}
    * :: Integer -> Integer -> Integer
(*) = Integer -> Integer -> Integer
multiplyInteger
instance MultiplicativeMonoid Integer where
    {-# INLINABLE one #-}
    one :: Integer
one = Integer
1
instance AdditiveSemigroup Bool where
    {-# INLINABLE (+) #-}
    + :: Bool -> Bool -> Bool
(+) = Bool -> Bool -> Bool
(||)
instance AdditiveMonoid Bool where
    {-# INLINABLE zero #-}
    zero :: Bool
zero = Bool
False
instance MultiplicativeSemigroup Bool where
    {-# INLINABLE (*) #-}
    * :: Bool -> Bool -> Bool
(*) = Bool -> Bool -> Bool
(&&)
instance MultiplicativeMonoid Bool where
    {-# INLINABLE one #-}
    one :: Bool
one = Bool
True
class (Ring s, AdditiveGroup v) => Module s v | v -> s where
    scale :: s -> v -> v
instance AdditiveSemigroup a => Semigroup (Sum a) where
    {-# INLINABLE (<>) #-}
    Sum a
a1 <> :: Sum a -> Sum a -> Sum a
<> Sum a
a2 = a -> Sum a
forall a. a -> Sum a
Sum (a
a1 a -> a -> a
forall a. AdditiveSemigroup a => a -> a -> a
+ a
a2)
instance AdditiveMonoid a => Monoid (Sum a) where
    {-# INLINABLE mempty #-}
    mempty :: Sum a
mempty = a -> Sum a
forall a. a -> Sum a
Sum a
forall a. AdditiveMonoid a => a
zero
instance MultiplicativeSemigroup a => Semigroup (Product a) where
    {-# INLINABLE (<>) #-}
    Product a
a1 <> :: Product a -> Product a -> Product a
<> Product a
a2 = a -> Product a
forall a. a -> Product a
Product (a
a1 a -> a -> a
forall a. MultiplicativeSemigroup a => a -> a -> a
* a
a2)
instance MultiplicativeMonoid a => Monoid (Product a) where
    {-# INLINABLE mempty #-}
    mempty :: Product a
mempty = a -> Product a
forall a. a -> Product a
Product a
forall a. MultiplicativeMonoid a => a
one
{-# INLINABLE divMod #-}
divMod :: Integer -> Integer -> (Integer, Integer)
divMod :: Integer -> Integer -> (Integer, Integer)
divMod Integer
x Integer
y = ( Integer
x Integer -> Integer -> Integer
`divideInteger` Integer
y, Integer
x Integer -> Integer -> Integer
`modInteger` Integer
y)
{-# INLINABLE quotRem #-}
quotRem :: Integer -> Integer -> (Integer, Integer)
quotRem :: Integer -> Integer -> (Integer, Integer)
quotRem Integer
x Integer
y = ( Integer
x Integer -> Integer -> Integer
`quotientInteger` Integer
y, Integer
x Integer -> Integer -> Integer
`remainderInteger` Integer
y)
{-# INLINABLE abs #-}
abs :: (Ord n, AdditiveGroup n) => n -> n
abs :: n -> n
abs n
x = if n
x n -> n -> Bool
forall a. Ord a => a -> a -> Bool
< n
forall a. AdditiveMonoid a => a
zero then n -> n
forall a. AdditiveGroup a => a -> a
negate n
x else n
x