{-# LANGUAGE LambdaCase #-}

-- | Definitions of primitive types, the values that inhabit these
-- types, and operations on these values.  A primitive value can also
-- be called a scalar.
--
-- This module diverges from the actual Futhark language in that it
-- does not distinguish signed and unsigned types.  Further, we allow
-- a "unit" type that is only indirectly present in source Futhark in
-- the form of empty tuples.
module Language.Futhark.Primitive
  ( -- * Types
    IntType (..),
    allIntTypes,
    FloatType (..),
    allFloatTypes,
    PrimType (..),
    allPrimTypes,
    module Data.Int,
    module Data.Word,
    Half,

    -- * Values
    IntValue (..),
    intValue,
    intValueType,
    valueIntegral,
    FloatValue (..),
    floatValue,
    floatValueType,
    PrimValue (..),
    primValueType,
    blankPrimValue,

    -- * Operations
    Overflow (..),
    Safety (..),
    UnOp (..),
    allUnOps,
    BinOp (..),
    allBinOps,
    ConvOp (..),
    allConvOps,
    CmpOp (..),
    allCmpOps,

    -- ** Unary Operations
    doUnOp,
    doComplement,
    doAbs,
    doFAbs,
    doSSignum,
    doUSignum,

    -- ** Binary Operations
    doBinOp,
    doAdd,
    doMul,
    doSDiv,
    doSMod,
    doPow,

    -- ** Conversion Operations
    doConvOp,
    doZExt,
    doSExt,
    doFPConv,
    doFPToUI,
    doFPToSI,
    doUIToFP,
    doSIToFP,
    intToInt64,
    intToWord64,
    flipConvOp,

    -- * Comparison Operations
    doCmpOp,
    doCmpEq,
    doCmpUlt,
    doCmpUle,
    doCmpSlt,
    doCmpSle,
    doFCmpLt,
    doFCmpLe,

    -- * Type Of
    binOpType,
    unOpType,
    cmpOpType,
    convOpType,

    -- * Primitive functions
    primFuns,

    -- * Utility
    zeroIsh,
    zeroIshInt,
    oneIsh,
    oneIshInt,
    negativeIsh,
    primBitSize,
    primByteSize,
    intByteSize,
    floatByteSize,
    commutativeBinOp,
    associativeBinOp,

    -- * Prettyprinting
    convOpFun,
    prettySigned,
  )
where

import Control.Category
import Data.Binary.Get qualified as G
import Data.Binary.Put qualified as P
import Data.Bits
  ( complement,
    countLeadingZeros,
    countTrailingZeros,
    popCount,
    shift,
    shiftR,
    xor,
    (.&.),
    (.|.),
  )
import Data.Fixed (mod') -- Weird location.
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Map qualified as M
import Data.Word (Word16, Word32, Word64, Word8)
import Foreign.C.Types (CUShort (..))
import Futhark.Util (convFloat)
import Futhark.Util.CMath
import Futhark.Util.Pretty
import Numeric.Half
import Prelude hiding (id, (.))

-- | An integer type, ordered by size.  Note that signedness is not a
-- property of the type, but a property of the operations performed on
-- values of these types.
data IntType
  = Int8
  | Int16
  | Int32
  | Int64
  deriving (IntType -> IntType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntType -> IntType -> Bool
$c/= :: IntType -> IntType -> Bool
== :: IntType -> IntType -> Bool
$c== :: IntType -> IntType -> Bool
Eq, Eq IntType
IntType -> IntType -> Bool
IntType -> IntType -> Ordering
IntType -> IntType -> IntType
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
min :: IntType -> IntType -> IntType
$cmin :: IntType -> IntType -> IntType
max :: IntType -> IntType -> IntType
$cmax :: IntType -> IntType -> IntType
>= :: IntType -> IntType -> Bool
$c>= :: IntType -> IntType -> Bool
> :: IntType -> IntType -> Bool
$c> :: IntType -> IntType -> Bool
<= :: IntType -> IntType -> Bool
$c<= :: IntType -> IntType -> Bool
< :: IntType -> IntType -> Bool
$c< :: IntType -> IntType -> Bool
compare :: IntType -> IntType -> Ordering
$ccompare :: IntType -> IntType -> Ordering
Ord, Int -> IntType -> ShowS
[IntType] -> ShowS
IntType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntType] -> ShowS
$cshowList :: [IntType] -> ShowS
show :: IntType -> String
$cshow :: IntType -> String
showsPrec :: Int -> IntType -> ShowS
$cshowsPrec :: Int -> IntType -> ShowS
Show, Int -> IntType
IntType -> Int
IntType -> [IntType]
IntType -> IntType
IntType -> IntType -> [IntType]
IntType -> IntType -> IntType -> [IntType]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: IntType -> IntType -> IntType -> [IntType]
$cenumFromThenTo :: IntType -> IntType -> IntType -> [IntType]
enumFromTo :: IntType -> IntType -> [IntType]
$cenumFromTo :: IntType -> IntType -> [IntType]
enumFromThen :: IntType -> IntType -> [IntType]
$cenumFromThen :: IntType -> IntType -> [IntType]
enumFrom :: IntType -> [IntType]
$cenumFrom :: IntType -> [IntType]
fromEnum :: IntType -> Int
$cfromEnum :: IntType -> Int
toEnum :: Int -> IntType
$ctoEnum :: Int -> IntType
pred :: IntType -> IntType
$cpred :: IntType -> IntType
succ :: IntType -> IntType
$csucc :: IntType -> IntType
Enum, IntType
forall a. a -> a -> Bounded a
maxBound :: IntType
$cmaxBound :: IntType
minBound :: IntType
$cminBound :: IntType
Bounded)

instance Pretty IntType where
  pretty :: forall ann. IntType -> Doc ann
pretty IntType
Int8 = Doc ann
"i8"
  pretty IntType
Int16 = Doc ann
"i16"
  pretty IntType
Int32 = Doc ann
"i32"
  pretty IntType
Int64 = Doc ann
"i64"

-- | A list of all integer types.
allIntTypes :: [IntType]
allIntTypes :: [IntType]
allIntTypes = [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]

-- | A floating point type.
data FloatType
  = Float16
  | Float32
  | Float64
  deriving (FloatType -> FloatType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FloatType -> FloatType -> Bool
$c/= :: FloatType -> FloatType -> Bool
== :: FloatType -> FloatType -> Bool
$c== :: FloatType -> FloatType -> Bool
Eq, Eq FloatType
FloatType -> FloatType -> Bool
FloatType -> FloatType -> Ordering
FloatType -> FloatType -> FloatType
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
min :: FloatType -> FloatType -> FloatType
$cmin :: FloatType -> FloatType -> FloatType
max :: FloatType -> FloatType -> FloatType
$cmax :: FloatType -> FloatType -> FloatType
>= :: FloatType -> FloatType -> Bool
$c>= :: FloatType -> FloatType -> Bool
> :: FloatType -> FloatType -> Bool
$c> :: FloatType -> FloatType -> Bool
<= :: FloatType -> FloatType -> Bool
$c<= :: FloatType -> FloatType -> Bool
< :: FloatType -> FloatType -> Bool
$c< :: FloatType -> FloatType -> Bool
compare :: FloatType -> FloatType -> Ordering
$ccompare :: FloatType -> FloatType -> Ordering
Ord, Int -> FloatType -> ShowS
[FloatType] -> ShowS
FloatType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FloatType] -> ShowS
$cshowList :: [FloatType] -> ShowS
show :: FloatType -> String
$cshow :: FloatType -> String
showsPrec :: Int -> FloatType -> ShowS
$cshowsPrec :: Int -> FloatType -> ShowS
Show, Int -> FloatType
FloatType -> Int
FloatType -> [FloatType]
FloatType -> FloatType
FloatType -> FloatType -> [FloatType]
FloatType -> FloatType -> FloatType -> [FloatType]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: FloatType -> FloatType -> FloatType -> [FloatType]
$cenumFromThenTo :: FloatType -> FloatType -> FloatType -> [FloatType]
enumFromTo :: FloatType -> FloatType -> [FloatType]
$cenumFromTo :: FloatType -> FloatType -> [FloatType]
enumFromThen :: FloatType -> FloatType -> [FloatType]
$cenumFromThen :: FloatType -> FloatType -> [FloatType]
enumFrom :: FloatType -> [FloatType]
$cenumFrom :: FloatType -> [FloatType]
fromEnum :: FloatType -> Int
$cfromEnum :: FloatType -> Int
toEnum :: Int -> FloatType
$ctoEnum :: Int -> FloatType
pred :: FloatType -> FloatType
$cpred :: FloatType -> FloatType
succ :: FloatType -> FloatType
$csucc :: FloatType -> FloatType
Enum, FloatType
forall a. a -> a -> Bounded a
maxBound :: FloatType
$cmaxBound :: FloatType
minBound :: FloatType
$cminBound :: FloatType
Bounded)

instance Pretty FloatType where
  pretty :: forall ann. FloatType -> Doc ann
pretty FloatType
Float16 = Doc ann
"f16"
  pretty FloatType
Float32 = Doc ann
"f32"
  pretty FloatType
Float64 = Doc ann
"f64"

-- | A list of all floating-point types.
allFloatTypes :: [FloatType]
allFloatTypes :: [FloatType]
allFloatTypes = [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]

-- | Low-level primitive types.
data PrimType
  = IntType IntType
  | FloatType FloatType
  | Bool
  | -- | An informationless type - An array of this type takes up no space.
    Unit
  deriving (PrimType -> PrimType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrimType -> PrimType -> Bool
$c/= :: PrimType -> PrimType -> Bool
== :: PrimType -> PrimType -> Bool
$c== :: PrimType -> PrimType -> Bool
Eq, Eq PrimType
PrimType -> PrimType -> Bool
PrimType -> PrimType -> Ordering
PrimType -> PrimType -> PrimType
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
min :: PrimType -> PrimType -> PrimType
$cmin :: PrimType -> PrimType -> PrimType
max :: PrimType -> PrimType -> PrimType
$cmax :: PrimType -> PrimType -> PrimType
>= :: PrimType -> PrimType -> Bool
$c>= :: PrimType -> PrimType -> Bool
> :: PrimType -> PrimType -> Bool
$c> :: PrimType -> PrimType -> Bool
<= :: PrimType -> PrimType -> Bool
$c<= :: PrimType -> PrimType -> Bool
< :: PrimType -> PrimType -> Bool
$c< :: PrimType -> PrimType -> Bool
compare :: PrimType -> PrimType -> Ordering
$ccompare :: PrimType -> PrimType -> Ordering
Ord, Int -> PrimType -> ShowS
[PrimType] -> ShowS
PrimType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PrimType] -> ShowS
$cshowList :: [PrimType] -> ShowS
show :: PrimType -> String
$cshow :: PrimType -> String
showsPrec :: Int -> PrimType -> ShowS
$cshowsPrec :: Int -> PrimType -> ShowS
Show)

instance Enum PrimType where
  toEnum :: Int -> PrimType
toEnum Int
0 = IntType -> PrimType
IntType IntType
Int8
  toEnum Int
1 = IntType -> PrimType
IntType IntType
Int16
  toEnum Int
2 = IntType -> PrimType
IntType IntType
Int32
  toEnum Int
3 = IntType -> PrimType
IntType IntType
Int64
  toEnum Int
4 = FloatType -> PrimType
FloatType FloatType
Float16
  toEnum Int
5 = FloatType -> PrimType
FloatType FloatType
Float32
  toEnum Int
6 = FloatType -> PrimType
FloatType FloatType
Float64
  toEnum Int
7 = PrimType
Bool
  toEnum Int
_ = PrimType
Unit

  fromEnum :: PrimType -> Int
fromEnum (IntType IntType
Int8) = Int
0
  fromEnum (IntType IntType
Int16) = Int
1
  fromEnum (IntType IntType
Int32) = Int
2
  fromEnum (IntType IntType
Int64) = Int
3
  fromEnum (FloatType FloatType
Float16) = Int
4
  fromEnum (FloatType FloatType
Float32) = Int
5
  fromEnum (FloatType FloatType
Float64) = Int
6
  fromEnum PrimType
Bool = Int
7
  fromEnum PrimType
Unit = Int
8

instance Bounded PrimType where
  minBound :: PrimType
minBound = IntType -> PrimType
IntType IntType
Int8
  maxBound :: PrimType
maxBound = PrimType
Unit

instance Pretty PrimType where
  pretty :: forall ann. PrimType -> Doc ann
pretty (IntType IntType
t) = forall a ann. Pretty a => a -> Doc ann
pretty IntType
t
  pretty (FloatType FloatType
t) = forall a ann. Pretty a => a -> Doc ann
pretty FloatType
t
  pretty PrimType
Bool = Doc ann
"bool"
  pretty PrimType
Unit = Doc ann
"unit"

-- | A list of all primitive types.
allPrimTypes :: [PrimType]
allPrimTypes :: [PrimType]
allPrimTypes =
  forall a b. (a -> b) -> [a] -> [b]
map IntType -> PrimType
IntType [IntType]
allIntTypes
    forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map FloatType -> PrimType
FloatType [FloatType]
allFloatTypes
    forall a. [a] -> [a] -> [a]
++ [PrimType
Bool, PrimType
Unit]

-- | An integer value.
data IntValue
  = Int8Value !Int8
  | Int16Value !Int16
  | Int32Value !Int32
  | Int64Value !Int64
  deriving (IntValue -> IntValue -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IntValue -> IntValue -> Bool
$c/= :: IntValue -> IntValue -> Bool
== :: IntValue -> IntValue -> Bool
$c== :: IntValue -> IntValue -> Bool
Eq, Eq IntValue
IntValue -> IntValue -> Bool
IntValue -> IntValue -> Ordering
IntValue -> IntValue -> IntValue
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
min :: IntValue -> IntValue -> IntValue
$cmin :: IntValue -> IntValue -> IntValue
max :: IntValue -> IntValue -> IntValue
$cmax :: IntValue -> IntValue -> IntValue
>= :: IntValue -> IntValue -> Bool
$c>= :: IntValue -> IntValue -> Bool
> :: IntValue -> IntValue -> Bool
$c> :: IntValue -> IntValue -> Bool
<= :: IntValue -> IntValue -> Bool
$c<= :: IntValue -> IntValue -> Bool
< :: IntValue -> IntValue -> Bool
$c< :: IntValue -> IntValue -> Bool
compare :: IntValue -> IntValue -> Ordering
$ccompare :: IntValue -> IntValue -> Ordering
Ord, Int -> IntValue -> ShowS
[IntValue] -> ShowS
IntValue -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IntValue] -> ShowS
$cshowList :: [IntValue] -> ShowS
show :: IntValue -> String
$cshow :: IntValue -> String
showsPrec :: Int -> IntValue -> ShowS
$cshowsPrec :: Int -> IntValue -> ShowS
Show)

instance Pretty IntValue where
  pretty :: forall ann. IntValue -> Doc ann
pretty (Int8Value Int8
v) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int8
v forall a. [a] -> [a] -> [a]
++ String
"i8"
  pretty (Int16Value Int16
v) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int16
v forall a. [a] -> [a] -> [a]
++ String
"i16"
  pretty (Int32Value Int32
v) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int32
v forall a. [a] -> [a] -> [a]
++ String
"i32"
  pretty (Int64Value Int64
v) = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int64
v forall a. [a] -> [a] -> [a]
++ String
"i64"

-- | Create an t'IntValue' from a type and an 'Integer'.
intValue :: Integral int => IntType -> int -> IntValue
intValue :: forall int. Integral int => IntType -> int -> IntValue
intValue IntType
Int8 = Int8 -> IntValue
Int8Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral
intValue IntType
Int16 = Int16 -> IntValue
Int16Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral
intValue IntType
Int32 = Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral
intValue IntType
Int64 = Int64 -> IntValue
Int64Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral

-- | The type of an integer value.
intValueType :: IntValue -> IntType
intValueType :: IntValue -> IntType
intValueType Int8Value {} = IntType
Int8
intValueType Int16Value {} = IntType
Int16
intValueType Int32Value {} = IntType
Int32
intValueType Int64Value {} = IntType
Int64

