fast-digits-0.3.2.0: tests/Tests.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
module Main (main) where
import Test.SmallCheck.Series as SC (Positive(..), NonNegative(..))
import Test.Tasty (TestTree, testGroup, defaultMain)
import Test.Tasty.SmallCheck as SC (testProperty)
import Test.Tasty.QuickCheck as QC (Positive(..), NonNegative(..), Property, (==>), (===), testProperty)
#ifdef MIN_VERSION_digits
import qualified Data.Digits as D (digitsRev, unDigits)
#endif
import Data.FastDigits (digits, undigits)
import Data.FastDigits.Internal (selectPower')
#ifdef MIN_VERSION_digits
digitsD :: Int -> Integer -> [Int]
digitsD base n = map fromInteger $ D.digitsRev (toInteger base) n
undigitsD :: Int -> [Int] -> Integer
undigitsD base ns = D.unDigits (toInteger base) (map toInteger ns)
#endif
digits10 :: Integer -> [Int]
digits10 = reverse . map (read . (:[])) . show
largeInteger :: [QC.Positive Int] -> QC.NonNegative Integer
largeInteger ns = QC.NonNegative $ read $ take 1000 $ '0' : concatMap (\(QC.Positive n) -> show n) ns
-- undigits base . digits base == id
qProperty1 :: QC.Positive Int -> [QC.Positive Int] -> QC.Property
qProperty1 (QC.Positive base) (largeInteger -> QC.NonNegative n) = base /= 1 QC.==>
undigits base (digits base n) === n
sProperty1 :: SC.Positive Int -> SC.NonNegative Integer -> Bool
sProperty1 (SC.Positive base) (SC.NonNegative n) = base == 1 ||
undigits base (digits base n) == n
#ifdef MIN_VERSION_digits
-- digits == digitsD
qProperty2 :: QC.Positive Int -> [QC.Positive Int] -> QC.Property
qProperty2 (QC.Positive base) (largeInteger -> QC.NonNegative n) = base /= 1 QC.==>
digits base n === digitsD base n
sProperty2 :: SC.Positive Int -> SC.NonNegative Integer -> Bool
sProperty2 (SC.Positive base) (SC.NonNegative n) = base == 1 ||
digits base n == digitsD base n
#endif
-- digits 10 == digits10
qProperty3 :: [QC.Positive Int] -> QC.Property
qProperty3 (largeInteger -> QC.NonNegative n) = n /= 0 QC.==>
digits 10 n === digits10 n
sProperty3 :: SC.Positive Integer -> Bool
sProperty3 (SC.Positive n) =
digits 10 n == digits10 n
-- All digits are between 0 and base - 1
qProperty4 :: QC.Positive Int -> [QC.Positive Int] -> QC.Property
qProperty4 (QC.Positive base) (largeInteger -> QC.NonNegative n) = base /= 1 QC.==>
all (\d -> d >= 0 && d < base) (digits base n)
sProperty4 :: SC.Positive Int -> SC.NonNegative Integer -> Bool
sProperty4 (SC.Positive base) (SC.NonNegative n) = base == 1 ||
all (\d -> d >= 0 && d < base) (digits base n)
-- Last digit is not 0
qProperty5 :: QC.Positive Int -> [QC.Positive Int] -> QC.Property
qProperty5 (QC.Positive base) (largeInteger -> QC.NonNegative n) = base /= 1 && n /= 0 QC.==>
((/= 0) $ last $ digits base n)
sProperty5 :: SC.Positive Int -> SC.Positive Integer -> Bool
sProperty5 (SC.Positive base) (SC.Positive n) = base == 1 ||
((/= 0) $ last $ digits base n)
#ifdef MIN_VERSION_digits
-- digits 2 == digitsD 2
qProperty6 :: [QC.Positive Int] -> QC.Property
qProperty6 (largeInteger -> QC.NonNegative n) =
digits 2 n === digitsD 2 n
sProperty6 :: SC.NonNegative Integer -> Bool
sProperty6 (SC.NonNegative n) =
digits 2 n == digitsD 2 n
-- digits 2 == digitsD 2 on integers of special form
qProperty7 :: QC.NonNegative Int -> QC.NonNegative Int -> QC.Property
qProperty7 (QC.NonNegative a) (QC.NonNegative b) =
digits 2 n === digitsD 2 n
where
n = toInteger a * toInteger (maxBound :: Int) + toInteger b
sProperty7 :: SC.NonNegative Int -> SC.NonNegative Int -> Bool
sProperty7 (SC.NonNegative a) (SC.NonNegative b) =
digits 2 n == digitsD 2 n
where
n = toInteger a * toInteger (maxBound :: Int) + toInteger b
#endif
qProperty8 :: QC.Positive Int -> QC.Property
qProperty8 (QC.Positive base') = base /= 1 QC.==>
base ^ power == poweredBase && poweredBase > maxBound `div` base
where
base = fromIntegral $ toInteger base'
(power, poweredBase) = selectPower' base
sProperty8 :: SC.Positive Int -> Bool
sProperty8 (SC.Positive base') = base == 1 ||
base ^ power == poweredBase && poweredBase > maxBound `div` base
where
base = fromIntegral $ toInteger base'
(power, poweredBase) = selectPower' base
testSuite :: TestTree
testSuite = testGroup "digits"
[ SC.testProperty "S undigits base . digits base == id" sProperty1
, QC.testProperty "Q undigits base . digits base == id" qProperty1
#ifdef MIN_VERSION_digits
, SC.testProperty "S digits == digitsD" sProperty2
, QC.testProperty "Q digits == digitsD" qProperty2
#endif
, SC.testProperty "S digits 10 == digits10" sProperty3
, QC.testProperty "Q digits 10 == digits10" qProperty3
, SC.testProperty "S All digits are between 0 and base - 1" sProperty4
, QC.testProperty "Q All digits are between 0 and base - 1" qProperty4
, SC.testProperty "S Last digit is not 0" sProperty5
, QC.testProperty "Q Last digit is not 0" qProperty5
#ifdef MIN_VERSION_digits
, SC.testProperty "S digits 2 == digitsD 2" sProperty6
, QC.testProperty "Q digits 2 == digitsD 2" qProperty6
, SC.testProperty "S digits 2 == digitsD 2 on integers of special form" sProperty7
, QC.testProperty "Q digits 2 == digitsD 2 on integers of special form" qProperty7
#endif
, SC.testProperty "S selectPower is correct" sProperty8
, QC.testProperty "Q selectPower is correct" qProperty8
]
main :: IO ()
main = defaultMain testSuite