📄 c_lip_impl.h
字号:
{
zaddmulp(*a, *b, rd, carry);
a++;
carry += NTL_RADIXM - (*b++);
}
*a += carry - NTL_RADIX; /* unnormalized */
}
#else
static
void zsubmul(long lams, long *lama, long *lamb)
{
long lami = (*lamb++)-1;
long lamcarry = 0;
zam_decl;
zam_init(*lamb, lams);
lamb++;
for (; lami > 0; lami--) {
zam_subloop(*lama, lamcarry, *lamb);
lama++;
lamb++;
}
zam_subfinish(*lama, lamcarry);
lama++;
*lama += lamcarry;
}
#endif
#endif
/*
zdiv21 returns quot, numhigh so
quot = (numhigh*NTL_RADIX + numlow)/denom;
numhigh = (numhigh*NTL_RADIX + numlow)%denom;
Assumes 0 <= numhigh < denom < NTL_RADIX and 0 <= numlow < NTL_RADIX.
*/
#define zdiv21(numhigh, numlow, denom, deninv, quot) \
{ \
long lr21; \
long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) \
+ (double) (numlow)) * (deninv)); \
long lp21; \
MulLo(lp21, lq21, denom); \
lr21 = (numhigh << NTL_NBITS) + numlow - lp21; \
if (lr21 < 0) { \
lq21--; \
lr21 += denom; \
} \
else if (lr21 >= denom) { \
lr21 -= denom; \
lq21++; \
} \
quot = lq21; \
numhigh = lr21; \
}
#if 0
#define zdiv21(numhigh, numlow, denom, deninv, quot) \
{ \
long lr21; \
long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) \
+ (double) (numlow)) * (deninv)); \
long lp21; \
MulLo(lp21, lq21, denom); \
lr21 = (numhigh << NTL_NBITS) + numlow - lp21; \
if (lr21 < 0) \
{ \
do \
{ \
lq21--; \
} while ((lr21 += denom) < 0); \
} \
else \
{ \
while (lr21 >= denom) \
{ \
lr21 -= denom; \
lq21++; \
}; \
} \
quot = lq21; \
numhigh = lr21; \
}
#endif
#if (NTL_ARITH_RIGHT_SHIFT && defined(NTL_AVOID_BRANCHING))
#define zrem21(numhigh, numlow, denom, deninv) \
{ \
long lr21; \
long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) \
+ (double) (numlow)) * (deninv)); \
long lp21; \
MulLo(lp21, lq21, denom); \
lr21 = (numhigh << NTL_NBITS) + numlow - lp21; \
lr21 += (lr21 >> (NTL_BITS_PER_LONG-1)) & denom; \
lr21 -= denom; \
lr21 += (lr21 >> (NTL_BITS_PER_LONG-1)) & denom; \
numhigh = lr21; \
}
#else
#define zrem21(numhigh, numlow, denom, deninv) \
{ \
long lr21; \
long lq21 = (long) (((NTL_FRADIX * (double) (numhigh)) \
+ (double) (numlow)) * (deninv)); \
long lp21; \
MulLo(lp21, lq21, denom); \
lr21 = (numhigh << NTL_NBITS) + numlow - lp21; \
if (lr21 < 0) lr21 += denom; \
else if (lr21 >= denom) lr21 -= denom; \
numhigh = lr21; \
}
#endif
void _ntl_zsetlength(_ntl_verylong *v, long len)
{
_ntl_verylong x = *v;
if (len < 0)
zhalt("negative size allocation in _ntl_zsetlength");
if (len >= (1L << (NTL_BITS_PER_LONG-4))/NTL_NBITS)
zhalt("size too big in _ntl_zsetlength");
#ifdef L_TO_G_CHECK_LEN
/* this makes sure that numbers don't get too big for GMP */
if (len >= (1L << (NTL_BITS_PER_INT-4)))
zhalt("size too big for GMP");
#endif
if (x) {
long oldlen = x[-1];
long fixed = oldlen & 1;
oldlen = oldlen >> 1;
if (fixed) {
if (len > oldlen)
zhalt("internal error: can't grow this _ntl_verylong");
else
return;
}
if (len <= oldlen) return;
len++; /* always allocate at least one more than requested */
oldlen = (long) (oldlen * 1.2); /* always increase by at least 20% */
if (len < oldlen)
len = oldlen;
/* round up to multiple of MIN_SETL */
len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
/* test len again */
if (len >= (1L << (NTL_BITS_PER_LONG-4))/NTL_NBITS)
zhalt("size too big in _ntl_zsetlength");
x[-1] = len << 1;
if (!(x = (_ntl_verylong)realloc((void*)(&(x[-1])), (len + 2) * (sizeof (long))))) {
zhalt("reallocation failed in _ntl_zsetlength");
}
}
else {
len++;
len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
/* test len again */
if (len >= (1L << (NTL_BITS_PER_LONG-4))/NTL_NBITS)
zhalt("size too big in _ntl_zsetlength");
if (!(x = (_ntl_verylong)malloc((len + 2)*(sizeof (long))))) {
zhalt("allocation failed in _ntl_zsetlength");
}
x[0] = len << 1;
x[1] = 1;
x[2] = 0;
}
*v = x+1;
}
void _ntl_zfree(_ntl_verylong *x)
{
_ntl_verylong y;
if (!(*x))
return;
if ((*x)[-1] & 1)
zhalt("Internal error: can't free this _ntl_verylong");
y = (*x - 1);
free((void*)y);
*x = 0;
}
long _ntl_zround_correction(_ntl_verylong a, long k, long residual)
{
long direction;
long p;
long sgn;
long bl;
long wh;
long i;
if (a[0] > 0)
sgn = 1;
else
sgn = -1;
p = k - 1;
bl = (p/NTL_NBITS);
wh = 1L << (p - NTL_NBITS*bl);
bl++;
if (a[bl] & wh) {
/* bit is 1...we have to see if lower bits are all 0
in order to implement "round to even" */
if (a[bl] & (wh - 1))
direction = 1;
else {
i = bl - 1;
while (i > 0 && a[i] == 0) i--;
if (i > 0)
direction = 1;
else
direction = 0;
}
/* use residual to break ties */
if (direction == 0 && residual != 0) {
if (residual == sgn)
direction = 1;
else
direction = -1;
}
if (direction == 0) {
/* round to even */
wh = wh << 1;
if (wh == NTL_RADIX) {
wh = 1;
bl++;
}
if (a[bl] & wh)
direction = 1;
else
direction = -1;
}
}
else
direction = -1;
if (direction == 1)
return sgn;
return 0;
}
double _ntl_zdoub_aux(_ntl_verylong n)
{
double res;
long i;
if (!n)
return ((double) 0);
if ((i = n[0]) < 0)
i = -i;
res = (double) (n[i--]);
for (; i; i--)
res = res * NTL_FRADIX + (double) (n[i]);
if (n[0] > 0)
return (res);
return (-res);
}
double _ntl_zdoub(_ntl_verylong n)
{
static _ntl_verylong tmp = 0;
long s;
long shamt;
long correction;
double x;
s = _ntl_z2log(n);
shamt = s - NTL_DOUBLE_PRECISION;
if (shamt <= 0)
return _ntl_zdoub_aux(n);
_ntl_zrshift(n, shamt, &tmp);
correction = _ntl_zround_correction(n, shamt, 0);
if (correction) _ntl_zsadd(tmp, correction, &tmp);
x = _ntl_zdoub_aux(tmp);
/* We could just write x = ldexp(x, shamt); however, if long's
* are bigger than int's, there is the possibility that shamt would be
* truncated. We could check for this and raise an error, but
* it is preferable to do it this way to get +/- infinity, if
* possible. */
while (shamt > 1024) {
x = ldexp(x, 1024);
shamt -= 1024;
}
x = ldexp(x, shamt);
return x;
}
double _ntl_zlog(_ntl_verylong n)
{
static _ntl_verylong tmp = 0;
static double log_2;
static long init = 0;
long s;
long shamt;
long correction;
double x;
if (!init) {
log_2 = log(2.0);
init = 1;
}
if (_ntl_zsign(n) <= 0)
zhalt("log argument <= 0");
s = _ntl_z2log(n);
shamt = s - NTL_DOUBLE_PRECISION;
if (shamt <= 0)
return log(_ntl_zdoub_aux(n));
_ntl_zrshift(n, shamt, &tmp);
correction = _ntl_zround_correction(n, shamt, 0);
if (correction) _ntl_zsadd(tmp, correction, &tmp);
x = _ntl_zdoub_aux(tmp);
return log(x) + shamt*log_2;
}
void _ntl_zdoubtoz(double a, _ntl_verylong *xx)
{
_ntl_verylong x;
long neg, i, t, sz;
a = floor(a);
if (!_ntl_IsFinite(&a))
zhalt("_ntl_zdoubtoz: attempt to convert non-finite value");
if (a < 0) {
a = -a;
neg = 1;
}
else
neg = 0;
if (a == 0) {
_ntl_zzero(xx);
return;
}
sz = 1;
a = a*NTL_FRADIX_INV;
while (a >= 1) {
a = a*NTL_FRADIX_INV;
sz++;
}
x = *xx;
if (MustAlloc(x, sz)) {
_ntl_zsetlength(&x, sz);
*xx = x;
}
for (i = sz; i > 0; i--) {
a = a*NTL_FRADIX;
t = (long) a;
x[i] = t;
a = a - t;
}
x[0] = (neg ? -sz : sz);
}
void _ntl_zzero(_ntl_verylong *aa)
{
if (!(*aa)) _ntl_zsetlength(aa, 1);
(*aa)[0] = 1;
(*aa)[1] = 0;
}
/* same as _ntl_zzero, except does not unnecessarily allocate space */
void _ntl_zzero1(_ntl_verylong *aa)
{
if (!(*aa)) return;
(*aa)[0] = 1;
(*aa)[1] = 0;
}
void _ntl_zone(_ntl_verylong *aa)
{
if (!(*aa)) _ntl_zsetlength(aa, 1);
(*aa)[0] = 1;
(*aa)[1] = 1;
}
void _ntl_zcopy(_ntl_verylong a, _ntl_verylong *bb)
{
long i;
_ntl_verylong b = *bb;
if (!a) {
_ntl_zzero(bb);
return;
}
if (a != b) {
if ((i = *a) < 0)
i = (-i);
if (MustAlloc(b, i)) {
_ntl_zsetlength(&b, i);
*bb = b;
}
for (; i >= 0; i--)
*b++ = *a++;
}
}
/* same as _ntl_zcopy, but does not unnecessarily allocate space */
void _ntl_zcopy1(_ntl_verylong a, _ntl_verylong *bb)
{
long i;
_ntl_verylong b = *bb;
if (!a) {
_ntl_zzero1(bb);
return;
}
if (a != b) {
if ((i = *a) < 0)
i = (-i);
if (MustAlloc(b, i)) {
_ntl_zsetlength(&b, i);
*bb = b;
}
for (; i >= 0; i--)
*b++ = *a++;
}
}
void _ntl_zintoz(long d, _ntl_verylong *aa)
{
long i;
long anegative;
unsigned long d1, d2;
_ntl_verylong a = *aa;
anegative = 0;
if (d < 0) {
anegative = 1;
d1 = - ((unsigned long) d);
}
else
d1 = d;
i = 0;
d2 = d1;
do {
d2 >>= NTL_NBITS;
i++;
}
while (d2 > 0);
if (MustAlloc(a, i)) {
_ntl_zsetlength(&a, i);
*aa = a;
}
i = 0;
a[1] = 0;
while (d1 > 0) {
a[++i] = d1 & NTL_RADIXM;
d1 >>= NTL_NBITS;
}
if (i > 0)
a[0] = i;
else
a[0] = 1;
if (anegative)
a[0] = (-a[0]);
}
/* same as _ntl_zintoz, but does not unnecessarily allocate space */
void _ntl_zintoz1(long d, _ntl_verylong *aa)
{
long i;
long anegative;
unsigned long d1, d2;
_ntl_verylong a = *aa;
if (!d && !a) return;
anegative = 0;
if (d < 0) {
anegative = 1;
d1 = -d;
}
else
d1 = d;
i = 0;
d2 = d1;
do {
d2 >>= NTL_NBITS;
i++;
}
while (d2 > 0);
if (MustAlloc(a, i)) {
_ntl_zsetlength(&a, i);
*aa = a;
}
i = 0;
a[1] = 0;
while (d1 > 0) {
a[++i] = d1 & NTL_RADIXM;
d1 >>= NTL_NBITS;
}
if (i > 0)
a[0] = i;
else
a[0] = 1;
if (anegative)
a[0] = (-a[0]);
}
void _ntl_zuintoz(unsigned long d, _ntl_verylong *aa)
{
long i;
unsigned long d1, d2;
_ntl_verylong a = *aa;
d1 = d;
i = 0;
d2 = d1;
do {
d2 >>= NTL_NBITS;
i++;
}
while (d2 > 0);
if (MustAlloc(a, i)) {
_ntl_zsetlength(&a, i);
*aa = a;
}
i = 0;
a[1] = 0;
while (d1 > 0) {
a[++i] = d1 & NTL_RADIXM;
d1 >>= NTL_NBITS;
}
if (i > 0)
a[0] = i;
else
a[0] = 1;
}
long _ntl_ztoint(_ntl_verylong a)
{
long d;
long sa;
if (!a)
return (0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -