Line | Exclusive | Inclusive | Code |
---|---|---|---|
1 | export isapproxzero | ||
2 | |||
3 | Base.iszero(v::AbstractVariable) = false | ||
4 | Base.iszero(m::AbstractMonomial) = false | ||
5 | 4 (0 %) |
4 (100 %)
samples spent calling
iszero
Base.iszero(t::AbstractTerm) = iszero(coefficient(t))
|
|
6 | Base.iszero(t::AbstractPolynomial) = iszero(nterms(t)) | ||
7 | |||
8 | # See https://github.com/blegat/MultivariatePolynomials.jl/issues/22 | ||
9 | # avoids the call to be transfered to eqconstant | ||
10 | Base.:(==)(α::Nothing, x::APL) = false | ||
11 | Base.:(==)(x::APL, α::Nothing) = false | ||
12 | Base.:(==)(α::Dict, x::APL) = false | ||
13 | Base.:(==)(x::APL, α::Dict) = false | ||
14 | Base.:(==)(α::Nothing, x::RationalPoly) = false | ||
15 | Base.:(==)(x::RationalPoly, α::Nothing) = false | ||
16 | Base.:(==)(α::Dict, x::RationalPoly) = false | ||
17 | Base.:(==)(x::RationalPoly, α::Dict) = false | ||
18 | |||
19 | function polyeqterm(p::AbstractPolynomial, t) | ||
20 | if iszero(p) | ||
21 | iszero(t) | ||
22 | else | ||
23 | # terms/nterms ignore zero terms | ||
24 | nterms(p) == 1 && leadingterm(p) == t | ||
25 | end | ||
26 | end | ||
27 | polyeqterm(p::APL, t) = polyeqterm(polynomial(p), t) | ||
28 | |||
29 | eqconstant(α, v::AbstractVariable) = false | ||
30 | eqconstant(v::AbstractVariable, α) = false | ||
31 | function _termeqconstant(t::AbstractTermLike, α) | ||
32 | if iszero(t) | ||
33 | iszero(α) | ||
34 | else | ||
35 | α == coefficient(t) && isconstant(t) | ||
36 | end | ||
37 | end | ||
38 | eqconstant(α, t::AbstractTermLike) = _termeqconstant(t, α) | ||
39 | eqconstant(t::AbstractTermLike, α) = _termeqconstant(t, α) | ||
40 | eqconstant(α, p::APL) = polyeqterm(p, α) | ||
41 | eqconstant(p::APL, α) = polyeqterm(p, α) | ||
42 | |||
43 | function Base.:(==)(t1::AbstractTerm, t2::AbstractTerm) | ||
44 | c1 = coefficient(t1) | ||
45 | c2 = coefficient(t2) | ||
46 | if iszero(c1) | ||
47 | iszero(c2) | ||
48 | else | ||
49 | c1 == c2 && monomial(t1) == monomial(t2) | ||
50 | end | ||
51 | end | ||
52 | Base.:(==)(p::AbstractPolynomial, t::AbstractTerm) = polyeqterm(p, t) | ||
53 | Base.:(==)(t::AbstractTerm, p::AbstractPolynomial) = polyeqterm(p, t) | ||
54 | |||
55 | function compare_terms(p1::AbstractPolynomial, p2::AbstractPolynomial, isz, op) | ||
56 | i1 = 1 | ||
57 | i2 = 1 | ||
58 | t1 = terms(p1) | ||
59 | t2 = terms(p2) | ||
60 | while true | ||
61 | while i1 <= length(t1) && isz(coefficient(t1[i1])) | ||
62 | i1 += 1 | ||
63 | end | ||
64 | while i2 <= length(t2) && isz(coefficient(t2[i2])) | ||
65 | i2 += 1 | ||
66 | end | ||
67 | if i1 > length(t1) && i2 > length(t2) | ||
68 | return true | ||
69 | end | ||
70 | if i1 > length(t1) || i2 > length(t2) | ||
71 | return false | ||
72 | end | ||
73 | if !op(t1[i1], t2[i2]) | ||
74 | return false | ||
75 | end | ||
76 | i1 += 1 | ||
77 | i2 += 1 | ||
78 | end | ||
79 | end | ||
80 | |||
81 | # Can there be zero term in TypedPolynomials ? | ||
82 | #function (==)(p1::AbstractPolynomial, p2::AbstractPolynomial) | ||
83 | # nterms(p1) != nterms(p2) && return false | ||
84 | # for (t1, t2) in zip(terms(p1), terms(p2)) | ||
85 | # @assert !iszero(t1) && !iszero(t2) # There should be no zero term | ||
86 | # if t1 != t2 | ||
87 | # return false | ||
88 | # end | ||
89 | # end | ||
90 | # return true | ||
91 | #end | ||
92 | Base.:(==)(p1::AbstractPolynomial, p2::AbstractPolynomial) = compare_terms(p1, p2, iszero, ==) | ||
93 | |||
94 | Base.:(==)(p::RationalPoly, q::RationalPoly) = p.num*q.den == q.num*p.den | ||
95 | # Solve ambiguity with (::PolyType, ::Any) | ||
96 | Base.:(==)(p::APL, q::RationalPoly) = p*q.den == q.num | ||
97 | Base.:(==)(q::RationalPoly, p::APL) = p == q | ||
98 | Base.:(==)(α, q::RationalPoly) = α*q.den == q.num | ||
99 | Base.:(==)(q::RationalPoly, α) = α == q | ||
100 | |||
101 | # α could be a JuMP affine expression | ||
102 | isapproxzero(α; ztol::Real=0.) = false | ||
103 | function isapproxzero(α::Number; ztol::Real=Base.rtoldefault(α, α, 0)) | ||
104 | abs(α) <= ztol | ||
105 | end | ||
106 | |||
107 | isapproxzero(m::AbstractMonomialLike; kwargs...) = false | ||
108 | isapproxzero(t::AbstractTermLike; kwargs...) = isapproxzero(coefficient(t); kwargs...) | ||
109 | isapproxzero(p::APL; kwargs...) = all(isapproxzero.(terms(p); kwargs...)) | ||
110 | isapproxzero(p::RationalPoly; kwargs...) = isapproxzero(p.num; kwargs...) | ||
111 | |||
112 | Base.isapprox(t1::AbstractTerm, t2::AbstractTerm; kwargs...) = isapprox(coefficient(t1), coefficient(t2); kwargs...) && monomial(t1) == monomial(t2) | ||
113 | function Base.isapprox(p1::AbstractPolynomial{S}, p2::AbstractPolynomial{T}; | ||
114 | atol=0, ztol::Real=iszero(atol) ? Base.rtoldefault(S, T, 0) : atol, kwargs...) where {S, T} | ||
115 | return compare_terms(p1, p2, t -> isapproxzero(t; ztol=ztol), | ||
116 | (x, y) -> isapprox(x, y; atol=atol, kwargs...)) | ||
117 | end | ||
118 | |||
119 | Base.isapprox(p::RationalPoly, q::RationalPoly; kwargs...) = isapprox(p.num*q.den, q.num*p.den; kwargs...) | ||
120 | Base.isapprox(p::RationalPoly, q::APL; kwargs...) = isapprox(p.num, q*p.den; kwargs...) | ||
121 | Base.isapprox(p::APL, q::RationalPoly; kwargs...) = isapprox(p*q.den, q.num; kwargs...) | ||
122 | Base.isapprox(q::RationalPoly{C}, α; kwargs...) where {C} = isapprox(q, constantterm(α, q.den); kwargs...) | ||
123 | Base.isapprox(α, q::RationalPoly{C}; kwargs...) where {C} = isapprox(constantterm(α, q.den), q; kwargs...) |