int ObNumber::div(const ObNumber &other, ObNumber &res) const { int ret = OB_SUCCESS; res.set_zero(); if (other.is_zero()) { jlog(WARNING, "divisor is zero"); ret = JD_DIVISION_BY_ZERO; } else if (!this->is_zero()) { res.vscale_ = QUOTIENT_SCALE; ObNumber dividend = *this; ObNumber divisor = other; ObNumber remainder; bool res_is_neg = false; if (dividend.is_negative()) { negate(dividend, dividend); res_is_neg = true; } if (dividend.vscale_ > DOUBLE_PRECISION_NDIGITS) { dividend.round_fraction_part(DOUBLE_PRECISION_NDIGITS); } if (divisor.vscale_ > SINGLE_PRECISION_NDIGITS) { divisor.round_fraction_part(SINGLE_PRECISION_NDIGITS); } if (dividend.vscale_ < divisor.vscale_ || res.vscale_ > dividend.vscale_ - divisor.vscale_) { if (OB_SUCCESS != (ret = dividend.left_shift(static_cast<int8_t> (res.vscale_ + divisor.vscale_ - dividend.vscale_), true))) { jlog(WARNING, "left shift overflow, err=%d res_vscale=%hhd other_vscale=%hhd this_vscale=%hhd", ret, res.vscale_, divisor.vscale_, dividend.vscale_); } } if (OB_LIKELY(OB_SUCCESS == ret)) { if (divisor.is_negative()) { negate(divisor, divisor); res_is_neg = !res_is_neg; } divisor.remove_leading_zeroes_unsigned(); div_words(dividend, divisor, res, remainder); if (OB_UNLIKELY(res_is_neg)) { negate(res, res); } res.remove_leading_zeroes(); } } return ret; }
int ObNumber::mul(const ObNumber &other, ObNumber &res) const { int ret = OB_SUCCESS; res.set_zero(); if (!this->is_zero() && !other.is_zero()) { ObNumber multiplicand = *this; ObNumber multiplier = other; bool res_is_neg = false; if (multiplicand.is_negative()) { negate(multiplicand, multiplicand); res_is_neg = true; } if (multiplier.is_negative()) { negate(multiplier, multiplier); res_is_neg = !res_is_neg; } if (multiplicand.vscale_ > SINGLE_PRECISION_NDIGITS) { multiplicand.round_fraction_part(SINGLE_PRECISION_NDIGITS); } if (multiplier.vscale_ > SINGLE_PRECISION_NDIGITS) { multiplier.round_fraction_part(SINGLE_PRECISION_NDIGITS); } res.vscale_ = static_cast<int8_t> (multiplicand.vscale_ + multiplier.vscale_); ret = mul_words(multiplicand, multiplier, res); res.remove_leading_zeroes(); if (res_is_neg) { negate(res, res); } } return ret; }
int ObNumber::compare(const ObNumber &other) const { int ret = 0; ObNumber res; if (OB_SUCCESS != this->sub(other, res)) { // return 0 even if error occur } else if (res.is_negative()) { ret = -1; } else if (!res.is_zero()) { ret = 1; } return ret; }