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 };
140
static double scaler10[]= {
141
1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
143
static double scaler1[]= {
144
1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9
148
#define sanity(d) DBUG_ASSERT((d)->len > 0)
150
#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
151
(d)->buf[(d)->len-1] | 1))
154
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
157
if (unlikely(intg1+frac1 > (len))) \
159
if (unlikely(intg1 > (len))) \
163
error=E_DEC_OVERFLOW; \
168
error=E_DEC_TRUNCATED; \
175
#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
178
dec1 a=(from1)+(from2)+(carry); \
179
DBUG_ASSERT((carry) <= 1); \
180
if (((carry)= a >= DIG_BASE)) /* no division here! */ \
185
#define ADD2(to, from1, from2, carry) \
188
dec2 a=((dec2)(from1))+(from2)+(carry); \
189
if (((carry)= a >= DIG_BASE)) \
191
if (unlikely(a >= DIG_BASE)) \
199
#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
202
dec1 a=(from1)-(from2)-(carry); \
203
if (((carry)= a < 0)) \
208
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
211
dec1 a=(from1)-(from2)-(carry); \
212
if (((carry)= a < 0)) \
214
if (unlikely(a < 0)) \
223
Get maximum value for given precision and scale
227
precision/scale - see decimal_bin_size() below
228
to - decimal where where the result will be stored
229
to->buf and to->len must be set.
232
void max_decimal(int precision, int frac, decimal_t *to)
236
DBUG_ASSERT(precision && precision >= frac);
239
if ((intpart= to->intg= (precision - frac)))
241
int firstdigits= intpart % DIG_PER_DEC1;
243
*buf++= powers10[firstdigits] - 1; /* get 9 99 999 ... */
244
for(intpart/= DIG_PER_DEC1; intpart; intpart--)
248
if ((to->frac= frac))
250
int lastdigits= frac % DIG_PER_DEC1;
251
for(frac/= DIG_PER_DEC1; frac; frac--)
254
*buf= frac_max[lastdigits - 1];
259
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
261
int intg= from->intg, i;
262
dec1 *buf0= from->buf;
263
i= ((intg - 1) % DIG_PER_DEC1) + 1;
264
while (intg > 0 && *buf0 == 0)
272
for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ;
273
DBUG_ASSERT(intg > 0);
283
Count actual length of fraction part (without ending zeroes)
286
decimal_actual_fraction()
287
from number for processing
290
int decimal_actual_fraction(decimal_t *from)
292
int frac= from->frac, i;
293
dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
298
i= ((frac - 1) % DIG_PER_DEC1 + 1);
299
while (frac > 0 && *buf0 == 0)
307
for (i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1);
308
*buf0 % powers10[i++] == 0;
316
Convert decimal to its printable string representation
320
from - value to convert
321
to - points to buffer where string representation
323
*to_len - in: size of to buffer
324
out: length of the actually written string
325
fixed_precision - 0 if representation can be variable length and
326
fixed_decimals will not be checked in this case.
327
Put number as with fixed point position with this
328
number of digits (sign counted and decimal point is
330
fixed_decimals - number digits after point.
331
filler - character to fill gaps in case of fixed_precision > 0
334
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
337
int decimal2string(decimal_t *from, char *to, int *to_len,
338
int fixed_precision, int fixed_decimals,
341
int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
342
/* number digits before decimal point */
343
int fixed_intg= (fixed_precision ?
344
(fixed_precision - fixed_decimals) : 0);
347
dec1 *buf, *buf0=from->buf, tmp;
349
DBUG_ASSERT(*to_len >= 2+from->sign);
351
/* removing leading zeroes */
352
buf0= remove_leading_zeroes(from, &intg);
353
if (unlikely(intg+frac==0))
360
if (!(intg_len= fixed_precision ? fixed_intg : intg))
362
frac_len= fixed_precision ? fixed_decimals : frac;
363
len= from->sign + intg_len + test(frac) + frac_len;
366
if (frac > fixed_decimals)
368
error= E_DEC_TRUNCATED;
369
frac= fixed_decimals;
371
if (intg > fixed_intg)
373
error= E_DEC_OVERFLOW;
377
else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
380
error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
381
if (frac && j >= frac + 1) j--;
389
len= from->sign + intg_len + test(frac) + frac_len;
399
char *s1= s + intg_len;
400
fill= frac_len - frac;
401
buf=buf0+ROUND_UP(intg);
403
for (; frac>0; frac-=DIG_PER_DEC1)
406
for (i=min(frac, DIG_PER_DEC1); i; i--)
418
fill= intg_len - intg;
420
fill--; /* symbol 0 before digital point */
426
for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
429
for (i=min(intg, DIG_PER_DEC1); i; i--)
432
*--s='0'+(uchar)(x-y*10);
444
Return bounds of decimal digits in the number
448
from - decimal number for processing
449
start_result - index (from 0 ) of first decimal digits will
450
be written by this address
451
end_result - index of position just after last decimal digit
452
be written by this address
455
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
458
dec1 *buf_beg= from->buf;
459
dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
460
dec1 *buf_end= end - 1;
462
/* find non-zero digit from number begining */
463
while (buf_beg < end && *buf_beg == 0)
469
*start_result= *end_result= 0;
473
/* find non-zero decimal digit from number begining */
474
if (buf_beg == from->buf && from->intg)
476
start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1));
482
start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
485
for (; *buf_beg < powers10[i--]; start++) ;
486
*start_result= start; /* index of first decimal digit (from 0) */
488
/* find non-zero digit at the end */
489
while (buf_end > buf_beg && *buf_end == 0)
491
/* find non-zero decimal digit from the end */
492
if (buf_end == end - 1 && from->frac)
494
stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
495
(i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
496
i= DIG_PER_DEC1 - i + 1;
500
stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
503
for (; *buf_end % powers10[i++] == 0; stop--) ;
504
*end_result= stop; /* index of position after last decimal digit (from 0) */
509
Left shift for alignment of data in buffer
513
dec pointer to decimal number which have to be shifted
514
shift number of decimal digits on which it should be shifted
515
beg/end bounds of decimal digits (see digits_bounds())
518
Result fitting in the buffer should be garanted.
519
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
522
void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
524
dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
525
dec1 *end= dec->buf + ROUND_UP(last) - 1;
526
int c_shift= DIG_PER_DEC1 - shift;
527
DBUG_ASSERT(from >= dec->buf);
528
DBUG_ASSERT(end < dec->buf + dec->len);
529
if (beg % DIG_PER_DEC1 < shift)
530
*(from - 1)= (*from) / powers10[c_shift];
531
for(; from < end; from++)
532
*from= ((*from % powers10[c_shift]) * powers10[shift] +
533
(*(from + 1)) / powers10[c_shift]);
534
*from= (*from % powers10[c_shift]) * powers10[shift];
539
Right shift for alignment of data in buffer
543
dec pointer to decimal number which have to be shifted
544
shift number of decimal digits on which it should be shifted
545
beg/end bounds of decimal digits (see digits_bounds())
548
Result fitting in the buffer should be garanted.
549
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
552
void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
554
dec1 *from= dec->buf + ROUND_UP(last) - 1;
555
dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
556
int c_shift= DIG_PER_DEC1 - shift;
557
DBUG_ASSERT(from < dec->buf + dec->len);
558
DBUG_ASSERT(end >= dec->buf);
559
if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
560
*(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
561
for(; from > end; from--)
562
*from= (*from / powers10[shift] +
563
(*(from - 1) % powers10[shift]) * powers10[c_shift]);
564
*from= *from / powers10[shift];
569
Shift of decimal digits in given number (with rounding if it need)
573
dec number to be shifted
574
shift number of decimal positions
575
shift > 0 means shift to left shift
576
shift < 0 meand right shift
578
In fact it is multipling on 10^shift.
581
E_DEC_OVERFLOW operation lead to overflow, number is untoched
582
E_DEC_TRUNCATED number was rounded to fit into buffer
585
int decimal_shift(decimal_t *dec, int shift)
587
/* index of first non zero digit (all indexes from 0) */
589
/* index of position after last decimal digit */
591
/* index of digit position just after point */
592
int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
593
/* new point position */
594
int new_point= point + shift;
595
/* number of digits in result */
596
int digits_int, digits_frac;
597
/* length of result and new fraction in big digits*/
598
int new_len, new_frac_len;
606
digits_bounds(dec, &beg, &end);
610
decimal_make_zero(dec);
614
digits_int= new_point - beg;
615
set_if_bigger(digits_int, 0);
616
digits_frac= end - new_point;
617
set_if_bigger(digits_frac, 0);
619
if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
622
int lack= new_len - dec->len;
625
if (new_frac_len < lack)
626
return E_DEC_OVERFLOW; /* lack more then we have in fraction */
628
/* cat off fraction part to allow new number to fit in our buffer */
629
err= E_DEC_TRUNCATED;
631
diff= digits_frac - (new_frac_len * DIG_PER_DEC1);
632
/* Make rounding method as parameter? */
633
decimal_round(dec, dec, end - point - diff, HALF_UP);
635
digits_frac= new_frac_len * DIG_PER_DEC1;
640
we lost all digits (they will be shifted out of buffer), so we can
643
decimal_make_zero(dec);
644
return E_DEC_TRUNCATED;
648
if (shift % DIG_PER_DEC1)
650
int l_mini_shift, r_mini_shift, mini_shift;
653
Calculate left/right shift to align decimal digits inside our bug
658
l_mini_shift= shift % DIG_PER_DEC1;
659
r_mini_shift= DIG_PER_DEC1 - l_mini_shift;
661
It is left shift so prefer left shift, but if we have not place from
662
left, we have to have it from right, because we checked length of
665
do_left= l_mini_shift <= beg;
666
DBUG_ASSERT(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
670
r_mini_shift= (-shift) % DIG_PER_DEC1;
671
l_mini_shift= DIG_PER_DEC1 - r_mini_shift;
672
/* see comment above */
673
do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
674
DBUG_ASSERT(!do_left || l_mini_shift <= beg);
678
do_mini_left_shift(dec, l_mini_shift, beg, end);
679
mini_shift=- l_mini_shift;
683
do_mini_right_shift(dec, r_mini_shift, beg, end);
684
mini_shift= r_mini_shift;
686
new_point+= mini_shift;
688
If number is shifted and correctly aligned in buffer we can
691
if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1)
693
dec->intg= digits_int;
694
dec->frac= digits_frac;
695
return err; /* already shifted as it should be */
701
/* if new 'decimal front' is in first digit, we do not need move digits */
702
if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 ||
705
/* need to move digits */
711
d_shift= new_front / DIG_PER_DEC1;
712
to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
713
barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
714
DBUG_ASSERT(to >= dec->buf);
715
DBUG_ASSERT(barier + d_shift < dec->buf + dec->len);
716
for(; to <= barier; to++)
717
*to= *(to + d_shift);
718
for(barier+= d_shift; to <= barier; to++)
725
d_shift= (1 - new_front) / DIG_PER_DEC1;
726
to= dec->buf + ROUND_UP(end) - 1 + d_shift;
727
barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
728
DBUG_ASSERT(to < dec->buf + dec->len);
729
DBUG_ASSERT(barier - d_shift >= dec->buf);
730
for(; to >= barier; to--)
731
*to= *(to - d_shift);
732
for(barier-= d_shift; to >= barier; to--)
735
d_shift*= DIG_PER_DEC1;
742
If there are gaps then fill ren with 0.
744
Only one of following 'for' loops will work becouse beg <= end
746
beg= ROUND_UP(beg + 1) - 1;
747
end= ROUND_UP(end) - 1;
748
DBUG_ASSERT(new_point >= 0);
750
/* We don't want negative new_point below */
752
new_point= ROUND_UP(new_point) - 1;
758
dec->buf[new_point]=0;
759
} while (--new_point > end);
763
for (; new_point < beg; new_point++)
764
dec->buf[new_point]= 0;
766
dec->intg= digits_int;
767
dec->frac= digits_frac;
773
Convert string to decimal
777
from - value to convert. Doesn't have to be \0 terminated!
778
to - decimal where where the result will be stored
779
to->buf and to->len must be set.
780
end - Pointer to pointer to end of string. Will on return be
781
set to the char after the last used character
782
fixed - use to->intg, to->frac as limits for input number
785
to->intg and to->frac can be modified even when fixed=1
786
(but only decreased, in this case)
789
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
790
In case of E_DEC_FATAL_ERROR *to is set to decimal zero
791
(to make error handling easier)
795
internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed)
797
const char *s= from, *s1, *endp, *end_of_string= *end;
798
int i, intg, frac, error, intg1, frac1;
802
error= E_DEC_BAD_NUM; /* In case of bad number */
803
while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
805
if (s == end_of_string)
808
if ((to->sign= (*s == '-')))
814
while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
817
if (s < end_of_string && *s=='.')
820
while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
822
frac= (int) (endp - s - 1);
840
error=E_DEC_TRUNCATED;
845
error=E_DEC_OVERFLOW;
848
intg1=ROUND_UP(intg);
849
frac1=ROUND_UP(frac);
850
if (intg1+frac1 > to->len)
858
intg1=ROUND_UP(intg);
859
frac1=ROUND_UP(frac);
860
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
863
frac=frac1*DIG_PER_DEC1;
864
if (error == E_DEC_OVERFLOW)
865
intg=intg1*DIG_PER_DEC1;
868
/* Error is guranteed to be set here */
875
for (x=0, i=0; intg; intg--)
877
x+= (*--s - '0')*powers10[i];
879
if (unlikely(++i == DIG_PER_DEC1))
890
for (x=0, i=0; frac; frac--)
892
x= (*++s1 - '0') + x*10;
894
if (unlikely(++i == DIG_PER_DEC1))
902
*buf=x*powers10[DIG_PER_DEC1-i];
904
/* Handle exponent */
905
if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
908
longlong exponent= my_strtoll10(endp+1, (char**) &end_of_string,
911
if (end_of_string != endp +1) /* If at least one digit */
913
*end= (char*) end_of_string;
916
error= E_DEC_BAD_NUM;
919
if (exponent > INT_MAX/2 || (str_error == 0 && exponent < 0))
921
error= E_DEC_OVERFLOW;
924
if (exponent < INT_MIN/2 && error != E_DEC_OVERFLOW)
926
error= E_DEC_TRUNCATED;
929
if (error != E_DEC_OVERFLOW)
930
error= decimal_shift(to, (int) exponent);
936
decimal_make_zero(to);
942
Convert decimal to double
946
from - value to convert
947
to - result will be stored there
953
int decimal2double(decimal_t *from, double *to)
957
dec1 *buf= from->buf;
959
for (i= from->intg; i > 0; i-= DIG_PER_DEC1)
960
result= result * DIG_BASE + *buf++;
962
for (i= from->frac; i > 0; i-= DIG_PER_DEC1) {
963
result= result * DIG_BASE + *buf++;
967
DBUG_PRINT("info", ("interm.: %f %d %f", result, exp,
968
scaler10[exp / 10] * scaler1[exp % 10]));
970
result/= scaler10[exp / 10] * scaler1[exp % 10];
972
*to= from->sign ? -result : result;
974
DBUG_PRINT("info", ("result: %f (%lx)", *to, *(ulong *)to));
980
Convert double to decimal
984
from - value to convert
985
to - result will be stored there
988
E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
991
int double2decimal(double from, decimal_t *to)
993
/* TODO: fix it, when we'll have dtoa */
994
char buff[400], *end;
996
DBUG_ENTER("double2decimal");
997
length= my_sprintf(buff, (buff, "%.16G", from));
998
DBUG_PRINT("info",("from: %g from_as_str: %s", from, buff));
1000
res= string2decimal(buff, to, &end);
1001
DBUG_PRINT("exit", ("res: %d", res));
1006
static int ull2dec(ulonglong from, decimal_t *to)
1008
int intg1, error=E_DEC_OK;
1014
for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE) ;
1015
if (unlikely(intg1 > to->len))
1018
error=E_DEC_OVERFLOW;
1021
to->intg=intg1*DIG_PER_DEC1;
1023
for (buf=to->buf+intg1; intg1; intg1--)
1025
ulonglong y=x/DIG_BASE;
1026
*--buf=(dec1)(x-y*DIG_BASE);
1032
int ulonglong2decimal(ulonglong from, decimal_t *to)
1035
return ull2dec(from, to);
1038
int longlong2decimal(longlong from, decimal_t *to)
1040
if ((to->sign= from < 0))
1041
return ull2dec(-from, to);
1042
return ull2dec(from, to);
1045
int decimal2ulonglong(decimal_t *from, ulonglong *to)
1047
dec1 *buf=from->buf;
1054
return E_DEC_OVERFLOW;
1057
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1060
x=x*DIG_BASE + *buf++;
1061
if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
1064
return E_DEC_OVERFLOW;
1068
for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1070
return E_DEC_TRUNCATED;
1074
int decimal2longlong(decimal_t *from, longlong *to)
1076
dec1 *buf=from->buf;
1080
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1085
we're calculating -|from| instead of |from| here
1086
because |LONGLONG_MIN| > LONGLONG_MAX
1087
so we can convert -9223372036854775808 correctly
1089
x=x*DIG_BASE - *buf++;
1090
if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
1093
the decimal is bigger than any possible integer
1094
return border integer depending on the sign
1096
*to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
1097
return E_DEC_OVERFLOW;
1100
/* boundary case: 9223372036854775808 */
1101
if (unlikely(from->sign==0 && x == LONGLONG_MIN))
1104
return E_DEC_OVERFLOW;
1107
*to=from->sign ? x : -x;
1108
for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1110
return E_DEC_TRUNCATED;
1115
Convert decimal to its binary fixed-length representation
1116
two representations of the same length can be compared with memcmp
1117
with the correct -1/0/+1 result
1121
from - value to convert
1122
to - points to buffer where string representation should be stored
1123
precision/scale - see decimal_bin_size() below
1126
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1129
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1132
for storage decimal numbers are converted to the "binary" format.
1134
This format has the following properties:
1135
1. length of the binary representation depends on the {precision, scale}
1136
as provided by the caller and NOT on the intg/frac of the decimal to
1138
2. binary representations of the same {precision, scale} can be compared
1139
with memcmp - with the same result as decimal_cmp() of the original
1140
decimals (not taking into account possible precision loss during
1143
This binary format is as follows:
1144
1. First the number is converted to have a requested precision and scale.
1145
2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes
1147
3. The first intg % DIG_PER_DEC1 digits are stored in the reduced
1148
number of bytes (enough bytes to store this number of digits -
1150
4. same for frac - full decimal_digit_t's are stored as is,
1151
the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes.
1152
5. If the number is negative - every byte is inversed.
1153
5. The very first bit of the resulting byte array is inverted (because
1154
memcmp compares unsigned bytes, see property 2 above)
1160
internally is represented as 3 decimal_digit_t's
1162
1 234567890 123400000
1164
(assuming we want a binary representation with precision=14, scale=4)
1167
00-00-00-01 0D-FB-38-D2 07-5A-EF-40
1169
now, middle decimal_digit_t is full - it stores 9 decimal digits. It goes
1170
into binary representation as is:
1173
........... 0D-FB-38-D2 ............
1175
First decimal_digit_t has only one decimal digit. We can store one digit in
1176
one byte, no need to waste four:
1178
01 0D-FB-38-D2 ............
1180
now, last digit. It's 123400000. We can store 1234 in two bytes:
1182
01 0D-FB-38-D2 04-D2
1184
So, we've packed 12 bytes number in 7 bytes.
1185
And now we invert the highest bit to get the final result:
1187
81 0D FB 38 D2 04 D2
1189
And for -1234567890.1234 it would be
1191
7E F2 04 37 2D FB 2D
1193
int decimal2bin(decimal_t *from, uchar *to, int precision, int frac)
1195
dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1196
int error=E_DEC_OK, intg=precision-frac,
1197
isize1, intg1, intg1x, from_intg,
1198
intg0=intg/DIG_PER_DEC1,
1199
frac0=frac/DIG_PER_DEC1,
1200
intg0x=intg-intg0*DIG_PER_DEC1,
1201
frac0x=frac-frac0*DIG_PER_DEC1,
1202
frac1=from->frac/DIG_PER_DEC1,
1203
frac1x=from->frac-frac1*DIG_PER_DEC1,
1204
isize0=intg0*sizeof(dec1)+dig2bytes[intg0x],
1205
fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x],
1206
fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
1207
const int orig_isize0= isize0;
1208
const int orig_fsize0= fsize0;
1211
buf1= remove_leading_zeroes(from, &from_intg);
1213
if (unlikely(from_intg+fsize1==0))
1215
mask=0; /* just in case */
1220
intg1=from_intg/DIG_PER_DEC1;
1221
intg1x=from_intg-intg1*DIG_PER_DEC1;
1222
isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
1224
if (intg < from_intg)
1226
buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
1227
intg1=intg0; intg1x=intg0x;
1228
error=E_DEC_OVERFLOW;
1230
else if (isize0 > isize1)
1232
while (isize0-- > isize1)
1235
if (fsize0 < fsize1)
1237
frac1=frac0; frac1x=frac0x;
1238
error=E_DEC_TRUNCATED;
1240
else if (fsize0 > fsize1 && frac1x)
1257
int i=dig2bytes[intg1x];
1258
dec1 x=(*buf1++ % powers10[intg1x]) ^ mask;
1261
case 1: mi_int1store(to, x); break;
1262
case 2: mi_int2store(to, x); break;
1263
case 3: mi_int3store(to, x); break;
1264
case 4: mi_int4store(to, x); break;
1265
default: DBUG_ASSERT(0);
1270
/* intg1+frac1 part */
1271
for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=sizeof(dec1))
1273
dec1 x=*buf1++ ^ mask;
1274
DBUG_ASSERT(sizeof(dec1) == 4);
1275
mi_int4store(to, x);
1282
int i=dig2bytes[frac1x],
1283
lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x);
1284
while (frac1x < lim && dig2bytes[frac1x] == i)
1286
x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask;
1289
case 1: mi_int1store(to, x); break;
1290
case 2: mi_int2store(to, x); break;
1291
case 3: mi_int3store(to, x); break;
1292
case 4: mi_int4store(to, x); break;
1293
default: DBUG_ASSERT(0);
1297
if (fsize0 > fsize1)
1299
uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
1301
while (fsize0-- > fsize1 && to < to_end)
1306
/* Check that we have written the whole decimal and nothing more */
1307
DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0);
1312
Restores decimal from its binary fixed-length representation
1316
from - value to convert
1318
precision/scale - see decimal_bin_size() below
1322
the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1325
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1328
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
1330
int error=E_DEC_OK, intg=precision-scale,
1331
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1332
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1333
intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1334
dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
1337
int bin_size= decimal_bin_size(precision, scale);
1340
d_copy= (uchar*) my_alloca(bin_size);
1341
memcpy(d_copy, from, bin_size);
1345
FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1346
if (unlikely(error))
1348
if (intg1 < intg0+(intg0x>0))
1350
from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1);
1351
frac0=frac0x=intg0x=0;
1361
to->sign=(mask != 0);
1362
to->intg=intg0*DIG_PER_DEC1+intg0x;
1363
to->frac=frac0*DIG_PER_DEC1+frac0x;
1367
int i=dig2bytes[intg0x];
1371
case 1: x=mi_sint1korr(from); break;
1372
case 2: x=mi_sint2korr(from); break;
1373
case 3: x=mi_sint3korr(from); break;
1374
case 4: x=mi_sint4korr(from); break;
1375
default: DBUG_ASSERT(0);
1379
if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1])
1381
if (buf > to->buf || *buf != 0)
1386
for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1388
DBUG_ASSERT(sizeof(dec1) == 4);
1389
*buf=mi_sint4korr(from) ^ mask;
1390
if (((uint32)*buf) > DIG_MAX)
1392
if (buf > to->buf || *buf != 0)
1395
to->intg-=DIG_PER_DEC1;
1397
DBUG_ASSERT(to->intg >=0);
1398
for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1400
DBUG_ASSERT(sizeof(dec1) == 4);
1401
*buf=mi_sint4korr(from) ^ mask;
1402
if (((uint32)*buf) > DIG_MAX)
1408
int i=dig2bytes[frac0x];
1412
case 1: x=mi_sint1korr(from); break;
1413
case 2: x=mi_sint2korr(from); break;
1414
case 3: x=mi_sint3korr(from); break;
1415
case 4: x=mi_sint4korr(from); break;
1416
default: DBUG_ASSERT(0);
1418
*buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
1419
if (((uint32)*buf) > DIG_MAX)
1428
decimal_make_zero(((decimal_t*) to));
1429
return(E_DEC_BAD_NUM);
1433
Returns the size of array to hold a decimal with given precision and scale
1437
(multiply by sizeof(dec1) to get the size if bytes)
1440
int decimal_size(int precision, int scale)
1442
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1443
return ROUND_UP(precision-scale)+ROUND_UP(scale);
1447
Returns the size of array to hold a binary representation of a decimal
1453
int decimal_bin_size(int precision, int scale)
1455
int intg=precision-scale,
1456
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1457
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
1459
DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
1460
return intg0*sizeof(dec1)+dig2bytes[intg0x]+
1461
frac0*sizeof(dec1)+dig2bytes[frac0x];
1465
Rounds the decimal to "scale" digits
1469
from - decimal to round,
1470
to - result buffer. from==to is allowed
1471
scale - to what position to round. can be negative!
1472
mode - round to nearest even or truncate
1475
scale can be negative !
1476
one TRUNCATED error (line XXX below) isn't treated very logical :(
1479
E_DEC_OK/E_DEC_TRUNCATED
1483
decimal_round(decimal_t *from, decimal_t *to, int scale,
1484
decimal_round_mode mode)
1486
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1487
frac1=ROUND_UP(from->frac), UNINIT_VAR(round_digit),
1488
intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1489
intg1=ROUND_UP(from->intg +
1490
(((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1491
dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1498
case HALF_EVEN: round_digit=5; break;
1499
case CEILING: round_digit= from->sign ? 10 : 0; break;
1500
case FLOOR: round_digit= from->sign ? 0 : 10; break;
1501
case TRUNCATE: round_digit=10; break;
1502
default: DBUG_ASSERT(0);
1505
if (unlikely(frac0+intg0 > len))
1508
scale=frac0*DIG_PER_DEC1;
1509
error=E_DEC_TRUNCATED;
1512
if (scale+from->intg < 0)
1514
decimal_make_zero(to);
1518
if (to != from || intg1>intg0)
1520
dec1 *p0= buf0+intg0+max(frac1, frac0);
1521
dec1 *p1= buf1+intg1+max(frac1, frac0);
1525
if (unlikely(intg1 > intg0))
1531
to->sign=from->sign;
1532
to->intg=min(intg0, len)*DIG_PER_DEC1;
1538
while (frac0-- > frac1)
1543
if (scale >= from->frac)
1544
goto done; /* nothing to do */
1546
buf0+=intg0+frac0-1;
1547
buf1+=intg0+frac0-1;
1548
if (scale == frac0*DIG_PER_DEC1)
1551
DBUG_ASSERT(frac0+intg0 >= 0);
1552
switch (round_digit) {
1555
dec1 *p0= buf0 + (frac1-frac0);
1556
for (; p0 > buf0; p0--)
1568
x= buf0[1]/DIG_MASK;
1569
do_inc= (x>5) || ((x == 5) &&
1570
(mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
1583
else if (frac0+intg0==0)
1585
decimal_make_zero(to);
1591
/* TODO - fix this code as it won't work for CEILING mode */
1592
int pos=frac0*DIG_PER_DEC1-scale-1;
1593
DBUG_ASSERT(frac0+intg0 > 0);
1594
x=*buf1 / powers10[pos];
1596
if (y > round_digit ||
1597
(round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
1599
*buf1=powers10[pos]*(x-y);
1602
In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal_digit_t's inside
1603
the buffer are as follows.
1608
Hence we need to set the 2nd field to 0.
1609
The same holds if we round 1.5e-9 to 2e-9.
1613
dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0);
1614
dec1 *end= to->buf + len;
1619
if (*buf1 >= DIG_BASE)
1623
while (carry && --buf1 >= to->buf)
1624
ADD(*buf1, *buf1, 0, carry);
1625
if (unlikely(carry))
1627
/* shifting the number to create space for new digit */
1628
if (frac0+intg0 >= len)
1631
scale=frac0*DIG_PER_DEC1;
1632
error=E_DEC_TRUNCATED; /* XXX */
1634
for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--)
1648
if (buf1-- == to->buf)
1650
/* making 'zero' with the proper scale */
1651
dec1 *p0= to->buf + frac0 + 1;
1653
to->frac= max(scale, 0);
1655
for (buf1= to->buf; buf1<p0; buf1++)
1662
/* Here we check 999.9 -> 1000 case when we need to increase intg */
1663
first_dig= to->intg % DIG_PER_DEC1;
1664
if (first_dig && (*buf1 >= powers10[first_dig]))
1676
Returns the size of the result of the operation
1679
decimal_result_size()
1680
from1 - operand of the unary operation or first operand of the
1682
from2 - second operand of the binary operation
1683
op - operation. one char '+', '-', '*', '/' are allowed
1684
others may be added later
1685
param - extra param to the operation. unused for '+', '-', '*'
1686
scale increment for '/'
1689
returned valued may be larger than the actual buffer requred
1690
in the operation, as decimal_result_size, by design, operates on
1691
precision/scale values only and not on the actual decimal number
1694
size of to->buf array in dec1 elements. to get size in bytes
1695
multiply by sizeof(dec1)
1698
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1702
return ROUND_UP(max(from1->intg, from2->intg)) +
1703
ROUND_UP(max(from1->frac, from2->frac));
1705
return ROUND_UP(max(from1->intg, from2->intg)+1) +
1706
ROUND_UP(max(from1->frac, from2->frac));
1708
return ROUND_UP(from1->intg+from2->intg)+
1709
ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1711
return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1712
default: DBUG_ASSERT(0);
1714
return -1; /* shut up the warning */
1717
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1719
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1720
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1721
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1722
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1726
/* is there a need for extra word because of carry ? */
1727
x=intg1 > intg2 ? from1->buf[0] :
1728
intg2 > intg1 ? from2->buf[0] :
1729
from1->buf[0] + from2->buf[0] ;
1730
if (unlikely(x > DIG_MAX-1)) /* yes, there is */
1733
to->buf[0]=0; /* safety */
1736
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1737
if (unlikely(error == E_DEC_OVERFLOW))
1739
max_decimal(to->len * DIG_PER_DEC1, 0, to);
1743
buf0=to->buf+intg0+frac0;
1745
to->sign=from1->sign;
1746
to->frac=max(from1->frac, from2->frac);
1747
to->intg=intg0*DIG_PER_DEC1;
1748
if (unlikely(error))
1750
set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1751
set_if_smaller(frac1, frac0);
1752
set_if_smaller(frac2, frac0);
1753
set_if_smaller(intg1, intg0);
1754
set_if_smaller(intg2, intg0);
1757
/* part 1 - max(frac) ... min (frac) */
1760
buf1=from1->buf+intg1+frac1;
1761
stop=from1->buf+intg1+frac2;
1762
buf2=from2->buf+intg2+frac2;
1763
stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
1767
buf1=from2->buf+intg2+frac2;
1768
stop=from2->buf+intg2+frac1;
1769
buf2=from1->buf+intg1+frac1;
1770
stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
1775
/* part 2 - min(frac) ... min(intg) */
1777
while (buf1 > stop2)
1779
ADD(*--buf0, *--buf1, *--buf2, carry);
1782
/* part 3 - min(intg) ... max(intg) */
1783
buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1784
((stop=from2->buf)+intg2-intg1) ;
1787
ADD(*--buf0, *--buf1, 0, carry);
1790
if (unlikely(carry))
1792
DBUG_ASSERT(buf0 == to->buf || buf0 == to->buf+1);
1798
if to==0, return -1/0/+1 - the result of the comparison */
1799
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1801
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1802
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1803
int frac0=max(frac1, frac2), error;
1804
dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1806
/* let carry:=1 if from2 > from1 */
1807
start1=buf1=from1->buf; stop1=buf1+intg1;
1808
start2=buf2=from2->buf; stop2=buf2+intg2;
1809
if (unlikely(*buf1 == 0))
1811
while (buf1 < stop1 && *buf1 == 0)
1814
intg1= (int) (stop1-buf1);
1816
if (unlikely(*buf2 == 0))
1818
while (buf2 < stop2 && *buf2 == 0)
1821
intg2= (int) (stop2-buf2);
1825
else if (intg2 == intg1)
1827
dec1 *end1= stop1 + (frac1 - 1);
1828
dec1 *end2= stop2 + (frac2 - 1);
1829
while (unlikely((buf1 <= end1) && (*end1 == 0)))
1831
while (unlikely((buf2 <= end2) && (*end2 == 0)))
1833
frac1= (int) (end1 - stop1) + 1;
1834
frac2= (int) (end2 - stop2) + 1;
1835
while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
1840
carry= *buf2 > *buf1;
1848
else /* short-circuit everything: from1 == from2 */
1850
if (to == 0) /* decimal_cmp() */
1852
decimal_make_zero(to);
1858
if (to == 0) /* decimal_cmp() */
1859
return carry == from1->sign ? 1 : -1;
1863
to->sign=from1->sign;
1865
/* ensure that always from1 > from2 (and intg1 >= intg2) */
1868
swap_variables(decimal_t *,from1,from1);
1869
swap_variables(dec1 *,start1, start2);
1870
swap_variables(int,intg1,intg2);
1871
swap_variables(int,frac1,frac2);
1872
to->sign= 1 - to->sign;
1875
FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
1876
buf0=to->buf+intg1+frac0;
1878
to->frac=max(from1->frac, from2->frac);
1879
to->intg=intg1*DIG_PER_DEC1;
1880
if (unlikely(error))
1882
set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1883
set_if_smaller(frac1, frac0);
1884
set_if_smaller(frac2, frac0);
1885
set_if_smaller(intg2, intg1);
1889
/* part 1 - max(frac) ... min (frac) */
1892
buf1=start1+intg1+frac1;
1893
stop1=start1+intg1+frac2;
1894
buf2=start2+intg2+frac2;
1895
while (frac0-- > frac1)
1897
while (buf1 > stop1)
1902
buf1=start1+intg1+frac1;
1903
buf2=start2+intg2+frac2;
1904
stop2=start2+intg2+frac1;
1905
while (frac0-- > frac2)
1907
while (buf2 > stop2)
1909
SUB(*--buf0, 0, *--buf2, carry);
1913
/* part 2 - min(frac) ... intg2 */
1914
while (buf2 > start2)
1916
SUB(*--buf0, *--buf1, *--buf2, carry);
1919
/* part 3 - intg2 ... intg1 */
1920
while (carry && buf1 > start1)
1922
SUB(*--buf0, *--buf1, 0, carry);
1925
while (buf1 > start1)
1928
while (buf0 > to->buf)
1934
int decimal_intg(decimal_t *from)
1938
tmp_res= remove_leading_zeroes(from, &res);
1942
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1944
if (likely(from1->sign == from2->sign))
1945
return do_add(from1, from2, to);
1946
return do_sub(from1, from2, to);
1949
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1951
if (likely(from1->sign == from2->sign))
1952
return do_sub(from1, from2, to);
1953
return do_add(from1, from2, to);
1956
int decimal_cmp(decimal_t *from1, decimal_t *from2)
1958
if (likely(from1->sign == from2->sign))
1959
return do_sub(from1, from2, 0);
1960
return from1->sign > from2->sign ? -1 : 1;
1963
int decimal_is_zero(decimal_t *from)
1965
dec1 *buf1=from->buf,
1966
*end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
1974
multiply two decimals
1978
from1, from2 - factors
1982
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
1985
in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
1986
and 63-digit number will take only 7 dec1 words (basically a 7-digit
1987
"base 999999999" number). Thus there's no need in fast multiplication
1988
algorithms, 7-digit numbers can be multiplied with a naive O(n*n)
1991
XXX if this library is to be used with huge numbers of thousands of
1992
digits, fast multiplication must be implemented.
1994
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
1996
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1997
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1998
intg0=ROUND_UP(from1->intg+from2->intg),
1999
frac0=frac1+frac2, error, i, j, d_to_move;
2000
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2001
*start2, *stop2, *stop1, *start0, carry;
2005
i=intg0; /* save 'ideal' values */
2007
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); /* bound size */
2008
to->sign=from1->sign != from2->sign;
2009
to->frac=from1->frac+from2->frac; /* store size in digits */
2010
to->intg=intg0*DIG_PER_DEC1;
2012
if (unlikely(error))
2014
set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
2015
set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
2016
if (unlikely(i > intg0)) /* bounded integer-part */
2022
frac1=frac2=0; /* frac0 is already 0 here */
2024
else /* bounded fract part */
2040
start0=to->buf+intg0+frac0-1;
2041
start2=buf2+frac2-1;
2045
bzero(to->buf, (intg0+frac0)*sizeof(dec1));
2047
for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
2050
for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
2053
dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2054
hi=(dec1)(p/DIG_BASE);
2055
lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2056
ADD2(*buf0, *buf0, lo, carry);
2062
return E_DEC_OVERFLOW;
2063
ADD2(*buf0, *buf0, 0, carry);
2065
for (buf0--; carry; buf0--)
2068
return E_DEC_OVERFLOW;
2069
ADD(*buf0, *buf0, 0, carry);
2073
/* Now we have to check for -0.000 case */
2077
dec1 *end= to->buf + intg0 + frac0;
2078
DBUG_ASSERT(buf != end);
2085
/* We got decimal zero */
2086
decimal_make_zero(to);
2092
d_to_move= intg0 + ROUND_UP(to->frac);
2093
while (!*buf1 && (to->intg > DIG_PER_DEC1))
2096
to->intg-= DIG_PER_DEC1;
2101
dec1 *cur_d= to->buf;
2102
for (; d_to_move--; cur_d++, buf1++)
2109
naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2110
it's ok for short numbers
2111
also we're using alloca() to allocate a temporary buffer
2113
XXX if this library is to be used with huge numbers of thousands of
2114
digits, fast division must be implemented and alloca should be
2115
changed to malloc (or at least fallback to malloc if alloca() fails)
2116
but then, decimal_mul() should be rewritten too :(
2118
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2119
decimal_t *to, decimal_t *mod, int scale_incr)
2121
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2122
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2123
UNINIT_VAR(error), i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2124
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2125
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2126
dec2 norm_factor, x, guess, y;
2133
/* removing all the leading zeroes */
2134
i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
2135
while (prec2 > 0 && *buf2 == 0)
2141
if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
2142
return E_DEC_DIV_ZERO;
2143
for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
2144
DBUG_ASSERT(prec2 > 0);
2146
i=((prec1-1) % DIG_PER_DEC1)+1;
2147
while (prec1 > 0 && *buf1 == 0)
2154
{ /* short-circuit everything: from1 == 0 */
2155
decimal_make_zero(to);
2158
for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2159
DBUG_ASSERT(prec1 > 0);
2161
/* let's fix scale_incr, taking into account frac1,frac2 increase */
2162
if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
2165
dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
2168
dintg/=DIG_PER_DEC1;
2172
intg0=ROUND_UP(dintg);
2175
/* we're calculating N1 % N2.
2176
The result will have
2177
frac=max(frac1, frac2), as for subtraction
2180
to->sign=from1->sign;
2181
to->frac=max(from1->frac, from2->frac);
2187
we're calculating N1/N2. N1 is in the buf1, has prec1 digits
2188
N2 is in the buf2, has prec2 digits. Scales are frac1 and
2190
Thus, the result will have
2191
frac = ROUND_UP(frac1+frac2+scale_incr)
2193
intg = (prec1-frac1) - (prec2-frac2) + 1
2196
frac0=ROUND_UP(frac1+frac2+scale_incr);
2197
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2198
to->sign=from1->sign != from2->sign;
2199
to->intg=intg0*DIG_PER_DEC1;
2200
to->frac=frac0*DIG_PER_DEC1;
2203
stop0=buf0+intg0+frac0;
2204
if (likely(div_mod))
2208
len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2209
set_if_bigger(len1, 3);
2210
if (!(tmp1=(dec1 *)my_alloca(len1*sizeof(dec1))))
2212
memcpy(tmp1, buf1, i*sizeof(dec1));
2213
bzero(tmp1+i, (len1-i)*sizeof(dec1));
2218
stop2=buf2+ROUND_UP(prec2)-1;
2220
/* removing end zeroes */
2221
while (*stop2 == 0 && stop2 >= start2)
2223
len2= (int) (stop2++ - start2);
2226
calculating norm2 (normalized *start2) - we need *start2 to be large
2227
(at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to
2228
normalize input numbers (as we don't make a copy of the divisor).
2229
Thus we normalize first dec1 of buf2 only, and we'll normalize *start1
2230
on the fly for the purpose of guesstimation only.
2231
It's also faster, as we're saving on normalization of buf2
2233
norm_factor=DIG_BASE/(*start2+1);
2234
norm2=(dec1)(norm_factor*start2[0]);
2236
norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
2238
if (*start1 < *start2)
2244
for (; buf0 < stop0; buf0++)
2246
/* short-circuit, if possible */
2247
if (unlikely(dcarry == 0 && *start1 < *start2))
2251
/* D3: make a guess */
2252
x=start1[0]+((dec2)dcarry)*DIG_BASE;
2254
guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
2255
if (unlikely(guess >= DIG_BASE))
2259
/* hmm, this is a suspicious trick - I removed normalization here */
2260
if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
2262
if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
2264
DBUG_ASSERT(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
2267
/* D4: multiply and subtract */
2270
DBUG_ASSERT(buf1 < stop1);
2271
for (carry=0; buf2 > start2; buf1--)
2274
x=guess * (*--buf2);
2275
hi=(dec1)(x/DIG_BASE);
2276
lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2277
SUB2(*buf1, *buf1, lo, carry);
2280
carry= dcarry < carry;
2282
/* D5: check the remainder */
2283
if (unlikely(carry))
2285
/* D6: correct the guess */
2289
for (carry=0; buf2 > start2; buf1--)
2291
ADD(*buf1, *buf1, *--buf2, carry);
2295
if (likely(div_mod))
2303
now the result is in tmp1, it has
2305
frac=max(frac1, frac2)=to->frac
2310
intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2311
frac0=ROUND_UP(to->frac);
2313
if (unlikely(frac0==0 && intg0==0))
2315
decimal_make_zero(to);
2320
if (unlikely(-intg0 >= to->len))
2322
decimal_make_zero(to);
2323
error=E_DEC_TRUNCATED;
2334
if (unlikely(intg0 > to->len))
2338
error=E_DEC_OVERFLOW;
2341
DBUG_ASSERT(intg0 <= ROUND_UP(from2->intg));
2342
stop1=start1+frac0+intg0;
2343
to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2345
if (unlikely(intg0+frac0 > to->len))
2347
stop1-=frac0+intg0-to->len;
2348
frac0=to->len-intg0;
2349
to->frac=frac0*DIG_PER_DEC1;
2350
error=E_DEC_TRUNCATED;
2352
DBUG_ASSERT(buf0 + (stop1 - start1) <= to->buf + to->len);
2353
while (start1 < stop1)
2362
division of two decimals
2371
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2378
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2380
return do_div_mod(from1, from2, to, 0, scale_incr);
2393
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2399
the modulus R in R = M mod N
2405
R = M - k*N, where k is integer
2407
thus, there's no requirement for M or N to be integers
2410
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2412
return do_div_mod(from1, from2, 0, to, 0);
2419
char buf1[100], buf2[100], buf3[100];
2421
void dump_decimal(decimal_t *d)
2424
printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2425
for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2426
printf("%09d, ", d->buf[i]);
2427
printf("%09d} */ ", d->buf[i]);
2431
void check_result_code(int actual, int want)
2435
printf("\n^^^^^^^^^^^^^ must return %d\n", want);
2441
void print_decimal(decimal_t *d, const char *orig, int actual, int want)
2446
if (full) dump_decimal(d);
2447
decimal2string(d, s, &slen, 0, 0, 0);
2449
check_result_code(actual, want);
2450
if (orig && strcmp(orig, s))
2452
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2462
/***********************************/
2463
printf("==== decimal2string ====\n");
2464
a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
2466
res=decimal2string(&a, s, &slen, 0, 0, 0);
2467
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2469
a.buf[1]=987000000; a.frac=3;
2471
res=decimal2string(&a, s, &slen, 0, 0, 0);
2472
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2476
res=decimal2string(&a, s, &slen, 0, 0, 0);
2477
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2480
res=decimal2string(&a, s, &slen, 0, 0, 0);
2481
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2484
res=decimal2string(&a, s, &slen, 0, 0, 0);
2485
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2487
a.buf[0]=987000000; a.frac=3; a.intg=0;
2489
res=decimal2string(&a, s, &slen, 0, 0, 0);
2490
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
2493
void test_s2d(const char *s, const char *orig, int ex)
2497
sprintf(s1, "'%s'", s);
2499
printf("len=%2d %-30s => res=%d ", a.len, s1,
2500
(res= string2decimal(s, &a, &end)));
2501
print_decimal(&a, orig, res, ex);
2505
void test_d2f(const char *s, int ex)
2511
sprintf(s1, "'%s'", s);
2513
string2decimal(s, &a, &end);
2514
res=decimal2double(&a, &x);
2515
if (full) dump_decimal(&a);
2516
printf("%-40s => res=%d %.*g\n", s1, res, a.intg+a.frac, x);
2517
check_result_code(res, ex);
2520
void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
2522
char s1[100], buf[100], *end;
2523
int res, i, size=decimal_bin_size(p, s);
2525
sprintf(s1, "'%s'", str);
2527
string2decimal(str, &a, &end);
2528
res=decimal2bin(&a, buf, p, s);
2529
printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
2533
for (i=0; i < size; i++)
2534
printf("%02x", ((uchar *)buf)[i]);
2536
res=bin2decimal(buf, &a, p, s);
2537
printf(" => res=%d ", res);
2538
print_decimal(&a, orig, res, ex);
2542
void test_f2d(double from, int ex)
2546
res=double2decimal(from, &a);
2547
printf("%-40.*f => res=%d ", DBL_DIG-2, from, res);
2548
print_decimal(&a, 0, res, ex);
2552
void test_ull2d(ulonglong from, const char *orig, int ex)
2557
res=ulonglong2decimal(from, &a);
2558
longlong10_to_str(from,s,10);
2559
printf("%-40s => res=%d ", s, res);
2560
print_decimal(&a, orig, res, ex);
2564
void test_ll2d(longlong from, const char *orig, int ex)
2569
res=longlong2decimal(from, &a);
2570
longlong10_to_str(from,s,-10);
2571
printf("%-40s => res=%d ", s, res);
2572
print_decimal(&a, orig, res, ex);
2576
void test_d2ull(const char *s, const char *orig, int ex)
2583
string2decimal(s, &a, &end);
2584
res=decimal2ulonglong(&a, &x);
2585
if (full) dump_decimal(&a);
2586
longlong10_to_str(x,s1,10);
2587
printf("%-40s => res=%d %s\n", s, res, s1);
2588
check_result_code(res, ex);
2589
if (orig && strcmp(orig, s1))
2591
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2596
void test_d2ll(const char *s, const char *orig, int ex)
2603
string2decimal(s, &a, &end);
2604
res=decimal2longlong(&a, &x);
2605
if (full) dump_decimal(&a);
2606
longlong10_to_str(x,s1,-10);
2607
printf("%-40s => res=%d %s\n", s, res, s1);
2608
check_result_code(res, ex);
2609
if (orig && strcmp(orig, s1))
2611
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2616
void test_da(const char *s1, const char *s2, const char *orig, int ex)
2620
sprintf(s, "'%s' + '%s'", s1, s2);
2622
string2decimal(s1, &a, &end);
2624
string2decimal(s2, &b, &end);
2625
res=decimal_add(&a, &b, &c);
2626
printf("%-40s => res=%d ", s, res);
2627
print_decimal(&c, orig, res, ex);
2631
void test_ds(const char *s1, const char *s2, const char *orig, int ex)
2635
sprintf(s, "'%s' - '%s'", s1, s2);
2637
string2decimal(s1, &a, &end);
2639
string2decimal(s2, &b, &end);
2640
res=decimal_sub(&a, &b, &c);
2641
printf("%-40s => res=%d ", s, res);
2642
print_decimal(&c, orig, res, ex);
2646
void test_dc(const char *s1, const char *s2, int orig)
2650
sprintf(s, "'%s' <=> '%s'", s1, s2);
2652
string2decimal(s1, &a, &end);
2654
string2decimal(s2, &b, &end);
2655
res=decimal_cmp(&a, &b);
2656
printf("%-40s => res=%d\n", s, res);
2659
printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
2664
void test_dm(const char *s1, const char *s2, const char *orig, int ex)
2668
sprintf(s, "'%s' * '%s'", s1, s2);
2670
string2decimal(s1, &a, &end);
2672
string2decimal(s2, &b, &end);
2673
res=decimal_mul(&a, &b, &c);
2674
printf("%-40s => res=%d ", s, res);
2675
print_decimal(&c, orig, res, ex);
2679
void test_dv(const char *s1, const char *s2, const char *orig, int ex)
2683
sprintf(s, "'%s' / '%s'", s1, s2);
2685
string2decimal(s1, &a, &end);
2687
string2decimal(s2, &b, &end);
2688
res=decimal_div(&a, &b, &c, 5);
2689
printf("%-40s => res=%d ", s, res);
2690
check_result_code(res, ex);
2691
if (res == E_DEC_DIV_ZERO)
2692
printf("E_DEC_DIV_ZERO");
2694
print_decimal(&c, orig, res, ex);
2698
void test_md(const char *s1, const char *s2, const char *orig, int ex)
2702
sprintf(s, "'%s' %% '%s'", s1, s2);
2704
string2decimal(s1, &a, &end);
2706
string2decimal(s2, &b, &end);
2707
res=decimal_mod(&a, &b, &c);
2708
printf("%-40s => res=%d ", s, res);
2709
check_result_code(res, ex);
2710
if (res == E_DEC_DIV_ZERO)
2711
printf("E_DEC_DIV_ZERO");
2713
print_decimal(&c, orig, res, ex);
2717
const char *round_mode[]=
2718
{"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
2720
void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
2725
sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2727
string2decimal(s1, &a, &end);
2728
res=decimal_round(&a, &b, n, mode);
2729
printf("%-40s => res=%d ", s, res);
2730
print_decimal(&b, orig, res, ex);
2735
void test_mx(int precision, int frac, const char *orig)
2738
sprintf(s, "%d, %d", precision, frac);
2739
max_decimal(precision, frac, &a);
2740
printf("%-40s => ", s);
2741
print_decimal(&a, orig, 0, 0);
2746
void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
2751
int slen= sizeof(s2);
2754
sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2755
s1, prec, dec, filler);
2757
string2decimal(s1, &a, &end);
2758
res= decimal2string(&a, s2, &slen, prec, dec, filler);
2759
printf("%-40s => res=%d '%s'", s, res, s2);
2760
check_result_code(res, ex);
2761
if (orig && strcmp(orig, s2))
2763
printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2770
void test_sh(const char *s1, int shift, const char *orig, int ex)
2774
sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2776
string2decimal(s1, &a, &end);
2777
res= decimal_shift(&a, shift);
2778
printf("%-40s => res=%d ", s, res);
2779
print_decimal(&a, orig, res, ex);
2784
void test_fr(const char *s1, const char *orig)
2787
sprintf(s, "'%s'", s1);
2788
printf("%-40s => ", s);
2790
string2decimal(s1, &a, &end);
2791
a.frac= decimal_actual_fraction(&a);
2792
print_decimal(&a, orig, 0, 0);
2800
a.len=sizeof(buf1)/sizeof(dec1);
2802
b.len=sizeof(buf2)/sizeof(dec1);
2804
c.len=sizeof(buf3)/sizeof(dec1);
2809
printf("==== string2decimal ====\n");
2810
test_s2d("12345", "12345", 0);
2811
test_s2d("12345.", "12345", 0);
2812
test_s2d("123.45", "123.45", 0);
2813
test_s2d("-123.45", "-123.45", 0);
2814
test_s2d(".00012345000098765", "0.00012345000098765", 0);
2815
test_s2d(".12345000098765", "0.12345000098765", 0);
2816
test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
2817
test_s2d("1234500009876.5", "1234500009876.5", 0);
2819
test_s2d("123450000098765", "98765", 2);
2820
test_s2d("123450.000098765", "123450", 1);
2821
a.len=sizeof(buf1)/sizeof(dec1);
2822
test_s2d("123E5", "12300000", 0);
2823
test_s2d("123E-2", "1.23", 0);
2825
printf("==== decimal2double ====\n");
2826
test_d2f("12345", 0);
2827
test_d2f("123.45", 0);
2828
test_d2f("-123.45", 0);
2829
test_d2f("0.00012345000098765", 0);
2830
test_d2f("1234500009876.5", 0);
2832
printf("==== double2decimal ====\n");
2835
test_f2d(-123.45, 0);
2836
test_f2d(0.00012345000098765, 0);
2837
test_f2d(1234500009876.5, 0);
2839
printf("==== ulonglong2decimal ====\n");
2840
test_ull2d(ULL(12345), "12345", 0);
2841
test_ull2d(ULL(0), "0", 0);
2842
test_ull2d(ULL(18446744073709551615), "18446744073709551615", 0);
2844
printf("==== decimal2ulonglong ====\n");
2845
test_d2ull("12345", "12345", 0);
2846
test_d2ull("0", "0", 0);
2847
test_d2ull("18446744073709551615", "18446744073709551615", 0);
2848
test_d2ull("18446744073709551616", "18446744073", 2);
2849
test_d2ull("-1", "0", 2);
2850
test_d2ull("1.23", "1", 1);
2851
test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
2853
printf("==== longlong2decimal ====\n");
2854
test_ll2d(LL(-12345), "-12345", 0);
2855
test_ll2d(LL(-1), "-1", 0);
2856
test_ll2d(LL(-9223372036854775807), "-9223372036854775807", 0);
2857
test_ll2d(ULL(9223372036854775808), "-9223372036854775808", 0);
2859
printf("==== decimal2longlong ====\n");
2860
test_d2ll("18446744073709551615", "18446744073", 2);
2861
test_d2ll("-1", "-1", 0);
2862
test_d2ll("-1.23", "-1", 1);
2863
test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
2864
test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
2865
test_d2ll("9223372036854775808", "9223372036854775807", 2);
2867
printf("==== do_add ====\n");
2868
test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
2869
test_da(".1" ,".45", "0.55", 0);
2870
test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
2871
test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
2872
test_da("99999999" ,"1", "100000000", 0);
2873
test_da("989999999" ,"1", "990000000", 0);
2874
test_da("999999999" ,"1", "1000000000", 0);
2875
test_da("12345" ,"123.45", "12468.45", 0);
2876
test_da("-12345" ,"-123.45", "-12468.45", 0);
2877
test_ds("-12345" ,"123.45", "-12468.45", 0);
2878
test_ds("12345" ,"-123.45", "12468.45", 0);
2880
printf("==== do_sub ====\n");
2881
test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
2882
test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
2883
test_ds("9999900000000.5", ".555","9999899999999.945", 0);
2884
test_ds("1111.5551", "1111.555","0.0001", 0);
2885
test_ds(".555", ".555","0", 0);
2886
test_ds("10000000", "1","9999999", 0);
2887
test_ds("1000001000", ".1","1000000999.9", 0);
2888
test_ds("1000000000", ".1","999999999.9", 0);
2889
test_ds("12345", "123.45","12221.55", 0);
2890
test_ds("-12345", "-123.45","-12221.55", 0);
2891
test_da("-12345", "123.45","-12221.55", 0);
2892
test_da("12345", "-123.45","12221.55", 0);
2893
test_ds("123.45", "12345","-12221.55", 0);
2894
test_ds("-123.45", "-12345","12221.55", 0);
2895
test_da("123.45", "-12345","-12221.55", 0);
2896
test_da("-123.45", "12345","12221.55", 0);
2897
test_da("5", "-6.0","-1.0", 0);
2899
printf("==== decimal_mul ====\n");
2900
test_dm("12", "10","120", 0);
2901
test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
2902
test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
2903
test_dm("123456", "987654321","121931851853376", 0);
2904
test_dm("123456", "9876543210","1219318518533760", 0);
2905
test_dm("123", "0.01","1.23", 0);
2906
test_dm("123", "0","0", 0);
2908
printf("==== decimal_div ====\n");
2909
test_dv("120", "10","12.000000000", 0);
2910
test_dv("123", "0.01","12300.000000000", 0);
2911
test_dv("120", "100000000000.00000","0.000000001200000000", 0);
2912
test_dv("123", "0","", 4);
2913
test_dv("0", "0", "", 4);
2914
test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
2915
test_dv("121931851853376", "987654321","123456.000000000", 0);
2916
test_dv("0", "987","0", 0);
2917
test_dv("1", "3","0.333333333", 0);
2918
test_dv("1.000000000000", "3","0.333333333333333333", 0);
2919
test_dv("1", "1","1.000000000", 0);
2920
test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
2921
test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
2922
test_dv("10.000000000060", "2","5.000000000030000000", 0);
2924
printf("==== decimal_mod ====\n");
2925
test_md("234","10","4", 0);
2926
test_md("234.567","10.555","2.357", 0);
2927
test_md("-234.567","10.555","-2.357", 0);
2928
test_md("234.567","-10.555","2.357", 0);
2930
test_md("99999999999999999999999999999999999999","3","0", 0);
2931
if (c.buf[1] != 0x3ABECA)
2933
printf("%X - overflow\n", c.buf[1]);
2937
printf("==== decimal2bin/bin2decimal ====\n");
2938
test_d2b2d("-10.55", 4, 2,"-10.55", 0);
2939
test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
2940
test_d2b2d("12345", 5, 0,"12345", 0);
2941
test_d2b2d("12345", 10, 3,"12345.000", 0);
2942
test_d2b2d("123.45", 10, 3,"123.450", 0);
2943
test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
2944
test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
2945
test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
2946
test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
2947
test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
2948
test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
2949
test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
2950
test_d2b2d("000000000.01", 7, 3,"0.010", 0);
2951
test_d2b2d("123.4", 10, 2, "123.40", 0);
2954
printf("==== decimal_cmp ====\n");
2955
test_dc("12","13",-1);
2956
test_dc("13","12",1);
2957
test_dc("-10","10",-1);
2958
test_dc("10","-10",1);
2959
test_dc("-12","-13",1);
2960
test_dc("0","12",-1);
2961
test_dc("-10","0",-1);
2964
printf("==== decimal_round ====\n");
2965
test_ro("5678.123451",-4,TRUNCATE,"0", 0);
2966
test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
2967
test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
2968
test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
2969
test_ro("5678.123451",0,TRUNCATE,"5678", 0);
2970
test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
2971
test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
2972
test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
2973
test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
2974
test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
2975
test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
2976
test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
2977
memset(buf2, 33, sizeof(buf2));
2978
test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
2979
test_ro("15.1",0,HALF_UP,"15", 0);
2980
test_ro("15.5",0,HALF_UP,"16", 0);
2981
test_ro("15.9",0,HALF_UP,"16", 0);
2982
test_ro("-15.1",0,HALF_UP,"-15", 0);
2983
test_ro("-15.5",0,HALF_UP,"-16", 0);
2984
test_ro("-15.9",0,HALF_UP,"-16", 0);
2985
test_ro("15.1",1,HALF_UP,"15.1", 0);
2986
test_ro("-15.1",1,HALF_UP,"-15.1", 0);
2987
test_ro("15.17",1,HALF_UP,"15.2", 0);
2988
test_ro("15.4",-1,HALF_UP,"20", 0);
2989
test_ro("-15.4",-1,HALF_UP,"-20", 0);
2990
test_ro("5.4",-1,HALF_UP,"10", 0);
2991
test_ro(".999", 0, HALF_UP, "1", 0);
2992
memset(buf2, 33, sizeof(buf2));
2993
test_ro("999999999", -9, HALF_UP, "1000000000", 0);
2994
test_ro("15.1",0,HALF_EVEN,"15", 0);
2995
test_ro("15.5",0,HALF_EVEN,"16", 0);
2996
test_ro("14.5",0,HALF_EVEN,"14", 0);
2997
test_ro("15.9",0,HALF_EVEN,"16", 0);
2998
test_ro("15.1",0,CEILING,"16", 0);
2999
test_ro("-15.1",0,CEILING,"-15", 0);
3000
test_ro("15.1",0,FLOOR,"15", 0);
3001
test_ro("-15.1",0,FLOOR,"-16", 0);
3002
test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
3003
test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
3005
b.buf[0]=DIG_BASE+1;
3007
test_ro(".3", 0, HALF_UP, "0", 0);
3009
if (b.buf[0] != DIG_BASE+1)
3011
printf("%d - underflow\n", b.buf[0]);
3015
printf("==== max_decimal ====\n");
3019
test_mx(4,2,"99.99");
3020
test_mx(6,3,"999.999");
3021
test_mx(8,4,"9999.9999");
3022
test_mx(10,5,"99999.99999");
3023
test_mx(12,6,"999999.999999");
3024
test_mx(14,7,"9999999.9999999");
3025
test_mx(16,8,"99999999.99999999");
3026
test_mx(18,9,"999999999.999999999");
3027
test_mx(20,10,"9999999999.9999999999");
3028
test_mx(20,20,"0.99999999999999999999");
3029
test_mx(20,0,"99999999999999999999");
3030
test_mx(40,20,"99999999999999999999.99999999999999999999");
3032
printf("==== decimal2string ====\n");
3033
test_pr("123.123", 0, 0, 0, "123.123", 0);
3034
test_pr("123.123", 7, 3, '0', "123.123", 0);
3035
test_pr("123.123", 9, 3, '0', "00123.123", 0);
3036
test_pr("123.123", 9, 4, '0', "0123.1230", 0);
3037
test_pr("123.123", 9, 5, '0', "123.12300", 0);
3038
test_pr("123.123", 9, 2, '0', "000123.12", 1);
3039
test_pr("123.123", 9, 6, '0', "23.123000", 2);
3041
printf("==== decimal_shift ====\n");
3042
test_sh("123.123", 1, "1231.23", 0);
3043
test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
3044
test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
3045
test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
3046
test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
3047
test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
3048
test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
3049
test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
3050
test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
3051
test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3052
test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3053
test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3054
test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3055
test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3056
test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3057
test_sh("123", 1, "1230", 0);
3058
test_sh("123", 10, "1230000000000", 0);
3059
test_sh(".123", 1, "1.23", 0);
3060
test_sh(".123", 10, "1230000000", 0);
3061
test_sh(".123", 14, "12300000000000", 0);
3062
test_sh("000.000", 1000, "0", 0);
3063
test_sh("000.", 1000, "0", 0);
3064
test_sh(".000", 1000, "0", 0);
3065
test_sh("1", 1000, "1", 2);
3066
test_sh("123.123", -1, "12.3123", 0);
3067
test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
3068
test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
3069
test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
3070
test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
3071
test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
3072
test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
3073
test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
3074
test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
3075
test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
3076
test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
3077
test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
3079
test_sh("123.123", -2, "1.23123", 0);
3080
test_sh("123.123", -3, "0.123123", 0);
3081
test_sh("123.123", -6, "0.000123123", 0);
3082
test_sh("123.123", -7, "0.0000123123", 0);
3083
test_sh("123.123", -15, "0.000000000000123123", 0);
3084
test_sh("123.123", -16, "0.000000000000012312", 1);
3085
test_sh("123.123", -17, "0.000000000000001231", 1);
3086
test_sh("123.123", -18, "0.000000000000000123", 1);
3087
test_sh("123.123", -19, "0.000000000000000012", 1);
3088
test_sh("123.123", -20, "0.000000000000000001", 1);
3089
test_sh("123.123", -21, "0", 1);
3090
test_sh(".000000000123", -1, "0.0000000000123", 0);
3091
test_sh(".000000000123", -6, "0.000000000000000123", 0);
3092
test_sh(".000000000123", -7, "0.000000000000000012", 1);
3093
test_sh(".000000000123", -8, "0.000000000000000001", 1);
3094
test_sh(".000000000123", -9, "0", 1);
3095
test_sh(".000000000123", 1, "0.00000000123", 0);
3096
test_sh(".000000000123", 8, "0.0123", 0);
3097
test_sh(".000000000123", 9, "0.123", 0);
3098
test_sh(".000000000123", 10, "1.23", 0);
3099
test_sh(".000000000123", 17, "12300000", 0);
3100
test_sh(".000000000123", 18, "123000000", 0);
3101
test_sh(".000000000123", 19, "1230000000", 0);
3102
test_sh(".000000000123", 20, "12300000000", 0);
3103
test_sh(".000000000123", 21, "123000000000", 0);
3104
test_sh(".000000000123", 22, "1230000000000", 0);
3105
test_sh(".000000000123", 23, "12300000000000", 0);
3106
test_sh(".000000000123", 24, "123000000000000", 0);
3107
test_sh(".000000000123", 25, "1230000000000000", 0);
3108
test_sh(".000000000123", 26, "12300000000000000", 0);
3109
test_sh(".000000000123", 27, "123000000000000000", 0);
3110
test_sh(".000000000123", 28, "0.000000000123", 2);
3111
test_sh("123456789.987654321", -1, "12345678.998765432", 1);
3112
test_sh("123456789.987654321", -2, "1234567.899876543", 1);
3113
test_sh("123456789.987654321", -8, "1.234567900", 1);
3114
test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
3115
test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
3116
test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
3117
test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
3118
test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
3119
test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
3120
test_sh("123456789.987654321", -27, "0", 1);
3121
test_sh("123456789.987654321", 1, "1234567900", 1);
3122
test_sh("123456789.987654321", 2, "12345678999", 1);
3123
test_sh("123456789.987654321", 4, "1234567899877", 1);
3124
test_sh("123456789.987654321", 8, "12345678998765432", 1);
3125
test_sh("123456789.987654321", 9, "123456789987654321", 0);
3126
test_sh("123456789.987654321", 10, "123456789.987654321", 2);
3127
test_sh("123456789.987654321", 0, "123456789.987654321", 0);
3128
a.len= sizeof(buf1)/sizeof(dec1);
3130
printf("==== decimal_actual_fraction ====\n");
3131
test_fr("1.123456789000000000", "1.123456789");
3132
test_fr("1.12345678000000000", "1.12345678");
3133
test_fr("1.1234567000000000", "1.1234567");
3134
test_fr("1.123456000000000", "1.123456");
3135
test_fr("1.12345000000000", "1.12345");
3136
test_fr("1.1234000000000", "1.1234");
3137
test_fr("1.123000000000", "1.123");
3138
test_fr("1.12000000000", "1.12");
3139
test_fr("1.1000000000", "1.1");
3140
test_fr("1.000000000", "1");
3141
test_fr("1.0", "1");
3142
test_fr("10000000000000000000.0", "10000000000000000000");