-- | Convert an t'IntValue' to any 'Integral' type.
valueIntegral :: Integral int => IntValue -> int
valueIntegral :: forall int. Integral int => IntValue -> int
valueIntegral (Int8Value Int8
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
v
valueIntegral (Int16Value Int16
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
v
valueIntegral (Int32Value Int32
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
v
valueIntegral (Int64Value Int64
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
v

-- | A floating-point value.
data FloatValue
  = Float16Value !Half
  | Float32Value !Float
  | Float64Value !Double
  deriving (Int -> FloatValue -> ShowS
[FloatValue] -> ShowS
FloatValue -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FloatValue] -> ShowS
$cshowList :: [FloatValue] -> ShowS
show :: FloatValue -> String
$cshow :: FloatValue -> String
showsPrec :: Int -> FloatValue -> ShowS
$cshowsPrec :: Int -> FloatValue -> ShowS
Show)

instance Eq FloatValue where
  Float16Value Half
x == :: FloatValue -> FloatValue -> Bool
== Float16Value Half
y = forall a. RealFloat a => a -> Bool
isNaN Half
x Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNaN Half
y Bool -> Bool -> Bool
|| Half
x forall a. Eq a => a -> a -> Bool
== Half
y
  Float32Value Float
x == Float32Value Float
y = forall a. RealFloat a => a -> Bool
isNaN Float
x Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNaN Float
y Bool -> Bool -> Bool
|| Float
x forall a. Eq a => a -> a -> Bool
== Float
y
  Float64Value Double
x == Float64Value Double
y = forall a. RealFloat a => a -> Bool
isNaN Double
x Bool -> Bool -> Bool
&& forall a. RealFloat a => a -> Bool
isNaN Double
y Bool -> Bool -> Bool
|| Double
x forall a. Eq a => a -> a -> Bool
== Double
y
  FloatValue
_ == FloatValue
_ = Bool
False

-- The derived Ord instance does not handle NaNs correctly.
instance Ord FloatValue where
  Float16Value Half
x <= :: FloatValue -> FloatValue -> Bool
<= Float16Value Half
y = Half
x forall a. Ord a => a -> a -> Bool
<= Half
y
  Float32Value Float
x <= Float32Value Float
y = Float
x forall a. Ord a => a -> a -> Bool
<= Float
y
  Float64Value Double
x <= Float64Value Double
y = Double
x forall a. Ord a => a -> a -> Bool
<= Double
y
  Float16Value Half
_ <= Float32Value Float
_ = Bool
True
  Float16Value Half
_ <= Float64Value Double
_ = Bool
True
  Float32Value Float
_ <= Float16Value Half
_ = Bool
False
  Float32Value Float
_ <= Float64Value Double
_ = Bool
True
  Float64Value Double
_ <= Float16Value Half
_ = Bool
False
  Float64Value Double
_ <= Float32Value Float
_ = Bool
False

  Float16Value Half
x < :: FloatValue -> FloatValue -> Bool
< Float16Value Half
y = Half
x forall a. Ord a => a -> a -> Bool
< Half
y
  Float32Value Float
x < Float32Value Float
y = Float
x forall a. Ord a => a -> a -> Bool
< Float
y
  Float64Value Double
x < Float64Value Double
y = Double
x forall a. Ord a => a -> a -> Bool
< Double
y
  Float16Value Half
_ < Float32Value Float
_ = Bool
True
  Float16Value Half
_ < Float64Value Double
_ = Bool
True
  Float32Value Float
_ < Float16Value Half
_ = Bool
False
  Float32Value Float
_ < Float64Value Double
_ = Bool
True
  Float64Value Double
_ < Float16Value Half
_ = Bool
False
  Float64Value Double
_ < Float32Value Float
_ = Bool
False

  > :: FloatValue -> FloatValue -> Bool
(>) = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Ord a => a -> a -> Bool
(<)
  >= :: FloatValue -> FloatValue -> Bool
(>=) = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Ord a => a -> a -> Bool
(<=)

instance Pretty FloatValue where
  pretty :: forall ann. FloatValue -> Doc ann
pretty (Float16Value Half
v)
    | forall a. RealFloat a => a -> Bool
isInfinite Half
v, Half
v forall a. Ord a => a -> a -> Bool
>= Half
0 = Doc ann
"f16.inf"
    | forall a. RealFloat a => a -> Bool
isInfinite Half
v, Half
v forall a. Ord a => a -> a -> Bool
< Half
0 = Doc ann
"-f16.inf"
    | forall a. RealFloat a => a -> Bool
isNaN Half
v = Doc ann
"f16.nan"
    | Bool
otherwise = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Half
v forall a. [a] -> [a] -> [a]
++ String
"f16"
  pretty (Float32Value Float
v)
    | forall a. RealFloat a => a -> Bool
isInfinite Float
v, Float
v forall a. Ord a => a -> a -> Bool
>= Float
0 = Doc ann
"f32.inf"
    | forall a. RealFloat a => a -> Bool
isInfinite Float
v, Float
v forall a. Ord a => a -> a -> Bool
< Float
0 = Doc ann
"-f32.inf"
    | forall a. RealFloat a => a -> Bool
isNaN Float
v = Doc ann
"f32.nan"
    | Bool
otherwise = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Float
v forall a. [a] -> [a] -> [a]
++ String
"f32"
  pretty (Float64Value Double
v)
    | forall a. RealFloat a => a -> Bool
isInfinite Double
v, Double
v forall a. Ord a => a -> a -> Bool
>= Double
0 = Doc ann
"f64.inf"
    | forall a. RealFloat a => a -> Bool
isInfinite Double
v, Double
v forall a. Ord a => a -> a -> Bool
< Double
0 = Doc ann
"-f64.inf"
    | forall a. RealFloat a => a -> Bool
isNaN Double
v = Doc ann
"f64.nan"
    | Bool
otherwise = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Double
v forall a. [a] -> [a] -> [a]
++ String
"f64"

-- | Create a t'FloatValue' from a type and a 'Rational'.
floatValue :: Real num => FloatType -> num -> FloatValue
floatValue :: forall num. Real num => FloatType -> num -> FloatValue
floatValue FloatType
Float16 = Half -> FloatValue
Float16Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Fractional a => Rational -> a
fromRational forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Real a => a -> Rational
toRational
floatValue FloatType
Float32 = Float -> FloatValue
Float32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Fractional a => Rational -> a
fromRational forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Real a => a -> Rational
toRational
floatValue FloatType
Float64 = Double -> FloatValue
Float64Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Fractional a => Rational -> a
fromRational forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Real a => a -> Rational
toRational

-- | The type of a floating-point value.
floatValueType :: FloatValue -> FloatType
floatValueType :: FloatValue -> FloatType
floatValueType Float16Value {} = FloatType
Float16
floatValueType Float32Value {} = FloatType
Float32
floatValueType Float64Value {} = FloatType
Float64

-- | Non-array values.
data PrimValue
  = IntValue !IntValue
  | FloatValue !FloatValue
  | BoolValue !Bool
  | -- | The only value of type 'Unit'.
    UnitValue
  deriving (PrimValue -> PrimValue -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrimValue -> PrimValue -> Bool
$c/= :: PrimValue -> PrimValue -> Bool
== :: PrimValue -> PrimValue -> Bool
$c== :: PrimValue -> PrimValue -> Bool
Eq, Eq PrimValue
PrimValue -> PrimValue -> Bool
PrimValue -> PrimValue -> Ordering
PrimValue -> PrimValue -> PrimValue
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
min :: PrimValue -> PrimValue -> PrimValue
$cmin :: PrimValue -> PrimValue -> PrimValue
max :: PrimValue -> PrimValue -> PrimValue
$cmax :: PrimValue -> PrimValue -> PrimValue
>= :: PrimValue -> PrimValue -> Bool
$c>= :: PrimValue -> PrimValue -> Bool
> :: PrimValue -> PrimValue -> Bool
$c> :: PrimValue -> PrimValue -> Bool
<= :: PrimValue -> PrimValue -> Bool
$c<= :: PrimValue -> PrimValue -> Bool
< :: PrimValue -> PrimValue -> Bool
$c< :: PrimValue -> PrimValue -> Bool
compare :: PrimValue -> PrimValue -> Ordering
$ccompare :: PrimValue -> PrimValue -> Ordering
Ord, Int -> PrimValue -> ShowS
[PrimValue] -> ShowS
PrimValue -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PrimValue] -> ShowS
$cshowList :: [PrimValue] -> ShowS
show :: PrimValue -> String
$cshow :: PrimValue -> String
showsPrec :: Int -> PrimValue -> ShowS
$cshowsPrec :: Int -> PrimValue -> ShowS
Show)

instance Pretty PrimValue where
  pretty :: forall ann. PrimValue -> Doc ann
pretty (IntValue IntValue
v) = forall a ann. Pretty a => a -> Doc ann
pretty IntValue
v
  pretty (BoolValue Bool
True) = Doc ann
"true"
  pretty (BoolValue Bool
False) = Doc ann
"false"
  pretty (FloatValue FloatValue
v) = forall a ann. Pretty a => a -> Doc ann
pretty FloatValue
v
  pretty PrimValue
UnitValue = Doc ann
"()"

-- | The type of a basic value.
primValueType :: PrimValue -> PrimType
primValueType :: PrimValue -> PrimType
primValueType (IntValue IntValue
v) = IntType -> PrimType
IntType forall a b. (a -> b) -> a -> b
$ IntValue -> IntType
intValueType IntValue
v
primValueType (FloatValue FloatValue
v) = FloatType -> PrimType
FloatType forall a b. (a -> b) -> a -> b
$ FloatValue -> FloatType
floatValueType FloatValue
v
primValueType BoolValue {} = PrimType
Bool
primValueType PrimValue
UnitValue = PrimType
Unit

-- | A "blank" value of the given primitive type - this is zero, or
-- whatever is close to it.  Don't depend on this value, but use it
-- for e.g. creating arrays to be populated by do-loops.
blankPrimValue :: PrimType -> PrimValue
blankPrimValue :: PrimType -> PrimValue
blankPrimValue (IntType IntType
Int8) = IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ Int8 -> IntValue
Int8Value Int8
0
blankPrimValue (IntType IntType
Int16) = IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ Int16 -> IntValue
Int16Value Int16
0
blankPrimValue (IntType IntType
Int32) = IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ Int32 -> IntValue
Int32Value Int32
0
blankPrimValue (IntType IntType
Int64) = IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ Int64 -> IntValue
Int64Value Int64
0
blankPrimValue (FloatType FloatType
Float16) = FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value Half
0.0
blankPrimValue (FloatType FloatType
Float32) = FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value Float
0.0
blankPrimValue (FloatType FloatType
Float64) = FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value Double
0.0
blankPrimValue PrimType
Bool = Bool -> PrimValue
BoolValue Bool
False
blankPrimValue PrimType
Unit = PrimValue
UnitValue

-- | Various unary operators.  It is a bit ad-hoc what is a unary
-- operator and what is a built-in function.  Perhaps these should all
-- go away eventually.
data UnOp
  = -- | E.g., @! True == False@.
    Not
  | -- | E.g., @~(~1) = 1@.
    Complement IntType
  | -- | @abs(-2) = 2@.
    Abs IntType
  | -- | @fabs(-2.0) = 2.0@.
    FAbs FloatType
  | -- | Signed sign function: @ssignum(-2)@ = -1.
    SSignum IntType
  | -- | Unsigned sign function: @usignum(2)@ = 1.
    USignum IntType
  | -- | Floating-point sign function.
    FSignum FloatType
  deriving (UnOp -> UnOp -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UnOp -> UnOp -> Bool
$c/= :: UnOp -> UnOp -> Bool
== :: UnOp -> UnOp -> Bool
$c== :: UnOp -> UnOp -> Bool
Eq, Eq UnOp
UnOp -> UnOp -> Bool
UnOp -> UnOp -> Ordering
UnOp -> UnOp -> UnOp
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
min :: UnOp -> UnOp -> UnOp
$cmin :: UnOp -> UnOp -> UnOp
max :: UnOp -> UnOp -> UnOp
$cmax :: UnOp -> UnOp -> UnOp
>= :: UnOp -> UnOp -> Bool
$c>= :: UnOp -> UnOp -> Bool
> :: UnOp -> UnOp -> Bool
$c> :: UnOp -> UnOp -> Bool
<= :: UnOp -> UnOp -> Bool
$c<= :: UnOp -> UnOp -> Bool
< :: UnOp -> UnOp -> Bool
$c< :: UnOp -> UnOp -> Bool
compare :: UnOp -> UnOp -> Ordering
$ccompare :: UnOp -> UnOp -> Ordering
Ord, Int -> UnOp -> ShowS
[UnOp] -> ShowS
UnOp -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UnOp] -> ShowS
$cshowList :: [UnOp] -> ShowS
show :: UnOp -> String
$cshow :: UnOp -> String
showsPrec :: Int -> UnOp -> ShowS
$cshowsPrec :: Int -> UnOp -> ShowS
Show)

-- | What to do in case of arithmetic overflow.  Futhark's semantics
-- are that overflow does wraparound, but for generated code (like
-- address arithmetic), it can be beneficial for overflow to be
-- undefined behaviour, as it allows better optimisation of things
-- such as GPU kernels.
--
-- Note that all values of this type are considered equal for 'Eq' and
-- 'Ord'.
data Overflow = OverflowWrap | OverflowUndef
  deriving (Int -> Overflow -> ShowS
[Overflow] -> ShowS
Overflow -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Overflow] -> ShowS
$cshowList :: [Overflow] -> ShowS
show :: Overflow -> String
$cshow :: Overflow -> String
showsPrec :: Int -> Overflow -> ShowS
$cshowsPrec :: Int -> Overflow -> ShowS
Show)

instance Eq Overflow where
  Overflow
_ == :: Overflow -> Overflow -> Bool
== Overflow
_ = Bool
True

instance Ord Overflow where
  Overflow
_ compare :: Overflow -> Overflow -> Ordering
`compare` Overflow
_ = Ordering
EQ

-- | Whether something is safe or unsafe (mostly function calls, and
-- in the context of whether operations are dynamically checked).
-- When we inline an 'Unsafe' function, we remove all safety checks in
-- its body.  The 'Ord' instance picks 'Unsafe' as being less than
-- 'Safe'.
--
-- For operations like integer division, a safe division will not
-- explode the computer in case of division by zero, but instead
-- return some unspecified value.  This always involves a run-time
-- check, so generally the unsafe variant is what the compiler will
-- insert, but guarded by an explicit assertion elsewhere.  Safe
-- operations are useful when the optimiser wants to move e.g. a
-- division to a location where the divisor may be zero, but where the
-- result will only be used when it is non-zero (so it doesn't matter
-- what result is provided with a zero divisor, as long as the program
-- keeps running).
data Safety = Unsafe | Safe deriving (Safety -> Safety -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Safety -> Safety -> Bool
$c/= :: Safety -> Safety -> Bool
== :: Safety -> Safety -> Bool
$c== :: Safety -> Safety -> Bool
Eq, Eq Safety
Safety -> Safety -> Bool
Safety -> Safety -> Ordering
Safety -> Safety -> Safety
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
min :: Safety -> Safety -> Safety
$cmin :: Safety -> Safety -> Safety
max :: Safety -> Safety -> Safety
$cmax :: Safety -> Safety -> Safety
>= :: Safety -> Safety -> Bool
$c>= :: Safety -> Safety -> Bool
> :: Safety -> Safety -> Bool
$c> :: Safety -> Safety -> Bool
<= :: Safety -> Safety -> Bool
$c<= :: Safety -> Safety -> Bool
< :: Safety -> Safety -> Bool
$c< :: Safety -> Safety -> Bool
compare :: Safety -> Safety -> Ordering
$ccompare :: Safety -> Safety -> Ordering
Ord, Int -> Safety -> ShowS
[Safety] -> ShowS
Safety -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Safety] -> ShowS
$cshowList :: [Safety] -> ShowS
show :: Safety -> String
$cshow :: Safety -> String
showsPrec :: Int -> Safety -> ShowS
$cshowsPrec :: Int -> Safety -> ShowS
Show)

