~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/decimal.cc

  • Committer: lbieber
  • Date: 2010-10-01 13:06:31 UTC
  • mfrom: (1802.2.2 drizzle-bug-651948)
  • mto: This revision was merged to the branch mainline in revision 1805.
  • Revision ID: lbieber@orisndriz08-20101001130631-xubscnhmj7r5dn6g
Merge Andrew - Fix bug 651948 - Index lengths not retrieved using drizzledump

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/** @file
17
17
 *
108
108
#include "drizzled/definitions.h"
109
109
#include "drizzled/internal/m_string.h"
110
110
#include "drizzled/charset_info.h"
111
 
#include "drizzled/type/decimal.h"
 
111
#include "drizzled/decimal.h"
112
112
 
113
113
#include <plugin/myisam/myisampack.h>
114
114
#include <drizzled/util/test.h>
157
157
                        "DECIMAL", "");
158
158
    break;
159
159
  case E_DEC_DIV_ZERO:
160
 
    my_error(ER_DIVISION_BY_ZERO, MYF(0));
 
160
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
161
                        ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
161
162
    break;
162
163
  case E_DEC_BAD_NUM:
163
164
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
178
179
/**
179
180
  @brief Converting decimal to string
180
181
 
181
 
  @details Convert given type::Decimal to String; allocate buffer as needed.
 
182
  @details Convert given my_decimal to String; allocate buffer as needed.
182
183
 
183
184
  @param[in]   mask        what problems to warn on (mask of E_DEC_* values)
184
185
  @param[in]   d           the decimal to print
194
195
    @retval E_DEC_OOM
195
196
*/
196
197
 
197
 
int class_decimal2string(const type::Decimal *d,
198
 
                         uint32_t fixed_dec, String *str)
 
198
int my_decimal2string(uint32_t mask, const my_decimal *d,
 
199
                      uint32_t fixed_prec, uint32_t fixed_dec,
 
200
                      char filler, String *str)
199
201
{
200
 
  uint32_t mask= E_DEC_FATAL_ERROR;
201
 
 
202
202
  /*
203
203
    Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
204
204
    holds true iff the type is also ZEROFILL, which in turn implies
207
207
    one if the user only wanted decimal places, but we force a leading
208
208
    zero on them. Because the type is implicitly UNSIGNED, we do not
209
209
    need to reserve a character for the sign. For all other cases,
210
 
    fixed_prec will be 0, and class_decimal_string_length() will be called
 
210
    fixed_prec will be 0, and my_decimal_string_length() will be called
211
211
    instead to calculate the required size of the buffer.
212
212
  */
213
 
  int length= (int)(0
214
 
                    ? (uint32_t)(((0 == fixed_dec) ? 1 : 0) + 1)
215
 
                    : (uint32_t)d->string_length());
 
213
  int length= (fixed_prec
 
214
               ? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
 
215
               : my_decimal_string_length(d));
216
216
  int result;
217
217
  if (str->alloc(length))
218
218
    return check_result(mask, E_DEC_OOM);
219
 
 
220
219
  result= decimal2string((decimal_t*) d, (char*) str->ptr(),
221
 
                         &length, (int)0, fixed_dec,
222
 
                         '0');
 
220
                         &length, (int)fixed_prec, fixed_dec,
 
221
                         filler);
223
222
  str->length(length);
224
223
  return check_result(mask, result);
225
224
}
244
243
   @retval E_DEC_OVERFLOW
245
244
*/
246
245
 
247
 
namespace type {
248
 
 
249
 
int Decimal::val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const
 
246
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
 
247
                      int scale)
250
248
{
251
249
  int err1= E_DEC_OK, err2;
252
 
  type::Decimal rounded;
253
 
  class_decimal2decimal(this, &rounded);
 
250
  my_decimal rounded;
 
251
  my_decimal2decimal(d, &rounded);
254
252
  rounded.frac= decimal_actual_fraction(&rounded);
255
253
  if (scale < rounded.frac)
256
254
  {
264
262
  return check_result(mask, err2);
265
263
}
266
264
 
267
 
} // namespace type
268
 
 
269
265
 
