long MP_modi(T x, long y) { assert(x); if (y == 0) RAISE(MP_Dividebyzero); else if (-BASE < y && y < BASE) { T z = tmp[2]; int r; int sx = sign(x), sy = y < 0; if (sx) { XP_neg(nbytes, tmp[0], x, 1); x = tmp[0]; x[nbytes-1] &= msb; } r = XP_quotient(nbytes, z, x, sy ? -y : y); if (sx != sy) { XP_neg(nbytes, z, z, 1); if (r != 0) { XP_diff(nbytes, z, z, 1); r = y - r; } z[nbytes-1] &= msb; } else if (sx && sign(z)) RAISE(MP_Overflow); if (nbits < 8 && (y < -(1<<(nbits-1)) || y >= (1<<(nbits-1)))) RAISE(MP_Overflow); return r; } else if (apply(MP_mod, tmp[2], x, y)) RAISE(MP_Overflow); return MP_toint(tmp[2]); }
T MP_div(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, z, x, nbytes, y, tmp[2], tmp[3])) RAISE(MP_Dividebyzero); if (sx != sy) { XP_neg(nbytes, z, z, 1); if (!iszero(tmp[2])) XP_diff(nbytes, z, z, 1); z[nbytes-1] &= msb; } else if (sx && sign(z)) 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_subui(T z, T x, unsigned long y) { assert(x); assert(z); if (y < BASE) { int borrow = XP_diff(nbytes, z, x, y); borrow |= z[nbytes-1]&~msb; z[nbytes-1] &= msb; if (borrow) RAISE(MP_Overflow); } else if (applyu(MP_subu, z, x, y)) RAISE(MP_Overflow); return z; }
T MP_subi(T z, T x, long y) { assert(x); assert(z); if (-BASE < y && y < BASE) { int sx = sign(x), sy = y < 0; if (sy) XP_sum (nbytes, z, x, -y); else XP_diff(nbytes, z, x, y); z[nbytes-1] &= msb; if (sx != sy && sy == sign(z)) RAISE(MP_Overflow); if (nbits < 8 && (y < -(1<<(nbits-1)) || y >= (1<<(nbits-1)))) RAISE(MP_Overflow); } else if (apply(MP_sub, z, x, y)) RAISE(MP_Overflow); return z; }