-- | Binary operators.  These correspond closely to the binary operators in
-- LLVM.  Most are parametrised by their expected input and output
-- types.
data BinOp
  = -- | Integer addition.
    Add IntType Overflow
  | -- | Floating-point addition.
    FAdd FloatType
  | -- | Integer subtraction.
    Sub IntType Overflow
  | -- | Floating-point subtraction.
    FSub FloatType
  | -- | Integer multiplication.
    Mul IntType Overflow
  | -- | Floating-point multiplication.
    FMul FloatType
  | -- | Unsigned integer division.  Rounds towards
    -- negativity infinity.  Note: this is different
    -- from LLVM.
    UDiv IntType Safety
  | -- | Unsigned integer division.  Rounds towards positive
    -- infinity.
    UDivUp IntType Safety
  | -- | Signed integer division.  Rounds towards
    -- negativity infinity.  Note: this is different
    -- from LLVM.
    SDiv IntType Safety
  | -- | Signed integer division.  Rounds towards positive
    -- infinity.
    SDivUp IntType Safety
  | -- | Floating-point division.
    FDiv FloatType
  | -- | Floating-point modulus.
    FMod FloatType
  | -- | Unsigned integer modulus; the countepart to 'UDiv'.
    UMod IntType Safety
  | -- | Signed integer modulus; the countepart to 'SDiv'.
    SMod IntType Safety
  | -- | Signed integer division.  Rounds towards zero.  This
    -- corresponds to the @sdiv@ instruction in LLVM and
    -- integer division in C.
    SQuot IntType Safety
  | -- | Signed integer division.  Rounds towards zero.  This
    -- corresponds to the @srem@ instruction in LLVM and
    -- integer modulo in C.
    SRem IntType Safety
  | -- | Returns the smallest of two signed integers.
    SMin IntType
  | -- | Returns the smallest of two unsigned integers.
    UMin IntType
  | -- | Returns the smallest of two floating-point numbers.
    FMin FloatType
  | -- | Returns the greatest of two signed integers.
    SMax IntType
  | -- | Returns the greatest of two unsigned integers.
    UMax IntType
  | -- | Returns the greatest of two floating-point numbers.
    FMax FloatType
  | -- | Left-shift.
    Shl IntType
  | -- | Logical right-shift, zero-extended.
    LShr IntType
  | -- | Arithmetic right-shift, sign-extended.
    AShr IntType
  | -- | Bitwise and.
    And IntType
  | -- | Bitwise or.
    Or IntType
  | -- | Bitwise exclusive-or.
    Xor IntType
  | -- | Integer exponentiation.
    Pow IntType
  | -- | Floating-point exponentiation.
    FPow FloatType
  | -- | Boolean and - not short-circuiting.
    LogAnd
  | -- | Boolean or - not short-circuiting.
    LogOr
  deriving (BinOp -> BinOp -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BinOp -> BinOp -> Bool
$c/= :: BinOp -> BinOp -> Bool
== :: BinOp -> BinOp -> Bool
$c== :: BinOp -> BinOp -> Bool
Eq, Eq BinOp
BinOp -> BinOp -> Bool
BinOp -> BinOp -> Ordering
BinOp -> BinOp -> BinOp
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
min :: BinOp -> BinOp -> BinOp
$cmin :: BinOp -> BinOp -> BinOp
max :: BinOp -> BinOp -> BinOp
$cmax :: BinOp -> BinOp -> BinOp
>= :: BinOp -> BinOp -> Bool
$c>= :: BinOp -> BinOp -> Bool
> :: BinOp -> BinOp -> Bool
$c> :: BinOp -> BinOp -> Bool
<= :: BinOp -> BinOp -> Bool
$c<= :: BinOp -> BinOp -> Bool
< :: BinOp -> BinOp -> Bool
$c< :: BinOp -> BinOp -> Bool
compare :: BinOp -> BinOp -> Ordering
$ccompare :: BinOp -> BinOp -> Ordering
Ord, Int -> BinOp -> ShowS
[BinOp] -> ShowS
BinOp -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BinOp] -> ShowS
$cshowList :: [BinOp] -> ShowS
show :: BinOp -> String
$cshow :: BinOp -> String
showsPrec :: Int -> BinOp -> ShowS
$cshowsPrec :: Int -> BinOp -> ShowS
Show)

-- | Comparison operators are like 'BinOp's, but they always return a
-- boolean value.  The somewhat ugly constructor names are straight
-- out of LLVM.
data CmpOp
  = -- | All types equality.
    CmpEq PrimType
  | -- | Unsigned less than.
    CmpUlt IntType
  | -- | Unsigned less than or equal.
    CmpUle IntType
  | -- | Signed less than.
    CmpSlt IntType
  | -- | Signed less than or equal.
    CmpSle IntType
  | -- Comparison operators for floating-point values.  TODO: extend
    -- this to handle NaNs and such, like the LLVM fcmp instruction.

    -- | Floating-point less than.
    FCmpLt FloatType
  | -- | Floating-point less than or equal.
    FCmpLe FloatType
  | -- Boolean comparison.

    -- | Boolean less than.
    CmpLlt
  | -- | Boolean less than or equal.
    CmpLle
  deriving (CmpOp -> CmpOp -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CmpOp -> CmpOp -> Bool
$c/= :: CmpOp -> CmpOp -> Bool
== :: CmpOp -> CmpOp -> Bool
$c== :: CmpOp -> CmpOp -> Bool
Eq, Eq CmpOp
CmpOp -> CmpOp -> Bool
CmpOp -> CmpOp -> Ordering
CmpOp -> CmpOp -> CmpOp
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
min :: CmpOp -> CmpOp -> CmpOp
$cmin :: CmpOp -> CmpOp -> CmpOp
max :: CmpOp -> CmpOp -> CmpOp
$cmax :: CmpOp -> CmpOp -> CmpOp
>= :: CmpOp -> CmpOp -> Bool
$c>= :: CmpOp -> CmpOp -> Bool
> :: CmpOp -> CmpOp -> Bool
$c> :: CmpOp -> CmpOp -> Bool
<= :: CmpOp -> CmpOp -> Bool
$c<= :: CmpOp -> CmpOp -> Bool
< :: CmpOp -> CmpOp -> Bool
$c< :: CmpOp -> CmpOp -> Bool
compare :: CmpOp -> CmpOp -> Ordering
$ccompare :: CmpOp -> CmpOp -> Ordering
Ord, Int -> CmpOp -> ShowS
[CmpOp] -> ShowS
CmpOp -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CmpOp] -> ShowS
$cshowList :: [CmpOp] -> ShowS
show :: CmpOp -> String
$cshow :: CmpOp -> String
showsPrec :: Int -> CmpOp -> ShowS
$cshowsPrec :: Int -> CmpOp -> ShowS
Show)

-- | Conversion operators try to generalise the @from t0 x to t1@
-- instructions from LLVM.
data ConvOp
  = -- | Zero-extend the former integer type to the latter.
    -- If the new type is smaller, the result is a
    -- truncation.
    ZExt IntType IntType
  | -- | Sign-extend the former integer type to the latter.
    -- If the new type is smaller, the result is a
    -- truncation.
    SExt IntType IntType
  | -- | Convert value of the former floating-point type to
    -- the latter.  If the new type is smaller, the result
    -- is a truncation.
    FPConv FloatType FloatType
  | -- | Convert a floating-point value to the nearest
    -- unsigned integer (rounding towards zero).
    FPToUI FloatType IntType
  | -- | Convert a floating-point value to the nearest
    -- signed integer (rounding towards zero).
    FPToSI FloatType IntType
  | -- | Convert an unsigned integer to a floating-point value.
    UIToFP IntType FloatType
  | -- | Convert a signed integer to a floating-point value.
    SIToFP IntType FloatType
  | -- | Convert an integer to a boolean value.  Zero
    -- becomes false; anything else is true.
    IToB IntType
  | -- | Convert a boolean to an integer.  True is converted
    -- to 1 and False to 0.
    BToI IntType
  | -- | Convert a float to a boolean value.  Zero becomes false;
    -- | anything else is true.
    FToB FloatType
  | -- | Convert a boolean to a float.  True is converted
    -- to 1 and False to 0.
    BToF FloatType
  deriving (ConvOp -> ConvOp -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ConvOp -> ConvOp -> Bool
$c/= :: ConvOp -> ConvOp -> Bool
== :: ConvOp -> ConvOp -> Bool
$c== :: ConvOp -> ConvOp -> Bool
Eq, Eq ConvOp
ConvOp -> ConvOp -> Bool
ConvOp -> ConvOp -> Ordering
ConvOp -> ConvOp -> ConvOp
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
min :: ConvOp -> ConvOp -> ConvOp
$cmin :: ConvOp -> ConvOp -> ConvOp
max :: ConvOp -> ConvOp -> ConvOp
$cmax :: ConvOp -> ConvOp -> ConvOp
>= :: ConvOp -> ConvOp -> Bool
$c>= :: ConvOp -> ConvOp -> Bool
> :: ConvOp -> ConvOp -> Bool
$c> :: ConvOp -> ConvOp -> Bool
<= :: ConvOp -> ConvOp -> Bool
$c<= :: ConvOp -> ConvOp -> Bool
< :: ConvOp -> ConvOp -> Bool
$c< :: ConvOp -> ConvOp -> Bool
compare :: ConvOp -> ConvOp -> Ordering
$ccompare :: ConvOp -> ConvOp -> Ordering
Ord, Int -> ConvOp -> ShowS
[ConvOp] -> ShowS
ConvOp -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ConvOp] -> ShowS
$cshowList :: [ConvOp] -> ShowS
show :: ConvOp -> String
$cshow :: ConvOp -> String
showsPrec :: Int -> ConvOp -> ShowS
$cshowsPrec :: Int -> ConvOp -> ShowS
Show)

-- | A list of all unary operators for all types.
allUnOps :: [UnOp]
allUnOps :: [UnOp]
allUnOps =
  UnOp
Not
    forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map IntType -> UnOp
Complement [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]
    forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map IntType -> UnOp
Abs [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]
    forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map FloatType -> UnOp
FAbs [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]
    forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map IntType -> UnOp
SSignum [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]
    forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map IntType -> UnOp
USignum [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]
    forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map FloatType -> UnOp
FSignum [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]

-- | A list of all binary operators for all types.
allBinOps :: [BinOp]
allBinOps :: [BinOp]
allBinOps =
  forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ IntType -> Overflow -> BinOp
Add forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Overflow
OverflowWrap, Overflow
OverflowUndef],
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FAdd [FloatType]
allFloatTypes,
      IntType -> Overflow -> BinOp
Sub forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Overflow
OverflowWrap, Overflow
OverflowUndef],
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FSub [FloatType]
allFloatTypes,
      IntType -> Overflow -> BinOp
Mul forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Overflow
OverflowWrap, Overflow
OverflowUndef],
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FMul [FloatType]
allFloatTypes,
      IntType -> Safety -> BinOp
UDiv forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      IntType -> Safety -> BinOp
UDivUp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      IntType -> Safety -> BinOp
SDiv forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      IntType -> Safety -> BinOp
SDivUp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FDiv [FloatType]
allFloatTypes,
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FMod [FloatType]
allFloatTypes,
      IntType -> Safety -> BinOp
