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}() |