{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}
{-|
module      :  Data.Number.Flint.Fmpz.Poly.Instances
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Fmpz.Poly.Instances (
    FmpzPoly (..)
  , module GHC.Exts
  , hermitePolynomial
  , cyclotomicPolynomial
) where

import Test.QuickCheck

import GHC.Exts

import System.IO.Unsafe
import Control.Monad

import Foreign.Ptr
import Foreign.C.String
import Foreign.Storable
import Foreign.Marshal.Alloc (free)
import Foreign.Marshal.Array (advancePtr)

import Data.Bits

import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.Instances
import Data.Number.Flint.Fmpz.Poly
import Data.Number.Flint.Fmpz.Poly.Factor

import Data.Number.Flint.UFD

instance Show FmpzPoly where
  show :: FmpzPoly -> String
show FmpzPoly
p = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
p forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
p -> do
      forall a. String -> (CString -> IO a) -> IO a
withCString String
"x" forall a b. (a -> b) -> a -> b
$ \CString
x -> do
        CString
cs <- Ptr CFmpzPoly -> CString -> IO CString
fmpz_poly_get_str_pretty Ptr CFmpzPoly
p CString
x
        String
s <- CString -> IO String
peekCString CString
cs
        forall a. Ptr a -> IO ()
free CString
cs
        forall (m :: * -> *) a. Monad m => a -> m a
return String
s

instance Num FmpzPoly where
  * :: FmpzPoly -> FmpzPoly -> FmpzPoly
(*) = forall {a}.
(Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a)
-> FmpzPoly -> FmpzPoly -> FmpzPoly
lift2 Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()
fmpz_poly_mul
  + :: FmpzPoly -> FmpzPoly -> FmpzPoly
(+) = forall {a}.
(Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a)
-> FmpzPoly -> FmpzPoly -> FmpzPoly
lift2 Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()
fmpz_poly_add
  (-) = forall {a}.
(Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a)
-> FmpzPoly -> FmpzPoly -> FmpzPoly
lift2 Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()
fmpz_poly_sub
  abs :: FmpzPoly -> FmpzPoly
abs = forall a. HasCallStack => a
undefined
  signum :: FmpzPoly -> FmpzPoly
signum = forall a. HasCallStack => a
undefined
  fromInteger :: Integer -> FmpzPoly
fromInteger Integer
x = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    let tmp :: Fmpz
tmp = forall a. Num a => Integer -> a
fromInteger Integer
x :: Fmpz
    FmpzPoly
result <- IO FmpzPoly
newFmpzPoly
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
result forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
result -> 
      forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
tmp forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
tmp -> do
      Ptr CFmpzPoly -> Ptr CFmpz -> IO ()
fmpz_poly_set_fmpz Ptr CFmpzPoly
result Ptr CFmpz
tmp
      forall (m :: * -> *) a. Monad m => a -> m a
return Ptr CFmpzPoly
result
    forall (m :: * -> *) a. Monad m => a -> m a
return FmpzPoly
result

instance Semigroup FmpzPoly where
  <> :: FmpzPoly -> FmpzPoly -> FmpzPoly
(<>) = forall {a}.
(Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a)
-> FmpzPoly -> FmpzPoly -> FmpzPoly
lift2 Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()
fmpz_poly_compose

instance Eq FmpzPoly where
  == :: FmpzPoly -> FmpzPoly -> Bool
(==) FmpzPoly
x FmpzPoly
y = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
x ->
      forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
y -> do
        CInt
f <- Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt
fmpz_poly_equal Ptr CFmpzPoly
x Ptr CFmpzPoly
y
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ CInt
f forall a. Eq a => a -> a -> Bool
== CInt
1

instance Ord FmpzPoly where
  compare :: FmpzPoly -> FmpzPoly -> Ordering
compare = forall a. HasCallStack => a
undefined
  
instance Real FmpzPoly where
  toRational :: FmpzPoly -> Rational
toRational = forall a. HasCallStack => a
undefined

instance Enum FmpzPoly where
  toEnum :: Int -> FmpzPoly
toEnum = forall a. HasCallStack => a
undefined
  fromEnum :: FmpzPoly -> Int
fromEnum = forall a. HasCallStack => a
undefined
  
instance Integral FmpzPoly where
  toInteger :: FmpzPoly -> Integer
toInteger = forall a. HasCallStack => a
undefined
  div :: FmpzPoly -> FmpzPoly -> FmpzPoly
div FmpzPoly
x FmpzPoly
y = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    FmpzPoly
p <- IO FmpzPoly
newFmpzPoly
    FmpzPoly
q <- IO FmpzPoly
newFmpzPoly
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
x ->
      forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
y ->
        forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
q forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
q ->
          Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()
fmpz_poly_div Ptr CFmpzPoly
q Ptr CFmpzPoly
x Ptr CFmpzPoly
y
    forall (m :: * -> *) a. Monad m => a -> m a
return FmpzPoly
q
  quotRem :: FmpzPoly -> FmpzPoly -> (FmpzPoly, FmpzPoly)
quotRem FmpzPoly
x FmpzPoly
y = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    FmpzPoly
p <- IO FmpzPoly
newFmpzPoly
    FmpzPoly
q <- IO FmpzPoly
newFmpzPoly
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
x ->
      forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
y ->
        forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
p forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
p ->
          forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
q forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
q ->
            Ptr CFmpzPoly
-> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()
fmpz_poly_divrem Ptr CFmpzPoly
p Ptr CFmpzPoly
q Ptr CFmpzPoly
x Ptr CFmpzPoly
y
    forall (m :: * -> *) a. Monad m => a -> m a
return (FmpzPoly
p, FmpzPoly
q)

instance UFD FmpzPoly where
  factor :: FmpzPoly -> [(FmpzPoly, Int)]
factor FmpzPoly
x = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
x -> do
      FmpzPolyFactor
f <- IO FmpzPolyFactor
newFmpzPolyFactor
      forall {a}.
FmpzPolyFactor
-> (Ptr CFmpzPolyFactor -> IO a) -> IO (FmpzPolyFactor, a)
withFmpzPolyFactor FmpzPolyFactor
f forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPolyFactor
f -> do
        Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> IO ()
fmpz_poly_factor Ptr CFmpzPolyFactor
f Ptr CFmpzPoly
x
        CFmpzPolyFactor Ptr CFmpz
c Ptr CFmpzPoly
d Ptr CLong
e CLong
n CLong
alloc <- forall a. Storable a => Ptr a -> IO a
peek Ptr CFmpzPolyFactor
f
        Fmpz
prefactor <- IO Fmpz
newFmpz
        forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
prefactor forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
prefactor -> Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_set Ptr CFmpz
prefactor Ptr CFmpz
c 
        let pre :: (FmpzPoly, Int)
pre = (forall l. IsList l => [Item l] -> l
fromList [Fmpz
prefactor] :: FmpzPoly, Int
1)
        [(FmpzPoly, Int)]
fac <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Int
0..forall a b. (Integral a, Num b) => a -> b
fromIntegral CLong
nforall a. Num a => a -> a -> a
-Int
1] forall a b. (a -> b) -> a -> b
$ \Int
j -> do
          CLong
m <- forall a. Storable a => Ptr a -> IO a
peek (Ptr CLong
e forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
j)
          FmpzPoly
r <- IO FmpzPoly
newFmpzPoly
          forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
r forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
r -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()
fmpz_poly_set Ptr CFmpzPoly
r (Ptr CFmpzPoly
d forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
j)
          forall (m :: * -> *) a. Monad m => a -> m a
return (FmpzPoly
r, forall a b. (Integral a, Num b) => a -> b
fromIntegral CLong
m)
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if Fmpz
prefactor forall a. Eq a => a -> a -> Bool
== Fmpz
1 then [(FmpzPoly, Int)]
fac else (FmpzPoly, Int)
pre forall a. a -> [a] -> [a]
: [(FmpzPoly, Int)]
fac
        
instance Arbitrary FmpzPoly where
  arbitrary :: Gen FmpzPoly
arbitrary = do
    [Fmpz]
c <- forall a. Gen a -> Gen [a]
listOf forall a. Arbitrary a => Gen a
arbitrary
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall l. IsList l => [Item l] -> l
fromList ([Fmpz]
c forall a. [a] -> [a] -> [a]
++ [Fmpz
1])

instance IsList FmpzPoly where
  type Item FmpzPoly = Fmpz
  fromList :: [Item FmpzPoly] -> FmpzPoly
