{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}

module Algebra.Ring.Polynomial.Test
  ( module Algebra.Ring.Polynomial.Monomial.Test,
    WrapPolynomial (..),
    arbitraryPolynomial,
    seriesPolynomial,
    HomogPoly (..),
    arbitraryHomogeneousPolynomial,
  )
where

import Algebra.Internal
import Algebra.Ring.Polynomial.Class
  ( Arity,
    Coefficient,
    IsOrderedPolynomial,
    polynomial,
  )
import Algebra.Ring.Polynomial.Monomial (OrderedMonomial (..))
import Algebra.Ring.Polynomial.Monomial.Test (arbitraryMonomialOfSum)
import qualified Data.Map as M
import Test.QuickCheck
  ( Arbitrary (..),
    Gen,
    elements,
    listOf1,
    sized,
  )
import Test.SmallCheck.Series (Serial (..), Series)
import Prelude

newtype WrapPolynomial polyn = WrapPolynomial {WrapPolynomial polyn -> polyn
runWrapPolynomial :: polyn}
  deriving (ReadPrec [WrapPolynomial polyn]
ReadPrec (WrapPolynomial polyn)
Int -> ReadS (WrapPolynomial polyn)
ReadS [WrapPolynomial polyn]
(Int -> ReadS (WrapPolynomial polyn))
-> ReadS [WrapPolynomial polyn]
-> ReadPrec (WrapPolynomial polyn)
-> ReadPrec [WrapPolynomial polyn]
-> Read (WrapPolynomial polyn)
forall polyn. Read polyn => ReadPrec [WrapPolynomial polyn]
forall polyn. Read polyn => ReadPrec (WrapPolynomial polyn)
forall polyn. Read polyn => Int -> ReadS (WrapPolynomial polyn)
forall polyn. Read polyn => ReadS [WrapPolynomial polyn]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [WrapPolynomial polyn]
$creadListPrec :: forall polyn. Read polyn => ReadPrec [WrapPolynomial polyn]
readPrec :: ReadPrec (WrapPolynomial polyn)
$creadPrec :: forall polyn. Read polyn => ReadPrec (WrapPolynomial polyn)
readList :: ReadS [WrapPolynomial polyn]
$creadList :: forall polyn. Read polyn => ReadS [WrapPolynomial polyn]
readsPrec :: Int -> ReadS (WrapPolynomial polyn)
$creadsPrec :: forall polyn. Read polyn => Int -> ReadS (WrapPolynomial polyn)
Read, Int -> WrapPolynomial polyn -> ShowS
[WrapPolynomial polyn] -> ShowS
WrapPolynomial polyn -> String
(Int -> WrapPolynomial polyn -> ShowS)
-> (WrapPolynomial polyn -> String)
-> ([WrapPolynomial polyn] -> ShowS)
-> Show (WrapPolynomial polyn)
forall polyn. Show polyn => Int -> WrapPolynomial polyn -> ShowS
forall polyn. Show polyn => [WrapPolynomial polyn] -> ShowS
forall polyn. Show polyn => WrapPolynomial polyn -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [WrapPolynomial polyn] -> ShowS
$cshowList :: forall polyn. Show polyn => [WrapPolynomial polyn] -> ShowS
show :: WrapPolynomial polyn -> String
$cshow :: forall polyn. Show polyn => WrapPolynomial polyn -> String
showsPrec :: Int -> WrapPolynomial polyn -> ShowS
$cshowsPrec :: forall polyn. Show polyn => Int -> WrapPolynomial polyn -> ShowS
Show, WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
(WrapPolynomial polyn -> WrapPolynomial polyn -> Bool)
-> (WrapPolynomial polyn -> WrapPolynomial polyn -> Bool)
-> Eq (WrapPolynomial polyn)
forall polyn.
Eq polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
$c/= :: forall polyn.
Eq polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
== :: WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
$c== :: forall polyn.
Eq polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
Eq, Eq (WrapPolynomial polyn)
Eq (WrapPolynomial polyn)
-> (WrapPolynomial polyn -> WrapPolynomial polyn -> Ordering)
-> (WrapPolynomial polyn -> WrapPolynomial polyn -> Bool)
-> (WrapPolynomial polyn -> WrapPolynomial polyn -> Bool)
-> (WrapPolynomial polyn -> WrapPolynomial polyn -> Bool)
-> (WrapPolynomial polyn -> WrapPolynomial polyn -> Bool)
-> (WrapPolynomial polyn
    -> WrapPolynomial polyn -> WrapPolynomial polyn)
-> (WrapPolynomial polyn
    -> WrapPolynomial polyn -> WrapPolynomial polyn)
-> Ord (WrapPolynomial polyn)
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
WrapPolynomial polyn -> WrapPolynomial polyn -> Ordering
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall polyn. Ord polyn => Eq (WrapPolynomial polyn)
forall polyn.
Ord polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
forall polyn.
Ord polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Ordering
forall polyn.
Ord polyn =>
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
min :: WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
$cmin :: forall polyn.
Ord polyn =>
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
max :: WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
$cmax :: forall polyn.
Ord polyn =>
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
>= :: WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
$c>= :: forall polyn.
Ord polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
> :: WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
$c> :: forall polyn.
Ord polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
<= :: WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
$c<= :: forall polyn.
Ord polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
< :: WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
$c< :: forall polyn.
Ord polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Bool
compare :: WrapPolynomial polyn -> WrapPolynomial polyn -> Ordering
$ccompare :: forall polyn.
Ord polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn -> Ordering
$cp1Ord :: forall polyn. Ord polyn => Eq (WrapPolynomial polyn)
Ord, Integer -> WrapPolynomial polyn
WrapPolynomial polyn -> WrapPolynomial polyn
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
(WrapPolynomial polyn
 -> WrapPolynomial polyn -> WrapPolynomial polyn)
-> (WrapPolynomial polyn
    -> WrapPolynomial polyn -> WrapPolynomial polyn)
-> (WrapPolynomial polyn
    -> WrapPolynomial polyn -> WrapPolynomial polyn)
-> (WrapPolynomial polyn -> WrapPolynomial polyn)
-> (WrapPolynomial polyn -> WrapPolynomial polyn)
-> (WrapPolynomial polyn -> WrapPolynomial polyn)
-> (Integer -> WrapPolynomial polyn)
-> Num (WrapPolynomial polyn)
forall polyn. Num polyn => Integer -> WrapPolynomial polyn
forall polyn.
Num polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn
forall polyn.
Num polyn =>
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> WrapPolynomial polyn
$cfromInteger :: forall polyn. Num polyn => Integer -> WrapPolynomial polyn
signum :: WrapPolynomial polyn -> WrapPolynomial polyn
$csignum :: forall polyn.
Num polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn
abs :: WrapPolynomial polyn -> WrapPolynomial polyn
$cabs :: forall polyn.
Num polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn
negate :: WrapPolynomial polyn -> WrapPolynomial polyn
$cnegate :: forall polyn.
Num polyn =>
WrapPolynomial polyn -> WrapPolynomial polyn
* :: WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
$c* :: forall polyn.
Num polyn =>
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
- :: WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
$c- :: forall polyn.
Num polyn =>
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
+ :: WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
$c+ :: forall polyn.
Num polyn =>
WrapPolynomial polyn
-> WrapPolynomial polyn -> WrapPolynomial polyn
Num)

