arithmoi-0.9.0.0: test-suite/Math/NumberTheory/Moduli/ChineseTests.hs
-- |
-- Module: Math.NumberTheory.Moduli.ChineseTests
-- Copyright: (c) 2016 Andrew Lelechenko
-- Licence: MIT
-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>
--
-- Tests for Math.NumberTheory.Moduli.Chinese
--
{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
module Math.NumberTheory.Moduli.ChineseTests
( testSuite
) where
import Test.Tasty
import Control.Arrow
import Data.List (tails)
import Math.NumberTheory.Moduli hiding (invertMod)
import Math.NumberTheory.TestUtils
-- | Check that 'chineseRemainder' is defined iff modulos are coprime.
-- Also check that the result is a solution of input modular equations.
chineseRemainderProperty :: [(Integer, Positive Integer)] -> Bool
chineseRemainderProperty rms' = case chineseRemainder rms of
Nothing -> not areCoprime
Just n -> areCoprime && map (n `mod`) ms == zipWith mod rs ms
where
rms = map (second getPositive) rms'
(rs, ms) = unzip rms
areCoprime = all (== 1) [ gcd m1 m2 | (m1 : m2s) <- tails ms, m2 <- m2s ]
-- | Check that 'chineseRemainder' matches 'chineseRemainder2'.
chineseRemainder2Property :: Integer -> Positive Integer -> Integer -> Positive Integer -> Bool
chineseRemainder2Property r1 (Positive m1) r2 (Positive m2) = gcd m1 m2 /= 1
|| Just (chineseRemainder2 (r1, m1) (r2, m2)) == chineseRemainder [(r1, m1), (r2, m2)]
chineseCoprimeProperty :: Integer -> Positive Integer -> Integer -> Positive Integer -> Bool
chineseCoprimeProperty n1 (Positive m1) n2 (Positive m2) = case gcd m1 m2 of
1 -> case chineseCoprime (n1, m1) (n2, m2) of
Nothing -> False
Just n -> n `mod` m1 == n1 `mod` m1 && n `mod` m2 == n2 `mod` m2
_ -> case chineseCoprime (n1, m1) (n2, m2) of
Nothing -> True
Just{} -> False
chineseProperty :: Integer -> Positive Integer -> Integer -> Positive Integer -> Bool
chineseProperty n1 (Positive m1) n2 (Positive m2) = if compatible
then case chinese (n1, m1) (n2, m2) of
Nothing -> False
Just n -> n `mod` m1 == n1 `mod` m1 && n `mod` m2 == n2 `mod` m2
else case chineseCoprime (n1, m1) (n2, m2) of
Nothing -> True
Just{} -> False
where
g = gcd m1 m2
compatible = n1 `mod` g == n2 `mod` g
testSuite :: TestTree
testSuite = testGroup "Chinese"
[ testSmallAndQuick "chineseRemainder" chineseRemainderProperty
, testSmallAndQuick "chineseRemainder2" chineseRemainder2Property
, testSmallAndQuick "chineseCoprime" chineseCoprimeProperty
, testSmallAndQuick "chinese" chineseProperty
]