packages feed

repa-fftw-3.2.3.1: exec/test.hs

-- | Main entry point for test executable.

module Main where

import Data.Array.Repa ((:.)(..), Array, DIM1, DIM2, DIM3, Shape, Z(..), toList)
import Data.Array.Repa.Eval (fromList)
import Data.Array.Repa.Repr.ForeignPtr (F)
import Data.Complex (Complex(..), magnitude)

import Test.Tasty (defaultMain, testGroup)
import Test.Tasty.HUnit (Assertion, assertBool, testCase)
import Test.Tasty.QuickCheck (Property, choose, forAll, testProperty, vector)

import Data.Array.Repa.FFTW (fft, ifft, fft2d, ifft2d, fft3d, ifft3d)


main :: IO ()
main = defaultMain $
    testGroup "repa-fftw"
    [ testCase "magsum1d-hunit" case_magsum1d
    , testCase "magsum2d-hunit" case_magsum2d
    , testCase "magsum3d-hunit" case_magsum3d
    , testProperty "magsum1d-qc" prop_magsum1d
    , testProperty "magsum2d-qc" prop_magsum2d
    , testProperty "magsum3d-qc" prop_magsum3d
    ]

case_magsum1d :: Assertion
case_magsum1d = do
    let a = fromList (Z :. 4) [i :+ 0 | i <- [0..3]]
    assertBool "diff is greater than epsilon" $ compareMagnitudeSum1d a

case_magsum2d :: Assertion
case_magsum2d = do
    let a = fromList (Z :. 4 :. 4) [i :+ 0 | i <- [0..15]]
    assertBool "diff is greater than epsilon" $ compareMagnitudeSum2d a

case_magsum3d :: Assertion
case_magsum3d = do
    let a = fromList (Z :. 4 :. 4 :. 4) [i :+ 0 | i <- [0..63]]
    assertBool "diff is greater than epsilon" $ compareMagnitudeSum3d a

prop_magsum1d :: Property
prop_magsum1d =
    forAll (choose (1, 16::Int)) $ \pow ->
    let size = (2 ^ pow)
    in forAll (vector size) $ \vals ->
       compareMagnitudeSum1d $ fromList (Z :. size) vals

prop_magsum2d :: Property
prop_magsum2d =
    forAll (choose (1, 4::Int)) $ \pow ->
    let extnt = 2 ^ pow
        size  = extnt ^ (2 :: Int)
    in  forAll (vector size) $ \vals ->
        compareMagnitudeSum2d $ fromList (Z :. extnt :. extnt) vals

prop_magsum3d :: Property
prop_magsum3d =
    forAll (choose (1, 4::Int)) $ \pow ->
    let extnt = 2 ^ pow
        size  = extnt ^ (3 :: Int)
    in  forAll (vector size) $ \vals ->
        compareMagnitudeSum3d $ fromList (Z :. extnt :. extnt :. extnt) vals

-- | Performs fft and ifft, then compareing magnitude of sum with the
-- original.
compareMagnitudeSum1d :: Array F DIM1 (Complex Double) -> Bool
compareMagnitudeSum1d = compareMagnitudeSum fft ifft

-- | Like 'compareMagnitudeSum', for 2-dimensional array.
compareMagnitudeSum2d :: Array F DIM2 (Complex Double) -> Bool
compareMagnitudeSum2d = compareMagnitudeSum fft2d ifft2d

-- | Like 'compareMagnitudeSum', for 3-dimensional array.
compareMagnitudeSum3d :: Array F DIM3 (Complex Double) -> Bool
compareMagnitudeSum3d = compareMagnitudeSum fft3d ifft3d

-- | Apply given functions, then compare the result with original.
compareMagnitudeSum ::
    (Shape sh)
    => (Array F sh (Complex Double) -> a)
    -- ^ Forward FFT function.
    -> (a -> Array F sh (Complex Double))
    -- ^ Inverse FFT function.
    -> Array F sh (Complex Double)
    -- ^ Original input.
    -> Bool
compareMagnitudeSum fn ifn arr = diff < epsilon
  where
    diff = abs (mag arr - mag arr')
    mag = magnitude . sum . toList
    arr' = ifn $ fn arr
    epsilon = 1e-2