instance
  (IsOrderedPolynomial poly, Arbitrary (Coefficient poly)) =>
  Arbitrary (WrapPolynomial poly)
  where
  arbitrary :: Gen (WrapPolynomial poly)
arbitrary =
    poly -> WrapPolynomial poly
forall polyn. polyn -> WrapPolynomial polyn
WrapPolynomial (poly -> WrapPolynomial poly)
-> ([(OrderedMonomial (MOrder poly) (Arity poly),
      Coefficient poly)]
    -> poly)
-> [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> WrapPolynomial poly
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
-> poly
forall poly.
IsOrderedPolynomial poly =>
Map (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
-> poly
polynomial (Map
   (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
 -> poly)
-> ([(OrderedMonomial (MOrder poly) (Arity poly),
      Coefficient poly)]
    -> Map
         (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly))
-> [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> poly
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> Map
     (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
      ([(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
 -> WrapPolynomial poly)
-> Gen
     [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> Gen (WrapPolynomial poly)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)
-> Gen
     [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
forall a. Gen a -> Gen [a]
listOf1 ((,) (OrderedMonomial (MOrder poly) (Arity poly)
 -> Coefficient poly
 -> (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly))
-> Gen (OrderedMonomial (MOrder poly) (Arity poly))
-> Gen
     (Coefficient poly
      -> (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (OrderedMonomial (MOrder poly) (Arity poly))
forall a. Arbitrary a => Gen a
arbitrary Gen
  (Coefficient poly
   -> (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly))
-> Gen (Coefficient poly)
-> Gen
     (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Coefficient poly)
forall a. Arbitrary a => Gen a
arbitrary)

instance
  (Monad m, IsOrderedPolynomial poly, Serial m (Coefficient poly)) =>
  Serial m (WrapPolynomial poly)
  where
  series :: Series m (WrapPolynomial poly)
series = poly -> WrapPolynomial poly
forall polyn. polyn -> WrapPolynomial polyn
WrapPolynomial (poly -> WrapPolynomial poly)
-> ([(OrderedMonomial (MOrder poly) (Arity poly),
      Coefficient poly)]
    -> poly)
-> [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> WrapPolynomial poly
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
-> poly
forall poly.
IsOrderedPolynomial poly =>
Map (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
-> poly
polynomial (Map
   (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
 -> poly)
-> ([(OrderedMonomial (MOrder poly) (Arity poly),
      Coefficient poly)]
    -> Map
         (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly))
-> [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> poly
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> Map
     (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
 -> WrapPolynomial poly)
-> Series
     m [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> Series m (WrapPolynomial poly)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Series
  m [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
forall (m :: * -> *) a. Serial m a => Series m a
series

arbitraryPolynomial :: (Arbitrary (Coefficient poly), IsOrderedPolynomial poly) => Gen poly
arbitraryPolynomial :: Gen poly
arbitraryPolynomial = WrapPolynomial poly -> poly
forall polyn. WrapPolynomial polyn -> polyn
runWrapPolynomial (WrapPolynomial poly -> poly)
-> Gen (WrapPolynomial poly) -> Gen poly
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (WrapPolynomial poly)
forall a. Arbitrary a => Gen a
arbitrary

seriesPolynomial :: (Serial m (Coefficient poly), IsOrderedPolynomial poly) => Series m poly
seriesPolynomial :: Series m poly
seriesPolynomial = WrapPolynomial poly -> poly
forall polyn. WrapPolynomial polyn -> polyn
runWrapPolynomial (WrapPolynomial poly -> poly)
-> Series m (WrapPolynomial poly) -> Series m poly
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Series m (WrapPolynomial poly)
forall (m :: * -> *) a. Serial m a => Series m a
series

newtype HomogPoly poly = HomogPoly {HomogPoly poly -> poly
getHomogPoly :: poly}

instance
  (IsOrderedPolynomial poly, Arbitrary (Coefficient poly)) =>
  Arbitrary (HomogPoly poly)
  where
  arbitrary :: Gen (HomogPoly poly)
arbitrary = (Int -> Gen (HomogPoly poly)) -> Gen (HomogPoly poly)
forall a. (Int -> Gen a) -> Gen a
sized ((Int -> Gen (HomogPoly poly)) -> Gen (HomogPoly poly))
-> (Int -> Gen (HomogPoly poly)) -> Gen (HomogPoly poly)
forall a b. (a -> b) -> a -> b
$ \Int
s -> do
    let sn :: SNat (Arity poly)
sn = SNat (Arity poly)
forall (n :: Nat). KnownNat n => SNat n
sNat :: SNat (Arity poly)
    Int
deg <- [Int] -> Gen Int
forall a. [a] -> Gen a
elements [Int
0 .. Int
s]
    poly -> HomogPoly poly
forall poly. poly -> HomogPoly poly
HomogPoly (poly -> HomogPoly poly)
-> ([(OrderedMonomial (MOrder poly) (Arity poly),
      Coefficient poly)]
    -> poly)
-> [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> HomogPoly poly
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
-> poly
forall poly.
IsOrderedPolynomial poly =>
Map (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
-> poly
polynomial (Map
   (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
 -> poly)
-> ([(OrderedMonomial (MOrder poly) (Arity poly),
      Coefficient poly)]
    -> Map
         (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly))
-> [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> poly
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> Map
     (OrderedMonomial (MOrder poly) (Arity poly)) (Coefficient poly)
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
      ([(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
 -> HomogPoly poly)
-> Gen
     [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
-> Gen (HomogPoly poly)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)
-> Gen
     [(OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)]
forall a. Gen a -> Gen [a]
listOf1 ((,) (OrderedMonomial (MOrder poly) (Arity poly)
 -> Coefficient poly
 -> (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly))
-> Gen (OrderedMonomial (MOrder poly) (Arity poly))
-> Gen
     (Coefficient poly
      -> (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Monomial (Arity poly) -> OrderedMonomial (MOrder poly) (Arity poly)
forall k (ordering :: k) (n :: Nat).
Monomial n -> OrderedMonomial ordering n
OrderedMonomial (Monomial (Arity poly)
 -> OrderedMonomial (MOrder poly) (Arity poly))
-> Gen (Monomial (Arity poly))
-> Gen (OrderedMonomial (MOrder poly) (Arity poly))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SNat (Arity poly) -> Int -> Gen (Monomial (Arity poly))
forall (n :: Nat). SNat n -> Int -> Gen (Monomial n)
arbitraryMonomialOfSum SNat (Arity poly)
sn Int
deg) Gen
  (Coefficient poly
   -> (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly))
-> Gen (Coefficient poly)
-> Gen
     (OrderedMonomial (MOrder poly) (Arity poly), Coefficient poly)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Coefficient poly)
forall a. Arbitrary a => Gen a
arbitrary)

arbitraryHomogeneousPolynomial :: (Arbitrary (Coefficient poly), IsOrderedPolynomial poly) => Gen poly
arbitraryHomogeneousPolynomial :: Gen poly
arbitraryHomogeneousPolynomial = HomogPoly poly -> poly
forall poly. HomogPoly poly -> poly
getHomogPoly (HomogPoly poly -> poly) -> Gen (HomogPoly poly) -> Gen poly
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (HomogPoly poly)
forall a. Arbitrary a => Gen a
arbitrary