📄 integer.cc
字号:
q = Icopy_one(q, samesign); } else if (yl == 1) { q = Icopy(q, x); unscale(q->s, q->len, ys[0], q->s); } else { IntRep* r = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, ys, yl, q->s, ql); if (!STATIC_IntRep(r)) delete r; } q->sgn = samesign; Icheck(q); return q;}void divide(const gInteger& Ix, long y, gInteger& Iq, long& rem){ const IntRep* x = Ix.rep; nonnil(x); IntRep* q = Iq.rep; int xl = x->len; // if (y == 0) (*lib_error_handler)("gInteger", "attempted division by zero"); assert(y != 0); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; int samesign = xsgn == ysgn; if (comp < 0) { rem = Itolong(x); q = Icopy_zero(q); } else if (comp == 0) { q = Icopy_one(q, samesign); rem = 0; } else if (yl == 1) { q = Icopy(q, x); rem = unscale(q->s, q->len, ys[0], q->s); } else { IntRep* r = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, ys, yl, q->s, ql); if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } Icheck(r); rem = Itolong(r); if (!STATIC_IntRep(r)) delete r; } rem = abs(rem); if (xsgn == I_NEGATIVE) rem = -rem; q->sgn = samesign; Icheck(q); Iq.rep = q;}void divide(const gInteger& Ix, const gInteger& Iy, gInteger& Iq, gInteger& Ir){ const IntRep* x = Ix.rep; nonnil(x); const IntRep* y = Iy.rep; nonnil(y); IntRep* q = Iq.rep; IntRep* r = Ir.rep; int xl = x->len; int yl = y->len; /* if (yl == 0) (*lib_error_handler)("gInteger", "attempted division by zero"); */ assert(yl != 0); int comp = ucompare(x, y); int xsgn = x->sgn; int ysgn = y->sgn; int samesign = xsgn == ysgn; if (comp < 0) { q = Icopy_zero(q); r = Icopy(r, x); } else if (comp == 0) { q = Icopy_one(q, samesign); r = Icopy_zero(r); } else if (yl == 1) { q = Icopy(q, x); int rem = unscale(q->s, q->len, y->s[0], q->s); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { IntRep* yy = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == q || y == r) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntRep*)y; r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, yy->s, yl, q->s, ql); if (yy != y && !STATIC_IntRep(yy)) delete yy; if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } q->sgn = samesign; Icheck(q); Iq.rep = q; Icheck(r); Ir.rep = r;}IntRep* mod(const IntRep* x, const IntRep* y, IntRep* r){ nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; // if (yl == 0) (*lib_error_handler)("gInteger", "attempted division by zero"); assert(yl != 0); int comp = ucompare(x, y); int xsgn = x->sgn; if (comp < 0) r = Icopy(r, x); else if (comp == 0) r = Icopy_zero(r); else if (yl == 1) { int rem = unscale(x->s, xl, y->s[0], 0); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { IntRep* yy = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == r) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntRep*)y; r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } do_divide(r->s, yy->s, yl, 0, xl - yl + 1); if (yy != y && !STATIC_IntRep(yy)) delete yy; if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } Icheck(r); return r;}IntRep* mod(const IntRep* x, long y, IntRep* r){ nonnil(x); int xl = x->len; // if (y == 0) (*lib_error_handler)("gInteger", "attempted division by zero"); assert(y != 0); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; if (comp < 0) r = Icopy(r, x); else if (comp == 0) r = Icopy_zero(r); else if (yl == 1) { int rem = unscale(x->s, xl, ys[0], 0); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { unsigned short prescale = (unsigned short) (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } do_divide(r->s, ys, yl, 0, xl - yl + 1); if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } Icheck(r); return r;}IntRep* lshift(const IntRep* x, long y, IntRep* r){ nonnil(x); int xl = x->len; if (xl == 0 || y == 0) { r = Icopy(r, x); return r; } int xrsame = x == r; int rsgn = x->sgn; long ay = (y < 0)? -y : y; int bw = (int) (ay / I_SHIFT); int sw = (int) (ay % I_SHIFT); if (y > 0) { int rl = bw + xl + 1; if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); unsigned short* botr = r->s; unsigned short* rs = &(botr[rl - 1]); const unsigned short* botx = (xrsame)? botr : x->s; const unsigned short* xs = &(botx[xl - 1]); unsigned long a = 0; while (xs >= botx) { a = up(a) | ((unsigned long)(*xs--) << sw); *rs-- = extract(down(a)); } *rs-- = extract(a); while (rs >= botr) *rs-- = 0; } else { int rl = xl - bw; if (rl < 0) r = Icopy_zero(r); else { if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); int rw = I_SHIFT - sw; unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); const unsigned short* botx = (xrsame)? rs : x->s; const unsigned short* xs = &(botx[bw]); const unsigned short* topx = &(botx[xl]); unsigned long a = (unsigned long)(*xs++) >> sw; while (xs < topx) { a |= (unsigned long)(*xs++) << rw; *rs++ = extract(a); a = down(a); } *rs++ = extract(a); if (xrsame) topr = (unsigned short*)topx; while (rs < topr) *rs++ = 0; } } r->sgn = rsgn; Icheck(r); return r;}IntRep* lshift(const IntRep* x, const IntRep* yy, int negatey, IntRep* r){ long y = Itolong(yy); if (negatey) y = -y; return lshift(x, y, r);}IntRep* bitop(const IntRep* x, const IntRep* y, IntRep* r, char op){ nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; int xsgn = x->sgn; int xrsame = x == r; int yrsame = y == r; if (xrsame || yrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); r->sgn = xsgn; unsigned short* rs = r->s; unsigned short* topr = &(rs[r->len]); const unsigned short* as; const unsigned short* bs; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? rs : x->s; bs = (yrsame)? rs : y->s; topb = &(bs[yl]); } else { bs = (xrsame)? rs : x->s; topb = &(bs[xl]); as = (yrsame)? rs : y->s; } switch (op) { case '&': while (bs < topb) *rs++ = *as++ & *bs++; while (rs < topr) *rs++ = 0; break; case '|': while (bs < topb) *rs++ = *as++ | *bs++; while (rs < topr) *rs++ = *as++; break; case '^': while (bs < topb) *rs++ = *as++ ^ *bs++; while (rs < topr) *rs++ = *as++; break; } Icheck(r); return r;}IntRep* bitop(const IntRep* x, long y, IntRep* r, char op){ nonnil(x); unsigned short tmp[SHORT_PER_LONG]; unsigned long u; int newsgn = (y >= 0); if (newsgn) u = y; else u = -y; int l = 0; while (u != 0) { tmp[l++] = extract(u); u = down(u); } int xl = x->len; int yl = l; int xsgn = x->sgn; int xrsame = x == r; if (xrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); r->sgn = xsgn; unsigned short* rs = r->s; unsigned short* topr = &(rs[r->len]); const unsigned short* as; const unsigned short* bs; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? rs : x->s; bs = tmp; topb = &(bs[yl]); } else { bs = (xrsame)? rs : x->s; topb = &(bs[xl]); as = tmp; } switch (op) { case '&': while (bs < topb) *rs++ = *as++ & *bs++; while (rs < topr) *rs++ = 0; break; case '|': while (bs < topb) *rs++ = *as++ | *bs++; while (rs < topr) *rs++ = *as++; break; case '^': while (bs < topb) *rs++ = *as++ ^ *bs++; while (rs < topr) *rs++ = *as++; break; } Icheck(r); return r;}IntRep* Compl(const IntRep* src, IntRep* r){ nonnil(src); r = Icopy(r, src); unsigned short* s = r->s; unsigned short* top = &(s[r->len - 1]); while (s < top) { unsigned short cmp = ~(*s); *s++ = cmp; } unsigned short a = *s; unsigned short b = 0; while (a != 0) { b <<= 1; if (!(a & 1)) b |= 1; a >>= 1; } *s = b; Icheck(r); return r;}void (setbit)(gInteger& x, long b){ if (b >= 0) { int bw = (int) ((unsigned long)b / I_SHIFT); int sw = (int) ((unsigned long)b % I_SHIFT); int xl = x.rep ? x.rep->len : 0; if (xl <= bw) x.rep = Iresize(x.rep, calc_len(xl, bw+1, 0)); x.rep->s[bw] |= (1 << sw); Icheck(x.rep); }}void clearbit(gInteger& x, long b){ if (b >= 0) { if (x.rep == 0) x.rep = &_ZeroRep; else { int bw = (int) ((unsigned long)b / I_SHIFT); int sw = (int) ((unsigned long)b % I_SHIFT); if (x.rep->len > bw) x.rep->s[bw] &= ~(1 << sw); } Icheck(x.rep); }}int testbit(const gInteger& x, long b){ if (x.rep != 0 && b >= 0) { int bw = (int) ((unsigned long)b / I_SHIFT); int sw = (int) ((unsigned long)b % I_SHIFT); return (bw < x.rep->len && (x.rep->s[bw] & (1 << sw)) != 0); } else return 0;}// A version of knuth's algorithm B / ex. 4.5.3.34// A better version that doesn't bother shifting all of `t' forthcomingIntRep* gcd(const IntRep* x, const IntRep* y){ nonnil(x); nonnil(y); int ul = x->len; int vl = y->len; if (vl == 0) return Ialloc(0, x->s, ul, I_POSITIVE, ul); else if (ul == 0) return Ialloc(0, y->s, vl, I_POSITIVE, vl); IntRep* u = Ialloc(0, x->s, ul, I_POSITIVE, ul); IntRep* v = Ialloc(0, y->s, vl, I_POSITIVE, vl);// find shift so that both not even long k = 0; int l = (ul <= vl)? ul : vl; int cont = 1, i; for (i = 0; i < l && cont; ++i) { unsigned long a = (i < ul)? u->s[i] : 0; unsigned long b = (i < vl)? v->s[i] : 0; for (unsigned int j = 0; j < I_SHIFT; ++j) { if ((a | b) & 1) { cont = 0; break; } else { ++k; a >>= 1; b >>= 1; } } } if (k != 0) { u = lshift(u, -k, u); v = lshift(v, -k, v); } IntRep* t; if (u->s[0] & 01) t = Ialloc(0, v->s, v->len, !v->sgn, v->len); else t = Ialloc(0, u->s, u->len, u->sgn, u->len); while (t->len != 0) { long s = 0; // shift t until odd cont = 1; int tl = t->len; for (i = 0; i < tl && cont; ++i) { unsigned long a = t->s[i]; for (unsigned int j = 0; j < I_SHIFT; ++j) { if (a & 1) { cont = 0; break; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -