You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
1.7 KiB
60 lines
1.7 KiB
// square().
|
|
|
|
// General includes.
|
|
#include "cl_sysdep.h"
|
|
|
|
// Specification.
|
|
#include "cln/integer.h"
|
|
|
|
|
|
// Implementation.
|
|
|
|
#include "cl_I.h"
|
|
#include "cl_DS.h"
|
|
#include "cl_low.h"
|
|
|
|
namespace cln {
|
|
|
|
const cl_I square (const cl_I& x)
|
|
{
|
|
// Methode:
|
|
// x Fixnum -> direkt multiplizieren
|
|
// sonst: zu DS machen, multiplizieren.
|
|
if (fixnump(x))
|
|
{ var sintV x_ = FN_to_V(x);
|
|
#if (cl_value_len > 32)
|
|
// nur falls x ein Integer mit höchstens 32 Bit ist:
|
|
if ((uintV)((sintV)sign_of(x_) ^ x_) < bit(31))
|
|
#endif
|
|
{
|
|
// Werte direkt multiplizieren:
|
|
var uint32 hi;
|
|
var uint32 lo;
|
|
mulu32((uint32)x_,(uint32)x_,hi=,lo=); // erst unsigned multiplizieren
|
|
if (x_ < 0) { hi -= 2*(uint32)x_; } // dann Korrektur für Vorzeichen
|
|
return L2_to_I(hi,lo);
|
|
}
|
|
}
|
|
CL_ALLOCA_STACK;
|
|
var const uintD* xMSDptr;
|
|
var uintC xlen;
|
|
var const uintD* xLSDptr;
|
|
I_to_NDS_nocopy(x, xMSDptr = , xlen = , xLSDptr = , cl_false,);
|
|
var uintD* ergMSDptr;
|
|
var uintC erglen = 2*xlen;
|
|
var uintD* ergLSDptr;
|
|
num_stack_alloc(erglen,ergMSDptr=,ergLSDptr=);
|
|
var uintC len = xlen;
|
|
var uintD MSD = mspref(xMSDptr,0);
|
|
if (MSD==0)
|
|
{ mspref(ergMSDptr,0) = 0; mspref(ergMSDptr,1) = 0; len--; }
|
|
cl_UDS_mul_square(xLSDptr,len,ergLSDptr);
|
|
if ((sintD)MSD < 0)
|
|
{ subfrom_loop_lsp(xLSDptr,ergLSDptr lspop xlen,xlen);
|
|
subfrom_loop_lsp(xLSDptr,ergLSDptr lspop xlen,xlen);
|
|
}
|
|
return DS_to_I(ergMSDptr,erglen);
|
|
}
|
|
// Bit complexity (x of length N): O(M(N)).
|
|
|
|
} // namespace cln
|