Ejemplo n.º 1
0
inline void ObNumber::div_uint32(const ObNumber &dividend, uint32_t divisor, ObNumber &quotient, ObNumber &remainder)
{
    OB_ASSERT(0 < dividend.nwords_);
    OB_ASSERT(MAX_NWORDS >= dividend.nwords_);
    OB_ASSERT(0 < divisor);
    int64_t carry = 0;
    for (int i = dividend.nwords_ - 1; i >= 0; --i)
    {
        carry = carry * BASE + dividend.words_[i];
        quotient.words_[i] = static_cast<uint32_t> (carry / divisor);
        carry = carry % divisor;
    }
    quotient.nwords_ = dividend.nwords_;
    quotient.remove_leading_zeroes();

    if (0 == carry)
    {
        remainder.set_zero(); // remainder is zero
    }
    else
    {
        remainder.words_[0] = static_cast<uint32_t> (carry);
        remainder.nwords_ = 1;
    }
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
int ObNumber::negate(ObNumber &res) const
{
    int ret = OB_SUCCESS;
    if (this->nwords_ >= MAX_NWORDS)
    {
        jlog(WARNING, "value out of range to do negate");
        ret = JD_VALUE_OUT_OF_RANGE;
    }
    else
    {
        res = *this;
        res.extend_words(static_cast<int8_t> (this->nwords_ + 1));
        negate(res, res);
        res.remove_leading_zeroes();
    }
    return ret;
}
Ejemplo n.º 4
0
int ObNumber::round_to(int8_t precision, int8_t scale, int8_t &nwords, int8_t &vscale, uint32_t *words) const
{
    OB_ASSERT(precision >= scale && 0 <= scale && NULL != words);
    int ret = OB_SUCCESS;
    ObNumber clone = *this;
    bool is_neg = is_negative();
    if (is_neg)
    {
        negate(clone, clone);
    }
    if (clone.vscale_ > scale)
    {
        clone.right_shift(static_cast<int8_t> (clone.vscale_ - scale));
        clone.remove_leading_zeroes();
    }
    ObNumber clone_clone = clone;
    int8_t vprec = 0;
    ObNumber remainder;
    while (!clone_clone.is_zero())
    {
        div_uint32(clone_clone, 10, clone_clone, remainder);
        clone_clone.remove_leading_zeroes();
        ++vprec;
    }
    if (vprec > precision)
    {
        ret = JD_VALUE_OUT_OF_RANGE;
        jlog(WARNING, "value is not representable with the precision and scale, p=%hhd s=%hhd vp=%hhd vs=%hhd",
                precision, scale, vprec, this->vscale_);
    }
    else
    {
        if (is_neg)
        {
            negate(clone, clone);
        }
        nwords = clone.nwords_;
        vscale = clone.vscale_;
        for (int8_t i = 0; i < clone.nwords_; ++i)
        {
            words[i] = clone.words_[i];
        }
    }
    return ret;
}
Ejemplo n.º 5
0
int ObNumber::add(const ObNumber &other, ObNumber &res) const
{
    int ret = OB_SUCCESS;
    res.set_zero();
    ObNumber n1 = *this;
    ObNumber n2 = other;
    if (n1.vscale_ > SINGLE_PRECISION_NDIGITS)
    {
        n1.round_fraction_part(SINGLE_PRECISION_NDIGITS);
    }
    if (n2.vscale_ > SINGLE_PRECISION_NDIGITS)
    {
        n2.round_fraction_part(SINGLE_PRECISION_NDIGITS);
    }
    int8_t res_nwords = static_cast<int8_t> (std::max(n1.nwords_, n2.nwords_) + 1);
    if (res_nwords > MAX_NWORDS)
    {
        jlog(WARNING, "number out of range");
        ret = JD_VALUE_OUT_OF_RANGE;
    }
    else
    {
        n1.extend_words(res_nwords);
        n2.extend_words(res_nwords);
    }
    if (n1.vscale_ > n2.vscale_)
    {
        ret = n2.left_shift(static_cast<int8_t> (n1.vscale_ - n2.vscale_), false);
    }
    else if (n1.vscale_ < n2.vscale_)
    {
        ret = n1.left_shift(static_cast<int8_t> (n2.vscale_ - n1.vscale_), false);
    }
    if (OB_SUCCESS == ret)
    {
        add_words(n1, n2, res);
        res.remove_leading_zeroes();
    }
    return ret;
}
Ejemplo n.º 6
0
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;
}