| Line | Exclusive | Inclusive | Code |
|---|---|---|---|
| 1 | struct Variable{Name} <: AbstractVariable | ||
| 2 | end | ||
| 3 | |||
| 4 | MP.name(::Type{Variable{N}}) where {N} = N | ||
| 5 | MP.name(v::Variable) = name(typeof(v)) | ||
| 6 | MP.name_base_indices(v::Variable) = name_base_indices(typeof(v)) | ||
| 7 | function MP.name_base_indices(v::Type{Variable{N}}) where N | ||
| 8 | name = string(N) | ||
| 9 | splits = split(string(N), r"[\[,\]]\s*", keepempty=false) | ||
| 10 | if length(splits) == 1 | ||
| 11 | return name, Int[] | ||
| 12 | else | ||
| 13 | return splits[1], parse.(Int, splits[2:end]) | ||
| 14 | end | ||
| 15 | end | ||
| 16 | |||
| 17 | |||
| 18 | MP.variables(v::Variable) = (v,) | ||
| 19 | MP.variables(::Type{V}) where {V <: Variable} = (V(),) | ||
| 20 | Base.hash(v::Variable, u::UInt) = hash(name(v), u) | ||
| 21 | |||
| 22 | checksorted(x::Tuple{Any}, cmp) = true | ||
| 23 | checksorted(x::Tuple{}, cmp) = true | ||
| 24 | checksorted(x::Tuple, cmp) = cmp(x[1], x[2]) && checksorted(Base.tail(x), cmp) | ||
| 25 | |||
| 26 | |||
| 27 | |||
| 28 | struct Monomial{V, N} <: AbstractMonomial | ||
| 29 | exponents::NTuple{N, Int} | ||
| 30 | |||
| 31 | function Monomial{V, N}(exponents::NTuple{N, Int}=ntuple(_ -> 0, Val{N}())) where {V, N} | ||
| 32 | @assert checksorted(V, >) | ||
| 33 | new{V, N}(exponents) | ||
| 34 | end | ||
| 35 | Monomial{V}(exponents::NTuple{N, Integer}=()) where {V, N} = Monomial{V, N}(exponents) | ||
| 36 | Monomial{V}(exponents::AbstractVector{<:Integer}) where {V} = Monomial{V}(NTuple{length(V), Int}(exponents)) | ||
| 37 | end | ||
| 38 | |||
| 39 | Monomial(v::Variable) = monomialtype(v)((1,)) | ||
| 40 | MP.monomial(v::Variable) = Monomial(v) | ||
| 41 | |||
| 42 | MP.variables(::Type{<:Monomial{V}}) where {V} = V | ||
| 43 | MP.variables(m::Monomial) = variables(typeof(m)) | ||
| 44 | MP.nvariables(::Type{<:Monomial{V}}) where {V} = length(V) | ||
| 45 | MP.nvariables(m::Monomial) = nvariables(typeof(m)) | ||
| 46 | MP.monomialtype(::Type{V}) where V<:Variable = monomialtype(V()) | ||
| 47 | MP.monomialtype(v::Variable) = Monomial{(v,), 1} | ||
| 48 | |||
| 49 | MP.exponents(m::Monomial) = m.exponents | ||
| 50 | MP.exponent(m::Monomial, i::Integer) = m.exponents[i] | ||
| 51 | _exponent(v::V, p1::Tuple{V, Integer}, p2...) where {V <: Variable} = p1[2] | ||
| 52 | _exponent(v::Variable, p1::Tuple{Variable, Integer}, p2...) = _exponent(v, p2...) | ||
| 53 | _exponent(v::Variable) = 0 | ||
| 54 | MP.exponent(m::Monomial, v::Variable) = _exponent(v, powers(m)...) | ||
| 55 | |||
| 56 | |||
| 57 | |||
| 58 | struct Term{CoeffType, M <: Monomial} <: AbstractTerm{CoeffType} | ||
| 59 | coefficient::CoeffType | ||
| 60 | monomial::M | ||
| 61 | end | ||
| 62 | Term(v::Variable) = Term(Monomial(v)) | ||
| 63 | Term(x, v::Variable) = Term(x, Monomial(v)) | ||
| 64 | Term(m::Monomial) = Term(1, m) | ||
| 65 | |||
| 66 | MP.coefficient(t::Term) = t.coefficient | ||
| 67 | MP.monomial(t::Term) = t.monomial | ||
| 68 | coefftype(::Type{<:Term{C}}) where {C} = C | ||
| 69 | MP.termtype(::Union{Term{C, M}, Type{<:Term{C, M}}}, ::Type{T}) where {C, M, T} = Term{T, M} | ||
| 70 | MP.termtype(::Union{M, Type{M}}, ::Type{T}) where {M<:Monomial, T} = Term{T, M} | ||
| 71 | MP.monomialtype(::Type{<:Term{C, M}}) where {C, M} = M | ||
| 72 | MP.monomialtype(t::Term) = monomialtype(typeof(t)) | ||
| 73 | MP.variables(t::Union{Term, Type{<:Term}}) = variables(monomialtype(t)) | ||
| 74 | MP.nvariables(t::Union{Term, Type{<:Term}}) = nvariables(monomialtype(t)) | ||
| 75 | |||
| 76 | struct Polynomial{CoeffType, T <: Term{CoeffType}, V <: AbstractVector{T}} <: AbstractPolynomial{CoeffType} | ||
| 77 | terms::V | ||
| 78 | |||
| 79 | 79 (9 %) | 79 (9 %) |
79 (9 %)
samples spent in Polynomial
Polynomial{C, T, V}(terms::AbstractVector{T}) where {C, T, V} = new{C, T, V}(terms)
79 (100 %) (ex.), 79 (100 %) (incl.) when called from Polynomial line 82 |
| 80 | Polynomial{C, T, V}(p::Polynomial{C, T, V}) where {C, T, V} = p | ||
| 81 | end | ||
| 82 | 79 (9 %) |
79 (100 %)
samples spent calling
Polynomial
Polynomial(terms::AbstractVector{T}) where {C, T <: Term{C}} = Polynomial{C, T, typeof(terms)}(terms)
|
|
| 83 | Polynomial(t::AbstractVector) = Polynomial(Term.(t)) | ||
| 84 | Polynomial(x) = Polynomial(Term(x)) | ||
| 85 | MP.termtype(::Type{<:Polynomial{C, T}}) where {C, T} = T | ||
| 86 | changeeltype(::Type{<:Vector}, ::Type{T}) where T = Vector{T} | ||
| 87 | function MP.polynomialtype(::Type{<:Polynomial{C, T, V}}, ::Type{NewC}) where {C, T, V, NewC} | ||
| 88 | NewT = termtype(T, NewC) | ||
| 89 | Polynomial{NewC, NewT, changeeltype(V, NewT)} | ||
| 90 | end | ||
| 91 | MP.polynomialtype(::Type{Term{C, M}}) where {C, M} = Polynomial{C, Term{C, M}, Vector{Term{C, M}}} | ||
| 92 | Polynomial(term::TT) where TT<:Term = Polynomial(iszero(term) ? TT[] : [term]) | ||
| 93 | |||
| 94 | MP.terms(p::Polynomial) = p.terms | ||
| 95 | MP.variables(::Union{Polynomial{C, T}, AbstractArray{<:Polynomial{C, T}}, Type{<:Polynomial{C, T}}}) where {C, T} = variables(T) | ||
| 96 | MP.nvariables(::Union{Polynomial{C, T}, AbstractArray{<:Polynomial{C, T}}, Type{<:Polynomial{C, T}}}) where {V, N, C, M<:Monomial{V, N}, T<:Term{C, M}} = N | ||
| 97 | const MonomialLike = Union{Variable, Monomial} | ||
| 98 | const TermLike = Union{MonomialLike, Term} | ||
| 99 | const PolynomialLike = Union{TermLike, Polynomial} | ||
| 100 | |||
| 101 | MP.variables(::Union{AbstractVector{T}, Type{<:AbstractVector{T}}}) where {T <: PolynomialLike} = variables(T) | ||
| 102 | MP.nvariables(::Union{AbstractVector{T}, Type{<:AbstractVector{T}}}) where {T <: PolynomialLike} = nvariables(T) | ||
| 103 | MP.variable_union_type(::Union{PolynomialLike, Type{<:PolynomialLike}}) = Variable | ||
| 104 | MP.constantmonomial(p::PolynomialLike) = Monomial{variables(p), nvariables(p)}() | ||
| 105 | MP.constantmonomial(::Type{TT}) where {TT<:PolynomialLike} = Monomial{variables(TT), nvariables(TT)}() | ||
| 106 | |||
| 107 | |||
| 108 | # Based on fillZfordeg!() from MultivariatePolynomials.jl by Benoit Legat | ||
| 109 | # https://github.com/blegat/MultivariatePolynomials.jl/blob/d85ad85de413afa20fc8f5354c980387218ced2c/src/mono.jl#L186-L259 | ||
| 110 | function monomial_powers(::Val{N}, degree) where N | ||
| 111 | result = Vector{NTuple{N, Int}}() | ||
| 112 | powers = zeros(Int, N) | ||
| 113 | powers[1] = degree | ||
| 114 | while true | ||
| 115 | push!(result, NTuple{N, Int}(powers)) | ||
| 116 | if powers[end] == degree | ||
| 117 | break | ||
| 118 | end | ||
| 119 | total = 1 | ||
| 120 | for j in (N - 1):-1:1 | ||
| 121 | if powers[j] != 0 | ||
| 122 | powers[j] -= 1 | ||
| 123 | powers[j+1] += total | ||
| 124 | break | ||
| 125 | else | ||
| 126 | total += powers[j+1] | ||
| 127 | powers[j+1] = 0 | ||
| 128 | end | ||
| 129 | end | ||
| 130 | end | ||
| 131 | result | ||
| 132 | end | ||
| 133 | |||
| 134 | function MP.monomials(vars::Tuple{Vararg{<:Variable}}, degree::Integer, filter::Function=m->true) | ||
| 135 | checksorted(vars, >) || throw(ArgumentError("Variables must be in order")) | ||
| 136 | Monomial{vars, length(vars)}[Monomial{vars}(p) for p in monomial_powers(Val{length(vars)}(), degree) if filter(Monomial{vars}(p))] | ||
| 137 | end | ||
| 138 | |||
| 139 | function MP.monomials(vars::Tuple{Vararg{<:Variable}}, degrees::AbstractArray, filter::Function=m->true) | ||
| 140 | checksorted(vars, >) || throw(ArgumentError("Variables must be in order")) | ||
| 141 | if isempty(degrees) | ||
| 142 | # Otherwise, the following error is thrown: "ArgumentError: argument to Flatten must contain at least one iterator" | ||
| 143 | Monomial{vars, length(vars)}[] | ||
| 144 | else | ||
| 145 | Monomial{vars, length(vars)}[Monomial{vars}(p) for d in sort(degrees, rev=true) | ||
| 146 | for p in monomial_powers(Val{length(vars)}(), d) if filter(Monomial{vars}(p))] | ||
| 147 | end | ||
| 148 | end | ||
| 149 | |||
| 150 | MP.similarvariable(::Union{PolynomialLike, Type{<:PolynomialLike}}, ::Type{Val{N}}) where N = Variable{N}() |