// sqrtp().
// General includes.
#include "cl_sysdep.h"
// Specification.
#include "cln/integer.h"
// Implementation.
#include "cl_I.h"
#include "cl_DS.h"
namespace cln {
cl_boolean sqrtp (const cl_I& x, cl_I* w)
{
// Methode:
// [Henri Cohen: A course in computational algebraic number theory, 2nd prnt.,
// section 1.7.2.]
// If x is a square, it has not only to be ==0,1 mod 4, but also
// - one of the 12 squares mod 64,
// - one of the 16 squares mod 63,
// - one of the 21 squares mod 65,
// - one of the 6 squares mod 11.
// Then we check whether the ISQRT gives the remainder 0.
static char squares_mod_11 [11] =
// 0 1 3 4 5 9
{ 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0 };
static char squares_mod_63 [63] =
// 0 1 4 7 9 16 18 22 25 28 36 37 43 46 49 58
{ 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0
};
static char squares_mod_64 [64] =
// 0 1 4 9 16 17 25 33 36 41 49 57
{ 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0
};
static char squares_mod_65 [65] =
// 0 1 4 9 10 14 16 25 26 29 30 35 36 39 40 49 51 55 56 61 64
{ 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0,
0, 1, 0, 0, 1
};
{ CL_ALLOCA_STACK;
var const uintD* x_MSDptr;
var uintC x_len;
var const uintD* x_LSDptr;
I_to_NDS_nocopy(x, x_MSDptr=,x_len=,x_LSDptr=, // Digit sequence >=0 zu x
cl_true, { *w = 0; return cl_true; } // 0 is a square
);
// Check mod 64.
{ var uintD lsd = lspref(x_LSDptr,0);
if (!squares_mod_64[lsd & 63])
{ return cl_false; } // not a square mod 64 -> not a square
}
// Check mod 63.
{ var cl_I_div_t div63 = cl_divide(x,L_to_FN(63));
if (!squares_mod_63[FN_to_UL(div63.remainder)])
{ return cl_false; } // not a square mod 63 -> not a square
}
// Check mod 65.
{ var cl_I_div_t div65 = cl_divide(x,L_to_FN(65));
if (!squares_mod_65[FN_to_UL(div65.remainder)])
{ return cl_false; } // not a square mod 65 -> not a square
}
// Check mod 11.
{ var cl_I_div_t div11 = cl_divide(x,L_to_FN(11));
if (!squares_mod_11[FN_to_UL(div11.remainder)])
{ return cl_false; } // not a square mod 11 -> not a square
}
// Check with full precision.
{ var DS y;
var cl_boolean squarep;
UDS_sqrt(x_MSDptr,x_len,x_LSDptr, &y, squarep=); // Wurzel ziehen
if (squarep)
{ *w = NUDS_to_I(y.MSDptr,y.len); } // als Integer
return squarep;
} }
}
// Bit complexity (x of length N): O(M(N)).
} // namespace cln
syntax highlighted by Code2HTML, v. 0.9.1