{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ViewPatterns #-}
--------------------------------------------------------------------------------
-- |
-- Module      : ArrayFire.FFI
-- Copyright   : David Johnson (c) 2019-2026
-- License     : BSD 3
-- Maintainer  : David Johnson <code@dmj.io>
-- Stability   : Experimental
-- Portability : GHC
--
-- Internal marshalling combinators that bridge the high-level API modules and
-- the raw @ArrayFire.Internal.*@ FFI bindings. Each combinator unwraps the
-- managed handles ('Array', 'Window', 'Features', 'RandomEngine'), allocates
-- the output pointers, invokes the supplied C function, checks the returned
-- 'AFErr' with 'throwAFError', and attaches the appropriate finalizer to any
-- newly-created handle. These helpers are not part of the public API.
--------------------------------------------------------------------------------
module ArrayFire.FFI where

import ArrayFire.Exception
import ArrayFire.Types
import ArrayFire.Internal.Defines
import ArrayFire.Internal.Features
import ArrayFire.Internal.Array
import ArrayFire.Internal.Types

import Control.Exception
import Control.Monad
import Data.Int
import Foreign.ForeignPtr
import Foreign.Storable
import Foreign.Ptr
import Foreign.C
import Foreign.Marshal.Alloc
import Foreign.Marshal.Utils (fillBytes)
import System.IO.Unsafe

-- | Like 'alloca' but zero-initialises the memory before handing the pointer
-- to the continuation. Prevents uninitialized stack garbage from leaking into
-- output scalars when the C function does not write the imaginary-part pointer
-- for real-valued arrays (e.g. af_mean_all_weighted).
calloca :: forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca :: forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca Ptr a -> IO b
f = (Ptr a -> IO b) -> IO b
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO b) -> IO b) -> (Ptr a -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \Ptr a
p -> Ptr a -> Word8 -> Int -> IO ()
forall a. Ptr a -> Word8 -> Int -> IO ()
fillBytes Ptr a
p Word8
0 (a -> Int
forall a. Storable a => a -> Int
sizeOf (a
forall a. HasCallStack => a
undefined :: a)) IO () -> IO b -> IO b
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr a -> IO b
f Ptr a
p

foreign import ccall unsafe "af_cast"
    af_cast :: Ptr AFArray -> AFArray -> AFDtype -> IO AFErr

foreign import ccall unsafe "af_release_array"
    af_release_array_ffi :: AFArray -> IO AFErr

-- | Applies a C function that takes three input 'Array's and produces a single
-- output 'Array'.
op3
  :: Array b
  -> Array a
  -> Array a
  -> (Ptr AFArray -> AFArray -> AFArray -> AFArray -> IO AFErr)
  -> Array a
{-# NOINLINE op3 #-}
op3 :: forall b a.
Array b
-> Array a
-> Array a
-> (Ptr AFWindow -> AFWindow -> AFWindow -> AFWindow -> IO AFErr)
-> Array a
op3 (Array ForeignPtr ()
fptr1) (Array ForeignPtr ()
fptr2) (Array ForeignPtr ()
fptr3) Ptr AFWindow -> AFWindow -> AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a)
-> (IO (Array a) -> IO (Array a)) -> IO (Array a) -> Array a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array a) -> IO (Array a)
forall a. IO a -> IO a
mask_ (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (Array a)) -> IO (Array a))
-> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      ForeignPtr () -> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr2 ((AFWindow -> IO (Array a)) -> IO (Array a))
-> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr2 -> do
         ForeignPtr () -> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr3 ((AFWindow -> IO (Array a)) -> IO (Array a))
-> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr3 -> do
           ptr <-
             (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
               AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1 AFWindow
ptr2 AFWindow
ptr3
               Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
           fptr <- newForeignPtr af_release_array_finalizer ptr
           pure (Array fptr)

-- | Like 'op3', but specialised to two 'Int32' index 'Array's alongside the
-- primary input.
op3Int
  :: Array a
  -> Array Int32
  -> Array Int32
  -> (Ptr AFArray -> AFArray -> AFArray -> AFArray -> IO AFErr)
  -> Array a
{-# NOINLINE op3Int #-}
op3Int :: forall a.
Array a
-> Array Int32
-> Array Int32
-> (Ptr AFWindow -> AFWindow -> AFWindow -> AFWindow -> IO AFErr)
-> Array a
op3Int (Array ForeignPtr ()
fptr1) (Array ForeignPtr ()
fptr2) (Array ForeignPtr ()
fptr3) Ptr AFWindow -> AFWindow -> AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a)
-> (IO (Array a) -> IO (Array a)) -> IO (Array a) -> Array a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array a) -> IO (Array a)
forall a. IO a -> IO a
mask_ (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (Array a)) -> IO (Array a))
-> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      ForeignPtr () -> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr2 ((AFWindow -> IO (Array a)) -> IO (Array a))
-> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr2 -> do
         ForeignPtr () -> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr3 ((AFWindow -> IO (Array a)) -> IO (Array a))
-> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr3 -> do
           ptr <-
             (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
               AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1 AFWindow
ptr2 AFWindow
ptr3
               Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
           fptr <- newForeignPtr af_release_array_finalizer ptr
           pure (Array fptr)

-- | Applies a C function that takes two input 'Array's and produces a single
-- output 'Array'.
op2
  :: Array b
  -> Array a
  -> (Ptr AFArray -> AFArray -> AFArray -> IO AFErr)
  -> Array c
{-# NOINLINE op2 #-}
op2 :: forall b a c.
Array b
-> Array a
-> (Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr)
-> Array c
op2 (Array ForeignPtr ()
fptr1) (Array ForeignPtr ()
fptr2) Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array c) -> Array c
forall a. IO a -> a
unsafePerformIO (IO (Array c) -> Array c)
-> (IO (Array c) -> IO (Array c)) -> IO (Array c) -> Array c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array c) -> IO (Array c)
forall a. IO a -> IO a
mask_ (IO (Array c) -> Array c) -> IO (Array c) -> Array c
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (Array c)) -> IO (Array c)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (Array c)) -> IO (Array c))
-> (AFWindow -> IO (Array c)) -> IO (Array c)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      ForeignPtr () -> (AFWindow -> IO (Array c)) -> IO (Array c)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr2 ((AFWindow -> IO (Array c)) -> IO (Array c))
-> (AFWindow -> IO (Array c)) -> IO (Array c)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr2 -> do
        ptr <-
          (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
            AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1 AFWindow
ptr2
            Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
        fptr <- newForeignPtr af_release_array_finalizer ptr
        pure (Array fptr)

-- | Like 'op2', but for comparison operations whose output 'Array' holds
-- boolean ('CBool') values.
op2bool
  :: Array b
  -> Array a
  -> (Ptr AFArray -> AFArray -> AFArray -> IO AFErr)
  -> Array CBool
{-# NOINLINE op2bool #-}
op2bool :: forall b a.
Array b
-> Array a
-> (Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr)
-> Array CBool
op2bool (Array ForeignPtr ()
fptr1) (Array ForeignPtr ()
fptr2) Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array CBool) -> Array CBool
forall a. IO a -> a
unsafePerformIO (IO (Array CBool) -> Array CBool)
-> (IO (Array CBool) -> IO (Array CBool))
-> IO (Array CBool)
-> Array CBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array CBool) -> IO (Array CBool)
forall a. IO a -> IO a
mask_ (IO (Array CBool) -> Array CBool)
-> IO (Array CBool) -> Array CBool
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (Array CBool)) -> IO (Array CBool)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (Array CBool)) -> IO (Array CBool))
-> (AFWindow -> IO (Array CBool)) -> IO (Array CBool)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      ForeignPtr () -> (AFWindow -> IO (Array CBool)) -> IO (Array CBool)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr2 ((AFWindow -> IO (Array CBool)) -> IO (Array CBool))
-> (AFWindow -> IO (Array CBool)) -> IO (Array CBool)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr2 -> do
        ptr <-
          (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
            AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1 AFWindow
ptr2
            Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
        fptr <- newForeignPtr af_release_array_finalizer ptr
        pure (Array fptr)


-- | Applies a C function that takes one input 'Array' and produces a pair of
-- output 'Array's.
op2p
  :: Array a
  -> (Ptr AFArray -> Ptr AFArray -> AFArray -> IO AFErr)
  -> (Array a, Array b)
{-# NOINLINE op2p #-}
op2p :: forall a b.
Array a
-> (Ptr AFWindow -> Ptr AFWindow -> AFWindow -> IO AFErr)
-> (Array a, Array b)
op2p (Array ForeignPtr ()
fptr1) Ptr AFWindow -> Ptr AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array a, Array b) -> (Array a, Array b)
forall a. IO a -> a
unsafePerformIO (IO (Array a, Array b) -> (Array a, Array b))
-> (IO (Array a, Array b) -> IO (Array a, Array b))
-> IO (Array a, Array b)
-> (Array a, Array b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array a, Array b) -> IO (Array a, Array b)
forall a. IO a -> IO a
mask_ (IO (Array a, Array b) -> (Array a, Array b))
-> IO (Array a, Array b) -> (Array a, Array b)
forall a b. (a -> b) -> a -> b
$ do
    (x,y) <- ForeignPtr ()
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow))
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
        (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput1 ->
          (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput2 -> do
            AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> Ptr AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput1 Ptr AFWindow
ptrInput2 AFWindow
ptr1
            (,) (AFWindow -> AFWindow -> (AFWindow, AFWindow))
-> IO AFWindow -> IO (AFWindow -> (AFWindow, AFWindow))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput1 IO (AFWindow -> (AFWindow, AFWindow))
-> IO AFWindow -> IO (AFWindow, AFWindow)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput2
    fptrA <- newForeignPtr af_release_array_finalizer x
    fptrB <- newForeignPtr af_release_array_finalizer y
    pure (Array fptrA, Array fptrB)

-- | Applies a C function that takes one input 'Array' and produces a triple of
-- output 'Array's (e.g. an SVD or LU decomposition).
op3p
  :: Array a
  -> (Ptr AFArray -> Ptr AFArray -> Ptr AFArray -> AFArray -> IO AFErr)
  -> (Array a, Array a, Array a)
{-# NOINLINE op3p #-}
op3p :: forall a.
Array a
-> (Ptr AFWindow
    -> Ptr AFWindow -> Ptr AFWindow -> AFWindow -> IO AFErr)
-> (Array a, Array a, Array a)
op3p (Array ForeignPtr ()
fptr1) Ptr AFWindow
-> Ptr AFWindow -> Ptr AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array a, Array a, Array a) -> (Array a, Array a, Array a)
forall a. IO a -> a
unsafePerformIO (IO (Array a, Array a, Array a) -> (Array a, Array a, Array a))
-> (IO (Array a, Array a, Array a)
    -> IO (Array a, Array a, Array a))
-> IO (Array a, Array a, Array a)
-> (Array a, Array a, Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array a, Array a, Array a) -> IO (Array a, Array a, Array a)
forall a. IO a -> IO a
mask_ (IO (Array a, Array a, Array a) -> (Array a, Array a, Array a))
-> IO (Array a, Array a, Array a) -> (Array a, Array a, Array a)
forall a b. (a -> b) -> a -> b
$ do
    (x,y,z) <- ForeignPtr ()
-> (AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (AFWindow, AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow, AFWindow))
-> (AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
        (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput1 ->
          (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput2 ->
            (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow))
-> IO (AFWindow, AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput3 -> do
              AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow
-> Ptr AFWindow -> Ptr AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput1 Ptr AFWindow
ptrInput2 Ptr AFWindow
ptrInput3 AFWindow
ptr1
              (,,) (AFWindow
 -> AFWindow -> AFWindow -> (AFWindow, AFWindow, AFWindow))
-> IO AFWindow
-> IO (AFWindow -> AFWindow -> (AFWindow, AFWindow, AFWindow))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput1 IO (AFWindow -> AFWindow -> (AFWindow, AFWindow, AFWindow))
-> IO AFWindow -> IO (AFWindow -> (AFWindow, AFWindow, AFWindow))
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput2 IO (AFWindow -> (AFWindow, AFWindow, AFWindow))
-> IO AFWindow -> IO (AFWindow, AFWindow, AFWindow)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput3
    fptrA <- newForeignPtr af_release_array_finalizer x
    fptrB <- newForeignPtr af_release_array_finalizer y
    fptrC <- newForeignPtr af_release_array_finalizer z
    pure (Array fptrA, Array fptrB, Array fptrC)

-- | Like 'op3p', but the C function also writes back a single 'Storable'
-- scalar in addition to the three output 'Array's.
op3p1
  :: Storable b
  => Array a
  -> (Ptr AFArray -> Ptr AFArray -> Ptr AFArray -> Ptr b -> AFArray -> IO AFErr)
  -> (Array a, Array a, Array a, b)
{-# NOINLINE op3p1 #-}
op3p1 :: forall b a.
Storable b =>
Array a
-> (Ptr AFWindow
    -> Ptr AFWindow -> Ptr AFWindow -> Ptr b -> AFWindow -> IO AFErr)
-> (Array a, Array a, Array a, b)
op3p1 (Array ForeignPtr ()
fptr1) Ptr AFWindow
-> Ptr AFWindow -> Ptr AFWindow -> Ptr b -> AFWindow -> IO AFErr
op =
  IO (Array a, Array a, Array a, b) -> (Array a, Array a, Array a, b)
forall a. IO a -> a
unsafePerformIO (IO (Array a, Array a, Array a, b)
 -> (Array a, Array a, Array a, b))
-> (IO (Array a, Array a, Array a, b)
    -> IO (Array a, Array a, Array a, b))
-> IO (Array a, Array a, Array a, b)
-> (Array a, Array a, Array a, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array a, Array a, Array a, b)
-> IO (Array a, Array a, Array a, b)
forall a. IO a -> IO a
mask_ (IO (Array a, Array a, Array a, b)
 -> (Array a, Array a, Array a, b))
-> IO (Array a, Array a, Array a, b)
-> (Array a, Array a, Array a, b)
forall a b. (a -> b) -> a -> b
$ do
    (x,y,z,g) <- ForeignPtr ()
-> (AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
 -> IO (AFWindow, AFWindow, AFWindow, b))
-> (AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
        (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
 -> IO (AFWindow, AFWindow, AFWindow, b))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput1 ->
          (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
 -> IO (AFWindow, AFWindow, AFWindow, b))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput2 ->
            (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
 -> IO (AFWindow, AFWindow, AFWindow, b))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput3 ->
              (Ptr b -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr b -> IO (AFWindow, AFWindow, AFWindow, b))
 -> IO (AFWindow, AFWindow, AFWindow, b))
-> (Ptr b -> IO (AFWindow, AFWindow, AFWindow, b))
-> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. (a -> b) -> a -> b
$ \Ptr b
ptrInput4 -> do
                AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow
-> Ptr AFWindow -> Ptr AFWindow -> Ptr b -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput1 Ptr AFWindow
ptrInput2 Ptr AFWindow
ptrInput3 Ptr b
ptrInput4 AFWindow
ptr1
                (,,,) (AFWindow
 -> AFWindow -> AFWindow -> b -> (AFWindow, AFWindow, AFWindow, b))
-> IO AFWindow
-> IO
     (AFWindow -> AFWindow -> b -> (AFWindow, AFWindow, AFWindow, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput1
                      IO (AFWindow -> AFWindow -> b -> (AFWindow, AFWindow, AFWindow, b))
-> IO AFWindow
-> IO (AFWindow -> b -> (AFWindow, AFWindow, AFWindow, b))
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput2
                      IO (AFWindow -> b -> (AFWindow, AFWindow, AFWindow, b))
-> IO AFWindow -> IO (b -> (AFWindow, AFWindow, AFWindow, b))
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput3
                      IO (b -> (AFWindow, AFWindow, AFWindow, b))
-> IO b -> IO (AFWindow, AFWindow, AFWindow, b)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr b -> IO b
forall a. Storable a => Ptr a -> IO a
peek Ptr b
ptrInput4
    fptrA <- newForeignPtr af_release_array_finalizer x
    fptrB <- newForeignPtr af_release_array_finalizer y
    fptrC <- newForeignPtr af_release_array_finalizer z
    pure (Array fptrA, Array fptrB, Array fptrC, g)

-- | Applies a C function that takes two input 'Array's and produces a pair of
-- output 'Array's. The element types of the outputs are free so callers can
-- pin them to whatever the C function actually produces (e.g. @u32@ index
-- arrays from the matcher functions).
op2p2
  :: Array a
  -> Array b
  -> (Ptr AFArray -> Ptr AFArray -> AFArray -> AFArray -> IO AFErr)
  -> (Array c, Array d)
{-# NOINLINE op2p2 #-}
op2p2 :: forall a b c d.
Array a
-> Array b
-> (Ptr AFWindow
    -> Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr)
-> (Array c, Array d)
op2p2 (Array ForeignPtr ()
fptr1) (Array ForeignPtr ()
fptr2) Ptr AFWindow -> Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array c, Array d) -> (Array c, Array d)
forall a. IO a -> a
unsafePerformIO (IO (Array c, Array d) -> (Array c, Array d))
-> (IO (Array c, Array d) -> IO (Array c, Array d))
-> IO (Array c, Array d)
-> (Array c, Array d)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array c, Array d) -> IO (Array c, Array d)
forall a. IO a -> IO a
mask_ (IO (Array c, Array d) -> (Array c, Array d))
-> IO (Array c, Array d) -> (Array c, Array d)
forall a b. (a -> b) -> a -> b
$ do
    (x,y) <-
      ForeignPtr ()
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow))
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
        ForeignPtr ()
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr2 ((AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow))
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr2 -> do
          (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput1 ->
            (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput2 -> do
              AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput1 Ptr AFWindow
ptrInput2 AFWindow
ptr1 AFWindow
ptr2
              (,) (AFWindow -> AFWindow -> (AFWindow, AFWindow))
-> IO AFWindow -> IO (AFWindow -> (AFWindow, AFWindow))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput1 IO (AFWindow -> (AFWindow, AFWindow))
-> IO AFWindow -> IO (AFWindow, AFWindow)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput2
    fptrA <- newForeignPtr af_release_array_finalizer x
    fptrB <- newForeignPtr af_release_array_finalizer y
    pure (Array fptrA, Array fptrB)

-- | Key/value variant of 'op2p2' used by sort-by-key operations. The input key
-- 'Array' is cast down to @s32@ before the C call (ArrayFire requires 32-bit
-- keys) and the resulting key 'Array' is cast back up to @s64@, releasing the
-- intermediate handles along the way.
op2p2kv
  :: Array Int
  -> Array a
  -> (Ptr AFArray -> Ptr AFArray -> AFArray -> AFArray -> IO AFErr)
  -> (Array Int, Array b)
{-# NOINLINE op2p2kv #-}
op2p2kv :: forall a b.
Array Int
-> Array a
-> (Ptr AFWindow
    -> Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr)
-> (Array Int, Array b)
op2p2kv (Array ForeignPtr ()
fptr1) (Array ForeignPtr ()
fptr2) Ptr AFWindow -> Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array Int, Array b) -> (Array Int, Array b)
forall a. IO a -> a
unsafePerformIO (IO (Array Int, Array b) -> (Array Int, Array b))
-> (IO (Array Int, Array b) -> IO (Array Int, Array b))
-> IO (Array Int, Array b)
-> (Array Int, Array b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array Int, Array b) -> IO (Array Int, Array b)
forall a. IO a -> IO a
mask_ (IO (Array Int, Array b) -> (Array Int, Array b))
-> IO (Array Int, Array b) -> (Array Int, Array b)
forall a b. (a -> b) -> a -> b
$ do
    (x, y) <-
      ForeignPtr ()
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow))
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
        ForeignPtr ()
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr2 ((AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow))
-> (AFWindow -> IO (AFWindow, AFWindow)) -> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr2 -> do
          castedKey <- (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
p -> do
            AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> AFDtype -> IO AFErr
af_cast Ptr AFWindow
p AFWindow
ptr1 AFDtype
s32
            Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
p
          calloca $ \Ptr AFWindow
ptrOutput1 ->
            (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, AFWindow))
 -> IO (AFWindow, AFWindow))
-> (Ptr AFWindow -> IO (AFWindow, AFWindow))
-> IO (AFWindow, AFWindow)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrOutput2 -> do
              IO () -> IO AFErr -> IO ()
forall a b. IO a -> IO b -> IO a
onException
                (AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> Ptr AFWindow -> AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrOutput1 Ptr AFWindow
ptrOutput2 AFWindow
castedKey AFWindow
ptr2)
                (AFWindow -> IO AFErr
af_release_array_ffi AFWindow
castedKey)
              _ <- AFWindow -> IO AFErr
af_release_array_ffi AFWindow
castedKey
              outKey <- peek ptrOutput1
              outVal <- peek ptrOutput2
              finalKey <- calloca $ \Ptr AFWindow
p -> do
                IO () -> IO AFErr -> IO ()
forall a b. IO a -> IO b -> IO a
onException
                  (AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> AFDtype -> IO AFErr
af_cast Ptr AFWindow
p AFWindow
outKey AFDtype
s64)
                  (AFWindow -> IO AFErr
af_release_array_ffi AFWindow
outKey IO AFErr -> IO AFErr -> IO AFErr
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AFWindow -> IO AFErr
af_release_array_ffi AFWindow
outVal)
                Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
p
              _ <- af_release_array_ffi outKey
              pure (finalKey, outVal)
    fptrA <- newForeignPtr af_release_array_finalizer x
    fptrB <- newForeignPtr af_release_array_finalizer y
    pure (Array fptrA, Array fptrB)

-- | Runs a C function that constructs a fresh 'Array' (taking no input
-- 'Array'), returning the result in 'IO'. The output pointer is zeroed before
-- the call so the finalizer is safe even if construction fails.
createArray'
  :: (Ptr AFArray -> IO AFErr)
  -> IO (Array a)
{-# NOINLINE createArray' #-}
createArray' :: forall a. (Ptr AFWindow -> IO AFErr) -> IO (Array a)
createArray' Ptr AFWindow -> IO AFErr
op =
  IO (Array a) -> IO (Array a)
forall a. IO a -> IO a
mask_ (IO (Array a) -> IO (Array a)) -> IO (Array a) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ do
    ptr <-
      (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput
        Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
    fptr <- newForeignPtr af_release_array_finalizer ptr
    pure (Array fptr)

-- | Pure counterpart of 'createArray'' for constructing an 'Array' from a C
-- function that takes no input 'Array'. The effect is hidden behind
-- 'unsafePerformIO'.
createArray
  :: (Ptr AFArray -> IO AFErr)
  -> Array a
{-# NOINLINE createArray #-}
createArray :: forall a. (Ptr AFWindow -> IO AFErr) -> Array a
createArray Ptr AFWindow -> IO AFErr
op =
  IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a)
-> (IO (Array a) -> IO (Array a)) -> IO (Array a) -> Array a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array a) -> IO (Array a)
forall a. IO a -> IO a
mask_ (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ do
    ptr <-
      (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput
        Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
    fptr <- newForeignPtr af_release_array_finalizer ptr
    pure (Array fptr)

-- | Runs a C function that constructs a 'Window' handle, attaching the
-- window-release finalizer to the result.
createWindow'
  :: (Ptr AFWindow -> IO AFErr)
  -> IO Window
createWindow' :: (Ptr AFWindow -> IO AFErr) -> IO Window
createWindow' Ptr AFWindow -> IO AFErr
op =
  IO Window -> IO Window
forall a. IO a -> IO a
mask_ (IO Window -> IO Window) -> IO Window -> IO Window
forall a b. (a -> b) -> a -> b
$ do
    ptr <-
      (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput
        Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
    fptr <- newForeignPtr af_release_window_finalizer ptr
    pure (Window fptr)

-- | Runs a C function against an existing 'Window' for its side effects,
-- returning unit.
opw
  :: Window
  -> (AFWindow -> IO AFErr)
  -> IO ()
opw :: Window -> (AFWindow -> IO AFErr) -> IO ()
opw (Window ForeignPtr ()
fptr) AFWindow -> IO AFErr
op
  = IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ())
-> ((AFWindow -> IO ()) -> IO ()) -> (AFWindow -> IO ()) -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignPtr () -> (AFWindow -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr ((AFWindow -> IO ()) -> IO ()) -> (AFWindow -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ (AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> (AFWindow -> IO AFErr) -> AFWindow -> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< AFWindow -> IO AFErr
op)

-- | Runs a C function against an existing 'Window' that writes back a single
-- 'Storable' value, returning it.
opw1
  :: Storable a
  => Window
  -> (Ptr a -> AFWindow -> IO AFErr)
  -> IO a
{-# NOINLINE opw1 #-}
opw1 :: forall a.
Storable a =>
Window -> (Ptr a -> AFWindow -> IO AFErr) -> IO a
opw1 (Window ForeignPtr ()
fptr) Ptr a -> AFWindow -> IO AFErr
op
  = IO a -> IO a
forall a. IO a -> IO a
mask_ (IO a -> IO a)
-> ((AFWindow -> IO a) -> IO a) -> (AFWindow -> IO a) -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignPtr () -> (AFWindow -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr ((AFWindow -> IO a) -> IO a) -> (AFWindow -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr -> do
       (Ptr a -> IO a) -> IO a
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO a) -> IO a) -> (Ptr a -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr a
p -> do
         AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> AFWindow -> IO AFErr
op Ptr a
p AFWindow
ptr
         Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
p

-- | Applies a C function that takes a single input 'Array' and produces a
-- single output 'Array'.
op1
  :: Array a
  -> (Ptr AFArray -> AFArray -> IO AFErr)
  -> Array b
{-# NOINLINE op1 #-}
op1 :: forall a b.
Array a -> (Ptr AFWindow -> AFWindow -> IO AFErr) -> Array b
op1 (Array ForeignPtr ()
fptr1) Ptr AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array b) -> Array b
forall a. IO a -> a
unsafePerformIO (IO (Array b) -> Array b)
-> (IO (Array b) -> IO (Array b)) -> IO (Array b) -> Array b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array b) -> IO (Array b)
forall a. IO a -> IO a
mask_ (IO (Array b) -> Array b) -> IO (Array b) -> Array b
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (Array b)) -> IO (Array b)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (Array b)) -> IO (Array b))
-> (AFWindow -> IO (Array b)) -> IO (Array b)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
      ptr <-
        (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
          AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1
          Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
      fptr <- newForeignPtr af_release_array_finalizer ptr
      pure (Array fptr)

-- | Applies a C function that takes a single input 'Features' and produces a
-- new 'Features' handle.
op1f
  :: Features
  -> (Ptr AFFeatures -> AFFeatures -> IO AFErr)
  -> Features
{-# NOINLINE op1f #-}
op1f :: Features -> (Ptr AFWindow -> AFWindow -> IO AFErr) -> Features
op1f (Features ForeignPtr ()
x) Ptr AFWindow -> AFWindow -> IO AFErr
op =
  IO Features -> Features
forall a. IO a -> a
unsafePerformIO (IO Features -> Features)
-> (IO Features -> IO Features) -> IO Features -> Features
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO Features -> IO Features
forall a. IO a -> IO a
mask_ (IO Features -> Features) -> IO Features -> Features
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO Features) -> IO Features
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
x ((AFWindow -> IO Features) -> IO Features)
-> (AFWindow -> IO Features) -> IO Features
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
      ptr <-
        (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
          AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1
          Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
      fptr <- newForeignPtr af_release_features ptr
      pure (Features fptr)

-- | Applies a C function that takes a single input 'RandomEngine' and produces
-- a new 'RandomEngine' handle, returned in 'IO'.
op1re
  :: RandomEngine
  -> (Ptr AFRandomEngine -> AFRandomEngine -> IO AFErr)
  -> IO RandomEngine
op1re :: RandomEngine
-> (Ptr AFWindow -> AFWindow -> IO AFErr) -> IO RandomEngine
op1re (RandomEngine ForeignPtr ()
x) Ptr AFWindow -> AFWindow -> IO AFErr
op = IO RandomEngine -> IO RandomEngine
forall a. IO a -> IO a
mask_ (IO RandomEngine -> IO RandomEngine)
-> IO RandomEngine -> IO RandomEngine
forall a b. (a -> b) -> a -> b
$
  ForeignPtr () -> (AFWindow -> IO RandomEngine) -> IO RandomEngine
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
x ((AFWindow -> IO RandomEngine) -> IO RandomEngine)
-> (AFWindow -> IO RandomEngine) -> IO RandomEngine
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
    ptr <-
      (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1
        Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
    fptr <- newForeignPtr af_release_random_engine_finalizer ptr
    pure (RandomEngine fptr)

-- | Applies a C function that takes a single input 'Array' and produces both a
-- 'Storable' scalar and an output 'Array' (e.g. an operation returning a value
-- and its location).
op1b
  :: Storable b
  => Array a
  -> (Ptr AFArray -> Ptr b -> AFArray -> IO AFErr)
  -> (b, Array a)
{-# NOINLINE op1b #-}
op1b :: forall b a.
Storable b =>
Array a
-> (Ptr AFWindow -> Ptr b -> AFWindow -> IO AFErr) -> (b, Array a)
op1b (Array ForeignPtr ()
fptr1) Ptr AFWindow -> Ptr b -> AFWindow -> IO AFErr
op =
  IO (b, Array a) -> (b, Array a)
forall a. IO a -> a
unsafePerformIO (IO (b, Array a) -> (b, Array a))
-> (IO (b, Array a) -> IO (b, Array a))
-> IO (b, Array a)
-> (b, Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (b, Array a) -> IO (b, Array a)
forall a. IO a -> IO a
mask_ (IO (b, Array a) -> (b, Array a))
-> IO (b, Array a) -> (b, Array a)
forall a b. (a -> b) -> a -> b
$
    ForeignPtr () -> (AFWindow -> IO (b, Array a)) -> IO (b, Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (b, Array a)) -> IO (b, Array a))
-> (AFWindow -> IO (b, Array a)) -> IO (b, Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
      (y,x) <-
        (Ptr AFWindow -> IO (AFWindow, b)) -> IO (AFWindow, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (AFWindow, b)) -> IO (AFWindow, b))
-> (Ptr AFWindow -> IO (AFWindow, b)) -> IO (AFWindow, b)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput1 ->
          (Ptr b -> IO (AFWindow, b)) -> IO (AFWindow, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr b -> IO (AFWindow, b)) -> IO (AFWindow, b))
-> (Ptr b -> IO (AFWindow, b)) -> IO (AFWindow, b)
forall a b. (a -> b) -> a -> b
$ \Ptr b
ptrInput2 -> do
            AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> Ptr b -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput1 Ptr b
ptrInput2 AFWindow
ptr1
            (,) (AFWindow -> b -> (AFWindow, b))
-> IO AFWindow -> IO (b -> (AFWindow, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput1 IO (b -> (AFWindow, b)) -> IO b -> IO (AFWindow, b)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr b -> IO b
forall a. Storable a => Ptr a -> IO a
peek Ptr b
ptrInput2
      fptr <- newForeignPtr af_release_array_finalizer y
      pure (x, Array fptr)

-- | Runs an 'AFErr'-returning C action purely for its side effects, throwing
-- on a non-success status.
afCall
  :: IO AFErr
  -> IO ()
afCall :: IO AFErr -> IO ()
afCall = IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ()) -> (IO AFErr -> IO ()) -> IO AFErr -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<)

-- | Loads an image from the given file path into a new 'Array'. The 'Bool'
-- flag selects whether the image is loaded in colour, and is marshalled to the
-- 'CBool' expected by the C function.
loadAFImage
  :: String
  -> Bool
  -> (Ptr AFArray -> CString -> CBool -> IO AFErr)
  -> IO (Array a)
loadAFImage :: forall a.
String
-> Bool
-> (Ptr AFWindow -> CString -> CBool -> IO AFErr)
-> IO (Array a)
loadAFImage String
s (Int -> CBool
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CBool) -> (Bool -> Int) -> Bool -> CBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Int
forall a. Enum a => a -> Int
fromEnum -> CBool
b) Ptr AFWindow -> CString -> CBool -> IO AFErr
op = IO (Array a) -> IO (Array a)
forall a. IO a -> IO a
mask_ (IO (Array a) -> IO (Array a)) -> IO (Array a) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$
  String -> (CString -> IO (Array a)) -> IO (Array a)
forall a. String -> (CString -> IO a) -> IO a
withCString String
s ((CString -> IO (Array a)) -> IO (Array a))
-> (CString -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \CString
cstr -> do
    p <- (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptr -> do
      AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> CString -> CBool -> IO AFErr
op Ptr AFWindow
ptr CString
cstr CBool
b
      Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptr
    fptr <- newForeignPtr af_release_array_finalizer p
    pure (Array fptr)

-- | Loads an image from the given file path into a new 'Array' in its native
-- format, without any colour-space conversion.
loadAFImageNative
  :: String
  -> (Ptr AFArray -> CString -> IO AFErr)
  -> IO (Array a)
loadAFImageNative :: forall a.
String -> (Ptr AFWindow -> CString -> IO AFErr) -> IO (Array a)
loadAFImageNative String
s Ptr AFWindow -> CString -> IO AFErr
op = IO (Array a) -> IO (Array a)
forall a. IO a -> IO a
mask_ (IO (Array a) -> IO (Array a)) -> IO (Array a) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$
  String -> (CString -> IO (Array a)) -> IO (Array a)
forall a. String -> (CString -> IO a) -> IO a
withCString String
s ((CString -> IO (Array a)) -> IO (Array a))
-> (CString -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \CString
cstr -> do
    p <- (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO AFWindow) -> IO AFWindow)
-> (Ptr AFWindow -> IO AFWindow) -> IO AFWindow
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptr -> do
      AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> CString -> IO AFErr
op Ptr AFWindow
ptr CString
cstr
      Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptr
    fptr <- newForeignPtr af_release_array_finalizer p
    pure (Array fptr)

-- | Runs a C function that mutates an 'Array' in place, returning unit.
inPlace :: Array a -> (AFArray -> IO AFErr) -> IO ()
inPlace :: forall a. Array a -> (AFWindow -> IO AFErr) -> IO ()
inPlace (Array ForeignPtr ()
fptr) AFWindow -> IO AFErr
op =
  IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ())
-> ((AFWindow -> IO ()) -> IO ()) -> (AFWindow -> IO ()) -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignPtr () -> (AFWindow -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr ((AFWindow -> IO ()) -> IO ()) -> (AFWindow -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ (AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> (AFWindow -> IO AFErr) -> AFWindow -> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< AFWindow -> IO AFErr
op)

-- | Runs a C function that mutates a 'RandomEngine' in place, returning unit.
inPlaceEng :: RandomEngine -> (AFRandomEngine -> IO AFErr) -> IO ()
inPlaceEng :: RandomEngine -> (AFWindow -> IO AFErr) -> IO ()
inPlaceEng (RandomEngine ForeignPtr ()
fptr) AFWindow -> IO AFErr
op =
  IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ())
-> ((AFWindow -> IO ()) -> IO ()) -> (AFWindow -> IO ()) -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignPtr () -> (AFWindow -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr ((AFWindow -> IO ()) -> IO ()) -> (AFWindow -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ (AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> (AFWindow -> IO AFErr) -> AFWindow -> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< AFWindow -> IO AFErr
op)

-- | Runs a C function that writes back a single 'Storable' value through an
-- output pointer, returning that value in 'IO'.
afCall1
  :: Storable a
  => (Ptr a -> IO AFErr)
  -> IO a
afCall1 :: forall a. Storable a => (Ptr a -> IO AFErr) -> IO a
afCall1 Ptr a -> IO AFErr
op =
  (Ptr a -> IO a) -> IO a
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO a) -> IO a) -> (Ptr a -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput -> do
    AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> IO AFErr
op Ptr a
ptrInput
    Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput

-- | Pure counterpart of 'afCall1' for reading back a single 'Storable' value.
-- The effect is hidden behind 'unsafePerformIO'.
afCall1'
  :: Storable a
  => (Ptr a -> IO AFErr)
  -> a
{-# NOINLINE afCall1' #-}
afCall1' :: forall a. Storable a => (Ptr a -> IO AFErr) -> a
afCall1' Ptr a -> IO AFErr
op =
  IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> (IO a -> IO a) -> IO a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> IO a
forall a. IO a -> IO a
mask_ (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
    (Ptr a -> IO a) -> IO a
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO a) -> IO a) -> (Ptr a -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput -> do
      AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> IO AFErr
op Ptr a
ptrInput
      Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput

-- | Extracts one of the component 'Array's of a 'Features' handle. The C
-- getters return the raw handle stored inside the features struct without
-- retaining it, so we retain it here before attaching the release finalizer;
-- otherwise the 'Features' finalizer and the 'Array' finalizer would double
-- free.
featuresToArray
  :: Features
  -> (Ptr AFArray -> AFFeatures -> IO AFErr)
  -> Array a
{-# NOINLINE featuresToArray #-}
featuresToArray :: forall a.
Features -> (Ptr AFWindow -> AFWindow -> IO AFErr) -> Array a
featuresToArray (Features ForeignPtr ()
fptr1) Ptr AFWindow -> AFWindow -> IO AFErr
op =
  IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a)
-> (IO (Array a) -> IO (Array a)) -> IO (Array a) -> Array a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Array a) -> IO (Array a)
forall a. IO a -> IO a
mask_ (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (Array a)) -> IO (Array a))
-> (AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
      (Ptr AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (Array a)) -> IO (Array a))
-> (Ptr AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> IO AFErr
op Ptr AFWindow
ptrInput AFWindow
ptr1
        (Ptr AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr AFWindow -> IO (Array a)) -> IO (Array a))
-> (Ptr AFWindow -> IO (Array a)) -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ \Ptr AFWindow
retainedArray -> do
          AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> AFWindow -> IO AFErr
af_retain_array Ptr AFWindow
retainedArray (AFWindow -> IO AFErr) -> IO AFWindow -> IO AFErr
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
ptrInput
          fptr <- FinalizerPtr () -> AFWindow -> IO (ForeignPtr ())
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr ()
af_release_array_finalizer (AFWindow -> IO (ForeignPtr ()))
-> IO AFWindow -> IO (ForeignPtr ())
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr AFWindow -> IO AFWindow
forall a. Storable a => Ptr a -> IO a
peek Ptr AFWindow
retainedArray
          pure (Array fptr)

-- | Reads back a single 'Storable' scalar describing a 'Features' handle (for
-- example its feature count), hiding the effect behind 'unsafePerformIO'.
infoFromFeatures
  :: Storable a
  => Features
  -> (Ptr a -> AFFeatures -> IO AFErr)
  -> a
{-# NOINLINE infoFromFeatures #-}
infoFromFeatures :: forall a.
Storable a =>
Features -> (Ptr a -> AFWindow -> IO AFErr) -> a
infoFromFeatures (Features ForeignPtr ()
fptr1) Ptr a -> AFWindow -> IO AFErr
op =
  IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> (IO a -> IO a) -> IO a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> IO a
forall a. IO a -> IO a
mask_ (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO a) -> IO a) -> (AFWindow -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
      (Ptr a -> IO a) -> IO a
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO a) -> IO a) -> (Ptr a -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> AFWindow -> IO AFErr
op Ptr a
ptrInput AFWindow
ptr1
        Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput

-- | Reads back a single 'Storable' scalar describing a 'RandomEngine' (for
-- example its seed or type), returning it in 'IO'.
infoFromRandomEngine
  :: Storable a
  => RandomEngine
  -> (Ptr a -> AFRandomEngine -> IO AFErr)
  -> IO a
infoFromRandomEngine :: forall a.
Storable a =>
RandomEngine -> (Ptr a -> AFWindow -> IO AFErr) -> IO a
infoFromRandomEngine (RandomEngine ForeignPtr ()
fptr1) Ptr a -> AFWindow -> IO AFErr
op =
  IO a -> IO a
forall a. IO a -> IO a
mask_ (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO a) -> IO a) -> (AFWindow -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
      (Ptr a -> IO a) -> IO a
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO a) -> IO a) -> (Ptr a -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> AFWindow -> IO AFErr
op Ptr a
ptrInput AFWindow
ptr1
        Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput

-- | Saves an 'Array' to the given file path using the supplied C function.
afSaveImage
  :: Array b
  -> String
  -> (CString -> AFArray -> IO AFErr)
  -> IO ()
afSaveImage :: forall b.
Array b -> String -> (CString -> AFWindow -> IO AFErr) -> IO ()
afSaveImage (Array ForeignPtr ()
fptr1) String
str CString -> AFWindow -> IO AFErr
op =
  String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCString String
str ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
cstr ->
    ForeignPtr () -> (AFWindow -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO ()) -> IO ()) -> (AFWindow -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$
      AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> (AFWindow -> IO AFErr) -> AFWindow -> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< CString -> AFWindow -> IO AFErr
op CString
cstr

-- | Reads back a single 'Storable' scalar describing an 'Array' (for example a
-- dimension or count), hiding the effect behind 'unsafePerformIO'.
infoFromArray
  :: Storable a
  => Array b
  -> (Ptr a -> AFArray -> IO AFErr)
  -> a
{-# NOINLINE infoFromArray #-}
infoFromArray :: forall a b.
Storable a =>
Array b -> (Ptr a -> AFWindow -> IO AFErr) -> a
infoFromArray (Array ForeignPtr ()
fptr1) Ptr a -> AFWindow -> IO AFErr
op =
  IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> (IO a -> IO a) -> IO a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> IO a
forall a. IO a -> IO a
mask_ (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO a) -> IO a) -> (AFWindow -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 -> do
      (Ptr a -> IO a) -> IO a
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO a) -> IO a) -> (Ptr a -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput -> do
        AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> AFWindow -> IO AFErr
op Ptr a
ptrInput AFWindow
ptr1
        Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput

-- | Like 'infoFromArray', but reads back a pair of 'Storable' scalars from a
-- single input 'Array'.
infoFromArray2
  :: forall a b arr. (Storable a, Storable b)
  => Array arr
  -> (Ptr a -> Ptr b -> AFArray -> IO AFErr)
  -> (a,b)
{-# NOINLINE infoFromArray2 #-}
infoFromArray2 :: forall a b arr.
(Storable a, Storable b) =>
Array arr -> (Ptr a -> Ptr b -> AFWindow -> IO AFErr) -> (a, b)
infoFromArray2 (Array ForeignPtr ()
fptr1) Ptr a -> Ptr b -> AFWindow -> IO AFErr
op =
  IO (a, b) -> (a, b)
forall a. IO a -> a
unsafePerformIO (IO (a, b) -> (a, b))
-> (IO (a, b) -> IO (a, b)) -> IO (a, b) -> (a, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (a, b) -> IO (a, b)
forall a. IO a -> IO a
mask_ (IO (a, b) -> (a, b)) -> IO (a, b) -> (a, b)
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (a, b)) -> IO (a, b)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (a, b)) -> IO (a, b))
-> (AFWindow -> IO (a, b)) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      (Ptr a -> IO (a, b)) -> IO (a, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr a -> IO (a, b)) -> IO (a, b))
-> (Ptr a -> IO (a, b)) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput1 ->
        (Ptr b -> IO (a, b)) -> IO (a, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr b -> IO (a, b)) -> IO (a, b))
-> (Ptr b -> IO (a, b)) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ \Ptr b
ptrInput2 -> do
          AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> Ptr b -> AFWindow -> IO AFErr
op Ptr a
ptrInput1 Ptr b
ptrInput2 AFWindow
ptr1
          (,) (a -> b -> (a, b)) -> IO a -> IO (b -> (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput1 IO (b -> (a, b)) -> IO b -> IO (a, b)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr b -> IO b
forall a. Storable a => Ptr a -> IO a
peek Ptr b
ptrInput2

-- | Like 'infoFromArray2', but reads back a pair of 'Storable' scalars derived
-- from two input 'Array's.
infoFromArray22
  :: forall a b arr. (Storable a, Storable b)
  => Array arr
  -> Array arr
  -> (Ptr a -> Ptr b -> AFArray -> AFArray -> IO AFErr)
  -> (a,b)
{-# NOINLINE infoFromArray22 #-}
infoFromArray22 :: forall a b arr.
(Storable a, Storable b) =>
Array arr
-> Array arr
-> (Ptr a -> Ptr b -> AFWindow -> AFWindow -> IO AFErr)
-> (a, b)
infoFromArray22 (Array ForeignPtr ()
fptr1) (Array ForeignPtr ()
fptr2) Ptr a -> Ptr b -> AFWindow -> AFWindow -> IO AFErr
op =
  IO (a, b) -> (a, b)
forall a. IO a -> a
unsafePerformIO (IO (a, b) -> (a, b))
-> (IO (a, b) -> IO (a, b)) -> IO (a, b) -> (a, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (a, b) -> IO (a, b)
forall a. IO a -> IO a
mask_ (IO (a, b) -> (a, b)) -> IO (a, b) -> (a, b)
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr () -> (AFWindow -> IO (a, b)) -> IO (a, b)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (a, b)) -> IO (a, b))
-> (AFWindow -> IO (a, b)) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      ForeignPtr () -> (AFWindow -> IO (a, b)) -> IO (a, b)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr2 ((AFWindow -> IO (a, b)) -> IO (a, b))
-> (AFWindow -> IO (a, b)) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr2 ->
        (Ptr a -> IO (a, b)) -> IO (a, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr a -> IO (a, b)) -> IO (a, b))
-> (Ptr a -> IO (a, b)) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput1 ->
          (Ptr b -> IO (a, b)) -> IO (a, b)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr b -> IO (a, b)) -> IO (a, b))
-> (Ptr b -> IO (a, b)) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ \Ptr b
ptrInput2 -> do
            AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> Ptr b -> AFWindow -> AFWindow -> IO AFErr
op Ptr a
ptrInput1 Ptr b
ptrInput2 AFWindow
ptr1 AFWindow
ptr2
            (,) (a -> b -> (a, b)) -> IO a -> IO (b -> (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput1 IO (b -> (a, b)) -> IO b -> IO (a, b)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr b -> IO b
forall a. Storable a => Ptr a -> IO a
peek Ptr b
ptrInput2

-- | Like 'infoFromArray', but reads back three 'Storable' scalars from a
-- single input 'Array'.
infoFromArray3
  :: forall a b c arr. (Storable a, Storable b, Storable c)
  => Array arr
  -> (Ptr a -> Ptr b -> Ptr c -> AFArray -> IO AFErr)
  -> (a,b,c)
{-# NOINLINE infoFromArray3 #-}
infoFromArray3 :: forall a b c arr.
(Storable a, Storable b, Storable c) =>
Array arr
-> (Ptr a -> Ptr b -> Ptr c -> AFWindow -> IO AFErr) -> (a, b, c)
infoFromArray3 (Array ForeignPtr ()
fptr1) Ptr a -> Ptr b -> Ptr c -> AFWindow -> IO AFErr
op =
  IO (a, b, c) -> (a, b, c)
forall a. IO a -> a
unsafePerformIO (IO (a, b, c) -> (a, b, c))
-> (IO (a, b, c) -> IO (a, b, c)) -> IO (a, b, c) -> (a, b, c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (a, b, c) -> IO (a, b, c)
forall a. IO a -> IO a
mask_ (IO (a, b, c) -> (a, b, c)) -> IO (a, b, c) -> (a, b, c)
forall a b. (a -> b) -> a -> b
$
    ForeignPtr () -> (AFWindow -> IO (a, b, c)) -> IO (a, b, c)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (a, b, c)) -> IO (a, b, c))
-> (AFWindow -> IO (a, b, c)) -> IO (a, b, c)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      (Ptr a -> IO (a, b, c)) -> IO (a, b, c)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr a -> IO (a, b, c)) -> IO (a, b, c))
-> (Ptr a -> IO (a, b, c)) -> IO (a, b, c)
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput1 ->
        (Ptr b -> IO (a, b, c)) -> IO (a, b, c)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr b -> IO (a, b, c)) -> IO (a, b, c))
-> (Ptr b -> IO (a, b, c)) -> IO (a, b, c)
forall a b. (a -> b) -> a -> b
$ \Ptr b
ptrInput2 ->
          (Ptr c -> IO (a, b, c)) -> IO (a, b, c)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
calloca ((Ptr c -> IO (a, b, c)) -> IO (a, b, c))
-> (Ptr c -> IO (a, b, c)) -> IO (a, b, c)
forall a b. (a -> b) -> a -> b
$ \Ptr c
ptrInput3 -> do
            AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> Ptr b -> Ptr c -> AFWindow -> IO AFErr
op Ptr a
ptrInput1 Ptr b
ptrInput2 Ptr c
ptrInput3 AFWindow
ptr1
            (,,) (a -> b -> c -> (a, b, c)) -> IO a -> IO (b -> c -> (a, b, c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput1
                 IO (b -> c -> (a, b, c)) -> IO b -> IO (c -> (a, b, c))
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr b -> IO b
forall a. Storable a => Ptr a -> IO a
peek Ptr b
ptrInput2
                 IO (c -> (a, b, c)) -> IO c -> IO (a, b, c)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr c -> IO c
forall a. Storable a => Ptr a -> IO a
peek Ptr c
ptrInput3

-- | Like 'infoFromArray', but reads back four 'Storable' scalars from a single
-- input 'Array' (for example all four dimensions).
infoFromArray4
  :: (Storable a, Storable b, Storable c, Storable d)
  => Array arr
  -> (Ptr a -> Ptr b -> Ptr c -> Ptr d -> AFArray -> IO AFErr)
  -> (a,b,c,d)
{-# NOINLINE infoFromArray4 #-}
infoFromArray4 :: forall a b c d arr.
(Storable a, Storable b, Storable c, Storable d) =>
Array arr
-> (Ptr a -> Ptr b -> Ptr c -> Ptr d -> AFWindow -> IO AFErr)
-> (a, b, c, d)
infoFromArray4 (Array ForeignPtr ()
fptr1) Ptr a -> Ptr b -> Ptr c -> Ptr d -> AFWindow -> IO AFErr
op =
  IO (a, b, c, d) -> (a, b, c, d)
forall a. IO a -> a
unsafePerformIO (IO (a, b, c, d) -> (a, b, c, d))
-> (IO (a, b, c, d) -> IO (a, b, c, d))
-> IO (a, b, c, d)
-> (a, b, c, d)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (a, b, c, d) -> IO (a, b, c, d)
forall a. IO a -> IO a
mask_ (IO (a, b, c, d) -> (a, b, c, d))
-> IO (a, b, c, d) -> (a, b, c, d)
forall a b. (a -> b) -> a -> b
$
    ForeignPtr () -> (AFWindow -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr ()
fptr1 ((AFWindow -> IO (a, b, c, d)) -> IO (a, b, c, d))
-> (AFWindow -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. (a -> b) -> a -> b
$ \AFWindow
ptr1 ->
      (Ptr a -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr a -> IO (a, b, c, d)) -> IO (a, b, c, d))
-> (Ptr a -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. (a -> b) -> a -> b
$ \Ptr a
ptrInput1 ->
        (Ptr b -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr b -> IO (a, b, c, d)) -> IO (a, b, c, d))
-> (Ptr b -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. (a -> b) -> a -> b
$ \Ptr b
ptrInput2 ->
          (Ptr c -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr c -> IO (a, b, c, d)) -> IO (a, b, c, d))
-> (Ptr c -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. (a -> b) -> a -> b
$ \Ptr c
ptrInput3 ->
            (Ptr d -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr d -> IO (a, b, c, d)) -> IO (a, b, c, d))
-> (Ptr d -> IO (a, b, c, d)) -> IO (a, b, c, d)
forall a b. (a -> b) -> a -> b
$ \Ptr d
ptrInput4 -> do
              AFErr -> IO ()
throwAFError (AFErr -> IO ()) -> IO AFErr -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> Ptr b -> Ptr c -> Ptr d -> AFWindow -> IO AFErr
op Ptr a
ptrInput1 Ptr b
ptrInput2 Ptr c
ptrInput3 Ptr d
ptrInput4 AFWindow
ptr1
              (,,,) (a -> b -> c -> d -> (a, b, c, d))
-> IO a -> IO (b -> c -> d -> (a, b, c, d))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
ptrInput1
                    IO (b -> c -> d -> (a, b, c, d))
-> IO b -> IO (c -> d -> (a, b, c, d))
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr b -> IO b
forall a. Storable a => Ptr a -> IO a
peek Ptr b
ptrInput2
                    IO (c -> d -> (a, b, c, d)) -> IO c -> IO (d -> (a, b, c, d))
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr c -> IO c
forall a. Storable a => Ptr a -> IO a
peek Ptr c
ptrInput3
                    IO (d -> (a, b, c, d)) -> IO d -> IO (a, b, c, d)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr d -> IO d
forall a. Storable a => Ptr a -> IO a
peek Ptr d
ptrInput4