dftExecuteWithPlan :: DFTPlanID
                   -> Plan
                   -> VS.Vector (Complex Double)
                   -> IO (VS.Vector (Complex Double))
dftExecuteWithPlan planID@(DFTPlanID t d i) plan vec = do
  v <- VSM.new (L.product d)
  VS.unsafeWith vec $ \ip -> VSM.unsafeWith v $ \op -> c_execute_dft plan ip op
  u <- VS.freeze v
  if t == IDFT1DG || t == IDFT2D
    then if L.null i
           then return $ VS.map (/ (fromIntegral . L.product $ d)) u
           else if size == 0
                  then error $
                       "dftExecuteWithPlan: dimension error.\n" L.++ "dims: " L.++
                       show d L.++
                       "\nIdx: " L.++
                       show i
                  else return $ VS.map (/ (fromIntegral size)) u
    else return u
  where
    size = L.product . L.take (L.last i - L.head i + 1) . L.drop (L.head i) $ d


dftExecuteWithPlan :: DFTPlanID
                   -> Plan
                   -> VS.Vector (Complex Double)
                   -> IO (VS.Vector (Complex Double))
dftExecuteWithPlan planID@(DFTPlanID t d i) plan vec = do
  v <- VSM.new (L.product d)
  VS.unsafeWith vec $ \ip -> VSM.unsafeWith v $ \op -> c_execute_dft plan ip op
  u <- VS.freeze v
  if t == IDFT1DG || t == IDFT2D
    then if L.null i
           then return $ VS.map (/ (fromIntegral . L.product $ d)) u
           else if size == 0
                  then error $
                       "dftExecuteWithPlan: dimension error.\n" L.++ "dims: " L.++
                       show d L.++
                       "\nIdx: " L.++
                       show i
                  else return $ VS.map (/ (fromIntegral size)) u
    else return u
  where
    size = L.product . L.take (L.last i - L.head i + 1) . L.drop (L.head i) $ d


dftExecuteWithPlan planID@(DFTPlanID t d i) plan vec = do
  v <- VSM.new (L.product d)
  VS.unsafeWith vec $ \ip -> VSM.unsafeWith v $ \op -> c_execute_dft plan ip op
  u <- VS.freeze v
  if t == IDFT1DG || t == IDFT2D
    then if L.null i
           then return $ VS.map (/ (fromIntegral . L.product $ d)) u
           else if size == 0
                  then error $
                       "dftExecuteWithPlan: dimension error.\n" L.++ "dims: " L.++
                       show d L.++
                       "\nIdx: " L.++
                       show i
                  else return $ VS.map (/ (fromIntegral size)) u
    else return u
  where
    size = L.product . L.take (L.last i - L.head i + 1) . L.drop (L.head i) $ d

