-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize map_coefficients, change_base_ring for some inputs #1994
base: master
Are you sure you want to change the base?
Optimize map_coefficients, change_base_ring for some inputs #1994
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1994 +/- ##
==========================================
- Coverage 88.34% 88.30% -0.04%
==========================================
Files 98 98
Lines 36211 36232 +21
==========================================
+ Hits 31991 31996 +5
- Misses 4220 4236 +16 ☔ View full report in Codecov by Sentry. |
b4f481a
to
550e2e6
Compare
@@ -182,21 +182,6 @@ function Base.hash(f::zzModMPolyRingElem, h::UInt) | |||
return UInt(1) # TODO: enhance or throw error | |||
end | |||
|
|||
function AbstractAlgebra.map_coefficients(F::fpField, f::QQMPolyRingElem; parent=polynomial_ring(F, nvars(parent(f)), cached=false)[1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the parent
computation here was wrong as it ignored the internal ordering
550e2e6
to
327751b
Compare
Namely if the input polynomial is a `QQMPolyRingElem` and the transformation "function" is `ZZ` resp. a `fpField`. Before this patch: julia> Qxy,(x,y) = QQ[:x,:y]; Zxy,_ = ZZ[:u,:v]; julia> f = 11*(x^2/2 + ZZ(3)^50*x*y^5/7 + y^6/12); julia> @b $f*84 160.000 ns (4 allocs: 200 bytes) julia> @b change_base_ring($ZZ, $f*84) 1.559 μs (45 allocs: 1.633 KiB) julia> @b change_base_ring($ZZ, $f*84; parent = $Zxy) 1.002 μs (24 allocs: 808 bytes) julia> @b map_coefficients($ZZ, $f*84; parent = $Zxy) 996.680 ns (24 allocs: 808 bytes) After this patch: julia> Qxy,(x,y) = QQ[:x,:y]; Zxy,_ = ZZ[:u,:v]; julia> f = 11*(x^2/2 + ZZ(3)^50*x*y^5/7 + y^6/12); julia> @b $f*84 111.693 ns (4 allocs: 200 bytes) julia> @b change_base_ring($ZZ, $f*84) 733.806 ns (30 allocs: 1.227 KiB) julia> @b change_base_ring($ZZ, $f*84; parent = $Zxy) 242.117 ns (9 allocs: 392 bytes) julia> @b map_coefficients($ZZ, $f*84; parent = $Zxy) 249.607 ns (9 allocs: 392 bytes) As a bonus we now also have a special `mul!` method which is even faster but is not suitable for the faint of heart: julia> @b mul!($Zxy(), $f, 84) 129.041 ns (5 allocs: 192 bytes)
327751b
to
1f40354
Compare
parent::ZZMPolyRing = AbstractAlgebra._change_mpoly_ring(R, parent(f), cached)) | ||
@req isinteger(_content_ptr(f)) "input polynomial must have integral coefficients" | ||
@req ngens(parent) == ngens(Nemo.parent(f)) "parents must have matching numbers of generators" | ||
@req internal_ordering(parent) == internal_ordering(Nemo.parent(f)) "parents must have matching internal ordering" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this too strict? Maybe instead of erroring out when the orderings don't match we should fall back to the generic code ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do other methods of map_coefficients
handle this? The one below works for different internal orderings, so IMO this one should do so as well, e.g. by delegating to some more generic approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh apparently I can use sort_terms!
to solve this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(A test case should also be added to verify this works as desired)
This should be ready for review now |
parent::ZZMPolyRing = AbstractAlgebra._change_mpoly_ring(R, parent(f), cached)) | ||
@req isinteger(_content_ptr(f)) "input polynomial must have integral coefficients" | ||
@req ngens(parent) == ngens(Nemo.parent(f)) "parents must have matching numbers of generators" | ||
@req internal_ordering(parent) == internal_ordering(Nemo.parent(f)) "parents must have matching internal ordering" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do other methods of map_coefficients
handle this? The one below works for different internal orderings, so IMO this one should do so as well, e.g. by delegating to some more generic approach
return mul!(zero(parent), f, 1) | ||
end | ||
|
||
function map_coefficients(F::fpField, f::QQMPolyRingElem; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently this function is untested so a test should be added (TODO)
m = inv(d) | ||
ctx = MPolyBuildCtx(parent) | ||
for x in zip(coefficients(f), exponent_vectors(f)) | ||
el = numerator(x[1] * dF) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could optimize this further by using _zpoly_ptr
(to avoid converting the internal fmpz
coefficients into fmpq
, and then back via a multiplication)
# obviously this only works if the integers is a multiple of the denominator of the polynomial | ||
function mul!(a::ZZMPolyRingElem, b::QQMPolyRingElem, c::IntegerUnion) | ||
x = QQFieldElem() | ||
GC.@preserve a b x begin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GC.@preserve a b x begin | |
GC.@preserve b x begin |
Namely if the input polynomial is a
QQMPolyRingElem
and the transformation "function" isZZ
resp. afpField
.Before this patch:
After this patch:
As a bonus we now also have a special
mul!
method which is even faster but is not suitable for the faint of heart:This needs work, at least tests. But I didn't want to forget this, plus this way I can get feedback.