97
97
implementation-defined.
102
#include "drizzled/definitions.h"
103
#include "drizzled/internal/m_string.h"
104
#include "drizzled/charset_info.h"
105
#include "drizzled/decimal.h"
107
#include <plugin/myisam/myisampack.h>
108
#include <drizzled/util/test.h>
100
111
#include <alloca.h>
101
#include <m_string.h>
103
#include <storage/myisam/myisampack.h>
104
#include <mystrings/decimal.h>
107
122
Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
125
140
#define DIG_MASK 100000000
126
141
#define DIG_BASE 1000000000
127
142
#define DIG_MAX (DIG_BASE-1)
128
#define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE)
129
143
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
130
144
static const dec1 powers10[DIG_PER_DEC1+1]={
131
145
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
323
349
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
326
int decimal2string(decimal_t *from, char *to, int *to_len,
352
int decimal2string(const decimal_t *from, char *to, int *to_len,
327
353
int fixed_precision, int fixed_decimals,
805
while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
831
while (s < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *s))
807
833
intg= (int) (s-s1);
808
834
if (s < end_of_string && *s=='.')
811
while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
837
while (endp < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *endp))
813
839
frac= (int) (endp - s - 1);
896
922
if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
899
const int64_t exponent= my_strtoll10(endp+1, (char**) &end_of_string,
925
const int64_t exponent= internal::my_strtoll10(endp+1, (char**) &end_of_string,
902
928
if (end_of_string != endp +1) /* If at least one digit */
941
967
E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
944
int decimal2double(decimal_t *from, double *to)
970
int decimal2double(const decimal_t *from, double *to)
946
972
char strbuf[FLOATING_POINT_BUFFER], *end;
947
973
int len= sizeof(strbuf);
950
976
rc = decimal2string(from, strbuf, &len, 0, 0, 0);
951
977
end= strbuf + len;
953
*to= my_strtod(strbuf, &end, &error);
979
*to= internal::my_strtod(strbuf, &end, &error);
955
981
return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
967
993
E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
970
int double2decimal(double from, decimal_t *to)
996
int double2decimal(const double from, decimal_t *to)
972
998
char buff[FLOATING_POINT_BUFFER], *end;
974
end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
1000
end= buff + internal::my_gcvt(from,
1001
internal::MY_GCVT_ARG_DOUBLE,
1002
sizeof(buff) - 1, buff, NULL);
975
1003
res= string2decimal(buff, to, &end);
1006
int uint64_t2decimal(uint64_t from, decimal_t *to)
1034
int uint64_t2decimal(const uint64_t from, decimal_t *to)
1009
1037
return ull2dec(from, to);
1012
int int64_t2decimal(int64_t from, decimal_t *to)
1040
int int64_t2decimal(const int64_t from, decimal_t *to)
1014
1042
if ((to->sign= from < 0))
1015
1043
return ull2dec(-from, to);
1016
1044
return ull2dec(from, to);
1019
int decimal2uint64_t(decimal_t *from, uint64_t *to)
1047
int decimal2uint64_t(const decimal_t *from, uint64_t *to)
1021
1049
dec1 *buf=from->buf;
1165
1193
7E F2 04 37 2D FB 2D
1167
int decimal2bin(decimal_t *from, uchar *to, int precision, int frac)
1195
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
1169
1197
dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1170
1198
int error=E_DEC_OK, intg=precision-frac,
1180
1208
fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
1181
1209
const int orig_isize0= isize0;
1182
1210
const int orig_fsize0= fsize0;
1211
unsigned char *orig_to= to;
1185
1213
buf1= remove_leading_zeroes(from, &from_intg);
1299
1327
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1302
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
1330
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1304
1332
int error=E_DEC_OK, intg=precision-scale,
1305
1333
intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1306
1334
intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1307
1335
intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1308
1336
dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
1337
const unsigned char *stop;
1338
unsigned char *d_copy;
1311
1339
int bin_size= decimal_bin_size(precision, scale);
1314
d_copy= (uchar*) alloca(bin_size);
1342
d_copy= (unsigned char*) alloca(bin_size);
1315
1343
memcpy(d_copy, from, bin_size);
1316
1344
d_copy[0]^= 0x80;
1405
Returns the size of array to hold a decimal with given precision and scale
1409
(multiply by sizeof(dec1) to get the size if bytes)
1412
int decimal_size(int precision, int scale)
1414
assert(scale >= 0 && precision > 0 && scale <= precision);
1415
return ROUND_UP(precision-scale)+ROUND_UP(scale);
1419
1433
Returns the size of array to hold a binary representation of a decimal
1455
decimal_round(decimal_t *from, decimal_t *to, int scale,
1469
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1456
1470
decimal_round_mode mode)
1458
1472
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1648
Returns the size of the result of the operation
1651
decimal_result_size()
1652
from1 - operand of the unary operation or first operand of the
1654
from2 - second operand of the binary operation
1655
op - operation. one char '+', '-', '*', '/' are allowed
1656
others may be added later
1657
param - extra param to the operation. unused for '+', '-', '*'
1658
scale increment for '/'
1661
returned valued may be larger than the actual buffer requred
1662
in the operation, as decimal_result_size, by design, operates on
1663
precision/scale values only and not on the actual decimal number
1666
size of to->buf array in dec1 elements. to get size in bytes
1667
multiply by sizeof(dec1)
1670
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1674
return ROUND_UP(max(from1->intg, from2->intg)) +
1675
ROUND_UP(max(from1->frac, from2->frac));
1677
return ROUND_UP(max(from1->intg, from2->intg)+1) +
1678
ROUND_UP(max(from1->frac, from2->frac));
1680
return ROUND_UP(from1->intg+from2->intg)+
1681
ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1683
return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1686
return -1; /* shut up the warning */
1689
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1661
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1691
1663
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1692
1664
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1726
1698
set_if_smaller(intg2, intg0);
1729
/* part 1 - max(frac) ... min (frac) */
1701
/* part 1 - cmax(frac) ... cmin(frac) */
1730
1702
if (frac1 > frac2)
1732
1704
buf1=from1->buf+intg1+frac1;
1744
1716
while (buf1 > stop)
1745
1717
*--buf0=*--buf1;
1747
/* part 2 - min(frac) ... min(intg) */
1719
/* part 2 - cmin(frac) ... cmin(intg) */
1749
1721
while (buf1 > stop2)
1751
1723
ADD(*--buf0, *--buf1, *--buf2, carry);
1754
/* part 3 - min(intg) ... max(intg) */
1726
/* part 3 - cmin(intg) ... cmax(intg) */
1755
1727
buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1756
1728
((stop=from2->buf)+intg2-intg1) ;
1757
1729
while (buf1 > stop)
1769
1741
/* to=from1-from2.
1770
1742
if to==0, return -1/0/+1 - the result of the comparison */
1771
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1743
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1773
1745
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1774
1746
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1837
1809
/* ensure that always from1 > from2 (and intg1 >= intg2) */
1840
swap_variables(decimal_t *,from1,from1);
1812
swap_variables(const decimal_t *,from1, from2);
1841
1813
swap_variables(dec1 *,start1, start2);
1842
1814
swap_variables(int,intg1,intg2);
1843
1815
swap_variables(int,frac1,frac2);
1885
/* part 2 - min(frac) ... intg2 */
1857
/* part 2 - cmin(frac) ... intg2 */
1886
1858
while (buf2 > start2)
1888
1860
SUB(*--buf0, *--buf1, *--buf2, carry);
1914
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1886
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1916
1888
if (likely(from1->sign == from2->sign))
1917
1889
return do_add(from1, from2, to);
1918
1890
return do_sub(from1, from2, to);
1921
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1893
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1923
1895
if (likely(from1->sign == from2->sign))
1924
1896
return do_sub(from1, from2, to);
1925
1897
return do_add(from1, from2, to);
1928
int decimal_cmp(decimal_t *from1, decimal_t *from2)
1900
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
1930
1902
if (likely(from1->sign == from2->sign))
1931
1903
return do_sub(from1, from2, 0);
1932
1904
return from1->sign > from2->sign ? -1 : 1;
1935
int decimal_is_zero(decimal_t *from)
1907
int decimal_is_zero(const decimal_t *from)
1937
1909
dec1 *buf1=from->buf,
1938
1910
*end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
1963
1935
XXX if this library is to be used with huge numbers of thousands of
1964
1936
digits, fast multiplication must be implemented.
1966
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
1938
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1968
1940
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1969
1941
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
2079
2051
changed to malloc (or at least fallback to malloc if alloca() fails)
2080
2052
but then, decimal_mul() should be rewritten too :(
2082
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2054
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2083
2055
decimal_t *to, decimal_t *mod, int scale_incr)
2085
2057
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2139
2111
/* we're calculating N1 % N2.
2140
2112
The result will have
2141
frac=max(frac1, frac2), as for subtraction
2113
frac=cmax(frac1, frac2), as for subtraction
2144
2116
to->sign=from1->sign;
2341
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2313
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
2343
2315
return do_div_mod(from1, from2, to, 0, scale_incr);
2370
2342
thus, there's no requirement for M or N to be integers
2373
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2345
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2375
2347
return do_div_mod(from1, from2, 0, to, 0);
2350
} /* namespace drizzled */
2496
2470
for (i=0; i < size; i++)
2497
printf("%02x", ((uchar *)buf)[i]);
2471
printf("%02x", ((unsigned char *)buf)[i]);
2499
2473
res=bin2decimal(buf, &a, p, s);
2500
2474
printf(" => res=%d ", res);
2520
2494
res=uint64_t2decimal(from, &a);
2521
int64_t10_to_str(from,s,10);
2495
internal::int64_t10_to_str(from,s,10);
2522
2496
printf("%-40s => res=%d ", s, res);
2523
2497
print_decimal(&a, orig, res, ex);
2532
2506
res=int64_t2decimal(from, &a);
2533
int64_t10_to_str(from,s,-10);
2507
internal::int64_t10_to_str(from,s,-10);
2534
2508
printf("%-40s => res=%d ", s, res);
2535
2509
print_decimal(&a, orig, res, ex);
2546
2520
string2decimal(s, &a, &end);
2547
2521
res=decimal2uint64_t(&a, &x);
2548
2522
if (full) dump_decimal(&a);
2549
int64_t10_to_str(x,s1,10);
2523
internal::int64_t10_to_str(x,s1,10);
2550
2524
printf("%-40s => res=%d %s\n", s, res, s1);
2551
2525
check_result_code(res, ex);
2552
2526
if (orig && strcmp(orig, s1))
2566
2540
string2decimal(s, &a, &end);
2567
2541
res=decimal2int64_t(&a, &x);
2568
2542
if (full) dump_decimal(&a);
2569
int64_t10_to_str(x,s1,-10);
2543
internal::int64_t10_to_str(x,s1,-10);
2570
2544
printf("%-40s => res=%d %s\n", s, res, s1);
2571
2545
check_result_code(res, ex);
2572
2546
if (orig && strcmp(orig, s1))