{-|
Module      : Math.Algebra.Hspray
Description : Multivariate polynomials on a ring.
Copyright   : (c) Stéphane Laurent, 2022-2024
License     : GPL-3
Maintainer  : laurent_step@outlook.fr

Deals with multivariate polynomials over a commutative ring. 
See README for examples.
-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}

module Math.Algebra.Hspray
  ( 
  -- * Classes

    FunctionLike (..)
  , isConstant
  , isUnivariate
  , isBivariate
  , isTrivariate
  -- * Main types

  , Exponents
  , Powers (..)
  , Spray
  , QSpray
  , QSpray'
  , Term
  -- * Basic sprays

  , lone
  , qlone
  , lone'
  , qlone'
  , monomial
  , qmonomial
  , unitSpray
  , zeroSpray
  , constantSpray
  -- * Showing a spray

  , prettySpray
  , prettySpray'
  , prettySpray''
  , prettySprayXYZ
  , prettySprayX1X2X3
  , showSpray
  , showSprayXYZ
  , showSprayXYZ'
  , showSprayX1X2X3
  , showSprayX1X2X3'
  , showNumSpray
  , showQSpray
  , showQSpray'
  , prettyNumSprayX1X2X3
  , prettyQSprayX1X2X3
  , prettyQSprayX1X2X3'
  , prettyNumSprayXYZ
  , prettyQSprayXYZ
  , prettyQSprayXYZ'
  , prettyNumSpray
  , prettyNumSpray'
  , prettyQSpray
  , prettyQSpray''
  , prettyQSpray'
  , prettyQSpray'''
  -- * Univariate polynomials and fractions of univariate polynomials

  --

  -- | The univariate polynomials and the fractions of univariate polynomials

  -- are used to defined the `OneParameterSpray` sprays, which represent 

  -- multivariate polynomials depending on a unique parameter. These sprays 

  -- lost their interest in version 0.4.0.0 (see CHANGELOG or README).

  , A (..)
  , Rational'
  , Polynomial 
  , QPolynomial 
  , RatioOfPolynomials
  , RatioOfQPolynomials
  , prettyRatioOfPolynomials
  , prettyRatioOfQPolynomials
  , constPoly
  , polyFromCoeffs
  , soleParameter
  , constQPoly
  , qpolyFromCoeffs
  , qsoleParameter
  , evalRatioOfPolynomials
  -- * One-parameter sprays

  --

  -- | The `OneParameterSpray` sprays represent multivariate polynomials with 

  -- coefficients depending on a unique parameter. These sprays lost their 

  -- interest in version 0.4.0.0 (see CHANGELOG or README). One can use the 

  -- more general `ParametricSpray` sprays instead.

  , OneParameterSpray
  , OneParameterQSpray
  , prettyOneParameterSprayX1X2X3
  , prettyOneParameterSprayXYZ
  , prettyOneParameterSpray
  , prettyOneParameterSpray'
  , prettyOneParameterQSprayX1X2X3
  , prettyOneParameterQSprayXYZ
  , prettyOneParameterQSpray
  , prettyOneParameterQSpray'
  , evalOneParameterSpray
  , substituteTheParameter
  , evalOneParameterSpray'
  , evalOneParameterSpray''
  -- * Ratios of sprays

  --

  -- | An object of type `RatioOfSprays` represents a fraction of two 

  -- multivariate polynomials.

  , RatioOfSprays (..)
  , RatioOfQSprays
  , (%:%)
  , (%//%)
  , (^/^)
  , (%/%)
  , isConstantRatioOfSprays
  , isPolynomialRatioOfSprays
  , zeroRatioOfSprays
  , zeroROS
  , unitRatioOfSprays
  , unitROS
  , constantRatioOfSprays
  , asRatioOfSprays
  , evalRatioOfSprays
  , substituteRatioOfSprays
  , fromRatioOfPolynomials
  , fromRatioOfQPolynomials
  , showRatioOfSprays
  , showRatioOfNumSprays
  , showRatioOfQSprays
  , showRatioOfSpraysXYZ
  , showRatioOfSpraysXYZ'
  , showRatioOfSpraysX1X2X3
  , showRatioOfSpraysX1X2X3'
  , prettyRatioOfQSpraysXYZ
  , prettyRatioOfQSpraysX1X2X3
  , prettyRatioOfQSprays
  , prettyRatioOfQSprays'
  , prettyRatioOfNumSpraysXYZ
  , prettyRatioOfNumSpraysX1X2X3
  , prettyRatioOfNumSprays
  , prettyRatioOfNumSprays'
  -- * Parametric sprays

  --

  -- | There are three types of parametric sprays: @OneParameterSpray@, 

  -- @SimpleParametricSpray@ and @ParametricSpray@. These are sprays of 

  -- type @Spray b@ where @b@ has the class @FunctionLike@. When we say 

  -- \"parametric spray\" in the documentation, we mean either 

  -- such a spray or more precisely a @ParametricSpray@ spray.

  , SimpleParametricSpray
  , SimpleParametricQSpray
  , ParametricSpray
  , ParametricQSpray
  , canCoerceToSimpleParametricSpray
  , asSimpleParametricSprayUnsafe
  , asSimpleParametricSpray
  , fromOneParameterSpray
  , fromOneParameterQSpray
  , parametricSprayToOneParameterSpray
  , parametricQSprayToOneParameterQSpray
  , gegenbauerPolynomial
  , jacobiPolynomial
  , numberOfParameters
  , changeParameters
  , substituteParameters
  , evalParametricSpray
  , evalParametricSpray'
  , prettyParametricQSprayABCXYZ
  , prettyParametricQSpray
  , prettyParametricNumSprayABCXYZ
  , prettyParametricNumSpray
  , prettySimpleParametricQSprayABCXYZ
  , prettySimpleParametricQSpray
  , prettySimpleParametricNumSprayABCXYZ
  , prettySimpleParametricNumSpray
  -- * Queries on a spray

  , getCoefficient
  , getConstantTerm
  , isZeroSpray
  , isConstantSpray
  , isHomogeneousSpray
  , allExponents
  , allCoefficients
  -- * Evaluation of a spray

  , evalSpray
  , substituteSpray
  , composeSpray
  , evalSpraySpray
  -- * Division of sprays

  , sprayDivision
  , sprayDivisionRemainder
  , pseudoDivision
  -- * Gröbner basis

  , groebnerBasis
  , reduceGroebnerBasis
  -- * Symmetric polynomials

  , esPolynomial
  , psPolynomial
  , isSymmetricSpray
  -- * Resultant, subresultants, and Sturm-Habicht sequence

  , resultant
  , resultant'
  , resultant1
  , subresultants
  , subresultants1
  , polynomialSubresultants
  , sturmHabichtSequence
  , principalSturmHabichtSequence
  -- * Number of real roots of a univariate spray. These functions can be very

  -- slow if the degree of the spray is not small. 

  , numberOfRealRoots
  , numberOfRealRoots'
  , numberOfRealRootsInOpenInterval
  , numberOfRealRootsInOpenInterval'
  , numberOfRealRootsInClosedInterval
  , numberOfRealRootsInClosedInterval'
  -- * Greatest common divisor

  , gcdSpray
  -- * Matrices

  , detLaplace
  , detLaplace'
  , characteristicPolynomial
  -- * Miscellaneous

  , sumOfSprays
  , productOfSprays
  , (.^)
  , (/>)
  , (/^)
  , fromList
  , toList
  , fromRationalSpray
  , isPolynomialOf
  , bombieriSpray
  , collinearSprays
  ) where
import qualified Algebra.Absolute              as AlgAbs
import qualified Algebra.Additive              as AlgAdd
import qualified Algebra.Differential          as AlgDiff
import qualified Algebra.Field                 as AlgField
import qualified Algebra.Module                as AlgMod
import qualified Algebra.RightModule           as AlgRightMod
import qualified Algebra.Ring                  as AlgRing
import qualified Algebra.ZeroTestable          as AlgZT
import qualified Data.Foldable                 as DF
import           Data.Function                  ( on )
import           Data.HashMap.Strict            ( HashMap )
import qualified Data.HashMap.Strict           as HM
import           Data.Hashable                  ( Hashable ( hashWithSalt ) )
import qualified Data.IntMap.Strict            as IM
import           Data.List                      ( sortBy
                                                , maximumBy 
                                                , (\\)
                                                , findIndices
                                                , elemIndices
                                                , nub
                                                , foldl1'
                                                , uncons
                                                )
import           Data.List.Extra                ( allSame
                                                , unsnoc 
                                                )
import           Data.Matrix                    ( Matrix 
                                                , fromLists
                                                , minorMatrix
                                                , nrows
                                                , ncols
                                                , submatrix
                                                )
import qualified Data.Matrix                   as DM
import           Data.Maybe                     ( isJust
                                                , isNothing
                                                , fromJust
                                                , fromMaybe
                                                )
import           Data.Ord                       ( comparing )
import qualified Data.Ratio                    as DR
import qualified GHC.Real                      as DR
import qualified Data.Sequence                 as S
import           Data.Sequence                  ( (><)
                                                , Seq 
                                                , dropWhileR
                                                , (|>)
                                                , index
                                                , adjust
                                                , fromFunction
                                                )
import           Data.Text                      ( Text
                                                , append
                                                , cons
                                                , intercalate
                                                , pack
                                                , snoc
                                                , unpack
                                                )
import           Data.Tuple.Extra               ( both, first )
import qualified MathObj.Matrix                as MathMatrix
import qualified MathObj.Polynomial            as MathPol
import           Number.Ratio                   ( T ( (:%) ), (%) )
import qualified Number.Ratio                  as NumberRatio
-- import qualified Algebra.PrincipalIdealDomain  as AlgPID

-- import qualified Algebra.Units  as AlgUnits

-- import qualified Algebra.IntegralDomain  as AlgID



-- Classes --------------------------------------------------------------------


-- | A spray represents a multivariate polynomial so it like a function. We 

-- introduce a class because it will be assigned to the ratios of sprays too.

class FunctionLike b where

  -- | Number of variables in a function-like object

  numberOfVariables :: b -> Int

  -- | Permutes the variables of a function-like object

  --

  -- >>> f :: Spray Rational -> Spray Rational -> Spray Rational -> Spray Rational

  -- >>> f p1 p2 p3 = p1^**^4 ^+^ (2*^p2^**^3) ^+^ (3*^p3^**^2) ^-^ (4*^unitSpray)

  -- >>> x1 = lone 1 :: Spray Rational

  -- >>> x2 = lone 2 :: Spray Rational

  -- >>> x3 = lone 3 :: Spray Rational

  -- >>> spray = f x1 x2 x3

  --

  -- prop> permuteVariables [3, 1, 2] spray == f x3 x1 x2

  permuteVariables :: 
       [Int] -- ^ permutation 

    -> b     -- ^ function-like object whose variables will be permuted

    -> b     -- ^ the function-like object with permuted variables


  -- | Swaps two variables of a function-like object

  -- 

  -- prop> swapVariables (1, 3) x == permuteVariables [3, 2, 1] x

  swapVariables :: 
       (Int, Int) -- ^ the indices of the variables to be swapped (starting at 1) 

    -> b          -- ^ function-like object whose variables will be swapped

    -> b          -- ^ the function-like object with swapped variables


  -- Whether a variable is involved in a function-like object

  --

  -- prop> involvesVariable (qlone 1 ^+^ qlone 3) 2 == False

  involvesVariable ::
       b     -- ^ function-like object

    -> Int   -- ^ index of the variable

    -> Bool 

  -- | Drops a given number of leading variables in a function-like object; 

  -- __very unsafe__, @dropVariables n x@ should /not/ be used if 

  -- @involvesVariable x i@ is @True@ for some @i@ in @1, ... n@

  --

  -- prop> dropVariables 1 (qlone 2 ^+^ qlone 3) == qlone 1 ^+^ qlone 2

  dropVariables :: 
       Int  -- ^ number of leading variables to drop

    -> b    -- ^ a function-like object

    -> b

  -- | Derivative of a function-like object

  --

  -- >>> x = lone 1 :: Spray Int

  -- >>> y = lone 2 :: Spray Int

  -- >>> spray = 2*^x ^-^ 3*^y^**^8

  -- >>> spray' = derivative 1 spray

  -- >>> putStrLn $ prettyNumSpray spray'

  -- 2

  derivative :: 
       Int -- ^ index of the variable of differentiation (starting at 1)

    -> b   -- ^ the object to be derivated

    -> b   -- ^ the derivated object


  -- | The type of the coefficients (this is @a@ for both @Spray a@ and @RatioOfSprays a@)

  type family BaseRing b

  -- | The type of the variables (this is @Spray a@ for both @Spray a@ and @RatioOfSprays a@)

  type family VariablesType b

  infixl 6 ^+^
  -- | Addition of two function-like objects

  (^+^) :: (AlgAdd.C b) => b -> b -> b
  (^+^) = b -> b -> b
forall a. C a => a -> a -> a
(AlgAdd.+)

  infixl 6 ^-^
  -- | Substraction of two function-like objects

  (^-^) :: (AlgAdd.C b) => b -> b -> b
  (^-^) = b -> b -> b
forall a. C a => a -> a -> a
(AlgAdd.-)

  infixl 7 ^*^
  -- | Multiplication of two function-like objects 

  (^*^) :: (AlgRing.C b) => b -> b -> b
  (^*^) = b -> b -> b
forall a. C a => a -> a -> a
(AlgRing.*)

  infixr 8 ^**^
  -- | Power of a function-like object

  (^**^) :: (AlgRing.C b) => b -> Int -> b
  (^**^) b
p Int
k = b
p b -> Integer -> b
forall a. C a => a -> Integer -> a
AlgRing.^ Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
k

  infixr 7 *^
  -- | Multiply a function-like object by a scalar

  (*^) :: BaseRing b -> b -> b

  infixl 6 +>
  -- | Add a function-like object to a constant 

  --

  -- prop> x +> spray == constantSpray x ^+^ spray

  (+>) :: BaseRing b -> b -> b

  infixr 6 <+
  -- | Add a constant to a function-like object

  --

  -- prop> object <+ x == x +> object

  (<+) :: b -> BaseRing b -> b
  (<+) = (BaseRing b -> b -> b) -> b -> BaseRing b -> b
forall a b c. (a -> b -> c) -> b -> a -> c
flip BaseRing b -> b -> b
forall b. FunctionLike b => BaseRing b -> b -> b
(+>) 

  -- | Evaluation (replacing the variables with some values) of a 

  -- function-like object

  --

  -- >>> x = lone 1 :: Spray Int

  -- >>> y = lone 2 :: Spray Int

  -- >>> spray = 2*^x^**^2 ^-^ 3*^y

  -- >>> evaluate spray [2, 1]

  -- 5

  evaluate :: 
    b               -- ^ function-like object to be evaluated, e.g. a spray

    -> [BaseRing b] -- ^ list of values to be substituted to its variables

    -> BaseRing b

  -- | Flipped version of @evaluate@

  --

  -- prop> evaluateAt [2, 1] spray == evaluate spray [2, 1]

  evaluateAt :: [BaseRing b] -> b -> BaseRing b
  evaluateAt = (b -> [BaseRing b] -> BaseRing b)
-> [BaseRing b] -> b -> BaseRing b
forall a b c. (a -> b -> c) -> b -> a -> c
flip b -> [BaseRing b] -> BaseRing b
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate

  -- | Partial evaluation of a function-like object (replace some variables 

  -- with some values)

  --

  -- >>> x1 = lone 1 :: Spray Int

  -- >>> x2 = lone 2 :: Spray Int

  -- >>> x3 = lone 3 :: Spray Int

  -- >>> spray = x1^**^2 ^-^ x2 ^+^ x3 ^-^ unitSpray

  -- >>> spray' = substitute [Just 2, Nothing, Just 3] spray

  -- >>> putStrLn $ prettyNumSprayX1X2X3 "x" spray'

  -- -x2 + 6 

  substitute :: 
    [Maybe (BaseRing b)] -- ^ @Just x@ to replace the variable with @x@, @Nothing@ for no replacement

    -> b                 -- ^ function-like object to be partially evaluated

    -> b

  -- | Polynomial change of variables of a function-like object

  --

  -- >>> x = lone 1 :: Spray Int

  -- >>> y = lone 2 :: Spray Int

  -- >>> spray = x ^*^ y

  -- >>> spray' = changeVariables spray [x ^+^ y, x ^-^ y]

  -- >>> putStrLn $ prettyNumSpray' spray'

  -- X^2 - Y^2

  changeVariables :: 
       b                 -- ^ function-like object such as a spray

    -> [VariablesType b] -- ^ list of new variables

    -> b

-- | Whether a function-like object has a constant value

isConstant :: FunctionLike b => b -> Bool
isConstant :: forall b. FunctionLike b => b -> Bool
isConstant b
f = b -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables b
f Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0

-- | Whether a function-like object represents an univariate function; it is considered 

-- that it is univariate if it is constant

isUnivariate :: FunctionLike b => b -> Bool
isUnivariate :: forall b. FunctionLike b => b -> Bool
isUnivariate b
f = b -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables b
f Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1

-- | Whether a function-like object represents a bivariate function; it is considered 

-- that it is bivariate if it is univariate

isBivariate :: FunctionLike b => b -> Bool
isBivariate :: forall b. FunctionLike b => b -> Bool
isBivariate b
f = b -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables b
f Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
2

-- | Whether a function-like object represents a trivariate function; it is considered 

-- that it is trivariate if it is bivariate

isTrivariate :: FunctionLike b => b -> Bool
isTrivariate :: forall b. FunctionLike b => b -> Bool
isTrivariate b
f = b -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables b
f Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
3


-- Additional operations to 'numeric-prelude'


infixr 7 />
-- | Divides by a scalar in a module over a field

(/>) :: (AlgField.C k, AlgMod.C k a) => a -> k -> a
a
x /> :: forall k a. (C k, C k a) => a -> k -> a
/> k
lambda = k -> k
forall a. C a => a -> a
AlgField.recip k
lambda k -> a -> a
forall a v. C a v => a -> v -> v
AlgMod.*> a
x

infixr 7 .^
-- | Scale by an integer (I do not find this operation in __numeric-prelude__)

--

-- prop> 3 .^ x == x Algebra.Additive.+ x Algebra.Additive.+ x

(.^) :: (AlgAdd.C a, Eq a) => Int -> a -> a
Int
k .^ :: forall a. (C a, Eq a) => Int -> a -> a
.^ a
x = if Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0
  then (a -> a -> a) -> a -> a -> Int -> a
forall {t} {t}. Integral t => (t -> t -> t) -> t -> t -> t -> t
powerOperation a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+) a
forall a. C a => a
AlgAdd.zero a
x Int
k
  else Int -> a -> a
forall a. (C a, Eq a) => Int -> a -> a
(.^) (-Int
k) (a -> a
forall a. C a => a -> a
AlgAdd.negate a
x)
  where 
    powerOperation :: (t -> t -> t) -> t -> t -> t -> t
powerOperation t -> t -> t
op =
      let go :: t -> t -> t -> t
go t
acc t
_ t
0 = t
acc
          go t
acc t
a t
n = t -> t -> t -> t
go (if t -> Bool
forall a. Integral a => a -> Bool
even t
n then t
acc else t -> t -> t
op t
acc t
a) (t -> t -> t
op t
a t
a) (t -> t -> t
forall a. Integral a => a -> a -> a
div t
n t
2)
      in t -> t -> t -> t
go


-- Univariate polynomials and ratios of univariate polynomials ----------------


-- | The new type @A a@ is used to attribute some instances to the 

-- type @Polynomial a@; it is needed to avoid orphan instances.

newtype A a = A a 
  deriving
    (A a -> A a -> Bool
(A a -> A a -> Bool) -> (A a -> A a -> Bool) -> Eq (A a)
forall a. Eq a => A a -> A a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => A a -> A a -> Bool
== :: A a -> A a -> Bool
$c/= :: forall a. Eq a => A a -> A a -> Bool
/= :: A a -> A a -> Bool
Eq, Int -> A a -> ShowS
[A a] -> ShowS
A a -> String
(Int -> A a -> ShowS)
-> (A a -> String) -> ([A a] -> ShowS) -> Show (A a)
forall a. Show a => Int -> A a -> ShowS
forall a. Show a => [A a] -> ShowS
forall a. Show a => A a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> A a -> ShowS
showsPrec :: Int -> A a -> ShowS
$cshow :: forall a. Show a => A a -> String
show :: A a -> String
$cshowList :: forall a. Show a => [A a] -> ShowS
showList :: [A a] -> ShowS
Show, A a
A a -> A a
A a -> A a -> A a
A a
-> (A a -> A a -> A a)
-> (A a -> A a -> A a)
-> (A a -> A a)
-> C (A a)
forall a. a -> (a -> a -> a) -> (a -> a -> a) -> (a -> a) -> C a
forall a. C a => A a
forall a. C a => A a -> A a
forall a. C a => A a -> A a -> A a
$czero :: forall a. C a => A a
zero :: A a
$c+ :: forall a. C a => A a -> A a -> A a
+ :: A a -> A a -> A a
$c- :: forall a. C a => A a -> A a -> A a
- :: A a -> A a -> A a
$cnegate :: forall a. C a => A a -> A a
negate :: A a -> A a
AlgAdd.C, C (A a)
A a
Integer -> A a
C (A a) =>
(A a -> A a -> A a)
-> A a -> (Integer -> A a) -> (A a -> Integer -> A a) -> C (A a)
A a -> Integer -> A a
A a -> A a -> A a
forall a.
C a =>
(a -> a -> a) -> a -> (Integer -> a) -> (a -> Integer -> a) -> C a
forall a. C a => C (A a)
forall a. C a => A a
forall a. C a => Integer -> A a
forall a. C a => A a -> Integer -> A a
forall a. C a => A a -> A a -> A a
$c* :: forall a. C a => A a -> A a -> A a
* :: A a -> A a -> A a
$cone :: forall a. C a => A a
one :: A a
$cfromInteger :: forall a. C a => Integer -> A a
fromInteger :: Integer -> A a
$c^ :: forall a. C a => A a -> Integer -> A a
^ :: A a -> Integer -> A a
AlgRing.C, C (A a)
C (A a) =>
(A a -> A a -> A a)
-> (A a -> A a)
-> (Rational' -> A a)
-> (A a -> Integer -> A a)
-> C (A a)
Rational' -> A a
A a -> A a
A a -> Integer -> A a
A a -> A a -> A a
forall a.
C a =>
(a -> a -> a)
-> (a -> a) -> (Rational' -> a) -> (a -> Integer -> a) -> C a
forall a. C a => C (A a)
forall a. C a => Rational' -> A a
forall a. C a => A a -> A a
forall a. C a => A a -> Integer -> A a
forall a. C a => A a -> A a -> A a
$c/ :: forall a. C a => A a -> A a -> A a
/ :: A a -> A a -> A a
$crecip :: forall a. C a => A a -> A a
recip :: A a -> A a
$cfromRational' :: forall a. C a => Rational' -> A a
fromRational' :: Rational' -> A a
$c^- :: forall a. C a => A a -> Integer -> A a
^- :: A a -> Integer -> A a
AlgField.C)

-- | The type @Rational'@ is used to introduce the univariate polynomials 

-- with rational coefficients (`QPolynomial`). It is similar to the well-known 

-- type @Rational@ (actually these two types are the same but @Rational'@ has 

-- more instances and we need them for the univariate polynomials).

type Rational' = NumberRatio.Rational

-- | The type @Polynomial a@ is used to represent univariate polynomials.

type Polynomial a         = MathPol.T (A a)
type QPolynomial          = Polynomial Rational'

-- The type @RatioOfPolynomials a@ is used to represent fractions of 

-- univariate polynomials.

type RatioOfPolynomials a = NumberRatio.T (Polynomial a)
type RatioOfQPolynomials  = RatioOfPolynomials Rational'

instance (Eq a, AlgField.C a) => FunctionLike (Polynomial a) where
  --

  numberOfVariables :: Polynomial a -> Int
  numberOfVariables :: Polynomial a -> Int
numberOfVariables Polynomial a
p = case Polynomial a -> Maybe Int
forall a. C a => T a -> Maybe Int
MathPol.degree Polynomial a
p of
    Maybe Int
Nothing -> Int
0
    Just Int
d  -> Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
1 Int
d
  --

  type BaseRing (Polynomial a) = a
  --

  type VariablesType (Polynomial a) = Polynomial a
  --

  (*^) :: a -> Polynomial a -> Polynomial a
  *^ :: a -> Polynomial a -> Polynomial a
(*^) a
lambda Polynomial a
pol = a -> Polynomial a
forall a. a -> Polynomial a
constPoly a
lambda Polynomial a -> Polynomial a -> Polynomial a
forall a. C a => a -> a -> a
AlgRing.* Polynomial a
pol
  --

  (+>) :: a -> Polynomial a -> Polynomial a
  +> :: a -> Polynomial a -> Polynomial a
(+>) a
x Polynomial a
pol = a -> Polynomial a
forall a. a -> Polynomial a
constPoly a
x Polynomial a -> Polynomial a -> Polynomial a
forall a. C a => a -> a -> a
AlgAdd.+ Polynomial a
pol
  --

  evaluate :: Polynomial a -> [a] -> a
  evaluate :: Polynomial a -> [a] -> a
evaluate Polynomial a
p [a]
xs = A a -> a
forall {a}. A a -> a
get (Polynomial a -> A a -> A a
forall a. C a => T a -> a -> a
MathPol.evaluate Polynomial a
p (a -> A a
forall a. a -> A a
A ([a]
xs [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)))
    where
      get :: A a -> a
get (A a
x) = a
x
  --

  substitute :: [Maybe a] -> Polynomial a -> Polynomial a
  substitute :: [Maybe a] -> Polynomial a -> Polynomial a
substitute [Maybe a]
x Polynomial a
p = 
    if Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing ([Maybe a]
x [Maybe a] -> Int -> Maybe a
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)
      then Polynomial a
p
      else a -> Polynomial a
forall a. a -> Polynomial a
constPoly (Polynomial a
-> [BaseRing (Polynomial a)] -> BaseRing (Polynomial a)
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate Polynomial a
p [Maybe (BaseRing (Polynomial a)) -> BaseRing (Polynomial a)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (BaseRing (Polynomial a)) -> BaseRing (Polynomial a))
-> Maybe (BaseRing (Polynomial a)) -> BaseRing (Polynomial a)
forall a b. (a -> b) -> a -> b
$ [Maybe a]
x [Maybe a] -> Int -> Maybe a
forall a. HasCallStack => [a] -> Int -> a
!! Int
0])
  -- 

  permuteVariables :: [Int] -> Polynomial a -> Polynomial a
  permuteVariables :: [Int] -> Polynomial a -> Polynomial a
permuteVariables = String -> [Int] -> Polynomial a -> Polynomial a
forall a. HasCallStack => String -> a
error String
"permuteVariables: there is only one variable."
  -- 

  swapVariables :: (Int, Int) -> Polynomial a -> Polynomial a
  swapVariables :: (Int, Int) -> Polynomial a -> Polynomial a
swapVariables = String -> (Int, Int) -> Polynomial a -> Polynomial a
forall a. HasCallStack => String -> a
error String
"swapVariables: there is only one variable."
  --

  involvesVariable :: Polynomial a -> Int -> Bool
  involvesVariable :: Polynomial a -> Int -> Bool
involvesVariable = String -> Polynomial a -> Int -> Bool
forall a. HasCallStack => String -> a
error String
"involvesVariable: not available for `Polynomial`"
  --

  dropVariables :: Int -> Polynomial a -> Polynomial a
  dropVariables :: Int -> Polynomial a -> Polynomial a
dropVariables = String -> Int -> Polynomial a -> Polynomial a
forall a. HasCallStack => String -> a
error String
"dropVariables: not available for `Polynomial`"
  --

  derivative :: Int -> Polynomial a -> Polynomial a
  derivative :: Int -> Polynomial a -> Polynomial a
derivative Int
i Polynomial a
p = 
    if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 
      then Polynomial a -> Polynomial a
forall a. C a => a -> a
AlgDiff.differentiate Polynomial a
p
      else a -> Polynomial a
forall a. a -> Polynomial a
constPoly a
forall a. C a => a
AlgAdd.zero
  --

  changeVariables :: Polynomial a -> [Polynomial a] -> Polynomial a
  changeVariables :: Polynomial a -> [Polynomial a] -> Polynomial a
changeVariables Polynomial a
p [Polynomial a]
ps = Polynomial a -> Polynomial a -> Polynomial a
forall a. C a => T a -> T a -> T a
MathPol.compose Polynomial a
p ([Polynomial a]
ps [Polynomial a] -> Int -> Polynomial a
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)

instance (Eq a, AlgField.C a) => FunctionLike (RatioOfPolynomials a) where
  numberOfVariables :: RatioOfPolynomials a -> Int
  numberOfVariables :: RatioOfPolynomials a -> Int
numberOfVariables (Polynomial a
p :% Polynomial a
q) = 
    Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Polynomial a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Polynomial a
p) (Polynomial a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Polynomial a
q)
  --

  type BaseRing (RatioOfPolynomials a) = a
  --

  type VariablesType (RatioOfPolynomials a) = Polynomial a
  --

  (*^) :: a -> RatioOfPolynomials a -> RatioOfPolynomials a
  *^ :: a -> RatioOfPolynomials a -> RatioOfPolynomials a
(*^) a
lambda RatioOfPolynomials a
rOP = a -> A a
forall a. a -> A a
A a
lambda A a -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfPolynomials a
rOP
  --

  (+>) :: a -> RatioOfPolynomials a -> RatioOfPolynomials a
  +> :: a -> RatioOfPolynomials a -> RatioOfPolynomials a
(+>) a
x RatioOfPolynomials a
rOP =  Polynomial a -> RatioOfPolynomials a
forall a. C a => a -> T a
NumberRatio.fromValue (a -> Polynomial a
forall a. a -> Polynomial a
constPoly a
x) RatioOfPolynomials a
-> RatioOfPolynomials a -> RatioOfPolynomials a
forall a. C a => a -> a -> a
AlgAdd.+ RatioOfPolynomials a
rOP
  --

  evaluate :: RatioOfPolynomials a -> [a] -> a
  evaluate :: RatioOfPolynomials a -> [a] -> a
evaluate RatioOfPolynomials a
r [a]
xs = Polynomial a
-> [BaseRing (Polynomial a)] -> BaseRing (Polynomial a)
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate (RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
r) [a]
[BaseRing (Polynomial a)]
xs a -> a -> a
forall a. C a => a -> a -> a
AlgField./ 
    Polynomial a
-> [BaseRing (Polynomial a)] -> BaseRing (Polynomial a)
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate (RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
r) [a]
[BaseRing (Polynomial a)]
xs
  --

  substitute :: [Maybe a] -> RatioOfPolynomials a -> RatioOfPolynomials a
  substitute :: [Maybe a] -> RatioOfPolynomials a -> RatioOfPolynomials a
substitute [Maybe a]
x RatioOfPolynomials a
r = 
    if Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing ([Maybe a]
x [Maybe a] -> Int -> Maybe a
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)
      then RatioOfPolynomials a
r
      else [Maybe (BaseRing (Polynomial a))] -> Polynomial a -> Polynomial a
forall b. FunctionLike b => [Maybe (BaseRing b)] -> b -> b
substitute [Maybe a]
[Maybe (BaseRing (Polynomial a))]
x (RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
r) Polynomial a -> Polynomial a -> RatioOfPolynomials a
forall a. C a => a -> a -> T a
%
        [Maybe (BaseRing (Polynomial a))] -> Polynomial a -> Polynomial a
forall b. FunctionLike b => [Maybe (BaseRing b)] -> b -> b
substitute [Maybe a]
[Maybe (BaseRing (Polynomial a))]
x (RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
r)
  -- 

  permuteVariables :: [Int] -> RatioOfPolynomials a -> RatioOfPolynomials a
  permuteVariables :: [Int] -> RatioOfPolynomials a -> RatioOfPolynomials a
permuteVariables = String -> [Int] -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a. HasCallStack => String -> a
error String
"permuteVariables: there is only one variable."
  -- 

  swapVariables :: (Int, Int) -> RatioOfPolynomials a -> RatioOfPolynomials a
  swapVariables :: (Int, Int) -> RatioOfPolynomials a -> RatioOfPolynomials a
swapVariables = String
-> (Int, Int) -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a. HasCallStack => String -> a
error String
"swapVariables: there is only one variable."
  --

  involvesVariable :: RatioOfPolynomials a -> Int -> Bool
  involvesVariable :: RatioOfPolynomials a -> Int -> Bool
involvesVariable = String -> RatioOfPolynomials a -> Int -> Bool
forall a. HasCallStack => String -> a
error String
"involvesVariable: not available for `RatioOfPolynomials`"
  --

  dropVariables :: Int -> RatioOfPolynomials a -> RatioOfPolynomials a
  dropVariables :: Int -> RatioOfPolynomials a -> RatioOfPolynomials a
dropVariables = String -> Int -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a. HasCallStack => String -> a
error String
"dropVariables: not available for `RatioOfPolynomials`"
  --

  derivative :: Int -> RatioOfPolynomials a -> RatioOfPolynomials a
  derivative :: Int -> RatioOfPolynomials a -> RatioOfPolynomials a
derivative Int
i RatioOfPolynomials a
r = 
    if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 
      then 
        (Polynomial a
p' Polynomial a -> Polynomial a -> Polynomial a
forall a. C a => a -> a -> a
AlgRing.* Polynomial a
q Polynomial a -> Polynomial a -> Polynomial a
forall a. C a => a -> a -> a
AlgAdd.- Polynomial a
p Polynomial a -> Polynomial a -> Polynomial a
forall a. C a => a -> a -> a
AlgRing.* Polynomial a
q') Polynomial a -> Polynomial a -> RatioOfPolynomials a
forall a. C a => a -> a -> T a
% Polynomial a
q Polynomial a -> Integer -> Polynomial a
forall a. C a => a -> Integer -> a
AlgRing.^ Integer
2
      else a -> Polynomial a
forall a. a -> Polynomial a
constPoly a
forall a. C a => a
AlgAdd.zero Polynomial a -> Polynomial a -> RatioOfPolynomials a
forall a. a -> a -> T a
:% a -> Polynomial a
forall a. a -> Polynomial a
constPoly a
forall a. C a => a
AlgRing.one
        where 
          p :: Polynomial a
p = RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
r
          q :: Polynomial a
q = RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
r
          p' :: Polynomial a
p' = Polynomial a -> Polynomial a
forall a. C a => a -> a
AlgDiff.differentiate Polynomial a
p
          q' :: Polynomial a
q' = Polynomial a -> Polynomial a
forall a. C a => a -> a
AlgDiff.differentiate Polynomial a
q
  --

  changeVariables :: 
    RatioOfPolynomials a -> [Polynomial a] -> RatioOfPolynomials a
  changeVariables :: RatioOfPolynomials a -> [Polynomial a] -> RatioOfPolynomials a
changeVariables RatioOfPolynomials a
r [Polynomial a]
ps = Polynomial a -> [VariablesType (Polynomial a)] -> Polynomial a
forall b. FunctionLike b => b -> [VariablesType b] -> b
changeVariables (RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
r) [Polynomial a]
[VariablesType (Polynomial a)]
ps Polynomial a -> Polynomial a -> RatioOfPolynomials a
forall a. C a => a -> a -> T a
%
    Polynomial a -> [VariablesType (Polynomial a)] -> Polynomial a
forall b. FunctionLike b => b -> [VariablesType b] -> b
changeVariables (RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
r) [Polynomial a]
[VariablesType (Polynomial a)]
ps 

instance (Eq a, AlgField.C a) => AlgZT.C (A a) where
  isZero :: A a -> Bool
  isZero :: A a -> Bool
isZero (A a
r) = a
r a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero

instance (Eq a, AlgField.C a) => AlgMod.C (A a) (RatioOfPolynomials a) where
  (*>) :: A a -> RatioOfPolynomials a -> RatioOfPolynomials a
  A a
lambda *> :: A a -> RatioOfPolynomials a -> RatioOfPolynomials a
*> RatioOfPolynomials a
rop = T (A a) -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a. C a => a -> T a -> T a
NumberRatio.scale (A a -> T (A a)
forall a. a -> T a
MathPol.const A a
lambda) RatioOfPolynomials a
rop 

instance (Eq a, AlgField.C a) => AlgRightMod.C (A a) (RatioOfPolynomials a) 
  where
  (<*) :: RatioOfPolynomials a -> A a -> RatioOfPolynomials a
  RatioOfPolynomials a
rop <* :: RatioOfPolynomials a -> A a -> RatioOfPolynomials a
<* A a
lambda = A a
lambda A a -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfPolynomials a
rop 

instance (Eq a, AlgField.C a) => AlgMod.C a (RatioOfPolynomials a) where
  (*>) :: a -> RatioOfPolynomials a -> RatioOfPolynomials a
  a
lambda *> :: a -> RatioOfPolynomials a -> RatioOfPolynomials a
*> RatioOfPolynomials a
rop = a -> A a
forall a. a -> A a
A a
lambda A a -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfPolynomials a
rop 

instance (Eq a, AlgField.C a) => AlgRightMod.C a (RatioOfPolynomials a) where
  (<*) :: RatioOfPolynomials a -> a -> RatioOfPolynomials a
  RatioOfPolynomials a
rop <* :: RatioOfPolynomials a -> a -> RatioOfPolynomials a
<* a
lambda = a
lambda a -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfPolynomials a
rop 

instance (Eq a, AlgField.C a) 
          => AlgMod.C (Polynomial a) (RatioOfPolynomials a) 
  where
  (*>) :: Polynomial a -> RatioOfPolynomials a -> RatioOfPolynomials a
  Polynomial a
p *> :: Polynomial a -> RatioOfPolynomials a -> RatioOfPolynomials a
*> RatioOfPolynomials a
r = Polynomial a -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a. C a => a -> T a -> T a
NumberRatio.scale Polynomial a
p RatioOfPolynomials a
r 

instance (Eq a, AlgField.C a) 
          => AlgRightMod.C (Polynomial a) (RatioOfPolynomials a) 
  where
  (<*) :: RatioOfPolynomials a -> Polynomial a -> RatioOfPolynomials a
  RatioOfPolynomials a
r <* :: RatioOfPolynomials a -> Polynomial a -> RatioOfPolynomials a
<* Polynomial a
p = Polynomial a
p Polynomial a -> RatioOfPolynomials a -> RatioOfPolynomials a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfPolynomials a
r 

-- | Constant univariate polynomial

constPoly :: a -> Polynomial a
constPoly :: forall a. a -> Polynomial a
constPoly a
x = A a -> T (A a)
forall a. a -> T a
MathPol.const (a -> A a
forall a. a -> A a
A a
x)

-- | Univariate polynomial from its coefficients (ordered by increasing degrees)

polyFromCoeffs :: [a] -> Polynomial a
polyFromCoeffs :: forall a. [a] -> Polynomial a
polyFromCoeffs [a]
as = [A a] -> T (A a)
forall a. [a] -> T a
MathPol.fromCoeffs ((a -> A a) -> [a] -> [A a]
forall a b. (a -> b) -> [a] -> [b]
map a -> A a
forall a. a -> A a
A [a]
as)

-- | The variable of a univariate polynomial; it is called \"soleParameter\" because 

-- this it represents the parameter of a `OneParameterSpray` spray

soleParameter :: AlgRing.C a => Polynomial a
soleParameter :: forall a. C a => Polynomial a
soleParameter = [a] -> Polynomial a
forall a. [a] -> Polynomial a
polyFromCoeffs [a
forall a. C a => a
AlgAdd.zero, a
forall a. C a => a
AlgRing.one] 

-- | Constant rational univariate polynomial

-- 

-- >>> import Number.Ratio ( (%) )

-- >>> constQPoly (2 % 3)

--

-- prop> constQPoly (2 % 3) == qpolyFromCoeffs [2 % 3]

constQPoly :: Rational' -> QPolynomial
constQPoly :: Rational' -> Polynomial Rational'
constQPoly = Rational' -> Polynomial Rational'
forall a. a -> Polynomial a
constPoly

-- | Rational univariate polynomial from coefficients

-- 

-- >>> import Number.Ratio ( (%) )

-- >>> qpolyFromCoeffs [2 % 3, 5, 7 % 4]

qpolyFromCoeffs :: [Rational'] -> QPolynomial
qpolyFromCoeffs :: [Rational'] -> Polynomial Rational'
qpolyFromCoeffs = [Rational'] -> Polynomial Rational'
forall a. [a] -> Polynomial a
polyFromCoeffs

-- | The variable of a univariate rational polynomial; it is called \"qsoleParameter\" 

-- because it represents the parameter of a `OneParameterQSpray` spray 

--

-- prop> qsoleParameter == qpolyFromCoeffs [0, 1] 

qsoleParameter :: QPolynomial
qsoleParameter :: Polynomial Rational'
qsoleParameter = [Rational'] -> Polynomial Rational'
qpolyFromCoeffs [Rational'
0, Rational'
1] 

{- 
-- show a ratio, helper function
showQ :: (Eq a, Num a, Show a) => NumberRatio.T a -> String
showQ q = if d == 1 
  then show n 
  else show n ++ "/" ++ show d
  where
    n = NumberRatio.numerator q
    d = NumberRatio.denominator q 
 -}

-- | identify a `Polynomial a` to a `Spray a`, in order to apply the show spray 

-- functions to the univariate polynomials

polynomialToSpray :: forall a. (Eq a, AlgRing.C a) => Polynomial a -> Spray a
polynomialToSpray :: forall a. (Eq a, C a) => Polynomial a -> Spray a
polynomialToSpray Polynomial a
pol = [Spray a] -> Spray a
forall a. (Eq a, C a) => [Spray a] -> Spray a
sumOfSprays [Spray a]
terms
  where
    coeffs :: [A a]
coeffs  = Polynomial a -> [A a]
forall a. T a -> [a]
MathPol.coeffs Polynomial a
pol
    indices :: [Int]
indices = (A a -> Bool) -> [A a] -> [Int]
forall a. (a -> Bool) -> [a] -> [Int]
findIndices (A a -> A a -> Bool
forall a. Eq a => a -> a -> Bool
/= a -> A a
forall a. a -> A a
A a
forall a. C a => a
AlgAdd.zero) [A a]
coeffs
    get :: A a -> a
    get :: A a -> a
get (A a
x) = a
x
    terms :: [Spray a]
terms = [A a -> a
get ([A a]
coeffs [A a] -> Int -> A a
forall a. HasCallStack => [a] -> Int -> a
!! Int
i) BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Int -> Int -> Spray a
forall a. C a => Int -> Int -> Spray a
lone' Int
1 Int
i | Int
i <- [Int]
indices]

qPolynomialToQSpray :: QPolynomial -> QSpray
qPolynomialToQSpray :: Polynomial Rational' -> Spray Rational
qPolynomialToQSpray Polynomial Rational'
pol = [Spray Rational] -> Spray Rational
forall a. (Eq a, C a) => [Spray a] -> Spray a
sumOfSprays [Spray Rational]
terms
  where
    coeffs :: [A Rational']
coeffs  = Polynomial Rational' -> [A Rational']
forall a. T a -> [a]
MathPol.coeffs Polynomial Rational'
pol
    indices :: [Int]
indices = (A Rational' -> Bool) -> [A Rational'] -> [Int]
forall a. (a -> Bool) -> [a] -> [Int]
findIndices (A Rational' -> A Rational' -> Bool
forall a. Eq a => a -> a -> Bool
/= Rational' -> A Rational'
forall a. a -> A a
A Rational'
0) [A Rational']
coeffs
    get :: A Rational' -> Rational
    get :: A Rational' -> Rational
get (A Rational'
x) = Rational' -> Integer
forall a. T a -> a
NumberRatio.numerator Rational'
x Integer -> Integer -> Rational
forall a. a -> a -> Ratio a
DR.:% Rational' -> Integer
forall a. T a -> a
NumberRatio.denominator Rational'
x
    terms :: [Spray Rational]
terms = [A Rational' -> Rational
get ([A Rational']
coeffs [A Rational'] -> Int -> A Rational'
forall a. HasCallStack => [a] -> Int -> a
!! Int
i) BaseRing (Spray Rational) -> Spray Rational -> Spray Rational
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Int -> Int -> Spray Rational
qlone' Int
1 Int
i | Int
i <- [Int]
indices]

-- helper function; it encloses a string between two given delimiters

bracify :: (String, String) -> String -> String
bracify :: (String, String) -> ShowS
bracify (String
lbrace, String
rbrace) String
x = String
lbrace String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
rbrace 

-- | helper function for prettyRatioOfPolynomials (and prettyOneParameterSpray)

showRatioOfPolynomials :: forall a. (Eq a, AlgField.C a) 
                  => (Spray a -> String) -> RatioOfPolynomials a -> String
showRatioOfPolynomials :: forall a.
(Eq a, C a) =>
(Spray a -> String) -> RatioOfPolynomials a -> String
showRatioOfPolynomials Spray a -> String
sprayShower RatioOfPolynomials a
polysRatio = 
  String
numeratorString String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
denominatorString
  where
    numerator :: Polynomial a
numerator         = RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
polysRatio
    denominator :: Polynomial a
denominator       = RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
polysRatio
    brackets :: Bool
brackets          = Polynomial a
denominator Polynomial a -> Polynomial a -> Bool
forall a. Eq a => a -> a -> Bool
/= A a -> Polynomial a
forall a. a -> T a
MathPol.const (a -> A a
forall a. a -> A a
A a
forall a. C a => a
AlgRing.one)
    enclose :: ShowS
enclose = (String, String) -> ShowS
bracify (String
"[ ", String
" ]")
    numeratorString :: String
numeratorString   = if Bool
brackets
      then ShowS
enclose (Spray a -> String
sprayShower (Polynomial a -> Spray a
forall a. (Eq a, C a) => Polynomial a -> Spray a
polynomialToSpray Polynomial a
numerator))
      else Spray a -> String
sprayShower (Polynomial a -> Spray a
forall a. (Eq a, C a) => Polynomial a -> Spray a
polynomialToSpray Polynomial a
numerator)
    denominatorString :: String
denominatorString = if Bool -> Bool
not Bool
brackets
      then String
""
      else String
" %//% " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
enclose (Spray a -> String
sprayShower (Polynomial a -> Spray a
forall a. (Eq a, C a) => Polynomial a -> Spray a
polynomialToSpray Polynomial a
denominator))

-- | Pretty form of a ratio of univariate polynomials with rational coefficients

prettyRatioOfQPolynomials ::
     String               -- ^ a string to denote the variable, e.g. @\"a\"@ 

  -> RatioOfQPolynomials 
  -> String 
prettyRatioOfQPolynomials :: String -> RatioOfQPolynomials -> String
prettyRatioOfQPolynomials String
var = (Spray Rational' -> String) -> RatioOfQPolynomials -> String
forall a.
(Eq a, C a) =>
(Spray a -> String) -> RatioOfPolynomials a -> String
showRatioOfPolynomials ([String] -> Spray Rational' -> String
prettyQSprayXYZ' [String
var])

-- | helper function for prettyRatioOfPolynomials (and prettyOneParameterSpray)

showQpol :: forall a. (Eq a, AlgField.C a) 
         => Polynomial a -> String -> (a -> String) -> Bool -> String
showQpol :: forall a.
(Eq a, C a) =>
Polynomial a -> String -> (a -> String) -> Bool -> String
showQpol Polynomial a
pol String
variable a -> String
showCoeff Bool
brackets = if Bool
brackets 
  then String
"[ " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
polyString String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" ]"
  else String
polyString
  where
    showCoeff' :: Int -> A a -> String
    showCoeff' :: Int -> A a -> String
showCoeff' Int
i (A a
coeff) = case Int
i of 
      Int
0 -> ((String, String) -> ShowS
bracify (String
"(", String
")") ShowS -> (a -> String) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
showCoeff) a
coeff
      Int
_ -> if a
coeff a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgRing.one 
        then String
"" 
        else ((String, String) -> ShowS
bracify (String
"(", String
")") ShowS -> (a -> String) -> a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
showCoeff) a
coeff
    coeffs :: [A a]
coeffs   = Polynomial a -> [A a]
forall a. T a -> [a]
MathPol.coeffs Polynomial a
pol
    nonzeros :: [Int]
nonzeros = (A a -> Bool) -> [A a] -> [Int]
forall a. (a -> Bool) -> [a] -> [Int]
findIndices (A a -> A a -> Bool
forall a. Eq a => a -> a -> Bool
/= a -> A a
forall a. a -> A a
A a
forall a. C a => a
AlgAdd.zero) [A a]
coeffs
    terms :: [Text]
terms    = (Int -> Text) -> [Int] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Text
pack (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
showTerm) [Int]
nonzeros
      where
        showTerm :: Int -> String
showTerm Int
i = case Int
i of 
          Int
0 -> Int -> A a -> String
showCoeff' Int
0 ([A a]
coeffs [A a] -> Int -> A a
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)
          Int
1 -> Int -> A a -> String
showCoeff' Int
1 ([A a]
coeffs [A a] -> Int -> A a
forall a. HasCallStack => [a] -> Int -> a
!! Int
1) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
variable
          Int
_ -> Int -> A a -> String
showCoeff' Int
i ([A a]
coeffs [A a] -> Int -> A a
forall a. HasCallStack => [a] -> Int -> a
!! Int
i) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
variable String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"^" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i
    polyString :: String
polyString = Text -> String
unpack (Text -> [Text] -> Text
intercalate (String -> Text
pack String
" + ") [Text]
terms)

-- | helper function for prettyRatioOfPolynomials (and prettyOneParameterSpray)

showQpolysRatio :: forall a. (Eq a, AlgField.C a) 
                   => String -> (a -> String) -> RatioOfPolynomials a -> String
showQpolysRatio :: forall a.
(Eq a, C a) =>
String -> (a -> String) -> RatioOfPolynomials a -> String
showQpolysRatio String
var a -> String
showCoeff RatioOfPolynomials a
polysRatio = String
numeratorString String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
denominatorString
  where
    denominator :: Polynomial a
denominator       = RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
polysRatio
    brackets :: Bool
brackets          = Polynomial a
denominator Polynomial a -> Polynomial a -> Bool
forall a. Eq a => a -> a -> Bool
/= a -> Polynomial a
forall a. a -> Polynomial a
constPoly a
forall a. C a => a
AlgRing.one
    numeratorString :: String
numeratorString   = 
      Polynomial a -> String -> (a -> String) -> Bool -> String
forall a.
(Eq a, C a) =>
Polynomial a -> String -> (a -> String) -> Bool -> String
showQpol (RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
polysRatio) String
var a -> String
showCoeff Bool
brackets
    denominatorString :: String
denominatorString = if Bool -> Bool
not Bool
brackets
      then String
""
      else String
" %//% " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Polynomial a -> String -> (a -> String) -> Bool -> String
forall a.
(Eq a, C a) =>
Polynomial a -> String -> (a -> String) -> Bool -> String
showQpol Polynomial a
denominator String
var a -> String
showCoeff Bool
True

-- | Pretty form of a ratio of univariate polynomials

prettyRatioOfPolynomials :: (Eq a, AlgField.C a, Show a) 
  => String               -- ^ string (usually a single letter) to denote the variable, e.g. @\"a\"@

  -> RatioOfPolynomials a 
  -> String 
prettyRatioOfPolynomials :: forall a.
(Eq a, C a, Show a) =>
String -> RatioOfPolynomials a -> String
prettyRatioOfPolynomials String
var = String -> (a -> String) -> RatioOfPolynomials a -> String
forall a.
(Eq a, C a) =>
String -> (a -> String) -> RatioOfPolynomials a -> String
showQpolysRatio String
var a -> String
forall a. Show a => a -> String
show 

{- -- | Pretty form of a ratio of univariate qpolynomials
prettyRatioOfQPolynomials' 
  :: String               -- ^ a string to denote the variable, e.g. @\"a\"@ 
  -> RatioOfQPolynomials 
  -> String 
prettyRatioOfQPolynomials' var = showQpolysRatio var showQ
 -}

-- | Evaluates a ratio of univariate polynomials

evalRatioOfPolynomials :: AlgField.C a 
  => a                    -- ^ the value at which the evaluation is desired

  -> RatioOfPolynomials a 
  -> a
evalRatioOfPolynomials :: forall a. C a => a -> RatioOfPolynomials a -> a
evalRatioOfPolynomials a
value RatioOfPolynomials a
polysRatio = 
  a
resultNumerator a -> a -> a
forall a. C a => a -> a -> a
AlgField./ a
resultDenominator
  where
    A a
resultNumerator   = 
      T (A a) -> A a -> A a
forall a. C a => T a -> a -> a
MathPol.evaluate (RatioOfPolynomials a -> T (A a)
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
polysRatio) (a -> A a
forall a. a -> A a
A a
value)
    A a
resultDenominator = 
      T (A a) -> A a -> A a
forall a. C a => T a -> a -> a
MathPol.evaluate (RatioOfPolynomials a -> T (A a)
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
polysRatio) (a -> A a
forall a. a -> A a
A a
value)


-- One-parameter sprays -------------------------------------------------------


type OneParameterSpray a = Spray (RatioOfPolynomials a)
type OneParameterQSpray  = OneParameterSpray Rational'

{- -- | simplifies a ratio of polynomials (simply by multiplying it by one)
simplifyRatioOfPolynomials :: 
  (Eq a, AlgField.C a) => RatioOfPolynomials a -> RatioOfPolynomials a
simplifyRatioOfPolynomials = (AlgRing.*) AlgRing.one

-- | Simplifies the coefficients (the fractions of univariate polynomials) of a 
-- one-parameter spray
simplifyOneParameterSpray :: 
  (Eq a, AlgField.C a) => OneParameterSpray a -> OneParameterSpray a
simplifyOneParameterSpray = HM.map simplifyRatioOfPolynomials
 -}

instance (Eq a, AlgField.C a) => AlgMod.C (Polynomial a) (OneParameterSpray a) where
  (*>) :: Polynomial a -> OneParameterSpray a -> OneParameterSpray a
  Polynomial a
p *> :: Polynomial a -> OneParameterSpray a -> OneParameterSpray a
*> OneParameterSpray a
spray = (Polynomial a
p Polynomial a -> Polynomial a -> T (Polynomial a)
forall a. a -> a -> T a
NumberRatio.:% Polynomial a
forall a. C a => a
AlgRing.one) BaseRing (OneParameterSpray a)
-> OneParameterSpray a -> OneParameterSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ OneParameterSpray a
spray

instance (Eq a, AlgField.C a) => AlgRightMod.C (Polynomial a) (OneParameterSpray a) where
  (<*) :: OneParameterSpray a -> Polynomial a -> OneParameterSpray a
  OneParameterSpray a
spray <* :: OneParameterSpray a -> Polynomial a -> OneParameterSpray a
<* Polynomial a
p = Polynomial a
p Polynomial a -> OneParameterSpray a -> OneParameterSpray a
forall a v. C a v => a -> v -> v
AlgMod.*> OneParameterSpray a
spray 

instance (Eq a, AlgField.C a) => AlgMod.C a (OneParameterSpray a) where
  (*>) :: a -> OneParameterSpray a -> OneParameterSpray a
  a
lambda *> :: a -> OneParameterSpray a -> OneParameterSpray a
*> OneParameterSpray a
spray = A a -> Polynomial a
forall a. a -> T a
MathPol.const (a -> A a
forall a. a -> A a
A a
lambda) Polynomial a -> OneParameterSpray a -> OneParameterSpray a
forall a v. C a v => a -> v -> v
AlgMod.*> OneParameterSpray a
spray

instance (Eq a, AlgField.C a) => AlgRightMod.C a (OneParameterSpray a) where
  (<*) :: OneParameterSpray a -> a -> OneParameterSpray a
  OneParameterSpray a
spray <* :: OneParameterSpray a -> a -> OneParameterSpray a
<* a
lambda = a
lambda a -> OneParameterSpray a -> OneParameterSpray a
forall a v. C a v => a -> v -> v
AlgMod.*> OneParameterSpray a
spray 

-- | Pretty form of a one-parameter spray, using a string (typically a letter) 

-- followed by an index to denote the variables

prettyOneParameterSprayX1X2X3 ::
     (Eq a, Show a, AlgField.C a) 
  => String              -- ^ string to denote the parameter of the spray, e.g. @\"a\"@

  -> String              -- ^ typically a letter, to denote the non-indexed variables

  -> OneParameterSpray a -- ^ a one-parameter spray; note that this function does not simplify it

  -> String 
prettyOneParameterSprayX1X2X3 :: forall a.
(Eq a, Show a, C a) =>
String -> String -> OneParameterSpray a -> String
prettyOneParameterSprayX1X2X3 String
a = (RatioOfPolynomials a -> String)
-> (String, String)
-> String
-> Spray (RatioOfPolynomials a)
-> String
forall a.
(a -> String) -> (String, String) -> String -> Spray a -> String
showSprayX1X2X3 (String -> RatioOfPolynomials a -> String
forall a.
(Eq a, C a, Show a) =>
String -> RatioOfPolynomials a -> String
prettyRatioOfPolynomials String
a) (String
"{ ", String
" }")

-- | Pretty form of a one-parameter spray, using some given strings (typically some 

-- letters) to denote the variables if possible, i.e. if enough letters are 

-- provided; otherwise this function behaves exactly like 

-- @prettyOneParameterSprayX1X2X3 a@ where @a@ is the first provided letter

prettyOneParameterSprayXYZ ::
     (Eq a, Show a, AlgField.C a) 
  => String              -- ^ string to denote the parameter of the spray, e.g. @\"a\"@

  -> [String]            -- ^ typically some letters, to denote the main variables

  -> OneParameterSpray a -- ^ a one-parameter spray; note that this function does not simplify it

  -> String 
prettyOneParameterSprayXYZ :: forall a.
(Eq a, Show a, C a) =>
String -> [String] -> OneParameterSpray a -> String
prettyOneParameterSprayXYZ String
a = (RatioOfPolynomials a -> String)
-> (String, String)
-> [String]
-> Spray (RatioOfPolynomials a)
-> String
forall a.
(a -> String) -> (String, String) -> [String] -> Spray a -> String
showSprayXYZ (String -> RatioOfPolynomials a -> String
forall a.
(Eq a, C a, Show a) =>
String -> RatioOfPolynomials a -> String
prettyRatioOfPolynomials String
a) (String
"{ ", String
" }")

-- | Pretty form of a one-parameter spray; see the definition below and see

-- `prettyOneParameterSprayXYZ`

--

-- prop> prettyOneParameterSpray a spray == prettyOneParameterSprayXYZ a ["x","y","z"] spray

prettyOneParameterSpray ::
     (Eq a, Show a, AlgField.C a) 
  => String              -- ^ string to denote the parameter of the spray, e.g. @\"a\"@

  -> OneParameterSpray a -- ^ a one-parameter spray; note that this function does not simplify it

  -> String 
prettyOneParameterSpray :: forall a.
(Eq a, Show a, C a) =>
String -> OneParameterSpray a -> String
prettyOneParameterSpray String
a = String -> [String] -> OneParameterSpray a -> String
forall a.
(Eq a, Show a, C a) =>
String -> [String] -> OneParameterSpray a -> String
prettyOneParameterSprayXYZ String
a [String
"x", String
"y", String
"z"]

-- | Pretty form of a one-parameter spray; see the definition below and see

-- `prettyOneParameterSprayXYZ`

--

-- prop> prettyOneParameterSpray' a spray == prettyOneParameterSprayXYZ a ["X","Y","Z"] spray

prettyOneParameterSpray' ::
     (Eq a, Show a, AlgField.C a) 
  => String              -- ^ string to denote the parameter of the spray, e.g. @\"a\"@

  -> OneParameterSpray a -- ^ a one-parameter spray; note that this function does not simplify it

  -> String 
prettyOneParameterSpray' :: forall a.
(Eq a, Show a, C a) =>
String -> OneParameterSpray a -> String
prettyOneParameterSpray' String
a = String -> [String] -> OneParameterSpray a -> String
forall a.
(Eq a, Show a, C a) =>
String -> [String] -> OneParameterSpray a -> String
prettyOneParameterSprayXYZ String
a [String
"X", String
"Y", String
"Z"]

-- | Pretty form of a one-parameter rational spray, using a string (typically a letter) 

-- followed by an index to denote the variables

prettyOneParameterQSprayX1X2X3 ::
     String          -- ^ usually a letter, to denote the parameter of the spray, e.g. @\"a\"@

  -> String          -- ^ usually a letter, to denote the non-indexed variables of the spray

  -> OneParameterQSpray  -- ^ a one-parameter rational spray; note that this function does not simplify it

  -> String 
prettyOneParameterQSprayX1X2X3 :: String -> String -> OneParameterQSpray -> String
prettyOneParameterQSprayX1X2X3 String
a String
x = 
  (RatioOfQPolynomials -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> OneParameterQSpray
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray (String -> RatioOfQPolynomials -> String
prettyRatioOfQPolynomials String
a) (String
"{ ", String
" }") (String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
x)

-- | Pretty form of a one-parameter rational spray, using some given strings (typically some 

-- letters) to denote the variables if possible, i.e. if enough letters are 

-- provided; otherwise this function behaves exactly like 

-- @prettyOneParameterQSprayX1X2X3 a@ where @a@ is the first provided letter

prettyOneParameterQSprayXYZ ::
     String             -- ^ usually a letter, to denote the parameter of the spray, e.g. @\"a\"@

  -> [String]           -- ^ usually some letters, to denote the variables of the spray

  -> OneParameterQSpray -- ^ a one-parameter rational spray; note that this function does not simplify it

  -> String 
prettyOneParameterQSprayXYZ :: String -> [String] -> OneParameterQSpray -> String
prettyOneParameterQSprayXYZ String
a [String]
letters = 
  (RatioOfQPolynomials -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> OneParameterQSpray
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray (String -> RatioOfQPolynomials -> String
prettyRatioOfQPolynomials String
a) (String
"{ ", String
" }") ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
letters)

-- | Pretty form of a one-parameter rational spray, using @\"x\"@, @\"y\"@ and @\"z\"@ for the variables 

-- if possible; i.e. if the spray does not have more than three variables, otherwise 

-- @\"x1\"@, @\"x2\"@, ... are used to denote the variables

--

-- prop> prettyOneParameterQSpray a == prettyOneParameterQSprayXYZ a ["x","y","z"]

prettyOneParameterQSpray ::
     String             -- ^ usually a letter, to denote the parameter of the spray, e.g. @\"a\"@

  -> OneParameterQSpray -- ^ the one-parameter rational spray to be printed; note that this function does not simplify it

  -> String 
prettyOneParameterQSpray :: String -> OneParameterQSpray -> String
prettyOneParameterQSpray String
a = String -> [String] -> OneParameterQSpray -> String
prettyOneParameterQSprayXYZ String
a [String
"x", String
"y", String
"z"] 

-- | Pretty form of a one-parameter rational spray, using @\"X\"@, @\"Y\"@ and @\"Z\"@ for the variables 

-- if possible; i.e. if the spray does not have more than three variables, otherwise 

-- @\"X1\"@, @\"X2\"@, ... are used 

--

-- prop> prettyOneParameterQSpray' a == prettyOneParameterQSprayXYZ a ["X","Y","Z"]

prettyOneParameterQSpray' ::
     String              -- ^ usually a letter, to denote the parameter of the spray, e.g. @\"a\"@

  -> OneParameterQSpray  -- ^ the one-parameter rational spray to be printed; note that this function does not simplify it

  -> String 
prettyOneParameterQSpray' :: String -> OneParameterQSpray -> String
prettyOneParameterQSpray' String
a = String -> [String] -> OneParameterQSpray -> String
prettyOneParameterQSprayXYZ String
a [String
"X", String
"Y", String
"Z"] 

-- | Substitutes a value to the parameter of a one-parameter spray 

-- (the variable occurring in its coefficients)

--

-- prop> evalOneParameterSpray spray x == substituteParameters spray [x]

evalOneParameterSpray :: 
  (Eq a, AlgField.C a) => OneParameterSpray a -> a -> Spray a
evalOneParameterSpray :: forall a. (Eq a, C a) => OneParameterSpray a -> a -> Spray a
evalOneParameterSpray OneParameterSpray a
spray a
x = 
  Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ (RatioOfPolynomials a -> a) -> OneParameterSpray a -> Spray a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map (a -> RatioOfPolynomials a -> a
forall a. C a => a -> RatioOfPolynomials a -> a
evalRatioOfPolynomials a
x) OneParameterSpray a
spray 

-- | Substitutes a value to the parameter of a one-parameter spray; 

-- same as `evalOneParameterSpray`

--

-- prop> substituteTheParameter spray x == substituteParameters spray [x]

substituteTheParameter :: 
  (Eq a, AlgField.C a) => OneParameterSpray a -> a -> Spray a
substituteTheParameter :: forall a. (Eq a, C a) => OneParameterSpray a -> a -> Spray a
substituteTheParameter OneParameterSpray a
spray a
x = OneParameterSpray a
-> [BaseRing (RatioOfPolynomials a)]
-> Spray (BaseRing (RatioOfPolynomials a))
forall b.
(FunctionLike b, Eq (BaseRing b), C (BaseRing b)) =>
Spray b -> [BaseRing b] -> Spray (BaseRing b)
substituteParameters OneParameterSpray a
spray [a
BaseRing (RatioOfPolynomials a)
x]

-- | Substitutes a value to the parameter of a one-parameter spray as well 

-- as some values to the variables of this spray

--

-- prop> evalOneParameterSpray' spray a xs == evalParametricSpray' spray [a] xs

evalOneParameterSpray' :: (Eq a, AlgField.C a) 
  => OneParameterSpray a -- ^ one-parameter spray to be evaluated

  -> a                   -- ^ a value for the parameter

  -> [a]                 -- ^ some values for the variables 

  -> a
evalOneParameterSpray' :: forall a. (Eq a, C a) => OneParameterSpray a -> a -> [a] -> a
evalOneParameterSpray' OneParameterSpray a
spray a
x [a]
xs = if [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= OneParameterSpray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables OneParameterSpray a
spray 
  then Spray a -> [a] -> a
forall a. (Eq a, C a) => Spray a -> [a] -> a
evalSpray (OneParameterSpray a -> a -> Spray a
forall a. (Eq a, C a) => OneParameterSpray a -> a -> Spray a
evalOneParameterSpray OneParameterSpray a
spray a
x) [a]
xs
  else String -> a
forall a. HasCallStack => String -> a
error String
"evalOneParameterSpray': not enough values provided."

-- | helper function for evalOneParameterSpray''

evalOneParameterTerm :: (Eq a, AlgField.C a) 
  => [a] -> Term (RatioOfPolynomials a) -> RatioOfPolynomials a
evalOneParameterTerm :: forall a.
(Eq a, C a) =>
[a] -> Term (RatioOfPolynomials a) -> RatioOfPolynomials a
evalOneParameterTerm [a]
xs (Powers
powers, RatioOfPolynomials a
coeff) = 
  [a] -> a
forall a. C a => [a] -> a
AlgRing.product ((a -> Integer -> a) -> [a] -> [Integer] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> Integer -> a
forall a. C a => a -> Integer -> a
(AlgRing.^) [a]
xs [Integer]
pows) BaseRing (RatioOfPolynomials a)
-> RatioOfPolynomials a -> RatioOfPolynomials a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ RatioOfPolynomials a
coeff
  where 
    pows :: [Integer]
pows = Seq Integer -> [Integer]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> Exponents -> Seq Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Powers -> Exponents
exponents Powers
powers)

-- | Substitutes some values to the variables of a one-parameter spray; same 

-- as `evalParametricSpray`

evalOneParameterSpray'' ::
  (Eq a, AlgField.C a) => OneParameterSpray a -> [a] -> RatioOfPolynomials a
evalOneParameterSpray'' :: forall a.
(Eq a, C a) =>
OneParameterSpray a -> [a] -> RatioOfPolynomials a
evalOneParameterSpray'' OneParameterSpray a
spray [a]
xs = if [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= OneParameterSpray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables OneParameterSpray a
spray
  then [RatioOfPolynomials a] -> RatioOfPolynomials a
forall a. C a => [a] -> a
AlgAdd.sum ([RatioOfPolynomials a] -> RatioOfPolynomials a)
-> [RatioOfPolynomials a] -> RatioOfPolynomials a
forall a b. (a -> b) -> a -> b
$ (Term (RatioOfPolynomials a) -> RatioOfPolynomials a)
-> [Term (RatioOfPolynomials a)] -> [RatioOfPolynomials a]
forall a b. (a -> b) -> [a] -> [b]
map ([a] -> Term (RatioOfPolynomials a) -> RatioOfPolynomials a
forall a.
(Eq a, C a) =>
[a] -> Term (RatioOfPolynomials a) -> RatioOfPolynomials a
evalOneParameterTerm [a]
xs) (OneParameterSpray a -> [Term (RatioOfPolynomials a)]
forall k v. HashMap k v -> [(k, v)]
HM.toList OneParameterSpray a
spray)
  else String -> RatioOfPolynomials a
forall a. HasCallStack => String -> a
error String
"evalOneParameterSpray'': not enough values provided."


-- Sprays ---------------------------------------------------------------------


type Exponents = Seq Int

-- | The type @Powers@ is used to represent the exponents of the monomial 

-- occurring in a term of a spray. The integer in the field @nvariables@ is 

-- the number of variables involved in this monomial (it is 3, not 2, for a 

-- monomial such as @x^2.z^3@, because the exponents of this monomial is the 

-- sequence @(2, 0, 3)@). Actually this integer is always the length of the 

-- sequence in the field @exponents@. The reason of the presence of the field 

-- @nvariables@ is that I thought that it was necessary when I started to 

-- develop the package, but now I think it is useless. The type @Powers@ will 

-- possibly be abandoned in a future version of the package. However we cannot

-- simply use the type `Exponents` to represent the exponents, because two 

-- sequences of exponents that differ only by some trailing zeros must be 

-- considered as identical, and they are considered as such with the type 

-- @Powers@ thanks to its @Eq@ instance. Instead of @Powers@, a new type 

-- encapsulating the `Exponents` type with such an @Eq@ instance should be 

-- enough to represent the exponents.

data Powers = Powers
  { Powers -> Exponents
exponents  :: Exponents
  , Powers -> Int
nvariables :: Int
  }
  deriving Int -> Powers -> ShowS
[Powers] -> ShowS
Powers -> String
(Int -> Powers -> ShowS)
-> (Powers -> String) -> ([Powers] -> ShowS) -> Show Powers
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Powers -> ShowS
showsPrec :: Int -> Powers -> ShowS
$cshow :: Powers -> String
show :: Powers -> String
$cshowList :: [Powers] -> ShowS
showList :: [Powers] -> ShowS
Show

nullPowers :: Powers
nullPowers :: Powers
nullPowers = Exponents -> Int -> Powers
Powers Exponents
forall a. Seq a
S.empty Int
0

powerize :: Exponents -> Powers
powerize :: Exponents -> Powers
powerize Exponents
expnts = Exponents -> Int -> Powers
Powers Exponents
expnts (Exponents -> Int
forall a. Seq a -> Int
S.length Exponents
expnts)

instance Eq Powers where
  (==) :: Powers -> Powers -> Bool
  Powers
pows1 == :: Powers -> Powers -> Bool
== Powers
pows2 = Exponents
expts1' Exponents -> Exponents -> Bool
forall a. Eq a => a -> a -> Bool
== Exponents
expts2'
    where 
      (Exponents
expts1', Exponents
expts2') = (Powers, Powers) -> (Exponents, Exponents)
harmonize (Powers
pows1, Powers
pows2)

instance Hashable Powers where
  hashWithSalt :: Int -> Powers -> Int
  hashWithSalt :: Int -> Powers -> Int
hashWithSalt Int
k Powers
pows = Int -> (Exponents, Int) -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
k (Powers -> Exponents
exponents Powers
pows, Powers -> Int
nvariables Powers
pows)

-- | append trailing zeros

growSequence :: Exponents -> Int -> Int -> Exponents
growSequence :: Exponents -> Int -> Int -> Exponents
growSequence Exponents
s Int
m Int
n = Exponents
s Exponents -> Exponents -> Exponents
forall a. Seq a -> Seq a -> Seq a
>< Int -> Int -> Exponents
forall a. Int -> a -> Seq a
S.replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
m) Int
0

growSequence' :: Int -> Exponents -> Exponents
growSequence' :: Int -> Exponents -> Exponents
growSequence' Int
n Exponents
s = Exponents -> Int -> Int -> Exponents
growSequence Exponents
s (Exponents -> Int
forall a. Seq a -> Int
S.length Exponents
s) Int
n

-- | append trailing zeros to get the same length

harmonize :: (Powers, Powers) -> (Exponents, Exponents)
harmonize :: (Powers, Powers) -> (Exponents, Exponents)
harmonize (Powers
pows1, Powers
pows2) = (Exponents
e1', Exponents
e2')
 where
  e1 :: Exponents
e1            = Powers -> Exponents
exponents Powers
pows1
  e2 :: Exponents
e2            = Powers -> Exponents
exponents Powers
pows2
  n1 :: Int
n1            = Powers -> Int
nvariables Powers
pows1
  n2 :: Int
n2            = Powers -> Int
nvariables Powers
pows2
  (Exponents
e1', Exponents
e2') = if Int
n1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n2
    then (Exponents -> Int -> Int -> Exponents
growSequence Exponents
e1 Int
n1 Int
n2, Exponents
e2)
    else (Exponents
e1, Exponents -> Int -> Int -> Exponents
growSequence Exponents
e2 Int
n2 Int
n1)

makePowers :: Exponents -> Powers
makePowers :: Exponents -> Powers
makePowers Exponents
expnts = Exponents -> Powers
powerize Exponents
s
  where 
    s :: Exponents
s = (Int -> Bool) -> Exponents -> Exponents
forall a. (a -> Bool) -> Seq a -> Seq a
dropWhileR (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0) Exponents
expnts

-- | An object of type @Spray a@ represents a multivariate polynomial whose 

-- coefficients are represented by the objects of type @a@, which must have 

-- a ring instance in order that we can add and multiply two polynomials. 

type Spray a = HashMap Powers a

-- | Most often, one deals with sprays with rational coefficients, so we 

-- dedicate a type alias for such sprays.

type QSpray = Spray Rational

-- | The type `Rational'` is helpful when dealing with `OneParameterSpray` 

-- sprays, but this type of sprays lost its interest in version 0.4.0.0 

-- (see CHANGELOG or README).

type QSpray' = Spray Rational'

type SafeSpray a = HashMap Exponents a

-- An object of type @Term a@ represents a term of a @Spray a@ spray. Applying

-- @Data.HashMap.Strict.toList@ to a @Spray a@ spray yields a list of @Term a@ 

-- objects. This type has probably no interest for the user, it is exported 

-- because it possibly has an interest for internal usage in a package using 

-- __hspray__.  

type Term a = (Powers, a)

instance (AlgRing.C a, Eq a) => FunctionLike (Spray a) where
  type BaseRing (Spray a) = a
  --

  type VariablesType (Spray a) = Spray a
  --

  (*^) :: a -> Spray a -> Spray a
  *^ :: a -> Spray a -> Spray a
(*^) a
lambda Spray a
pol = a
lambda a -> Spray a -> Spray a
forall a v. C a v => a -> v -> v
AlgMod.*> Spray a
pol
  --

  (+>) :: a -> Spray a -> Spray a
  +> :: a -> Spray a -> Spray a
(+>) a
x Spray a
spray = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero 
    then Spray a
spray 
    else Spray a -> Term a -> Spray a
forall a. (C a, Eq a) => Spray a -> Term a -> Spray a
addTerm Spray a
spray (Powers
nullPowers, a
x)
  --

  evaluate :: Spray a -> [a] -> a
  evaluate :: Spray a -> [a] -> a
evaluate Spray a
spray [a]
xyz = if [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xyz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray 
    then [a] -> Spray a -> a
forall a. C a => [a] -> Spray a -> a
evalSprayHelper [a]
xyz Spray a
spray
    else String -> a
forall a. HasCallStack => String -> a
error String
"evaluate: not enough values provided."
  --

  substitute :: [Maybe a] -> Spray a -> Spray a
  substitute :: [Maybe a] -> Spray a -> Spray a
substitute [Maybe a]
subs Spray a
spray = if [Maybe a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Maybe a]
subs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n 
    then Spray a
spray'
    else String -> Spray a
forall a. HasCallStack => String -> a
error String
"substitute: incorrect length of the substitutions list."
    where
      n :: Int
n      = Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray
      terms :: [Term a]
terms  = Spray a -> [Term a]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
spray
      spray' :: Spray a
spray' = [Term a] -> Spray a
forall a. (Eq a, C a) => [Term a] -> Spray a
sumTerms ((Term a -> Term a) -> [Term a] -> [Term a]
forall a b. (a -> b) -> [a] -> [b]
map Term a -> Term a
substituteTerm [Term a]
terms)
      substituteTerm :: Term a -> Term a
      substituteTerm :: Term a -> Term a
substituteTerm (Powers
powers, a
coeff) = (Powers
powers'', a
coeff')
        where
          pows :: Exponents
pows     = Powers -> Exponents
exponents Powers
powers
          nv :: Int
nv       = Powers -> Int
nvariables Powers
powers
          indices :: [Int]
indices  = (Maybe a -> Bool) -> [Maybe a] -> [Int]
forall a. (a -> Bool) -> [a] -> [Int]
findIndices Maybe a -> Bool
forall a. Maybe a -> Bool
isJust (Int -> [Maybe a] -> [Maybe a]
forall a. Int -> [a] -> [a]
take Int
nv [Maybe a]
subs)
          pows' :: [Integer]
pows'    = [Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Exponents
pows Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
i) | Int
i <- [Int]
indices]
          xyz :: [a]
xyz      = [Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust ([Maybe a]
subs [Maybe a] -> Int -> Maybe a
forall a. HasCallStack => [a] -> Int -> a
!! Int
i) | Int
i <- [Int]
indices]
          coeff' :: a
coeff'   = a
coeff a -> a -> a
forall a. C a => a -> a -> a
AlgRing.* [a] -> a
forall a. C a => [a] -> a
AlgRing.product ((a -> Integer -> a) -> [a] -> [Integer] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> Integer -> a
forall a. C a => a -> Integer -> a
(AlgRing.^) [a]
xyz [Integer]
pows')
          f :: Int -> Int -> Int
f Int
i Int
a    = if Int
i Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int]
indices then Int
0 else Int
a
          pows'' :: Exponents
pows''   = (Int -> Int -> Int) -> Exponents -> Exponents
forall a b. (Int -> a -> b) -> Seq a -> Seq b
S.mapWithIndex Int -> Int -> Int
f Exponents
pows
          powers'' :: Powers
powers'' = Exponents -> Powers
makePowers Exponents
pows''
  --

  changeVariables :: Spray a -> [Spray a] -> Spray a
  changeVariables :: Spray a -> [Spray a] -> Spray a
changeVariables = Spray a -> [Spray a] -> Spray a
forall a. (C a, Eq a) => Spray a -> [Spray a] -> Spray a
composeSpray
  --

  numberOfVariables :: Spray a -> Int
  numberOfVariables :: Spray a -> Int
numberOfVariables Spray a
spray =
    if [Powers] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Powers]
powers then Int
0 else [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ((Powers -> Int) -> [Powers] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Powers -> Int
nvariables [Powers]
powers)
    where
      powers :: [Powers]
powers = Spray a -> [Powers]
forall k v. HashMap k v -> [k]
HM.keys Spray a
spray
  --

  permuteVariables :: [Int] -> Spray a -> Spray a
  permuteVariables :: [Int] -> Spray a -> Spray a
permuteVariables [Int]
permutation Spray a
spray = 
    if [Int] -> Bool
isPermutation [Int]
permutation Bool -> Bool -> Bool
&& Int
n' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n  
      then Spray a
spray'
      else String -> Spray a
forall a. HasCallStack => String -> a
error String
"permuteVariables: invalid permutation."
    where
      spray' :: Spray a
spray' = if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
spray
        then Spray a
spray
        else [Term a] -> Spray a
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([Powers] -> [a] -> [Term a]
forall a b. [a] -> [b] -> [(a, b)]
zip [Powers]
powers' [a]
coeffs)
      n :: Int
n  = Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray
      n' :: Int
n' = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
permutation
      isPermutation :: [Int] -> Bool
isPermutation [Int]
pmtn = 
        (Bool -> Bool
not (Bool -> Bool) -> ([Int] -> Bool) -> [Int] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) [Int]
pmtn Bool -> Bool -> Bool
&& [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Int]
pmtn Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 Bool -> Bool -> Bool
&& [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Int] -> [Int]
forall a. Eq a => [a] -> [a]
nub [Int]
pmtn) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n'
      intmap :: IntMap Int
intmap         = [(Int, Int)] -> IntMap Int
forall a. [(Int, a)] -> IntMap a
IM.fromList ([Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
permutation [Int
1 .. Int
n'])
      invpermutation :: [Int]
invpermutation = [IntMap Int
intmap IntMap Int -> Int -> Int
forall a. IntMap a -> Int -> a
IM.! Int
i | Int
i <- [Int
1 .. Int
n']]
      permuteSeq :: Exponents -> Exponents
permuteSeq Exponents
x   = 
        (Int -> Int -> Int) -> Exponents -> Exponents
forall a b. (Int -> a -> b) -> Seq a -> Seq b
S.mapWithIndex (\Int
i Int
_ -> Exponents
x Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` ([Int]
invpermutation [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) Exponents
x 
      ([Powers]
powers, [a]
coeffs) = [Term a] -> ([Powers], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip (Spray a -> [Term a]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
spray)
      f :: Powers -> Powers
f Powers
pows = let expnts :: Exponents
expnts = (Exponents -> Exponents
permuteSeq (Exponents -> Exponents)
-> (Exponents -> Exponents) -> Exponents -> Exponents
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Exponents -> Exponents
growSequence' Int
n') (Powers -> Exponents
exponents Powers
pows) in
                   Exponents -> Powers
makePowers Exponents
expnts
      powers' :: [Powers]
powers' = (Powers -> Powers) -> [Powers] -> [Powers]
forall a b. (a -> b) -> [a] -> [b]
map Powers -> Powers
f [Powers]
powers
  --

  swapVariables :: (Int, Int) -> Spray a -> Spray a
  swapVariables :: (Int, Int) -> Spray a -> Spray a
swapVariables (Int
i, Int
j) Spray a
spray = 
    if Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
1 Bool -> Bool -> Bool
&& Int
jInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
1  
      then Spray a
spray'
      else String -> Spray a
forall a. HasCallStack => String -> a
error String
"swapVariables: invalid indices."
    where
      spray' :: Spray a
spray' = if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
spray
        then Spray a
spray
        else [Term a] -> Spray a
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([Powers] -> [a] -> [Term a]
forall a b. [a] -> [b] -> [(a, b)]
zip [Powers]
powers' [a]
coeffs)
      n :: Int
n = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray, Int
i, Int
j]
      f :: Int -> Int
f Int
k | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
i    = Int
j
          | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
j    = Int
i
          | Bool
otherwise = Int
k
      transposition :: [Int]
transposition = (Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Int
f [Int
1 .. Int
n]
      permuteSeq :: Exponents -> Exponents
permuteSeq Exponents
x  = 
        (Int -> Int -> Int) -> Exponents -> Exponents
forall a b. (Int -> a -> b) -> Seq a -> Seq b
S.mapWithIndex (\Int
ii Int
_ -> Exponents
x Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` ([Int]
transposition [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
ii Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) Exponents
x 
      ([Powers]
powers, [a]
coeffs) = [Term a] -> ([Powers], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip (Spray a -> [Term a]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
spray)
      g :: Powers -> Powers
g Powers
pows = let expnts :: Exponents
expnts = (Exponents -> Exponents
permuteSeq (Exponents -> Exponents)
-> (Exponents -> Exponents) -> Exponents -> Exponents
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Exponents -> Exponents
growSequence' Int
n) (Powers -> Exponents
exponents Powers
pows) in
                 Exponents -> Powers
makePowers Exponents
expnts
      powers' :: [Powers]
powers' = (Powers -> Powers) -> [Powers] -> [Powers]
forall a b. (a -> b) -> [a] -> [b]
map Powers -> Powers
g [Powers]
powers
  --

  involvesVariable :: Spray a -> Int -> Bool
  involvesVariable :: Spray a -> Int -> Bool
involvesVariable Spray a
spray Int
i = (Exponents -> Bool) -> [Exponents] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Exponents -> Bool
f (Spray a -> [Exponents]
forall a. Spray a -> [Exponents]
allExponents Spray a
spray)
    where
      f :: Exponents -> Bool
f Exponents
expnts = let p :: Maybe Int
p = Int -> Exponents -> Maybe Int
forall a. Int -> Seq a -> Maybe a
S.lookup (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Exponents
expnts in 
        Maybe Int -> Bool
forall a. Maybe a -> Bool
isJust Maybe Int
p Bool -> Bool -> Bool
&& Maybe Int
p Maybe Int -> Maybe Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int -> Maybe Int
forall a. a -> Maybe a
Just Int
0 
  --

  dropVariables :: Int -> Spray a -> Spray a
  dropVariables :: Int -> Spray a -> Spray a
dropVariables Int
n = (Powers -> Powers) -> Spray a -> Spray a
forall k2 k1 v.
(Eq k2, Hashable k2) =>
(k1 -> k2) -> HashMap k1 v -> HashMap k2 v
HM.mapKeys Powers -> Powers
f
    where
      f :: Powers -> Powers
f (Powers Exponents
exps Int
nv) = Exponents -> Int -> Powers
Powers (Int -> Exponents -> Exponents
forall a. Int -> Seq a -> Seq a
S.drop Int
n Exponents
exps) (Int
nv Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n)
  --

  derivative :: Int -> Spray a -> Spray a 
  derivative :: Int -> Spray a -> Spray a
derivative Int
i Spray a
p = if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
1 
    then Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [Term a] -> Spray a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> [(k, v)] -> HashMap k v
HM.fromListWith a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+) [Term a]
terms
    else String -> Spray a
forall a. HasCallStack => String -> a
error String
"derivative: invalid index."
    where
      terms :: [Term a]
terms = [ Term a -> Term a
derivTerm Term a
term | Term a
term <- Spray a -> [Term a]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
p ]
      derivTerm :: Term a -> Term a 
      derivTerm :: Term a -> Term a
derivTerm (Powers
pows, a
coef) = if Int
i' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Exponents -> Int
forall a. Seq a -> Int
S.length Exponents
expts 
        then (Powers
nullPowers, a
forall a. C a => a
AlgAdd.zero)
        else (Powers
pows', a
coef')
        where
          i' :: Int
i'     = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
          expts :: Exponents
expts  = Powers -> Exponents
exponents Powers
pows
          expt_i :: Int
expt_i = Exponents
expts Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
i'
          expts' :: Exponents
expts' = (Int -> Int) -> Int -> Exponents -> Exponents
forall a. (a -> a) -> Int -> Seq a -> Seq a
adjust (Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
1) Int
i' Exponents
expts
          coef' :: a
coef'  = Int
expt_i Int -> a -> a
forall a. (C a, Eq a) => Int -> a -> a
.^ a
coef
          pows' :: Powers
pows'  = Exponents -> Powers
makePowers Exponents
expts' 

-- | addition of two sprays

addSprays :: (AlgAdd.C a, Eq a) => Spray a -> Spray a -> Spray a
addSprays :: forall a. (C a, Eq a) => Spray a -> Spray a -> Spray a
addSprays Spray a
p Spray a
q = Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> Spray a -> Spray a -> Spray a
forall k v.
Eq k =>
(v -> v -> v) -> HashMap k v -> HashMap k v -> HashMap k v
HM.unionWith a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+) Spray a
p Spray a
q -- HM.foldlWithKey' f p q

--  where 

--    f s powers coef = HM.insertWith (AlgAdd.+) powers coef s


-- | addition of a term to a spray

addTerm :: (AlgAdd.C a, Eq a) => Spray a -> Term a -> Spray a
addTerm :: forall a. (C a, Eq a) => Spray a -> Term a -> Spray a
addTerm Spray a
spray (Powers
powers, a
coeff) = 
  if Powers -> Spray a -> a
forall a. C a => Powers -> Spray a -> a
getCoefficient' Powers
powers Spray a
spray a -> a -> a
forall a. C a => a -> a -> a
AlgAdd.+ a
coeff a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero
    then 
      Powers -> Spray a -> Spray a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete Powers
powers Spray a
spray
    else
      (a -> a -> a) -> Powers -> a -> Spray a -> Spray a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
HM.insertWith a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+) Powers
powers a
coeff Spray a
spray

-- | sum list of terms

sumTerms :: (Eq a, AlgAdd.C a) => [Term a] -> Spray a
sumTerms :: forall a. (Eq a, C a) => [Term a] -> Spray a
sumTerms = Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a)
-> ([Term a] -> Spray a) -> [Term a] -> Spray a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> a) -> [Term a] -> Spray a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> [(k, v)] -> HashMap k v
HM.fromListWith a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+) 

-- | opposite spray

negateSpray :: AlgAdd.C a => Spray a -> Spray a
negateSpray :: forall a. C a => Spray a -> Spray a
negateSpray = (a -> a) -> HashMap Powers a -> HashMap Powers a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map a -> a
forall a. C a => a -> a
AlgAdd.negate

-- | scale a spray by a scalar

scaleSpray :: (AlgRing.C a, Eq a) => a -> Spray a -> Spray a
scaleSpray :: forall a. (C a, Eq a) => a -> Spray a -> Spray a
scaleSpray a
lambda Spray a
p = Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ (a -> a) -> Spray a -> Spray a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map (a
lambda a -> a -> a
forall a. C a => a -> a -> a
AlgRing.*) Spray a
p

-- | multiply two terms

multTerm :: AlgRing.C a => Term a -> Term a -> Term a
multTerm :: forall a. C a => Term a -> Term a -> Term a
multTerm (Powers
pows1, a
coef1) (Powers
pows2, a
coef2) = (Powers
pows, a
coef1 a -> a -> a
forall a. C a => a -> a -> a
AlgRing.* a
coef2)
 where
  (Exponents
expts1', Exponents
expts2') = (Powers, Powers) -> (Exponents, Exponents)
harmonize (Powers
pows1, Powers
pows2)
  expts :: Exponents
expts              = (Int -> Int -> Int) -> Exponents -> Exponents -> Exponents
forall a b c. (a -> b -> c) -> Seq a -> Seq b -> Seq c
S.zipWith Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) Exponents
expts1' Exponents
expts2'
  pows :: Powers
pows               = Exponents -> Powers
makePowers Exponents
expts

-- | multiply a spray by a term

multSprayByTerm :: (Eq a, AlgRing.C a) => Spray a -> Term a -> Spray a
multSprayByTerm :: forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
spray Term a
term = Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ [Term a] -> Spray a
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList [Term a]
prods
  where
    prods :: [Term a]
prods = [Term a -> Term a -> Term a
forall a. C a => Term a -> Term a -> Term a
multTerm Term a
trm Term a
term | Term a
trm <- Spray a -> [Term a]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
spray]

-- | multiply two sprays

multSprays :: (AlgRing.C a, Eq a) => Spray a -> Spray a -> Spray a
multSprays :: forall a. (C a, Eq a) => Spray a -> Spray a -> Spray a
multSprays Spray a
p Spray a
q = Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [(Powers, a)] -> Spray a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> [(k, v)] -> HashMap k v
HM.fromListWith a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+) [(Powers, a)]
prods
 where
  p' :: [(Powers, a)]
p'    = Spray a -> [(Powers, a)]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
p
  q' :: [(Powers, a)]
q'    = Spray a -> [(Powers, a)]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
q
  prods :: [(Powers, a)]
prods = [ (Powers, a) -> (Powers, a) -> (Powers, a)
forall a. C a => Term a -> Term a -> Term a
multTerm (Powers, a)
mp (Powers, a)
mq | (Powers, a)
mp <- [(Powers, a)]
p', (Powers, a)
mq <- [(Powers, a)]
q' ]

instance (AlgAdd.C a, Eq a) => AlgAdd.C (Spray a) where
  (+) :: Spray a -> Spray a -> Spray a
  Spray a
p + :: Spray a -> Spray a -> Spray a
+ Spray a
q  = Spray a -> Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a -> Spray a
addSprays Spray a
p Spray a
q
  zero :: Spray a
  zero :: Spray a
zero   = Spray a
forall k v. HashMap k v
HM.empty
  negate :: Spray a -> Spray a
  negate :: Spray a -> Spray a
negate = Spray a -> Spray a
forall a. C a => Spray a -> Spray a
negateSpray

instance (AlgRing.C a, Eq a) => AlgMod.C a (Spray a) where
  (*>) :: a -> Spray a -> Spray a
  a
lambda *> :: a -> Spray a -> Spray a
*> Spray a
p = a -> Spray a -> Spray a
forall a. (C a, Eq a) => a -> Spray a -> Spray a
scaleSpray a
lambda Spray a
p

instance (AlgRing.C a, Eq a) => AlgRightMod.C a (Spray a) where
  (<*) :: Spray a -> a -> Spray a
  Spray a
p <* :: Spray a -> a -> Spray a
<* a
lambda = a -> Spray a -> Spray a
forall a. (C a, Eq a) => a -> Spray a -> Spray a
scaleSpray a
lambda Spray a
p

instance (AlgRing.C a, Eq a) => AlgRing.C (Spray a) where
  (*) :: Spray a -> Spray a -> Spray a
  Spray a
p * :: Spray a -> Spray a -> Spray a
* Spray a
q = Spray a -> Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a -> Spray a
multSprays Spray a
p Spray a
q
  one :: Spray a
  one :: Spray a
one = Powers -> a -> Spray a
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton (Exponents -> Int -> Powers
Powers Exponents
forall a. Seq a
S.empty Int
0) a
forall a. C a => a
AlgRing.one

infixr 7 /^
-- | Divides a spray by a scalar; you can equivalently use `(/>)` if the type 

-- of the scalar is not ambiguous

(/^) :: (AlgField.C a, Eq a) => Spray a -> a -> Spray a
/^ :: forall a. (C a, Eq a) => Spray a -> a -> Spray a
(/^) Spray a
spray a
lambda = Spray a
spray Spray a -> a -> Spray a
forall k a. (C k, C k a) => a -> k -> a
/> a
lambda

-- | remove zero terms of a spray

removeZeroTerms :: (AlgAdd.C a, Eq a) => Spray a -> Spray a
removeZeroTerms :: forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms = (a -> Bool) -> HashMap Powers a -> HashMap Powers a
forall v k. (v -> Bool) -> HashMap k v -> HashMap k v
HM.filter (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. C a => a
AlgAdd.zero)

-- | helper function for lone and lone'

lonePower :: Int -> Int -> Powers
lonePower :: Int -> Int -> Powers
lonePower Int
n Int
p = if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 
  then Powers
nullPowers
  else Exponents -> Int -> Powers
Powers (Int -> Int -> Exponents
forall a. Int -> a -> Seq a
S.replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int
0 Exponents -> Int -> Exponents
forall a. Seq a -> a -> Seq a
|> Int
p) Int
n

-- | The @n@-th polynomial variable @x_n@ as a spray; one usually builds a 

-- spray by introducing these variables and combining them with the arithmetic 

-- operations

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> spray = 2*^x^**^2 ^-^ 3*^y

-- >>> putStrLn $ prettyNumSpray spray

-- 2*x^2 - 3*y

--

-- prop> lone 0 == unitSpray

lone :: AlgRing.C a => Int -> Spray a
lone :: forall a. C a => Int -> Spray a
lone Int
n = if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 
  then Powers -> a -> HashMap Powers a
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton (Int -> Int -> Powers
lonePower Int
n Int
1) a
forall a. C a => a
AlgRing.one
  else String -> HashMap Powers a
forall a. HasCallStack => String -> a
error String
"lone: invalid index."

-- | The @n@-th polynomial variable for rational sprays; this is just a 

-- specialization of `lone`

qlone :: Int -> QSpray
qlone :: Int -> Spray Rational
qlone = Int -> Spray Rational
forall a. C a => Int -> Spray a
lone

-- | The spray @x_n^p@; more efficient than exponentiating @lone n@

--

-- prop> lone' 2 10 = lone 2 ^**^ 10

lone' :: 
     AlgRing.C a 
  => Int     -- ^ index 

  -> Int     -- ^ exponent

  -> Spray a
lone' :: forall a. C a => Int -> Int -> Spray a
lone' Int
n Int
p 
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0     = String -> Spray a
forall a. HasCallStack => String -> a
error String
"lone': invalid index."
  | Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0     = String -> Spray a
forall a. HasCallStack => String -> a
error String
"lone': invalid exponent"
  | Bool
otherwise = Powers -> a -> Spray a
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton (Int -> Int -> Powers
lonePower Int
n Int
p) a
forall a. C a => a
AlgRing.one

-- | The rational spray @x_n^p@

qlone' :: 
     Int     -- ^ index 

  -> Int     -- ^ exponent

  -> QSpray
qlone' :: Int -> Int -> Spray Rational
qlone' = Int -> Int -> Spray Rational
forall a. C a => Int -> Int -> Spray a
lone'

loneTerm' :: AlgRing.C a => Int -> Int -> Term a
loneTerm' :: forall a. C a => Int -> Int -> Term a
loneTerm' Int
n Int
p = (Int -> Int -> Powers
lonePower Int
n Int
p, a
forall a. C a => a
AlgRing.one)

-- | Monomial spray, e.g. @monomial [(1,4),(3,2)]@ is @x^4.z^2@; indices 

-- and exponents must be positive but this is not checked

-- prop> monomial [(1, 4), (3, 2)] == (lone 1 ^**^ 4) ^*^ (lone 3 ^**^ 2)

monomial :: 
     AlgRing.C a
  => [(Int, Int)] -- ^ list of (index, exponent); duplicates are deleted

  -> Spray a
monomial :: forall a. C a => [(Int, Int)] -> Spray a
monomial [(Int, Int)]
nps = if [(Int, Int)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Int, Int)]
nps 
  then Spray a
forall a. C a => Spray a
unitSpray 
  else Powers -> a -> Spray a
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton (Exponents -> Powers
powerize Exponents
expnts) a
forall a. C a => a
AlgRing.one
  where 
    nps' :: [(Int, Int)]
nps' = [(Int, Int)] -> [(Int, Int)]
forall a. Eq a => [a] -> [a]
nub [(Int, Int)]
nps
    nv :: Int
nv = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (((Int, Int) -> Int) -> [(Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Int) -> Int
forall a b. (a, b) -> a
fst [(Int, Int)]
nps')
    expnts :: Exponents
expnts = [Int] -> Exponents
forall a. [a] -> Seq a
S.fromList ([Int] -> Exponents) -> [Int] -> Exponents
forall a b. (a -> b) -> a -> b
$ [Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (Int -> [(Int, Int)] -> Maybe Int
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Int
i [(Int, Int)]
nps') | Int
i <- [Int
1 .. Int
nv]]

-- | Monomial rational spray, a specialization of 'monomial'

--

-- prop> qmonomial [(1, 4), (3, 2)] == (qlone 1 ^**^ 4) ^*^ (qlone 3 ^**^ 2)

qmonomial :: 
     [(Int, Int)]
  -> QSpray
qmonomial :: [(Int, Int)] -> Spray Rational
qmonomial = [(Int, Int)] -> Spray Rational
forall a. C a => [(Int, Int)] -> Spray a
monomial

-- | The unit spray

--

-- prop> spray ^*^ unitSpray == spray

unitSpray :: AlgRing.C a => Spray a
unitSpray :: forall a. C a => Spray a
unitSpray = Powers -> a -> HashMap Powers a
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton Powers
nullPowers a
forall a. C a => a
AlgRing.one

-- | The null spray

--

-- prop> spray ^+^ zeroSpray == spray

zeroSpray :: (Eq a, AlgAdd.C a) => Spray a
zeroSpray :: forall a. (Eq a, C a) => Spray a
zeroSpray = Spray a
forall a. C a => a
AlgAdd.zero

-- | Whether a spray is the zero spray

isZeroSpray :: Spray a -> Bool
isZeroSpray :: forall a. Spray a -> Bool
isZeroSpray = HashMap Powers a -> Bool
forall k v. HashMap k v -> Bool
HM.null 

-- | Constant spray

--

-- prop> constantSpray 3 == 3 *^ unitSpray

constantSpray :: (Eq a, AlgAdd.C a) => a -> Spray a
constantSpray :: forall a. (Eq a, C a) => a -> Spray a
constantSpray a
c = if a
c a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero 
  then HashMap Powers a
forall k v. HashMap k v
HM.empty 
  else Powers -> a -> HashMap Powers a
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton Powers
nullPowers a
c

-- | Get coefficient of a term of a spray 

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> p = 2 *^ (2 *^ (x^**^3 ^*^ y^**^2)) ^+^ 4*^z ^+^ 5*^unitSpray

-- >>> getCoefficient [3, 2] p -- coefficient of x^3.y^2 

-- 4

-- >>> getCoefficient [3, 2, 0] p -- same as getCoefficient [3, 2] p 

-- 4

-- >>> getCoefficient [0, 4] p -- coefficient of y^4

-- 0

getCoefficient :: 
    AlgAdd.C a 
  => [Int]   -- ^ sequence of exponents; trailing zeros are dropped

  -> Spray a -- ^ spray

  -> a       -- ^ coefficient of the monomial given by the sequence of exponents

getCoefficient :: forall a. C a => [Int] -> Spray a -> a
getCoefficient [Int]
expnts = Powers -> Spray a -> a
forall a. C a => Powers -> Spray a -> a
getCoefficient' Powers
powers
  where
    powers :: Powers
powers = Exponents -> Powers
makePowers ([Int] -> Exponents
forall a. [a] -> Seq a
S.fromList [Int]
expnts)

getCoefficient' :: AlgAdd.C a => Powers -> Spray a -> a
getCoefficient' :: forall a. C a => Powers -> Spray a -> a
getCoefficient' Powers
powers Spray a
spray = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
forall a. C a => a
AlgAdd.zero (Powers -> Spray a -> Maybe a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup Powers
powers Spray a
spray)

-- | Get the constant term of a spray

--

-- prop> getConstantTerm p == getCoefficient [] p 

getConstantTerm :: AlgAdd.C a => Spray a -> a
getConstantTerm :: forall a. C a => Spray a -> a
getConstantTerm = Powers -> Spray a -> a
forall a. C a => Powers -> Spray a -> a
getCoefficient' Powers
nullPowers

-- | remove the constant term of a spray

removeConstantTerm :: Spray a -> Spray a
removeConstantTerm :: forall a. Spray a -> Spray a
removeConstantTerm = Powers -> HashMap Powers a -> HashMap Powers a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete Powers
nullPowers

-- | Whether a spray is constant; same as `isConstant`

isConstantSpray :: (Eq a, AlgRing.C a) => Spray a -> Bool
isConstantSpray :: forall a. (Eq a, C a) => Spray a -> Bool
isConstantSpray = Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant

-- | helper function to unify evalSpray and evalSpraySpray

evalSprayHelper :: forall a. AlgRing.C a => [a] -> Spray a -> a
evalSprayHelper :: forall a. C a => [a] -> Spray a -> a
evalSprayHelper [a]
xyz Spray a
spray = 
  [a] -> a
forall a. C a => [a] -> a
AlgAdd.sum ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ (Term a -> a) -> [Term a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Term a -> a
evalTerm (Spray a -> [Term a]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
spray)
  where
    evalTerm :: Term a -> a
    evalTerm :: Term a -> a
evalTerm (Powers
powers, a
coeff) = 
      a
coeff a -> a -> a
forall a. C a => a -> a -> a
AlgRing.* [a] -> a
forall a. C a => [a] -> a
AlgRing.product ((a -> Integer -> a) -> [a] -> [Integer] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> Integer -> a
forall a. C a => a -> Integer -> a
(AlgRing.^) [a]
xyz [Integer]
pows)
      where 
        pows :: [Integer]
pows = Seq Integer -> [Integer]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> Exponents -> Seq Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Powers -> Exponents
exponents Powers
powers)

-- | Evaluates a spray; same as `evaluate`

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> spray = 2*^x^**^2 ^-^ 3*^y

-- >>> evalSpray spray [2, 1]

-- 5

evalSpray :: (Eq a, AlgRing.C a) => Spray a -> [a] -> a
evalSpray :: forall a. (Eq a, C a) => Spray a -> [a] -> a
evalSpray = Spray a -> [a] -> a
Spray a -> [BaseRing (Spray a)] -> BaseRing (Spray a)
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate

-- | Evaluates the coefficients of a spray with spray coefficients; 

-- same as `substituteParameters`

evalSpraySpray :: (Eq a, AlgRing.C a) => Spray (Spray a) -> [a] -> Spray a
evalSpraySpray :: forall a. (Eq a, C a) => Spray (Spray a) -> [a] -> Spray a
evalSpraySpray Spray (Spray a)
spray [a]
xyz = if [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xyz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n 
  then Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ (Spray a -> a) -> Spray (Spray a) -> Spray a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map ([a] -> Spray a -> a
forall a. C a => [a] -> Spray a -> a
evalSprayHelper [a]
xyz) Spray (Spray a)
spray
  else String -> Spray a
forall a. HasCallStack => String -> a
error String
"evalSpraySpray: not enough values provided."
    where 
      n :: Int
n = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (HashMap Powers Int -> [Int]
forall k v. HashMap k v -> [v]
HM.elems (HashMap Powers Int -> [Int]) -> HashMap Powers Int -> [Int]
forall a b. (a -> b) -> a -> b
$ (Spray a -> Int) -> Spray (Spray a) -> HashMap Powers Int
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray (Spray a)
spray)

-- | spray from term

fromTerm :: Term a -> Spray a
fromTerm :: forall a. Term a -> Spray a
fromTerm (Powers
pows, a
coeff) = Powers -> a -> HashMap Powers a
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton Powers
pows a
coeff

-- | Substitutes some values to some variables of a spray; same as `substitute`

--

-- >>> x1 = lone 1 :: Spray Int

-- >>> x2 = lone 2 :: Spray Int

-- >>> x3 = lone 3 :: Spray Int

-- >>> p = x1^**^2 ^-^ x2 ^+^ x3 ^-^ unitSpray

-- >>> p' = substituteSpray [Just 2, Nothing, Just 3] p

-- >>> putStrLn $ prettyNumSprayX1X2X3 "x" p'

-- -x2 + 6 

substituteSpray :: (Eq a, AlgRing.C a) => [Maybe a] -> Spray a -> Spray a
substituteSpray :: forall a. (Eq a, C a) => [Maybe a] -> Spray a -> Spray a
substituteSpray = [Maybe a] -> Spray a -> Spray a
[Maybe (BaseRing (Spray a))] -> Spray a -> Spray a
forall b. FunctionLike b => [Maybe (BaseRing b)] -> b -> b
substitute 

-- | Converts a spray with rational coefficients to a spray with double 

-- coefficients (useful for evaluation)

fromRationalSpray :: Spray Rational -> Spray Double
fromRationalSpray :: Spray Rational -> Spray Double
fromRationalSpray = (Rational -> Double) -> Spray Rational -> Spray Double
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map Rational -> Double
forall a. Fractional a => Rational -> a
fromRational

-- | Sustitutes the variables of a spray with some sprays; same as `changeVariables`

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> p = x ^+^ y

-- >>> q = composeSpray p [x ^+^ y ^+^ z, z]

-- >>> putStrLn $ prettyNumSpray' q

-- X + Y + 2*Z

composeSpray :: 
  forall a. (AlgRing.C a, Eq a) => Spray a -> [Spray a] -> Spray a
composeSpray :: forall a. (C a, Eq a) => Spray a -> [Spray a] -> Spray a
composeSpray Spray a
p = Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a)
-> ([Spray a] -> Spray a) -> [Spray a] -> Spray a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Spray (Spray a) -> [Spray a] -> Spray a
forall a. (Eq a, C a) => Spray a -> [a] -> a
evalSpray (Spray a -> Spray (Spray a)
identify Spray a
p)
  where 
    identify :: Spray a -> Spray (Spray a)
    identify :: Spray a -> Spray (Spray a)
identify = (a -> Spray a) -> Spray a -> Spray (Spray a)
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray

-- | Creates a spray from a list of terms

fromList :: 
  (AlgRing.C a, Eq a)
  => [([Int], a)]        -- ^ list of (exponents, coefficient)

  -> Spray a
fromList :: forall a. (C a, Eq a) => [([Int], a)] -> Spray a
fromList [([Int], a)]
x = Spray a -> Spray a
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> [(Powers, a)] -> Spray a
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> [(k, v)] -> HashMap k v
HM.fromListWith a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+) ([(Powers, a)] -> Spray a) -> [(Powers, a)] -> Spray a
forall a b. (a -> b) -> a -> b
$ (([Int], a) -> (Powers, a)) -> [([Int], a)] -> [(Powers, a)]
forall a b. (a -> b) -> [a] -> [b]
map
              (([Int] -> Powers) -> ([Int], a) -> (Powers, a)
forall a a' b. (a -> a') -> (a, b) -> (a', b)
first (Exponents -> Powers
makePowers (Exponents -> Powers) -> ([Int] -> Exponents) -> [Int] -> Powers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> Exponents
forall a. [a] -> Seq a
S.fromList)) [([Int], a)]
x


-- pretty stuff ---------------------------------------------------------------


-- | Prints a spray; this function is exported for possible usage in other packages

showSpray ::
     (a -> String)           -- ^ function mapping a coefficient to a string, typically 'show'

  -> (String, String)        -- ^ pair of braces to enclose the coefficients

  -> ([Exponents] -> [String]) -- ^ function mapping a list of exponents to a list of strings representing the monomials corresponding to these exponents

  -> Spray a                 -- ^ the spray to be printed

  -> String
showSpray :: forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray a -> String
showCoef (String, String)
braces [Exponents] -> [String]
showMonomials Spray a
spray = 
  if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray 
    then String
"0"
    else Text -> String
unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
intercalate (String -> Text
pack String
" + ") [Text]
stringTerms
  where
    terms :: [Term a]
terms = Spray a -> [Term a]
forall a. Spray a -> [Term a]
orderedTerms Spray a
spray
    ([Powers]
powers, [a]
coeffs) = [Term a] -> ([Powers], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip [Term a]
terms
    stringMonomials :: [String]
stringMonomials = [Exponents] -> [String]
showMonomials ((Powers -> Exponents) -> [Powers] -> [Exponents]
forall a b. (a -> b) -> [a] -> [b]
map Powers -> Exponents
exponents [Powers]
powers)
    stringTerms :: [Text]
stringTerms = (a -> String -> Text) -> [a] -> [String] -> [Text]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> String -> Text
f [a]
coeffs [String]
stringMonomials
    f :: a -> String -> Text
f a
coeff String
smonomial 
      | String
smonomial String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"" = String -> Text
pack String
scoeff'
      | String
scoeff String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
""    = String -> Text
pack String
smonomial
      | Bool
otherwise       = String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
scoeff' String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"*" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
smonomial
      where
        scoeff :: String
scoeff  = a -> String
showCoef a
coeff
        scoeff' :: String
scoeff' = (String, String) -> ShowS
bracify (String, String)
braces String
scoeff 

-- | Prints a spray, with monomials shown as "x.z^2", and with 

-- a user-defined showing function for the coefficients

showSprayXYZ ::
     (a -> String)           -- ^ function mapping a coefficient to a string, typically 'show'

  -> (String, String)        -- ^ used to enclose the coefficients, usually a pair of braces

  -> [String]                -- ^ typically some letters, to print the variables

  -> Spray a                 -- ^ the spray to be printed

  -> String
showSprayXYZ :: forall a.
(a -> String) -> (String, String) -> [String] -> Spray a -> String
showSprayXYZ a -> String
showCoef (String, String)
braces [String]
letters Spray a
spray =
  if [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
letters
    then ShowS
forall a. HasCallStack => String -> a
error String
"showSprayXYZ: empty list of strings."
    else (a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray a -> String
showCoef (String, String)
braces ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
letters) Spray a
spray

-- | Prints a spray, with monomials shown as @\"x.z^2\"@, and with 

-- a user-defined showing function for the coefficients; this is the same as 

-- the function `showSprayXYZ` with the pair of braces @("(", ")")@

showSprayXYZ' ::
     (a -> String)           -- ^ function mapping a coefficient to a string, typically 'show'

  -> [String]                -- ^ typically some letters, to print the variables

  -> Spray a                 -- ^ the spray to be printed

  -> String
showSprayXYZ' :: forall a. (a -> String) -> [String] -> Spray a -> String
showSprayXYZ' a -> String
showCoef = (a -> String) -> (String, String) -> [String] -> Spray a -> String
forall a.
(a -> String) -> (String, String) -> [String] -> Spray a -> String
showSprayXYZ a -> String
showCoef (String
"(", String
")")

-- | Pretty form of a spray with monomials displayed in the style of @\"x.z^2\"@; 

-- you should rather use `prettyNumSprayXYZ` or `prettyQSprayXYZ` if your 

-- coefficients are numeric

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ 4*^z^**^3

-- >>> putStrLn $ prettySprayXYZ ["X", "Y", "Z"] p

-- (2)*X + (3)*Y^2 + (-4)*Z^3

-- >>> putStrLn $ prettySprayXYZ ["X", "Y"] p

-- (2)*X1 + (3)*X2^2 + (-4)*X3^3

prettySprayXYZ :: 
     (Show a) 
  => [String]                -- ^ typically some letters, to print the variables

  -> Spray a                 -- ^ the spray to be printed

  -> String
prettySprayXYZ :: forall a. Show a => [String] -> Spray a -> String
prettySprayXYZ = (a -> String) -> [String] -> Spray a -> String
forall a. (a -> String) -> [String] -> Spray a -> String
showSprayXYZ' a -> String
forall a. Show a => a -> String
show
  
-- | Pretty form of a spray, with monomials shown as "x1.x3^2", and with 

-- a user-defined showing function for the coefficients

showSprayX1X2X3 ::
     (a -> String)           -- ^ function mapping a coefficient to a string, typically 'show'

  -> (String, String)        -- ^ used to enclose the coefficients

  -> String                  -- ^ typically a letter, to print the non-indexed variables

  -> Spray a                 -- ^ the spray to be printed

  -> String
showSprayX1X2X3 :: forall a.
(a -> String) -> (String, String) -> String -> Spray a -> String
showSprayX1X2X3 a -> String
showCoef (String, String)
braces String
letter =
  (a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray a -> String
showCoef (String, String)
braces (String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
letter)

-- | Pretty form of a spray, with monomials shown as "x1.x3^2", and with 

-- a user-defined showing function for the coefficients; this is the same as 

-- the function `showSprayX1X2X3` with the pair of braces @("(", ")")@ used to 

-- enclose the coefficients

showSprayX1X2X3' ::
     (a -> String)           -- ^ function mapping a coefficient to a string, e.g. 'show'

  -> String                  -- ^ typically a letter, to print the non-indexed variables

  -> Spray a                 -- ^ the spray to be printed

  -> String
showSprayX1X2X3' :: forall a. (a -> String) -> String -> Spray a -> String
showSprayX1X2X3' a -> String
showCoef = (a -> String) -> (String, String) -> String -> Spray a -> String
forall a.
(a -> String) -> (String, String) -> String -> Spray a -> String
showSprayX1X2X3 a -> String
showCoef (String
"(", String
")")

-- | Pretty form of a spray with monomials displayed in the style of @\"x1.x3^2\"@; 

-- you should rather use `prettyNumSprayX1X2X3` or `prettyQSprayX1X2X3` if your 

-- coefficients are numeric

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> spray = 2*^x ^+^ 3*^y^**^2 ^-^ 4*^z^**^3

-- >>> putStrLn $ prettySprayX1X2X3 "X" spray

-- (2)*X1 + (3)*X2^2 + (-4)*X3^3

prettySprayX1X2X3 :: 
     Show a 
  => String                -- ^ typically a letter, to print the non-indexed variables

  -> Spray a               -- ^ the spray to be printed

  -> String
prettySprayX1X2X3 :: forall a. Show a => String -> Spray a -> String
prettySprayX1X2X3 = (a -> String) -> String -> Spray a -> String
forall a. (a -> String) -> String -> Spray a -> String
showSprayX1X2X3' a -> String
forall a. Show a => a -> String
show

-- | Pretty form of a spray with monomials displayed in the style of @\"x.z^2\"@; 

-- you should rather use `prettyNumSpray` or `prettyQSpray` if you deal with 

-- sprays with numeric coefficients

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ 4*^z^**^3

-- >>> putStrLn $ prettySpray p

-- (2)*x + (3)*y^2 + (-4)*z^3

-- >>> putStrLn $ prettySpray (p ^+^ lone 4)

-- (2)*x1 + (3)*x2^2 + (-4)*x3^3 + x4

--

-- prop> prettySpray spray == prettySprayXYZ ["x", "y", "z"] spray

prettySpray :: (Show a) => Spray a -> String
prettySpray :: forall a. Show a => Spray a -> String
prettySpray = [String] -> Spray a -> String
forall a. Show a => [String] -> Spray a -> String
prettySprayXYZ [String
"x", String
"y", String
"z"]

-- | Pretty form of a spray, with monomials shown as @\"x1.x3^2\"@; use 

-- `prettySprayX1X2X3` to change the letter (or `prettyNumSprayX1X2X3` 

-- or `prettyQSprayX1X2X3` if the coefficients are numeric)

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ 4*^z^**^3

-- >>> putStrLn $ prettySpray' p

-- (2)*x1 + (3)*x2^2 + (-4)*x3^3 

prettySpray' :: Show a => Spray a -> String
prettySpray' :: forall a. Show a => Spray a -> String
prettySpray' = String -> Spray a -> String
forall a. Show a => String -> Spray a -> String
prettySprayX1X2X3 String
"x"

-- | showMonomialOld "x" [0, 2, 1] = x^(0, 2, 1)

showMonomialsOld :: String -> [Exponents] -> [String]
showMonomialsOld :: String -> [Exponents] -> [String]
showMonomialsOld String
var = (Exponents -> String) -> [Exponents] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Exponents -> String
showMonomialOld String
var) 
  where
    showMonomialOld :: String -> Exponents -> String
    showMonomialOld :: String -> Exponents -> String
showMonomialOld String
a Exponents
pows = 
      Text -> String
unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text
append (String -> Text
pack String
x) (Char -> Text -> Text
cons Char
'(' (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Char -> Text
snoc Text
string Char
')')
      where
        x :: String
x      = String
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"^"
        string :: Text
string = Text -> [Text] -> Text
intercalate (String -> Text
pack String
", ") ((Int -> Text) -> [Int] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Text
pack (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show) (Exponents -> [Int]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList Exponents
pows))

-- | Pretty form of a spray; you will probably prefer `prettySpray` or `prettySpray'`

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ 4*^z^**^3

-- >>> putStrLn $ prettySpray'' "x" p

-- (2)*x^(1) + (3)*x^(0, 2) + (-4)*x^(0, 0, 3)

prettySpray'' ::
     Show a 
  => String        -- ^ a string denoting the variables, e.g. \"x\"

  -> Spray a       -- ^ the spray

  -> String
prettySpray'' :: forall a. Show a => String -> Spray a -> String
prettySpray'' String
var = (a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray a -> String
forall a. Show a => a -> String
show (String
"(", String
")") (String -> [Exponents] -> [String]
showMonomialsOld String
var)

-- | Show a spray with numeric coefficients; this function is exported for 

-- possible usage in other packages

showNumSpray :: 
     (Num a, Ord a)
  => ([Exponents] -> [String]) -- ^ function mapping a list of monomial exponents to a list of strings representing the monomials

  -> (a -> String)             -- ^ function mapping a positive coefficient to a string

  -> Spray a
  -> String
showNumSpray :: forall a.
(Num a, Ord a) =>
([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
showNumSpray [Exponents] -> [String]
showMonomials a -> String
showCoeff Spray a
spray = 
  if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray 
    then String
"0" 
    else [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (String -> ShowS) -> [String] -> [String] -> [String]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith String -> ShowS
forall a. [a] -> [a] -> [a]
(++) [String]
stringSigns [String]
stringTerms
  where
    terms :: [Term a]
terms = Spray a -> [Term a]
forall a. Spray a -> [Term a]
orderedTerms Spray a
spray
    coeffs :: [a]
coeffs = (Term a -> a) -> [Term a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Term a -> a
forall a b. (a, b) -> b
snd [Term a]
terms
    (a
firstCoeff, [a]
otherCoeffs) = Maybe (a, [a]) -> (a, [a])
forall a. HasCallStack => Maybe a -> a
fromJust ([a] -> Maybe (a, [a])
forall a. [a] -> Maybe (a, [a])
uncons [a]
coeffs)
    firstSign :: String
firstSign   = if a
firstCoeff a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 then String
"" else String
"-"
    otherSigns :: [String]
otherSigns  = (a -> String) -> [a] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\a
x -> if a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 then String
" + " else String
" - ") [a]
otherCoeffs
    stringSigns :: [String]
stringSigns = String
firstSign String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
otherSigns
    absCoeffs :: [a]
absCoeffs = (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map a -> a
forall a. Num a => a -> a
abs [a]
coeffs
    powers :: [Exponents]
powers = (Term a -> Exponents) -> [Term a] -> [Exponents]
forall a b. (a -> b) -> [a] -> [b]
map (Powers -> Exponents
exponents (Powers -> Exponents) -> (Term a -> Powers) -> Term a -> Exponents
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term a -> Powers
forall a b. (a, b) -> a
fst) [Term a]
terms
    stringMonomials :: [String]
stringMonomials = [Exponents] -> [String]
showMonomials [Exponents]
powers
    stringTerms :: [String]
stringTerms = (a -> ShowS) -> [a] -> [String] -> [String]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> ShowS
f [a]
absCoeffs [String]
stringMonomials
    f :: a -> ShowS
f a
acoeff String
smonomial 
      | String
smonomial String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"" = a -> String
showCoeff a
acoeff
      | String
scoeff String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
""    = String
smonomial
      | Bool
otherwise       = String
scoeff String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"*" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
smonomial
      where
        scoeff :: String
scoeff = if a
acoeff a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 then String
"" else a -> String
showCoeff a
acoeff

-- | showMonomialX1X2X3 "X" [0, 2, 1] = "X2^2.X3"

showMonomialX1X2X3 :: String -> Exponents -> Text
showMonomialX1X2X3 :: String -> Exponents -> Text
showMonomialX1X2X3 String
x Exponents
pows = Text
x1x2x3
 where
  f :: Int -> Int -> Text
f Int
i Int
p 
    | Int
p Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0    = String -> Text
pack String
""
    | Int
p Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1    = String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i
    | Bool
otherwise = String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"^" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
p
  indices :: [Int]
indices = (Int -> Bool) -> Exponents -> [Int]
forall a. (a -> Bool) -> Seq a -> [Int]
S.findIndicesL (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) Exponents
pows
  x1x2x3 :: Text
x1x2x3 = 
    Text -> [Text] -> Text
intercalate (String -> Text
pack String
".") [Int -> Int -> Text
f (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Exponents
pows Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
i) | Int
i <- [Int]
indices]

-- | showMonomialsX1X2X3 "X" [[0, 2, 1], [1, 2]] = ["X2^2.X3", "X1.X2"]

showMonomialsX1X2X3 :: String -> [Exponents] -> [String]
showMonomialsX1X2X3 :: String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
x = (Exponents -> String) -> [Exponents] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> String
unpack (Text -> String) -> (Exponents -> Text) -> Exponents -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exponents -> Text
showMonomialX1X2X3 String
x)

-- | showMonomialXYZ ["X", "Y", "Z"] 3 [1, 2, 1] = X.Y^2.Z

--   showMonomialXYZ ["X", "Y", "Z"] 3 [1, 2, 1, 2] = X1.X2^2.X3.X4^2

showMonomialXYZ :: [String] -> Int -> Exponents -> Text
showMonomialXYZ :: [String] -> Int -> Exponents -> Text
showMonomialXYZ [String]
letters Int
n Exponents
pows = if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
letters
  then Text
xyz
  else String -> Exponents -> Text
showMonomialX1X2X3 ([String]
letters [String] -> Int -> String
forall a. HasCallStack => [a] -> Int -> a
!! Int
0) Exponents
pows
 where
  f :: String -> a -> Text
f String
letter a
p 
    | a
p a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0    = String -> Text
pack String
""
    | a
p a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1    = String -> Text
pack String
letter
    | Bool
otherwise = String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
letter String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"^" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
p
  indices :: [Int]
indices = (Int -> Bool) -> Exponents -> [Int]
forall a. (a -> Bool) -> Seq a -> [Int]
S.findIndicesL (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) Exponents
pows
  xyz :: Text
xyz = Text -> [Text] -> Text
intercalate (String -> Text
pack String
".") 
        [String -> Int -> Text
forall {a}. (Eq a, Num a, Show a) => String -> a -> Text
f ([String]
letters [String] -> Int -> String
forall a. HasCallStack => [a] -> Int -> a
!! Int
i) (Exponents
pows Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
i) | Int
i <- [Int]
indices]

-- | showMonomialsXYZ ["X", "Y", "Z"] [[0, 2, 1], [1, 2]] = ["Y^2.Z", "X.Y^2"]

showMonomialsXYZ :: [String] -> [Exponents] -> [String]
showMonomialsXYZ :: [String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
letters [Exponents]
powers = 
  (Exponents -> String) -> [Exponents] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> String
unpack (Text -> String) -> (Exponents -> Text) -> Exponents -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Int -> Exponents -> Text
showMonomialXYZ [String]
letters Int
n) [Exponents]
powers
  where 
    n :: Int
n = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ((Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Exponents -> Int
forall a. Seq a -> Int
S.length [Exponents]
powers)

-- | Pretty form of a spray with numeric coefficients, printing monomials as @\"x1.x3^2\"@

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ 4*^z^**^3

-- >>> putStrLn $ prettyNumSprayX1X2X3 "x" p

-- 2*x1 + 3*x2^2 - 4*x3^3 

prettyNumSprayX1X2X3 :: (Num a, Ord a, Show a)
  => String   -- ^ usually a letter such as @\"x\"@ to denote the non-indexed variables

  -> Spray a
  -> String
prettyNumSprayX1X2X3 :: forall a. (Num a, Ord a, Show a) => String -> Spray a -> String
prettyNumSprayX1X2X3 String
x = ([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
forall a.
(Num a, Ord a) =>
([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
showNumSpray (String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
x) a -> String
forall a. Show a => a -> String
show

-- | Pretty form of a spray with numeric coefficients, printing monomials as @\"x.z^2\"@

-- if possible, i.e. if enough letters are provided, otherwise as @\"x1.x3^2\"@

--

-- >>> x = lone 1 :: Spray Int

-- >>> y = lone 2 :: Spray Int

-- >>> z = lone 3 :: Spray Int

-- >>> w = lone 4 :: Spray Int

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ 4*^z^**^3

-- >>> putStrLn $ prettyNumSprayXYZ ["x","y","z"] p

-- 2*x + 3*y^2 - 4*z^3 

-- >>> putStrLn $ prettyNumSprayXYZ ["x","y","z"] (p ^+^ w)

-- 2*x1 + 3*x2^2 - 4*x3^3 + x4

-- >>> putStrLn $ prettyNumSprayXYZ ["a","b","c"] (p ^+^ w)

-- 2*a1 + 3*a2^2 - 4*a3^3 + a4

prettyNumSprayXYZ :: (Num a, Ord a, Show a)
  => [String] -- ^ usually some letters, denoting the variables

  -> Spray a
  -> String
prettyNumSprayXYZ :: forall a. (Num a, Ord a, Show a) => [String] -> Spray a -> String
prettyNumSprayXYZ [String]
letters = ([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
forall a.
(Num a, Ord a) =>
([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
showNumSpray ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
letters) a -> String
forall a. Show a => a -> String
show

-- | helper function for showQSpray

showRatio :: Rational -> String
showRatio :: Rational -> String
showRatio Rational
q = if Integer
d Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1 
  then Integer -> String
forall a. Show a => a -> String
show Integer
n 
  else String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
d String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
  where
    n :: Integer
n = Rational -> Integer
forall a. Ratio a -> a
DR.numerator Rational
q
    d :: Integer
d = Rational -> Integer
forall a. Ratio a -> a
DR.denominator Rational
q 

-- | helper function for showQSpray' 

showRatio' :: (Eq a, Num a, Show a) => NumberRatio.T a -> String
showRatio' :: forall a. (Eq a, Num a, Show a) => T a -> String
showRatio' T a
q = if a
d a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 
  then a -> String
forall a. Show a => a -> String
show a
n 
  else String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
d String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
  where
    n :: a
n = T a -> a
forall a. T a -> a
NumberRatio.numerator T a
q
    d :: a
d = T a -> a
forall a. T a -> a
NumberRatio.denominator T a
q 

-- | Prints a `QSpray`; for internal usage but exported for usage in other packages

showQSpray :: 
   ([Exponents] -> [String]) -- ^ function printing monomials

  -> QSpray
  -> String
showQSpray :: ([Exponents] -> [String]) -> Spray Rational -> String
showQSpray [Exponents] -> [String]
showMonomials = ([Exponents] -> [String])
-> (Rational -> String) -> Spray Rational -> String
forall a.
(Num a, Ord a) =>
([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
showNumSpray [Exponents] -> [String]
showMonomials Rational -> String
showRatio

-- | Prints a `QSpray'`; for internal usage but exported for usage in other packages

showQSpray' :: 
   ([Exponents] -> [String]) -- ^ function mapping a list of monomials exponents to a list of strings

  -> QSpray'
  -> String
showQSpray' :: ([Exponents] -> [String]) -> Spray Rational' -> String
showQSpray' [Exponents] -> [String]
showMonomials = ([Exponents] -> [String])
-> (Rational' -> String) -> Spray Rational' -> String
forall a.
(Num a, Ord a) =>
([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
showNumSpray [Exponents] -> [String]
showMonomials Rational' -> String
forall a. (Eq a, Num a, Show a) => T a -> String
showRatio'

-- | Pretty form of a spray with rational coefficients, printing monomials in 

-- the style of @\"x1.x3^2\"@

--

-- >>> x = lone 1 :: QSpray

-- >>> y = lone 2 :: QSpray

-- >>> z = lone 3 :: QSpray

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ (4%3)*^z^**^3

-- >>> putStrLn $ prettyQSprayX1X2X3 "x" p

-- 2*x1 + 3*x2^2 - (4/3)*x3^3 

prettyQSprayX1X2X3 :: 
     String   -- ^ usually a letter such as @\"x\"@, to denote the non-indexed variables

  -> QSpray
  -> String
prettyQSprayX1X2X3 :: String -> Spray Rational -> String
prettyQSprayX1X2X3 String
x = ([Exponents] -> [String]) -> Spray Rational -> String
showQSpray (String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
x)

-- | Same as `prettyQSprayX1X2X3` but for a `QSpray'` spray

prettyQSprayX1X2X3' :: 
     String   -- ^ usually a letter such as @\"x\"@, to denote the non-indexed variables

  -> QSpray'
  -> String
prettyQSprayX1X2X3' :: String -> Spray Rational' -> String
prettyQSprayX1X2X3' String
x = ([Exponents] -> [String]) -> Spray Rational' -> String
showQSpray' (String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
x)

-- | Pretty form of a spray with rational coefficients, printing monomials in 

-- the style of @\"x.z^2\"@ with the provided letters if possible, i.e. if enough 

-- letters are provided, otherwise in the style @\"x1.x3^2\"@, taking the first 

-- provided letter to denote the non-indexed variables

--

-- >>> x = lone 1 :: QSpray

-- >>> y = lone 2 :: QSpray

-- >>> z = lone 3 :: QSpray

-- >>> p = 2*^x ^+^ 3*^y^**^2 ^-^ (4%3)*^z^**^3

-- >>> putStrLn $ prettyQSprayXYZ ["x","y","z"] p

-- 2*x + 3*y^2 - (4/3)*z^3 

-- >>> putStrLn $ prettyQSprayXYZ ["x","y"] p

-- 2*x1 + 3*x2^2 - (4%3)*x3^3

-- >>> putStrLn $ prettyQSprayXYZ ["a","b"] p

-- 2*a1 + 3*a2^2 - (4/3)*a3^3

prettyQSprayXYZ :: 
    [String]   -- ^ usually some letters, to denote the variables

  -> QSpray
  -> String
prettyQSprayXYZ :: [String] -> Spray Rational -> String
prettyQSprayXYZ [String]
letters = ([Exponents] -> [String]) -> Spray Rational -> String
showQSpray ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
letters)

-- | Same as `prettyQSprayXYZ` but for a `QSpray'` spray

prettyQSprayXYZ' :: 
    [String]   -- ^ usually some letters, to denote the variables

  -> QSpray'
  -> String
prettyQSprayXYZ' :: [String] -> Spray Rational' -> String
prettyQSprayXYZ' [String]
letters = ([Exponents] -> [String]) -> Spray Rational' -> String
showQSpray' ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
letters)

-- | Pretty printing of a spray with rational coefficients

-- prop> prettyQSpray == prettyQSprayXYZ ["x", "y", "z"]

prettyQSpray :: QSpray -> String
prettyQSpray :: Spray Rational -> String
prettyQSpray = [String] -> Spray Rational -> String
prettyQSprayXYZ [String
"x", String
"y", String
"z"]

-- | Pretty printing of a spray with rational coefficients

-- prop> prettyQSpray'' == prettyQSprayXYZ ["X", "Y", "Z"]

prettyQSpray'' :: QSpray -> String
prettyQSpray'' :: Spray Rational -> String
prettyQSpray'' = [String] -> Spray Rational -> String
prettyQSprayXYZ [String
"X", String
"Y", String
"Z"]

-- | Pretty printing of a spray with rational coefficients

-- prop> prettyQSpray' == prettyQSprayXYZ' ["x", "y", "z"]

prettyQSpray' :: QSpray' -> String
prettyQSpray' :: Spray Rational' -> String
prettyQSpray' = [String] -> Spray Rational' -> String
prettyQSprayXYZ' [String
"x", String
"y", String
"z"]

-- | Pretty printing of a spray with rational coefficients

-- prop> prettyQSpray''' == prettyQSprayXYZ' ["X", "Y", "Z"]

prettyQSpray''' :: QSpray' -> String
prettyQSpray''' :: Spray Rational' -> String
prettyQSpray''' = [String] -> Spray Rational' -> String
prettyQSprayXYZ' [String
"X", String
"Y", String
"Z"]

-- | Pretty printing of a spray with numeric coefficients

-- prop> prettyNumSpray == prettyNumSprayXYZ ["x", "y", "z"]

prettyNumSpray :: (Num a, Ord a, Show a) => Spray a -> String
prettyNumSpray :: forall a. (Num a, Ord a, Show a) => Spray a -> String
prettyNumSpray = [String] -> Spray a -> String
forall a. (Num a, Ord a, Show a) => [String] -> Spray a -> String
prettyNumSprayXYZ [String
"x", String
"y", String
"z"]

-- | Pretty printing of a spray with numeric coefficients

-- prop> prettyNumSpray' == prettyNumSprayXYZ ["X", "Y", "Z"]

prettyNumSpray' :: (Num a, Ord a, Show a) => Spray a -> String
prettyNumSpray' :: forall a. (Num a, Ord a, Show a) => Spray a -> String
prettyNumSpray' = [String] -> Spray a -> String
forall a. (Num a, Ord a, Show a) => [String] -> Spray a -> String
prettyNumSprayXYZ [String
"X", String
"Y", String
"Z"]


-- misc -----------------------------------------------------------------------


-- | spray as safe spray

safeSpray :: Spray a -> SafeSpray a
safeSpray :: forall a. Spray a -> SafeSpray a
safeSpray = (Powers -> Exponents) -> HashMap Powers a -> HashMap Exponents a
forall k2 k1 v.
(Eq k2, Hashable k2) =>
(k1 -> k2) -> HashMap k1 v -> HashMap k2 v
HM.mapKeys Powers -> Exponents
exponents

getCoefficient'' :: AlgAdd.C a => Exponents -> SafeSpray a -> a
getCoefficient'' :: forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' Exponents
powers SafeSpray a
spray' = 
  a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
forall a. C a => a
AlgAdd.zero (Exponents -> SafeSpray a -> Maybe a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup Exponents
powers SafeSpray a
spray')

getConstantTerm'' :: AlgAdd.C a => SafeSpray a -> a
getConstantTerm'' :: forall a. C a => SafeSpray a -> a
getConstantTerm'' = Exponents -> SafeSpray a -> a
forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' Exponents
forall a. Seq a
S.empty

removeConstantTerm'' :: SafeSpray a -> SafeSpray a
removeConstantTerm'' :: forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' = Exponents -> HashMap Exponents a -> HashMap Exponents a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete Exponents
forall a. Seq a
S.empty

-- | Sum of sprays

sumOfSprays :: (Eq a, AlgAdd.C a) => [Spray a] -> Spray a
sumOfSprays :: forall a. (Eq a, C a) => [Spray a] -> Spray a
sumOfSprays = [Spray a] -> Spray a
forall a. C a => [a] -> a
AlgAdd.sum

-- | Product of sprays

productOfSprays :: (Eq a, AlgRing.C a) => [Spray a] -> Spray a
productOfSprays :: forall a. (Eq a, C a) => [Spray a] -> Spray a
productOfSprays = [Spray a] -> Spray a
forall a. C a => [a] -> a
AlgRing.product

-- | ordered terms of a spray

orderedTerms :: Spray a -> [Term a]
orderedTerms :: forall a. Spray a -> [Term a]
orderedTerms Spray a
spray = 
  (Term a -> Term a -> Ordering) -> [Term a] -> [Term a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((Exponents -> Exponents -> Ordering)
-> Exponents -> Exponents -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip Exponents -> Exponents -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Exponents -> Exponents -> Ordering)
-> (Term a -> Exponents) -> Term a -> Term a -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (Powers -> Exponents
exponents (Powers -> Exponents) -> (Term a -> Powers) -> Term a -> Exponents
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term a -> Powers
forall a b. (a, b) -> a
fst)) (Spray a -> [Term a]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
spray)

-- | Spray as a list

toList :: Spray a -> [([Int], a)]
toList :: forall a. Spray a -> [([Int], a)]
toList Spray a
p = HashMap [Int] a -> [([Int], a)]
forall k v. HashMap k v -> [(k, v)]
HM.toList (HashMap [Int] a -> [([Int], a)])
-> HashMap [Int] a -> [([Int], a)]
forall a b. (a -> b) -> a -> b
$ (Powers -> [Int]) -> Spray a -> HashMap [Int] a
forall k2 k1 v.
(Eq k2, Hashable k2) =>
(k1 -> k2) -> HashMap k1 v -> HashMap k2 v
HM.mapKeys (Exponents -> [Int]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList (Exponents -> [Int]) -> (Powers -> Exponents) -> Powers -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Powers -> Exponents
exponents) Spray a
p

-- | Bombieri spray (for internal usage in the \'__scubature__\' package)

bombieriSpray :: (Eq a, AlgAdd.C a) => Spray a -> Spray a
bombieriSpray :: forall a. (Eq a, C a) => Spray a -> Spray a
bombieriSpray = (Powers -> a -> a) -> HashMap Powers a -> HashMap Powers a
forall k v1 v2. (k -> v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.mapWithKey Powers -> a -> a
forall {a}. (C a, Eq a) => Powers -> a -> a
f
 where
  f :: Powers -> a -> a
f Powers
pows          = Int -> a -> a
forall a. (C a, Eq a) => Int -> a -> a
times (Exponents -> Int
forall {a}. (Num a, Enum a, Eq a) => Seq a -> a
pfactorial (Exponents -> Int) -> Exponents -> Int
forall a b. (a -> b) -> a -> b
$ Powers -> Exponents
exponents Powers
pows)
  pfactorial :: Seq a -> a
pfactorial Seq a
pows = [a] -> a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ Seq a -> [a]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList (Seq a -> [a]) -> Seq a -> [a]
forall a b. (a -> b) -> a -> b
$ a -> a
forall {a}. (Num a, Enum a) => a -> a
factorial (a -> a) -> Seq a -> Seq a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> Bool) -> Seq a -> Seq a
forall a. (a -> Bool) -> Seq a -> Seq a
S.filter (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0) Seq a
pows
  factorial :: a -> a
factorial a
n     = [a] -> a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [a
2 .. a
n]
  times :: Int -> a -> a
times Int
k a
x       = Int
k Int -> a -> a
forall a. (C a, Eq a) => Int -> a -> a
.^ a
x 

-- | Whether two sprays are equal up to a scalar factor

collinearSprays :: (Eq a, AlgRing.C a) => Spray a -> Spray a -> Bool
collinearSprays :: forall a. (Eq a, C a) => Spray a -> Spray a -> Bool
collinearSprays Spray a
spray1 Spray a
spray2 = 
  Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray1 Bool -> Bool -> Bool
&& Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray2 Bool -> Bool -> Bool
||
    (Bool -> Bool
not (Bool -> Bool) -> (Spray a -> Bool) -> Spray a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray) Spray a
spray1 Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> (Spray a -> Bool) -> Spray a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray) Spray a
spray2 Bool -> Bool -> Bool
&&
      (Powers, a) -> a
forall a b. (a, b) -> b
snd (Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm Spray a
spray1) BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
spray2 Spray a -> Spray a -> Bool
forall a. Eq a => a -> a -> Bool
== (Powers, a) -> a
forall a b. (a, b) -> b
snd (Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm Spray a
spray2) BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
spray1

-- | Checks whether the multivariate polynomial defined by a spray is homogeneous 

-- and also returns the degree in case this is true

isHomogeneousSpray :: (Eq a, AlgRing.C a) => Spray a -> (Bool, Maybe Int)
isHomogeneousSpray :: forall a. (Eq a, C a) => Spray a -> (Bool, Maybe Int)
isHomogeneousSpray Spray a
spray 
  | Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
spray                     = (Bool
True, Int -> Maybe Int
forall a. a -> Maybe a
Just Int
0)
  | Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
spray a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. C a => a
AlgAdd.zero = (Bool
False, Maybe Int
forall a. Maybe a
Nothing)
  | Bool
otherwise                            = (Bool
check, Maybe Int
deg)
  where
    degrees :: [Int]
degrees = (Powers -> Int) -> [Powers] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int
forall a. Num a => Seq a -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (Exponents -> Int) -> (Powers -> Exponents) -> Powers -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Powers -> Exponents
exponents) (Spray a -> [Powers]
forall k v. HashMap k v -> [k]
HM.keys Spray a
spray)
    check :: Bool
check = [Int] -> Bool
forall a. Eq a => [a] -> Bool
allSame [Int]
degrees
    deg :: Maybe Int
deg = if Bool
check then Int -> Maybe Int
forall a. a -> Maybe a
Just ([Int]
degrees [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
0) else Maybe Int
forall a. Maybe a
Nothing 

-- | Get all the exponents of a spray

allExponents :: Spray a -> [Exponents]
allExponents :: forall a. Spray a -> [Exponents]
allExponents Spray a
spray = (Powers -> Exponents) -> [Powers] -> [Exponents]
forall a b. (a -> b) -> [a] -> [b]
map Powers -> Exponents
exponents (Spray a -> [Powers]
forall k v. HashMap k v -> [k]
HM.keys Spray a
spray)

-- | Get all the coefficients of a spray

allCoefficients :: Spray a -> [a]
allCoefficients :: forall a. Spray a -> [a]
allCoefficients = HashMap Powers a -> [a]
forall k v. HashMap k v -> [v]
HM.elems

-- division stuff -------------------------------------------------------------


-- | index of the maximum of a list

-- maxWithIndex :: Ord a => [a] -> (Int, a)

-- maxWithIndex = maximumBy (comparing snd) . zip [0 .. ]


-- | leading term of a spray 

leadingTerm :: Spray a -> Term a
leadingTerm :: forall a. Spray a -> Term a
leadingTerm Spray a
p = (Powers
biggest, Spray a
p Spray a -> Powers -> a
forall k v.
(Eq k, Hashable k, HasCallStack) =>
HashMap k v -> k -> v
HM.! Powers
biggest) 
  where
    powers :: [Powers]
powers  = Spray a -> [Powers]
forall k v. HashMap k v -> [k]
HM.keys Spray a
p
    biggest :: Powers
biggest = (Powers -> Powers -> Ordering) -> [Powers] -> Powers
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
maximumBy ((Powers -> Exponents) -> Powers -> Powers -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Powers -> Exponents
exponents) [Powers]
powers
--    (i, biggest) = maxWithIndex powers

    -- biggest = powers !! i


-- | whether a term divides another term

divides :: Term a -> Term a -> Bool
divides :: forall a. Term a -> Term a -> Bool
divides (Powers
powsP, a
_) (Powers
powsQ, a
_) = Int
nvP Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
nvQ Bool -> Bool -> Bool
&& Bool
lower
  where
    nvP :: Int
nvP = Powers -> Int
nvariables Powers
powsP
    nvQ :: Int
nvQ = Powers -> Int
nvariables Powers
powsQ
    expntsP :: Exponents
expntsP = Powers -> Exponents
exponents Powers
powsP
    expntsQ :: Exponents
expntsQ = Powers -> Exponents
exponents Powers
powsQ
    lower :: Bool
lower   = ((Int, Int) -> Bool) -> Seq (Int, Int) -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
DF.all ((Int -> Int -> Bool) -> (Int, Int) -> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(<=)) (Exponents -> Exponents -> Seq (Int, Int)
forall a b. Seq a -> Seq b -> Seq (a, b)
S.zip Exponents
expntsP Exponents
expntsQ)

-- | quotient of term Q by term P, assuming P divides Q

quotient :: AlgField.C a => Term a -> Term a -> Term a
quotient :: forall a. C a => Term a -> Term a -> Term a
quotient (Powers
powsQ, a
coeffQ) (Powers
powsP, a
coeffP) = (Powers
pows, a
coeff)
  where
    (Exponents
expntsP, Exponents
expntsQ) = (Powers, Powers) -> (Exponents, Exponents)
harmonize (Powers
powsP, Powers
powsQ)
    expnts :: Exponents
expnts             = (Int -> Int -> Int) -> Exponents -> Exponents -> Exponents
forall a b c. (a -> b -> c) -> Seq a -> Seq b -> Seq c
S.zipWith (-) Exponents
expntsQ Exponents
expntsP
    pows :: Powers
pows               = Exponents -> Powers
makePowers Exponents
expnts
    coeff :: a
coeff              = a
coeffQ a -> a -> a
forall a. C a => a -> a -> a
AlgField./ a
coeffP

-- | Remainder of the division of a spray by a list of divisors, 

-- using the lexicographic ordering of the monomials

sprayDivisionRemainder :: forall a. (Eq a, AlgField.C a) 
                          => Spray a -> [Spray a] -> Spray a
sprayDivisionRemainder :: forall a. (Eq a, C a) => Spray a -> [Spray a] -> Spray a
sprayDivisionRemainder Spray a
p [Spray a]
qs = 
  if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 
    then String -> Spray a
forall a. HasCallStack => String -> a
error String
"sprayDivisionRemainder: the list of divisors is empty." 
    else Spray a -> Spray a -> Spray a
ogo Spray a
p Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  where
    n :: Int
n = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
qs
    qsltqs :: [(Spray a, Term a)]
qsltqs = [Spray a] -> [Term a] -> [(Spray a, Term a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Spray a]
qs ((Spray a -> Term a) -> [Spray a] -> [Term a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm [Spray a]
qs)
    g :: Term a -> Spray a -> Spray a -> (Spray a, Spray a)
    g :: Term a -> Spray a -> Spray a -> (Spray a, Spray a)
g Term a
lts Spray a
s Spray a
r = (Powers -> Spray a -> Spray a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete (Term a -> Powers
forall a b. (a, b) -> a
fst Term a
lts) Spray a
s, Spray a -> Term a -> Spray a
forall a. (C a, Eq a) => Spray a -> Term a -> Spray a
addTerm Spray a
r Term a
lts)
    go :: Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
    go :: Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
go Term a
lts !Spray a
s Spray a
r !Int
i !Bool
divoccured
      | Bool
divoccured = (Spray a
s, Spray a
r)
      | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n     = Term a -> Spray a -> Spray a -> (Spray a, Spray a)
g Term a
lts Spray a
s Spray a
r 
      | Bool
otherwise  = Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
go Term a
lts Spray a
news Spray a
r (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Bool
newdivoccured
        where
          (Spray a
q, Term a
ltq)      = [(Spray a, Term a)]
qsltqs [(Spray a, Term a)] -> Int -> (Spray a, Term a)
forall a. HasCallStack => [a] -> Int -> a
!! Int
i
          newdivoccured :: Bool
newdivoccured = Term a -> Term a -> Bool
forall a. Term a -> Term a -> Bool
divides Term a
ltq Term a
lts
          news :: Spray a
news          = if Bool
newdivoccured
            then Spray a
s Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
q (Term a -> Term a -> Term a
forall a. C a => Term a -> Term a -> Term a
quotient Term a
lts Term a
ltq)
            else Spray a
s
    ogo :: Spray a -> Spray a -> Spray a
    ogo :: Spray a -> Spray a -> Spray a
ogo !Spray a
s !Spray a
r 
      | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
s    = Spray a
r
      | Bool
otherwise        = Spray a -> Spray a -> Spray a
ogo Spray a
s' Spray a
r'
        where
          (Spray a
s', Spray a
r') = Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
go (Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm Spray a
s) Spray a
s Spray a
r Int
0 Bool
False

-- | Division of a spray by a spray

sprayDivision :: 
  (Eq a, AlgField.C a) 
  => Spray a            -- ^ dividand 

  -> Spray a            -- ^ divisor

  -> (Spray a, Spray a) -- ^ (quotient, remainder)

sprayDivision :: forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
sprayDivision Spray a
sprayA Spray a
sprayB =
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
sprayB
    then if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sprayB
      then 
        String -> (Spray a, Spray a)
forall a. HasCallStack => String -> a
error String
"sprayDivision: division by zero."
      else 
        let c :: a
c = Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
sprayB in (Spray a
sprayA Spray a -> a -> Spray a
forall k a. (C k, C k a) => a -> k -> a
/> a
c, Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray)
    else Spray a -> Spray a -> (Spray a, Spray a)
forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
sprayDivision0 Spray a
sprayA Spray a
sprayB

sprayDivision0 :: forall a. (Eq a, AlgField.C a) 
  => Spray a            -- ^ dividand 

  -> Spray a            -- ^ divisor

  -> (Spray a, Spray a) -- ^ (quotient, remainder)

sprayDivision0 :: forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
sprayDivision0 Spray a
sprayA Spray a
sprayB =
  Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
ogo Spray a
sprayA Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  where
    ltB :: Term a
ltB = Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm Spray a
sprayB
    ogo :: Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
    ogo :: Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
ogo !Spray a
p !Spray a
q !Spray a
r 
      | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
p    = (Spray a
q, Spray a
r)
      | Bool
otherwise        = Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
ogo Spray a
p' Spray a
q' Spray a
r'
        where
          ltp :: Term a
ltp = Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm Spray a
p
          (Spray a
p', Spray a
q', Spray a
r') = if Term a -> Term a -> Bool
forall a. Term a -> Term a -> Bool
divides Term a
ltB Term a
ltp
            then (Spray a
newp, Spray a
newq, Spray a
r)
            else (Powers -> Spray a -> Spray a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete (Term a -> Powers
forall a b. (a, b) -> a
fst Term a
ltp) Spray a
p, Spray a
q, Spray a -> Term a -> Spray a
forall a. (C a, Eq a) => Spray a -> Term a -> Spray a
addTerm Spray a
r Term a
ltp)
          qtnt :: Term a
qtnt  = Term a -> Term a -> Term a
forall a. C a => Term a -> Term a -> Term a
quotient Term a
ltp Term a
ltB
          newp :: Spray a
newp = Spray a
p Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
sprayB Term a
qtnt
          newq :: Spray a
newq = Spray a -> Term a -> Spray a
forall a. (C a, Eq a) => Spray a -> Term a -> Spray a
addTerm Spray a
q Term a
qtnt

-- | division of univariate sprays with degree(dividend) >= degree(divisor)

univariateSprayDivision :: forall a. (Eq a, AlgField.C a) 
  => Spray a            -- ^ dividand 

  -> Spray a            -- ^ divisor

  -> (Spray a, Spray a) -- ^ (quotient, remainder)

univariateSprayDivision :: forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
univariateSprayDivision Spray a
sprayA Spray a
sprayB =
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
sprayB 
    then 
      let c :: a
c = Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
sprayB in (Spray a
sprayA Spray a -> a -> Spray a
forall k a. (C k, C k a) => a -> k -> a
/> a
c, Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray)
    else 
      Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
ogo Spray a
sprayA Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  where
    (Powers
powsLTB, a
coeffLTB) = Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm Spray a
sprayB
    degB :: Exponents
degB = Powers -> Exponents
exponents Powers
powsLTB
    expntLTB :: Int
expntLTB = Exponents
degB Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0
    ogo :: Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
    ogo :: Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
ogo !Spray a
p !Spray a
q !Spray a
r
      | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
p = (Spray a
q, Spray a
r)
      | Bool
otherwise     = Spray a -> Spray a -> Spray a -> (Spray a, Spray a)
ogo Spray a
p' Spray a
q' Spray a
r'
        where
          (Powers
powsLTP, a
coeffLTP)  = Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm Spray a
p
          degP :: Exponents
degP = Powers -> Exponents
exponents Powers
powsLTP
          (Spray a
p', Spray a
q', Spray a
r') = if Exponents
degB Exponents -> Exponents -> Bool
forall a. Ord a => a -> a -> Bool
<= Exponents
degP
            then (Spray a
newp, Spray a
newq, Spray a
r)
            else (Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray, Spray a
q, Spray a
r Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ Spray a
p)
          newp :: Spray a
newp = Spray a
p Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a -> (Powers, a) -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
sprayB (Powers, a)
qtnt
          newq :: Spray a
newq = Spray a -> (Powers, a) -> Spray a
forall a. (C a, Eq a) => Spray a -> Term a -> Spray a
addTerm Spray a
q (Powers, a)
qtnt
          qtnt :: (Powers, a)
qtnt = (Powers
pows, a
coeff)
          expntLTP :: Int
expntLTP = Exponents
degP Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0
          pows :: Powers
pows = if Int
expntLTP Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
expntLTB
            then Powers
nullPowers 
            else Exponents -> Int -> Powers
Powers (Int -> Exponents
forall a. a -> Seq a
S.singleton (Int
expntLTP Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
expntLTB)) Int
1
          coeff :: a
coeff = a
coeffLTP a -> a -> a
forall a. C a => a -> a -> a
AlgField./ a
coeffLTB


-- Groebner stuff -------------------------------------------------------------


-- | slight modification of `sprayDivisionRemainder` to speed up groebner00

sprayDivisionRemainder' ::
     forall a. (Eq a, AlgField.C a) 
  => Spray a -> HashMap Int (Spray a, Term a) -> Spray a
sprayDivisionRemainder' :: forall a.
(Eq a, C a) =>
Spray a -> HashMap Int (Spray a, Term a) -> Spray a
sprayDivisionRemainder' Spray a
p HashMap Int (Spray a, Term a)
qsltqs = Spray a -> Spray a -> Spray a
ogo Spray a
p Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  where
    n :: Int
n = HashMap Int (Spray a, Term a) -> Int
forall k v. HashMap k v -> Int
HM.size HashMap Int (Spray a, Term a)
qsltqs
    g :: Term a -> Spray a -> Spray a -> (Spray a, Spray a)
    g :: Term a -> Spray a -> Spray a -> (Spray a, Spray a)
g Term a
lts Spray a
s Spray a
r = (Powers -> Spray a -> Spray a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete (Term a -> Powers
forall a b. (a, b) -> a
fst Term a
lts) Spray a
s, Spray a -> Term a -> Spray a
forall a. (C a, Eq a) => Spray a -> Term a -> Spray a
addTerm Spray a
r Term a
lts)
    go :: Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
    go :: Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
go Term a
lts !Spray a
s Spray a
r !Int
i !Bool
divoccured
      | Bool
divoccured = (Spray a
s, Spray a
r)
      | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n     = Term a -> Spray a -> Spray a -> (Spray a, Spray a)
g Term a
lts Spray a
s Spray a
r 
      | Bool
otherwise  = Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
go Term a
lts Spray a
news Spray a
r (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Bool
newdivoccured
        where
          (Spray a
q, Term a
ltq)      = HashMap Int (Spray a, Term a)
qsltqs HashMap Int (Spray a, Term a) -> Int -> (Spray a, Term a)
forall k v.
(Eq k, Hashable k, HasCallStack) =>
HashMap k v -> k -> v
HM.! Int
i
          newdivoccured :: Bool
newdivoccured = Term a -> Term a -> Bool
forall a. Term a -> Term a -> Bool
divides Term a
ltq Term a
lts
          news :: Spray a
news = if Bool
newdivoccured
            then Spray a
s Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
q (Term a -> Term a -> Term a
forall a. C a => Term a -> Term a -> Term a
quotient Term a
lts Term a
ltq)
            else Spray a
s
    ogo :: Spray a -> Spray a -> Spray a
    ogo :: Spray a -> Spray a -> Spray a
ogo !Spray a
s !Spray a
r 
      | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
s    = Spray a
r
      | Bool
otherwise        = Spray a -> Spray a -> Spray a
ogo Spray a
s' Spray a
r'
        where
          (Spray a
s', Spray a
r') = Term a -> Spray a -> Spray a -> Int -> Bool -> (Spray a, Spray a)
go (Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm Spray a
s) Spray a
s Spray a
r Int
0 Bool
False

-- combinations of two among n

combn2 :: Int -> Int -> HashMap Int (Int, Int)
combn2 :: Int -> Int -> HashMap Int (Int, Int)
combn2 Int
n Int
s = [(Int, (Int, Int))] -> HashMap Int (Int, Int)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([Int] -> [(Int, Int)] -> [(Int, (Int, Int))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 .. ] ([Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
row1 [Int]
row2)) 
  where
    range1 :: [Int]
range1 = [Int
1 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]
    row1 :: [Int]
row1   = Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
drop Int
s ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ (Int -> [Int]) -> [Int] -> [Int]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Int
i -> [Int
0 .. Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]) [Int]
range1 
    row2 :: [Int]
row2   = Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
drop Int
s ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ (Int -> [Int]) -> [Int] -> [Int]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Int
i -> Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
i Int
i) [Int]
range1

-- the "S polynomial"

sPolynomial :: (Eq a, AlgField.C a) 
               => (Spray a, Term a) -> (Spray a, Term a) -> Spray a
sPolynomial :: forall a.
(Eq a, C a) =>
(Spray a, Term a) -> (Spray a, Term a) -> Spray a
sPolynomial (Spray a
p, (Powers
lpowsP, a
lcoefP)) (Spray a
q, (Powers
lpowsQ, a
lcoefQ)) = 
  Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
p Term a
wp Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
q Term a
wq
  where
    (Exponents
lexpntsP, Exponents
lexpntsQ) = (Powers, Powers) -> (Exponents, Exponents)
harmonize (Powers
lpowsP, Powers
lpowsQ)
    gamma :: Exponents
gamma = (Int -> Int -> Int) -> Exponents -> Exponents -> Exponents
forall a b c. (a -> b -> c) -> Seq a -> Seq b -> Seq c
S.zipWith Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Exponents
lexpntsP Exponents
lexpntsQ
    betaP :: Exponents
betaP = (Int -> Int -> Int) -> Exponents -> Exponents -> Exponents
forall a b c. (a -> b -> c) -> Seq a -> Seq b -> Seq c
S.zipWith (-) Exponents
gamma Exponents
lexpntsP
    betaQ :: Exponents
betaQ = (Int -> Int -> Int) -> Exponents -> Exponents -> Exponents
forall a b c. (a -> b -> c) -> Seq a -> Seq b -> Seq c
S.zipWith (-) Exponents
gamma Exponents
lexpntsQ
    wp :: Term a
wp = (Exponents -> Powers
makePowers Exponents
betaP, a -> a
forall a. C a => a -> a
AlgField.recip a
lcoefP)
    wq :: Term a
wq = (Exponents -> Powers
makePowers Exponents
betaQ, a -> a
forall a. C a => a -> a
AlgField.recip a
lcoefQ)

-- | groebner basis, not minimal and not reduced

groebner00 :: forall a. (Eq a, AlgField.C a) => [Spray a] -> [Spray a]
groebner00 :: forall a. (Eq a, C a) => [Spray a] -> [Spray a]
groebner00 [Spray a]
sprays = Int
-> Int
-> HashMap Int (Int, Int)
-> HashMap Int (Spray a, Term a)
-> [Spray a]
go Int
0 Int
j0 HashMap Int (Int, Int)
combins0 HashMap Int (Spray a, Term a)
spraysMap
  where
    j0 :: Int
j0       = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
sprays
    combins0 :: HashMap Int (Int, Int)
combins0 = Int -> Int -> HashMap Int (Int, Int)
combn2 Int
j0 Int
0
    ltsprays :: [Term a]
ltsprays       = (Spray a -> Term a) -> [Spray a] -> [Term a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm [Spray a]
sprays
    spraysltsprays :: [(Spray a, Term a)]
spraysltsprays = [Spray a] -> [Term a] -> [(Spray a, Term a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Spray a]
sprays [Term a]
ltsprays 
    spraysMap :: HashMap Int (Spray a, Term a)
spraysMap      = [(Int, (Spray a, Term a))] -> HashMap Int (Spray a, Term a)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([Int] -> [(Spray a, Term a)] -> [(Int, (Spray a, Term a))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 .. Int
j0Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] [(Spray a, Term a)]
spraysltsprays)
    go :: Int -> Int -> HashMap Int (Int, Int) 
          -> HashMap Int (Spray a, Term a) -> [Spray a]
    go :: Int
-> Int
-> HashMap Int (Int, Int)
-> HashMap Int (Spray a, Term a)
-> [Spray a]
go !Int
i !Int
j !HashMap Int (Int, Int)
combins !HashMap Int (Spray a, Term a)
gpolysMap
      | Int
j Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
100 = String -> [Spray a]
forall a. HasCallStack => String -> a
error 
          String
"groebnerBasis: stopped because reached the limit; please fill an issue."
      | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== HashMap Int (Int, Int) -> Int
forall a. HashMap Int a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length HashMap Int (Int, Int)
combins = ((Spray a, Term a) -> Spray a) -> [(Spray a, Term a)] -> [Spray a]
forall a b. (a -> b) -> [a] -> [b]
map (Spray a, Term a) -> Spray a
forall a b. (a, b) -> a
fst (HashMap Int (Spray a, Term a) -> [(Spray a, Term a)]
forall k v. HashMap k v -> [v]
HM.elems HashMap Int (Spray a, Term a)
gpolysMap)
      | Bool
otherwise           = Int
-> Int
-> HashMap Int (Int, Int)
-> HashMap Int (Spray a, Term a)
-> [Spray a]
go Int
i' Int
j' HashMap Int (Int, Int)
combins' HashMap Int (Spray a, Term a)
gpolysMap'
        where
          (Int
k, Int
l)   = HashMap Int (Int, Int)
combins HashMap Int (Int, Int) -> Int -> (Int, Int)
forall k v.
(Eq k, Hashable k, HasCallStack) =>
HashMap k v -> k -> v
HM.! Int
i
          sfg :: Spray a
sfg      = (Spray a, Term a) -> (Spray a, Term a) -> Spray a
forall a.
(Eq a, C a) =>
(Spray a, Term a) -> (Spray a, Term a) -> Spray a
sPolynomial (HashMap Int (Spray a, Term a)
gpolysMap HashMap Int (Spray a, Term a) -> Int -> (Spray a, Term a)
forall k v.
(Eq k, Hashable k, HasCallStack) =>
HashMap k v -> k -> v
HM.! Int
k) (HashMap Int (Spray a, Term a)
gpolysMap HashMap Int (Spray a, Term a) -> Int -> (Spray a, Term a)
forall k v.
(Eq k, Hashable k, HasCallStack) =>
HashMap k v -> k -> v
HM.! Int
l)
          sbarfg :: Spray a
sbarfg   = Spray a -> HashMap Int (Spray a, Term a) -> Spray a
forall a.
(Eq a, C a) =>
Spray a -> HashMap Int (Spray a, Term a) -> Spray a
sprayDivisionRemainder' Spray a
sfg HashMap Int (Spray a, Term a)
gpolysMap
          ltsbarfg :: Term a
ltsbarfg = Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm Spray a
sbarfg
          (Int
i', Int
j', HashMap Int (Spray a, Term a)
gpolysMap', HashMap Int (Int, Int)
combins') = if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sbarfg
            then
              (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, Int
j, HashMap Int (Spray a, Term a)
gpolysMap, HashMap Int (Int, Int)
combins)
            else
              ( Int
0
              , Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
              , Int
-> (Spray a, Term a)
-> HashMap Int (Spray a, Term a)
-> HashMap Int (Spray a, Term a)
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert Int
j (Spray a
sbarfg, Term a
ltsbarfg) HashMap Int (Spray a, Term a)
gpolysMap
              , Int -> Int -> HashMap Int (Int, Int)
combn2 (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
              )

-- | groebner basis, minimal but not reduced

groebner0 :: forall a. (Eq a, AlgField.C a) => [Spray a] -> [Spray a]
groebner0 :: forall a. (Eq a, C a) => [Spray a] -> [Spray a]
groebner0 [Spray a]
sprays = 
  if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1 then [Spray a]
sprays else [[Spray a]
basis00 [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
k | Int
k <- [Int
0 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] [Int] -> [Int] -> [Int]
forall a. Eq a => [a] -> [a] -> [a]
\\ [Int]
discard]
  where
    n :: Int
n       = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
basis00
    basis00 :: [Spray a]
basis00 = [Spray a] -> [Spray a]
forall a. (Eq a, C a) => [Spray a] -> [Spray a]
groebner00 [Spray a]
sprays
    go :: Int -> [Int] -> [Int]
    go :: Int -> [Int] -> [Int]
go !Int
i [Int]
toRemove
      | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n    = [Int]
toRemove
      | Bool
otherwise = Int -> [Int] -> [Int]
go (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) [Int]
toRemove'
        where
          ltf :: Term a
ltf    = Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm ([Spray a]
basis00 [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
i)
          toDrop :: [Int]
toDrop = [Int]
toRemove [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
i]
          igo :: Int -> Bool
          igo :: Int -> Bool
igo !Int
j 
            | Int
j Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n          = Bool
False
            | Int
j Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int]
toDrop = Int -> Bool
igo (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
            | Bool
otherwise       = Bool
ok Bool -> Bool -> Bool
|| Int -> Bool
igo (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
              where 
                ok :: Bool
ok = Term a -> Term a -> Bool
forall a. Term a -> Term a -> Bool
divides (Spray a -> Term a
forall a. Spray a -> Term a
leadingTerm ([Spray a]
basis00 [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
j)) Term a
ltf
          toRemove' :: [Int]
toRemove' = if Int -> Bool
igo Int
0 then [Int]
toDrop else [Int]
toRemove
    discard :: [Int]
discard = Int -> [Int] -> [Int]
go Int
0 []

-- | Reduces a Gröbner basis

reduceGroebnerBasis :: forall a. (Eq a, AlgField.C a) => [Spray a] -> [Spray a]
reduceGroebnerBasis :: forall a. (Eq a, C a) => [Spray a] -> [Spray a]
reduceGroebnerBasis [Spray a]
gbasis = 
  if [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
gbasis Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 
    then (Int -> Spray a) -> [Int] -> [Spray a]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Spray a
reduction [Int
0 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] 
    else [Spray a]
ngbasis
  where
    normalize :: Spray a -> Spray a
    normalize :: Spray a -> Spray a
normalize Spray a
spray = Spray a
spray Spray a -> a -> Spray a
forall k a. (C k, C k a) => a -> k -> a
/> a
coef
      where
        (Powers
_, a
coef) = Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm Spray a
spray
    ngbasis :: [Spray a]
ngbasis = (Spray a -> Spray a) -> [Spray a] -> [Spray a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> Spray a
normalize [Spray a]
gbasis
    n :: Int
n       = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
ngbasis
    reduction :: Int -> Spray a
    reduction :: Int -> Spray a
reduction Int
i = Spray a -> [Spray a] -> Spray a
forall a. (Eq a, C a) => Spray a -> [Spray a] -> Spray a
sprayDivisionRemainder ([Spray a]
ngbasis [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
i) [Spray a]
rest
      where
        rest :: [Spray a]
rest = [[Spray a]
ngbasis [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
k | Int
k <- [Int
0 .. Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]

-- | Gröbner basis, always minimal and possibly reduced

--

-- prop> groebnerBasis sprays True == reduceGroebnerBasis (groebnerBasis sprays False)

groebnerBasis ::
     forall a. (Eq a, AlgField.C a) 
  => [Spray a] -- ^ list of sprays 

  -> Bool      -- ^ whether to return the reduced basis

  -> [Spray a]
groebnerBasis :: forall a. (Eq a, C a) => [Spray a] -> Bool -> [Spray a]
groebnerBasis [Spray a]
sprays Bool
reduced = 
  if Bool
reduced then [Spray a] -> [Spray a]
forall a. (Eq a, C a) => [Spray a] -> [Spray a]
reduceGroebnerBasis [Spray a]
gbasis0 else (Spray a -> Spray a) -> [Spray a] -> [Spray a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> Spray a
normalize [Spray a]
gbasis0
  where
    gbasis0 :: [Spray a]
gbasis0 = [Spray a] -> [Spray a]
forall a. (Eq a, C a) => [Spray a] -> [Spray a]
groebner0 [Spray a]
sprays
    normalize :: Spray a -> Spray a
    normalize :: Spray a -> Spray a
normalize Spray a
spray = Spray a
spray Spray a -> a -> Spray a
forall k a. (C k, C k a) => a -> k -> a
/> a
coef
      where
        (Powers
_, a
coef) = Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm Spray a
spray


-- elementary symmetric polynomials -------------------------------------------


-- | combinations of k elements among a list

combinationsOf :: Int -> [a] -> [[a]]
combinationsOf :: forall a. Int -> [a] -> [[a]]
combinationsOf Int
_ []        = String -> [[a]]
forall a. HasCallStack => String -> a
error String
"combinationsOf: should not happen."
combinationsOf Int
1 [a]
as        = (a -> [a]) -> [a] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
map a -> [a]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [a]
as
combinationsOf Int
k as :: [a]
as@(a
_:[a]
xs) = 
  Int -> Int -> [a] -> [[a]] -> [[a]]
forall a. Int -> Int -> [a] -> [[a]] -> [[a]]
run (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Int
kInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [a]
as ([[a]] -> [[a]]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> a -> b
$ Int -> [a] -> [[a]]
forall a. Int -> [a] -> [[a]]
combinationsOf (Int
kInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [a]
xs
  where
    l :: Int
l = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
as
    run :: Int -> Int -> [a] -> [[a]] -> [[a]]
    run :: forall a. Int -> Int -> [a] -> [[a]] -> [[a]]
run Int
n Int
i [a]
ys [[a]]
cs 
      | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
i    = ([a] -> [a]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
map ([a]
ys [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++) [[a]]
cs
      | Bool
otherwise = ([a] -> [a]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
map (a
qa -> [a] -> [a]
forall a. a -> [a] -> [a]
:) [[a]]
cs [[a]] -> [[a]] -> [[a]]
forall a. [a] -> [a] -> [a]
++ Int -> Int -> [a] -> [[a]] -> [[a]]
forall a. Int -> Int -> [a] -> [[a]] -> [[a]]
run (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Int
i [a]
qs (Int -> [[a]] -> [[a]]
forall a. Int -> [a] -> [a]
drop Int
dc [[a]]
cs)
      where
        f :: [a] -> (a, [a])
        f :: forall a. [a] -> (a, [a])
f []     = String -> (a, [a])
forall a. HasCallStack => String -> a
error String
"combinationsOf: should not happen."
        f (a
b:[a]
bs) = (a
b, [a]
bs)
        (a
q, [a]
qs)  = [a] -> (a, [a])
forall a. [a] -> (a, [a])
f (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) [a]
ys)
        dc :: Int
dc       = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [Int
1 .. Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]

-- | generates all permutations of a binary sequence

permutationsBinarySequence :: Int -> Int -> [Seq Int]
permutationsBinarySequence :: Int -> Int -> [Exponents]
permutationsBinarySequence Int
nzeros Int
nones = 
  let n :: Int
n = Int
nzeros Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
nones in 
    ([Int] -> Exponents) -> [[Int]] -> [Exponents]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> [Int] -> Exponents
binarySequence Int
n) (Int -> [Int] -> [[Int]]
forall a. Int -> [a] -> [[a]]
combinationsOf Int
nones [Int
0 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1])
  where
    binarySequence :: Int -> [Int] -> Seq Int
    binarySequence :: Int -> [Int] -> Exponents
binarySequence Int
n [Int]
combo = Int -> (Int -> Int) -> Exponents
forall a. Int -> (Int -> a) -> Seq a
fromFunction Int
n Int -> Int
f 
      where
        f :: Int -> Int
        f :: Int -> Int
f Int
i = Bool -> Int
forall a. Enum a => a -> Int
fromEnum (Int
i Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int]
combo)

-- | Elementary symmetric polynomial

--

-- >>> putStrLn $ prettySpray' (esPolynomial 3 2)

-- (1)*x1.x2 + (1)*x1.x3 + (1)*x2.x3

esPolynomial ::
     (AlgRing.C a, Eq a) 
  => Int -- ^ number of variables

  -> Int -- ^ index

  -> Spray a
esPolynomial :: forall a. (C a, Eq a) => Int -> Int -> Spray a
esPolynomial Int
n Int
k
  | Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 
    = String -> Spray a
forall a. HasCallStack => String -> a
error String
"esPolynomial: both arguments must be positive integers."
  | Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n     = Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0    = Spray a
forall a. C a => Spray a
unitSpray
  | Bool
otherwise = Spray a
spray
  where
    perms :: [Exponents]
perms = Int -> Int -> [Exponents]
permutationsBinarySequence (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k) Int
k
    spray :: Spray a
spray = [(Powers, a)] -> Spray a
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([(Powers, a)] -> Spray a) -> [(Powers, a)] -> Spray a
forall a b. (a -> b) -> a -> b
$ (Exponents -> (Powers, a)) -> [Exponents] -> [(Powers, a)]
forall a b. (a -> b) -> [a] -> [b]
map (\Exponents
expts -> (Exponents -> Powers
makePowers Exponents
expts, a
forall a. C a => a
AlgRing.one)) [Exponents]
perms

-- | Power sum polynomial

psPolynomial ::
     forall a. (AlgRing.C a, Eq a) 
  => Int -- ^ number of variables

  -> Int -- ^ power

  -> Spray a
psPolynomial :: forall a. (C a, Eq a) => Int -> Int -> Spray a
psPolynomial Int
n Int
k
  | Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 
    = String -> Spray a
forall a. HasCallStack => String -> a
error String
"psPolynomial: both arguments must be positive integers."
  | Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n     = Spray a
forall a. C a => a
AlgAdd.zero
  | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0    = Int
n Int -> Spray a -> Spray a
forall a. (C a, Eq a) => Int -> a -> a
.^ Spray a
forall a. C a => Spray a
unitSpray
  | Bool
otherwise = Spray a
spray
  where
    spray :: Spray a
spray = [(Powers, a)] -> Spray a
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList ([(Powers, a)] -> Spray a) -> [(Powers, a)] -> Spray a
forall a b. (a -> b) -> a -> b
$ (Int -> (Powers, a)) -> [Int] -> [(Powers, a)]
forall a b. (a -> b) -> [a] -> [b]
map Int -> (Powers, a)
f [Int
1 .. Int
n]
    f :: Int -> (Powers, a)
    f :: Int -> (Powers, a)
f Int
j = (Exponents -> Int -> Powers
Powers Exponents
expts Int
j, a
forall a. C a => a
AlgRing.one)
      where
        expts :: Exponents
expts = Int -> Int -> Exponents
forall a. Int -> a -> Seq a
S.replicate (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Int
0 Exponents -> Int -> Exponents
forall a. Seq a -> a -> Seq a
|> Int
k

-- | Whether a spray is a symmetric polynomial, an inefficient algorithm 

-- (use the function with the same name in the __jackpolynomials__ package 

-- if you need efficiency)

isSymmetricSpray :: forall a. (AlgField.C a, Eq a) => Spray a -> Bool
isSymmetricSpray :: forall a. (C a, Eq a) => Spray a -> Bool
isSymmetricSpray Spray a
spray = Bool
check
  where
    n :: Int
n = Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray
    indices :: [Int]
indices = [Int
1 .. Int
n]
    gPolys :: [Spray a]
gPolys  = [Int -> Int -> Spray a
forall a. (C a, Eq a) => Int -> Int -> Spray a
esPolynomial Int
n Int
i Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Int -> Spray a
forall a. C a => Int -> Spray a
lone (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i) | Int
i <- [Int]
indices]
    gbasis :: [Spray a]
gbasis  = [Spray a] -> [Spray a]
forall a. (Eq a, C a) => [Spray a] -> [Spray a]
groebner0 [Spray a]
gPolys
    spray' :: Spray a
spray'  = Spray a -> Spray a
forall a. Spray a -> Spray a
removeConstantTerm Spray a
spray
    g :: Spray a
g       = Spray a -> [Spray a] -> Spray a
forall a. (Eq a, C a) => Spray a -> [Spray a] -> Spray a
sprayDivisionRemainder Spray a
spray' [Spray a]
gbasis
    check :: Bool
check   = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Spray a -> Int -> Bool
forall b. FunctionLike b => b -> Int -> Bool
involvesVariable Spray a
g) [Int
1 .. Int
n]

-- | Whether a spray can be written as a polynomial of a given list of sprays;

-- this polynomial is returned if this is true

--

-- >>> x = lone 1 :: Spray Rational

-- >>> y = lone 2 :: Spray Rational

-- >>> p1 = x ^+^ y

-- >>> p2 = x ^-^ y

-- >>> p = p1 ^*^ p2

-- 

-- prop> isPolynomialOf p [p1, p2] == (True, Just $ x ^*^ y)

isPolynomialOf :: forall a. (AlgField.C a, Eq a) 
                  => Spray a -> [Spray a] -> (Bool, Maybe (Spray a))
isPolynomialOf :: forall a.
(C a, Eq a) =>
Spray a -> [Spray a] -> (Bool, Maybe (Spray a))
isPolynomialOf Spray a
spray [Spray a]
sprays
  | Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
spray = (Bool
True, Spray a -> Maybe (Spray a)
forall a. a -> Maybe a
Just Spray a
spray)
  | [Spray a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Spray a]
sprays      = String -> (Bool, Maybe (Spray a))
forall a. HasCallStack => String -> a
error String
"isPolynomialOf: the list of sprays is empty."
  | Bool
otherwise        = (Bool, Maybe (Spray a))
result 
  where
    nov :: Int
nov = Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray
    n :: Int
n   = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (Spray a -> Int) -> [Spray a] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables [Spray a]
sprays
    result :: (Bool, Maybe (Spray a))
result
      | Int
nov Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n   = (Bool
False, Maybe (Spray a)
forall a. Maybe a
Nothing)
      | Bool
otherwise = (Bool
check, Maybe (Spray a)
poly)
        where
          m :: Int
m            = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
sprays
          yPolys :: [Spray a]
yPolys       = [Int -> Spray a
forall a. C a => Int -> Spray a
lone (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i) | Int
i <- [Int
1 .. Int
m]]  
          gPolys :: [Spray a]
gPolys       = (Spray a -> Spray a -> Spray a)
-> [Spray a] -> [Spray a] -> [Spray a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
(^-^) [Spray a]
sprays [Spray a]
yPolys
          gbasis0 :: [Spray a]
gbasis0      = [Spray a] -> [Spray a]
forall a. (Eq a, C a) => [Spray a] -> [Spray a]
groebner0 [Spray a]
gPolys
          constantTerm :: a
constantTerm = Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
spray
          spray' :: Spray a
spray'       = Spray a -> Spray a
forall a. Spray a -> Spray a
removeConstantTerm Spray a
spray
          g :: Spray a
g            = Spray a -> [Spray a] -> Spray a
forall a. (Eq a, C a) => Spray a -> [Spray a] -> Spray a
sprayDivisionRemainder Spray a
spray' [Spray a]
gbasis0
          check :: Bool
check        = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Spray a -> Int -> Bool
forall b. FunctionLike b => b -> Int -> Bool
involvesVariable Spray a
g) [Int
1 .. Int
n]
          poly :: Maybe (Spray a)
poly         = if Bool
check
            then Spray a -> Maybe (Spray a)
forall a. a -> Maybe a
Just (a
BaseRing (Spray a)
constantTerm BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
+> Int -> Spray a -> Spray a
forall b. FunctionLike b => Int -> b -> b
dropVariables Int
n Spray a
g)
            else Maybe (Spray a)
forall a. Maybe a
Nothing


-- resultant ------------------------------------------------------------------


-- | sylvester matrix

sylvesterMatrix :: AlgAdd.C a => [a] -> [a] -> Matrix a
sylvesterMatrix :: forall a. C a => [a] -> [a] -> Matrix a
sylvesterMatrix [a]
x [a]
y = [[a]] -> Matrix a
forall a. [[a]] -> Matrix a
fromLists ([[a]]
xrows [[a]] -> [[a]] -> [[a]]
forall a. [a] -> [a] -> [a]
++ [[a]]
yrows) 
  where
    m :: Int
m = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    n :: Int
n = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
y Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    xrows :: [[a]]
xrows = [Int -> a -> [a]
forall a. Int -> a -> [a]
replicate Int
i a
forall a. C a => a
AlgAdd.zero [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
x [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) a
forall a. C a => a
AlgAdd.zero 
             | Int
i <- [Int
0 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]
    yrows :: [[a]]
yrows = [Int -> a -> [a]
forall a. Int -> a -> [a]
replicate Int
i a
forall a. C a => a
AlgAdd.zero [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
y [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) a
forall a. C a => a
AlgAdd.zero 
             | Int
i <- [Int
0 .. Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]

-- | "truncated" Sylvester matrix

sylvesterMatrix' :: AlgRing.C a => [a] -> [a] -> Int -> Matrix a
sylvesterMatrix' :: forall a. C a => [a] -> [a] -> Int -> Matrix a
sylvesterMatrix' [a]
x [a]
y Int
k = if Int
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 
  then [[a]] -> Matrix a
forall a. [[a]] -> Matrix a
fromLists [[a
forall a. C a => a
AlgRing.one]] -- plays the role of the empty matrix: 

                                 -- the point to get is determinant=1 

                                 -- (because the empty matrix is not allowed

                                 -- in the matrix package)

  else Int -> Int -> Int -> Int -> Matrix a -> Matrix a
forall a. Int -> Int -> Int -> Int -> Matrix a -> Matrix a
submatrix Int
1 Int
s Int
1 Int
s (Matrix a -> Matrix a) -> Matrix a -> Matrix a
forall a b. (a -> b) -> a -> b
$ [[a]] -> Matrix a
forall a. [[a]] -> Matrix a
fromLists ([[a]]
xrows [[a]] -> [[a]] -> [[a]]
forall a. [a] -> [a] -> [a]
++ [[a]]
yrows) 
  where
    m :: Int
m = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    n :: Int
n = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
y Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    s :: Int
s = Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
k
    xrows :: [[a]]
xrows = [Int -> a -> [a]
forall a. Int -> a -> [a]
replicate Int
i a
forall a. C a => a
AlgAdd.zero [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
x [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) a
forall a. C a => a
AlgAdd.zero 
             | Int
i <- [Int
0 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k]]
    yrows :: [[a]]
yrows = [Int -> a -> [a]
forall a. Int -> a -> [a]
replicate Int
i a
forall a. C a => a
AlgAdd.zero [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
y [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) a
forall a. C a => a
AlgAdd.zero 
             | Int
i <- [Int
0 .. Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k]]

-- | the coefficients of a spray as a univariate spray in x_1 with 

-- spray coefficients

sprayCoefficients :: (Eq a, AlgRing.C a) => Spray a -> [Spray a]
sprayCoefficients :: forall a. (Eq a, C a) => Spray a -> [Spray a]
sprayCoefficients Spray a
spray = 
  if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 
    then [Spray a
constantTerm]
    else [Spray a]
sprays
  where
    n :: Int
n = Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray 
    spray'' :: SafeSpray a
spray'' = Spray a -> SafeSpray a
forall a. Spray a -> SafeSpray a
safeSpray Spray a
spray
    spray' :: SafeSpray a
spray' = SafeSpray a -> SafeSpray a
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' SafeSpray a
spray''
    ([Exponents]
expnts', [a]
coeffs') = [(Exponents, a)] -> ([Exponents], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip (SafeSpray a -> [(Exponents, a)]
forall k v. HashMap k v -> [(k, v)]
HM.toList SafeSpray a
spray')
    constantTerm :: Spray a
constantTerm = (a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray (a -> Spray a) -> (SafeSpray a -> a) -> SafeSpray a -> Spray a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SafeSpray a -> a
forall a. C a => SafeSpray a -> a
getConstantTerm'') SafeSpray a
spray''
    xpows :: [Int]
xpows              = (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) [Exponents]
expnts'
    powers'' :: [Powers]
powers''           = 
      (Exponents -> Powers) -> [Exponents] -> [Powers]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Powers
powerize (Exponents -> Powers)
-> (Exponents -> Exponents) -> Exponents -> Powers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Exponents -> Exponents
forall a. Int -> Seq a -> Seq a
S.deleteAt Int
0) [Exponents]
expnts'
    sprays'' :: [Spray a]
sprays''           = (Powers -> a -> Spray a) -> [Powers] -> [a] -> [Spray a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (((Powers, a) -> Spray a) -> Powers -> a -> Spray a
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (Powers, a) -> Spray a
forall a. Term a -> Spray a
fromTerm) [Powers]
powers'' [a]
coeffs'
    imap :: IntMap (Spray a)
imap               = (Spray a -> Spray a -> Spray a)
-> [(Int, Spray a)] -> IntMap (Spray a)
forall a. (a -> a -> a) -> [(Int, a)] -> IntMap a
IM.fromListWith Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
(^+^) ([Int] -> [Spray a] -> [(Int, Spray a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
xpows [Spray a]
sprays'')
    imap' :: IntMap (Spray a)
imap'              = (Spray a -> Spray a -> Spray a)
-> Int -> Spray a -> IntMap (Spray a) -> IntMap (Spray a)
forall a. (a -> a -> a) -> Int -> a -> IntMap a -> IntMap a
IM.insertWith Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
(^+^) Int
0 Spray a
constantTerm IntMap (Spray a)
imap
    permutation :: [Int]
permutation = [Int
2 .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1]
    deg :: Int
deg = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
xpows
    sprays :: [Spray a]
sprays = [
      [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation (Spray a -> Maybe (Spray a) -> Spray a
forall a. a -> Maybe a -> a
fromMaybe Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray (Int -> IntMap (Spray a) -> Maybe (Spray a)
forall a. Int -> IntMap a -> Maybe a
IM.lookup Int
i IntMap (Spray a)
imap'))
      | Int
i <- [Int
deg, Int
degInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
0]
      ]

-- | Resultant of two /univariate/ sprays

resultant1 :: (Eq a, AlgRing.C a) => Spray a -> Spray a -> a
resultant1 :: forall a. (Eq a, C a) => Spray a -> Spray a -> a
resultant1 Spray a
p Spray a
q = 
  if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1 
    then Matrix a -> a
forall a. (Eq a, C a) => Matrix a -> a
detLaplace (Matrix a -> a) -> Matrix a -> a
forall a b. (a -> b) -> a -> b
$ [a] -> [a] -> Matrix a
forall a. C a => [a] -> [a] -> Matrix a
sylvesterMatrix [a]
pcoeffs [a]
qcoeffs
    else String -> a
forall a. HasCallStack => String -> a
error String
"resultant1: the two sprays must be univariate."
  where
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
p) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
q)
    p'' :: SafeSpray a
p'' = Spray a -> SafeSpray a
forall a. Spray a -> SafeSpray a
safeSpray Spray a
p
    q'' :: SafeSpray a
q'' = Spray a -> SafeSpray a
forall a. Spray a -> SafeSpray a
safeSpray Spray a
q
    pexpnts :: [Int]
pexpnts = 
      (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) ([Exponents] -> [Int]) -> [Exponents] -> [Int]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> [Exponents]
forall k v. HashMap k v -> [k]
HM.keys (SafeSpray a -> [Exponents]) -> SafeSpray a -> [Exponents]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> SafeSpray a
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' SafeSpray a
p''
    qexpnts :: [Int]
qexpnts = 
      (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) ([Exponents] -> [Int]) -> [Exponents] -> [Int]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> [Exponents]
forall k v. HashMap k v -> [k]
HM.keys (SafeSpray a -> [Exponents]) -> SafeSpray a -> [Exponents]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> SafeSpray a
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' SafeSpray a
q''
    p0 :: a
p0 = SafeSpray a -> a
forall a. C a => SafeSpray a -> a
getConstantTerm'' SafeSpray a
p''
    q0 :: a
q0 = SafeSpray a -> a
forall a. C a => SafeSpray a -> a
getConstantTerm'' SafeSpray a
q''
    pcoeffs :: [a]
pcoeffs = if [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
pexpnts 
      then [a
p0]
      else [Exponents -> SafeSpray a -> a
forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' (Int -> Exponents
forall a. a -> Seq a
S.singleton Int
i) SafeSpray a
p'' | Int
i <- [Int
maxp, Int
maxpInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
1]] 
            [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
p0]
      where
        maxp :: Int
maxp = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
pexpnts
    qcoeffs :: [a]
qcoeffs = if [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
qexpnts 
      then [a
q0]
      else [Exponents -> SafeSpray a -> a
forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' (Int -> Exponents
forall a. a -> Seq a
S.singleton Int
i) SafeSpray a
q'' | Int
i <- [Int
maxq, Int
maxqInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
1]] 
            [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
q0]
      where
        maxq :: Int
maxq = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
qexpnts

-- | Subresultants of two /univariate/ sprays. This function makes several calls

-- to `detLaplace` and then it can be slow.

subresultants1 :: (Eq a, AlgRing.C a) => Spray a -> Spray a -> [a]
subresultants1 :: forall a. (Eq a, C a) => Spray a -> Spray a -> [a]
subresultants1 Spray a
p Spray a
q = if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1 
  then (Int -> a) -> [Int] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Matrix a -> a
forall a. (Eq a, C a) => Matrix a -> a
detLaplace (Matrix a -> a) -> (Int -> Matrix a) -> Int -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a] -> Int -> Matrix a
forall a. C a => [a] -> [a] -> Int -> Matrix a
sylvesterMatrix' [a]
pcoeffs [a]
qcoeffs) [Int
0 .. Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
d Int
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
  else String -> [a]
forall a. HasCallStack => String -> a
error String
"subresultants1: the two sprays must be univariate."
  where
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
p) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
q)
    p'' :: SafeSpray a
p'' = Spray a -> SafeSpray a
forall a. Spray a -> SafeSpray a
safeSpray Spray a
p
    q'' :: SafeSpray a
q'' = Spray a -> SafeSpray a
forall a. Spray a -> SafeSpray a
safeSpray Spray a
q
    pexpnts :: [Int]
pexpnts = 
      (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) ([Exponents] -> [Int]) -> [Exponents] -> [Int]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> [Exponents]
forall k v. HashMap k v -> [k]
HM.keys (SafeSpray a -> [Exponents]) -> SafeSpray a -> [Exponents]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> SafeSpray a
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' SafeSpray a
p''
    qexpnts :: [Int]
qexpnts = 
      (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) ([Exponents] -> [Int]) -> [Exponents] -> [Int]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> [Exponents]
forall k v. HashMap k v -> [k]
HM.keys (SafeSpray a -> [Exponents]) -> SafeSpray a -> [Exponents]
forall a b. (a -> b) -> a -> b
$ SafeSpray a -> SafeSpray a
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' SafeSpray a
q''
    p0 :: a
p0 = SafeSpray a -> a
forall a. C a => SafeSpray a -> a
getConstantTerm'' SafeSpray a
p''
    q0 :: a
q0 = SafeSpray a -> a
forall a. C a => SafeSpray a -> a
getConstantTerm'' SafeSpray a
q''
    pcoeffs :: [a]
pcoeffs = if [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
pexpnts 
      then [a
p0]
      else [Exponents -> SafeSpray a -> a
forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' (Int -> Exponents
forall a. a -> Seq a
S.singleton Int
i) SafeSpray a
p'' | Int
i <- [Int
maxp, Int
maxpInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
1]] 
            [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
p0]
      where
        maxp :: Int
maxp = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
pexpnts
    qcoeffs :: [a]
qcoeffs = if [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
qexpnts 
      then [a
q0]
      else [Exponents -> SafeSpray a -> a
forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' (Int -> Exponents
forall a. a -> Seq a
S.singleton Int
i) SafeSpray a
q''| Int
i <- [Int
maxq, Int
maxqInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
1]] 
            [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
q0]
      where
        maxq :: Int
maxq = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
qexpnts
    d :: Int
d = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
pcoeffs
    e :: Int
e = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
qcoeffs

-- | Resultant of two sprays

resultant :: (Eq a, AlgRing.C a) 
  => Int     -- ^ indicator of the variable with respect to which the resultant is desired (e.g. 1 for x)

  -> Spray a 
  -> Spray a 
  -> Spray a
resultant :: forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> Spray a
resultant Int
var Spray a
p Spray a
q = 
  if Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
1 Bool -> Bool -> Bool
&& Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n 
    then [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation' Spray a
det
    else String -> Spray a
forall a. HasCallStack => String -> a
error String
"resultant: invalid variable index."
  where
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
p) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
q)
    permutation :: [Int]
permutation  = [Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2 .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1]
    permutation' :: [Int]
permutation' = [Int
var .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]
    p' :: Spray a
p' = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
p
    q' :: Spray a
q' = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
q
    det :: Spray a
det = Matrix (Spray a) -> Spray a
forall a. (Eq a, C a) => Matrix a -> a
detLaplace (Matrix (Spray a) -> Spray a) -> Matrix (Spray a) -> Spray a
forall a b. (a -> b) -> a -> b
$ 
          [Spray a] -> [Spray a] -> Matrix (Spray a)
forall a. C a => [a] -> [a] -> Matrix a
sylvesterMatrix (Spray a -> [Spray a]
forall a. (Eq a, C a) => Spray a -> [Spray a]
sprayCoefficients Spray a
p') (Spray a -> [Spray a]
forall a. (Eq a, C a) => Spray a -> [Spray a]
sprayCoefficients Spray a
q')

-- | Subresultants of two sprays (the /principal/ subresultants, while the 

-- `polynomialSubresultants` function returns the polynomial subresultants). 

-- This function makes several calls to `detLaplace` and then it can be slow.

subresultants :: (Eq a, AlgRing.C a) 
  => Int     -- ^ indicator of the variable with respect to which the subresultants are desired (e.g. 1 for x)

  -> Spray a 
  -> Spray a 
  -> [Spray a]
subresultants :: forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> [Spray a]
subresultants Int
var Spray a
p Spray a
q 
  | Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1 = String -> [Spray a]
forall a. HasCallStack => String -> a
error String
"subresultants: invalid variable index."
  | Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n = String -> [Spray a]
forall a. HasCallStack => String -> a
error String
"subresultants: too large variable index."
  | Bool
otherwise = (Int -> Spray a) -> [Int] -> [Spray a]
forall a b. (a -> b) -> [a] -> [b]
map (Spray a -> Spray a
permute' (Spray a -> Spray a) -> (Int -> Spray a) -> Int -> Spray a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix (Spray a) -> Spray a
forall a. (Eq a, C a) => Matrix a -> a
detLaplace (Matrix (Spray a) -> Spray a)
-> (Int -> Matrix (Spray a)) -> Int -> Spray a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Spray a] -> [Spray a] -> Int -> Matrix (Spray a)
forall a. C a => [a] -> [a] -> Int -> Matrix a
sylvesterMatrix' [Spray a]
pcoeffs [Spray a]
qcoeffs) 
                    [Int
0 .. Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
d Int
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
  where
    pcoeffs :: [Spray a]
pcoeffs = Spray a -> [Spray a]
forall a. (Eq a, C a) => Spray a -> [Spray a]
sprayCoefficients Spray a
p'
    qcoeffs :: [Spray a]
qcoeffs = Spray a -> [Spray a]
forall a. (Eq a, C a) => Spray a -> [Spray a]
sprayCoefficients Spray a
q'
    d :: Int
d = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
pcoeffs
    e :: Int
e = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
qcoeffs
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
p) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
q)
    permutation :: [Int]
permutation = Int
var Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int
1 .. Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
n]
    permute :: Spray a -> Spray a
permute     = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation
    p' :: Spray a
p' = Spray a -> Spray a
permute Spray a
p 
    q' :: Spray a
q' = Spray a -> Spray a
permute Spray a
q 
    permutation' :: [Int]
permutation' = [Int
2 .. Int
var] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ (Int
1 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
n])
    permute' :: Spray a -> Spray a
permute'     = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation'

-- | Resultant of two sprays with coefficients in a field; this function is more 

-- efficient than the function `resultant`

resultant' :: forall a. (Eq a, AlgField.C a) 
  => Int     -- ^ indicator of the variable with respect to which the resultant is desired (e.g. 1 for x)

  -> Spray a 
  -> Spray a 
  -> Spray a
resultant' :: forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> Spray a
resultant' Int
var Spray a
sprayA Spray a
sprayB 
  | Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1 Bool -> Bool -> Bool
|| Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n                         
    = String -> Spray a
forall a. HasCallStack => String -> a
error String
"resultant': invalid variable index." 
  | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sprayA Bool -> Bool -> Bool
|| Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sprayB 
    = Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
  | Bool
otherwise 
    = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation' (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ Spray a -> Spray a -> Spray a -> Spray a -> Spray a -> Spray a
go Spray a
forall a. C a => Spray a
unitSpray Spray a
forall a. C a => Spray a
unitSpray Spray a
s0 Spray a
p0 Spray a
q0
  where
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayA) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayB)
    permutation :: [Int]
permutation  = [Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
var]
    permutation' :: [Int]
permutation' = [Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
var] 
    sprayA' :: Spray a
sprayA' = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
sprayA
    sprayB' :: Spray a
sprayB' = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
sprayB
    degA :: Int
degA = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n Spray a
sprayA'
    degB :: Int
degB = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n Spray a
sprayB'
    content :: Spray a -> Spray a
    content :: Spray a -> Spray a
content Spray a
spray = (Spray a -> Spray a -> Spray a) -> [Spray a] -> Spray a
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
foldl1' Spray a -> Spray a -> Spray a
forall a. (Eq a, C a) => Spray a -> Spray a -> Spray a
gcdSpray (Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sprayCoefficients' Int
n Spray a
spray)
    exactDivisionBy :: Spray a -> Spray a -> Spray a
    exactDivisionBy :: Spray a -> Spray a -> Spray a
exactDivisionBy Spray a
b Spray a
a = 
      if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
remainder 
        then Spray a
quo 
        else String -> Spray a
forall a. HasCallStack => String -> a
error String
"exactDivisionBy: should not happen."
      where
        (Spray a
quo, Spray a
remainder) = Spray a -> Spray a -> (Spray a, Spray a)
forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
sprayDivision Spray a
a Spray a
b
    contA :: Spray a
contA = Spray a -> Spray a
content Spray a
sprayA'
    contB :: Spray a
contB = Spray a -> Spray a
content Spray a
sprayB'
    sprayA'' :: Spray a
sprayA'' = Spray a -> Spray a -> Spray a
exactDivisionBy Spray a
contA Spray a
sprayA'
    sprayB'' :: Spray a
sprayB'' = Spray a -> Spray a -> Spray a
exactDivisionBy Spray a
contB Spray a
sprayB'
    t :: Spray a
t = Spray a
contASpray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
degB Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
contBSpray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
degA
    s0 :: Spray a
s0 = if Int
degA Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
degB Bool -> Bool -> Bool
&& Int -> Bool
forall a. Integral a => a -> Bool
odd Int
degA Bool -> Bool -> Bool
&& Int -> Bool
forall a. Integral a => a -> Bool
odd Int
degB 
      then Spray a -> Spray a
forall a. C a => a -> a
AlgAdd.negate Spray a
forall a. C a => Spray a
unitSpray :: Spray a
      else Spray a
forall a. C a => Spray a
unitSpray
    (Spray a
p0, Spray a
q0) = if Int
degA Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
degB
      then (Spray a
sprayA'', Spray a
sprayB'')
      else (Spray a
sprayB'', Spray a
sprayA'')
    go :: Spray a -> Spray a -> Spray a -> Spray a -> Spray a -> Spray a
    go :: Spray a -> Spray a -> Spray a -> Spray a -> Spray a -> Spray a
go Spray a
g Spray a
h Spray a
s Spray a
p Spray a
q = 
      if Int
degq' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
        then Spray a
s' Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
t Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
h''
        else Spray a -> Spray a -> Spray a -> Spray a -> Spray a -> Spray a
go Spray a
g' Spray a
h' Spray a
s' Spray a
p' Spray a
q'
        where
          degp :: Int
degp           = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n Spray a
p
          degq :: Int
degq           = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n Spray a
q
          delta :: Int
delta          = Int
degp Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
degq
          s' :: Spray a
s' = if Int -> Bool
forall a. Integral a => a -> Bool
odd Int
degp Bool -> Bool -> Bool
&& Int -> Bool
forall a. Integral a => a -> Bool
odd Int
degq 
            then Spray a -> Spray a
forall a. C a => a -> a
AlgAdd.negate Spray a
s 
            else Spray a
s
          (Spray a
_, (Spray a
_, Spray a
r)) = Int -> Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
forall a.
(Eq a, C a) =>
Int -> Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
pseudoDivision' Int
n Spray a
p Spray a
q
          p' :: Spray a
p'             = Spray a
q
          q' :: Spray a
q'             = Spray a -> Spray a -> Spray a
exactDivisionBy (Spray a
g Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
hSpray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
delta) Spray a
r
          (Int
degp', Spray a
ellp') = Int -> Spray a -> (Int, Spray a)
forall a. (Eq a, C a) => Int -> Spray a -> (Int, Spray a)
degreeAndLeadingCoefficient Int
n Spray a
p'
          (Int
degq', Spray a
ellq') = Int -> Spray a -> (Int, Spray a)
forall a. (Eq a, C a) => Int -> Spray a -> (Int, Spray a)
degreeAndLeadingCoefficient Int
n Spray a
q'
          g' :: Spray a
g'  = Spray a
ellp'
          h' :: Spray a
h'  = Spray a -> Spray a -> Spray a
exactDivisionBy (Spray a
hSpray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
delta) (Spray a
h Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
g'Spray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
delta)
          h'' :: Spray a
h'' = Spray a -> Spray a -> Spray a
exactDivisionBy (Spray a
h'Spray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
degp') (Spray a
h' Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
ellq'Spray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
degp')

-- | Polynomial subresultants of two sprays (the `subresultants` function 

-- computes the /principal/ subresultants).

-- This function makes several calls to `detLaplace` and then it can be slow.

polynomialSubresultants :: 
    (Eq a, AlgRing.C a) 
  => Int     -- ^ index of the variable with respect to which the subresultants will be computed (e.g. 2 for @y@)

  -> Spray a 
  -> Spray a 
  -> [Spray a]
polynomialSubresultants :: forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> [Spray a]
polynomialSubresultants Int
var Spray a
p Spray a
q 
  | Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1 Bool -> Bool -> Bool
|| Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
d               
    = String -> [Spray a]
forall a. HasCallStack => String -> a
error String
"polynomialSubresultants: invalid variable index." 
  | Bool
otherwise = [Int -> Spray a
sres Int
i | Int
i <- [Int
0 .. Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
n Int
m]]
  where
    d :: Int
d = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
p) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
q)
    permutation :: [Int]
permutation  = [Int
dInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
d] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
dInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
var]
    permutation' :: [Int]
permutation' = [Int
varInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 .. Int
d] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
var] 
    p' :: Spray a
p' = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
p
    q' :: Spray a
q' = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
q
    pcoeffs :: [Spray a]
pcoeffs = [Spray a] -> [Spray a]
forall a. [a] -> [a]
reverse ([Spray a] -> [Spray a]) -> [Spray a] -> [Spray a]
forall a b. (a -> b) -> a -> b
$ Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sprayCoefficients' Int
d Spray a
p'
    qcoeffs :: [Spray a]
qcoeffs = [Spray a] -> [Spray a]
forall a. [a] -> [a]
reverse ([Spray a] -> [Spray a]) -> [Spray a] -> [Spray a]
forall a b. (a -> b) -> a -> b
$ Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sprayCoefficients' Int
d Spray a
q'
    pcoeff :: Int -> Spray a
pcoeff Int
k = if Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 then Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray else [Spray a]
pcoeffs [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
k
    qcoeff :: Int -> Spray a
qcoeff Int
k = if Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 then Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray else [Spray a]
qcoeffs [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
k
    n :: Int
n = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
pcoeffs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    m :: Int
m = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
qcoeffs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    x :: Int -> Term a
x = Int -> Int -> Term a
forall a. C a => Int -> Int -> Term a
loneTerm' Int
d
    prow :: Int -> Int -> [Spray a]
prow Int
i Int
k = Int -> Spray a -> [Spray a]
forall a. Int -> a -> [a]
replicate Int
k Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray [Spray a] -> [Spray a] -> [Spray a]
forall a. [a] -> [a] -> [a]
++ 
                 [Int -> Spray a
pcoeff Int
j | Int
j <- [Int
n, Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2]] [Spray a] -> [Spray a] -> [Spray a]
forall a. [a] -> [a] -> [a]
++ 
                  [Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
p' (Int -> Term a
x (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k))]
    prows :: Int -> [[Spray a]]
prows Int
i = [Int -> Int -> [Spray a]
prow Int
i Int
k | Int
k <- [Int
0 .. Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]]
    qrow :: Int -> Int -> [Spray a]
qrow Int
i Int
k = Int -> Spray a -> [Spray a]
forall a. Int -> a -> [a]
replicate Int
k Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray [Spray a] -> [Spray a] -> [Spray a]
forall a. [a] -> [a] -> [a]
++ 
                 [Int -> Spray a
qcoeff Int
j | Int
j <- [Int
m, Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2]] [Spray a] -> [Spray a] -> [Spray a]
forall a. [a] -> [a] -> [a]
++
                  [Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
q' (Int -> Term a
x (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k))]
    qrows :: Int -> [[Spray a]]
qrows Int
i = [Int -> Int -> [Spray a]
qrow Int
i Int
k | Int
k <- [Int
0 .. Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]]
    matrix :: Int -> Matrix (Spray a)
matrix Int
i = [[Spray a]] -> Matrix (Spray a)
forall a. [[a]] -> Matrix a
fromLists (Int -> [[Spray a]]
prows Int
i [[Spray a]] -> [[Spray a]] -> [[Spray a]]
forall a. [a] -> [a] -> [a]
++ Int -> [[Spray a]]
qrows Int
i)
    sres :: Int -> Spray a
sres Int
i = if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
m Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n 
      then Spray a
q 
      else [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation' (Spray a -> Spray a) -> Spray a -> Spray a
forall a b. (a -> b) -> a -> b
$ Matrix (Spray a) -> Spray a
forall a. (Eq a, C a) => Matrix a -> a
detLaplace (Int -> Matrix (Spray a)
matrix Int
i)

-- | Sturm-Habicht sequence of a spray. This function calls `polynomialSubresultants`

-- and then it can be slow. 

sturmHabichtSequence :: 
    (Eq a, AlgRing.C a) 
  => Int     -- ^ index of the variable with respect to which the Sturm-Habicht sequence will be computed (e.g. 2 for @y@)

  -> Spray a 
  -> [Spray a]
sturmHabichtSequence :: forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sturmHabichtSequence Int
var Spray a
spray 
  | Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1 Bool -> Bool -> Bool
|| Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
d               
    = String -> [Spray a]
forall a. HasCallStack => String -> a
error String
"sturmHabichtSequence: invalid variable index." 
  | Bool
otherwise = [Spray a]
signedSubresultants [Spray a] -> [Spray a] -> [Spray a]
forall a. [a] -> [a] -> [a]
++ [Spray a
spray', Spray a
spray]
  where
    d :: Int
d = Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray
    spray' :: Spray a
spray' = Int -> Spray a -> Spray a
forall b. FunctionLike b => Int -> b -> b
derivative Int
var Spray a
spray
    spraySubresultants :: [Spray a]
spraySubresultants = Int -> Spray a -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> [Spray a]
polynomialSubresultants Int
var Spray a
spray Spray a
spray'
    n :: Int
n = [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
spraySubresultants 
    delta :: [Bool]
delta = [Int -> Bool
forall a. Integral a => a -> Bool
odd (Int -> Bool) -> Int -> Bool
forall a b. (a -> b) -> a -> b
$ ((Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)Int -> Int -> Int
forall a. Num a => a -> a -> a
*(Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k)) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2 | Int
k <- [Int
0 .. Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2]]
    negateIf :: Bool -> a -> a
negateIf Bool
test = if Bool
test then a -> a
forall a. C a => a -> a
AlgAdd.negate else a -> a
forall a. a -> a
id
    signedSubresultants :: [Spray a]
signedSubresultants = (Bool -> Spray a -> Spray a) -> [Bool] -> [Spray a] -> [Spray a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Bool -> Spray a -> Spray a
forall {a}. C a => Bool -> a -> a
negateIf [Bool]
delta [Spray a]
spraySubresultants

-- | Principal Sturm-Habicht sequence of a spray. This function calls `sturmHabicht` 

-- sequence and then it can be slow.

principalSturmHabichtSequence :: 
    (Eq a, AlgRing.C a) 
  => Int     -- ^ index of the variable with respect to which the Sturm-Habicht sequence will be computed (e.g. 2 for @y@)

  -> Spray a 
  -> [Spray a]
principalSturmHabichtSequence :: forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
principalSturmHabichtSequence Int
var Spray a
spray 
  | Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1 Bool -> Bool -> Bool
|| Int
var Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
d               
    = String -> [Spray a]
forall a. HasCallStack => String -> a
error String
"principalSturmHabichtSequence: invalid variable index." 
  | Bool
otherwise = [Int -> Spray a
jcoeff Int
j | Int
j <- [Int
0 .. [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
sHS Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]]
  where
    d :: Int
d = Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray
    sHS :: [Spray a]
sHS = Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sturmHabichtSequence Int
var Spray a
spray
    permutation :: [Int]
permutation  = [Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
var Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 .. Int
d] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
var]
    permutation' :: [Int]
permutation' = [Int
var Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 .. Int
d] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1 .. Int
var] 
    jcoeff :: Int -> Spray a
jcoeff Int
j = if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sHSj Bool -> Bool -> Bool
|| Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
coeffs
      then Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray
      else [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation' ([Spray a]
coeffs [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
j)
      where
        sHSj :: Spray a
sHSj = [Spray a]
sHS [Spray a] -> Int -> Spray a
forall a. HasCallStack => [a] -> Int -> a
!! Int
j
        p :: Spray a
p = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
sHSj
        coeffs :: [Spray a]
coeffs = [Spray a] -> [Spray a]
forall a. [a] -> [a]
reverse ([Spray a] -> [Spray a]) -> [Spray a] -> [Spray a]
forall a b. (a -> b) -> a -> b
$ Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sprayCoefficients' Int
d Spray a
p -- what if numberOfVariables p /= d ?



-- Number of real roots in interval -------------------------------------------


_signVariations :: (a -> Char) -> [a] -> Int
_signVariations :: forall a. (a -> Char) -> [a] -> Int
_signVariations a -> Char
signFunc [a]
as = Int
v1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
v2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
v3
  where
    count :: a -> [a] -> Int
count a
x [a]
xs = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((a -> Int) -> [a] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> Int
forall a. Enum a => a -> Int
fromEnum (Bool -> Int) -> (a -> Bool) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x)) [a]
xs)
    l :: Int
l = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
as
    signs :: String
signs = (a -> Char) -> [a] -> String
forall a b. (a -> b) -> [a] -> [b]
map a -> Char
signFunc [a]
as
    chunks2 :: [(Char, Char)]
chunks2 = [(String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! Int
i, String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)) | Int
i <- [Int
0 .. Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2]]
    v1 :: Int
v1 = (Char, Char) -> [(Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'+', Char
'-') [(Char, Char)]
chunks2
           Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Char, Char) -> [(Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'-', Char
'+') [(Char, Char)]
chunks2
    chunks3 :: [(Char, Char, Char)]
chunks3 = [(String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! Int
i, String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1), String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)) | Int
i <- [Int
0 .. Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
3]]
    chunks4 :: [(Char, Char, Char, Char)]
chunks4 = [(String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! Int
i, String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1), String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2), String
signs String -> Int -> Char
forall a. HasCallStack => [a] -> Int -> a
!! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3)) 
                | Int
i <- [Int
0 .. Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
4]]
    v2 :: Int
v2 = (Char, Char, Char) -> [(Char, Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'-', Char
'0', Char
'+') [(Char, Char, Char)]
chunks3 Int -> Int -> Int
forall a. Num a => a -> a -> a
+
           (Char, Char, Char) -> [(Char, Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'+', Char
'0', Char
'-') [(Char, Char, Char)]
chunks3 Int -> Int -> Int
forall a. Num a => a -> a -> a
+
             (Char, Char, Char, Char) -> [(Char, Char, Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'+', Char
'0', Char
'0', Char
'-') [(Char, Char, Char, Char)]
chunks4 Int -> Int -> Int
forall a. Num a => a -> a -> a
+
               (Char, Char, Char, Char) -> [(Char, Char, Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'-', Char
'0', Char
'0', Char
'+') [(Char, Char, Char, Char)]
chunks4
    v3 :: Int
v3 = (Char, Char, Char, Char) -> [(Char, Char, Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'+', Char
'0', Char
'0', Char
'+') [(Char, Char, Char, Char)]
chunks4 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 
           (Char, Char, Char, Char) -> [(Char, Char, Char, Char)] -> Int
forall {a}. Eq a => a -> [a] -> Int
count (Char
'-', Char
'0', Char
'0', Char
'-') [(Char, Char, Char, Char)]
chunks4

signVariations :: (Eq a, Num a) => [a] -> Int
signVariations :: forall a. (Eq a, Num a) => [a] -> Int
signVariations = (a -> Char) -> [a] -> Int
forall a. (a -> Char) -> [a] -> Int
_signVariations a -> Char
forall {a}. (Eq a, Num a) => a -> Char
signFunc
  where
    signFunc :: a -> Char
signFunc a
a
      | a -> a
forall a. Num a => a -> a
signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Char
'0'
      | a -> a
forall a. Num a => a -> a
signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 = Char
'+'
      | Bool
otherwise     = Char
'-' 

signVariations' :: (Eq a, AlgAbs.C a) => [a] -> Int
signVariations' :: forall a. (Eq a, C a) => [a] -> Int
signVariations' = (a -> Char) -> [a] -> Int
forall a. (a -> Char) -> [a] -> Int
_signVariations a -> Char
forall {a}. (Eq a, C a) => a -> Char
signFunc
  where
    signFunc :: a -> Char
signFunc a
a
      | a -> a
forall a. C a => a -> a
AlgAbs.signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero = Char
'0'
      | a -> a
forall a. C a => a -> a
AlgAbs.signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgRing.one = Char
'+'
      | Bool
otherwise                      = Char
'-' 

_numberOfRealRootsInOpenInterval :: 
  (AlgRing.C a, Ord a) => ([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInOpenInterval :: forall a.
(C a, Ord a) =>
([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInOpenInterval [a] -> Int
signVariationsFunc Spray a
spray Maybe a
alpha Maybe a
beta 
  | Spray a -> Bool
forall a. (Eq a, C a) => Spray a -> Bool
isConstantSpray Spray a
spray =
    if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray 
      then String -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRootsInOpenInterval: the spray is null."
      else Int
0
  | Bool
alphaIsJust Bool -> Bool -> Bool
&& Bool
betaIsJust = 
    if a
alpha' a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
beta'
      then Int
0
      else
        if Maybe a
alpha Maybe a -> Maybe a -> Bool
forall a. Ord a => a -> a -> Bool
> Maybe a
beta
          then 
            String -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRootsInOpenInterval: the bounds are not ordered."
          else 
            if Bool
isZeroAtBeta then Int
svDiff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 else Int
svDiff
  | Bool
alphaIsJust = Int
svDiff
  | Bool
betaIsJust  = if Bool
isZeroAtBeta then Int
svDiff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 else Int
svDiff
  | Bool
otherwise   = Int
svDiff 
  where
    alphaIsJust :: Bool
alphaIsJust = Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
alpha
    betaIsJust :: Bool
betaIsJust  = Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
beta
    alpha' :: a
alpha' = if Bool
alphaIsJust then Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust Maybe a
alpha else a
forall a. HasCallStack => a
undefined
    beta' :: a
beta'  = if Bool
betaIsJust then Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust Maybe a
beta else a
forall a. HasCallStack => a
undefined
    evaluateAtMinusInfinity :: Spray b -> b
evaluateAtMinusInfinity Spray b
p = if Spray b -> Bool
forall a. (Eq a, C a) => Spray a -> Bool
isConstantSpray Spray b
p 
      then Spray b -> b
forall a. C a => Spray a -> a
getConstantTerm Spray b
p
      else let 
        (Int
deg, b
lCoeff) = (Powers -> Int) -> (Powers, b) -> (Int, b)
forall a a' b. (a -> a') -> (a, b) -> (a', b)
first ((Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`S.index` Int
0) (Exponents -> Int) -> (Powers -> Exponents) -> Powers -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Powers -> Exponents
exponents) (Spray b -> (Powers, b)
forall a. Spray a -> Term a
leadingTerm Spray b
p) in
        if Int -> Bool
forall a. Integral a => a -> Bool
even Int
deg then b
lCoeff else b -> b
forall a. C a => a -> a
AlgAdd.negate b
lCoeff
    evaluateAtPlusInfinity :: Spray a -> a
evaluateAtPlusInfinity Spray a
p = if Spray a -> Bool
forall a. (Eq a, C a) => Spray a -> Bool
isConstantSpray Spray a
p 
      then Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
p
      else ((Powers, a) -> a
forall a b. (a, b) -> b
snd ((Powers, a) -> a) -> (Spray a -> (Powers, a)) -> Spray a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm) Spray a
p
    ([Spray a]
ginit, Spray a
glast) = 
      Maybe ([Spray a], Spray a) -> ([Spray a], Spray a)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe ([Spray a], Spray a) -> ([Spray a], Spray a))
-> Maybe ([Spray a], Spray a) -> ([Spray a], Spray a)
forall a b. (a -> b) -> a -> b
$ [Spray a] -> Maybe ([Spray a], Spray a)
forall a. [a] -> Maybe ([a], a)
unsnoc ([Spray a] -> Maybe ([Spray a], Spray a))
-> [Spray a] -> Maybe ([Spray a], Spray a)
forall a b. (a -> b) -> a -> b
$ (Spray a -> Bool) -> [Spray a] -> [Spray a]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Spray a -> Bool) -> Spray a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray) (Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sturmHabichtSequence Int
1 Spray a
spray)
    eval1 :: Spray a -> BaseRing (Spray a)
eval1 = 
      if Bool
alphaIsJust then [BaseRing (Spray a)] -> Spray a -> BaseRing (Spray a)
forall b. FunctionLike b => [BaseRing b] -> b -> BaseRing b
evaluateAt [a
BaseRing (Spray a)
alpha'] else Spray a -> a
Spray a -> BaseRing (Spray a)
forall {b}. (Eq b, C b) => Spray b -> b
evaluateAtMinusInfinity
    eval2 :: Spray a -> BaseRing (Spray a)
eval2 = 
      if Bool
betaIsJust then [BaseRing (Spray a)] -> Spray a -> BaseRing (Spray a)
forall b. FunctionLike b => [BaseRing b] -> b -> BaseRing b
evaluateAt [a
BaseRing (Spray a)
beta'] else Spray a -> a
Spray a -> BaseRing (Spray a)
forall {b}. (Eq b, C b) => Spray b -> b
evaluateAtPlusInfinity
    sprayAtAlpha :: BaseRing (Spray a)
sprayAtAlpha = Spray a -> BaseRing (Spray a)
eval1 Spray a
glast
    sprayAtBeta :: BaseRing (Spray a)
sprayAtBeta  = Spray a -> BaseRing (Spray a)
eval2 Spray a
glast
    isZeroAtBeta :: Bool
isZeroAtBeta = a
BaseRing (Spray a)
sprayAtBeta a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero
    galpha :: [a]
galpha = (Spray a -> a) -> [Spray a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> a
Spray a -> BaseRing (Spray a)
eval1 [Spray a]
ginit [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
BaseRing (Spray a)
sprayAtAlpha]
    gbeta :: [a]
gbeta  = (Spray a -> a) -> [Spray a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> a
Spray a -> BaseRing (Spray a)
eval2 [Spray a]
ginit [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
BaseRing (Spray a)
sprayAtBeta]
    svAtAlpha :: Int
svAtAlpha = [a] -> Int
signVariationsFunc [a]
galpha
    svAtBeta :: Int
svAtBeta  = [a] -> Int
signVariationsFunc [a]
gbeta
    svDiff :: Int
svDiff    = Int
svAtAlpha Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
svAtBeta

_numberOfRealRootsInClosedInterval :: 
   (AlgRing.C a, Ord a) => ([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInClosedInterval :: forall a.
(C a, Ord a) =>
([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInClosedInterval [a] -> Int
signVariationsFunc Spray a
spray Maybe a
alpha Maybe a
beta = 
  ([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
forall a.
(C a, Ord a) =>
([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInOpenInterval [a] -> Int
signVariationsFunc Spray a
spray Maybe a
alpha Maybe a
beta Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
toAdd
  where
    alphaIsJust :: Bool
alphaIsJust = Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
alpha
    betaIsJust :: Bool
betaIsJust  = Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
beta
    alpha' :: a
alpha' = if Bool
alphaIsJust then Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust Maybe a
alpha else a
forall a. HasCallStack => a
undefined
    beta' :: a
beta'  = if Bool
betaIsJust then Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust Maybe a
beta else a
forall a. HasCallStack => a
undefined
    isZeroAtAlpha :: Bool
isZeroAtAlpha = Bool
alphaIsJust Bool -> Bool -> Bool
&& [BaseRing (Spray a)] -> Spray a -> BaseRing (Spray a)
forall b. FunctionLike b => [BaseRing b] -> b -> BaseRing b
evaluateAt [a
BaseRing (Spray a)
alpha'] Spray a
spray a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero
    isZeroAtBeta :: Bool
isZeroAtBeta  = Bool
betaIsJust Bool -> Bool -> Bool
&& [BaseRing (Spray a)] -> Spray a -> BaseRing (Spray a)
forall b. FunctionLike b => [BaseRing b] -> b -> BaseRing b
evaluateAt [a
BaseRing (Spray a)
beta'] Spray a
spray a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero
    toAdd :: Int
toAdd = 
      if Maybe a
alpha Maybe a -> Maybe a -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe a
beta
        then Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
isZeroAtAlpha
        else Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
isZeroAtAlpha Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
isZeroAtBeta

-- | Number of real roots of a spray in an open interval (that makes sense 

-- only for a spray on a ring embeddable in the real numbers).

numberOfRealRootsInOpenInterval :: 
  (Num a, AlgRing.C a, Ord a) 
  => Spray a -- ^ a spray

  -> Maybe a -- ^ lower bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Maybe a -- ^ upper bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Int
numberOfRealRootsInOpenInterval :: forall a.
(Num a, C a, Ord a) =>
Spray a -> Maybe a -> Maybe a -> Int
numberOfRealRootsInOpenInterval Spray a
spray = 
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
spray 
    then ([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
forall a.
(C a, Ord a) =>
([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInOpenInterval [a] -> Int
forall a. (Eq a, Num a) => [a] -> Int
signVariations Spray a
spray
    else String -> Maybe a -> Maybe a -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRootsInOpenInterval: the spray is not univariate."

-- | Number of real roots of a spray in a closed interval (that makes sense 

-- only for a spray on a ring embeddable in the real numbers). The roots are 

-- not counted with their multiplicity.

numberOfRealRootsInClosedInterval :: 
  (Num a, AlgRing.C a, Ord a) 
  => Spray a -- ^ a spray

  -> Maybe a -- ^ lower bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Maybe a -- ^ upper bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Int
numberOfRealRootsInClosedInterval :: forall a.
(Num a, C a, Ord a) =>
Spray a -> Maybe a -> Maybe a -> Int
numberOfRealRootsInClosedInterval Spray a
spray = 
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
spray 
    then ([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
forall a.
(C a, Ord a) =>
([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInClosedInterval [a] -> Int
forall a. (Eq a, Num a) => [a] -> Int
signVariations Spray a
spray
    else String -> Maybe a -> Maybe a -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRootsInClosedInterval: the spray is not univariate."
 
-- | Number of real roots of a spray in an open interval (that makes sense 

-- only for a spray on a ring embeddable in the real numbers).

numberOfRealRootsInOpenInterval' :: 
  (AlgAbs.C a, Ord a) 
  => Spray a -- ^ a spray

  -> Maybe a -- ^ lower bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Maybe a -- ^ upper bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Int
numberOfRealRootsInOpenInterval' :: forall a. (C a, Ord a) => Spray a -> Maybe a -> Maybe a -> Int
numberOfRealRootsInOpenInterval' Spray a
spray =
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
spray 
    then ([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
forall a.
(C a, Ord a) =>
([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInOpenInterval [a] -> Int
forall a. (Eq a, C a) => [a] -> Int
signVariations' Spray a
spray
    else String -> Maybe a -> Maybe a -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRootsInOpenInterval': the spray is not univariate."

-- | Number of real roots of a spray in a closed interval (that makes sense 

-- only for a spray on a ring embeddable in the real numbers). The roots are 

-- not counted with their multiplicity.

numberOfRealRootsInClosedInterval' :: 
  (AlgAbs.C a, Ord a) 
  => Spray a -- ^ a spray

  -> Maybe a -- ^ lower bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Maybe a -- ^ upper bound of the interval; use @Just@ for a finite bound, and @Nothing@ for minus infinity

  -> Int
numberOfRealRootsInClosedInterval' :: forall a. (C a, Ord a) => Spray a -> Maybe a -> Maybe a -> Int
numberOfRealRootsInClosedInterval' Spray a
spray =
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
spray 
    then ([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
forall a.
(C a, Ord a) =>
([a] -> Int) -> Spray a -> Maybe a -> Maybe a -> Int
_numberOfRealRootsInClosedInterval [a] -> Int
forall a. (Eq a, C a) => [a] -> Int
signVariations' Spray a
spray
    else String -> Maybe a -> Maybe a -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRootsInClosedInterval': the spray is not univariate."


-- Number of real roots -------------------------------------------------------


runLengthEncoding :: Eq a => [a] -> [(a,Int)]
runLengthEncoding :: forall a. Eq a => [a] -> [(a, Int)]
runLengthEncoding = (a -> [(a, Int)] -> [(a, Int)]) -> [(a, Int)] -> [a] -> [(a, Int)]
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> [(a, Int)] -> [(a, Int)]
forall {b} {a}. (Num b, Eq a) => a -> [(a, b)] -> [(a, b)]
code []
  where 
    code :: a -> [(a, b)] -> [(a, b)]
code a
c []         = [(a
c,b
1)]
    code a
c ((a
x,b
n):[(a, b)]
ts) 
      | a
c a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x        = (a
x,b
nb -> b -> b
forall a. Num a => a -> a -> a
+b
1)(a, b) -> [(a, b)] -> [(a, b)]
forall a. a -> [a] -> [a]
:[(a, b)]
ts
      | Bool
otherwise     = (a
c,b
1)(a, b) -> [(a, b)] -> [(a, b)]
forall a. a -> [a] -> [a]
:(a
x,b
n)(a, b) -> [(a, b)] -> [(a, b)]
forall a. a -> [a] -> [a]
:[(a, b)]
ts

_signPermanencesAndVariations :: (a -> Char) -> [a] -> (Int, Int)
_signPermanencesAndVariations :: forall a. (a -> Char) -> [a] -> (Int, Int)
_signPermanencesAndVariations a -> Char
signFunc [a]
as = (Int
permanences, Int
variations)
  where
    signs :: String
signs = (a -> Char) -> [a] -> String
forall a b. (a -> b) -> [a] -> [b]
map a -> Char
signFunc [a]
as
    rle :: [(Char, Int)]
rle = String -> [(Char, Int)]
forall a. Eq a => [a] -> [(a, Int)]
runLengthEncoding String
signs
    l :: Int
l = [(Char, Int)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Char, Int)]
rle
    lengths :: [Int]
lengths = ((Char, Int) -> Int) -> [(Char, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Char, Int) -> Int
forall a b. (a, b) -> b
snd [(Char, Int)]
rle
    permanences :: Int
permanences = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
lengths Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l
    variations :: Int
variations = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1

signPermanencesAndVariations :: (Eq a, Num a) => [a] -> (Int, Int)
signPermanencesAndVariations :: forall a. (Eq a, Num a) => [a] -> (Int, Int)
signPermanencesAndVariations = (a -> Char) -> [a] -> (Int, Int)
forall a. (a -> Char) -> [a] -> (Int, Int)
_signPermanencesAndVariations a -> Char
forall {a}. (Eq a, Num a) => a -> Char
signFunc
  where
    signFunc :: a -> Char
signFunc a
a = if a -> a
forall a. Num a => a -> a
signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 then Char
'+' else Char
'-'

signPermanencesAndVariations' :: (Eq a, AlgAbs.C a) => [a] -> (Int, Int)
signPermanencesAndVariations' :: forall a. (Eq a, C a) => [a] -> (Int, Int)
signPermanencesAndVariations' = (a -> Char) -> [a] -> (Int, Int)
forall a. (a -> Char) -> [a] -> (Int, Int)
_signPermanencesAndVariations a -> Char
forall {a}. (Eq a, C a) => a -> Char
signFunc
  where
    signFunc :: a -> Char
signFunc a
a = if a -> a
forall a. C a => a -> a
AlgAbs.signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgRing.one then Char
'+' else Char
'-'

distributionsOfZeros :: (Eq a, AlgAdd.C a) => [a] -> ([Int], [Int], [Int])
distributionsOfZeros :: forall a. (Eq a, C a) => [a] -> ([Int], [Int], [Int])
distributionsOfZeros [a]
as = ([Int]
i_, [Int]
k_, [Int]
ik_)
  where
    symbol :: a -> Char
symbol a
a = if a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero then Char
'0' else Char
'*'
    symbols :: String
symbols = (a -> Char) -> [a] -> String
forall a b. (a -> b) -> [a] -> [b]
map a -> Char
forall {a}. (Eq a, C a) => a -> Char
symbol [a]
as String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
'0']
    lengths :: [Int]
lengths = ((Char, Int) -> Int) -> [(Char, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Char, Int) -> Int
forall a b. (a, b) -> b
snd (String -> [(Char, Int)]
forall a. Eq a => [a] -> [(a, Int)]
runLengthEncoding String
symbols)
    l :: Int
l = [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
lengths
    cumulativeLengths :: [Int]
cumulativeLengths = (Int -> Int -> Int) -> Int -> [Int] -> [Int]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) Int
0 [Int]
lengths
    range :: [Int]
range = [Int
0 .. Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]
    ik_ :: [Int]
ik_ = [[Int]
cumulativeLengths [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
i | Int
i <- [Int]
range, Int -> Bool
forall a. Integral a => a -> Bool
even Int
i]
    i_ :: [Int]
i_ = [[Int]
cumulativeLengths [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 | Int
i <- [Int]
range, Int -> Bool
forall a. Integral a => a -> Bool
odd Int
i]
    k_ :: [Int]
k_ = [[Int]
lengths [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
i | Int
i <- [Int
0 .. Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2], Int -> Bool
forall a. Integral a => a -> Bool
odd Int
i] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [[Int]
lengths [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]

_blocksAndEpsilons :: (Eq a, AlgAdd.C a) => (a -> Int) -> [a] -> ([[a]], [Int])
_blocksAndEpsilons :: forall a. (Eq a, C a) => (a -> Int) -> [a] -> ([[a]], [Int])
_blocksAndEpsilons a -> Int
signFunc [a]
as = ([[a]]
blocks, [Int]
epsilons)
  where
    ([Int]
i_, [Int]
k_, [Int]
ik_) = [a] -> ([Int], [Int], [Int])
forall a. (Eq a, C a) => [a] -> ([Int], [Int], [Int])
distributionsOfZeros [a]
as
    t :: Int
t = [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
i_
    blocks :: [[a]]
blocks = [[[a]
as [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
m | Int
m <- [[Int]
ik_ [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
n .. [Int]
i_ [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
n]] | Int
n <- [Int
0 .. Int
tInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]
    epsilon :: Int -> Int
epsilon Int
s = let ks :: Int
ks = [Int]
k_ [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
s in if Int -> Bool
forall a. Integral a => a -> Bool
odd Int
ks 
      then
        Int
0
      else
        (if Int -> Bool
forall a. Integral a => a -> Bool
even (Int
ks Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2) then Int
1 else -Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* 
          a -> Int
signFunc ([a]
as [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! ([Int]
ik_ [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1))) Int -> Int -> Int
forall a. Num a => a -> a -> a
* a -> Int
signFunc ([a]
as [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! ([Int]
i_ [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
s))
    epsilons :: [Int]
epsilons = [Int -> Int
epsilon Int
n | Int
n <- [Int
0 .. Int
tInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2]]

blocksAndEpsilons :: (Eq a, AlgAdd.C a, Num a) => [a] -> ([[a]], [Int])
blocksAndEpsilons :: forall a. (Eq a, C a, Num a) => [a] -> ([[a]], [Int])
blocksAndEpsilons = (a -> Int) -> [a] -> ([[a]], [Int])
forall a. (Eq a, C a) => (a -> Int) -> [a] -> ([[a]], [Int])
_blocksAndEpsilons a -> Int
forall {a} {a}. (Eq a, Num a, Num a) => a -> a
signFunc 
  where
    signFunc :: a -> a
signFunc a
a = if a -> a
forall a. Num a => a -> a
signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 then a
1 else -a
1

blocksAndEpsilons' :: (Eq a, AlgAbs.C a) => [a] -> ([[a]], [Int])
blocksAndEpsilons' :: forall a. (Eq a, C a) => [a] -> ([[a]], [Int])
blocksAndEpsilons' = (a -> Int) -> [a] -> ([[a]], [Int])
forall a. (Eq a, C a) => (a -> Int) -> [a] -> ([[a]], [Int])
_blocksAndEpsilons a -> Int
forall {a} {a}. (Eq a, C a, Num a) => a -> a
signFunc 
  where
    signFunc :: a -> a
signFunc a
a = if a -> a
forall a. C a => a -> a
AlgAbs.signum a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgRing.one then a
1 else -a
1

_C :: ([a] -> (Int, Int)) -> ([[a]], [Int]) -> Int
_C :: forall a. ([a] -> (Int, Int)) -> ([[a]], [Int]) -> Int
_C [a] -> (Int, Int)
signPermanencesAndVariationsFunc ([[a]]
blocks, [Int]
epsilons) = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
pvs Int -> Int -> Int
forall a. Num a => a -> a -> a
- [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
epsilons
  where
    permanencesMinusVariations :: [a] -> Int
permanencesMinusVariations [a]
as = 
      let (Int
p, Int
v) = [a] -> (Int, Int)
signPermanencesAndVariationsFunc [a]
as in Int
p Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
v 
    pvs :: [Int]
pvs = ([a] -> Int) -> [[a]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> Int
permanencesMinusVariations [[a]]
blocks

-- | Number of real roots of a spray (that makes sense only for a spray on a 

-- ring embeddable in the real numbers). The roots are not counted with their 

-- multiplicity.

numberOfRealRoots :: (Eq a, AlgRing.C a, Num a) => Spray a -> Int
numberOfRealRoots :: forall a. (Eq a, C a, Num a) => Spray a -> Int
numberOfRealRoots Spray a
spray = 
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
spray 
    then 
      if Spray a -> Bool
forall a. (Eq a, C a) => Spray a -> Bool
isConstantSpray Spray a
spray 
        then if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray
          then String -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRoots: the spray is null."
          else Int
0
        else ([a] -> (Int, Int)) -> ([[a]], [Int]) -> Int
forall a. ([a] -> (Int, Int)) -> ([[a]], [Int]) -> Int
_C [a] -> (Int, Int)
forall a. (Eq a, Num a) => [a] -> (Int, Int)
signPermanencesAndVariations ([a] -> ([[a]], [Int])
forall a. (Eq a, C a, Num a) => [a] -> ([[a]], [Int])
blocksAndEpsilons ([a] -> ([[a]], [Int])) -> [a] -> ([[a]], [Int])
forall a b. (a -> b) -> a -> b
$ [a] -> [a]
forall a. [a] -> [a]
reverse [a]
as)
    else 
      String -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRoots: the spray is not univariate."
  where
    as :: [a]
as = (Spray a -> a) -> [Spray a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm (Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
principalSturmHabichtSequence Int
1 Spray a
spray)

-- | Number of real roots of a spray (that makes sense only for a spray on a 

-- ring embeddable in the real numbers). The roots are not counted with their 

-- multiplicity.

numberOfRealRoots' :: (Eq a, AlgAbs.C a) => Spray a -> Int
numberOfRealRoots' :: forall a. (Eq a, C a) => Spray a -> Int
numberOfRealRoots' Spray a
spray = 
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
spray 
    then 
      if Spray a -> Bool
forall a. (Eq a, C a) => Spray a -> Bool
isConstantSpray Spray a
spray 
        then if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray
          then String -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRoots: the spray is null."
          else Int
0
        else ([a] -> (Int, Int)) -> ([[a]], [Int]) -> Int
forall a. ([a] -> (Int, Int)) -> ([[a]], [Int]) -> Int
_C [a] -> (Int, Int)
forall a. (Eq a, C a) => [a] -> (Int, Int)
signPermanencesAndVariations' ([a] -> ([[a]], [Int])
forall a. (Eq a, C a) => [a] -> ([[a]], [Int])
blocksAndEpsilons' ([a] -> ([[a]], [Int])) -> [a] -> ([[a]], [Int])
forall a b. (a -> b) -> a -> b
$ [a] -> [a]
forall a. [a] -> [a]
reverse [a]
as)
    else 
      String -> Int
forall a. HasCallStack => String -> a
error String
"numberOfRealRoots': the spray is not univariate."
  where
    as :: [a]
as = (Spray a -> a) -> [Spray a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm (Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
principalSturmHabichtSequence Int
1 Spray a
spray)


-- GCD stuff ------------------------------------------------------------------


-- | the spray coefficients of a spray as a univariate spray in x_n 

sprayCoefficients' :: (Eq a, AlgRing.C a) => Int -> Spray a -> [Spray a]
sprayCoefficients' :: forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sprayCoefficients' Int
n Spray a
spray 
  | Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
n = [Spray a
spray]
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0                       = [a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray a
constantTerm]
  | Bool
otherwise                    = [Spray a]
sprays 
  where
    permutation :: [Int]
permutation = [Int
2 .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1]
    spray' :: SafeSpray a
spray'      = Spray a -> SafeSpray a
forall a. Spray a -> SafeSpray a
safeSpray (Spray a -> SafeSpray a) -> Spray a -> SafeSpray a
forall a b. (a -> b) -> a -> b
$ [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
spray
    spray'' :: SafeSpray a
spray'' = SafeSpray a -> SafeSpray a
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' SafeSpray a
spray'
    ([Exponents]
expnts', [a]
coeffs') = [(Exponents, a)] -> ([Exponents], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip (SafeSpray a -> [(Exponents, a)]
forall k v. HashMap k v -> [(k, v)]
HM.toList SafeSpray a
spray'')
    constantTerm :: a
constantTerm = SafeSpray a -> a
forall a. C a => SafeSpray a -> a
getConstantTerm'' SafeSpray a
spray'
    xpows :: [Int]
xpows = (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) [Exponents]
expnts'
    powers'' :: [Powers]
powers'' = (Exponents -> Powers) -> [Exponents] -> [Powers]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Powers
powerize (Exponents -> Powers)
-> (Exponents -> Exponents) -> Exponents -> Powers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Exponents -> Exponents
forall a. Int -> Seq a -> Seq a
S.deleteAt Int
0) [Exponents]
expnts'
    sprays'' :: [Spray a]
sprays'' = (Powers -> a -> Spray a) -> [Powers] -> [a] -> [Spray a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (((Powers, a) -> Spray a) -> Powers -> a -> Spray a
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (Powers, a) -> Spray a
forall a. Term a -> Spray a
fromTerm) [Powers]
powers'' [a]
coeffs'
    imap :: IntMap (Spray a)
imap   = (Spray a -> Spray a -> Spray a)
-> [(Int, Spray a)] -> IntMap (Spray a)
forall a. (a -> a -> a) -> [(Int, a)] -> IntMap a
IM.fromListWith Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
(^+^) ([Int] -> [Spray a] -> [(Int, Spray a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
xpows [Spray a]
sprays'')
    imap' :: IntMap (Spray a)
imap'  = (Spray a -> Spray a -> Spray a)
-> Int -> Spray a -> IntMap (Spray a) -> IntMap (Spray a)
forall a. (a -> a -> a) -> Int -> a -> IntMap a -> IntMap a
IM.insertWith Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
(^+^) Int
0 (a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray a
constantTerm) IntMap (Spray a)
imap
    deg :: Int
deg    = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
xpows
    sprays :: [Spray a]
sprays = [
        Spray a -> Maybe (Spray a) -> Spray a
forall a. a -> Maybe a -> a
fromMaybe Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray (Int -> IntMap (Spray a) -> Maybe (Spray a)
forall a. Int -> IntMap a -> Maybe a
IM.lookup Int
i IntMap (Spray a)
imap')
        | Int
i <- [Int
deg, Int
degInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
0]
      ]

-- | the degree of a spray as a univariate spray in x_n with spray coefficients

degree :: (Eq a, AlgRing.C a) => Int -> Spray a -> Int
degree :: forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n Spray a
spray 
  | Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
spray = 
      if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
spray 
        then Int
forall a. Bounded a => a
minBound -- (should not happen)

        else Int
0
  | Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
n = Int
0
  | Bool
otherwise                    = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
xpows
    where
      permutation :: [Int]
permutation = [Int
2 .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1]
      spray' :: Spray a
spray'      = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
spray
      powers' :: [Powers]
powers'     = Spray a -> [Powers]
forall k v. HashMap k v -> [k]
HM.keys (Spray a -> [Powers]) -> Spray a -> [Powers]
forall a b. (a -> b) -> a -> b
$ Spray a -> Spray a
forall a. Spray a -> Spray a
removeConstantTerm Spray a
spray'
      xpows :: [Int]
xpows       = (Powers -> Int) -> [Powers] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ((Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) (Exponents -> Int) -> (Powers -> Exponents) -> Powers -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Powers -> Exponents
exponents) [Powers]
powers'

-- | the degree and the leading coefficient of a spray as a univariate spray 

-- in x_n with spray coefficients

degreeAndLeadingCoefficient :: (Eq a, AlgRing.C a) 
                                => Int -> Spray a -> (Int, Spray a)
degreeAndLeadingCoefficient :: forall a. (Eq a, C a) => Int -> Spray a -> (Int, Spray a)
degreeAndLeadingCoefficient Int
n Spray a
spray 
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0                       = (
                                    if a
constantTerm a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero 
                                      then Int
forall a. Bounded a => a
minBound -- (should not happen)

                                      else Int
0, 
                                    a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray a
constantTerm
                                   )
  | Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
n = (Int
0, Spray a
spray)
  | Bool
otherwise                    = (Int
deg, Spray a
leadingCoeff)
  where
    permutation :: [Int]
permutation  = [Int
2 .. Int
n] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
1]
    spray' :: Spray a
spray'       = [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
spray
    constantTerm :: a
constantTerm = Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
spray'
    spray'' :: Spray a
spray''            = Spray a -> Spray a
forall a. Spray a -> Spray a
removeConstantTerm Spray a
spray'
    ([Powers]
powers', [a]
coeffs') = [(Powers, a)] -> ([Powers], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip (Spray a -> [(Powers, a)]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray a
spray'')
    expnts' :: [Exponents]
expnts'            = (Powers -> Exponents) -> [Powers] -> [Exponents]
forall a b. (a -> b) -> [a] -> [b]
map Powers -> Exponents
exponents [Powers]
powers'
    xpows :: [Int]
xpows = (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) [Exponents]
expnts'
    deg :: Int
deg   = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
xpows
    is :: [Int]
is    = Int -> [Int] -> [Int]
forall a. Eq a => a -> [a] -> [Int]
elemIndices Int
deg [Int]
xpows
    powers'' :: [Powers]
powers'' = [Exponents -> Powers
powerize (Int -> Exponents -> Exponents
forall a. Int -> Seq a -> Seq a
S.deleteAt Int
0 ([Exponents]
expnts' [Exponents] -> Int -> Exponents
forall a. HasCallStack => [a] -> Int -> a
!! Int
i)) | Int
i <- [Int]
is]
    coeffs'' :: [a]
coeffs'' = [[a]
coeffs' [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
i | Int
i <- [Int]
is]
    leadingCoeff :: Spray a
leadingCoeff = [(Powers, a)] -> Spray a
forall a. (Eq a, C a) => [Term a] -> Spray a
sumTerms ([Powers] -> [a] -> [(Powers, a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Powers]
powers'' [a]
coeffs'')

-- | Pseudo-division of two sprays @A@ and @B@ such that @deg(A) >= deg(B)@

-- where @deg@ is the degree with respect to the outermost variable.

pseudoDivision :: (Eq a, AlgRing.C a)
  => Spray a                       -- ^ A

  -> Spray a                       -- ^ B

  -> (Spray a, (Spray a, Spray a)) -- ^ (C, (Q, R)) such that C^*^A = B^*^Q ^+^ R

pseudoDivision :: forall a.
(Eq a, C a) =>
Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
pseudoDivision Spray a
sprayA Spray a
sprayB = 
  Int -> Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
forall a.
(Eq a, C a) =>
Int -> Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
pseudoDivision' (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayA) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayB))
                    Spray a
sprayA Spray a
sprayB

-- | pseudo-division of two sprays, assuming degA >= degB >= 0

pseudoDivision' :: (Eq a, AlgRing.C a)
  => Int                           -- ^ number of variables

  -> Spray a                       -- ^ A

  -> Spray a                       -- ^ B

  -> (Spray a, (Spray a, Spray a)) -- ^ (C, (Q, R)) such that C^*^A = B^*^Q ^+^ R

pseudoDivision' :: forall a.
(Eq a, C a) =>
Int -> Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
pseudoDivision' Int
n Spray a
sprayA Spray a
sprayB 
  | Int
degB Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
forall a. Bounded a => a
minBound = String -> (Spray a, (Spray a, Spray a))
forall a. HasCallStack => String -> a
error String
"pseudoDivision: pseudo-division by 0."
  | Int
degA Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
degB      = String -> (Spray a, (Spray a, Spray a))
forall a. HasCallStack => String -> a
error String
"pseudoDivision: degree(A) < degree(B)."
  | Bool
otherwise        = (Spray a
ellB Spray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^ Int
delta , Spray a -> Spray a -> Int -> (Spray a, Spray a)
go Spray a
sprayA Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray Int
delta)
  where
    degA :: Int
degA         = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n Spray a
sprayA
    (Int
degB, Spray a
ellB) = Int -> Spray a -> (Int, Spray a)
forall a. (Eq a, C a) => Int -> Spray a -> (Int, Spray a)
degreeAndLeadingCoefficient Int
n Spray a
sprayB
    delta :: Int
delta        = Int
degA Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
degB Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
    go :: Spray a -> Spray a -> Int -> (Spray a, Spray a)
go Spray a
sprayR Spray a
sprayQ Int
e = 
      if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sprayR Bool -> Bool -> Bool
|| Int
degR Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
degB
        then (Spray a
q Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
sprayQ, Spray a
q Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
sprayR)
        else Spray a -> Spray a -> Int -> (Spray a, Spray a)
go (Spray a
ellB Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
sprayR Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a
sprayS Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
sprayB) 
                (Spray a
ellB Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
sprayQ Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ Spray a
sprayS) 
                (Int
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
      where
        (Int
degR, Spray a
ellR) = Int -> Spray a -> (Int, Spray a)
forall a. (Eq a, C a) => Int -> Spray a -> (Int, Spray a)
degreeAndLeadingCoefficient Int
n Spray a
sprayR
        q :: Spray a
q            = Spray a
ellB Spray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^ Int
e
        sprayS :: Spray a
sprayS       = Spray a -> Term a -> Spray a
forall a. (Eq a, C a) => Spray a -> Term a -> Spray a
multSprayByTerm Spray a
ellR (Int -> Int -> Term a
forall a. C a => Int -> Int -> Term a
loneTerm' Int
n (Int
degR Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
degB))

{- spray1,spray2 :: QSpray
spray1 = let x = qlone 1
             y = qlone 2
             z = qlone 3
         in
          (-5)*^x^**^3 ^-^ 11*^(x^**^2^*^y) ^-^ 11*^(x^*^y^**^2) ^-^ 8*^(x^*^y^*^z) ^+^ 20*^(x^*^z^**^2) ^-^ 5*^y^**^3 ^+^ 20*^(y^*^z^**^2)
spray2 = let x = qlone 1
             y = qlone 2
             z = qlone 3
         in
          x^*^y ^-^ x^*^z ^-^ y^*^z ^+^ z^**^2
 -}

-- | recursive GCD function

gcdKX1dotsXn :: forall a. (Eq a, AlgField.C a) 
                => Int -> Spray a -> Spray a -> Spray a
gcdKX1dotsXn :: forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> Spray a
gcdKX1dotsXn Int
n Spray a
sprayA Spray a
sprayB
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0              = a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray (a -> Spray a) -> a -> Spray a
forall a b. (a -> b) -> a -> b
$ Spray a -> Spray a -> a
gcdKX0 Spray a
sprayA Spray a
sprayB
  | Int
degB Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
degA         = Int -> Spray a -> Spray a -> Spray a
forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> Spray a
gcdKX1dotsXn Int
n Spray a
sprayB Spray a
sprayA 
  | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sprayB  = Spray a
sprayA
  | Bool
otherwise           = Spray a -> Spray a -> Spray a -> Spray a -> Spray a
go Spray a
sprayA' Spray a
sprayB' Spray a
forall a. C a => Spray a
unitSpray Spray a
forall a. C a => Spray a
unitSpray
  where
    gcdKX0 :: Spray a -> Spray a -> a
    gcdKX0 :: Spray a -> Spray a -> a
gcdKX0 = (Spray a -> a) -> Spray a -> Spray a -> a
forall a b. a -> b -> a
const ((Spray a -> a) -> Spray a -> Spray a -> a)
-> (Spray a -> a) -> Spray a -> Spray a -> a
forall a b. (a -> b) -> a -> b
$ a -> Spray a -> a
forall a b. a -> b -> a
const a
forall a. C a => a
AlgRing.one 
    n' :: Int
n' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayA) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayB)
    degA :: Int
degA = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n' Spray a
sprayA
    degB :: Int
degB = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n' Spray a
sprayB
    gcdKX1dotsXm :: Spray a -> Spray a -> Spray a
gcdKX1dotsXm = Int -> Spray a -> Spray a -> Spray a
forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> Spray a
gcdKX1dotsXn (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
    content :: Spray a -> Spray a
    content :: Spray a -> Spray a
content Spray a
spray = (Spray a -> Spray a -> Spray a) -> [Spray a] -> Spray a
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
foldl1' Spray a -> Spray a -> Spray a
gcdKX1dotsXm (Int -> Spray a -> [Spray a]
forall a. (Eq a, C a) => Int -> Spray a -> [Spray a]
sprayCoefficients' Int
n' Spray a
spray)
    exactDivisionBy :: Spray a -> Spray a -> Spray a
    exactDivisionBy :: Spray a -> Spray a -> Spray a
exactDivisionBy Spray a
b Spray a
a = 
      if Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
remainder 
        then Spray a
quo 
        else String -> Spray a
forall a. HasCallStack => String -> a
error String
"exactDivisionBy: should not happen."
      where
        (Spray a
quo, Spray a
remainder) = Spray a -> Spray a -> (Spray a, Spray a)
forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
sprayDivision Spray a
a Spray a
b
    reduceSpray :: Spray a -> Spray a
    reduceSpray :: Spray a -> Spray a
reduceSpray Spray a
spray = Spray a -> Spray a -> Spray a
exactDivisionBy (Spray a -> Spray a
content Spray a
spray) Spray a
spray 
    contA :: Spray a
contA   = Spray a -> Spray a
content Spray a
sprayA
    contB :: Spray a
contB   = Spray a -> Spray a
content Spray a
sprayB
    d :: Spray a
d       = Spray a -> Spray a -> Spray a
gcdKX1dotsXm Spray a
contA Spray a
contB 
    sprayA' :: Spray a
sprayA' = Spray a -> Spray a -> Spray a
exactDivisionBy Spray a
contA Spray a
sprayA 
    sprayB' :: Spray a
sprayB' = Spray a -> Spray a -> Spray a
exactDivisionBy Spray a
contB Spray a
sprayB 
    go :: Spray a -> Spray a -> Spray a -> Spray a -> Spray a
    go :: Spray a -> Spray a -> Spray a -> Spray a -> Spray a
go Spray a
sprayA'' Spray a
sprayB'' Spray a
g Spray a
h 
      | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
sprayR            = Spray a
d Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a -> Spray a
reduceSpray Spray a
sprayB''
      | Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayR Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Spray a
d
      | Bool
otherwise = Spray a -> Spray a -> Spray a -> Spray a -> Spray a
go Spray a
sprayB'' 
                       (Spray a -> Spray a -> Spray a
exactDivisionBy (Spray a
g Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
hSpray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
delta) Spray a
sprayR)
                       Spray a
ellB'' ---- ellA''

                       (Spray a -> Spray a -> Spray a
exactDivisionBy (Spray a
hSpray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
delta) (Spray a
h Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
ellB''Spray a -> Int -> Spray a
forall b. (FunctionLike b, C b) => b -> Int -> b
^**^Int
delta)) --- g^**^delta

        where
          (Spray a
_, (Spray a
_, Spray a
sprayR)) = Int -> Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
forall a.
(Eq a, C a) =>
Int -> Spray a -> Spray a -> (Spray a, (Spray a, Spray a))
pseudoDivision' Int
n' Spray a
sprayA'' Spray a
sprayB''
          -- (degA'', ellA'') = degreeAndLeadingCoefficient n' sprayA''

          -- degB''           = degree n' sprayB''

          degA'' :: Int
degA''           = Int -> Spray a -> Int
forall a. (Eq a, C a) => Int -> Spray a -> Int
degree Int
n' Spray a
sprayA''
          (Int
degB'', Spray a
ellB'') = Int -> Spray a -> (Int, Spray a)
forall a. (Eq a, C a) => Int -> Spray a -> (Int, Spray a)
degreeAndLeadingCoefficient Int
n' Spray a
sprayB''
          delta :: Int
delta            = Int
degA'' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
degB''

-- | Greatest common divisor of two sprays with coefficients in a field

gcdSpray :: forall a. (Eq a, AlgField.C a) => Spray a -> Spray a -> Spray a
gcdSpray :: forall a. (Eq a, C a) => Spray a -> Spray a -> Spray a
gcdSpray Spray a
sprayA Spray a
sprayB = Int -> Spray a -> Spray a -> Spray a
forall a. (Eq a, C a) => Int -> Spray a -> Spray a -> Spray a
gcdKX1dotsXn Int
n Spray a
sprayA Spray a
sprayB 
  where
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayA) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
sprayB)


-- Matrices -------------------------------------------------------------------


-- | Determinant of a matrix with entries in a ring by using Laplace 

-- expansion (this is slow); the __numeric-prelude__ package provides some 

-- stuff to deal with matrices over a ring but it does not provide the 

-- determinant

detLaplace :: forall a. (Eq a, AlgRing.C a) => Matrix a -> a
detLaplace :: forall a. (Eq a, C a) => Matrix a -> a
detLaplace Matrix a
b = 
  if Matrix a -> Int
forall a. Matrix a -> Int
nrows Matrix a
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Matrix a -> Int
forall a. Matrix a -> Int
ncols Matrix a
b 
    then Matrix a -> a
detUnsafe Matrix a
b
    else String -> a
forall a. HasCallStack => String -> a
error String
"detLaplace: the matrix is not square."
  where 
    detUnsafe :: Matrix a -> a
detUnsafe Matrix a
m = if Matrix a -> Int
forall a. Matrix a -> Int
nrows Matrix a
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 
      then 
        Matrix a
m Matrix a -> (Int, Int) -> a
forall a. Matrix a -> (Int, Int) -> a
DM.! (Int
1,Int
1)
      else 
        [a] -> a
suml1 
          [Int -> a -> a
forall {a} {a}. (Integral a, C a) => a -> a -> a
negateIf Int
i (a -> a -> a
times (Matrix a
m Matrix a -> (Int, Int) -> a
forall a. Matrix a -> (Int, Int) -> a
DM.! (Int
i,Int
1)) (Matrix a -> a
detUnsafe (Int -> Int -> Matrix a -> Matrix a
forall a. Int -> Int -> Matrix a -> Matrix a
minorMatrix Int
i Int
1 Matrix a
m))) 
          | Int
i <- [Int
1 .. Matrix a -> Int
forall a. Matrix a -> Int
nrows Matrix a
m]]
    suml1 :: [a] -> a
suml1      = (a -> a -> a) -> [a] -> a
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
foldl1' a -> a -> a
forall a. C a => a -> a -> a
(AlgAdd.+)
    negateIf :: a -> a -> a
negateIf a
i = if a -> Bool
forall a. Integral a => a -> Bool
even a
i then a -> a
forall a. C a => a -> a
AlgAdd.negate else a -> a
forall a. a -> a
id
    times :: a -> a -> a
    times :: a -> a -> a
times a
x a
y = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. C a => a
AlgAdd.zero then a
forall a. C a => a
AlgAdd.zero else a
x a -> a -> a
forall a. C a => a -> a -> a
AlgRing.* a
y

-- | Determinant of a matrix over a ring by using Laplace expansion; this is 

-- the same as `detLaplace` but for a matrix from the __numeric-prelude__ 

-- package

detLaplace' :: forall a. (Eq a, AlgRing.C a) => MathMatrix.T a -> a
detLaplace' :: forall a. (Eq a, C a) => T a -> a
detLaplace' T a
m = Matrix a -> a
forall a. (Eq a, C a) => Matrix a -> a
detLaplace ([[a]] -> Matrix a
forall a. [[a]] -> Matrix a
DM.fromLists ([[a]] -> Matrix a) -> [[a]] -> Matrix a
forall a b. (a -> b) -> a -> b
$ T a -> [[a]]
forall a. T a -> [[a]]
MathMatrix.rows T a
m) 

-- | Characteristic polynomial of a square matrix

--

-- >>> import Data.Matrix (Matrix, fromLists)

-- >>> m = fromLists [ [12, 16, 4]

-- >>>               , [16, 2, 8]

-- >>>               , [8, 18, 10] ] :: Matrix Int

-- >>> spray = characteristicPolynomial m

-- >>> putStrLn $ prettyNumSpray spray

-- -x^3 + 24*x^2 + 268*x - 1936

characteristicPolynomial :: (Eq a, AlgRing.C a) => Matrix a -> Spray a
characteristicPolynomial :: forall a. (Eq a, C a) => Matrix a -> Spray a
characteristicPolynomial Matrix a
m = 
  if Matrix a -> Int
forall a. Matrix a -> Int
nrows Matrix a
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Matrix a -> Int
forall a. Matrix a -> Int
ncols Matrix a
m 
    then String -> Spray a
forall a. HasCallStack => String -> a
error String
"characteristicPolynomial: the matrix is not square."
    else Matrix (Spray a) -> Spray a
forall a. (Eq a, C a) => Matrix a -> a
detLaplace Matrix (Spray a)
m'
  where
    m' :: Matrix (Spray a)
m' = ((Int, Int) -> a -> Spray a) -> Matrix a -> Matrix (Spray a)
forall a b. ((Int, Int) -> a -> b) -> Matrix a -> Matrix b
DM.mapPos (Int, Int) -> a -> Spray a
f Matrix a
m
    f :: (Int, Int) -> a -> Spray a
f (Int
i, Int
j) a
mij = if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
j 
      then a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray a
mij Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a
x
      else a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray a
mij
    x :: Spray a
x = Int -> Spray a
forall a. C a => Int -> Spray a
lone Int
1


-- Ratios of sprays -----------------------------------------------------------


-- | A @RatioOfSprays a@ object represents a fraction of two multivariate 

-- polynomials whose coefficients are of type @a@, which represents a field. 

-- These two polynomials are represented by two @Spray a@ objects. Generally 

-- we do not use this constructor to build a ratio of sprays: we use the `%//%`

-- operator instead, because it always returns an irreducible ratio of sprays, 

-- meaning that its corresponding fraction of polynomials is irreducible, i.e. 

-- its numerator and its denominator are coprime. You can use this constructor 

-- if you are /sure/ that the numerator and the denominator are coprime. This 

-- can save some computation time, but unfortunate consequences can occur if 

-- the numerator and the denominator are not coprime. An arithmetic operation

-- on ratios of sprays always returns an irreducible ratio of sprays under the 

-- condition that the ratios of sprays it involves are irreducible. Moreover, 

-- it never returns a ratio of sprays with a constant denominator other than 

-- the unit spray. If you use this constructor with a constant denominator, 

-- always set this denominator to the unit spray (by dividing the numerator 

-- by the constant value of the denominator).

data RatioOfSprays a = RatioOfSprays
  { forall a. RatioOfSprays a -> Spray a
_numerator   :: Spray a
  , forall a. RatioOfSprays a -> Spray a
_denominator :: Spray a
  }
  deriving Int -> RatioOfSprays a -> ShowS
[RatioOfSprays a] -> ShowS
RatioOfSprays a -> String
(Int -> RatioOfSprays a -> ShowS)
-> (RatioOfSprays a -> String)
-> ([RatioOfSprays a] -> ShowS)
-> Show (RatioOfSprays a)
forall a. Show a => Int -> RatioOfSprays a -> ShowS
forall a. Show a => [RatioOfSprays a] -> ShowS
forall a. Show a => RatioOfSprays a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> RatioOfSprays a -> ShowS
showsPrec :: Int -> RatioOfSprays a -> ShowS
$cshow :: forall a. Show a => RatioOfSprays a -> String
show :: RatioOfSprays a -> String
$cshowList :: forall a. Show a => [RatioOfSprays a] -> ShowS
showList :: [RatioOfSprays a] -> ShowS
Show

type RatioOfQSprays = RatioOfSprays Rational

instance (Eq a, AlgField.C a) => FunctionLike (RatioOfSprays a) where
  type BaseRing (RatioOfSprays a) = a
  --

  type VariablesType (RatioOfSprays a) = Spray a
  --

  (*^) :: a -> RatioOfSprays a -> RatioOfSprays a
  *^ :: a -> RatioOfSprays a -> RatioOfSprays a
(*^) a
lambda RatioOfSprays a
rOS = a
lambda a -> RatioOfSprays a -> RatioOfSprays a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfSprays a
rOS
  --

  (+>) :: a -> RatioOfSprays a -> RatioOfSprays a
  +> :: a -> RatioOfSprays a -> RatioOfSprays a
(+>) a
x RatioOfSprays a
rOS =  RatioOfSprays a
rOS RatioOfSprays a -> RatioOfSprays a -> RatioOfSprays a
forall a. C a => a -> a -> a
AlgAdd.+ Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays (a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray a
x)
  --

  substitute :: [Maybe a] -> RatioOfSprays a -> RatioOfSprays a
  substitute :: [Maybe a] -> RatioOfSprays a -> RatioOfSprays a
substitute [Maybe a]
subs (RatioOfSprays Spray a
p Spray a
q) = 
    [Maybe (BaseRing (Spray a))] -> Spray a -> Spray a
forall b. FunctionLike b => [Maybe (BaseRing b)] -> b -> b
substitute [Maybe a]
[Maybe (BaseRing (Spray a))]
subs Spray a
p Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
%//% [Maybe (BaseRing (Spray a))] -> Spray a -> Spray a
forall b. FunctionLike b => [Maybe (BaseRing b)] -> b -> b
substitute [Maybe a]
[Maybe (BaseRing (Spray a))]
subs Spray a
q  
  --

  evaluate :: RatioOfSprays a -> [a] -> a
  evaluate :: RatioOfSprays a -> [a] -> a
evaluate (RatioOfSprays Spray a
p Spray a
q) [a]
xyz = Spray a -> [BaseRing (Spray a)] -> BaseRing (Spray a)
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate Spray a
p [a]
[BaseRing (Spray a)]
xyz a -> a -> a
forall a. C a => a -> a -> a
AlgField./ Spray a -> [BaseRing (Spray a)] -> BaseRing (Spray a)
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate Spray a
q [a]
[BaseRing (Spray a)]
xyz
  --

  changeVariables :: RatioOfSprays a -> [Spray a] -> RatioOfSprays a
  changeVariables :: RatioOfSprays a -> [Spray a] -> RatioOfSprays a
changeVariables RatioOfSprays a
rOS [Spray a]
newVariables = 
    if [Spray a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Spray a]
newVariables Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< RatioOfSprays a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables RatioOfSprays a
rOS
      then 
        String -> RatioOfSprays a
forall a. HasCallStack => String -> a
error String
"changeVariables: not enough new variables provided."
      else
        Spray a -> [VariablesType (Spray a)] -> Spray a
forall b. FunctionLike b => b -> [VariablesType b] -> b
changeVariables (RatioOfSprays a -> Spray a
forall a. RatioOfSprays a -> Spray a
_numerator RatioOfSprays a
rOS) [Spray a]
[VariablesType (Spray a)]
newVariables 
          Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
%//% Spray a -> [VariablesType (Spray a)] -> Spray a
forall b. FunctionLike b => b -> [VariablesType b] -> b
changeVariables (RatioOfSprays a -> Spray a
forall a. RatioOfSprays a -> Spray a
_denominator RatioOfSprays a
rOS) [Spray a]
[VariablesType (Spray a)]
newVariables 
  --

  numberOfVariables :: RatioOfSprays a -> Int
  numberOfVariables :: RatioOfSprays a -> Int
numberOfVariables (RatioOfSprays Spray a
p Spray a
q) = 
    Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
p) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
q)
  --

  permuteVariables :: [Int] -> RatioOfSprays a -> RatioOfSprays a
  permuteVariables :: [Int] -> RatioOfSprays a -> RatioOfSprays a
permuteVariables [Int]
permutation (RatioOfSprays Spray a
p Spray a
q) = 
    [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
p Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
%//% [Int] -> Spray a -> Spray a
forall b. FunctionLike b => [Int] -> b -> b
permuteVariables [Int]
permutation Spray a
q
  --

  swapVariables :: (Int, Int) -> RatioOfSprays a -> RatioOfSprays a
  swapVariables :: (Int, Int) -> RatioOfSprays a -> RatioOfSprays a
swapVariables (Int
i, Int
j) (RatioOfSprays Spray a
p Spray a
q) = 
    (Int, Int) -> Spray a -> Spray a
forall b. FunctionLike b => (Int, Int) -> b -> b
swapVariables (Int
i, Int
j) Spray a
p Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
%//% (Int, Int) -> Spray a -> Spray a
forall b. FunctionLike b => (Int, Int) -> b -> b
swapVariables (Int
i, Int
j) Spray a
q
  --

  involvesVariable :: RatioOfSprays a -> Int -> Bool
  involvesVariable :: RatioOfSprays a -> Int -> Bool
involvesVariable (RatioOfSprays Spray a
p Spray a
q) Int
i = 
    Spray a -> Int -> Bool
forall b. FunctionLike b => b -> Int -> Bool
involvesVariable Spray a
p Int
i Bool -> Bool -> Bool
|| Spray a -> Int -> Bool
forall b. FunctionLike b => b -> Int -> Bool
involvesVariable Spray a
q Int
i
  --

  dropVariables :: Int -> RatioOfSprays a -> RatioOfSprays a
  dropVariables :: Int -> RatioOfSprays a -> RatioOfSprays a
dropVariables Int
n (RatioOfSprays Spray a
p Spray a
q) = 
    Int -> Spray a -> Spray a
forall b. FunctionLike b => Int -> b -> b
dropVariables Int
n Spray a
p Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
%//% Int -> Spray a -> Spray a
forall b. FunctionLike b => Int -> b -> b
dropVariables Int
n Spray a
q 
  --

  derivative :: Int -> RatioOfSprays a -> RatioOfSprays a
  derivative :: Int -> RatioOfSprays a -> RatioOfSprays a
derivative Int
i (RatioOfSprays Spray a
p Spray a
q) = (Spray a
p' Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a
p Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q') Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
%//% (Spray a
q Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q)
    where
      p' :: Spray a
p' = Int -> Spray a -> Spray a
forall b. FunctionLike b => Int -> b -> b
derivative Int
i Spray a
p
      q' :: Spray a
q' = Int -> Spray a -> Spray a
forall b. FunctionLike b => Int -> b -> b
derivative Int
i Spray a
q

-- | quotients of two univariate sprays by their gcd

-- we use `sprayDivision0` because this function is called 

-- (by `irreducibleFraction`) with non-constant sprays only

quotientsByGCD :: 
  (Eq a, AlgField.C a) => Spray a -> Spray a -> (Spray a, Spray a)
quotientsByGCD :: forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
quotientsByGCD Spray a
sprayA Spray a
sprayB = 
  if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
sprayA Bool -> Bool -> Bool
&& Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isUnivariate Spray a
sprayB
    then
      Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> (Spray a, Spray a)
forall {a}.
(Eq a, C a) =>
Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> (Spray a, Spray a)
go Spray a
sprayA Spray a
sprayB Spray a
forall a. C a => Spray a
unitSpray Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray Spray a
forall a. C a => Spray a
unitSpray
    else
      (Spray a -> Spray a -> Spray a
forall a. (Eq a, C a) => Spray a -> Spray a -> Spray a
exactDivision Spray a
sprayA Spray a
g, Spray a -> Spray a -> Spray a
forall a. (Eq a, C a) => Spray a -> Spray a -> Spray a
exactDivision Spray a
sprayB Spray a
g)
    where 
      exactDivision :: Spray a -> Spray a -> Spray a
exactDivision Spray a
p Spray a
q = (Spray a, Spray a) -> Spray a
forall a b. (a, b) -> a
fst (Spray a -> Spray a -> (Spray a, Spray a)
forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
sprayDivision0 Spray a
p Spray a
q)
      g :: Spray a
g = Spray a -> Spray a -> Spray a
forall a. (Eq a, C a) => Spray a -> Spray a -> Spray a
gcdSpray Spray a
sprayA Spray a
sprayB
      go :: Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> (Spray a, Spray a)
go Spray a
oldr Spray a
r Spray a
olds Spray a
s Spray a
oldt Spray a
t 
        | Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray a
r = (a
BaseRing (Spray a)
c BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a -> Spray a
forall a. C a => a -> a
AlgAdd.negate Spray a
t, a
BaseRing (Spray a)
c BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
s) -- monic denominator

        | Bool
otherwise     = 
            Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> Spray a
-> (Spray a, Spray a)
go Spray a
r Spray a
remainder Spray a
s (Spray a
olds Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a
quo Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
s) Spray a
t (Spray a
oldt Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray a
quo Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
t)
          where
            (Spray a
quo, Spray a
remainder) = Spray a -> Spray a -> (Spray a, Spray a)
forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
univariateSprayDivision Spray a
oldr Spray a
r
            c :: a
c = a -> a
forall a. C a => a -> a
AlgField.recip ((Powers, a) -> a
forall a b. (a, b) -> b
snd ((Powers, a) -> a) -> (Powers, a) -> a
forall a b. (a -> b) -> a -> b
$ Spray a -> (Powers, a)
forall a. Spray a -> Term a
leadingTerm Spray a
s)

-- | irreducible fraction of sprays

irreducibleFraction ::
  (Eq a, AlgField.C a) => Spray a -> Spray a -> RatioOfSprays a
irreducibleFraction :: forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
irreducibleFraction Spray a
p Spray a
q = RatioOfSprays a -> RatioOfSprays a
forall a. (Eq a, C a) => RatioOfSprays a -> RatioOfSprays a
adjustFraction RatioOfSprays a
rOS
  where
    rOS :: RatioOfSprays a
rOS = if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
p Bool -> Bool -> Bool
|| Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
q
      then Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
p Spray a
q 
      else let (Spray a
a, Spray a
b) = Spray a -> Spray a -> (Spray a, Spray a)
forall a. (Eq a, C a) => Spray a -> Spray a -> (Spray a, Spray a)
quotientsByGCD Spray a
p Spray a
q in Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
a Spray a
b

-- | set denominator to 1 if it is constant

adjustFraction :: (Eq a, AlgField.C a) => RatioOfSprays a -> RatioOfSprays a
adjustFraction :: forall a. (Eq a, C a) => RatioOfSprays a -> RatioOfSprays a
adjustFraction (RatioOfSprays Spray a
p Spray a
q) = if Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant Spray a
q 
  then Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays (Spray a
p Spray a -> a -> Spray a
forall a. (C a, Eq a) => Spray a -> a -> Spray a
/^ Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
q) Spray a
forall a. C a => Spray a
unitSpray
  else Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
p Spray a
q

instance (AlgRing.C a, Eq a) => Eq (RatioOfSprays a) where
  (==) :: RatioOfSprays a -> RatioOfSprays a -> Bool
  == :: RatioOfSprays a -> RatioOfSprays a -> Bool
(==) (RatioOfSprays Spray a
p Spray a
q) (RatioOfSprays Spray a
p' Spray a
q') = 
    Spray a -> Bool
forall a. Spray a -> Bool
isZeroSpray (Spray a
p Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q'  Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^-^  Spray a
p' Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q)

instance (AlgField.C a, Eq a) => AlgAdd.C (RatioOfSprays a) where
  (+) :: RatioOfSprays a -> RatioOfSprays a -> RatioOfSprays a
  + :: RatioOfSprays a -> RatioOfSprays a -> RatioOfSprays a
(+) (RatioOfSprays Spray a
p Spray a
q) (RatioOfSprays Spray a
p' Spray a
q') = 
    Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
irreducibleFraction (Spray a
p Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q'  Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^+^  Spray a
p' Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q) (Spray a
q Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q')
  zero :: RatioOfSprays a
  zero :: RatioOfSprays a
zero = Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
forall a. (Eq a, C a) => Spray a
zeroSpray Spray a
forall a. C a => Spray a
unitSpray
  negate :: RatioOfSprays a -> RatioOfSprays a
  negate :: RatioOfSprays a -> RatioOfSprays a
negate (RatioOfSprays Spray a
p Spray a
q) = Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays (Spray a -> Spray a
forall a. C a => Spray a -> Spray a
negateSpray Spray a
p) Spray a
q

instance (AlgField.C a, Eq a) => AlgMod.C a (RatioOfSprays a) where
  (*>) :: a -> RatioOfSprays a -> RatioOfSprays a
  a
lambda *> :: a -> RatioOfSprays a -> RatioOfSprays a
*> (RatioOfSprays Spray a
p Spray a
q) = Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays (a
BaseRing (Spray a)
lambda BaseRing (Spray a) -> Spray a -> Spray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Spray a
p) Spray a
q

instance (AlgField.C a, Eq a) => AlgRightMod.C a (RatioOfSprays a) where
  (<*) :: RatioOfSprays a -> a -> RatioOfSprays a
  RatioOfSprays a
rOS <* :: RatioOfSprays a -> a -> RatioOfSprays a
<* a
lambda = a
lambda a -> RatioOfSprays a -> RatioOfSprays a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfSprays a
rOS

instance (AlgField.C a, Eq a) => AlgMod.C (Spray a) (RatioOfSprays a) where
  (*>) :: Spray a -> RatioOfSprays a -> RatioOfSprays a
  Spray a
spray *> :: Spray a -> RatioOfSprays a -> RatioOfSprays a
*> (RatioOfSprays Spray a
p Spray a
q) = Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
irreducibleFraction (Spray a
spray Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
p) Spray a
q

instance (AlgField.C a, Eq a) => AlgRightMod.C (Spray a) (RatioOfSprays a) where
  (<*) :: RatioOfSprays a -> Spray a -> RatioOfSprays a
  RatioOfSprays a
rOS <* :: RatioOfSprays a -> Spray a -> RatioOfSprays a
<* Spray a
spray = Spray a
spray Spray a -> RatioOfSprays a -> RatioOfSprays a
forall a v. C a v => a -> v -> v
AlgMod.*> RatioOfSprays a
rOS

instance (AlgField.C a, Eq a) => AlgRing.C (RatioOfSprays a) where
  (*) :: RatioOfSprays a -> RatioOfSprays a -> RatioOfSprays a
  * :: RatioOfSprays a -> RatioOfSprays a -> RatioOfSprays a
(*) (RatioOfSprays Spray a
p Spray a
q) (RatioOfSprays Spray a
p' Spray a
q') = 
    Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
irreducibleFraction (Spray a
p Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
p') (Spray a
q Spray a -> Spray a -> Spray a
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray a
q')
  (^) :: RatioOfSprays a -> Integer -> RatioOfSprays a
  ^ :: RatioOfSprays a -> Integer -> RatioOfSprays a
(^) (RatioOfSprays Spray a
p Spray a
q) Integer
n = if Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 
    then Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays (Spray a
p Spray a -> Integer -> Spray a
forall a. C a => a -> Integer -> a
AlgRing.^ Integer
n) (Spray a
q Spray a -> Integer -> Spray a
forall a. C a => a -> Integer -> a
AlgRing.^ Integer
n)
    else Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays (Spray a
q Spray a -> Integer -> Spray a
forall a. C a => a -> Integer -> a
AlgRing.^ (-Integer
n)) (Spray a
p Spray a -> Integer -> Spray a
forall a. C a => a -> Integer -> a
AlgRing.^ (-Integer
n))
  one :: RatioOfSprays a
  one :: RatioOfSprays a
one = Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
forall a. C a => Spray a
unitSpray Spray a
forall a. C a => Spray a
unitSpray

instance (AlgField.C a, Eq a) => AlgField.C (RatioOfSprays a) where
  recip :: RatioOfSprays a -> RatioOfSprays a
  recip :: RatioOfSprays a -> RatioOfSprays a
recip (RatioOfSprays Spray a
p Spray a
q) = Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
q Spray a
p

infixl 7 %:%
-- | Ratio of sprays from numerator and denominator, 

-- __without reducing the fraction__

(%:%) :: Spray a -> Spray a -> RatioOfSprays a 
%:% :: forall a. Spray a -> Spray a -> RatioOfSprays a
(%:%) = Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays

infixl 7 %//%
-- | Irreducible ratio of sprays from numerator and denominator; alias of @(^/^)@

(%//%) :: (Eq a, AlgField.C a) => Spray a -> Spray a -> RatioOfSprays a 
%//% :: forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
(%//%) = Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
irreducibleFraction 

infixl 7 ^/^
-- | Irreducible ratio of sprays from numerator and denominator; alias of @(%//%)@

(^/^) :: (Eq a, AlgField.C a) => Spray a -> Spray a -> RatioOfSprays a 
^/^ :: forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
(^/^) = Spray a -> Spray a -> RatioOfSprays a
forall a. (Eq a, C a) => Spray a -> Spray a -> RatioOfSprays a
irreducibleFraction 

infixl 7 %/%
-- | Division of a ratio of sprays by a spray; the result is an 

-- irreducible fraction

(%/%) :: (Eq a, AlgField.C a) => RatioOfSprays a -> Spray a -> RatioOfSprays a 
%/% :: forall a.
(Eq a, C a) =>
RatioOfSprays a -> Spray a -> RatioOfSprays a
(%/%) RatioOfSprays a
rOS Spray a
spray = RatioOfSprays a
rOS RatioOfSprays a -> RatioOfSprays a -> RatioOfSprays a
forall a. C a => a -> a -> a
AlgRing.* Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
forall a. C a => Spray a
unitSpray Spray a
spray 

-- | Whether a ratio of sprays is constant; same as `isConstant`

isConstantRatioOfSprays :: (Eq a, AlgField.C a) => RatioOfSprays a -> Bool
isConstantRatioOfSprays :: forall a. (Eq a, C a) => RatioOfSprays a -> Bool
isConstantRatioOfSprays = RatioOfSprays a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant

-- | Whether a ratio of sprays actually is polynomial, that is, whether its 

-- denominator is a constant spray (and then it should be the unit spray)

--

-- >>> x = qlone 1

-- >>> y = qlone 2

-- >>> p = x^**^4 ^-^ y^**^4

-- >>> q = x ^-^ y

-- >>> isPolynomialRatioOfSprays $ p %//% q

-- True

-- >>> isPolynomialRatioOfSprays $ p %:% q

-- False

isPolynomialRatioOfSprays :: (Eq a, AlgRing.C a) => RatioOfSprays a -> Bool
isPolynomialRatioOfSprays :: forall a. (Eq a, C a) => RatioOfSprays a -> Bool
isPolynomialRatioOfSprays = Spray a -> Bool
forall b. FunctionLike b => b -> Bool
isConstant (Spray a -> Bool)
-> (RatioOfSprays a -> Spray a) -> RatioOfSprays a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RatioOfSprays a -> Spray a
forall a. RatioOfSprays a -> Spray a
_denominator

-- | The null ratio of sprays

zeroRatioOfSprays, zeroROS :: (AlgField.C a, Eq a) => RatioOfSprays a
zeroRatioOfSprays :: forall a. (C a, Eq a) => RatioOfSprays a
zeroRatioOfSprays = RatioOfSprays a
forall a. C a => a
AlgAdd.zero
zeroROS :: forall a. (C a, Eq a) => RatioOfSprays a
zeroROS = RatioOfSprays a
forall a. C a => a
AlgAdd.zero

-- | The unit ratio of sprays

unitRatioOfSprays, unitROS :: (AlgField.C a, Eq a) => RatioOfSprays a
unitRatioOfSprays :: forall a. (C a, Eq a) => RatioOfSprays a
unitRatioOfSprays = RatioOfSprays a
forall a. C a => a
AlgRing.one
unitROS :: forall a. (C a, Eq a) => RatioOfSprays a
unitROS = RatioOfSprays a
forall a. C a => a
AlgRing.one

-- | Constant ratio of sprays

constantRatioOfSprays :: (Eq a, AlgRing.C a) => a -> RatioOfSprays a
constantRatioOfSprays :: forall a. (Eq a, C a) => a -> RatioOfSprays a
constantRatioOfSprays a
x = Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays (a -> Spray a
forall a. (Eq a, C a) => a -> Spray a
constantSpray a
x)

-- | Evaluates a ratio of sprays; same as `evaluate`

evalRatioOfSprays :: (Eq a, AlgField.C a) => RatioOfSprays a -> [a] -> a
evalRatioOfSprays :: forall a. (Eq a, C a) => RatioOfSprays a -> [a] -> a
evalRatioOfSprays = RatioOfSprays a -> [a] -> a
RatioOfSprays a
-> [BaseRing (RatioOfSprays a)] -> BaseRing (RatioOfSprays a)
forall b. FunctionLike b => b -> [BaseRing b] -> BaseRing b
evaluate

-- | Substitutes some values to some variables of a ratio of sprays; same as `substitute`

substituteRatioOfSprays :: 
  (Eq a, AlgField.C a) => [Maybe a] -> RatioOfSprays a -> RatioOfSprays a
substituteRatioOfSprays :: forall a.
(Eq a, C a) =>
[Maybe a] -> RatioOfSprays a -> RatioOfSprays a
substituteRatioOfSprays = [Maybe a] -> RatioOfSprays a -> RatioOfSprays a
[Maybe (BaseRing (RatioOfSprays a))]
-> RatioOfSprays a -> RatioOfSprays a
forall b. FunctionLike b => [Maybe (BaseRing b)] -> b -> b
substitute

-- | Coerces a spray to a ratio of sprays

asRatioOfSprays :: AlgRing.C a => Spray a -> RatioOfSprays a
asRatioOfSprays :: forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays Spray a
spray = Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays Spray a
spray Spray a
forall a. C a => Spray a
unitSpray

-- | Converts a ratio of polynomials to a ratio of sprays

fromRatioOfPolynomials :: 
  (Eq a, AlgRing.C a) => RatioOfPolynomials a -> RatioOfSprays a
fromRatioOfPolynomials :: forall a. (Eq a, C a) => RatioOfPolynomials a -> RatioOfSprays a
fromRatioOfPolynomials RatioOfPolynomials a
rop = 
  Spray a -> Spray a -> RatioOfSprays a
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays 
    (Polynomial a -> Spray a
forall a. (Eq a, C a) => Polynomial a -> Spray a
polynomialToSpray (Polynomial a -> Spray a) -> Polynomial a -> Spray a
forall a b. (a -> b) -> a -> b
$ RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.numerator RatioOfPolynomials a
rop) 
    (Polynomial a -> Spray a
forall a. (Eq a, C a) => Polynomial a -> Spray a
polynomialToSpray (Polynomial a -> Spray a) -> Polynomial a -> Spray a
forall a b. (a -> b) -> a -> b
$ RatioOfPolynomials a -> Polynomial a
forall a. T a -> a
NumberRatio.denominator RatioOfPolynomials a
rop)  

-- | Converts a ratio of rational polynomials to a ratio of rational sprays; 

-- this is not a specialization of `fromRatioOfPolynomials` because 

-- @RatioOfQPolynomials@ is @RatioOfPolynomials a@ with 

-- @a = Rational'@, not with @a = Rational@

fromRatioOfQPolynomials :: RatioOfQPolynomials -> RatioOfQSprays
fromRatioOfQPolynomials :: RatioOfQPolynomials -> RatioOfSprays Rational
fromRatioOfQPolynomials RatioOfQPolynomials
rop = 
  Spray Rational -> Spray Rational -> RatioOfSprays Rational
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays 
    (Polynomial Rational' -> Spray Rational
qPolynomialToQSpray (Polynomial Rational' -> Spray Rational)
-> Polynomial Rational' -> Spray Rational
forall a b. (a -> b) -> a -> b
$ RatioOfQPolynomials -> Polynomial Rational'
forall a. T a -> a
NumberRatio.numerator RatioOfQPolynomials
rop) 
    (Polynomial Rational' -> Spray Rational
qPolynomialToQSpray (Polynomial Rational' -> Spray Rational)
-> Polynomial Rational' -> Spray Rational
forall a b. (a -> b) -> a -> b
$ RatioOfQPolynomials -> Polynomial Rational'
forall a. T a -> a
NumberRatio.denominator RatioOfQPolynomials
rop)  

-- | General function to print a `RatioOfSprays` object

showRatioOfSprays :: (Eq a, AlgRing.C a) 
  => ((Spray a, Spray a) -> (String, String)) -- ^ function which prints a pair of sprays that will be applied to the numerator and the denominator

  -> (String, String)                         -- ^ pair of braces to enclose the numerator and the denominator

  -> String                                   -- ^ represents the quotient bar

  -> RatioOfSprays a 
  -> String
showRatioOfSprays :: forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays (Spray a, Spray a) -> (String, String)
spraysShower (String, String)
braces String
quotientBar (RatioOfSprays Spray a
p Spray a
q) = 
  String
numeratorString String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
denominatorString
  where
    enclose :: ShowS
enclose = (String, String) -> ShowS
bracify (String, String)
braces
    (String
pString, String
qString) = (Spray a, Spray a) -> (String, String)
spraysShower (Spray a
p, Spray a
q)
    numeratorString :: String
numeratorString   = ShowS
enclose String
pString
    denominatorString :: String
denominatorString = if Spray a
q Spray a -> Spray a -> Bool
forall a. Eq a => a -> a -> Bool
== Spray a
forall a. C a => Spray a
unitSpray
      then String
""
      else String
quotientBar String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
enclose String
qString

showTwoSpraysXYZ :: (Eq a, AlgRing.C a)
  => (a -> String)           -- ^ function mapping a coefficient to a string, typically 'show'

  -> (String, String)        -- ^ used to enclose the coefficients, usually a pair of braces

  -> [String]                -- ^ typically some letters, to print the variables

  -> (Spray a, Spray a)      -- ^ the two sprays to be printed

  -> (String, String)
showTwoSpraysXYZ :: forall a.
(Eq a, C a) =>
(a -> String)
-> (String, String)
-> [String]
-> (Spray a, Spray a)
-> (String, String)
showTwoSpraysXYZ a -> String
showCoef (String, String)
braces [String]
letters (Spray a
spray1, Spray a
spray2) =
  (Spray a -> String) -> (Spray a, Spray a) -> (String, String)
forall a b. (a -> b) -> (a, a) -> (b, b)
both ((a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray a -> String
showCoef (String, String)
braces [Exponents] -> [String]
showMonomials) (Spray a
spray1, Spray a
spray2)
  where
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray1) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray2)
    showMonomials :: [Exponents] -> [String]
showMonomials = (Exponents -> String) -> [Exponents] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> String
unpack (Text -> String) -> (Exponents -> Text) -> Exponents -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Int -> Exponents -> Text
showMonomialXYZ [String]
letters Int
n)

showTwoSpraysX1X2X3 ::
     (a -> String)           -- ^ function mapping a coefficient to a string, typically 'show'

  -> (String, String)        -- ^ used to enclose the coefficients, usually a pair of braces

  -> String                  -- ^ typically a letter, to print the non-indexed variables

  -> (Spray a, Spray a)      -- ^ the two sprays to be printed

  -> (String, String)
showTwoSpraysX1X2X3 :: forall a.
(a -> String)
-> (String, String)
-> String
-> (Spray a, Spray a)
-> (String, String)
showTwoSpraysX1X2X3 a -> String
showCoef (String, String)
braces String
letter (Spray a
spray1, Spray a
spray2) =
  (Spray a -> String) -> (Spray a, Spray a) -> (String, String)
forall a b. (a -> b) -> (a, a) -> (b, b)
both ((a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray a -> String
showCoef (String, String)
braces [Exponents] -> [String]
showMonomials) (Spray a
spray1, Spray a
spray2)
  where
    showMonomials :: [Exponents] -> [String]
showMonomials = String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
letter

showTwoNumSprays :: (Num a, Ord a)
  => (a -> String)           -- ^ function mapping a positive coefficient to a string

  -> ([Exponents] -> [String]) -- ^ prints the monomials

  -> (Spray a, Spray a)      -- ^ the two sprays to be printed

  -> (String, String)
showTwoNumSprays :: forall a.
(Num a, Ord a) =>
(a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
showTwoNumSprays a -> String
showPositiveCoef [Exponents] -> [String]
showMonomials =
  (Spray a -> String) -> (Spray a, Spray a) -> (String, String)
forall a b. (a -> b) -> (a, a) -> (b, b)
both (([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
forall a.
(Num a, Ord a) =>
([Exponents] -> [String]) -> (a -> String) -> Spray a -> String
showNumSpray [Exponents] -> [String]
showMonomials a -> String
showPositiveCoef)

showTwoQSprays :: 
     ([Exponents] -> [String]) -- ^ prints the monomials

  -> (QSpray, QSpray)        -- ^ the two sprays to be printed

  -> (String, String)
showTwoQSprays :: ([Exponents] -> [String])
-> (Spray Rational, Spray Rational) -> (String, String)
showTwoQSprays = (Rational -> String)
-> ([Exponents] -> [String])
-> (Spray Rational, Spray Rational)
-> (String, String)
forall a.
(Num a, Ord a) =>
(a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
showTwoNumSprays Rational -> String
showRatio

showTwoNumSpraysXYZ :: (AlgRing.C a, Num a, Ord a)
  => (a -> String)           -- ^ function mapping a positive coefficient to a string

  -> [String]                -- ^ typically some letters, to print the variables

  -> (Spray a, Spray a)      -- ^ the two sprays to be printed

  -> (String, String)
showTwoNumSpraysXYZ :: forall a.
(C a, Num a, Ord a) =>
(a -> String) -> [String] -> (Spray a, Spray a) -> (String, String)
showTwoNumSpraysXYZ a -> String
showPositiveCoef [String]
letters (Spray a
spray1, Spray a
spray2) =
  (a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
forall a.
(Num a, Ord a) =>
(a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
showTwoNumSprays a -> String
showPositiveCoef [Exponents] -> [String]
showMonomials (Spray a
spray1, Spray a
spray2)
  where
    n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray1) (Spray a -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray a
spray2)
    showMonomials :: [Exponents] -> [String]
showMonomials = (Exponents -> String) -> [Exponents] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> String
unpack (Text -> String) -> (Exponents -> Text) -> Exponents -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Int -> Exponents -> Text
showMonomialXYZ [String]
letters Int
n)

showTwoQSpraysXYZ ::
     [String]              -- ^ typically some letters, to print the variables

  -> (QSpray, QSpray)      -- ^ the two sprays to be printed

  -> (String, String)
showTwoQSpraysXYZ :: [String] -> (Spray Rational, Spray Rational) -> (String, String)
showTwoQSpraysXYZ = (Rational -> String)
-> [String] -> (Spray Rational, Spray Rational) -> (String, String)
forall a.
(C a, Num a, Ord a) =>
(a -> String) -> [String] -> (Spray a, Spray a) -> (String, String)
showTwoNumSpraysXYZ Rational -> String
showRatio

showTwoNumSpraysX1X2X3 :: (Num a, Ord a)
  => (a -> String)           -- ^ function mapping a positive coefficient to a string

  -> String                  -- ^ typically a letter, to print the non-indexed variable

  -> (Spray a, Spray a)      -- ^ the two sprays to be printed

  -> (String, String)
showTwoNumSpraysX1X2X3 :: forall a.
(Num a, Ord a) =>
(a -> String) -> String -> (Spray a, Spray a) -> (String, String)
showTwoNumSpraysX1X2X3 a -> String
showPositiveCoef String
letter (Spray a
spray1, Spray a
spray2) =
  (a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
forall a.
(Num a, Ord a) =>
(a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
showTwoNumSprays a -> String
showPositiveCoef [Exponents] -> [String]
showMonomials (Spray a
spray1, Spray a
spray2)
  where
    showMonomials :: [Exponents] -> [String]
showMonomials = String -> [Exponents] -> [String]
showMonomialsX1X2X3 String
letter

showTwoQSpraysX1X2X3 ::
      String               -- ^ typically a letter, to print the non-indexed variables

  -> (QSpray, QSpray)      -- ^ the two sprays to be printed

  -> (String, String)
showTwoQSpraysX1X2X3 :: String -> (Spray Rational, Spray Rational) -> (String, String)
showTwoQSpraysX1X2X3 = (Rational -> String)
-> String -> (Spray Rational, Spray Rational) -> (String, String)
forall a.
(Num a, Ord a) =>
(a -> String) -> String -> (Spray a, Spray a) -> (String, String)
showTwoNumSpraysX1X2X3 Rational -> String
showRatio

-- | Prints a ratio of sprays with numeric coefficients

showRatioOfNumSprays :: (Num a, Ord a, AlgRing.C a) 
  => (a -> String)           -- ^ function mapping a positive coefficient to a string

  -> ([Exponents] -> [String]) -- ^ prints the monomials

  -> (String, String)        -- ^ pair of braces to enclose the numerator and the denominator

  -> String                  -- ^ represents the quotient bar

  -> RatioOfSprays a 
  -> String
showRatioOfNumSprays :: forall a.
(Num a, Ord a, C a) =>
(a -> String)
-> ([Exponents] -> [String])
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfNumSprays a -> String
showPositiveCoef [Exponents] -> [String]
showMonomials = 
  ((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays ((a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
forall a.
(Num a, Ord a) =>
(a -> String)
-> ([Exponents] -> [String])
-> (Spray a, Spray a)
-> (String, String)
showTwoNumSprays a -> String
showPositiveCoef [Exponents] -> [String]
showMonomials)

-- | Prints a ratio of sprays with rational coefficients

showRatioOfQSprays ::  
     ([Exponents] -> [String]) -- ^ prints the monomials

  -> (String, String)        -- ^ pair of braces to enclose the numerator and the denominator

  -> String                  -- ^ represents the quotient bar

  -> RatioOfQSprays 
  -> String
showRatioOfQSprays :: ([Exponents] -> [String])
-> (String, String) -> String -> RatioOfSprays Rational -> String
showRatioOfQSprays [Exponents] -> [String]
showMonomials = 
  ((Spray Rational, Spray Rational) -> (String, String))
-> (String, String) -> String -> RatioOfSprays Rational -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays (([Exponents] -> [String])
-> (Spray Rational, Spray Rational) -> (String, String)
showTwoQSprays [Exponents] -> [String]
showMonomials)

-- | Prints a ratio of sprays with numeric coefficients

showRatioOfNumSpraysXYZ :: (Num a, Ord a, AlgRing.C a) 
  => (a -> String)           -- ^ function mapping a positive coefficient to a string

  -> [String]                -- ^ typically some letters, to print the variables

  -> (String, String)        -- ^ pair of braces to enclose the numerator and the denominator

  -> String                  -- ^ represents the quotient bar

  -> RatioOfSprays a 
  -> String
showRatioOfNumSpraysXYZ :: forall a.
(Num a, Ord a, C a) =>
(a -> String)
-> [String]
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfNumSpraysXYZ a -> String
showPositiveCoef [String]
letters = 
  ((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays ((a -> String) -> [String] -> (Spray a, Spray a) -> (String, String)
forall a.
(C a, Num a, Ord a) =>
(a -> String) -> [String] -> (Spray a, Spray a) -> (String, String)
showTwoNumSpraysXYZ a -> String
showPositiveCoef [String]
letters)

-- | Prints a ratio of sprays with numeric coefficients

showRatioOfNumSpraysX1X2X3 :: (Num a, Ord a, AlgRing.C a) 
  => (a -> String)          -- ^ function mapping a positive coefficient to a string

  -> String                 -- ^ typically a letter, to print the variables

  -> (String, String)       -- ^ pair of braces to enclose the numerator and the denominator

  -> String                 -- ^ represents the quotient bar

  -> RatioOfSprays a 
  -> String
showRatioOfNumSpraysX1X2X3 :: forall a.
(Num a, Ord a, C a) =>
(a -> String)
-> String
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfNumSpraysX1X2X3 a -> String
showPositiveCoef String
letter = 
  ((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays ((a -> String) -> String -> (Spray a, Spray a) -> (String, String)
forall a.
(Num a, Ord a) =>
(a -> String) -> String -> (Spray a, Spray a) -> (String, String)
showTwoNumSpraysX1X2X3 a -> String
showPositiveCoef String
letter)

-- | Prints a ratio of sprays with rational coefficients

showRatioOfQSpraysXYZ ::  
     [String]                -- ^ typically some letters, to print the variables

  -> (String, String)        -- ^ pair of braces to enclose the numerator and the denominator

  -> String                  -- ^ represents the quotient bar

  -> RatioOfQSprays
  -> String
showRatioOfQSpraysXYZ :: [String]
-> (String, String) -> String -> RatioOfSprays Rational -> String
showRatioOfQSpraysXYZ [String]
letters = ((Spray Rational, Spray Rational) -> (String, String))
-> (String, String) -> String -> RatioOfSprays Rational -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays ([String] -> (Spray Rational, Spray Rational) -> (String, String)
showTwoQSpraysXYZ [String]
letters)

-- | Prints a ratio of sprays with rational coefficients

showRatioOfQSpraysX1X2X3 ::  
     String                -- ^ typically a letter, to print the variables

  -> (String, String)      -- ^ pair of braces to enclose the numerator and the denominator

  -> String                -- ^ represents the quotient bar

  -> RatioOfQSprays
  -> String
showRatioOfQSpraysX1X2X3 :: String
-> (String, String) -> String -> RatioOfSprays Rational -> String
showRatioOfQSpraysX1X2X3 String
letter = ((Spray Rational, Spray Rational) -> (String, String))
-> (String, String) -> String -> RatioOfSprays Rational -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays (String -> (Spray Rational, Spray Rational) -> (String, String)
showTwoQSpraysX1X2X3 String
letter)

-- | Prints a ratio of sprays 

showRatioOfSpraysXYZ :: forall a. (Eq a, AlgField.C a) 
  => [String]         -- ^ typically some letters, to represent the variables

  -> (a -> String)    -- ^ function mapping a coefficient to a string, typically 'show'

  -> (String, String) -- ^ used to enclose the coefficients, usually a pair of braces

  -> (String, String) -- ^ pair of braces to enclose the numerator and the denominator

  -> String           -- ^ represents the quotient bar

  -> RatioOfSprays a 
  -> String
showRatioOfSpraysXYZ :: forall a.
(Eq a, C a) =>
[String]
-> (a -> String)
-> (String, String)
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfSpraysXYZ [String]
letters a -> String
showCoef (String, String)
coeffBraces = 
  ((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays ((a -> String)
-> (String, String)
-> [String]
-> (Spray a, Spray a)
-> (String, String)
forall a.
(Eq a, C a) =>
(a -> String)
-> (String, String)
-> [String]
-> (Spray a, Spray a)
-> (String, String)
showTwoSpraysXYZ a -> String
showCoef (String, String)
coeffBraces [String]
letters)

-- | Prints a ratio of sprays 

showRatioOfSpraysXYZ' :: (Eq a, AlgField.C a)
  => [String]         -- ^ typically some letters, to represent the variables

  -> (a -> String)    -- ^ function mapping a coefficient to a string, typically 'show'

  -> RatioOfSprays a
  -> String
showRatioOfSpraysXYZ' :: forall a.
(Eq a, C a) =>
[String] -> (a -> String) -> RatioOfSprays a -> String
showRatioOfSpraysXYZ' [String]
letters a -> String
showCoef = 
  [String]
-> (a -> String)
-> (String, String)
-> (String, String)
-> String
-> RatioOfSprays a
-> String
forall a.
(Eq a, C a) =>
[String]
-> (a -> String)
-> (String, String)
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfSpraysXYZ [String]
letters a -> String
showCoef (String
"(", String
")") (String
"[ ", String
" ]") String
" %//% "

-- | Prints a ratio of sprays 

showRatioOfSpraysX1X2X3 :: forall a. (Eq a, AlgField.C a) 
  => String           -- ^ typically a letter, to represent the variables

  -> (a -> String)    -- ^ function mapping a coefficient to a string, typically 'show'

  -> (String, String) -- ^ used to enclose the coefficients, usually a pair of braces

  -> (String, String) -- ^ pair of braces to enclose the numerator and the denominator

  -> String           -- ^ represents the quotient bar

  -> RatioOfSprays a 
  -> String
showRatioOfSpraysX1X2X3 :: forall a.
(Eq a, C a) =>
String
-> (a -> String)
-> (String, String)
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfSpraysX1X2X3 String
letter a -> String
showCoef (String, String)
coeffBraces = 
  ((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
forall a.
(Eq a, C a) =>
((Spray a, Spray a) -> (String, String))
-> (String, String) -> String -> RatioOfSprays a -> String
showRatioOfSprays ((a -> String)
-> (String, String)
-> String
-> (Spray a, Spray a)
-> (String, String)
forall a.
(a -> String)
-> (String, String)
-> String
-> (Spray a, Spray a)
-> (String, String)
showTwoSpraysX1X2X3 a -> String
showCoef (String, String)
coeffBraces String
letter)

-- | Prints a ratio of sprays 

showRatioOfSpraysX1X2X3' :: (Eq a, AlgField.C a)
  => String          -- ^ typically a letter, to represent the variables

  -> (a -> String)   -- ^ function mapping a coefficient to a string, typically 'show'

  -> RatioOfSprays a
  -> String
showRatioOfSpraysX1X2X3' :: forall a.
(Eq a, C a) =>
String -> (a -> String) -> RatioOfSprays a -> String
showRatioOfSpraysX1X2X3' String
letter a -> String
showCoef = 
  String
-> (a -> String)
-> (String, String)
-> (String, String)
-> String
-> RatioOfSprays a
-> String
forall a.
(Eq a, C a) =>
String
-> (a -> String)
-> (String, String)
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfSpraysX1X2X3 String
letter a -> String
showCoef (String
"(", String
")") (String
"[ ", String
" ]") String
" %//% "

-- | Prints a ratio of sprays with rational coefficients

prettyRatioOfQSpraysXYZ :: 
     [String]         -- ^ typically some letters, to represent the variables

  -> RatioOfQSprays
  -> String
prettyRatioOfQSpraysXYZ :: [String] -> RatioOfSprays Rational -> String
prettyRatioOfQSpraysXYZ [String]
letters = 
  [String]
-> (String, String) -> String -> RatioOfSprays Rational -> String
showRatioOfQSpraysXYZ [String]
letters (String
"[ ", String
" ]") String
" %//% "

-- | Prints a ratio of sprays with rational coefficients

--

-- prop> prettyRatioOfQSprays rOS == prettyRatioOfQSpraysXYZ ["x","y","z"] rOS

prettyRatioOfQSprays :: RatioOfQSprays -> String
prettyRatioOfQSprays :: RatioOfSprays Rational -> String
prettyRatioOfQSprays = [String] -> RatioOfSprays Rational -> String
prettyRatioOfQSpraysXYZ [String
"x", String
"y", String
"z"]

-- | Prints a ratio of sprays with rational coefficients

--

-- prop> prettyRatioOfQSprays' rOS == prettyRatioOfQSpraysXYZ ["X","Y","Z"] rOS

prettyRatioOfQSprays' :: RatioOfQSprays -> String
prettyRatioOfQSprays' :: RatioOfSprays Rational -> String
prettyRatioOfQSprays' = [String] -> RatioOfSprays Rational -> String
prettyRatioOfQSpraysXYZ [String
"X", String
"Y", String
"Z"]

-- | Prints a ratio of sprays with rational coefficients, printing the monomials 

-- in the style of @\"x1^2.x2.x3^3\"@

prettyRatioOfQSpraysX1X2X3 :: 
     String         -- ^ typically a letter, to represent the non-indexed variables

  -> RatioOfQSprays
  -> String
prettyRatioOfQSpraysX1X2X3 :: String -> RatioOfSprays Rational -> String
prettyRatioOfQSpraysX1X2X3 String
letter = 
  String
-> (String, String) -> String -> RatioOfSprays Rational -> String
showRatioOfQSpraysX1X2X3 String
letter (String
"[ ", String
" ]") String
" %//% "

-- | Prints a ratio of sprays with numeric coefficients

prettyRatioOfNumSpraysXYZ :: (Num a, Ord a, AlgRing.C a, Show a)
  => [String]         -- ^ typically some letters, to represent the variables

  -> RatioOfSprays a
  -> String
prettyRatioOfNumSpraysXYZ :: forall a.
(Num a, Ord a, C a, Show a) =>
[String] -> RatioOfSprays a -> String
prettyRatioOfNumSpraysXYZ [String]
letters = 
  (a -> String)
-> [String]
-> (String, String)
-> String
-> RatioOfSprays a
-> String
forall a.
(Num a, Ord a, C a) =>
(a -> String)
-> [String]
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfNumSpraysXYZ a -> String
forall a. Show a => a -> String
show [String]
letters (String
"[ ", String
" ]") String
" %//% "

-- | Prints a ratio of sprays with numeric coefficients

--

-- prop> prettyRatioOfNumSprays rOS == prettyRatioOfNumSpraysXYZ ["x","y","z"] rOS

prettyRatioOfNumSprays :: 
  (Num a, Ord a, AlgRing.C a, Show a) => RatioOfSprays a -> String
prettyRatioOfNumSprays :: forall a. (Num a, Ord a, C a, Show a) => RatioOfSprays a -> String
prettyRatioOfNumSprays = [String] -> RatioOfSprays a -> String
forall a.
(Num a, Ord a, C a, Show a) =>
[String] -> RatioOfSprays a -> String
prettyRatioOfNumSpraysXYZ [String
"x", String
"y", String
"z"]

-- | Prints a ratio of sprays with numeric coefficients

--

-- prop> prettyRatioOfNumSprays' rOS == prettyRatioOfNumSpraysXYZ ["X","Y","Z"] rOS

prettyRatioOfNumSprays' :: 
  (Num a, Ord a, AlgRing.C a, Show a) => RatioOfSprays a -> String
prettyRatioOfNumSprays' :: forall a. (Num a, Ord a, C a, Show a) => RatioOfSprays a -> String
prettyRatioOfNumSprays' = [String] -> RatioOfSprays a -> String
forall a.
(Num a, Ord a, C a, Show a) =>
[String] -> RatioOfSprays a -> String
prettyRatioOfNumSpraysXYZ [String
"X", String
"Y", String
"Z"]

-- | Prints a ratio of sprays with numeric coefficients, printing the monomials 

-- in the style of @\"x1^2.x2.x3^3\"@

prettyRatioOfNumSpraysX1X2X3 :: (Num a, Ord a, AlgRing.C a, Show a)
  => String          -- ^ typically a letter, to represent the variables

  -> RatioOfSprays a
  -> String
prettyRatioOfNumSpraysX1X2X3 :: forall a.
(Num a, Ord a, C a, Show a) =>
String -> RatioOfSprays a -> String
prettyRatioOfNumSpraysX1X2X3 String
letter = 
  (a -> String)
-> String
-> (String, String)
-> String
-> RatioOfSprays a
-> String
forall a.
(Num a, Ord a, C a) =>
(a -> String)
-> String
-> (String, String)
-> String
-> RatioOfSprays a
-> String
showRatioOfNumSpraysX1X2X3 a -> String
forall a. Show a => a -> String
show String
letter (String
"[ ", String
" ]") String
" %//% "


-- Parametric sprays ----------------------------------------------------------


type SimpleParametricSpray a = Spray (Spray a)
type SimpleParametricQSpray  = SimpleParametricSpray Rational
type ParametricSpray a = Spray (RatioOfSprays a)
type ParametricQSpray  = ParametricSpray Rational

instance (Eq a, AlgRing.C a) => AlgMod.C a (SimpleParametricSpray a) where
  (*>) :: a -> SimpleParametricSpray a -> SimpleParametricSpray a
  a
lambda *> :: a -> SimpleParametricSpray a -> SimpleParametricSpray a
*> SimpleParametricSpray a
pspray = (HashMap Powers a -> HashMap Powers a)
-> SimpleParametricSpray a -> SimpleParametricSpray a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map (a
lambda a -> HashMap Powers a -> HashMap Powers a
forall a v. C a v => a -> v -> v
AlgMod.*>) SimpleParametricSpray a
pspray

instance (Eq a, AlgRing.C a) => AlgRightMod.C a (SimpleParametricSpray a) where
  (<*) :: SimpleParametricSpray a -> a -> SimpleParametricSpray a
  SimpleParametricSpray a
pspray <* :: SimpleParametricSpray a -> a -> SimpleParametricSpray a
<* a
lambda = (HashMap Powers a -> HashMap Powers a)
-> SimpleParametricSpray a -> SimpleParametricSpray a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map (HashMap Powers a -> a -> HashMap Powers a
forall a b. C a b => b -> a -> b
AlgRightMod.<* a
lambda) SimpleParametricSpray a
pspray

instance (Eq a, AlgField.C a) => AlgMod.C a (ParametricSpray a) where
  (*>) :: a -> ParametricSpray a -> ParametricSpray a
  a
lambda *> :: a -> ParametricSpray a -> ParametricSpray a
*> ParametricSpray a
pspray = (RatioOfSprays a -> RatioOfSprays a)
-> ParametricSpray a -> ParametricSpray a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map (a
lambda a -> RatioOfSprays a -> RatioOfSprays a
forall a v. C a v => a -> v -> v
AlgMod.*>) ParametricSpray a
pspray

instance (Eq a, AlgField.C a) => AlgRightMod.C a (ParametricSpray a) where
  (<*) :: ParametricSpray a -> a -> ParametricSpray a
  ParametricSpray a
pspray <* :: ParametricSpray a -> a -> ParametricSpray a
<* a
lambda = (RatioOfSprays a -> RatioOfSprays a)
-> ParametricSpray a -> ParametricSpray a
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map (RatioOfSprays a -> a -> RatioOfSprays a
forall a b. C a b => b -> a -> b
AlgRightMod.<* a
lambda) ParametricSpray a
pspray

instance (Eq a, AlgField.C a) => AlgMod.C (Spray a) (ParametricSpray a) where
  (*>) :: Spray a -> ParametricSpray a -> ParametricSpray a
  Spray a
spray *> :: Spray a -> ParametricSpray a -> ParametricSpray a
*> ParametricSpray a
pspray = Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays Spray a
spray BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ ParametricSpray a
pspray

instance (Eq a, AlgField.C a) => AlgRightMod.C (Spray a) (ParametricSpray a) where
  (<*) :: ParametricSpray a -> Spray a -> ParametricSpray a
  ParametricSpray a
pspray <* :: ParametricSpray a -> Spray a -> ParametricSpray a
<* Spray a
spray = Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays Spray a
spray BaseRing (ParametricSpray a)
-> ParametricSpray a -> ParametricSpray a
forall b. FunctionLike b => BaseRing b -> b -> b
*^ ParametricSpray a
pspray

-- | Number of parameters in a parametric spray

--

-- >>> numberOfParameters (jacobiPolynomial 4)

-- 2

numberOfParameters :: FunctionLike b => Spray b -> Int
numberOfParameters :: forall b. FunctionLike b => Spray b -> Int
numberOfParameters Spray b
pspray = 
  if Spray b -> Bool
forall a. Spray a -> Bool
isZeroSpray Spray b
pspray
    then Int
0
    else 
      [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ((b -> Int) -> [b] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map b -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables (Spray b -> [b]
forall a. Spray a -> [a]
allCoefficients Spray b
pspray))

-- | Apply polynomial transformations to the parameters of a parametric spray; 

-- e.g. you have a two-parameters polynomial \(P_{a, b}(X, Y, Z)\) and you want

-- to get \(P_{a^2, b^2}(X, Y, Z)\), or the one-parameter polynomial 

-- \(P_{a, a}(X, Y, Z)\)

-- 

-- >>> jp = jacobiPolynomial 4

-- >>> a = qlone 1

-- >>> b = qlone 2

-- >>> changeParameters jp [a^**^2, b^**^2]

changeParameters :: 
  (FunctionLike b, Eq b, AlgAdd.C b) 
  => Spray b           -- ^ @OneParameterSpray a@, @SimpleParametricSpray a@, or @ParametricSpray a@

  -> [VariablesType b] -- ^ @[Polynomial a]@ or @[Spray a]@, the new variables 

  -> Spray b
changeParameters :: forall b.
(FunctionLike b, Eq b, C b) =>
Spray b -> [VariablesType b] -> Spray b
changeParameters Spray b
pspray [VariablesType b]
newParameters = 
  if [VariablesType b] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [VariablesType b]
newParameters Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Spray b -> Int
forall b. FunctionLike b => Spray b -> Int
numberOfParameters Spray b
pspray
    then 
      String -> Spray b
forall a. HasCallStack => String -> a
error String
"changeParameters: not enough new parameters provided."
    else 
      Spray b -> Spray b
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (Spray b -> Spray b) -> Spray b -> Spray b
forall a b. (a -> b) -> a -> b
$ (b -> b) -> Spray b -> Spray b
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map (b -> [VariablesType b] -> b
forall b. FunctionLike b => b -> [VariablesType b] -> b
`changeVariables` [VariablesType b]
newParameters) Spray b
pspray

-- | Substitutes some values to the parameters of a parametric spray

--

-- >>> jacobi3 = jacobiPolynomial 3

-- >>> legendre3 = substituteParameters jp [0, 0]

substituteParameters :: 
    (FunctionLike b, Eq (BaseRing b), AlgAdd.C (BaseRing b)) 
  => Spray b            -- ^ @OneParameterSpray a@, @SimpleParametricSpray a@, or @ParametricSpray a@ 

  -> [BaseRing b]       -- ^ values of type @a@ to be substituted to the parameters

  -> Spray (BaseRing b) -- ^ output: a @Spray a@ spray

substituteParameters :: forall b.
(FunctionLike b, Eq (BaseRing b), C (BaseRing b)) =>
Spray b -> [BaseRing b] -> Spray (BaseRing b)
substituteParameters Spray b
pspray [BaseRing b]
values = 
  if [BaseRing b] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BaseRing b]
values Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Spray b -> Int
forall b. FunctionLike b => Spray b -> Int
numberOfParameters Spray b
pspray
    then 
      String -> HashMap Powers (BaseRing b)
forall a. HasCallStack => String -> a
error String
"substituteParameters: not enough values provided."
    else 
      HashMap Powers (BaseRing b) -> HashMap Powers (BaseRing b)
forall a. (C a, Eq a) => Spray a -> Spray a
removeZeroTerms (HashMap Powers (BaseRing b) -> HashMap Powers (BaseRing b))
-> HashMap Powers (BaseRing b) -> HashMap Powers (BaseRing b)
forall a b. (a -> b) -> a -> b
$ (b -> BaseRing b) -> Spray b -> HashMap Powers (BaseRing b)
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map ([BaseRing b] -> b -> BaseRing b
forall b. FunctionLike b => [BaseRing b] -> b -> BaseRing b
evaluateAt [BaseRing b]
values) Spray b
pspray 

-- | helper function for evalParametricSpray

evalTerm' :: 
  (AlgMod.C (BaseRing b) b) => [BaseRing b] -> Term b -> b
evalTerm' :: forall b. C (BaseRing b) b => [BaseRing b] -> Term b -> b
evalTerm' [BaseRing b]
xs (Powers
powers, b
coeff) = 
  [BaseRing b] -> BaseRing b
forall a. C a => [a] -> a
AlgRing.product ((BaseRing b -> Integer -> BaseRing b)
-> [BaseRing b] -> [Integer] -> [BaseRing b]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith BaseRing b -> Integer -> BaseRing b
forall a. C a => a -> Integer -> a
(AlgRing.^) [BaseRing b]
xs [Integer]
pows) BaseRing b -> b -> b
forall a v. C a v => a -> v -> v
AlgMod.*> b
coeff
  where 
    pows :: [Integer]
pows = Seq Integer -> [Integer]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> Exponents -> Seq Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Powers -> Exponents
exponents Powers
powers)

-- | Substitutes some values to the variables of a parametric spray

evalParametricSpray ::
  (Eq b, AlgMod.C (BaseRing b) b, AlgRing.C b) 
  => Spray b            -- ^ @OneParameterSpray a@, @SimpleParametricSpray a@, or @ParametricSpray a@ 

  -> [BaseRing b]       -- ^ values of type @a@ to be substituted to the variables

  -> b
evalParametricSpray :: forall b.
(Eq b, C (BaseRing b) b, C b) =>
Spray b -> [BaseRing b] -> b
evalParametricSpray Spray b
spray [BaseRing b]
xs = if [BaseRing b] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BaseRing b]
xs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Spray b -> Int
forall b. FunctionLike b => b -> Int
numberOfVariables Spray b
spray
  then [b] -> b
forall a. C a => [a] -> a
AlgAdd.sum ([b] -> b) -> [b] -> b
forall a b. (a -> b) -> a -> b
$ (Term b -> b) -> [Term b] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map ([BaseRing b] -> Term b -> b
forall b. C (BaseRing b) b => [BaseRing b] -> Term b -> b
evalTerm' [BaseRing b]
xs) (Spray b -> [Term b]
forall k v. HashMap k v -> [(k, v)]
HM.toList Spray b
spray)
  else String -> b
forall a. HasCallStack => String -> a
error String
"evalParametricSpray: not enough values provided."

-- | Substitutes some values to the parameters of a parametric spray as well as 

-- some values to its variables

evalParametricSpray' ::
  (FunctionLike b, Eq (BaseRing b), AlgMod.C (BaseRing b) b) 
  => Spray b      -- ^ @OneParameterSpray a@, @SimpleParametricSpray a@, or @ParametricSpray a@ 

  -> [BaseRing b] -- ^ values of type @a@ to be substituted to the parameters

  -> [BaseRing b] -- ^ values of type @a@ to be substituted to the variables

  -> BaseRing b   -- ^ result: a value of type @a@

evalParametricSpray' :: forall b.
(FunctionLike b, Eq (BaseRing b), C (BaseRing b) b) =>
Spray b -> [BaseRing b] -> [BaseRing b] -> BaseRing b
evalParametricSpray' Spray b
spray [BaseRing b]
as [BaseRing b]
xs = 
  [BaseRing (Spray (BaseRing b))]
-> Spray (BaseRing b) -> BaseRing (Spray (BaseRing b))
forall b. FunctionLike b => [BaseRing b] -> b -> BaseRing b
evaluateAt [BaseRing b]
[BaseRing (Spray (BaseRing b))]
xs (Spray b -> [BaseRing b] -> Spray (BaseRing b)
forall b.
(FunctionLike b, Eq (BaseRing b), C (BaseRing b)) =>
Spray b -> [BaseRing b] -> Spray (BaseRing b)
substituteParameters Spray b
spray [BaseRing b]
as)

-- | Whether the coefficients of a parametric spray polynomially 

-- depend on their parameters; I do not know why, but it seems to be the case 

-- for the Jacobi polynomials 

--

-- >>> canCoerceToSimpleParametricSpray (jacobiPolynomial 8)

-- True

canCoerceToSimpleParametricSpray :: 
  (Eq a, AlgRing.C a) => ParametricSpray a -> Bool
canCoerceToSimpleParametricSpray :: forall a. (Eq a, C a) => ParametricSpray a -> Bool
canCoerceToSimpleParametricSpray ParametricSpray a
spray = 
  (RatioOfSprays a -> Bool) -> [RatioOfSprays a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all RatioOfSprays a -> Bool
forall a. (Eq a, C a) => RatioOfSprays a -> Bool
isPolynomialRatioOfSprays (ParametricSpray a -> [RatioOfSprays a]
forall a. Spray a -> [a]
allCoefficients ParametricSpray a
spray)

-- | Coerces a parametric spray to a simple parametric spray, without 

-- checking this makes sense with `canCoerceToSimpleParametricSpray`

asSimpleParametricSprayUnsafe :: ParametricSpray a -> SimpleParametricSpray a
asSimpleParametricSprayUnsafe :: forall a. ParametricSpray a -> SimpleParametricSpray a
asSimpleParametricSprayUnsafe = (RatioOfSprays a -> Spray a)
-> HashMap Powers (RatioOfSprays a) -> HashMap Powers (Spray a)
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map RatioOfSprays a -> Spray a
forall a. RatioOfSprays a -> Spray a
_numerator

-- | Coerces a parametric spray to a simple parametric spray, after

-- checking this makes sense with `canCoerceToSimpleParametricSpray`

asSimpleParametricSpray :: 
  (Eq a, AlgRing.C a) => ParametricSpray a -> SimpleParametricSpray a
asSimpleParametricSpray :: forall a.
(Eq a, C a) =>
ParametricSpray a -> SimpleParametricSpray a
asSimpleParametricSpray ParametricSpray a
spray = 
  if ParametricSpray a -> Bool
forall a. (Eq a, C a) => ParametricSpray a -> Bool
canCoerceToSimpleParametricSpray ParametricSpray a
spray 
    then ParametricSpray a -> SimpleParametricSpray a
forall a. ParametricSpray a -> SimpleParametricSpray a
asSimpleParametricSprayUnsafe ParametricSpray a
spray
    else String -> SimpleParametricSpray a
forall a. HasCallStack => String -> a
error (String -> SimpleParametricSpray a)
-> String -> SimpleParametricSpray a
forall a b. (a -> b) -> a -> b
$
      String
"asSimpleParametricSpray: this parametric spray is not coercible" String -> ShowS
forall a. [a] -> [a] -> [a]
++ 
      String
" to a simple parametric spray."

-- | Converts a `OneParameterSpray a` spray to a `ParametricSpray a`

fromOneParameterSpray :: 
  (Eq a, AlgRing.C a) => OneParameterSpray a -> ParametricSpray a
fromOneParameterSpray :: forall a. (Eq a, C a) => OneParameterSpray a -> ParametricSpray a
fromOneParameterSpray = (RatioOfPolynomials a -> RatioOfSprays a)
-> HashMap Powers (RatioOfPolynomials a)
-> HashMap Powers (RatioOfSprays a)
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map RatioOfPolynomials a -> RatioOfSprays a
forall a. (Eq a, C a) => RatioOfPolynomials a -> RatioOfSprays a
fromRatioOfPolynomials

-- | Converts a `OneParameterQSpray` spray to a `ParametricQSpray`

fromOneParameterQSpray :: OneParameterQSpray -> ParametricQSpray
fromOneParameterQSpray :: OneParameterQSpray -> ParametricQSpray
fromOneParameterQSpray = (RatioOfQPolynomials -> RatioOfSprays Rational)
-> OneParameterQSpray -> ParametricQSpray
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map RatioOfQPolynomials -> RatioOfSprays Rational
fromRatioOfQPolynomials

-- | Converts a `SimpleParametricSpray a` spray to a `ParametricSpray a`

fromSimpleParametricSpray :: 
  AlgRing.C a => SimpleParametricSpray a -> ParametricSpray a
fromSimpleParametricSpray :: forall a. C a => SimpleParametricSpray a -> ParametricSpray a
fromSimpleParametricSpray = (Spray a -> RatioOfSprays a)
-> HashMap Powers (Spray a) -> HashMap Powers (RatioOfSprays a)
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map Spray a -> RatioOfSprays a
forall a. C a => Spray a -> RatioOfSprays a
asRatioOfSprays

-- | Converts a parametric spray to a one-parameter spray, without checking

-- the conversion makes sense

parametricSprayToOneParameterSpray :: 
  forall a. (Eq a, AlgField.C a) => ParametricSpray a -> OneParameterSpray a
parametricSprayToOneParameterSpray :: forall a. (Eq a, C a) => ParametricSpray a -> OneParameterSpray a
parametricSprayToOneParameterSpray = (RatioOfSprays a -> RatioOfPolynomials a)
-> HashMap Powers (RatioOfSprays a)
-> HashMap Powers (RatioOfPolynomials a)
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map RatioOfSprays a -> RatioOfPolynomials a
toRatioOfPolynomials
  where
    toRatioOfPolynomials :: RatioOfSprays a -> RatioOfPolynomials a
    toRatioOfPolynomials :: RatioOfSprays a -> RatioOfPolynomials a
toRatioOfPolynomials (RatioOfSprays Spray a
p Spray a
q) = 
      Spray a -> Polynomial a
toPolynomial Spray a
p Polynomial a -> Polynomial a -> RatioOfPolynomials a
forall a. C a => a -> a -> T a
% Spray a -> Polynomial a
toPolynomial Spray a
q
      where
        toPolynomial :: Spray a -> Polynomial a
        toPolynomial :: Spray a -> Polynomial a
toPolynomial Spray a
spray = [a] -> Polynomial a
forall a. [a] -> Polynomial a
polyFromCoeffs [a]
coeffs
          where
            spray'' :: SafeSpray a
spray'' = SafeSpray a -> SafeSpray a
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' (Spray a -> SafeSpray a
forall a. Spray a -> SafeSpray a
safeSpray Spray a
spray)
            coeffs :: [a]
coeffs = Spray a -> a
forall a. C a => Spray a -> a
getConstantTerm Spray a
spray a -> [a] -> [a]
forall a. a -> [a] -> [a]
: 
              [Exponents -> SafeSpray a -> a
forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' (Int -> Exponents
forall a. a -> Seq a
S.singleton Int
i) SafeSpray a
spray'' | Int
i <- [Int
1 .. Int
deg]]
            deg :: Int
deg = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (Int
0 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
expnts)
            expnts :: [Int]
expnts = (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) (SafeSpray a -> [Exponents]
forall k v. HashMap k v -> [k]
HM.keys SafeSpray a
spray'')

{- -- | division of two univariate sprays
longDivision :: (Eq a, AlgField.C a) => Spray a -> Spray a -> (Spray a, Spray a)
longDivision sprayA sprayB = both fromCoeffs (polydiv coeffsA coeffsB)
  where
    fromCoeffs as = if S.null as
      then zeroSpray 
      else sumTerms terms
      where
        l = S.length as
        terms = (Powers S.empty 0, as `index` (l-1)) :
          map (\i -> (Powers (S.singleton i) 1, as `index` (l-1-i))) [1 .. l-1]
    shift n l = l >< S.replicate n AlgAdd.zero
    pad n l = if n > 0 then S.replicate n AlgAdd.zero >< l else l
    zipWith' op xs ys = S.zipWith op (pad (-d) xs) (pad d ys)
      where d = S.length xs - S.length ys
    coeffsA = coefficientsUnivariateSpray sprayA
    coeffsB = coefficientsUnivariateSpray sprayB
    coefficientsUnivariateSpray spray = coeffs
      where
        coeffs = S.fromList [getCoefficient' (Powers (S.singleton i) 1) spray' | 
                  i <- [deg, deg-1 .. 1]] |> getConstantTerm spray
        deg = maximum (0 : expnts)
        spray' = removeConstantTerm spray
        expnts = map ((`index` 0) . exponents) (HM.keys spray')
    polydiv as bs = aux as bs S.empty
      where aux f s q | ddif < 0 = (q, f)
                      | otherwise = aux f' s q'
              where ddif = S.length (norm f) - S.length (norm s)
                    k = f `index` 0 AlgField./ s `index` 0
                    ks = (AlgRing.* k) <$> shift ddif s
                    q' = zipWith' (AlgAdd.+) q $ shift ddif (S.singleton k)
                    f' = norm $ S.drop 1 $ zipWith' (AlgAdd.-) f ks
                    norm = S.dropWhileL (== AlgAdd.zero)  
 -}

-- | Converts a rational parametric spray to a rational one-parameter spray, 

-- without checking the conversion makes sense

parametricQSprayToOneParameterQSpray :: ParametricQSpray -> OneParameterQSpray
parametricQSprayToOneParameterQSpray :: ParametricQSpray -> OneParameterQSpray
parametricQSprayToOneParameterQSpray = (RatioOfSprays Rational -> RatioOfQPolynomials)
-> ParametricQSpray -> OneParameterQSpray
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HM.map RatioOfSprays Rational -> RatioOfQPolynomials
toRatioOfQPolynomials
  where
    toRatioOfQPolynomials :: RatioOfQSprays -> RatioOfQPolynomials
    toRatioOfQPolynomials :: RatioOfSprays Rational -> RatioOfQPolynomials
toRatioOfQPolynomials (RatioOfSprays Spray Rational
p Spray Rational
q) = 
      Spray Rational -> Polynomial Rational'
toQPolynomial Spray Rational
p Polynomial Rational' -> Polynomial Rational' -> RatioOfQPolynomials
forall a. C a => a -> a -> T a
% Spray Rational -> Polynomial Rational'
toQPolynomial Spray Rational
q
      where
        toQPolynomial :: QSpray -> QPolynomial
        toQPolynomial :: Spray Rational -> Polynomial Rational'
toQPolynomial Spray Rational
spray = [Rational'] -> Polynomial Rational'
forall a. [a] -> Polynomial a
polyFromCoeffs [Rational']
coeffs'
          where
            spray'' :: SafeSpray Rational
spray'' = SafeSpray Rational -> SafeSpray Rational
forall a. SafeSpray a -> SafeSpray a
removeConstantTerm'' (Spray Rational -> SafeSpray Rational
forall a. Spray a -> SafeSpray a
safeSpray Spray Rational
spray)
            coeffs' :: [Rational']
coeffs' = Rational -> Rational'
f (Spray Rational -> Rational
forall a. C a => Spray a -> a
getConstantTerm Spray Rational
spray) Rational' -> [Rational'] -> [Rational']
forall a. a -> [a] -> [a]
: 
              [Rational -> Rational'
f (Rational -> Rational') -> Rational -> Rational'
forall a b. (a -> b) -> a -> b
$ Exponents -> SafeSpray Rational -> Rational
forall a. C a => Exponents -> SafeSpray a -> a
getCoefficient'' (Int -> Exponents
forall a. a -> Seq a
S.singleton Int
i) SafeSpray Rational
spray'' | Int
i <- [Int
1 .. Int
deg]]
            f :: Rational -> Rational'
            f :: Rational -> Rational'
f Rational
r = Rational -> Integer
forall a. Ratio a -> a
DR.numerator Rational
r Integer -> Integer -> Rational'
forall a. a -> a -> T a
:% Rational -> Integer
forall a. Ratio a -> a
DR.denominator Rational
r
            deg :: Int
deg = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (Int
0 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: (Exponents -> Int) -> [Exponents] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Exponents -> Int -> Int
forall a. Seq a -> Int -> a
`index` Int
0) [Exponents]
expnts)
            expnts :: [Exponents]
expnts = SafeSpray Rational -> [Exponents]
forall k v. HashMap k v -> [k]
HM.keys SafeSpray Rational
spray''

-- | [Gegenbauer polynomials](https://en.wikipedia.org/wiki/Gegenbauer_polynomials); 

-- we mainly provide them to give an example of the @SimpleParametricSpray@ type

--

-- >>> gp = gegenbauerPolynomial 3

-- >>> putStrLn $ prettySimpleParametricQSpray gp

-- { (4/3)*a^3 + 4*a^2 + (8/3)*a }*X^3 + { -2*a^2 - 2*a }*X

-- >>> putStrLn $ prettyQSpray'' $ substituteParameters gp [1]

-- 8*X^3 - 4*X

gegenbauerPolynomial :: Int -> SimpleParametricQSpray 
gegenbauerPolynomial :: Int -> SimpleParametricQSpray
gegenbauerPolynomial Int
n 
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = SimpleParametricQSpray
forall a. C a => Spray a
unitSpray
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = (Int
2Int -> Spray Rational -> Spray Rational
forall a. (C a, Eq a) => Int -> a -> a
.^Spray Rational
a) BaseRing SimpleParametricQSpray
-> SimpleParametricQSpray -> SimpleParametricQSpray
forall b. FunctionLike b => BaseRing b -> b -> b
*^ SimpleParametricQSpray
x
  | Bool
otherwise = 
    (Int
2Int -> Spray Rational -> Spray Rational
forall a. (C a, Eq a) => Int -> a -> a
.^((Rational
n'Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
-Rational
1) BaseRing (Spray Rational) -> Spray Rational -> Spray Rational
forall b. FunctionLike b => BaseRing b -> b -> b
+> Spray Rational
a) Spray Rational -> Rational -> Spray Rational
forall a. (C a, Eq a) => Spray a -> a -> Spray a
/^ Rational
n') BaseRing SimpleParametricQSpray
-> SimpleParametricQSpray -> SimpleParametricQSpray
forall b. FunctionLike b => BaseRing b -> b -> b
*^ (SimpleParametricQSpray
x SimpleParametricQSpray
-> SimpleParametricQSpray -> SimpleParametricQSpray
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Int -> SimpleParametricQSpray
gegenbauerPolynomial (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) SimpleParametricQSpray
-> SimpleParametricQSpray -> SimpleParametricQSpray
forall b. (FunctionLike b, C b) => b -> b -> b
^-^
      (((Rational
n'Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
-Rational
1) BaseRing (Spray Rational) -> Spray Rational -> Spray Rational
forall b. FunctionLike b => BaseRing b -> b -> b
+> Int
2Int -> Spray Rational -> Spray Rational
forall a. (C a, Eq a) => Int -> a -> a
.^Spray Rational
a Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray Rational
forall a. C a => Spray a
unitSpray) Spray Rational -> Rational -> Spray Rational
forall a. (C a, Eq a) => Spray a -> a -> Spray a
/^ Rational
n') BaseRing SimpleParametricQSpray
-> SimpleParametricQSpray -> SimpleParametricQSpray
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Int -> SimpleParametricQSpray
gegenbauerPolynomial (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2)
  where 
    x :: SimpleParametricQSpray
x = Int -> SimpleParametricQSpray
forall a. C a => Int -> Spray a
lone Int
1 :: SimpleParametricQSpray
    a :: Spray Rational
a = Int -> Spray Rational
forall a. C a => Int -> Spray a
lone Int
1 :: QSpray
    n' :: Rational
n'  = Int -> Rational
forall a. Real a => a -> Rational
toRational Int
n

-- | [Jacobi polynomial](https://en.wikipedia.org/wiki/Jacobi_polynomials); 

-- the @n@-th Jacobi polynomial is a univariate polynomial of degree @n@ with 

-- two parameters, except for the case @n=0@ where it has no parameter

--

-- >>> jP = jacobiPolynomial 1

-- >>> putStrLn $ prettyParametricQSprayABCXYZ ["alpha", "beta"] ["X"] jP

-- { [ (1/2)*alpha + (1/2)*beta + 1 ] }*X + { [ (1/2)*alpha - (1/2)*beta ] }

jacobiPolynomial :: Int -> ParametricQSpray
jacobiPolynomial :: Int -> ParametricQSpray
jacobiPolynomial Int
n 
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0  = String -> ParametricQSpray
forall a. HasCallStack => String -> a
error String
"jacobiPolynomial: `n` must be positive." 
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = ParametricQSpray
forall a. C a => Spray a
unitSpray
  | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = 
      SimpleParametricQSpray -> ParametricQSpray
forall a. C a => SimpleParametricSpray a -> ParametricSpray a
fromSimpleParametricSpray (SimpleParametricQSpray -> ParametricQSpray)
-> SimpleParametricQSpray -> ParametricQSpray
forall a b. (a -> b) -> a -> b
$   
        (((Spray Rational
gamma0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ Rational
BaseRing (Spray Rational)
2) Spray Rational -> Rational -> Spray Rational
forall a. (C a, Eq a) => Spray a -> a -> Spray a
/^ Rational
2) BaseRing SimpleParametricQSpray
-> SimpleParametricQSpray -> SimpleParametricQSpray
forall b. FunctionLike b => BaseRing b -> b -> b
*^ 
          (SimpleParametricQSpray
x SimpleParametricQSpray
-> BaseRing SimpleParametricQSpray -> SimpleParametricQSpray
forall b. FunctionLike b => b -> BaseRing b -> b
<+ Spray Rational -> Spray Rational
forall a. C a => a -> a
AlgAdd.negate Spray Rational
forall a. C a => a
AlgRing.one)) SimpleParametricQSpray
-> BaseRing SimpleParametricQSpray -> SimpleParametricQSpray
forall b. FunctionLike b => b -> BaseRing b -> b
<+ (Spray Rational
alpha0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ Rational
BaseRing (Spray Rational)
1)
  | Bool
otherwise = 
      ParametricQSpray
spray ParametricQSpray -> ParametricQSpray -> ParametricQSpray
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Int -> ParametricQSpray
jacobiPolynomial (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) ParametricQSpray -> ParametricQSpray -> ParametricQSpray
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ RatioOfSprays Rational
BaseRing ParametricQSpray
rOS BaseRing ParametricQSpray -> ParametricQSpray -> ParametricQSpray
forall b. FunctionLike b => BaseRing b -> b -> b
*^ Int -> ParametricQSpray
jacobiPolynomial (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2)
  where
    alpha0 :: Spray Rational
alpha0 = Int -> Spray Rational
qlone Int
1
    beta0 :: Spray Rational
beta0  = Int -> Spray Rational
qlone Int
2
    gamma0 :: Spray Rational
gamma0 = Spray Rational
alpha0 Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^+^ Spray Rational
beta0
    x :: SimpleParametricQSpray
x = Int -> SimpleParametricQSpray
forall a. C a => Int -> Spray a
lone Int
1 :: SimpleParametricQSpray
    n' :: Rational
n' = Int -> Rational
forall a. Real a => a -> Rational
toRational Int
n
    a0 :: Spray Rational
a0 = Spray Rational
alpha0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ (Rational
n' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
1)
    b0 :: Spray Rational
b0 = Spray Rational
beta0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ (Rational
n' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
1)
    c0 :: Spray Rational
c0 = Spray Rational
gamma0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ (Rational
2 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
n')
    c0' :: Spray Rational
c0' = Spray Rational
c0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ (-Rational
1)
    c0'' :: Spray Rational
c0'' = Spray Rational
c0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ (-Rational
2)
    divisor :: Spray Rational
divisor = (Rational
BaseRing (Spray Rational)
n' BaseRing (Spray Rational) -> Spray Rational -> Spray Rational
forall b. FunctionLike b => BaseRing b -> b -> b
*^ (Spray Rational
c0 Spray Rational -> BaseRing (Spray Rational) -> Spray Rational
forall b. FunctionLike b => b -> BaseRing b -> b
<+ (-Rational
n'))) Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray Rational
c0''
    divisor' :: Spray Rational
divisor' = Int
2 Int -> Spray Rational -> Spray Rational
forall a. (C a, Eq a) => Int -> a -> a
.^ Spray Rational
divisor
    divide :: Spray Rational -> RatioOfSprays Rational
divide = (Spray Rational -> Spray Rational -> RatioOfSprays Rational
forall a. Spray a -> Spray a -> RatioOfSprays a
`RatioOfSprays` Spray Rational
divisor')
    spray :: ParametricQSpray
spray = [(Powers, RatioOfSprays Rational)] -> ParametricQSpray
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList [
        (
          Powers
nullPowers
        , Spray Rational -> RatioOfSprays Rational
divide (Spray Rational -> RatioOfSprays Rational)
-> Spray Rational -> RatioOfSprays Rational
forall a b. (a -> b) -> a -> b
$ Spray Rational
c0' Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ (Spray Rational
alpha0 Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^-^ Spray Rational
beta0) Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray Rational
gamma0
        ),
        (
          Exponents -> Int -> Powers
Powers (Int -> Exponents
forall a. a -> Seq a
S.singleton Int
1) Int
1
        , Spray Rational -> RatioOfSprays Rational
divide (Spray Rational -> RatioOfSprays Rational)
-> Spray Rational -> RatioOfSprays Rational
forall a b. (a -> b) -> a -> b
$ Spray Rational
c0' Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray Rational
c0 Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray Rational
c0''
        )
      ]
    rOS :: RatioOfSprays Rational
rOS = Spray Rational -> Spray Rational -> RatioOfSprays Rational
forall a. Spray a -> Spray a -> RatioOfSprays a
RatioOfSprays (Spray Rational
a0 Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray Rational
b0 Spray Rational -> Spray Rational -> Spray Rational
forall b. (FunctionLike b, C b) => b -> b -> b
^*^ Spray Rational
c0) Spray Rational
divisor

-- | Pretty form of a numeric parametric spray, using some given strings (typically some 

-- letters) to denote the parameters and some given strings (typically some letters) to 

-- denote the variables; rather use `prettyParametricQSprayABCXYZ` for a rational 

-- parametric spray

prettyParametricNumSprayABCXYZ ::
  (Num a, Ord a, Show a, AlgField.C a)
  => [String]           -- ^ usually some letters, to denote the parameters of the spray

  -> [String]           -- ^ usually some letters, to denote the variables of the spray

  -> ParametricSpray a  -- ^ a parametric numeric spray

  -> String 
prettyParametricNumSprayABCXYZ :: forall a.
(Num a, Ord a, Show a, C a) =>
[String] -> [String] -> ParametricSpray a -> String
prettyParametricNumSprayABCXYZ [String]
abc [String]
xyz ParametricSpray a
spray = 
  (RatioOfSprays a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> ParametricSpray a
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray RatioOfSprays a -> String
rOSShower (String
"{ ", String
" }") ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
xyz) ParametricSpray a
spray
  where
    rOSShower :: RatioOfSprays a -> String
rOSShower = if ParametricSpray a -> Int
forall b. FunctionLike b => Spray b -> Int
numberOfParameters ParametricSpray a
spray Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
abc
      then [String] -> RatioOfSprays a -> String
forall a.
(Num a, Ord a, C a, Show a) =>
[String] -> RatioOfSprays a -> String
prettyRatioOfNumSpraysXYZ [String]
abc
      else String -> RatioOfSprays a -> String
forall a.
(Num a, Ord a, C a, Show a) =>
String -> RatioOfSprays a -> String
prettyRatioOfNumSpraysX1X2X3 ([String]
abc [String] -> Int -> String
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)

-- | Pretty form of a numeric parametric spray; rather use `prettyParametricQSpray` for 

-- a rational parametric spray

--

-- prop> prettyParametricNumSpray == prettyParametricNumSprayABCXYZ ["a"] ["X","Y","Z"]

prettyParametricNumSpray ::
  (Num a, Ord a, Show a, AlgField.C a)
  => ParametricSpray a  -- ^ a parametric numeric spray

  -> String 
prettyParametricNumSpray :: forall a.
(Num a, Ord a, Show a, C a) =>
ParametricSpray a -> String
prettyParametricNumSpray = [String] -> [String] -> ParametricSpray a -> String
forall a.
(Num a, Ord a, Show a, C a) =>
[String] -> [String] -> ParametricSpray a -> String
prettyParametricNumSprayABCXYZ [String
"a"] [String
"X", String
"Y", String
"Z"]

-- | Pretty form of a parametric rational spray, using some given strings (typically some 

-- letters) to denote the parameters and some given strings (typically some letters) to 

-- denote the variables

--

-- >>> type PQS = ParametricQSpray

-- >>> :{

-- >>> f :: (QSpray, QSpray) -> (PQS, PQS, PQS) -> PQS

-- >>> f (a, b) (x, y, z) = 

-- >>>   (a %:% (a ^+^ b)) *^ x^**^2  ^+^  (b %:% (a ^+^ b)) *^ (y ^*^ z)

-- >>> :}

-- >>> a = qlone 1

-- >>> b = qlone 2

-- >>> x = lone 1 :: PQS

-- >>> y = lone 2 :: PQS

-- >>> z = lone 3 :: PQS

-- >>> pqs = f (a, b) (x, y, z)

-- >>> putStrLn $ prettyParametricQSprayABCXYZ ["a","b"] ["X","Y","Z"] pqs

-- { [ a ] %//% [ a + b ] }*X^2 + { [ b ] %//% [ a + b ] }*Y.Z

prettyParametricQSprayABCXYZ ::
     [String]           -- ^ usually some letters, to denote the parameters of the spray

  -> [String]           -- ^ usually some letters, to denote the variables of the spray

  -> ParametricQSpray   -- ^ a parametric rational spray

  -> String 
prettyParametricQSprayABCXYZ :: [String] -> [String] -> ParametricQSpray -> String
prettyParametricQSprayABCXYZ [String]
abc [String]
xyz ParametricQSpray
spray = 
  (RatioOfSprays Rational -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> ParametricQSpray
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray RatioOfSprays Rational -> String
rOSShower (String
"{ ", String
" }") ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
xyz) ParametricQSpray
spray
  where
    rOSShower :: RatioOfSprays Rational -> String
rOSShower = if ParametricQSpray -> Int
forall b. FunctionLike b => Spray b -> Int
numberOfParameters ParametricQSpray
spray Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
abc
      then [String] -> RatioOfSprays Rational -> String
prettyRatioOfQSpraysXYZ [String]
abc
      else String -> RatioOfSprays Rational -> String
prettyRatioOfQSpraysX1X2X3 ([String]
abc [String] -> Int -> String
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)

-- | Pretty form of a parametric rational spray

--

-- prop> prettyParametricQSpray == prettyParametricQSprayABCXYZ ["a"] ["X","Y","Z"]

prettyParametricQSpray :: ParametricQSpray -> String 
prettyParametricQSpray :: ParametricQSpray -> String
prettyParametricQSpray = [String] -> [String] -> ParametricQSpray -> String
prettyParametricQSprayABCXYZ [String
"a"] [String
"X", String
"Y", String
"Z"]

-- | Pretty form of a numeric simple parametric spray, using some given strings (typically some 

-- letters) to denote the parameters and some given strings (typically some letters) to 

-- denote the variables; rather use `prettySimpleParametricQSprayABCXYZ` for a rational 

-- simple parametric spray

prettySimpleParametricNumSprayABCXYZ ::
  (Num a, Ord a, Show a, AlgRing.C a)
  => [String]                 -- ^ usually some letters, to denote the parameters of the spray

  -> [String]                 -- ^ usually some letters, to denote the variables of the spray

  -> SimpleParametricSpray a  -- ^ a numeric simple parametric spray

  -> String 
prettySimpleParametricNumSprayABCXYZ :: forall a.
(Num a, Ord a, Show a, C a) =>
[String] -> [String] -> SimpleParametricSpray a -> String
prettySimpleParametricNumSprayABCXYZ [String]
abc [String]
xyz SimpleParametricSpray a
spray = 
  (Spray a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> SimpleParametricSpray a
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray Spray a -> String
rOSShower (String
"{ ", String
" }") ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
xyz) SimpleParametricSpray a
spray
  where
    rOSShower :: Spray a -> String
rOSShower = if SimpleParametricSpray a -> Int
forall b. FunctionLike b => Spray b -> Int
numberOfParameters SimpleParametricSpray a
spray Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
abc
      then [String] -> Spray a -> String
forall a. (Num a, Ord a, Show a) => [String] -> Spray a -> String
prettyNumSprayXYZ [String]
abc
      else String -> Spray a -> String
forall a. (Num a, Ord a, Show a) => String -> Spray a -> String
prettyNumSprayX1X2X3 ([String]
abc [String] -> Int -> String
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)

-- | Pretty form of a numeric simple parametric spray; rather use 

-- `prettySimpleParametricQSpray` for a numeric simple parametric spray

--

-- prop> prettySimpleParametricNumSpray == prettySimpleParametricNumSprayABCXYZ ["a"] ["X","Y","Z"]

prettySimpleParametricNumSpray ::
  (Num a, Ord a, Show a, AlgRing.C a)
  => SimpleParametricSpray a  -- ^ a numeric simple parametric spray

  -> String 
prettySimpleParametricNumSpray :: forall a.
(Num a, Ord a, Show a, C a) =>
SimpleParametricSpray a -> String
prettySimpleParametricNumSpray = 
  [String] -> [String] -> SimpleParametricSpray a -> String
forall a.
(Num a, Ord a, Show a, C a) =>
[String] -> [String] -> SimpleParametricSpray a -> String
prettySimpleParametricNumSprayABCXYZ [String
"a"] [String
"X", String
"Y", String
"Z"]

-- | Pretty form of a simple parametric rational spray, using some given strings (typically some 

-- letters) to denote the parameters and some given strings (typically some letters) to 

-- denote the variables

--

-- >>> type SPQS = SimpleParametricQSpray

-- >>> :{

-- >>> f :: (QSpray, QSpray) -> (SPQS, SPQS, SPQS) -> SPQS

-- >>> f (a, b) (x, y, z) = 

-- >>>   (a ^+^ b) *^ x^**^2  ^+^  (a^**^2 ^+^ b^**^2) *^ (y ^*^ z)

-- >>> :}

-- >>> a = qlone 1

-- >>> b = qlone 2

-- >>> x = lone 1 :: SPQS

-- >>> y = lone 2 :: SPQS

-- >>> z = lone 3 :: SPQS

-- >>> spqs = f (a, b) (x, y, z)

-- >>> putStrLn $ prettySimpleParametricQSprayABCXYZ ["a","b"] ["X","Y","Z"] spqs

-- { a + b }*X^2 + { a^2 + b^2 }*Y.Z

prettySimpleParametricQSprayABCXYZ ::
     [String]               -- ^ usually some letters, to denote the parameters of the spray

  -> [String]               -- ^ usually some letters, to denote the variables of the spray

  -> SimpleParametricQSpray -- ^ a parametric rational spray

  -> String 
prettySimpleParametricQSprayABCXYZ :: [String] -> [String] -> SimpleParametricQSpray -> String
prettySimpleParametricQSprayABCXYZ [String]
abc [String]
xyz SimpleParametricQSpray
spray = 
  (Spray Rational -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> SimpleParametricQSpray
-> String
forall a.
(a -> String)
-> (String, String)
-> ([Exponents] -> [String])
-> Spray a
-> String
showSpray Spray Rational -> String
sprayShower (String
"{ ", String
" }") ([String] -> [Exponents] -> [String]
showMonomialsXYZ [String]
xyz) SimpleParametricQSpray
spray
  where
    sprayShower :: Spray Rational -> String
sprayShower = if SimpleParametricQSpray -> Int
forall b. FunctionLike b => Spray b -> Int
numberOfParameters SimpleParametricQSpray
spray Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
abc
      then [String] -> Spray Rational -> String
prettyQSprayXYZ [String]
abc
      else String -> Spray Rational -> String
prettyQSprayX1X2X3 ([String]
abc [String] -> Int -> String
forall a. HasCallStack => [a] -> Int -> a
!! Int
0)

-- | Pretty form of a simple parametric rational spray

--

-- prop> prettySimpleParametricQSpray == prettySimpleParametricQSprayABCXYZ ["a"] ["X","Y","Z"]

prettySimpleParametricQSpray :: SimpleParametricQSpray -> String 
prettySimpleParametricQSpray :: SimpleParametricQSpray -> String
prettySimpleParametricQSpray = 
  [String] -> [String] -> SimpleParametricQSpray -> String
prettySimpleParametricQSprayABCXYZ [String
"a"] [String
"X", String
"Y", String
"Z"]