270
266
/**
271
267
  @brief Convert string for decimal when string can be in some multibyte charset
274
270
  @param  from            string to process
275
271
  @param  length          length of given string
276
272
  @param  charset         charset of given string
 
273
  @param  decimal_value   buffer for result storing
277
274
 
278
275
  @return Error code
279
276
   @retval E_DEC_OK
283
280
   @retval E_DEC_OOM
284
281
*/
285
282
 
286
 
int type::Decimal::store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset)
 
283
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
 
284
                   const CHARSET_INFO * charset, my_decimal *decimal_value)
287
285
{
288
286
  char *end, *from_end;
289
287
  int err;
291
289
  String tmp(buff, sizeof(buff), &my_charset_bin);
292
290
  if (charset->mbminlen > 1)
293
291
  {
294
 
    size_t dummy_errors;
 
292
    uint32_t dummy_errors;
295
293
    tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
296
294
    from= tmp.ptr();
297
295
    length=  tmp.length();
298
296
    charset= &my_charset_bin;
299
297
  }
300
298
  from_end= end= (char*) from+length;
301
 
  err= string2decimal((char *)from, (decimal_t*) this, &end);
 
299
  err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
302
300
  if (end != from_end && !err)
303
301
  {
304
302
    /* Give warning if there is something other than end space */
311
309
      }
312
310
    }
313
311
  }
314
 
  check_result_and_overflow(mask, err);
 
312
  check_result_and_overflow(mask, err, decimal_value);
315
313
  return err;
316
314
}
317
315
 
318
 
void type::Decimal::convert(double &result) const
319
 
{
320
 
  decimal2double(static_cast<const decimal_t*>(this), &result);
321
 
}
322
316
 
323
 
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec)
 
317
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
324
318
{
325
319
  int64_t date;
326
320
  date = (ltime->year*100L + ltime->month)*100L + ltime->day;
327
 
  if (ltime->time_type > type::DRIZZLE_TIMESTAMP_DATE)
 
321
  if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
328
322
    date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
329
 
 
330
 
  if (int2_class_decimal(E_DEC_FATAL_ERROR, date, false, dec))
 
323
  if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
331
324
    return dec;
332
 
 
333
325
  if (ltime->second_part)
334
326
  {
335
327
    dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
336
328
    dec->frac= 6;
337
329
  }
338
 
 
339
330
  return dec;
340
331
}
341
332
 
342
333
 
343
 
void class_decimal_trim(uint32_t *precision, uint32_t *scale)
 
334
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
344
335
{
345
336
  if (!(*precision) && !(*scale))
346
337
  {
373
364
#define DIG_MASK     100000000
374
365
#define DIG_BASE     1000000000
375
366
#define DIG_MAX      (DIG_BASE-1)
376
 
 
377
 
template<typename T> 
378
 
inline static T round_up(const T &x)
379
 
{
380
 
  return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
381
 
}
382
 
 
 
367
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
383
368
static const dec1 powers10[DIG_PER_DEC1+1]={
384
369
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
385
370
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
388
373
  999900000, 999990000, 999999000,
389
374
  999999900, 999999990 };
390
375
 
391
 
#ifdef HAVE_VALGRIND
 
376
#ifdef HAVE_purify
392
377
#define sanity(d) assert((d)->len > 0)
393
378
#else
394
379
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
395
380
                              (d)->buf[(d)->len-1] | 1))
396
381
#endif
397
382
 
398
 
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
399
 
{
400
 
  if (unlikely(intg1+frac1 > len))
401
 
  {
402
 
    if (unlikely(intg1 > len))
403
 
    {
404
 
      intg1=(len);
405
 
      frac1=0;
406
 
      error=E_DEC_OVERFLOW;
407
 
    }
408
 
    else
409
 
    {
410
 
      frac1=(len)-intg1;
411
 
      error=E_DEC_TRUNCATED;
412
 
    }
413
 
  }
414
 
  else
415
 
    error=E_DEC_OK;
416
 
}
417
 
 
418
 
/* assume carry <= 1 */
419
 
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
420
 
{
421
 
  dec1 a=from1+from2+carry;
422
 
  assert(carry <= 1);
423
 
  if ((carry= (a >= DIG_BASE))) /* no division here! */
424
 
    a-=DIG_BASE;
425
 
  to=a;
426
 
}
427
 
 
428
 
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
429
 