fromList [Item FmpzPoly]
c = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    FmpzPoly
p <- IO FmpzPoly
newFmpzPoly
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
p forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
p -> 
      forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
0..forall (t :: * -> *) a. Foldable t => t a -> Int
length [Item FmpzPoly]
cforall a. Num a => a -> a -> a
-Int
1] forall a b. (a -> b) -> a -> b
$ \Int
j ->
        forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz ([Item FmpzPoly]
cforall a. [a] -> Int -> a
!!Int
j) forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
a -> 
          Ptr CFmpzPoly -> CLong -> Ptr CFmpz -> IO ()
fmpz_poly_set_coeff_fmpz Ptr CFmpzPoly
p (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
j) Ptr CFmpz
a
    forall (m :: * -> *) a. Monad m => a -> m a
return FmpzPoly
p
  toList :: FmpzPoly -> [Item FmpzPoly]
toList FmpzPoly
p = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ 
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
p forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
p -> do
      CLong
d <- Ptr CFmpzPoly -> IO CLong
fmpz_poly_degree Ptr CFmpzPoly
p
      forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [CLong
0..CLong
d] forall a b. (a -> b) -> a -> b
$ \CLong
j -> do
        Fmpz
c <- IO Fmpz
newFmpz
        forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
c forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
c -> Ptr CFmpz -> Ptr CFmpzPoly -> CLong -> IO ()
fmpz_poly_get_coeff_fmpz Ptr CFmpz
c Ptr CFmpzPoly
p CLong
j
        forall (m :: * -> *) a. Monad m => a -> m a
return Fmpz
c

lift2 :: (Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a)
-> FmpzPoly -> FmpzPoly -> FmpzPoly
lift2 Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a
f FmpzPoly
x FmpzPoly
y = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
  FmpzPoly
result <- IO FmpzPoly
newFmpzPoly
  forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
result forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
result -> do
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
x -> do
      forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
y -> do
        Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a
f Ptr CFmpzPoly
result Ptr CFmpzPoly
x Ptr CFmpzPoly
y
  forall (m :: * -> *) a. Monad m => a -> m a
return FmpzPoly
result

lift1 :: (Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a) -> FmpzPoly -> FmpzPoly
lift1 Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a
f FmpzPoly
x = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
  FmpzPoly
result <- IO FmpzPoly
newFmpzPoly
  forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
result forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
result ->
    forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
x ->
    Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO a
f Ptr CFmpzPoly
result Ptr CFmpzPoly
x
  forall (m :: * -> *) a. Monad m => a -> m a
return FmpzPoly
result

-- special functions -----------------------------------------------------------

cyclotomicPolynomial :: CULong -> FmpzPoly
cyclotomicPolynomial CULong
n = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
  FmpzPoly
poly <- IO FmpzPoly
newFmpzPoly
  forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
poly forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
poly ->
    Ptr CFmpzPoly -> CULong -> IO ()
fmpz_poly_cyclotomic Ptr CFmpzPoly
poly CULong
n
  forall (m :: * -> *) a. Monad m => a -> m a
return FmpzPoly
poly
  
hermitePolynomial :: CULong -> FmpzPoly
hermitePolynomial CULong
n = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
  FmpzPoly
poly <- IO FmpzPoly
newFmpzPoly
  forall {a}. FmpzPoly -> (Ptr CFmpzPoly -> IO a) -> IO (FmpzPoly, a)
withFmpzPoly FmpzPoly
poly forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzPoly
poly ->
    Ptr CFmpzPoly -> CULong -> IO ()
fmpz_poly_hermite_h Ptr CFmpzPoly
poly CULong
n
  forall (m :: * -> *) a. Monad m => a -> m a
return FmpzPoly
poly