00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "base/numeric.h"
00029 #include "base/common.hpp"
00030 #include "base/string.hpp"
00031 #include "base/memory.hpp"
00032 #include "base/number.hpp"
00033 #include "base/list.hpp"
00034
00035 BEGIN_TERIMBER_NAMESPACE
00036 #pragma pack(4)
00037
00038 inline
00039 size_t
00040 room_count(size_t x)
00041 {
00042 size_t res;
00043 for (res = 1; x /= numeric::_radix; ++res);
00044 return res;
00045 }
00046
00047
00049
00050 const numeric_radix numeric::_radix = RADIX10;
00052 numeric::numeric(byte_allocator* allocator_) :
00053 _vec(1, allocator_), _scale(0), _precision(1), _sign(false)
00054 {
00055 _vec[0] = 0;
00056 }
00057
00058 numeric::~numeric()
00059 {
00060 }
00061
00062 numeric::numeric(ub1_t x, size_t length, byte_allocator* allocator_) :
00063 _vec(length, allocator_), _scale(0), _precision(length), _sign(false)
00064 {
00065 _vec.fill(x, length);
00066 }
00067
00068 numeric::numeric(const ub1_t* x, size_t length, byte_allocator* allocator_) :
00069 _vec(length, allocator_), _scale(0), _precision(length), _sign(false)
00070 {
00071 _vec.copy(x, length);
00072 }
00073
00074 numeric::numeric(sb4_t x, byte_allocator* allocator_) :
00075 _vec(room_count(x), allocator_), _scale(0), _precision(0), _sign(x < 0)
00076 {
00077 _precision = _vec.size();
00078 x *= _sign ? -1 : 1;
00079
00080 for (size_t index = 0; (size_t)index < _precision; ++index)
00081 {
00082 _vec[index] = (ub1_t)(x % _radix);
00083 x /= _radix;
00084 }
00085 }
00086
00087 numeric::numeric(sb8_t x, byte_allocator* allocator_) :
00088 _vec(1, allocator_), _scale(0), _precision(1), _sign(false)
00089 {
00090 _vec[0] = 0;
00091 char buf[128] = {0};
00092 size_t len = str_template::strprint(buf, 128, I64d, x);
00093 scan(buf, len, '.');
00094 }
00095
00096 numeric::numeric(float x, byte_allocator* allocator_) :
00097 _vec(1, allocator_), _scale(0), _precision(1), _sign(false)
00098 {
00099 _vec[0] = 0;
00100 char buf[128] = {0};
00101 size_t len = str_template::strprint(buf, 128, "%hf", x);
00102
00103 scan(buf, len, '.');
00104 }
00105
00106 numeric::numeric(double x, byte_allocator* allocator_) :
00107 _vec(1, allocator_), _scale(0), _precision(1), _sign(false)
00108 {
00109 _vec[0] = 0;
00110 char buf[128] = {0};
00111 size_t len = str_template::strprint(buf, 128, "%f", x);
00112
00113 scan(buf, len, '.');
00114 }
00115
00116 numeric::numeric(const char *x, size_t len, numeric_radix radix, byte_allocator* allocator_) :
00117 _vec(1, allocator_), _scale(0), _precision(0), _sign(false)
00118 {
00119
00120 _vec[0] = 0;
00121
00122 if (!x || !*x)
00123 return;
00124
00125 len = (len == os_minus_one) ? strlen(x) : len;
00126
00127 if (strncmp("0x", x, 2) == 0)
00128 radix = RADIX16;
00129
00130 for (size_t index = 0; index < len; ++index)
00131 {
00132 ub1_t digit = 0;
00133 if (!symbol_to_byte(digit, x[index], radix))
00134 continue;
00135
00136 numeric res((sb4_t)digit, _vec.get_allocator());
00137
00138 if (radix == RADIX10)
00139 *this << 1;
00140 else
00141 *this *= numeric((sb4_t)radix);
00142
00143 *this += res;
00144 }
00145
00146 _sign = x[0] == '-';
00147 }
00148
00149 numeric::numeric(const char *x, size_t len, char delimeter, byte_allocator* allocator_) :
00150 _vec(1, allocator_), _scale(0), _precision(0), _sign(false)
00151 {
00152 scan(x, len, delimeter);
00153 }
00154
00155 numeric::numeric(const wchar_t *x, size_t len, wchar_t delimeter, byte_allocator* allocator_) :
00156 _vec(1, allocator_), _scale(0), _precision(0), _sign(false)
00157 {
00158 scan(x, len, delimeter);
00159 }
00160
00161 bool
00162 numeric::format(char* buf, char delimeter) const
00163 {
00164 if (compare(*this, zero()) == 0)
00165 {
00166 *buf++ = '0';
00167 *buf = 0;
00168 return true;
00169 }
00170
00171 if (_sign)
00172 *buf++ = '-';
00173
00174 for (size_t index = _precision - 1; index >= 0; --index)
00175 {
00176 if (_scale != 0 && _scale == index + 1)
00177 {
00178 if (index == _precision - 1)
00179 *buf++ = '0';
00180
00181 *buf++ = delimeter;
00182 }
00183
00184 byte_to_symbol(*buf, _vec[index]);
00185 ++buf;
00186 }
00187
00188 *buf = 0;
00189 return true;
00190 }
00191
00192 bool
00193 numeric::persist(ub1_t* buf, size_t size) const
00194 {
00195
00196
00197
00198
00199 size_t required = 1 + sizeof(size_t) * 2 + _precision;
00200 if (required > size)
00201 return false;
00202
00203
00204 buf[0] = _sign ? 1 : 0;
00205 memcpy(buf + 1, &_scale, sizeof(size_t));
00206 memcpy(buf + 1 + sizeof(size_t), &_precision, sizeof(size_t));
00207
00208 for (size_t index = 0; index < _precision; ++index)
00209 buf[index + sizeof(size_t) * 2 + 1] = _vec[index];
00210
00211 return true;
00212 }
00213
00214 bool
00215 numeric::parse(const ub1_t* buf)
00216 {
00217
00218
00219
00220
00221 if (!buf)
00222 return false;
00223
00224 _sign = buf[0] != 0;
00225 memcpy(&_scale, buf + 1, sizeof(size_t));
00226 memcpy(&_precision, buf + 1 + sizeof(size_t), sizeof(size_t));
00227
00228 if (_precision)
00229 _vec.resize(_precision, true);
00230
00231 for (size_t index = 0; index < _precision; ++index)
00232 _vec[index] = buf[index + sizeof(size_t) * 2 + 1];
00233
00234 return true;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 bool
00276 numeric::parse_orcl(const ub1_t* buf)
00277 {
00278
00279 if (!buf)
00280 return false;
00281
00282 bool negative = false;
00283
00284 if (buf[0] == 128)
00285 {
00286 *this = zero();
00287 return true;
00288 }
00289 else if (buf[0] >= 173 && buf[0] <= 213)
00290 negative = false;
00291 else if (buf[0] >= 42 && buf[0] <= 82)
00292 negative = true;
00293 else
00294 return false;
00295
00296
00297 sb1_t exponent = (negative ? ~buf[0] : buf[0]) - 193;
00298
00299 sb8_t base = negative ? 101 - buf[1] : buf[1] - 1;
00300
00301 numeric tmp(base, _vec.get_allocator());
00302
00303 size_t mantissa = 0;
00304
00305 while (mantissa < 19 &&
00306 (!negative && buf[mantissa + 2] != 0
00307 || negative && buf[mantissa + 2] != 102)
00308 )
00309 {
00310 if (buf[mantissa + 2] > (100 + (negative ? 1 : 0)))
00311 return false;
00312
00313 tmp << 2;
00314 tmp += numeric(negative ? (sb4_t)(101 - buf[mantissa + 2]) : (sb4_t)(buf[mantissa + 2] - 1));
00315 ++mantissa;
00316 }
00317
00318
00319 sb1_t shift = 0;
00320 if (exponent > 0 && (sb4_t)mantissa < exponent)
00321 {
00322 while (exponent > (sb4_t)mantissa)
00323 {
00324 tmp << 2;
00325 --exponent;
00326 }
00327 }
00328 else if (exponent < 0)
00329 {
00330 while (exponent < (sb4_t)(mantissa + shift))
00331 {
00332 tmp >> 2;
00333 --shift;
00334 }
00335 }
00336
00337
00338 tmp._scale = (mantissa - exponent) * 2;
00339 if (tmp._precision < tmp._scale)
00340 tmp._precision = tmp._scale;
00341
00342 if (negative)
00343 tmp.negative();
00344
00345 tmp.cutjunk();
00346 *this = tmp;
00347 return true;
00348 }
00349
00350
00351 int
00352 numeric::compare_orcl(const ub1_t* x, const ub1_t* y)
00353 {
00354 if (!x)
00355 return (y != 0 ? -1 : 0);
00356 else if (!y)
00357 return 1;
00358
00359
00360 int xsign = 0, ysign = 0;
00361
00362
00363 if (x[0] == 128)
00364 xsign = 0;
00365 else if (x[0] >= 173 && x[0] <= 213)
00366 xsign = 1;
00367 else if (x[0] >= 42 && x[0] <= 82)
00368 xsign = -1;
00369 else
00370 {
00371 assert(false);
00372 }
00373
00374 if (y[0] == 128)
00375 ysign = 0;
00376 else if (y[0] >= 173 && y[0] <= 213)
00377 ysign = 1;
00378 else if (y[0] >= 42 && y[0] <= 82)
00379 ysign = -1;
00380 else
00381 {
00382 assert(false);
00383 }
00384
00385
00386 if (!xsign && !ysign)
00387 return 0;
00388 else if (xsign < ysign)
00389 return -1;
00390 else if (ysign < xsign)
00391 return 1;
00392
00393 sb1_t xexponent = (xsign < 0 ? ~x[0] : x[0]) - 193;
00394 sb1_t yexponent = (ysign < 0 ? ~y[0] : y[0]) - 193;
00395
00396 if (xexponent < yexponent)
00397 return xsign > 0 ? -1 : 1;
00398 else if (yexponent < xexponent)
00399 return xsign < 0 ? -1 : 1;
00400
00401
00402 sb8_t xbase = xsign < 0 ? 101 - x[1] : x[1] - 1;
00403 sb8_t ybase = ysign < 0 ? 101 - y[1] : y[1] - 1;
00404
00405 if (xbase < ybase)
00406 return xsign > 0 ? -1 : 1;
00407 else if (ybase < xbase)
00408 return xsign < 0 ? -1 : 1;
00409
00410 size_t xmantissa = 0, ymantissa = 0;
00411
00412 while (xmantissa < 19 &&
00413 (xsign > 0 && x[xmantissa + 2] != 0
00414 || xsign < 0 && x[xmantissa + 2] != 102)
00415
00416 &&
00417 ymantissa < 19 &&
00418 (ysign > 0 && y[ymantissa + 2] != 0
00419 || ysign < 0 && y[ymantissa + 2] != 102)
00420 )
00421 {
00422 assert(x[xmantissa + 2] <= (100 + (xsign < 0 ? 1 : 0)));
00423 assert(y[ymantissa + 2] <= (100 + (ysign < 0 ? 1 : 0)));
00424
00425 sb4_t xnext = xsign < 0 ? (sb4_t)(101 - x[xmantissa + 2]) : (sb4_t)(x[xmantissa + 2] - 1);
00426 sb4_t ynext = ysign < 0 ? (sb4_t)(101 - y[ymantissa + 2]) : (sb4_t)(y[ymantissa + 2] - 1);
00427
00428 if (xnext < ynext)
00429 return xsign > 0 ? -1 : 1;
00430 else if (ynext < xnext)
00431 return xsign < 0 ? -1 : 1;
00432
00433 ++xmantissa;
00434 ++ymantissa;
00435 }
00436
00437 if (ymantissa < 19 &&
00438 (ysign > 0 && y[ymantissa + 2] != 0
00439 || ysign < 0 && y[ymantissa + 2] != 102)
00440 )
00441 return -1;
00442
00443 if (xmantissa < 19 &&
00444 (xsign > 0 && x[xmantissa + 2] != 0
00445 || xsign < 0 && x[xmantissa + 2] != 102)
00446 )
00447 return 1;
00448
00449 return 0;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 bool
00482 numeric::persist_orcl(ub1_t* buf) const
00483 {
00484
00485
00486 if (_precision > 38)
00487 return false;
00488
00489 if (is_zero())
00490 {
00491 buf[0] = 128;
00492 buf[1] = 0;
00493 return true;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 size_t scale_moved = 0;
00512 size_t tail_zero = 0;
00513 size_t precision_moved = 0;
00514
00515 if (!_scale)
00516 {
00517
00518 precision_moved = _precision;
00519 }
00520 else if (_precision != _scale)
00521 {
00522 tail_zero = _scale % 2;
00523 scale_moved = _scale + tail_zero;
00524
00525 precision_moved = _precision;
00526 }
00527 else
00528 {
00529 assert(_precision == _scale);
00530
00531 tail_zero = _scale % 2;
00532 scale_moved = _scale + tail_zero;
00533
00534
00535 precision_moved = _precision;
00536 while (!_vec[precision_moved - 1] && precision_moved)
00537 {
00538 --precision_moved;
00539 }
00540 }
00541
00542 bool odd_base = (precision_moved + tail_zero) % 2 != 0;
00543
00544 assert(scale_moved % 2 == 0);
00545
00546 sb1_t exponent = (sb1_t)(precision_moved + tail_zero - (odd_base ? 0 : 1) - scale_moved) / 2;
00547
00548
00549 sb1_t base = odd_base ? _vec[precision_moved - 1] :
00550 _vec[precision_moved - 1] *10 + _vec[precision_moved - 2];
00551
00552 if (sign())
00553 buf[1] = 101 - base;
00554 else
00555 buf[1] = base + 1;
00556
00557
00558 buf[0] = sign() ? (~exponent - 193) : (exponent + 193);
00559
00560
00561 size_t mantissa_upper_index = precision_moved - (odd_base ? 1 : 2);
00562 size_t mantissa_lower_index = tail_zero;
00563
00564 assert((mantissa_upper_index - mantissa_lower_index) % 2 == 0);
00565
00566 size_t length_mantissa = (mantissa_upper_index - mantissa_lower_index) / 2;
00567
00568
00569 for (size_t index = 0; index < length_mantissa; ++index)
00570 {
00571 ub1_t result = _vec[2*index + mantissa_lower_index] + _vec[2*index + 1 + mantissa_lower_index] * 10;
00572 buf[length_mantissa - index + 1] = (sign() ? 101 - result : result + 1);
00573 }
00574
00575 if (tail_zero)
00576 {
00577 ++length_mantissa;
00578 ub1_t result = _vec[0] * 10;
00579 buf[length_mantissa + 1] = (sign() ? 101 - result : result + 1);
00580 }
00581
00582 if (length_mantissa < 19)
00583 buf[length_mantissa + 2] = (sign() ? 102 : 0);
00584
00585 return true;
00586 }
00587
00588 size_t
00589 numeric::orcl_len() const
00590 {
00591 if (is_zero())
00592 {
00593 return 2;
00594 }
00595 else
00596 {
00597 bool odd_scale = _scale % 2 != 0;
00598 size_t scale = _scale + (odd_scale ? 1 : 0);
00599 size_t precision = _precision + (odd_scale ? 1 : 0);
00600 bool odd_precision = precision % 2 != 0;
00601 size_t mantissa = precision / 2;
00602 return mantissa + 2 + (odd_precision ? 1 : 0);
00603 }
00604 }
00605
00606 bool
00607 numeric::persist_sql(ub1_t& sign, ub1_t* buf, ub1_t& precision, sb1_t& scale) const
00608 {
00609
00610 numeric value = *this;
00611 value << (int)_scale;
00612 numeric divider((sb4_t)256);
00613
00614 size_t index = 0;
00615 while (!value.is_zero())
00616 {
00617 numeric res = value % divider;
00618 buf[index] = res._vec[0] + 10 * res._vec[1] + 100 * res._vec[2];
00619 value /= divider;
00620 ++index;
00621 }
00622
00623 sign = _sign ? 0 : 1;
00624 precision = (ub1_t)_precision;
00625 scale = (ub1_t)_scale;
00626
00627 return true;
00628 }
00629
00630 bool
00631 numeric::parse_sql(ub1_t sign, const ub1_t* buf, ub1_t precision, sb1_t scale)
00632 {
00633
00634 size_t index = 0;
00635 numeric tmp = zero();
00636 numeric power((sb4_t)1);
00637 numeric multiplier((sb4_t)256);
00638
00639 while (buf[index])
00640 {
00641 tmp += power * numeric((sb4_t)buf[index]);
00642 power *= multiplier;
00643 ++index;
00644 }
00645
00646
00647 tmp._scale = scale;
00648 tmp._sign = sign == 0;
00649
00650 *this = tmp;
00651 return true;
00652 }
00653
00654
00655 numeric&
00656 numeric::negative()
00657 {
00658 _sign = true;
00659 return *this;
00660 }
00661
00662 bool
00663 numeric::sign() const
00664 {
00665 return _sign;
00666 }
00667
00668 size_t
00669 numeric::scale() const
00670 {
00671 return _scale;
00672 }
00673
00674 size_t
00675 numeric::precision() const
00676 {
00677 return _precision;
00678 }
00679
00680
00681 const numeric&
00682 numeric::zero()
00683 {
00684 const static numeric s_zero;
00685 return s_zero;
00686 }
00687
00688
00689 const numeric&
00690 numeric::one()
00691 {
00692 const static numeric s_one((sb4_t)1);
00693 return s_one;
00694 }
00695
00696 bool
00697 numeric::is_zero() const
00698 {
00699 for (size_t index = 0; index < _precision; ++index)
00700 if (_vec[index])
00701 return false;
00702
00703 return true;
00704 }
00705
00706 numeric&
00707 numeric::operator++()
00708 {
00709 return *this += one();
00710 }
00711
00712 numeric
00713 numeric::operator++(int)
00714 {
00715 numeric tmp(*this);
00716 *this += one();
00717 return tmp;
00718 }
00719
00720 numeric&
00721 numeric::operator--()
00722 {
00723 return *this -= one();
00724 }
00725
00726 numeric
00727 numeric::operator--(int)
00728 {
00729 numeric tmp(*this);
00730 *this -= one();
00731 return tmp;
00732 }
00733
00734 numeric&
00735 numeric::operator+=(const numeric& x)
00736 {
00737 numeric res(_vec.get_allocator());
00738 if (!_sign)
00739 {
00740 if (!x._sign)
00741 *this = plus(res, *this, x);
00742 else
00743 if (compare(*this, x) < 0)
00744 {
00745 *this = minus(res, x, *this);
00746 _sign = true;
00747 }
00748 else
00749 *this = minus(res, *this, x);
00750 }
00751 else
00752 {
00753 if (x._sign)
00754 *this = plus(res, *this, x);
00755 else
00756 if (compare(*this, x) <= 0)
00757 {
00758 *this = minus(res, x, *this);
00759 _sign = false;
00760 }
00761 else
00762 *this = minus(res, *this, x);
00763 }
00764
00765 return cutjunk();
00766 }
00767
00768 numeric&
00769 numeric::operator-=(const numeric& x)
00770 {
00771 numeric res(_vec.get_allocator());
00772 if (!_sign)
00773 {
00774 if (x._sign)
00775 *this = plus(res, *this, x);
00776 else
00777 if (compare(*this, x) < 0)
00778 {
00779 *this = minus(res, x, *this);
00780 _sign = true;
00781 }
00782 else
00783 *this = minus(res, *this, x);
00784 }
00785 else
00786 {
00787 if (!x._sign)
00788 *this = plus(res, *this, x);
00789 else
00790 if (compare(*this, x) <= 0)
00791 {
00792 *this = minus(res, x, *this);
00793 _sign = false;
00794 }
00795 else
00796 *this = minus(res, *this, x);
00797 }
00798
00799 return cutjunk();
00800 }
00801
00802 numeric&
00803 numeric::operator*=(const numeric& x)
00804 {
00805 numeric res(_vec.get_allocator());
00806 *this = multiply(res, *this, x);
00807 _sign ^= x._sign;
00808 return cutjunk();
00809 }
00810
00811 numeric&
00812 numeric::operator/=(const numeric& x)
00813 {
00814 numeric res(_vec.get_allocator());
00815 numeric reminder(_vec.get_allocator());
00816 *this = divide(res, reminder, *this, x);
00817 _sign ^= x._sign;
00818 return cutjunk();
00819 }
00820
00821 numeric&
00822 numeric::operator%=(const numeric& x)
00823 {
00824 numeric res(_vec.get_allocator());
00825 numeric reminder(_vec.get_allocator());
00826 divide(res, reminder, *this, x);
00827 *this = reminder;
00828 _sign ^= x._sign;
00829 return cutjunk();
00830 }
00831
00832 numeric::numeric(const numeric& x) :
00833 _vec(x._vec), _scale(x._scale), _precision(x._precision), _sign(x._sign)
00834 {
00835 }
00836
00837 numeric&
00838 numeric::operator=(const numeric& x)
00839 {
00840 if (this != &x)
00841 {
00842 _vec = x._vec;
00843 _sign = x._sign;
00844 _precision = x._precision;
00845 _scale = x._scale;
00846 }
00847 return *this;
00848 }
00849
00850 numeric&
00851 numeric::cutjunk()
00852 {
00853
00854 size_t head = (_precision) ? _precision - 1 : 0;
00855 for (; head >= _scale;)
00856 if (_vec[head])
00857 break;
00858 else
00859 --_precision, --head;
00860
00861 size_t tail = 0;
00862 for (; tail < _scale;)
00863 if (_vec[tail])
00864 break;
00865 else
00866 ++tail;
00867
00868 if (tail)
00869 {
00870 _vec >> tail;
00871 _precision -= tail;
00872 _scale -= tail;
00873 }
00874
00875 return *this;
00876 }
00877
00878 numeric&
00879 numeric::operator<<(int shift)
00880 {
00881 if (shift)
00882 {
00883 if (shift < 0)
00884 return *this >> -shift;
00885
00886 int decr = __min(shift, (int)_scale);
00887 shift -= decr;
00888 _scale -= decr;
00889
00890 if (shift)
00891 {
00892 _precision += shift;
00893 _vec.reserve(_precision);
00894 _vec << shift;
00895 }
00896 }
00897
00898 return *this;
00899 }
00900
00901 numeric&
00902 numeric::operator>>(int shift)
00903 {
00904 if (shift)
00905 {
00906 if (shift < 0)
00907 return *this << shift;
00908
00909
00910 _scale += (size_t)shift;
00911
00912 if (_precision < _scale)
00913 _precision = _scale;
00914
00915
00916 _vec.reserve(_precision);
00917 }
00918
00919 return *this;
00920 }
00921
00922 bool
00923 numeric::operator==(const numeric& x)
00924 {
00925 return _sign == x._sign && compare(*this, x) == 0;
00926 }
00927
00928 bool
00929 numeric::operator!=(const numeric& x)
00930 {
00931 return !(*this == x);
00932 }
00933
00934 bool
00935 numeric::operator<(const numeric& x)
00936 {
00937 return _sign && !x._sign || !(_sign ^ x._sign) && compare(_sign ? x : *this, _sign ? *this : x) < 0;
00938 }
00939
00940 bool
00941 numeric::operator<=(const numeric& x)
00942 {
00943 return _sign && !x._sign || !(_sign ^ x._sign) && compare(_sign ? x : *this, _sign ? *this : x) <= 0;
00944 }
00945
00946 bool
00947 numeric::operator>(const numeric& x)
00948 {
00949 return !(*this <= x);
00950 }
00951
00952 bool
00953 numeric::operator>=(const numeric& x)
00954 {
00955 return !(*this < x);
00956 }
00957
00958
00960
00961 numeric&
00962 numeric::plus(numeric& res, const numeric& x, const numeric& y)
00963 {
00964 size_t x_whole = x._precision - x._scale;
00965 size_t y_whole = y._precision - y._scale;
00966
00967 int scale = (int)__max(x._scale, y._scale);
00968 size_t precision = scale + __max(x_whole, y_whole);
00969
00970 res._vec.reserve(precision + 1);
00971 res._precision = precision;
00972 res._scale = scale;
00973
00974 ub1_t carry = 0;
00975
00976
00977 int shift = (int)x._scale - (int)y._scale;
00978 for (int iscale = 0; iscale < (int)scale; ++iscale)
00979 {
00980 ub1_t sum = carry;
00981 if (shift > 0)
00982 sum += x._vec[iscale] + (iscale >= shift ? y._vec[iscale - shift] : 0);
00983 else if (shift < 0)
00984 sum += y._vec[iscale] + (iscale >= -shift ? x._vec[iscale + shift] : 0);
00985 else
00986 sum += x._vec[iscale] + y._vec[iscale];
00987
00988 res._vec[iscale] = sum % _radix;
00989 carry = sum / _radix;
00990 }
00991
00992
00993 for (int iprecision = scale; iprecision < (int)precision; ++iprecision)
00994 {
00995 ub1_t sum = carry;
00996 if (iprecision - (int)scale < (int)(x._precision - x._scale))
00997 sum += x._vec[iprecision - scale + x._scale];
00998 if (iprecision - (int)scale < (int)(y._precision - y._scale))
00999 sum += y._vec[iprecision - scale + y._scale];
01000
01001 res._vec[iprecision] = sum % _radix;
01002 carry = sum / _radix;
01003 }
01004
01005 if (carry)
01006 {
01007 res._vec[precision] = carry;
01008 ++res._precision;
01009 }
01010
01011 return res;
01012 }
01013
01014
01015 numeric&
01016 numeric::minus(numeric& res, const numeric& x, const numeric& y)
01017 {
01018 size_t x_whole = x._precision - x._scale;
01019 size_t y_whole = y._precision - y._scale;
01020
01021 size_t scale = __max(x._scale, y._scale);
01022 assert(x_whole >= y_whole);
01023 size_t precision = x_whole + scale;
01024
01025 res._vec.reserve(precision);
01026 res._precision = precision;
01027 res._scale = scale;
01028
01029 ub1_t borrow = 0;
01030
01031
01032 int shift = (int)x._scale - (int)y._scale;
01033 for (int iscale = 0; iscale < (int)scale; ++iscale)
01034 {
01035 sb1_t sub = 0;
01036 if (shift > 0)
01037 sub = x._vec[iscale] - (iscale >= shift ? y._vec[iscale - shift] : 0) - borrow;
01038 else if (shift < 0)
01039 sub = (iscale >= -shift ? x._vec[iscale + shift] : 0) - y._vec[iscale] - borrow;
01040 else
01041 sub = x._vec[iscale] - y._vec[iscale] - borrow;
01042
01043 res._vec[iscale] = sub >= 0 ? sub : _radix + sub;
01044 borrow = sub >= 0 ? 0 : 1;
01045 }
01046
01047
01048 for (int iprecision = (int)scale; iprecision < (int)precision; ++iprecision)
01049 {
01050 sb1_t sub = 0;
01051 if (iprecision - (int)scale < (int)(x._precision - x._scale))
01052 sub += x._vec[iprecision - scale + x._scale];
01053 if (iprecision - (int)scale < (int)(y._precision - y._scale))
01054 sub -= y._vec[iprecision - scale + y._scale];
01055
01056 sub -= borrow;
01057
01058 res._vec[iprecision] = sub >= 0 ? sub : _radix + sub;
01059 borrow = sub >= 0 ? 0 : 1;
01060 }
01061
01062
01063 assert(borrow == 0);
01064 return res;
01065 }
01066
01067
01068 numeric&
01069 numeric::multiply(numeric& res, const numeric& x, const numeric& y)
01070 {
01071
01072 size_t max_room = x._precision * y._precision + 1;
01073
01074 res._vec.reserve(max_room);
01075
01076 ub1_t mult = 0;
01077 res._vec.fill(0, max_room);
01078 res._precision = 0;
01079 res._scale = 0;
01080
01081
01082 numeric row((ub1_t)0, max_room, res._vec.get_allocator());
01083
01084 for (int iy = 0; iy < (int)y._precision; ++iy, ++mult)
01085 {
01086
01087 row._vec.fill(0, max_room);
01088 row._precision = x._precision;
01089 row._scale = 0;
01090 ub1_t carry = 0;
01091
01092 for (int ix = 0; ix < (int)x._precision; ++ix)
01093 {
01094
01095 ub1_t sum = x._vec[ix] * y._vec[iy];
01096
01097 sum += carry;
01098
01099 row._vec[ix] = sum % _radix;
01100
01101 carry = sum / _radix;
01102 }
01103
01104 if (carry)
01105 {
01106
01107 row._vec[x._precision] = carry;
01108
01109 ++row._precision;
01110 }
01111
01112
01113 row._vec << mult;
01114 row._precision += mult;
01115
01116 res += row;
01117 }
01118
01119
01120 res._scale = x._scale + y._scale;
01121 if (res._precision < res._scale)
01122 res._precision = res._scale;
01123 return res;
01124 }
01125
01126
01127
01128
01129 numeric&
01130 numeric::divide(numeric& res, numeric& reminder, const numeric& dividend, const numeric& divider)
01131 {
01132 reminder = zero();
01133
01134 if (divider.is_zero())
01135 exception::_throw("Divided by zero");
01136
01137 if (dividend.is_zero())
01138 {
01139 res = zero();
01140 return res;
01141 }
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 int initial_scale = 0;
01159
01160 numeric dividend_(dividend);
01161 numeric divider_(divider);
01162 dividend_.cutjunk();
01163 divider_.cutjunk();
01164
01165 int dividend_scale = (int)dividend_._scale;
01166 int divider_scale = (int)divider_._scale;
01167 int max_scale = __max(dividend_scale, divider_scale);
01168
01169 dividend_ << 2 * max_scale - dividend_scale;
01170 divider_ << max_scale - divider_scale;
01171
01172
01173 while (compare(dividend_, divider_) > 0)
01174 {
01175 if (divider_._scale)
01176 --divider_._scale;
01177 else
01178 divider_._vec.reserve(++divider_._precision) << 1;
01179
01180 --initial_scale;
01181 }
01182
01183
01184 if (initial_scale < 0 && compare(dividend_, divider_) < 0)
01185 {
01186 if (divider_._scale)
01187 {
01188 ++divider_._scale;
01189 ++initial_scale;
01190 }
01191 else
01192 divider_._vec.reserve(--divider_._precision) >> 1;
01193 }
01194
01195
01196 res = zero();
01197
01198
01199 int rounds = initial_scale;
01200 numeric circles(res._vec.get_allocator());
01201
01202 while (rounds < 0)
01203 {
01204 res._vec.reserve(++res._precision) << 1;
01205
01206 circles = zero();
01207 while (compare(dividend_, divider_) >= 0)
01208 {
01209 ++circles;
01210 dividend_ -= divider_;
01211 }
01212
01213 res += circles;
01214 divider_._vec >> 1;
01215 --divider_._precision;
01216 ++rounds;
01217 }
01218
01219 reminder = dividend_.cutjunk();
01220 res._vec.reserve(res._scale = (max_scale - dividend_scale + divider_scale));
01221 if (res._precision < res._scale)
01222 res._precision = res._scale;
01223 return res;
01224 }
01225
01226
01227 int
01228 numeric::compare(const numeric& x, const numeric& y)
01229 {
01230 int x_whole = (int)x._precision - (int)x._scale;
01231 int y_whole = (int)y._precision - (int)y._scale;
01232
01233 if (x_whole > y_whole)
01234 return 1;
01235 else if (x_whole < y_whole)
01236 return -1;
01237 else
01238 {
01239 for (int index = x_whole - 1; index >= 0; --index)
01240 {
01241 if (x._vec[index + x._scale] == y._vec[index + y._scale])
01242 continue;
01243 else
01244 return x._vec[index + x._scale] > y._vec[index + y._scale] ? 1 : -1;
01245 }
01246 }
01247
01248
01249
01250 int min_fraction = (int)__min(x._scale, y._scale);
01251
01252 for (int index = min_fraction - 1; index >= 0; --index)
01253 {
01254 if (x._vec[index + x._scale - min_fraction] == y._vec[index + y._scale - min_fraction])
01255 continue;
01256 else
01257 return x._vec[index + x._scale - min_fraction] > y._vec[index + y._scale - min_fraction] ? 1 : -1;
01258 }
01259
01260 if (x._scale == y._scale)
01261 return 0;
01262 else
01263 return x._scale > y._scale ? 1 : -1;
01264 }
01265
01266
01268 numeric operator+(const numeric& x, const numeric& y)
01269 {
01270 numeric res(x);
01271 res += y;
01272 return res.cutjunk();
01273 }
01274
01275 numeric operator-(const numeric& x, const numeric& y)
01276 {
01277 numeric res(x);
01278 res -= y;
01279 return res.cutjunk();
01280 }
01281
01282 numeric operator*(const numeric& x, const numeric& y)
01283 {
01284 numeric res(x);
01285 res *= y;
01286 return res.cutjunk();
01287 }
01288
01289 numeric operator/(const numeric& x, const numeric& y)
01290 {
01291 numeric res(x);
01292 res /= y;
01293 return res.cutjunk();
01294 }
01295
01296 numeric operator%(const numeric& x, const numeric& y)
01297 {
01298 numeric res(x);
01299 res %= y;
01300 return res.cutjunk();
01301 }
01302
01304 numeric&
01305 numeric::scan(const char* x, size_t len, char delimeter)
01306 {
01307 _vec[0] = 0;
01308 _sign = false;
01309 _precision = 1;
01310 _scale = 0;
01311
01312 if (!x || !*x)
01313 return *this;;
01314
01315 bool after_delimeter = false;
01316 numeric divider((sb4_t)1, _vec.get_allocator());
01317
01318 for (size_t index = 0; index < len; ++index)
01319 {
01320 ub1_t digit = 0;
01321
01322 if (symbol_to_byte(digit, x[index], RADIX16))
01323 ;
01324 else if (x[index] == delimeter && !after_delimeter)
01325 {
01326 after_delimeter = true;
01327 continue;
01328 }
01329 else
01330 continue;
01331
01332 if (!after_delimeter)
01333 {
01334 *this << 1;
01335 *this += numeric((sb4_t)digit);
01336 }
01337 else
01338 {
01339 if (divider._scale == divider._precision)
01340 divider._vec.reserve(++divider._precision);
01341 ++divider._scale;
01342
01343 numeric fraction((sb4_t)digit, _vec.get_allocator());
01344 fraction *= divider;
01345 *this += fraction;
01346 }
01347 }
01348
01349 _sign = (ub1_t)x[0] == '-';
01350 cutjunk();
01351 return *this;
01352 }
01353
01354 numeric&
01355 numeric::scan(const wchar_t* x, size_t len, wchar_t delimeter)
01356 {
01357 _vec[0] = 0;
01358 _sign = false;
01359 _precision = 1;
01360 _scale = 0;
01361
01362 if (!x || !*x || !len)
01363 return *this;
01364
01365 bool after_delimeter = false;
01366 numeric divider((sb4_t)1, _vec.get_allocator());
01367
01368 for (size_t index = 0; index < len; ++index)
01369 {
01370 ub1_t digit = 0;
01371
01372 if (symbol_to_byte(digit, x[index], RADIX16))
01373 ;
01374 else if (x[index] == delimeter && !after_delimeter)
01375 {
01376 after_delimeter = true;
01377 continue;
01378 }
01379 else
01380 continue;
01381
01382 if (!after_delimeter)
01383 {
01384 *this << 1;
01385 *this += numeric((sb4_t)digit);
01386 }
01387 else
01388 {
01389 if (divider._scale == divider._precision)
01390 divider._vec.reserve(++divider._precision);
01391 ++divider._scale;
01392
01393 numeric fraction((sb4_t)digit, _vec.get_allocator());
01394 fraction *= divider;
01395 *this += fraction;
01396 }
01397 }
01398
01399 _sign = (ub1_t)x[0] == '-';
01400 return *this;
01401 }
01402
01403
01404 #pragma pack()
01405 END_TERIMBER_NAMESPACE
01406