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