inline void ObNumber::div_uint32(const ObNumber ÷nd, uint32_t divisor, ObNumber "ient, 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; } }
static int int_decimal(const ObObjCastParams ¶ms, const ObExprObj &in, ObExprObj &out) { UNUSED(params); OB_ASSERT(in.get_type() == ObIntType); ObNumber num; num.from(in.get_int()); out.set_decimal(num); // @todo optimize return OB_SUCCESS; }
static int mtime_decimal(const ObObjCastParams ¶ms, const ObExprObj &in, ObExprObj &out) { UNUSED(params); OB_ASSERT(in.get_type() == ObModifyTimeType); ObNumber num; num.from(static_cast<int64_t> (in.get_mtime())); out.set_decimal(num); return OB_SUCCESS; }
void ObObj::print_value(FILE* fd) { switch (get_type()) { case ObNullType: fprintf(fd, "nil"); break; case ObIntType: fprintf(fd, "%ld", value_.int_val); break; case ObVarcharType: fprintf(fd, "%.*s", val_len_, value_.varchar_val); break; case ObFloatType: fprintf(fd, "%2f", value_.float_val); break; case ObDoubleType: fprintf(fd, "%2lf", value_.double_val); break; case ObDateTimeType: fprintf(fd, "%s", time2str(value_.time_val)); break; case ObPreciseDateTimeType: fprintf(fd, "%s", time2str(value_.precisetime_val)); break; case ObModifyTimeType: fprintf(fd, "%s", time2str(value_.modifytime_val)); break; case ObCreateTimeType: fprintf(fd, "%s", time2str(value_.createtime_val)); break; case ObSeqType: fprintf(fd, "seq"); break; case ObExtendType: fprintf(fd, "%lde", value_.ext_val); break; case ObBoolType: fprintf(fd, "%c", value_.bool_val ? 'Y': 'N'); break; case ObDecimalType: { char num_buf[ObNumber::MAX_PRINTABLE_SIZE]; ObNumber num; get_decimal(num); num.to_string(num_buf, ObNumber::MAX_PRINTABLE_SIZE); fprintf(fd, "%s", num_buf); break; } default: break; } }
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; }
int ObObj::set_decimal(const ObNumber &num, int8_t precision, int8_t scale, bool is_add /*= false*/) { int ret = OB_SUCCESS; set_flag(is_add); meta_.type_ = ObDecimalType; meta_.dec_precision_ = static_cast<uint8_t>(precision) & META_PREC_MASK; meta_.dec_scale_ = static_cast<uint8_t>(scale) & META_SCALE_MASK; int8_t nwords = 0; int8_t vscale = 0; uint32_t words[ObNumber::MAX_NWORDS]; ret = num.round_to(precision, scale, nwords, vscale, words); if (OB_SUCCESS == ret) { if (nwords <= 3) { meta_.dec_nwords_ = static_cast<uint8_t>(nwords - 1) & META_NWORDS_MASK; meta_.dec_vscale_ = static_cast<uint8_t>(vscale) & META_VSCALE_MASK; memcpy(reinterpret_cast<uint32_t*>(&val_len_), words, sizeof(uint32_t)*nwords); } else { //@todo, use ob_pool.h to allocate memory ret = OB_NOT_IMPLEMENT; } } return ret; }
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; }
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; }
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; }
static int varchar_decimal(const ObObjCastParams ¶ms, const ObExprObj &in, ObExprObj &out) { int ret = OB_SUCCESS; UNUSED(params); OB_ASSERT(in.get_type() == ObVarcharType); const string &varchar = in.get_varchar(); ObNumber num; if (OB_SUCCESS != (ret = num.from(varchar.data(), varchar.length()))) { jlog(WARNING, "failed to convert varchar to decimal, err=%d varchar=%.*s", ret, varchar.length(), varchar.data()); } else { out.set_decimal(num); // @todo optimize } return OB_SUCCESS; }
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; }
static int double_decimal(const ObObjCastParams ¶ms, const ObExprObj &in, ObExprObj &out) { int ret = OB_SUCCESS; UNUSED(params); OB_ASSERT(in.get_type() == ObDoubleType); static const int64_t MAX_DOUBLE_PRINT_SIZE = 64; char buf[MAX_DOUBLE_PRINT_SIZE]; snprintf(buf, MAX_DOUBLE_PRINT_SIZE, "%f", in.get_double()); ObNumber num; if (OB_SUCCESS != (ret = num.from(buf))) { jlog(WARNING, "failed to convert float to decimal, err=%d", ret); } else { out.set_decimal(num); } return ret; }
void ObNumber::round_fraction_part(int8_t scale) { ObNumber *clone = this; ObNumber neg_this; bool is_neg = is_negative(); if (is_neg) { negate(*this, neg_this); clone = &neg_this; } if (vscale_ > scale) { clone->right_shift(static_cast<int8_t> (vscale_ - scale)); } if (is_neg) { negate(*clone, *this); } remove_leading_zeroes(); }
int ObObj::get_decimal(ObNumber &num, bool &is_add) const { int ret = OB_OBJ_TYPE_ERROR; if (ObDecimalType == meta_.type_) { ret = OB_SUCCESS; is_add = (ADD == meta_.op_flag_); int8_t nwords = static_cast<int8_t>(meta_.dec_nwords_ + 1); int8_t vscale = meta_.dec_vscale_; if (nwords <= 3) { num.from(vscale, nwords, reinterpret_cast<const uint32_t*>(&val_len_)); } else { num.from(vscale, nwords, value_.dec_words_); } } return ret; }
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; }
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; }
void ObNumber::knuth_div_unsigned(const uint32_t *dividend, const ObNumber &divisor, ObNumber "ient, 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); } }
inline void ObNumber::div_words(const ObNumber ÷nd, const ObNumber &divisor, ObNumber "ient, 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 } }
void ObObj::dump(const int32_t log_level /*=TBSYS_LOG_LEVEL_DEBUG*/) const { int64_t int_val = 0; bool bool_val = false; bool is_add = false; float float_val = 0.0f; double double_val = 0.0f; ObString str_val; ObNumber num; char num_buf[ObNumber::MAX_PRINTABLE_SIZE]; switch (get_type()) { case ObNullType: TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObNull",pthread_self()); break; case ObIntType: get_int(int_val,is_add); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObInt, val:%ld,is_add:%s",pthread_self(),int_val,is_add ? "true" : "false"); break; case ObVarcharType: get_varchar(str_val); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObVarChar,len :%d,val:",pthread_self(),str_val.length()); common::hex_dump(str_val.ptr(),str_val.length(),true,log_level); break; case ObFloatType: get_float(float_val,is_add); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObFloat, val:%f,is_add:%s",pthread_self(),float_val,is_add ? "true" : "false"); break; case ObDoubleType: get_double(double_val,is_add); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObDouble, val:%f,is_add:%s",pthread_self(),double_val,is_add ? "true" : "false"); break; case ObDateTimeType: get_datetime(int_val,is_add); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObDateTime(seconds), val:%ld,is_add:%s",pthread_self(),int_val,is_add ? "true" : "false"); break; case ObPreciseDateTimeType: get_precise_datetime(int_val,is_add); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObPreciseDateTime(microseconds), val:%ld,is_add:%s",pthread_self(),int_val,is_add ? "true" : "false"); break; case ObSeqType: //TODO break; case ObCreateTimeType: get_createtime(int_val); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObCreateTime, val:%ld",pthread_self(),int_val); break; case ObModifyTimeType: get_modifytime(int_val); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObModifyTime, val:%ld",pthread_self(),int_val); break; case ObBoolType: get_bool(bool_val); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObBool, val:%s",pthread_self(),bool_val?"true":"false"); break; case ObExtendType: get_ext(int_val); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObExt, val:%ld",pthread_self(),int_val); break; case ObDecimalType: get_decimal(num, is_add); num.to_string(num_buf, ObNumber::MAX_PRINTABLE_SIZE); TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level), "[%ld] type:ObDecimalType, val:%s, is_add:%s", pthread_self(), num_buf, is_add ? "true" : "false"); break; default: TBSYS_LOGGER.logMessage(TBSYS_LOG_NUM_LEVEL(log_level)," [%ld] unexpected type (%d)",pthread_self(),get_type()); break; } }
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; }
int64_t ObObj::to_string(char* buffer, const int64_t length) const { static const char* obj_type_name[] = { "null", "int", "float", "double", "datetime", "precisedatetime", "varchar", "seq", "createtime", "modifytime", "extend", "bool", "decimal" }; int64_t int_val = 0; float float_val = 0.0; double double_val = 0.0; bool is_add = false; ObString str_val; int32_t type = meta_.type_; int64_t pos = 0; if (type > ObMinType && type < ObMaxType) { databuff_printf(buffer, length, pos, "%s:", obj_type_name[meta_.type_]); } else { databuff_printf(buffer, length, pos, "%s", "unknown"); } { switch(meta_.type_) { case ObNullType: break; case ObIntType: get_int(int_val,is_add); databuff_printf(buffer, length, pos, "%s%ld", is_add ? "+" : "", int_val); break; case ObVarcharType: get_varchar(str_val); databuff_printf(buffer, length, pos, "%.*s", str_val.length(), str_val.ptr()); break; case ObFloatType: get_float(float_val,is_add); databuff_printf(buffer, length, pos, "%s%f", is_add ? "+" : "", float_val); break; case ObDoubleType: get_double(double_val,is_add); databuff_printf(buffer, length, pos, "%s%.12lf", is_add ? "+" : "", double_val); break; case ObDateTimeType: get_datetime(int_val,is_add); databuff_printf(buffer, length, pos, "%s%ld", is_add ? "+" : "", int_val); break; case ObPreciseDateTimeType: get_precise_datetime(int_val,is_add); databuff_printf(buffer, length, pos, "%s%ld", is_add ? "+" : "", int_val); break; case ObSeqType: //TODO break; case ObCreateTimeType: get_createtime(int_val); databuff_printf(buffer, length, pos, "%ld", int_val); break; case ObModifyTimeType: get_modifytime(int_val); databuff_printf(buffer, length, pos, "%ld", int_val); break; case ObExtendType: get_ext(int_val); if (MIN_OBJECT_VALUE == int_val) { databuff_printf(buffer, length, pos, "min"); } else if (MAX_OBJECT_VALUE == int_val) { databuff_printf(buffer, length, pos, "max"); } else { databuff_printf(buffer, length, pos, "%ld", int_val); } break; case ObBoolType: databuff_printf(buffer, length, pos, "%c", value_.bool_val ? 'Y': 'N'); break; case ObDecimalType: { char num_buf[ObNumber::MAX_PRINTABLE_SIZE]; ObNumber num; get_decimal(num); num.to_string(num_buf, ObNumber::MAX_PRINTABLE_SIZE); databuff_printf(buffer, length, pos, "%s", num_buf); break; } default: break; } } return pos; }
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; }