Repository navigation
A quadratic whose discriminant is a square is answered without the root - #2170
Merged
Rafael-SOWNet merged 2 commits intoOct 27, 2026
Merged
Conversation
SolveQuadratic wrote sqrt(b^2 - 4ac) whatever the discriminant was. With
polynomial coefficients and a square discriminant that left the square
under the root: a z^2 - (a^2 - bc) z - abc has discriminant (a^2 + bc)^2
and roots a and -bc/a, and came back as
(a^2 - bc -/+ sqrt((a^2 - bc)^2 + 4 a^2 bc)) / (2a). So did the most
ordinary one, z^2 - (p + q) z + pq, whose roots are p and q.
Either square root of the discriminant gives the same pair of roots, so
any polynomial r with r^2 = b^2 - 4ac serves, with no absolute value.
Where a, b and c parse as polynomials and the discriminant is a rational
number times the square of one (MultivariatePolynomial.TrySquareRoot, the
exact square root the integrator already uses), each numerator -b -/+ r
is reduced by its greatest common divisor with 2a. Where the number's root
is not rational, it is the one factor left outside: a +/- sqrt(2),
(p + q)/2 +/- i (p - q)/2. Anything else takes the formula as before.
On 2.6.0 and on this branch, Solve:
a*z^2 - (a^2 - b*c)*z - a*b*c = 0 sqrt form -> { -b * c / a, a }
x^2 - (p + q)*x + p*q = 0 sqrt form -> { q, p }
x^2 - 2*a*x + a^2 - 2 = 0 sqrt form -> { a - sqrt(2), a + sqrt(2) }
Fourteen such equations had every root substituted back at sampled values
of the other symbols, with residual 0. Unit suite 17,138 passed, 0 failed;
RootCheck 596/596 clean; CasBench 120/121, its one unsolved row unchanged.
Fixes #2140
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2170 +/- ##
=======================================
Coverage 86.42% 86.42%
=======================================
Files 295 295
Lines 64806 64879 +73
Branches 19059 19083 +24
=======================================
+ Hits 56009 56074 +65
- Misses 4768 4774 +6
- Partials 4029 4031 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
…mial is built The performance gate failed on #2170: SolveEasyMedium, x^2 + x + a, allocated 69,690 B against a baseline of 66,661 (+4.5%, band 3%). Its discriminant 1 - 4a is of degree one in a and cannot be a square, but the three coefficients were parsed, multiplied and normalized before TrySquareRoot said so. A square has an even degree in every variable, and where 2 deg b and deg a + deg c differ the larger is the discriminant's degree, so a quadratic for which that is odd is refused first. Degrees as written bound the true ones; a coefficient that cancels inside itself can be refused when it need not be, which leaves it to the formula as before. On one machine, B per SolveEquation: master this x2 + x + a 66,976 67,064 x2 + b*x + a 70,488 70,616 x2 + x + 1 450,114 450,282 The fourteen equations still check by substitution, and the unit suite is 17,138 passed, 0 failed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
Rafael-SOWNet
added a commit
that referenced
this pull request
Oct 27, 2026
…2173) A polynomial whose powers share a factor is solved in x^gcd, and its roots are the gcd-th roots of what that gives. With the factor 2 that is a square root, written sqrt(y) whatever y was, so an equation with no term in x kept the square under the root that #2170 took out of the formula: x^2 = (a + b)^2 was { sqrt((a + b)^2), -sqrt((a + b)^2) }. x^2 = y is the quadratic x^2 - y = 0, so with the factor 2 each y goes through the same exact root as the formula, and keeps sqrt where it is not a rational number times a square. The parity check in front refuses a y of odd degree in a symbol, such as x^2 = a, before any polynomial is built. On 2.6.0 and on this branch, Solve: x^2 = (a + b)^2 sqrt form -> { -a - b, a + b } x^4 - (a^2 + b^2)*x^2 + a^2*b^2 = 0 nested sqrt -> { -b, b, -a, a } sin(x)^2 = (a + 1)^2 arcsin(sqrt((a + 1)^2)) -> arcsin(a + 1) The eigenvalues of [[0, J], [J, 0]] are J and -J instead of +-sqrt(J^2); Eigenvalues is new since 2.6.0, so its test and doc comment are updated and no released answer changes there. Twenty-three equations had every root substituted back at sampled values of the other symbols, with residual 0. Unit suite 17,144 passed, 0 failed; RootCheck 596/596 clean; CasBench 120/121, unchanged. Part of #2140 Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Rafael-SOWNet
deleted the
a-square-discriminant-is-taken-out-of-the-root
branch
October 28, 2026 10:27
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.
Fixes #2140.
The defect:
SolveQuadraticwrotesqrt(b^2 - 4ac)whatever the discriminant was. With polynomial coefficients and a discriminant that is a square, the square stayed under the root.Solvea*z^2 - (a^2 - b*c)*z - a*b*c = 0{ (a ^ 2 + -b * c - sqrt((-(a ^ 2 + -b * c)) ^ 2 - 4 * a * -a * b * c)) / (2 * a), … }{ -b * c / a, a }x^2 - (p + q)*x + p*q = 0{ (p + q - sqrt((-(p + q)) ^ 2 - 4 * p * q)) / 2, … }{ q, p }x^2 - 2*a*x + a^2 - 2 = 0{ (-(-2) * a - sqrt(((-2) * a) ^ 2 - 4 * (a ^ 2 + -2))) / 2, … }{ a - sqrt(2), a + sqrt(2) }2*x^2 - 2*(p + q)*x + p^2 + q^2 = 0{ (-(-2) * (p + q) - sqrt(((-2) * (p + q)) ^ 2 - 8 * (p ^ 2 + q ^ 2))) / 4, … }{ 1/2 * p + 1/2 * q - i * (1/2 * p - 1/2 * q), … }Why the change is sound: either square root of the discriminant gives the same pair of roots,
(-b ∓ r)/(2a), so any polynomialrwithr^2 = b^2 - 4acserves, and no absolute value is needed.The change: it applies where
a,bandcparse as polynomials and the discriminant is a rational number times the square of a polynomial. The square root comes fromMultivariatePolynomial.TrySquareRoot, the exact one the integrator already uses.-b ∓ ris reduced by its greatest common divisor with2a, rational factors included.sqrt(k), ori sqrt(k)) is the only factor left outside.3x^2 - 2(a + b)x + ab, whose discriminant4(a^2 - ab + b^2)is no square, is unchanged.Checked:
SquareDiscriminantTest: 10 rows. Each checks that the expected roots are there, by value, and that no radical is left over a polynomial.ln(x) + ln(y) - ln(x * y), is the same as in the committed report.Performance:
SolveEasyMedium(x^2 + x + a) allocated 69,690 B against 66,661, +4.5% where the band is 3%. Its discriminant1 - 4acannot be a square, but the coefficients were turned into polynomials before that was found.SolveEquation, measured on one machine:x2 + x + ax2 + b*x + ax2 + x + 1Not in this PR:
x^2 + (p - q)^2/4 = 0is still{ sqrt(-(p - q) ^ 2 / 4), … }. The same argument holds there, since both signs are in the set, but that code is the n-th root inversion for every exponent, and changing it needs its own measurement.factor::z::…refusing the polynomial from the issue isMathS.Polynomials.Factordeclining a bivariate coefficient ring. That is separate too.🤖 Generated with Claude Code
https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura