Repository navigation
Split a rational function at a rational root of its denominator (#233) - #690
Merged
Happypig375 merged 2 commits intoAug 4, 2026
Merged
Conversation
The table matched k/(ax^2 + bx + c) only when k did not mention x, so anything with a variable on top had no antiderivative at all: int x / (x^2 + 2x + 5) int (x + 3) / (x^2 + 3x + 2) int x / (x + 1) A linear numerator is a multiple of the denominator's derivative plus a constant: px + q = (p/2a)(2ax + b) + (q - pb/2a). The first part integrates to a logarithm and the second is the constant-numerator case that was already there, so this only needs the rewrite. The same rewrite one degree down turns (px + q)/(bx + c) into the constant p/b plus a remainder over the divisor. Both are guarded on the leading coefficient being a non-zero number, since the rewrite divides by it. A quadratic denominator with a vanishing quadratic term falls through to the linear arm rather than being divided by zero. Also 1/cos(u)^2 and 1/sin(u)^2, which are written that way at least as often as sec(u)^2 and csc(u)^2, and none of the four shapes was recognised. Corpus 88/117 -> 91/117: int:table and int:rational-quadratic reach 100%, and int:partial-fractions goes from 2 out of 5 to 3. 3901 unit tests and 127 F# tests pass, no wrong answers in the corpus, and the property checker's 1320 checks are clean. x^2/(x^4 + 1) and 1/(x^3 + 1) are still out of reach: both need the denominator factored first, which is a different piece of work.
A linear or quadratic denominator was answered in one piece, but nothing read anything above that, so 1/(x^3 + 1) had no antiderivative at all. It is on the list of what is missing in #233. The decomposition is done a step at a time rather than in full, because a step is all that is needed: what is left over is a smaller problem of the same kind, and by the time its denominator is a quadratic there is already a rule for it. 1/(x^3 + 1) splits at the root -1 into (1/3)/(x + 1) and (2 - x)/(3(x^2 - x + 1)), and the second is a linear numerator over a quadratic, which the previous commit reads as it stands. Each step takes a degree off the denominator, so it ends. The coefficient is Heaviside's -- at the root every other term of the decomposition is finite, so A = N(r)/Q(r) -- and what is left, N - A*Q, then has that root by construction and divides exactly. All of it on the exact ratios, reusing the rational root search already here for factoring. Rational roots only, and simple ones. A denominator with no rational root, such as x^4 + 1, and one whose root repeats, which would need a term over the square as well, are both left unevaluated rather than answered wrongly. A denominator below degree three is left to the rules that answer it in one piece. Ten integrals gained, each checked by differentiating back: 1/(x^3 + 1), x/(x^3 + 1), 1/(x^3 - x), 1/(x^3 + x), 1/(x^4 - 1), x/(x^4 - 1), (x^2 + 1)/(x^3 - x), 1/((x - 1)(x - 2)(x - 3)) whether written factored or multiplied out, and (x + 1)/(x^3 - x^2 - 2x). 21 tests, 10 of which fail without the change. 4038 in all, 127 F#, corpus 105/117 with the partial fraction category at 80% from 60% and nothing wrong, in error or timing out. 1320 property checks.
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #690 +/- ##
==========================================
- Coverage 80.99% 80.57% -0.42%
==========================================
Files 155 156 +1
Lines 13687 13006 -681
Branches 1957 2141 +184
==========================================
- Hits 11086 10480 -606
+ Misses 1990 1920 -70
+ Partials 611 606 -5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on #681 — the first of the two commits is that PR, and the diff will shrink to the second once it lands.
Named in #233's own list of what is missing.
A linear or quadratic denominator was answered in one piece, but nothing read anything above that.
A step at a time, not the whole decomposition
A step is all that is needed: what is left over is a smaller problem of the same kind, and by the time its denominator is a quadratic there is already a rule for it.
and the second of those is a linear numerator over a quadratic, which #681 reads as it stands. Each step takes a degree off the denominator, so it ends.
The coefficient is Heaviside's — at the root every other term of the decomposition is finite, so
A = N(r)/Q(r)— and what is left,N − A·Q, then has that root by construction and divides exactly. All of it on exact ratios, reusing the rational-root search already here for factoring.What it gains
Ten integrals, each checked by differentiating the answer back and comparing at points:
1/(x³+1),x/(x³+1)1/(x³−x),1/(x³+x)1/(x⁴−1),x/(x⁴−1)(x²+1)/(x³−x)1/((x−1)(x−2)(x−3))(x+1)/(x³−x²−2x)What it declines
Rational roots only, and simple ones:
x²/(x⁴+1)is left unevaluated.x⁴+1factors only over the irrationals.(x − r)²as well, which this does not produce.All four are left unevaluated rather than answered wrongly, and the first two are pinned as such.
Verification
21 tests, 10 of which fail without the change. 4038 unit tests and 127 F# tests on both target frameworks, none failing. 117-problem self-verifying corpus at 105/117 —
int:partial-fractionsgoes from 60% to 80% — with nothing wrong, in error or timing out. 1320 property checks over 151 expressions, none failing.