htestu-0.1.0.0: src/Test/HTestU.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Test.HTestU
( TestResult
, runBattery
, toResults
, runBatteryToResults
, c_smallCrush
, c_crush
, c_bigCrush
) where
import System.Random (RandomGen)
import Foreign.Marshal.Alloc (free)
import Foreign.Marshal.Array (peekArray)
import Foreign.Storable (peek)
import Foreign.Ptr (freeHaskellFunPtr)
import System.IO.Unsafe (unsafePerformIO)
import Test.HTestU.Wrapping (Battery, genToWrappedCallback, c_createGenerator, c_deleteGenerator)
import Test.HTestU.BatteryResult (BatteryResultStruct(..))
import Test.HTestU.Streaming (RandomStream)
-- | Type for presenting a result of a test, instead of a p-value
data TestResult = Fail | Suspect | OK deriving (Eq, Show)
-- | P-value serving as a border for a failure in TestU01, greater => failure or suspicious value
failurePvalue :: Double
failurePvalue = 0.0000000001 -- 10^(-10)
-- | P-value serving as a border for a suspicious value in TestU01, greater => failure
suspectPvalue :: Double
suspectPvalue = 0.001 -- 10^(-3)
-- | Prettifying a p-value to a test result
pValueToResult :: Double -> TestResult
pValueToResult pvalue | pvalue < failurePvalue || pvalue > 1.0 - failurePvalue = Fail
| pvalue < suspectPvalue || pvalue > 1.0 - suspectPvalue = Suspect
| otherwise = OK
-- | Prettifying a list of result p-values
toResults :: [Double] -> [TestResult]
toResults = map pValueToResult
-- | Run a given battery and present pretty results
runBatteryToResults :: RandomGen g => (g -> RandomStream) -> g -> Battery -> [TestResult]
runBatteryToResults = ((toResults .) .) . runBattery
-- | Run a given battery and present resulting p-values
-- NOTE: returns [Double] instead of IO [Double], because it is transparent (for the same gen result should be the same)
runBattery :: RandomGen g => (g -> RandomStream) -> g -> Battery -> [Double]
runBattery streamer gen crush = unsafePerformIO $ do
callback <- genToWrappedCallback streamer gen
generatorPtr <- c_createGenerator callback
batteryResult <- crush generatorPtr
(BR ps tests) <- peek batteryResult
c_deleteGenerator generatorPtr
freeHaskellFunPtr callback
free batteryResult
cDoublePvalues <- peekArray (fromIntegral tests) ps
return $ map realToFrac cDoublePvalues
{-# NOINLINE runBattery #-}
-- | Runs SmallCrush battery, 10 tests
foreign import ccall safe "bbattery_SmallCrush" c_smallCrush :: Battery
-- | Runs Crush battery, 96 tests
foreign import ccall safe "bbattery_Crush" c_crush :: Battery
-- | Runs BigCrush Battery, 106 tests
foreign import ccall safe "bbattery_BigCrush" c_bigCrush :: Battery