1 /* Copyright (c) 2004, 2014, Oracle and/or its affiliates.
2 Copyright (c) 2009, 2014, Monty Program Ab.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
16
17 /*
18 =======================================================================
19 NOTE: this library implements SQL standard "exact numeric" type
20 and is not at all generic, but rather intentinally crippled to
21 follow the standard :)
22 =======================================================================
23 Quoting the standard
24 (SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
25
26 4.4.2 Characteristics of numbers, page 27:
27
28 An exact numeric type has a precision P and a scale S. P is a positive
29 integer that determines the number of significant digits in a
30 particular radix R, where R is either 2 or 10. S is a non-negative
31 integer. Every value of an exact numeric type of scale S is of the
32 form n*10^{-S}, where n is an integer such that -R^P <= n <= R^P.
33
34 [...]
35
36 If an assignment of some number would result in a loss of its most
37 significant digit, an exception condition is raised. If least
38 significant digits are lost, implementation-defined rounding or
39 truncating occurs, with no exception condition being raised.
40
41 [...]
42
43 Whenever an exact or approximate numeric value is assigned to an exact
44 numeric value site, an approximation of its value that preserves
45 leading significant digits after rounding or truncating is represented
46 in the declared type of the target. The value is converted to have the
47 precision and scale of the target. The choice of whether to truncate
48 or round is implementation-defined.
49
50 [...]
51
52 All numeric values between the smallest and the largest value,
53 inclusive, in a given exact numeric type have an approximation
54 obtained by rounding or truncation for that type; it is
55 implementation-defined which other numeric values have such
56 approximations.
57
58 5.3 <literal>, page 143
59
60 <exact numeric literal> ::=
61 <unsigned integer> [ <period> [ <unsigned integer> ] ]
62 | <period> <unsigned integer>
63
64 6.1 <data type>, page 165:
65
66 19) The <scale> of an <exact numeric type> shall not be greater than
67 the <precision> of the <exact numeric type>.
68
69 20) For the <exact numeric type>s DECIMAL and NUMERIC:
70
71 a) The maximum value of <precision> is implementation-defined.
72 <precision> shall not be greater than this value.
73 b) The maximum value of <scale> is implementation-defined. <scale>
74 shall not be greater than this maximum value.
75
76 21) NUMERIC specifies the data type exact numeric, with the decimal
77 precision and scale specified by the <precision> and <scale>.
78
79 22) DECIMAL specifies the data type exact numeric, with the decimal
80 scale specified by the <scale> and the implementation-defined
81 decimal precision equal to or greater than the value of the
82 specified <precision>.
83
84 6.26 <numeric value expression>, page 241:
85
86 1) If the declared type of both operands of a dyadic arithmetic
87 operator is exact numeric, then the declared type of the result is
88 an implementation-defined exact numeric type, with precision and
89 scale determined as follows:
90
91 a) Let S1 and S2 be the scale of the first and second operands
92 respectively.
93 b) The precision of the result of addition and subtraction is
94 implementation-defined, and the scale is the maximum of S1 and S2.
95 c) The precision of the result of multiplication is
96 implementation-defined, and the scale is S1 + S2.
97 d) The precision and scale of the result of division are
98 implementation-defined.
99 */
100
101 #include "strings_def.h"
102 #include <m_ctype.h>
103 #include <myisampack.h>
104 #include <my_sys.h> /* for my_alloca */
105 #include <decimal.h>
106
107 /*
108 Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
109 So one variable of type decimal_digit_t is limited:
110
111 0 < decimal_digit <= DIG_MAX < DIG_BASE
112
113 in the struct st_decimal_t:
114
115 intg is the number of *decimal* digits (NOT number of decimal_digit_t's !)
116 before the point
117 frac - number of decimal digits after the point
118 buf is an array of decimal_digit_t's
119 len is the length of buf (length of allocated space) in decimal_digit_t's,
120 not in bytes
121 */
122 typedef decimal_digit_t dec1;
123 typedef longlong dec2;
124
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 static const dec1 powers10[DIG_PER_DEC1+1]={
131 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
132 static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
133 static const dec1 frac_max[DIG_PER_DEC1-1]={
134 900000000, 990000000, 999000000,
135 999900000, 999990000, 999999000,
136 999999900, 999999990 };
137
ROUND_UP(int x)138 static inline int ROUND_UP(int x)
139 {
140 return (x + (x > 0 ? DIG_PER_DEC1 - 1 : 0)) / DIG_PER_DEC1;
141 }
142
143 #ifdef HAVE_valgrind
144 #define sanity(d) DBUG_ASSERT((d)->len > 0)
145 #else
146 #define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
147 (d)->buf[(d)->len-1] | 1))
148 #endif
149
150 #define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
151 do \
152 { \
153 if (unlikely(intg1+frac1 > (len))) \
154 { \
155 if (unlikely(intg1 > (len))) \
156 { \
157 intg1=(len); \
158 frac1=0; \
159 error=E_DEC_OVERFLOW; \
160 } \
161 else \
162 { \
163 frac1=(len)-intg1; \
164 error=E_DEC_TRUNCATED; \
165 } \
166 } \
167 else \
168 error=E_DEC_OK; \
169 } while(0)
170
171 #define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
172 do \
173 { \
174 dec1 a=(from1)+(from2)+(carry); \
175 DBUG_ASSERT((carry) <= 1); \
176 if (((carry)= a >= DIG_BASE)) /* no division here! */ \
177 a-=DIG_BASE; \
178 (to)=a; \
179 } while(0)
180
181 #define ADD2(to, from1, from2, carry) \
182 do \
183 { \
184 dec2 a=((dec2)(from1))+(from2)+(carry); \
185 if (((carry)= a >= DIG_BASE)) \
186 a-=DIG_BASE; \
187 if (unlikely(a >= DIG_BASE)) \
188 { \
189 a-=DIG_BASE; \
190 carry++; \
191 } \
192 (to)=(dec1) a; \
193 } while(0)
194
195 #define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
196 do \
197 { \
198 dec1 a=(from1)-(from2)-(carry); \
199 if (((carry)= a < 0)) \
200 a+=DIG_BASE; \
201 (to)=a; \
202 } while(0)
203
204 #define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
205 do \
206 { \
207 dec1 a=(from1)-(from2)-(carry); \
208 if (((carry)= a < 0)) \
209 a+=DIG_BASE; \
210 if (unlikely(a < 0)) \
211 { \
212 a+=DIG_BASE; \
213 carry++; \
214 } \
215 (to)=a; \
216 } while(0)
217
218 /*
219 Get maximum value for given precision and scale
220
221 SYNOPSIS
222 max_decimal()
223 precision/scale - see decimal_bin_size() below
224 to - decimal where where the result will be stored
225 to->buf and to->len must be set.
226 */
227
max_decimal(int precision,int frac,decimal_t * to)228 void max_decimal(int precision, int frac, decimal_t *to)
229 {
230 int intpart;
231 dec1 *buf= to->buf;
232 DBUG_ASSERT(precision && precision >= frac);
233
234 to->sign= 0;
235 if ((intpart= to->intg= (precision - frac)))
236 {
237 int firstdigits= intpart % DIG_PER_DEC1;
238 if (firstdigits)
239 *buf++= powers10[firstdigits] - 1; /* get 9 99 999 ... */
240 for(intpart/= DIG_PER_DEC1; intpart; intpart--)
241 *buf++= DIG_MAX;
242 }
243
244 if ((to->frac= frac))
245 {
246 int lastdigits= frac % DIG_PER_DEC1;
247 for(frac/= DIG_PER_DEC1; frac; frac--)
248 *buf++= DIG_MAX;
249 if (lastdigits)
250 *buf= frac_max[lastdigits - 1];
251 }
252 }
253
254
remove_leading_zeroes(const decimal_t * from,int * intg_result)255 static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
256 {
257 int intg= from->intg, i;
258 dec1 *buf0= from->buf;
259 i= ((intg - 1) % DIG_PER_DEC1) + 1;
260 while (intg > 0 && *buf0 == 0)
261 {
262 intg-= i;
263 i= DIG_PER_DEC1;
264 buf0++;
265 }
266 if (intg > 0)
267 {
268 for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ;
269 DBUG_ASSERT(intg > 0);
270 }
271 else
272 intg=0;
273 *intg_result= intg;
274 return buf0;
275 }
276
277
278 /*
279 Count actual length of fraction part (without ending zeroes)
280
281 SYNOPSIS
282 decimal_actual_fraction()
283 from number for processing
284 */
285
decimal_actual_fraction(const decimal_t * from)286 int decimal_actual_fraction(const decimal_t *from)
287 {
288 int frac= from->frac, i;
289 dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
290
291 if (frac == 0)
292 return 0;
293
294 i= ((frac - 1) % DIG_PER_DEC1 + 1);
295 while (frac > 0 && *buf0 == 0)
296 {
297 frac-= i;
298 i= DIG_PER_DEC1;
299 buf0--;
300 }
301 if (frac > 0)
302 {
303 for (i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1);
304 *buf0 % powers10[i++] == 0;
305 frac--) {}
306 }
307 return frac;
308 }
309
310
311 /*
312 Convert decimal to its printable string representation
313
314 SYNOPSIS
315 decimal2string()
316 from - value to convert
317 to - points to buffer where string representation
318 should be stored
319 *to_len - in: size of to buffer (incl. terminating '\0')
320 out: length of the actually written string (excl. '\0')
321 fixed_precision - 0 if representation can be variable length and
322 fixed_decimals will not be checked in this case.
323 Put number as with fixed point position with this
324 number of digits (sign counted and decimal point is
325 counted)
326 fixed_decimals - number digits after point.
327 filler - character to fill gaps in case of fixed_precision > 0
328
329 RETURN VALUE
330 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
331 */
332
decimal2string(const decimal_t * from,char * to,int * to_len,int fixed_precision,int fixed_decimals,char filler)333 int decimal2string(const decimal_t *from, char *to, int *to_len,
334 int fixed_precision, int fixed_decimals,
335 char filler)
336 {
337 /* {intg_len, frac_len} output widths; {intg, frac} places in input */
338 int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
339 /* number digits before decimal point */
340 int fixed_intg= (fixed_precision ?
341 (fixed_precision - fixed_decimals) : 0);
342 int error=E_DEC_OK;
343 char *s=to;
344 dec1 *buf, *buf0=from->buf, tmp;
345
346 DBUG_ASSERT(*to_len >= 2+ (int) from->sign);
347
348 /* removing leading zeroes */
349 buf0= remove_leading_zeroes(from, &intg);
350 if (unlikely(intg+frac==0))
351 {
352 intg=1;
353 tmp=0;
354 buf0=&tmp;
355 }
356
357 if (!(intg_len= fixed_precision ? fixed_intg : intg))
358 intg_len= 1;
359 frac_len= fixed_precision ? fixed_decimals : frac;
360 len= from->sign + intg_len + MY_TEST(frac) + frac_len;
361 if (fixed_precision)
362 {
363 if (frac > fixed_decimals)
364 {
365 error= E_DEC_TRUNCATED;
366 frac= fixed_decimals;
367 }
368 if (intg > fixed_intg)
369 {
370 error= E_DEC_OVERFLOW;
371 intg= fixed_intg;
372 }
373 }
374 else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
375 {
376 int j= len-*to_len;
377 error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
378 if (frac && j >= frac + 1) j--;
379 if (j > frac)
380 {
381 intg-= j-frac;
382 frac= 0;
383 }
384 else
385 frac-=j;
386 frac_len= frac;
387 len= from->sign + intg_len + MY_TEST(frac) + frac_len;
388 }
389 *to_len=len;
390 s[len]=0;
391
392 if (from->sign)
393 *s++='-';
394
395 if (frac)
396 {
397 char *s1= s + intg_len;
398 fill= frac_len - frac;
399 buf=buf0+ROUND_UP(intg);
400 *s1++='.';
401 for (; frac>0; frac-=DIG_PER_DEC1)
402 {
403 dec1 x=*buf++;
404 for (i=MY_MIN(frac, DIG_PER_DEC1); i; i--)
405 {
406 dec1 y=x/DIG_MASK;
407 *s1++='0'+(uchar)y;
408 x-=y*DIG_MASK;
409 x*=10;
410 }
411 }
412 for(; fill; fill--)
413 *s1++=filler;
414 }
415
416 fill= intg_len - intg;
417 if (intg == 0)
418 fill--; /* symbol 0 before digital point */
419 for(; fill; fill--)
420 *s++=filler;
421 if (intg)
422 {
423 s+=intg;
424 for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
425 {
426 dec1 x=*--buf;
427 for (i=MY_MIN(intg, DIG_PER_DEC1); i; i--)
428 {
429 dec1 y=x/10;
430 *--s='0'+(uchar)(x-y*10);
431 x=y;
432 }
433 }
434 }
435 else
436 *s= '0';
437 return error;
438 }
439
440
441 /*
442 Return bounds of decimal digits in the number
443
444 SYNOPSIS
445 digits_bounds()
446 from - decimal number for processing
447 start_result - index (from 0 ) of first decimal digits will
448 be written by this address
449 end_result - index of position just after last decimal digit
450 be written by this address
451 */
452
digits_bounds(decimal_t * from,int * start_result,int * end_result)453 static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
454 {
455 int start, stop, i;
456 dec1 *buf_beg= from->buf;
457 dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
458 dec1 *buf_end= end - 1;
459
460 /* find non-zero digit from number beginning */
461 while (buf_beg < end && *buf_beg == 0)
462 buf_beg++;
463
464 if (buf_beg >= end)
465 {
466 /* it is zero */
467 *start_result= *end_result= 0;
468 return;
469 }
470
471 /* find non-zero decimal digit from number beginning */
472 if (buf_beg == from->buf && from->intg)
473 {
474 start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1));
475 i--;
476 }
477 else
478 {
479 i= DIG_PER_DEC1 - 1;
480 start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
481 }
482 if (buf_beg < end)
483 for (; *buf_beg < powers10[i--]; start++) ;
484 *start_result= start; /* index of first decimal digit (from 0) */
485
486 /* find non-zero digit at the end */
487 while (buf_end > buf_beg && *buf_end == 0)
488 buf_end--;
489 /* find non-zero decimal digit from the end */
490 if (buf_end == end - 1 && from->frac)
491 {
492 stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
493 (i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
494 i= DIG_PER_DEC1 - i + 1;
495 }
496 else
497 {
498 stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
499 i= 1;
500 }
501 for (; *buf_end % powers10[i++] == 0; stop--) {}
502 *end_result= stop; /* index of position after last decimal digit (from 0) */
503 }
504
505
506 /*
507 Left shift for alignment of data in buffer
508
509 SYNOPSIS
510 do_mini_left_shift()
511 dec pointer to decimal number which have to be shifted
512 shift number of decimal digits on which it should be shifted
513 beg/end bounds of decimal digits (see digits_bounds())
514
515 NOTE
516 Result fitting in the buffer should be garanted.
517 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
518 */
519
do_mini_left_shift(decimal_t * dec,int shift,int beg,int last)520 void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
521 {
522 dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
523 dec1 *end= dec->buf + ROUND_UP(last) - 1;
524 int c_shift= DIG_PER_DEC1 - shift;
525 DBUG_ASSERT(from >= dec->buf);
526 DBUG_ASSERT(end < dec->buf + dec->len);
527 if (beg % DIG_PER_DEC1 < shift)
528 *(from - 1)= (*from) / powers10[c_shift];
529 for(; from < end; from++)
530 *from= ((*from % powers10[c_shift]) * powers10[shift] +
531 (*(from + 1)) / powers10[c_shift]);
532 *from= (*from % powers10[c_shift]) * powers10[shift];
533 }
534
535
536 /*
537 Right shift for alignment of data in buffer
538
539 SYNOPSIS
540 do_mini_left_shift()
541 dec pointer to decimal number which have to be shifted
542 shift number of decimal digits on which it should be shifted
543 beg/end bounds of decimal digits (see digits_bounds())
544
545 NOTE
546 Result fitting in the buffer should be garanted.
547 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
548 */
549
do_mini_right_shift(decimal_t * dec,int shift,int beg,int last)550 void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
551 {
552 dec1 *from= dec->buf + ROUND_UP(last) - 1;
553 dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
554 int c_shift= DIG_PER_DEC1 - shift;
555 DBUG_ASSERT(from < dec->buf + dec->len);
556 DBUG_ASSERT(end >= dec->buf);
557 if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
558 *(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
559 for(; from > end; from--)
560 *from= (*from / powers10[shift] +
561 (*(from - 1) % powers10[shift]) * powers10[c_shift]);
562 *from= *from / powers10[shift];
563 }
564
565
566 /*
567 Shift of decimal digits in given number (with rounding if it need)
568
569 SYNOPSIS
570 decimal_shift()
571 dec number to be shifted
572 shift number of decimal positions
573 shift > 0 means shift to left shift
574 shift < 0 meand right shift
575 NOTE
576 In fact it is multipling on 10^shift.
577 RETURN
578 E_DEC_OK OK
579 E_DEC_OVERFLOW operation lead to overflow, number is untoched
580 E_DEC_TRUNCATED number was rounded to fit into buffer
581 */
582
decimal_shift(decimal_t * dec,int shift)583 int decimal_shift(decimal_t *dec, int shift)
584 {
585 /* index of first non zero digit (all indexes from 0) */
586 int beg;
587 /* index of position after last decimal digit */
588 int end;
589 /* index of digit position just after point */
590 int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
591 /* new point position */
592 int new_point= point + shift;
593 /* number of digits in result */
594 int digits_int, digits_frac;
595 /* length of result and new fraction in big digits*/
596 int new_len, new_frac_len;
597 /* return code */
598 int err= E_DEC_OK;
599 int new_front;
600
601 if (shift == 0)
602 return E_DEC_OK;
603
604 digits_bounds(dec, &beg, &end);
605
606 if (beg == end)
607 {
608 decimal_make_zero(dec);
609 return E_DEC_OK;
610 }
611
612 digits_int= new_point - beg;
613 set_if_bigger(digits_int, 0);
614 digits_frac= end - new_point;
615 set_if_bigger(digits_frac, 0);
616
617 if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
618 dec->len)
619 {
620 int lack= new_len - dec->len;
621 int diff;
622
623 if (new_frac_len < lack)
624 return E_DEC_OVERFLOW; /* lack more then we have in fraction */
625
626 /* cat off fraction part to allow new number to fit in our buffer */
627 err= E_DEC_TRUNCATED;
628 new_frac_len-= lack;
629 diff= digits_frac - (new_frac_len * DIG_PER_DEC1);
630 /* Make rounding method as parameter? */
631 decimal_round(dec, dec, end - point - diff, HALF_UP);
632 end-= diff;
633 digits_frac= new_frac_len * DIG_PER_DEC1;
634
635 if (end <= beg)
636 {
637 /*
638 we lost all digits (they will be shifted out of buffer), so we can
639 just return 0
640 */
641 decimal_make_zero(dec);
642 return E_DEC_TRUNCATED;
643 }
644 }
645
646 if (shift % DIG_PER_DEC1)
647 {
648 int l_mini_shift, r_mini_shift, mini_shift;
649 int do_left;
650 /*
651 Calculate left/right shift to align decimal digits inside our bug
652 digits correctly
653 */
654 if (shift > 0)
655 {
656 l_mini_shift= shift % DIG_PER_DEC1;
657 r_mini_shift= DIG_PER_DEC1 - l_mini_shift;
658 /*
659 It is left shift so prefer left shift, but if we have not place from
660 left, we have to have it from right, because we checked length of
661 result
662 */
663 do_left= l_mini_shift <= beg;
664 DBUG_ASSERT(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
665 }
666 else
667 {
668 r_mini_shift= (-shift) % DIG_PER_DEC1;
669 l_mini_shift= DIG_PER_DEC1 - r_mini_shift;
670 /* see comment above */
671 do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
672 DBUG_ASSERT(!do_left || l_mini_shift <= beg);
673 }
674 if (do_left)
675 {
676 do_mini_left_shift(dec, l_mini_shift, beg, end);
677 mini_shift= -l_mini_shift;
678 }
679 else
680 {
681 do_mini_right_shift(dec, r_mini_shift, beg, end);
682 mini_shift= r_mini_shift;
683 }
684 new_point+= mini_shift;
685 /*
686 If number is shifted and correctly aligned in buffer we can
687 finish
688 */
689 if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1)
690 {
691 dec->intg= digits_int;
692 dec->frac= digits_frac;
693 return err; /* already shifted as it should be */
694 }
695 beg+= mini_shift;
696 end+= mini_shift;
697 }
698
699 /* if new 'decimal front' is in first digit, we do not need move digits */
700 if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 ||
701 new_front < 0)
702 {
703 /* need to move digits */
704 int d_shift;
705 dec1 *to, *barier;
706 if (new_front > 0)
707 {
708 /* move left */
709 d_shift= new_front / DIG_PER_DEC1;
710 to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
711 barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
712 DBUG_ASSERT(to >= dec->buf);
713 DBUG_ASSERT(barier + d_shift < dec->buf + dec->len);
714 for(; to <= barier; to++)
715 *to= *(to + d_shift);
716 for(barier+= d_shift; to <= barier; to++)
717 *to= 0;
718 d_shift= -d_shift;
719 }
720 else
721 {
722 /* move right */
723 d_shift= (1 - new_front) / DIG_PER_DEC1;
724 to= dec->buf + ROUND_UP(end) - 1 + d_shift;
725 barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
726 DBUG_ASSERT(to < dec->buf + dec->len);
727 DBUG_ASSERT(barier - d_shift >= dec->buf);
728 for(; to >= barier; to--)
729 *to= *(to - d_shift);
730 for(barier-= d_shift; to >= barier; to--)
731 *to= 0;
732 }
733 d_shift*= DIG_PER_DEC1;
734 beg+= d_shift;
735 end+= d_shift;
736 new_point+= d_shift;
737 }
738
739 /*
740 If there are gaps then fill ren with 0.
741
742 Only one of following 'for' loops will work because beg <= end
743 */
744 beg= ROUND_UP(beg + 1) - 1;
745 end= ROUND_UP(end) - 1;
746 DBUG_ASSERT(new_point >= 0);
747
748 /* We don't want negative new_point below */
749 if (new_point != 0)
750 new_point= ROUND_UP(new_point) - 1;
751
752 if (new_point > end)
753 {
754 do
755 {
756 dec->buf[new_point]=0;
757 } while (--new_point > end);
758 }
759 else
760 {
761 for (; new_point < beg; new_point++)
762 dec->buf[new_point]= 0;
763 }
764 dec->intg= digits_int;
765 dec->frac= digits_frac;
766 return err;
767 }
768
769
770 /*
771 Convert string to decimal
772
773 SYNOPSIS
774 internal_str2decl()
775 from - value to convert. Doesn't have to be \0 terminated!
776 to - decimal where where the result will be stored
777 to->buf and to->len must be set.
778 end - Pointer to pointer to end of string. Will on return be
779 set to the char after the last used character
780 fixed - use to->intg, to->frac as limits for input number
781
782 NOTE
783 to->intg and to->frac can be modified even when fixed=1
784 (but only decreased, in this case)
785
786 RETURN VALUE
787 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
788 In case of E_DEC_FATAL_ERROR *to is set to decimal zero
789 (to make error handling easier)
790 */
791
792 int
internal_str2dec(const char * from,decimal_t * to,char ** end,my_bool fixed)793 internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed)
794 {
795 const char *s= from, *s1, *endp, *end_of_string= *end;
796 int i, intg, frac, error, intg1, frac1;
797 dec1 x,*buf;
798 sanity(to);
799
800 error= E_DEC_BAD_NUM; /* In case of bad number */
801 while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
802 s++;
803 if (s == end_of_string)
804 goto fatal_error;
805
806 if ((to->sign= (*s == '-')))
807 s++;
808 else if (*s == '+')
809 s++;
810
811 s1=s;
812 while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
813 s++;
814 intg= (int) (s-s1);
815 /*
816 If the integer part is long enough and it has multiple leading zeros,
817 let's trim them, so this expression can return 1 without overflowing:
818 CAST(CONCAT(REPEAT('0',90),'1') AS DECIMAL(10))
819 */
820 if (intg > DIG_PER_DEC1 && s1[0] == '0' && s1[1] == '0')
821 {
822 /*
823 Keep at least one digit, to avoid an empty string.
824 So we trim '0000' to '0' rather than to ''.
825 Otherwise the below code (converting digits to to->buf)
826 would fail on a fatal error.
827 */
828 const char *iend= s - 1;
829 for ( ; s1 < iend && *s1 == '0'; s1++)
830 { }
831 intg= (int) (s-s1);
832 }
833 if (s < end_of_string && *s=='.')
834 {
835 endp= s+1;
836 while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
837 endp++;
838 frac= (int) (endp - s - 1);
839 }
840 else
841 {
842 frac= 0;
843 endp= s;
844 }
845
846 *end= (char*) endp;
847
848 if (frac+intg == 0)
849 goto fatal_error;
850
851 error= 0;
852 if (fixed)
853 {
854 if (frac > to->frac)
855 {
856 error=E_DEC_TRUNCATED;
857 frac=to->frac;
858 }
859 if (intg > to->intg)
860 {
861 error=E_DEC_OVERFLOW;
862 intg=to->intg;
863 }
864 intg1=ROUND_UP(intg);
865 frac1=ROUND_UP(frac);
866 if (intg1+frac1 > to->len)
867 {
868 error= E_DEC_OOM;
869 goto fatal_error;
870 }
871 }
872 else
873 {
874 intg1=ROUND_UP(intg);
875 frac1=ROUND_UP(frac);
876 FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
877 if (unlikely(error))
878 {
879 frac=frac1*DIG_PER_DEC1;
880 if (error == E_DEC_OVERFLOW)
881 intg=intg1*DIG_PER_DEC1;
882 }
883 }
884 /* Error is guaranteed to be set here */
885 to->intg=intg;
886 to->frac=frac;
887
888 buf=to->buf+intg1;
889 s1=s;
890
891 for (x=0, i=0; intg; intg--)
892 {
893 x+= (*--s - '0')*powers10[i];
894
895 if (unlikely(++i == DIG_PER_DEC1))
896 {
897 *--buf=x;
898 x=0;
899 i=0;
900 }
901 }
902 if (i)
903 *--buf=x;
904
905 buf=to->buf+intg1;
906 for (x=0, i=0; frac; frac--)
907 {
908 x= (*++s1 - '0') + x*10;
909
910 if (unlikely(++i == DIG_PER_DEC1))
911 {
912 *buf++=x;
913 x=0;
914 i=0;
915 }
916 }
917 if (i)
918 *buf=x*powers10[DIG_PER_DEC1-i];
919
920 /* Handle exponent */
921 if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
922 {
923 int str_error;
924 const char *end_of_exponent= end_of_string;
925 longlong exponent= my_strtoll10(endp+1, (char**) &end_of_exponent,
926 &str_error);
927
928 if (end_of_exponent != endp +1) /* If at least one digit */
929 {
930 *end= (char*) end_of_exponent;
931 if (str_error > 0)
932 {
933 if (str_error == MY_ERRNO_ERANGE)
934 {
935 /*
936 Exponent is:
937 - a huge positive number that does not fit into ulonglong
938 - a huge negative number that does not fit into longlong
939 Skip all remaining digits.
940 */
941 for ( ; end_of_exponent < end_of_string &&
942 my_isdigit(&my_charset_latin1, *end_of_exponent)
943 ; end_of_exponent++)
944 { }
945 *end= (char*) end_of_exponent;
946 if (exponent == ~0)
947 {
948 if (!decimal_is_zero(to))
949 {
950 /*
951 Non-zero mantissa and a huge positive exponent that
952 does not fit into ulonglong, e.g.:
953 1e111111111111111111111
954 */
955 error= E_DEC_OVERFLOW;
956 }
957 else
958 {
959 /*
960 Zero mantissa and a huge positive exponent that
961 does not fit into ulonglong, e.g.:
962 0e111111111111111111111
963 Return zero without warnings.
964 */
965 }
966 }
967 else
968 {
969 /*
970 Huge negative exponent that does not fit into longlong, e.g.
971 1e-111111111111111111111
972 0e-111111111111111111111
973 Return zero without warnings.
974 */
975 }
976 goto fatal_error;
977 }
978
979 /*
980 Some other error, e.g. MY_ERRNO_EDOM
981 */
982 error= E_DEC_BAD_NUM;
983 goto fatal_error;
984 }
985 if (exponent > INT_MAX/2 || (str_error == 0 && exponent < 0))
986 {
987 /*
988 The exponent fits into ulonglong, but it's still huge, e.g.
989 1e1111111111
990 */
991 if (!decimal_is_zero(to))
992 error= E_DEC_OVERFLOW;
993 goto fatal_error;
994 }
995 if (exponent < INT_MIN/2 && error != E_DEC_OVERFLOW)
996 {
997 error= E_DEC_TRUNCATED;
998 goto fatal_error;
999 }
1000 if (error != E_DEC_OVERFLOW)
1001 error= decimal_shift(to, (int) exponent);
1002 }
1003 }
1004 if (to->sign && decimal_is_zero(to))
1005 to->sign= 0;
1006 return error;
1007
1008 fatal_error:
1009 decimal_make_zero(to);
1010 return error;
1011 }
1012
1013
1014 /*
1015 Convert decimal to double
1016
1017 SYNOPSIS
1018 decimal2double()
1019 from - value to convert
1020 to - result will be stored there
1021
1022 RETURN VALUE
1023 E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1024 */
1025
decimal2double(const decimal_t * from,double * to)1026 int decimal2double(const decimal_t *from, double *to)
1027 {
1028 char strbuf[FLOATING_POINT_BUFFER], *end;
1029 int len= sizeof(strbuf);
1030 int rc, error;
1031
1032 rc = decimal2string(from, strbuf, &len, 0, 0, 0);
1033 end= strbuf + len;
1034
1035 DBUG_PRINT("info", ("interm.: %s", strbuf));
1036
1037 *to= my_strtod(strbuf, &end, &error);
1038
1039 DBUG_PRINT("info", ("result: %f", *to));
1040
1041 return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
1042 }
1043
1044 /*
1045 Convert double to decimal
1046
1047 SYNOPSIS
1048 double2decimal()
1049 from - value to convert
1050 to - result will be stored there
1051
1052 RETURN VALUE
1053 E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1054 */
1055
double2decimal(double from,decimal_t * to)1056 int double2decimal(double from, decimal_t *to)
1057 {
1058 char buff[FLOATING_POINT_BUFFER], *end;
1059 int res;
1060 DBUG_ENTER("double2decimal");
1061 end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
1062 res= string2decimal(buff, to, &end);
1063 DBUG_PRINT("exit", ("res: %d", res));
1064 DBUG_RETURN(res);
1065 }
1066
1067
ull2dec(ulonglong from,decimal_t * to)1068 static int ull2dec(ulonglong from, decimal_t *to)
1069 {
1070 int intg1, error=E_DEC_OK;
1071 ulonglong x=from;
1072 dec1 *buf;
1073
1074 sanity(to);
1075
1076 if (!from)
1077 {
1078 decimal_make_zero(to);
1079 return E_DEC_OK;
1080 }
1081
1082 for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE) {}
1083 if (unlikely(intg1 > to->len))
1084 {
1085 intg1=to->len;
1086 error=E_DEC_OVERFLOW;
1087 }
1088 to->frac=0;
1089 for(to->intg= (intg1-1)*DIG_PER_DEC1; from; to->intg++, from/=10) {}
1090
1091 for (buf=to->buf+intg1; intg1; intg1--)
1092 {
1093 ulonglong y=x/DIG_BASE;
1094 *--buf=(dec1)(x-y*DIG_BASE);
1095 x=y;
1096 }
1097 return error;
1098 }
1099
ulonglong2decimal(ulonglong from,decimal_t * to)1100 int ulonglong2decimal(ulonglong from, decimal_t *to)
1101 {
1102 to->sign=0;
1103 return ull2dec(from, to);
1104 }
1105
longlong2decimal(longlong from,decimal_t * to)1106 int longlong2decimal(longlong from, decimal_t *to)
1107 {
1108 if ((to->sign= from < 0))
1109 {
1110 if (from == LONGLONG_MIN) // avoid undefined behavior
1111 return ull2dec((ulonglong)LONGLONG_MIN, to);
1112 return ull2dec(-from, to);
1113 }
1114 return ull2dec(from, to);
1115 }
1116
decimal2ulonglong(const decimal_t * from,ulonglong * to)1117 int decimal2ulonglong(const decimal_t *from, ulonglong *to)
1118 {
1119 dec1 *buf=from->buf;
1120 ulonglong x=0;
1121 int intg, frac;
1122
1123 if (from->sign)
1124 {
1125 *to= 0;
1126 return E_DEC_OVERFLOW;
1127 }
1128
1129 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1130 {
1131 ulonglong y=x;
1132 x=x*DIG_BASE + *buf++;
1133 if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
1134 {
1135 *to=ULONGLONG_MAX;
1136 return E_DEC_OVERFLOW;
1137 }
1138 }
1139 *to=x;
1140 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1141 if (*buf++)
1142 return E_DEC_TRUNCATED;
1143 return E_DEC_OK;
1144 }
1145
decimal2longlong(const decimal_t * from,longlong * to)1146 int decimal2longlong(const decimal_t *from, longlong *to)
1147 {
1148 dec1 *buf=from->buf;
1149 longlong x=0;
1150 int intg, frac;
1151
1152 for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1153 {
1154 longlong y=x;
1155 /*
1156 Attention: trick!
1157 we're calculating -|from| instead of |from| here
1158 because |LONGLONG_MIN| > LONGLONG_MAX
1159 so we can convert -9223372036854775808 correctly
1160 */
1161 x=x*DIG_BASE - *buf++;
1162 if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
1163 {
1164 /*
1165 the decimal is bigger than any possible integer
1166 return border integer depending on the sign
1167 */
1168 *to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
1169 return E_DEC_OVERFLOW;
1170 }
1171 }
1172 /* boundary case: 9223372036854775808 */
1173 if (unlikely(from->sign==0 && x == LONGLONG_MIN))
1174 {
1175 *to= LONGLONG_MAX;
1176 return E_DEC_OVERFLOW;
1177 }
1178
1179 *to=from->sign ? x : -x;
1180 for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1181 if (*buf++)
1182 return E_DEC_TRUNCATED;
1183 return E_DEC_OK;
1184 }
1185
1186 /*
1187 Convert decimal to its binary fixed-length representation
1188 two representations of the same length can be compared with memcmp
1189 with the correct -1/0/+1 result
1190
1191 SYNOPSIS
1192 decimal2bin()
1193 from - value to convert
1194 to - points to buffer where string representation should be stored
1195 precision/scale - see decimal_bin_size() below
1196
1197 NOTE
1198 the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1199
1200 RETURN VALUE
1201 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1202
1203 DESCRIPTION
1204 for storage decimal numbers are converted to the "binary" format.
1205
1206 This format has the following properties:
1207 1. length of the binary representation depends on the {precision, scale}
1208 as provided by the caller and NOT on the intg/frac of the decimal to
1209 convert.
1210 2. binary representations of the same {precision, scale} can be compared
1211 with memcmp - with the same result as decimal_cmp() of the original
1212 decimals (not taking into account possible precision loss during
1213 conversion).
1214
1215 This binary format is as follows:
1216 1. First the number is converted to have a requested precision and scale.
1217 2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes
1218 as is
1219 3. The first intg % DIG_PER_DEC1 digits are stored in the reduced
1220 number of bytes (enough bytes to store this number of digits -
1221 see dig2bytes)
1222 4. same for frac - full decimal_digit_t's are stored as is,
1223 the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes.
1224 5. If the number is negative - every byte is inversed.
1225 5. The very first bit of the resulting byte array is inverted (because
1226 memcmp compares unsigned bytes, see property 2 above)
1227
1228 Example:
1229
1230 1234567890.1234
1231
1232 internally is represented as 3 decimal_digit_t's
1233
1234 1 234567890 123400000
1235
1236 (assuming we want a binary representation with precision=14, scale=4)
1237 in hex it's
1238
1239 00-00-00-01 0D-FB-38-D2 07-5A-EF-40
1240
1241 now, middle decimal_digit_t is full - it stores 9 decimal digits. It goes
1242 into binary representation as is:
1243
1244
1245 ........... 0D-FB-38-D2 ............
1246
1247 First decimal_digit_t has only one decimal digit. We can store one digit in
1248 one byte, no need to waste four:
1249
1250 01 0D-FB-38-D2 ............
1251
1252 now, last digit. It's 123400000. We can store 1234 in two bytes:
1253
1254 01 0D-FB-38-D2 04-D2
1255
1256 So, we've packed 12 bytes number in 7 bytes.
1257 And now we invert the highest bit to get the final result:
1258
1259 81 0D FB 38 D2 04 D2
1260
1261 And for -1234567890.1234 it would be
1262
1263 7E F2 04 C7 2D FB 2D
1264 */
decimal2bin(const decimal_t * from,uchar * to,int precision,int frac)1265 int decimal2bin(const decimal_t *from, uchar *to, int precision, int frac)
1266 {
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;
1281 uchar *orig_to= to;
1282
1283 buf1= remove_leading_zeroes(from, &from_intg);
1284
1285 if (unlikely(from_intg+fsize1==0))
1286 {
1287 mask=0; /* just in case */
1288 intg=1;
1289 buf1=&mask;
1290 }
1291
1292 intg1=from_intg/DIG_PER_DEC1;
1293 intg1x=from_intg-intg1*DIG_PER_DEC1;
1294 isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
1295
1296 if (intg < from_intg)
1297 {
1298 buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
1299 intg1=intg0; intg1x=intg0x;
1300 error=E_DEC_OVERFLOW;
1301 }
1302 else if (isize0 > isize1)
1303 {
1304 while (isize0-- > isize1)
1305 *to++= (char)mask;
1306 }
1307 if (fsize0 < fsize1)
1308 {
1309 frac1=frac0; frac1x=frac0x;
1310 error=E_DEC_TRUNCATED;
1311 }
1312 else if (fsize0 > fsize1 && frac1x)
1313 {
1314 if (frac0 == frac1)
1315 {
1316 frac1x=frac0x;
1317 fsize0= fsize1;
1318 }
1319 else
1320 {
1321 frac1++;
1322 frac1x=0;
1323 }
1324 }
1325
1326 /* intg1x part */
1327 if (intg1x)
1328 {
1329 int i=dig2bytes[intg1x];
1330 dec1 x=(*buf1++ % powers10[intg1x]) ^ mask;
1331 switch (i)
1332 {
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);
1338 }
1339 to+=i;
1340 }
1341
1342 /* intg1+frac1 part */
1343 for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=sizeof(dec1))
1344 {
1345 dec1 x=*buf1++ ^ mask;
1346 DBUG_ASSERT(sizeof(dec1) == 4);
1347 mi_int4store(to, x);
1348 }
1349
1350 /* frac1x part */
1351 if (frac1x)
1352 {
1353 dec1 x;
1354 int i=dig2bytes[frac1x],
1355 lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x);
1356 while (frac1x < lim && dig2bytes[frac1x] == i)
1357 frac1x++;
1358 x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask;
1359 switch (i)
1360 {
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);
1366 }
1367 to+=i;
1368 }
1369 if (fsize0 > fsize1)
1370 {
1371 uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
1372
1373 while (fsize0-- > fsize1 && to < to_end)
1374 *to++= (uchar)mask;
1375 }
1376 orig_to[0]^= 0x80;
1377
1378 /* Check that we have written the whole decimal and nothing more */
1379 DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0);
1380 return error;
1381 }
1382
1383 /*
1384 Restores decimal from its binary fixed-length representation
1385
1386 SYNOPSIS
1387 bin2decimal()
1388 from - value to convert
1389 to - result
1390 precision/scale - see decimal_bin_size() below
1391
1392 NOTE
1393 see decimal2bin()
1394 the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1395
1396 RETURN VALUE
1397 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1398 */
1399
bin2decimal(const uchar * from,decimal_t * to,int precision,int scale)1400 int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
1401 {
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;
1407 const uchar *stop;
1408 uchar *d_copy;
1409 int bin_size= decimal_bin_size(precision, scale);
1410
1411 sanity(to);
1412 d_copy= (uchar*) my_alloca(bin_size);
1413 memcpy(d_copy, from, bin_size);
1414 d_copy[0]^= 0x80;
1415 from= d_copy;
1416
1417 FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1418 if (unlikely(error))
1419 {
1420 if (intg1 < intg0+(intg0x>0))
1421 {
1422 from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1);
1423 frac0=frac0x=intg0x=0;
1424 intg0=intg1;
1425 }
1426 else
1427 {
1428 frac0x=0;
1429 frac0=frac1;
1430 }
1431 }
1432
1433 to->sign=(mask != 0);
1434 to->intg=intg0*DIG_PER_DEC1+intg0x;
1435 to->frac=frac0*DIG_PER_DEC1+frac0x;
1436
1437 if (intg0x)
1438 {
1439 int i=dig2bytes[intg0x];
1440 dec1 UNINIT_VAR(x);
1441 switch (i)
1442 {
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: abort();
1448 }
1449 from+=i;
1450 *buf=x ^ mask;
1451 if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1])
1452 goto err;
1453 if (buf > to->buf || *buf != 0)
1454 buf++;
1455 else
1456 to->intg-=intg0x;
1457 }
1458 for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1459 {
1460 DBUG_ASSERT(sizeof(dec1) == 4);
1461 *buf=mi_sint4korr(from) ^ mask;
1462 if (((uint32)*buf) > DIG_MAX)
1463 goto err;
1464 if (buf > to->buf || *buf != 0)
1465 buf++;
1466 else
1467 to->intg-=DIG_PER_DEC1;
1468 }
1469 DBUG_ASSERT(to->intg >=0);
1470 for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1471 {
1472 DBUG_ASSERT(sizeof(dec1) == 4);
1473 *buf=mi_sint4korr(from) ^ mask;
1474 if (((uint32)*buf) > DIG_MAX)
1475 goto err;
1476 buf++;
1477 }
1478 if (frac0x)
1479 {
1480 int i=dig2bytes[frac0x];
1481 dec1 UNINIT_VAR(x);
1482 switch (i)
1483 {
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: abort();
1489 }
1490 *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
1491 if (((uint32)*buf) > DIG_MAX)
1492 goto err;
1493 buf++;
1494 }
1495 my_afree(d_copy);
1496
1497 /*
1498 No digits? We have read the number zero, of unspecified precision.
1499 Make it a proper zero, with non-zero precision.
1500 */
1501 if (to->intg == 0 && to->frac == 0)
1502 decimal_make_zero(to);
1503 return error;
1504
1505 err:
1506 my_afree(d_copy);
1507 decimal_make_zero(to);
1508 return(E_DEC_BAD_NUM);
1509 }
1510
1511 /*
1512 Returns the size of array to hold a decimal with given precision and scale
1513
1514 RETURN VALUE
1515 size in dec1
1516 (multiply by sizeof(dec1) to get the size if bytes)
1517 */
1518
decimal_size(int precision,int scale)1519 int decimal_size(int precision, int scale)
1520 {
1521 DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1522 return ROUND_UP(precision-scale)+ROUND_UP(scale);
1523 }
1524
1525 /*
1526 Returns the size of array to hold a binary representation of a decimal
1527
1528 RETURN VALUE
1529 size in bytes
1530 */
1531
decimal_bin_size(int precision,int scale)1532 int decimal_bin_size(int precision, int scale)
1533 {
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;
1537
1538 DBUG_ASSERT(scale >= 0);
1539 DBUG_ASSERT(precision > 0);
1540 DBUG_ASSERT(scale <= precision);
1541 return intg0*sizeof(dec1)+dig2bytes[intg0x]+
1542 frac0*sizeof(dec1)+dig2bytes[frac0x];
1543 }
1544
1545 /*
1546 Rounds the decimal to "scale" digits
1547
1548 SYNOPSIS
1549 decimal_round()
1550 from - decimal to round,
1551 to - result buffer. from==to is allowed
1552 scale - to what position to round. can be negative!
1553 mode - round to nearest even or truncate
1554
1555 NOTES
1556 scale can be negative !
1557 one TRUNCATED error (line XXX below) isn't treated very logical :(
1558
1559 RETURN VALUE
1560 E_DEC_OK/E_DEC_TRUNCATED
1561 */
1562
1563 int
decimal_round(const decimal_t * from,decimal_t * to,int scale,decimal_round_mode mode)1564 decimal_round(const decimal_t *from, decimal_t *to, int scale,
1565 decimal_round_mode mode)
1566 {
1567 int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1568 frac1=ROUND_UP(from->frac), UNINIT_VAR(round_digit),
1569 intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len;
1570
1571 dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1572 int first_dig;
1573
1574 sanity(to);
1575
1576 switch (mode) {
1577 case HALF_UP:
1578 case HALF_EVEN: round_digit=5; break;
1579 case CEILING: round_digit= from->sign ? 10 : 0; break;
1580 case FLOOR: round_digit= from->sign ? 0 : 10; break;
1581 case TRUNCATE: round_digit=10; break;
1582 default: DBUG_ASSERT(0);
1583 }
1584
1585 /*
1586 For my_decimal we always use len == DECIMAL_BUFF_LENGTH == 9
1587 For internal testing here (ifdef MAIN) we always use len == 100/4
1588 */
1589 DBUG_ASSERT(from->len == to->len);
1590
1591 if (unlikely(frac0+intg0 > len))
1592 {
1593 frac0=len-intg0;
1594 scale=frac0*DIG_PER_DEC1;
1595 error=E_DEC_TRUNCATED;
1596 }
1597
1598 if (scale+from->intg < 0)
1599 {
1600 decimal_make_zero(to);
1601 return E_DEC_OK;
1602 }
1603
1604 if (to != from)
1605 {
1606 dec1 *p0= buf0+intg0+MY_MAX(frac1, frac0);
1607 dec1 *p1= buf1+intg0+MY_MAX(frac1, frac0);
1608
1609 DBUG_ASSERT(p0 - buf0 <= len);
1610 DBUG_ASSERT(p1 - buf1 <= len);
1611
1612 while (buf0 < p0)
1613 *(--p1) = *(--p0);
1614
1615 buf0=to->buf;
1616 buf1=to->buf;
1617 to->sign=from->sign;
1618 to->intg=MY_MIN(intg0, len)*DIG_PER_DEC1;
1619 }
1620
1621 if (frac0 > frac1)
1622 {
1623 buf1+=intg0+frac1;
1624 while (frac0-- > frac1)
1625 *buf1++=0;
1626 goto done;
1627 }
1628
1629 if (scale >= from->frac)
1630 goto done; /* nothing to do */
1631
1632 buf0+=intg0+frac0-1;
1633 buf1+=intg0+frac0-1;
1634 if (scale == frac0*DIG_PER_DEC1)
1635 {
1636 int do_inc= FALSE;
1637 DBUG_ASSERT(frac0+intg0 >= 0);
1638 switch (round_digit) {
1639 case 0:
1640 {
1641 dec1 *p0= buf0 + (frac1-frac0);
1642 for (; p0 > buf0; p0--)
1643 {
1644 if (*p0)
1645 {
1646 do_inc= TRUE;
1647 break;
1648 }
1649 }
1650 break;
1651 }
1652 case 5:
1653 {
1654 x= buf0[1]/DIG_MASK;
1655 do_inc= (x>5) || ((x == 5) &&
1656 (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
1657 break;
1658 }
1659 default:
1660 break;
1661 }
1662 if (do_inc)
1663 {
1664 if (frac0+intg0>0)
1665 (*buf1)++;
1666 else
1667 *(++buf1)=DIG_BASE;
1668 }
1669 else if (frac0+intg0==0)
1670 {
1671 decimal_make_zero(to);
1672 return E_DEC_OK;
1673 }
1674 }
1675 else
1676 {
1677 /* TODO - fix this code as it won't work for CEILING mode */
1678 int pos=frac0*DIG_PER_DEC1-scale-1;
1679 DBUG_ASSERT(frac0+intg0 > 0);
1680 x=*buf1 / powers10[pos];
1681 y=x % 10;
1682 if (y > round_digit ||
1683 (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
1684 x+=10;
1685 *buf1=powers10[pos]*(x-y);
1686 }
1687 if (*buf1 >= DIG_BASE)
1688 {
1689 carry=1;
1690 *buf1-=DIG_BASE;
1691 while (carry && --buf1 >= to->buf)
1692 ADD(*buf1, *buf1, 0, carry);
1693 if (unlikely(carry))
1694 {
1695 /* shifting the number to create space for new digit */
1696 if (frac0+intg0 >= len)
1697 {
1698 frac0--;
1699 scale=frac0*DIG_PER_DEC1;
1700 error=E_DEC_TRUNCATED; /* XXX */
1701 }
1702 for (buf1=to->buf+intg0+MY_MAX(frac0,0); buf1 > to->buf; buf1--)
1703 {
1704 buf1[0]=buf1[-1];
1705 }
1706 *buf1=1;
1707 to->intg++;
1708 intg0++;
1709 }
1710 }
1711 else
1712 {
1713 for (;;)
1714 {
1715 if (likely(*buf1))
1716 break;
1717 if (buf1-- == to->buf)
1718 {
1719 /* making 'zero' with the proper scale */
1720 dec1 *p0= to->buf + frac0 + 1;
1721 to->intg=1;
1722 to->frac= MY_MAX(scale, 0);
1723 to->sign= 0;
1724 for (buf1= to->buf; buf1<p0; buf1++)
1725 *buf1= 0;
1726 return E_DEC_OK;
1727 }
1728 }
1729 }
1730 /*
1731 In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal_digit_t's inside
1732 the buffer are as follows.
1733
1734 Before <1, 5e8>
1735 After <2, 5e8>
1736
1737 Hence we need to set the 2nd field to 0.
1738 The same holds if we round 1.5e-9 to 2e-9.
1739 */
1740 if (frac0 < frac1)
1741 {
1742 dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0);
1743 dec1 *end= to->buf + len;
1744
1745 while (buf < end)
1746 *buf++=0;
1747 }
1748
1749 /* Here we check 999.9 -> 1000 case when we need to increase intg */
1750 first_dig= to->intg % DIG_PER_DEC1;
1751 if (first_dig && (*buf1 >= powers10[first_dig]))
1752 to->intg++;
1753
1754 if (scale<0)
1755 scale=0;
1756
1757 done:
1758 to->frac=scale;
1759 return error;
1760 }
1761
1762 /*
1763 Returns the size of the result of the operation
1764
1765 SYNOPSIS
1766 decimal_result_size()
1767 from1 - operand of the unary operation or first operand of the
1768 binary operation
1769 from2 - second operand of the binary operation
1770 op - operation. one char '+', '-', '*', '/' are allowed
1771 others may be added later
1772 param - extra param to the operation. unused for '+', '-', '*'
1773 scale increment for '/'
1774
1775 NOTE
1776 returned valued may be larger than the actual buffer required
1777 in the operation, as decimal_result_size, by design, operates on
1778 precision/scale values only and not on the actual decimal number
1779
1780 RETURN VALUE
1781 size of to->buf array in dec1 elements. to get size in bytes
1782 multiply by sizeof(dec1)
1783 */
1784
decimal_result_size(decimal_t * from1,decimal_t * from2,char op,int param)1785 int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1786 {
1787 switch (op) {
1788 case '-':
1789 return ROUND_UP(MY_MAX(from1->intg, from2->intg)) +
1790 ROUND_UP(MY_MAX(from1->frac, from2->frac));
1791 case '+':
1792 return ROUND_UP(MY_MAX(from1->intg, from2->intg)+1) +
1793 ROUND_UP(MY_MAX(from1->frac, from2->frac));
1794 case '*':
1795 return ROUND_UP(from1->intg+from2->intg)+
1796 ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1797 case '/':
1798 return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1799 default: DBUG_ASSERT(0);
1800 }
1801 return -1; /* shut up the warning */
1802 }
1803
do_add(const decimal_t * from1,const decimal_t * from2,decimal_t * to)1804 static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1805 {
1806 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1807 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1808 frac0=MY_MAX(frac1, frac2), intg0=MY_MAX(intg1, intg2), error;
1809 dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1810
1811 sanity(to);
1812
1813 /* is there a need for extra word because of carry ? */
1814 x=intg1 > intg2 ? from1->buf[0] :
1815 intg2 > intg1 ? from2->buf[0] :
1816 from1->buf[0] + from2->buf[0] ;
1817 if (unlikely(x > DIG_MAX-1)) /* yes, there is */
1818 {
1819 intg0++;
1820 to->buf[0]=0; /* safety */
1821 }
1822
1823 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1824 if (unlikely(error == E_DEC_OVERFLOW))
1825 {
1826 max_decimal(to->len * DIG_PER_DEC1, 0, to);
1827 return error;
1828 }
1829
1830 buf0=to->buf+intg0+frac0;
1831
1832 to->sign=from1->sign;
1833 to->frac=MY_MAX(from1->frac, from2->frac);
1834 to->intg=intg0*DIG_PER_DEC1;
1835 if (unlikely(error))
1836 {
1837 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1838 set_if_smaller(frac1, frac0);
1839 set_if_smaller(frac2, frac0);
1840 set_if_smaller(intg1, intg0);
1841 set_if_smaller(intg2, intg0);
1842 }
1843
1844 /* part 1 - MY_MAX(frac) ... min (frac) */
1845 if (frac1 > frac2)
1846 {
1847 buf1=from1->buf+intg1+frac1;
1848 stop=from1->buf+intg1+frac2;
1849 buf2=from2->buf+intg2+frac2;
1850 stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
1851 }
1852 else
1853 {
1854 buf1=from2->buf+intg2+frac2;
1855 stop=from2->buf+intg2+frac1;
1856 buf2=from1->buf+intg1+frac1;
1857 stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
1858 }
1859 while (buf1 > stop)
1860 *--buf0=*--buf1;
1861
1862 /* part 2 - MY_MIN(frac) ... MY_MIN(intg) */
1863 carry=0;
1864 while (buf1 > stop2)
1865 {
1866 ADD(*--buf0, *--buf1, *--buf2, carry);
1867 }
1868
1869 /* part 3 - MY_MIN(intg) ... MY_MAX(intg) */
1870 buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1871 ((stop=from2->buf)+intg2-intg1) ;
1872 while (buf1 > stop)
1873 {
1874 ADD(*--buf0, *--buf1, 0, carry);
1875 }
1876
1877 if (unlikely(carry))
1878 *--buf0=1;
1879 DBUG_ASSERT(buf0 == to->buf || buf0 == to->buf+1);
1880
1881 return error;
1882 }
1883
1884 /* to=from1-from2.
1885 if to==0, return -1/0/+1 - the result of the comparison */
do_sub(const decimal_t * from1,const decimal_t * from2,decimal_t * to)1886 static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1887 {
1888 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1889 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1890 int frac0=MY_MAX(frac1, frac2), error;
1891 dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2;
1892 my_bool carry=0;
1893
1894 /* let carry:=1 if from2 > from1 */
1895 start1=buf1=from1->buf; stop1=buf1+intg1;
1896 start2=buf2=from2->buf; stop2=buf2+intg2;
1897 if (unlikely(*buf1 == 0))
1898 {
1899 while (buf1 < stop1 && *buf1 == 0)
1900 buf1++;
1901 start1=buf1;
1902 intg1= (int) (stop1-buf1);
1903 }
1904 if (unlikely(*buf2 == 0))
1905 {
1906 while (buf2 < stop2 && *buf2 == 0)
1907 buf2++;
1908 start2=buf2;
1909 intg2= (int) (stop2-buf2);
1910 }
1911 if (intg2 > intg1)
1912 carry=1;
1913 else if (intg2 == intg1)
1914 {
1915 dec1 *end1= stop1 + (frac1 - 1);
1916 dec1 *end2= stop2 + (frac2 - 1);
1917 while (unlikely((buf1 <= end1) && (*end1 == 0)))
1918 end1--;
1919 while (unlikely((buf2 <= end2) && (*end2 == 0)))
1920 end2--;
1921 frac1= (int) (end1 - stop1) + 1;
1922 frac2= (int) (end2 - stop2) + 1;
1923 while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
1924 buf1++, buf2++;
1925 if (buf1 <= end1)
1926 {
1927 if (buf2 <= end2)
1928 carry= *buf2 > *buf1;
1929 else
1930 carry= 0;
1931 }
1932 else
1933 {
1934 if (buf2 <= end2)
1935 carry=1;
1936 else /* short-circuit everything: from1 == from2 */
1937 {
1938 if (to == 0) /* decimal_cmp() */
1939 return 0;
1940 decimal_make_zero(to);
1941 return E_DEC_OK;
1942 }
1943 }
1944 }
1945
1946 if (to == 0) /* decimal_cmp() */
1947 return carry == from1->sign ? 1 : -1;
1948
1949 sanity(to);
1950
1951 to->sign=from1->sign;
1952
1953 /* ensure that always from1 > from2 (and intg1 >= intg2) */
1954 if (carry)
1955 {
1956 swap_variables(const decimal_t *, from1, from2);
1957 swap_variables(dec1 *,start1, start2);
1958 swap_variables(int,intg1,intg2);
1959 swap_variables(int,frac1,frac2);
1960 to->sign= !to->sign;
1961 }
1962
1963 FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
1964 buf0=to->buf+intg1+frac0;
1965
1966 to->frac=MY_MAX(from1->frac, from2->frac);
1967 to->intg=intg1*DIG_PER_DEC1;
1968 if (unlikely(error))
1969 {
1970 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1971 set_if_smaller(frac1, frac0);
1972 set_if_smaller(frac2, frac0);
1973 set_if_smaller(intg2, intg1);
1974 }
1975 carry=0;
1976
1977 /* part 1 - MY_MAX(frac) ... min (frac) */
1978 if (frac1 > frac2)
1979 {
1980 buf1=start1+intg1+frac1;
1981 stop1=start1+intg1+frac2;
1982 buf2=start2+intg2+frac2;
1983 while (frac0-- > frac1)
1984 *--buf0=0;
1985 while (buf1 > stop1)
1986 *--buf0=*--buf1;
1987 }
1988 else
1989 {
1990 buf1=start1+intg1+frac1;
1991 buf2=start2+intg2+frac2;
1992 stop2=start2+intg2+frac1;
1993 while (frac0-- > frac2)
1994 *--buf0=0;
1995 while (buf2 > stop2)
1996 {
1997 SUB(*--buf0, 0, *--buf2, carry);
1998 }
1999 }
2000
2001 /* part 2 - MY_MIN(frac) ... intg2 */
2002 while (buf2 > start2)
2003 {
2004 SUB(*--buf0, *--buf1, *--buf2, carry);
2005 }
2006
2007 /* part 3 - intg2 ... intg1 */
2008 while (carry && buf1 > start1)
2009 {
2010 SUB(*--buf0, *--buf1, 0, carry);
2011 }
2012
2013 while (buf1 > start1)
2014 *--buf0=*--buf1;
2015
2016 while (buf0 > to->buf)
2017 *--buf0=0;
2018
2019 return error;
2020 }
2021
decimal_intg(const decimal_t * from)2022 int decimal_intg(const decimal_t *from)
2023 {
2024 int res;
2025 remove_leading_zeroes(from, &res);
2026 return res;
2027 }
2028
decimal_add(const decimal_t * from1,const decimal_t * from2,decimal_t * to)2029 int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2030 {
2031 if (likely(from1->sign == from2->sign))
2032 return do_add(from1, from2, to);
2033 return do_sub(from1, from2, to);
2034 }
2035
decimal_sub(const decimal_t * from1,const decimal_t * from2,decimal_t * to)2036 int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2037 {
2038 if (likely(from1->sign == from2->sign))
2039 return do_sub(from1, from2, to);
2040 return do_add(from1, from2, to);
2041 }
2042
decimal_cmp(const decimal_t * from1,const decimal_t * from2)2043 int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
2044 {
2045 if (likely(from1->sign == from2->sign))
2046 return do_sub(from1, from2, 0);
2047 return from1->sign > from2->sign ? -1 : 1;
2048 }
2049
decimal_is_zero(const decimal_t * from)2050 int decimal_is_zero(const decimal_t *from)
2051 {
2052 dec1 *buf1=from->buf,
2053 *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2054 while (buf1 < end)
2055 if (*buf1++)
2056 return 0;
2057 return 1;
2058 }
2059
2060 /*
2061 multiply two decimals
2062
2063 SYNOPSIS
2064 decimal_mul()
2065 from1, from2 - factors
2066 to - product
2067
2068 RETURN VALUE
2069 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
2070
2071 NOTES
2072 in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
2073 and 63-digit number will take only 7 dec1 words (basically a 7-digit
2074 "base 999999999" number). Thus there's no need in fast multiplication
2075 algorithms, 7-digit numbers can be multiplied with a naive O(n*n)
2076 method.
2077
2078 XXX if this library is to be used with huge numbers of thousands of
2079 digits, fast multiplication must be implemented.
2080 */
decimal_mul(const decimal_t * from1,const decimal_t * from2,decimal_t * to)2081 int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2082 {
2083 int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
2084 frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
2085 intg0=ROUND_UP(from1->intg+from2->intg),
2086 frac0=frac1+frac2, error, i, j, d_to_move;
2087 dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2088 *start2, *stop2, *stop1, *start0, carry;
2089
2090 sanity(to);
2091
2092 i=intg0; /* save 'ideal' values */
2093 j=frac0;
2094 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); /* bound size */
2095 to->sign=from1->sign != from2->sign;
2096 to->frac=from1->frac+from2->frac; /* store size in digits */
2097 to->intg=intg0*DIG_PER_DEC1;
2098
2099 if (unlikely(error))
2100 {
2101 set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
2102 set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
2103 if (unlikely(i > intg0)) /* bounded integer-part */
2104 {
2105 i-=intg0;
2106 j=i >> 1;
2107 intg1-= j;
2108 intg2-=i-j;
2109 frac1=frac2=0; /* frac0 is already 0 here */
2110 }
2111 else /* bounded fract part */
2112 {
2113 j-=frac0;
2114 i=j >> 1;
2115 if (frac1 <= frac2)
2116 {
2117 frac1-= i;
2118 frac2-=j-i;
2119 }
2120 else
2121 {
2122 frac2-= i;
2123 frac1-=j-i;
2124 }
2125 }
2126 }
2127 start0=to->buf+intg0+frac0-1;
2128 start2=buf2+frac2-1;
2129 stop1=buf1-intg1;
2130 stop2=buf2-intg2;
2131
2132 bzero(to->buf, (intg0+frac0)*sizeof(dec1));
2133
2134 for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
2135 {
2136 carry=0;
2137 for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
2138 {
2139 dec1 hi, lo;
2140 dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2141 hi=(dec1)(p/DIG_BASE);
2142 lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2143 ADD2(*buf0, *buf0, lo, carry);
2144 carry+=hi;
2145 }
2146 if (carry)
2147 {
2148 if (buf0 < to->buf)
2149 return E_DEC_OVERFLOW;
2150 ADD2(*buf0, *buf0, 0, carry);
2151 }
2152 for (buf0--; carry; buf0--)
2153 {
2154 if (buf0 < to->buf)
2155 return E_DEC_OVERFLOW;
2156 ADD(*buf0, *buf0, 0, carry);
2157 }
2158 }
2159
2160 /* Remove trailing zero words in frac part */
2161 frac0= ROUND_UP(to->frac);
2162
2163 if (frac0 > 0 && to->buf[intg0 + frac0 - 1] == 0)
2164 {
2165 do
2166 {
2167 frac0--;
2168 } while (frac0 > 0 && to->buf[intg0 + frac0 - 1] == 0);
2169 to->frac= DIG_PER_DEC1 * frac0;
2170 }
2171
2172 /* Remove heading zero words in intg part */
2173 buf1= to->buf;
2174 d_to_move= intg0 + frac0;
2175 while (!*buf1 && (to->intg > DIG_PER_DEC1))
2176 {
2177 buf1++;
2178 to->intg-= DIG_PER_DEC1;
2179 d_to_move--;
2180 }
2181 if (to->buf < buf1)
2182 {
2183 dec1 *cur_d= to->buf;
2184 for (; d_to_move--; cur_d++, buf1++)
2185 *cur_d= *buf1;
2186 }
2187
2188 /* Now we have to check for -0.000 case */
2189 if (to->sign && to->frac == 0 && to->buf[0] == 0)
2190 {
2191 DBUG_ASSERT(to->intg <= DIG_PER_DEC1);
2192 /* We got decimal zero */
2193 decimal_make_zero(to);
2194 }
2195 return error;
2196 }
2197
2198 /*
2199 naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2200 it's ok for short numbers
2201 also we're using alloca() to allocate a temporary buffer
2202
2203 XXX if this library is to be used with huge numbers of thousands of
2204 digits, fast division must be implemented and alloca should be
2205 changed to malloc (or at least fallback to malloc if alloca() fails)
2206 but then, decimal_mul() should be rewritten too :(
2207 */
do_div_mod(const decimal_t * from1,const decimal_t * from2,decimal_t * to,decimal_t * mod,int scale_incr)2208 static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2209 decimal_t *to, decimal_t *mod, int scale_incr)
2210 {
2211 int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2212 frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2213 UNINIT_VAR(error), i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2214 dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2215 *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2216 dec2 norm_factor, x, guess, y;
2217
2218 if (mod)
2219 to=mod;
2220
2221 sanity(to);
2222
2223 /* removing all the leading zeroes */
2224 i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
2225 while (prec2 > 0 && *buf2 == 0)
2226 {
2227 prec2-= i;
2228 i= DIG_PER_DEC1;
2229 buf2++;
2230 }
2231 if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
2232 return E_DEC_DIV_ZERO;
2233 for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
2234 DBUG_ASSERT(prec2 > 0);
2235
2236 i=((prec1-1) % DIG_PER_DEC1)+1;
2237 while (prec1 > 0 && *buf1 == 0)
2238 {
2239 prec1-=i;
2240 i=DIG_PER_DEC1;
2241 buf1++;
2242 }
2243 if (prec1 <= 0)
2244 { /* short-circuit everything: from1 == 0 */
2245 decimal_make_zero(to);
2246 return E_DEC_OK;
2247 }
2248 for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2249 DBUG_ASSERT(prec1 > 0);
2250
2251 /* let's fix scale_incr, taking into account frac1,frac2 increase */
2252 if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
2253 scale_incr=0;
2254
2255 dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
2256 if (dintg < 0)
2257 {
2258 dintg/=DIG_PER_DEC1;
2259 intg0=0;
2260 }
2261 else
2262 intg0=ROUND_UP(dintg);
2263 if (mod)
2264 {
2265 /* we're calculating N1 % N2.
2266 The result will have
2267 frac=MY_MAX(frac1, frac2), as for subtraction
2268 intg=intg2
2269 */
2270 to->sign=from1->sign;
2271 to->frac=MY_MAX(from1->frac, from2->frac);
2272 frac0=0;
2273 }
2274 else
2275 {
2276 /*
2277 we're calculating N1/N2. N1 is in the buf1, has prec1 digits
2278 N2 is in the buf2, has prec2 digits. Scales are frac1 and
2279 frac2 accordingly.
2280 Thus, the result will have
2281 frac = ROUND_UP(frac1+frac2+scale_incr)
2282 and
2283 intg = (prec1-frac1) - (prec2-frac2) + 1
2284 prec = intg+frac
2285 */
2286 frac0=ROUND_UP(frac1+frac2+scale_incr);
2287 FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2288 to->sign=from1->sign != from2->sign;
2289 to->intg=intg0*DIG_PER_DEC1;
2290 to->frac=frac0*DIG_PER_DEC1;
2291 }
2292 buf0=to->buf;
2293 stop0=buf0+intg0+frac0;
2294 if (likely(div_mod))
2295 while (dintg++ < 0 && buf0 < &to->buf[to->len])
2296 {
2297 *buf0++=0;
2298 }
2299
2300 len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2301 set_if_bigger(len1, 3);
2302 if (!(tmp1=(dec1 *)my_alloca(len1*sizeof(dec1))))
2303 return E_DEC_OOM;
2304 memcpy(tmp1, buf1, i*sizeof(dec1));
2305 bzero(tmp1+i, (len1-i)*sizeof(dec1));
2306
2307 start1=tmp1;
2308 stop1=start1+len1;
2309 start2=buf2;
2310 stop2=buf2+ROUND_UP(prec2)-1;
2311
2312 /* removing end zeroes */
2313 while (*stop2 == 0 && stop2 >= start2)
2314 stop2--;
2315 len2= (int) (stop2++ - start2);
2316
2317 /*
2318 calculating norm2 (normalized *start2) - we need *start2 to be large
2319 (at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to
2320 normalize input numbers (as we don't make a copy of the divisor).
2321 Thus we normalize first dec1 of buf2 only, and we'll normalize *start1
2322 on the fly for the purpose of guesstimation only.
2323 It's also faster, as we're saving on normalization of buf2
2324 */
2325 norm_factor=DIG_BASE/(*start2+1);
2326 norm2=(dec1)(norm_factor*start2[0]);
2327 if (unlikely(len2>0))
2328 norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
2329
2330 if (*start1 < *start2)
2331 dcarry=*start1++;
2332 else
2333 dcarry=0;
2334
2335 /* main loop */
2336 for (; buf0 < stop0; buf0++)
2337 {
2338 /* short-circuit, if possible */
2339 if (unlikely(dcarry == 0 && *start1 < *start2))
2340 guess=0;
2341 else
2342 {
2343 /* D3: make a guess */
2344 x=start1[0]+((dec2)dcarry)*DIG_BASE;
2345 y=start1[1];
2346 guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
2347 if (unlikely(guess >= DIG_BASE))
2348 guess=DIG_BASE-1;
2349 if (unlikely(len2>0))
2350 {
2351 /* hmm, this is a suspicious trick - I removed normalization here */
2352 if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
2353 guess--;
2354 if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
2355 guess--;
2356 DBUG_ASSERT(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
2357 }
2358
2359 /* D4: multiply and subtract */
2360 buf2=stop2;
2361 buf1=start1+len2;
2362 DBUG_ASSERT(buf1 < stop1);
2363 for (carry=0; buf2 > start2; buf1--)
2364 {
2365 dec1 hi, lo;
2366 x=guess * (*--buf2);
2367 hi=(dec1)(x/DIG_BASE);
2368 lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2369 SUB2(*buf1, *buf1, lo, carry);
2370 carry+=hi;
2371 }
2372 carry= dcarry < carry;
2373
2374 /* D5: check the remainder */
2375 if (unlikely(carry))
2376 {
2377 /* D6: correct the guess */
2378 guess--;
2379 buf2=stop2;
2380 buf1=start1+len2;
2381 for (carry=0; buf2 > start2; buf1--)
2382 {
2383 ADD(*buf1, *buf1, *--buf2, carry);
2384 }
2385 }
2386 }
2387 if (likely(div_mod))
2388 {
2389 DBUG_ASSERT(buf0 < to->buf + to->len);
2390 *buf0=(dec1)guess;
2391 }
2392 #ifdef WORKAROUND_GCC_4_3_2_BUG
2393 dcarry= *(volatile dec1 *)start1;
2394 #else
2395 dcarry= *start1;
2396 #endif
2397 start1++;
2398 }
2399 if (mod)
2400 {
2401 /*
2402 now the result is in tmp1, it has
2403 intg=prec1-frac1
2404 frac=MY_MAX(frac1, frac2)=to->frac
2405 */
2406 if (dcarry)
2407 *--start1=dcarry;
2408 buf0=to->buf;
2409 intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2410 frac0=ROUND_UP(to->frac);
2411 error=E_DEC_OK;
2412 if (unlikely(frac0==0 && intg0==0))
2413 {
2414 decimal_make_zero(to);
2415 goto done;
2416 }
2417 if (intg0<=0)
2418 {
2419 if (unlikely(-intg0 >= to->len))
2420 {
2421 decimal_make_zero(to);
2422 error=E_DEC_TRUNCATED;
2423 goto done;
2424 }
2425 stop1= start1 + frac0 + intg0;
2426 frac0+=intg0;
2427 to->intg=0;
2428 while (intg0++ < 0)
2429 *buf0++=0;
2430 }
2431 else
2432 {
2433 if (unlikely(intg0 > to->len))
2434 {
2435 frac0=0;
2436 intg0=to->len;
2437 error=E_DEC_OVERFLOW;
2438 goto done;
2439 }
2440 DBUG_ASSERT(intg0 <= ROUND_UP(from2->intg));
2441 stop1=start1+frac0+intg0;
2442 to->intg=MY_MIN(intg0*DIG_PER_DEC1, from2->intg);
2443 }
2444 if (unlikely(intg0+frac0 > to->len))
2445 {
2446 stop1-=frac0+intg0-to->len;
2447 frac0=to->len-intg0;
2448 to->frac=frac0*DIG_PER_DEC1;
2449 error=E_DEC_TRUNCATED;
2450 }
2451 DBUG_ASSERT(buf0 + (stop1 - start1) <= to->buf + to->len);
2452 while (start1 < stop1)
2453 *buf0++=*start1++;
2454 }
2455 done:
2456 my_afree(tmp1);
2457 return error;
2458 }
2459
2460 /*
2461 division of two decimals
2462
2463 SYNOPSIS
2464 decimal_div()
2465 from1 - dividend
2466 from2 - divisor
2467 to - quotient
2468
2469 RETURN VALUE
2470 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2471
2472 NOTES
2473 see do_div_mod()
2474 */
2475
2476 int
decimal_div(const decimal_t * from1,const decimal_t * from2,decimal_t * to,int scale_incr)2477 decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to,
2478 int scale_incr)
2479 {
2480 return do_div_mod(from1, from2, to, 0, scale_incr);
2481 }
2482
2483 /*
2484 modulus
2485
2486 SYNOPSIS
2487 decimal_mod()
2488 from1 - dividend
2489 from2 - divisor
2490 to - modulus
2491
2492 RETURN VALUE
2493 E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2494
2495 NOTES
2496 see do_div_mod()
2497
2498 DESCRIPTION
2499 the modulus R in R = M mod N
2500
2501 is defined as
2502
2503 0 <= |R| < |M|
2504 sign R == sign M
2505 R = M - k*N, where k is integer
2506
2507 thus, there's no requirement for M or N to be integers
2508 */
2509
decimal_mod(const decimal_t * from1,const decimal_t * from2,decimal_t * to)2510 int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2511 {
2512 return do_div_mod(from1, from2, 0, to, 0);
2513 }
2514
2515 #ifdef MAIN
2516
2517 int full= 0;
2518 decimal_t a, b, c;
2519 char buf1[100], buf2[100], buf3[100];
2520
dump_decimal(decimal_t * d)2521 void dump_decimal(decimal_t *d)
2522 {
2523 int i;
2524 printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2525 for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2526 printf("%09d, ", d->buf[i]);
2527 printf("%09d} */ ", d->buf[i]);
2528 }
2529
2530
check_result_code(int actual,int want)2531 void check_result_code(int actual, int want)
2532 {
2533 if (actual != want)
2534 {
2535 printf("\n^^^^^^^^^^^^^ must return %d\n", want);
2536 exit(1);
2537 }
2538 }
2539
2540
print_decimal(decimal_t * d,const char * orig,int actual,int want)2541 void print_decimal(decimal_t *d, const char *orig, int actual, int want)
2542 {
2543 char s[100];
2544 int slen=sizeof(s);
2545
2546 if (full) dump_decimal(d);
2547 decimal2string(d, s, &slen, 0, 0, 0);
2548 printf("'%s'", s);
2549 check_result_code(actual, want);
2550 if (orig && strcmp(orig, s))
2551 {
2552 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2553 exit(1);
2554 }
2555 }
2556
test_d2s()2557 void test_d2s()
2558 {
2559 char s[100];
2560 int slen, res;
2561
2562 /***********************************/
2563 printf("==== decimal2string ====\n");
2564 a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
2565 slen=sizeof(s);
2566 res=decimal2string(&a, s, &slen, 0, 0, 0);
2567 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2568
2569 a.buf[1]=987000000; a.frac=3;
2570 slen=sizeof(s);
2571 res=decimal2string(&a, s, &slen, 0, 0, 0);
2572 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2573
2574 a.sign=1;
2575 slen=sizeof(s);
2576 res=decimal2string(&a, s, &slen, 0, 0, 0);
2577 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2578
2579 slen=8;
2580 res=decimal2string(&a, s, &slen, 0, 0, 0);
2581 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2582
2583 slen=5;
2584 res=decimal2string(&a, s, &slen, 0, 0, 0);
2585 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2586
2587 a.buf[0]=987000000; a.frac=3; a.intg=0;
2588 slen=sizeof(s);
2589 res=decimal2string(&a, s, &slen, 0, 0, 0);
2590 dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2591 }
2592
test_s2d(const char * s,const char * orig,int ex)2593 void test_s2d(const char *s, const char *orig, int ex)
2594 {
2595 char s1[100], *end;
2596 int res;
2597 sprintf(s1, "'%s'", s);
2598 end= strend(s);
2599 printf("len=%2d %-30s => res=%d ", a.len, s1,
2600 (res= string2decimal(s, &a, &end)));
2601 print_decimal(&a, orig, res, ex);
2602 printf("\n");
2603 }
2604
test_d2f(const char * s,int ex)2605 void test_d2f(const char *s, int ex)
2606 {
2607 char s1[100], *end;
2608 double x;
2609 int res;
2610
2611 sprintf(s1, "'%s'", s);
2612 end= strend(s);
2613 string2decimal(s, &a, &end);
2614 res=decimal2double(&a, &x);
2615 if (full) dump_decimal(&a);
2616 printf("%-40s => res=%d %.*g\n", s1, res, a.intg+a.frac, x);
2617 check_result_code(res, ex);
2618 }
2619
test_d2b2d(const char * str,int p,int s,const char * orig,int ex)2620 void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
2621 {
2622 char s1[100], buf[100], *end;
2623 int res, i, size=decimal_bin_size(p, s);
2624
2625 sprintf(s1, "'%s'", str);
2626 end= strend(str);
2627 string2decimal(str, &a, &end);
2628 res=decimal2bin(&a, buf, p, s);
2629 printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
2630 if (full)
2631 {
2632 printf("0x");
2633 for (i=0; i < size; i++)
2634 printf("%02x", ((uchar *)buf)[i]);
2635 }
2636 res=bin2decimal(buf, &a, p, s);
2637 printf(" => res=%d ", res);
2638 print_decimal(&a, orig, res, ex);
2639 printf("\n");
2640 }
2641
test_f2d(double from,int ex)2642 void test_f2d(double from, int ex)
2643 {
2644 int res;
2645
2646 res=double2decimal(from, &a);
2647 printf("%-40.*f => res=%d ", DBL_DIG-2, from, res);
2648 print_decimal(&a, 0, res, ex);
2649 printf("\n");
2650 }
2651
test_ull2d(ulonglong from,const char * orig,int ex)2652 void test_ull2d(ulonglong from, const char *orig, int ex)
2653 {
2654 char s[100];
2655 int res;
2656
2657 res=ulonglong2decimal(from, &a);
2658 longlong10_to_str(from,s,10);
2659 printf("%-40s => res=%d ", s, res);
2660 print_decimal(&a, orig, res, ex);
2661 printf("\n");
2662 }
2663
test_ll2d(longlong from,const char * orig,int ex)2664 void test_ll2d(longlong from, const char *orig, int ex)
2665 {
2666 char s[100];
2667 int res;
2668
2669 res=longlong2decimal(from, &a);
2670 longlong10_to_str(from,s,-10);
2671 printf("%-40s => res=%d ", s, res);
2672 print_decimal(&a, orig, res, ex);
2673 printf("\n");
2674 }
2675
test_d2ull(const char * s,const char * orig,int ex)2676 void test_d2ull(const char *s, const char *orig, int ex)
2677 {
2678 char s1[100], *end;
2679 ulonglong x;
2680 int res;
2681
2682 end= strend(s);
2683 string2decimal(s, &a, &end);
2684 res=decimal2ulonglong(&a, &x);
2685 if (full) dump_decimal(&a);
2686 longlong10_to_str(x,s1,10);
2687 printf("%-40s => res=%d %s\n", s, res, s1);
2688 check_result_code(res, ex);
2689 if (orig && strcmp(orig, s1))
2690 {
2691 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2692 exit(1);
2693 }
2694 }
2695
test_d2ll(const char * s,const char * orig,int ex)2696 void test_d2ll(const char *s, const char *orig, int ex)
2697 {
2698 char s1[100], *end;
2699 longlong x;
2700 int res;
2701
2702 end= strend(s);
2703 string2decimal(s, &a, &end);
2704 res=decimal2longlong(&a, &x);
2705 if (full) dump_decimal(&a);
2706 longlong10_to_str(x,s1,-10);
2707 printf("%-40s => res=%d %s\n", s, res, s1);
2708 check_result_code(res, ex);
2709 if (orig && strcmp(orig, s1))
2710 {
2711 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2712 exit(1);
2713 }
2714 }
2715
test_da(const char * s1,const char * s2,const char * orig,int ex)2716 void test_da(const char *s1, const char *s2, const char *orig, int ex)
2717 {
2718 char s[100], *end;
2719 int res;
2720 sprintf(s, "'%s' + '%s'", s1, s2);
2721 end= strend(s1);
2722 string2decimal(s1, &a, &end);
2723 end= strend(s2);
2724 string2decimal(s2, &b, &end);
2725 res=decimal_add(&a, &b, &c);
2726 printf("%-40s => res=%d ", s, res);
2727 print_decimal(&c, orig, res, ex);
2728 printf("\n");
2729 }
2730
test_ds(const char * s1,const char * s2,const char * orig,int ex)2731 void test_ds(const char *s1, const char *s2, const char *orig, int ex)
2732 {
2733 char s[100], *end;
2734 int res;
2735 sprintf(s, "'%s' - '%s'", s1, s2);
2736 end= strend(s1);
2737 string2decimal(s1, &a, &end);
2738 end= strend(s2);
2739 string2decimal(s2, &b, &end);
2740 res=decimal_sub(&a, &b, &c);
2741 printf("%-40s => res=%d ", s, res);
2742 print_decimal(&c, orig, res, ex);
2743 printf("\n");
2744 }
2745
test_dc(const char * s1,const char * s2,int orig)2746 void test_dc(const char *s1, const char *s2, int orig)
2747 {
2748 char s[100], *end;
2749 int res;
2750 sprintf(s, "'%s' <=> '%s'", s1, s2);
2751 end= strend(s1);
2752 string2decimal(s1, &a, &end);
2753 end= strend(s2);
2754 string2decimal(s2, &b, &end);
2755 res=decimal_cmp(&a, &b);
2756 printf("%-40s => res=%d\n", s, res);
2757 if (orig != res)
2758 {
2759 printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
2760 exit(1);
2761 }
2762 }
2763
test_dm(const char * s1,const char * s2,const char * orig,int ex)2764 void test_dm(const char *s1, const char *s2, const char *orig, int ex)
2765 {
2766 char s[100], *end;
2767 int res;
2768 sprintf(s, "'%s' * '%s'", s1, s2);
2769 end= strend(s1);
2770 string2decimal(s1, &a, &end);
2771 end= strend(s2);
2772 string2decimal(s2, &b, &end);
2773 res=decimal_mul(&a, &b, &c);
2774 printf("%-40s => res=%d ", s, res);
2775 print_decimal(&c, orig, res, ex);
2776 printf("\n");
2777 }
2778
test_dv(const char * s1,const char * s2,const char * orig,int ex)2779 void test_dv(const char *s1, const char *s2, const char *orig, int ex)
2780 {
2781 char s[100], *end;
2782 int res;
2783 sprintf(s, "'%s' / '%s'", s1, s2);
2784 end= strend(s1);
2785 string2decimal(s1, &a, &end);
2786 end= strend(s2);
2787 string2decimal(s2, &b, &end);
2788 res=decimal_div(&a, &b, &c, 5);
2789 printf("%-40s => res=%d ", s, res);
2790 check_result_code(res, ex);
2791 if (res == E_DEC_DIV_ZERO)
2792 printf("E_DEC_DIV_ZERO");
2793 else
2794 print_decimal(&c, orig, res, ex);
2795 printf("\n");
2796 }
2797
test_md(const char * s1,const char * s2,const char * orig,int ex)2798 void test_md(const char *s1, const char *s2, const char *orig, int ex)
2799 {
2800 char s[100], *end;
2801 int res;
2802 sprintf(s, "'%s' %% '%s'", s1, s2);
2803 end= strend(s1);
2804 string2decimal(s1, &a, &end);
2805 end= strend(s2);
2806 string2decimal(s2, &b, &end);
2807 res=decimal_mod(&a, &b, &c);
2808 printf("%-40s => res=%d ", s, res);
2809 check_result_code(res, ex);
2810 if (res == E_DEC_DIV_ZERO)
2811 printf("E_DEC_DIV_ZERO");
2812 else
2813 print_decimal(&c, orig, res, ex);
2814 printf("\n");
2815 }
2816
2817 const char *round_mode[]=
2818 {"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
2819
test_ro(const char * s1,int n,decimal_round_mode mode,const char * orig,int ex)2820 void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
2821 int ex)
2822 {
2823 char s[100], *end;
2824 int res;
2825 sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2826 end= strend(s1);
2827 string2decimal(s1, &a, &end);
2828 res=decimal_round(&a, &b, n, mode);
2829 printf("%-40s => res=%d ", s, res);
2830 print_decimal(&b, orig, res, ex);
2831 printf("\n");
2832 }
2833
2834
test_mx(int precision,int frac,const char * orig)2835 void test_mx(int precision, int frac, const char *orig)
2836 {
2837 char s[100];
2838 sprintf(s, "%d, %d", precision, frac);
2839 max_decimal(precision, frac, &a);
2840 printf("%-40s => ", s);
2841 print_decimal(&a, orig, 0, 0);
2842 printf("\n");
2843 }
2844
2845
test_pr(const char * s1,int prec,int dec,char filler,const char * orig,int ex)2846 void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
2847 int ex)
2848 {
2849 char s[100], *end;
2850 char s2[100];
2851 int slen= sizeof(s2);
2852 int res;
2853
2854 sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2855 s1, prec, dec, filler);
2856 end= strend(s1);
2857 string2decimal(s1, &a, &end);
2858 res= decimal2string(&a, s2, &slen, prec, dec, filler);
2859 printf("%-40s => res=%d '%s'", s, res, s2);
2860 check_result_code(res, ex);
2861 if (orig && strcmp(orig, s2))
2862 {
2863 printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2864 exit(1);
2865 }
2866 printf("\n");
2867 }
2868
2869
test_sh(const char * s1,int shift,const char * orig,int ex)2870 void test_sh(const char *s1, int shift, const char *orig, int ex)
2871 {
2872 char s[100], *end;
2873 int res;
2874 sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2875 end= strend(s1);
2876 string2decimal(s1, &a, &end);
2877 res= decimal_shift(&a, shift);
2878 printf("%-40s => res=%d ", s, res);
2879 print_decimal(&a, orig, res, ex);
2880 printf("\n");
2881 }
2882
2883
test_fr(const char * s1,const char * orig)2884 void test_fr(const char *s1, const char *orig)
2885 {
2886 char s[100], *end;
2887 sprintf(s, "'%s'", s1);
2888 printf("%-40s => ", s);
2889 end= strend(s1);
2890 string2decimal(s1, &a, &end);
2891 a.frac= decimal_actual_fraction(&a);
2892 print_decimal(&a, orig, 0, 0);
2893 printf("\n");
2894 }
2895
2896
main()2897 int main()
2898 {
2899 a.buf=(void*)buf1;
2900 a.len=sizeof(buf1)/sizeof(dec1);
2901 b.buf=(void*)buf2;
2902 b.len=sizeof(buf2)/sizeof(dec1);
2903 c.buf=(void*)buf3;
2904 c.len=sizeof(buf3)/sizeof(dec1);
2905
2906 if (full)
2907 test_d2s();
2908
2909 printf("==== string2decimal ====\n");
2910 test_s2d("12345", "12345", 0);
2911 test_s2d("12345.", "12345", 0);
2912 test_s2d("123.45", "123.45", 0);
2913 test_s2d("-123.45", "-123.45", 0);
2914 test_s2d(".00012345000098765", "0.00012345000098765", 0);
2915 test_s2d(".12345000098765", "0.12345000098765", 0);
2916 test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
2917 test_s2d("1234500009876.5", "1234500009876.5", 0);
2918 a.len=1;
2919 test_s2d("123450000098765", "98765", 2);
2920 test_s2d("123450.000098765", "123450", 1);
2921 a.len=sizeof(buf1)/sizeof(dec1);
2922 test_s2d("123E5", "12300000", 0);
2923 test_s2d("123E-2", "1.23", 0);
2924
2925 printf("==== decimal2double ====\n");
2926 test_d2f("12345", 0);
2927 test_d2f("123.45", 0);
2928 test_d2f("-123.45", 0);
2929 test_d2f("0.00012345000098765", 0);
2930 test_d2f("1234500009876.5", 0);
2931
2932 printf("==== double2decimal ====\n");
2933 test_f2d(12345, 0);
2934 test_f2d(1.0/3, 0);
2935 test_f2d(-123.45, 0);
2936 test_f2d(0.00012345000098765, 0);
2937 test_f2d(1234500009876.5, 0);
2938
2939 printf("==== ulonglong2decimal ====\n");
2940 test_ull2d(ULL(12345), "12345", 0);
2941 test_ull2d(ULL(0), "0", 0);
2942 test_ull2d(ULL(18446744073709551615), "18446744073709551615", 0);
2943
2944 printf("==== decimal2ulonglong ====\n");
2945 test_d2ull("12345", "12345", 0);
2946 test_d2ull("0", "0", 0);
2947 test_d2ull("18446744073709551615", "18446744073709551615", 0);
2948 test_d2ull("18446744073709551616", "18446744073", 2);
2949 test_d2ull("-1", "0", 2);
2950 test_d2ull("1.23", "1", 1);
2951 test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
2952
2953 printf("==== longlong2decimal ====\n");
2954 test_ll2d(LL(-12345), "-12345", 0);
2955 test_ll2d(LL(-1), "-1", 0);
2956 test_ll2d(LL(-9223372036854775807), "-9223372036854775807", 0);
2957 test_ll2d(ULL(9223372036854775808), "-9223372036854775808", 0);
2958
2959 printf("==== decimal2longlong ====\n");
2960 test_d2ll("18446744073709551615", "18446744073", 2);
2961 test_d2ll("-1", "-1", 0);
2962 test_d2ll("-1.23", "-1", 1);
2963 test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
2964 test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
2965 test_d2ll("9223372036854775808", "9223372036854775807", 2);
2966
2967 printf("==== do_add ====\n");
2968 test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
2969 test_da(".1" ,".45", "0.55", 0);
2970 test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
2971 test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
2972 test_da("99999999" ,"1", "100000000", 0);
2973 test_da("989999999" ,"1", "990000000", 0);
2974 test_da("999999999" ,"1", "1000000000", 0);
2975 test_da("12345" ,"123.45", "12468.45", 0);
2976 test_da("-12345" ,"-123.45", "-12468.45", 0);
2977 test_ds("-12345" ,"123.45", "-12468.45", 0);
2978 test_ds("12345" ,"-123.45", "12468.45", 0);
2979
2980 printf("==== do_sub ====\n");
2981 test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
2982 test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
2983 test_ds("9999900000000.5", ".555","9999899999999.945", 0);
2984 test_ds("1111.5551", "1111.555","0.0001", 0);
2985 test_ds(".555", ".555","0", 0);
2986 test_ds("10000000", "1","9999999", 0);
2987 test_ds("1000001000", ".1","1000000999.9", 0);
2988 test_ds("1000000000", ".1","999999999.9", 0);
2989 test_ds("12345", "123.45","12221.55", 0);
2990 test_ds("-12345", "-123.45","-12221.55", 0);
2991 test_da("-12345", "123.45","-12221.55", 0);
2992 test_da("12345", "-123.45","12221.55", 0);
2993 test_ds("123.45", "12345","-12221.55", 0);
2994 test_ds("-123.45", "-12345","12221.55", 0);
2995 test_da("123.45", "-12345","-12221.55", 0);
2996 test_da("-123.45", "12345","12221.55", 0);
2997 test_da("5", "-6.0","-1.0", 0);
2998
2999 printf("==== decimal_mul ====\n");
3000 test_dm("12", "10","120", 0);
3001 test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
3002 test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
3003 test_dm("123456", "987654321","121931851853376", 0);
3004 test_dm("123456", "9876543210","1219318518533760", 0);
3005 test_dm("123", "0.01","1.23", 0);
3006 test_dm("123", "0","0", 0);
3007
3008 printf("==== decimal_div ====\n");
3009 test_dv("120", "10","12.000000000", 0);
3010 test_dv("123", "0.01","12300.000000000", 0);
3011 test_dv("120", "100000000000.00000","0.000000001200000000", 0);
3012 test_dv("123", "0","", 4);
3013 test_dv("0", "0", "", 4);
3014 test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
3015 test_dv("121931851853376", "987654321","123456.000000000", 0);
3016 test_dv("0", "987","0", 0);
3017 test_dv("1", "3","0.333333333", 0);
3018 test_dv("1.000000000000", "3","0.333333333333333333", 0);
3019 test_dv("1", "1","1.000000000", 0);
3020 test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
3021 test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
3022 test_dv("10.000000000060", "2","5.000000000030000000", 0);
3023
3024 printf("==== decimal_mod ====\n");
3025 test_md("234","10","4", 0);
3026 test_md("234.567","10.555","2.357", 0);
3027 test_md("-234.567","10.555","-2.357", 0);
3028 test_md("234.567","-10.555","2.357", 0);
3029 c.buf[1]=0x3ABECA;
3030 test_md("99999999999999999999999999999999999999","3","0", 0);
3031 if (c.buf[1] != 0x3ABECA)
3032 {
3033 printf("%X - overflow\n", c.buf[1]);
3034 exit(1);
3035 }
3036
3037 printf("==== decimal2bin/bin2decimal ====\n");
3038 test_d2b2d("-10.55", 4, 2,"-10.55", 0);
3039 test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
3040 test_d2b2d("12345", 5, 0,"12345", 0);
3041 test_d2b2d("12345", 10, 3,"12345.000", 0);
3042 test_d2b2d("123.45", 10, 3,"123.450", 0);
3043 test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
3044 test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
3045 test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
3046 test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
3047 test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
3048 test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
3049 test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
3050 test_d2b2d("000000000.01", 7, 3,"0.010", 0);
3051 test_d2b2d("123.4", 10, 2, "123.40", 0);
3052
3053
3054 printf("==== decimal_cmp ====\n");
3055 test_dc("12","13",-1);
3056 test_dc("13","12",1);
3057 test_dc("-10","10",-1);
3058 test_dc("10","-10",1);
3059 test_dc("-12","-13",1);
3060 test_dc("0","12",-1);
3061 test_dc("-10","0",-1);
3062 test_dc("4","4",0);
3063
3064 printf("==== decimal_round ====\n");
3065 test_ro("5678.123451",-4,TRUNCATE,"0", 0);
3066 test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
3067 test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
3068 test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
3069 test_ro("5678.123451",0,TRUNCATE,"5678", 0);
3070 test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
3071 test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
3072 test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
3073 test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
3074 test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
3075 test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
3076 test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
3077 memset(buf2, 33, sizeof(buf2));
3078 test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
3079 test_ro("15.1",0,HALF_UP,"15", 0);
3080 test_ro("15.5",0,HALF_UP,"16", 0);
3081 test_ro("15.9",0,HALF_UP,"16", 0);
3082 test_ro("-15.1",0,HALF_UP,"-15", 0);
3083 test_ro("-15.5",0,HALF_UP,"-16", 0);
3084 test_ro("-15.9",0,HALF_UP,"-16", 0);
3085 test_ro("15.1",1,HALF_UP,"15.1", 0);
3086 test_ro("-15.1",1,HALF_UP,"-15.1", 0);
3087 test_ro("15.17",1,HALF_UP,"15.2", 0);
3088 test_ro("15.4",-1,HALF_UP,"20", 0);
3089 test_ro("-15.4",-1,HALF_UP,"-20", 0);
3090 test_ro("5.4",-1,HALF_UP,"10", 0);
3091 test_ro(".999", 0, HALF_UP, "1", 0);
3092 memset(buf2, 33, sizeof(buf2));
3093 test_ro("999999999", -9, HALF_UP, "1000000000", 0);
3094 test_ro("15.1",0,HALF_EVEN,"15", 0);
3095 test_ro("15.5",0,HALF_EVEN,"16", 0);
3096 test_ro("14.5",0,HALF_EVEN,"14", 0);
3097 test_ro("15.9",0,HALF_EVEN,"16", 0);
3098 test_ro("15.1",0,CEILING,"16", 0);
3099 test_ro("-15.1",0,CEILING,"-15", 0);
3100 test_ro("15.1",0,FLOOR,"15", 0);
3101 test_ro("-15.1",0,FLOOR,"-16", 0);
3102 test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
3103 test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
3104
3105 b.buf[0]=DIG_BASE+1;
3106 b.buf++;
3107 test_ro(".3", 0, HALF_UP, "0", 0);
3108 b.buf--;
3109 if (b.buf[0] != DIG_BASE+1)
3110 {
3111 printf("%d - underflow\n", b.buf[0]);
3112 exit(1);
3113 }
3114
3115 printf("==== max_decimal ====\n");
3116 test_mx(1,1,"0.9");
3117 test_mx(1,0,"9");
3118 test_mx(2,1,"9.9");
3119 test_mx(4,2,"99.99");
3120 test_mx(6,3,"999.999");
3121 test_mx(8,4,"9999.9999");
3122 test_mx(10,5,"99999.99999");
3123 test_mx(12,6,"999999.999999");
3124 test_mx(14,7,"9999999.9999999");
3125 test_mx(16,8,"99999999.99999999");
3126 test_mx(18,9,"999999999.999999999");
3127 test_mx(20,10,"9999999999.9999999999");
3128 test_mx(20,20,"0.99999999999999999999");
3129 test_mx(20,0,"99999999999999999999");
3130 test_mx(40,20,"99999999999999999999.99999999999999999999");
3131
3132 printf("==== decimal2string ====\n");
3133 test_pr("123.123", 0, 0, 0, "123.123", 0);
3134 test_pr("123.123", 7, 3, '0', "123.123", 0);
3135 test_pr("123.123", 9, 3, '0', "00123.123", 0);
3136 test_pr("123.123", 9, 4, '0', "0123.1230", 0);
3137 test_pr("123.123", 9, 5, '0', "123.12300", 0);
3138 test_pr("123.123", 9, 2, '0', "000123.12", 1);
3139 test_pr("123.123", 9, 6, '0', "23.123000", 2);
3140
3141 printf("==== decimal_shift ====\n");
3142 test_sh("123.123", 1, "1231.23", 0);
3143 test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
3144 test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
3145 test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
3146 test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
3147 test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
3148 test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
3149 test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
3150 test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
3151 test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3152 test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3153 test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3154 test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3155 test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3156 test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3157 test_sh("123", 1, "1230", 0);
3158 test_sh("123", 10, "1230000000000", 0);
3159 test_sh(".123", 1, "1.23", 0);
3160 test_sh(".123", 10, "1230000000", 0);
3161 test_sh(".123", 14, "12300000000000", 0);
3162 test_sh("000.000", 1000, "0", 0);
3163 test_sh("000.", 1000, "0", 0);
3164 test_sh(".000", 1000, "0", 0);
3165 test_sh("1", 1000, "1", 2);
3166 test_sh("123.123", -1, "12.3123", 0);
3167 test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
3168 test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
3169 test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
3170 test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
3171 test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
3172 test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
3173 test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
3174 test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
3175 test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
3176 test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
3177 test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
3178 a.len= 2;
3179 test_sh("123.123", -2, "1.23123", 0);
3180 test_sh("123.123", -3, "0.123123", 0);
3181 test_sh("123.123", -6, "0.000123123", 0);
3182 test_sh("123.123", -7, "0.0000123123", 0);
3183 test_sh("123.123", -15, "0.000000000000123123", 0);
3184 test_sh("123.123", -16, "0.000000000000012312", 1);
3185 test_sh("123.123", -17, "0.000000000000001231", 1);
3186 test_sh("123.123", -18, "0.000000000000000123", 1);
3187 test_sh("123.123", -19, "0.000000000000000012", 1);
3188 test_sh("123.123", -20, "0.000000000000000001", 1);
3189 test_sh("123.123", -21, "0", 1);
3190 test_sh(".000000000123", -1, "0.0000000000123", 0);
3191 test_sh(".000000000123", -6, "0.000000000000000123", 0);
3192 test_sh(".000000000123", -7, "0.000000000000000012", 1);
3193 test_sh(".000000000123", -8, "0.000000000000000001", 1);
3194 test_sh(".000000000123", -9, "0", 1);
3195 test_sh(".000000000123", 1, "0.00000000123", 0);
3196 test_sh(".000000000123", 8, "0.0123", 0);
3197 test_sh(".000000000123", 9, "0.123", 0);
3198 test_sh(".000000000123", 10, "1.23", 0);
3199 test_sh(".000000000123", 17, "12300000", 0);
3200 test_sh(".000000000123", 18, "123000000", 0);
3201 test_sh(".000000000123", 19, "1230000000", 0);
3202 test_sh(".000000000123", 20, "12300000000", 0);
3203 test_sh(".000000000123", 21, "123000000000", 0);
3204 test_sh(".000000000123", 22, "1230000000000", 0);
3205 test_sh(".000000000123", 23, "12300000000000", 0);
3206 test_sh(".000000000123", 24, "123000000000000", 0);
3207 test_sh(".000000000123", 25, "1230000000000000", 0);
3208 test_sh(".000000000123", 26, "12300000000000000", 0);
3209 test_sh(".000000000123", 27, "123000000000000000", 0);
3210 test_sh(".000000000123", 28, "0.000000000123", 2);
3211 test_sh("123456789.987654321", -1, "12345678.998765432", 1);
3212 test_sh("123456789.987654321", -2, "1234567.899876543", 1);
3213 test_sh("123456789.987654321", -8, "1.234567900", 1);
3214 test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
3215 test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
3216 test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
3217 test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
3218 test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
3219 test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
3220 test_sh("123456789.987654321", -27, "0", 1);
3221 test_sh("123456789.987654321", 1, "1234567900", 1);
3222 test_sh("123456789.987654321", 2, "12345678999", 1);
3223 test_sh("123456789.987654321", 4, "1234567899877", 1);
3224 test_sh("123456789.987654321", 8, "12345678998765432", 1);
3225 test_sh("123456789.987654321", 9, "123456789987654321", 0);
3226 test_sh("123456789.987654321", 10, "123456789.987654321", 2);
3227 test_sh("123456789.987654321", 0, "123456789.987654321", 0);
3228 a.len= sizeof(buf1)/sizeof(dec1);
3229
3230 printf("==== decimal_actual_fraction ====\n");
3231 test_fr("1.123456789000000000", "1.123456789");
3232 test_fr("1.12345678000000000", "1.12345678");
3233 test_fr("1.1234567000000000", "1.1234567");
3234 test_fr("1.123456000000000", "1.123456");
3235 test_fr("1.12345000000000", "1.12345");
3236 test_fr("1.1234000000000", "1.1234");
3237 test_fr("1.123000000000", "1.123");
3238 test_fr("1.12000000000", "1.12");
3239 test_fr("1.1000000000", "1.1");
3240 test_fr("1.000000000", "1");
3241 test_fr("1.0", "1");
3242 test_fr("10000000000000000000.0", "10000000000000000000");
3243
3244 return 0;
3245 }
3246 #endif
3247