Skip to content
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

Jaa/is nilpotent #1974

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open

Conversation

JohnAAbbott
Copy link
Contributor

Usefully faster implementation of is_nilpotent(::ResElem), but it is longer...

Copy link

codecov bot commented Dec 13, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 87.98%. Comparing base (16fa2cf) to head (6c5912f).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1974   +/-   ##
=======================================
  Coverage   87.98%   87.98%           
=======================================
  Files          98       98           
  Lines       36450    36461   +11     
=======================================
+ Hits        32071    32082   +11     
  Misses       4379     4379           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -115,6 +115,8 @@ is_zero(a::QQFieldElemOrPtr) = is_zero(_num_ptr(a))

is_unit(a::QQFieldElem) = !iszero(a)

is_nilpotent(a::QQFieldElem) = iszero(a)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure we really need or want these methods here -- I would expect this to be handled by a generic method in AA, something like this:

function is_nilpotent(a::T) where {T <: RingElem}
  is_domain_type(parent_type(T)) && return izero(a)
  throw(NotImplementedError(:is_nilpotent, a))
end

In general I think it would be better to first have the generic code in AA ready. BTW you mentioned again during the call today the problem of dealing with infinite series -- so I'll also mention again that this is not necessary for now -- the above method takes care of it well enough for now.

So a first PR just adding e.g. that method and perhaps a few tests would already be a good start. Adding is_unit methods can then come in one more further PRs. And then once AA is ready and released we can add missing or optimized bits in Nemo.

@@ -20,6 +20,8 @@ base_ring(a::ZZModRing) = ZZ

parent(a::ZZModRingElem) = a.parent

is_domain_type(::Type{ZZModRingElem}) = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessary as we have this in AA:

# Type can only represent elements of domains
# false unless explicitly specified
is_domain_type(R::Type{T}) where T <: RingElem = false

g = gcd(r, m)
(g == m) && return true
(g == 1) && return false
m /= g
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
m /= g
m = divexact(m, g)

Since e.g. / is doing the wrong thing if T === Int:

julia> Int(2)/Int(3)
0.6666666666666666

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bother! I was hoping to do "in place" arithmetic with m /= g but I suspect that m = divexact(m,g) is not in place. Too bad, I guess. I'll check what the time penalty is...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m /= g is just syntactic sugar for m = m / g and does not work in place anyway.

We have divexact! for a few types to support in-place, but AFAIK this is still mostly in Nemo and and not yet generically implemented in AA. That could be subjective of a future PR. For now just use divexact ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: in AbstractAlgebra/src/Residue.jl near line 73 there is the function definition

lift(a::ResElem{Int}) = BigInt(data(a))

Why is the result cast to a BigInt? I had expected the result to be of type Int or maybe UInt; and if the result is to be cast to a "big integer" then wouldn't ZZRingElem be more natural (but then it seems that ZZRingElem is not visible inside AbstractAlgebra... sigh!)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

divexact was faster -- good! I shall replace the call to lift by a call to data so that the code actually does what the reader might reasonably expect. I shall also add an overflow test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed all the changes... waiting for GitHub to find my mistakes...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants