Skip to content

Roots vs fractioned powers? #204

Open
Open

Description

@WhiteBlackGoose

That is quite a vague and ambiguous topic when it comes to computational algebra. As we know, n-th root is something whose n-th power is the root's argument. So technically there are a lot of such numbers. The simplest way to represent a root is fractioned powers, e. g. square root of x is x^(1/2).

There we come to another problem: we know that (x ^ a) ^ b = x ^ (a * b), and we know, that 1/2 * 2 = 1. So technically we get that sqrt(x^2) = x which is actually okay to me, but in most common cases it won't be accepted. Reason: principle root.

There're more ambiguous stuff, I might add some more info to this issue. Any thoughts are welcomed and may be discussed in this thread.

Activity

  1. unpinned this issue on Jun 12, 2024
  2. Rafael-SOWNet commented on Aug 16, 2026

    @Rafael-SOWNet
    Member

    Some measurements for the thread, since the ambiguity is easier to argue about with the current behaviour written down. master at a45a7256, default codomain (complex).

    written node Simplify Evaled
    sqrt(x) Powf sqrt(x) sqrt(x)
    x ^ (1/2) Powf sqrt(x) sqrt(x)
    sqrt(x ^ 2) Powf sqrt(x ^ 2) sqrt(x ^ 2)
    (x ^ 2) ^ (1/2) Powf sqrt(x ^ 2) sqrt(x ^ 2)
    sqrt(-1) Powf i i
    (-8) ^ (1/3) Powf -2 -2

    The library already made the choice this issue is about, in the direction the issue prefers. There is no root node — sqrt(x) is Powf(x, 1/2) — and sqrt(x ^ 2) is not simplified to x. So (x^a)^b = x^(a*b) is not applied unconditionally, which is the guard against the principal-root problem in the body.

    (-8) ^ (1/3) = -2 is worth noting as the one that will surprise: the real cube root rather than the principal complex one, which is 1 + i*sqrt(3). That is a deliberate-looking choice and it is inconsistent with sqrt(-1) = i taking the principal branch. If any single thing here deserves an issue of its own, I think it is that pair.

    sqrt(x) and x ^ (1/2) are not structurally equal, though they simplify alike — and the cost models rank them differently:

    model sqrt(x) x ^ (1/2)
    Default 10.000 13.000
    SmallestTree 3.000 5.000
    FewestRadicals 1.003 1.005

    Both are counted as one radical by FewestRadicals — that is right, and it is right only since #953, which taught the feature models to read the exponent's value rather than its written node (#950). Before that, an exponent written as 2 ^ (-1) was not seen as a radical at all.

    So the practical state is: one representation, two spellings, ranked by size rather than by kind, and no unconditional exponent-merging rule. The remaining ambiguity is the branch question — which root x ^ (1/n) denotes for negative x — and that is where MathS.Settings.Codomain already carries a decision the rules can consult, as Logf now does since #916.

  3. Happypig375 commented on Sep 18, 2026

    @Happypig375
    Member

    This really needs an escalation to whether we need a dedicated node for the radical sign (presumably yes because the selection of principal root that is implied by the surd). Part of v3 redesign

  4. added this to the 3.0 milestone on Sep 18, 2026
  5. Happypig375 commented on Sep 27, 2026

    @Happypig375
    Member

    Assigning goal type with the central design question being the above comment

  6. added theissue type on Sep 27, 2026
  7. Rafael-SOWNet commented on Oct 14, 2026

    @Rafael-SOWNet
    Member

    Another instance, from the integrator. Measured on master acd4702:

    value
    (-3.35)^(-18/5) 0.012877… (real root)
    (-3.35)^(-3/10) * (-3.35)^(-33/10) 0.003979… + 0.012247…i (principal)

    The exponents sum to -18/5, so x^a x^b = x^(a+b) fails at a negative base once one exponent has an odd denominator and the others don't. The integrator gathers powers of one base when it normalises an integrand. So (d + k x)^(-3 - 2p) (d + k x)^p (a k + c d x)^p is answered as if it were (d + k x)^(-3 - p) (a k + c d x)^p, which is exact for a symbolic p. After substituting p = 3/10 and x = -0.7 the derivative of that answer is no longer the integrand, because (d + k x)^(-18/5) is now evaluated as a real root. With p = 1/3, p = -7/4 or a symbolic p it agrees.

  8. Rafael-SOWNet commented on Oct 22, 2026

    @Rafael-SOWNet
    Member

    Two data points for this, from the upper incomplete gamma function (#2077, #2078).

    The real root has a bound. Number.Pow takes the real root only for an exact exponent whose denominator is below 10, because that is where its root search stops. (-8)^(1/3) is -2, but (-8)^(1/11) takes the principal branch. SimplificationContract §6's table says "odd denominator" and does not mention the bound.

    A function that takes the principal branch now meets it. gamma(a, z) takes the principal branch of z^a, as mpmath's gammainc and Mathematica's Gamma[a, z] do. Its derivative -z^(a - 1) e^(-z) goes through the power. So at a negative z, with a an exact rational of odd denominator below 10, the evaluated derivative is not the derivative of the value. At a = 2/5, z = -17/15, the function's value has imaginary part -3.667, while z^(-3/5) in the derivative is real.

    Either reading would make the two agree, if it held everywhere. Today the node follows the references and documents the mismatch (MathS.IncompleteGamma, from #2078).

    🤖 Generated with Claude Code

    https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

  9. Rafael-SOWNet commented on Oct 22, 2026

    @Rafael-SOWNet
    Member

    A correction to my comment above. Keeping gamma(a, z) on the principal branch was wrong, and the node now takes the power's branch instead (PR to follow, from the-incomplete-gamma-function-takes-the-powers-branch).

    The mismatch was not only between a derivative and a value. Every antiderivative written in the function inherits it. With the next integration rule, ∫₁² e^(x^3) dx came out as (gamma(1/3, -8) - gamma(1/3, -1))/3 = -137.76 + …i. Quadrature gives 275.51, the same number turned by e^(-2iπ/3). Differentiating the antiderivative back matched the integrand, because the symbolic derivative takes the real root consistently, so the corpus harness could not see it.

    Gamma(a, z) = Gamma(a) - z^a g(a, z) with g entire, so taking z^a from the power is one factor, (-1)^p e^(-iπp/q) on the cut. gamma(1/3, -2) is then real, 10.2125…, matching DLMF 8.7.3's sum with the real root at 90 digits. The function and its derivative then agree wherever the power does. Whichever way this issue is decided, the node should follow the power. It now does, so a change to the power carries it along.

    🤖 Generated with Claude Code

    https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions