Skip to content

Commit 8e19e99

Browse files
blegatYingboMa
andauthored
Speedup for content (#200)
* Speedup for content Co-authored-by: Yingbo Ma <[email protected]> * Add gcd for terms * Fixes * Fix * Add credits to SIMDPolynomials * Fix test * Exclude test where it was overflowing anyway Co-authored-by: Yingbo Ma <[email protected]>
1 parent 79f164d commit 8e19e99

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

src/gcd.jl

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ function Base.gcd(p1::APL{T}, p2::APL{S}, algo::AbstractUnivariateGCDAlgorithm=G
129129
return inflate(g, shift, defl)::MA.promote_operation(gcd, typeof(p1), typeof(p2))
130130
end
131131

132+
function Base.gcd(t1::AbstractTermLike{T}, t2::AbstractTermLike{S}, algo::AbstractUnivariateGCDAlgorithm=GeneralizedEuclideanAlgorithm()) where {T, S}
133+
return term(_coefficient_gcd(coefficient(t1), coefficient(t2)), gcd(monomial(t1), monomial(t2)))
134+
end
135+
132136
# Inspired from to `AbstractAlgebra.deflation`
133137
function deflation(p::AbstractPolynomialLike)
134138
if iszero(p)
@@ -508,6 +512,18 @@ _simplifier(a, b, algo) = _gcd(a, b, algo)
508512
# which makes the size of the `BigInt`s grow significantly which slows things down.
509513
_simplifier(a::Rational, b::Rational, algo) = gcd(a.num, b.num) // gcd(a.den, b.den)
510514

515+
# Largely inspired from from `YingboMa/SIMDPolynomials.jl`.
516+
function termwise_content(p::APL)
517+
ts = terms(p)
518+
length(ts) == 1 && return first(ts)
519+
g = gcd(ts[1], ts[2])
520+
isone(g) || for i in 3:length(ts)
521+
g = gcd(g, ts[i])
522+
isone(g) && break
523+
end
524+
return g
525+
end
526+
511527
"""
512528
content(poly::AbstractPolynomialLike{T}, algo::AbstractUnivariateGCDAlgorithm) where {T}
513529
@@ -524,11 +540,28 @@ function content(poly::APL{T}, algo::AbstractUnivariateGCDAlgorithm) where {T}
524540
P = MA.promote_operation(gcd, T, T)
525541
# This is tricky to infer a `content` calls `gcd` which calls `content`, etc...
526542
# To help Julia break the loop, we annotate the result here.
527-
return reduce(
528-
(a, b) -> _simplifier(a, b, algo),
529-
coefficients(poly),
530-
init = zero(P),
531-
)::P
543+
coefs = coefficients(poly)
544+
length(coefs) == 0 && return zero(T)
545+
length(coefs) == 1 && return first(coefs)
546+
# Largely inspired from from `YingboMa/SIMDPolynomials.jl`.
547+
if T <: APL
548+
for i in eachindex(coefs)
549+
if nterms(coefs[i]) == 1
550+
g = gcd(termwise_content(coefs[1]), termwise_content(coefs[2]))
551+
isone(g) || for i in 3:length(coefs)
552+
g = gcd(g, termwise_content(coefs[i]))
553+
isone(g) && break
554+
end
555+
return convert(P, g)
556+
end
557+
end
558+
end
559+
g = gcd(coefs[1], coefs[2])::P
560+
isone(g) || for i in 3:length(coefs)
561+
g = _simplifier(g, coefs[i], algo)::P
562+
isone(g) && break
563+
end
564+
return g::P
532565
end
533566
function content(poly::APL{T}, algo::AbstractUnivariateGCDAlgorithm) where {T<:AbstractFloat}
534567
return one(T)

test/division.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ function _mult_test(a, b)
151151
end
152152
function mult_test(expected, a, b, algo)
153153
g = @inferred MP._simplifier(a, b, algo)
154-
@test g isa promote_type(polynomialtype(a), polynomialtype(b))
154+
@test g isa Base.promote_typeof(a, b)
155155
_mult_test(expected, g)
156156
end
157157
function mult_test(expected, a::Number, b, algo)
@@ -213,7 +213,7 @@ function multivariate_gcd_test(::Type{T}, algo=GeneralizedEuclideanAlgorithm())
213213
y^2*z^3 + y*z^4 + y^3 + y^3*z - y - z,
214214
algo,
215215
)
216-
if T != Int || (algo != GeneralizedEuclideanAlgorithm(false, false) && algo != GeneralizedEuclideanAlgorithm(true, false))
216+
if T != Int
217217
test_relatively_prime(
218218
-3o*y^2*z^3 - 3*y^4 + y*z^3 + z^4 + 2*y^3 + 2*y^2*z - y,
219219
3o*y^3*z^3 - 2*y^5 + y^2*z^3 + y*z^4 + y^3 + y^3*z - y - z,

0 commit comments

Comments
 (0)