~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/decimal.cc

  • Committer: Brian Aker
  • Date: 2010-09-12 01:42:27 UTC
  • mto: (1759.2.1 build)
  • mto: This revision was merged to the branch mainline in revision 1762.
  • Revision ID: brian@tangent.org-20100912014227-krt6d9z5ohqrokhb
Add two plugins to handle the string and math functions.

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 */
15
 
 
16
 
/** @file
17
 
 *
18
 
 * @brief  SQL standard-compliant decimal number handling
19
 
 *
20
 
 * @note
21
 
 * This library implements SQL standard "exact numeric" type
22
 
 * and is not at all generic, but rather intentinally crippled to
23
 
 * follow the standard :) 
24
 
 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
25
15
 
26
16
/*
27
17
=======================================================================
 
18
  NOTE: this library implements SQL standard "exact numeric" type
 
19
  and is not at all generic, but rather intentinally crippled to
 
20
  follow the standard :)
 
21
=======================================================================
28
22
  Quoting the standard
29
23
  (SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
30
24
 
157
151
                        "DECIMAL", "");
158
152
    break;
159
153
  case E_DEC_DIV_ZERO:
160
 
    my_error(ER_DIVISION_BY_ZERO, MYF(0));
 
154
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
155
                        ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
161
156
    break;
162
157
  case E_DEC_BAD_NUM:
163
158
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
187
182
  @param[in]   filler      what char to pad with (ZEROFILL et al.)
188
183
  @param[out]  *str        where to store the resulting string
189
184
 
190
 
  @return error code
 
185
  @return error coce
191
186
    @retval E_DEC_OK
192
187
    @retval E_DEC_TRUNCATED
193
188
    @retval E_DEC_OVERFLOW
209
204
    fixed_prec will be 0, and my_decimal_string_length() will be called
210
205
    instead to calculate the required size of the buffer.
211
206
  */
212
 
  int length= (int)(fixed_prec
213
 
                    ? (uint32_t)(fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
214
 
                    : (uint32_t)my_decimal_string_length(d));
 
207
  int length= (fixed_prec
 
208
               ? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
 
209
               : my_decimal_string_length(d));
215
210
  int result;
216
211
  if (str->alloc(length))
217
212
    return check_result(mask, E_DEC_OOM);
223
218
}
224
219
 
225
220
 
226
 
/**
227
 
  @brief  Convert from decimal to binary representation
228
 
 
229
 
  @param[in]   mask        error processing mask
230
 
  @param[in]   d           number for conversion
231
 
  @param[out]  bin         pointer to buffer where to write result
232
 
  @param[in]   prec        overall number of decimal digits
233
 
  @param[in]   scale       number of decimal digits after decimal point
234
 
 
235
 
  @note
 
221
/*
 
222
  Convert from decimal to binary representation
 
223
 
 
224
  SYNOPSIS
 
225
    my_decimal2binary()
 
226
    mask        error processing mask
 
227
    d           number for conversion
 
228
    bin         pointer to buffer where to write result
 
229
    prec        overall number of decimal digits
 
230
    scale       number of decimal digits after decimal point
 
231
 
 
232
  NOTE
236
233
    Before conversion we round number if it need but produce truncation
237
234
    error in this case
238
235
 
239
 
  @return error code
240
 
   @retval E_DEC_OK
241
 
   @retval E_DEC_TRUNCATED
242
 
   @retval E_DEC_OVERFLOW
 
236
  RETURN
 
237
    E_DEC_OK
 
238
    E_DEC_TRUNCATED
 
239
    E_DEC_OVERFLOW
243
240
*/
244
241
 
245
242
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
262
259
}
263
260
 
264
261
 
265
 
/**
266
 
  @brief Convert string for decimal when string can be in some multibyte charset
267
 
 
268
 
  @param  mask            error processing mask
269
 
  @param  from            string to process
270
 
  @param  length          length of given string
271
 
  @param  charset         charset of given string
272
 
  @param  decimal_value   buffer for result storing
273
 
 
274
 
  @return Error code
275
 
   @retval E_DEC_OK
276
 
   @retval E_DEC_TRUNCATED
277
 
   @retval E_DEC_OVERFLOW
278
 
   @retval E_DEC_BAD_NUM
279
 
   @retval E_DEC_OOM
 
262
/*
 
263
  Convert string for decimal when string can be in some multibyte charset
 
264
 
 
265
  SYNOPSIS
 
266
    str2my_decimal()
 
267
    mask            error processing mask
 
268
    from            string to process
 
269
    length          length of given string
 
270
    charset         charset of given string
 
271
    decimal_value   buffer for result storing
 
272
 
 
273
  RESULT
 
274
    E_DEC_OK
 
275
    E_DEC_TRUNCATED
 
276
    E_DEC_OVERFLOW
 
277
    E_DEC_BAD_NUM
 
278
    E_DEC_OOM
280
279
*/
281
280
 
282
281
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
288
287
  String tmp(buff, sizeof(buff), &my_charset_bin);
289
288
  if (charset->mbminlen > 1)
290
289
  {
291
 
    size_t dummy_errors;
 
290
    uint32_t dummy_errors;
292
291
    tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
293
292
    from= tmp.ptr();
294
293
    length=  tmp.length();
363
362
#define DIG_MASK     100000000
364
363
#define DIG_BASE     1000000000
365
364
#define DIG_MAX      (DIG_BASE-1)
366
 
 
367
 
template<typename T> 
368
 
inline static T round_up(const T &x)
369
 
{
370
 
  return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
371
 
}
372
 
 
 
365
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
373
366
static const dec1 powers10[DIG_PER_DEC1+1]={
374
367
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
375
368
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
378
371
  999900000, 999990000, 999999000,
379
372
  999999900, 999999990 };
380
373
 
381
 
#ifdef HAVE_VALGRIND
 
374
#ifdef HAVE_purify
382
375
#define sanity(d) assert((d)->len > 0)
383
376
#else
384
377
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
385
378
                              (d)->buf[(d)->len-1] | 1))
386
379
#endif
387
380
 
388
 
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
389
 
{
390
 
  if (unlikely(intg1+frac1 > len))
391
 
  {
392
 
    if (unlikely(intg1 > len))
393
 
    {
394
 
      intg1=(len);
395
 
      frac1=0;
396
 
      error=E_DEC_OVERFLOW;
397
 
    }
398
 
    else
399
 
    {
400
 
      frac1=(len)-intg1;
401
 
      error=E_DEC_TRUNCATED;
402
 
    }
403
 
  }
404
 
  else
405
 
    error=E_DEC_OK;
406
 
}
407
 
 
408
 
/* assume carry <= 1 */
409
 
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
410
 
{
411
 
  dec1 a=from1+from2+carry;
412
 
  assert(carry <= 1);
413
 
  if ((carry= (a >= DIG_BASE))) /* no division here! */
414
 
    a-=DIG_BASE;
415
 
  to=a;
416
 
}
417
 
 
418
 
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
419
 
{
420
 
  dec2 a=dec2(from1)+from2+carry;
421
 
  if ((carry= (a >= DIG_BASE)))
422
 
    a-=DIG_BASE;
423
 
  if (unlikely(a >= DIG_BASE))
424
 
  {
425
 
    a-=DIG_BASE;
426
 
    carry++;
427
 
  }
428
 
  to=dec1(a);
429
 
}
430
 
 
431
 
/* to=from1-from2 */
432
 
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
433
 
{
434
 
  dec1 a=from1-from2-carry;
435
 
  if ((carry= (a < 0)))
436
 
    a+=DIG_BASE;
437
 
  to=a;
438
 
}
439
 
 
440
 
/* to=from1-from2 */
441
 
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
442
 
{
443
 
  dec1 a=from1-from2-carry;
444
 
  if ((carry= (a < 0)))
445
 
    a+=DIG_BASE;
446
 
  if (unlikely(a < 0))
447
 
  {
448
 
    a+=DIG_BASE;
449
 
    carry++;
450
 
  }
451
 
  to=a;
452
 
}
 
381
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error)                   \
 
382
        do                                                              \
 
383
        {                                                               \
 
384
          if (unlikely(intg1+frac1 > (len)))                            \
 
385
          {                                                             \
 
386
            if (unlikely(intg1 > (len)))                                \
 
387
            {                                                           \
 
388
              intg1=(len);                                              \
 
389
              frac1=0;                                                  \
 
390
              error=E_DEC_OVERFLOW;                                     \
 
391
            }                                                           \
 
392
            else                                                        \
 
393
            {                                                           \
 
394
              frac1=(len)-intg1;                                        \
 
395
              error=E_DEC_TRUNCATED;                                    \
 
396
            }                                                           \
 
397
          }                                                             \
 
398
          else                                                          \
 
399
            error=E_DEC_OK;                                             \
 
400
        } while(0)
 
401
 
 
402
#define ADD(to, from1, from2, carry)  /* assume carry <= 1 */           \
 
403
        do                                                              \
 
404
        {                                                               \
 
405
          dec1 a=(from1)+(from2)+(carry);                               \
 
406
          assert((carry) <= 1);                                    \
 
407
          if (((carry)= a >= DIG_BASE)) /* no division here! */         \
 
408
            a-=DIG_BASE;                                                \
 
409
          (to)=a;                                                       \
 
410
        } while(0)
 
411
 
 
412
#define ADD2(to, from1, from2, carry)                                   \
 
413
        do                                                              \
 
414
        {                                                               \
 
415
          dec2 a=((dec2)(from1))+(from2)+(carry);                       \
 
416
          if (((carry)= a >= DIG_BASE))                                 \
 
417
            a-=DIG_BASE;                                                \
 
418
          if (unlikely(a >= DIG_BASE))                                  \
 
419
          {                                                             \
 
420
            a-=DIG_BASE;                                                \
 
421
            carry++;                                                    \
 
422
          }                                                             \
 
423
          (to)=(dec1) a;                                                \
 
424
        } while(0)
 
425
 
 
426
#define SUB(to, from1, from2, carry) /* to=from1-from2 */               \
 
427
        do                                                              \
 
428
        {                                                               \
 
429
          dec1 a=(from1)-(from2)-(carry);                               \
 
430
          if (((carry)= a < 0))                                         \
 
431
            a+=DIG_BASE;                                                \
 
432
          (to)=a;                                                       \
 
433
        } while(0)
 
434
 
 
435
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */              \
 
436
        do                                                              \
 
437
        {                                                               \
 
438
          dec1 a=(from1)-(from2)-(carry);                               \
 
439
          if (((carry)= a < 0))                                         \
 
440
            a+=DIG_BASE;                                                \
 
441
          if (unlikely(a < 0))                                          \
 
442
          {                                                             \
 
443
            a+=DIG_BASE;                                                \
 
444
            carry++;                                                    \
 
445
          }                                                             \
 
446
          (to)=a;                                                       \
 
447
        } while(0)
453
448
 
454
449
/**
455
 
  @brief  Get maximum value for given precision and scale
456
 
 
457
 
  @param  precision/scale  see decimal_bin_size() below
458
 
  @param  to              decimal where where the result will be stored
 
450
  Swap the contents of two variables.
 
451
 */
 
452
#define swap_variables(TYPE, a, b) \
 
453
  do {                             \
 
454
    TYPE dummy;                    \
 
455
    dummy= a;                      \
 
456
    a= b;                          \
 
457
    b= dummy;                      \
 
458
  } while (0)
 
459
 
 
460
 
 
461
 
 
462
/*
 
463
  Get maximum value for given precision and scale
 
464
 
 
465
  SYNOPSIS
 
466
    max_decimal()
 
467
    precision/scale - see decimal_bin_size() below
 
468
    to              - decimal where where the result will be stored
459
469
                      to->buf and to->len must be set.
460
470
*/
461
471
 
509
519
}
510
520
 
511
521
 
512
 
/**
513
 
 @brief Count actual length of fraction part (without ending zeroes)
 
522
/*
 
523
  Count actual length of fraction part (without ending zeroes)
514
524
 
515
 
 @param from    number for processing
 
525
  SYNOPSIS
 
526
    decimal_actual_fraction()
 
527
    from    number for processing
516
528
*/
517
529
 
518
530
int decimal_actual_fraction(decimal_t *from)
519
531
{
520
532
  int frac= from->frac, i;
521
 
  dec1 *buf0= from->buf + round_up(from->intg) + round_up(frac) - 1;
 
533
  dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
522
534
 
523
535
  if (frac == 0)
524
536
    return 0;
538
550
}
539
551
 
540
552
 
541
 
/**
542
 
 @brief  Convert decimal to its printable string representation
 
553
/*
 
554
  Convert decimal to its printable string representation
543
555
 
544
 
 @param  from       value to convert
545
 
 @param  to         points to buffer where string representation
546
 
                    should be stored
547
 
 @param  to_len     in:  size of to buffer
548
 
                    out: length of the actually written string
549
 
 @param  fixed_precision 0 if representation can be variable length and
 
556
  SYNOPSIS
 
557
    decimal2string()
 
558
      from            - value to convert
 
559
      to              - points to buffer where string representation
 
560
                        should be stored
 
561
      *to_len         - in:  size of to buffer
 
562
                        out: length of the actually written string
 
563
      fixed_precision - 0 if representation can be variable length and
550
564
                        fixed_decimals will not be checked in this case.
551
565
                        Put number as with fixed point position with this
552
566
                        number of digits (sign counted and decimal point is
553
567
                        counted)
554
 
 @param  fixed_decimals  number digits after point.
555
 
 @param  filler          character to fill gaps in case of fixed_precision > 0
 
568
      fixed_decimals  - number digits after point.
 
569
      filler          - character to fill gaps in case of fixed_precision > 0
556
570
 
557
 
 @return error code
558
 
   @retval E_DEC_OK
559
 
   @retval E_DEC_TRUNCATED
560
 
   @retval E_DEC_OVERFLOW
 
571
  RETURN VALUE
 
572
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
561
573
*/
 
574
 
562
575
int decimal2string(const decimal_t *from, char *to, int *to_len,
563
576
                   int fixed_precision, int fixed_decimals,
564
577
                   char filler)
623
636
  {
624
637
    char *s1= s + intg_len;
625
638
    fill= frac_len - frac;
626
 
    buf=buf0+round_up(intg);
 
639
    buf=buf0+ROUND_UP(intg);
627
640
    *s1++='.';
628
641
    for (; frac>0; frac-=DIG_PER_DEC1)
629
642
    {
648
661
  if (intg)
649
662
  {
650
663
    s+=intg;
651
 
    for (buf=buf0+round_up(intg); intg>0; intg-=DIG_PER_DEC1)
 
664
    for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
652
665
    {
653
666
      dec1 x=*--buf;
654
667
      for (i=min(intg, DIG_PER_DEC1); i; i--)
665
678
}
666
679
 
667
680
 
668
 
/**
669
 
 @brief  Return bounds of decimal digits in the number
 
681
/*
 
682
  Return bounds of decimal digits in the number
670
683
 
671
 
 @param  from  decimal number for processing
672
 
 @param  start_result  index (from 0 ) of first decimal digits will
673
 
                       be written by this address
674
 
 @param  end_result   index of position just after last decimal digit
 
684
  SYNOPSIS
 
685
    digits_bounds()
 
686
      from         - decimal number for processing
 
687
      start_result - index (from 0 ) of first decimal digits will
 
688
                     be written by this address
 
689
      end_result   - index of position just after last decimal digit
675
690
                     be written by this address
676
691
*/
 
692
 
677
693
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
678
694
{
679
695
  int start, stop, i;
680
696
  dec1 *buf_beg= from->buf;
681
 
  dec1 *end= from->buf + round_up(from->intg) + round_up(from->frac);
 
697
  dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
682
698
  dec1 *buf_end= end - 1;
683
699
 
684
700
  /* find non-zero digit from number begining */
727
743
}
728
744
 
729
745
 
730
 
/**
731
 
 @param Left shift for alignment of data in buffer
732
 
 
733
 
 @param  dec     pointer to decimal number which have to be shifted
734
 
 @param  shift   number of decimal digits on which it should be shifted
735
 
 @param  beg     beginning of decimal digits (see digits_bounds())
736
 
 @param  end     end of decimal digits (see digits_bounds())
737
 
 
738
 
 @note
739
 
   Result fitting in the buffer should be garanted.
740
 
   'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
741
 
   
742
 
 @todo  Above note is unclear - is 'garanted' a typo for 'guaranteed'
743
 
 or 'granted'?
 
746
/*
 
747
  Left shift for alignment of data in buffer
 
748
 
 
749
  SYNOPSIS
 
750
    do_mini_left_shift()
 
751
    dec     pointer to decimal number which have to be shifted
 
752
    shift   number of decimal digits on which it should be shifted
 
753
    beg/end bounds of decimal digits (see digits_bounds())
 
754
 
 
755
  NOTE
 
756
    Result fitting in the buffer should be garanted.
 
757
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
744
758
*/
 
759
 
745
760
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
746
761
{
747
 
  dec1 *from= dec->buf + round_up(beg + 1) - 1;
748
 
  dec1 *end= dec->buf + round_up(last) - 1;
 
762
  dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
 
763
  dec1 *end= dec->buf + ROUND_UP(last) - 1;
749
764
  int c_shift= DIG_PER_DEC1 - shift;
750
765
  assert(from >= dec->buf);
751
766
  assert(end < dec->buf + dec->len);
758
773
}
759
774
 
760
775
 
761
 
/**
762
 
  @brief Right shift for alignment of data in buffer
763
 
 
764
 
  @param  dec     pointer to decimal number which have to be shifted
765
 
  @param  shift   number of decimal digits on which it should be shifted
766
 
  @param  beg     beginning of decimal digits (see digits_bounds())
767
 
  @param  end     end of decimal digits (see digits_bounds())
768
 
 
769
 
  @note
 
776
/*
 
777
  Right shift for alignment of data in buffer
 
778
 
 
779
  SYNOPSIS
 
780
    do_mini_left_shift()
 
781
    dec     pointer to decimal number which have to be shifted
 
782
    shift   number of decimal digits on which it should be shifted
 
783
    beg/end bounds of decimal digits (see digits_bounds())
 
784
 
 
785
  NOTE
770
786
    Result fitting in the buffer should be garanted.
771
787
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
772
788
*/
 
789
 
773
790
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
774
791
{
775
 
  dec1 *from= dec->buf + round_up(last) - 1;
776
 
  dec1 *end= dec->buf + round_up(beg + 1) - 1;
 
792
  dec1 *from= dec->buf + ROUND_UP(last) - 1;
 
793
  dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
777
794
  int c_shift= DIG_PER_DEC1 - shift;
778
795
  assert(from < dec->buf + dec->len);
779
796
  assert(end >= dec->buf);
786
803
}
787
804
 
788
805
 
789
 
/**
790
 
  @brief  Shift of decimal digits in given number (with rounding if it need)
 
806
/*
 
807
  Shift of decimal digits in given number (with rounding if it need)
791
808
 
792
 
  @param  dec       number to be shifted
793
 
  @param  shift     number of decimal positions
 
809
  SYNOPSIS
 
810
    decimal_shift()
 
811
    dec       number to be shifted
 
812
    shift     number of decimal positions
794
813
              shift > 0 means shift to left shift
795
814
              shift < 0 meand right shift
796
 
 
797
 
  @note
 
815
  NOTE
798
816
    In fact it is multipling on 10^shift.
 
817
  RETURN
 
818
    E_DEC_OK          OK
 
819
    E_DEC_OVERFLOW    operation lead to overflow, number is untoched
 
820
    E_DEC_TRUNCATED   number was rounded to fit into buffer
 
821
*/
799
822
 
800
 
  @return  Error code
801
 
   @retval E_DEC_OK          OK
802
 
   @retval E_DEC_OVERFLOW    operation lead to overflow, number is untoched
803
 
   @retval E_DEC_TRUNCATED   number was rounded to fit into buffer
804
 
*/
805
823
static int decimal_shift(decimal_t *dec, int shift)
806
824
{
807
825
  /* index of first non zero digit (all indexes from 0) */
809
827
  /* index of position after last decimal digit */
810
828
  int end;
811
829
  /* index of digit position just after point */
812
 
  int point= round_up(dec->intg) * DIG_PER_DEC1;
 
830
  int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
813
831
  /* new point position */
814
832
  int new_point= point + shift;
815
833
  /* number of digits in result */
836
854
  digits_frac= end - new_point;
837
855
  set_if_bigger(digits_frac, 0);
838
856
 
839
 
  if ((new_len= round_up(digits_int) + (new_frac_len= round_up(digits_frac))) >
 
857
  if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
840
858
      dec->len)
841
859
  {
842
860
    int lack= new_len - dec->len;
896
914
    if (do_left)
897
915
    {
898
916
      do_mini_left_shift(dec, l_mini_shift, beg, end);
899
 
      mini_shift= (-l_mini_shift);
 
917
      mini_shift=- l_mini_shift;
900
918
    }
901
919
    else
902
920
    {
929
947
    {
930
948
      /* move left */
931
949
      d_shift= new_front / DIG_PER_DEC1;
932
 
      to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
933
 
      barier= dec->buf + (round_up(end) - 1 - d_shift);
 
950
      to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
 
951
      barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
934
952
      assert(to >= dec->buf);
935
953
      assert(barier + d_shift < dec->buf + dec->len);
936
954
      for(; to <= barier; to++)
943
961
    {
944
962
      /* move right */
945
963
      d_shift= (1 - new_front) / DIG_PER_DEC1;
946
 
      to= dec->buf + round_up(end) - 1 + d_shift;
947
 
      barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
 
964
      to= dec->buf + ROUND_UP(end) - 1 + d_shift;
 
965
      barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
948
966
      assert(to < dec->buf + dec->len);
949
967
      assert(barier - d_shift >= dec->buf);
950
968
      for(; to >= barier; to--)
963
981
 
964
982
    Only one of following 'for' loops will work becouse beg <= end
965
983
  */
966
 
  beg= round_up(beg + 1) - 1;
967
 
  end= round_up(end) - 1;
 
984
  beg= ROUND_UP(beg + 1) - 1;
 
985
  end= ROUND_UP(end) - 1;
968
986
  assert(new_point >= 0);
969
987
 
970
988
  /* We don't want negative new_point below */
971
989
  if (new_point != 0)
972
 
    new_point= round_up(new_point) - 1;
 
990
    new_point= ROUND_UP(new_point) - 1;
973
991
 
974
992
  if (new_point > end)
975
993
  {
989
1007
}
990
1008
 
991
1009
 
992
 
/**
993
 
  @brief  Convert string to decimal
 
1010
/*
 
1011
  Convert string to decimal
994
1012
 
995
 
  @param  from    value to convert. Doesn't have to be \0 terminated!
996
 
  @param  to      decimal where where the result will be stored
 
1013
  SYNOPSIS
 
1014
    internal_str2decl()
 
1015
      from    - value to convert. Doesn't have to be \0 terminated!
 
1016
      to      - decimal where where the result will be stored
997
1017
                to->buf and to->len must be set.
998
 
  @param  end     Pointer to pointer to end of string. Will on return be
 
1018
      end     - Pointer to pointer to end of string. Will on return be
999
1019
                set to the char after the last used character
1000
 
  @param  fixed   use to->intg, to->frac as limits for input number
 
1020
      fixed   - use to->intg, to->frac as limits for input number
1001
1021
 
1002
 
  @note
 
1022
  NOTE
1003
1023
    to->intg and to->frac can be modified even when fixed=1
1004
1024
    (but only decreased, in this case)
1005
1025
 
1006
 
  @return
 
1026
  RETURN VALUE
1007
1027
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
1008
1028
    In case of E_DEC_FATAL_ERROR *to is set to decimal zero
1009
1029
    (to make error handling easier)
1010
1030
*/
 
1031
 
1011
1032
int
1012
1033
internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
1013
1034
{
1064
1085
      error=E_DEC_OVERFLOW;
1065
1086
      intg=to->intg;
1066
1087
    }
1067
 
    intg1=round_up(intg);
1068
 
    frac1=round_up(frac);
 
1088
    intg1=ROUND_UP(intg);
 
1089
    frac1=ROUND_UP(frac);
1069
1090
    if (intg1+frac1 > to->len)
1070
1091
    {
1071
1092
      error= E_DEC_OOM;
1074
1095
  }
1075
1096
  else
1076
1097
  {
1077
 
    intg1=round_up(intg);
1078
 
    frac1=round_up(frac);
1079
 
    fix_intg_frac_error(to->len, intg1, frac1, error);
 
1098
    intg1=ROUND_UP(intg);
 
1099
    frac1=ROUND_UP(frac);
 
1100
    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1080
1101
    if (unlikely(error))
1081
1102
    {
1082
1103
      frac=frac1*DIG_PER_DEC1;
1157
1178
}
1158
1179
 
1159
1180
 
1160
 
/**
1161
 
  @param Convert decimal to double
1162
 
 
1163
 
  @param[in]   from   value to convert
1164
 
  @param[out]  to     result will be stored there
1165
 
 
1166
 
  @return
 
1181
/*
 
1182
  Convert decimal to double
 
1183
 
 
1184
  SYNOPSIS
 
1185
    decimal2double()
 
1186
      from    - value to convert
 
1187
      to      - result will be stored there
 
1188
 
 
1189
  RETURN VALUE
1167
1190
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1168
1191
*/
1169
1192
 
1181
1204
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
1182
1205
}
1183
1206
 
1184
 
/**
1185
 
 @param  Convert double to decimal
1186
 
 
1187
 
 @param[in]  from    value to convert
1188
 
 @param[out] to      result will be stored there
1189
 
 
1190
 
 @return
 
1207
/*
 
1208
  Convert double to decimal
 
1209
 
 
1210
  SYNOPSIS
 
1211
    double2decimal()
 
1212
      from    - value to convert
 
1213
      to      - result will be stored there
 
1214
 
 
1215
  RETURN VALUE
1191
1216
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1192
1217
*/
1193
1218
 
1311
1336
  return E_DEC_OK;
1312
1337
}
1313
1338
 
1314
 
/**
1315
 
 @brief
1316
 
  Convert decimal to its binary fixed-length representation (suitable for
1317
 
  comparing with memcmp)
1318
 
 
 
1339
/*
 
1340
  Convert decimal to its binary fixed-length representation
 
1341
  two representations of the same length can be compared with memcmp
 
1342
  with the correct -1/0/+1 result
 
1343
 
 
1344
  SYNOPSIS
 
1345
    decimal2bin()
 
1346
      from    - value to convert
 
1347
      to      - points to buffer where string representation should be stored
 
1348
      precision/scale - see decimal_bin_size() below
 
1349
 
 
1350
  NOTE
 
1351
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
 
1352
 
 
1353
  RETURN VALUE
 
1354
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
 
1355
 
 
1356
  DESCRIPTION
1319
1357
    for storage decimal numbers are converted to the "binary" format.
1320
1358
 
1321
1359
    This format has the following properties:
1376
1414
    And for -1234567890.1234 it would be
1377
1415
 
1378
1416
                7E F2 04 37 2D FB 2D
1379
 
 
1380
 
 
1381
 
  @param from      value to convert
1382
 
  @param to        points to buffer where string representation should be stored
1383
 
  @param precision see decimal_bin_size() below
1384
 
  @param frac      see decimal_bin_size() below
1385
 
 
1386
 
  @note
1387
 
    The buffer is assumed to be of the size decimal_bin_size(precision, scale)
1388
 
 
1389
 
  @return
1390
 
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1391
 
 
1392
1417
*/
1393
1418
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
1394
1419
{
1508
1533
  return error;
1509
1534
}
1510
1535
 
1511
 
/**
1512
 
 @brief Restores decimal from its binary fixed-length representation
1513
 
 
1514
 
 @param  from    value to convert
1515
 
 @param  to      result
1516
 
 @param  precision see decimal_bin_size() below
1517
 
 @param  scale     see decimal_bin_size() below
1518
 
 
1519
 
 @note
 
1536
/*
 
1537
  Restores decimal from its binary fixed-length representation
 
1538
 
 
1539
  SYNOPSIS
 
1540
    bin2decimal()
 
1541
      from    - value to convert
 
1542
      to      - result
 
1543
      precision/scale - see decimal_bin_size() below
 
1544
 
 
1545
  NOTE
1520
1546
    see decimal2bin()
1521
1547
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1522
1548
 
1523
 
 @return
 
1549
  RETURN VALUE
1524
1550
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1525
1551
*/
 
1552
 
1526
1553
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1527
1554
{
1528
1555
  int error=E_DEC_OK, intg=precision-scale,
1540
1567
  d_copy[0]^= 0x80;
1541
1568
  from= d_copy;
1542
1569
 
1543
 
  fix_intg_frac_error(to->len, intg1, frac1, error);
 
1570
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1544
1571
  if (unlikely(error))
1545
1572
  {
1546
1573
    if (intg1 < intg0+(intg0x>0))
1625
1652
  return(E_DEC_BAD_NUM);
1626
1653
}
1627
1654
 
1628
 
/**
1629
 
 @brief  Returns the size of array to hold a binary representation of a decimal
 
1655
/*
 
1656
  Returns the size of array to hold a binary representation of a decimal
1630
1657
 
1631
 
 @return  Size in bytes
 
1658
  RETURN VALUE
 
1659
    size in bytes
1632
1660
*/
 
1661
 
1633
1662
int decimal_bin_size(int precision, int scale)
1634
1663
{
1635
1664
  int intg=precision-scale,
1641
1670
         frac0*sizeof(dec1)+dig2bytes[frac0x];
1642
1671
}
1643
1672
 
1644
 
/**
1645
 
 @brief  Rounds the decimal to "scale" digits
1646
 
 
1647
 
 @param from    - decimal to round,
1648
 
 @param to      - result buffer. from==to is allowed
1649
 
 @param scale   - to what position to round. can be negative!
1650
 
 @param mode    - round to nearest even or truncate
1651
 
 
1652
 
 @note
 
1673
/*
 
1674
  Rounds the decimal to "scale" digits
 
1675
 
 
1676
  SYNOPSIS
 
1677
    decimal_round()
 
1678
      from    - decimal to round,
 
1679
      to      - result buffer. from==to is allowed
 
1680
      scale   - to what position to round. can be negative!
 
1681
      mode    - round to nearest even or truncate
 
1682
 
 
1683
  NOTES
1653
1684
    scale can be negative !
1654
1685
    one TRUNCATED error (line XXX below) isn't treated very logical :(
1655
1686
 
1656
 
 @return
 
1687
  RETURN VALUE
1657
1688
    E_DEC_OK/E_DEC_TRUNCATED
1658
1689
*/
 
1690
 
1659
1691
int
1660
1692
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1661
1693
              decimal_round_mode mode)
1662
1694
{
1663
 
  int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
1664
 
      frac1=round_up(from->frac), round_digit= 0,
1665
 
      intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
1666
 
      intg1=round_up(from->intg +
 
1695
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
 
1696
      frac1=ROUND_UP(from->frac), round_digit= 0,
 
1697
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
 
1698
      intg1=ROUND_UP(from->intg +
1667
1699
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1668
1700
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1669
1701
  int first_dig;
1765
1797
  }
1766
1798
  else
1767
1799
  {
1768
 
  /** @todo fix this code as it won't work for CEILING mode */
 
1800
    /* TODO - fix this code as it won't work for CEILING mode */
1769
1801
    int pos=frac0*DIG_PER_DEC1-scale-1;
1770
1802
    assert(frac0+intg0 > 0);
1771
1803
    x=*buf1 / powers10[pos];
1798
1830
    carry=1;
1799
1831
    *buf1-=DIG_BASE;
1800
1832
    while (carry && --buf1 >= to->buf)
1801
 
      add(*buf1, *buf1, 0, carry);
 
1833
      ADD(*buf1, *buf1, 0, carry);
1802
1834
    if (unlikely(carry))
1803
1835
    {
1804
1836
      /* shifting the number to create space for new digit */
1851
1883
 
1852
1884
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1853
1885
{
1854
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1855
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
 
1886
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1887
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1856
1888
      frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1857
1889
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1858
1890
 
1868
1900
    to->buf[0]=0; /* safety */
1869
1901
  }
1870
1902
 
1871
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
1903
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1872
1904
  if (unlikely(error == E_DEC_OVERFLOW))
1873
1905
  {
1874
1906
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1911
1943
  carry=0;
1912
1944
  while (buf1 > stop2)
1913
1945
  {
1914
 
    add(*--buf0, *--buf1, *--buf2, carry);
 
1946
    ADD(*--buf0, *--buf1, *--buf2, carry);
1915
1947
  }
1916
1948
 
1917
1949
  /* part 3 - cmin(intg) ... cmax(intg) */
1919
1951
                        ((stop=from2->buf)+intg2-intg1) ;
1920
1952
  while (buf1 > stop)
1921
1953
  {
1922
 
    add(*--buf0, *--buf1, 0, carry);
 
1954
    ADD(*--buf0, *--buf1, 0, carry);
1923
1955
  }
1924
1956
 
1925
1957
  if (unlikely(carry))
1933
1965
   if to==0, return -1/0/+1 - the result of the comparison */
1934
1966
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1935
1967
{
1936
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1937
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac);
 
1968
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1969
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1938
1970
  int frac0=max(frac1, frac2), error;
1939
1971
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1940
1972
 
2000
2032
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
2001
2033
  if (carry)
2002
2034
  {
2003
 
    swap(from1, from2);
2004
 
    swap(start1, start2);
2005
 
    swap(intg1, intg2);
2006
 
    swap(frac1, frac2);
 
2035
    swap_variables(const decimal_t *,from1, from2);
 
2036
    swap_variables(dec1 *,start1, start2);
 
2037
    swap_variables(int,intg1,intg2);
 
2038
    swap_variables(int,frac1,frac2);
2007
2039
    to->sign= 1 - to->sign;
2008
2040
  }
2009
2041
 
2010
 
  fix_intg_frac_error(to->len, intg1, frac0, error);
 
2042
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
2011
2043
  buf0=to->buf+intg1+frac0;
2012
2044
 
2013
2045
  to->frac=max(from1->frac, from2->frac);
2041
2073
      *--buf0=0;
2042
2074
    while (buf2 > stop2)
2043
2075
    {
2044
 
      sub(*--buf0, 0, *--buf2, carry);
 
2076
      SUB(*--buf0, 0, *--buf2, carry);
2045
2077
    }
2046
2078
  }
2047
2079
 
2048
2080
  /* part 2 - cmin(frac) ... intg2 */
2049
2081
  while (buf2 > start2)
2050
2082
  {
2051
 
    sub(*--buf0, *--buf1, *--buf2, carry);
 
2083
    SUB(*--buf0, *--buf1, *--buf2, carry);
2052
2084
  }
2053
2085
 
2054
2086
  /* part 3 - intg2 ... intg1 */
2055
2087
  while (carry && buf1 > start1)
2056
2088
  {
2057
 
    sub(*--buf0, *--buf1, 0, carry);
 
2089
    SUB(*--buf0, *--buf1, 0, carry);
2058
2090
  }
2059
2091
 
2060
2092
  while (buf1 > start1)
2098
2130
int decimal_is_zero(const decimal_t *from)
2099
2131
{
2100
2132
  dec1 *buf1=from->buf,
2101
 
       *end=buf1+round_up(from->intg)+round_up(from->frac);
 
2133
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2102
2134
  while (buf1 < end)
2103
2135
    if (*buf1++)
2104
2136
      return 0;
2105
2137
  return 1;
2106
2138
}
2107
2139
 
2108
 
/**
2109
 
 @brief multiply two decimals
2110
 
 
2111
 
 @param[in]   from1  First factor
2112
 
 @param[in]   from2  Second factor
2113
 
 @param[out]  to     product
2114
 
 
2115
 
 @return
 
2140
/*
 
2141
  multiply two decimals
 
2142
 
 
2143
  SYNOPSIS
 
2144
    decimal_mul()
 
2145
      from1, from2 - factors
 
2146
      to      - product
 
2147
 
 
2148
  RETURN VALUE
2116
2149
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
2117
2150
 
2118
 
 @note
 
2151
  NOTES
2119
2152
    in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
2120
2153
    and 63-digit number will take only 7 dec1 words (basically a 7-digit
2121
2154
    "base 999999999" number).  Thus there's no need in fast multiplication
2127
2160
*/
2128
2161
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2129
2162
{
2130
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
2131
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
2132
 
      intg0=round_up(from1->intg+from2->intg),
 
2163
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
2164
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
 
2165
      intg0=ROUND_UP(from1->intg+from2->intg),
2133
2166
      frac0=frac1+frac2, error, i, j, d_to_move;
2134
2167
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2135
2168
       *start2, *stop2, *stop1, *start0, carry;
2138
2171
 
2139
2172
  i=intg0;
2140
2173
  j=frac0;
2141
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
2174
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2142
2175
  to->sign=from1->sign != from2->sign;
2143
2176
  to->frac=from1->frac+from2->frac;
2144
2177
  to->intg=intg0*DIG_PER_DEC1;
2179
2212
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2180
2213
      hi=(dec1)(p/DIG_BASE);
2181
2214
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2182
 
      add2(*buf0, *buf0, lo, carry);
 
2215
      ADD2(*buf0, *buf0, lo, carry);
2183
2216
      carry+=hi;
2184
2217
    }
2185
2218
    if (carry)
2186
2219
    {
2187
2220
      if (buf0 < to->buf)
2188
2221
        return E_DEC_OVERFLOW;
2189
 
      add2(*buf0, *buf0, 0, carry);
 
2222
      ADD2(*buf0, *buf0, 0, carry);
2190
2223
    }
2191
2224
    for (buf0--; carry; buf0--)
2192
2225
    {
2193
2226
      if (buf0 < to->buf)
2194
2227
        return E_DEC_OVERFLOW;
2195
 
      add(*buf0, *buf0, 0, carry);
 
2228
      ADD(*buf0, *buf0, 0, carry);
2196
2229
    }
2197
2230
  }
2198
2231
 
2215
2248
    }
2216
2249
  }
2217
2250
  buf1= to->buf;
2218
 
  d_to_move= intg0 + round_up(to->frac);
 
2251
  d_to_move= intg0 + ROUND_UP(to->frac);
2219
2252
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2220
2253
  {
2221
2254
    buf1++;
2231
2264
  return error;
2232
2265
}
2233
2266
 
2234
 
/**
 
2267
/*
2235
2268
  naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2236
2269
  it's ok for short numbers
2237
2270
  also we're using alloca() to allocate a temporary buffer
2238
2271
 
2239
 
  @todo
2240
 
  If this library is to be used with huge numbers of thousands of
 
2272
  XXX if this library is to be used with huge numbers of thousands of
2241
2273
  digits, fast division must be implemented and alloca should be
2242
2274
  changed to malloc (or at least fallback to malloc if alloca() fails)
2243
2275
  but then, decimal_mul() should be rewritten too :(
2245
2277
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2246
2278
                       decimal_t *to, decimal_t *mod, int scale_incr)
2247
2279
{
2248
 
  int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2249
 
      frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
 
2280
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
 
2281
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2250
2282
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2251
2283
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2252
2284
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2296
2328
    intg0=0;
2297
2329
  }
2298
2330
  else
2299
 
    intg0=round_up(dintg);
 
2331
    intg0=ROUND_UP(dintg);
2300
2332
  if (mod)
2301
2333
  {
2302
2334
    /* we're calculating N1 % N2.
2315
2347
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2316
2348
      frac2 accordingly.
2317
2349
      Thus, the result will have
2318
 
         frac = round_up(frac1+frac2+scale_incr)
 
2350
         frac = ROUND_UP(frac1+frac2+scale_incr)
2319
2351
      and
2320
2352
         intg = (prec1-frac1) - (prec2-frac2) + 1
2321
2353
         prec = intg+frac
2322
2354
    */
2323
 
    frac0=round_up(frac1+frac2+scale_incr);
2324
 
    fix_intg_frac_error(to->len, intg0, frac0, error);
 
2355
    frac0=ROUND_UP(frac1+frac2+scale_incr);
 
2356
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2325
2357
    to->sign=from1->sign != from2->sign;
2326
2358
    to->intg=intg0*DIG_PER_DEC1;
2327
2359
    to->frac=frac0*DIG_PER_DEC1;
2332
2364
    while (dintg++ < 0)
2333
2365
      *buf0++=0;
2334
2366
 
2335
 
  len1=(i=round_up(prec1))+round_up(2*frac2+scale_incr+1) + 1;
 
2367
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2336
2368
  set_if_bigger(len1, 3);
2337
2369
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
2338
2370
    return E_DEC_OOM;
2342
2374
  start1=tmp1;
2343
2375
  stop1=start1+len1;
2344
2376
  start2=buf2;
2345
 
  stop2=buf2+round_up(prec2)-1;
 
2377
  stop2=buf2+ROUND_UP(prec2)-1;
2346
2378
 
2347
2379
  /* removing end zeroes */
2348
2380
  while (*stop2 == 0 && stop2 >= start2)
2401
2433
        x=guess * (*--buf2);
2402
2434
        hi=(dec1)(x/DIG_BASE);
2403
2435
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2404
 
        sub2(*buf1, *buf1, lo, carry);
 
2436
        SUB2(*buf1, *buf1, lo, carry);
2405
2437
        carry+=hi;
2406
2438
      }
2407
2439
      carry= dcarry < carry;
2415
2447
        buf1=start1+len2;
2416
2448
        for (carry=0; buf2 > start2; buf1--)
2417
2449
        {
2418
 
          add(*buf1, *buf1, *--buf2, carry);
 
2450
          ADD(*buf1, *buf1, *--buf2, carry);
2419
2451
        }
2420
2452
      }
2421
2453
    }
2434
2466
    if (dcarry)
2435
2467
      *--start1=dcarry;
2436
2468
    buf0=to->buf;
2437
 
    intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
2438
 
    frac0=round_up(to->frac);
 
2469
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
 
2470
    frac0=ROUND_UP(to->frac);
2439
2471
    error=E_DEC_OK;
2440
2472
    if (unlikely(frac0==0 && intg0==0))
2441
2473
    {
2465
2497
        error=E_DEC_OVERFLOW;
2466
2498
        goto done;
2467
2499
      }
2468
 
      assert(intg0 <= round_up(from2->intg));
 
2500
      assert(intg0 <= ROUND_UP(from2->intg));
2469
2501
      stop1=start1+frac0+intg0;
2470
2502
      to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2471
2503
    }
2484
2516
  return error;
2485
2517
}
2486
2518
 
2487
 
/**
2488
 
 @brief  division of two decimals
2489
 
 
2490
 
 @param[in]  from1   dividend
2491
 
 @param[in]  from2   divisor
2492
 
 @param[out] to      quotient
2493
 
 
2494
 
 @return
 
2519
/*
 
2520
  division of two decimals
 
2521
 
 
2522
  SYNOPSIS
 
2523
    decimal_div()
 
2524
      from1   - dividend
 
2525
      from2   - divisor
 
2526
      to      - quotient
 
2527
 
 
2528
  RETURN VALUE
2495
2529
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2496
2530
 
2497
 
 @note
 
2531
  NOTES
2498
2532
    see do_div_mod()
2499
2533
*/
 
2534
 
2500
2535
int
2501
2536
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
2502
2537
{
2503
2538
  return do_div_mod(from1, from2, to, 0, scale_incr);
2504
2539
}
2505
2540
 
2506
 
/**
2507
 
 @brief modulus
2508
 
 
2509
 
 the modulus R in    R = M mod N
2510
 
 
2511
 
 is defined as
2512
 
 
2513
 
 0 <= |R| < |M|
2514
 
 sign R == sign M
2515
 
 R = M - k*N, where k is integer
2516
 
 
2517
 
 thus, there's no requirement for M or N to be integers
2518
 
 
2519
 
 
2520
 
 @param from1   dividend
2521
 
 @param from2   divisor
2522
 
 @param to      modulus
2523
 
 
2524
 
 @return
 
2541
/*
 
2542
  modulus
 
2543
 
 
2544
  SYNOPSIS
 
2545
    decimal_mod()
 
2546
      from1   - dividend
 
2547
      from2   - divisor
 
2548
      to      - modulus
 
2549
 
 
2550
  RETURN VALUE
2525
2551
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2526
2552
 
2527
 
 @note
 
2553
  NOTES
2528
2554
    see do_div_mod()
2529
2555
 
 
2556
  DESCRIPTION
 
2557
    the modulus R in    R = M mod N
 
2558
 
 
2559
   is defined as
 
2560
 
 
2561
     0 <= |R| < |M|
 
2562
     sign R == sign M
 
2563
     R = M - k*N, where k is integer
 
2564
 
 
2565
   thus, there's no requirement for M or N to be integers
2530
2566
*/
 
2567
 
2531
2568
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2532
2569
{
2533
2570
  return do_div_mod(from1, from2, 0, to, 0);
2545
2582
{
2546
2583
  int i;
2547
2584
  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2548
 
  for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
 
2585
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2549
2586
    printf("%09d, ", d->buf[i]);
2550
2587
  printf("%09d} */ ", d->buf[i]);
2551
2588
}