UMod forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      IntType -> Safety -> BinOp
SMod forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      IntType -> Safety -> BinOp
SQuot forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      IntType -> Safety -> BinOp
SRem forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Safety
Unsafe, Safety
Safe],
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
SMin [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
UMin [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FMin [FloatType]
allFloatTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
SMax [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
UMax [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FMax [FloatType]
allFloatTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
Shl [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
LShr [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
AShr [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
And [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
Or [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
Xor [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> BinOp
Pow [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> BinOp
FPow [FloatType]
allFloatTypes,
      [BinOp
LogAnd, BinOp
LogOr]
    ]

-- | A list of all comparison operators for all types.
allCmpOps :: [CmpOp]
allCmpOps :: [CmpOp]
allCmpOps =
  forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ forall a b. (a -> b) -> [a] -> [b]
map PrimType -> CmpOp
CmpEq [PrimType]
allPrimTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> CmpOp
CmpUlt [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> CmpOp
CmpUle [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> CmpOp
CmpSlt [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map IntType -> CmpOp
CmpSle [IntType]
allIntTypes,
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> CmpOp
FCmpLt [FloatType]
allFloatTypes,
      forall a b. (a -> b) -> [a] -> [b]
map FloatType -> CmpOp
FCmpLe [FloatType]
allFloatTypes,
      [CmpOp
CmpLlt, CmpOp
CmpLle]
    ]

-- | A list of all conversion operators for all types.
allConvOps :: [ConvOp]
allConvOps :: [ConvOp]
allConvOps =
  forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ IntType -> IntType -> ConvOp
ZExt forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [IntType]
allIntTypes,
      IntType -> IntType -> ConvOp
SExt forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [IntType]
allIntTypes,
      FloatType -> FloatType -> ConvOp
FPConv forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FloatType]
allFloatTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [FloatType]
allFloatTypes,
      FloatType -> IntType -> ConvOp
FPToUI forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FloatType]
allFloatTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [IntType]
allIntTypes,
      FloatType -> IntType -> ConvOp
FPToSI forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FloatType]
allFloatTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [IntType]
allIntTypes,
      IntType -> FloatType -> ConvOp
UIToFP forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [FloatType]
allFloatTypes,
      IntType -> FloatType -> ConvOp
SIToFP forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [FloatType]
allFloatTypes,
      IntType -> ConvOp
IToB forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes,
      IntType -> ConvOp
BToI forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [IntType]
allIntTypes,
      FloatType -> ConvOp
FToB forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FloatType]
allFloatTypes,
      FloatType -> ConvOp
BToF forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FloatType]
allFloatTypes
    ]

-- | Apply an 'UnOp' to an operand.  Returns 'Nothing' if the
-- application is mistyped.
doUnOp :: UnOp -> PrimValue -> Maybe PrimValue
doUnOp :: UnOp -> PrimValue -> Maybe PrimValue
doUnOp UnOp
Not (BoolValue Bool
b) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not Bool
b
doUnOp Complement {} (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue
doComplement IntValue
v
doUnOp Abs {} (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue
doAbs IntValue
v
doUnOp FAbs {} (FloatValue FloatValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ FloatValue -> FloatValue
doFAbs FloatValue
v
doUnOp SSignum {} (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue
doSSignum IntValue
v
doUnOp USignum {} (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue
doUSignum IntValue
v
doUnOp FSignum {} (FloatValue FloatValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ FloatValue -> FloatValue
doFSignum FloatValue
v
doUnOp UnOp
_ PrimValue
_ = forall a. Maybe a
Nothing

-- | E.g., @~(~1) = 1@.
doComplement :: IntValue -> IntValue
doComplement :: IntValue -> IntValue
doComplement IntValue
v = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v) forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> a
complement forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v

-- | @abs(-2) = 2@.
doAbs :: IntValue -> IntValue
doAbs :: IntValue -> IntValue
doAbs IntValue
v = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v) forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v

-- | @abs(-2.0) = 2.0@.
doFAbs :: FloatValue -> FloatValue
doFAbs :: FloatValue -> FloatValue
doFAbs (Float16Value Half
x) = Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs Half
x
doFAbs (Float32Value Float
x) = Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs Float
x
doFAbs (Float64Value Double
x) = Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs Double
x

-- | @ssignum(-2)@ = -1.
doSSignum :: IntValue -> IntValue
doSSignum :: IntValue -> IntValue
doSSignum IntValue
v = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v) forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
signum forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v

-- | @usignum(-2)@ = -1.
doUSignum :: IntValue -> IntValue
doUSignum :: IntValue -> IntValue
doUSignum IntValue
v = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v) forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
signum forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v

-- | @fsignum(-2.0)@ = -1.0.
doFSignum :: FloatValue -> FloatValue
doFSignum :: FloatValue -> FloatValue
doFSignum (Float16Value Half
v) = Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
signum Half
v
doFSignum (Float32Value Float
v) = Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
signum Float
v
doFSignum (Float64Value Double
v) = Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
signum Double
v

-- | Apply a 'BinOp' to an operand.  Returns 'Nothing' if the
-- application is mistyped, or outside the domain (e.g. division by
-- zero).
doBinOp :: BinOp -> PrimValue -> PrimValue -> Maybe PrimValue
doBinOp :: BinOp -> PrimValue -> PrimValue -> Maybe PrimValue
doBinOp Add {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doAdd
doBinOp FAdd {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp forall a. Num a => a -> a -> a
(+) forall a. Num a => a -> a -> a
(+) forall a. Num a => a -> a -> a
(+)
doBinOp Sub {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doSub
doBinOp FSub {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp (-) (-) (-)
doBinOp Mul {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doMul
doBinOp FMul {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp forall a. Num a => a -> a -> a
(*) forall a. Num a => a -> a -> a
(*) forall a. Num a => a -> a -> a
(*)
doBinOp UDiv {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doUDiv
doBinOp UDivUp {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doUDivUp
doBinOp SDiv {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doSDiv
doBinOp SDivUp {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doSDivUp
doBinOp FDiv {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp forall a. Fractional a => a -> a -> a
(/) forall a. Fractional a => a -> a -> a
(/) forall a. Fractional a => a -> a -> a
(/)
doBinOp FMod {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp forall a. Real a => a -> a -> a
mod' forall a. Real a => a -> a -> a
mod' forall a. Real a => a -> a -> a
mod'
doBinOp UMod {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doUMod
doBinOp SMod {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doSMod
doBinOp SQuot {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doSQuot
doBinOp SRem {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doSRem
doBinOp SMin {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doSMin
doBinOp UMin {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doUMin
doBinOp FMin {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp forall {a}. RealFloat a => a -> a -> a
fmin forall {a}. RealFloat a => a -> a -> a
fmin forall {a}. RealFloat a => a -> a -> a
fmin
  where
    fmin :: a -> a -> a
fmin a
x a
y
      | forall a. RealFloat a => a -> Bool
isNaN a
x = a
y
      | forall a. RealFloat a => a -> Bool
isNaN a
y = a
x
      | Bool
otherwise = forall a. Ord a => a -> a -> a
min a
x a
y
doBinOp SMax {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doSMax
doBinOp UMax {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doUMax
doBinOp FMax {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp forall {a}. RealFloat a => a -> a -> a
fmax forall {a}. RealFloat a => a -> a -> a
fmax forall {a}. RealFloat a => a -> a -> a
fmax
  where
    fmax :: a -> a -> a
fmax a
x a
y
      | forall a. RealFloat a => a -> Bool
isNaN a
x = a
y
      | forall a. RealFloat a => a -> Bool
isNaN a
y = a
x
      | Bool
otherwise = forall a. Ord a => a -> a -> a
max a
x a
y
doBinOp Shl {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doShl
doBinOp LShr {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doLShr
doBinOp AShr {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doAShr
doBinOp And {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doAnd
doBinOp Or {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doOr
doBinOp Xor {} = (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
doXor
doBinOp Pow {} = (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
doPow
doBinOp FPow {} = (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp forall a. Floating a => a -> a -> a
(**) forall a. Floating a => a -> a -> a
(**) forall a. Floating a => a -> a -> a
(**)
doBinOp LogAnd {} = (Bool -> Bool -> Bool) -> PrimValue -> PrimValue -> Maybe PrimValue
doBoolBinOp Bool -> Bool -> Bool
(&&)
doBinOp LogOr {} = (Bool -> Bool -> Bool) -> PrimValue -> PrimValue -> Maybe PrimValue
doBoolBinOp Bool -> Bool -> Bool
(||)

doIntBinOp ::
  (IntValue -> IntValue -> IntValue) ->
  PrimValue ->
  PrimValue ->
  Maybe PrimValue
doIntBinOp :: (IntValue -> IntValue -> IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doIntBinOp IntValue -> IntValue -> IntValue
f (IntValue IntValue
v1) (IntValue IntValue
v2) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> IntValue
f IntValue
v1 IntValue
v2
doIntBinOp IntValue -> IntValue -> IntValue
_ PrimValue
_ PrimValue
_ = forall a. Maybe a
Nothing

doRiskyIntBinOp ::
  (IntValue -> IntValue -> Maybe IntValue) ->
  PrimValue ->
  PrimValue ->
  Maybe PrimValue
doRiskyIntBinOp :: (IntValue -> IntValue -> Maybe IntValue)
-> PrimValue -> PrimValue -> Maybe PrimValue
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
f (IntValue IntValue
v1) (IntValue IntValue
v2) =
  IntValue -> PrimValue
IntValue forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IntValue -> IntValue -> Maybe IntValue
f IntValue
v1 IntValue
v2
doRiskyIntBinOp IntValue -> IntValue -> Maybe IntValue
_ PrimValue
_ PrimValue
_ = forall a. Maybe a
Nothing

doFloatBinOp ::
  (Half -> Half -> Half) ->
  (Float -> Float -> Float) ->
  (Double -> Double -> Double) ->
  PrimValue ->
  PrimValue ->
  Maybe PrimValue
doFloatBinOp :: (Half -> Half -> Half)
-> (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue
-> PrimValue
-> Maybe PrimValue
doFloatBinOp Half -> Half -> Half
f16 Float -> Float -> Float
_ Double -> Double -> Double
_ (FloatValue (Float16Value Half
v1)) (FloatValue (Float16Value Half
v2)) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ Half -> Half -> Half
f16 Half
v1 Half
v2
doFloatBinOp Half -> Half -> Half
_ Float -> Float -> Float
f32 Double -> Double -> Double
_ (FloatValue (Float32Value Float
v1)) (FloatValue (Float32Value Float
v2)) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
f32 Float
v1 Float
v2
doFloatBinOp Half -> Half -> Half
_ Float -> Float -> Float
_ Double -> Double -> Double
f64 (FloatValue (Float64Value Double
v1)) (FloatValue (Float64Value Double
v2)) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
f64 Double
v1 Double
v2
doFloatBinOp Half -> Half -> Half
_ Float -> Float -> Float
_ Double -> Double -> Double
_ PrimValue
_ PrimValue
_ = forall a. Maybe a
Nothing

doBoolBinOp ::
  (Bool -> Bool -> Bool) ->
  PrimValue ->
  PrimValue ->
  Maybe PrimValue
doBoolBinOp :: (Bool -> Bool -> Bool) -> PrimValue -> PrimValue -> Maybe PrimValue
doBoolBinOp Bool -> Bool -> Bool
f (BoolValue Bool
v1) (BoolValue Bool
v2) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> Bool
f Bool
v1 Bool
v2
doBoolBinOp Bool -> Bool -> Bool
_ PrimValue
_ PrimValue
_ = forall a. Maybe a
Nothing

-- | Integer addition.
doAdd :: IntValue -> IntValue -> IntValue
doAdd :: IntValue -> IntValue -> IntValue
doAdd IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Num a => a -> a -> a
+ IntValue -> Int64
intToInt64 IntValue
v2

-- | Integer subtraction.
doSub :: IntValue -> IntValue -> IntValue
doSub :: IntValue -> IntValue -> IntValue
doSub IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Num a => a -> a -> a
- IntValue -> Int64
intToInt64 IntValue
v2

-- | Integer multiplication.
doMul :: IntValue -> IntValue -> IntValue
doMul :: IntValue -> IntValue -> IntValue
doMul IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Num a => a -> a -> a
* IntValue -> Int64
intToInt64 IntValue
v2

-- | Unsigned integer division.  Rounds towards negativity infinity.
-- Note: this is different from LLVM.
doUDiv :: IntValue -> IntValue -> Maybe IntValue
doUDiv :: IntValue -> IntValue -> Maybe IntValue
doUDiv IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise =
      forall a. a -> Maybe a
Just forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$
        IntValue -> Word64
intToWord64 IntValue
v1 forall a. Integral a => a -> a -> a
`div` IntValue -> Word64
intToWord64 IntValue
v2

-- | Unsigned integer division.  Rounds towards positive infinity.
doUDivUp :: IntValue -> IntValue -> Maybe IntValue
doUDivUp :: IntValue -> IntValue -> Maybe IntValue
doUDivUp IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise =
      forall a. a -> Maybe a
Just forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$
        (IntValue -> Word64
intToWord64 IntValue
v1 forall a. Num a => a -> a -> a
+ IntValue -> Word64
intToWord64 IntValue
v2 forall a. Num a => a -> a -> a
- Word64
1) forall a. Integral a => a -> a -> a
`div` IntValue -> Word64
intToWord64 IntValue
v2

-- | Signed integer division.  Rounds towards negativity infinity.
-- Note: this is different from LLVM.
doSDiv :: IntValue -> IntValue -> Maybe IntValue
doSDiv :: IntValue -> IntValue -> Maybe IntValue
doSDiv IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$
        forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$
          IntValue -> Int64
intToInt64 IntValue
v1 forall a. Integral a => a -> a -> a
`div` IntValue -> Int64
intToInt64 IntValue
v2

-- | Signed integer division.  Rounds towards positive infinity.
doSDivUp :: IntValue -> IntValue -> Maybe IntValue
doSDivUp :: IntValue -> IntValue -> Maybe IntValue
doSDivUp IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise =
      forall a. a -> Maybe a
Just forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$
        (IntValue -> Int64
intToInt64 IntValue
v1 forall a. Num a => a -> a -> a
+ IntValue -> Int64
intToInt64 IntValue
v2 forall a. Num a => a -> a -> a
- Int64
1) forall a. Integral a => a -> a -> a
`div` IntValue -> Int64
intToInt64 IntValue
v2

-- | Unsigned integer modulus; the countepart to 'UDiv'.
doUMod :: IntValue -> IntValue -> Maybe IntValue
doUMod :: IntValue -> IntValue -> Maybe IntValue
doUMod IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v1 forall a. Integral a => a -> a -> a
`mod` IntValue -> Word64
intToWord64 IntValue
v2

-- | Signed integer modulus; the countepart to 'SDiv'.
doSMod :: IntValue -> IntValue -> Maybe IntValue
doSMod :: IntValue -> IntValue -> Maybe IntValue
doSMod IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Integral a => a -> a -> a
`mod` IntValue -> Int64
intToInt64 IntValue
v2

-- | Signed integer division.  Rounds towards zero.
-- This corresponds to the @sdiv@ instruction in LLVM.
doSQuot :: IntValue -> IntValue -> Maybe IntValue
doSQuot :: IntValue -> IntValue -> Maybe IntValue
doSQuot IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Integral a => a -> a -> a
`quot` IntValue -> Int64
intToInt64 IntValue
v2

-- | Signed integer division.  Rounds towards zero.
-- This corresponds to the @srem@ instruction in LLVM.
doSRem :: IntValue -> IntValue -> Maybe IntValue
doSRem :: IntValue -> IntValue -> Maybe IntValue
doSRem IntValue
v1 IntValue
v2
  | IntValue -> Bool
zeroIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Integral a => a -> a -> a
`rem` IntValue -> Int64
intToInt64 IntValue
v2

-- | Minimum of two signed integers.
doSMin :: IntValue -> IntValue -> IntValue
doSMin :: IntValue -> IntValue -> IntValue
doSMin IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Ord a => a -> a -> a
`min` IntValue -> Int64
intToInt64 IntValue
v2

-- | Minimum of two unsigned integers.
doUMin :: IntValue -> IntValue -> IntValue
doUMin :: IntValue -> IntValue -> IntValue
doUMin IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v1 forall a. Ord a => a -> a -> a
`min` IntValue -> Word64
intToWord64 IntValue
v2

-- | Maximum of two signed integers.
doSMax :: IntValue -> IntValue -> IntValue
doSMax :: IntValue -> IntValue -> IntValue
doSMax IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Ord a => a -> a -> a
`max` IntValue -> Int64
intToInt64 IntValue
v2

-- | Maximum of two unsigned integers.
doUMax :: IntValue -> IntValue -> IntValue
doUMax :: IntValue -> IntValue -> IntValue
doUMax IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v1 forall a. Ord a => a -> a -> a
`max` IntValue -> Word64
intToWord64 IntValue
v2

-- | Left-shift.
doShl :: IntValue -> IntValue -> IntValue
doShl :: IntValue -> IntValue -> IntValue
doShl IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Bits a => a -> Int -> a
`shift` IntValue -> Int
intToInt IntValue
v2

-- | Logical right-shift, zero-extended.
doLShr :: IntValue -> IntValue -> IntValue
doLShr :: IntValue -> IntValue -> IntValue
doLShr IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v1 forall a. Bits a => a -> Int -> a
`shift` forall a. Num a => a -> a
negate (IntValue -> Int
intToInt IntValue
v2)

-- | Arithmetic right-shift, sign-extended.
doAShr :: IntValue -> IntValue -> IntValue
doAShr :: IntValue -> IntValue -> IntValue
doAShr IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a. Bits a => a -> Int -> a
`shift` forall a. Num a => a -> a
negate (IntValue -> Int
intToInt IntValue
v2)

-- | Bitwise and.
doAnd :: IntValue -> IntValue -> IntValue
doAnd :: IntValue -> IntValue -> IntValue
doAnd IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v1 forall a. Bits a => a -> a -> a
.&. IntValue -> Word64
intToWord64 IntValue
v2

-- | Bitwise or.
doOr :: IntValue -> IntValue -> IntValue
doOr :: IntValue -> IntValue -> IntValue
doOr IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v1 forall a. Bits a => a -> a -> a
.|. IntValue -> Word64
intToWord64 IntValue
v2

-- | Bitwise exclusive-or.
doXor :: IntValue -> IntValue -> IntValue
doXor :: IntValue -> IntValue -> IntValue
doXor IntValue
v1 IntValue
v2 = forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v1 forall a. Bits a => a -> a -> a
`xor` IntValue -> Word64
intToWord64 IntValue
v2

-- | Signed integer exponentatation.
doPow :: IntValue -> IntValue -> Maybe IntValue
doPow :: IntValue -> IntValue -> Maybe IntValue
doPow IntValue
v1 IntValue
v2
  | IntValue -> Bool
negativeIshInt IntValue
v2 = forall a. Maybe a
Nothing
  | Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall int. Integral int => IntType -> int -> IntValue
intValue (IntValue -> IntType
intValueType IntValue
v1) forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v1 forall a b. (Num a, Integral b) => a -> b -> a
^ IntValue -> Int64
intToInt64 IntValue
v2

-- | Apply a 'ConvOp' to an operand.  Returns 'Nothing' if the
-- application is mistyped.
doConvOp :: ConvOp -> PrimValue -> Maybe PrimValue
doConvOp :: ConvOp -> PrimValue -> Maybe PrimValue
doConvOp (ZExt IntType
_ IntType
to) (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ IntValue -> IntType -> IntValue
doZExt IntValue
v IntType
to
doConvOp (SExt IntType
_ IntType
to) (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ IntValue -> IntType -> IntValue
doSExt IntValue
v IntType
to
doConvOp (FPConv FloatType
_ FloatType
to) (FloatValue FloatValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ FloatValue -> FloatType -> FloatValue
doFPConv FloatValue
v FloatType
to
doConvOp (FPToUI FloatType
_ IntType
to) (FloatValue FloatValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ FloatValue -> IntType -> IntValue
doFPToUI FloatValue
v IntType
to
doConvOp (FPToSI FloatType
_ IntType
to) (FloatValue FloatValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ FloatValue -> IntType -> IntValue
doFPToSI FloatValue
v IntType
to
doConvOp (UIToFP IntType
_ FloatType
to) (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ IntValue -> FloatType -> FloatValue
doUIToFP IntValue
v FloatType
to
doConvOp (SIToFP IntType
_ FloatType
to) (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ IntValue -> FloatType -> FloatValue
doSIToFP IntValue
v FloatType
to
doConvOp (IToB IntType
_) (IntValue IntValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v forall a. Eq a => a -> a -> Bool
/= Int64
0
doConvOp (BToI IntType
to) (BoolValue Bool
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ forall int. Integral int => IntType -> int -> IntValue
intValue IntType
to forall a b. (a -> b) -> a -> b
$ if Bool
v then Int
1 else Int
0 :: Int
doConvOp (FToB FloatType
_) (FloatValue FloatValue
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ FloatValue -> Double
floatToDouble FloatValue
v forall a. Eq a => a -> a -> Bool
/= Double
0
doConvOp (BToF FloatType
to) (BoolValue Bool
v) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ forall num. Real num => FloatType -> num -> FloatValue
floatValue FloatType
to forall a b. (a -> b) -> a -> b
$ if Bool
v then Double
1 else Double
0 :: Double
doConvOp ConvOp
_ PrimValue
_ = forall a. Maybe a
Nothing

-- | Turn the conversion the other way around.  Note that most
-- conversions are lossy, so there is no guarantee the value will
-- round-trip.
flipConvOp :: ConvOp -> ConvOp
flipConvOp :: ConvOp -> ConvOp
flipConvOp (ZExt IntType
from IntType
to) = IntType -> IntType -> ConvOp
ZExt IntType
to IntType
from
flipConvOp (SExt IntType
from IntType
to) = IntType -> IntType -> ConvOp
SExt IntType
to IntType
from
flipConvOp (FPConv FloatType
from FloatType
to) = FloatType -> FloatType -> ConvOp
FPConv FloatType
to FloatType
from
flipConvOp (FPToUI FloatType
from IntType
to) = IntType -> FloatType -> ConvOp
UIToFP IntType
to FloatType
from
flipConvOp (FPToSI FloatType
from IntType
to) = IntType -> FloatType -> ConvOp
SIToFP IntType
to FloatType
from
flipConvOp (UIToFP IntType
from FloatType
to) = FloatType -> IntType -> ConvOp
FPToSI FloatType
to IntType
from
flipConvOp (SIToFP IntType
from FloatType
to) = FloatType -> IntType -> ConvOp
FPToSI FloatType
to IntType
from
flipConvOp (IToB IntType
from) = IntType -> ConvOp
BToI IntType
from
flipConvOp (BToI IntType
to) = IntType -> ConvOp
IToB IntType
to
flipConvOp (FToB FloatType
from) = FloatType -> ConvOp
BToF FloatType
from
flipConvOp (BToF FloatType
to) = FloatType -> ConvOp
FToB FloatType
to

-- | Zero-extend the given integer value to the size of the given
-- type.  If the type is smaller than the given value, the result is a
-- truncation.
doZExt :: IntValue -> IntType -> IntValue
doZExt :: IntValue -> IntType -> IntValue
doZExt (Int8Value Int8
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
x :: Word8)
doZExt (Int16Value Int16
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
x :: Word16)
doZExt (Int32Value Int32
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
x :: Word32)
doZExt (Int64Value Int64
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
x :: Word64)

-- | Sign-extend the given integer value to the size of the given
-- type.  If the type is smaller than the given value, the result is a
-- truncation.
doSExt :: IntValue -> IntType -> IntValue
doSExt :: IntValue -> IntType -> IntValue
doSExt (Int8Value Int8
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger Int8
x
doSExt (Int16Value Int16
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger Int16
x
doSExt (Int32Value Int32
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger Int32
x
doSExt (Int64Value Int64
x) IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> Integer
toInteger Int64
x

-- | Convert the former floating-point type to the latter.
doFPConv :: FloatValue -> FloatType -> FloatValue
doFPConv :: FloatValue -> FloatType -> FloatValue
doFPConv FloatValue
v FloatType
Float16 = Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ FloatValue -> Half
floatToHalf FloatValue
v
doFPConv FloatValue
v FloatType
Float32 = Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ FloatValue -> Float
floatToFloat FloatValue
v
doFPConv FloatValue
v FloatType
Float64 = Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ FloatValue -> Double
floatToDouble FloatValue
v

-- | Convert a floating-point value to the nearest
-- unsigned integer (rounding towards zero).
doFPToUI :: FloatValue -> IntType -> IntValue
doFPToUI :: FloatValue -> IntType -> IntValue
doFPToUI FloatValue
v IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t (forall a b. (RealFrac a, Integral b) => a -> b
truncate forall a b. (a -> b) -> a -> b
$ FloatValue -> Double
floatToDouble FloatValue
v :: Word64)

-- | Convert a floating-point value to the nearest
-- signed integer (rounding towards zero).
doFPToSI :: FloatValue -> IntType -> IntValue
doFPToSI :: FloatValue -> IntType -> IntValue
doFPToSI FloatValue
v IntType
t = forall int. Integral int => IntType -> int -> IntValue
intValue IntType
t (forall a b. (RealFrac a, Integral b) => a -> b
truncate forall a b. (a -> b) -> a -> b
$ FloatValue -> Double
floatToDouble FloatValue
v :: Word64)

-- | Convert an unsigned integer to a floating-point value.
doUIToFP :: IntValue -> FloatType -> FloatValue
doUIToFP :: IntValue -> FloatType -> FloatValue
doUIToFP IntValue
v FloatType
t = forall num. Real num => FloatType -> num -> FloatValue
floatValue FloatType
t forall a b. (a -> b) -> a -> b
$ IntValue -> Word64
intToWord64 IntValue
v

-- | Convert a signed integer to a floating-point value.
doSIToFP :: IntValue -> FloatType -> FloatValue
doSIToFP :: IntValue -> FloatType -> FloatValue
doSIToFP IntValue
v FloatType
t = forall num. Real num => FloatType -> num -> FloatValue
floatValue FloatType
t forall a b. (a -> b) -> a -> b
$ IntValue -> Int64
intToInt64 IntValue
v

-- | Apply a 'CmpOp' to an operand.  Returns 'Nothing' if the
-- application is mistyped.
doCmpOp :: CmpOp -> PrimValue -> PrimValue -> Maybe Bool
doCmpOp :: CmpOp -> PrimValue -> PrimValue -> Maybe Bool
doCmpOp CmpEq {} PrimValue
v1 PrimValue
v2 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ PrimValue -> PrimValue -> Bool
doCmpEq PrimValue
v1 PrimValue
v2
doCmpOp CmpUlt {} (IntValue IntValue
v1) (IntValue IntValue
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Bool
doCmpUlt IntValue
v1 IntValue
v2
doCmpOp CmpUle {} (IntValue IntValue
v1) (IntValue IntValue
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Bool
doCmpUle IntValue
v1 IntValue
v2
doCmpOp CmpSlt {} (IntValue IntValue
v1) (IntValue IntValue
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Bool
doCmpSlt IntValue
v1 IntValue
v2
doCmpOp CmpSle {} (IntValue IntValue
v1) (IntValue IntValue
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Bool
doCmpSle IntValue
v1 IntValue
v2
doCmpOp FCmpLt {} (FloatValue FloatValue
v1) (FloatValue FloatValue
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> FloatValue -> Bool
doFCmpLt FloatValue
v1 FloatValue
v2
doCmpOp FCmpLe {} (FloatValue FloatValue
v1) (FloatValue FloatValue
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> FloatValue -> Bool
doFCmpLe FloatValue
v1 FloatValue
v2
doCmpOp CmpLlt {} (BoolValue Bool
v1) (BoolValue Bool
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not Bool
v1 Bool -> Bool -> Bool
&& Bool
v2
doCmpOp CmpLle {} (BoolValue Bool
v1) (BoolValue Bool
v2) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool
v1 Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
v2)
doCmpOp CmpOp
_ PrimValue
_ PrimValue
_ = forall a. Maybe a
Nothing

-- | Compare any two primtive values for exact equality.
doCmpEq :: PrimValue -> PrimValue -> Bool
doCmpEq :: PrimValue -> PrimValue -> Bool
doCmpEq (FloatValue (Float32Value Float
v1)) (FloatValue (Float32Value Float
v2)) = Float
v1 forall a. Eq a => a -> a -> Bool
== Float
v2
doCmpEq (FloatValue (Float64Value Double
v1)) (FloatValue (Float64Value Double
v2)) = Double
v1 forall a. Eq a => a -> a -> Bool
== Double
v2
doCmpEq PrimValue
v1 PrimValue
v2 = PrimValue
v1 forall a. Eq a => a -> a -> Bool
== PrimValue
v2

-- | Unsigned less than.
doCmpUlt :: IntValue -> IntValue -> Bool
doCmpUlt :: IntValue -> IntValue -> Bool
doCmpUlt IntValue
v1 IntValue
v2 = IntValue -> Word64
intToWord64 IntValue
v1 forall a. Ord a => a -> a -> Bool
< IntValue -> Word64
intToWord64 IntValue
v2

-- | Unsigned less than or equal.
doCmpUle :: IntValue -> IntValue -> Bool
doCmpUle :: IntValue -> IntValue -> Bool
doCmpUle IntValue
v1 IntValue
v2 = IntValue -> Word64
intToWord64 IntValue
v1 forall a. Ord a => a -> a -> Bool
<= IntValue -> Word64
intToWord64 IntValue
v2

-- | Signed less than.
doCmpSlt :: IntValue -> IntValue -> Bool
doCmpSlt :: IntValue -> IntValue -> Bool
doCmpSlt = forall a. Ord a => a -> a -> Bool
(<)

-- | Signed less than or equal.
doCmpSle :: IntValue -> IntValue -> Bool
doCmpSle :: IntValue -> IntValue -> Bool
doCmpSle = forall a. Ord a => a -> a -> Bool
(<=)

-- | Floating-point less than.
doFCmpLt :: FloatValue -> FloatValue -> Bool
doFCmpLt :: FloatValue -> FloatValue -> Bool
doFCmpLt = forall a. Ord a => a -> a -> Bool
(<)

-- | Floating-point less than or equal.
doFCmpLe :: FloatValue -> FloatValue -> Bool
doFCmpLe :: FloatValue -> FloatValue -> Bool
doFCmpLe = forall a. Ord a => a -> a -> Bool
(<=)

-- | Translate an t'IntValue' to 'Word64'.  This is guaranteed to fit.
intToWord64 :: IntValue -> Word64
intToWord64 :: IntValue -> Word64
intToWord64 (Int8Value Int8
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
v :: Word8)
intToWord64 (Int16Value Int16
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
v :: Word16)
intToWord64 (Int32Value Int32
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
v :: Word32)
intToWord64 (Int64Value Int64
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
v :: Word64)

-- | Translate an t'IntValue' to t'Int64'.  This is guaranteed to fit.
intToInt64 :: IntValue -> Int64
intToInt64 :: IntValue -> Int64
intToInt64 (Int8Value Int8
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
v
intToInt64 (Int16Value Int16
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
v
intToInt64 (Int32Value Int32
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
v
intToInt64 (Int64Value Int64
v) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
v

-- | Careful - there is no guarantee this will fit.
intToInt :: IntValue -> Int
intToInt :: IntValue -> Int
intToInt = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IntValue -> Int64
intToInt64

floatToDouble :: FloatValue -> Double
floatToDouble :: FloatValue -> Double
floatToDouble (Float16Value Half
v)
  | forall a. RealFloat a => a -> Bool
isInfinite Half
v, Half
v forall a. Ord a => a -> a -> Bool
> Half
0 = Double
1 forall a. Fractional a => a -> a -> a
/ Double
0
  | forall a. RealFloat a => a -> Bool
isInfinite Half
v, Half
v forall a. Ord a => a -> a -> Bool
< Half
0 = -Double
1 forall a. Fractional a => a -> a -> a
/ Double
0
  | forall a. RealFloat a => a -> Bool
isNaN Half
v = Double
0 forall a. Fractional a => a -> a -> a
/ Double
0
  | Bool
otherwise = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational Half
v
floatToDouble (Float32Value Float
v)
  | forall a. RealFloat a => a -> Bool
isInfinite Float
v, Float
v forall a. Ord a => a -> a -> Bool
> Float
0 = Double
1 forall a. Fractional a => a -> a -> a
/ Double
0
  | forall a. RealFloat a => a -> Bool
isInfinite Float
v, Float
v forall a. Ord a => a -> a -> Bool
< Float
0 = -Double
1 forall a. Fractional a => a -> a -> a
/ Double
0
  | forall a. RealFloat a => a -> Bool
isNaN Float
v = Double
0 forall a. Fractional a => a -> a -> a
/ Double
0
  | Bool
otherwise = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational Float
v
floatToDouble (Float64Value Double
v) = Double
v

floatToFloat :: FloatValue -> Float
floatToFloat :: FloatValue -> Float
floatToFloat (Float16Value Half
v)
  | forall a. RealFloat a => a -> Bool
isInfinite Half
v, Half
v forall a. Ord a => a -> a -> Bool
> Half
0 = Float
1 forall a. Fractional a => a -> a -> a
/ Float
0
  | forall a. RealFloat a => a -> Bool
isInfinite Half
v, Half
v forall a. Ord a => a -> a -> Bool
< Half
0 = -Float
1 forall a. Fractional a => a -> a -> a
/ Float
0
  | forall a. RealFloat a => a -> Bool
isNaN Half
v = Float
0 forall a. Fractional a => a -> a -> a
/ Float
0
  | Bool
otherwise = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational Half
v
floatToFloat (Float32Value Float
v) = Float
v
floatToFloat (Float64Value Double
v)
  | forall a. RealFloat a => a -> Bool
isInfinite Double
v, Double
v forall a. Ord a => a -> a -> Bool
> Double
0 = Float
1 forall a. Fractional a => a -> a -> a
/ Float
0
  | forall a. RealFloat a => a -> Bool
isInfinite Double
v, Double
v forall a. Ord a => a -> a -> Bool
< Double
0 = -Float
1 forall a. Fractional a => a -> a -> a
/ Float
0
  | forall a. RealFloat a => a -> Bool
isNaN Double
v = Float
0 forall a. Fractional a => a -> a -> a
/ Float
0
  | Bool
otherwise = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational Double
v

floatToHalf :: FloatValue -> Half
floatToHalf :: FloatValue -> Half
floatToHalf (Float16Value Half
v) = Half
v
floatToHalf (Float32Value Float
v)
  | forall a. RealFloat a => a -> Bool
isInfinite Float
v, Float
v forall a. Ord a => a -> a -> Bool
> Float
0 = Half
1 forall a. Fractional a => a -> a -> a
/ Half
0
  | forall a. RealFloat a => a -> Bool
isInfinite Float
v, Float
v forall a. Ord a => a -> a -> Bool
< Float
0 = -Half
1 forall a. Fractional a => a -> a -> a
/ Half
0
  | forall a. RealFloat a => a -> Bool
isNaN Float
v = Half
0 forall a. Fractional a => a -> a -> a
/ Half
0
  | Bool
otherwise = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational Float
v
floatToHalf (Float64Value Double
v)
  | forall a. RealFloat a => a -> Bool
isInfinite Double
v, Double
v forall a. Ord a => a -> a -> Bool
> Double
0 = Half
1 forall a. Fractional a => a -> a -> a
/ Half
0
  | forall a. RealFloat a => a -> Bool
isInfinite Double
v, Double
v forall a. Ord a => a -> a -> Bool
< Double
0 = -Half
1 forall a. Fractional a => a -> a -> a
/ Half
0
  | forall a. RealFloat a => a -> Bool
isNaN Double
v = Half
0 forall a. Fractional a => a -> a -> a
/ Half
0
  | Bool
otherwise = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational Double
v

-- | The result type of a binary operator.
binOpType :: BinOp -> PrimType
binOpType :: BinOp -> PrimType
binOpType (Add IntType
t Overflow
_) = IntType -> PrimType
IntType IntType
t
binOpType (Sub IntType
t Overflow
_) = IntType -> PrimType
IntType IntType
t
binOpType (Mul IntType
t Overflow
_) = IntType -> PrimType
IntType IntType
t
binOpType (SDiv IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (SDivUp IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (SMod IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (SQuot IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (SRem IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (UDiv IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (UDivUp IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (UMod IntType
t Safety
_) = IntType -> PrimType
IntType IntType
t
binOpType (SMin IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (UMin IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (FMin FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
binOpType (SMax IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (UMax IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (FMax FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
binOpType (Shl IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (LShr IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (AShr IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (And IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (Or IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (Xor IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (Pow IntType
t) = IntType -> PrimType
IntType IntType
t
binOpType (FPow FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
binOpType BinOp
LogAnd = PrimType
Bool
binOpType BinOp
LogOr = PrimType
Bool
binOpType (FAdd FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
binOpType (FSub FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
binOpType (FMul FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
binOpType (FDiv FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
binOpType (FMod FloatType
t) = FloatType -> PrimType
FloatType FloatType
t

-- | The operand types of a comparison operator.
cmpOpType :: CmpOp -> PrimType
cmpOpType :: CmpOp -> PrimType
cmpOpType (CmpEq PrimType
t) = PrimType
t
cmpOpType (CmpSlt IntType
t) = IntType -> PrimType
IntType IntType
t
cmpOpType (CmpSle IntType
t) = IntType -> PrimType
IntType IntType
t
cmpOpType (CmpUlt IntType
t) = IntType -> PrimType
IntType IntType
t
cmpOpType (CmpUle IntType
t) = IntType -> PrimType
IntType IntType
t
cmpOpType (FCmpLt FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
cmpOpType (FCmpLe FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
cmpOpType CmpOp
CmpLlt = PrimType
Bool
cmpOpType CmpOp
CmpLle = PrimType
Bool

-- | The operand and result type of a unary operator.
unOpType :: UnOp -> PrimType
unOpType :: UnOp -> PrimType
unOpType (SSignum IntType
t) = IntType -> PrimType
IntType IntType
t
unOpType (USignum IntType
t) = IntType -> PrimType
IntType IntType
t
unOpType UnOp
Not = PrimType
Bool
unOpType (Complement IntType
t) = IntType -> PrimType
IntType IntType
t
unOpType (Abs IntType
t) = IntType -> PrimType
IntType IntType
t
unOpType (FAbs FloatType
t) = FloatType -> PrimType
FloatType FloatType
t
unOpType (FSignum FloatType
t) = FloatType -> PrimType
FloatType FloatType
t

-- | The input and output types of a conversion operator.
convOpType :: ConvOp -> (PrimType, PrimType)
convOpType :: ConvOp -> (PrimType, PrimType)
convOpType (ZExt IntType
from IntType
to) = (IntType -> PrimType
IntType IntType
from, IntType -> PrimType
IntType IntType
to)
convOpType (SExt IntType
from IntType
to) = (IntType -> PrimType
IntType IntType
from, IntType -> PrimType
IntType IntType
to)
convOpType (FPConv FloatType
from FloatType
to) = (FloatType -> PrimType
FloatType FloatType
from, FloatType -> PrimType
FloatType FloatType
to)
convOpType (FPToUI FloatType
from IntType
to) = (FloatType -> PrimType
FloatType FloatType
from, IntType -> PrimType
IntType IntType
to)
convOpType (FPToSI FloatType
from IntType
to) = (FloatType -> PrimType
FloatType FloatType
from, IntType -> PrimType
IntType IntType
to)
convOpType (UIToFP IntType
from FloatType
to) = (IntType -> PrimType
IntType IntType
from, FloatType -> PrimType
FloatType FloatType
to)
convOpType (SIToFP IntType
from FloatType
to) = (IntType -> PrimType
IntType IntType
from, FloatType -> PrimType
FloatType FloatType
to)
convOpType (IToB IntType
from) = (IntType -> PrimType
IntType IntType
from, PrimType
Bool)
convOpType (BToI IntType
to) = (PrimType
Bool, IntType -> PrimType
IntType IntType
to)
convOpType (FToB FloatType
from) = (FloatType -> PrimType
FloatType FloatType
from, PrimType
Bool)
convOpType (BToF FloatType
to) = (PrimType
Bool, FloatType -> PrimType
FloatType FloatType
to)

halfToWord :: Half -> Word16
halfToWord :: Half -> Word16
halfToWord (Half (CUShort Word16
x)) = Word16
x

wordToHalf :: Word16 -> Half
wordToHalf :: Word16 -> Half
wordToHalf = CUShort -> Half
Half forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Word16 -> CUShort
CUShort

floatToWord :: Float -> Word32
floatToWord :: Float -> Word32
floatToWord = forall a. Get a -> ByteString -> a
G.runGet Get Word32
G.getWord32le forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Put -> ByteString
P.runPut forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Put
P.putFloatle

wordToFloat :: Word32 -> Float
wordToFloat :: Word32 -> Float
wordToFloat = forall a. Get a -> ByteString -> a
G.runGet Get Float
G.getFloatle forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Put -> ByteString
P.runPut forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Word32 -> Put
P.putWord32le

doubleToWord :: Double -> Word64
doubleToWord :: Double -> Word64
doubleToWord = forall a. Get a -> ByteString -> a
G.runGet Get Word64
G.getWord64le forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Put -> ByteString
P.runPut forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Double -> Put
P.putDoublele

wordToDouble :: Word64 -> Double
wordToDouble :: Word64 -> Double
wordToDouble = forall a. Get a -> ByteString -> a
G.runGet Get Double
G.getDoublele forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Put -> ByteString
P.runPut forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Word64 -> Put
P.putWord64le

-- | A mapping from names of primitive functions to their parameter
-- types, their result type, and a function for evaluating them.
primFuns ::
  M.Map
    String
    ( [PrimType],
      PrimType,
      [PrimValue] -> Maybe PrimValue
    )
primFuns :: Map String ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue)
primFuns =
  forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
    [ forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"sqrt16" forall a. Floating a => a -> a
sqrt,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"sqrt32" forall a. Floating a => a -> a
sqrt,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"sqrt64" forall a. Floating a => a -> a
sqrt,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"cbrt16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
cbrtf forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"cbrt32" Float -> Float
cbrtf,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"cbrt64" Double -> Double
cbrt,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"log16" forall a. Floating a => a -> a
log,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"log32" forall a. Floating a => a -> a
log,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"log64" forall a. Floating a => a -> a
log,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"log10_16" (forall a. Floating a => a -> a -> a
logBase Half
10),
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"log10_32" (forall a. Floating a => a -> a -> a
logBase Float
10),
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"log10_64" (forall a. Floating a => a -> a -> a
logBase Double
10),
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"log2_16" (forall a. Floating a => a -> a -> a
logBase Half
2),
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"log2_32" (forall a. Floating a => a -> a -> a
logBase Float
2),
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"log2_64" (forall a. Floating a => a -> a -> a
logBase Double
2),
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"exp16" forall a. Floating a => a -> a
exp,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"exp32" forall a. Floating a => a -> a
exp,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"exp64" forall a. Floating a => a -> a
exp,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"sin16" forall a. Floating a => a -> a
sin,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"sin32" forall a. Floating a => a -> a
sin,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"sin64" forall a. Floating a => a -> a
sin,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"sinh16" forall a. Floating a => a -> a
sinh,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"sinh32" forall a. Floating a => a -> a
sinh,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"sinh64" forall a. Floating a => a -> a
sinh,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"cos16" forall a. Floating a => a -> a
cos,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"cos32" forall a. Floating a => a -> a
cos,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"cos64" forall a. Floating a => a -> a
cos,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"cosh16" forall a. Floating a => a -> a
cosh,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"cosh32" forall a. Floating a => a -> a
cosh,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"cosh64" forall a. Floating a => a -> a
cosh,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"tan16" forall a. Floating a => a -> a
tan,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"tan32" forall a. Floating a => a -> a
tan,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"tan64" forall a. Floating a => a -> a
tan,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"tanh16" forall a. Floating a => a -> a
tanh,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"tanh32" forall a. Floating a => a -> a
tanh,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"tanh64" forall a. Floating a => a -> a
tanh,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"asin16" forall a. Floating a => a -> a
asin,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"asin32" forall a. Floating a => a -> a
asin,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"asin64" forall a. Floating a => a -> a
asin,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"asinh16" forall a. Floating a => a -> a
asinh,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"asinh32" forall a. Floating a => a -> a
asinh,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"asinh64" forall a. Floating a => a -> a
asinh,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"acos16" forall a. Floating a => a -> a
acos,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"acos32" forall a. Floating a => a -> a
acos,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"acos64" forall a. Floating a => a -> a
acos,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"acosh16" forall a. Floating a => a -> a
acosh,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"acosh32" forall a. Floating a => a -> a
acosh,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"acosh64" forall a. Floating a => a -> a
acosh,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"atan16" forall a. Floating a => a -> a
atan,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"atan32" forall a. Floating a => a -> a
atan,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"atan64" forall a. Floating a => a -> a
atan,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"atanh16" forall a. Floating a => a -> a
atanh,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"atanh32" forall a. Floating a => a -> a
atanh,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"atanh64" forall a. Floating a => a -> a
atanh,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"round16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
roundFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"round32" Float -> Float
roundFloat,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"round64" Double -> Double
roundDouble,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"ceil16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
ceilFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"ceil32" Float -> Float
ceilFloat,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"ceil64" Double -> Double
ceilDouble,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"floor16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
floorFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"floor32" Float -> Float
floorFloat,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"floor64" Double -> Double
floorDouble,
      --
      forall {a}.
a
-> (Half -> Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16_2 String
"nextafter16" (\Half
x Half
y -> forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
nextafterf (forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat Half
x) (forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat Half
y)),
      forall {a}.
a
-> (Float -> Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32_2 String
"nextafter32" Float -> Float -> Float
nextafterf,
      forall {a}.
a
-> (Double -> Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64_2 String
"nextafter64" Double -> Double -> Double
nextafter,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"gamma16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
tgammaf forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"gamma32" Float -> Float
tgammaf,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"gamma64" Double -> Double
tgamma,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"lgamma16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
lgammaf forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"lgamma32" Float -> Float
lgammaf,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"lgamma64" Double -> Double
lgamma,
      --
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"erf16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
erff forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"erf32" Float -> Float
erff,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"erf64" Double -> Double
erf,
      --
      forall {a}.
a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 String
"erfc16" forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Float
erfcf forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat,
      forall {a}.
a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 String
"erfc32" Float -> Float
erfcf,
      forall {a}.
a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 String
"erfc64" Double -> Double
erfc,
      --
      forall {a} {a}.
a
-> (Int8 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i8 String
"clz8" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countLeadingZeros,
      forall {a} {a}.
a
-> (Int16 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i16 String
"clz16" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countLeadingZeros,
      forall {a} {a}.
a
-> (Int32 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i32 String
"clz32" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countLeadingZeros,
      forall {a} {a}.
a
-> (Int64 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i64 String
"clz64" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countLeadingZeros,
      forall {a} {a}.
a
-> (Int8 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i8 String
"ctz8" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countTrailingZeros,
      forall {a} {a}.
a
-> (Int16 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i16 String
"ctz16" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countTrailingZeros,
      forall {a} {a}.
a
-> (Int32 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i32 String
"ctz32" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countTrailingZeros,
      forall {a} {a}.
a
-> (Int64 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i64 String
"ctz64" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall b. FiniteBits b => b -> Int
countTrailingZeros,
      forall {a} {a}.
a
-> (Int8 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i8 String
"popc8" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Bits a => a -> Int
popCount,
      forall {a} {a}.
a
-> (Int16 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i16 String
"popc16" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Bits a => a -> Int
popCount,
      forall {a} {a}.
a
-> (Int32 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i32 String
"popc32" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Bits a => a -> Int
popCount,
      forall {a} {a}.
a
-> (Int64 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i64 String
"popc64" forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Bits a => a -> Int
popCount,
      ( String
"mad_hi8",
        ( [IntType -> PrimType
IntType IntType
Int8, IntType -> PrimType
IntType IntType
Int8, IntType -> PrimType
IntType IntType
Int8],
          IntType -> PrimType
IntType IntType
Int8,
          \case
            [IntValue (Int8Value Int8
a), IntValue (Int8Value Int8
b), IntValue (Int8Value Int8
c)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int8 -> IntValue
Int8Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int8 -> Int8
mad_hi8 (Int8 -> IntValue
Int8Value Int8
a) (Int8 -> IntValue
Int8Value Int8
b) Int8
c
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"mad_hi16",
        ( [IntType -> PrimType
IntType IntType
Int16, IntType -> PrimType
IntType IntType
Int16, IntType -> PrimType
IntType IntType
Int16],
          IntType -> PrimType
IntType IntType
Int16,
          \case
            [IntValue (Int16Value Int16
a), IntValue (Int16Value Int16
b), IntValue (Int16Value Int16
c)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int16 -> IntValue
Int16Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int16 -> Int16
mad_hi16 (Int16 -> IntValue
Int16Value Int16
a) (Int16 -> IntValue
Int16Value Int16
b) Int16
c
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"mad_hi32",
        ( [IntType -> PrimType
IntType IntType
Int32, IntType -> PrimType
IntType IntType
Int32, IntType -> PrimType
IntType IntType
Int32],
          IntType -> PrimType
IntType IntType
Int32,
          \case
            [IntValue (Int32Value Int32
a), IntValue (Int32Value Int32
b), IntValue (Int32Value Int32
c)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int32 -> Int32
mad_hi32 (Int32 -> IntValue
Int32Value Int32
a) (Int32 -> IntValue
Int32Value Int32
b) Int32
c
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"mad_hi64",
        ( [IntType -> PrimType
IntType IntType
Int64, IntType -> PrimType
IntType IntType
Int64, IntType -> PrimType
IntType IntType
Int64],
          IntType -> PrimType
IntType IntType
Int64,
          \case
            [IntValue (Int64Value Int64
a), IntValue (Int64Value Int64
b), IntValue (Int64Value Int64
c)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int64 -> IntValue
Int64Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int64 -> Int64
mad_hi64 (Int64 -> IntValue
Int64Value Int64
a) (Int64 -> IntValue
Int64Value Int64
b) Int64
c
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"mul_hi8",
        ( [IntType -> PrimType
IntType IntType
Int8, IntType -> PrimType
IntType IntType
Int8],
          IntType -> PrimType
IntType IntType
Int8,
          \case
            [IntValue (Int8Value Int8
a), IntValue (Int8Value Int8
b)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int8 -> IntValue
Int8Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int8
mul_hi8 (Int8 -> IntValue
Int8Value Int8
a) (Int8 -> IntValue
Int8Value Int8
b)
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"mul_hi16",
        ( [IntType -> PrimType
IntType IntType
Int16, IntType -> PrimType
IntType IntType
Int16],
          IntType -> PrimType
IntType IntType
Int16,
          \case
            [IntValue (Int16Value Int16
a), IntValue (Int16Value Int16
b)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int16 -> IntValue
Int16Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int16
mul_hi16 (Int16 -> IntValue
Int16Value Int16
a) (Int16 -> IntValue
Int16Value Int16
b)
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"mul_hi32",
        ( [IntType -> PrimType
IntType IntType
Int32, IntType -> PrimType
IntType IntType
Int32],
          IntType -> PrimType
IntType IntType
Int32,
          \case
            [IntValue (Int32Value Int32
a), IntValue (Int32Value Int32
b)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int32 -> IntValue
Int32Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int32
mul_hi32 (Int32 -> IntValue
Int32Value Int32
a) (Int32 -> IntValue
Int32Value Int32
b)
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"mul_hi64",
        ( [IntType -> PrimType
IntType IntType
Int64, IntType -> PrimType
IntType IntType
Int64],
          IntType -> PrimType
IntType IntType
Int64,
          \case
            [IntValue (Int64Value Int64
a), IntValue (Int64Value Int64
b)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int64 -> IntValue
Int64Value forall a b. (a -> b) -> a -> b
$ IntValue -> IntValue -> Int64
mul_hi64 (Int64 -> IntValue
Int64Value Int64
a) (Int64 -> IntValue
Int64Value Int64
b)
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      --
      ( String
"atan2_16",
        ( [FloatType -> PrimType
FloatType FloatType
Float16, FloatType -> PrimType
FloatType FloatType
Float16],
          FloatType -> PrimType
FloatType FloatType
Float16,
          \case
            [FloatValue (Float16Value Half
x), FloatValue (Float16Value Half
y)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ forall {a}. RealFloat a => a -> a -> a
atan2 Half
x Half
y
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"atan2_32",
        ( [FloatType -> PrimType
FloatType FloatType
Float32, FloatType -> PrimType
FloatType FloatType
Float32],
          FloatType -> PrimType
FloatType FloatType
Float32,
          \case
            [FloatValue (Float32Value Float
x), FloatValue (Float32Value Float
y)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ forall {a}. RealFloat a => a -> a -> a
atan2 Float
x Float
y
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"atan2_64",
        ( [FloatType -> PrimType
FloatType FloatType
Float64, FloatType -> PrimType
FloatType FloatType
Float64],
          FloatType -> PrimType
FloatType FloatType
Float64,
          \case
            [FloatValue (Float64Value Double
x), FloatValue (Float64Value Double
y)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ forall {a}. RealFloat a => a -> a -> a
atan2 Double
x Double
y
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      --
      ( String
"hypot16",
        ( [FloatType -> PrimType
FloatType FloatType
Float16, FloatType -> PrimType
FloatType FloatType
Float16],
          FloatType -> PrimType
FloatType FloatType
Float16,
          \case
            [FloatValue (Float16Value Half
x), FloatValue (Float16Value Half
y)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
hypotf (forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat Half
x) (forall from to. (RealFloat from, RealFloat to) => from -> to
convFloat Half
y)
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"hypot32",
        ( [FloatType -> PrimType
FloatType FloatType
Float32, FloatType -> PrimType
FloatType FloatType
Float32],
          FloatType -> PrimType
FloatType FloatType
Float32,
          \case
            [FloatValue (Float32Value Float
x), FloatValue (Float32Value Float
y)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
hypotf Float
x Float
y
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"hypot64",
        ( [FloatType -> PrimType
FloatType FloatType
Float64, FloatType -> PrimType
FloatType FloatType
Float64],
          FloatType -> PrimType
FloatType FloatType
Float64,
          \case
            [FloatValue (Float64Value Double
x), FloatValue (Float64Value Double
y)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
hypot Double
x Double
y
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"isinf16",
        ( [FloatType -> PrimType
FloatType FloatType
Float16],
          PrimType
Bool,
          \case
            [FloatValue (Float16Value Half
x)] -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ forall a. RealFloat a => a -> Bool
isInfinite Half
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"isinf32",
        ( [FloatType -> PrimType
FloatType FloatType
Float32],
          PrimType
Bool,
          \case
            [FloatValue (Float32Value Float
x)] -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ forall a. RealFloat a => a -> Bool
isInfinite Float
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"isinf64",
        ( [FloatType -> PrimType
FloatType FloatType
Float64],
          PrimType
Bool,
          \case
            [FloatValue (Float64Value Double
x)] -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ forall a. RealFloat a => a -> Bool
isInfinite Double
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"isnan16",
        ( [FloatType -> PrimType
FloatType FloatType
Float16],
          PrimType
Bool,
          \case
            [FloatValue (Float16Value Half
x)] -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ forall a. RealFloat a => a -> Bool
isNaN Half
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"isnan32",
        ( [FloatType -> PrimType
FloatType FloatType
Float32],
          PrimType
Bool,
          \case
            [FloatValue (Float32Value Float
x)] -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ forall a. RealFloat a => a -> Bool
isNaN Float
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"isnan64",
        ( [FloatType -> PrimType
FloatType FloatType
Float64],
          PrimType
Bool,
          \case
            [FloatValue (Float64Value Double
x)] -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> PrimValue
BoolValue forall a b. (a -> b) -> a -> b
$ forall a. RealFloat a => a -> Bool
isNaN Double
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"to_bits16",
        ( [FloatType -> PrimType
FloatType FloatType
Float16],
          IntType -> PrimType
IntType IntType
Int16,
          \case
            [FloatValue (Float16Value Half
x)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ Int16 -> IntValue
Int16Value forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Half -> Word16
halfToWord Half
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"to_bits32",
        ( [FloatType -> PrimType
FloatType FloatType
Float32],
          IntType -> PrimType
IntType IntType
Int32,
          \case
            [FloatValue (Float32Value Float
x)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ Int32 -> IntValue
Int32Value forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Float -> Word32
floatToWord Float
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"to_bits64",
        ( [FloatType -> PrimType
FloatType FloatType
Float64],
          IntType -> PrimType
IntType IntType
Int64,
          \case
            [FloatValue (Float64Value Double
x)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntValue -> PrimValue
IntValue forall a b. (a -> b) -> a -> b
$ Int64 -> IntValue
Int64Value forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Double -> Word64
doubleToWord Double
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"from_bits16",
        ( [IntType -> PrimType
IntType IntType
Int16],
          FloatType -> PrimType
FloatType FloatType
Float16,
          \case
            [IntValue (Int16Value Int16
x)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ Word16 -> Half
wordToHalf forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"from_bits32",
        ( [IntType -> PrimType
IntType IntType
Int32],
          FloatType -> PrimType
FloatType FloatType
Float32,
          \case
            [IntValue (Int32Value Int32
x)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ Word32 -> Float
wordToFloat forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      ( String
"from_bits64",
        ( [IntType -> PrimType
IntType IntType
Int64],
          FloatType -> PrimType
FloatType FloatType
Float64,
          \case
            [IntValue (Int64Value Int64
x)] ->
              forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ Word64 -> Double
wordToDouble forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
x
            [PrimValue]
_ -> forall a. Maybe a
Nothing
        )
      ),
      forall {a}.
a
-> (Half -> Half -> Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16_3 String
"lerp16" (\Half
v0 Half
v1 Half
t -> Half
v0 forall a. Num a => a -> a -> a
+ (Half
v1 forall a. Num a => a -> a -> a
- Half
v0) forall a. Num a => a -> a -> a
* forall a. Ord a => a -> a -> a
max Half
0 (forall a. Ord a => a -> a -> a
min Half
1 Half
t)),
      forall {a}.
a
-> (Float -> Float -> Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32_3 String
"lerp32" (\Float
v0 Float
v1 Float
t -> Float
v0 forall a. Num a => a -> a -> a
+ (Float
v1 forall a. Num a => a -> a -> a
- Float
v0) forall a. Num a => a -> a -> a
* forall a. Ord a => a -> a -> a
max Float
0 (forall a. Ord a => a -> a -> a
min Float
1 Float
t)),
      forall {a}.
a
-> (Double -> Double -> Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64_3 String
"lerp64" (\Double
v0 Double
v1 Double
t -> Double
v0 forall a. Num a => a -> a -> a
+ (Double
v1 forall a. Num a => a -> a -> a
- Double
v0) forall a. Num a => a -> a -> a
* forall a. Ord a => a -> a -> a
max Double
0 (forall a. Ord a => a -> a -> a
min Double
1 Double
t)),
      forall {a}.
a
-> (Half -> Half -> Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16_3 String
"mad16" (\Half
a Half
b Half
c -> Half
a forall a. Num a => a -> a -> a
* Half
b forall a. Num a => a -> a -> a
+ Half
c),
      forall {a}.
a
-> (Float -> Float -> Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32_3 String
"mad32" (\Float
a Float
b Float
c -> Float
a forall a. Num a => a -> a -> a
* Float
b forall a. Num a => a -> a -> a
+ Float
c),
      forall {a}.
a
-> (Double -> Double -> Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64_3 String
"mad64" (\Double
a Double
b Double
c -> Double
a forall a. Num a => a -> a -> a
* Double
b forall a. Num a => a -> a -> a
+ Double
c),
      forall {a}.
a
-> (Half -> Half -> Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16_3 String
"fma16" (\Half
a Half
b Half
c -> Half
a forall a. Num a => a -> a -> a
* Half
b forall a. Num a => a -> a -> a
+ Half
c),
      forall {a}.
a
-> (Float -> Float -> Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32_3 String
"fma32" (\Float
a Float
b Float
c -> Float
a forall a. Num a => a -> a -> a
* Float
b forall a. Num a => a -> a -> a
+ Float
c),
      forall {a}.
a
-> (Double -> Double -> Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64_3 String
"fma64" (\Double
a Double
b Double
c -> Double
a forall a. Num a => a -> a -> a
* Double
b forall a. Num a => a -> a -> a
+ Double
c)
    ]
  where
    i8 :: a
-> (Int8 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i8 a
s Int8 -> a
f = (a
s, ([IntType -> PrimType
IntType IntType
Int8], IntType -> PrimType
IntType IntType
Int32, forall {a}. (Int8 -> a) -> [PrimValue] -> Maybe a
i8PrimFun Int8 -> a
f))
    i16 :: a
-> (Int16 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i16 a
s Int16 -> a
f = (a
s, ([IntType -> PrimType
IntType IntType
Int16], IntType -> PrimType
IntType IntType
Int32, forall {a}. (Int16 -> a) -> [PrimValue] -> Maybe a
i16PrimFun Int16 -> a
f))
    i32 :: a
-> (Int32 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i32 a
s Int32 -> a
f = (a
s, ([IntType -> PrimType
IntType IntType
Int32], IntType -> PrimType
IntType IntType
Int32, forall {a}. (Int32 -> a) -> [PrimValue] -> Maybe a
i32PrimFun Int32 -> a
f))
    i64 :: a
-> (Int64 -> a)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe a))
i64 a
s Int64 -> a
f = (a
s, ([IntType -> PrimType
IntType IntType
Int64], IntType -> PrimType
IntType IntType
Int32, forall {a}. (Int64 -> a) -> [PrimValue] -> Maybe a
i64PrimFun Int64 -> a
f))
    f16 :: a
-> (Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16 a
s Half -> Half
f = (a
s, ([FloatType -> PrimType
FloatType FloatType
Float16], FloatType -> PrimType
FloatType FloatType
Float16, (Half -> Half) -> [PrimValue] -> Maybe PrimValue
f16PrimFun Half -> Half
f))
    f32 :: a
-> (Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32 a
s Float -> Float
f = (a
s, ([FloatType -> PrimType
FloatType FloatType
Float32], FloatType -> PrimType
FloatType FloatType
Float32, (Float -> Float) -> [PrimValue] -> Maybe PrimValue
f32PrimFun Float -> Float
f))
    f64 :: a
-> (Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64 a
s Double -> Double
f = (a
s, ([FloatType -> PrimType
FloatType FloatType
Float64], FloatType -> PrimType
FloatType FloatType
Float64, (Double -> Double) -> [PrimValue] -> Maybe PrimValue
f64PrimFun Double -> Double
f))
    f16_2 :: a
-> (Half -> Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16_2 a
s Half -> Half -> Half
f =
      ( a
s,
        ( [FloatType -> PrimType
FloatType FloatType
Float16, FloatType -> PrimType
FloatType FloatType
Float16],
          FloatType -> PrimType
FloatType FloatType
Float16,
          (Half -> Half -> Half) -> [PrimValue] -> Maybe PrimValue
f16PrimFun2 Half -> Half -> Half
f
        )
      )
    f32_2 :: a
-> (Float -> Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32_2 a
s Float -> Float -> Float
f =
      ( a
s,
        ( [FloatType -> PrimType
FloatType FloatType
Float32, FloatType -> PrimType
FloatType FloatType
Float32],
          FloatType -> PrimType
FloatType FloatType
Float32,
          (Float -> Float -> Float) -> [PrimValue] -> Maybe PrimValue
f32PrimFun2 Float -> Float -> Float
f
        )
      )
    f64_2 :: a
-> (Double -> Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64_2 a
s Double -> Double -> Double
f =
      ( a
s,
        ( [FloatType -> PrimType
FloatType FloatType
Float64, FloatType -> PrimType
FloatType FloatType
Float64],
          FloatType -> PrimType
FloatType FloatType
Float64,
          (Double -> Double -> Double) -> [PrimValue] -> Maybe PrimValue
f64PrimFun2 Double -> Double -> Double
f
        )
      )
    f16_3 :: a
-> (Half -> Half -> Half -> Half)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f16_3 a
s Half -> Half -> Half -> Half
f =
      ( a
s,
        ( [FloatType -> PrimType
FloatType FloatType
Float16, FloatType -> PrimType
FloatType FloatType
Float16, FloatType -> PrimType
FloatType FloatType
Float16],
          FloatType -> PrimType
FloatType FloatType
Float16,
          (Half -> Half -> Half -> Half) -> [PrimValue] -> Maybe PrimValue
f16PrimFun3 Half -> Half -> Half -> Half
f
        )
      )
    f32_3 :: a
-> (Float -> Float -> Float -> Float)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f32_3 a
s Float -> Float -> Float -> Float
f =
      ( a
s,
        ( [FloatType -> PrimType
FloatType FloatType
Float32, FloatType -> PrimType
FloatType FloatType
Float32, FloatType -> PrimType
FloatType FloatType
Float32],
          FloatType -> PrimType
FloatType FloatType
Float32,
          (Float -> Float -> Float -> Float)
-> [PrimValue] -> Maybe PrimValue
f32PrimFun3 Float -> Float -> Float -> Float
f
        )
      )
    f64_3 :: a
-> (Double -> Double -> Double -> Double)
-> (a, ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue))
f64_3 a
s Double -> Double -> Double -> Double
f =
      ( a
s,
        ( [FloatType -> PrimType
FloatType FloatType
Float64, FloatType -> PrimType
FloatType FloatType
Float64, FloatType -> PrimType
FloatType FloatType
Float64],
          FloatType -> PrimType
FloatType FloatType
Float64,
          (Double -> Double -> Double -> Double)
-> [PrimValue] -> Maybe PrimValue
f64PrimFun3 Double -> Double -> Double -> Double
f
        )
      )

    i8PrimFun :: (Int8 -> a) -> [PrimValue] -> Maybe a
i8PrimFun Int8 -> a
f [IntValue (Int8Value Int8
x)] =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Int8 -> a
f Int8
x
    i8PrimFun Int8 -> a
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    i16PrimFun :: (Int16 -> a) -> [PrimValue] -> Maybe a
i16PrimFun Int16 -> a
f [IntValue (Int16Value Int16
x)] =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Int16 -> a
f Int16
x
    i16PrimFun Int16 -> a
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    i32PrimFun :: (Int32 -> a) -> [PrimValue] -> Maybe a
i32PrimFun Int32 -> a
f [IntValue (Int32Value Int32
x)] =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Int32 -> a
f Int32
x
    i32PrimFun Int32 -> a
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    i64PrimFun :: (Int64 -> a) -> [PrimValue] -> Maybe a
i64PrimFun Int64 -> a
f [IntValue (Int64Value Int64
x)] =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Int64 -> a
f Int64
x
    i64PrimFun Int64 -> a
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f16PrimFun :: (Half -> Half) -> [PrimValue] -> Maybe PrimValue
f16PrimFun Half -> Half
f [FloatValue (Float16Value Half
x)] =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ Half -> Half
f Half
x
    f16PrimFun Half -> Half
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f32PrimFun :: (Float -> Float) -> [PrimValue] -> Maybe PrimValue
f32PrimFun Float -> Float
f [FloatValue (Float32Value Float
x)] =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ Float -> Float
f Float
x
    f32PrimFun Float -> Float
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f64PrimFun :: (Double -> Double) -> [PrimValue] -> Maybe PrimValue
f64PrimFun Double -> Double
f [FloatValue (Float64Value Double
x)] =
      forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ Double -> Double
f Double
x
    f64PrimFun Double -> Double
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f16PrimFun2 :: (Half -> Half -> Half) -> [PrimValue] -> Maybe PrimValue
f16PrimFun2
      Half -> Half -> Half
f
      [ FloatValue (Float16Value Half
a),
        FloatValue (Float16Value Half
b)
        ] =
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ Half -> Half -> Half
f Half
a Half
b
    f16PrimFun2 Half -> Half -> Half
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f32PrimFun2 :: (Float -> Float -> Float) -> [PrimValue] -> Maybe PrimValue
f32PrimFun2
      Float -> Float -> Float
f
      [ FloatValue (Float32Value Float
a),
        FloatValue (Float32Value Float
b)
        ] =
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
f Float
a Float
b
    f32PrimFun2 Float -> Float -> Float
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f64PrimFun2 :: (Double -> Double -> Double) -> [PrimValue] -> Maybe PrimValue
f64PrimFun2
      Double -> Double -> Double
f
      [ FloatValue (Float64Value Double
a),
        FloatValue (Float64Value Double
b)
        ] =
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
f Double
a Double
b
    f64PrimFun2 Double -> Double -> Double
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f16PrimFun3 :: (Half -> Half -> Half -> Half) -> [PrimValue] -> Maybe PrimValue
f16PrimFun3
      Half -> Half -> Half -> Half
f
      [ FloatValue (Float16Value Half
a),
        FloatValue (Float16Value Half
b),
        FloatValue (Float16Value Half
c)
        ] =
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Half -> FloatValue
Float16Value forall a b. (a -> b) -> a -> b
$ Half -> Half -> Half -> Half
f Half
a Half
b Half
c
    f16PrimFun3 Half -> Half -> Half -> Half
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f32PrimFun3 :: (Float -> Float -> Float -> Float)
-> [PrimValue] -> Maybe PrimValue
f32PrimFun3
      Float -> Float -> Float -> Float
f
      [ FloatValue (Float32Value Float
a),
        FloatValue (Float32Value Float
b),
        FloatValue (Float32Value Float
c)
        ] =
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Float -> FloatValue
Float32Value forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float -> Float
f Float
a Float
b Float
c
    f32PrimFun3 Float -> Float -> Float -> Float
_ [PrimValue]
_ = forall a. Maybe a
Nothing

    f64PrimFun3 :: (Double -> Double -> Double -> Double)
-> [PrimValue] -> Maybe PrimValue
f64PrimFun3
      Double -> Double -> Double -> Double
f
      [ FloatValue (Float64Value Double
a),
        FloatValue (Float64Value Double
b),
        FloatValue (Float64Value Double
c)
        ] =
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatValue -> PrimValue
FloatValue forall a b. (a -> b) -> a -> b
$ Double -> FloatValue
Float64Value forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> Double
f Double
a Double
b Double
c
    f64PrimFun3 Double -> Double -> Double -> Double
_ [PrimValue]
_ = forall a. Maybe a
Nothing

-- | Is the given value kind of zero?
zeroIsh :: PrimValue -> Bool
zeroIsh :: PrimValue -> Bool
zeroIsh (IntValue IntValue
k) = IntValue -> Bool
zeroIshInt IntValue
k
zeroIsh (FloatValue (Float16Value Half
k)) = Half
k forall a. Eq a => a -> a -> Bool
== Half
0
zeroIsh (FloatValue (Float32Value Float
k)) = Float
k forall a. Eq a => a -> a -> Bool
== Float
0
zeroIsh (FloatValue (Float64Value Double
k)) = Double
k forall a. Eq a => a -> a -> Bool
== Double
0
zeroIsh (BoolValue Bool
False) = Bool
True
zeroIsh PrimValue
_ = Bool
False

-- | Is the given value kind of one?
oneIsh :: PrimValue -> Bool
oneIsh :: PrimValue -> Bool
oneIsh (IntValue IntValue
k) = IntValue -> Bool
oneIshInt IntValue
k
oneIsh (FloatValue (Float16Value Half
k)) = Half
k forall a. Eq a => a -> a -> Bool
== Half
1
oneIsh (FloatValue (Float32Value Float
k)) = Float
k forall a. Eq a => a -> a -> Bool
== Float
1
oneIsh (FloatValue (Float64Value Double
k)) = Double
k forall a. Eq a => a -> a -> Bool
== Double
1
oneIsh (BoolValue Bool
True) = Bool
True
oneIsh PrimValue
_ = Bool
False

-- | Is the given value kind of negative?
negativeIsh :: PrimValue -> Bool
negativeIsh :: PrimValue -> Bool
negativeIsh (IntValue IntValue
k) = IntValue -> Bool
negativeIshInt IntValue
k
negativeIsh (FloatValue (Float16Value Half
k)) = Half
k forall a. Ord a => a -> a -> Bool
< Half
0
negativeIsh (FloatValue (Float32Value Float
k)) = Float
k forall a. Ord a => a -> a -> Bool
< Float
0
negativeIsh (FloatValue (Float64Value Double
k)) = Double
k forall a. Ord a => a -> a -> Bool
< Double
0
negativeIsh (BoolValue Bool
_) = Bool
False
negativeIsh PrimValue
UnitValue = Bool
False

-- | Is the given integer value kind of zero?
zeroIshInt :: IntValue -> Bool
zeroIshInt :: IntValue -> Bool
zeroIshInt (Int8Value Int8
k) = Int8
k forall a. Eq a => a -> a -> Bool
== Int8
0
zeroIshInt (Int16Value Int16
k) = Int16
k forall a. Eq a => a -> a -> Bool
== Int16
0
zeroIshInt (Int32Value Int32
k) = Int32
k forall a. Eq a => a -> a -> Bool
== Int32
0
zeroIshInt (Int64Value Int64
k) = Int64
k forall a. Eq a => a -> a -> Bool
== Int64
0

-- | Is the given integer value kind of one?
oneIshInt :: IntValue -> Bool
oneIshInt :: IntValue -> Bool
oneIshInt (Int8Value Int8
k) = Int8
k forall a. Eq a => a -> a -> Bool
== Int8
1
oneIshInt (Int16Value Int16
k) = Int16
k forall a. Eq a => a -> a -> Bool
== Int16
1
oneIshInt (Int32Value Int32
k) = Int32
k forall a. Eq a => a -> a -> Bool
== Int32
1
oneIshInt (Int64Value Int64
k) = Int64
k forall a. Eq a => a -> a -> Bool
== Int64
1

-- | Is the given integer value kind of negative?
negativeIshInt :: IntValue -> Bool
negativeIshInt :: IntValue -> Bool
negativeIshInt (Int8Value Int8
k) = Int8
k forall a. Ord a => a -> a -> Bool
< Int8
0
negativeIshInt (Int16Value Int16
k) = Int16
k forall a. Ord a => a -> a -> Bool
< Int16
0
negativeIshInt (Int32Value Int32
k) = Int32
k forall a. Ord a => a -> a -> Bool
< Int32
0
negativeIshInt (Int64Value Int64
k) = Int64
k forall a. Ord a => a -> a -> Bool
< Int64
0

-- | The size of a value of a given primitive type in bits.
primBitSize :: PrimType -> Int
primBitSize :: PrimType -> Int
primBitSize = (forall a. Num a => a -> a -> a
* Int
8) forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Num a => PrimType -> a
primByteSize

-- | The size of a value of a given primitive type in eight-bit bytes.
primByteSize :: Num a => PrimType -> a
primByteSize :: forall a. Num a => PrimType -> a
primByteSize (IntType IntType
t) = forall a. Num a => IntType -> a
intByteSize IntType
t
primByteSize (FloatType FloatType
t) = forall a. Num a => FloatType -> a
floatByteSize FloatType
t
primByteSize PrimType
Bool = a
1
primByteSize PrimType
Unit = a
0

-- | The size of a value of a given integer type in eight-bit bytes.
intByteSize :: Num a => IntType -> a
intByteSize :: forall a. Num a => IntType -> a
intByteSize IntType
Int8 = a
1
intByteSize IntType
Int16 = a
2
intByteSize IntType
Int32 = a
4
intByteSize IntType
Int64 = a
8

-- | The size of a value of a given floating-point type in eight-bit bytes.
floatByteSize :: Num a => FloatType -> a
floatByteSize :: forall a. Num a => FloatType -> a
floatByteSize FloatType
Float16 = a
2
floatByteSize FloatType
Float32 = a
4
floatByteSize FloatType
Float64 = a
8

-- | True if the given binary operator is commutative.
commutativeBinOp :: BinOp -> Bool
commutativeBinOp :: BinOp -> Bool
commutativeBinOp Add {} = Bool
True
commutativeBinOp FAdd {} = Bool
True
commutativeBinOp Mul {} = Bool
True
commutativeBinOp FMul {} = Bool
True
commutativeBinOp And {} = Bool
True
commutativeBinOp Or {} = Bool
True
commutativeBinOp Xor {} = Bool
True
commutativeBinOp LogOr {} = Bool
True
commutativeBinOp LogAnd {} = Bool
True
commutativeBinOp SMax {} = Bool
True
commutativeBinOp SMin {} = Bool
True
commutativeBinOp UMax {} = Bool
True
commutativeBinOp UMin {} = Bool
True
commutativeBinOp FMax {} = Bool
True
commutativeBinOp FMin {} = Bool
True
commutativeBinOp BinOp
_ = Bool
False

-- | True if the given binary operator is associative.
associativeBinOp :: BinOp -> Bool
associativeBinOp :: BinOp -> Bool
associativeBinOp Add {} = Bool
True
associativeBinOp Mul {} = Bool
True
associativeBinOp And {} = Bool
True
associativeBinOp Or {} = Bool
True
associativeBinOp Xor {} = Bool
True
associativeBinOp LogOr {} = Bool
True
associativeBinOp LogAnd {} = Bool
True
associativeBinOp SMax {} = Bool
True
associativeBinOp SMin {} = Bool
True
associativeBinOp UMax {} = Bool
True
associativeBinOp UMin {} = Bool
True
associativeBinOp FMax {} = Bool
True
associativeBinOp FMin {} = Bool
True
associativeBinOp BinOp
_ = Bool
False

-- Prettyprinting instances

instance Pretty BinOp where
  pretty :: forall ann. BinOp -> Doc ann
pretty (Add IntType
t Overflow
OverflowWrap) = forall a. String -> IntType -> Doc a
taggedI String
"add" IntType
t
  pretty (Add IntType
t Overflow
OverflowUndef) = forall a. String -> IntType -> Doc a
taggedI String
"add_nw" IntType
t
  pretty (Sub IntType
t Overflow
OverflowWrap) = forall a. String -> IntType -> Doc a
taggedI String
"sub" IntType
t
  pretty (Sub IntType
t Overflow
OverflowUndef) = forall a. String -> IntType -> Doc a
taggedI String
"sub_nw" IntType
t
  pretty (Mul IntType
t Overflow
OverflowWrap) = forall a. String -> IntType -> Doc a
taggedI String
"mul" IntType
t
  pretty (Mul IntType
t Overflow
OverflowUndef) = forall a. String -> IntType -> Doc a
taggedI String
"mul_nw" IntType
t
  pretty (FAdd FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fadd" FloatType
t
  pretty (FSub FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fsub" FloatType
t
  pretty (FMul FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fmul" FloatType
t
  pretty (UDiv IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"udiv_safe" IntType
t
  pretty (UDiv IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"udiv" IntType
t
  pretty (UDivUp IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"udiv_up_safe" IntType
t
  pretty (UDivUp IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"udiv_up" IntType
t
  pretty (UMod IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"umod_safe" IntType
t
  pretty (UMod IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"umod" IntType
t
  pretty (SDiv IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"sdiv_safe" IntType
t
  pretty (SDiv IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"sdiv" IntType
t
  pretty (SDivUp IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"sdiv_up_safe" IntType
t
  pretty (SDivUp IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"sdiv_up" IntType
t
  pretty (SMod IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"smod_safe" IntType
t
  pretty (SMod IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"smod" IntType
t
  pretty (SQuot IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"squot_safe" IntType
t
  pretty (SQuot IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"squot" IntType
t
  pretty (SRem IntType
t Safety
Safe) = forall a. String -> IntType -> Doc a
taggedI String
"srem_safe" IntType
t
  pretty (SRem IntType
t Safety
Unsafe) = forall a. String -> IntType -> Doc a
taggedI String
"srem" IntType
t
  pretty (FDiv FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fdiv" FloatType
t
  pretty (FMod FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fmod" FloatType
t
  pretty (SMin IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"smin" IntType
t
  pretty (UMin IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"umin" IntType
t
  pretty (FMin FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fmin" FloatType
t
  pretty (SMax IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"smax" IntType
t
  pretty (UMax IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"umax" IntType
t
  pretty (FMax FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fmax" FloatType
t
  pretty (Shl IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"shl" IntType
t
  pretty (LShr IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"lshr" IntType
t
  pretty (AShr IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"ashr" IntType
t
  pretty (And IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"and" IntType
t
  pretty (Or IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"or" IntType
t
  pretty (Xor IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"xor" IntType
t
  pretty (Pow IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"pow" IntType
t
  pretty (FPow FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fpow" FloatType
t
  pretty BinOp
LogAnd = Doc ann
"logand"
  pretty BinOp
LogOr = Doc ann
"logor"

instance Pretty CmpOp where
  pretty :: forall ann. CmpOp -> Doc ann
pretty (CmpEq PrimType
t) = Doc ann
"eq_" forall a. Semigroup a => a -> a -> a
<> forall a ann. Pretty a => a -> Doc ann
pretty PrimType
t
  pretty (CmpUlt IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"ult" IntType
t
  pretty (CmpUle IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"ule" IntType
t
  pretty (CmpSlt IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"slt" IntType
t
  pretty (CmpSle IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"sle" IntType
t
  pretty (FCmpLt FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"lt" FloatType
t
  pretty (FCmpLe FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"le" FloatType
t
  pretty CmpOp
CmpLlt = Doc ann
"llt"
  pretty CmpOp
CmpLle = Doc ann
"lle"

instance Pretty ConvOp where
  pretty :: forall ann. ConvOp -> Doc ann
pretty ConvOp
op = forall from to a.
(Pretty from, Pretty to) =>
String -> from -> to -> Doc a
convOp (ConvOp -> String
convOpFun ConvOp
op) PrimType
from PrimType
to
    where
      (PrimType
from, PrimType
to) = ConvOp -> (PrimType, PrimType)
convOpType ConvOp
op

instance Pretty UnOp where
  pretty :: forall ann. UnOp -> Doc ann
pretty UnOp
Not = Doc ann
"not"
  pretty (Abs IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"abs" IntType
t
  pretty (FAbs FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fabs" FloatType
t
  pretty (SSignum IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"ssignum" IntType
t
  pretty (USignum IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"usignum" IntType
t
  pretty (FSignum FloatType
t) = forall a. String -> FloatType -> Doc a
taggedF String
"fsignum" FloatType
t
  pretty (Complement IntType
t) = forall a. String -> IntType -> Doc a
taggedI String
"complement" IntType
t

-- | The human-readable name for a 'ConvOp'.  This is used to expose
-- the 'ConvOp' in the @intrinsics@ module of a Futhark program.
convOpFun :: ConvOp -> String
convOpFun :: ConvOp -> String
convOpFun ZExt {} = String
"zext"
convOpFun SExt {} = String
"sext"
convOpFun FPConv {} = String
"fpconv"
convOpFun FPToUI {} = String
"fptoui"
convOpFun FPToSI {} = String
"fptosi"
convOpFun UIToFP {} = String
"uitofp"
convOpFun SIToFP {} = String
"sitofp"
convOpFun IToB {} = String
"itob"
convOpFun BToI {} = String
"btoi"
convOpFun FToB {} = String
"ftob"
convOpFun BToF {} = String
"btof"

taggedI :: String -> IntType -> Doc a
taggedI :: forall a. String -> IntType -> Doc a
taggedI String
s IntType
Int8 = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
"8"
taggedI String
s IntType
Int16 = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
"16"
taggedI String
s IntType
Int32 = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
"32"
taggedI String
s IntType
Int64 = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
"64"

taggedF :: String -> FloatType -> Doc a
taggedF :: forall a. String -> FloatType -> Doc a
taggedF String
s FloatType
Float16 = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
"16"
taggedF String
s FloatType
Float32 = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
"32"
taggedF String
s FloatType
Float64 = forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
"64"

convOp :: (Pretty from, Pretty to) => String -> from -> to -> Doc a
convOp :: forall from to a.
(Pretty from, Pretty to) =>
String -> from -> to -> Doc a
convOp String
s from
from to
to = forall a ann. Pretty a => a -> Doc ann
pretty String
s forall a. Semigroup a => a -> a -> a
<> Doc a
"_" forall a. Semigroup a => a -> a -> a
<> forall a ann. Pretty a => a -> Doc ann
pretty from
from forall a. Semigroup a => a -> a -> a
<> Doc a
"_" forall a. Semigroup a => a -> a -> a
<> forall a ann. Pretty a => a -> Doc ann
pretty to
to

-- | True if signed.  Only makes a difference for integer types.
prettySigned :: Bool -> PrimType -> String
prettySigned :: Bool -> PrimType -> String
prettySigned Bool
True (IntType IntType
it) = Char
'u' forall a. a -> [a] -> [a]
: forall a. Int -> [a] -> [a]
drop Int
1 (forall a. Pretty a => a -> String
prettyString IntType
it)
prettySigned Bool
_ PrimType
t = forall a. Pretty a => a -> String
prettyString PrimType
t

mul_hi8 :: IntValue -> IntValue -> Int8
mul_hi8 :: IntValue -> IntValue -> Int8
mul_hi8 IntValue
a IntValue
b =
  let a' :: Word64
a' = IntValue -> Word64
intToWord64 IntValue
a
      b' :: Word64
b' = IntValue -> Word64
intToWord64 IntValue
b
   in forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR (Word64
a' forall a. Num a => a -> a -> a
* Word64
b') Int
8)

mul_hi16 :: IntValue -> IntValue -> Int16
mul_hi16 :: IntValue -> IntValue -> Int16
mul_hi16 IntValue
a IntValue
b =
  let a' :: Word64
a' = IntValue -> Word64
intToWord64 IntValue
a
      b' :: Word64
b' = IntValue -> Word64
intToWord64 IntValue
b
   in forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR (Word64
a' forall a. Num a => a -> a -> a
* Word64
b') Int
16)

mul_hi32 :: IntValue -> IntValue -> Int32
mul_hi32 :: IntValue -> IntValue -> Int32
mul_hi32 IntValue
a IntValue
b =
  let a' :: Word64
a' = IntValue -> Word64
intToWord64 IntValue
a
      b' :: Word64
b' = IntValue -> Word64
intToWord64 IntValue
b
   in forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR (Word64
a' forall a. Num a => a -> a -> a
* Word64
b') Int
32)

mul_hi64 :: IntValue -> IntValue -> Int64
mul_hi64 :: IntValue -> IntValue -> Int64
mul_hi64 IntValue
a IntValue
b =
  let a' :: Integer
a' = (forall a. Integral a => a -> Integer
toInteger forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IntValue -> Word64
intToWord64) IntValue
a
      b' :: Integer
b' = (forall a. Integral a => a -> Integer
toInteger forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IntValue -> Word64
intToWord64) IntValue
b
   in forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR (Integer
a' forall a. Num a => a -> a -> a
* Integer
b') Int
64)

mad_hi8 :: IntValue -> IntValue -> Int8 -> Int8
mad_hi8 :: IntValue -> IntValue -> Int8 -> Int8
mad_hi8 IntValue
a IntValue
b Int8
c = IntValue -> IntValue -> Int8
mul_hi8 IntValue
a IntValue
b forall a. Num a => a -> a -> a
+ Int8
c

mad_hi16 :: IntValue -> IntValue -> Int16 -> Int16
mad_hi16 :: IntValue -> IntValue -> Int16 -> Int16
mad_hi16 IntValue
a IntValue
b Int16
c = IntValue -> IntValue -> Int16
mul_hi16 IntValue
a IntValue
b forall a. Num a => a -> a -> a
+ Int16
c

mad_hi32 :: IntValue -> IntValue -> Int32 -> Int32
mad_hi32 :: IntValue -> IntValue -> Int32 -> Int32
mad_hi32 IntValue
a IntValue
b Int32
c = IntValue -> IntValue -> Int32
mul_hi32 IntValue
a IntValue
b forall a. Num a => a -> a -> a
+ Int32
c

mad_hi64 :: IntValue -> IntValue -> Int64 -> Int64
mad_hi64 :: IntValue -> IntValue -> Int64 -> Int64
mad_hi64 IntValue
a IntValue
b Int64
c = IntValue -> IntValue -> Int64
mul_hi64 IntValue
a IntValue
b forall a. Num a => a -> a -> a
+ Int64
c