{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE PatternGuards       #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections       #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeOperators       #-}
{-# LANGUAGE ViewPatterns        #-}
-- |
-- Module      : Data.Array.Accelerate.Math.FFT.LLVM.PTX
-- Copyright   : [2017..2020] The Accelerate Team
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--

module Data.Array.Accelerate.Math.FFT.LLVM.PTX (

  fft,
  fft1D,
  fft2D,
  fft3D,

) where

import Data.Array.Accelerate.Math.FFT.Mode
import Data.Array.Accelerate.Math.FFT.Type
import Data.Array.Accelerate.Math.FFT.LLVM.PTX.Base
import Data.Array.Accelerate.Math.FFT.LLVM.PTX.Plans

import Data.Array.Accelerate.Analysis.Match
import Data.Array.Accelerate.Data.Complex
import Data.Array.Accelerate.Error
import Data.Array.Accelerate.Lifetime
import Data.Array.Accelerate.Representation.Array
import Data.Array.Accelerate.Representation.Shape
import Data.Array.Accelerate.Sugar.Elt
import Data.Primitive.Vec

import Data.Array.Accelerate.LLVM.PTX.Foreign

import Foreign.CUDA.Ptr                                             ( DevicePtr, castDevPtr )
import qualified Foreign.CUDA.FFT                                   as FFT

import Control.Monad.Reader
import Data.Hashable
import System.IO.Unsafe


fft :: forall sh e. HasCallStack
    => Mode
    -> ShapeR sh
    -> NumericR e
    -> ForeignAcc (Array sh (Vec2 e) -> Array sh (Vec2 e))
fft :: Mode
-> ShapeR sh
-> NumericR e
-> ForeignAcc (Array sh (Vec2 e) -> Array sh (Vec2 e))
fft Mode
mode ShapeR sh
shR NumericR e
eR
  | Just sh :~: DIM1
Refl <- ShapeR sh -> ShapeR DIM1 -> Maybe (sh :~: DIM1)
forall s t. ShapeR s -> ShapeR t -> Maybe (s :~: t)
matchShapeR ShapeR sh
shR ShapeR DIM1
dim1 = Mode
-> NumericR e
-> ForeignAcc (Array DIM1 (Vec2 e) -> Array DIM1 (Vec2 e))
forall e.
Mode
-> NumericR e
-> ForeignAcc (Array DIM1 (Vec2 e) -> Array DIM1 (Vec2 e))
fft1D Mode
mode NumericR e
eR
  | Just sh :~: DIM2
Refl <- ShapeR sh -> ShapeR DIM2 -> Maybe (sh :~: DIM2)
forall s t. ShapeR s -> ShapeR t -> Maybe (s :~: t)
matchShapeR ShapeR sh
shR ShapeR DIM2
dim2 = String
-> (Array DIM2 (Vec2 e) -> Par PTX (Future (Array DIM2 (Vec2 e))))
-> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e))
forall a b.
String -> (a -> Par PTX (Future b)) -> ForeignAcc (a -> b)
ForeignAcc String
"cuda.fft2.many" ((Array DIM2 (Vec2 e) -> Par PTX (Future (Array DIM2 (Vec2 e))))
 -> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e)))
-> (Array DIM2 (Vec2 e) -> Par PTX (Future (Array DIM2 (Vec2 e))))
-> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e))
forall a b. (a -> b) -> a -> b
$ Plans (DIM2, Type)
-> Mode
-> ShapeR DIM2
-> NumericR e
-> Array DIM2 (Vec2 e)
-> Par PTX (Future (Array DIM2 (Vec2 e)))
forall sh e.
Plans (sh, Type)
-> Mode
-> ShapeR sh
-> NumericR e
-> Array sh (Vec2 e)
-> Par PTX (Future (Array sh (Vec2 e)))
fft' Plans (DIM2, Type)
fft2DMany_plans Mode
mode ShapeR sh
ShapeR DIM2
shR NumericR e
eR
  | Just sh :~: DIM3
