1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19
=======================================================================
20
NOTE: this library implements SQL standard "exact numeric" type
21
and is not at all generic, but rather intentinally crippled to
22
follow the standard :)
23
=======================================================================
25
(SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
27
4.4.2 Characteristics of numbers, page 27:
29
An exact numeric type has a precision P and a scale S. P is a positive
30
integer that determines the number of significant digits in a
31
particular radix R, where R is either 2 or 10. S is a non-negative
32
integer. Every value of an exact numeric type of scale S is of the
33
form n*10^{-S}, where n is an integer such that ďż˝-R^P <= n <= R^P.
37
If an assignment of some number would result in a loss of its most
38
significant digit, an exception condition is raised. If least
39
significant digits are lost, implementation-defined rounding or
40
truncating occurs, with no exception condition being raised.
44
Whenever an exact or approximate numeric value is assigned to an exact
45
numeric value site, an approximation of its value that preserves
46
leading significant digits after rounding or truncating is represented
47
in the declared type of the target. The value is converted to have the
48
precision and scale of the target. The choice of whether to truncate
49
or round is implementation-defined.
53
All numeric values between the smallest and the largest value,
54
inclusive, in a given exact numeric type have an approximation
55
obtained by rounding or truncation for that type; it is
56
implementation-defined which other numeric values have such
59
5.3 <literal>, page 143
61
<exact numeric literal> ::=
62
<unsigned integer> [ <period> [ <unsigned integer> ] ]
63
| <period> <unsigned integer>
65
6.1 <data type>, page 165:
67
19) The <scale> of an <exact numeric type> shall not be greater than
68
the <precision> of the <exact numeric type>.
70
20) For the <exact numeric type>s DECIMAL and NUMERIC:
72
a) The maximum value of <precision> is implementation-defined.
73
<precision> shall not be greater than this value.
74
b) The maximum value of <scale> is implementation-defined. <scale>
75
shall not be greater than this maximum value.
77
21) NUMERIC specifies the data type exact numeric, with the decimal
78
precision and scale specified by the <precision> and <scale>.
80
22) DECIMAL specifies the data type exact numeric, with the decimal
81
scale specified by the <scale> and the implementation-defined
82
decimal precision equal to or greater than the value of the
83
specified <precision>.
85
6.26 <numeric value expression>, page 241:
87
1) If the declared type of both operands of a dyadic arithmetic
88
operator is exact numeric, then the declared type of the result is
89
an implementation-defined exact numeric type, with precision and
90
scale determined as follows:
92
a) Let S1 and S2 be the scale of the first and second operands
94
b) The precision of the result of addition and subtraction is
95
implementation-defined, and the scale is the maximum of S1 and S2.
96
c) The precision of the result of multiplication is
97
implementation-defined, and the scale is S1 + S2.
98
d) The precision and scale of the result of division are
99
implementation-defined.
102
#include <my_global.h>
104
#include <myisampack.h>
105
#include <my_sys.h> /* for my_alloca */
106
#include <m_string.h>
110
Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
111
So one variable of type decimal_digit_t is limited:
113
0 < decimal_digit <= DIG_MAX < DIG_BASE
115
in the struct st_decimal_t:
117
intg is the number of *decimal* digits (NOT number of decimal_digit_t's !)
119
frac - number of decimal digits after the point
120
buf is an array of decimal_digit_t's
121
len is the length of buf (length of allocated space) in decimal_digit_t's,
124
typedef decimal_digit_t dec1;
125
typedef longlong dec2;
127
#define DIG_PER_DEC1 9
128
#define DIG_MASK 100000000
129
#define DIG_BASE 1000000000
130
#define DIG_MAX (DIG_BASE-1)
131
#define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE)
132
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
133
static const dec1 powers10[DIG_PER_DEC1+1]={
134
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
135
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
136
static const dec1 frac_max[DIG_PER_DEC1-1]={
137
900000000, 990000000, 999000000,
138
999900000, 999990000, 999999000,
139
999999900, 999999990 };
142
#define sanity(d) DBUG_ASSERT((d)->len > 0)
144
#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
145
(d)->buf[(d)->len-1] | 1))
148
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
151
if (unlikely(intg1+frac1 > (len))) \
153
if (unlikely(intg1 > (len))) \
157
error=E_DEC_OVERFLOW; \
162
error=E_DEC_TRUNCATED; \
169
#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
172
dec1 a=(from1)+(from2)+(carry); \
173
DBUG_ASSERT((carry) <= 1); \
174
if (((carry)= a >= DIG_BASE)) /* no division here! */ \
179
#define ADD2(to, from1, from2, carry) \
182
dec2 a=((dec2)(from1))+(from2)+(carry); \
183
if (((carry)= a >= DIG_BASE)) \
185
if (unlikely(a >= DIG_BASE)) \
193
#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
196
dec1 a=(from1)-(from2)-(carry); \
197
if (((carry)= a < 0)) \
202
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
205
dec1 a=(from1)-(from2)-(carry); \
206
if (((carry)= a < 0)) \
208
if (unlikely(a < 0)) \
217
Get maximum value for given precision and scale
221
precision/scale - see decimal_bin_size() below
222
to - decimal where where the result will be stored
223
to->buf and to->len must be set.
226
void max_decimal(int precision, int frac, decimal_t *to)
230
DBUG_ASSERT(precision && precision >= frac);
233
if ((intpart= to->intg= (precision - frac)))
235
int firstdigits= intpart % DIG_PER_DEC1;
237
*buf++= powers10[firstdigits] - 1; /* get 9 99 999 ... */
238
for(intpart/= DIG_PER_DEC1; intpart; intpart--)
242
if ((to->frac= frac))
244
int lastdigits= frac % DIG_PER_DEC1;
245
for(frac/= DIG_PER_DEC1; frac; frac--)
248
*buf= frac_max[lastdigits - 1];
253
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
255
int intg= from->intg, i;
256
dec1 *buf0= from->buf;
257
i= ((intg - 1) % DIG_PER_DEC1) + 1;
258
while (intg > 0 && *buf0 == 0)
266
for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ;
267
DBUG_ASSERT(intg > 0);
277
Count actual length of fraction part (without ending zeroes)
280
decimal_actual_fraction()
281
from number for processing
284
int decimal_actual_fraction(decimal_t *from)
286
int frac= from->frac, i;
287
dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
292
i= ((frac - 1) % DIG_PER_DEC1 + 1);
293
while (frac > 0 && *buf0 == 0)
301
for (i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1); *buf0 % powers10[i++] == 0; frac--) {};
308
Convert decimal to its printable string representation
312
from - value to convert
313
to - points to buffer where string representation
315
*to_len - in: size of to buffer
316
out: length of the actually written string
317
fixed_precision - 0 if representation can be variable length and
318
fixed_decimals will not be checked in this case.
319
Put number as with fixed point position with this
320
number of digits (sign counted and decimal point is
322
fixed_decimals - number digits after point.
323
filler - character to fill gaps in case of fixed_precision > 0
326
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
329
int decimal2string(decimal_t *from, char *to, int *to_len,
330
int fixed_precision, int fixed_decimals,
333
int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
334
/* number digits before decimal point */
335
int fixed_intg= (fixed_precision ?
336
(fixed_precision - fixed_decimals) : 0);
339
dec1 *buf, *buf0=from->buf, tmp;
341
DBUG_ASSERT(*to_len >= 2+from->sign);
343
/* removing leading zeroes */
344
buf0= remove_leading_zeroes(from, &intg);
345
if (unlikely(intg+frac==0))
352
if (!(intg_len= fixed_precision ? fixed_intg : intg))
354
frac_len= fixed_precision ? fixed_decimals : frac;
355
len= from->sign + intg_len + test(frac) + frac_len;
358
if (frac > fixed_decimals)
360
error= E_DEC_TRUNCATED;
361
frac= fixed_decimals;
363
if (intg > fixed_intg)
365
error= E_DEC_OVERFLOW;
369
else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
372
error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
373
if (frac && j >= frac + 1) j--;
381
len= from->sign + intg_len + test(frac) + frac_len;
391
char *s1= s + intg_len;
392
fill= frac_len - frac;
393
buf=buf0+ROUND_UP(intg);
395
for (; frac>0; frac-=DIG_PER_DEC1)
398
for (i=min(frac, DIG_PER_DEC1); i; i--)
410
fill= intg_len - intg;
412
fill--; /* symbol 0 before digital point */
418
for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
421
for (i=min(intg, DIG_PER_DEC1); i; i--)
424
*--s='0'+(uchar)(x-y*10);
436
Return bounds of decimal digits in the number
440
from - decimal number for processing
441
start_result - index (from 0 ) of first decimal digits will
442
be written by this address
443
end_result - index of position just after last decimal digit
444
be written by this address
447
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
450
dec1 *buf_beg= from->buf;
451
dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
452
dec1 *buf_end= end - 1;
454
/* find non-zero digit from number begining */
455
while (buf_beg < end && *buf_beg == 0)
461
*start_result= *end_result= 0;
465
/* find non-zero decimal digit from number begining */
466
if (buf_beg == from->buf && from->intg)
468
start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1));
474
start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
477
for (; *buf_beg < powers10[i--]; start++) ;
478
*start_result= start; /* index of first decimal digit (from 0) */
480
/* find non-zero digit at the end */
481
while (buf_end > buf_beg && *buf_end == 0)
483
/* find non-zero decimal digit from the end */
484
if (buf_end == end - 1 && from->frac)
486
stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
487
(i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
488
i= DIG_PER_DEC1 - i + 1;
492
stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
495
for (; *buf_end % powers10[i++] == 0; stop--) {};
496
*end_result= stop; /* index of position after last decimal digit (from 0) */
501
Left shift for alignment of data in buffer
505
dec pointer to decimal number which have to be shifted
506
shift number of decimal digits on which it should be shifted
507
beg/end bounds of decimal digits (see digits_bounds())
510
Result fitting in the buffer should be garanted.
511
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
514
void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
516
dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
517
dec1 *end= dec->buf + ROUND_UP(last) - 1;
518
int c_shift= DIG_PER_DEC1 - shift;
519
DBUG_ASSERT(from >= dec->buf);
520
DBUG_ASSERT(end < dec->buf + dec->len);
521
if (beg % DIG_PER_DEC1 < shift)
522
*(from - 1)= (*from) / powers10[c_shift];
523
for(; from < end; from++)
524
*from= ((*from % powers10[c_shift]) * powers10[shift] +
525
(*(from + 1)) / powers10[c_shift]);
526
*from= (*from % powers10[c_shift]) * powers10[shift];
531
Right shift for alignment of data in buffer
535
dec pointer to decimal number which have to be shifted
536
shift number of decimal digits on which it should be shifted
537
beg/end bounds of decimal digits (see digits_bounds())
540
Result fitting in the buffer should be garanted.
541
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
544
void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
546
dec1 *from= dec->buf + ROUND_UP(last) - 1;
547
dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
548
int c_shift= DIG_PER_DEC1 - shift;
549
DBUG_ASSERT(from < dec->buf + dec->len);
550
DBUG_ASSERT(end >= dec->buf);
551
if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
552
*(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
553
for(; from > end; from--)
554
*from= (*from / powers10[shift] +
555
(*(from - 1) % powers10[shift]) * powers10[c_shift]);
556
*from= *from / powers10[shift];
561
Shift of decimal digits in given number (with rounding if it need)
565
dec number to be shifted
566
shift number of decimal positions
567
shift > 0 means shift to left shift
568
shift < 0 meand right shift
570
In fact it is multipling on 10^shift.
573
E_DEC_OVERFLOW operation lead to overflow, number is untoched
574
E_DEC_TRUNCATED number was rounded to fit into buffer
577
int decimal_shift(decimal_t *dec, int shift)
579
/* index of first non zero digit (all indexes from 0) */
581
/* index of position after last decimal digit */
583
/* index of digit position just after point */
584
int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
585
/* new point position */
586
int new_point= point + shift;
587
/* number of digits in result */
588
int digits_int, digits_frac;
589
/* length of result and new fraction in big digits*/
590
int new_len, new_frac_len;
598
digits_bounds(dec, &beg, &end);
602
decimal_make_zero(dec);
606
digits_int= new_point - beg;
607
set_if_bigger(digits_int, 0);
608
digits_frac= end - new_point;
609
set_if_bigger(digits_frac, 0);
611
if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
614
int lack= new_len - dec->len;
617
if (new_frac_len < lack)
618
return E_DEC_OVERFLOW; /* lack more then we have in fraction */
620
/* cat off fraction part to allow new number to fit in our buffer */
621
err= E_DEC_TRUNCATED;
623
diff= digits_frac - (new_frac_len * DIG_PER_DEC1);
624
/* Make rounding method as parameter? */
625
decimal_round(dec, dec, end - point - diff, HALF_UP);
627
digits_frac= new_frac_len * DIG_PER_DEC1;
632
we lost all digits (they will be shifted out of buffer), so we can
635
decimal_make_zero(dec);
636
return E_DEC_TRUNCATED;
640
if (shift % DIG_PER_DEC1)
642
int l_mini_shift, r_mini_shift, mini_shift;
645
Calculate left/right shift to align decimal digits inside our bug
650
l_mini_shift= shift % DIG_PER_DEC1;
651
r_mini_shift= DIG_PER_DEC1 - l_mini_shift;
653
It is left shift so prefer left shift, but if we have not place from
654
left, we have to have it from right, because we checked length of
657
do_left= l_mini_shift <= beg;
658
DBUG_ASSERT(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
662
r_mini_shift= (-shift) % DIG_PER_DEC1;
663
l_mini_shift= DIG_PER_DEC1 - r_mini_shift;
664
/* see comment above */
665
do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
666
DBUG_ASSERT(!do_left || l_mini_shift <= beg);
670
do_mini_left_shift(dec, l_mini_shift, beg, end);
671
mini_shift=- l_mini_shift;
675
do_mini_right_shift(dec, r_mini_shift, beg, end);
676
mini_shift= r_mini_shift;
678
new_point+= mini_shift;
680
If number is shifted and correctly aligned in buffer we can
683
if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1)
685
dec->intg= digits_int;
686
dec->frac= digits_frac;
687
return err; /* already shifted as it should be */
693
/* if new 'decimal front' is in first digit, we do not need move digits */
694
if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 ||
697
/* need to move digits */
703
d_shift= new_front / DIG_PER_DEC1;
704
to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
705
barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
706
DBUG_ASSERT(to >= dec->buf);
707
DBUG_ASSERT(barier + d_shift < dec->buf + dec->len);
708
for(; to <= barier; to++)
709
*to= *(to + d_shift);
710
for(barier+= d_shift; to <= barier; to++)
717
d_shift= (1 - new_front) / DIG_PER_DEC1;
718
to= dec->buf + ROUND_UP(end) - 1 + d_shift;
719
barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
720
DBUG_ASSERT(to < dec->buf + dec->len);
721
DBUG_ASSERT(barier - d_shift >= dec->buf);
722
for(; to >= barier; to--)
723
*to= *(to - d_shift);
724
for(barier-= d_shift; to >= barier; to--)
727
d_shift*= DIG_PER_DEC1;
734
If there are gaps then fill ren with 0.
736
Only one of following 'for' loops will work becouse beg <= end
738
beg= ROUND_UP(beg + 1) - 1;
739
end= ROUND_UP(end) - 1;
740
DBUG_ASSERT(new_point >= 0);
742
/* We don't want negative new_point below */
744
new_point= ROUND_UP(new_point) - 1;
750
dec->buf[new_point]=0;
751
} while (--new_point > end);
755
for (; new_point < beg; new_point++)
756
dec->buf[new_point]= 0;
758
dec->intg= digits_int;
759
dec->frac= digits_frac;
765
Convert string to decimal
769
from - value to convert. Doesn't have to be \0 terminated!
770
to - decimal where where the result will be stored
771
to->buf and to->len must be set.
772
end - Pointer to pointer to end of string. Will on return be
773
set to the char after the last used character
774
fixed - use to->intg, to->frac as limits for input number
777
to->intg and to->frac can be modified even when fixed=1
778
(but only decreased, in this case)
781
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
782
In case of E_DEC_FATAL_ERROR *to is set to decimal zero
783
(to make error handling easier)
787
internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed)
789
const char *s= from, *s1, *endp, *end_of_string= *end;
790
int i, intg, frac, error, intg1, frac1;
794
error= E_DEC_BAD_NUM; /* In case of bad number */
795
while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
797
if (s == end_of_string)
800
if ((to->sign= (*s == '-')))
806
while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
809
if (s < end_of_string && *s=='.')
812
while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
814
frac= (int) (endp - s - 1);
832
error=E_DEC_TRUNCATED;
837
error=E_DEC_OVERFLOW;
840
intg1=ROUND_UP(intg);
841
frac1=ROUND_UP(frac);
842
if (intg1+frac1 > to->len)
850
intg1=ROUND_UP(intg);
851
frac1=ROUND_UP(frac);
852
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
855
frac=frac1*DIG_PER_DEC1;
856
if (error == E_DEC_OVERFLOW)
857
intg=intg1*DIG_PER_DEC1;
860
/* Error is guranteed to be set here */
867
for (x=0, i=0; intg; intg--)
869
x+= (*--s - '0')*powers10[i];
871
if (unlikely(++i == DIG_PER_DEC1))
882
for (x=0, i=0; frac; frac--)
884
x= (*++s1 - '0') + x*10;
886
if (unlikely(++i == DIG_PER_DEC1))
894
*buf=x*powers10[DIG_PER_DEC1-i];
896
/* Handle exponent */
897
if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
900
longlong exponent= my_strtoll10(endp+1, (char**) &end_of_string,
903
if (end_of_string != endp +1) /* If at least one digit */
905
*end= (char*) end_of_string;
908
error= E_DEC_BAD_NUM;
911
if (exponent > INT_MAX/2 || (str_error == 0 && exponent < 0))
913
error= E_DEC_OVERFLOW;
916
if (exponent < INT_MIN/2 && error != E_DEC_OVERFLOW)
918
error= E_DEC_TRUNCATED;
921
if (error != E_DEC_OVERFLOW)
922
error= decimal_shift(to, (int) exponent);
928
decimal_make_zero(to);
934
Convert decimal to double
938
from - value to convert
939
to - result will be stored there
942
E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
945
int decimal2double(decimal_t *from, double *to)
947
char strbuf[FLOATING_POINT_BUFFER], *end;
948
int len= sizeof(strbuf);
951
rc = decimal2string(from, strbuf, &len, 0, 0, 0);
954
DBUG_PRINT("info", ("interm.: %s", strbuf));
956
*to= my_strtod(strbuf, &end, &error);
958
DBUG_PRINT("info", ("result: %f (%lx)", *to, *(ulong *)to));
960
return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
964
Convert double to decimal
968
from - value to convert
969
to - result will be stored there
972
E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
975
int double2decimal(double from, decimal_t *to)
977
char buff[FLOATING_POINT_BUFFER], *end;
979
DBUG_ENTER("double2decimal");
980
end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
981
res= string2decimal(buff, to, &end);
982
DBUG_PRINT("exit", ("res: %d", res));
987
static int ull2dec(ulonglong from, decimal_t *to)
989
int intg1, error=E_DEC_OK;
995
for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE) {};
996
if (unlikely(intg1 > to->len))
999
error=E_DEC_OVERFLOW;
1002
to->intg=intg1*DIG_PER_DEC1;
1004
for (buf=to->buf+intg1; intg1; intg1--)
1006
ulonglong y=x/DIG_BASE;
1007
*--buf=(dec1)(x-y*DIG_BASE);
1013
int ulonglong2decimal(ulonglong from, decimal_t *to)
1016
return ull2dec(from, to);
1019
int longlong2decimal(longlong from, decimal_t *to)
1021
if ((to->sign= from < 0))
1022
return ull2dec(-from, to);
1023
return ull2dec(from, to);
1026
int decimal2ulonglong(decimal_t *from, ulonglong *to)
1028
dec1 *buf=from->buf;
1035
return E_DEC_OVERFLOW;
1038
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1041
x=x*DIG_BASE + *buf++;
1042
if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
1045
return E_DEC_OVERFLOW;
1049
for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1051
return E_DEC_TRUNCATED;
1055
int decimal2longlong(decimal_t *from, longlong *to)
1057
dec1 *buf=from->buf;
1061
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1066
we're calculating -|from| instead of |from| here
1067
because |LONGLONG_MIN| > LONGLONG_MAX
1068
so we can convert -9223372036854775808 correctly
1070
x=x*DIG_BASE - *buf++;
1071
if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
1074
the decimal is bigger than any possible integer
1075
return border integer depending on the sign
1077
*to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
1078
return E_DEC_OVERFLOW;
1081
/* boundary case: 9223372036854775808 */
1082
if (unlikely(from->sign==0 && x == LONGLONG_MIN))
1085
return E_DEC_OVERFLOW;
1088
*to=from->sign ? x : -x;
1089
for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1091
return E_DEC_TRUNCATED;
1096
Convert decimal to its binary fixed-length representation
1097
two representations of the same length can be compared with memcmp
1098
with the correct -1/0/+1 result
1102
from - value to convert
1103
to - points to buffer where string representation should be stored
1104
precision/scale - see decimal_bin_size() below
1107
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1110
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1113
for storage decimal numbers are converted to the "binary" format.
1115
This format has the following properties:
1116
1. length of the binary representation depends on the {precision, scale}
1117
as provided by the caller and NOT on the intg/frac of the decimal to
1119
2. binary representations of the same {precision, scale} can be compared
1120
with memcmp - with the same result as decimal_cmp() of the original
1121
decimals (not taking into account possible precision loss during
1124
This binary format is as follows:
1125
1. First the number is converted to have a requested precision and scale.
1126
2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes
1128
3. The first intg % DIG_PER_DEC1 digits are stored in the reduced
1129
number of bytes (enough bytes to store this number of digits -
1131
4. same for frac - full decimal_digit_t's are stored as is,
1132
the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes.
1133
5. If the number is negative - every byte is inversed.
1134
5. The very first bit of the resulting byte array is inverted (because
1135
memcmp compares unsigned bytes, see property 2 above)
1141
internally is represented as 3 decimal_digit_t's
1143
1 234567890 123400000
1145
(assuming we want a binary representation with precision=14, scale=4)
1148
00-00-00-01 0D-FB-38-D2 07-5A-EF-40
1150
now, middle decimal_digit_t is full - it stores 9 decimal digits. It goes
1151
into binary representation as is:
1154
........... 0D-FB-38-D2 ............
1156
First decimal_digit_t has only one decimal digit. We can store one digit in
1157
one byte, no need to waste four:
1159
01 0D-FB-38-D2 ............
1161
now, last digit. It's 123400000. We can store 1234 in two bytes:
1163
01 0D-FB-38-D2 04-D2
1165
So, we've packed 12 bytes number in 7 bytes.
1166
And now we invert the highest bit to get the final result:
1168
81 0D FB 38 D2 04 D2
1170
And for -1234567890.1234 it would be
1172
7E F2 04 37 2D FB 2D
1174
int decimal2bin(decimal_t *from, uchar *to, int precision, int frac)
1176
dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1177
int error=E_DEC_OK, intg=precision-frac,
1178
isize1, intg1, intg1x, from_intg,
1179
intg0=intg/DIG_PER_DEC1,
1180
frac0=frac/DIG_PER_DEC1,
1181
intg0x=intg-intg0*DIG_PER_DEC1,
1182
frac0x=frac-frac0*DIG_PER_DEC1,
1183
frac1=from->frac/DIG_PER_DEC1,
1184
frac1x=from->frac-frac1*DIG_PER_DEC1,
1185
isize0=intg0*sizeof(dec1)+dig2bytes[intg0x],
1186
fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x],
1187
fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
1188
const int orig_isize0= isize0;
1189
const int orig_fsize0= fsize0;
1192
buf1= remove_leading_zeroes(from, &from_intg);
1194
if (unlikely(from_intg+fsize1==0))
1196
mask=0; /* just in case */
1201
intg1=from_intg/DIG_PER_DEC1;
1202
intg1x=from_intg-intg1*DIG_PER_DEC1;
1203
isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
1205
if (intg < from_intg)
1207
buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
1208
intg1=intg0; intg1x=intg0x;
1209
error=E_DEC_OVERFLOW;
1211
else if (isize0 > isize1)
1213
while (isize0-- > isize1)
1216
if (fsize0 < fsize1)
1218
frac1=frac0; frac1x=frac0x;
1219
error=E_DEC_TRUNCATED;
1221
else if (fsize0 > fsize1 && frac1x)
1238
int i=dig2bytes[intg1x];
1239
dec1 x=(*buf1++ % powers10[intg1x]) ^ mask;
1242
case 1: mi_int1store(to, x); break;
1243
case 2: mi_int2store(to, x); break;
1244
case 3: mi_int3store(to, x); break;
1245
case 4: mi_int4store(to, x); break;
1246
default: DBUG_ASSERT(0);
1251
/* intg1+frac1 part */
1252
for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=sizeof(dec1))
1254
dec1 x=*buf1++ ^ mask;
1255
DBUG_ASSERT(sizeof(dec1) == 4);
1256
mi_int4store(to, x);
1263
int i=dig2bytes[frac1x],
1264
lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x);
1265
while (frac1x < lim && dig2bytes[frac1x] == i)
1267
x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask;
1270
case 1: mi_int1store(to, x); break;
1271
case 2: mi_int2store(to, x); break;
1272
case 3: mi_int3store(to, x); break;
1273
case 4: mi_int4store(to, x); break;
1274
default: DBUG_ASSERT(0);
1278
if (fsize0 > fsize1)
1280
uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
1282
while (fsize0-- > fsize1 && to < to_end)
1287
/* Check that we have written the whole decimal and nothing more */
1288
DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0);
1293
Restores decimal from its binary fixed-length representation
1297
from - value to convert
1299
precision/scale - see decimal_bin_size() below
1303
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1306
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1309
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
1311
int error=E_DEC_OK, intg=precision-scale,
1312
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1313
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1314
intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1315
dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
1318
int bin_size= decimal_bin_size(precision, scale);
1321
d_copy= (uchar*) my_alloca(bin_size);
1322
memcpy(d_copy, from, bin_size);
1326
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1327
if (unlikely(error))
1329
if (intg1 < intg0+(intg0x>0))
1331
from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1);
1332
frac0=frac0x=intg0x=0;
1342
to->sign=(mask != 0);
1343
to->intg=intg0*DIG_PER_DEC1+intg0x;
1344
to->frac=frac0*DIG_PER_DEC1+frac0x;
1348
int i=dig2bytes[intg0x];
1352
case 1: x=mi_sint1korr(from); break;
1353
case 2: x=mi_sint2korr(from); break;
1354
case 3: x=mi_sint3korr(from); break;
1355
case 4: x=mi_sint4korr(from); break;
1356
default: DBUG_ASSERT(0);
1360
if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1])
1362
if (buf > to->buf || *buf != 0)
1367
for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1369
DBUG_ASSERT(sizeof(dec1) == 4);
1370
*buf=mi_sint4korr(from) ^ mask;
1371
if (((uint32)*buf) > DIG_MAX)
1373
if (buf > to->buf || *buf != 0)
1376
to->intg-=DIG_PER_DEC1;
1378
DBUG_ASSERT(to->intg >=0);
1379
for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1381
DBUG_ASSERT(sizeof(dec1) == 4);
1382
*buf=mi_sint4korr(from) ^ mask;
1383
if (((uint32)*buf) > DIG_MAX)
1389
int i=dig2bytes[frac0x];
1393
case 1: x=mi_sint1korr(from); break;
1394
case 2: x=mi_sint2korr(from); break;
1395
case 3: x=mi_sint3korr(from); break;
1396
case 4: x=mi_sint4korr(from); break;
1397
default: DBUG_ASSERT(0);
1399
*buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
1400
if (((uint32)*buf) > DIG_MAX)
1409
decimal_make_zero(((decimal_t*) to));
1410
return(E_DEC_BAD_NUM);
1414
Returns the size of array to hold a decimal with given precision and scale
1418
(multiply by sizeof(dec1) to get the size if bytes)
1421
int decimal_size(int precision, int scale)
1423
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1424
return ROUND_UP(precision-scale)+ROUND_UP(scale);
1428
Returns the size of array to hold a binary representation of a decimal
1434
int decimal_bin_size(int precision, int scale)
1436
int intg=precision-scale,
1437
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1438
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
1440
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1441
return intg0*sizeof(dec1)+dig2bytes[intg0x]+
1442
frac0*sizeof(dec1)+dig2bytes[frac0x];
1446
Rounds the decimal to "scale" digits
1450
from - decimal to round,
1451
to - result buffer. from==to is allowed
1452
scale - to what position to round. can be negative!
1453
mode - round to nearest even or truncate
1456
scale can be negative !
1457
one TRUNCATED error (line XXX below) isn't treated very logical :(
1460
E_DEC_OK/E_DEC_TRUNCATED
1464
decimal_round(decimal_t *from, decimal_t *to, int scale,
1465
decimal_round_mode mode)
1467
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1468
frac1=ROUND_UP(from->frac), round_digit= 0,
1469
intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1470
intg1=ROUND_UP(from->intg +
1471
(((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1472
dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1479
case HALF_EVEN: round_digit=5; break;
1480
case CEILING: round_digit= from->sign ? 10 : 0; break;
1481
case FLOOR: round_digit= from->sign ? 0 : 10; break;
1482
case TRUNCATE: round_digit=10; break;
1483
default: DBUG_ASSERT(0);
1486
if (unlikely(frac0+intg0 > len))
1489
scale=frac0*DIG_PER_DEC1;
1490
error=E_DEC_TRUNCATED;
1493
if (scale+from->intg < 0)
1495
decimal_make_zero(to);
1499
if (to != from || intg1>intg0)
1501
dec1 *p0= buf0+intg0+max(frac1, frac0);
1502
dec1 *p1= buf1+intg1+max(frac1, frac0);
1506
if (unlikely(intg1 > intg0))
1512
to->sign=from->sign;
1513
to->intg=min(intg0, len)*DIG_PER_DEC1;
1519
while (frac0-- > frac1)
1524
if (scale >= from->frac)
1525
goto done; /* nothing to do */
1527
buf0+=intg0+frac0-1;
1528
buf1+=intg0+frac0-1;
1529
if (scale == frac0*DIG_PER_DEC1)
1532
DBUG_ASSERT(frac0+intg0 >= 0);
1533
switch (round_digit) {
1536
dec1 *p0= buf0 + (frac1-frac0);
1537
for (; p0 > buf0; p0--)
1549
x= buf0[1]/DIG_MASK;
1550
do_inc= (x>5) || ((x == 5) &&
1551
(mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
1564
else if (frac0+intg0==0)
1566
decimal_make_zero(to);
1572
/* TODO - fix this code as it won't work for CEILING mode */
1573
int pos=frac0*DIG_PER_DEC1-scale-1;
1574
DBUG_ASSERT(frac0+intg0 > 0);
1575
x=*buf1 / powers10[pos];
1577
if (y > round_digit ||
1578
(round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
1580
*buf1=powers10[pos]*(x-y);
1583
In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal_digit_t's inside
1584
the buffer are as follows.
1589
Hence we need to set the 2nd field to 0.
1590
The same holds if we round 1.5e-9 to 2e-9.
1594
dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0);
1595
dec1 *end= to->buf + len;
1600
if (*buf1 >= DIG_BASE)
1604
while (carry && --buf1 >= to->buf)
1605
ADD(*buf1, *buf1, 0, carry);
1606
if (unlikely(carry))
1608
/* shifting the number to create space for new digit */
1609
if (frac0+intg0 >= len)
1612
scale=frac0*DIG_PER_DEC1;
1613
error=E_DEC_TRUNCATED; /* XXX */
1615
for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--)
1629
if (buf1-- == to->buf)
1631
/* making 'zero' with the proper scale */
1632
dec1 *p0= to->buf + frac0 + 1;
1634
to->frac= max(scale, 0);
1636
for (buf1= to->buf; buf1<p0; buf1++)
1643
/* Here we check 999.9 -> 1000 case when we need to increase intg */
1644
first_dig= to->intg % DIG_PER_DEC1;
1645
if (first_dig && (*buf1 >= powers10[first_dig]))
1657
Returns the size of the result of the operation
1660
decimal_result_size()
1661
from1 - operand of the unary operation or first operand of the
1663
from2 - second operand of the binary operation
1664
op - operation. one char '+', '-', '*', '/' are allowed
1665
others may be added later
1666
param - extra param to the operation. unused for '+', '-', '*'
1667
scale increment for '/'
1670
returned valued may be larger than the actual buffer requred
1671
in the operation, as decimal_result_size, by design, operates on
1672
precision/scale values only and not on the actual decimal number
1675
size of to->buf array in dec1 elements. to get size in bytes
1676
multiply by sizeof(dec1)
1679
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1683
return ROUND_UP(max(from1->intg, from2->intg)) +
1684
ROUND_UP(max(from1->frac, from2->frac));
1686
return ROUND_UP(max(from1->intg, from2->intg)+1) +
1687
ROUND_UP(max(from1->frac, from2->frac));
1689
return ROUND_UP(from1->intg+from2->intg)+
1690
ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1692
return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1693
default: DBUG_ASSERT(0);
1695
return -1; /* shut up the warning */
1698
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1700
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1701
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1702
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1703
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1707
/* is there a need for extra word because of carry ? */
1708
x=intg1 > intg2 ? from1->buf[0] :
1709
intg2 > intg1 ? from2->buf[0] :
1710
from1->buf[0] + from2->buf[0] ;
1711
if (unlikely(x > DIG_MAX-1)) /* yes, there is */
1714
to->buf[0]=0; /* safety */
1717
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1718
if (unlikely(error == E_DEC_OVERFLOW))
1720
max_decimal(to->len * DIG_PER_DEC1, 0, to);
1724
buf0=to->buf+intg0+frac0;
1726
to->sign=from1->sign;
1727
to->frac=max(from1->frac, from2->frac);
1728
to->intg=intg0*DIG_PER_DEC1;
1729
if (unlikely(error))
1731
set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1732
set_if_smaller(frac1, frac0);
1733
set_if_smaller(frac2, frac0);
1734
set_if_smaller(intg1, intg0);
1735
set_if_smaller(intg2, intg0);
1738
/* part 1 - max(frac) ... min (frac) */
1741
buf1=from1->buf+intg1+frac1;
1742
stop=from1->buf+intg1+frac2;
1743
buf2=from2->buf+intg2+frac2;
1744
stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
1748
buf1=from2->buf+intg2+frac2;
1749
stop=from2->buf+intg2+frac1;
1750
buf2=from1->buf+intg1+frac1;
1751
stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
1756
/* part 2 - min(frac) ... min(intg) */
1758
while (buf1 > stop2)
1760
ADD(*--buf0, *--buf1, *--buf2, carry);
1763
/* part 3 - min(intg) ... max(intg) */
1764
buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1765
((stop=from2->buf)+intg2-intg1) ;
1768
ADD(*--buf0, *--buf1, 0, carry);
1771
if (unlikely(carry))
1773
DBUG_ASSERT(buf0 == to->buf || buf0 == to->buf+1);
1779
if to==0, return -1/0/+1 - the result of the comparison */
1780
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1782
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1783
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1784
int frac0=max(frac1, frac2), error;
1785
dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1787
/* let carry:=1 if from2 > from1 */
1788
start1=buf1=from1->buf; stop1=buf1+intg1;
1789
start2=buf2=from2->buf; stop2=buf2+intg2;
1790
if (unlikely(*buf1 == 0))
1792
while (buf1 < stop1 && *buf1 == 0)
1795
intg1= (int) (stop1-buf1);
1797
if (unlikely(*buf2 == 0))
1799
while (buf2 < stop2 && *buf2 == 0)
1802
intg2= (int) (stop2-buf2);
1806
else if (intg2 == intg1)
1808
dec1 *end1= stop1 + (frac1 - 1);
1809
dec1 *end2= stop2 + (frac2 - 1);
1810
while (unlikely((buf1 <= end1) && (*end1 == 0)))
1812
while (unlikely((buf2 <= end2) && (*end2 == 0)))
1814
frac1= (int) (end1 - stop1) + 1;
1815
frac2= (int) (end2 - stop2) + 1;
1816
while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
1821
carry= *buf2 > *buf1;
1829
else /* short-circuit everything: from1 == from2 */
1831
if (to == 0) /* decimal_cmp() */
1833
decimal_make_zero(to);
1839
if (to == 0) /* decimal_cmp() */
1840
return carry == from1->sign ? 1 : -1;
1844
to->sign=from1->sign;
1846
/* ensure that always from1 > from2 (and intg1 >= intg2) */
1849
swap_variables(decimal_t *,from1,from1);
1850
swap_variables(dec1 *,start1, start2);
1851
swap_variables(int,intg1,intg2);
1852
swap_variables(int,frac1,frac2);
1853
to->sign= 1 - to->sign;
1856
FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
1857
buf0=to->buf+intg1+frac0;
1859
to->frac=max(from1->frac, from2->frac);
1860
to->intg=intg1*DIG_PER_DEC1;
1861
if (unlikely(error))
1863
set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1864
set_if_smaller(frac1, frac0);
1865
set_if_smaller(frac2, frac0);
1866
set_if_smaller(intg2, intg1);
1870
/* part 1 - max(frac) ... min (frac) */
1873
buf1=start1+intg1+frac1;
1874
stop1=start1+intg1+frac2;
1875
buf2=start2+intg2+frac2;
1876
while (frac0-- > frac1)
1878
while (buf1 > stop1)
1883
buf1=start1+intg1+frac1;
1884
buf2=start2+intg2+frac2;
1885
stop2=start2+intg2+frac1;
1886
while (frac0-- > frac2)
1888
while (buf2 > stop2)
1890
SUB(*--buf0, 0, *--buf2, carry);
1894
/* part 2 - min(frac) ... intg2 */
1895
while (buf2 > start2)
1897
SUB(*--buf0, *--buf1, *--buf2, carry);
1900
/* part 3 - intg2 ... intg1 */
1901
while (carry && buf1 > start1)
1903
SUB(*--buf0, *--buf1, 0, carry);
1906
while (buf1 > start1)
1909
while (buf0 > to->buf)
1915
int decimal_intg(decimal_t *from)
1919
tmp_res= remove_leading_zeroes(from, &res);
1923
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1925
if (likely(from1->sign == from2->sign))
1926
return do_add(from1, from2, to);
1927
return do_sub(from1, from2, to);
1930
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1932
if (likely(from1->sign == from2->sign))
1933
return do_sub(from1, from2, to);
1934
return do_add(from1, from2, to);
1937
int decimal_cmp(decimal_t *from1, decimal_t *from2)
1939
if (likely(from1->sign == from2->sign))
1940
return do_sub(from1, from2, 0);
1941
return from1->sign > from2->sign ? -1 : 1;
1944
int decimal_is_zero(decimal_t *from)
1946
dec1 *buf1=from->buf,
1947
*end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
1955
multiply two decimals
1959
from1, from2 - factors
1963
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
1966
in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
1967
and 63-digit number will take only 7 dec1 words (basically a 7-digit
1968
"base 999999999" number). Thus there's no need in fast multiplication
1969
algorithms, 7-digit numbers can be multiplied with a naive O(n*n)
1972
XXX if this library is to be used with huge numbers of thousands of
1973
digits, fast multiplication must be implemented.
1975
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
1977
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1978
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1979
intg0=ROUND_UP(from1->intg+from2->intg),
1980
frac0=frac1+frac2, error, i, j, d_to_move;
1981
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
1982
*start2, *stop2, *stop1, *start0, carry;
1988
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1989
to->sign=from1->sign != from2->sign;
1990
to->frac=from1->frac+from2->frac;
1991
to->intg=intg0*DIG_PER_DEC1;
1993
if (unlikely(error))
1995
set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1996
set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
1997
if (unlikely(i > intg0))
2003
frac1=frac2=0; /* frac0 is already 0 here */
2013
start0=to->buf+intg0+frac0-1;
2014
start2=buf2+frac2-1;
2018
bzero(to->buf, (intg0+frac0)*sizeof(dec1));
2020
for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
2023
for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
2026
dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2027
hi=(dec1)(p/DIG_BASE);
2028
lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2029
ADD2(*buf0, *buf0, lo, carry);
2035
return E_DEC_OVERFLOW;
2036
ADD2(*buf0, *buf0, 0, carry);
2038
for (buf0--; carry; buf0--)
2041
return E_DEC_OVERFLOW;
2042
ADD(*buf0, *buf0, 0, carry);
2046
/* Now we have to check for -0.000 case */
2050
dec1 *end= to->buf + intg0 + frac0;
2051
DBUG_ASSERT(buf != end);
2058
/* We got decimal zero */
2059
decimal_make_zero(to);
2065
d_to_move= intg0 + ROUND_UP(to->frac);
2066
while (!*buf1 && (to->intg > DIG_PER_DEC1))
2069
to->intg-= DIG_PER_DEC1;
2074
dec1 *cur_d= to->buf;
2075
for (; d_to_move--; cur_d++, buf1++)
2082
naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2083
it's ok for short numbers
2084
also we're using alloca() to allocate a temporary buffer
2086
XXX if this library is to be used with huge numbers of thousands of
2087
digits, fast division must be implemented and alloca should be
2088
changed to malloc (or at least fallback to malloc if alloca() fails)
2089
but then, decimal_mul() should be rewritten too :(
2091
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2092
decimal_t *to, decimal_t *mod, int scale_incr)
2094
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2095
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2096
error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2097
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2098
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2099
dec2 norm_factor, x, guess, y;
2106
/* removing all the leading zeroes */
2107
i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
2108
while (prec2 > 0 && *buf2 == 0)
2114
if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
2115
return E_DEC_DIV_ZERO;
2116
for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
2117
DBUG_ASSERT(prec2 > 0);
2119
i=((prec1-1) % DIG_PER_DEC1)+1;
2120
while (prec1 > 0 && *buf1 == 0)
2127
{ /* short-circuit everything: from1 == 0 */
2128
decimal_make_zero(to);
2131
for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2132
DBUG_ASSERT(prec1 > 0);
2134
/* let's fix scale_incr, taking into account frac1,frac2 increase */
2135
if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
2138
dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
2141
dintg/=DIG_PER_DEC1;
2145
intg0=ROUND_UP(dintg);
2148
/* we're calculating N1 % N2.
2149
The result will have
2150
frac=max(frac1, frac2), as for subtraction
2153
to->sign=from1->sign;
2154
to->frac=max(from1->frac, from2->frac);
2160
we're calculating N1/N2. N1 is in the buf1, has prec1 digits
2161
N2 is in the buf2, has prec2 digits. Scales are frac1 and
2163
Thus, the result will have
2164
frac = ROUND_UP(frac1+frac2+scale_incr)
2166
intg = (prec1-frac1) - (prec2-frac2) + 1
2169
frac0=ROUND_UP(frac1+frac2+scale_incr);
2170
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2171
to->sign=from1->sign != from2->sign;
2172
to->intg=intg0*DIG_PER_DEC1;
2173
to->frac=frac0*DIG_PER_DEC1;
2176
stop0=buf0+intg0+frac0;
2177
if (likely(div_mod))
2181
len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2182
set_if_bigger(len1, 3);
2183
if (!(tmp1=(dec1 *)my_alloca(len1*sizeof(dec1))))
2185
memcpy(tmp1, buf1, i*sizeof(dec1));
2186
bzero(tmp1+i, (len1-i)*sizeof(dec1));
2191
stop2=buf2+ROUND_UP(prec2)-1;
2193
/* removing end zeroes */
2194
while (*stop2 == 0 && stop2 >= start2)
2196
len2= (int) (stop2++ - start2);
2199
calculating norm2 (normalized *start2) - we need *start2 to be large
2200
(at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to
2201
normalize input numbers (as we don't make a copy of the divisor).
2202
Thus we normalize first dec1 of buf2 only, and we'll normalize *start1
2203
on the fly for the purpose of guesstimation only.
2204
It's also faster, as we're saving on normalization of buf2
2206
norm_factor=DIG_BASE/(*start2+1);
2207
norm2=(dec1)(norm_factor*start2[0]);
2209
norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
2211
if (*start1 < *start2)
2217
for (; buf0 < stop0; buf0++)
2219
/* short-circuit, if possible */
2220
if (unlikely(dcarry == 0 && *start1 < *start2))
2224
/* D3: make a guess */
2225
x=start1[0]+((dec2)dcarry)*DIG_BASE;
2227
guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
2228
if (unlikely(guess >= DIG_BASE))
2232
/* hmm, this is a suspicious trick - I removed normalization here */
2233
if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
2235
if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
2237
DBUG_ASSERT(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
2240
/* D4: multiply and subtract */
2243
DBUG_ASSERT(buf1 < stop1);
2244
for (carry=0; buf2 > start2; buf1--)
2247
x=guess * (*--buf2);
2248
hi=(dec1)(x/DIG_BASE);
2249
lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2250
SUB2(*buf1, *buf1, lo, carry);
2253
carry= dcarry < carry;
2255
/* D5: check the remainder */
2256
if (unlikely(carry))
2258
/* D6: correct the guess */
2262
for (carry=0; buf2 > start2; buf1--)
2264
ADD(*buf1, *buf1, *--buf2, carry);
2268
if (likely(div_mod))
2276
now the result is in tmp1, it has
2278
frac=max(frac1, frac2)=to->frac
2283
intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2284
frac0=ROUND_UP(to->frac);
2286
if (unlikely(frac0==0 && intg0==0))
2288
decimal_make_zero(to);
2293
if (unlikely(-intg0 >= to->len))
2295
decimal_make_zero(to);
2296
error=E_DEC_TRUNCATED;
2307
if (unlikely(intg0 > to->len))
2311
error=E_DEC_OVERFLOW;
2314
DBUG_ASSERT(intg0 <= ROUND_UP(from2->intg));
2315
stop1=start1+frac0+intg0;
2316
to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2318
if (unlikely(intg0+frac0 > to->len))
2320
stop1-=frac0+intg0-to->len;
2321
frac0=to->len-intg0;
2322
to->frac=frac0*DIG_PER_DEC1;
2323
error=E_DEC_TRUNCATED;
2325
DBUG_ASSERT(buf0 + (stop1 - start1) <= to->buf + to->len);
2326
while (start1 < stop1)
2335
division of two decimals
2344
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2351
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2353
return do_div_mod(from1, from2, to, 0, scale_incr);
2366
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2372
the modulus R in R = M mod N
2378
R = M - k*N, where k is integer
2380
thus, there's no requirement for M or N to be integers
2383
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2385
return do_div_mod(from1, from2, 0, to, 0);
2392
char buf1[100], buf2[100], buf3[100];
2394
void dump_decimal(decimal_t *d)
2397
printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2398
for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2399
printf("%09d, ", d->buf[i]);
2400
printf("%09d} */ ", d->buf[i]);
2404
void check_result_code(int actual, int want)
2408
printf("\n^^^^^^^^^^^^^ must return %d\n", want);
2414
void print_decimal(decimal_t *d, const char *orig, int actual, int want)
2419
if (full) dump_decimal(d);
2420
decimal2string(d, s, &slen, 0, 0, 0);
2422
check_result_code(actual, want);
2423
if (orig && strcmp(orig, s))
2425
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2435
/***********************************/
2436
printf("==== decimal2string ====\n");
2437
a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
2439
res=decimal2string(&a, s, &slen, 0, 0, 0);
2440
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2442
a.buf[1]=987000000; a.frac=3;
2444
res=decimal2string(&a, s, &slen, 0, 0, 0);
2445
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2449
res=decimal2string(&a, s, &slen, 0, 0, 0);
2450
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2453
res=decimal2string(&a, s, &slen, 0, 0, 0);
2454
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2457
res=decimal2string(&a, s, &slen, 0, 0, 0);
2458
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2460
a.buf[0]=987000000; a.frac=3; a.intg=0;
2462
res=decimal2string(&a, s, &slen, 0, 0, 0);
2463
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2466
void test_s2d(const char *s, const char *orig, int ex)
2470
sprintf(s1, "'%s'", s);
2472
printf("len=%2d %-30s => res=%d ", a.len, s1,
2473
(res= string2decimal(s, &a, &end)));
2474
print_decimal(&a, orig, res, ex);
2478
void test_d2f(const char *s, int ex)
2484
sprintf(s1, "'%s'", s);
2486
string2decimal(s, &a, &end);
2487
res=decimal2double(&a, &x);
2488
if (full) dump_decimal(&a);
2489
printf("%-40s => res=%d %.*g\n", s1, res, a.intg+a.frac, x);
2490
check_result_code(res, ex);
2493
void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
2495
char s1[100], buf[100], *end;
2496
int res, i, size=decimal_bin_size(p, s);
2498
sprintf(s1, "'%s'", str);
2500
string2decimal(str, &a, &end);
2501
res=decimal2bin(&a, buf, p, s);
2502
printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
2506
for (i=0; i < size; i++)
2507
printf("%02x", ((uchar *)buf)[i]);
2509
res=bin2decimal(buf, &a, p, s);
2510
printf(" => res=%d ", res);
2511
print_decimal(&a, orig, res, ex);
2515
void test_f2d(double from, int ex)
2519
res=double2decimal(from, &a);
2520
printf("%-40.*f => res=%d ", DBL_DIG-2, from, res);
2521
print_decimal(&a, 0, res, ex);
2525
void test_ull2d(ulonglong from, const char *orig, int ex)
2530
res=ulonglong2decimal(from, &a);
2531
longlong10_to_str(from,s,10);
2532
printf("%-40s => res=%d ", s, res);
2533
print_decimal(&a, orig, res, ex);
2537
void test_ll2d(longlong from, const char *orig, int ex)
2542
res=longlong2decimal(from, &a);
2543
longlong10_to_str(from,s,-10);
2544
printf("%-40s => res=%d ", s, res);
2545
print_decimal(&a, orig, res, ex);
2549
void test_d2ull(const char *s, const char *orig, int ex)
2556
string2decimal(s, &a, &end);
2557
res=decimal2ulonglong(&a, &x);
2558
if (full) dump_decimal(&a);
2559
longlong10_to_str(x,s1,10);
2560
printf("%-40s => res=%d %s\n", s, res, s1);
2561
check_result_code(res, ex);
2562
if (orig && strcmp(orig, s1))
2564
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2569
void test_d2ll(const char *s, const char *orig, int ex)
2576
string2decimal(s, &a, &end);
2577
res=decimal2longlong(&a, &x);
2578
if (full) dump_decimal(&a);
2579
longlong10_to_str(x,s1,-10);
2580
printf("%-40s => res=%d %s\n", s, res, s1);
2581
check_result_code(res, ex);
2582
if (orig && strcmp(orig, s1))
2584
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2589
void test_da(const char *s1, const char *s2, const char *orig, int ex)
2593
sprintf(s, "'%s' + '%s'", s1, s2);
2595
string2decimal(s1, &a, &end);
2597
string2decimal(s2, &b, &end);
2598
res=decimal_add(&a, &b, &c);
2599
printf("%-40s => res=%d ", s, res);
2600
print_decimal(&c, orig, res, ex);
2604
void test_ds(const char *s1, const char *s2, const char *orig, int ex)
2608
sprintf(s, "'%s' - '%s'", s1, s2);
2610
string2decimal(s1, &a, &end);
2612
string2decimal(s2, &b, &end);
2613
res=decimal_sub(&a, &b, &c);
2614
printf("%-40s => res=%d ", s, res);
2615
print_decimal(&c, orig, res, ex);
2619
void test_dc(const char *s1, const char *s2, int orig)
2623
sprintf(s, "'%s' <=> '%s'", s1, s2);
2625
string2decimal(s1, &a, &end);
2627
string2decimal(s2, &b, &end);
2628
res=decimal_cmp(&a, &b);
2629
printf("%-40s => res=%d\n", s, res);
2632
printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
2637
void test_dm(const char *s1, const char *s2, const char *orig, int ex)
2641
sprintf(s, "'%s' * '%s'", s1, s2);
2643
string2decimal(s1, &a, &end);
2645
string2decimal(s2, &b, &end);
2646
res=decimal_mul(&a, &b, &c);
2647
printf("%-40s => res=%d ", s, res);
2648
print_decimal(&c, orig, res, ex);
2652
void test_dv(const char *s1, const char *s2, const char *orig, int ex)
2656
sprintf(s, "'%s' / '%s'", s1, s2);
2658
string2decimal(s1, &a, &end);
2660
string2decimal(s2, &b, &end);
2661
res=decimal_div(&a, &b, &c, 5);
2662
printf("%-40s => res=%d ", s, res);
2663
check_result_code(res, ex);
2664
if (res == E_DEC_DIV_ZERO)
2665
printf("E_DEC_DIV_ZERO");
2667
print_decimal(&c, orig, res, ex);
2671
void test_md(const char *s1, const char *s2, const char *orig, int ex)
2675
sprintf(s, "'%s' %% '%s'", s1, s2);
2677
string2decimal(s1, &a, &end);
2679
string2decimal(s2, &b, &end);
2680
res=decimal_mod(&a, &b, &c);
2681
printf("%-40s => res=%d ", s, res);
2682
check_result_code(res, ex);
2683
if (res == E_DEC_DIV_ZERO)
2684
printf("E_DEC_DIV_ZERO");
2686
print_decimal(&c, orig, res, ex);
2690
const char *round_mode[]=
2691
{"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
2693
void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
2698
sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2700
string2decimal(s1, &a, &end);
2701
res=decimal_round(&a, &b, n, mode);
2702
printf("%-40s => res=%d ", s, res);
2703
print_decimal(&b, orig, res, ex);
2708
void test_mx(int precision, int frac, const char *orig)
2711
sprintf(s, "%d, %d", precision, frac);
2712
max_decimal(precision, frac, &a);
2713
printf("%-40s => ", s);
2714
print_decimal(&a, orig, 0, 0);
2719
void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
2724
int slen= sizeof(s2);
2727
sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2728
s1, prec, dec, filler);
2730
string2decimal(s1, &a, &end);
2731
res= decimal2string(&a, s2, &slen, prec, dec, filler);
2732
printf("%-40s => res=%d '%s'", s, res, s2);
2733
check_result_code(res, ex);
2734
if (orig && strcmp(orig, s2))
2736
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2743
void test_sh(const char *s1, int shift, const char *orig, int ex)
2747
sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2749
string2decimal(s1, &a, &end);
2750
res= decimal_shift(&a, shift);
2751
printf("%-40s => res=%d ", s, res);
2752
print_decimal(&a, orig, res, ex);
2757
void test_fr(const char *s1, const char *orig)
2760
sprintf(s, "'%s'", s1);
2761
printf("%-40s => ", s);
2763
string2decimal(s1, &a, &end);
2764
a.frac= decimal_actual_fraction(&a);
2765
print_decimal(&a, orig, 0, 0);
2773
a.len=sizeof(buf1)/sizeof(dec1);
2775
b.len=sizeof(buf2)/sizeof(dec1);
2777
c.len=sizeof(buf3)/sizeof(dec1);
2782
printf("==== string2decimal ====\n");
2783
test_s2d("12345", "12345", 0);
2784
test_s2d("12345.", "12345", 0);
2785
test_s2d("123.45", "123.45", 0);
2786
test_s2d("-123.45", "-123.45", 0);
2787
test_s2d(".00012345000098765", "0.00012345000098765", 0);
2788
test_s2d(".12345000098765", "0.12345000098765", 0);
2789
test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
2790
test_s2d("1234500009876.5", "1234500009876.5", 0);
2792
test_s2d("123450000098765", "98765", 2);
2793
test_s2d("123450.000098765", "123450", 1);
2794
a.len=sizeof(buf1)/sizeof(dec1);
2795
test_s2d("123E5", "12300000", 0);
2796
test_s2d("123E-2", "1.23", 0);
2798
printf("==== decimal2double ====\n");
2799
test_d2f("12345", 0);
2800
test_d2f("123.45", 0);
2801
test_d2f("-123.45", 0);
2802
test_d2f("0.00012345000098765", 0);
2803
test_d2f("1234500009876.5", 0);
2805
printf("==== double2decimal ====\n");
2808
test_f2d(-123.45, 0);
2809
test_f2d(0.00012345000098765, 0);
2810
test_f2d(1234500009876.5, 0);
2812
printf("==== ulonglong2decimal ====\n");
2813
test_ull2d(ULL(12345), "12345", 0);
2814
test_ull2d(ULL(0), "0", 0);
2815
test_ull2d(ULL(18446744073709551615), "18446744073709551615", 0);
2817
printf("==== decimal2ulonglong ====\n");
2818
test_d2ull("12345", "12345", 0);
2819
test_d2ull("0", "0", 0);
2820
test_d2ull("18446744073709551615", "18446744073709551615", 0);
2821
test_d2ull("18446744073709551616", "18446744073", 2);
2822
test_d2ull("-1", "0", 2);
2823
test_d2ull("1.23", "1", 1);
2824
test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
2826
printf("==== longlong2decimal ====\n");
2827
test_ll2d(LL(-12345), "-12345", 0);
2828
test_ll2d(LL(-1), "-1", 0);
2829
test_ll2d(LL(-9223372036854775807), "-9223372036854775807", 0);
2830
test_ll2d(ULL(9223372036854775808), "-9223372036854775808", 0);
2832
printf("==== decimal2longlong ====\n");
2833
test_d2ll("18446744073709551615", "18446744073", 2);
2834
test_d2ll("-1", "-1", 0);
2835
test_d2ll("-1.23", "-1", 1);
2836
test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
2837
test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
2838
test_d2ll("9223372036854775808", "9223372036854775807", 2);
2840
printf("==== do_add ====\n");
2841
test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
2842
test_da(".1" ,".45", "0.55", 0);
2843
test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
2844
test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
2845
test_da("99999999" ,"1", "100000000", 0);
2846
test_da("989999999" ,"1", "990000000", 0);
2847
test_da("999999999" ,"1", "1000000000", 0);
2848
test_da("12345" ,"123.45", "12468.45", 0);
2849
test_da("-12345" ,"-123.45", "-12468.45", 0);
2850
test_ds("-12345" ,"123.45", "-12468.45", 0);
2851
test_ds("12345" ,"-123.45", "12468.45", 0);
2853
printf("==== do_sub ====\n");
2854
test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
2855
test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
2856
test_ds("9999900000000.5", ".555","9999899999999.945", 0);
2857
test_ds("1111.5551", "1111.555","0.0001", 0);
2858
test_ds(".555", ".555","0", 0);
2859
test_ds("10000000", "1","9999999", 0);
2860
test_ds("1000001000", ".1","1000000999.9", 0);
2861
test_ds("1000000000", ".1","999999999.9", 0);
2862
test_ds("12345", "123.45","12221.55", 0);
2863
test_ds("-12345", "-123.45","-12221.55", 0);
2864
test_da("-12345", "123.45","-12221.55", 0);
2865
test_da("12345", "-123.45","12221.55", 0);
2866
test_ds("123.45", "12345","-12221.55", 0);
2867
test_ds("-123.45", "-12345","12221.55", 0);
2868
test_da("123.45", "-12345","-12221.55", 0);
2869
test_da("-123.45", "12345","12221.55", 0);
2870
test_da("5", "-6.0","-1.0", 0);
2872
printf("==== decimal_mul ====\n");
2873
test_dm("12", "10","120", 0);
2874
test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
2875
test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
2876
test_dm("123456", "987654321","121931851853376", 0);
2877
test_dm("123456", "9876543210","1219318518533760", 0);
2878
test_dm("123", "0.01","1.23", 0);
2879
test_dm("123", "0","0", 0);
2881
printf("==== decimal_div ====\n");
2882
test_dv("120", "10","12.000000000", 0);
2883
test_dv("123", "0.01","12300.000000000", 0);
2884
test_dv("120", "100000000000.00000","0.000000001200000000", 0);
2885
test_dv("123", "0","", 4);
2886
test_dv("0", "0", "", 4);
2887
test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
2888
test_dv("121931851853376", "987654321","123456.000000000", 0);
2889
test_dv("0", "987","0", 0);
2890
test_dv("1", "3","0.333333333", 0);
2891
test_dv("1.000000000000", "3","0.333333333333333333", 0);
2892
test_dv("1", "1","1.000000000", 0);
2893
test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
2894
test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
2895
test_dv("10.000000000060", "2","5.000000000030000000", 0);
2897
printf("==== decimal_mod ====\n");
2898
test_md("234","10","4", 0);
2899
test_md("234.567","10.555","2.357", 0);
2900
test_md("-234.567","10.555","-2.357", 0);
2901
test_md("234.567","-10.555","2.357", 0);
2903
test_md("99999999999999999999999999999999999999","3","0", 0);
2904
if (c.buf[1] != 0x3ABECA)
2906
printf("%X - overflow\n", c.buf[1]);
2910
printf("==== decimal2bin/bin2decimal ====\n");
2911
test_d2b2d("-10.55", 4, 2,"-10.55", 0);
2912
test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
2913
test_d2b2d("12345", 5, 0,"12345", 0);
2914
test_d2b2d("12345", 10, 3,"12345.000", 0);
2915
test_d2b2d("123.45", 10, 3,"123.450", 0);
2916
test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
2917
test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
2918
test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
2919
test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
2920
test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
2921
test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
2922
test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
2923
test_d2b2d("000000000.01", 7, 3,"0.010", 0);
2924
test_d2b2d("123.4", 10, 2, "123.40", 0);
2927
printf("==== decimal_cmp ====\n");
2928
test_dc("12","13",-1);
2929
test_dc("13","12",1);
2930
test_dc("-10","10",-1);
2931
test_dc("10","-10",1);
2932
test_dc("-12","-13",1);
2933
test_dc("0","12",-1);
2934
test_dc("-10","0",-1);
2937
printf("==== decimal_round ====\n");
2938
test_ro("5678.123451",-4,TRUNCATE,"0", 0);
2939
test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
2940
test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
2941
test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
2942
test_ro("5678.123451",0,TRUNCATE,"5678", 0);
2943
test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
2944
test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
2945
test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
2946
test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
2947
test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
2948
test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
2949
test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
2950
memset(buf2, 33, sizeof(buf2));
2951
test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
2952
test_ro("15.1",0,HALF_UP,"15", 0);
2953
test_ro("15.5",0,HALF_UP,"16", 0);
2954
test_ro("15.9",0,HALF_UP,"16", 0);
2955
test_ro("-15.1",0,HALF_UP,"-15", 0);
2956
test_ro("-15.5",0,HALF_UP,"-16", 0);
2957
test_ro("-15.9",0,HALF_UP,"-16", 0);
2958
test_ro("15.1",1,HALF_UP,"15.1", 0);
2959
test_ro("-15.1",1,HALF_UP,"-15.1", 0);
2960
test_ro("15.17",1,HALF_UP,"15.2", 0);
2961
test_ro("15.4",-1,HALF_UP,"20", 0);
2962
test_ro("-15.4",-1,HALF_UP,"-20", 0);
2963
test_ro("5.4",-1,HALF_UP,"10", 0);
2964
test_ro(".999", 0, HALF_UP, "1", 0);
2965
memset(buf2, 33, sizeof(buf2));
2966
test_ro("999999999", -9, HALF_UP, "1000000000", 0);
2967
test_ro("15.1",0,HALF_EVEN,"15", 0);
2968
test_ro("15.5",0,HALF_EVEN,"16", 0);
2969
test_ro("14.5",0,HALF_EVEN,"14", 0);
2970
test_ro("15.9",0,HALF_EVEN,"16", 0);
2971
test_ro("15.1",0,CEILING,"16", 0);
2972
test_ro("-15.1",0,CEILING,"-15", 0);
2973
test_ro("15.1",0,FLOOR,"15", 0);
2974
test_ro("-15.1",0,FLOOR,"-16", 0);
2975
test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
2976
test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
2978
b.buf[0]=DIG_BASE+1;
2980
test_ro(".3", 0, HALF_UP, "0", 0);
2982
if (b.buf[0] != DIG_BASE+1)
2984
printf("%d - underflow\n", b.buf[0]);
2988
printf("==== max_decimal ====\n");
2992
test_mx(4,2,"99.99");
2993
test_mx(6,3,"999.999");
2994
test_mx(8,4,"9999.9999");
2995
test_mx(10,5,"99999.99999");
2996
test_mx(12,6,"999999.999999");
2997
test_mx(14,7,"9999999.9999999");
2998
test_mx(16,8,"99999999.99999999");
2999
test_mx(18,9,"999999999.999999999");
3000
test_mx(20,10,"9999999999.9999999999");
3001
test_mx(20,20,"0.99999999999999999999");
3002
test_mx(20,0,"99999999999999999999");
3003
test_mx(40,20,"99999999999999999999.99999999999999999999");
3005
printf("==== decimal2string ====\n");
3006
test_pr("123.123", 0, 0, 0, "123.123", 0);
3007
test_pr("123.123", 7, 3, '0', "123.123", 0);
3008
test_pr("123.123", 9, 3, '0', "00123.123", 0);
3009
test_pr("123.123", 9, 4, '0', "0123.1230", 0);
3010
test_pr("123.123", 9, 5, '0', "123.12300", 0);
3011
test_pr("123.123", 9, 2, '0', "000123.12", 1);
3012
test_pr("123.123", 9, 6, '0', "23.123000", 2);
3014
printf("==== decimal_shift ====\n");
3015
test_sh("123.123", 1, "1231.23", 0);
3016
test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
3017
test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
3018
test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
3019
test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
3020
test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
3021
test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
3022
test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
3023
test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
3024
test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3025
test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3026
test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3027
test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3028
test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3029
test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3030
test_sh("123", 1, "1230", 0);
3031
test_sh("123", 10, "1230000000000", 0);
3032
test_sh(".123", 1, "1.23", 0);
3033
test_sh(".123", 10, "1230000000", 0);
3034
test_sh(".123", 14, "12300000000000", 0);
3035
test_sh("000.000", 1000, "0", 0);
3036
test_sh("000.", 1000, "0", 0);
3037
test_sh(".000", 1000, "0", 0);
3038
test_sh("1", 1000, "1", 2);
3039
test_sh("123.123", -1, "12.3123", 0);
3040
test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
3041
test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
3042
test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
3043
test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
3044
test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
3045
test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
3046
test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
3047
test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
3048
test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
3049
test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
3050
test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
3052
test_sh("123.123", -2, "1.23123", 0);
3053
test_sh("123.123", -3, "0.123123", 0);
3054
test_sh("123.123", -6, "0.000123123", 0);
3055
test_sh("123.123", -7, "0.0000123123", 0);
3056
test_sh("123.123", -15, "0.000000000000123123", 0);
3057
test_sh("123.123", -16, "0.000000000000012312", 1);
3058
test_sh("123.123", -17, "0.000000000000001231", 1);
3059
test_sh("123.123", -18, "0.000000000000000123", 1);
3060
test_sh("123.123", -19, "0.000000000000000012", 1);
3061
test_sh("123.123", -20, "0.000000000000000001", 1);
3062
test_sh("123.123", -21, "0", 1);
3063
test_sh(".000000000123", -1, "0.0000000000123", 0);
3064
test_sh(".000000000123", -6, "0.000000000000000123", 0);
3065
test_sh(".000000000123", -7, "0.000000000000000012", 1);
3066
test_sh(".000000000123", -8, "0.000000000000000001", 1);
3067
test_sh(".000000000123", -9, "0", 1);
3068
test_sh(".000000000123", 1, "0.00000000123", 0);
3069
test_sh(".000000000123", 8, "0.0123", 0);
3070
test_sh(".000000000123", 9, "0.123", 0);
3071
test_sh(".000000000123", 10, "1.23", 0);
3072
test_sh(".000000000123", 17, "12300000", 0);
3073
test_sh(".000000000123", 18, "123000000", 0);
3074
test_sh(".000000000123", 19, "1230000000", 0);
3075
test_sh(".000000000123", 20, "12300000000", 0);
3076
test_sh(".000000000123", 21, "123000000000", 0);
3077
test_sh(".000000000123", 22, "1230000000000", 0);
3078
test_sh(".000000000123", 23, "12300000000000", 0);
3079
test_sh(".000000000123", 24, "123000000000000", 0);
3080
test_sh(".000000000123", 25, "1230000000000000", 0);
3081
test_sh(".000000000123", 26, "12300000000000000", 0);
3082
test_sh(".000000000123", 27, "123000000000000000", 0);
3083
test_sh(".000000000123", 28, "0.000000000123", 2);
3084
test_sh("123456789.987654321", -1, "12345678.998765432", 1);
3085
test_sh("123456789.987654321", -2, "1234567.899876543", 1);
3086
test_sh("123456789.987654321", -8, "1.234567900", 1);
3087
test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
3088
test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
3089
test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
3090
test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
3091
test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
3092
test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
3093
test_sh("123456789.987654321", -27, "0", 1);
3094
test_sh("123456789.987654321", 1, "1234567900", 1);
3095
test_sh("123456789.987654321", 2, "12345678999", 1);
3096
test_sh("123456789.987654321", 4, "1234567899877", 1);
3097
test_sh("123456789.987654321", 8, "12345678998765432", 1);
3098
test_sh("123456789.987654321", 9, "123456789987654321", 0);
3099
test_sh("123456789.987654321", 10, "123456789.987654321", 2);
3100
test_sh("123456789.987654321", 0, "123456789.987654321", 0);
3101
a.len= sizeof(buf1)/sizeof(dec1);
3103
printf("==== decimal_actual_fraction ====\n");
3104
test_fr("1.123456789000000000", "1.123456789");
3105
test_fr("1.12345678000000000", "1.12345678");
3106
test_fr("1.1234567000000000", "1.1234567");
3107
test_fr("1.123456000000000", "1.123456");
3108
test_fr("1.12345000000000", "1.12345");
3109
test_fr("1.1234000000000", "1.1234");
3110
test_fr("1.123000000000", "1.123");
3111
test_fr("1.12000000000", "1.12");
3112
test_fr("1.1000000000", "1.1");
3113
test_fr("1.000000000", "1");
3114
test_fr("1.0", "1");
3115
test_fr("10000000000000000000.0", "10000000000000000000");