T MP_mod(T z, T x, T y) { int sx, sy; assert(x); assert(y); assert(z); sx = sign(x); sy = sign(y); if (sx) { XP_neg(nbytes, tmp[0], x, 1); x = tmp[0]; x[nbytes-1] &= msb; } if (sy) { XP_neg(nbytes, tmp[1], y, 1); y = tmp[1]; y[nbytes-1] &= msb; } else { memcpy(tmp[1], y, nbytes); y = tmp[1]; } if (!XP_div(nbytes, tmp[2], x, nbytes, y, z, tmp[3])) RAISE(MP_Dividebyzero); if (sx != sy) { if (!iszero(z)) XP_sub(nbytes, z, y, z, 0); } else if (sx && sign(tmp[2])) RAISE(MP_Overflow); return z; }
T AP_mod(T x, T y) { T q, r; assert(x); assert(y); assert(!iszero(y)); q = mk(x->ndigits); r = mk(y->ndigits); { XP_T tmp = ALLOC(x->ndigits + y->ndigits + 2); XP_div(x->ndigits, q->digits, x->digits, y->ndigits, y->digits, r->digits, tmp); FREE(tmp); } normalize(q, q->size); normalize(r, r->size); q->sign = iszero(q) || ((x->sign^y->sign) == 0) ? 1 : -1; if (!((x->sign^y->sign) == 0) && !iszero(r)) { int borrow = XP_sub(r->size, r->digits, y->digits, r->digits, 0); assert(borrow == 0); normalize(r, r->size); } AP_free(&q); return r; }
T MP_subu(T z, T x, T y) { int borrow; assert(x); assert(y); assert(z); borrow = XP_sub(nbytes, z, x, y, 0); borrow |= z[nbytes-1]&~msb; z[nbytes-1] &= msb; if (borrow) RAISE(MP_Overflow); return z; }
static T sub(T z, T x, T y) { int borrow, n = y->ndigits; borrow = XP_sub(n, z->digits, x->digits, y->digits, 0); if (x->ndigits > n) borrow = XP_diff(x->ndigits - n, &z->digits[n], &x->digits[n], borrow); assert(borrow == 0); return normalize(z, z->size); }
T MP_sub(T z, T x, T y) { int sx, sy; assert(x); assert(y); assert(z); sx = sign(x); sy = sign(y); XP_sub(nbytes, z, x, y, 0); z[nbytes-1] &= msb; if (sx != sy && sy == sign(z)) RAISE(MP_Overflow); return z; }