-- |
-- Module:      Math.NumberTheory.Moduli.EquationsTests
-- Copyright:   (c) 2018 Andrew Lelechenko
-- Licence:     MIT
-- Maintainer:  Andrew Lelechenko <andrew.lelechenko@gmail.com>
--

{-# LANGUAGE ScopedTypeVariables #-}

module Math.NumberTheory.Moduli.EquationsTests
  ( testSuite
  ) where

import Test.Tasty

import Data.List (sort)
import Data.Mod
import Data.Proxy
import GHC.TypeNats (KnownNat, SomeNat(..), someNatVal)
import Numeric.Natural

import Math.NumberTheory.Moduli (SomeMod(..))
import Math.NumberTheory.Moduli.Equations
import Math.NumberTheory.Moduli.Singleton
import Math.NumberTheory.TestUtils

wrapSome :: KnownNat m => ([Mod m], [Mod m]) -> ([SomeMod], [SomeMod])
wrapSome (xs, ys) = (map SomeMod xs, map SomeMod ys)

solveLinearProp :: KnownNat m => Mod m -> Mod m -> ([Mod m], [Mod m])
solveLinearProp a b =
  ( sort (solveLinear a b)
  , filter (\x -> a * x + b == 0) [minBound .. maxBound]
  )

solveLinearProperty1 :: (Positive Natural, Integer, Integer) -> ([SomeMod], [SomeMod])
solveLinearProperty1 (Positive m, a, b) = case someNatVal m of
  SomeNat (_ :: Proxy t) -> wrapSome $ solveLinearProp (fromInteger a :: Mod t) (fromInteger b)

solveQuadraticProp :: KnownNat m => Mod m -> Mod m -> Mod m -> ([Mod m], [Mod m])
solveQuadraticProp a b c =
  ( sort (solveQuadratic sfactors a b c)
  , filter (\x -> a * x * x + b * x + c == 0) [minBound .. maxBound]
  )

solveQuadraticProperty1 :: (Positive Natural, Integer, Integer, Integer) -> ([SomeMod], [SomeMod])
solveQuadraticProperty1 (Positive m, a, b, c) = case someNatVal m of
  SomeNat (_ :: Proxy t) -> wrapSome $ solveQuadraticProp (fromInteger a :: Mod t) (fromInteger b) (fromInteger c)

testSuite :: TestTree
testSuite = testGroup "Equations"
  [ testEqualSmallAndQuick "solveLinear"    solveLinearProperty1
  , testEqualSmallAndQuick "solveQuadratic" solveQuadraticProperty1
  ]
