?? c_lip_impl.h
字號:
}
if (sa < sb) {
i = sa;
maxab = sb;
}
else {
i = sb;
maxab = sa;
}
if (MustAlloc(c, maxab+1)) {
_ntl_zsetlength(&c, maxab + 1);
if (a_alias) a = c;
if (b_alias) b = c;
*cc = c;
}
pc = c;
carry = 0;
do {
long t = (*(++a)) + (*(++b)) + carry;
carry = t >> NTL_NBITS;
*(++pc) = t & NTL_RADIXM;
i--;
} while (i);
i = sa-sb;
if (!i) goto i_exit;
if (i < 0) {
i = -i;
a = b;
}
if (!carry) goto carry_exit;
for (;;) {
long t = (*(++a)) + 1;
carry = t >> NTL_NBITS;
*(++pc) = t & NTL_RADIXM;
i--;
if (!i) goto i_exit;
if (!carry) goto carry_exit;
}
i_exit:
if (carry) {
*(++pc) = 1;
maxab++;
}
*c = anegative ? -maxab : maxab;
return;
carry_exit:
if (pc != a) {
do {
*(++pc) = *(++a);
i--;
} while (i);
}
*c = anegative ? -maxab : maxab;
}
else {
/* signs a and b are different...use _ntl_zsub */
if (anegative) {
a[0] = -sa;
_ntl_zsub(b, a, cc);
if (!a_alias) a[0] = sa;
}
else {
b[0] = -sb;
_ntl_zsub(a, b, cc);
if (!b_alias) b[0] = sb;
}
}
}
void
_ntl_zsub(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *cc)
{
long sa;
long sb;
long anegative;
long a_alias, b_alias;
_ntl_verylong c;
if (!b) {
if (a)
_ntl_zcopy(a, cc);
else
_ntl_zzero(cc);
return;
}
if (!a) {
_ntl_zcopy(b, cc);
_ntl_znegate(cc);
return;
}
c = *cc;
a_alias = (a == c);
b_alias = (b == c);
if ((anegative = ((sa = a[0]) < 0)) == ((sb = b[0]) < 0)) {
/* signs agree */
long i, carry, *pc;
if (anegative) {
sa = -sa;
sb = -sb;
}
carry = sa - sb;
if (!carry) {
long *aa = a + sa;
long *bb = b + sa;
i = sa;
while (i && !(carry = (*aa - *bb))) {
aa--; bb--; i--;
}
}
if (!carry) {
_ntl_zzero(cc);
return;
}
if (carry < 0) {
{ long t = sa; sa = sb; sb = t; }
{ long t = a_alias; a_alias = b_alias; b_alias = t; }
{ long *t = a; a = b; b = t; }
anegative = !anegative;
}
if (MustAlloc(c, sa)) {
_ntl_zsetlength(&c, sa);
/* must have !a_alias */
if (b_alias) b = c;
*cc = c;
}
i = sb;
carry = 0;
pc = c;
do {
#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
long t = (*(++a)) - (*(++b)) - carry;
carry = (t < 0);
#else
long t = (*(++a)) - (*(++b)) + carry;
carry = t >> NTL_NBITS;
#endif
*(++pc) = t & NTL_RADIXM;
i--;
} while (i);
i = sa-sb;
while (carry) {
long t = (*(++a)) - 1;
#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
carry = (t < 0);
#else
carry = t >> NTL_NBITS;
#endif
*(++pc) = t & NTL_RADIXM;
i--;
}
if (i) {
if (pc != a) {
do {
*(++pc) = *(++a);
i--;
} while (i);
}
}
else {
while (sa > 1 && *pc == 0) { sa--; pc--; }
}
if (anegative) sa = -sa;
*c = sa;
}
else {
/* signs of a and b are different...use _ntl_zadd */
if (anegative) {
a[0] = -sa;
_ntl_zadd(a, b, cc);
if (!a_alias) a[0] = sa;
c = *cc;
c[0] = -c[0];
}
else {
b[0] = -sb;
_ntl_zadd(a, b, cc);
if (!b_alias) b[0] = sb;
}
}
}
void
_ntl_zsmul(_ntl_verylong a, long d, _ntl_verylong *bb)
{
long sa;
long anegative, bnegative;
_ntl_verylong b;
long a_alias;
if (d == 2) {
_ntl_z2mul(a, bb);
return;
}
if ((d >= NTL_RADIX) || (d <= -NTL_RADIX)) {
static _ntl_verylong x = 0;
_ntl_zintoz(d,&x);
_ntl_zmul(a, x, bb);
return;
}
if (!a || (a[0] == 1 && a[1] == 0)) {
_ntl_zzero(bb);
return;
}
if (!d) {
_ntl_zzero(bb);
return;
}
/* both inputs non-zero */
anegative = 0;
bnegative = 0;
if ((sa = a[0]) < 0) {
anegative = 1;
a[0] = sa = (-sa);
if (d < 0)
d = (-d);
else
bnegative = 1;
}
else if (bnegative = (d < 0))
d = (-d);
b = *bb;
a_alias = (a == b);
if (MustAlloc(b, sa + 1)) {
_ntl_zsetlength(&b, sa + 1);
if (a_alias) a = b;
*bb = b;
}
zsxmul(d, b+1, a);
sa++;
while ((sa > 1) && (!(b[sa])))
sa--;
b[0] = sa;
if (bnegative)
b[0] = (-b[0]);
if (anegative && !a_alias)
a[0] = -a[0];
}
void _ntl_zsubpos(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *cc)
{
long sa;
long sb;
long *c, *pc;
long i, carry;
long b_alias;
if (!b) {
if (a)
_ntl_zcopy(a, cc);
else
_ntl_zzero(cc);
return;
}
if (!a) {
_ntl_zzero(cc);
return;
}
sa = a[0];
sb = b[0];
c = *cc;
b_alias = (b == c);
if (MustAlloc(c, sa)) {
_ntl_zsetlength(&c, sa);
if (b_alias) b = c;
*cc = c;
}
i = sb;
carry = 0;
pc = c;
while (i) {
#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
long t = (*(++a)) - (*(++b)) - carry;
carry = (t < 0);
#else
long t = (*(++a)) - (*(++b)) + carry;
carry = t >> NTL_NBITS;
#endif
*(++pc) = t & NTL_RADIXM;
i--;
}
i = sa-sb;
while (carry) {
long t = (*(++a)) - 1;
#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
carry = (t < 0);
#else
carry = t >> NTL_NBITS;
#endif
*(++pc) = t & NTL_RADIXM;
i--;
}
if (i) {
if (pc != a) {
do {
*(++pc) = *(++a);
i--;
} while (i);
}
}
else {
while (sa > 1 && *pc == 0) { sa--; pc--; }
}
*c = sa;
}
static long *kmem = 0; /* globals for Karatsuba */
static long max_kmem = 0;
/* These cross-over points were estimated using
a Sparc-10, a Sparc-20, and a Pentium-90. */
#if (defined(NTL_SINGLE_MUL))
#define KARX (18)
#else
#define KARX (16)
#endif
/* Auxilliary routines for Karatsuba */
static
void kar_fold(long *T, long *b, long hsa)
{
long sb, *p2, *p3, i, carry;
sb = *b;
p2 = b + hsa;
p3 = T;
carry = 0;
for (i = sb-hsa; i>0; i--) {
long t = (*(++b)) + (*(++p2)) + carry;
carry = t >> NTL_NBITS;
*(++p3) = t & NTL_RADIXM;
}
for (i = (hsa << 1) - sb; i>0; i--) {
long t = (*(++b)) + carry;
carry = t >> NTL_NBITS;
*(++p3) = t & NTL_RADIXM;
}
if (carry) {
*(++p3) = carry;
*T = hsa + 1;
}
else
*T = hsa;
}
static
void kar_sub(long *T, long *c)
{
long i, carry;
i = *c;
carry = 0;
while (i>0) {
#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
long t = (*(++T)) - (*(++c)) - carry;
carry = (t < 0);
#else
long t = (*(++T)) - (*(++c)) + carry;
carry = t >> NTL_NBITS;
#endif
*T = t & NTL_RADIXM;
i--;
}
while (carry) {
long t = (*(++T)) - 1;
#if (!NTL_ARITH_RIGHT_SHIFT || defined(NTL_CLEAN_INT))
carry = (t < 0);
#else
carry = t >> NTL_NBITS;
#endif
*T = t & NTL_RADIXM;
}
}
static
void kar_add(long *c, long *T, long hsa)
{
long i, carry;
c += hsa;
i = *T;
while (T[i] == 0 && i > 0) i--;
carry = 0;
while (i>0) {
long t = (*(++c)) + (*(++T)) + carry;
carry = t >> NTL_NBITS;
*c = t & NTL_RADIXM;
i--;
}
while (carry) {
long t = (*(++c)) + 1;
carry = t >> NTL_NBITS;
*c = t & NTL_RADIXM;
}
}
static
void kar_fix(long *c, long *T, long hsa)
{
long i, carry, s;
s = *T;
i = hsa;
while (i>0) {
*(++c) = *(++T);
i--;
}
i = s - hsa;
carry = 0;
while (i > 0) {
long t = (*(++c)) + (*(++T)) + carry;
carry = t >> NTL_NBITS;
*c = t & NTL_RADIXM;
i--;
}
while (carry) {
long t = (*(++c)) + 1;
carry = t >> NTL_NBITS;
*c = t & NTL_RADIXM;
}
}
static
void kar_mul(long *c, long *a, long *b, long *stk)
{
long sa, sb, sc;
if (*a < *b) { long *t = a; a = b; b = t; }
sa = *a;
sb = *b;
sc = sa + sb;
if (sb < KARX) {
/* classic algorithm */
long *pc, i, *pb;
pc = c;
for (i = sc; i; i--) {
pc++;
*pc = 0;
}
pc = c;
pb = b;
for (i = sb; i; i--) {
pb++;
pc++;
zaddmul(*pb, pc, a);
}
}
else {
long hsa = (sa + 1) >> 1;
if (hsa < sb) {
/* normal case */
long *T1, *T2, *T3;
/* allocate space */
T1 = stk; stk += hsa + 2;
T2 = stk; stk += hsa + 2;
T3 = stk; stk += (hsa << 1) + 3;
if (stk-kmem > max_kmem) zhalt("internal error: kmem overflow");
/* compute T1 = a_lo + a_hi */
kar_fold(T1, a, hsa);
/* compute T2 = b_lo + b_hi */
kar_fold(T2, b, hsa);
/* recursively compute T3 = T1 * T2 */
kar_mul(T3, T1, T2, stk);
/* recursively compute a_hi * b_hi into high part of c */
/* and subtract from T3 */
{
long olda, oldb;
olda = a[hsa]; a[hsa] = sa-hsa;
oldb = b[hsa]; b[hsa] = sb-hsa;
kar_mul(c + (hsa << 1), a + hsa, b + hsa, stk);
kar_sub(T3, c + (hsa << 1));
a[hsa] = olda;
b[hsa] = oldb;
}
/* recursively compute a_lo*b_lo into low part of c */
/* and subtract from T3 */
*a = hsa;
*b = hsa;
kar_mul(c, a, b, stk);
kar_sub(T3, c);
*a = sa;
*b = sb;
/* finally, add T3 * NTL_RADIX^{hsa} to c */
kar_add(c, T3, hsa);
}
else {
/* degenerate case */
long *T;
T = stk; stk += sb + hsa + 1;
if (stk-kmem > max_kmem) zhalt("internal error: kmem overflow");
/* recursively compute b*a_hi into high part of c */
{
long olda;
olda = a[hsa]; a[hsa] = sa-hsa;
kar_mul(c + hsa, a + hsa, b, stk);
a[hsa] = olda;
}
/* recursively compute b*a_lo into T
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -