From 265b40e456d313e4f07b7ba262d5c989947636ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 29 Aug 2017 17:49:16 +0200 Subject: [PATCH] Fix #51 --- README.md | 1 + docs/make.jl | 5 ++- docs/src/differentiation.md | 8 ++++ docs/src/division.md | 15 ++++++++ docs/src/index.md | 26 +++++++++---- docs/src/substitution.md | 15 ++++++++ docs/src/{apireference.md => types.md} | 15 +++++++- src/MultivariatePolynomials.jl | 51 +++++++++++++++++++++++--- src/{comparision.jl => comparison.jl} | 0 src/differentiation.jl | 23 ++++++++++++ src/division.jl | 7 ++-- src/monomial.jl | 16 +------- src/polynomial.jl | 23 +++++++++++- src/rational.jl | 3 ++ src/substitution.jl | 27 ++++++++++++-- src/term.jl | 7 +++- test/monomial.jl | 6 +++ test/polynomial.jl | 9 +++++ test/rational.jl | 2 + test/term.jl | 6 +++ test/utils.jl | 10 ++--- test/variable.jl | 13 +------ 22 files changed, 230 insertions(+), 58 deletions(-) create mode 100644 docs/src/differentiation.md create mode 100644 docs/src/division.md create mode 100644 docs/src/substitution.md rename docs/src/{apireference.md => types.md} (59%) rename src/{comparision.jl => comparison.jl} (100%) diff --git a/README.md b/README.md index 286b6975..b9e6daa5 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ The following packages provides multivariate polynomials that implement the inte The following packages extend/use the interface: * [SemialgebraicSets](https://github.com/blegat/SemialgebraicSets.jl) : Sets defined by inequalities and equalities between polynomials and algorithms for solving polynomial systems of equations. +* [HomotopyContinuation](https://github.com/saschatimme/HomotopyContinuation.jl) : Solving systems of polynomials via homotopy continuation. * [MultivariateMoments](https://github.com/blegat/MultivariateMoments.jl) : Moments of multivariate measures and their scalar product with polynomials. * [PolyJuMP](https://github.com/JuliaOpt/PolyJuMP.jl) : A [JuMP](https://github.com/JuliaOpt/JuMP.jl) extension for Polynomial Optimization. * [SumOfSquares](https://github.com/JuliaOpt/SumOfSquares.jl) : Certifying the nonnegativity of polynomials, minimizing/maximizing polynomials and optimization over sum of squares polynomials using Sum of Squares Programming. diff --git a/docs/make.jl b/docs/make.jl index 7efa6349..a03d9842 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,7 +5,10 @@ makedocs( sitename = "MultivariatePolynomials", pages = [ "Introduction" => "index.md", - "Reference" => "apireference.md", + "Types" => "types.md", + "Substitution" => "substitution.md", + "Differentiation" => "differentiation.md", + "Division" => "division.md", ] ) diff --git a/docs/src/differentiation.md b/docs/src/differentiation.md new file mode 100644 index 00000000..e868a41b --- /dev/null +++ b/docs/src/differentiation.md @@ -0,0 +1,8 @@ +# Differentiation + +Given a polynomial, say ``p(x, y) = 3x^2y + x + 2y + 1``, we can differentiate it by a variable, say ``x`` and get ``\partial p(x, y) / \partial x = 6xy + 1``. +We can also differentiate it by both of its variable and get the vector ``[6xy+1, 3x^2+1]``. + +```@docs +differentiate +``` diff --git a/docs/src/division.md b/docs/src/division.md new file mode 100644 index 00000000..a77e7e8a --- /dev/null +++ b/docs/src/division.md @@ -0,0 +1,15 @@ +# Division + +The `gcd` and `lcm` functions of `Base` have been implemented for monomials, you have for example `gcd(x^2*y^7*z^3, x^4*y^5*z^2)` returning `x^2*y^5*z^2` and `lcm(x^2*y^7*z^3, x^4*y^5*z^2)` returning `x^4*y^7*z^3`. + +Given two polynomials, ``p`` and ``d``, there are unique ``r`` and ``q`` such that ``p = q d + r`` and the leading term of ``d`` does not divide the leading term of ``r``. +You can obtain ``q`` using the `div` function and ``r`` using the `rem` function. +The `divrem` function returns ``(q, r)``. + +Given a polynomial ``p`` and divisors ``d_1, \ldots, d_n``, one can find ``r`` and ``q_1, \ldots, q_n`` such that ``p = q_1 d_1 + \cdots + q_n d_n + r`` and none of the leading terms of ``q_1, \ldots, q_n`` divide the leading term of ``r``. +You can obtain the vector ``[q_1, \ldots, q_n]`` using `div(p, d)` where ``d = [d_1, \ldots, d_n]`` and ``r`` using the `rem` function with the same arguments. +The `divrem` function returns ``(q, r)``. + +```@docs +divides +``` diff --git a/docs/src/index.md b/docs/src/index.md index 2e380bee..fb40493b 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,18 +1,28 @@ # MultivariatePolynomials [MultivariatePolynomials.jl](https://github.com/blegat/MultivariatePolynomials.jl) is an implementation independent library for manipulating multivariate polynomials. -It defines abstract types and an API for multivariate monomials, terms, polynomials, moments and measures and gives default implementation for common operations on them using the API. -If you want to manipulate multivariate polynomials easily and efficiently while being able to easily switch between different implementations, this library is exactly what you are looking for. +It defines abstract types and an API for multivariate monomials, terms, polynomials and gives default implementation for common operations on them using the API. -Supported operations are : basic arithmetic, rational polynomials, differentiation and evaluation/substitution, division and duality operations between polynomials and moments. -There is also support for solving systems of equations (soon!) and building (semi)algebraic sets. +On the one hand, This packages allows you to implement algorithms on multivariate polynomials that will be independant on the representation of the polynomial that will be chosen by the user. +On the other hand, it allows the user to easily switch between different representations of polynomials to see which one is faster for the algorithm that he is using. -Currently, the following implementations are available: +Supported operations are : basic arithmetic, rational polynomials, evaluation/substitution, differentiation and division. -* [TypedPolynomials](https://github.com/rdeits/TypedPolynomials.jl) -* [DynamicPolynomials](https://github.com/blegat/DynamicPolynomials.jl) +The following packages provide representations of multivariate polynomials that implement the interface: +* [TypedPolynomials](https://github.com/rdeits/TypedPolynomials.jl) : Commutative polynomials of arbitrary coefficient types +* [DynamicPolynomials](https://github.com/blegat/DynamicPolynomials.jl) : Commutative and non-commutative polynomials of arbitrary coefficient types + +The following packages extend the interface and/or implement algorithms using the interface: + +* [SemialgebraicSets](https://github.com/blegat/SemialgebraicSets.jl) : Sets defined by inequalities and equalities between polynomials and algorithms for solving polynomial systems of equations. +* [HomotopyContinuation](https://github.com/saschatimme/HomotopyContinuation.jl) : Solving systems of polynomials via homotopy continuation. +* [MultivariateMoments](https://github.com/blegat/MultivariateMoments.jl) : Moments of multivariate measures and their scalar product with polynomials. +* [PolyJuMP](https://github.com/JuliaOpt/PolyJuMP.jl) : A [JuMP](https://github.com/JuliaOpt/JuMP.jl) extension for Polynomial Optimization. +* [SumOfSquares](https://github.com/JuliaOpt/SumOfSquares.jl) : Certifying the nonnegativity of polynomials, minimizing/maximizing polynomials and optimization over sum of squares polynomials using Sum of Squares Programming. + +## Contents ```@contents -Pages = ["apireference.md"] +Pages = ["types.md", "substitution.md", "differentiation.md", "division.md"] Depth = 3 ``` diff --git a/docs/src/substitution.md b/docs/src/substitution.md new file mode 100644 index 00000000..f5c9c381 --- /dev/null +++ b/docs/src/substitution.md @@ -0,0 +1,15 @@ +# Subtitution + +Given a polynomial, say ``p(x, y) = 3x^2y + x + 2y + 1``, one can evaluate it at a given point, e.g. ``p(2, 1) = 12 + 2 + 2 + 1 = 17`` or substitute one or more variable by a value or polynomial, e.g. ``p(x, xy^2 + 1) = 3x^2(xy^2+1) + x + 2(xy^2+1) + 1 = 3x^3y^2 + 2xy^2 + 3x^2 + x + 3``. +We distinguish the two operation as follows + +* We call an evaluation an operation where **every** variable should be replace by a new value or polynomial, the syntax is `p(x => 2, y => 1)`. +* We call a subsitution an operation where **some** (or all variables) are subtituted into a new value or polynomial, the syntax is `subs(p, y => x*y^2 + 1)`. + +The distinction is important for type stability for some implementations (it is important for [DynamicPolynomials](https://github.com/blegat/DynamicPolynomials.jl) but not for [TypedPolynomials](https://github.com/rdeits/TypedPolynomials.jl)). +Indeed consider a polynomial with `Int` coefficients for which we ask to replace some variables with `Int` values. If all the variables are replaced with `Int`s, the return type should be `Int`. +However, if some variables only are replaced by `Int` then the return type should be a polynomial with `Int` coefficients. + +```@docs +subs +``` diff --git a/docs/src/apireference.md b/docs/src/types.md similarity index 59% rename from docs/src/apireference.md rename to docs/src/types.md index b1ba8c56..2606ea1c 100644 --- a/docs/src/apireference.md +++ b/docs/src/types.md @@ -2,11 +2,12 @@ CurrentModule = MultivariatePolynomials ``` -# API +# Types ## Variables ```@docs +AbstractVariable variable name similarvariable @@ -16,6 +17,8 @@ similarvariable ## Monomials ```@docs +AbstractMonomialLike +AbstractMonomial monomialtype variables nvariables @@ -23,7 +26,6 @@ exponents degree isconstant powers -divides constantmonomial mapexponents ``` @@ -31,6 +33,8 @@ mapexponents ## Terms ```@docs +AbstractTermLike +AbstractTerm term termtype coefficient @@ -43,6 +47,8 @@ zeroterm ## Polynomials ```@docs +AbstractPolynomialLike +AbstractPolynomial polynomial polynomialtype terms @@ -60,6 +66,11 @@ removemonomials monic ``` +## Rational Polynomial Function + +A rational polynomial function can be constructed with the `/` operator. Common operations such as `+`, `-`, `*`, `-` have been implemented between rational functions. +The numerator and denominator polynomials can be retrieved by the `numerator` and `denominator` functions. + ## Monomial Vectors ```@docs diff --git a/src/MultivariatePolynomials.jl b/src/MultivariatePolynomials.jl index a59e5032..464b241f 100644 --- a/src/MultivariatePolynomials.jl +++ b/src/MultivariatePolynomials.jl @@ -9,38 +9,77 @@ import Base: *, +, -, /, ^, ==, one, zero, transpose, isapprox, @pure, dot, copy export AbstractPolynomialLike, AbstractTermLike, AbstractMonomialLike +""" + AbstractPolynomialLike{T} + +Abstract type for a value that can act like a polynomial. For instance, an `AbstractTerm{T}` is an `AbstractPolynomialType{T}` since it can act as a polynomial of only one term. +""" abstract type AbstractPolynomialLike{T} end +""" + AbstractTermLike{T} + +Abstract type for a value that can act like a term. For instance, an `AbstractMonomial` is an `AbstractTermLike{Int}` since it can act as a term with coefficient `1`. +""" abstract type AbstractTermLike{T} <: AbstractPolynomialLike{T} end +""" + AbstractMonomialLike + +Abstract type for a value that can act like a monomial. For instance, an `AbstractVariable` is an `AbstractMonomialLike` since it can act as a monomial of one variable with degree `1`. +""" abstract type AbstractMonomialLike <: AbstractTermLike{Int} end export AbstractVariable, AbstractMonomial, AbstractTerm, AbstractPolynomial +""" + AbstractVariable <: AbstractMonomialLike + +Abstract type for a variable. +""" abstract type AbstractVariable <: AbstractMonomialLike end + +""" + AbstractMonomial <: AbstractMonomialLike + +Abstract type for a monomial, i.e. a product of variables elevated to a nonnegative integer power. +""" abstract type AbstractMonomial <: AbstractMonomialLike end + +""" + AbstractTerm{T} <: AbstractTerm{T} + +Abstract type for a term of coefficient type `T`, i.e. the product between a value of type `T` and a monomial. +""" abstract type AbstractTerm{T} <: AbstractTermLike{T} end + +""" + AbstractPolynomial{T} <: AbstractPolynomialLike{T} + +Abstract type for a polynomial of coefficient type `T`, i.e. a sum of `AbstractTerm{T}`s. +""" abstract type AbstractPolynomial{T} <: AbstractPolynomialLike{T} end const APL{T} = AbstractPolynomialLike{T} include("zip.jl") + include("variable.jl") include("monomial.jl") include("term.jl") -include("monovec.jl") include("polynomial.jl") +include("monovec.jl") include("rational.jl") -include("conversion.jl") -include("promote.jl") +include("show.jl") include("hash.jl") +include("promote.jl") +include("conversion.jl") + include("operators.jl") -include("comparision.jl") +include("comparison.jl") include("substitution.jl") include("differentiation.jl") include("division.jl") -include("show.jl") - end # module diff --git a/src/comparision.jl b/src/comparison.jl similarity index 100% rename from src/comparision.jl rename to src/comparison.jl diff --git a/src/differentiation.jl b/src/differentiation.jl index afdc7782..87733e29 100644 --- a/src/differentiation.jl +++ b/src/differentiation.jl @@ -1,6 +1,29 @@ # I do not use it but I import the function to add a method export differentiate +""" + differentiate(p::AbstractPolynomialLike, v::AbstractVariable, deg::Int=1) + +Differentiate `deg` times the polynomial `p` by the variable `v`. + + differentiate(p::AbstractPolynomialLike, vs, deg::Int=1) + +Differentiate `deg` times the polynomial `p` by the variables of the vector or tuple of variable `vs` and return an array of dimension `deg`. + + differentiate(p::AbstractArray{<:AbstractPolynomialLike, N}, vs, deg::Int=1) where N + +Differentiate the polynomials in `p` by the variables of the vector or tuple of variable `vs` and return an array of dimension `N+deg`. + +### Examples + +```julia +p = 3x^2*y + x + 2y + 1 +differentiate(p, x) # should return 6xy + 1 +differentiate(p, (x, y)) # should return [6xy+1, 3x^2+1] +``` +""" +function differentiate end + # Fallback for everything else _diff_promote_op(::Type{T}, ::Type{<:AbstractVariable}) where T = T differentiate(α::T, v::AbstractVariable) where T = zero(T) diff --git a/src/division.jl b/src/division.jl index b51e37a3..877c2f4c 100644 --- a/src/division.jl +++ b/src/division.jl @@ -1,13 +1,14 @@ -export monic +export divides """ divides(t1::AbstractTermLike, t2::AbstractTermLike) Returns whether the monomial of t1 divides the monomial of t2. -# Examples +### Examples -Calling `divides(3x*y, 2x^2*y)` should return true but calling `divides(x*y, y)` should return false. +Calling `divides(2x^2y, 3xy)` should return false because `x^2y` does not divide `xy` since `x` has a degree 2 in `x^2y` which is greater than the degree of `x` on `xy`. +However, calling `divides(3xy, 2x^2y)` should return true. """ function divides(t1::AbstractTermLike, t2::AbstractTermLike) divides(monomial(t1), monomial(t2)) diff --git a/src/monomial.jl b/src/monomial.jl index ba28f0b7..86de1493 100644 --- a/src/monomial.jl +++ b/src/monomial.jl @@ -1,4 +1,4 @@ -export variables, nvariables, exponents, degree, isconstant, powers, divides, constantmonomial, mapexponents +export variables, nvariables, exponents, degree, isconstant, powers, constantmonomial, mapexponents """ monomialtype(p::AbstractPolynomialLike) @@ -11,7 +11,7 @@ Returns the type of the monomials of a polynomial of type `PT`. """ monomialtype(::Union{M, Type{M}}) where M<:AbstractMonomial = M monomialtype(::Union{PT, Type{PT}}) where PT <: APL = monomialtype(termtype(PT)) -monomialtype(::Union{AbstractVector{PT}, Type{AbstractVector{PT}}}) where PT <: APL = monomialtype(PT) +monomialtype(::Union{AbstractVector{PT}, Type{<:AbstractVector{PT}}}) where PT <: APL = monomialtype(PT) """ variables(p::AbstractPolynomialLike) @@ -99,18 +99,6 @@ Calling `powers(3x^4*y) should return `((x, 4), (y, 1))`. """ powers(t::AbstractTermLike) = tuplezip(variables(t), exponents(t)) -""" - divides(t1::AbstractTermLike, t2::AbstractTermLike) - -Returns whether `monomial(t1)` divides `monomial(t2)`. - -### Examples - -Calling `divides(2x^2y, 3xy)` should return false because `x^2y` does not divide `xy` since `x` has a degree 2 in `x^2y` which is greater than the degree of `x` on `xy`. -However, calling `divides(3xy, 2x^2y)` should return true. -""" -function divides end - """ constantmonomial(p::AbstractPolynomialType) diff --git a/src/polynomial.jl b/src/polynomial.jl index ccb0db76..816dae0d 100644 --- a/src/polynomial.jl +++ b/src/polynomial.jl @@ -2,7 +2,7 @@ export polynomial, polynomialtype, terms, nterms, coefficients, monomials export coefficienttype, monomialtype export mindegree, maxdegree, extdegree export leadingterm, leadingcoefficient, leadingmonomial -export removeleadingterm, removemonomials +export removeleadingterm, removemonomials, monic Base.norm(p::AbstractPolynomialLike, r::Int=2) = norm(coefficients(p), r) @@ -60,11 +60,30 @@ function polynomial(Q::AbstractMatrix, mv::AbstractVector, ::Type{T}) where T polynomial(polynomial(Q, mv), T) end +""" + polynomialtype(p::AbstractPolynomialLike) + +Returns the type that `p` would have if it was converted into a polynomial. + + polynomialtype(::Type{PT}) where PT<:AbstractPolynomialLike + +Returns the same as `polynomialtype(::PT)`. + + polynomialtype(p::AbstractPolynomialLike, ::Type{T}) where T + +Returns the type that `p` would have if it was converted into a polynomial of coefficient type `T`. + + termtype(::Type{PT}, ::Type{T}) where {PT<:AbstractPolynomialLike, T} + +Returns the same as `polynomialtype(::PT, ::Type{T})`. +""" polynomialtype(::Union{P, Type{P}}) where P <: APL = Base.promote_op(polynomial, P) polynomialtype(::Union{P, Type{P}}) where P <: AbstractPolynomial = P polynomialtype(::Union{M, Type{M}}) where M<:AbstractMonomialLike = polynomialtype(termtype(M)) polynomialtype(::Union{M, Type{M}}, ::Type{T}) where {M<:AbstractMonomialLike, T} = polynomialtype(termtype(M, T)) polynomialtype(::Union{P, Type{P}}, ::Type{T}) where {P <: APL, T} = polynomialtype(polynomialtype(P), T) +polynomialtype(::Union{AbstractVector{PT}, Type{<:AbstractVector{PT}}}) where PT <: APL = polynomialtype(PT) +polynomialtype(::Union{AbstractVector{PT}, Type{<:AbstractVector{PT}}}, ::Type{T}) where {PT <: APL, T} = polynomialtype(PT, T) function uniqterms(ts::AbstractVector{T}) where T <: AbstractTerm result = T[] @@ -308,6 +327,8 @@ end """ monic(p::AbstractPolynomialLike) + +Returns `p / leadingcoefficient(p)` where the leading coefficient of the returned polynomials is made sure to be exactly one to avoid rounding error. """ function monic(p::APL) α = leadingcoefficient(p) diff --git a/src/rational.jl b/src/rational.jl index 4fa268b7..64f3f909 100644 --- a/src/rational.jl +++ b/src/rational.jl @@ -7,6 +7,9 @@ struct RationalPoly{NT <: APL, DT <: APL} den::DT end +Base.numerator(r::RationalPoly) = r.num +Base.denominator(r::RationalPoly) = r.den + Base.convert(::Type{RationalPoly{NT, DT}}, q::RationalPoly{NT, DT}) where {NT, DT} = q Base.convert(::Type{RationalPoly{NTout, DTout}}, q::RationalPoly{NTin, DTin}) where {NTout, DTout, NTin, DTin} = convert(NTout, q.num) / convert(DTout, q.den) #function Base.convert(::Type{RationalPoly{NT, DT}}, p::NT) where {NT, DT} diff --git a/src/substitution.jl b/src/substitution.jl index 40133d31..3a695e8c 100644 --- a/src/substitution.jl +++ b/src/substitution.jl @@ -81,9 +81,30 @@ substitute(::AST, x, s::Substitutions) = x #substitute(::AST, x, s::AbstractSubstitution...) = x """ -eval replace all variables by a new value and subs replace some of them. -we use different function for that because of type inferability. -with eval, Julia knows that all PolyVar will be replaced by values so it can do better inference. + subs(p, s::AbstractSubstitution...) + +Apply the substitutions `s` to `p`. +Use `p(s...)` if we are sure that all the variables are substited in `s`. + +The allowed substutions are: + +* `v => p` where `v` is a variable and `p` a polynomial, e.g. `x => 1` or `x => x^2*y + x + y`. +* `V => P` where `V` is a tuple or vector of variables and `P` a tuple or vector of polynomials, e.g. `(x, y) => (y, x)` or `(y, x) => (2, 1)`. + +The order of the variables is lexicographic with the name with TypedPolynomials and by order of creation with DynamicPolynomials. +Since there is no guarantee on the order of the variables, substitution directly with a tuple or a vetor is not allowed. +You can use `p(variables(p) => (1, 2))` instead if you are sure of the order of the variables (e.g. the name order matches the creation order). + +### Examples + +```julia +p = 3x^2*y + x + 2y + 1 +p(x => 2, y => 1) # Return type is Int +subs(p, x => 2, y => 1) # Return type is Int in TypedPolynomials but is a polynomial of Int coefficients in DynamicPolynomials +subs(p, y => x*y^2 + 1) +p(y => 2) # Do not do that, this works fine with TypedPolynomials but it will not return a correct result with DynamicPolynomials since it thinks that the return type is `Int`. +``` + """ subs(p, s::AbstractSubstitution...) = substitute(Subs(), p, s) diff --git a/src/term.jl b/src/term.jl index 9c3a1270..655075a0 100644 --- a/src/term.jl +++ b/src/term.jl @@ -37,11 +37,14 @@ Returns the type of the terms of `p` but with coefficient type `T`. Returns the type of the terms of a polynomial of type `PT` but with coefficient type `T`. """ -termtype(::Union{P, Type{P}}) where P <: APL = Base.promote_op(first ∘ terms, P) termtype(::Union{T, Type{T}}) where T <: AbstractTerm = T +termtype(::Union{P, Type{P}}) where P <: APL = Base.promote_op(first ∘ terms, P) +termtype(p::Union{APL, Type{<:APL}}, ::Type{T}) where T = termtype(termtype(p), T) +termtype(m::Union{M, Type{M}}) where M<:AbstractMonomialLike = termtype(m, Int) termtype(v::Union{AbstractVariable, Type{<:AbstractVariable}}) = termtype(monomialtype(v)) termtype(v::Union{AbstractVariable, Type{<:AbstractVariable}}, ::Type{T}) where T = termtype(monomialtype(v), T) -termtype(::Union{M, Type{M}}) where M<:AbstractMonomialLike = termtype(M, Int) +termtype(::Union{AbstractVector{PT}, Type{<:AbstractVector{PT}}}) where PT <: APL = termtype(PT) +termtype(::Union{AbstractVector{PT}, Type{<:AbstractVector{PT}}}, ::Type{T}) where {PT <: APL, T} = termtype(PT, T) """ coefficient(t::AbstractTermLike) diff --git a/test/monomial.jl b/test/monomial.jl index af1626bb..b1bf963a 100644 --- a/test/monomial.jl +++ b/test/monomial.jl @@ -29,6 +29,12 @@ const MP = MultivariatePolynomials @test_throws ErrorException variable(x*y[1]) @test_throws ErrorException variable(constantmonomial(typeof(x))) + m = x^2 + typetests(m) + typetests([x^2, x^3]) + @test (@inferred polynomial(m)) isa AbstractPolynomial{Int} + @test (@inferred polynomial(m, Float64)) isa AbstractPolynomial{Float64} + @test variable(x^1) == x @test variable(x^1) isa AbstractVariable @test variable(x^2 + x - x^2) == x diff --git a/test/polynomial.jl b/test/polynomial.jl index f9dfd3d8..db5695e9 100644 --- a/test/polynomial.jl +++ b/test/polynomial.jl @@ -33,6 +33,15 @@ Mod.@polyvar y + p = 3x^2*y^4 + 2x + typetests(p) + typetests([p, x + y]) + @test (@inferred polynomial(p)) isa AbstractPolynomial{Int} + @test (@inferred polynomial(p, Float64)) isa AbstractPolynomial{Float64} + + @test (@inferred 2x^2*y + 0.0x*y) == 2x^2*y + @test (@inferred 0.0x^2*y + 3x*y) == 3x*y + @test iszero(((x + x) - 2x) * (x * (x ^ 2 + y ^ 2))) @test Tuple(variables([x + 1, y^2])) == (x, y) diff --git a/test/rational.jl b/test/rational.jl index 84f2c878..6d95c808 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -20,4 +20,6 @@ @test (x^2 + 1) / (2x) != nothing @test Dict{Int,Int}() != x / (x^2 + 1) @test (x^2 + 1) / (2x) != Dict{Int,Int}() + @test numerator(x / x^2) == x + @test denominator(x / x^2) == x^2 end diff --git a/test/term.jl b/test/term.jl index 544b427a..bce3dab9 100644 --- a/test/term.jl +++ b/test/term.jl @@ -37,6 +37,12 @@ @test degree(2x^2, y) == 0 @test degree(2x^2, y) == 0 + t = 3x^2*y^4 + typetests(t) + typetests([t, 2x]) + @test (@inferred polynomial(t)) isa AbstractPolynomial{Int} + @test (@inferred polynomial(t, Float64)) isa AbstractPolynomial{Float64} + @test_throws InexactError push!([1], 2x) @test_throws ErrorException push!([x^2], 2x) end diff --git a/test/utils.jl b/test/utils.jl index 104849b5..e4662194 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -10,19 +10,17 @@ end CustomPoly(p::AbstractPolynomial{T}) where T = CustomPoly{T, typeof(p)}(p) MultivariatePolynomials.terms(p::CustomPoly) = terms(p.p) -function _typetests(x::Union{AbstractPolynomialLike{T}, Type{<:AbstractPolynomialLike{T}}}) where T +function _typetests(x, ::Type{T}) where T @test (@inferred monomialtype(x)) <: AbstractMonomial @test (@inferred termtype(x)) <: AbstractTerm{Int} @test (@inferred termtype(x, Float64)) <: AbstractTerm{Float64} @test (@inferred polynomialtype(x)) <: AbstractPolynomial{Int} - @test (@inferred polynomial(x)) isa AbstractPolynomial{Int} @test (@inferred polynomialtype(x, Float64)) <: AbstractPolynomial{Float64} - @test (@inferred polynomial(x, Float64)) isa AbstractPolynomial{Float64} end -function typetests(x::AbstractPolynomialLike{T}) where T - _typetests(x) - _typetests(typeof(x)) +function typetests(x::Union{AbstractPolynomialLike{T}, Vector{<:AbstractPolynomialLike{T}}}) where T + _typetests(x, T) + _typetests(typeof(x), T) end diff --git a/test/variable.jl b/test/variable.jl index d6e635b1..ddc90933 100644 --- a/test/variable.jl +++ b/test/variable.jl @@ -24,20 +24,9 @@ import MultivariatePolynomials: AbstractVariable, similarvariable, @similarvaria @test one(x) isa AbstractMonomial @inferred one(x) - @test (@inferred monomialtype(x)) <: AbstractMonomial - @test (@inferred monomialtype(typeof(x))) <: AbstractMonomial - - @test (@inferred termtype(x)) <: AbstractTerm{Int} - @test (@inferred termtype(x, Float64)) <: AbstractTerm{Float64} - @test (@inferred termtype(typeof(x))) <: AbstractTerm{Int} - @test (@inferred termtype(typeof(x), Float64)) <: AbstractTerm{Float64} - - @test (@inferred polynomialtype(x)) <: AbstractPolynomial{Int} + typetests(x) @test (@inferred polynomial(x)) isa AbstractPolynomial{Int} - @test (@inferred polynomialtype(x, Float64)) <: AbstractPolynomial{Float64} @test (@inferred polynomial(x, Float64)) isa AbstractPolynomial{Float64} - @test (@inferred polynomialtype(typeof(x))) <: AbstractPolynomial{Int} - @test (@inferred polynomialtype(typeof(x), Float64)) <: AbstractPolynomial{Float64} @test nterms(x) == 1 @test @inferred(terms(x)) == [x]