Refl <- ShapeR sh -> ShapeR DIM3 -> Maybe (sh :~: DIM3)
forall s t. ShapeR s -> ShapeR t -> Maybe (s :~: t)
matchShapeR ShapeR sh
shR ShapeR DIM3
dim3 = String
-> (Array DIM3 (Vec2 e) -> Par PTX (Future (Array DIM3 (Vec2 e))))
-> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e))
forall a b.
String -> (a -> Par PTX (Future b)) -> ForeignAcc (a -> b)
ForeignAcc String
"cuda.fft3.many" ((Array DIM3 (Vec2 e) -> Par PTX (Future (Array DIM3 (Vec2 e))))
 -> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e)))
-> (Array DIM3 (Vec2 e) -> Par PTX (Future (Array DIM3 (Vec2 e))))
-> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e))
forall a b. (a -> b) -> a -> b
$ Plans (DIM3, Type)
-> Mode
-> ShapeR DIM3
-> NumericR e
-> Array DIM3 (Vec2 e)
-> Par PTX (Future (Array DIM3 (Vec2 e)))
forall sh e.
Plans (sh, Type)
-> Mode
-> ShapeR sh
-> NumericR e
-> Array sh (Vec2 e)
-> Par PTX (Future (Array sh (Vec2 e)))
fft' Plans (DIM3, Type)
fft3DMany_plans Mode
mode ShapeR sh
ShapeR DIM3
shR NumericR e
eR
  | Bool
otherwise = String -> ForeignAcc (Array sh (Vec2 e) -> Array sh (Vec2 e))
forall a. HasCallStack => String -> a
internalError String
"only for 1D..3D inner-dimension transforms"

fft1D :: Mode -> NumericR e -> ForeignAcc (Array DIM1 (Vec2 e) -> Array DIM1 (Vec2 e))
fft1D :: Mode
-> NumericR e
-> ForeignAcc (Array DIM1 (Vec2 e) -> Array DIM1 (Vec2 e))
fft1D Mode
mode NumericR e
eR = String
-> (Array DIM1 (Vec2 e) -> Par PTX (Future (Array DIM1 (Vec2 e))))
-> ForeignAcc (Array DIM1 (Vec2 e) -> Array DIM1 (Vec2 e))
forall a b.
String -> (a -> Par PTX (Future b)) -> ForeignAcc (a -> b)
ForeignAcc String
"cuda.fft1d" ((Array DIM1 (Vec2 e) -> Par PTX (Future (Array DIM1 (Vec2 e))))
 -> ForeignAcc (Array DIM1 (Vec2 e) -> Array DIM1 (Vec2 e)))
-> (Array DIM1 (Vec2 e) -> Par PTX (Future (Array DIM1 (Vec2 e))))
-> ForeignAcc (Array DIM1 (Vec2 e) -> Array DIM1 (Vec2 e))
forall a b. (a -> b) -> a -> b
$ Plans (DIM1, Type)
-> Mode
-> ShapeR DIM1
-> NumericR e
-> Array DIM1 (Vec2 e)
-> Par PTX (Future (Array DIM1 (Vec2 e)))
forall sh e.
Plans (sh, Type)
-> Mode
-> ShapeR sh
-> NumericR e
-> Array sh (Vec2 e)
-> Par PTX (Future (Array sh (Vec2 e)))
fft' Plans (DIM1, Type)
fft1D_plans Mode
mode ShapeR DIM1
dim1 NumericR e
eR

fft2D :: Mode -> NumericR e -> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e))
fft2D :: Mode
-> NumericR e
-> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e))
fft2D Mode
mode NumericR e
eR = String
-> (Array DIM2 (Vec2 e) -> Par PTX (Future (Array DIM2 (Vec2 e))))
-> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e))
forall a b.
String -> (a -> Par PTX (Future b)) -> ForeignAcc (a -> b)
ForeignAcc String
"cuda.fft2d" ((Array DIM2 (Vec2 e) -> Par PTX (Future (Array DIM2 (Vec2 e))))
 -> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e)))
-> (Array DIM2 (Vec2 e) -> Par PTX (Future (Array DIM2 (Vec2 e))))
-> ForeignAcc (Array DIM2 (Vec2 e) -> Array DIM2 (Vec2 e))
forall a b. (a -> b) -> a -> b
$ Plans (DIM2, Type)
-> Mode
-> ShapeR DIM2
-> NumericR e
-> Array DIM2 (Vec2 e)
-> Par PTX (Future (Array DIM2 (Vec2 e)))
forall sh e.
Plans (sh, Type)
-> Mode
-> ShapeR sh
-> NumericR e
-> Array sh (Vec2 e)
-> Par PTX (Future (Array sh (Vec2 e)))
fft' Plans (DIM2, Type)
fft2D_plans Mode
mode ShapeR DIM2
dim2 NumericR e
eR

