Skip to content

A fractional power, and the tangent, are substitutions (#233) - #1146

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
integrate-tangent-substitution
Sep 2, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
integrate-tangent-substitution

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Two substitutions, in one PR because neither reaches sqrt(tan(x)) without the other.
That integral is the last of the five #233 lists, and the one it calls "very painful,
requires different solvers"
— which it is. Three capabilities in a row:

int sqrt(tan(x)) dx
  u = tan(x),  dx = du/(1 + u^2)   ->  int sqrt(u)/(1 + u^2) du
  t = sqrt(u), a fractional power  ->  int 2t^2/(1 + t^4) dt
  1 + t^4 factored over the reals  ->  logarithms and arctangents

Take any one away and it comes back unevaluated. The third landed in #1145; the first two
are here.

The corpus reached 40 of 40

The gate's one unsolved problem was int:hard — and int:hard is sqrt(tan(x)),
chosen for that list as the standing example of an integral out of reach:

new("int:hard", Op.Integrate, "sqrt(tan(x))", Verdict.Unsolved),

It now solves. The gate reached that verdict independently of anything I wrote, by
differentiating the answer back. Baseline refreshed the way its own failure message
directs; Corpus.cs and corpus-baseline.tsv are both in the diff.

The fractional power

A power substitution rewrites the other powers of the variable into powers of itself: for
u = x^r the identity is x^n = u^(n/r), applied wherever n/r is a whole number. A
whole r reaches only the powers it divides, which is all this did before. An r of
1/2 reaches every one of them — including the bare x, which a whole r never can
— so int sqrt(x)/(1 + x^2) becomes int 2u^2/(1 + u^4) du.

New with it: 1/(1 + sqrt(x)), 1/(sqrt(x) * (1 + x)), 1/(sqrt(x) * (1 + x^2)),
1/(sqrt(x) + x).

The rewrite takes two passes, and that is not tidiness. The tree is rewritten from the
leaves up, so in one pass the x inside sqrt(x) is reached before the sqrt(x) node is
— and with u = sqrt(x) that turns it into sqrt(u^2) rather than u, leaving an
integrand free of x and no more integrable than it started. Written powers first, a
leftover bare x second.

The tangent

An integrand that is a function of tan(x) and of nothing else becomes a rational function
under u = tan(x), with dx as du/(1 + u^2). The test is the rewrite itself: replace
every tan(x) and see whether an x survives. tan(x) + x keeps one and is declined —
correctly; it is answered, but by linearity over the sum.

Why it is a step of its own rather than a candidate for the general substitution. The
general one divides the integrand by du/dx and asks what is left, which works while the
substitution survives the division. Here it does not: sqrt(tan(x)) over the derivative of
sqrt(tan(x)) is 2 tan(x) cos(x)^2, which is sin(2x) and is simplified to it — a
correct answer to a question that has stopped being about the tangent. Rewriting asks a
different question and does not lose the shape.

The rule for the tangent itself is reached first and still wins: int tan(x) is
-ln(cos(x)) + C, not the longer thing this would produce. Pinned by a test.

What is still declined, and why

Recorded in the tests rather than left to be inferred from an absence. Each is declined by
what the rewrite hands on, not by the rewrite:

integrand becomes why
sqrt(cotan(x)) — cotan is its own node, not a reciprocal of the tangent, so this never starts
tan(x)^2, tan(x)^3 u^2/(1+u^2), u^3/(1+u^2) improper; dividing that out is not something the rational integrator does
1/(1 + tan(x)^2) 1/(1+u^2)^2 repeated irreducible quadratic
sqrt(x)/(1 + x^4) 2u^2/(1+u^8) degree eight, neither factorable over Q nor biquadratic
sqrt(x)/(x + 1) 2u^2/(1+u^2) improper

The improper-fraction row covers three of those and is the obvious next piece of work —
int tan(x)^2 is tan(x) - x, and it looking out of reach while sqrt(tan(x)) works is
the wrong way round.

Verification

Full suite 9341 passed, 0 failed, 14 skipped. Corpus 40 solved of 40.

Every new answer is checked by differentiating it back and comparing at sampled points,
through helpers that first assert the antiderivative contains no integral( — without that
guard the check passes vacuously, since d/dx of an unevaluated integral(f, x) is f.
Points for the tangent cases stay inside one branch, on (0, pi/2), where sqrt(tan(x))
is real.

BREAKING-CHANGES.md carries the entry, and the #1145 entry is corrected in place where it
said sqrt(tan(x)) was not answered.

On closing #233

All five integrals the issue lists are now solved. I have not written a closing keyword:
its title asks for more integral solvers generally, which is broader than the five, so that
is the maintainer's call rather than a merge side effect.

Part of #233.

Two substitutions, in one change because neither reaches `sqrt(tan(x))`
without the other. That integral is the last of the five #233 lists, and the
one it calls "very painful, requires different solvers", which it is:

  int sqrt(tan(x)) dx
    u = tan(x),  dx = du/(1 + u^2)   ->  int sqrt(u)/(1 + u^2) du
    t = sqrt(u), a fractional power  ->  int 2t^2/(1 + t^4) dt
    1 + t^4 factored over the reals  ->  logarithms and arctangents

Take any one of the three away and it comes back unevaluated. The third
landed in #1145.

The fractional power. A power substitution rewrites the other powers of the
variable into powers of itself: for `u = x^r` the identity is `x^n = u^(n/r)`,
applied wherever `n/r` is whole. A whole `r` reaches only the powers it
divides, which is all this did before; an `r` of `1/2` reaches every one of
them, the bare `x` included, which a whole `r` never can. So
`int sqrt(x)/(1 + x^2)` becomes `int 2u^2/(1 + u^4) du`, and
`1/(1 + sqrt(x))`, `1/(sqrt(x) * (1 + x))`, `1/(sqrt(x) * (1 + x^2))` and
`1/(sqrt(x) + x)` come with it.

The rewrite takes two passes, written powers first and a leftover bare `x`
second, because the tree is rewritten from the leaves up: in one pass the `x`
inside `sqrt(x)` is reached before the `sqrt(x)` node is, and `u = sqrt(x)`
turns it into `sqrt(u^2)` rather than `u` -- an integrand free of `x` and no
more integrable than it started.

The tangent. An integrand that is a function of `tan(x)` and of nothing else
becomes a rational function under `u = tan(x)`, with `dx` as `du/(1 + u^2)`.
The test is the rewrite itself: replace every `tan(x)` and see whether an `x`
survives.

It is a step of its own rather than a candidate for the general substitution.
The general one divides by `du/dx` and asks what is left, which works while
the substitution survives the division; here it does not, since
`sqrt(tan(x))` over the derivative of `sqrt(tan(x))` is `2 tan(x) cos(x)^2`,
which is `sin(2x)` and is simplified to it -- a correct answer to a question
that has stopped being about the tangent.

The corpus gate now reads 40 solved of 40. Its one unsolved problem was
`int:hard`, which is `sqrt(tan(x))`, chosen for that list as the standing
example of an integral out of reach; the gate reached the verdict by
differentiating the answer back rather than by comparing it with anything.
Baseline refreshed as its message directs.

What is still declined is recorded in the tests rather than left to be
inferred: `cotan` is its own node and not a reciprocal of the tangent, so
`sqrt(cotan(x))` never starts; `tan(x)^2` and `tan(x)^3` become improper
fractions, which the rational integrator does not divide out;
`1/(1 + tan(x)^2)` becomes a repeated irreducible quadratic; and
`sqrt(x)/(1 + x^4)` becomes a degree-eight denominator that is neither
factorable over the rationals nor a biquadratic.

All five integrals the issue lists are now solved. Not closing it: its title
asks for more integral solvers generally, and that is broader than the five.

Part of #233.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
@Rafael-SOWNet
Rafael-SOWNet merged commit 6eba229 into master Sep 2, 2026
31 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the integrate-tangent-substitution branch September 2, 2026 17:31
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