{
430
 
  dec2 a=dec2(from1)+from2+carry;
431
 
  if ((carry= (a >= DIG_BASE)))
432
 
    a-=DIG_BASE;
433
 
  if (unlikely(a >= DIG_BASE))
434
 
  {
435
 
    a-=DIG_BASE;
436
 
    carry++;
437
 
  }
438
 
  to=dec1(a);
439
 
}
440
 
 
441
 
/* to=from1-from2 */
442
 
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
443
 
{
444
 
  dec1 a=from1-from2-carry;
445
 
  if ((carry= (a < 0)))
446
 
    a+=DIG_BASE;
447
 
  to=a;
448
 
}
449
 
 
450
 
/* to=from1-from2 */
451
 
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
452
 
{
453
 
  dec1 a=from1-from2-carry;
454
 
  if ((carry= (a < 0)))
455
 
    a+=DIG_BASE;
456
 
  if (unlikely(a < 0))
457
 
  {
458
 
    a+=DIG_BASE;
459
 
    carry++;
460
 
  }
461
 
  to=a;
462
 
}
 
383
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error)                   \
 
384
        do                                                              \
 
385
        {                                                               \
 
386
          if (unlikely(intg1+frac1 > (len)))                            \
 
387
          {                                                             \
 
388
            if (unlikely(intg1 > (len)))                                \
 
389
            {                                                           \
 
390
              intg1=(len);                                              \
 
391
              frac1=0;                                                  \
 
392
              error=E_DEC_OVERFLOW;                                     \
 
393
            }                                                           \
 
394
            else                                                        \
 
395
            {                                                           \
 
396
              frac1=(len)-intg1;                                        \
 
397
              error=E_DEC_TRUNCATED;                                    \
 
398
            }                                                           \
 
399
          }                                                             \
 
400
          else                                                          \
 
401
            error=E_DEC_OK;                                             \
 
402
        } while(0)
 
403
 
 
404
#define ADD(to, from1, from2, carry)  /* assume carry <= 1 */           \
 
405
        do                                                              \
 
406
        {                                                               \
 
407
          dec1 a=(from1)+(from2)+(carry);                               \
 
408
          assert((carry) <= 1);                                    \
 
409
          if (((carry)= a >= DIG_BASE)) /* no division here! */         \
 
410
            a-=DIG_BASE;                                                \
 
411
          (to)=a;                                                       \
 
412
        } while(0)
 
413
 
 
414
#define ADD2(to, from1, from2, carry)                                   \
 
415
        do                                                              \
 
416
        {                                                               \
 
417
          dec2 a=((dec2)(from1))+(from2)+(carry);                       \
 
418
          if (((carry)= a >= DIG_BASE))                                 \
 
419
            a-=DIG_BASE;                                                \
 
420
          if (unlikely(a >= DIG_BASE))                                  \
 
421
          {                                                             \
 
422
            a-=DIG_BASE;                                                \
 
423
            carry++;                                                    \
 
424
          }                                                             \
 
425
          (to)=(dec1) a;                                                \
 
426
        } while(0)
 
427
 
 
428
#define SUB(to, from1, from2, carry) /* to=from1-from2 */               \
 
429
        do                                                              \
 
430
        {                                                               \
 
431
          dec1 a=(from1)-(from2)-(carry);                               \
 
432
          if (((carry)= a < 0))                                         \
 
433
            a+=DIG_BASE;                                                \
 
434
          (to)=a;                                                       \
 
435
        } while(0)
 
436
 
 
437
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */              \
 
438
        do                                                              \
 
439
        {                                                               \
 
440
          dec1 a=(from1)-(from2)-(carry);                               \
 
441
          if (((carry)= a < 0))                                         \
 
442
            a+=DIG_BASE;                                                \
 
443
          if (unlikely(a < 0))                                          \
 
444
          {                                                             \
 
445
            a+=DIG_BASE;                                                \
 
446
            carry++;                                                    \
 
447
          }                                                             \
 
448
          (to)=a;                                                       \
 
449
        } while(0)
 
450
 
 
451
/**
 
452
  Swap the contents of two variables.
 
453
 */
 
454
#define swap_variables(TYPE, a, b) \
 
