📄 g_lip_impl.h
字号:
if (ZEROP(a)) {
_ntl_gcopy(b, cc);
return;
}
if (ZEROP(b)) {
_ntl_gcopy(a, cc);
return;
}
GET_SIZE_NEG(sa, aneg, a);
GET_SIZE_NEG(sb, bneg, b);
if (sa < sb) {
SWAP_BIGINT(a, b);
SWAP_LONG(sa, sb);
SWAP_LONG(aneg, bneg);
}
/* sa >= sb */
c = *cc;
a_alias = (a == c);
b_alias = (b == c);
if (aneg == bneg) {
/* same sign => addition */
sc = sa + 1;
if (MustAlloc(c, sc)) {
_ntl_gsetlength(&c, sc);
if (a_alias) a = c;
if (b_alias) b = c;
*cc = c;
}
adata = DATA(a);
bdata = DATA(b);
cdata = DATA(c);
carry = mpn_add(cdata, adata, sa, bdata, sb);
if (carry)
cdata[sc-1] = carry;
else
sc--;
if (aneg) sc = -sc;
SIZE(c) = sc;
}
else {
/* opposite sign => subtraction */
sc = sa;
if (MustAlloc(c, sc)) {
_ntl_gsetlength(&c, sc);
if (a_alias) a = c;
if (b_alias) b = c;
*cc = c;
}
adata = DATA(a);
bdata = DATA(b);
cdata = DATA(c);
if (sa > sb)
cmp = 1;
else
cmp = mpn_cmp(adata, bdata, sa);
if (cmp == 0) {
SIZE(c) = 0;
}
else {
if (cmp < 0) cmp = 0;
if (cmp > 0) cmp = 1;
/* abs(a) != abs(b) && (abs(a) > abs(b) <=> cmp) */
if (cmp)
mpn_sub(cdata, adata, sa, bdata, sb);
else
mpn_sub(cdata, bdata, sb, adata, sa); /* sa == sb */
STRIP(sc, cdata);
if (aneg == cmp) sc = -sc;
SIZE(c) = sc;
}
}
}
void
_ntl_gsadd(_ntl_gbigint a, long b, _ntl_gbigint *cc)
{
static _ntl_gbigint B = 0;
_ntl_gintoz(b, &B);
_ntl_gadd(a, B, cc);
}
void
_ntl_gsub(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
{
long sa, aneg, sb, bneg, sc, cmp, rev;
mp_limb_t *adata, *bdata, *cdata, carry;
_ntl_gbigint c;
long a_alias, b_alias;
if (ZEROP(a)) {
_ntl_gcopy(b, cc);
c = *cc;
if (c) SIZE(c) = -SIZE(c);
return;
}
if (ZEROP(b)) {
_ntl_gcopy(a, cc);
return;
}
GET_SIZE_NEG(sa, aneg, a);
GET_SIZE_NEG(sb, bneg, b);
if (sa < sb) {
SWAP_BIGINT(a, b);
SWAP_LONG(sa, sb);
SWAP_LONG(aneg, bneg);
rev = 1;
}
else
rev = 0;
/* sa >= sb */
c = *cc;
a_alias = (a == c);
b_alias = (b == c);
if (aneg != bneg) {
/* opposite sign => addition */
sc = sa + 1;
if (MustAlloc(c, sc)) {
_ntl_gsetlength(&c, sc);
if (a_alias) a = c;
if (b_alias) b = c;
*cc = c;
}
adata = DATA(a);
bdata = DATA(b);
cdata = DATA(c);
carry = mpn_add(cdata, adata, sa, bdata, sb);
if (carry)
cdata[sc-1] = carry;
else
sc--;
if (aneg ^ rev) sc = -sc;
SIZE(c) = sc;
}
else {
/* same sign => subtraction */
sc = sa;
if (MustAlloc(c, sc)) {
_ntl_gsetlength(&c, sc);
if (a_alias) a = c;
if (b_alias) b = c;
*cc = c;
}
adata = DATA(a);
bdata = DATA(b);
cdata = DATA(c);
if (sa > sb)
cmp = 1;
else
cmp = mpn_cmp(adata, bdata, sa);
if (cmp == 0) {
SIZE(c) = 0;
}
else {
if (cmp < 0) cmp = 0;
if (cmp > 0) cmp = 1;
/* abs(a) != abs(b) && (abs(a) > abs(b) <=> cmp) */
if (cmp)
mpn_sub(cdata, adata, sa, bdata, sb);
else
mpn_sub(cdata, bdata, sb, adata, sa); /* sa == sb */
STRIP(sc, cdata);
if ((aneg == cmp) ^ rev) sc = -sc;
SIZE(c) = sc;
}
}
}
void
_ntl_gsubpos(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
{
long sa, sb, sc;
mp_limb_t *adata, *bdata, *cdata;
_ntl_gbigint c;
long a_alias, b_alias;
if (ZEROP(a)) {
_ntl_gzero(cc);
return;
}
if (ZEROP(b)) {
_ntl_gcopy(a, cc);
return;
}
sa = SIZE(a);
sb = SIZE(b);
c = *cc;
a_alias = (a == c);
b_alias = (b == c);
sc = sa;
if (MustAlloc(c, sc)) {
_ntl_gsetlength(&c, sc);
if (a_alias) a = c;
if (b_alias) b = c;
*cc = c;
}
adata = DATA(a);
bdata = DATA(b);
cdata = DATA(c);
mpn_sub(cdata, adata, sa, bdata, sb);
STRIP(sc, cdata);
SIZE(c) = sc;
}
void _ntl_gmul(_ntl_gbigint a, _ntl_gbigint b, _ntl_gbigint *cc)
{
static _ntl_gbigint mem = 0;
long sa, aneg, sb, bneg, alias, sc;
mp_limb_t *adata, *bdata, *cdata, msl;
_ntl_gbigint c;
if (ZEROP(a) || ZEROP(b)) {
_ntl_gzero(cc);
return;
}
GET_SIZE_NEG(sa, aneg, a);
GET_SIZE_NEG(sb, bneg, b);
if (a == *cc || b == *cc) {
c = mem;
alias = 1;
}
else {
c = *cc;
alias = 0;
}
sc = sa + sb;
if (MustAlloc(c, sc))
_ntl_gsetlength(&c, sc);
if (alias)
mem = c;
else
*cc = c;
adata = DATA(a);
bdata = DATA(b);
cdata = DATA(c);
if (sa >= sb)
msl = mpn_mul(cdata, adata, sa, bdata, sb);
else
msl = mpn_mul(cdata, bdata, sb, adata, sa);
if (!msl) sc--;
if (aneg != bneg) sc = -sc;
SIZE(c) = sc;
if (alias) _ntl_gcopy(mem, cc);
}
void _ntl_gsq(_ntl_gbigint a, _ntl_gbigint *cc)
{
_ntl_gmul(a, a, cc);
/* this is good enough...eventually, mpn_sqr_n will be called */
}
/*
* DIRT: this implementation of _ntl_gsmul relies crucially
* on the assumption that the number of bits per limb_t is at least
* equal to the number of bits per long.
*/
void
_ntl_gsmul(_ntl_gbigint a, long d, _ntl_gbigint *bb)
{
long sa, sb;
long anegative, bnegative;
_ntl_gbigint b;
mp_limb_t *adata, *bdata;
mp_limb_t dd, carry;
long a_alias;
if (ZEROP(a) || !d) {
_ntl_gzero(bb);
return;
}
GET_SIZE_NEG(sa, anegative, a);
if (d < 0) {
dd = - ((mp_limb_t) d); /* careful ! */
bnegative = 1-anegative;
}
else {
dd = (mp_limb_t) d;
bnegative = anegative;
}
sb = sa + 1;
b = *bb;
a_alias = (a == b);
if (MustAlloc(b, sb)) {
_ntl_gsetlength(&b, sb);
if (a_alias) a = b;
*bb = b;
}
adata = DATA(a);
bdata = DATA(b);
if (dd == 2)
carry = mpn_lshift(bdata, adata, sa, 1);
else
carry = mpn_mul_1(bdata, adata, sa, dd);
if (carry)
bdata[sa] = carry;
else
sb--;
if (bnegative) sb = -sb;
SIZE(b) = sb;
}
/*
* DIRT: this implementation of _ntl_gsdiv relies crucially
* on the assumption that the number of bits per limb_t is at least
* equal to the number of bits per long.
*/
long _ntl_gsdiv(_ntl_gbigint a, long d, _ntl_gbigint *bb)
{
long sa, aneg, sb, dneg;
_ntl_gbigint b;
mp_limb_t dd, *adata, *bdata;
long r;
if (!d) {
ghalt("division by zero in _ntl_gsdiv");
}
if (ZEROP(a)) {
_ntl_gzero(bb);
return (0);
}
GET_SIZE_NEG(sa, aneg, a);
if (d < 0) {
dd = - ((mp_limb_t) d); /* careful ! */
dneg = 1;
}
else {
dd = (mp_limb_t) d;
dneg = 0;
}
sb = sa;
b = *bb;
if (MustAlloc(b, sb)) {
/* if b aliases a, then b won't move */
_ntl_gsetlength(&b, sb);
*bb = b;
}
adata = DATA(a);
bdata = DATA(b);
if (dd == 2)
r = mpn_rshift(bdata, adata, sa, 1) >> (NTL_ZZ_NBITS - 1);
else
r = mpn_divmod_1(bdata, adata, sa, dd);
if (bdata[sb-1] == 0)
sb--;
SIZE(b) = sb;
if (aneg || dneg) {
if (aneg != dneg) {
if (!r) {
SIZE(b) = -SIZE(b);
}
else {
_ntl_gsadd(b, 1, &b);
SIZE(b) = -SIZE(b);
if (dneg)
r = r + d;
else
r = d - r;
*bb = b;
}
}
else
r = -r;
}
return r;
}
/*
* DIRT: this implementation of _ntl_gsmod relies crucially
* on the assumption that the number of bits per limb_t is at least
* equal to the number of bits per long.
*/
long _ntl_gsmod(_ntl_gbigint a, long d)
{
long sa, aneg, dneg;
mp_limb_t dd, *adata;
long r;
if (!d) {
ghalt("division by zero in _ntl_gsmod");
}
if (ZEROP(a)) {
return (0);
}
GET_SIZE_NEG(sa, aneg, a);
if (d < 0) {
dd = - ((mp_limb_t) d); /* careful ! */
dneg = 1;
}
else {
dd = (mp_limb_t) d;
dneg = 0;
}
adata = DATA(a);
if (dd == 2)
r = adata[0] & 1;
else
r = mpn_mod_1(adata, sa, dd);
if (aneg || dneg) {
if (aneg != dneg) {
if (r) {
if (dneg)
r = r + d;
else
r = d - r;
}
}
else
r = -r;
}
return r;
}
void _ntl_gdiv(_ntl_gbigint a, _ntl_gbigint d,
_ntl_gbigint *bb, _ntl_gbigint *rr)
{
static _ntl_gbigint b = 0, rmem = 0;
_ntl_gbigint r;
long sa, aneg, sb, sd, dneg, sr, in_place;
mp_limb_t *adata, *ddata, *bdata, *rdata;
if (ZEROP(d)) {
ghalt("division by zero in _ntl_gdiv");
}
if (ZEROP(a)) {
if (bb) _ntl_gzero(bb);
if (rr) _ntl_gzero(rr);
return;
}
GET_SIZE_NEG(sa, aneg, a);
GET_SIZE_NEG(sd, dneg, d);
if (!aneg && !dneg && rr && *rr != a && *rr != d) {
in_place = 1;
r = *rr;
}
else {
in_place = 0;
r = rmem;
}
if (sa < sd) {
_ntl_gzero(&b);
_ntl_gcopy(a, &r);
if (aneg) SIZE(r) = -SIZE(r);
goto done;
}
sb = sa-sd+1;
if (MustAlloc(b, sb))
_ntl_gsetlength(&b, sb);
sr = sd;
if (MustAlloc(r, sr))
_ntl_gsetlength(&r, sr);
adata = DATA(a);
ddata = DATA(d);
bdata = DATA(b);
rdata = DATA(r);
mpn_tdiv_qr(bdata, rdata, 0, adata, sa, ddata, sd);
if (bdata[sb-1] == 0)
sb--;
SIZE(b) = sb;
STRIP(sr, rdata);
SIZE(r) = sr;
done:
if (aneg || dneg) {
if (aneg != dneg) {
if (ZEROP(r)) {
SIZE(b) = -SIZE(b);
}
else {
if (bb) {
_ntl_gsadd(b, 1, &b);
SIZE(b) = -SIZE(b);
}
if (rr) {
if (dneg)
_ntl_gadd(r, d, &r);
else
_ntl_gsub(d, r, &r);
}
}
}
else
SIZE(r) = -SIZE(r);
}
if (bb) _ntl_gcopy(b, bb);
if (in_place)
*rr = r;
else {
if (rr) _ntl_gcopy(r, rr);
rmem = r;
}
}
/* a simplified mod operation: assumes a >= 0, d > 0 are non-negative,
* that space for the result has already been allocated,
* and that inputs do not alias output. */
static
void gmod_simple(_ntl_gbigint a, _ntl_gbigint d, _ntl_gbigint *rr)
{
static _ntl_gbigint b = 0;
long sa, sb, sd, sr;
mp_limb_t *adata, *ddata, *bdata, *rdata;
_ntl_gbigint r;
if (ZEROP(a)) {
_ntl_gzero(rr);
return;
}
sa = SIZE(a);
sd = SIZE(d);
if (sa < sd) {
_ntl_gcopy(a, rr);
return;
}
sb = sa-sd+1;
if (MustAlloc(b, sb))
_ntl_gsetlength(&b, sb);
sr = sd;
r = *rr;
adata = DATA(a);
ddata = DATA(d);
bdata = DATA(b);
rdata = DATA(r);
mpn_tdiv_qr(bdata, rdata, 0, adata, sa, ddata, sd);
STRIP(sr, rdata);
SIZE(r) = sr;
}
void _ntl_gmod(_ntl_gbigint a, _ntl_gbigint d, _ntl_gbigint *rr)
{
_ntl_gdiv(a, d, 0, rr);
}
void _ntl_gquickmod(_ntl_gbigint *rr, _ntl_gbigint d)
{
_ntl_gdiv(*rr, d, 0, rr);
}
void _ntl_gsqrt(_ntl_gbigint n, _ntl_gbigint *rr)
{
static _ntl_gbigint r = 0;
long sn, sr;
mp_limb_t *ndata, *rdata;
if (ZEROP(n)) {
_ntl_gzero(rr);
return;
}
sn = SIZE(n);
if (sn < 0) ghalt("negative argument to _ntl_sqrt");
sr = (sn+1)/2;
_ntl_gsetlength(&r, sr);
ndata = DATA(n);
rdata = DATA(r);
mpn_sqrtrem(rdata, 0, ndata, sn);
STRIP(sr, rdata);
SIZE(r) = sr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -