Skip to content

Take a repeated rational root out of a denominator all at once - #871

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
fix/repeated-rational-root-partial-fractions
Aug 10, 2026
Merged

Take a repeated rational root out of a denominator all at once#871
Rafael-SOWNet merged 1 commit into
masterfrom
fix/repeated-rational-root-partial-fractions

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Collaborator

TrySplitOffRationalRoot divided one factor of (x - r) out of the denominator and gave up if the quotient still vanished there — the code said so plainly:

var atRoot = Evaluate(q, root);
if (atRoot.IsZero)
    continue;                       // repeated root, see above

So a denominator whose only rational root is a repeated one was never split at all. 1/(x^4 + x^2) had no antiderivative, though x^4 + x^2 is x^2(x^2 + 1) and the decomposition is just 1/x^2 - 1/(x^2 + 1).

The fix

A root of multiplicity m contributes a term over the m-th power rather than the first. So divide the root out as many times as it goes, and use the power that came out. What was already there is this with m fixed at 1 — one degree still comes off the denominator each step, so it terminates for exactly the reason the single-root case did.

before after
1 / (x^4 + x^2) no antiderivative solved
1 / (x^3 + x^2) no antiderivative solved
1 / (x^2 * (x + 1)) no antiderivative solved
1 / ((x - 1)^2 * (x + 2)) no antiderivative solved
1 / ((x + 1)^3 * (x - 2)) no antiderivative solved
x / ((x - 1)^2 * (x^2 + 1)) no antiderivative solved
(x + 1) / (x^3 - x^2) no antiderivative solved

Every one is checked by differentiating the answer back and comparing at points, so a wrong antiderivative cannot pass as a solved one. That is the existing AssertIsAntiderivative helper in the file, reused rather than reinvented.

How it was found

Not by reading the code. Running the casbench corpus against master left x^2/(x^4 + 1) unsolved, and while probing what was and was not reachable around it, 1/(x^4 + x^2) turned up — a denominator that factors over Q and still had no answer. The corpus had no repeated-root case at all, which is why this went unnoticed; four have been added.

The boundary, asserted rather than implied

Denominators with no rational root stay out of reach: x^4 + 1 is irreducible over Q and only factors once real coefficients are allowed, which needs partial fractions with algebraic coefficients. There is now a test asserting those are declined, so the edge is visible in the suite instead of inferred from an absence.

Worth recording: the pieces past that edge already work. (x + 1)/(x^2 - sqrt(2)*x + 1) and 1/(x^2 - sqrt(2)*x + 1) both integrate in 2 ms, so for x^4 + 1 the only missing step is the factorisation itself.

Verification

  • 6118 C# tests pass, 0 failed — 9 new
  • 130 F# wrapper tests pass
  • propcheck: 1340 property checks, 0 failures — unchanged
  • casbench: 117/119 of the problems with an elementary answer, up from 113/115 with the four new cases

🤖 Generated with Claude Code

TrySplitOffRationalRoot divided one factor of (x - r) out of the denominator and gave up
if the quotient still vanished there, with the comment "repeated root". So a denominator
whose only rational root is a repeated one was never split at all: 1/(x^4 + x^2) had no
antiderivative, though x^4 + x^2 is x^2(x^2 + 1) and the decomposition is 1/x^2 minus
1/(x^2 + 1).

A root of multiplicity m contributes a term over the m-th power rather than the first, so
the fix is to divide the root out as many times as it goes and use the power that came out.
What was already there is this with m fixed at 1. One degree still comes off the denominator
each step, so it terminates for the reason the single-root case did.

    1 / (x^4 + x^2)                 no antiderivative  ->  solved
    1 / (x^3 + x^2)                 no antiderivative  ->  solved
    1 / ((x - 1)^2 * (x + 2))       no antiderivative  ->  solved
    1 / ((x + 1)^3 * (x - 2))       no antiderivative  ->  solved
    x / ((x - 1)^2 * (x^2 + 1))     no antiderivative  ->  solved
    (x + 1) / (x^3 - x^2)           no antiderivative  ->  solved

Every one checked by differentiating the answer back and comparing at points, so a wrong
antiderivative cannot pass as a solved one. The single-root cases that worked before still
do, and propcheck is unchanged at 1340 checks with no failures.

Denominators with no rational root at all remain out of reach -- x^4 + 1 is irreducible
over Q and only factors once real coefficients are allowed. There is a test asserting that
too, so the boundary is visible rather than inferred from an absence.

Verified: 6118 C# tests and 130 F# tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Rafael-SOWNet
Rafael-SOWNet merged commit 55c74c4 into master Aug 10, 2026
25 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the fix/repeated-rational-root-partial-fractions branch August 10, 2026 23:35
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.

1 participant