Skip to content

A power of a quotient is split only where that keeps its branch - #1755

Merged
Rafael-SOWNet merged 3 commits into
masterfrom
a-power-of-a-reciprocal-keeps-its-branch
Oct 4, 2026
Merged

Rafael-SOWNet merged 3 commits into
masterfrom
a-power-of-a-reciprocal-keeps-its-branch

Conversation

@Rafael-SOWNet

@Rafael-SOWNet Rafael-SOWNet commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

Closes #1734.

Simplify wrote (c/a)^d * a^e as c^d * a^(e - d) for every numeric d, which splits the power of the quotient as (c/a)^d = c^d a^(-d). That holds for a whole d, and for a rational d with an odd denominator over a positive c, where a negative base takes its real root. For any other d it moves the branch wherever a is negative: (1/(-2))^(1/2) is 0.707i and (-2)^(-1/2) is -0.707i. 2.5.0 does the same:

expression at its value Simplify on 2.5.0 and master f18a7d2b this
sqrt(x)*sqrt(1/x) x = -2 -1 1 provided not x = 0 unchanged
sqrt(1/x)*x x = -0.63 -0.794i sqrt(x), 0.794i there unchanged
(2/x)^(1/2)*x x = -3 -2.449i sqrt(2) * sqrt(x), 2.449i there unchanged
sec(x)^(3/2)*cos(x)^(3/2) x = 2 -1 1 provided not cos(x) = 0 unchanged
(1/x)^(1/3)*x^(1/3) x = -2 1 1 provided not x = 0 the same

The fourth is the constant some antiderivatives carry, K = sec(x)^p cos(x)^p beside an answer for a power of the cosine, so a Simplify of such an answer made it wrong where the cosine is negative.

What changes. Both spellings of the two rules, the data form in MatchedRules.cs and the switch arms in Patterns.Power.cs, fire only where the split holds, through one predicate, Patterns.AReciprocalPowerSplits: a whole d, or a rational d with an odd denominator over a positive c. Where two powers of a then combine, the second exponent has to read a negative a the same way, whole or an odd root, since an odd root beside a principal one does not combine either. Elsewhere the expression is left as written, which is what the contract's O6 asks of a rule whose assumption cannot be decided.

Tests: ReciprocalPowerBranchTest, seven rows compared as complex numbers at a negative point, all seven changed in value by Simplify on master, and three the rule still simplifies, unchanged. BoundCheck carries the four shapes now, and on master it finds four disagreements in them.

Harnesses: on the branch before master was merged, CanonCheck and Confluence matched their baselines, and RuleCheck, SimpSweep and BoundCheck found nothing; CI runs all five on the merge.

Measured on the integrator, whose answers Simplify reads and whose corpus harness simplifies an answer that does not check out as written, first on the 1,019 problems of family 4 with a fractional power of the secant, the cosecant or the cotangent beside its reciprocal, 414 run, at the corpus's 5-second budget, against master 8f3757cd, the branch's base:

master this
solved 72 72
wrong 0 0
past the budget 88 87

Measured then on the Rubi corpus against master 8f3757cd:

master this
family 0, independent suites (1814) 1766 1766
family 1, 40 a file (1381) 1296 1292
families 2 to 8, sampled (2410) 2215 2214

The harness counts no answer wrong in the pocket or the sample on either build. Of the 17 problems the two builds disagreed on, run again one build at a time, each answers 7. Master's own is 1/sqrt(csch(2 ln(c x))), answered in 1.4 s through the split: where c x < 1 the integrand is imaginary and the answer's derivative is not it, at x = 0.31, 0.57 and 0.83, the split moving the branch exactly as in the table above; the harness, which compares on the real domain, counted it solved. This one declines it; on the merge with master f18a7d2b, which carries #1752, both answer it on both sides of zero. This one's own is (A + B x^2)/(x^(3/2) (b x^2 + c x^4)^2), at twenty seconds, at the edge of the harness's patience, and the six both answer take seventeen to twenty-four. The four family 1 loses in the sample are four of those twenty-second problems, and family 6's two are one more and the csch above. Three that master declines after sixteen to twenty seconds run past the patience here, declined either way.

The suite passes on the merge with master f18a7d2b, 722b6915, 14,836 tests with 13 skipped. Every row of the first table is as it says there. With master moved on to a27661f3, two more integration rules in it, the 4,153 calculus and corpus tests that run pass on that merge as well, with 2 skipped.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

Rafael-SOWNet and others added 3 commits October 4, 2026 06:55
Simplify wrote (c/a)^d * a^e as c^d * a^(e - d) for every numeric d,
which splits the power of the quotient as (c/a)^d = c^d a^(-d). That
holds for a whole d, and for a rational d with an odd denominator over a
positive c, where a negative base takes its real root; for any other d
it moves the branch wherever a is negative: (1/(-2))^(1/2) is 0.707i and
(-2)^(-1/2) is -0.707i. So sqrt(x) sqrt(1/x) simplified to 1 where it is
-1 for every negative x, and sec(x)^(3/2) cos(x)^(3/2) to 1 where it is
-1 wherever the cosine is negative. Both spellings of the two rules now
fire only where the split holds.

Fixes #1734.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
@Rafael-SOWNet Rafael-SOWNet added this to the 2.6.0 milestone Oct 4, 2026
@Rafael-SOWNet
Rafael-SOWNet merged commit 9848e46 into master Oct 4, 2026
34 checks passed
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.

Simplify splits the power of a quotient across the branch cut: sqrt(x)*sqrt(1/x) is 1

1 participant