ac-library-hs-1.2.6.0: test/Tests/Extra/Math/Montgomery64.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TypeFamilies #-}
module Tests.Extra.Math.Montgomery64 (tests) where
import AtCoder.Extra.Math qualified as ACEM
import AtCoder.Extra.Math.Montgomery64 qualified as M
import Data.Bits
import Data.WideWord.Word128 (Word128 (..))
import Data.Word (Word64)
import Test.Tasty
import Test.Tasty.QuickCheck qualified as QC
to128 :: (Integral a) => a -> Word128
to128 = fromIntegral
mulMod :: Word64 -> Word64 -> Word64 -> Word64
mulMod m x y = word128Lo64 $! (to128 (x `mod` m) * to128 (y `mod` m)) `mod` to128 m
p :: Word64 -> Bool
p m = odd m && m <= bit 62
prop_mulMod :: QC.Positive Word64 -> Word64 -> Word64 -> QC.Property
prop_mulMod (QC.Positive m) x y =
p m QC.==>
let !mont = M.fromVal m
!res = M.decode mont $ M.mulMod mont (M.encode mont x) (M.encode mont y)
!expected = mulMod m x y
in res QC.=== expected
prop_powMod :: QC.Positive Word64 -> Word64 -> QC.Positive Int -> QC.Property
prop_powMod (QC.Positive m) x (QC.Positive n) =
p m QC.==>
let !mont = M.fromVal m
!res = M.decode mont $ M.powMod mont (M.encode mont x) n
!expected = ACEM.power (mulMod m) n (x `mod` m)
in res QC.=== expected
tests :: [TestTree]
tests =
[ QC.testProperty "mulMod" prop_mulMod,
QC.testProperty "powMod" prop_powMod
]