~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/decimal.cc

  • Committer: Brian Aker
  • Date: 2009-07-11 19:23:04 UTC
  • mfrom: (1089.1.14 merge)
  • Revision ID: brian@gaz-20090711192304-ootijyl5yf9jq9kd
Merge Brian

Show diffs side-by-side

added added

removed removed

Lines of Context:
97
97
      implementation-defined.
98
98
*/
99
99
 
 
100
#include <drizzled/global.h>
 
101
 
 
102
#include "m_string.h"
 
103
#include "m_ctype.h"
 
104
#include "decimal.h"
 
105
 
 
106
#include <plugin/myisam/myisampack.h>
 
107
#include <drizzled/util/test.h>
 
108
 
100
109
#include <alloca.h>
101
 
#include <m_string.h>
102
 
#include <m_ctype.h>
103
 
#include <storage/myisam/myisampack.h>
104
 
#include <mystrings/decimal.h>
 
110
 
 
111
#include <algorithm>
 
112
 
 
113
using namespace std;
 
114
 
105
115
 
106
116
/*
107
117
  Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
125
135
#define DIG_MASK     100000000
126
136
#define DIG_BASE     1000000000
127
137
#define DIG_MAX      (DIG_BASE-1)
128
 
#define DIG_BASE2    ((dec2)DIG_BASE * (dec2)DIG_BASE)
129
138
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
130
139
static const dec1 powers10[DIG_PER_DEC1+1]={
131
140
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
210
219
          (to)=a;                                                       \
211
220
        } while(0)
212
221
 
 
222
/**
 
223
  Swap the contents of two variables.
 
224
 */
 
225
#define swap_variables(TYPE, a, b) \
 
226
  do {                             \
 
227
    TYPE dummy;                    \
 
228
    dummy= a;                      \
 
229
    a= b;                          \
 
230
    b= dummy;                      \
 
231
  } while (0)
 
232
 
 
233
 
213
234
/*
214
235
  Get maximum value for given precision and scale
215
236
 
395
416
      for (i=min(frac, DIG_PER_DEC1); i; i--)
396
417
      {
397
418
        dec1 y=x/DIG_MASK;
398
 
        *s1++='0'+(uchar)y;
 
419
        *s1++='0'+(unsigned char)y;
399
420
        x-=y*DIG_MASK;
400
421
        x*=10;
401
422
      }
418
439
      for (i=min(intg, DIG_PER_DEC1); i; i--)
419
440
      {
420
441
        dec1 y=x/10;
421
 
        *--s='0'+(uchar)(x-y*10);
 
442
        *--s='0'+(unsigned char)(x-y*10);
422
443
        x=y;
423
444
      }
424
445
    }
735
756
  beg= ROUND_UP(beg + 1) - 1;
736
757
  end= ROUND_UP(end) - 1;
737
758
  assert(new_point >= 0);
738
 
  
 
759
 
739
760
  /* We don't want negative new_point below */
740
761
  if (new_point != 0)
741
762
    new_point= ROUND_UP(new_point) - 1;
791
812
  sanity(to);
792
813
 
793
814
  error= E_DEC_BAD_NUM;                         /* In case of bad number */
794
 
  while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
 
815
  while (s < end_of_string && my_isspace(&my_charset_utf8_general_ci, *s))
795
816
    s++;
796
817
  if (s == end_of_string)
797
818
    goto fatal_error;
802
823
    s++;
803
824
 
804
825
  s1=s;
805
 
  while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
 
826
  while (s < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *s))
806
827
    s++;
807
828
  intg= (int) (s-s1);
808
829
  if (s < end_of_string && *s=='.')
809
830
  {
810
831
    endp= s+1;
811
 
    while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
 
832
    while (endp < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *endp))
812
833
      endp++;
813
834
    frac= (int) (endp - s - 1);
814
835
  }
949
970
 
950
971
  rc = decimal2string(from, strbuf, &len, 0, 0, 0);
951
972
  end= strbuf + len;
952
 
  
 
973
 
953
974
  *to= my_strtod(strbuf, &end, &error);
954
 
             
 
975
 
955
976
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
956
977
}
957
978
 
1164
1185
 
1165
1186
                7E F2 04 37 2D FB 2D
1166
1187
*/
1167
 
int decimal2bin(decimal_t *from, uchar *to, int precision, int frac)
 
1188
int decimal2bin(decimal_t *from, unsigned char *to, int precision, int frac)
1168
1189
{
1169
1190
  dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1170
1191
  int error=E_DEC_OK, intg=precision-frac,
1180
1201
      fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
1181
1202
  const int orig_isize0= isize0;
1182
1203
  const int orig_fsize0= fsize0;
1183
 
  uchar *orig_to= to;
 
1204
  unsigned char *orig_to= to;
1184
1205
 
1185
1206
  buf1= remove_leading_zeroes(from, &from_intg);
1186
1207
 
1270
1291
  }
1271
1292
  if (fsize0 > fsize1)
1272
1293
  {
1273
 
    uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
 
1294
    unsigned char *to_end= orig_to + orig_fsize0 + orig_isize0;
1274
1295
 
1275
1296
    while (fsize0-- > fsize1 && to < to_end)
1276
 
      *to++= (uchar)mask;
 
1297
      *to++= (unsigned char)mask;
1277
1298
  }
1278
1299
  orig_to[0]^= 0x80;
1279
1300
 
1299
1320
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1300
1321
*/
1301
1322
 
1302
 
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
 
1323
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1303
1324
{
1304
1325
  int error=E_DEC_OK, intg=precision-scale,
1305
1326
      intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1306
1327
      intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1307
1328
      intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1308
1329
  dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
1309
 
  const uchar *stop;
1310
 
  uchar *d_copy;
 
1330
  const unsigned char *stop;
 
1331
  unsigned char *d_copy;
1311
1332
  int bin_size= decimal_bin_size(precision, scale);
1312
1333
 
1313
1334
  sanity(to);
1314
 
  d_copy= (uchar*) alloca(bin_size);
 
1335
  d_copy= (unsigned char*) alloca(bin_size);
1315
1336
  memcpy(d_copy, from, bin_size);
1316
1337
  d_copy[0]^= 0x80;
1317
1338
  from= d_copy;
1726
1747
    set_if_smaller(intg2, intg0);
1727
1748
  }
1728
1749
 
1729
 
  /* part 1 - max(frac) ... min (frac) */
 
1750
  /* part 1 - cmax(frac) ... cmin(frac) */
1730
1751
  if (frac1 > frac2)
1731
1752
  {
1732
1753
    buf1=from1->buf+intg1+frac1;
1744
1765
  while (buf1 > stop)
1745
1766
    *--buf0=*--buf1;
1746
1767
 
1747
 
  /* part 2 - min(frac) ... min(intg) */
 
1768
  /* part 2 - cmin(frac) ... cmin(intg) */
1748
1769
  carry=0;
1749
1770
  while (buf1 > stop2)
1750
1771
  {
1751
1772
    ADD(*--buf0, *--buf1, *--buf2, carry);
1752
1773
  }
1753
1774
 
1754
 
  /* part 3 - min(intg) ... max(intg) */
 
1775
  /* part 3 - cmin(intg) ... cmax(intg) */
1755
1776
  buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1756
1777
                        ((stop=from2->buf)+intg2-intg1) ;
1757
1778
  while (buf1 > stop)
1858
1879
  }
1859
1880
  carry=0;
1860
1881
 
1861
 
  /* part 1 - max(frac) ... min (frac) */
 
1882
  /* part 1 - cmax(frac) ... cmin(frac) */
1862
1883
  if (frac1 > frac2)
1863
1884
  {
1864
1885
    buf1=start1+intg1+frac1;
1882
1903
    }
1883
1904
  }
1884
1905
 
1885
 
  /* part 2 - min(frac) ... intg2 */
 
1906
  /* part 2 - cmin(frac) ... intg2 */
1886
1907
  while (buf2 > start2)
1887
1908
  {
1888
1909
    SUB(*--buf0, *--buf1, *--buf2, carry);
2138
2159
  {
2139
2160
    /* we're calculating N1 % N2.
2140
2161
       The result will have
2141
 
         frac=max(frac1, frac2), as for subtraction
 
2162
         frac=cmax(frac1, frac2), as for subtraction
2142
2163
         intg=intg2
2143
2164
    */
2144
2165
    to->sign=from1->sign;
2266
2287
    /*
2267
2288
      now the result is in tmp1, it has
2268
2289
        intg=prec1-frac1
2269
 
        frac=max(frac1, frac2)=to->frac
 
2290
        frac=cmax(frac1, frac2)=to->frac
2270
2291
    */
2271
2292
    if (dcarry)
2272
2293
      *--start1=dcarry;
2494
2515
  {
2495
2516
    printf("0x");
2496
2517
    for (i=0; i < size; i++)
2497
 
      printf("%02x", ((uchar *)buf)[i]);
 
2518
      printf("%02x", ((unsigned char *)buf)[i]);
2498
2519
  }
2499
2520
  res=bin2decimal(buf, &a, p, s);
2500
2521
  printf(" => res=%d ", res);