accelerate-examples-1.0.0.0: examples/nofib/QuickCheck/Arbitrary/Shape.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module QuickCheck.Arbitrary.Shape where
import Test.QuickCheck
import Data.Array.Accelerate ( Shape, Z(..), (:.)(..) )
import qualified Data.Array.Accelerate.Array.Sugar as Sugar
instance Arbitrary Z where
arbitrary = return Z
shrink _ = []
instance Arbitrary sh => Arbitrary (sh :. Int) where
arbitrary = do
sh <- arbitrary
NonNegative sz <- arbitrary
return (sh :. sz)
--
shrink (sh :. sz) =
[ sh :. sz' | sz' <- shrink sz, sz' >= 0 ] ++
[ sh' :. sz | sh' <- shrink sh ]
-- Generate an arbitrary shape with approximately this many elements in each
-- dimension. If the generated shape does not contain approximately the
-- specified number of elements (within 10%), the shape is thrown out and a new
-- one is generated.
--
-- NOTE:
-- * Shapes of zero dimension ignore the target size.
-- * Requesting high dimension shapes of very few elements may take same time
-- to generate an appropriate random instance.
--
arbitraryShape :: forall sh. (Shape sh, Arbitrary sh) => Int -> Gen sh
arbitraryShape size =
let
eps = 0.1 :: Double
dim = Sugar.rank (undefined :: sh)
target
| dim == 0 = 1
| otherwise = size * dim
wiggle = round $ fromIntegral target * eps
minsize = target - wiggle
maxsize = target + wiggle
in
arbitrary `suchThat` \sh -> let n = Sugar.size sh
in n >= minsize && n <= maxsize