@@ -19,21 +19,81 @@ Base.gcd(m1::AbstractMonomialLike, m2::AbstractMonomialLike) = mapexponents(min,
1919Base. lcm (m1:: AbstractMonomialLike , m2:: AbstractMonomialLike ) = mapexponents (max, m1, m2)
2020
2121# _div(a, b) assumes that b divides a
22+ _div (a:: Union{Rational, AbstractFloat} , b) = a / b
23+ _div (a, b) = div (a, b)
2224_div (m1:: AbstractMonomialLike , m2:: AbstractMonomialLike ) = mapexponents (- , m1, m2)
2325function _div (t:: AbstractTerm , m:: AbstractMonomial )
24- coefficient (t) * _div (monomial (t), m)
26+ term ( coefficient (t), _div (monomial (t), m) )
2527end
2628function _div (t1:: AbstractTermLike , t2:: AbstractTermLike )
27- (coefficient (t1) / coefficient (t2)) * _div (monomial (t1), monomial (t2))
29+ term (_div (coefficient (t1), coefficient (t2)), _div (monomial (t1), monomial (t2)))
30+ end
31+ function _div (f:: APL , g:: APL )
32+ lt = leadingterm (g)
33+ rf = MA. copy_if_mutable (f)
34+ rg = removeleadingterm (g)
35+ q = zero (rf)
36+ while ! iszero (rf)
37+ ltf = leadingterm (rf)
38+ qt = _div (ltf, lt)
39+ q = MA. add! (q, qt)
40+ rf = MA. operate! (removeleadingterm, rf)
41+ rf = MA. operate! (MA. sub_mul, rf, qt, rg)
42+ end
43+ return q
2844end
2945
3046Base. div (f:: APL , g:: Union{APL, AbstractVector{<:APL}} ; kwargs... ) = divrem (f, g; kwargs... )[1 ]
3147Base. rem (f:: APL , g:: Union{APL, AbstractVector{<:APL}} ; kwargs... ) = divrem (f, g; kwargs... )[2 ]
3248
33- proddiff (x, y) = x/ y - x/ y
49+ # FIXME What should we do for `Rational` ?
50+ function pseudo_rem (f:: APL , g:: APL{<:Union{Rational, AbstractFloat}} , algo)
51+ return true , rem (f, g)
52+ end
53+
54+ function pseudo_rem (f:: APL , g:: APL , algo)
55+ ltg = leadingterm (g)
56+ rg = removeleadingterm (g)
57+ ltf = leadingterm (f)
58+ if ! divides (monomial (ltg), ltf)
59+ return false , f
60+ end
61+ while divides (monomial (ltg), ltf)
62+ new_f = constantterm (coefficient (ltg), f) * removeleadingterm (f)
63+ new_g = term (coefficient (ltf), _div (monomial (ltf), monomial (ltg))) * rg
64+ # Check with `::` that we don't have any type unstability on this variable.
65+ f = (new_f - new_g):: typeof (f)
66+ if algo. primitive_rem
67+ f = primitive_part (f, algo):: typeof (f)
68+ end
69+ if algo. skip_last && maxdegree (f) == maxdegree (g)
70+ break
71+ end
72+ ltf = leadingterm (f)
73+ end
74+ return true , f
75+ end
76+ function MA. promote_operation (
77+ :: typeof (pseudo_rem),
78+ :: Type{P} ,
79+ :: Type{Q} ,
80+ ) where {T,S<: Union{Rational, AbstractFloat} ,P<: APL{T} ,Q<: APL{S} }
81+ return MA. promote_operation (rem, P, Q)
82+ end
83+ function MA. promote_operation (:: typeof (pseudo_rem), :: Type{P} , :: Type{Q} ) where {T,S,P<: APL{T} ,Q<: APL{S} }
84+ U1 = MA. promote_operation (* , S, T)
85+ U2 = MA. promote_operation (* , T, S)
86+ # `promote_type(P, Q)` is needed for TypedPolynomials in case they use different variables
87+ return polynomialtype (promote_type (P, Q), MA. promote_operation (- , U1, U2))
88+ end
89+
90+ function MA. promote_operation (:: Union{typeof(div), typeof(rem)} , :: Type{P} , g:: Type{Q} ) where {T,S,P<: APL{T} ,Q<: APL{S} }
91+ U = MA. promote_operation (/ , T, S)
92+ # `promote_type(P, Q)` is needed for TypedPolynomials in case they use different variables
93+ return polynomialtype (promote_type (P, Q), MA. promote_operation (- , U, U))
94+ end
3495function Base. divrem (f:: APL{T} , g:: APL{S} ; kwargs... ) where {T, S}
35- # `promote_type(typeof(f), typeof(g))` is needed for TypedPolynomials in case they use different variables
36- rf = convert (polynomialtype (promote_type (typeof (f), typeof (g)), Base. promote_op (proddiff, T, S)), MA. copy_if_mutable (f))
96+ rf = convert (MA. promote_operation (div, typeof (f), typeof (g)), MA. copy_if_mutable (f))
3797 q = zero (rf)
3898 r = zero (rf)
3999 lt = leadingterm (g)
@@ -61,8 +121,7 @@ function Base.divrem(f::APL{T}, g::APL{S}; kwargs...) where {T, S}
61121 q, r
62122end
63123function Base. divrem (f:: APL{T} , g:: AbstractVector{<:APL{S}} ; kwargs... ) where {T, S}
64- # `promote_type(typeof(f), eltype(g))` is needed for TypedPolynomials in case they use different variables
65- rf = convert (polynomialtype (promote_type (typeof (f), eltype (g)), Base. promote_op (proddiff, T, S)), MA. copy_if_mutable (f))
124+ rf = convert (MA. promote_operation (div, typeof (f), eltype (g)), MA. copy_if_mutable (f))
66125 r = zero (rf)
67126 q = similar (g, typeof (rf))
68127 for i in eachindex (q)
@@ -105,12 +164,3 @@ function Base.divrem(f::APL{T}, g::AbstractVector{<:APL{S}}; kwargs...) where {T
105164 end
106165 q, r
107166end
108-
109- function Base. gcd (p:: AbstractPolynomialLike{T} , q:: AbstractPolynomialLike{S} ) where {T, S}
110- if isapproxzero (q)
111- convert (polynomialtype (p, Base. promote_op (proddiff, T, S)), p)
112- else
113- gcd (q, rem (p, q))
114- end
115- end
116- Base. lcm (p:: AbstractPolynomialLike , q:: AbstractPolynomialLike ) = p * div (q, gcd (p, q))
0 commit comments