fft3D :: Mode -> NumericR e -> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e))
fft3D :: Mode
-> NumericR e
-> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e))
fft3D Mode
mode NumericR e
eR = String
-> (Array DIM3 (Vec2 e) -> Par PTX (Future (Array DIM3 (Vec2 e))))
-> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e))
forall a b.
String -> (a -> Par PTX (Future b)) -> ForeignAcc (a -> b)
ForeignAcc String
"cuda.fft3d" ((Array DIM3 (Vec2 e) -> Par PTX (Future (Array DIM3 (Vec2 e))))
 -> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e)))
-> (Array DIM3 (Vec2 e) -> Par PTX (Future (Array DIM3 (Vec2 e))))
-> ForeignAcc (Array DIM3 (Vec2 e) -> Array DIM3 (Vec2 e))
forall a b. (a -> b) -> a -> b
$ Plans (DIM3, Type)
-> Mode
-> ShapeR DIM3
-> NumericR e
-> Array DIM3 (Vec2 e)
-> Par PTX (Future (Array DIM3 (Vec2 e)))
forall sh e.
Plans (sh, Type)
-> Mode
-> ShapeR sh
-> NumericR e
-> Array sh (Vec2 e)
-> Par PTX (Future (Array sh (Vec2 e)))
fft' Plans (DIM3, Type)
fft3D_plans Mode
mode ShapeR DIM3
dim3 NumericR e
eR


-- Internals
-- ---------

{-# INLINEABLE fft' #-}
fft' :: forall sh e.
        Plans (sh, FFT.Type)
     -> Mode
     -> ShapeR sh
     -> NumericR e
     -> Array sh (Vec2 e)
     -> Par PTX (Future (Array sh (Vec2 e)))
fft' :: Plans (sh, Type)
-> Mode
-> ShapeR sh
-> NumericR e
-> Array sh (Vec2 e)
-> Par PTX (Future (Array sh (Vec2 e)))
fft' Plans (sh, Type)
plans Mode
mode ShapeR sh
shR NumericR e
eR =
  let
      go :: ArrayR (Array sh (Vec2 e)) -> Array sh (Vec2 e) -> Par PTX (Future (Array sh (Vec2 e)))
      go :: ArrayR (Array sh (Vec2 e))
-> Array sh (Vec2 e) -> Par PTX (Future (Array sh (Vec2 e)))
go ArrayR (Array sh (Vec2 e))
aR Array sh (Vec2 e)
ain = do
        let
            sh :: sh
sh = Array sh (Vec2 e) -> sh
forall sh e. Array sh e -> sh
shape Array sh (Vec2 e)
ain
            t :: Type
t  = NumericR e -> Type
forall e. NumericR e -> Type
fftType NumericR e
eR
        --
        Array sh (Vec2 e)
aout    <- ArrayR (Array sh (Vec2 e)) -> sh -> Par PTX (Array sh (Vec2 e))
forall arch sh e.
Remote arch =>
ArrayR (Array sh e) -> sh -> Par arch (Array sh e)
allocateRemote ArrayR (Array sh (Vec2 e))
aR sh
sh
        Stream
stream  <- (ParState -> Stream) -> Par PTX Stream
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ParState -> Stream
ptxStream
        Future (Array sh (Vec2 e))
future  <- Par PTX (Future (Array sh (Vec2 e)))
forall arch a.
(Async arch, HasCallStack) =>
Par arch (FutureR arch a)
new
        LLVM PTX () -> Par PTX ()
forall arch a.
(Async arch, HasCallStack) =>
LLVM arch a -> Par arch a
liftPar (LLVM PTX () -> Par PTX ()) -> LLVM PTX () -> Par PTX ()
forall a b. (a -> b) -> a -> b
$
          NumericR e
-> Array sh (Vec2 e)
-> Stream
-> (DevicePtr e -> LLVM PTX ())
-> LLVM PTX ()
forall e sh b.
NumericR e
-> Array sh (Vec2 e)
-> Stream
-> (DevicePtr e -> LLVM PTX b)
-> LLVM PTX b
withArray NumericR e
eR Array sh (Vec2 e)
ain Stream
stream   ((DevicePtr e -> LLVM PTX ()) -> LLVM PTX ())
-> (DevicePtr e -> LLVM PTX ()) -> LLVM PTX ()
forall a b. (a -> b) -> a -> b
$ \DevicePtr e
d_in  -> do
           NumericR e
-> Array sh (Vec2 e)
-> Stream
-> (DevicePtr e -> LLVM PTX ())
-> LLVM PTX ()
forall e sh b.
NumericR e
-> Array sh (Vec2 e)
-> Stream
-> (DevicePtr e -> LLVM PTX b)
-> LLVM PTX b
withArray NumericR e
eR Array sh (Vec2 e)
aout Stream
stream ((DevicePtr e -> LLVM PTX ()) -> LLVM PTX ())
-> (DevicePtr e -> LLVM PTX ()) -> LLVM PTX ()
forall a b. (a -> b) -> a -> b
$ \DevicePtr e
d_out -> do
            Plans (sh, Type)
-> (sh, Type) -> (Handle -> LLVM PTX ()) -> LLVM PTX ()
forall a b. Plans a -> a -> (Handle -> LLVM PTX b) -> LLVM PTX b
withPlan Plans (sh, Type)
plans (sh
sh,Type
t)   ((Handle -> LLVM PTX ()) -> LLVM PTX ())
-> (Handle -> LLVM PTX ()) -> LLVM PTX ()
forall a b. (a -> b) -> a -> b
$ \Handle
h     -> do
              IO () -> LLVM PTX ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> LLVM PTX ()) -> IO () -> LLVM PTX ()
