00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 #include <config.h>
00107
00108 #include <drizzled/definitions.h>
00109 #include <drizzled/internal/m_string.h>
00110 #include <drizzled/charset_info.h>
00111 #include <drizzled/type/decimal.h>
00112
00113 #include <plugin/myisam/myisampack.h>
00114 #include <drizzled/util/test.h>
00115
00116 #ifdef HAVE_ALLOCA_H
00117 #include <alloca.h>
00118 #endif
00119
00120 #include <algorithm>
00121 #include <time.h>
00122 #include <drizzled/current_session.h>
00123 #include <drizzled/error.h>
00124 #include <drizzled/field.h>
00125 #include <drizzled/internal/my_sys.h>
00126
00127 using namespace std;
00128
00129 namespace drizzled
00130 {
00143 int decimal_operation_results(int result)
00144 {
00145 switch (result) {
00146 case E_DEC_OK:
00147 break;
00148 case E_DEC_TRUNCATED:
00149 push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00150 ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
00151 "", (long)-1);
00152 break;
00153 case E_DEC_OVERFLOW:
00154 push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00155 ER_TRUNCATED_WRONG_VALUE,
00156 ER(ER_TRUNCATED_WRONG_VALUE),
00157 "DECIMAL", "");
00158 break;
00159 case E_DEC_DIV_ZERO:
00160 my_error(ER_DIVISION_BY_ZERO, MYF(0));
00161 break;
00162 case E_DEC_BAD_NUM:
00163 push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00164 ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
00165 ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
00166 "decimal", "", "", (long)-1);
00167 break;
00168 case E_DEC_OOM:
00169 my_error(ER_OUT_OF_RESOURCES, MYF(0));
00170 break;
00171 default:
00172 assert(0);
00173 }
00174 return result;
00175 }
00176
00177
00197 int class_decimal2string(const type::Decimal *d,
00198 uint32_t fixed_dec, String *str)
00199 {
00200 uint32_t mask= E_DEC_FATAL_ERROR;
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 int length= (int)(0
00214 ? (uint32_t)(((0 == fixed_dec) ? 1 : 0) + 1)
00215 : (uint32_t)d->string_length());
00216 int result;
00217 if (str->alloc(length))
00218 return check_result(mask, E_DEC_OOM);
00219
00220 result= decimal2string((decimal_t*) d, (char*) str->ptr(),
00221 &length, (int)0, fixed_dec,
00222 '0');
00223 str->length(length);
00224 return check_result(mask, result);
00225 }
00226
00227
00247 namespace type {
00248
00249 int Decimal::val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const
00250 {
00251 int err1= E_DEC_OK, err2;
00252 type::Decimal rounded;
00253 class_decimal2decimal(this, &rounded);
00254 rounded.frac= decimal_actual_fraction(&rounded);
00255 if (scale < rounded.frac)
00256 {
00257 err1= E_DEC_TRUNCATED;
00258
00259 decimal_round(&rounded, &rounded, scale, HALF_UP);
00260 }
00261 err2= decimal2bin(&rounded, bin, prec, scale);
00262 if (!err2)
00263 err2= err1;
00264 return check_result(mask, err2);
00265 }
00266
00267 }
00268
00269
00286 int type::Decimal::store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset)
00287 {
00288 char *end, *from_end;
00289 int err;
00290 char buff[STRING_BUFFER_USUAL_SIZE];
00291 String tmp(buff, sizeof(buff), &my_charset_bin);
00292 if (charset->mbminlen > 1)
00293 {
00294 size_t dummy_errors;
00295 tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
00296 from= tmp.ptr();
00297 length= tmp.length();
00298 charset= &my_charset_bin;
00299 }
00300 from_end= end= (char*) from+length;
00301 err= string2decimal((char *)from, (decimal_t*) this, &end);
00302 if (end != from_end && !err)
00303 {
00304
00305 for ( ; end < from_end; end++)
00306 {
00307 if (!my_isspace(&my_charset_utf8_general_ci, *end))
00308 {
00309 err= E_DEC_TRUNCATED;
00310 break;
00311 }
00312 }
00313 }
00314 check_result_and_overflow(mask, err);
00315 return err;
00316 }
00317
00318 void type::Decimal::convert(double &result) const
00319 {
00320 decimal2double(static_cast<const decimal_t*>(this), &result);
00321 }
00322
00323 type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec)
00324 {
00325 int64_t date;
00326 date = (ltime->year*100L + ltime->month)*100L + ltime->day;
00327 if (ltime->time_type > type::DRIZZLE_TIMESTAMP_DATE)
00328 date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
00329
00330 if (int2_class_decimal(E_DEC_FATAL_ERROR, date, false, dec))
00331 return dec;
00332
00333 if (ltime->second_part)
00334 {
00335 dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
00336 dec->frac= 6;
00337 }
00338
00339 return dec;
00340 }
00341
00342
00343 void class_decimal_trim(uint32_t *precision, uint32_t *scale)
00344 {
00345 if (!(*precision) && !(*scale))
00346 {
00347 *precision= 10;
00348 *scale= 0;
00349 return;
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 typedef decimal_digit_t dec1;
00370 typedef int64_t dec2;
00371
00372 #define DIG_PER_DEC1 9
00373 #define DIG_MASK 100000000
00374 #define DIG_BASE 1000000000
00375 #define DIG_MAX (DIG_BASE-1)
00376
00377 template<typename T>
00378 inline static T round_up(const T &x)
00379 {
00380 return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
00381 }
00382
00383 static const dec1 powers10[DIG_PER_DEC1+1]={
00384 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
00385 static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
00386 static const dec1 frac_max[DIG_PER_DEC1-1]={
00387 900000000, 990000000, 999000000,
00388 999900000, 999990000, 999999000,
00389 999999900, 999999990 };
00390
00391 #ifdef HAVE_VALGRIND
00392 #define sanity(d) assert((d)->len > 0)
00393 #else
00394 #define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
00395 (d)->buf[(d)->len-1] | 1))
00396 #endif
00397
00398 inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
00399 {
00400 if (unlikely(intg1+frac1 > len))
00401 {
00402 if (unlikely(intg1 > len))
00403 {
00404 intg1=(len);
00405 frac1=0;
00406 error=E_DEC_OVERFLOW;
00407 }
00408 else
00409 {
00410 frac1=(len)-intg1;
00411 error=E_DEC_TRUNCATED;
00412 }
00413 }
00414 else
00415 error=E_DEC_OK;
00416 }
00417
00418
00419 inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
00420 {
00421 dec1 a=from1+from2+carry;
00422 assert(carry <= 1);
00423 if ((carry= (a >= DIG_BASE)))
00424 a-=DIG_BASE;
00425 to=a;
00426 }
00427
00428 inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
00429 {
00430 dec2 a=dec2(from1)+from2+carry;
00431 if ((carry= (a >= DIG_BASE)))
00432 a-=DIG_BASE;
00433 if (unlikely(a >= DIG_BASE))
00434 {
00435 a-=DIG_BASE;
00436 carry++;
00437 }
00438 to=dec1(a);
00439 }
00440
00441
00442 inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
00443 {
00444 dec1 a=from1-from2-carry;
00445 if ((carry= (a < 0)))
00446 a+=DIG_BASE;
00447 to=a;
00448 }
00449
00450
00451 inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
00452 {
00453 dec1 a=from1-from2-carry;
00454 if ((carry= (a < 0)))
00455 a+=DIG_BASE;
00456 if (unlikely(a < 0))
00457 {
00458 a+=DIG_BASE;
00459 carry++;
00460 }
00461 to=a;
00462 }
00463
00472 void max_decimal(int precision, int frac, decimal_t *to)
00473 {
00474 int intpart;
00475 dec1 *buf= to->buf;
00476 assert(precision && precision >= frac);
00477
00478 to->sign= 0;
00479 if ((intpart= to->intg= (precision - frac)))
00480 {
00481 const int firstdigits= intpart % DIG_PER_DEC1;
00482 if (firstdigits)
00483 *buf++= powers10[firstdigits] - 1;
00484 for(intpart/= DIG_PER_DEC1; intpart; intpart--)
00485 *buf++= DIG_MAX;
00486 }
00487
00488 if ((to->frac= frac))
00489 {
00490 const int lastdigits= frac % DIG_PER_DEC1;
00491 for(frac/= DIG_PER_DEC1; frac; frac--)
00492 *buf++= DIG_MAX;
00493 if (lastdigits)
00494 *buf= frac_max[lastdigits - 1];
00495 }
00496 }
00497
00498
00499 static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
00500 {
00501 int intg= from->intg, i;
00502 dec1 *buf0= from->buf;
00503 i= ((intg - 1) % DIG_PER_DEC1) + 1;
00504 while (intg > 0 && *buf0 == 0)
00505 {
00506 intg-= i;
00507 i= DIG_PER_DEC1;
00508 buf0++;
00509 }
00510 if (intg > 0)
00511 {
00512 for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ;
00513 assert(intg > 0);
00514 }
00515 else
00516 intg=0;
00517 *intg_result= intg;
00518 return buf0;
00519 }
00520
00521
00528 int decimal_actual_fraction(decimal_t *from)
00529 {
00530 int frac= from->frac, i;
00531 dec1 *buf0= from->buf + round_up(from->intg) + round_up(frac) - 1;
00532
00533 if (frac == 0)
00534 return 0;
00535
00536 i= ((frac - 1) % DIG_PER_DEC1 + 1);
00537 while (frac > 0 && *buf0 == 0)
00538 {
00539 frac-= i;
00540 i= DIG_PER_DEC1;
00541 buf0--;
00542 }
00543 if (frac > 0)
00544 {
00545 for (i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1); *buf0 % powers10[i++] == 0; frac--) {};
00546 }
00547 return frac;
00548 }
00549
00550
00572 int decimal2string(const decimal_t *from, char *to, int *to_len,
00573 int fixed_precision, int fixed_decimals,
00574 char filler)
00575 {
00576 int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
00577
00578 int fixed_intg= (fixed_precision ?
00579 (fixed_precision - fixed_decimals) : 0);
00580 int error=E_DEC_OK;
00581 char *s=to;
00582 dec1 *buf, *buf0=from->buf, tmp;
00583
00584 assert(*to_len >= 2+from->sign);
00585
00586
00587 buf0= remove_leading_zeroes(from, &intg);
00588 if (unlikely(intg+frac==0))
00589 {
00590 intg=1;
00591 tmp=0;
00592 buf0=&tmp;
00593 }
00594
00595 if (!(intg_len= fixed_precision ? fixed_intg : intg))
00596 intg_len= 1;
00597 frac_len= fixed_precision ? fixed_decimals : frac;
00598 len= from->sign + intg_len + test(frac) + frac_len;
00599 if (fixed_precision)
00600 {
00601 if (frac > fixed_decimals)
00602 {
00603 error= E_DEC_TRUNCATED;
00604 frac= fixed_decimals;
00605 }
00606 if (intg > fixed_intg)
00607 {
00608 error= E_DEC_OVERFLOW;
00609 intg= fixed_intg;
00610 }
00611 }
00612 else if (unlikely(len > --*to_len))
00613 {
00614 int j= len-*to_len;
00615 error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
00616 if (frac && j >= frac + 1) j--;
00617 if (j > frac)
00618 {
00619 intg-= j-frac;
00620 frac= 0;
00621 }
00622 else
00623 frac-=j;
00624 len= from->sign + intg_len + test(frac) + frac_len;
00625 }
00626 *to_len=len;
00627 s[len]=0;
00628
00629 if (from->sign)
00630 *s++='-';
00631
00632 if (frac)
00633 {
00634 char *s1= s + intg_len;
00635 fill= frac_len - frac;
00636 buf=buf0+round_up(intg);
00637 *s1++='.';
00638 for (; frac>0; frac-=DIG_PER_DEC1)
00639 {
00640 dec1 x=*buf++;
00641 for (i=min(frac, DIG_PER_DEC1); i; i--)
00642 {
00643 dec1 y=x/DIG_MASK;
00644 *s1++='0'+(unsigned char)y;
00645 x-=y*DIG_MASK;
00646 x*=10;
00647 }
00648 }
00649 for(; fill; fill--)
00650 *s1++=filler;
00651 }
00652
00653 fill= intg_len - intg;
00654 if (intg == 0)
00655 fill--;
00656 for(; fill; fill--)
00657 *s++=filler;
00658 if (intg)
00659 {
00660 s+=intg;
00661 for (buf=buf0+round_up(intg); intg>0; intg-=DIG_PER_DEC1)
00662 {
00663 dec1 x=*--buf;
00664 for (i=min(intg, DIG_PER_DEC1); i; i--)
00665 {
00666 dec1 y=x/10;
00667 *--s='0'+(unsigned char)(x-y*10);
00668 x=y;
00669 }
00670 }
00671 }
00672 else
00673 *s= '0';
00674 return error;
00675 }
00676
00677
00687 static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
00688 {
00689 int start, stop, i;
00690 dec1 *buf_beg= from->buf;
00691 dec1 *end= from->buf + round_up(from->intg) + round_up(from->frac);
00692 dec1 *buf_end= end - 1;
00693
00694
00695 while (buf_beg < end && *buf_beg == 0)
00696 buf_beg++;
00697
00698 if (buf_beg >= end)
00699 {
00700
00701 *start_result= *end_result= 0;
00702 return;
00703 }
00704
00705
00706 if (buf_beg == from->buf && from->intg)
00707 {
00708 start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1));
00709 i--;
00710 }
00711 else
00712 {
00713 i= DIG_PER_DEC1 - 1;
00714 start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
00715 }
00716 if (buf_beg < end)
00717 for (; *buf_beg < powers10[i--]; start++) ;
00718 *start_result= start;
00719
00720
00721 while (buf_end > buf_beg && *buf_end == 0)
00722 buf_end--;
00723
00724 if (buf_end == end - 1 && from->frac)
00725 {
00726 stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
00727 (i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
00728 i= DIG_PER_DEC1 - i + 1;
00729 }
00730 else
00731 {
00732 stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
00733 i= 1;
00734 }
00735 for (; *buf_end % powers10[i++] == 0; stop--) {};
00736 *end_result= stop;
00737 }
00738
00739
00755 static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
00756 {
00757 dec1 *from= dec->buf + round_up(beg + 1) - 1;
00758 dec1 *end= dec->buf + round_up(last) - 1;
00759 int c_shift= DIG_PER_DEC1 - shift;
00760 assert(from >= dec->buf);
00761 assert(end < dec->buf + dec->len);
00762 if (beg % DIG_PER_DEC1 < shift)
00763 *(from - 1)= (*from) / powers10[c_shift];
00764 for(; from < end; from++)
00765 *from= ((*from % powers10[c_shift]) * powers10[shift] +
00766 (*(from + 1)) / powers10[c_shift]);
00767 *from= (*from % powers10[c_shift]) * powers10[shift];
00768 }
00769
00770
00783 static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
00784 {
00785 dec1 *from= dec->buf + round_up(last) - 1;
00786 dec1 *end= dec->buf + round_up(beg + 1) - 1;
00787 int c_shift= DIG_PER_DEC1 - shift;
00788 assert(from < dec->buf + dec->len);
00789 assert(end >= dec->buf);
00790 if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
00791 *(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
00792 for(; from > end; from--)
00793 *from= (*from / powers10[shift] +
00794 (*(from - 1) % powers10[shift]) * powers10[c_shift]);
00795 *from= *from / powers10[shift];
00796 }
00797
00798
00815 static int decimal_shift(decimal_t *dec, int shift)
00816 {
00817
00818 int beg;
00819
00820 int end;
00821
00822 int point= round_up(dec->intg) * DIG_PER_DEC1;
00823
00824 int new_point= point + shift;
00825
00826 int digits_int, digits_frac;
00827
00828 int new_len, new_frac_len;
00829
00830 int err= E_DEC_OK;
00831 int new_front;
00832
00833 if (shift == 0)
00834 return E_DEC_OK;
00835
00836 digits_bounds(dec, &beg, &end);
00837
00838 if (beg == end)
00839 {
00840 dec->set_zero();
00841 return E_DEC_OK;
00842 }
00843
00844 digits_int= new_point - beg;
00845 set_if_bigger(digits_int, 0);
00846 digits_frac= end - new_point;
00847 set_if_bigger(digits_frac, 0);
00848
00849 if ((new_len= round_up(digits_int) + (new_frac_len= round_up(digits_frac))) >
00850 dec->len)
00851 {
00852 int lack= new_len - dec->len;
00853 int diff;
00854
00855 if (new_frac_len < lack)
00856 return E_DEC_OVERFLOW;
00857
00858
00859 err= E_DEC_TRUNCATED;
00860 new_frac_len-= lack;
00861 diff= digits_frac - (new_frac_len * DIG_PER_DEC1);
00862
00863 decimal_round(dec, dec, end - point - diff, HALF_UP);
00864 end-= diff;
00865 digits_frac= new_frac_len * DIG_PER_DEC1;
00866
00867 if (end <= beg)
00868 {
00869
00870
00871
00872
00873 dec->set_zero();
00874
00875 return E_DEC_TRUNCATED;
00876 }
00877 }
00878
00879 if (shift % DIG_PER_DEC1)
00880 {
00881 int l_mini_shift, r_mini_shift, mini_shift;
00882 int do_left;
00883
00884
00885
00886
00887 if (shift > 0)
00888 {
00889 l_mini_shift= shift % DIG_PER_DEC1;
00890 r_mini_shift= DIG_PER_DEC1 - l_mini_shift;
00891
00892
00893
00894
00895
00896 do_left= l_mini_shift <= beg;
00897 assert(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
00898 }
00899 else
00900 {
00901 r_mini_shift= (-shift) % DIG_PER_DEC1;
00902 l_mini_shift= DIG_PER_DEC1 - r_mini_shift;
00903
00904 do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
00905 assert(!do_left || l_mini_shift <= beg);
00906 }
00907 if (do_left)
00908 {
00909 do_mini_left_shift(dec, l_mini_shift, beg, end);
00910 mini_shift= (-l_mini_shift);
00911 }
00912 else
00913 {
00914 do_mini_right_shift(dec, r_mini_shift, beg, end);
00915 mini_shift= r_mini_shift;
00916 }
00917 new_point+= mini_shift;
00918
00919
00920
00921
00922 if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1)
00923 {
00924 dec->intg= digits_int;
00925 dec->frac= digits_frac;
00926 return err;
00927 }
00928 beg+= mini_shift;
00929 end+= mini_shift;
00930 }
00931
00932
00933 if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 ||
00934 new_front < 0)
00935 {
00936
00937 int d_shift;
00938 dec1 *to, *barier;
00939 if (new_front > 0)
00940 {
00941
00942 d_shift= new_front / DIG_PER_DEC1;
00943 to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
00944 barier= dec->buf + (round_up(end) - 1 - d_shift);
00945 assert(to >= dec->buf);
00946 assert(barier + d_shift < dec->buf + dec->len);
00947 for(; to <= barier; to++)
00948 *to= *(to + d_shift);
00949 for(barier+= d_shift; to <= barier; to++)
00950 *to= 0;
00951 d_shift= -d_shift;
00952 }
00953 else
00954 {
00955
00956 d_shift= (1 - new_front) / DIG_PER_DEC1;
00957 to= dec->buf + round_up(end) - 1 + d_shift;
00958 barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
00959 assert(to < dec->buf + dec->len);
00960 assert(barier - d_shift >= dec->buf);
00961 for(; to >= barier; to--)
00962 *to= *(to - d_shift);
00963 for(barier-= d_shift; to >= barier; to--)
00964 *to= 0;
00965 }
00966 d_shift*= DIG_PER_DEC1;
00967 beg+= d_shift;
00968 end+= d_shift;
00969 new_point+= d_shift;
00970 }
00971
00972
00973
00974
00975
00976
00977 beg= round_up(beg + 1) - 1;
00978 end= round_up(end) - 1;
00979 assert(new_point >= 0);
00980
00981
00982 if (new_point != 0)
00983 new_point= round_up(new_point) - 1;
00984
00985 if (new_point > end)
00986 {
00987 do
00988 {
00989 dec->buf[new_point]=0;
00990 } while (--new_point > end);
00991 }
00992 else
00993 {
00994 for (; new_point < beg; new_point++)
00995 dec->buf[new_point]= 0;
00996 }
00997 dec->intg= digits_int;
00998 dec->frac= digits_frac;
00999 return err;
01000 }
01001
01002
01022 int
01023 internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
01024 {
01025 char *s= from, *s1;
01026 char *end_of_string = *end;
01027 char *endp;
01028 int i, intg, frac, error, intg1, frac1;
01029 dec1 x,*buf;
01030 sanity(to);
01031
01032 error= E_DEC_BAD_NUM;
01033 while (s < end_of_string && my_isspace(&my_charset_utf8_general_ci, *s))
01034 s++;
01035 if (s == end_of_string)
01036 goto fatal_error;
01037
01038 if ((to->sign= (*s == '-')))
01039 s++;
01040 else if (*s == '+')
01041 s++;
01042
01043 s1=s;
01044 while (s < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *s))
01045 s++;
01046 intg= (int) (s-s1);
01047 if (s < end_of_string && *s=='.')
01048 {
01049 endp= s+1;
01050 while (endp < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *endp))
01051 endp++;
01052 frac= (int) (endp - s - 1);
01053 }
01054 else
01055 {
01056 frac= 0;
01057 endp= s;
01058 }
01059
01060 *end= endp;
01061
01062 if (frac+intg == 0)
01063 goto fatal_error;
01064
01065 error= 0;
01066 if (fixed)
01067 {
01068 if (frac > to->frac)
01069 {
01070 error=E_DEC_TRUNCATED;
01071 frac=to->frac;
01072 }
01073 if (intg > to->intg)
01074 {
01075 error=E_DEC_OVERFLOW;
01076 intg=to->intg;
01077 }
01078 intg1=round_up(intg);
01079 frac1=round_up(frac);
01080 if (intg1+frac1 > to->len)
01081 {
01082 error= E_DEC_OOM;
01083 goto fatal_error;
01084 }
01085 }
01086 else
01087 {
01088 intg1=round_up(intg);
01089 frac1=round_up(frac);
01090 fix_intg_frac_error(to->len, intg1, frac1, error);
01091 if (unlikely(error))
01092 {
01093 frac=frac1*DIG_PER_DEC1;
01094 if (error == E_DEC_OVERFLOW)
01095 intg=intg1*DIG_PER_DEC1;
01096 }
01097 }
01098
01099 to->intg=intg;
01100 to->frac=frac;
01101
01102 buf=to->buf+intg1;
01103 s1=s;
01104
01105 for (x=0, i=0; intg; intg--)
01106 {
01107 x+= (*--s - '0')*powers10[i];
01108
01109 if (unlikely(++i == DIG_PER_DEC1))
01110 {
01111 *--buf=x;
01112 x=0;
01113 i=0;
01114 }
01115 }
01116 if (i)
01117 *--buf=x;
01118
01119 buf=to->buf+intg1;
01120 for (x=0, i=0; frac; frac--)
01121 {
01122 x= (*++s1 - '0') + x*10;
01123
01124 if (unlikely(++i == DIG_PER_DEC1))
01125 {
01126 *buf++=x;
01127 x=0;
01128 i=0;
01129 }
01130 }
01131 if (i)
01132 *buf=x*powers10[DIG_PER_DEC1-i];
01133
01134
01135 if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
01136 {
01137 int str_error;
01138 const int64_t exponent= internal::my_strtoll10(endp+1, (char**) &end_of_string,
01139 &str_error);
01140
01141 if (end_of_string != endp +1)
01142 {
01143 *end= (char*) end_of_string;
01144 if (str_error > 0)
01145 {
01146 error= E_DEC_BAD_NUM;
01147 goto fatal_error;
01148 }
01149 if (exponent > INT_MAX/2 || (str_error == 0 && exponent < 0))
01150 {
01151 error= E_DEC_OVERFLOW;
01152 goto fatal_error;
01153 }
01154 if (exponent < INT_MIN/2 && error != E_DEC_OVERFLOW)
01155 {
01156 error= E_DEC_TRUNCATED;
01157 goto fatal_error;
01158 }
01159 if (error != E_DEC_OVERFLOW)
01160 error= decimal_shift(to, (int) exponent);
01161 }
01162 }
01163 return error;
01164
01165 fatal_error:
01166 to->set_zero();
01167 return error;
01168 }
01169
01170
01181 int decimal2double(const decimal_t *from, double *to)
01182 {
01183 char strbuf[FLOATING_POINT_BUFFER], *end;
01184 int len= sizeof(strbuf);
01185 int rc, error;
01186
01187 rc = decimal2string(from, strbuf, &len, 0, 0, 0);
01188 end= strbuf + len;
01189
01190 *to= internal::my_strtod(strbuf, &end, &error);
01191
01192 return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
01193 }
01194
01205 int double2decimal(const double from, decimal_t *to)
01206 {
01207 char buff[FLOATING_POINT_BUFFER], *end;
01208 int res;
01209 end= buff + internal::my_gcvt(from,
01210 internal::MY_GCVT_ARG_DOUBLE,
01211 sizeof(buff) - 1, buff, NULL);
01212 res= string2decimal(buff, to, &end);
01213 return(res);
01214 }
01215
01216
01217 static int ull2dec(uint64_t from, decimal_t *to)
01218 {
01219 int intg1, error=E_DEC_OK;
01220 uint64_t x=from;
01221 dec1 *buf;
01222
01223 sanity(to);
01224
01225 for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE) {};
01226 if (unlikely(intg1 > to->len))
01227 {
01228 intg1=to->len;
01229 error=E_DEC_OVERFLOW;
01230 }
01231 to->frac=0;
01232 to->intg=intg1*DIG_PER_DEC1;
01233
01234 for (buf=to->buf+intg1; intg1; intg1--)
01235 {
01236 uint64_t y=x/DIG_BASE;
01237 *--buf=(dec1)(x-y*DIG_BASE);
01238 x=y;
01239 }
01240 return error;
01241 }
01242
01243 int uint64_t2decimal(const uint64_t from, decimal_t *to)
01244 {
01245 to->sign=0;
01246 return ull2dec(from, to);
01247 }
01248
01249 int int64_t2decimal(const int64_t from, decimal_t *to)
01250 {
01251 if ((to->sign= from < 0))
01252 return ull2dec(-from, to);
01253 return ull2dec(from, to);
01254 }
01255
01256 int decimal2uint64_t(const decimal_t *from, uint64_t *to)
01257 {
01258 dec1 *buf=from->buf;
01259 uint64_t x=0;
01260 int intg, frac;
01261
01262 if (from->sign)
01263 {
01264 *to= 0ULL;
01265 return E_DEC_OVERFLOW;
01266 }
01267
01268 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
01269 {
01270 uint64_t y=x;
01271 x=x*DIG_BASE + *buf++;
01272 if (unlikely(y > ((uint64_t) UINT64_MAX/DIG_BASE) || x < y))
01273 {
01274 *to=UINT64_MAX;
01275 return E_DEC_OVERFLOW;
01276 }
01277 }
01278 *to=x;
01279 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
01280 if (*buf++)
01281 return E_DEC_TRUNCATED;
01282 return E_DEC_OK;
01283 }
01284
01285 int decimal2int64_t(const decimal_t *from, int64_t *to)
01286 {
01287 dec1 *buf=from->buf;
01288 int64_t x=0;
01289 int intg, frac;
01290
01291 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
01292 {
01293 int64_t y=x;
01294
01295
01296
01297
01298
01299
01300 x=x*DIG_BASE - *buf++;
01301 if (unlikely(y < (INT64_MIN/DIG_BASE) || x > y))
01302 {
01303
01304
01305
01306
01307 *to= from->sign ? INT64_MIN : INT64_MAX;
01308 return E_DEC_OVERFLOW;
01309 }
01310 }
01311
01312 if (unlikely(from->sign==0 && x == INT64_MIN))
01313 {
01314 *to= INT64_MAX;
01315 return E_DEC_OVERFLOW;
01316 }
01317
01318 *to=from->sign ? x : -x;
01319 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
01320 if (*buf++)
01321 return E_DEC_TRUNCATED;
01322 return E_DEC_OK;
01323 }
01324
01404 int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
01405 {
01406 dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
01407 int error=E_DEC_OK, intg=precision-frac,
01408 isize1, intg1, intg1x, from_intg,
01409 intg0=intg/DIG_PER_DEC1,
01410 frac0=frac/DIG_PER_DEC1,
01411 intg0x=intg-intg0*DIG_PER_DEC1,
01412 frac0x=frac-frac0*DIG_PER_DEC1,
01413 frac1=from->frac/DIG_PER_DEC1,
01414 frac1x=from->frac-frac1*DIG_PER_DEC1,
01415 isize0=intg0*sizeof(dec1)+dig2bytes[intg0x],
01416 fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x],
01417 fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
01418 const int orig_isize0= isize0;
01419 const int orig_fsize0= fsize0;
01420 unsigned char *orig_to= to;
01421
01422 buf1= remove_leading_zeroes(from, &from_intg);
01423
01424 if (unlikely(from_intg+fsize1==0))
01425 {
01426 mask=0;
01427 intg=1;
01428 buf1=&mask;
01429 }
01430
01431 intg1=from_intg/DIG_PER_DEC1;
01432 intg1x=from_intg-intg1*DIG_PER_DEC1;
01433 isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
01434
01435 if (intg < from_intg)
01436 {
01437 buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
01438 intg1=intg0; intg1x=intg0x;
01439 error=E_DEC_OVERFLOW;
01440 }
01441 else if (isize0 > isize1)
01442 {
01443 while (isize0-- > isize1)
01444 *to++= (char)mask;
01445 }
01446 if (fsize0 < fsize1)
01447 {
01448 frac1=frac0; frac1x=frac0x;
01449 error=E_DEC_TRUNCATED;
01450 }
01451 else if (fsize0 > fsize1 && frac1x)
01452 {
01453 if (frac0 == frac1)
01454 {
01455 frac1x=frac0x;
01456 fsize0= fsize1;
01457 }
01458 else
01459 {
01460 frac1++;
01461 frac1x=0;
01462 }
01463 }
01464
01465
01466 if (intg1x)
01467 {
01468 int i=dig2bytes[intg1x];
01469 dec1 x=(*buf1++ % powers10[intg1x]) ^ mask;
01470 switch (i)
01471 {
01472 case 1: mi_int1store(to, x); break;
01473 case 2: mi_int2store(to, x); break;
01474 case 3: mi_int3store(to, x); break;
01475 case 4: mi_int4store(to, x); break;
01476 default: assert(0);
01477 }
01478 to+=i;
01479 }
01480
01481
01482 for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=sizeof(dec1))
01483 {
01484 dec1 x=*buf1++ ^ mask;
01485 assert(sizeof(dec1) == 4);
01486 mi_int4store(to, x);
01487 }
01488
01489
01490 if (frac1x)
01491 {
01492 dec1 x;
01493 int i=dig2bytes[frac1x],
01494 lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x);
01495 while (frac1x < lim && dig2bytes[frac1x] == i)
01496 frac1x++;
01497 x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask;
01498 switch (i)
01499 {
01500 case 1: mi_int1store(to, x); break;
01501 case 2: mi_int2store(to, x); break;
01502 case 3: mi_int3store(to, x); break;
01503 case 4: mi_int4store(to, x); break;
01504 default: assert(0);
01505 }
01506 to+=i;
01507 }
01508 if (fsize0 > fsize1)
01509 {
01510 unsigned char *to_end= orig_to + orig_fsize0 + orig_isize0;
01511
01512 while (fsize0-- > fsize1 && to < to_end)
01513 *to++= (unsigned char)mask;
01514 }
01515 orig_to[0]^= 0x80;
01516
01517
01518 assert(to == orig_to + orig_fsize0 + orig_isize0);
01519 return error;
01520 }
01521
01537 int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
01538 {
01539 int error=E_DEC_OK, intg=precision-scale,
01540 intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
01541 intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
01542 intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
01543 dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
01544 const unsigned char *stop;
01545 unsigned char *d_copy;
01546 int bin_size= decimal_bin_size(precision, scale);
01547
01548 sanity(to);
01549 d_copy= (unsigned char*) alloca(bin_size);
01550 memcpy(d_copy, from, bin_size);
01551 d_copy[0]^= 0x80;
01552 from= d_copy;
01553
01554 fix_intg_frac_error(to->len, intg1, frac1, error);
01555 if (unlikely(error))
01556 {
01557 if (intg1 < intg0+(intg0x>0))
01558 {
01559 from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1);
01560 frac0=frac0x=intg0x=0;
01561 intg0=intg1;
01562 }
01563 else
01564 {
01565 frac0x=0;
01566 frac0=frac1;
01567 }
01568 }
01569
01570 to->sign=(mask != 0);
01571 to->intg=intg0*DIG_PER_DEC1+intg0x;
01572 to->frac=frac0*DIG_PER_DEC1+frac0x;
01573
01574 if (intg0x)
01575 {
01576 int i=dig2bytes[intg0x];
01577 dec1 x= 0;
01578 switch (i)
01579 {
01580 case 1: x=mi_sint1korr(from); break;
01581 case 2: x=mi_sint2korr(from); break;
01582 case 3: x=mi_sint3korr(from); break;
01583 case 4: x=mi_sint4korr(from); break;
01584 default: assert(0);
01585 }
01586 from+=i;
01587 *buf=x ^ mask;
01588 if (((uint64_t)*buf) >= (uint64_t) powers10[intg0x+1])
01589 goto err;
01590 if (buf > to->buf || *buf != 0)
01591 buf++;
01592 else
01593 to->intg-=intg0x;
01594 }
01595 for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
01596 {
01597 assert(sizeof(dec1) == 4);
01598 *buf=mi_sint4korr(from) ^ mask;
01599 if (((uint32_t)*buf) > DIG_MAX)
01600 goto err;
01601 if (buf > to->buf || *buf != 0)
01602 buf++;
01603 else
01604 to->intg-=DIG_PER_DEC1;
01605 }
01606 assert(to->intg >=0);
01607 for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
01608 {
01609 assert(sizeof(dec1) == 4);
01610 *buf=mi_sint4korr(from) ^ mask;
01611 if (((uint32_t)*buf) > DIG_MAX)
01612 goto err;
01613 buf++;
01614 }
01615 if (frac0x)
01616 {
01617 int i=dig2bytes[frac0x];
01618 dec1 x= 0;
01619 switch (i)
01620 {
01621 case 1: x=mi_sint1korr(from); break;
01622 case 2: x=mi_sint2korr(from); break;
01623 case 3: x=mi_sint3korr(from); break;
01624 case 4: x=mi_sint4korr(from); break;
01625 default: assert(0);
01626 }
01627 *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
01628 if (((uint32_t)*buf) > DIG_MAX)
01629 goto err;
01630 buf++;
01631 }
01632 return error;
01633
01634 err:
01635 to->set_zero();
01636 return(E_DEC_BAD_NUM);
01637 }
01638
01644 int decimal_bin_size(int precision, int scale)
01645 {
01646 int intg=precision-scale,
01647 intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
01648 intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
01649
01650 assert(scale >= 0 && precision > 0 && scale <= precision);
01651 return intg0*sizeof(dec1)+dig2bytes[intg0x]+
01652 frac0*sizeof(dec1)+dig2bytes[frac0x];
01653 }
01654
01670 int
01671 decimal_round(const decimal_t *from, decimal_t *to, int scale,
01672 decimal_round_mode mode)
01673 {
01674 int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
01675 frac1=round_up(from->frac), round_digit= 0,
01676 intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
01677 intg1=round_up(from->intg +
01678 (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
01679 dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
01680 int first_dig;
01681
01682 sanity(to);
01683
01684 switch (mode) {
01685 case HALF_UP:
01686 case HALF_EVEN: round_digit=5; break;
01687 case CEILING: round_digit= from->sign ? 10 : 0; break;
01688 case FLOOR: round_digit= from->sign ? 0 : 10; break;
01689 case TRUNCATE: round_digit=10; break;
01690 default: assert(0);
01691 }
01692
01693 if (unlikely(frac0+intg0 > len))
01694 {
01695 frac0=len-intg0;
01696 scale=frac0*DIG_PER_DEC1;
01697 error=E_DEC_TRUNCATED;
01698 }
01699
01700 if (scale+from->intg < 0)
01701 {
01702 to->set_zero();
01703 return E_DEC_OK;
01704 }
01705
01706 if (to != from || intg1>intg0)
01707 {
01708 dec1 *p0= buf0+intg0+max(frac1, frac0);
01709 dec1 *p1= buf1+intg1+max(frac1, frac0);
01710
01711 while (buf0 < p0)
01712 *(--p1) = *(--p0);
01713 if (unlikely(intg1 > intg0))
01714 to->buf[0]= 0;
01715
01716 intg0= intg1;
01717 buf0=to->buf;
01718 buf1=to->buf;
01719 to->sign=from->sign;
01720 to->intg=min(intg0, len)*DIG_PER_DEC1;
01721 }
01722
01723 if (frac0 > frac1)
01724 {
01725 buf1+=intg0+frac1;
01726 while (frac0-- > frac1)
01727 *buf1++=0;
01728 goto done;
01729 }
01730
01731 if (scale >= from->frac)
01732 goto done;
01733
01734 buf0+=intg0+frac0-1;
01735 buf1+=intg0+frac0-1;
01736 if (scale == frac0*DIG_PER_DEC1)
01737 {
01738 int do_inc= false;
01739 assert(frac0+intg0 >= 0);
01740 switch (round_digit) {
01741 case 0:
01742 {
01743 dec1 *p0= buf0 + (frac1-frac0);
01744 for (; p0 > buf0; p0--)
01745 {
01746 if (*p0)
01747 {
01748 do_inc= true;
01749 break;
01750 }
01751 }
01752 break;
01753 }
01754 case 5:
01755 {
01756 x= buf0[1]/DIG_MASK;
01757 do_inc= (x>5) || ((x == 5) &&
01758 (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
01759 break;
01760 }
01761 default:
01762 break;
01763 }
01764 if (do_inc)
01765 {
01766 if (frac0+intg0>0)
01767 (*buf1)++;
01768 else
01769 *(++buf1)=DIG_BASE;
01770 }
01771 else if (frac0+intg0==0)
01772 {
01773 to->set_zero();
01774 return E_DEC_OK;
01775 }
01776 }
01777 else
01778 {
01780 int pos=frac0*DIG_PER_DEC1-scale-1;
01781 assert(frac0+intg0 > 0);
01782 x=*buf1 / powers10[pos];
01783 y=x % 10;
01784 if (y > round_digit ||
01785 (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
01786 x+=10;
01787 *buf1=powers10[pos]*(x-y);
01788 }
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 if (frac0 < frac1)
01800 {
01801 dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0);
01802 dec1 *end= to->buf + len;
01803
01804 while (buf < end)
01805 *buf++=0;
01806 }
01807 if (*buf1 >= DIG_BASE)
01808 {
01809 carry=1;
01810 *buf1-=DIG_BASE;
01811 while (carry && --buf1 >= to->buf)
01812 add(*buf1, *buf1, 0, carry);
01813 if (unlikely(carry))
01814 {
01815
01816 if (frac0+intg0 >= len)
01817 {
01818 frac0--;
01819 scale=frac0*DIG_PER_DEC1;
01820 error=E_DEC_TRUNCATED;
01821 }
01822 for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--)
01823 {
01824 buf1[0]=buf1[-1];
01825 }
01826 *buf1=1;
01827 to->intg++;
01828 }
01829 }
01830 else
01831 {
01832 for (;;)
01833 {
01834 if (likely(*buf1))
01835 break;
01836 if (buf1-- == to->buf)
01837 {
01838
01839 dec1 *p0= to->buf + frac0 + 1;
01840 to->intg=1;
01841 to->frac= max(scale, 0);
01842 to->sign= 0;
01843 for (buf1= to->buf; buf1<p0; buf1++)
01844 *buf1= 0;
01845 return E_DEC_OK;
01846 }
01847 }
01848 }
01849
01850
01851 first_dig= to->intg % DIG_PER_DEC1;
01852 if (first_dig && (*buf1 >= powers10[first_dig]))
01853 to->intg++;
01854
01855 if (scale<0)
01856 scale=0;
01857
01858 done:
01859 to->frac=scale;
01860 return error;
01861 }
01862
01863 static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
01864 {
01865 int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
01866 frac1=round_up(from1->frac), frac2=round_up(from2->frac),
01867 frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
01868 dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
01869
01870 sanity(to);
01871
01872
01873 x=intg1 > intg2 ? from1->buf[0] :
01874 intg2 > intg1 ? from2->buf[0] :
01875 from1->buf[0] + from2->buf[0] ;
01876 if (unlikely(x > DIG_MAX-1))
01877 {
01878 intg0++;
01879 to->buf[0]=0;
01880 }
01881
01882 fix_intg_frac_error(to->len, intg0, frac0, error);
01883 if (unlikely(error == E_DEC_OVERFLOW))
01884 {
01885 max_decimal(to->len * DIG_PER_DEC1, 0, to);
01886 return error;
01887 }
01888
01889 buf0=to->buf+intg0+frac0;
01890
01891 to->sign=from1->sign;
01892 to->frac=max(from1->frac, from2->frac);
01893 to->intg=intg0*DIG_PER_DEC1;
01894 if (unlikely(error))
01895 {
01896 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
01897 set_if_smaller(frac1, frac0);
01898 set_if_smaller(frac2, frac0);
01899 set_if_smaller(intg1, intg0);
01900 set_if_smaller(intg2, intg0);
01901 }
01902
01903
01904 if (frac1 > frac2)
01905 {
01906 buf1=from1->buf+intg1+frac1;
01907 stop=from1->buf+intg1+frac2;
01908 buf2=from2->buf+intg2+frac2;
01909 stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
01910 }
01911 else
01912 {
01913 buf1=from2->buf+intg2+frac2;
01914 stop=from2->buf+intg2+frac1;
01915 buf2=from1->buf+intg1+frac1;
01916 stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
01917 }
01918 while (buf1 > stop)
01919 *--buf0=*--buf1;
01920
01921
01922 carry=0;
01923 while (buf1 > stop2)
01924 {
01925 add(*--buf0, *--buf1, *--buf2, carry);
01926 }
01927
01928
01929 buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
01930 ((stop=from2->buf)+intg2-intg1) ;
01931 while (buf1 > stop)
01932 {
01933 add(*--buf0, *--buf1, 0, carry);
01934 }
01935
01936 if (unlikely(carry))
01937 *--buf0=1;
01938 assert(buf0 == to->buf || buf0 == to->buf+1);
01939
01940 return error;
01941 }
01942
01943
01944
01945 static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
01946 {
01947 int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
01948 frac1=round_up(from1->frac), frac2=round_up(from2->frac);
01949 int frac0=max(frac1, frac2), error;
01950 dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
01951
01952
01953 start1=buf1=from1->buf; stop1=buf1+intg1;
01954 start2=buf2=from2->buf; stop2=buf2+intg2;
01955 if (unlikely(*buf1 == 0))
01956 {
01957 while (buf1 < stop1 && *buf1 == 0)
01958 buf1++;
01959 start1=buf1;
01960 intg1= (int) (stop1-buf1);
01961 }
01962 if (unlikely(*buf2 == 0))
01963 {
01964 while (buf2 < stop2 && *buf2 == 0)
01965 buf2++;
01966 start2=buf2;
01967 intg2= (int) (stop2-buf2);
01968 }
01969 if (intg2 > intg1)
01970 carry=1;
01971 else if (intg2 == intg1)
01972 {
01973 dec1 *end1= stop1 + (frac1 - 1);
01974 dec1 *end2= stop2 + (frac2 - 1);
01975 while (unlikely((buf1 <= end1) && (*end1 == 0)))
01976 end1--;
01977 while (unlikely((buf2 <= end2) && (*end2 == 0)))
01978 end2--;
01979 frac1= (int) (end1 - stop1) + 1;
01980 frac2= (int) (end2 - stop2) + 1;
01981 while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
01982 buf1++, buf2++;
01983 if (buf1 <= end1)
01984 {
01985 if (buf2 <= end2)
01986 carry= *buf2 > *buf1;
01987 else
01988 carry= 0;
01989 }
01990 else
01991 {
01992 if (buf2 <= end2)
01993 carry=1;
01994 else
01995 {
01996 if (to == 0)
01997 return 0;
01998
01999 to->set_zero();
02000
02001 return E_DEC_OK;
02002 }
02003 }
02004 }
02005
02006 if (to == 0)
02007 return carry == from1->sign ? 1 : -1;
02008
02009 sanity(to);
02010
02011 to->sign=from1->sign;
02012
02013
02014 if (carry)
02015 {
02016 swap(from1, from2);
02017 swap(start1, start2);
02018 swap(intg1, intg2);
02019 swap(frac1, frac2);
02020 to->sign= 1 - to->sign;
02021 }
02022
02023 fix_intg_frac_error(to->len, intg1, frac0, error);
02024 buf0=to->buf+intg1+frac0;
02025
02026 to->frac=max(from1->frac, from2->frac);
02027 to->intg=intg1*DIG_PER_DEC1;
02028 if (unlikely(error))
02029 {
02030 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
02031 set_if_smaller(frac1, frac0);
02032 set_if_smaller(frac2, frac0);
02033 set_if_smaller(intg2, intg1);
02034 }
02035 carry=0;
02036
02037
02038 if (frac1 > frac2)
02039 {
02040 buf1=start1+intg1+frac1;
02041 stop1=start1+intg1+frac2;
02042 buf2=start2+intg2+frac2;
02043 while (frac0-- > frac1)
02044 *--buf0=0;
02045 while (buf1 > stop1)
02046 *--buf0=*--buf1;
02047 }
02048 else
02049 {
02050 buf1=start1+intg1+frac1;
02051 buf2=start2+intg2+frac2;
02052 stop2=start2+intg2+frac1;
02053 while (frac0-- > frac2)
02054 *--buf0=0;
02055 while (buf2 > stop2)
02056 {
02057 sub(*--buf0, 0, *--buf2, carry);
02058 }
02059 }
02060
02061
02062 while (buf2 > start2)
02063 {
02064 sub(*--buf0, *--buf1, *--buf2, carry);
02065 }
02066
02067
02068 while (carry && buf1 > start1)
02069 {
02070 sub(*--buf0, *--buf1, 0, carry);
02071 }
02072
02073 while (buf1 > start1)
02074 *--buf0=*--buf1;
02075
02076 while (buf0 > to->buf)
02077 *--buf0=0;
02078
02079 return error;
02080 }
02081
02082 int decimal_intg(const decimal_t *from)
02083 {
02084 int res;
02085 dec1 *tmp_res;
02086 tmp_res= remove_leading_zeroes(from, &res);
02087 return res;
02088 }
02089
02090 int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
02091 {
02092 if (likely(from1->sign == from2->sign))
02093 return do_add(from1, from2, to);
02094 return do_sub(from1, from2, to);
02095 }
02096
02097 int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
02098 {
02099 if (likely(from1->sign == from2->sign))
02100 return do_sub(from1, from2, to);
02101 return do_add(from1, from2, to);
02102 }
02103
02104 int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
02105 {
02106 if (likely(from1->sign == from2->sign))
02107 return do_sub(from1, from2, 0);
02108 return from1->sign > from2->sign ? -1 : 1;
02109 }
02110
02111 int decimal_t::isZero() const
02112 {
02113 dec1 *buf1= buf,
02114 *end= buf1 +round_up(intg) +round_up(frac);
02115
02116 while (buf1 < end)
02117 {
02118 if (*buf1++)
02119 {
02120 return 0;
02121 }
02122 }
02123
02124 return 1;
02125 }
02126
02147 int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
02148 {
02149 int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
02150 frac1=round_up(from1->frac), frac2=round_up(from2->frac),
02151 intg0=round_up(from1->intg+from2->intg),
02152 frac0=frac1+frac2, error, i, j, d_to_move;
02153 dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
02154 *start2, *stop2, *stop1, *start0, carry;
02155
02156 sanity(to);
02157
02158 i=intg0;
02159 j=frac0;
02160 fix_intg_frac_error(to->len, intg0, frac0, error);
02161 to->sign=from1->sign != from2->sign;
02162 to->frac=from1->frac+from2->frac;
02163 to->intg=intg0*DIG_PER_DEC1;
02164
02165 if (unlikely(error))
02166 {
02167 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
02168 set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
02169 if (unlikely(i > intg0))
02170 {
02171 i-=intg0;
02172 j=i >> 1;
02173 intg1-= j;
02174 intg2-=i-j;
02175 frac1=frac2=0;
02176 }
02177 else
02178 {
02179 j-=frac0;
02180 i=j >> 1;
02181 frac1-= i;
02182 frac2-=j-i;
02183 }
02184 }
02185 start0=to->buf+intg0+frac0-1;
02186 start2=buf2+frac2-1;
02187 stop1=buf1-intg1;
02188 stop2=buf2-intg2;
02189
02190 memset(to->buf, 0, (intg0+frac0)*sizeof(dec1));
02191
02192 for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
02193 {
02194 carry=0;
02195 for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
02196 {
02197 dec1 hi, lo;
02198 dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
02199 hi=(dec1)(p/DIG_BASE);
02200 lo=(dec1)(p-((dec2)hi)*DIG_BASE);
02201 add2(*buf0, *buf0, lo, carry);
02202 carry+=hi;
02203 }
02204 if (carry)
02205 {
02206 if (buf0 < to->buf)
02207 return E_DEC_OVERFLOW;
02208 add2(*buf0, *buf0, 0, carry);
02209 }
02210 for (buf0--; carry; buf0--)
02211 {
02212 if (buf0 < to->buf)
02213 return E_DEC_OVERFLOW;
02214 add(*buf0, *buf0, 0, carry);
02215 }
02216 }
02217
02218
02219 if (to->sign)
02220 {
02221 dec1 *buf= to->buf;
02222 dec1 *end= to->buf + intg0 + frac0;
02223 assert(buf != end);
02224 for (;;)
02225 {
02226 if (*buf)
02227 break;
02228 if (++buf == end)
02229 {
02230
02231 to->set_zero();
02232 break;
02233 }
02234 }
02235 }
02236 buf1= to->buf;
02237 d_to_move= intg0 + round_up(to->frac);
02238 while (!*buf1 && (to->intg > DIG_PER_DEC1))
02239 {
02240 buf1++;
02241 to->intg-= DIG_PER_DEC1;
02242 d_to_move--;
02243 }
02244 if (to->buf < buf1)
02245 {
02246 dec1 *cur_d= to->buf;
02247 for (; d_to_move--; cur_d++, buf1++)
02248 *cur_d= *buf1;
02249 }
02250 return error;
02251 }
02252
02264 static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
02265 decimal_t *to, decimal_t *mod, int scale_incr)
02266 {
02267 int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
02268 frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
02269 error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
02270 dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
02271 *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
02272 dec2 norm_factor, x, guess, y;
02273
02274 if (mod)
02275 to=mod;
02276
02277 sanity(to);
02278
02279
02280 i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
02281 while (prec2 > 0 && *buf2 == 0)
02282 {
02283 prec2-= i;
02284 i= DIG_PER_DEC1;
02285 buf2++;
02286 }
02287 if (prec2 <= 0)
02288 return E_DEC_DIV_ZERO;
02289 for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
02290 assert(prec2 > 0);
02291
02292 i=((prec1-1) % DIG_PER_DEC1)+1;
02293 while (prec1 > 0 && *buf1 == 0)
02294 {
02295 prec1-=i;
02296 i=DIG_PER_DEC1;
02297 buf1++;
02298 }
02299 if (prec1 <= 0)
02300 {
02301 to->set_zero();
02302 return E_DEC_OK;
02303 }
02304 for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
02305 assert(prec1 > 0);
02306
02307
02308 if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
02309 scale_incr=0;
02310
02311 dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
02312 if (dintg < 0)
02313 {
02314 dintg/=DIG_PER_DEC1;
02315 intg0=0;
02316 }
02317 else
02318 intg0=round_up(dintg);
02319 if (mod)
02320 {
02321
02322
02323
02324
02325
02326 to->sign=from1->sign;
02327 to->frac=max(from1->frac, from2->frac);
02328 frac0=0;
02329 }
02330 else
02331 {
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342 frac0=round_up(frac1+frac2+scale_incr);
02343 fix_intg_frac_error(to->len, intg0, frac0, error);
02344 to->sign=from1->sign != from2->sign;
02345 to->intg=intg0*DIG_PER_DEC1;
02346 to->frac=frac0*DIG_PER_DEC1;
02347 }
02348 buf0=to->buf;
02349 stop0=buf0+intg0+frac0;
02350 if (likely(div_mod))
02351 while (dintg++ < 0)
02352 *buf0++=0;
02353
02354 len1=(i=round_up(prec1))+round_up(2*frac2+scale_incr+1) + 1;
02355 set_if_bigger(len1, 3);
02356 if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
02357 return E_DEC_OOM;
02358 memcpy(tmp1, buf1, i*sizeof(dec1));
02359 memset(tmp1+i, 0, (len1-i)*sizeof(dec1));
02360
02361 start1=tmp1;
02362 stop1=start1+len1;
02363 start2=buf2;
02364 stop2=buf2+round_up(prec2)-1;
02365
02366
02367 while (*stop2 == 0 && stop2 >= start2)
02368 stop2--;
02369 len2= (int) (stop2++ - start2);
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379 norm_factor=DIG_BASE/(*start2+1);
02380 norm2=(dec1)(norm_factor*start2[0]);
02381 if (likely(len2>0))
02382 norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
02383
02384 if (*start1 < *start2)
02385 dcarry=*start1++;
02386 else
02387 dcarry=0;
02388
02389
02390 for (; buf0 < stop0; buf0++)
02391 {
02392
02393 if (unlikely(dcarry == 0 && *start1 < *start2))
02394 guess=0;
02395 else
02396 {
02397
02398 x=start1[0]+((dec2)dcarry)*DIG_BASE;
02399 y=start1[1];
02400 guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
02401 if (unlikely(guess >= DIG_BASE))
02402 guess=DIG_BASE-1;
02403 if (likely(len2>0))
02404 {
02405
02406 if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
02407 guess--;
02408 if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
02409 guess--;
02410 assert(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
02411 }
02412
02413
02414 buf2=stop2;
02415 buf1=start1+len2;
02416 assert(buf1 < stop1);
02417 for (carry=0; buf2 > start2; buf1--)
02418 {
02419 dec1 hi, lo;
02420 x=guess * (*--buf2);
02421 hi=(dec1)(x/DIG_BASE);
02422 lo=(dec1)(x-((dec2)hi)*DIG_BASE);
02423 sub2(*buf1, *buf1, lo, carry);
02424 carry+=hi;
02425 }
02426 carry= dcarry < carry;
02427
02428
02429 if (unlikely(carry))
02430 {
02431
02432 guess--;
02433 buf2=stop2;
02434 buf1=start1+len2;
02435 for (carry=0; buf2 > start2; buf1--)
02436 {
02437 add(*buf1, *buf1, *--buf2, carry);
02438 }
02439 }
02440 }
02441 if (likely(div_mod))
02442 *buf0=(dec1)guess;
02443 dcarry= *start1;
02444 start1++;
02445 }
02446 if (mod)
02447 {
02448
02449
02450
02451
02452
02453 if (dcarry)
02454 *--start1=dcarry;
02455 buf0=to->buf;
02456 intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
02457 frac0=round_up(to->frac);
02458 error=E_DEC_OK;
02459 if (unlikely(frac0==0 && intg0==0))
02460 {
02461 to->set_zero();
02462 goto done;
02463 }
02464 if (intg0<=0)
02465 {
02466 if (unlikely(-intg0 >= to->len))
02467 {
02468 to->set_zero();
02469 error=E_DEC_TRUNCATED;
02470 goto done;
02471 }
02472 stop1=start1+frac0;
02473 frac0+=intg0;
02474 to->intg=0;
02475 while (intg0++ < 0)
02476 *buf0++=0;
02477 }
02478 else
02479 {
02480 if (unlikely(intg0 > to->len))
02481 {
02482 frac0=0;
02483 intg0=to->len;
02484 error=E_DEC_OVERFLOW;
02485 goto done;
02486 }
02487 assert(intg0 <= round_up(from2->intg));
02488 stop1=start1+frac0+intg0;
02489 to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
02490 }
02491 if (unlikely(intg0+frac0 > to->len))
02492 {
02493 stop1-=frac0+intg0-to->len;
02494 frac0=to->len-intg0;
02495 to->frac=frac0*DIG_PER_DEC1;
02496 error=E_DEC_TRUNCATED;
02497 }
02498 assert(buf0 + (stop1 - start1) <= to->buf + to->len);
02499 while (start1 < stop1)
02500 *buf0++=*start1++;
02501 }
02502 done:
02503 return error;
02504 }
02505
02519 int
02520 decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
02521 {
02522 return do_div_mod(from1, from2, to, 0, scale_incr);
02523 }
02524
02550 int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
02551 {
02552 return do_div_mod(from1, from2, 0, to, 0);
02553 }
02554
02555 std::ostream& operator<<(std::ostream& output, const type::Decimal &dec)
02556 {
02557 drizzled::String str;
02558
02559 class_decimal2string(&dec, 0, &str);
02560
02561 output << "type::Decimal:(";
02562 output << str.c_ptr();
02563 output << ")";
02564
02565 return output;
02566 }
02567
02568 }
02569
02570 #ifdef MAIN
02571
02572 int full= 0;
02573 decimal_t a, b, c;
02574 char buf1[100], buf2[100], buf3[100];
02575
02576 void dump_decimal(decimal_t *d)
02577 {
02578 int i;
02579 printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
02580 for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
02581 printf("%09d, ", d->buf[i]);
02582 printf("%09d} */ ", d->buf[i]);
02583 }
02584
02585
02586 void check_result_code(int actual, int want)
02587 {
02588 if (actual != want)
02589 {
02590 printf("\n^^^^^^^^^^^^^ must return %d\n", want);
02591 exit(1);
02592 }
02593 }
02594
02595
02596 void print_decimal(decimal_t *d, const char *orig, int actual, int want)
02597 {
02598 char s[100];
02599 int slen=sizeof(s);
02600
02601 if (full) dump_decimal(d);
02602 decimal2string(d, s, &slen, 0, 0, 0);
02603 printf("'%s'", s);
02604 check_result_code(actual, want);
02605 if (orig && strcmp(orig, s))
02606 {
02607 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
02608 exit(1);
02609 }
02610 }
02611
02612 void test_d2s()
02613 {
02614 char s[100];
02615 int slen, res;
02616
02617
02618 printf("==== decimal2string ====\n");
02619 a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
02620 slen=sizeof(s);
02621 res=decimal2string(&a, s, &slen, 0, 0, 0);
02622 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
02623
02624 a.buf[1]=987000000; a.frac=3;
02625 slen=sizeof(s);
02626 res=decimal2string(&a, s, &slen, 0, 0, 0);
02627 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
02628
02629 a.sign=1;
02630 slen=sizeof(s);
02631 res=decimal2string(&a, s, &slen, 0, 0, 0);
02632 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
02633
02634 slen=8;
02635 res=decimal2string(&a, s, &slen, 0, 0, 0);
02636 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
02637
02638 slen=5;
02639 res=decimal2string(&a, s, &slen, 0, 0, 0);
02640 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
02641
02642 a.buf[0]=987000000; a.frac=3; a.intg=0;
02643 slen=sizeof(s);
02644 res=decimal2string(&a, s, &slen, 0, 0, 0);
02645 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
02646 }
02647
02648 void test_s2d(const char *s, const char *orig, int ex)
02649 {
02650 char s1[100], *end;
02651 int res;
02652 snprintf(s1, sizeof(s1), "'%s'", s);
02653 end= strend(s);
02654 printf("len=%2d %-30s => res=%d ", a.len, s1,
02655 (res= string2decimal(s, &a, &end)));
02656 print_decimal(&a, orig, res, ex);
02657 printf("\n");
02658 }
02659
02660 void test_d2f(const char *s, int ex)
02661 {
02662 char s1[100], *end;
02663 double x;
02664 int res;
02665
02666 snprintf(s1, sizeof(s1), "'%s'", s);
02667 end= strend(s);
02668 string2decimal(s, &a, &end);
02669 res=decimal2double(&a, &x);
02670 if (full) dump_decimal(&a);
02671 printf("%-40s => res=%d %.*g\n", s1, res, a.intg+a.frac, x);
02672 check_result_code(res, ex);
02673 }
02674
02675 void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
02676 {
02677 char s1[100], buf[100], *end;
02678 int res, i, size=decimal_bin_size(p, s);
02679
02680 snprintf(s1, sizeof(s1), "'%s'", str);
02681 end= strend(str);
02682 string2decimal(str, &a, &end);
02683 res=decimal2bin(&a, buf, p, s);
02684 printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
02685 if (full)
02686 {
02687 printf("0x");
02688 for (i=0; i < size; i++)
02689 printf("%02x", ((unsigned char *)buf)[i]);
02690 }
02691 res=bin2decimal(buf, &a, p, s);
02692 printf(" => res=%d ", res);
02693 print_decimal(&a, orig, res, ex);
02694 printf("\n");
02695 }
02696
02697 void test_f2d(double from, int ex)
02698 {
02699 int res;
02700
02701 res=double2decimal(from, &a);
02702 printf("%-40.*f => res=%d ", DBL_DIG-2, from, res);
02703 print_decimal(&a, 0, res, ex);
02704 printf("\n");
02705 }
02706
02707 void test_ull2d(uint64_t from, const char *orig, int ex)
02708 {
02709 char s[100];
02710 int res;
02711
02712 res=uint64_t2decimal(from, &a);
02713 internal::int64_t10_to_str(from,s,10);
02714 printf("%-40s => res=%d ", s, res);
02715 print_decimal(&a, orig, res, ex);
02716 printf("\n");
02717 }
02718
02719 void test_ll2d(int64_t from, const char *orig, int ex)
02720 {
02721 char s[100];
02722 int res;
02723
02724 res=int64_t2decimal(from, &a);
02725 internal::int64_t10_to_str(from,s,-10);
02726 printf("%-40s => res=%d ", s, res);
02727 print_decimal(&a, orig, res, ex);
02728 printf("\n");
02729 }
02730
02731 void test_d2ull(const char *s, const char *orig, int ex)
02732 {
02733 char s1[100], *end;
02734 uint64_t x;
02735 int res;
02736
02737 end= strend(s);
02738 string2decimal(s, &a, &end);
02739 res=decimal2uint64_t(&a, &x);
02740 if (full) dump_decimal(&a);
02741 internal::int64_t10_to_str(x,s1,10);
02742 printf("%-40s => res=%d %s\n", s, res, s1);
02743 check_result_code(res, ex);
02744 if (orig && strcmp(orig, s1))
02745 {
02746 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
02747 exit(1);
02748 }
02749 }
02750
02751 void test_d2ll(const char *s, const char *orig, int ex)
02752 {
02753 char s1[100], *end;
02754 int64_t x;
02755 int res;
02756
02757 end= strend(s);
02758 string2decimal(s, &a, &end);
02759 res=decimal2int64_t(&a, &x);
02760 if (full) dump_decimal(&a);
02761 internal::int64_t10_to_str(x,s1,-10);
02762 printf("%-40s => res=%d %s\n", s, res, s1);
02763 check_result_code(res, ex);
02764 if (orig && strcmp(orig, s1))
02765 {
02766 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
02767 exit(1);
02768 }
02769 }
02770
02771 void test_da(const char *s1, const char *s2, const char *orig, int ex)
02772 {
02773 char s[100], *end;
02774 int res;
02775 snprintf(s, sizeof(s), "'%s' + '%s'", s1, s2);
02776 end= strend(s1);
02777 string2decimal(s1, &a, &end);
02778 end= strend(s2);
02779 string2decimal(s2, &b, &end);
02780 res=decimal_add(&a, &b, &c);
02781 printf("%-40s => res=%d ", s, res);
02782 print_decimal(&c, orig, res, ex);
02783 printf("\n");
02784 }
02785
02786 void test_ds(const char *s1, const char *s2, const char *orig, int ex)
02787 {
02788 char s[100], *end;
02789 int res;
02790 snprintf(s, sizeof(s), "'%s' - '%s'", s1, s2);
02791 end= strend(s1);
02792 string2decimal(s1, &a, &end);
02793 end= strend(s2);
02794 string2decimal(s2, &b, &end);
02795 res=decimal_sub(&a, &b, &c);
02796 printf("%-40s => res=%d ", s, res);
02797 print_decimal(&c, orig, res, ex);
02798 printf("\n");
02799 }
02800
02801 void test_dc(const char *s1, const char *s2, int orig)
02802 {
02803 char s[100], *end;
02804 int res;
02805 snprintf(s, sizeof(s), "'%s' <=> '%s'", s1, s2);
02806 end= strend(s1);
02807 string2decimal(s1, &a, &end);
02808 end= strend(s2);
02809 string2decimal(s2, &b, &end);
02810 res=decimal_cmp(&a, &b);
02811 printf("%-40s => res=%d\n", s, res);
02812 if (orig != res)
02813 {
02814 printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
02815 exit(1);
02816 }
02817 }
02818
02819 void test_dm(const char *s1, const char *s2, const char *orig, int ex)
02820 {
02821 char s[100], *end;
02822 int res;
02823 snprintf(s, sizeof(s), "'%s' * '%s'", s1, s2);
02824 end= strend(s1);
02825 string2decimal(s1, &a, &end);
02826 end= strend(s2);
02827 string2decimal(s2, &b, &end);
02828 res=decimal_mul(&a, &b, &c);
02829 printf("%-40s => res=%d ", s, res);
02830 print_decimal(&c, orig, res, ex);
02831 printf("\n");
02832 }
02833
02834 void test_dv(const char *s1, const char *s2, const char *orig, int ex)
02835 {
02836 char s[100], *end;
02837 int res;
02838 snprintf(s, sizeof(s), "'%s' / '%s'", s1, s2);
02839 end= strend(s1);
02840 string2decimal(s1, &a, &end);
02841 end= strend(s2);
02842 string2decimal(s2, &b, &end);
02843 res=decimal_div(&a, &b, &c, 5);
02844 printf("%-40s => res=%d ", s, res);
02845 check_result_code(res, ex);
02846 if (res == E_DEC_DIV_ZERO)
02847 printf("E_DEC_DIV_ZERO");
02848 else
02849 print_decimal(&c, orig, res, ex);
02850 printf("\n");
02851 }
02852
02853 void test_md(const char *s1, const char *s2, const char *orig, int ex)
02854 {
02855 char s[100], *end;
02856 int res;
02857 snprintf(s, sizeof(s), "'%s' %% '%s'", s1, s2);
02858 end= strend(s1);
02859 string2decimal(s1, &a, &end);
02860 end= strend(s2);
02861 string2decimal(s2, &b, &end);
02862 res=decimal_mod(&a, &b, &c);
02863 printf("%-40s => res=%d ", s, res);
02864 check_result_code(res, ex);
02865 if (res == E_DEC_DIV_ZERO)
02866 printf("E_DEC_DIV_ZERO");
02867 else
02868 print_decimal(&c, orig, res, ex);
02869 printf("\n");
02870 }
02871
02872 const char *round_mode[]=
02873 {"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
02874
02875 void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
02876 int ex)
02877 {
02878 char s[100], *end;
02879 int res;
02880 snprintf(s, sizeof(s), "'%s', %d, %s", s1, n, round_mode[mode]);
02881 end= strend(s1);
02882 string2decimal(s1, &a, &end);
02883 res=decimal_round(&a, &b, n, mode);
02884 printf("%-40s => res=%d ", s, res);
02885 print_decimal(&b, orig, res, ex);
02886 printf("\n");
02887 }
02888
02889
02890 void test_mx(int precision, int frac, const char *orig)
02891 {
02892 char s[100];
02893 snprintf(s, sizeof(s), "%d, %d", precision, frac);
02894 max_decimal(precision, frac, &a);
02895 printf("%-40s => ", s);
02896 print_decimal(&a, orig, 0, 0);
02897 printf("\n");
02898 }
02899
02900
02901 void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
02902 int ex)
02903 {
02904 char s[100], *end;
02905 char s2[100];
02906 int slen= sizeof(s2);
02907 int res;
02908
02909 snprintf(s, sizeof(s), filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
02910 s1, prec, dec, filler);
02911 end= strend(s1);
02912 string2decimal(s1, &a, &end);
02913 res= decimal2string(&a, s2, &slen, prec, dec, filler);
02914 printf("%-40s => res=%d '%s'", s, res, s2);
02915 check_result_code(res, ex);
02916 if (orig && strcmp(orig, s2))
02917 {
02918 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
02919 exit(1);
02920 }
02921 printf("\n");
02922 }
02923
02924
02925 void test_sh(const char *s1, int shift, const char *orig, int ex)
02926 {
02927 char s[100], *end;
02928 int res;
02929 snprintf(s, sizeof(s), "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
02930 end= strend(s1);
02931 string2decimal(s1, &a, &end);
02932 res= decimal_shift(&a, shift);
02933 printf("%-40s => res=%d ", s, res);
02934 print_decimal(&a, orig, res, ex);
02935 printf("\n");
02936 }
02937
02938
02939 void test_fr(const char *s1, const char *orig)
02940 {
02941 char s[100], *end;
02942 snprintf(s, sizeof(s), "'%s'", s1);
02943 printf("%-40s => ", s);
02944 end= strend(s1);
02945 string2decimal(s1, &a, &end);
02946 a.frac= decimal_actual_fraction(&a);
02947 print_decimal(&a, orig, 0, 0);
02948 printf("\n");
02949 }
02950
02951
02952 int main()
02953 {
02954 a.buf=(void*)buf1;
02955 a.len=sizeof(buf1)/sizeof(dec1);
02956 b.buf=(void*)buf2;
02957 b.len=sizeof(buf2)/sizeof(dec1);
02958 c.buf=(void*)buf3;
02959 c.len=sizeof(buf3)/sizeof(dec1);
02960
02961 if (full)
02962 test_d2s();
02963
02964 printf("==== string2decimal ====\n");
02965 test_s2d("12345", "12345", 0);
02966 test_s2d("12345.", "12345", 0);
02967 test_s2d("123.45", "123.45", 0);
02968 test_s2d("-123.45", "-123.45", 0);
02969 test_s2d(".00012345000098765", "0.00012345000098765", 0);
02970 test_s2d(".12345000098765", "0.12345000098765", 0);
02971 test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
02972 test_s2d("1234500009876.5", "1234500009876.5", 0);
02973 a.len=1;
02974 test_s2d("123450000098765", "98765", 2);
02975 test_s2d("123450.000098765", "123450", 1);
02976 a.len=sizeof(buf1)/sizeof(dec1);
02977 test_s2d("123E5", "12300000", 0);
02978 test_s2d("123E-2", "1.23", 0);
02979
02980 printf("==== decimal2double ====\n");
02981 test_d2f("12345", 0);
02982 test_d2f("123.45", 0);
02983 test_d2f("-123.45", 0);
02984 test_d2f("0.00012345000098765", 0);
02985 test_d2f("1234500009876.5", 0);
02986
02987 printf("==== double2decimal ====\n");
02988 test_f2d(12345, 0);
02989 test_f2d(1.0/3, 0);
02990 test_f2d(-123.45, 0);
02991 test_f2d(0.00012345000098765, 0);
02992 test_f2d(1234500009876.5, 0);
02993
02994 printf("==== uint64_t2decimal ====\n");
02995 test_ull2d(12345ULL, "12345", 0);
02996 test_ull2d(0ULL, "0", 0);
02997 test_ull2d(18446744073709551615ULL, "18446744073709551615", 0);
02998
02999 printf("==== decimal2uint64_t ====\n");
03000 test_d2ull("12345", "12345", 0);
03001 test_d2ull("0", "0", 0);
03002 test_d2ull("18446744073709551615", "18446744073709551615", 0);
03003 test_d2ull("18446744073709551616", "18446744073", 2);
03004 test_d2ull("-1", "0", 2);
03005 test_d2ull("1.23", "1", 1);
03006 test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
03007
03008 printf("==== int64_t2decimal ====\n");
03009 test_ll2d(12345LL, "-12345", 0);
03010 test_ll2d(1LL, "-1", 0);
03011 test_ll2d(9223372036854775807LL, "-9223372036854775807", 0);
03012 test_ll2d(9223372036854775808ULL, "-9223372036854775808", 0);
03013
03014 printf("==== decimal2int64_t ====\n");
03015 test_d2ll("18446744073709551615", "18446744073", 2);
03016 test_d2ll("-1", "-1", 0);
03017 test_d2ll("-1.23", "-1", 1);
03018 test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
03019 test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
03020 test_d2ll("9223372036854775808", "9223372036854775807", 2);
03021
03022 printf("==== do_add ====\n");
03023 test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
03024 test_da(".1" ,".45", "0.55", 0);
03025 test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
03026 test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
03027 test_da("99999999" ,"1", "100000000", 0);
03028 test_da("989999999" ,"1", "990000000", 0);
03029 test_da("999999999" ,"1", "1000000000", 0);
03030 test_da("12345" ,"123.45", "12468.45", 0);
03031 test_da("-12345" ,"-123.45", "-12468.45", 0);
03032 test_ds("-12345" ,"123.45", "-12468.45", 0);
03033 test_ds("12345" ,"-123.45", "12468.45", 0);
03034
03035 printf("==== do_sub ====\n");
03036 test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
03037 test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
03038 test_ds("9999900000000.5", ".555","9999899999999.945", 0);
03039 test_ds("1111.5551", "1111.555","0.0001", 0);
03040 test_ds(".555", ".555","0", 0);
03041 test_ds("10000000", "1","9999999", 0);
03042 test_ds("1000001000", ".1","1000000999.9", 0);
03043 test_ds("1000000000", ".1","999999999.9", 0);
03044 test_ds("12345", "123.45","12221.55", 0);
03045 test_ds("-12345", "-123.45","-12221.55", 0);
03046 test_da("-12345", "123.45","-12221.55", 0);
03047 test_da("12345", "-123.45","12221.55", 0);
03048 test_ds("123.45", "12345","-12221.55", 0);
03049 test_ds("-123.45", "-12345","12221.55", 0);
03050 test_da("123.45", "-12345","-12221.55", 0);
03051 test_da("-123.45", "12345","12221.55", 0);
03052 test_da("5", "-6.0","-1.0", 0);
03053
03054 printf("==== decimal_mul ====\n");
03055 test_dm("12", "10","120", 0);
03056 test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
03057 test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
03058 test_dm("123456", "987654321","121931851853376", 0);
03059 test_dm("123456", "9876543210","1219318518533760", 0);
03060 test_dm("123", "0.01","1.23", 0);
03061 test_dm("123", "0","0", 0);
03062
03063 printf("==== decimal_div ====\n");
03064 test_dv("120", "10","12.000000000", 0);
03065 test_dv("123", "0.01","12300.000000000", 0);
03066 test_dv("120", "100000000000.00000","0.000000001200000000", 0);
03067 test_dv("123", "0","", 4);
03068 test_dv("0", "0", "", 4);
03069 test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
03070 test_dv("121931851853376", "987654321","123456.000000000", 0);
03071 test_dv("0", "987","0", 0);
03072 test_dv("1", "3","0.333333333", 0);
03073 test_dv("1.000000000000", "3","0.333333333333333333", 0);
03074 test_dv("1", "1","1.000000000", 0);
03075 test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
03076 test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
03077 test_dv("10.000000000060", "2","5.000000000030000000", 0);
03078
03079 printf("==== decimal_mod ====\n");
03080 test_md("234","10","4", 0);
03081 test_md("234.567","10.555","2.357", 0);
03082 test_md("-234.567","10.555","-2.357", 0);
03083 test_md("234.567","-10.555","2.357", 0);
03084 c.buf[1]=0x3ABECA;
03085 test_md("99999999999999999999999999999999999999","3","0", 0);
03086 if (c.buf[1] != 0x3ABECA)
03087 {
03088 printf("%X - overflow\n", c.buf[1]);
03089 exit(1);
03090 }
03091
03092 printf("==== decimal2bin/bin2decimal ====\n");
03093 test_d2b2d("-10.55", 4, 2,"-10.55", 0);
03094 test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
03095 test_d2b2d("12345", 5, 0,"12345", 0);
03096 test_d2b2d("12345", 10, 3,"12345.000", 0);
03097 test_d2b2d("123.45", 10, 3,"123.450", 0);
03098 test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
03099 test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
03100 test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
03101 test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
03102 test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
03103 test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
03104 test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
03105 test_d2b2d("000000000.01", 7, 3,"0.010", 0);
03106 test_d2b2d("123.4", 10, 2, "123.40", 0);
03107
03108
03109 printf("==== decimal_cmp ====\n");
03110 test_dc("12","13",-1);
03111 test_dc("13","12",1);
03112 test_dc("-10","10",-1);
03113 test_dc("10","-10",1);
03114 test_dc("-12","-13",1);
03115 test_dc("0","12",-1);
03116 test_dc("-10","0",-1);
03117 test_dc("4","4",0);
03118
03119 printf("==== decimal_round ====\n");
03120 test_ro("5678.123451",-4,TRUNCATE,"0", 0);
03121 test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
03122 test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
03123 test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
03124 test_ro("5678.123451",0,TRUNCATE,"5678", 0);
03125 test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
03126 test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
03127 test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
03128 test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
03129 test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
03130 test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
03131 test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
03132 memset(buf2, 33, sizeof(buf2));
03133 test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
03134 test_ro("15.1",0,HALF_UP,"15", 0);
03135 test_ro("15.5",0,HALF_UP,"16", 0);
03136 test_ro("15.9",0,HALF_UP,"16", 0);
03137 test_ro("-15.1",0,HALF_UP,"-15", 0);
03138 test_ro("-15.5",0,HALF_UP,"-16", 0);
03139 test_ro("-15.9",0,HALF_UP,"-16", 0);
03140 test_ro("15.1",1,HALF_UP,"15.1", 0);
03141 test_ro("-15.1",1,HALF_UP,"-15.1", 0);
03142 test_ro("15.17",1,HALF_UP,"15.2", 0);
03143 test_ro("15.4",-1,HALF_UP,"20", 0);
03144 test_ro("-15.4",-1,HALF_UP,"-20", 0);
03145 test_ro("5.4",-1,HALF_UP,"10", 0);
03146 test_ro(".999", 0, HALF_UP, "1", 0);
03147 memset(buf2, 33, sizeof(buf2));
03148 test_ro("999999999", -9, HALF_UP, "1000000000", 0);
03149 test_ro("15.1",0,HALF_EVEN,"15", 0);
03150 test_ro("15.5",0,HALF_EVEN,"16", 0);
03151 test_ro("14.5",0,HALF_EVEN,"14", 0);
03152 test_ro("15.9",0,HALF_EVEN,"16", 0);
03153 test_ro("15.1",0,CEILING,"16", 0);
03154 test_ro("-15.1",0,CEILING,"-15", 0);
03155 test_ro("15.1",0,FLOOR,"15", 0);
03156 test_ro("-15.1",0,FLOOR,"-16", 0);
03157 test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
03158 test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
03159
03160 b.buf[0]=DIG_BASE+1;
03161 b.buf++;
03162 test_ro(".3", 0, HALF_UP, "0", 0);
03163 b.buf--;
03164 if (b.buf[0] != DIG_BASE+1)
03165 {
03166 printf("%d - underflow\n", b.buf[0]);
03167 exit(1);
03168 }
03169
03170 printf("==== max_decimal ====\n");
03171 test_mx(1,1,"0.9");
03172 test_mx(1,0,"9");
03173 test_mx(2,1,"9.9");
03174 test_mx(4,2,"99.99");
03175 test_mx(6,3,"999.999");
03176 test_mx(8,4,"9999.9999");
03177 test_mx(10,5,"99999.99999");
03178 test_mx(12,6,"999999.999999");
03179 test_mx(14,7,"9999999.9999999");
03180 test_mx(16,8,"99999999.99999999");
03181 test_mx(18,9,"999999999.999999999");
03182 test_mx(20,10,"9999999999.9999999999");
03183 test_mx(20,20,"0.99999999999999999999");
03184 test_mx(20,0,"99999999999999999999");
03185 test_mx(40,20,"99999999999999999999.99999999999999999999");
03186
03187 printf("==== decimal2string ====\n");
03188 test_pr("123.123", 0, 0, 0, "123.123", 0);
03189 test_pr("123.123", 7, 3, '0', "123.123", 0);
03190 test_pr("123.123", 9, 3, '0', "00123.123", 0);
03191 test_pr("123.123", 9, 4, '0', "0123.1230", 0);
03192 test_pr("123.123", 9, 5, '0', "123.12300", 0);
03193 test_pr("123.123", 9, 2, '0', "000123.12", 1);
03194 test_pr("123.123", 9, 6, '0', "23.123000", 2);
03195
03196 printf("==== decimal_shift ====\n");
03197 test_sh("123.123", 1, "1231.23", 0);
03198 test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
03199 test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
03200 test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
03201 test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
03202 test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
03203 test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
03204 test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
03205 test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
03206 test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
03207 test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
03208 test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
03209 test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
03210 test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
03211 test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
03212 test_sh("123", 1, "1230", 0);
03213 test_sh("123", 10, "1230000000000", 0);
03214 test_sh(".123", 1, "1.23", 0);
03215 test_sh(".123", 10, "1230000000", 0);
03216 test_sh(".123", 14, "12300000000000", 0);
03217 test_sh("000.000", 1000, "0", 0);
03218 test_sh("000.", 1000, "0", 0);
03219 test_sh(".000", 1000, "0", 0);
03220 test_sh("1", 1000, "1", 2);
03221 test_sh("123.123", -1, "12.3123", 0);
03222 test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
03223 test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
03224 test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
03225 test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
03226 test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
03227 test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
03228 test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
03229 test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
03230 test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
03231 test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
03232 test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
03233 a.len= 2;
03234 test_sh("123.123", -2, "1.23123", 0);
03235 test_sh("123.123", -3, "0.123123", 0);
03236 test_sh("123.123", -6, "0.000123123", 0);
03237 test_sh("123.123", -7, "0.0000123123", 0);
03238 test_sh("123.123", -15, "0.000000000000123123", 0);
03239 test_sh("123.123", -16, "0.000000000000012312", 1);
03240 test_sh("123.123", -17, "0.000000000000001231", 1);
03241 test_sh("123.123", -18, "0.000000000000000123", 1);
03242 test_sh("123.123", -19, "0.000000000000000012", 1);
03243 test_sh("123.123", -20, "0.000000000000000001", 1);
03244 test_sh("123.123", -21, "0", 1);
03245 test_sh(".000000000123", -1, "0.0000000000123", 0);
03246 test_sh(".000000000123", -6, "0.000000000000000123", 0);
03247 test_sh(".000000000123", -7, "0.000000000000000012", 1);
03248 test_sh(".000000000123", -8, "0.000000000000000001", 1);
03249 test_sh(".000000000123", -9, "0", 1);
03250 test_sh(".000000000123", 1, "0.00000000123", 0);
03251 test_sh(".000000000123", 8, "0.0123", 0);
03252 test_sh(".000000000123", 9, "0.123", 0);
03253 test_sh(".000000000123", 10, "1.23", 0);
03254 test_sh(".000000000123", 17, "12300000", 0);
03255 test_sh(".000000000123", 18, "123000000", 0);
03256 test_sh(".000000000123", 19, "1230000000", 0);
03257 test_sh(".000000000123", 20, "12300000000", 0);
03258 test_sh(".000000000123", 21, "123000000000", 0);
03259 test_sh(".000000000123", 22, "1230000000000", 0);
03260 test_sh(".000000000123", 23, "12300000000000", 0);
03261 test_sh(".000000000123", 24, "123000000000000", 0);
03262 test_sh(".000000000123", 25, "1230000000000000", 0);
03263 test_sh(".000000000123", 26, "12300000000000000", 0);
03264 test_sh(".000000000123", 27, "123000000000000000", 0);
03265 test_sh(".000000000123", 28, "0.000000000123", 2);
03266 test_sh("123456789.987654321", -1, "12345678.998765432", 1);
03267 test_sh("123456789.987654321", -2, "1234567.899876543", 1);
03268 test_sh("123456789.987654321", -8, "1.234567900", 1);
03269 test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
03270 test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
03271 test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
03272 test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
03273 test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
03274 test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
03275 test_sh("123456789.987654321", -27, "0", 1);
03276 test_sh("123456789.987654321", 1, "1234567900", 1);
03277 test_sh("123456789.987654321", 2, "12345678999", 1);
03278 test_sh("123456789.987654321", 4, "1234567899877", 1);
03279 test_sh("123456789.987654321", 8, "12345678998765432", 1);
03280 test_sh("123456789.987654321", 9, "123456789987654321", 0);
03281 test_sh("123456789.987654321", 10, "123456789.987654321", 2);
03282 test_sh("123456789.987654321", 0, "123456789.987654321", 0);
03283 a.len= sizeof(buf1)/sizeof(dec1);
03284
03285 printf("==== decimal_actual_fraction ====\n");
03286 test_fr("1.123456789000000000", "1.123456789");
03287 test_fr("1.12345678000000000", "1.12345678");
03288 test_fr("1.1234567000000000", "1.1234567");
03289 test_fr("1.123456000000000", "1.123456");
03290 test_fr("1.12345000000000", "1.12345");
03291 test_fr("1.1234000000000", "1.1234");
03292 test_fr("1.123000000000", "1.123");
03293 test_fr("1.12000000000", "1.12");
03294 test_fr("1.1000000000", "1.1");
03295 test_fr("1.000000000", "1");
03296 test_fr("1.0", "1");
03297 test_fr("10000000000000000000.0", "10000000000000000000");
03298
03299 return 0;
03300 }
03301
03302 #endif