{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module LLVM.Extra.Arithmetic (
   -- * arithmetic: generalized and improved type inference
   Additive (zero, add, sub, neg), one, inc, dec,
   PseudoRing (mul), square,
   Scalar,
   PseudoModule (scale),
   Field (fdiv),
   IntegerConstant(fromInteger'),
   RationalConstant(fromRational'),
   idiv, irem,
   FloatingComparison(fcmp), Comparison(cmp),
   CmpResult, LLVM.CmpPredicate(..),
   Logic (and, or, xor, inv),
   Real (min, max, abs, signum),
   Fraction (truncate, fraction),
   signedFraction, addToPhase, incPhase,
   -- * pointer arithmetic
   advanceArrayElementPtr,
   decreaseArrayElementPtr,
   -- * transcendental functions
   Algebraic (sqrt),
   Transcendental (pi, sin, cos, exp, log, pow),
   exp2, log2, log10,
   ) where

import qualified LLVM.Util.Intrinsic as Intrinsic
import LLVM.Extra.ArithmeticPrivate
   (inc, dec, advanceArrayElementPtr, decreaseArrayElementPtr, )

import qualified LLVM.Extra.Tuple as Tuple
import qualified LLVM.Extra.ScalarOrVector as SoV
import qualified LLVM.Core as LLVM
import LLVM.Core
   (CodeGenFunction, value, Value, ConstValue,
    IsInteger, IsFloating, IsArithmetic)

import Control.Monad (liftM2, liftM3, )

import Prelude hiding
   (Real, and, or, sqrt, sin, cos, exp, log, abs, min, max, truncate, )



{- |
This and the following type classes
are intended for arithmetic operations on wrappers around LLVM types.
E.g. you might define a fixed point fraction type by

> newtype Fixed = Fixed Int32

and then use the same methods for floating point and fixed point arithmetic.

In contrast to the arithmetic methods in the @llvm@ wrapper,
in our methods the types of operands and result match.
Advantage: Type inference determines most of the types automatically.
Disadvantage: You cannot use constant values directly,
but you have to convert them all to 'Value'.
-}
class (Tuple.Zero a) => Additive a where
   zero :: a
   add :: a -> a -> CodeGenFunction r a
   sub :: a -> a -> CodeGenFunction r a
   neg :: a -> CodeGenFunction r a

instance (IsArithmetic a) => Additive (Value a) where
   zero :: Value a
zero = ConstValue a -> Value a
forall a. ConstValue a -> Value a
LLVM.value ConstValue a
forall a. IsType a => ConstValue a
LLVM.zero
   add :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
add = Value a -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsArithmetic a =>
Value a -> Value a -> CodeGenFunction r (Value a)
LLVM.add
   sub :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
sub = Value a -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsArithmetic a =>
Value a -> Value a -> CodeGenFunction r (Value a)
LLVM.sub
   neg :: forall r. Value a -> CodeGenFunction r (Value a)
neg = Value a -> CodeGenFunction r (Value a)
forall a r.
IsArithmetic a =>
Value a -> CodeGenFunction r (Value a)
LLVM.neg

instance (IsInteger a) => Additive (ConstValue a) where
   zero :: ConstValue a
zero = ConstValue a
forall a. IsType a => ConstValue a
LLVM.zero
   add :: forall r.
ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
add = ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
ConstValue a
-> ConstValue a
-> CodeGenFunction r (BinOpValue ConstValue ConstValue a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.iadd
   sub :: forall r.
ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
sub = ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
ConstValue a
-> ConstValue a
-> CodeGenFunction r (BinOpValue ConstValue ConstValue a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.isub
   neg :: forall r. ConstValue a -> CodeGenFunction r (ConstValue a)
neg = ConstValue a
-> ConstValue a
-> CodeGenFunction r (BinOpValue ConstValue ConstValue a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.isub ConstValue a
forall a. IsType a => ConstValue a
LLVM.zero

instance (Additive a, Additive b) => Additive (a,b) where
   zero :: (a, b)
zero = (a
forall a. Additive a => a
zero, b
forall a. Additive a => a
zero)
   add :: forall r. (a, b) -> (a, b) -> CodeGenFunction r (a, b)
add (a
x0,b
x1) (a
y0,b
y1) =
      (a -> b -> (a, b))
-> CodeGenFunction r a
-> CodeGenFunction r b
-> CodeGenFunction r (a, b)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
add a
x0 a
y0) (b -> b -> CodeGenFunction r b
forall r. b -> b -> CodeGenFunction r b
forall a r. Additive a => a -> a -> CodeGenFunction r a
add b
x1 b
y1)
   sub :: forall r. (a, b) -> (a, b) -> CodeGenFunction r (a, b)
sub (a
x0,b
x1) (a
y0,b
y1) =
      (a -> b -> (a, b))
-> CodeGenFunction r a
-> CodeGenFunction r b
-> CodeGenFunction r (a, b)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
sub a
x0 a
y0) (b -> b -> CodeGenFunction r b
forall r. b -> b -> CodeGenFunction r b
forall a r. Additive a => a -> a -> CodeGenFunction r a
sub b
x1 b
y1)
   neg :: forall r. (a, b) -> CodeGenFunction r (a, b)
neg (a
x0,b
x1) =
      (a -> b -> (a, b))
-> CodeGenFunction r a
-> CodeGenFunction r b
-> CodeGenFunction r (a, b)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) (a -> CodeGenFunction r a
forall r. a -> CodeGenFunction r a
forall a r. Additive a => a -> CodeGenFunction r a
neg a
x0)    (b -> CodeGenFunction r b
forall r. b -> CodeGenFunction r b
forall a r. Additive a => a -> CodeGenFunction r a
neg b
x1)

instance (Additive a, Additive b, Additive c) => Additive (a,b,c) where
   zero :: (a, b, c)
zero = (a
forall a. Additive a => a
zero, b
forall a. Additive a => a
zero, c
forall a. Additive a => a
zero)
   add :: forall r. (a, b, c) -> (a, b, c) -> CodeGenFunction r (a, b, c)
add (a
x0,b
x1,c
x2) (a
y0,b
y1,c
y2) =
      (a -> b -> c -> (a, b, c))
-> CodeGenFunction r a
-> CodeGenFunction r b
-> CodeGenFunction r c
-> CodeGenFunction r (a, b, c)
forall (m :: * -> *) a1 a2 a3 r.
Monad m =>
(a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 (,,) (a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
add a
x0 a
y0) (b -> b -> CodeGenFunction r b
forall r. b -> b -> CodeGenFunction r b
forall a r. Additive a => a -> a -> CodeGenFunction r a
add b
x1 b
y1) (c -> c -> CodeGenFunction r c
forall r. c -> c -> CodeGenFunction r c
forall a r. Additive a => a -> a -> CodeGenFunction r a
add c
x2 c
y2)
   sub :: forall r. (a, b, c) -> (a, b, c) -> CodeGenFunction r (a, b, c)
sub (a
x0,b
x1,c
x2) (a
y0,b
y1,c
y2) =
      (a -> b -> c -> (a, b, c))
-> CodeGenFunction r a
-> CodeGenFunction r b
-> CodeGenFunction r c
-> CodeGenFunction r (a, b, c)
forall (m :: * -> *) a1 a2 a3 r.
Monad m =>
(a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 (,,) (a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
sub a
x0 a
y0) (b -> b -> CodeGenFunction r b
forall r. b -> b -> CodeGenFunction r b
forall a r. Additive a => a -> a -> CodeGenFunction r a
sub b
x1 b
y1) (c -> c -> CodeGenFunction r c
forall r. c -> c -> CodeGenFunction r c
forall a r. Additive a => a -> a -> CodeGenFunction r a
sub c
x2 c
y2)
   neg :: forall r. (a, b, c) -> CodeGenFunction r (a, b, c)
neg (a
x0,b
x1,c
x2) =
      (a -> b -> c -> (a, b, c))
-> CodeGenFunction r a
-> CodeGenFunction r b
-> CodeGenFunction r c
-> CodeGenFunction r (a, b, c)
forall (m :: * -> *) a1 a2 a3 r.
Monad m =>
(a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 (,,) (a -> CodeGenFunction r a
forall r. a -> CodeGenFunction r a
forall a r. Additive a => a -> CodeGenFunction r a
neg a
x0)    (b -> CodeGenFunction r b
forall r. b -> CodeGenFunction r b
forall a r. Additive a => a -> CodeGenFunction r a
neg b
x1)    (c -> CodeGenFunction r c
forall r. c -> CodeGenFunction r c
forall a r. Additive a => a -> CodeGenFunction r a
neg c
x2)


class (Additive a) => PseudoRing a where
   mul :: a -> a -> CodeGenFunction r a

instance (IsArithmetic v) => PseudoRing (Value v) where
   mul :: forall r. Value v -> Value v -> CodeGenFunction r (Value v)
mul = Value v -> Value v -> CodeGenFunction r (Value v)
forall a r.
IsArithmetic a =>
Value a -> Value a -> CodeGenFunction r (Value a)
LLVM.mul

instance (IsInteger v) => PseudoRing (ConstValue v) where
   mul :: forall r.
ConstValue v -> ConstValue v -> CodeGenFunction r (ConstValue v)
mul = ConstValue v -> ConstValue v -> CodeGenFunction r (ConstValue v)
ConstValue v
-> ConstValue v
-> CodeGenFunction r (BinOpValue ConstValue ConstValue v)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.imul


type family Scalar vector
type instance Scalar (Value a) = Value (SoV.Scalar a)
type instance Scalar (ConstValue a) = ConstValue (SoV.Scalar a)

class (PseudoRing (Scalar v), Additive v) => PseudoModule v where
   scale :: Scalar v -> v -> CodeGenFunction r v

instance (SoV.PseudoModule v) => PseudoModule (Value v) where
   scale :: forall r.
Scalar (Value v) -> Value v -> CodeGenFunction r (Value v)
scale = Value (Scalar v) -> Value v -> CodeGenFunction r (Value v)
Scalar (Value v) -> Value v -> CodeGenFunction r (Value v)
forall v a r.
(PseudoModule v, a ~ Scalar v) =>
Value a -> Value v -> CodeGenFunction r (Value v)
forall a r.
(a ~ Scalar v) =>
Value a -> Value v -> CodeGenFunction r (Value v)
SoV.scale


class IntegerConstant a where
   fromInteger' :: Integer -> a

instance SoV.IntegerConstant a => IntegerConstant (ConstValue a) where
   fromInteger' :: Integer -> ConstValue a
fromInteger' = Integer -> ConstValue a
forall a. IntegerConstant a => Integer -> ConstValue a
SoV.constFromInteger

instance SoV.IntegerConstant a => IntegerConstant (Value a) where
   fromInteger' :: Integer -> Value a
fromInteger' = ConstValue a -> Value a
forall a. ConstValue a -> Value a
value (ConstValue a -> Value a)
-> (Integer -> ConstValue a) -> Integer -> Value a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> ConstValue a
forall a. IntegerConstant a => Integer -> ConstValue a
SoV.constFromInteger


one :: (IntegerConstant a) => a
one :: forall a. IntegerConstant a => a
one = Integer -> a
forall a. IntegerConstant a => Integer -> a
fromInteger' Integer
1


{-
more general alternative to 'inc',
but you may not like the resulting type constraints
-}
_inc ::
   (PseudoRing a, IntegerConstant a) =>
   a -> CodeGenFunction r a
_inc :: forall a r.
(PseudoRing a, IntegerConstant a) =>
a -> CodeGenFunction r a
_inc a
x = a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
add a
x a
forall a. IntegerConstant a => a
one

_dec ::
   (PseudoRing a, IntegerConstant a) =>
   a -> CodeGenFunction r a
_dec :: forall a r.
(PseudoRing a, IntegerConstant a) =>
a -> CodeGenFunction r a
_dec a
x = a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
sub a
x a
forall a. IntegerConstant a => a
one


square ::
   (PseudoRing a) =>
   a -> CodeGenFunction r a
square :: forall a r. PseudoRing a => a -> CodeGenFunction r a
square a
x = a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. PseudoRing a => a -> a -> CodeGenFunction r a
mul a
x a
x


class (PseudoRing a) => Field a where
   fdiv :: a -> a -> CodeGenFunction r a

instance (LLVM.IsFloating v) => Field (Value v) where
   fdiv :: forall r. Value v -> Value v -> CodeGenFunction r (Value v)
fdiv = Value v -> Value v -> CodeGenFunction r (Value v)
forall a r.
IsFloating a =>
Value a -> Value a -> CodeGenFunction r (Value a)
LLVM.fdiv


class (IntegerConstant a) => RationalConstant a where
   fromRational' :: Rational -> a

instance SoV.RationalConstant a => RationalConstant (ConstValue a) where
   fromRational' :: Rational -> ConstValue a
fromRational' = Rational -> ConstValue a
forall a. RationalConstant a => Rational -> ConstValue a
SoV.constFromRational

instance SoV.RationalConstant a => RationalConstant (Value a) where
   fromRational' :: Rational -> Value a
fromRational' = ConstValue a -> Value a
forall a. ConstValue a -> Value a
value (ConstValue a -> Value a)
-> (Rational -> ConstValue a) -> Rational -> Value a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> ConstValue a
forall a. RationalConstant a => Rational -> ConstValue a
SoV.constFromRational



{- |
In Haskell terms this is a 'quot'.
-}
idiv ::
   (IsInteger a) =>
   Value a -> Value a -> CodeGenFunction r (Value a)
idiv :: forall a r.
IsInteger a =>
Value a -> Value a -> CodeGenFunction r (Value a)
idiv = Value a -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsInteger a =>
Value a -> Value a -> CodeGenFunction r (Value a)
LLVM.idiv

irem ::
   (IsInteger a) =>
   Value a -> Value a -> CodeGenFunction r (Value a)
irem :: forall a r.
IsInteger a =>
Value a -> Value a -> CodeGenFunction r (Value a)
irem = Value a -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsInteger a =>
Value a -> Value a -> CodeGenFunction r (Value a)
LLVM.irem



class (Additive a) => Real a where
   min :: a -> a -> CodeGenFunction r a
   max :: a -> a -> CodeGenFunction r a
   abs :: a -> CodeGenFunction r a
   signum :: a -> CodeGenFunction r a

instance (SoV.Real a) => Real (Value a) where
   min :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
min = Value a -> Value a -> CodeGenFunction r (Value a)
forall r. Value a -> Value a -> CodeGenFunction r (Value a)
forall a r.
Real a =>
Value a -> Value a -> CodeGenFunction r (Value a)
SoV.min
   max :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
max = Value a -> Value a -> CodeGenFunction r (Value a)
forall r. Value a -> Value a -> CodeGenFunction r (Value a)
forall a r.
Real a =>
Value a -> Value a -> CodeGenFunction r (Value a)
SoV.max
   abs :: forall r. Value a -> CodeGenFunction r (Value a)
abs = Value a -> CodeGenFunction r (Value a)
forall r. Value a -> CodeGenFunction r (Value a)
forall a r. Real a => Value a -> CodeGenFunction r (Value a)
SoV.abs
   signum :: forall r. Value a -> CodeGenFunction r (Value a)
signum = Value a -> CodeGenFunction r (Value a)
forall r. Value a -> CodeGenFunction r (Value a)
forall a r. Real a => Value a -> CodeGenFunction r (Value a)
SoV.signum


class (Real a) => Fraction a where
   truncate :: a -> CodeGenFunction r a
   fraction :: a -> CodeGenFunction r a

instance (SoV.Fraction a) => Fraction (Value a) where
   truncate :: forall r. Value a -> CodeGenFunction r (Value a)
truncate = Value a -> CodeGenFunction r (Value a)
forall r. Value a -> CodeGenFunction r (Value a)
forall a r. Fraction a => Value a -> CodeGenFunction r (Value a)
SoV.truncate
   fraction :: forall r. Value a -> CodeGenFunction r (Value a)
fraction = Value a -> CodeGenFunction r (Value a)
forall r. Value a -> CodeGenFunction r (Value a)
forall a r. Fraction a => Value a -> CodeGenFunction r (Value a)
SoV.fraction

signedFraction ::
   (Fraction a) =>
   a -> CodeGenFunction r a
signedFraction :: forall a r. Fraction a => a -> CodeGenFunction r a
signedFraction a
x =
   a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
sub a
x (a -> CodeGenFunction r a)
-> CodeGenFunction r a -> CodeGenFunction r a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> CodeGenFunction r a
forall r. a -> CodeGenFunction r a
forall a r. Fraction a => a -> CodeGenFunction r a
truncate a
x

addToPhase ::
   (Fraction a) =>
   a -> a -> CodeGenFunction r a
addToPhase :: forall a r. Fraction a => a -> a -> CodeGenFunction r a
addToPhase a
d a
p =
   a -> CodeGenFunction r a
forall r. a -> CodeGenFunction r a
forall a r. Fraction a => a -> CodeGenFunction r a
fraction (a -> CodeGenFunction r a)
-> CodeGenFunction r a -> CodeGenFunction r a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
add a
d a
p

{- |
both increment and phase must be non-negative
-}
incPhase ::
   (Fraction a) =>
   a -> a -> CodeGenFunction r a
incPhase :: forall a r. Fraction a => a -> a -> CodeGenFunction r a
incPhase a
d a
p =
   a -> CodeGenFunction r a
forall a r. Fraction a => a -> CodeGenFunction r a
signedFraction (a -> CodeGenFunction r a)
-> CodeGenFunction r a -> CodeGenFunction r a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> a -> CodeGenFunction r a
forall r. a -> a -> CodeGenFunction r a
forall a r. Additive a => a -> a -> CodeGenFunction r a
add a
d a
p


class Comparison a where
   type CmpResult a
   cmp :: LLVM.CmpPredicate -> a -> a -> CodeGenFunction r (CmpResult a)

instance (LLVM.CmpRet a) => Comparison (Value a) where
   type CmpResult (Value a) = Value (LLVM.CmpResult a)
   cmp :: forall r.
CmpPredicate
-> Value a -> Value a -> CodeGenFunction r (CmpResult (Value a))
cmp = CmpPredicate
-> Value a
-> Value a
-> CodeGenFunction r (CmpValueResult Value Value a)
CmpPredicate
-> Value a -> Value a -> CodeGenFunction r (CmpResult (Value a))
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, CmpRet a) =>
CmpPredicate
-> value0 a
-> value1 a
-> CodeGenFunction r (CmpValueResult value0 value1 a)
LLVM.cmp

instance (LLVM.CmpRet a) => Comparison (ConstValue a) where
   type CmpResult (ConstValue a) = ConstValue (LLVM.CmpResult a)
   cmp :: forall r.
CmpPredicate
-> ConstValue a
-> ConstValue a
-> CodeGenFunction r (CmpResult (ConstValue a))
cmp = CmpPredicate
-> ConstValue a
-> ConstValue a
-> CodeGenFunction r (CmpValueResult ConstValue ConstValue a)
CmpPredicate
-> ConstValue a
-> ConstValue a
-> CodeGenFunction r (CmpResult (ConstValue a))
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, CmpRet a) =>
CmpPredicate
-> value0 a
-> value1 a
-> CodeGenFunction r (CmpValueResult value0 value1 a)
LLVM.cmp


class (Comparison a) => FloatingComparison a where
   fcmp :: LLVM.FPPredicate -> a -> a -> CodeGenFunction r (CmpResult a)

instance (IsFloating a, LLVM.CmpRet a) => FloatingComparison (Value a) where
   fcmp :: forall r.
FPPredicate
-> Value a -> Value a -> CodeGenFunction r (CmpResult (Value a))
fcmp = FPPredicate
-> Value a
-> Value a
-> CodeGenFunction r (CmpValueResult Value Value a)
FPPredicate
-> Value a -> Value a -> CodeGenFunction r (CmpResult (Value a))
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, CmpRet a, IsFloating a) =>
FPPredicate
-> value0 a
-> value1 a
-> CodeGenFunction r (CmpValueResult value0 value1 a)
LLVM.fcmp

instance (IsFloating a, LLVM.CmpRet a) => FloatingComparison (ConstValue a) where
   fcmp :: forall r.
FPPredicate
-> ConstValue a
-> ConstValue a
-> CodeGenFunction r (CmpResult (ConstValue a))
fcmp = FPPredicate
-> ConstValue a
-> ConstValue a
-> CodeGenFunction r (CmpValueResult ConstValue ConstValue a)
FPPredicate
-> ConstValue a
-> ConstValue a
-> CodeGenFunction r (CmpResult (ConstValue a))
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, CmpRet a, IsFloating a) =>
FPPredicate
-> value0 a
-> value1 a
-> CodeGenFunction r (CmpValueResult value0 value1 a)
LLVM.fcmp



class Logic a where
   and :: a -> a -> CodeGenFunction r a
   or :: a -> a -> CodeGenFunction r a
   xor :: a -> a -> CodeGenFunction r a
   inv :: a -> CodeGenFunction r a

instance (LLVM.IsInteger a) => Logic (Value a) where
   and :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
and = Value a -> Value a -> CodeGenFunction r (Value a)
Value a -> Value a -> CodeGenFunction r (BinOpValue Value Value a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.and
   or :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
or = Value a -> Value a -> CodeGenFunction r (Value a)
Value a -> Value a -> CodeGenFunction r (BinOpValue Value Value a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.or
   xor :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
xor = Value a -> Value a -> CodeGenFunction r (Value a)
Value a -> Value a -> CodeGenFunction r (BinOpValue Value Value a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.xor
   inv :: forall r. Value a -> CodeGenFunction r (Value a)
inv = Value a -> CodeGenFunction r (Value a)
forall (value :: * -> *) a r.
(ValueCons value, IsInteger a) =>
value a -> CodeGenFunction r (value a)
LLVM.inv

instance (LLVM.IsInteger a) => Logic (ConstValue a) where
   and :: forall r.
ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
and = ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
ConstValue a
-> ConstValue a
-> CodeGenFunction r (BinOpValue ConstValue ConstValue a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.and
   or :: forall r.
ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
or = ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
ConstValue a
-> ConstValue a
-> CodeGenFunction r (BinOpValue ConstValue ConstValue a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.or
   xor :: forall r.
ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
xor = ConstValue a -> ConstValue a -> CodeGenFunction r (ConstValue a)
ConstValue a
-> ConstValue a
-> CodeGenFunction r (BinOpValue ConstValue ConstValue a)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.xor
   inv :: forall r. ConstValue a -> CodeGenFunction r (ConstValue a)
inv = ConstValue a -> CodeGenFunction r (ConstValue a)
forall (value :: * -> *) a r.
(ValueCons value, IsInteger a) =>
value a -> CodeGenFunction r (value a)
LLVM.inv



class Field a => Algebraic a where
   sqrt :: a -> CodeGenFunction r a

instance (IsFloating a) => Algebraic (Value a) where
   sqrt :: forall r. Value a -> CodeGenFunction r (Value a)
sqrt = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"sqrt"


class Algebraic a => Transcendental a where
   pi :: CodeGenFunction r a
   sin, cos, exp, log :: a -> CodeGenFunction r a
   pow :: a -> a -> CodeGenFunction r a

instance (IsFloating a, SoV.TranscendentalConstant a) => Transcendental (Value a) where
   pi :: forall r. CodeGenFunction r (Value a)
pi = Value a -> CodeGenFunction r (Value a)
forall a. a -> CodeGenFunction r a
forall (m :: * -> *) a. Monad m => a -> m a
return (Value a -> CodeGenFunction r (Value a))
-> Value a -> CodeGenFunction r (Value a)
forall a b. (a -> b) -> a -> b
$ ConstValue a -> Value a
forall a. ConstValue a -> Value a
value ConstValue a
forall a. TranscendentalConstant a => ConstValue a
SoV.constPi
   sin :: forall r. Value a -> CodeGenFunction r (Value a)
sin = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"sin"
   cos :: forall r. Value a -> CodeGenFunction r (Value a)
cos = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"cos"
   exp :: forall r. Value a -> CodeGenFunction r (Value a)
exp = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"exp"
   log :: forall r. Value a -> CodeGenFunction r (Value a)
log = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"log"
   pow :: forall r. Value a -> Value a -> CodeGenFunction r (Value a)
pow = String -> Value a -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call2 String
"pow"


exp2 :: (IsFloating a) => Value a -> CodeGenFunction r (Value a)
exp2 :: forall a r. IsFloating a => Value a -> CodeGenFunction r (Value a)
exp2 = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"exp2"

log2 :: (IsFloating a) => Value a -> CodeGenFunction r (Value a)
log2 :: forall a r. IsFloating a => Value a -> CodeGenFunction r (Value a)
log2 = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"log2"

log10 :: (IsFloating a) => Value a -> CodeGenFunction r (Value a)
log10 :: forall a r. IsFloating a => Value a -> CodeGenFunction r (Value a)
log10 = String -> Value a -> CodeGenFunction r (Value a)
forall a r.
IsFirstClass a =>
String -> Value a -> CodeGenFunction r (Value a)
Intrinsic.call1 String
"log10"