{-# LANGUAGE CPP       #-}
{-# LANGUAGE MagicHash #-}
-- |
-- Module      : Data.Array.Accelerate.Internal.LLVM.PTX
-- Copyright   : [2016..2020] Trevor L. McDonell
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--

module Data.Array.Accelerate.Internal.LLVM.PTX (

  -- Operators from Num2
  addWithCarryInt64#, mulWithCarryInt64#,
  addWithCarryWord64#, mulWithCarryWord64#,

  -- Operators from Num
  addInt128#, subInt128#, mulInt128#,
  addWord128#, subWord128#, mulWord128#,

  -- Operators from Integral
  quotInt128#, remInt128#, quotRemInt128#,
  quotWord128#, remWord128#, quotRemWord128#,

) where

import Data.Array.Accelerate                                        as A
import Data.Array.Accelerate.Sugar.Elt
import Data.Array.Accelerate.Internal.BigInt
import Data.Array.Accelerate.Internal.BigWord
import Data.Array.Accelerate.Internal.Orphans.Elt                   ()

#ifdef ACCELERATE_LLVM_PTX_BACKEND
import Data.Array.Accelerate.LLVM.CodeGen.Sugar
import Data.Array.Accelerate.LLVM.PTX.Foreign                       as A
import qualified Data.Array.Accelerate.Internal.LLVM.Prim           as Prim
#endif


#ifdef ACCELERATE_LLVM_PTX_BACKEND
wrap2 :: (Elt a, Elt b, Elt c)
      => String                                       -- name of the operation
      -> IRFun1 PTX () (EltR (a, b) -> EltR c)        -- foreign implementation
      -> (Exp a -> Exp b -> Exp c)                    -- fallback implementation
      -> Exp a
      -> Exp b
      -> Exp c
wrap2 :: String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
str IRFun1 PTX () (EltR (a, b) -> EltR c)
f Exp a -> Exp b -> Exp c
g = (Exp (Plain (Exp a), Plain (Exp b)) -> Exp c)
-> Exp a -> Exp b -> Exp c
forall (f :: * -> *) a b c.
Lift f (f a, f b) =>
(f (Plain (f a), Plain (f b)) -> f c) -> f a -> f b -> f c
A.curry (ForeignExp (EltR (a, b) -> EltR c)
-> (Exp (a, b) -> Exp c) -> Exp (a, b) -> Exp c
forall x y (asm :: * -> *).
(Elt x, Elt y, Foreign asm) =>
asm (EltR x -> EltR y) -> (Exp x -> Exp y) -> Exp x -> Exp y
foreignExp (String
-> IRFun1 PTX () ((((), EltR a), EltR b) -> EltR c)
-> ForeignExp ((((), EltR a), EltR b) -> EltR c)
forall x y. String -> IRFun1 PTX () (x -> y) -> ForeignExp (x -> y)
ForeignExp String
str IRFun1 PTX () ((((), EltR a), EltR b) -> EltR c)
IRFun1 PTX () (EltR (a, b) -> EltR c)
f) ((Exp a -> Exp b -> Exp c)
-> Exp (Plain (Exp a), Plain (Exp b)) -> Exp c
forall (f :: * -> *) a b c.
Unlift f (f a, f b) =>
(f a -> f b -> f c) -> f (Plain (f a), Plain (f b)) -> f c
A.uncurry Exp a -> Exp b -> Exp c
g))
#endif

-- Operations from Num2
-- --------------------

addWithCarryInt64#
    :: (Exp Int64 -> Exp Int64 -> Exp (Int64, Word64))
    -> Exp Int64
    -> Exp Int64
    -> Exp (Int64, Word64)
#ifdef ACCELERATE_LLVM_PTX_BACKEND
addWithCarryInt64# :: (Exp Int64 -> Exp Int64 -> Exp (Int64, Word64))
-> Exp Int64 -> Exp Int64 -> Exp (Int64, Word64)
addWithCarryInt64# = String
-> IRFun1 PTX () (EltR (Int64, Int64) -> EltR (Int64, Word64))
-> (Exp Int64 -> Exp Int64 -> Exp (Int64, Word64))
-> Exp Int64
-> Exp Int64
-> Exp (Int64, Word64)
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"addWithCarryInt64#" IRFun1 PTX () (EltR (Int64, Int64) -> EltR (Int64, Word64))
forall arch.
IRFun1 arch () (EltR (Int64, Int64) -> EltR (Int64, Word64))
Prim.addWithCarryInt64#
#else
addWithCarryInt64# = id
#endif

mulWithCarryInt64#
    :: (Exp Int64 -> Exp Int64 -> Exp (Int64, Word64))
    -> Exp Int64
    -> Exp Int64
    -> Exp (Int64, Word64)
#ifdef ACCELERATE_LLVM_PTX_BACKEND
mulWithCarryInt64# :: (Exp Int64 -> Exp Int64 -> Exp (Int64, Word64))
-> Exp Int64 -> Exp Int64 -> Exp (Int64, Word64)
mulWithCarryInt64# = String
-> IRFun1 PTX () (EltR (Int64, Int64) -> EltR (Int64, Word64))
-> (Exp Int64 -> Exp Int64 -> Exp (Int64, Word64))
-> Exp Int64
-> Exp Int64
-> Exp (Int64, Word64)
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"mulWithCarryInt64#" IRFun1 PTX () (EltR (Int64, Int64) -> EltR (Int64, Word64))
forall arch.
IRFun1 arch () (EltR (Int64, Int64) -> EltR (Int64, Word64))
Prim.mulWithCarryInt64#
#else
mulWithCarryInt64# = id
#endif

addWithCarryWord64#
    :: (Exp Word64 -> Exp Word64 -> Exp (Word64, Word64))
    -> Exp Word64
    -> Exp Word64
    -> Exp (Word64, Word64)
#ifdef ACCELERATE_LLVM_PTX_BACKEND
addWithCarryWord64# :: (Exp Word64 -> Exp Word64 -> Exp (Word64, Word64))
-> Exp Word64 -> Exp Word64 -> Exp (Word64, Word64)
addWithCarryWord64# = String
-> IRFun1 PTX () (EltR (Word64, Word64) -> EltR (Word64, Word64))
-> (Exp Word64 -> Exp Word64 -> Exp (Word64, Word64))
-> Exp Word64
-> Exp Word64
-> Exp (Word64, Word64)
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"addWithCarryWord64#" IRFun1 PTX () (EltR (Word64, Word64) -> EltR (Word64, Word64))
forall arch.
IRFun1 arch () (EltR (Word64, Word64) -> EltR (Word64, Word64))
Prim.addWithCarryWord64#
#else
addWithCarryWord64# = id
#endif

mulWithCarryWord64#
    :: (Exp Word64 -> Exp Word64 -> Exp (Word64, Word64))
    -> Exp Word64
    -> Exp Word64
    -> Exp (Word64, Word64)
#ifdef ACCELERATE_LLVM_PTX_BACKEND
mulWithCarryWord64# :: (Exp Word64 -> Exp Word64 -> Exp (Word64, Word64))
-> Exp Word64 -> Exp Word64 -> Exp (Word64, Word64)
mulWithCarryWord64# = String
-> IRFun1 PTX () (EltR (Word64, Word64) -> EltR (Word64, Word64))
-> (Exp Word64 -> Exp Word64 -> Exp (Word64, Word64))
-> Exp Word64
-> Exp Word64
-> Exp (Word64, Word64)
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"mulWithCarryWord64#" IRFun1 PTX () (EltR (Word64, Word64) -> EltR (Word64, Word64))
forall arch.
IRFun1 arch () (EltR (Word64, Word64) -> EltR (Word64, Word64))
Prim.mulWithCarryWord64#
#else
mulWithCarryWord64# = id
#endif


-- Operations from Num
-- -------------------

addInt128#
    :: (Exp Int128 -> Exp Int128 -> Exp Int128)
    -> Exp Int128
    -> Exp Int128
    -> Exp Int128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
addInt128# :: (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128 -> Exp Int128 -> Exp Int128
addInt128# = String
-> IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
-> (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128
-> Exp Int128
-> Exp Int128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"addInt128#" IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
forall arch. IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
Prim.addInt128#
#else
addInt128# = id
#endif

subInt128#
    :: (Exp Int128 -> Exp Int128 -> Exp Int128)
    -> Exp Int128
    -> Exp Int128
    -> Exp Int128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
subInt128# :: (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128 -> Exp Int128 -> Exp Int128
subInt128# = String
-> IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
-> (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128
-> Exp Int128
-> Exp Int128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"subInt128#" IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
forall arch. IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
Prim.subInt128#
#else
subInt128# = id
#endif

mulInt128#
    :: (Exp Int128 -> Exp Int128 -> Exp Int128)
    -> Exp Int128
    -> Exp Int128
    -> Exp Int128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
mulInt128# :: (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128 -> Exp Int128 -> Exp Int128
mulInt128# = String
-> IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
-> (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128
-> Exp Int128
-> Exp Int128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"mulInt128#" IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
forall arch. IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
Prim.mulInt128#
#else
mulInt128# = id
#endif

addWord128#
    :: (Exp Word128 -> Exp Word128 -> Exp Word128)
    -> Exp Word128
    -> Exp Word128
    -> Exp Word128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
addWord128# :: (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128 -> Exp Word128 -> Exp Word128
addWord128# = String
-> IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
-> (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128
-> Exp Word128
-> Exp Word128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"addWord128#" IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
forall arch.
IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
Prim.addWord128#
#else
addWord128# = id
#endif

subWord128#
    :: (Exp Word128 -> Exp Word128 -> Exp Word128)
    -> Exp Word128
    -> Exp Word128
    -> Exp Word128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
subWord128# :: (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128 -> Exp Word128 -> Exp Word128
subWord128# = String
-> IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
-> (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128
-> Exp Word128
-> Exp Word128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"subWord128#" IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
forall arch.
IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
Prim.subWord128#
#else
subWord128# = id
#endif

mulWord128#
    :: (Exp Word128 -> Exp Word128 -> Exp Word128)
    -> Exp Word128
    -> Exp Word128
    -> Exp Word128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
mulWord128# :: (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128 -> Exp Word128 -> Exp Word128
mulWord128# = String
-> IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
-> (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128
-> Exp Word128
-> Exp Word128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"mulWord128#" IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
forall arch.
IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
Prim.mulWord128#
#else
mulWord128# = id
#endif


-- Operations from Integral
-- ------------------------

quotInt128#
    :: (Exp Int128 -> Exp Int128 -> Exp Int128)
    -> Exp Int128
    -> Exp Int128
    -> Exp Int128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
quotInt128# :: (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128 -> Exp Int128 -> Exp Int128
quotInt128# = String
-> IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
-> (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128
-> Exp Int128
-> Exp Int128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"quotInt128#" IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
forall arch. IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
Prim.quotInt128#
#else
quotInt128# = id
#endif

remInt128#
    :: (Exp Int128 -> Exp Int128 -> Exp Int128)
    -> Exp Int128
    -> Exp Int128
    -> Exp Int128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
remInt128# :: (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128 -> Exp Int128 -> Exp Int128
remInt128# = String
-> IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
-> (Exp Int128 -> Exp Int128 -> Exp Int128)
-> Exp Int128
-> Exp Int128
-> Exp Int128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"remInt128#" IRFun1 PTX () (EltR (Int128, Int128) -> EltR Int128)
forall arch. IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
Prim.remInt128#
#else
remInt128# = id
#endif

quotRemInt128#
    :: (Exp Int128 -> Exp Int128 -> Exp (Int128, Int128))
    -> Exp Int128
    -> Exp Int128
    -> Exp (Int128, Int128)
#ifdef ACCELERATE_LLVM_PTX_BACKEND
quotRemInt128# :: (Exp Int128 -> Exp Int128 -> Exp (Int128, Int128))
-> Exp Int128 -> Exp Int128 -> Exp (Int128, Int128)
quotRemInt128# = String
-> IRFun1 PTX () (EltR (Int128, Int128) -> EltR (Int128, Int128))
-> (Exp Int128 -> Exp Int128 -> Exp (Int128, Int128))
-> Exp Int128
-> Exp Int128
-> Exp (Int128, Int128)
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"quotRemInt128#" IRFun1 PTX () (EltR (Int128, Int128) -> EltR (Int128, Int128))
forall arch.
IRFun1 arch () (EltR (Int128, Int128) -> EltR (Int128, Int128))
Prim.quotRemInt128#
#else
quotRemInt128# = id
#endif

quotWord128#
    :: (Exp Word128 -> Exp Word128 -> Exp Word128)
    -> Exp Word128
    -> Exp Word128
    -> Exp Word128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
quotWord128# :: (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128 -> Exp Word128 -> Exp Word128
quotWord128# = String
-> IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
-> (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128
-> Exp Word128
-> Exp Word128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"quotWord128#" IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
forall arch.
IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
Prim.quotWord128#
#else
quotWord128# = id
#endif

remWord128#
    :: (Exp Word128 -> Exp Word128 -> Exp Word128)
    -> Exp Word128
    -> Exp Word128
    -> Exp Word128
#ifdef ACCELERATE_LLVM_PTX_BACKEND
remWord128# :: (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128 -> Exp Word128 -> Exp Word128
remWord128# = String
-> IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
-> (Exp Word128 -> Exp Word128 -> Exp Word128)
-> Exp Word128
-> Exp Word128
-> Exp Word128
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"remWord128#" IRFun1 PTX () (EltR (Word128, Word128) -> EltR Word128)
forall arch.
IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
Prim.remWord128#
#else
remWord128# = id
#endif

quotRemWord128#
    :: (Exp Word128 -> Exp Word128 -> Exp (Word128, Word128))
    -> Exp Word128
    -> Exp Word128
    -> Exp (Word128, Word128)
#ifdef ACCELERATE_LLVM_PTX_BACKEND
quotRemWord128# :: (Exp Word128 -> Exp Word128 -> Exp (Word128, Word128))
-> Exp Word128 -> Exp Word128 -> Exp (Word128, Word128)
quotRemWord128# = String
-> IRFun1
     PTX () (EltR (Word128, Word128) -> EltR (Word128, Word128))
-> (Exp Word128 -> Exp Word128 -> Exp (Word128, Word128))
-> Exp Word128
-> Exp Word128
-> Exp (Word128, Word128)
forall a b c.
(Elt a, Elt b, Elt c) =>
String
-> IRFun1 PTX () (EltR (a, b) -> EltR c)
-> (Exp a -> Exp b -> Exp c)
-> Exp a
-> Exp b
-> Exp c
wrap2 String
"quotRemWord128#" IRFun1 PTX () (EltR (Word128, Word128) -> EltR (Word128, Word128))
forall arch.
IRFun1 arch () (EltR (Word128, Word128) -> EltR (Word128, Word128))
Prim.quotRemWord128#
#else
quotRemWord128# = id
#endif