packages feed

accelerate-0.8.0.0: examples/simple/src/Random.hs

{-# LANGUAGE BangPatterns, FlexibleContexts, ScopedTypeVariables #-}
{-# LANGUAGE ParallelListComp #-}

module Random where

import System.Random.MWC
import Data.Array.IArray
import Data.Array.Unboxed               (UArray)
import Data.Array.IO                    (MArray, IOUArray)
import Control.Exception                (evaluate)
import qualified Data.Array.MArray      as M
import qualified Data.Array.Accelerate  as Acc


-- Convert an unboxed array to an Accelerate array
--
convertVector :: (IArray UArray e, Acc.Elem e) => UArray Int e -> IO (Acc.Vector e)
convertVector v =
  let arr = Acc.fromIArray v
  in  evaluate (arr `Acc.indexArray` 0) >> return arr


-- Generate a random, uniformly distributed vector of specified size. The second
-- argument can be used to modify the generated value (e.g. map into a certain
-- range)
--
randomVector
  :: (Variate a, MArray IOUArray e IO, IArray UArray e)
  => GenIO -> (a -> e) -> Int -> IO (UArray Int e)

randomVector gen f n = do
  mu  <- M.newArray_ (0,n-1) :: MArray IOUArray e IO => IO (IOUArray Int e)
  let go !i | i < n     = uniform gen >>= (\e -> M.writeArray mu i (f e)) >> go (i+1)
            | otherwise = M.unsafeFreeze mu
  go 0


-- Compare two vectors element-wise for equality, for a given measure of
-- similarity. The index and values are printed for pairs that fail.
--
validate
  :: (IArray UArray e, Ix ix, Show e, Show ix)
  => (e -> e -> Bool) -> UArray ix e -> UArray ix e -> IO Bool

validate f ref arr =
  let sim = filter (not . null) [ if f x y then [] else ">>> " ++ shows i ": " ++ show (x,y)
                                  | (i,x) <- assocs ref
                                  | y     <- elems arr ]
  in if null sim
        then putStrLn "Valid"                  >> return True
        else mapM_ putStrLn ("INVALID!" : sim) >> return False


-- Floating point equality with relative tolerance
--
similar :: (Fractional a, Ord a) => a -> a -> Bool
similar x y =
  let epsilon = 0.0001
  in  abs ((x-y) / (x+y+epsilon)) < epsilon