100 #include <my_global.h>
102 #include <myisampack.h>
104 #include <m_string.h>
122 typedef decimal_digit_t dec1;
123 typedef longlong dec2;
125 #define DIG_PER_DEC1 9
126 #define DIG_MASK 100000000
127 #define DIG_BASE 1000000000
128 #define DIG_MAX (DIG_BASE-1)
129 #define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE)
130 #define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
131 static const dec1 powers10[DIG_PER_DEC1+1]={
132 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
133 static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
134 static const dec1 frac_max[DIG_PER_DEC1-1]={
135 900000000, 990000000, 999000000,
136 999900000, 999990000, 999999000,
137 999999900, 999999990 };
140 #define sanity(d) DBUG_ASSERT((d)->len > 0)
142 #define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
143 (d)->buf[(d)->len-1] | 1))
146 #define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
149 if (unlikely(intg1+frac1 > (len))) \
151 if (unlikely(intg1 > (len))) \
155 error=E_DEC_OVERFLOW; \
160 error=E_DEC_TRUNCATED; \
167 #define ADD(to, from1, from2, carry) \
170 dec1 a=(from1)+(from2)+(carry); \
171 DBUG_ASSERT((carry) <= 1); \
172 if (((carry)= a >= DIG_BASE)) \
177 #define ADD2(to, from1, from2, carry) \
180 dec2 a=((dec2)(from1))+(from2)+(carry); \
181 if (((carry)= a >= DIG_BASE)) \
183 if (unlikely(a >= DIG_BASE)) \
191 #define SUB(to, from1, from2, carry) \
194 dec1 a=(from1)-(from2)-(carry); \
195 if (((carry)= a < 0)) \
200 #define SUB2(to, from1, from2, carry) \
203 dec1 a=(from1)-(from2)-(carry); \
204 if (((carry)= a < 0)) \
206 if (unlikely(a < 0)) \
224 void max_decimal(
int precision,
int frac,
decimal_t *
to)
228 DBUG_ASSERT(precision && precision >= frac);
231 if ((intpart= to->intg= (precision - frac)))
233 int firstdigits= intpart % DIG_PER_DEC1;
235 *buf++= powers10[firstdigits] - 1;
236 for(intpart/= DIG_PER_DEC1; intpart; intpart--)
240 if ((to->frac= frac))
242 int lastdigits= frac % DIG_PER_DEC1;
243 for(frac/= DIG_PER_DEC1; frac; frac--)
246 *buf= frac_max[lastdigits - 1];
251 static dec1 *remove_leading_zeroes(
const decimal_t *from,
int *intg_result)
253 int intg= from->intg,
i;
254 dec1 *buf0= from->buf;
255 i= ((intg - 1) % DIG_PER_DEC1) + 1;
256 while (intg > 0 && *buf0 == 0)
264 for (
i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[
i--]; intg--) ;
265 DBUG_ASSERT(intg > 0);
282 int decimal_actual_fraction(
decimal_t *from)
284 int frac= from->frac,
i;
285 dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
290 i= ((frac - 1) % DIG_PER_DEC1 + 1);
291 while (frac > 0 && *buf0 == 0)
299 for (
i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1);
300 *buf0 % powers10[
i++] == 0;
329 int decimal2string(
const decimal_t *from,
char *to,
int *to_len,
330 int fixed_precision,
int fixed_decimals,
334 int len, intg, frac= from->frac,
i, intg_len, frac_len, fill;
336 int fixed_intg= (fixed_precision ?
337 (fixed_precision - fixed_decimals) : 0);
340 dec1 *
buf, *buf0=from->buf, tmp;
342 DBUG_ASSERT(*to_len >= 2+from->sign);
345 buf0= remove_leading_zeroes(from, &intg);
346 if (unlikely(intg+frac==0))
353 if (!(intg_len= fixed_precision ? fixed_intg : intg))
355 frac_len= fixed_precision ? fixed_decimals : frac;
356 len= from->sign + intg_len +
test(frac) + frac_len;
359 if (frac > fixed_decimals)
361 error= E_DEC_TRUNCATED;
362 frac= fixed_decimals;
364 if (intg > fixed_intg)
366 error= E_DEC_OVERFLOW;
370 else if (unlikely(len > --*to_len))
372 int j= len - *to_len;
373 error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
379 if (frac && j >= frac + 1)
384 intg_len= intg-= j-frac;
390 len= from->sign + intg_len +
test(frac) + frac_len;
400 char *s1= s + intg_len;
401 fill= frac_len - frac;
402 buf=buf0+ROUND_UP(intg);
404 for (; frac>0; frac-=DIG_PER_DEC1)
407 for (
i= MY_MIN(frac, DIG_PER_DEC1);
i;
i--)
415 for(; fill > 0; fill--)
419 fill= intg_len - intg;
422 for(; fill > 0; fill--)
427 for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
430 for (
i= MY_MIN(intg, DIG_PER_DEC1);
i;
i--)
433 *--s=
'0'+(uchar)(x-y*10);
457 static void digits_bounds(
decimal_t *from,
int *start_result,
int *end_result)
460 dec1 *buf_beg= from->buf;
461 dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
462 dec1 *buf_end= end - 1;
465 while (buf_beg < end && *buf_beg == 0)
471 *start_result= *end_result= 0;
476 if (buf_beg == from->buf && from->intg)
478 start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1));
484 start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
487 for (; *buf_beg < powers10[i--]; start++) ;
488 *start_result= start;
491 while (buf_end > buf_beg && *buf_end == 0)
494 if (buf_end == end - 1 && from->frac)
496 stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
497 (i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
498 i= DIG_PER_DEC1 - i + 1;
502 stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
505 for (; *buf_end % powers10[i++] == 0; stop--) ;
524 void do_mini_left_shift(
decimal_t *dec,
int shift,
int beg,
int last)
526 dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
527 dec1 *end= dec->buf + ROUND_UP(last) - 1;
528 int c_shift= DIG_PER_DEC1 - shift;
529 DBUG_ASSERT(from >= dec->buf);
530 DBUG_ASSERT(end < dec->buf + dec->len);
531 if (beg % DIG_PER_DEC1 < shift)
532 *(from - 1)= (*from) / powers10[c_shift];
533 for(; from < end; from++)
534 *from= ((*from % powers10[c_shift]) * powers10[shift] +
535 (*(from + 1)) / powers10[c_shift]);
536 *from= (*from % powers10[c_shift]) * powers10[shift];
554 void do_mini_right_shift(
decimal_t *dec,
int shift,
int beg,
int last)
556 dec1 *from= dec->buf + ROUND_UP(last) - 1;
557 dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
558 int c_shift= DIG_PER_DEC1 - shift;
559 DBUG_ASSERT(from < dec->buf + dec->len);
560 DBUG_ASSERT(end >= dec->buf);
561 if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
562 *(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
563 for(; from > end; from--)
564 *from= (*from / powers10[shift] +
565 (*(from - 1) % powers10[shift]) * powers10[c_shift]);
566 *from= *from / powers10[shift];
587 int decimal_shift(
decimal_t *dec,
int shift)
594 int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
596 int new_point= point + shift;
598 int digits_int, digits_frac;
600 int new_len, new_frac_len;
608 digits_bounds(dec, &beg, &end);
612 decimal_make_zero(dec);
616 digits_int= new_point - beg;
617 set_if_bigger(digits_int, 0);
618 digits_frac= end - new_point;
619 set_if_bigger(digits_frac, 0);
621 if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
624 int lack= new_len - dec->len;
627 if (new_frac_len < lack)
628 return E_DEC_OVERFLOW;
631 err= E_DEC_TRUNCATED;
633 diff= digits_frac - (new_frac_len * DIG_PER_DEC1);
635 decimal_round(dec, dec, end - point - diff, HALF_UP);
637 digits_frac= new_frac_len * DIG_PER_DEC1;
645 decimal_make_zero(dec);
646 return E_DEC_TRUNCATED;
650 if (shift % DIG_PER_DEC1)
652 int l_mini_shift, r_mini_shift, mini_shift;
660 l_mini_shift= shift % DIG_PER_DEC1;
661 r_mini_shift= DIG_PER_DEC1 - l_mini_shift;
667 do_left= l_mini_shift <= beg;
668 DBUG_ASSERT(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
672 r_mini_shift= (-shift) % DIG_PER_DEC1;
673 l_mini_shift= DIG_PER_DEC1 - r_mini_shift;
675 do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
676 DBUG_ASSERT(!do_left || l_mini_shift <= beg);
680 do_mini_left_shift(dec, l_mini_shift, beg, end);
681 mini_shift= -l_mini_shift;
685 do_mini_right_shift(dec, r_mini_shift, beg, end);
686 mini_shift= r_mini_shift;
688 new_point+= mini_shift;
693 if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1)
695 dec->intg= digits_int;
696 dec->frac= digits_frac;
704 if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 ||
713 d_shift= new_front / DIG_PER_DEC1;
714 to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
715 barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
716 DBUG_ASSERT(to >= dec->buf);
717 DBUG_ASSERT(barier + d_shift < dec->buf + dec->len);
718 for(; to <= barier; to++)
719 *to= *(to + d_shift);
720 for(barier+= d_shift; to <= barier; to++)
727 d_shift= (1 - new_front) / DIG_PER_DEC1;
728 to= dec->buf + ROUND_UP(end) - 1 + d_shift;
729 barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
730 DBUG_ASSERT(to < dec->buf + dec->len);
731 DBUG_ASSERT(barier - d_shift >= dec->buf);
732 for(; to >= barier; to--)
733 *to= *(to - d_shift);
734 for(barier-= d_shift; to >= barier; to--)
737 d_shift*= DIG_PER_DEC1;
748 beg= ROUND_UP(beg + 1) - 1;
749 end= ROUND_UP(end) - 1;
750 DBUG_ASSERT(new_point >= 0);
754 new_point= ROUND_UP(new_point) - 1;
760 dec->buf[new_point]=0;
761 }
while (--new_point > end);
765 for (; new_point < beg; new_point++)
766 dec->buf[new_point]= 0;
768 dec->intg= digits_int;
769 dec->frac= digits_frac;
797 internal_str2dec(
const char *from,
decimal_t *to,
char **end, my_bool fixed)
799 const char *s= from, *s1, *endp, *end_of_string= *end;
800 int i, intg, frac, error, intg1, frac1;
804 error= E_DEC_BAD_NUM;
805 while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
807 if (s == end_of_string)
810 if ((to->sign= (*s ==
'-')))
816 while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
819 if (s < end_of_string && *s==
'.')
822 while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
824 frac= (int) (endp - s - 1);
842 error=E_DEC_TRUNCATED;
847 error=E_DEC_OVERFLOW;
850 intg1=ROUND_UP(intg);
851 frac1=ROUND_UP(frac);
852 if (intg1+frac1 > to->len)
860 intg1=ROUND_UP(intg);
861 frac1=ROUND_UP(frac);
862 FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
865 frac=frac1*DIG_PER_DEC1;
866 if (error == E_DEC_OVERFLOW)
867 intg=intg1*DIG_PER_DEC1;
877 for (x=0, i=0; intg; intg--)
879 x+= (*--s -
'0')*powers10[i];
881 if (unlikely(++i == DIG_PER_DEC1))
892 for (x=0, i=0; frac; frac--)
894 x= (*++s1 -
'0') + x*10;
896 if (unlikely(++i == DIG_PER_DEC1))
904 *buf=x*powers10[DIG_PER_DEC1-
i];
907 if (endp+1 < end_of_string && (*endp ==
'e' || *endp ==
'E'))
910 longlong exponent= my_strtoll10(endp+1, (
char**) &end_of_string,
913 if (end_of_string != endp +1)
915 *end= (
char*) end_of_string;
918 error= E_DEC_BAD_NUM;
921 if (exponent > INT_MAX/2 || (str_error == 0 && exponent < 0))
923 error= E_DEC_OVERFLOW;
926 if (exponent < INT_MIN/2 && error != E_DEC_OVERFLOW)
928 error= E_DEC_TRUNCATED;
931 if (error != E_DEC_OVERFLOW)
932 error= decimal_shift(to, (
int) exponent);
938 decimal_make_zero(to);
955 int decimal2double(
const decimal_t *from,
double *to)
957 char strbuf[FLOATING_POINT_BUFFER], *end;
958 int len=
sizeof(strbuf);
961 rc = decimal2string(from, strbuf, &len, 0, 0, 0);
964 DBUG_PRINT(
"info", (
"interm.: %s", strbuf));
966 *to= my_strtod(strbuf, &end, &error);
968 DBUG_PRINT(
"info", (
"result: %f", *to));
970 return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
985 int double2decimal(
double from,
decimal_t *to)
987 char buff[FLOATING_POINT_BUFFER], *end;
989 DBUG_ENTER(
"double2decimal");
990 end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE,
sizeof(buff) - 1, buff, NULL);
991 res= string2decimal(buff, to, &end);
992 DBUG_PRINT(
"exit", (
"res: %d", res));
997 static int ull2dec(ulonglong from,
decimal_t *to)
999 int intg1, error=E_DEC_OK;
1005 for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE) ;
1006 if (unlikely(intg1 > to->len))
1009 error=E_DEC_OVERFLOW;
1012 to->intg=intg1*DIG_PER_DEC1;
1014 for (buf=to->buf+intg1; intg1; intg1--)
1016 ulonglong y=x/DIG_BASE;
1017 *--buf=(dec1)(x-y*DIG_BASE);
1023 int ulonglong2decimal(ulonglong from,
decimal_t *to)
1026 return ull2dec(from, to);
1029 int longlong2decimal(longlong from,
decimal_t *to)
1031 if ((to->sign= from < 0))
1032 return ull2dec(-from, to);
1033 return ull2dec(from, to);
1036 int decimal2ulonglong(
decimal_t *from, ulonglong *to)
1038 dec1 *buf=from->buf;
1045 return E_DEC_OVERFLOW;
1048 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1051 x=x*DIG_BASE + *buf++;
1052 if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
1055 return E_DEC_OVERFLOW;
1059 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1061 return E_DEC_TRUNCATED;
1065 int decimal2longlong(
decimal_t *from, longlong *to)
1067 dec1 *buf=from->buf;
1071 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1080 x=x*DIG_BASE - *buf++;
1081 if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
1087 *to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
1088 return E_DEC_OVERFLOW;
1092 if (unlikely(from->sign==0 && x == LONGLONG_MIN))
1095 return E_DEC_OVERFLOW;
1098 *to=from->sign ? x : -x;
1099 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1101 return E_DEC_TRUNCATED;
1106 #define LLDIV_MIN -1000000000000000000LL
1107 #define LLDIV_MAX 1000000000000000000LL
1115 int decimal2lldiv_t(
const decimal_t *from, lldiv_t *to)
1117 int int_part= ROUND_UP(from->intg);
1118 int frac_part= ROUND_UP(from->frac);
1122 to->quot= from->sign ? LLDIV_MIN : LLDIV_MAX;
1123 return E_DEC_OVERFLOW;
1126 to->quot= ((longlong) from->buf[0]) * DIG_BASE + from->buf[1];
1127 else if (int_part == 1)
1128 to->quot= from->buf[0];
1131 to->rem= frac_part ? from->buf[int_part] : 0;
1134 to->quot= -to->quot;
1152 int double2lldiv_t(
double nr, lldiv_t *lld)
1156 lld->quot= LLDIV_MAX;
1158 return E_DEC_OVERFLOW;
1160 else if (nr < LLDIV_MIN)
1162 lld->quot= LLDIV_MIN;
1164 return E_DEC_OVERFLOW;
1167 lld->quot= (longlong) (nr > 0 ? floor(nr) : ceil(nr));
1169 lld->rem= (longlong) rint((nr - (
double) lld->quot) * 1000000000);
1177 if (lld->rem > 999999999LL)
1178 lld->rem= 999999999LL;
1179 else if (lld->rem < -999999999LL)
1180 lld->rem= -999999999LL;
1265 int decimal2bin(
decimal_t *from, uchar *to,
int precision,
int frac)
1267 dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1268 int error=E_DEC_OK, intg=precision-frac,
1269 isize1, intg1, intg1x, from_intg,
1270 intg0=intg/DIG_PER_DEC1,
1271 frac0=frac/DIG_PER_DEC1,
1272 intg0x=intg-intg0*DIG_PER_DEC1,
1273 frac0x=frac-frac0*DIG_PER_DEC1,
1274 frac1=from->frac/DIG_PER_DEC1,
1275 frac1x=from->frac-frac1*DIG_PER_DEC1,
1276 isize0=intg0*
sizeof(dec1)+dig2bytes[intg0x],
1277 fsize0=frac0*
sizeof(dec1)+dig2bytes[frac0x],
1278 fsize1=frac1*
sizeof(dec1)+dig2bytes[frac1x];
1279 const int orig_isize0= isize0;
1280 const int orig_fsize0= fsize0;
1283 buf1= remove_leading_zeroes(from, &from_intg);
1285 if (unlikely(from_intg+fsize1==0))
1292 intg1=from_intg/DIG_PER_DEC1;
1293 intg1x=from_intg-intg1*DIG_PER_DEC1;
1294 isize1=intg1*
sizeof(dec1)+dig2bytes[intg1x];
1296 if (intg < from_intg)
1298 buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
1299 intg1=intg0; intg1x=intg0x;
1300 error=E_DEC_OVERFLOW;
1302 else if (isize0 > isize1)
1304 while (isize0-- > isize1)
1307 if (fsize0 < fsize1)
1309 frac1=frac0; frac1x=frac0x;
1310 error=E_DEC_TRUNCATED;
1312 else if (fsize0 > fsize1 && frac1x)
1329 int i=dig2bytes[intg1x];
1330 dec1 x=(*buf1++ % powers10[intg1x]) ^ mask;
1333 case 1: mi_int1store(to, x);
break;
1334 case 2: mi_int2store(to, x);
break;
1335 case 3: mi_int3store(to, x);
break;
1336 case 4: mi_int4store(to, x);
break;
1337 default: DBUG_ASSERT(0);
1343 for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=
sizeof(dec1))
1345 dec1 x=*buf1++ ^ mask;
1346 DBUG_ASSERT(
sizeof(dec1) == 4);
1347 mi_int4store(to, x);
1354 int i=dig2bytes[frac1x],
1355 lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x);
1356 while (frac1x < lim && dig2bytes[frac1x] == i)
1358 x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask;
1361 case 1: mi_int1store(to, x);
break;
1362 case 2: mi_int2store(to, x);
break;
1363 case 3: mi_int3store(to, x);
break;
1364 case 4: mi_int4store(to, x);
break;
1365 default: DBUG_ASSERT(0);
1369 if (fsize0 > fsize1)
1371 uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
1373 while (fsize0-- > fsize1 && to < to_end)
1379 DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0);
1400 int bin2decimal(
const uchar *from,
decimal_t *to,
int precision,
int scale)
1402 int error=E_DEC_OK, intg=precision-scale,
1403 intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1404 intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1405 intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1406 dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
1409 int bin_size= decimal_bin_size(precision, scale);
1412 d_copy= (uchar*) my_alloca(bin_size);
1413 memcpy(d_copy, from, bin_size);
1417 FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1418 if (unlikely(error))
1420 if (intg1 < intg0+(intg0x>0))
1422 from+=dig2bytes[intg0x]+
sizeof(dec1)*(intg0-intg1);
1423 frac0=frac0x=intg0x=0;
1433 to->sign=(mask != 0);
1434 to->intg=intg0*DIG_PER_DEC1+intg0x;
1435 to->frac=frac0*DIG_PER_DEC1+frac0x;
1439 int i=dig2bytes[intg0x];
1443 case 1: x=mi_sint1korr(from);
break;
1444 case 2: x=mi_sint2korr(from);
break;
1445 case 3: x=mi_sint3korr(from);
break;
1446 case 4: x=mi_sint4korr(from);
break;
1447 default: DBUG_ASSERT(0);
1451 if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1])
1453 if (buf > to->buf || *buf != 0)
1458 for (stop=from+intg0*
sizeof(dec1); from < stop; from+=
sizeof(dec1))
1460 DBUG_ASSERT(
sizeof(dec1) == 4);
1461 *buf=mi_sint4korr(from) ^ mask;
1462 if (((uint32)*buf) > DIG_MAX)
1464 if (buf > to->buf || *buf != 0)
1467 to->intg-=DIG_PER_DEC1;
1469 DBUG_ASSERT(to->intg >=0);
1470 for (stop=from+frac0*
sizeof(dec1); from < stop; from+=
sizeof(dec1))
1472 DBUG_ASSERT(
sizeof(dec1) == 4);
1473 *buf=mi_sint4korr(from) ^ mask;
1474 if (((uint32)*buf) > DIG_MAX)
1480 int i=dig2bytes[frac0x];
1484 case 1: x=mi_sint1korr(from);
break;
1485 case 2: x=mi_sint2korr(from);
break;
1486 case 3: x=mi_sint3korr(from);
break;
1487 case 4: x=mi_sint4korr(from);
break;
1488 default: DBUG_ASSERT(0);
1490 *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
1491 if (((uint32)*buf) > DIG_MAX)
1501 if (to->intg == 0 && to->frac == 0)
1502 decimal_make_zero(to);
1507 decimal_make_zero(to);
1508 return(E_DEC_BAD_NUM);
1519 int decimal_size(
int precision,
int scale)
1521 DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1522 return ROUND_UP(precision-scale)+ROUND_UP(scale);
1532 int decimal_bin_size(
int precision,
int scale)
1534 int intg=precision-scale,
1535 intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1536 intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
1538 DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1539 return intg0*
sizeof(dec1)+dig2bytes[intg0x]+
1540 frac0*
sizeof(dec1)+dig2bytes[frac0x];
1563 decimal_round_mode
mode)
1565 int frac0=scale>0 ? ROUND_UP(scale) : (scale + 1)/DIG_PER_DEC1,
1566 frac1=ROUND_UP(from->frac), UNINIT_VAR(round_digit),
1567 intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len;
1569 dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1576 case HALF_EVEN: round_digit=5;
break;
1577 case CEILING: round_digit= from->sign ? 10 : 0;
break;
1578 case FLOOR: round_digit= from->sign ? 0 : 10;
break;
1579 case TRUNCATE: round_digit=10;
break;
1580 default: DBUG_ASSERT(0);
1587 DBUG_ASSERT(from->len == to->len);
1589 if (unlikely(frac0+intg0 > len))
1592 scale=frac0*DIG_PER_DEC1;
1593 error=E_DEC_TRUNCATED;
1596 if (scale+from->intg < 0)
1598 decimal_make_zero(to);
1604 dec1 *p0= buf0 + intg0 + MY_MAX(frac1, frac0);
1605 dec1 *p1= buf1 + intg0 + MY_MAX(frac1, frac0);
1607 DBUG_ASSERT(p0 - buf0 <= len);
1608 DBUG_ASSERT(p1 - buf1 <= len);
1615 to->sign=from->sign;
1616 to->intg= MY_MIN(intg0, len) * DIG_PER_DEC1;
1622 while (frac0-- > frac1)
1627 if (scale >= from->frac)
1630 buf0+=intg0+frac0-1;
1631 buf1+=intg0+frac0-1;
1632 if (scale == frac0*DIG_PER_DEC1)
1635 DBUG_ASSERT(frac0+intg0 >= 0);
1636 switch (round_digit) {
1639 dec1 *p0= buf0 + (frac1-frac0);
1640 for (; p0 > buf0; p0--)
1652 x= buf0[1]/DIG_MASK;
1653 do_inc= (x>5) || ((x == 5) &&
1654 (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
1667 else if (frac0+intg0==0)
1669 decimal_make_zero(to);
1676 int pos=frac0*DIG_PER_DEC1-scale-1;
1677 DBUG_ASSERT(frac0+intg0 > 0);
1678 x=*buf1 / powers10[pos];
1680 if (y > round_digit ||
1681 (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
1683 *buf1=powers10[pos]*(x-y);
1697 dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0);
1698 dec1 *end= to->buf + len;
1703 if (*buf1 >= DIG_BASE)
1707 while (carry && --buf1 >= to->buf)
1708 ADD(*buf1, *buf1, 0, carry);
1709 if (unlikely(carry))
1712 if (frac0+intg0 >= len)
1715 scale=frac0*DIG_PER_DEC1;
1716 error=E_DEC_TRUNCATED;
1718 for (buf1=to->buf + intg0 + MY_MAX(frac0, 0); buf1 > to->buf; buf1--)
1721 if (buf1 < to->buf + len)
1724 error= E_DEC_OVERFLOW;
1728 if (to->intg < len * DIG_PER_DEC1)
1731 error= E_DEC_OVERFLOW;
1740 if (buf1-- == to->buf)
1743 dec1 *p0= to->buf + frac0 + 1;
1745 to->frac= MY_MAX(scale, 0);
1747 for (buf1= to->buf; buf1<p0; buf1++)
1755 first_dig= to->intg % DIG_PER_DEC1;
1756 if (first_dig && (*buf1 >= powers10[first_dig]))
1763 DBUG_ASSERT(to->intg <= (len * DIG_PER_DEC1));
1795 return ROUND_UP(MY_MAX(from1->intg, from2->intg)) +
1796 ROUND_UP(MY_MAX(from1->frac, from2->frac));
1798 return ROUND_UP(MY_MAX(from1->intg, from2->intg)+1) +
1799 ROUND_UP(MY_MAX(from1->frac, from2->frac));
1801 return ROUND_UP(from1->intg+from2->intg)+
1802 ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1804 return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1805 default: DBUG_ASSERT(0);
1812 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1813 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1814 frac0= MY_MAX(frac1, frac2), intg0= MY_MAX(intg1, intg2), error;
1815 dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1820 x=intg1 > intg2 ? from1->buf[0] :
1821 intg2 > intg1 ? from2->buf[0] :
1822 from1->buf[0] + from2->buf[0] ;
1823 if (unlikely(x > DIG_MAX-1))
1829 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1830 if (unlikely(error == E_DEC_OVERFLOW))
1832 max_decimal(to->len * DIG_PER_DEC1, 0, to);
1836 buf0=to->buf+intg0+frac0;
1838 to->sign=from1->sign;
1839 to->frac= MY_MAX(from1->frac, from2->frac);
1840 to->intg=intg0*DIG_PER_DEC1;
1841 if (unlikely(error))
1843 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1844 set_if_smaller(frac1, frac0);
1845 set_if_smaller(frac2, frac0);
1846 set_if_smaller(intg1, intg0);
1847 set_if_smaller(intg2, intg0);
1853 buf1=from1->buf+intg1+frac1;
1854 stop=from1->buf+intg1+frac2;
1855 buf2=from2->buf+intg2+frac2;
1856 stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
1860 buf1=from2->buf+intg2+frac2;
1861 stop=from2->buf+intg2+frac1;
1862 buf2=from1->buf+intg1+frac1;
1863 stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
1870 while (buf1 > stop2)
1872 ADD(*--buf0, *--buf1, *--buf2, carry);
1876 buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1877 ((stop=from2->buf)+intg2-intg1) ;
1880 ADD(*--buf0, *--buf1, 0, carry);
1883 if (unlikely(carry))
1885 DBUG_ASSERT(buf0 == to->buf || buf0 == to->buf+1);
1894 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1895 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1896 int frac0= MY_MAX(frac1, frac2), error;
1897 dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1900 start1=buf1=from1->buf; stop1=buf1+intg1;
1901 start2=buf2=from2->buf; stop2=buf2+intg2;
1902 if (unlikely(*buf1 == 0))
1904 while (buf1 < stop1 && *buf1 == 0)
1907 intg1= (int) (stop1-buf1);
1909 if (unlikely(*buf2 == 0))
1911 while (buf2 < stop2 && *buf2 == 0)
1914 intg2= (int) (stop2-buf2);
1918 else if (intg2 == intg1)
1920 dec1 *end1= stop1 + (frac1 - 1);
1921 dec1 *end2= stop2 + (frac2 - 1);
1922 while (unlikely((buf1 <= end1) && (*end1 == 0)))
1924 while (unlikely((buf2 <= end2) && (*end2 == 0)))
1926 frac1= (int) (end1 - stop1) + 1;
1927 frac2= (int) (end2 - stop2) + 1;
1928 while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
1933 carry= *buf2 > *buf1;
1945 decimal_make_zero(to);
1952 return carry == from1->sign ? 1 : -1;
1956 to->sign=from1->sign;
1961 swap_variables(
const decimal_t *, from1, from2);
1962 swap_variables(dec1 *,start1, start2);
1963 swap_variables(
int,intg1,intg2);
1964 swap_variables(
int,frac1,frac2);
1965 to->sign= 1 - to->sign;
1968 FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
1969 buf0=to->buf+intg1+frac0;
1971 to->frac= MY_MAX(from1->frac, from2->frac);
1972 to->intg=intg1*DIG_PER_DEC1;
1973 if (unlikely(error))
1975 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1976 set_if_smaller(frac1, frac0);
1977 set_if_smaller(frac2, frac0);
1978 set_if_smaller(intg2, intg1);
1985 buf1=start1+intg1+frac1;
1986 stop1=start1+intg1+frac2;
1987 buf2=start2+intg2+frac2;
1988 while (frac0-- > frac1)
1990 while (buf1 > stop1)
1995 buf1=start1+intg1+frac1;
1996 buf2=start2+intg2+frac2;
1997 stop2=start2+intg2+frac1;
1998 while (frac0-- > frac2)
2000 while (buf2 > stop2)
2002 SUB(*--buf0, 0, *--buf2, carry);
2007 while (buf2 > start2)
2009 SUB(*--buf0, *--buf1, *--buf2, carry);
2013 while (carry && buf1 > start1)
2015 SUB(*--buf0, *--buf1, 0, carry);
2018 while (buf1 > start1)
2021 while (buf0 > to->buf)
2030 remove_leading_zeroes(from, &res);
2036 if (likely(from1->sign == from2->sign))
2037 return do_add(from1, from2, to);
2038 return do_sub(from1, from2, to);
2043 if (likely(from1->sign == from2->sign))
2044 return do_sub(from1, from2, to);
2045 return do_add(from1, from2, to);
2050 if (likely(from1->sign == from2->sign))
2051 return do_sub(from1, from2, 0);
2052 return from1->sign > from2->sign ? -1 : 1;
2055 int decimal_is_zero(
const decimal_t *from)
2057 dec1 *buf1=from->buf,
2058 *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2088 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
2089 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
2090 intg0=ROUND_UP(from1->intg+from2->intg),
2091 frac0=frac1+frac2, error, iii, jjj, d_to_move;
2092 dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2093 *start2, *stop2, *stop1, *start0, carry;
2099 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2100 to->sign= from1->sign != from2->sign;
2101 to->frac= from1->frac + from2->frac;
2102 set_if_smaller(to->frac, NOT_FIXED_DEC);
2103 to->intg=intg0*DIG_PER_DEC1;
2105 if (unlikely(error))
2107 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
2108 set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
2109 if (unlikely(iii > intg0))
2133 start0=to->buf+intg0+frac0-1;
2134 start2=buf2+frac2-1;
2138 memset(to->buf, 0, (intg0+frac0)*
sizeof(dec1));
2140 for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
2143 for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
2146 dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2147 hi=(dec1)(p/DIG_BASE);
2148 lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2149 ADD2(*buf0, *buf0, lo, carry);
2155 return E_DEC_OVERFLOW;
2156 ADD2(*buf0, *buf0, 0, carry);
2158 for (buf0--; carry; buf0--)
2161 return E_DEC_OVERFLOW;
2162 ADD(*buf0, *buf0, 0, carry);
2170 dec1 *end= to->buf + intg0 + frac0;
2171 DBUG_ASSERT(buf != end);
2179 decimal_make_zero(to);
2185 d_to_move= intg0 + ROUND_UP(to->frac);
2186 while (!*buf1 && (to->intg > DIG_PER_DEC1))
2189 to->intg-= DIG_PER_DEC1;
2194 dec1 *cur_d= to->buf;
2195 for (; d_to_move--; cur_d++, buf1++)
2214 int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2215 frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2216 UNINIT_VAR(error),
i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2217 dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2218 *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2219 dec2 norm_factor, x, guess, y;
2227 i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
2228 while (prec2 > 0 && *buf2 == 0)
2235 return E_DEC_DIV_ZERO;
2236 for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
2237 DBUG_ASSERT(prec2 > 0);
2239 i=((prec1-1) % DIG_PER_DEC1)+1;
2240 while (prec1 > 0 && *buf1 == 0)
2248 decimal_make_zero(to);
2251 for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2252 DBUG_ASSERT(prec1 > 0);
2255 if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
2258 dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
2261 dintg/=DIG_PER_DEC1;
2265 intg0=ROUND_UP(dintg);
2273 to->sign=from1->sign;
2274 to->frac= MY_MAX(from1->frac, from2->frac);
2289 frac0=ROUND_UP(frac1+frac2+scale_incr);
2290 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2291 to->sign=from1->sign != from2->sign;
2292 to->intg=intg0*DIG_PER_DEC1;
2293 to->frac=frac0*DIG_PER_DEC1;
2296 stop0=buf0+intg0+frac0;
2297 if (likely(div_mod))
2298 while (dintg++ < 0 && buf0 < &to->buf[to->len])
2303 len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2304 set_if_bigger(len1, 3);
2305 if (!(tmp1=(dec1 *)my_alloca(len1*
sizeof(dec1))))
2307 memcpy(tmp1, buf1, i*
sizeof(dec1));
2308 memset(tmp1+i, 0, (len1-i)*
sizeof(dec1));
2313 stop2=buf2+ROUND_UP(prec2)-1;
2316 while (*stop2 == 0 && stop2 >= start2)
2318 len2= (int) (stop2++ - start2);
2328 norm_factor=DIG_BASE/(*start2+1);
2329 norm2=(dec1)(norm_factor*start2[0]);
2331 norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
2333 if (*start1 < *start2)
2339 for (; buf0 < stop0; buf0++)
2342 if (unlikely(dcarry == 0 && *start1 < *start2))
2347 x=start1[0]+((dec2)dcarry)*DIG_BASE;
2349 guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
2350 if (unlikely(guess >= DIG_BASE))
2355 if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
2357 if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
2359 DBUG_ASSERT(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
2365 DBUG_ASSERT(buf1 < stop1);
2366 for (carry=0; buf2 > start2; buf1--)
2369 x=guess * (*--buf2);
2370 hi=(dec1)(x/DIG_BASE);
2371 lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2372 SUB2(*buf1, *buf1, lo, carry);
2375 carry= dcarry < carry;
2378 if (unlikely(carry))
2384 for (carry=0; buf2 > start2; buf1--)
2386 ADD(*buf1, *buf1, *--buf2, carry);
2390 if (likely(div_mod))
2392 DBUG_ASSERT(buf0 < to->buf + to->len);
2408 intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2409 frac0=ROUND_UP(to->frac);
2411 if (unlikely(frac0==0 && intg0==0))
2413 decimal_make_zero(to);
2418 if (unlikely(-intg0 >= to->len))
2420 decimal_make_zero(to);
2421 error=E_DEC_TRUNCATED;
2432 if (unlikely(intg0 > to->len))
2436 error=E_DEC_OVERFLOW;
2439 DBUG_ASSERT(intg0 <= ROUND_UP(from2->intg));
2440 stop1=start1+frac0+intg0;
2441 to->intg= MY_MIN(intg0 * DIG_PER_DEC1, from2->intg);
2443 if (unlikely(intg0+frac0 > to->len))
2445 stop1-=frac0+intg0-to->len;
2446 frac0=to->len-intg0;
2447 to->frac=frac0*DIG_PER_DEC1;
2448 error=E_DEC_TRUNCATED;
2450 DBUG_ASSERT(buf0 + (stop1 - start1) <= to->buf + to->len);
2451 while (start1 < stop1)
2456 tmp1= remove_leading_zeroes(to, &to->intg);
2458 memmove(to->buf, tmp1,
2459 (ROUND_UP(to->intg) + ROUND_UP(to->frac)) *
sizeof(dec1));
2483 return do_div_mod(from1, from2, to, 0, scale_incr);
2515 return do_div_mod(from1, from2, 0, to, 0);