forall a b. (a -> b) -> a -> b
$ NumericR e
-> Handle
-> Mode
-> Stream
-> DevicePtr (Complex e)
-> DevicePtr (Complex e)
-> IO ()
forall e.
NumericR e
-> Handle
-> Mode
-> Stream
-> DevicePtr (Complex e)
-> DevicePtr (Complex e)
-> IO ()
cuFFT NumericR e
eR Handle
h Mode
mode Stream
stream (DevicePtr e -> DevicePtr (Complex e)
forall a b. DevicePtr a -> DevicePtr b
castDevPtr DevicePtr e
d_in) (DevicePtr e -> DevicePtr (Complex e)
forall a b. DevicePtr a -> DevicePtr b
castDevPtr DevicePtr e
d_out)
        --
        FutureR PTX (Array sh (Vec2 e)) -> Array sh (Vec2 e) -> Par PTX ()
forall arch a.
(Async arch, HasCallStack) =>
FutureR arch a -> a -> Par arch ()
put FutureR PTX (Array sh (Vec2 e))
Future (Array sh (Vec2 e))
future Array sh (Vec2 e)
aout
        Future (Array sh (Vec2 e)) -> Par PTX (Future (Array sh (Vec2 e)))
forall (m :: * -> *) a. Monad m => a -> m a
return Future (Array sh (Vec2 e))
future
  in
  case NumericR e
eR of
    NumericR e
NumericRfloat32 -> ArrayR (Array sh (Vec2 e))
-> Array sh (Vec2 e) -> Par PTX (Future (Array sh (Vec2 e)))
go (ShapeR sh -> TypeR (Vec2 e) -> ArrayR (Array sh (Vec2 e))
forall sh e. ShapeR sh -> TypeR e -> ArrayR (Array sh e)
ArrayR ShapeR sh
shR (Elt (Complex Float) => TypeR (EltR (Complex Float))
forall a. Elt a => TypeR (EltR a)
eltR @(Complex Float)))
    NumericR e
NumericRfloat64 -> ArrayR (Array sh (Vec2 e))
-> Array sh (Vec2 e) -> Par PTX (Future (Array sh (Vec2 e)))
go (ShapeR sh -> TypeR (Vec2 e) -> ArrayR (Array sh (Vec2 e))
forall sh e. ShapeR sh -> TypeR e -> ArrayR (Array sh e)
ArrayR ShapeR sh
shR (Elt (Complex Double) => TypeR (EltR (Complex Double))
forall a. Elt a => TypeR (EltR a)
eltR @(Complex Double)))