455
  do {                             \
 
456
    TYPE dummy;                    \
 
457
    dummy= a;                      \
 
458
    a= b;                          \
 
459
    b= dummy;                      \
 
460
  } while (0)
 
461
 
 
462
 
463
463
 
464
464
/**
465
465
  @brief  Get maximum value for given precision and scale
528
528
int decimal_actual_fraction(decimal_t *from)
529
529
{
530
530
  int frac= from->frac, i;
531
 
  dec1 *buf0= from->buf + round_up(from->intg) + round_up(frac) - 1;
 
531
  dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
532
532
 
533
533
  if (frac == 0)
534
534
    return 0;
633
633
  {
634
634
    char *s1= s + intg_len;
635
635
    fill= frac_len - frac;
636
 
    buf=buf0+round_up(intg);
 
636
    buf=buf0+ROUND_UP(intg);
637
637
    *s1++='.';
638
638
    for (; frac>0; frac-=DIG_PER_DEC1)
639
639
    {
658
658
  if (intg)
659
659
  {
660
660
    s+=intg;
661
 
    for (buf=buf0+round_up(intg); intg>0; intg-=DIG_PER_DEC1)
 
661
    for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
662
662
    {
663
663
      dec1 x=*--buf;
664
664
      for (i=min(intg, DIG_PER_DEC1); i; i--)
688
688
{
689
689
  int start, stop, i;
690
690
  dec1 *buf_beg= from->buf;
691
 
  dec1 *end= from->buf + round_up(from->intg) + round_up(from->frac);
 
691
  dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
692
692
  dec1 *buf_end= end - 1;
693
693
 
694
694
  /* find non-zero digit from number begining */
754
754
*/
755
755
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
756
756
{
757
 
  dec1 *from= dec->buf + round_up(beg + 1) - 1;
758
 
  dec1 *end= dec->buf + round_up(last) - 1;
 
757
  dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
 
758
  dec1 *end= dec->buf + ROUND_UP(last) - 1;
759
759
  int c_shift= DIG_PER_DEC1 - shift;
760
760
  assert(from >= dec->buf);
761
761
  assert(end < dec->buf + dec->len);
782
782
*/
783
783
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
784
784
{
785
 
  dec1 *from= dec->buf + round_up(last) - 1;
786
 
  dec1 *end= dec->buf + round_up(beg + 1) - 1;
 
785
  dec1 *from= dec->buf + ROUND_UP(last) - 1;
 
786
  dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
787
787
  int c_shift= DIG_PER_DEC1 - shift;
788
788
  assert(from < dec->buf + dec->len);
789
789
  assert(end >= dec->buf);
819
819
  /* index of position after last decimal digit */
820
820
  int end;
821
821
  /* index of digit position just after point */
822
 
  int point= round_up(dec->intg) * DIG_PER_DEC1;
 
822
  int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
823
823
  /* new point position */
824
824
  int new_point= point + shift;
825
825
  /* number of digits in result */
837
837
 
838
838
  if (beg == end)
839
839
  {
840
 
    dec->set_zero();
 
840
    decimal_make_zero(dec);
841
841
    return E_DEC_OK;
842
842
  }
843
843
 
846
846
  digits_frac= end - new_point;
847
847
  set_if_bigger(digits_frac, 0);
848
848
 
849
 
  if ((new_len= round_up(digits_int) + (new_frac_len= round_up(digits_frac))) >
 
849
  if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
850
850
      dec->len)
851
851
  {
852
852
    int lack= new_len - dec->len;
870
870
        we lost all digits (they will be shifted out of buffer), so we can
871
871
        just return 0
872
872
      */
873
 
      dec->set_zero();
874
 
 
 
873
      decimal_make_zero(dec);
875
874
      return E_DEC_TRUNCATED;
876
875
    }
877
876
  }
907
906
    if (do_left)
908
907
    {
909
908
      do_mini_left_shift(dec, l_mini_shift, beg, end);
910
 
      mini_shift= (-l_mini_shift);
 
909
      mini_shift=- l_mini_shift;
911
910
    }
912
911
    else
913
912
    {
940
939
    {
941
940
      /* move left */
942
941
      d_shift= new_front / DIG_PER_DEC1;
943
 
      to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
944
 
      barier= dec->buf + (round_up(end) - 1 - d_shift);
 
942
      to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
 
943
      barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
945
944
      assert(to >= dec->buf);
946
945
      assert(barier + d_shift < dec->buf + dec->len);
947
946
      for(; to <= barier; to++)
954
953
    {
955
954
      /* move right */
956
955
      d_shift= (1 - new_front) / DIG_PER_DEC1;
957
 
      to= dec->buf + round_up(end) - 1 + d_shift;
958
 
      barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
 
956
      to= dec->buf + ROUND_UP(end) - 1 + d_shift;
 
957
      barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
959
958
      assert(to < dec->buf + dec->len);
960
959
      assert(barier - d_shift >= dec->buf);
961
960
      for(; to >= barier; to--)
974
973
 
975
974
    Only one of following 'for' loops will work becouse beg <= end
976
975
  */
977
 
  beg= round_up(beg + 1) - 1;
978
 
  end= round_up(end) - 1;
 
976
  beg= ROUND_UP(beg + 1) - 1;
 
977
  end= ROUND_UP(end) - 1;
979
978
  assert(new_point >= 0);
980
979
 
981
980
  /* We don't want negative new_point below */
982
981
  if (new_point != 0)
983
 
    new_point= round_up(new_point) - 1;
 
982
    new_point= ROUND_UP(new_point) - 1;
984
983
 
985
984
  if (new_point > end)
986
985
  {
1075
1074
      error=E_DEC_OVERFLOW;
1076
1075
      intg=to->intg;
1077
1076
    }
1078
 
    intg1=round_up(intg);
1079
 
    frac1=round_up(frac);
 
1077
    intg1=ROUND_UP(intg);
 
1078
    frac1=ROUND_UP(frac);
1080
1079
    if (intg1+frac1 > to->len)
1081
1080
    {
1082
1081
      error= E_DEC_OOM;
1085
1084
  }
1086
1085
  else
1087
1086
  {
1088
 
    intg1=round_up(intg);
1089
 
    frac1=round_up(frac);
1090
 
    fix_intg_frac_error(to->len, intg1, frac1, error);
 
1087
    intg1=ROUND_UP(intg);
 
1088
    frac1=ROUND_UP(frac);
 
1089
    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1091
1090
    if (unlikely(error))
1092
1091
    {
1093
1092
      frac=frac1*DIG_PER_DEC1;
1163
1162
  return error;
1164
1163
 
1165
1164
fatal_error:
1166
 
  to->set_zero();
 
1165
  decimal_make_zero(to);
1167
1166
  return error;
1168
1167
}
1169
1168
 
1551
1550
  d_copy[0]^= 0x80;
1552
1551
  from= d_copy;
1553
1552
 
1554
 
  fix_intg_frac_error(to->len, intg1, frac1, error);
 
1553
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1555
1554
  if (unlikely(error))
1556
1555
  {
1557
1556
    if (intg1 < intg0+(intg0x>0))
1632
1631
  return error;
1633
1632
 
1634
1633
err:
1635
 
  to->set_zero();
 
1634
  decimal_make_zero(((decimal_t*) to));
1636
1635
  return(E_DEC_BAD_NUM);
1637
1636
}
1638
1637
 
1671
1670
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1672
1671
              decimal_round_mode mode)
1673
1672
{
1674
 
  int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
1675
 
      frac1=round_up(from->frac), round_digit= 0,
1676
 
      intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
1677
 
      intg1=round_up(from->intg +
 
1673
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
 
1674
      frac1=ROUND_UP(from->frac), round_digit= 0,
 
1675
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
 
1676
      intg1=ROUND_UP(from->intg +
1678
1677
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1679
1678
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1680
1679
  int first_dig;
1699
1698
 
1700
1699
  if (scale+from->intg < 0)
1701
1700
  {
1702
 
    to->set_zero();
 
1701
    decimal_make_zero(to);
1703
1702
    return E_DEC_OK;
1704
1703
  }
1705
1704
 
1770
1769
    }
1771
1770
    else if (frac0+intg0==0)
1772
1771
    {
1773
 
      to->set_zero();
 
1772
      decimal_make_zero(to);
1774
1773
      return E_DEC_OK;
1775
1774
    }
1776
1775
  }
1809
1808
    carry=1;
1810
1809
    *buf1-=DIG_BASE;
1811
1810
    while (carry && --buf1 >= to->buf)
1812
 
      add(*buf1, *buf1, 0, carry);
 
1811
      ADD(*buf1, *buf1, 0, carry);
1813
1812
    if (unlikely(carry))
1814
1813
    {
1815
1814
      /* shifting the number to create space for new digit */
1862
1861
 
1863
1862
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1864
1863
{
1865
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1866
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
 
1864
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1865
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1867
1866
      frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1868
1867
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1869
1868
 
1879
1878
    to->buf[0]=0; /* safety */
1880
1879
  }
1881
1880
 
1882
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
1881
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1883
1882
  if (unlikely(error == E_DEC_OVERFLOW))
1884
1883
  {
1885
1884
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1922
1921
  carry=0;
1923
1922
  while (buf1 > stop2)
1924
1923
  {
1925
 
    add(*--buf0, *--buf1, *--buf2, carry);
 
1924
    ADD(*--buf0, *--buf1, *--buf2, carry);
1926
1925
  }
1927
1926
 
1928
1927
  /* part 3 - cmin(intg) ... cmax(intg) */
1930
1929
                        ((stop=from2->buf)+intg2-intg1) ;
1931
1930
  while (buf1 > stop)
1932
1931
  {
1933
 
    add(*--buf0, *--buf1, 0, carry);
 
1932
    ADD(*--buf0, *--buf1, 0, carry);
1934
1933
  }
1935
1934
 
1936
1935
  if (unlikely(carry))
1944
1943
   if to==0, return -1/0/+1 - the result of the comparison */
1945
1944
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1946
1945
{
1947
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1948
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac);
 
1946
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1947
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1949
1948
  int frac0=max(frac1, frac2), error;
1950
1949
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1951
1950
 
1995
1994
      {
1996
1995
        if (to == 0) /* decimal_cmp() */
1997
1996
          return 0;
1998
 
 
1999
 
        to->set_zero();
2000
 
 
 
1997
        decimal_make_zero(to);
2001
1998
        return E_DEC_OK;
2002
1999
      }
2003
2000
    }
2013
2010
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
2014
2011
  if (carry)
2015
2012
  {
2016
 
    swap(from1, from2);
2017
 
    swap(start1, start2);
2018
 
    swap(intg1, intg2);
2019
 
    swap(frac1, frac2);
 
2013
    swap_variables(const decimal_t *,from1, from2);
 
2014
    swap_variables(dec1 *,start1, start2);
 
2015
    swap_variables(int,intg1,intg2);
 
2016
    swap_variables(int,frac1,frac2);
2020
2017
    to->sign= 1 - to->sign;
2021
2018
  }
2022
2019
 
2023
 
  fix_intg_frac_error(to->len, intg1, frac0, error);
 
2020
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
2024
2021
  buf0=to->buf+intg1+frac0;
2025
2022
 
2026
2023
  to->frac=max(from1->frac, from2->frac);
2054
2051
      *--buf0=0;
2055
2052
    while (buf2 > stop2)
2056
2053
    {
2057
 
      sub(*--buf0, 0, *--buf2, carry);
 
2054
      SUB(*--buf0, 0, *--buf2, carry);
2058
2055
    }
2059
2056
  }
2060
2057
 
2061
2058
  /* part 2 - cmin(frac) ... intg2 */
2062
2059
  while (buf2 > start2)
2063
2060
  {
2064
 
    sub(*--buf0, *--buf1, *--buf2, carry);
 
2061
    SUB(*--buf0, *--buf1, *--buf2, carry);
2065
2062
  }
2066
2063
 
2067
2064
  /* part 3 - intg2 ... intg1 */
2068
2065
  while (carry && buf1 > start1)
2069
2066
  {
2070
 
    sub(*--buf0, *--buf1, 0, carry);
 
2067
    SUB(*--buf0, *--buf1, 0, carry);
2071
2068
  }
2072
2069
 
2073
2070
  while (buf1 > start1)
2108
2105
  return from1->sign > from2->sign ? -1 : 1;
2109
2106
}
2110
2107
 
2111
 
int decimal_t::isZero() const
 
2108
int decimal_is_zero(const decimal_t *from)
2112
2109
{
2113
 
  dec1 *buf1= buf,
2114
 
       *end= buf1 +round_up(intg) +round_up(frac);
2115
 
 
 
2110
  dec1 *buf1=from->buf,
 
2111
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2116
2112
  while (buf1 < end)
2117
 
  {
2118
2113
    if (*buf1++)
2119
 
    {
2120
2114
      return 0;
2121
 
    }
2122
 
  }
2123
 
 
2124
2115
  return 1;
2125
2116
}
2126
2117
 
2146
2137
*/
2147
2138
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2148
2139
{
2149
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
2150
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
2151
 
      intg0=round_up(from1->intg+from2->intg),
 
2140
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
2141
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
 
2142
      intg0=ROUND_UP(from1->intg+from2->intg),
2152
2143
      frac0=frac1+frac2, error, i, j, d_to_move;
2153
2144
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2154
2145
       *start2, *stop2, *stop1, *start0, carry;
2157
2148
 
2158
2149
  i=intg0;
2159
2150
  j=frac0;
2160
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
2151
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2161
2152
  to->sign=from1->sign != from2->sign;
2162
2153
  to->frac=from1->frac+from2->frac;
2163
2154
  to->intg=intg0*DIG_PER_DEC1;
2198
2189
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2199
2190
      hi=(dec1)(p/DIG_BASE);
2200
2191
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2201
 
      add2(*buf0, *buf0, lo, carry);
 
2192
      ADD2(*buf0, *buf0, lo, carry);
2202
2193
      carry+=hi;
2203
2194
    }
2204
2195
    if (carry)
2205
2196
    {
2206
2197
      if (buf0 < to->buf)
2207
2198
        return E_DEC_OVERFLOW;
2208
 
      add2(*buf0, *buf0, 0, carry);
 
2199
      ADD2(*buf0, *buf0, 0, carry);
2209
2200
    }
2210
2201
    for (buf0--; carry; buf0--)
2211
2202
    {
2212
2203
      if (buf0 < to->buf)
2213
2204
        return E_DEC_OVERFLOW;
2214
 
      add(*buf0, *buf0, 0, carry);
 
2205
      ADD(*buf0, *buf0, 0, carry);
2215
2206
    }
2216
2207
  }
2217
2208
 
2228
2219
      if (++buf == end)
2229
2220
      {
2230
2221
        /* We got decimal zero */
2231
 
        to->set_zero();
 
2222
        decimal_make_zero(to);
2232
2223
        break;
2233
2224
      }
2234
2225
    }
2235
2226
  }
2236
2227
  buf1= to->buf;
2237
 
  d_to_move= intg0 + round_up(to->frac);
 
2228
  d_to_move= intg0 + ROUND_UP(to->frac);
2238
2229
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2239
2230
  {
2240
2231
    buf1++;
2264
2255
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2265
2256
                       decimal_t *to, decimal_t *mod, int scale_incr)
2266
2257
{
2267
 
  int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2268
 
      frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
 
2258
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
 
2259
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2269
2260
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2270
2261
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2271
2262
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2298
2289
  }
2299
2290
  if (prec1 <= 0)
2300
2291
  { /* short-circuit everything: from1 == 0 */
2301
 
    to->set_zero();
 
2292
    decimal_make_zero(to);
2302
2293
    return E_DEC_OK;
2303
2294
  }
2304
2295
  for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2315
2306
    intg0=0;
2316
2307
  }
2317
2308
  else
2318
 
    intg0=round_up(dintg);
 
2309
    intg0=ROUND_UP(dintg);
2319
2310
  if (mod)
2320
2311
  {
2321
2312
    /* we're calculating N1 % N2.
2334
2325
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2335
2326
      frac2 accordingly.
2336
2327
      Thus, the result will have
2337
 
         frac = round_up(frac1+frac2+scale_incr)
 
2328
         frac = ROUND_UP(frac1+frac2+scale_incr)
2338
2329
      and
2339
2330
         intg = (prec1-frac1) - (prec2-frac2) + 1
2340
2331
         prec = intg+frac
2341
2332
    */
2342
 
    frac0=round_up(frac1+frac2+scale_incr);
2343
 
    fix_intg_frac_error(to->len, intg0, frac0, error);
 
2333
    frac0=ROUND_UP(frac1+frac2+scale_incr);
 
2334
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2344
2335
    to->sign=from1->sign != from2->sign;
2345
2336
    to->intg=intg0*DIG_PER_DEC1;
2346
2337
    to->frac=frac0*DIG_PER_DEC1;
2351
2342
    while (dintg++ < 0)
2352
2343
      *buf0++=0;
2353
2344
 
2354
 
  len1=(i=round_up(prec1))+round_up(2*frac2+scale_incr+1) + 1;
 
2345
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2355
2346
  set_if_bigger(len1, 3);
2356
2347
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
2357
2348
    return E_DEC_OOM;
2361
2352
  start1=tmp1;
2362
2353
  stop1=start1+len1;
2363
2354
  start2=buf2;
2364
 
  stop2=buf2+round_up(prec2)-1;
 
2355
  stop2=buf2+ROUND_UP(prec2)-1;
2365
2356
 
2366
2357
  /* removing end zeroes */
2367
2358
  while (*stop2 == 0 && stop2 >= start2)
2420
2411
        x=guess * (*--buf2);
2421
2412
        hi=(dec1)(x/DIG_BASE);
2422
2413
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2423
 
        sub2(*buf1, *buf1, lo, carry);
 
2414
        SUB2(*buf1, *buf1, lo, carry);
2424
2415
        carry+=hi;
2425
2416
      }
2426
2417
      carry= dcarry < carry;
2434
2425
        buf1=start1+len2;
2435
2426
        for (carry=0; buf2 > start2; buf1--)
2436
2427
        {
2437
 
          add(*buf1, *buf1, *--buf2, carry);
 
2428
          ADD(*buf1, *buf1, *--buf2, carry);
2438
2429
        }
2439
2430
      }
2440
2431
    }
2453
2444
    if (dcarry)
2454
2445
      *--start1=dcarry;
2455
2446
    buf0=to->buf;
2456
 
    intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
2457
 
    frac0=round_up(to->frac);
 
2447
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
 
2448
    frac0=ROUND_UP(to->frac);
2458
2449
    error=E_DEC_OK;
2459
2450
    if (unlikely(frac0==0 && intg0==0))
2460
2451
    {
2461
 
      to->set_zero();
 
2452
      decimal_make_zero(to);
2462
2453
      goto done;
2463
2454
    }
2464
2455
    if (intg0<=0)
2465
2456
    {
2466
2457
      if (unlikely(-intg0 >= to->len))
2467
2458
      {
2468
 
        to->set_zero();
 
2459
        decimal_make_zero(to);
2469
2460
        error=E_DEC_TRUNCATED;
2470
2461
        goto done;
2471
2462
      }
2484
2475
        error=E_DEC_OVERFLOW;
2485
2476
        goto done;
2486
2477
      }
2487
 
      assert(intg0 <= round_up(from2->intg));
 
2478
      assert(intg0 <= ROUND_UP(from2->intg));
2488
2479
      stop1=start1+frac0+intg0;
2489
2480
      to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2490
2481
    }
2552
2543
  return do_div_mod(from1, from2, 0, to, 0);
2553
2544
}
2554
2545
 
2555
 
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec)
2556
 
{
2557
 
  drizzled::String str;
2558
 
 
2559
 
  class_decimal2string(&dec, 0, &str);
2560
 
 
2561
 
  output << "type::Decimal:(";
2562
 
  output <<  str.c_ptr();
2563
 
  output << ")";
2564
 
 
2565
 
  return output;  // for multiple << operators.
2566
 
}
2567
 
 
2568
2546
} /* namespace drizzled */
2569
2547
 
2570
2548
#ifdef MAIN
2577
2555
{
2578
2556
  int i;
2579
2557
  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2580
 
  for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
 
2558
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2581
2559
    printf("%09d, ", d->buf[i]);
2582
2560
  printf("%09d} */ ", d->buf[i]);
2583
2561
}
3298
3276
 
3299
3277
  return 0;
3300
3278
}
3301
 
 
3302
3279
#endif