Skip to content

"fraction" fixes - #4462

Open
pzinn wants to merge 5 commits into
Macaulay2:developmentfrom
pzinn:frac
Open

"fraction" fixes#4462
pzinn wants to merge 5 commits into
Macaulay2:developmentfrom
pzinn:frac

Conversation

@pzinn

@pzinn pzinn commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

This fixes two somewhat related bugs in the handling of fractions:

R=QQ[a,b]/(a*b-1)
1/a -- before: fails to realise it's b, after: gives b
lift(oo,R) -- before: fails to lift, after: lifts

basically, M2 did not correctly simplify the denominator when it was a unit, leading to lots of oddities (this is only the simplest example). now it does a much cleaner job.

AI disclosure

I formulated the fixes, but codex helped with the c++.

@pzinn pzinn changed the title "frac" fixes "fraction" fixes Jul 2, 2026
@d-torrance d-torrance added the Engine Macaulay2/e label Jul 2, 2026

@d-torrance d-torrance left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed with @local-ring. Just a couple questions and comments

Comment thread M2/Macaulay2/e/rings/frac.cpp
Comment thread M2/Macaulay2/e/rings/frac.cpp
Comment thread M2/Macaulay2/tests/normal/frac.m2
@d-torrance d-torrance linked an issue Jul 19, 2026 that may be closed by this pull request

@d-torrance d-torrance left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for making the changes! I have a few other suggestions. (Thanks to Claude 🤖 for suggesting a few things, too.)

gens gb Iloc
///

TEST /// -- normalize ambient-unit denominators

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This test never gets run because of the end on line 875. Would you move it up?

(While you're at it, would you mind moving up the promote/lift test just underneath it? I fell into the same trap in #4204 lol.)

// TODO uniformise behaviour of invert for noninvertible elements
if (dynamic_cast<const PolyRingQuotient *>(R_) != nullptr)
{
denom_inverse = R_->invert(f->denom); // for quotient rings, don't call is_unit since it calls invert internally

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

With this, we can run into #3973, where we didn't before:

i1 : K = toField(QQ[a]/(a^2 - 2))

o1 = K

o1 : PolynomialRing

i2 : B = K[t]/(t^2 - a)

o2 = B

o2 : QuotientRing

i3 : 1/(t + 1)
--internal error: ring element gcd computation failed
Aborted (core dumped)

In 1.26.06, we get:

i3 : 1/(t + 1)

       1
o3 = -----
     t + 1

o3 : frac B

const RingElement *b = RingElement::make_raw(R_, y);
const RingElement *c = rawGCDRingElement(a, b, nullptr, false);
if (!c) return;
if (!R_->is_equal(y, R_->one()))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If $y = 1$, then we would have already returned a few lines ago (since simplify_unit_denominator(f) would have returned true, so this if statement isn't necessary. (And the same comment for the local ring version below.)


ring_elem denom_inverse;
// TODO uniformise behaviour of invert for noninvertible elements
if (dynamic_cast<const PolyRingQuotient *>(R_) != nullptr)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think R_->is_quotient_ring() would be clearer

if (dynamic_cast<const PolyRingQuotient *>(R_) != nullptr)
{
denom_inverse = R_->invert(f->denom); // for quotient rings, don't call is_unit since it calls invert internally
if (R_->is_zero(denom_inverse)) return false; // for non invertible elements, returns zero denominator

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What does "returns zero denominator" mean in this comment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Engine Macaulay2/e

Projects

None yet

Development

Successfully merging this pull request may close these issues.

error multiplying matrices with entries in fraction field

2 participants