# Determine whether a polynomial is a perfect square

I want to check for a polynomial whether it is a perfect square.

Using the functions for polynomial factoring and decomposition, this is possible by first applying FactorList, after which you can check all these terms whether there is a polynomial that has degree equal the half of the original polynomial and divides the original polynomial twice. However, this seems like unoptimal use of Mathematica and takes time as well, as we have to iterate through a list.

Using Sqrt (a bit naive, I know) combined with PolynomialQ does not work either as Mathematica (rightly) doesn't simplify this.

Hence, my question is: is there any relatively simple (i.e. easier/less computationally heavy) method for determining whether a polynomial is a square?

Edit: three small examples:

CheckIfSquare[x^2 - 1] should give False.

CheckIfSquare[x^2 - 2x + 1] should give True as $x^2 - 2x + 1 = (x-1)^2$.

CheckIfSquare[x^3] should give False, even though x^3 is not squarefree, it is not a square itself.

• FactorSquareFreeList is cheaper than full factorization. Then check that all exponents other than for the constant term are even. – Daniel Lichtblau Jan 27 '17 at 23:49
• @DanielLichtblau: Thanks, this seems already better than my own soluton. Anythins possible without using any form of FactorList? – Stapler Jan 27 '17 at 23:54
• You could also add fast negative criterion at the beginning by returning False if plugging in a value for x results in a non-square number. – Chip Hurst Jan 28 '17 at 0:26
• @ChipHurst: Thanks, that makes sense. – Stapler Jan 28 '17 at 12:27
• FSFL is really different from FL in that is is based entirely on GCD computations. No actual "factorization" is performed. – Daniel Lichtblau Jan 28 '17 at 16:49

This code can be streamlined, but it seems to work:

CheckIfSquare[poly_] :=
AllTrue[Transpose[Drop[FactorList[poly], 1]][[2]], EvenQ[#]&]


Check:

CheckIfSquare[x^2 - 1]


(* False *)

CheckIfSquare[x^2 - 2 x + 1]


(* True *)

CheckIfSquare[x^3]


(* False *)

And....

CheckIfSquare[81 - 108 x + 54 x^2 - 12 x^3 + x^4]


(* True *)

...as 81 - 108 x + 54 x^2 - 12 x^3 + x^4 = (x-3)^4

Closely related, based on Daniel Lichtblau:

AllTrue[
Drop[FactorSquareFreeList[(x + 1)^2 (x - 9)^4], 1]
[[All, 2]], EvenQ]

• But what about $x^3$? It will come up as not being squarefree, but it is not a perfect square. I'll add it to the question. – Stapler Jan 28 '17 at 0:03
• Thanks for the effort, this seems to work. – Stapler Jan 28 '17 at 12:28

A little trick I learned long, long ago.

CheckIfSquare[p_] := Simplify[D[p, x]^2] === Simplify[4 p]


x^2-1 returns False, x^2-2 x+1 returns True, x^3 returns False

As always, using equality on the result of a chain of calculations on approximate coefficients may fail. There might be other cases I haven't thought of where this can fail, I can't think of any at the moment. But it is just so cute. And it requires no factorization at all.

EDIT: Late last night I realize that I had forgotten the details of using this and had made a mistake in this. The original purpose of this trick was to rapidly see if it was possible to find a factor of a polynomial without needing to invoke full factorization and when the power of something like MMA wasn't available. The polynomial GCD of the polynomial and it's derivative would give that. It actually fails even for some quadratics like (2 x - 7)^2 and only works correctly when the derivative of the factor equals 1 and the polynomial is quadratic. Thanks for the comments letting everyone know that I made a mistake here and FactorSquareFreeList followed by processing the degrees returned from that should be used.

• Very elegant! I like this solution, and as I am using polynomials with rational coefficients, approximations should be no problem. – Stapler Jan 28 '17 at 12:30
• I think this is only correct when p is quadratic. With n = Exponent[p, x], the degree of D[p, x]^2 is 2n-2 and the degree of 4p is n. – Chip Hurst Jan 28 '17 at 15:47