Issue in Polynomial Modulo

122 views
Skip to first unread message

Taylor Huang

unread,
Oct 5, 2025, 8:11:55 AM (7 days ago) Oct 5
to sage-devel
Hi all,

Cutting to the chase, I realized that the modulo operator "%" is un-naturally defined to be constant-zero in the fraction field of polynomials. This has caused the following issue.

See the following minimal code on the online Sage server: Sage Cell Server

In this example, we are doing 1 modulo x+1, which supposedly should give us 1 as output. However, since the datatype of x+1 is rational polynomial, it produces 0 as output.

I imagine there are two ways that may potentially solve this issue:
(1) Disgard the modulo operator % for fraction field! In the mathematical sense there is no interesting modulo (other than producing zero) for fraction field anyway, so such an operator seems more confusing than helpful. Removing % from fraction field should also cause the triggering of coersion from rational polynomial to a polynomial in the above example.
(2) Perform the modulo only on the integral ideal. Upon each time we compute f%g in a fraction field, we can derive its ring of integer O, and, return a representative in the co-set f + g*O. In the above example, this should also return the representative 1.

Best,
Yu-Hsuan (Taylor)

Grégory Vanuxem

unread,
Oct 6, 2025, 2:21:54 PM (6 days ago) Oct 6
to sage-...@googlegroups.com
Thas't normal. Corece it yourself.
> --
> You received this message because you are subscribed to the Google Groups "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/sage-devel/56a6410d-3644-4b7a-9181-d0911d1dee17n%40googlegroups.com.

Taylor Huang

unread,
Oct 6, 2025, 3:27:28 PM (6 days ago) Oct 6
to sage-devel
Hi, I don't think it's normal in a computer algebra system that 1%((x^2-1)/(x-1)) equals zero. It is a mal-design, if not a bug.
g.va...@gmail.com 在 2025年10月6日 星期一晚上8:21:54 [UTC+2] 的信中寫道:

Nils Bruin

unread,
Oct 6, 2025, 3:39:29 PM (6 days ago) Oct 6
to sage-devel
This question was also posed on sage-support. Probably the most important thing is that x = y*(x//y) + (x%y) to maintain consistency. 

Presently that actually fails in QQ, because there is a work-around there to make "%" something else than just constant 0:

3*QQ(2)//QQ(3)+(QQ(2)%QQ(3))

There are other side-effects of the way in which the work-around on QQ.__mod__ is implemented that lead to nonsensical  results; see the comment on the sage-support threat: https://groups.google.com/g/sage-support/c/uuVTX2s7Xvk

So, clearly: having "%" just return 0 on fields is not useful in itself. However, it does provide consistency between operators, which can mean that certain generically implemented algorithms can be applied unchanged between ZZ and QQ, for instance.

If we value "%" being a little bit more useful even at the cost of breaking consistency then we should take a careful look at how to do that while avoiding the problems that are currently arising for QQ.__mod__ . It would be nice for Z subset QQ and F[x] subset F(x) to be in step on this, but then improve the QQ case in the process.

It is the case that the difference between ZZ and QQ is important in sage and that users who are running into problems with them not being separated appropriately probably will run into problems further down the line anyway, even if this particular hurdle is modified. Same for F[x] and F(x).

Grégory Vanuxem

unread,
Oct 6, 2025, 4:21:12 PM (6 days ago) Oct 6
to sage-...@googlegroups.com
I do not understand this question. It's a field. So everything is good. 


Coerce it first 

Nils Bruin

unread,
Oct 6, 2025, 4:35:24 PM (6 days ago) Oct 6
to sage-devel
On Monday, 6 October 2025 at 13:21:12 UTC-7 g.va...@gmail.com wrote:
I do not understand this question. It's a field. So everything is good. 

I think the observation is that if a%b is predictably 0 then why have the operator at all? 

There are also cases where the coercion framework gets in the way. For instance

with

R.<x> = QQ[]
((x+1)/(x-2)) % (x-1)
 
could just work in a well-defined way, since the denominator is coprime to the modulus. But it doesn't, because in this case the coercion framework gets its hands on the modulus first and coerces it into the fraction field.

In the case of integers and rationals, this is caught by a custom QQ.__mod__ that tries to recover an integer from the modulus:

QQ(2/3) % 5

but it is a little too greedy in doing so, so we get some nonsensical things back as well:

QQ(2/3) % GF(7)(12)

I think the latter is actually worse than QQ(2/3) % QQ(5) returning an error or 0, so there is definitely a bug report hiding here somewhere. Whether it's the behaviour originally pointed out is a matter to analyze elsewhere.

Perhaps a better way to explain this to the coercion framework is to have a partial "right-action" of ZZ on QQ through % (which is going to be just some partial map from QQ x ZZ -> QQ; no nice properties otherwise). These cases show that just treating "%" as a binary operator where one should strive for common parents is perhaps not the best fit.

Grégory Vanuxem

unread,
Oct 7, 2025, 8:05:31 AM (5 days ago) Oct 7
to sage-...@googlegroups.com
Hello, 


Le lun. 6 oct. 2025, 22:35, Nils Bruin <nbr...@sfu.ca> a écrit :
On Monday, 6 October 2025 at 13:21:12 UTC-7 g.va...@gmail.com wrote:
I do not understand this question. It's a field. So everything is good. 

I think the observation is that if a%b is predictably 0 then why have the operator at all?

Inheritance I think

Greg

There are also cases where the coercion framework gets in the way. For instance

with

R.<x> = QQ[]
((x+1)/(x-2)) % (x-1)
 
could just work in a well-defined way, since the denominator is coprime to the modulus. But it doesn't, because in this case the coercion framework gets its hands on the modulus first and coerces it into the fraction field.

In the case of integers and rationals, this is caught by a custom QQ.__mod__ that tries to recover an integer from the modulus:

QQ(2/3) % 5

but it is a little too greedy in doing so, so we get some nonsensical things back as well:

QQ(2/3) % GF(7)(12)

I think the latter is actually worse than QQ(2/3) % QQ(5) returning an error or 0, so there is definitely a bug report hiding here somewhere. Whether it's the behaviour originally pointed out is a matter to analyze elsewhere.

Perhaps a better way to explain this to the coercion framework is to have a partial "right-action" of ZZ on QQ through % (which is going to be just some partial map from QQ x ZZ -> QQ; no nice properties otherwise). These cases show that just treating "%" as a binary operator where one should strive for common parents is perhaps not the best fit.

--
You received this message because you are subscribed to the Google Groups "sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages