~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/decimal.cc

  • Committer: Brian Aker
  • Date: 2010-02-07 01:33:54 UTC
  • Revision ID: brian@gaz-20100207013354-d2pg1n68u5c09pgo
Remove giant include header to its own file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
97
97
      implementation-defined.
98
98
*/
99
99
 
 
100
#include "config.h"
 
101
 
 
102
#include "drizzled/definitions.h"
 
103
#include "drizzled/internal/m_string.h"
 
104
#include "drizzled/charset_info.h"
 
105
#include "drizzled/decimal.h"
 
106
 
 
107
#include <plugin/myisam/myisampack.h>
 
108
#include <drizzled/util/test.h>
 
109
 
 
110
#ifdef HAVE_ALLOCA_H
100
111
#include <alloca.h>
101
 
#include <m_string.h>
102
 
#include <m_ctype.h>
103
 
#include <storage/myisam/myisampack.h>
104
 
#include <mystrings/decimal.h>
 
112
#endif
 
113
 
 
114
#include <algorithm>
 
115
 
 
116
using namespace std;
 
117
 
 
118
namespace drizzled
 
119
{
105
120
 
106
121
/*
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};
210
224
          (to)=a;                                                       \
211
225
        } while(0)
212
226
 
 
227
/**
 
228
  Swap the contents of two variables.
 
229
 */
 
230
#define swap_variables(TYPE, a, b) \
 
231
  do {                             \
 
232
    TYPE dummy;                    \
 
233
    dummy= a;                      \
 
234
    a= b;                          \
 
235
    b= dummy;                      \
 
236
  } while (0)
 
237
 
 
238
 
213
239
/*
214
240
  Get maximum value for given precision and scale
215
241
 
247
273
}
248
274
 
249
275
 
250
 
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
 
276
static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
251
277
{
252
278
  int intg= from->intg, i;
253
279
  dec1 *buf0= from->buf;
323
349
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
324
350
*/
325
351
 
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,
328
354
                   char filler)
329
355
{
395
421
      for (i=min(frac, DIG_PER_DEC1); i; i--)
396
422
      {
397
423
        dec1 y=x/DIG_MASK;
398
 
        *s1++='0'+(uchar)y;
 
424
        *s1++='0'+(unsigned char)y;
399
425
        x-=y*DIG_MASK;
400
426
        x*=10;
401
427
      }
418
444
      for (i=min(intg, DIG_PER_DEC1); i; i--)
419
445
      {
420
446
        dec1 y=x/10;
421
 
        *--s='0'+(uchar)(x-y*10);
 
447
        *--s='0'+(unsigned char)(x-y*10);
422
448
        x=y;
423
449
      }
424
450
    }
735
761
  beg= ROUND_UP(beg + 1) - 1;
736
762
  end= ROUND_UP(end) - 1;
737
763
  assert(new_point >= 0);
738
 
  
 
764
 
739
765
  /* We don't want negative new_point below */
740
766
  if (new_point != 0)
741
767
    new_point= ROUND_UP(new_point) - 1;
791
817
  sanity(to);
792
818
 
793
819
  error= E_DEC_BAD_NUM;                         /* In case of bad number */
794
 
  while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
 
820
  while (s < end_of_string && my_isspace(&my_charset_utf8_general_ci, *s))
795
821
    s++;
796
822
  if (s == end_of_string)
797
823
    goto fatal_error;
802
828
    s++;
803
829
 
804
830
  s1=s;
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))
806
832
    s++;
807
833
  intg= (int) (s-s1);
808
834
  if (s < end_of_string && *s=='.')
809
835
  {
810
836
    endp= s+1;
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))
812
838
      endp++;
813
839
    frac= (int) (endp - s - 1);
814
840
  }
896
922
  if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
897
923
  {
898
924
    int str_error;
899
 
    const int64_t exponent= my_strtoll10(endp+1, (char**) &end_of_string,
900
 
                                    &str_error);
 
925
    const int64_t exponent= internal::my_strtoll10(endp+1, (char**) &end_of_string,
 
926
                                                   &str_error);
901
927
 
902
928
    if (end_of_string != endp +1)               /* If at least one digit */
903
929
    {
941
967
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
942
968
*/
943
969
 
944
 
int decimal2double(decimal_t *from, double *to)
 
970
int decimal2double(const decimal_t *from, double *to)
945
971
{
946
972
  char strbuf[FLOATING_POINT_BUFFER], *end;
947
973
  int len= sizeof(strbuf);
949
975
 
950
976
  rc = decimal2string(from, strbuf, &len, 0, 0, 0);
951
977
  end= strbuf + len;
952
 
  
953
 
  *to= my_strtod(strbuf, &end, &error);
954
 
             
 
978
 
 
979
  *to= internal::my_strtod(strbuf, &end, &error);
 
980
 
955
981
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
956
982
}
957
983
 
967
993
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
968
994
*/
969
995
 
970
 
int double2decimal(double from, decimal_t *to)
 
996
int double2decimal(const double from, decimal_t *to)
971
997
{
972
998
  char buff[FLOATING_POINT_BUFFER], *end;
973
999
  int res;
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);
976
1004
  return(res);
977
1005
}
1003
1031
  return error;
1004
1032
}
1005
1033
 
1006
 
int uint64_t2decimal(uint64_t from, decimal_t *to)
 
1034
int uint64_t2decimal(const uint64_t from, decimal_t *to)
1007
1035
{
1008
1036
  to->sign=0;
1009
1037
  return ull2dec(from, to);
1010
1038
}
1011
1039
 
1012
 
int int64_t2decimal(int64_t from, decimal_t *to)
 
1040
int int64_t2decimal(const int64_t from, decimal_t *to)
1013
1041
{
1014
1042
  if ((to->sign= from < 0))
1015
1043
    return ull2dec(-from, to);
1016
1044
  return ull2dec(from, to);
1017
1045
}
1018
1046
 
1019
 
int decimal2uint64_t(decimal_t *from, uint64_t *to)
 
1047
int decimal2uint64_t(const decimal_t *from, uint64_t *to)
1020
1048
{
1021
1049
  dec1 *buf=from->buf;
1022
1050
  uint64_t x=0;
1045
1073
  return E_DEC_OK;
1046
1074
}
1047
1075
 
1048
 
int decimal2int64_t(decimal_t *from, int64_t *to)
 
1076
int decimal2int64_t(const decimal_t *from, int64_t *to)
1049
1077
{
1050
1078
  dec1 *buf=from->buf;
1051
1079
  int64_t x=0;
1164
1192
 
1165
1193
                7E F2 04 37 2D FB 2D
1166
1194
*/
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)
1168
1196
{
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;
1183
 
  uchar *orig_to= to;
 
1211
  unsigned char *orig_to= to;
1184
1212
 
1185
1213
  buf1= remove_leading_zeroes(from, &from_intg);
1186
1214
 
1270
1298
  }
1271
1299
  if (fsize0 > fsize1)
1272
1300
  {
1273
 
    uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
 
1301
    unsigned char *to_end= orig_to + orig_fsize0 + orig_isize0;
1274
1302
 
1275
1303
    while (fsize0-- > fsize1 && to < to_end)
1276
 
      *to++= (uchar)mask;
 
1304
      *to++= (unsigned char)mask;
1277
1305
  }
1278
1306
  orig_to[0]^= 0x80;
1279
1307
 
1299
1327
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1300
1328
*/
1301
1329
 
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)
1303
1331
{
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;
1309
 
  const uchar *stop;
1310
 
  uchar *d_copy;
 
1337
  const unsigned char *stop;
 
1338
  unsigned char *d_copy;
1311
1339
  int bin_size= decimal_bin_size(precision, scale);
1312
1340
 
1313
1341
  sanity(to);
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;
1317
1345
  from= d_copy;
1402
1430
}
1403
1431
 
1404
1432
/*
1405
 
  Returns the size of array to hold a decimal with given precision and scale
1406
 
 
1407
 
  RETURN VALUE
1408
 
    size in dec1
1409
 
    (multiply by sizeof(dec1) to get the size if bytes)
1410
 
*/
1411
 
 
1412
 
int decimal_size(int precision, int scale)
1413
 
{
1414
 
  assert(scale >= 0 && precision > 0 && scale <= precision);
1415
 
  return ROUND_UP(precision-scale)+ROUND_UP(scale);
1416
 
}
1417
 
 
1418
 
/*
1419
1433
  Returns the size of array to hold a binary representation of a decimal
1420
1434
 
1421
1435
  RETURN VALUE
1452
1466
*/
1453
1467
 
1454
1468
int
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)
1457
1471
{
1458
1472
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1644
1658
  return error;
1645
1659
}
1646
1660
 
1647
 
/*
1648
 
  Returns the size of the result of the operation
1649
 
 
1650
 
  SYNOPSIS
1651
 
    decimal_result_size()
1652
 
      from1   - operand of the unary operation or first operand of the
1653
 
                binary operation
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 '/'
1659
 
 
1660
 
  NOTE
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
1664
 
 
1665
 
  RETURN VALUE
1666
 
    size of to->buf array in dec1 elements. to get size in bytes
1667
 
    multiply by sizeof(dec1)
1668
 
*/
1669
 
 
1670
 
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1671
 
{
1672
 
  switch (op) {
1673
 
  case '-':
1674
 
    return ROUND_UP(max(from1->intg, from2->intg)) +
1675
 
           ROUND_UP(max(from1->frac, from2->frac));
1676
 
  case '+':
1677
 
    return ROUND_UP(max(from1->intg, from2->intg)+1) +
1678
 
           ROUND_UP(max(from1->frac, from2->frac));
1679
 
  case '*':
1680
 
    return ROUND_UP(from1->intg+from2->intg)+
1681
 
           ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1682
 
  case '/':
1683
 
    return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1684
 
  default: assert(0);
1685
 
  }
1686
 
  return -1; /* shut up the warning */
1687
 
}
1688
 
 
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)
1690
1662
{
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);
1727
1699
  }
1728
1700
 
1729
 
  /* part 1 - max(frac) ... min (frac) */
 
1701
  /* part 1 - cmax(frac) ... cmin(frac) */
1730
1702
  if (frac1 > frac2)
1731
1703
  {
1732
1704
    buf1=from1->buf+intg1+frac1;
1744
1716
  while (buf1 > stop)
1745
1717
    *--buf0=*--buf1;
1746
1718
 
1747
 
  /* part 2 - min(frac) ... min(intg) */
 
1719
  /* part 2 - cmin(frac) ... cmin(intg) */
1748
1720
  carry=0;
1749
1721
  while (buf1 > stop2)
1750
1722
  {
1751
1723
    ADD(*--buf0, *--buf1, *--buf2, carry);
1752
1724
  }
1753
1725
 
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)
1768
1740
 
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)
1772
1744
{
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) */
1838
1810
  if (carry)
1839
1811
  {
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);
1858
1830
  }
1859
1831
  carry=0;
1860
1832
 
1861
 
  /* part 1 - max(frac) ... min (frac) */
 
1833
  /* part 1 - cmax(frac) ... cmin(frac) */
1862
1834
  if (frac1 > frac2)
1863
1835
  {
1864
1836
    buf1=start1+intg1+frac1;
1882
1854
    }
1883
1855
  }
1884
1856
 
1885
 
  /* part 2 - min(frac) ... intg2 */
 
1857
  /* part 2 - cmin(frac) ... intg2 */
1886
1858
  while (buf2 > start2)
1887
1859
  {
1888
1860
    SUB(*--buf0, *--buf1, *--buf2, carry);
1903
1875
  return error;
1904
1876
}
1905
1877
 
1906
 
int decimal_intg(decimal_t *from)
 
1878
int decimal_intg(const decimal_t *from)
1907
1879
{
1908
1880
  int res;
1909
1881
  dec1 *tmp_res;
1911
1883
  return res;
1912
1884
}
1913
1885
 
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)
1915
1887
{
1916
1888
  if (likely(from1->sign == from2->sign))
1917
1889
    return do_add(from1, from2, to);
1918
1890
  return do_sub(from1, from2, to);
1919
1891
}
1920
1892
 
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)
1922
1894
{
1923
1895
  if (likely(from1->sign == from2->sign))
1924
1896
    return do_sub(from1, from2, to);
1925
1897
  return do_add(from1, from2, to);
1926
1898
}
1927
1899
 
1928
 
int decimal_cmp(decimal_t *from1, decimal_t *from2)
 
1900
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
1929
1901
{
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;
1933
1905
}
1934
1906
 
1935
 
int decimal_is_zero(decimal_t *from)
 
1907
int decimal_is_zero(const decimal_t *from)
1936
1908
{
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.
1965
1937
*/
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)
1967
1939
{
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 :(
2081
2053
*/
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)
2084
2056
{
2085
2057
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2138
2110
  {
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
2142
2114
         intg=intg2
2143
2115
    */
2144
2116
    to->sign=from1->sign;
2266
2238
    /*
2267
2239
      now the result is in tmp1, it has
2268
2240
        intg=prec1-frac1
2269
 
        frac=max(frac1, frac2)=to->frac
 
2241
        frac=cmax(frac1, frac2)=to->frac
2270
2242
    */
2271
2243
    if (dcarry)
2272
2244
      *--start1=dcarry;
2338
2310
*/
2339
2311
 
2340
2312
int
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)
2342
2314
{
2343
2315
  return do_div_mod(from1, from2, to, 0, scale_incr);
2344
2316
}
2370
2342
   thus, there's no requirement for M or N to be integers
2371
2343
*/
2372
2344
 
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)
2374
2346
{
2375
2347
  return do_div_mod(from1, from2, 0, to, 0);
2376
2348
}
2377
2349
 
 
2350
} /* namespace drizzled */
 
2351
 
2378
2352
#ifdef MAIN
2379
2353
 
2380
2354
int full= 0;
2494
2468
  {
2495
2469
    printf("0x");
2496
2470
    for (i=0; i < size; i++)
2497
 
      printf("%02x", ((uchar *)buf)[i]);
 
2471
      printf("%02x", ((unsigned char *)buf)[i]);
2498
2472
  }
2499
2473
  res=bin2decimal(buf, &a, p, s);
2500
2474
  printf(" => res=%d ", res);
2518
2492
  int res;
2519
2493
 
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);
2524
2498
  printf("\n");
2530
2504
  int res;
2531
2505
 
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);
2536
2510
  printf("\n");
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))