| 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...) |