Skip to content

Integrate a quotient whose numerator is not constant (#233) - #681

Merged
Happypig375 merged 1 commit into
ASC-Community:masterfrom
Rafael-SOWNet:feat/rational-integration
Aug 4, 2026
Merged

Happypig375 merged 1 commit into
ASC-Community:masterfrom
Rafael-SOWNet:feat/rational-integration

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Part of #233 (the partial-fractioning line), and a gap next to it.

What was missing

The table matched k/(ax^2 + bx + c) only when k did not mention x. Anything with a variable on top fell through every solver:

"x / (x ^ 2 + 2 * x + 5)".ToEntity().Integrate("x")      // integral(x / (x^2 + 2x + 5), x)
"(x + 3) / (x ^ 2 + 3 * x + 2)".ToEntity().Integrate("x")  // integral(...)
"x / (x + 1)".ToEntity().Integrate("x")                  // integral(...)

What this adds

A linear numerator over a quadratic. px + q 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 ln|ax^2 + bx + c| and the second is the constant-numerator case that IntegrateRationalQuadratic already handles, including its split on the sign of the discriminant. So this is only the rewrite — no new closed forms and no new cases to get wrong.

A linear numerator over a linear denominator, which is the same rewrite one degree down: the quotient is 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 whose quadratic term vanishes falls through to the linear arm rather than being divided by zero, and there is a test for that.

1/cos(u)^2 and 1/sin(u)^2. Written that way at least as often as sec(u)^2 and csc(u)^2, and none of the four shapes was recognised. sec and csc themselves already were.

Verification

  • 21 new tests. Each answer is checked by differentiating it back and comparing against the integrand at points inside its domain, so a wrong closed form fails rather than an unexpected spelling of a right one.
  • 3901 unit tests, 0 failed. 127 F# tests, 0 failed. Both target frameworks build.
  • Solver corpus 88/117 -> 91/117, still 0 wrong, 0 error, 0 timeout. int:table and int:rational-quadratic reach 100%; int:partial-fractions goes from 2 out of 5 to 3.
  • A property checker over 151 expressions (1320 checks) is clean.

Not covered

x^2/(x^4 + 1) and 1/(x^3 + 1) — the two remaining int:partial-fractions entries — still return unevaluated. Both need the denominator factored before the fractions can be split, and x^4 + 1 factors only over the irrationals. That is a separate piece of work.

@codecov-commenter

codecov-commenter commented Aug 3, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.43%. Comparing base (90c00a8) to head (c15cf90).
⚠️ Report is 56 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #681      +/-   ##
==========================================
- Coverage   80.99%   80.43%   -0.57%     
==========================================
  Files         155      156       +1     
  Lines       13687    12934     -753     
  Branches     1957     2126     +169     
==========================================
- Hits        11086    10403     -683     
+ Misses       1990     1923      -67     
+ Partials      611      608       -3     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.
@Rafael-SOWNet
Rafael-SOWNet force-pushed the feat/rational-integration branch from f4d67d6 to c15cf90 Compare August 4, 2026 07:21
@Rafael-SOWNet

Copy link
Copy Markdown
Member Author

Rebased onto master now that #675 has landed. The two touch the same switch in IntegralPatterns.cs; the arms are disjoint and both are kept. Order was checked — TryGetPolyQuadratic and TryGetPolyLinear both fail on a root, so the general quotient arms added here cannot steal the radical cases #675 added above them. 4017 tests, none failing.

@Happypig375
Happypig375 merged commit 47ba93b into ASC-Community:master Aug 4, 2026
24 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the feat/rational-integration branch August 4, 2026 20:48
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