--
-- Execute the FFT
--
{-# INLINE cuFFT #-}
cuFFT :: NumericR e
      -> FFT.Handle
      -> Mode
      -> Stream
      -> DevicePtr (Complex e)
      -> DevicePtr (Complex e)
      -> IO ()
cuFFT :: NumericR e
-> Handle
-> Mode
-> Stream
-> DevicePtr (Complex e)
-> DevicePtr (Complex e)
-> IO ()
cuFFT NumericR e
eR Handle
p Mode
mode Stream
stream DevicePtr (Complex e)
d_in DevicePtr (Complex e)
d_out =
  Stream -> (Stream -> IO ()) -> IO ()
forall a b. Lifetime a -> (a -> IO b) -> IO b
withLifetime Stream
stream ((Stream -> IO ()) -> IO ()) -> (Stream -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Stream
s -> do
    Handle -> Stream -> IO ()
FFT.setStream Handle
p Stream
s
    case NumericR e
eR of
      NumericR e
NumericRfloat32 -> Handle
-> Mode
-> DevicePtr (Complex Float)
-> DevicePtr (Complex Float)
-> IO ()
FFT.execC2C Handle
p (Mode -> Mode
fftMode Mode
mode) DevicePtr (Complex e)
DevicePtr (Complex Float)
d_in DevicePtr (Complex e)
DevicePtr (Complex Float)
d_out
      NumericR e
NumericRfloat64 -> Handle
-> Mode
-> DevicePtr (Complex Double)
-> DevicePtr (Complex Double)
-> IO ()
FFT.execZ2Z Handle
p (Mode -> Mode
fftMode Mode
mode) DevicePtr (Complex e)
DevicePtr (Complex Double)
d_in DevicePtr (Complex e)
DevicePtr (Complex Double)
d_out

fftType :: NumericR e -> FFT.Type
fftType :: NumericR e -> Type
fftType NumericR e
NumericRfloat32 = Type
FFT.C2C
fftType NumericR e
NumericRfloat64 = Type
FFT.Z2Z

fftMode :: Mode -> FFT.Mode
fftMode :: Mode -> Mode
fftMode Mode
Forward = Mode
FFT.Forward
fftMode Mode
_       = Mode
FFT.Inverse

-- Plan caches
-- -----------

{-# NOINLINE fft1D_plans #-}
fft1D_plans :: Plans (DIM1, FFT.Type)
fft1D_plans :: Plans (DIM1, Type)
fft1D_plans
  = IO (Plans (DIM1, Type)) -> Plans (DIM1, Type)
forall a. IO a -> a
unsafePerformIO
  (IO (Plans (DIM1, Type)) -> Plans (DIM1, Type))
-> IO (Plans (DIM1, Type)) -> Plans (DIM1, Type)
forall a b. (a -> b) -> a -> b
$ ((DIM1, Type) -> IO Handle)
-> ((DIM1, Type) -> Int) -> IO (Plans (DIM1, Type))
forall a. (a -> IO Handle) -> (a -> Int) -> IO (Plans a)
createPlan (\(((), Int
n), Type
t) -> Int -> Type -> Int -> IO Handle
FFT.plan1D Int
n Type
t Int
1)
               (\(((), Int
n), Type
t) -> Type -> Int
forall a. Enum a => a -> Int
fromEnum Type
t Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
n)

{-# NOINLINE fft2D_plans #-}
fft2D_plans :: Plans (DIM2, FFT.Type)
fft2D_plans :: Plans (DIM2, Type)
fft2D_plans
  = IO (Plans (DIM2, Type)) -> Plans (DIM2, Type)
forall a. IO a -> a
unsafePerformIO
  (IO (Plans (DIM2, Type)) -> Plans (DIM2, Type))
-> IO (Plans (DIM2, Type)) -> Plans (DIM2, Type)
forall a b. (a -> b) -> a -> b
$ ((DIM2, Type) -> IO Handle)
-> ((DIM2, Type) -> Int) -> IO (Plans (DIM2, Type))
forall a. (a -> IO Handle) -> (a -> Int) -> IO (Plans a)
createPlan (\((((),Int
h),Int
w), Type
t) -> Int -> Int -> Type -> IO Handle
FFT.plan2D Int
h Int
w Type
t)
               (\((((),Int
h),Int
w), Type
t) -> Type -> Int
forall a. Enum a => a -> Int
fromEnum Type
t Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
h Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
w)

{-# NOINLINE fft3D_plans #-}
fft3D_plans :: Plans (DIM3, FFT.Type)
fft3D_plans :: Plans (DIM3, Type)
fft3D_plans
  = IO (Plans (DIM3, Type)) -> Plans (DIM3, Type)
forall a. IO a -> a
unsafePerformIO
  (IO (Plans (DIM3, Type)) -> Plans (DIM3, Type))
-> IO (Plans (DIM3, Type)) -> Plans (DIM3, Type)
forall a b. (a -> b) -> a -> b
$ ((DIM3, Type) -> IO Handle)
-> ((DIM3, Type) -> Int) -> IO (Plans (DIM3, Type))
forall a. (a -> IO Handle) -> (a -> Int) -> IO (Plans a)
createPlan (\(((((),Int
d),Int
h),Int
w), Type
t) -> Int -> Int -> Int -> Type -> IO Handle
FFT.plan3D Int
d Int
h Int
w Type
t)
               (\(((((),Int
d),Int
h),Int
w), Type
t) -> Type -> Int
forall a. Enum a => a -> Int
fromEnum Type
t Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
d Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
h Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
w)

{-# NOINLINE fft2DMany_plans #-}
fft2DMany_plans :: Plans (DIM2, FFT.Type)
fft2DMany_plans :: Plans (DIM2, Type)
fft2DMany_plans
  = IO (Plans (DIM2, Type)) -> Plans (DIM2, Type)
forall a. IO a -> a
unsafePerformIO
  (IO (Plans (DIM2, Type)) -> Plans (DIM2, Type))
-> IO (Plans (DIM2, Type)) -> Plans (DIM2, Type)
forall a b. (a -> b) -> a -> b
$ ((DIM2, Type) -> IO Handle)
-> ((DIM2, Type) -> Int) -> IO (Plans (DIM2, Type))
forall a. (a -> IO Handle) -> (a -> Int) -> IO (Plans a)
createPlan (\((((),Int
h),Int
w), Type
t) -> [Int]
-> Maybe ([Int], Int, Int)
-> Maybe ([Int], Int, Int)
-> Type
-> Int
-> IO Handle
FFT.planMany [Int
w] Maybe ([Int], Int, Int)
forall a. Maybe a
Nothing Maybe ([Int], Int, Int)
forall a. Maybe a
Nothing Type
t Int
h)
               (\((((),Int
h),Int
w), Type
t) -> Type -> Int
forall a. Enum a => a -> Int
fromEnum Type
t Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
h Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
w)

{-# NOINLINE fft3DMany_plans #-}
fft3DMany_plans :: Plans (DIM3, FFT.Type)
fft3DMany_plans :: Plans (DIM3, Type)
fft3DMany_plans
  = IO (Plans (DIM3, Type)) -> Plans (DIM3, Type)
forall a. IO a -> a
unsafePerformIO
  (IO (Plans (DIM3, Type)) -> Plans (DIM3, Type))
-> IO (Plans (DIM3, Type)) -> Plans (DIM3, Type)
forall a b. (a -> b) -> a -> b
$ ((DIM3, Type) -> IO Handle)
-> ((DIM3, Type) -> Int) -> IO (Plans (DIM3, Type))
forall a. (a -> IO Handle) -> (a -> Int) -> IO (Plans a)
createPlan (\(((((()),Int
d),Int
h),Int
w), Type
t) -> [Int]
-> Maybe ([Int], Int, Int)
-> Maybe ([Int], Int, Int)
-> Type
-> Int
-> IO Handle
FFT.planMany [Int
w] Maybe ([Int], Int, Int)
forall a. Maybe a
Nothing Maybe ([Int], Int, Int)
forall a. Maybe a
Nothing Type
t (Int
dInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
h))
               (\(((((()),Int
d),Int
h),Int
w), Type
t) -> Type -> Int
forall a. Enum a => a -> Int
fromEnum Type
t Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
d Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
h Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Int
w)