After looking at this question, particularly this answer, I wrote my own performance test, using the two functions
isSq2 = Compile[{{n,_Integer}}, Floor@# == # & @ Sqrt @ n];
SquareQ08[n_] :=
JacobiSymbol[n, 541] =!= -1 && JacobiSymbol[n, 547] =!= -1 &&
JacobiSymbol[n, 557] =!= -1 && JacobiSymbol[n, 563] =!= -1 &&
JacobiSymbol[n, 569] =!= -1 && JacobiSymbol[n, 647] =!= -1 &&
JacobiSymbol[n, 653] =!= -1 && JacobiSymbol[n, 659] =!= -1 &&
IntegerQ@Sqrt@n;
I found that indeed isSq2
was much faster for "small" numbers. But I also found that isSq2
worked for larger numbers. Looking further, it seems that Compile
works on machine-size integers, which on my box range up to $2^{63}-1$. So first question:
Is this true? Does
Compile
really work on all machine-size integers (which may vary depending on your box)? Is this explicitly documented anywhere other than that statement on the documentation page forCompile
?
So assuming that the answer to the above question was true, I compared performace for larger integers, and ran across the following issue:
Table[isSq2[10^14 + i], {i, {-1, 0, 1}}]
(* {False, True, True} *)
Table[SquareQ08[10^14 + i], {i, {-1, 0, 1}}]
(* {False, True, False} *)
Clearly isSq2
erroneously returns True
for $10^{14}+1$, which is far smaller than $2^{63}-1$. Further, testing random collections of 10000 numbers or so in that range (including the 10000 integers on either side of $10^{14}$), I can find no other integers for which the two functions return different values.
What is going on here? Is there something wrong with my code? And if so, why does it fail precisely for those two integers?
Edit:
After the discussion below with @JohnMcGee, the issue is that compiled Sqrt
always returns floats, and for the case I gave, 10^14+1 == 10^14
. So the real reason that isSq2
does not work for larger integers is not that Compile
d stuff fails for integers larger than $2^{31}$; it is because of roundoff error in floating point computations! So then my question is:
For what range of floating point values can I count on
isSq2
doing the right thing? The documentation of==
is a little vague in this regard.
isSq2
work with integers rather than reals? $\endgroup$