The special functions are substitutions, and powers of one base gather across the bar - #1638
Merged
Merged
Conversation
…r across the bar None of the nine special functions was a candidate for the substitution u = g(x), so an integrand that is a power of one beside its derivative had no route: e^(c - b^2 x^2) erf(b x)^n, Ei(b x) e^(b x)/x and Si(b x) sin(b x)/x were left unevaluated. Each is a candidate now, as the logarithm is, and its elementary derivative is the differential: e^(c - b^2 x^2) erf(b x) is sqrt(pi) e^c/(2b) u du under u = erf(b x). A constant in the exponent still stopped it: divided by du/dx, e^(c - b^2 x^2) over the e^(-(b x)^2) of the derivative is e^c, and the quotient is simplified only a level, so the x in it was left and the candidate refused, where e^(-b^2 x^2) erf(b x) was answered. The divisor's factors are spread to the power -1 now, the powers of one base gathered, and the result simplified a level, which is where e^(c - (b x)^2 + (b x)^2) becomes e^c. Both only where they can answer. A special function is offered only where its derivative can be the differential: an exponential of a quadratic for the error functions, a logarithm below the bar for li, and something in x below the bar for the others, whose derivatives divide by their argument. Offered beside anything, x cosh(a + b x) Shi(a + b x) went from a second to ten, simplifying quotients of exponentials that were never going to lose their x. And the powers are gathered only for a special-function candidate: done for every candidate that left an x, the exponentials of 1/((c + d x)^3 (a + a tanh(e + f x))) were gathered and simplified for each one, and seven declines of a third of a second became timeouts. The nine are listed once, in IsASpecialFunction, where the solver listed them three times. Rubi's family 8, #1501's tranche of 420: 258 -> 296 solved, 0 wrong, against master at ad05a79. Nothing without a special function moves. The independent suites are 1753 of 1814 on both; families 1 to 7 at five problems a file are 809 and 811 of 912 run side by side, and the two that moved, 3.2.1 #12 and 6.7.1 #180, are answered alone by both, in 18 and 22 s: master's timeouts there were the load. 0 wrong everywhere. SpecialFunctionSubstitutionTest has nine rows from Rubi's 8.1, 8.3 and 8.4, each differentiated back with its parameters pinned. Part of #1501. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rafael-SOWNet
added a commit
that referenced
this pull request
Oct 1, 2026
…, and so is its square (#1639) x Si(b x) sin(b x) was left unevaluated where Si(b x) sin(b x) was not. By parts it is Si(b x) against x sin(b x), and the integral of that factor was taken with parts off, which x sin(b x) needs. Beside a special function of a linear argument, a polynomial times something else is integrated by the polynomial's parts now, which end in as many steps as its degree, and what is left, the special function's derivative times polynomials and elementary functions, is given parts in turn. A square of a special function of b x is two rounds of parts, and the remainder of the first comes back as one product over a sum, (b x Ei(b x) - e^(b x)) e^(b x)/(b x) for Ei(b x)^2, that no rule reads whole, where its terms e^(b x) Ei(b x) and e^(2 b x)/(b x) are each answered when asked. So where the remainder after a special function is not answered, its terms are asked one at a time: the ordinary way first, and then as questions of their own. That is only at the top, where such asking reaches. It is done once, since a term asked so is at the top itself, and the same asking inside it lifted the search again with the depth reset each time: together with a rule that wrote a + b x as t, x Ei(a + b x)^2 grew a test host to twelve gigabytes. A decline that the once-only flag caused is not cached (Integration.DeclinedForItsScope), as a decline that ran out of depth is not. It covers a multiple of x only: of a + b x the remainder divides by the linear, its terms are the exponentials a hyperbolic function is written as, and the decline of x Shi(a + b x)^2 went from a second to past twenty asking them. Rubi's family 8, #1501's tranche of 420: 296 -> 367 solved, 0 wrong, 0 timeout, against master with #1638. The 71 gains are 0 of 71 on master and 71 of 71 here run alone, and the 53 still declined take 103 s against 117 s together, median ratio 1.00, the slowest change being x^2 Ci(a + b x) cos(a + b x), 0.25 s to 2 s. Nothing else moves: the independent suites are 1756 of 1814 and families 1 to 7 at five a file 813 of 912 on both, 0 wrong everywhere, and what is declined in both costs what it did (11.9 s against 11.5 s, 98.1 s against 98.9 s). The unit tests pass, 14,247, and the performance gate passes on ee5cb79e, whose tree is this commit's but for this entry in BREAKING-CHANGES.md: allocation is what the baseline says on all 19 gated benchmarks. SpecialFunctionsByPartsTest: six rows beside a power and the elementary factor of the derivative, eleven squares, each differentiated back with its parameters pinned. Part of #1501. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
None of the nine special functions was a candidate for the substitution
u = g(x). So an integrand that is a power of one beside its derivative had no route, and these were left unevaluated:e^(c - b^2 x^2) erf(b x)^nEi(b x) e^(b x)/xSi(b x) sin(b x)/xEach special function is a candidate now, as the logarithm is, and its elementary derivative is the differential:
e^(c - b^2 x^2) erf(b x)issqrt(pi) e^c/(2b) u duunderu = erf(b x).du/dx,e^(c - b^2 x^2)over thee^(-(b x)^2)of the derivative ise^c. The quotient was simplified only a level, so thexin it was left and the candidate refused, wheree^(-b^2 x^2) erf(b x)was answered. The divisor's factors are now spread to the power -1, the powers of one base gathered, and the result simplified a level, which is wheree^(c - (b x)^2 + (b x)^2)becomese^c.li. For the others, whose derivatives divide by their argument, it means something inxbelow the bar. Offered beside anything,x cosh(a + b x) Shi(a + b x)went from a second to ten, simplifying quotients of exponentials that were never going to lose theirx.x, it gathered and simplified the exponentials of1/((c + d x)^3 (a + a tanh(e + f x)))once for each candidate. Seven declines of a third of a second became timeouts.The nine functions were listed three times in the solver, so they are listed once now, in
IsASpecialFunction.Measured
"e^(c - b^2*x^2)*erf(b*x)".Integrate("x")UnrecognizedFunctionParseException: there is no functionerfe ^ c * pi ^ (1/2) * erf(b * x) ^ 2 / 2 / (2 * b) + C"e^(b*x)*Ei(b*x)/x".Integrate("x")Ei * e ^ (b * x) + C, withEia variableEi(b * x) ^ 2 / 2 + C"Si(b*x)*sin(b*x)/x".Integrate("x")Si * -cos(b * x) + C, withSia variableSi(b * x) ^ 2 / 2 + Cad05a79b.fd1a4416, which is this change onad05a79b. Allocation matches the baseline on all 19 gated benchmarks.SpecialFunctionSubstitutionTesthas nine rows from Rubi's 8.1, 8.3 and 8.4, each differentiated back with its parameters pinned.Part of #1501.
🤖 Generated with Claude Code