Skip to content

MathS.Polynomials.Factor drops a constant content, so the factorisation is not equal to its input #1092

Description

@Rafael-SOWNet

MathS.Polynomials.Factor returns a product that does not equal the polynomial it factored
when the numeric content is a bare constant and the polynomial has more than one variable.

Measured on master at 69e40108:

input Factor(·, "x") (answer - input).Simplify()
4 * x^2 - 4 * y^2 (x + y) * (x - y) -3 * x ^ 2 + 3 * y ^ 2
2 * x^2 - 2 * y^2 (x + y) * (x - y) y ^ 2 - x ^ 2
3 * x * y + 3 * y y * 3 * (x + 1) 0
5 * x^2 * y - 5 * y y * 5 * (x + 1) * (x - 1) 0
2 * x^2 - 2 2 * (x + 1) * (x - 1) 0

The factor 4 is simply gone. This is a wrong answer rather than an untidy one: the contract of
a factorisation is that multiplying the factors gives back the input, and here it does not.

Where it comes from

KroneckerFactorization.Factor documents its result as "each of positive degree in main" — so
a constant content is deliberately not among the factors it returns, and the caller has to put
it back. MathS.Polynomials.Kronecker assembles the returned factors into a product and returns
it without ever doing so.

The rows that come out right take a different path. 3 * x * y + 3 * y has content 3 * y, which
is not a constant, so FactorAfterTakingOutTheContent handles it and reinstates the content
itself. 2 * x^2 - 2 is univariate and never reaches the substitution. Only "multivariate and
the content is a pure number" lands in the gap.

Why it matters more than the row count suggests

Everything else in this layer is checked by exact division — a candidate that does not divide the
input is refused, which is what makes a refusal the worst it can do. That check is on the
factors; nothing checks the assembled product against the input, so a constant lost during
assembly is lost silently.

Found while wiring the polynomial layer into Entity.Factorize for #1018, where the wrong answer
would have reached a much more used API. Worth fixing before that lands.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions