Esempio n. 1
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;
}
Esempio n. 2
0
int ObNumber::cast_to_int64(int64_t &i64) const
{
    int ret = OB_SUCCESS;
    i64 = 0;
    bool is_neg = is_negative();
    ObNumber pos_clone = *this;
    if (is_neg)
    {
        negate(*this, pos_clone);
    }

    ObNumber remainder;
    int vscale = vscale_;
    int digits[DOUBLE_PRECISION_NDIGITS];
    int digit_idx = DOUBLE_PRECISION_NDIGITS - 1;
    while (!pos_clone.is_zero())
    {
        div_uint32(pos_clone, 10, pos_clone, remainder);
        if (vscale > 0)
        {
            vscale--;
        }
        else
        {
            OB_ASSERT(digit_idx >= 0);
            if (remainder.is_zero())
            {
                digits[digit_idx--] = 0;
            }
            else
            {
                OB_ASSERT(1 == remainder.nwords_);
                OB_ASSERT(remainder.words_[0] < 10 && remainder.words_[0] > 0);
                digits[digit_idx--] = remainder.words_[0];
            }
        } // end while
    }
    OB_ASSERT(digit_idx >= -1);
    for (int i = digit_idx + 1; i < DOUBLE_PRECISION_NDIGITS; ++i)
    {
        i64 = i64 * 10 + digits[i];
    }
    if (is_neg)
    {
        i64 = -i64;
    }
    return ret;
}
Esempio n. 3
0
bool ObObj::is_true() const
{
  bool ret = false;
  switch (get_type())
  {
    case ObBoolType:
      ret = value_.bool_val;
      break;
    case ObVarcharType:
      ret = (val_len_ > 0);
      break;
    case ObIntType:
      ret = (value_.int_val != 0);
      break;
    case ObDecimalType:
      {
        ObNumber dec;
        bool is_add = false;
        if (OB_SUCCESS == get_decimal(dec, is_add))
        {
          ret = !dec.is_zero();
        }
        break;
      }
    case ObFloatType:
      ret = (fabsf(value_.float_val) > FLOAT_EPSINON);
      break;
    case ObDoubleType:
      ret = (fabs(value_.double_val) > DOUBLE_EPSINON);
      break;
    case ObDateTimeType:
    case ObPreciseDateTimeType:
    case ObCreateTimeType:
    case ObModifyTimeType:
      {
        int64_t ts1 = 0;
        get_timestamp(ts1);
        ret = (0 != ts1);
        break;
      }
    default:
      break;
  }
  return ret;
}
Esempio n. 4
0
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
void ObNumber::knuth_div_unsigned(const uint32_t *dividend,
        const ObNumber &divisor,
        ObNumber &quotient, int8_t qidx, ObNumber &remainder)
{
    OB_ASSERT(divisor.words_[divisor.nwords_ - 1] >= HALF_BASE); // (BASE ^ divisor_n)/2 <= divisor
    OB_ASSERT(0 <= qidx && qidx < MAX_NWORDS);
    ObNumber cdividend;
    cdividend.nwords_ = static_cast<int8_t> (divisor.nwords_ + 1);
    for (int8_t i = 0; i < cdividend.nwords_; ++i)
    {
        cdividend.words_[i] = dividend[i];
    }
    ObNumber base;
    base.from(BASE);
    ObNumber p;
    mul_words(base, divisor, p);
    p.remove_leading_zeroes_unsigned();

    int cmp = compare_words_unsigned(cdividend, p);
    if (cmp >= 0)
    {
        sub_words_unsigned(cdividend, p, cdividend);
        knuth_div_unsigned(cdividend.words_, divisor, quotient, qidx, remainder); // recursively called at most once
        quotient.words_[qidx + 1] = 1;
    }
    else
    {
        int8_t n = divisor.nwords_;
        uint64_t q = (UBASE * dividend[n] + dividend[n - 1]) / divisor.words_[n - 1];
        if (q >= UBASE)
        {
            q = UBASE - 1;
        }
        ObNumber Q;
        Q.from(q);
        ObNumber T;
        mul_words(Q, divisor, T);
        T.remove_leading_zeroes_unsigned();
        for (int i = 0; i < 2; ++i)
        {
            cmp = compare_words_unsigned(T, cdividend);
            if (cmp > 0)
            {
                Q.from(--q);
                sub_words_unsigned(T, divisor, T);
            }
            else
            {
                break;
            }
        } // end for
        if (Q.nwords_ == 1)
        {
            quotient.words_[qidx] = Q.words_[0];
        }
        else
        {
            OB_ASSERT(Q.is_zero());
            quotient.words_[qidx] = 0;
        }
        sub_words_unsigned(cdividend, T, remainder);
    }
}
Esempio n. 7
0
int64_t ObNumber::to_string(char* buf, const int64_t buf_len) const
{
    int64_t pos = 0;
    OB_ASSERT(nwords_ <= MAX_NWORDS);
    OB_ASSERT(nwords_ > 0);
    char inner_buf[MAX_PRINTABLE_SIZE];
    ObNumber clone;
    bool is_neg = is_negative();
    if (is_neg)
    {
        negate(*this, clone);
    }
    else
    {
        clone = *this;
    }
    ObNumber remainder;
    int i = MAX_PRINTABLE_SIZE;
    while (!clone.is_zero())
    {
        div_uint32(clone, 10, clone, remainder);
        if (remainder.is_zero())
        {
            inner_buf[--i] = '0';
        }
        else
        {
            OB_ASSERT(1 == remainder.nwords_);
            OB_ASSERT(remainder.words_[0] < 10 && remainder.words_[0] > 0);
            inner_buf[--i] = static_cast<char> ('0' + remainder.words_[0]);
        }
        OB_ASSERT(0 < i);
    } // end while
    int64_t dec_digits_num = MAX_PRINTABLE_SIZE - i;
    if (0 == dec_digits_num)
    {
        databuff_printf(buf, buf_len, pos, "0");
    }
    else
    {
        if (is_neg)
        {
            databuff_printf(buf, buf_len, pos, "-");
        }
        if (clone.vscale_ >= dec_digits_num)
        {
            // 0.0...0xxx
            databuff_printf(buf, buf_len, pos, "0.");
            for (int j = 0; j < clone.vscale_ - dec_digits_num; ++j)
            {
                databuff_printf(buf, buf_len, pos, "0");
            }
            if (NULL != buf && 0 <= pos && dec_digits_num < buf_len - pos)
            {
                memcpy(buf + pos, inner_buf + i, dec_digits_num);
                pos += dec_digits_num;
                buf[pos] = '\0';
            }
        }
        else
        {
            if (NULL != buf && 0 <= pos && dec_digits_num - clone.vscale_ < buf_len - pos)
            {
                memcpy(buf + pos, inner_buf + i, dec_digits_num - clone.vscale_); // digits before the point
                pos += dec_digits_num - clone.vscale_;
            }
            if (clone.vscale_ > 0)
            {
                if (NULL != buf && 0 <= pos && 1 + clone.vscale_ < buf_len - pos)
                {
                    buf[pos++] = '.';
                    memcpy(buf + pos, inner_buf + i + dec_digits_num - clone.vscale_, clone.vscale_); // digits after the point
                    pos += clone.vscale_;
                }
            }
            if (NULL != buf && 0 <= pos && 0 < buf_len - pos)
            {
                buf[pos] = '\0';
            }
        }
    }
    OB_ASSERT(pos <= buf_len);
    return pos;
}
Esempio n. 8
0
inline void ObNumber::div_words(const ObNumber &dividend, const ObNumber &divisor, ObNumber &quotient, ObNumber &remainder)
{
    OB_ASSERT(!dividend.is_zero());
    OB_ASSERT(!divisor.is_zero());
    OB_ASSERT(0 < dividend.nwords_ && dividend.nwords_ <= MAX_NWORDS);
    OB_ASSERT(0 < divisor.nwords_ && divisor.nwords_ <= MAX_NWORDS);

    if (1 == divisor.nwords_)
    {
        // fast algorithm
        div_uint32(dividend, divisor.words_[0], quotient, remainder);
    }
    else
    {
        // Knuth's algorithm, Volumn 2, Section 4.3, Page 235
        ObNumber cdivisor;
        ObNumber cdividend;
        if (divisor.words_[divisor.nwords_ - 1] < HALF_BASE)
        {
            // make sure (BASE ^ n)/2 <= divisor
            uint32_t factor = static_cast<uint32_t> (BASE / (divisor.words_[divisor.nwords_ - 1] + 1));
            mul_uint32(divisor, factor, cdivisor, true);
            mul_uint32(dividend, factor, cdividend, true);
            OB_ASSERT(cdivisor.words_[cdivisor.nwords_ - 1] >= HALF_BASE);
        }
        else
        {
            cdividend = dividend;
            cdivisor = divisor;
        }

        if (cdividend.nwords_ < cdivisor.nwords_) // include the case when dividend is zero
        {
            quotient.set_zero();
            remainder = dividend;
        }
        else if (cdividend.nwords_ == cdivisor.nwords_)
        {
            int cmp = compare_words_unsigned(cdividend, cdivisor);
            if (cmp < 0)
            {
                quotient.set_zero();
                remainder = dividend;
            }
            else
            {
                quotient.nwords_ = 1;
                quotient.words_[0] = 1;
                sub_words_unsigned(cdividend, cdivisor, remainder);
            }
        }
        else // dividend.nwords_ >= 1 + divosor.nwords_
        {
            quotient.nwords_ = static_cast<int8_t> (cdividend.nwords_ - cdivisor.nwords_ + 1);
            memset(quotient.words_, 0, sizeof (quotient.words_));
            for (int8_t i = static_cast<int8_t> (cdividend.nwords_ - cdivisor.nwords_ - 1); i >= 0; --i)
            {
                knuth_div_unsigned(&cdividend.words_[i], cdivisor, quotient, i, remainder);
                for (int8_t j = 0; j < cdivisor.nwords_; ++j)
                {
                    cdividend.words_[i + j] = remainder.words_[j];
                }
            }
        }
    }
    if (quotient.nwords_ > 0
            && static_cast<int64_t> (quotient.words_[quotient.nwords_ - 1]) >= HALF_BASE)
    {
        quotient.words_[quotient.nwords_++] = 0; // quotient is always positive
    }
    if (remainder.nwords_ > 0
            && static_cast<int64_t> (remainder.words_[remainder.nwords_ - 1]) >= HALF_BASE)
    {
        remainder.words_[remainder.nwords_++] = 0; // remainder is always positive
    }
}