~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/*
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
=======================================================================
22
  Quoting the standard
23
  (SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
24
25
4.4.2 Characteristics of numbers, page 27:
26
27
  An exact numeric type has a precision P and a scale S. P is a positive
28
  integer that determines the number of significant digits in a
29
  particular radix R, where R is either 2 or 10. S is a non-negative
30
  integer. Every value of an exact numeric type of scale S is of the
31
  form n*10^{-S}, where n is an integer such that ­-R^P <= n <= R^P.
32
33
  [...]
34
35
  If an assignment of some number would result in a loss of its most
36
  significant digit, an exception condition is raised. If least
37
  significant digits are lost, implementation-defined rounding or
38
  truncating occurs, with no exception condition being raised.
39
40
  [...]
41
42
  Whenever an exact or approximate numeric value is assigned to an exact
43
  numeric value site, an approximation of its value that preserves
44
  leading significant digits after rounding or truncating is represented
45
  in the declared type of the target. The value is converted to have the
46
  precision and scale of the target. The choice of whether to truncate
47
  or round is implementation-defined.
48
49
  [...]
50
51
  All numeric values between the smallest and the largest value,
52
  inclusive, in a given exact numeric type have an approximation
53
  obtained by rounding or truncation for that type; it is
54
  implementation-defined which other numeric values have such
55
  approximations.
56
57
5.3 <literal>, page 143
58
59
  <exact numeric literal> ::=
60
    <unsigned integer> [ <period> [ <unsigned integer> ] ]
61
  | <period> <unsigned integer>
62
63
6.1 <data type>, page 165:
64
65
  19) The <scale> of an <exact numeric type> shall not be greater than
66
      the <precision> of the <exact numeric type>.
67
68
  20) For the <exact numeric type>s DECIMAL and NUMERIC:
69
70
    a) The maximum value of <precision> is implementation-defined.
71
       <precision> shall not be greater than this value.
72
    b) The maximum value of <scale> is implementation-defined. <scale>
73
       shall not be greater than this maximum value.
74
75
  21) NUMERIC specifies the data type exact numeric, with the decimal
76
      precision and scale specified by the <precision> and <scale>.
77
78
  22) DECIMAL specifies the data type exact numeric, with the decimal
79
      scale specified by the <scale> and the implementation-defined
80
      decimal precision equal to or greater than the value of the
81
      specified <precision>.
82
83
6.26 <numeric value expression>, page 241:
84
85
  1) If the declared type of both operands of a dyadic arithmetic
86
     operator is exact numeric, then the declared type of the result is
87
     an implementation-defined exact numeric type, with precision and
88
     scale determined as follows:
89
90
   a) Let S1 and S2 be the scale of the first and second operands
91
      respectively.
92
   b) The precision of the result of addition and subtraction is
93
      implementation-defined, and the scale is the maximum of S1 and S2.
94
   c) The precision of the result of multiplication is
95
      implementation-defined, and the scale is S1 + S2.
96
   d) The precision and scale of the result of division are
97
      implementation-defined.
98
*/
99
549 by Monty Taylor
Took gettext.h out of header files.
100
#include <config.h>
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
101
#include <alloca.h>
212.5.39 by Monty Taylor
Phew. Moved my_base and my_global.
102
#include <m_string.h>
1 by brian
clean slate
103
#include <m_ctype.h>
212.4.2 by Monty Taylor
Fixed the includes in places to make the myisam header file move work.
104
#include <storage/myisam/myisampack.h>
212.5.4 by Monty Taylor
Renamed strings to mystrings, for include/lib naming consistency.
105
#include <mystrings/decimal.h>
1 by brian
clean slate
106
492.1.7 by Monty Taylor
Moved test() to its own file.
107
#include <drizzled/util/test.h>
1 by brian
clean slate
108
/*
109
  Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
110
  So one variable of type decimal_digit_t is limited:
111
112
      0 < decimal_digit <= DIG_MAX < DIG_BASE
113
114
  in the struct st_decimal_t:
115
116
    intg is the number of *decimal* digits (NOT number of decimal_digit_t's !)
117
         before the point
118
    frac - number of decimal digits after the point
119
    buf is an array of decimal_digit_t's
120
    len is the length of buf (length of allocated space) in decimal_digit_t's,
121
        not in bytes
122
*/
123
typedef decimal_digit_t dec1;
152 by Brian Aker
longlong replacement
124
typedef int64_t      dec2;
1 by brian
clean slate
125
126
#define DIG_PER_DEC1 9
127
#define DIG_MASK     100000000
128
#define DIG_BASE     1000000000
129
#define DIG_MAX      (DIG_BASE-1)
130
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
131
static const dec1 powers10[DIG_PER_DEC1+1]={
132
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
133
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
134
static const dec1 frac_max[DIG_PER_DEC1-1]={
135
  900000000, 990000000, 999000000,
136
  999900000, 999990000, 999999000,
137
  999999900, 999999990 };
138
139
#ifdef HAVE_purify
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
140
#define sanity(d) assert((d)->len > 0)
1 by brian
clean slate
141
#else
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
142
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
1 by brian
clean slate
143
                              (d)->buf[(d)->len-1] | 1))
144
#endif
145
146
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error)                   \
147
        do                                                              \
148
        {                                                               \
149
          if (unlikely(intg1+frac1 > (len)))                            \
150
          {                                                             \
151
            if (unlikely(intg1 > (len)))                                \
152
            {                                                           \
153
              intg1=(len);                                              \
154
              frac1=0;                                                  \
155
              error=E_DEC_OVERFLOW;                                     \
156
            }                                                           \
157
            else                                                        \
158
            {                                                           \
159
              frac1=(len)-intg1;                                        \
160
              error=E_DEC_TRUNCATED;                                    \
161
            }                                                           \
162
          }                                                             \
163
          else                                                          \
164
            error=E_DEC_OK;                                             \
165
        } while(0)
166
167
#define ADD(to, from1, from2, carry)  /* assume carry <= 1 */           \
168
        do                                                              \
169
        {                                                               \
170
          dec1 a=(from1)+(from2)+(carry);                               \
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
171
          assert((carry) <= 1);                                    \
1 by brian
clean slate
172
          if (((carry)= a >= DIG_BASE)) /* no division here! */         \
173
            a-=DIG_BASE;                                                \
174
          (to)=a;                                                       \
175
        } while(0)
176
177
#define ADD2(to, from1, from2, carry)                                   \
178
        do                                                              \
179
        {                                                               \
180
          dec2 a=((dec2)(from1))+(from2)+(carry);                       \
181
          if (((carry)= a >= DIG_BASE))                                 \
182
            a-=DIG_BASE;                                                \
183
          if (unlikely(a >= DIG_BASE))                                  \
184
          {                                                             \
185
            a-=DIG_BASE;                                                \
186
            carry++;                                                    \
187
          }                                                             \
188
          (to)=(dec1) a;                                                \
189
        } while(0)
190
191
#define SUB(to, from1, from2, carry) /* to=from1-from2 */               \
192
        do                                                              \
193
        {                                                               \
194
          dec1 a=(from1)-(from2)-(carry);                               \
195
          if (((carry)= a < 0))                                         \
196
            a+=DIG_BASE;                                                \
197
          (to)=a;                                                       \
198
        } while(0)
199
200
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */              \
201
        do                                                              \
202
        {                                                               \
203
          dec1 a=(from1)-(from2)-(carry);                               \
204
          if (((carry)= a < 0))                                         \
205
            a+=DIG_BASE;                                                \
206
          if (unlikely(a < 0))                                          \
207
          {                                                             \
208
            a+=DIG_BASE;                                                \
209
            carry++;                                                    \
210
          }                                                             \
211
          (to)=a;                                                       \
212
        } while(0)
213
322.2.2 by Mats Kindahl
Hiding THD::proc_info field and providing a setter and getter.
214
/**
215
  Swap the contents of two variables.
216
 */
217
#define swap_variables(TYPE, a, b) \
218
  do {                             \
219
    TYPE dummy;                    \
220
    dummy= a;                      \
221
    a= b;                          \
222
    b= dummy;                      \
223
  } while (0)
224
225
1 by brian
clean slate
226
/*
227
  Get maximum value for given precision and scale
228
229
  SYNOPSIS
230
    max_decimal()
231
    precision/scale - see decimal_bin_size() below
232
    to              - decimal where where the result will be stored
233
                      to->buf and to->len must be set.
234
*/
235
236
void max_decimal(int precision, int frac, decimal_t *to)
237
{
238
  int intpart;
239
  dec1 *buf= to->buf;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
240
  assert(precision && precision >= frac);
1 by brian
clean slate
241
242
  to->sign= 0;
243
  if ((intpart= to->intg= (precision - frac)))
244
  {
266.7.10 by Andy Lester
make things more const-correct
245
    const int firstdigits= intpart % DIG_PER_DEC1;
1 by brian
clean slate
246
    if (firstdigits)
247
      *buf++= powers10[firstdigits] - 1; /* get 9 99 999 ... */
248
    for(intpart/= DIG_PER_DEC1; intpart; intpart--)
249
      *buf++= DIG_MAX;
250
  }
251
252
  if ((to->frac= frac))
253
  {
266.7.10 by Andy Lester
make things more const-correct
254
    const int lastdigits= frac % DIG_PER_DEC1;
1 by brian
clean slate
255
    for(frac/= DIG_PER_DEC1; frac; frac--)
256
      *buf++= DIG_MAX;
257
    if (lastdigits)
258
      *buf= frac_max[lastdigits - 1];
259
  }
260
}
261
262
263
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
264
{
265
  int intg= from->intg, i;
266
  dec1 *buf0= from->buf;
267
  i= ((intg - 1) % DIG_PER_DEC1) + 1;
268
  while (intg > 0 && *buf0 == 0)
269
  {
270
    intg-= i;
271
    i= DIG_PER_DEC1;
272
    buf0++;
273
  }
274
  if (intg > 0)
275
  {
276
    for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
277
    assert(intg > 0);
1 by brian
clean slate
278
  }
279
  else
280
    intg=0;
281
  *intg_result= intg;
282
  return buf0;
283
}
284
285
286
/*
287
  Count actual length of fraction part (without ending zeroes)
288
289
  SYNOPSIS
290
    decimal_actual_fraction()
291
    from    number for processing
292
*/
293
294
int decimal_actual_fraction(decimal_t *from)
295
{
296
  int frac= from->frac, i;
297
  dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
298
299
  if (frac == 0)
300
    return 0;
301
302
  i= ((frac - 1) % DIG_PER_DEC1 + 1);
303
  while (frac > 0 && *buf0 == 0)
304
  {
305
    frac-= i;
306
    i= DIG_PER_DEC1;
307
    buf0--;
308
  }
309
  if (frac > 0)
310
  {
311
    for (i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1); *buf0 % powers10[i++] == 0; frac--) {};
312
  }
313
  return frac;
314
}
315
316
317
/*
318
  Convert decimal to its printable string representation
319
320
  SYNOPSIS
321
    decimal2string()
322
      from            - value to convert
323
      to              - points to buffer where string representation
324
                        should be stored
325
      *to_len         - in:  size of to buffer
326
                        out: length of the actually written string
327
      fixed_precision - 0 if representation can be variable length and
328
                        fixed_decimals will not be checked in this case.
329
                        Put number as with fixed point position with this
330
                        number of digits (sign counted and decimal point is
331
                        counted)
332
      fixed_decimals  - number digits after point.
333
      filler          - character to fill gaps in case of fixed_precision > 0
334
335
  RETURN VALUE
336
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
337
*/
338
339
int decimal2string(decimal_t *from, char *to, int *to_len,
340
                   int fixed_precision, int fixed_decimals,
341
                   char filler)
342
{
343
  int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
344
  /* number digits before decimal point */
345
  int fixed_intg= (fixed_precision ?
346
                   (fixed_precision - fixed_decimals) : 0);
347
  int error=E_DEC_OK;
348
  char *s=to;
349
  dec1 *buf, *buf0=from->buf, tmp;
350
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
351
  assert(*to_len >= 2+from->sign);
1 by brian
clean slate
352
353
  /* removing leading zeroes */
354
  buf0= remove_leading_zeroes(from, &intg);
355
  if (unlikely(intg+frac==0))
356
  {
357
    intg=1;
358
    tmp=0;
359
    buf0=&tmp;
360
  }
361
362
  if (!(intg_len= fixed_precision ? fixed_intg : intg))
363
    intg_len= 1;
364
  frac_len= fixed_precision ? fixed_decimals : frac;
365
  len= from->sign + intg_len + test(frac) + frac_len;
366
  if (fixed_precision)
367
  {
368
    if (frac > fixed_decimals)
369
    {
370
      error= E_DEC_TRUNCATED;
371
      frac= fixed_decimals;
372
    }
373
    if (intg > fixed_intg)
374
    {
375
      error= E_DEC_OVERFLOW;
376
      intg= fixed_intg;
377
    }
378
  }
379
  else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
380
  {
381
    int j= len-*to_len;
382
    error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
383
    if (frac && j >= frac + 1) j--;
384
    if (j > frac)
385
    {
386
      intg-= j-frac;
387
      frac= 0;
388
    }
389
    else
390
      frac-=j;
391
    len= from->sign + intg_len + test(frac) + frac_len;
392
  }
393
  *to_len=len;
394
  s[len]=0;
395
396
  if (from->sign)
397
    *s++='-';
398
399
  if (frac)
400
  {
401
    char *s1= s + intg_len;
402
    fill= frac_len - frac;
403
    buf=buf0+ROUND_UP(intg);
404
    *s1++='.';
405
    for (; frac>0; frac-=DIG_PER_DEC1)
406
    {
407
      dec1 x=*buf++;
398.1.4 by Monty Taylor
Renamed max/min.
408
      for (i=cmin(frac, DIG_PER_DEC1); i; i--)
1 by brian
clean slate
409
      {
410
        dec1 y=x/DIG_MASK;
481 by Brian Aker
Remove all of uchar.
411
        *s1++='0'+(unsigned char)y;
1 by brian
clean slate
412
        x-=y*DIG_MASK;
413
        x*=10;
414
      }
415
    }
416
    for(; fill; fill--)
417
      *s1++=filler;
418
  }
419
420
  fill= intg_len - intg;
421
  if (intg == 0)
422
    fill--; /* symbol 0 before digital point */
423
  for(; fill; fill--)
424
    *s++=filler;
425
  if (intg)
426
  {
427
    s+=intg;
428
    for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
429
    {
430
      dec1 x=*--buf;
398.1.4 by Monty Taylor
Renamed max/min.
431
      for (i=cmin(intg, DIG_PER_DEC1); i; i--)
1 by brian
clean slate
432
      {
433
        dec1 y=x/10;
481 by Brian Aker
Remove all of uchar.
434
        *--s='0'+(unsigned char)(x-y*10);
1 by brian
clean slate
435
        x=y;
436
      }
437
    }
438
  }
439
  else
440
    *s= '0';
441
  return error;
442
}
443
444
445
/*
446
  Return bounds of decimal digits in the number
447
448
  SYNOPSIS
449
    digits_bounds()
450
      from         - decimal number for processing
451
      start_result - index (from 0 ) of first decimal digits will
452
                     be written by this address
453
      end_result   - index of position just after last decimal digit
454
                     be written by this address
455
*/
456
457
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
458
{
459
  int start, stop, i;
460
  dec1 *buf_beg= from->buf;
461
  dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
462
  dec1 *buf_end= end - 1;
463
464
  /* find non-zero digit from number begining */
465
  while (buf_beg < end && *buf_beg == 0)
466
    buf_beg++;
467
468
  if (buf_beg >= end)
469
  {
470
    /* it is zero */
471
    *start_result= *end_result= 0;
472
    return;
473
  }
474
475
  /* find non-zero decimal digit from number begining */
476
  if (buf_beg == from->buf && from->intg)
477
  {
478
    start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1));
479
    i--;
480
  }
481
  else
482
  {
483
    i= DIG_PER_DEC1 - 1;
484
    start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
485
  }
486
  if (buf_beg < end)
487
    for (; *buf_beg < powers10[i--]; start++) ;
488
  *start_result= start; /* index of first decimal digit (from 0) */
489
490
  /* find non-zero digit at the end */
491
  while (buf_end > buf_beg  && *buf_end == 0)
492
    buf_end--;
493
  /* find non-zero decimal digit from the end */
494
  if (buf_end == end - 1 && from->frac)
495
  {
496
    stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
497
           (i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
498
    i= DIG_PER_DEC1 - i + 1;
499
  }
500
  else
501
  {
502
    stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
503
    i= 1;
504
  }
505
  for (; *buf_end % powers10[i++] == 0; stop--) {};
506
  *end_result= stop; /* index of position after last decimal digit (from 0) */
507
}
508
509
510
/*
511
  Left shift for alignment of data in buffer
512
513
  SYNOPSIS
514
    do_mini_left_shift()
515
    dec     pointer to decimal number which have to be shifted
516
    shift   number of decimal digits on which it should be shifted
517
    beg/end bounds of decimal digits (see digits_bounds())
518
519
  NOTE
520
    Result fitting in the buffer should be garanted.
521
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
522
*/
523
53.2.13 by Monty Taylor
Various static declares.
524
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
1 by brian
clean slate
525
{
526
  dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
527
  dec1 *end= dec->buf + ROUND_UP(last) - 1;
528
  int c_shift= DIG_PER_DEC1 - shift;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
529
  assert(from >= dec->buf);
530
  assert(end < dec->buf + dec->len);
1 by brian
clean slate
531
  if (beg % DIG_PER_DEC1 < shift)
532
    *(from - 1)= (*from) / powers10[c_shift];
533
  for(; from < end; from++)
534
    *from= ((*from % powers10[c_shift]) * powers10[shift] +
535
            (*(from + 1)) / powers10[c_shift]);
536
  *from= (*from % powers10[c_shift]) * powers10[shift];
537
}
538
539
540
/*
541
  Right shift for alignment of data in buffer
542
543
  SYNOPSIS
544
    do_mini_left_shift()
545
    dec     pointer to decimal number which have to be shifted
546
    shift   number of decimal digits on which it should be shifted
547
    beg/end bounds of decimal digits (see digits_bounds())
548
549
  NOTE
550
    Result fitting in the buffer should be garanted.
551
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
552
*/
553
53.2.13 by Monty Taylor
Various static declares.
554
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
1 by brian
clean slate
555
{
556
  dec1 *from= dec->buf + ROUND_UP(last) - 1;
557
  dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
558
  int c_shift= DIG_PER_DEC1 - shift;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
559
  assert(from < dec->buf + dec->len);
560
  assert(end >= dec->buf);
1 by brian
clean slate
561
  if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
562
    *(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
563
  for(; from > end; from--)
564
    *from= (*from / powers10[shift] +
565
            (*(from - 1) % powers10[shift]) * powers10[c_shift]);
566
  *from= *from / powers10[shift];
567
}
568
569
570
/*
571
  Shift of decimal digits in given number (with rounding if it need)
572
573
  SYNOPSIS
574
    decimal_shift()
575
    dec       number to be shifted
576
    shift     number of decimal positions
577
              shift > 0 means shift to left shift
578
              shift < 0 meand right shift
579
  NOTE
580
    In fact it is multipling on 10^shift.
581
  RETURN
582
    E_DEC_OK          OK
583
    E_DEC_OVERFLOW    operation lead to overflow, number is untoched
584
    E_DEC_TRUNCATED   number was rounded to fit into buffer
585
*/
586
53.2.13 by Monty Taylor
Various static declares.
587
static int decimal_shift(decimal_t *dec, int shift)
1 by brian
clean slate
588
{
589
  /* index of first non zero digit (all indexes from 0) */
590
  int beg;
591
  /* index of position after last decimal digit */
592
  int end;
593
  /* index of digit position just after point */
594
  int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
595
  /* new point position */
596
  int new_point= point + shift;
597
  /* number of digits in result */
598
  int digits_int, digits_frac;
599
  /* length of result and new fraction in big digits*/
600
  int new_len, new_frac_len;
601
  /* return code */
602
  int err= E_DEC_OK;
603
  int new_front;
604
605
  if (shift == 0)
606
    return E_DEC_OK;
607
608
  digits_bounds(dec, &beg, &end);
609
610
  if (beg == end)
611
  {
612
    decimal_make_zero(dec);
613
    return E_DEC_OK;
614
  }
615
616
  digits_int= new_point - beg;
617
  set_if_bigger(digits_int, 0);
618
  digits_frac= end - new_point;
619
  set_if_bigger(digits_frac, 0);
620
621
  if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
622
      dec->len)
623
  {
624
    int lack= new_len - dec->len;
625
    int diff;
626
627
    if (new_frac_len < lack)
628
      return E_DEC_OVERFLOW; /* lack more then we have in fraction */
629
630
    /* cat off fraction part to allow new number to fit in our buffer */
631
    err= E_DEC_TRUNCATED;
632
    new_frac_len-= lack;
633
    diff= digits_frac - (new_frac_len * DIG_PER_DEC1);
634
    /* Make rounding method as parameter? */
635
    decimal_round(dec, dec, end - point - diff, HALF_UP);
636
    end-= diff;
637
    digits_frac= new_frac_len * DIG_PER_DEC1;
638
639
    if (end <= beg)
640
    {
641
      /*
642
        we lost all digits (they will be shifted out of buffer), so we can
643
        just return 0
644
      */
645
      decimal_make_zero(dec);
646
      return E_DEC_TRUNCATED;
647
    }
648
  }
649
650
  if (shift % DIG_PER_DEC1)
651
  {
652
    int l_mini_shift, r_mini_shift, mini_shift;
653
    int do_left;
654
    /*
655
      Calculate left/right shift to align decimal digits inside our bug
656
      digits correctly
657
    */
658
    if (shift > 0)
659
    {
660
      l_mini_shift= shift % DIG_PER_DEC1;
661
      r_mini_shift= DIG_PER_DEC1 - l_mini_shift;
662
      /*
663
        It is left shift so prefer left shift, but if we have not place from
664
        left, we have to have it from right, because we checked length of
665
        result
666
      */
667
      do_left= l_mini_shift <= beg;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
668
      assert(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
1 by brian
clean slate
669
    }
670
    else
671
    {
672
      r_mini_shift= (-shift) % DIG_PER_DEC1;
673
      l_mini_shift= DIG_PER_DEC1 - r_mini_shift;
674
      /* see comment above */
675
      do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
676
      assert(!do_left || l_mini_shift <= beg);
1 by brian
clean slate
677
    }
678
    if (do_left)
679
    {
680
      do_mini_left_shift(dec, l_mini_shift, beg, end);
681
      mini_shift=- l_mini_shift;
682
    }
683
    else
684
    {
685
      do_mini_right_shift(dec, r_mini_shift, beg, end);
686
      mini_shift= r_mini_shift;
687
    }
688
    new_point+= mini_shift;
689
    /*
690
      If number is shifted and correctly aligned in buffer we can
691
      finish
692
    */
693
    if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1)
694
    {
695
      dec->intg= digits_int;
696
      dec->frac= digits_frac;
697
      return err;                 /* already shifted as it should be */
698
    }
699
    beg+= mini_shift;
700
    end+= mini_shift;
701
  }
702
703
  /* if new 'decimal front' is in first digit, we do not need move digits */
704
  if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 ||
705
      new_front < 0)
706
  {
707
    /* need to move digits */
708
    int d_shift;
709
    dec1 *to, *barier;
710
    if (new_front > 0)
711
    {
712
      /* move left */
713
      d_shift= new_front / DIG_PER_DEC1;
714
      to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
715
      barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
716
      assert(to >= dec->buf);
717
      assert(barier + d_shift < dec->buf + dec->len);
1 by brian
clean slate
718
      for(; to <= barier; to++)
719
        *to= *(to + d_shift);
720
      for(barier+= d_shift; to <= barier; to++)
721
        *to= 0;
722
      d_shift= -d_shift;
723
    }
724
    else
725
    {
726
      /* move right */
727
      d_shift= (1 - new_front) / DIG_PER_DEC1;
728
      to= dec->buf + ROUND_UP(end) - 1 + d_shift;
729
      barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
730
      assert(to < dec->buf + dec->len);
731
      assert(barier - d_shift >= dec->buf);
1 by brian
clean slate
732
      for(; to >= barier; to--)
733
        *to= *(to - d_shift);
734
      for(barier-= d_shift; to >= barier; to--)
735
        *to= 0;
736
    }
737
    d_shift*= DIG_PER_DEC1;
738
    beg+= d_shift;
739
    end+= d_shift;
740
    new_point+= d_shift;
741
  }
742
743
  /*
744
    If there are gaps then fill ren with 0.
745
746
    Only one of following 'for' loops will work becouse beg <= end
747
  */
748
  beg= ROUND_UP(beg + 1) - 1;
749
  end= ROUND_UP(end) - 1;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
750
  assert(new_point >= 0);
1 by brian
clean slate
751
  
752
  /* We don't want negative new_point below */
753
  if (new_point != 0)
754
    new_point= ROUND_UP(new_point) - 1;
755
756
  if (new_point > end)
757
  {
758
    do
759
    {
760
      dec->buf[new_point]=0;
761
    } while (--new_point > end);
762
  }
763
  else
764
  {
765
    for (; new_point < beg; new_point++)
766
      dec->buf[new_point]= 0;
767
  }
768
  dec->intg= digits_int;
769
  dec->frac= digits_frac;
770
  return err;
771
}
772
773
774
/*
775
  Convert string to decimal
776
777
  SYNOPSIS
778
    internal_str2decl()
779
      from    - value to convert. Doesn't have to be \0 terminated!
780
      to      - decimal where where the result will be stored
781
                to->buf and to->len must be set.
782
      end     - Pointer to pointer to end of string. Will on return be
783
		set to the char after the last used character
784
      fixed   - use to->intg, to->frac as limits for input number
785
786
  NOTE
787
    to->intg and to->frac can be modified even when fixed=1
788
    (but only decreased, in this case)
789
790
  RETURN VALUE
791
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
792
    In case of E_DEC_FATAL_ERROR *to is set to decimal zero
793
    (to make error handling easier)
794
*/
795
796
int
287.3.10 by Monty Taylor
Const correctness change.
797
internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
1 by brian
clean slate
798
{
287.3.10 by Monty Taylor
Const correctness change.
799
  char *s= from, *s1;
266.7.10 by Andy Lester
make things more const-correct
800
  char *end_of_string = *end;
801
  char *endp;
1 by brian
clean slate
802
  int i, intg, frac, error, intg1, frac1;
803
  dec1 x,*buf;
804
  sanity(to);
805
806
  error= E_DEC_BAD_NUM;                         /* In case of bad number */
383.1.11 by Brian Aker
Cleanup default character set.
807
  while (s < end_of_string && my_isspace(&my_charset_utf8_general_ci, *s))
1 by brian
clean slate
808
    s++;
809
  if (s == end_of_string)
810
    goto fatal_error;
811
812
  if ((to->sign= (*s == '-')))
813
    s++;
814
  else if (*s == '+')
815
    s++;
816
817
  s1=s;
383.1.11 by Brian Aker
Cleanup default character set.
818
  while (s < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *s))
1 by brian
clean slate
819
    s++;
820
  intg= (int) (s-s1);
821
  if (s < end_of_string && *s=='.')
822
  {
823
    endp= s+1;
383.1.11 by Brian Aker
Cleanup default character set.
824
    while (endp < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *endp))
1 by brian
clean slate
825
      endp++;
826
    frac= (int) (endp - s - 1);
827
  }
828
  else
829
  {
830
    frac= 0;
831
    endp= s;
832
  }
833
266.7.10 by Andy Lester
make things more const-correct
834
  *end= endp;
1 by brian
clean slate
835
836
  if (frac+intg == 0)
837
    goto fatal_error;
838
839
  error= 0;
840
  if (fixed)
841
  {
842
    if (frac > to->frac)
843
    {
844
      error=E_DEC_TRUNCATED;
845
      frac=to->frac;
846
    }
847
    if (intg > to->intg)
848
    {
849
      error=E_DEC_OVERFLOW;
850
      intg=to->intg;
851
    }
852
    intg1=ROUND_UP(intg);
853
    frac1=ROUND_UP(frac);
854
    if (intg1+frac1 > to->len)
855
    {
856
      error= E_DEC_OOM;
857
      goto fatal_error;
858
    }
859
  }
860
  else
861
  {
862
    intg1=ROUND_UP(intg);
863
    frac1=ROUND_UP(frac);
864
    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
865
    if (unlikely(error))
866
    {
867
      frac=frac1*DIG_PER_DEC1;
868
      if (error == E_DEC_OVERFLOW)
869
        intg=intg1*DIG_PER_DEC1;
870
    }
871
  }
872
  /* Error is guranteed to be set here */
873
  to->intg=intg;
874
  to->frac=frac;
875
876
  buf=to->buf+intg1;
877
  s1=s;
878
879
  for (x=0, i=0; intg; intg--)
880
  {
881
    x+= (*--s - '0')*powers10[i];
882
883
    if (unlikely(++i == DIG_PER_DEC1))
884
    {
885
      *--buf=x;
886
      x=0;
887
      i=0;
888
    }
889
  }
890
  if (i)
891
    *--buf=x;
892
893
  buf=to->buf+intg1;
894
  for (x=0, i=0; frac; frac--)
895
  {
896
    x= (*++s1 - '0') + x*10;
897
898
    if (unlikely(++i == DIG_PER_DEC1))
899
    {
900
      *buf++=x;
901
      x=0;
902
      i=0;
903
    }
904
  }
905
  if (i)
906
    *buf=x*powers10[DIG_PER_DEC1-i];
907
908
  /* Handle exponent */
909
  if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
910
  {
911
    int str_error;
266.7.10 by Andy Lester
make things more const-correct
912
    const int64_t exponent= my_strtoll10(endp+1, (char**) &end_of_string,
1 by brian
clean slate
913
                                    &str_error);
914
915
    if (end_of_string != endp +1)               /* If at least one digit */
916
    {
917
      *end= (char*) end_of_string;
918
      if (str_error > 0)
919
      {
920
        error= E_DEC_BAD_NUM;
921
        goto fatal_error;
922
      }
923
      if (exponent > INT_MAX/2 || (str_error == 0 && exponent < 0))
924
      {
925
        error= E_DEC_OVERFLOW;
926
        goto fatal_error;
927
      }
928
      if (exponent < INT_MIN/2 && error != E_DEC_OVERFLOW)
929
      {
930
        error= E_DEC_TRUNCATED;
931
        goto fatal_error;
932
      }
933
      if (error != E_DEC_OVERFLOW)
934
        error= decimal_shift(to, (int) exponent);
935
    }
936
  }
937
  return error;
938
939
fatal_error:
940
  decimal_make_zero(to);
941
  return error;
942
}
943
944
945
/*
946
  Convert decimal to double
947
948
  SYNOPSIS
949
    decimal2double()
950
      from    - value to convert
951
      to      - result will be stored there
952
953
  RETURN VALUE
954
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
955
*/
956
957
int decimal2double(decimal_t *from, double *to)
958
{
959
  char strbuf[FLOATING_POINT_BUFFER], *end;
960
  int len= sizeof(strbuf);
961
  int rc, error;
962
963
  rc = decimal2string(from, strbuf, &len, 0, 0, 0);
964
  end= strbuf + len;
965
  
966
  *to= my_strtod(strbuf, &end, &error);
967
             
968
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
969
}
970
971
/*
972
  Convert double to decimal
973
974
  SYNOPSIS
975
    double2decimal()
976
      from    - value to convert
977
      to      - result will be stored there
978
979
  RETURN VALUE
980
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
981
*/
982
983
int double2decimal(double from, decimal_t *to)
984
{
985
  char buff[FLOATING_POINT_BUFFER], *end;
986
  int res;
987
  end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
988
  res= string2decimal(buff, to, &end);
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
989
  return(res);
1 by brian
clean slate
990
}
991
992
151 by Brian Aker
Ulonglong to uint64_t
993
static int ull2dec(uint64_t from, decimal_t *to)
1 by brian
clean slate
994
{
995
  int intg1, error=E_DEC_OK;
151 by Brian Aker
Ulonglong to uint64_t
996
  uint64_t x=from;
1 by brian
clean slate
997
  dec1 *buf;
998
999
  sanity(to);
1000
1001
  for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE) {};
1002
  if (unlikely(intg1 > to->len))
1003
  {
1004
    intg1=to->len;
1005
    error=E_DEC_OVERFLOW;
1006
  }
1007
  to->frac=0;
1008
  to->intg=intg1*DIG_PER_DEC1;
1009
1010
  for (buf=to->buf+intg1; intg1; intg1--)
1011
  {
151 by Brian Aker
Ulonglong to uint64_t
1012
    uint64_t y=x/DIG_BASE;
1 by brian
clean slate
1013
    *--buf=(dec1)(x-y*DIG_BASE);
1014
    x=y;
1015
  }
1016
  return error;
1017
}
1018
151 by Brian Aker
Ulonglong to uint64_t
1019
int uint64_t2decimal(uint64_t from, decimal_t *to)
1 by brian
clean slate
1020
{
1021
  to->sign=0;
1022
  return ull2dec(from, to);
1023
}
1024
152 by Brian Aker
longlong replacement
1025
int int64_t2decimal(int64_t from, decimal_t *to)
1 by brian
clean slate
1026
{
1027
  if ((to->sign= from < 0))
1028
    return ull2dec(-from, to);
1029
  return ull2dec(from, to);
1030
}
1031
151 by Brian Aker
Ulonglong to uint64_t
1032
int decimal2uint64_t(decimal_t *from, uint64_t *to)
1 by brian
clean slate
1033
{
1034
  dec1 *buf=from->buf;
151 by Brian Aker
Ulonglong to uint64_t
1035
  uint64_t x=0;
1 by brian
clean slate
1036
  int intg, frac;
1037
1038
  if (from->sign)
1039
  {
80.1.1 by Brian Aker
LL() cleanup
1040
      *to= 0ULL;
1 by brian
clean slate
1041
      return E_DEC_OVERFLOW;
1042
  }
1043
1044
  for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1045
  {
151 by Brian Aker
Ulonglong to uint64_t
1046
    uint64_t y=x;
1 by brian
clean slate
1047
    x=x*DIG_BASE + *buf++;
163 by Brian Aker
Merge Monty's code.
1048
    if (unlikely(y > ((uint64_t) UINT64_MAX/DIG_BASE) || x < y))
1 by brian
clean slate
1049
    {
163 by Brian Aker
Merge Monty's code.
1050
      *to=UINT64_MAX;
1 by brian
clean slate
1051
      return E_DEC_OVERFLOW;
1052
    }
1053
  }
1054
  *to=x;
1055
  for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1056
    if (*buf++)
1057
      return E_DEC_TRUNCATED;
1058
  return E_DEC_OK;
1059
}
1060
152 by Brian Aker
longlong replacement
1061
int decimal2int64_t(decimal_t *from, int64_t *to)
1 by brian
clean slate
1062
{
1063
  dec1 *buf=from->buf;
152 by Brian Aker
longlong replacement
1064
  int64_t x=0;
1 by brian
clean slate
1065
  int intg, frac;
1066
1067
  for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
1068
  {
152 by Brian Aker
longlong replacement
1069
    int64_t y=x;
1 by brian
clean slate
1070
    /*
1071
      Attention: trick!
1072
      we're calculating -|from| instead of |from| here
163 by Brian Aker
Merge Monty's code.
1073
      because |INT64_MIN| > INT64_MAX
1 by brian
clean slate
1074
      so we can convert -9223372036854775808 correctly
1075
    */
1076
    x=x*DIG_BASE - *buf++;
163 by Brian Aker
Merge Monty's code.
1077
    if (unlikely(y < (INT64_MIN/DIG_BASE) || x > y))
1 by brian
clean slate
1078
    {
1079
      /*
1080
        the decimal is bigger than any possible integer
1081
        return border integer depending on the sign
1082
      */
163 by Brian Aker
Merge Monty's code.
1083
      *to= from->sign ? INT64_MIN : INT64_MAX;
1 by brian
clean slate
1084
      return E_DEC_OVERFLOW;
1085
    }
1086
  }
1087
  /* boundary case: 9223372036854775808 */
163 by Brian Aker
Merge Monty's code.
1088
  if (unlikely(from->sign==0 && x == INT64_MIN))
1 by brian
clean slate
1089
  {
163 by Brian Aker
Merge Monty's code.
1090
    *to= INT64_MAX;
1 by brian
clean slate
1091
    return E_DEC_OVERFLOW;
1092
  }
1093
1094
  *to=from->sign ? x : -x;
1095
  for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
1096
    if (*buf++)
1097
      return E_DEC_TRUNCATED;
1098
  return E_DEC_OK;
1099
}
1100
1101
/*
1102
  Convert decimal to its binary fixed-length representation
1103
  two representations of the same length can be compared with memcmp
1104
  with the correct -1/0/+1 result
1105
1106
  SYNOPSIS
1107
    decimal2bin()
1108
      from    - value to convert
1109
      to      - points to buffer where string representation should be stored
1110
      precision/scale - see decimal_bin_size() below
1111
1112
  NOTE
1113
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1114
1115
  RETURN VALUE
1116
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1117
1118
  DESCRIPTION
1119
    for storage decimal numbers are converted to the "binary" format.
1120
1121
    This format has the following properties:
1122
      1. length of the binary representation depends on the {precision, scale}
1123
      as provided by the caller and NOT on the intg/frac of the decimal to
1124
      convert.
1125
      2. binary representations of the same {precision, scale} can be compared
1126
      with memcmp - with the same result as decimal_cmp() of the original
1127
      decimals (not taking into account possible precision loss during
1128
      conversion).
1129
1130
    This binary format is as follows:
1131
      1. First the number is converted to have a requested precision and scale.
1132
      2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes
1133
         as is
1134
      3. The first intg % DIG_PER_DEC1 digits are stored in the reduced
1135
         number of bytes (enough bytes to store this number of digits -
1136
         see dig2bytes)
1137
      4. same for frac - full decimal_digit_t's are stored as is,
1138
         the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes.
1139
      5. If the number is negative - every byte is inversed.
1140
      5. The very first bit of the resulting byte array is inverted (because
1141
         memcmp compares unsigned bytes, see property 2 above)
1142
1143
    Example:
1144
1145
      1234567890.1234
1146
1147
    internally is represented as 3 decimal_digit_t's
1148
1149
      1 234567890 123400000
1150
1151
    (assuming we want a binary representation with precision=14, scale=4)
1152
    in hex it's
1153
1154
      00-00-00-01  0D-FB-38-D2  07-5A-EF-40
1155
1156
    now, middle decimal_digit_t is full - it stores 9 decimal digits. It goes
1157
    into binary representation as is:
1158
1159
1160
      ...........  0D-FB-38-D2 ............
1161
1162
    First decimal_digit_t has only one decimal digit. We can store one digit in
1163
    one byte, no need to waste four:
1164
1165
                01 0D-FB-38-D2 ............
1166
1167
    now, last digit. It's 123400000. We can store 1234 in two bytes:
1168
1169
                01 0D-FB-38-D2 04-D2
1170
1171
    So, we've packed 12 bytes number in 7 bytes.
1172
    And now we invert the highest bit to get the final result:
1173
1174
                81 0D FB 38 D2 04 D2
1175
1176
    And for -1234567890.1234 it would be
1177
1178
                7E F2 04 37 2D FB 2D
1179
*/
481 by Brian Aker
Remove all of uchar.
1180
int decimal2bin(decimal_t *from, unsigned char *to, int precision, int frac)
1 by brian
clean slate
1181
{
1182
  dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1183
  int error=E_DEC_OK, intg=precision-frac,
1184
      isize1, intg1, intg1x, from_intg,
1185
      intg0=intg/DIG_PER_DEC1,
1186
      frac0=frac/DIG_PER_DEC1,
1187
      intg0x=intg-intg0*DIG_PER_DEC1,
1188
      frac0x=frac-frac0*DIG_PER_DEC1,
1189
      frac1=from->frac/DIG_PER_DEC1,
1190
      frac1x=from->frac-frac1*DIG_PER_DEC1,
1191
      isize0=intg0*sizeof(dec1)+dig2bytes[intg0x],
1192
      fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x],
1193
      fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
1194
  const int orig_isize0= isize0;
1195
  const int orig_fsize0= fsize0;
481 by Brian Aker
Remove all of uchar.
1196
  unsigned char *orig_to= to;
1 by brian
clean slate
1197
1198
  buf1= remove_leading_zeroes(from, &from_intg);
1199
1200
  if (unlikely(from_intg+fsize1==0))
1201
  {
1202
    mask=0; /* just in case */
1203
    intg=1;
1204
    buf1=&mask;
1205
  }
1206
1207
  intg1=from_intg/DIG_PER_DEC1;
1208
  intg1x=from_intg-intg1*DIG_PER_DEC1;
1209
  isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
1210
1211
  if (intg < from_intg)
1212
  {
1213
    buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
1214
    intg1=intg0; intg1x=intg0x;
1215
    error=E_DEC_OVERFLOW;
1216
  }
1217
  else if (isize0 > isize1)
1218
  {
1219
    while (isize0-- > isize1)
1220
      *to++= (char)mask;
1221
  }
1222
  if (fsize0 < fsize1)
1223
  {
1224
    frac1=frac0; frac1x=frac0x;
1225
    error=E_DEC_TRUNCATED;
1226
  }
1227
  else if (fsize0 > fsize1 && frac1x)
1228
  {
1229
    if (frac0 == frac1)
1230
    {
1231
      frac1x=frac0x;
1232
      fsize0= fsize1;
1233
    }
1234
    else
1235
    {
1236
      frac1++;
1237
      frac1x=0;
1238
    }
1239
  }
1240
1241
  /* intg1x part */
1242
  if (intg1x)
1243
  {
1244
    int i=dig2bytes[intg1x];
1245
    dec1 x=(*buf1++ % powers10[intg1x]) ^ mask;
1246
    switch (i)
1247
    {
1248
      case 1: mi_int1store(to, x); break;
1249
      case 2: mi_int2store(to, x); break;
1250
      case 3: mi_int3store(to, x); break;
1251
      case 4: mi_int4store(to, x); break;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1252
      default: assert(0);
1 by brian
clean slate
1253
    }
1254
    to+=i;
1255
  }
1256
1257
  /* intg1+frac1 part */
1258
  for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=sizeof(dec1))
1259
  {
1260
    dec1 x=*buf1++ ^ mask;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1261
    assert(sizeof(dec1) == 4);
1 by brian
clean slate
1262
    mi_int4store(to, x);
1263
  }
1264
1265
  /* frac1x part */
1266
  if (frac1x)
1267
  {
1268
    dec1 x;
1269
    int i=dig2bytes[frac1x],
1270
        lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x);
1271
    while (frac1x < lim && dig2bytes[frac1x] == i)
1272
      frac1x++;
1273
    x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask;
1274
    switch (i)
1275
    {
1276
      case 1: mi_int1store(to, x); break;
1277
      case 2: mi_int2store(to, x); break;
1278
      case 3: mi_int3store(to, x); break;
1279
      case 4: mi_int4store(to, x); break;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1280
      default: assert(0);
1 by brian
clean slate
1281
    }
1282
    to+=i;
1283
  }
1284
  if (fsize0 > fsize1)
1285
  {
481 by Brian Aker
Remove all of uchar.
1286
    unsigned char *to_end= orig_to + orig_fsize0 + orig_isize0;
1 by brian
clean slate
1287
1288
    while (fsize0-- > fsize1 && to < to_end)
481 by Brian Aker
Remove all of uchar.
1289
      *to++= (unsigned char)mask;
1 by brian
clean slate
1290
  }
1291
  orig_to[0]^= 0x80;
1292
1293
  /* Check that we have written the whole decimal and nothing more */
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1294
  assert(to == orig_to + orig_fsize0 + orig_isize0);
1 by brian
clean slate
1295
  return error;
1296
}
1297
1298
/*
1299
  Restores decimal from its binary fixed-length representation
1300
1301
  SYNOPSIS
1302
    bin2decimal()
1303
      from    - value to convert
1304
      to      - result
1305
      precision/scale - see decimal_bin_size() below
1306
1307
  NOTE
1308
    see decimal2bin()
1309
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1310
1311
  RETURN VALUE
1312
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1313
*/
1314
481 by Brian Aker
Remove all of uchar.
1315
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1 by brian
clean slate
1316
{
1317
  int error=E_DEC_OK, intg=precision-scale,
1318
      intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1319
      intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1320
      intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1321
  dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
481 by Brian Aker
Remove all of uchar.
1322
  const unsigned char *stop;
1323
  unsigned char *d_copy;
1 by brian
clean slate
1324
  int bin_size= decimal_bin_size(precision, scale);
1325
1326
  sanity(to);
481 by Brian Aker
Remove all of uchar.
1327
  d_copy= (unsigned char*) alloca(bin_size);
1 by brian
clean slate
1328
  memcpy(d_copy, from, bin_size);
1329
  d_copy[0]^= 0x80;
1330
  from= d_copy;
1331
1332
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1333
  if (unlikely(error))
1334
  {
1335
    if (intg1 < intg0+(intg0x>0))
1336
    {
1337
      from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1);
1338
      frac0=frac0x=intg0x=0;
1339
      intg0=intg1;
1340
    }
1341
    else
1342
    {
1343
      frac0x=0;
1344
      frac0=frac1;
1345
    }
1346
  }
1347
1348
  to->sign=(mask != 0);
1349
  to->intg=intg0*DIG_PER_DEC1+intg0x;
1350
  to->frac=frac0*DIG_PER_DEC1+frac0x;
1351
1352
  if (intg0x)
1353
  {
1354
    int i=dig2bytes[intg0x];
1355
    dec1 x= 0;
1356
    switch (i)
1357
    {
1358
      case 1: x=mi_sint1korr(from); break;
1359
      case 2: x=mi_sint2korr(from); break;
1360
      case 3: x=mi_sint3korr(from); break;
1361
      case 4: x=mi_sint4korr(from); break;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1362
      default: assert(0);
1 by brian
clean slate
1363
    }
1364
    from+=i;
1365
    *buf=x ^ mask;
151 by Brian Aker
Ulonglong to uint64_t
1366
    if (((uint64_t)*buf) >= (uint64_t) powers10[intg0x+1])
1 by brian
clean slate
1367
      goto err;
1368
    if (buf > to->buf || *buf != 0)
1369
      buf++;
1370
    else
1371
      to->intg-=intg0x;
1372
  }
1373
  for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1374
  {
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1375
    assert(sizeof(dec1) == 4);
1 by brian
clean slate
1376
    *buf=mi_sint4korr(from) ^ mask;
205 by Brian Aker
uint32 -> uin32_t
1377
    if (((uint32_t)*buf) > DIG_MAX)
1 by brian
clean slate
1378
      goto err;
1379
    if (buf > to->buf || *buf != 0)
1380
      buf++;
1381
    else
1382
      to->intg-=DIG_PER_DEC1;
1383
  }
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1384
  assert(to->intg >=0);
1 by brian
clean slate
1385
  for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
1386
  {
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1387
    assert(sizeof(dec1) == 4);
1 by brian
clean slate
1388
    *buf=mi_sint4korr(from) ^ mask;
205 by Brian Aker
uint32 -> uin32_t
1389
    if (((uint32_t)*buf) > DIG_MAX)
1 by brian
clean slate
1390
      goto err;
1391
    buf++;
1392
  }
1393
  if (frac0x)
1394
  {
1395
    int i=dig2bytes[frac0x];
1396
    dec1 x= 0;
1397
    switch (i)
1398
    {
1399
      case 1: x=mi_sint1korr(from); break;
1400
      case 2: x=mi_sint2korr(from); break;
1401
      case 3: x=mi_sint3korr(from); break;
1402
      case 4: x=mi_sint4korr(from); break;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1403
      default: assert(0);
1 by brian
clean slate
1404
    }
1405
    *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
205 by Brian Aker
uint32 -> uin32_t
1406
    if (((uint32_t)*buf) > DIG_MAX)
1 by brian
clean slate
1407
      goto err;
1408
    buf++;
1409
  }
1410
  return error;
1411
1412
err:
1413
  decimal_make_zero(((decimal_t*) to));
1414
  return(E_DEC_BAD_NUM);
1415
}
1416
1417
/*
1418
  Returns the size of array to hold a decimal with given precision and scale
1419
1420
  RETURN VALUE
1421
    size in dec1
1422
    (multiply by sizeof(dec1) to get the size if bytes)
1423
*/
1424
1425
int decimal_size(int precision, int scale)
1426
{
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1427
  assert(scale >= 0 && precision > 0 && scale <= precision);
1 by brian
clean slate
1428
  return ROUND_UP(precision-scale)+ROUND_UP(scale);
1429
}
1430
1431
/*
1432
  Returns the size of array to hold a binary representation of a decimal
1433
1434
  RETURN VALUE
1435
    size in bytes
1436
*/
1437
1438
int decimal_bin_size(int precision, int scale)
1439
{
1440
  int intg=precision-scale,
1441
      intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1442
      intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
1443
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1444
  assert(scale >= 0 && precision > 0 && scale <= precision);
1 by brian
clean slate
1445
  return intg0*sizeof(dec1)+dig2bytes[intg0x]+
1446
         frac0*sizeof(dec1)+dig2bytes[frac0x];
1447
}
1448
1449
/*
1450
  Rounds the decimal to "scale" digits
1451
1452
  SYNOPSIS
1453
    decimal_round()
1454
      from    - decimal to round,
1455
      to      - result buffer. from==to is allowed
1456
      scale   - to what position to round. can be negative!
1457
      mode    - round to nearest even or truncate
1458
1459
  NOTES
1460
    scale can be negative !
1461
    one TRUNCATED error (line XXX below) isn't treated very logical :(
1462
1463
  RETURN VALUE
1464
    E_DEC_OK/E_DEC_TRUNCATED
1465
*/
1466
1467
int
1468
decimal_round(decimal_t *from, decimal_t *to, int scale,
1469
              decimal_round_mode mode)
1470
{
1471
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1472
      frac1=ROUND_UP(from->frac), round_digit= 0,
1473
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1474
      intg1=ROUND_UP(from->intg +
1475
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1476
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1477
  int first_dig;
1478
1479
  sanity(to);
1480
1481
  switch (mode) {
1482
  case HALF_UP:
1483
  case HALF_EVEN:       round_digit=5; break;
1484
  case CEILING:         round_digit= from->sign ? 10 : 0; break;
1485
  case FLOOR:           round_digit= from->sign ? 0 : 10; break;
1486
  case TRUNCATE:        round_digit=10; break;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1487
  default: assert(0);
1 by brian
clean slate
1488
  }
1489
1490
  if (unlikely(frac0+intg0 > len))
1491
  {
1492
    frac0=len-intg0;
1493
    scale=frac0*DIG_PER_DEC1;
1494
    error=E_DEC_TRUNCATED;
1495
  }
1496
1497
  if (scale+from->intg < 0)
1498
  {
1499
    decimal_make_zero(to);
1500
    return E_DEC_OK;
1501
  }
1502
1503
  if (to != from || intg1>intg0)
1504
  {
398.1.4 by Monty Taylor
Renamed max/min.
1505
    dec1 *p0= buf0+intg0+cmax(frac1, frac0);
1506
    dec1 *p1= buf1+intg1+cmax(frac1, frac0);
1 by brian
clean slate
1507
1508
    while (buf0 < p0)
1509
      *(--p1) = *(--p0);
1510
    if (unlikely(intg1 > intg0))
1511
      to->buf[0]= 0;
1512
1513
    intg0= intg1;
1514
    buf0=to->buf;
1515
    buf1=to->buf;
1516
    to->sign=from->sign;
398.1.4 by Monty Taylor
Renamed max/min.
1517
    to->intg=cmin(intg0, len)*DIG_PER_DEC1;
1 by brian
clean slate
1518
  }
1519
1520
  if (frac0 > frac1)
1521
  {
1522
    buf1+=intg0+frac1;
1523
    while (frac0-- > frac1)
1524
      *buf1++=0;
1525
    goto done;
1526
  }
1527
1528
  if (scale >= from->frac)
1529
    goto done; /* nothing to do */
1530
1531
  buf0+=intg0+frac0-1;
1532
  buf1+=intg0+frac0-1;
1533
  if (scale == frac0*DIG_PER_DEC1)
1534
  {
163 by Brian Aker
Merge Monty's code.
1535
    int do_inc= false;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1536
    assert(frac0+intg0 >= 0);
1 by brian
clean slate
1537
    switch (round_digit) {
1538
    case 0:
1539
    {
1540
      dec1 *p0= buf0 + (frac1-frac0);
1541
      for (; p0 > buf0; p0--)
1542
      {
1543
        if (*p0)
1544
        {
163 by Brian Aker
Merge Monty's code.
1545
          do_inc= true;
1 by brian
clean slate
1546
          break;
1547
        }
1548
      }
1549
      break;
1550
    }
1551
    case 5:
1552
    {
1553
      x= buf0[1]/DIG_MASK;
1554
      do_inc= (x>5) || ((x == 5) &&
1555
                        (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
1556
      break;
1557
    }
1558
    default:
1559
      break;
1560
    }
1561
    if (do_inc)
1562
    {
1563
      if (frac0+intg0>0)
1564
        (*buf1)++;
1565
      else
1566
        *(++buf1)=DIG_BASE;
1567
    }
1568
    else if (frac0+intg0==0)
1569
    {
1570
      decimal_make_zero(to);
1571
      return E_DEC_OK;
1572
    }
1573
  }
1574
  else
1575
  {
1576
    /* TODO - fix this code as it won't work for CEILING mode */
1577
    int pos=frac0*DIG_PER_DEC1-scale-1;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1578
    assert(frac0+intg0 > 0);
1 by brian
clean slate
1579
    x=*buf1 / powers10[pos];
1580
    y=x % 10;
1581
    if (y > round_digit ||
1582
        (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
1583
      x+=10;
1584
    *buf1=powers10[pos]*(x-y);
1585
  }
1586
  /*
1587
    In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal_digit_t's inside
1588
    the buffer are as follows.
1589
1590
    Before <1, 5e8>
1591
    After  <2, 5e8>
1592
1593
    Hence we need to set the 2nd field to 0.
1594
    The same holds if we round 1.5e-9 to 2e-9.
1595
   */
1596
  if (frac0 < frac1)
1597
  {
1598
    dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0);
1599
    dec1 *end= to->buf + len;
1600
1601
    while (buf < end)
1602
      *buf++=0;
1603
  }
1604
  if (*buf1 >= DIG_BASE)
1605
  {
1606
    carry=1;
1607
    *buf1-=DIG_BASE;
1608
    while (carry && --buf1 >= to->buf)
1609
      ADD(*buf1, *buf1, 0, carry);
1610
    if (unlikely(carry))
1611
    {
1612
      /* shifting the number to create space for new digit */
1613
      if (frac0+intg0 >= len)
1614
      {
1615
        frac0--;
1616
        scale=frac0*DIG_PER_DEC1;
1617
        error=E_DEC_TRUNCATED; /* XXX */
1618
      }
398.1.4 by Monty Taylor
Renamed max/min.
1619
      for (buf1=to->buf+intg0+cmax(frac0,0); buf1 > to->buf; buf1--)
1 by brian
clean slate
1620
      {
1621
        buf1[0]=buf1[-1];
1622
      }
1623
      *buf1=1;
1624
      to->intg++;
1625
    }
1626
  }
1627
  else
1628
  {
1629
    for (;;)
1630
    {
1631
      if (likely(*buf1))
1632
        break;
1633
      if (buf1-- == to->buf)
1634
      {
1635
        /* making 'zero' with the proper scale */
1636
        dec1 *p0= to->buf + frac0 + 1;
1637
        to->intg=1;
398.1.4 by Monty Taylor
Renamed max/min.
1638
        to->frac= cmax(scale, 0);
1 by brian
clean slate
1639
        to->sign= 0;
1640
        for (buf1= to->buf; buf1<p0; buf1++)
1641
          *buf1= 0;
1642
        return E_DEC_OK;
1643
      }
1644
    }
1645
  }
1646
1647
  /* Here we  check 999.9 -> 1000 case when we need to increase intg */
1648
  first_dig= to->intg % DIG_PER_DEC1;
1649
  if (first_dig && (*buf1 >= powers10[first_dig]))
1650
    to->intg++;
1651
1652
  if (scale<0)
1653
    scale=0;
1654
1655
done:
1656
  to->frac=scale;
1657
  return error;
1658
}
1659
1660
/*
1661
  Returns the size of the result of the operation
1662
1663
  SYNOPSIS
1664
    decimal_result_size()
1665
      from1   - operand of the unary operation or first operand of the
1666
                binary operation
1667
      from2   - second operand of the binary operation
1668
      op      - operation. one char '+', '-', '*', '/' are allowed
1669
                others may be added later
1670
      param   - extra param to the operation. unused for '+', '-', '*'
1671
                scale increment for '/'
1672
1673
  NOTE
1674
    returned valued may be larger than the actual buffer requred
1675
    in the operation, as decimal_result_size, by design, operates on
1676
    precision/scale values only and not on the actual decimal number
1677
1678
  RETURN VALUE
1679
    size of to->buf array in dec1 elements. to get size in bytes
1680
    multiply by sizeof(dec1)
1681
*/
1682
1683
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1684
{
1685
  switch (op) {
1686
  case '-':
398.1.4 by Monty Taylor
Renamed max/min.
1687
    return ROUND_UP(cmax(from1->intg, from2->intg)) +
1688
           ROUND_UP(cmax(from1->frac, from2->frac));
1 by brian
clean slate
1689
  case '+':
398.1.4 by Monty Taylor
Renamed max/min.
1690
    return ROUND_UP(cmax(from1->intg, from2->intg)+1) +
1691
           ROUND_UP(cmax(from1->frac, from2->frac));
1 by brian
clean slate
1692
  case '*':
1693
    return ROUND_UP(from1->intg+from2->intg)+
1694
           ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1695
  case '/':
1696
    return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1697
  default: assert(0);
1 by brian
clean slate
1698
  }
1699
  return -1; /* shut up the warning */
1700
}
1701
1702
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1703
{
1704
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1705
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
398.1.4 by Monty Taylor
Renamed max/min.
1706
      frac0=cmax(frac1, frac2), intg0=cmax(intg1, intg2), error;
1 by brian
clean slate
1707
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1708
1709
  sanity(to);
1710
1711
  /* is there a need for extra word because of carry ? */
1712
  x=intg1 > intg2 ? from1->buf[0] :
1713
    intg2 > intg1 ? from2->buf[0] :
1714
    from1->buf[0] + from2->buf[0] ;
1715
  if (unlikely(x > DIG_MAX-1)) /* yes, there is */
1716
  {
1717
    intg0++;
1718
    to->buf[0]=0; /* safety */
1719
  }
1720
1721
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1722
  if (unlikely(error == E_DEC_OVERFLOW))
1723
  {
1724
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1725
    return error;
1726
  }
1727
1728
  buf0=to->buf+intg0+frac0;
1729
1730
  to->sign=from1->sign;
398.1.4 by Monty Taylor
Renamed max/min.
1731
  to->frac=cmax(from1->frac, from2->frac);
1 by brian
clean slate
1732
  to->intg=intg0*DIG_PER_DEC1;
1733
  if (unlikely(error))
1734
  {
1735
    set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1736
    set_if_smaller(frac1, frac0);
1737
    set_if_smaller(frac2, frac0);
1738
    set_if_smaller(intg1, intg0);
1739
    set_if_smaller(intg2, intg0);
1740
  }
1741
398.1.4 by Monty Taylor
Renamed max/min.
1742
  /* part 1 - cmax(frac) ... cmin(frac) */
1 by brian
clean slate
1743
  if (frac1 > frac2)
1744
  {
1745
    buf1=from1->buf+intg1+frac1;
1746
    stop=from1->buf+intg1+frac2;
1747
    buf2=from2->buf+intg2+frac2;
1748
    stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
1749
  }
1750
  else
1751
  {
1752
    buf1=from2->buf+intg2+frac2;
1753
    stop=from2->buf+intg2+frac1;
1754
    buf2=from1->buf+intg1+frac1;
1755
    stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
1756
  }
1757
  while (buf1 > stop)
1758
    *--buf0=*--buf1;
1759
398.1.4 by Monty Taylor
Renamed max/min.
1760
  /* part 2 - cmin(frac) ... cmin(intg) */
1 by brian
clean slate
1761
  carry=0;
1762
  while (buf1 > stop2)
1763
  {
1764
    ADD(*--buf0, *--buf1, *--buf2, carry);
1765
  }
1766
398.1.4 by Monty Taylor
Renamed max/min.
1767
  /* part 3 - cmin(intg) ... cmax(intg) */
1 by brian
clean slate
1768
  buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1769
                        ((stop=from2->buf)+intg2-intg1) ;
1770
  while (buf1 > stop)
1771
  {
1772
    ADD(*--buf0, *--buf1, 0, carry);
1773
  }
1774
1775
  if (unlikely(carry))
1776
    *--buf0=1;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1777
  assert(buf0 == to->buf || buf0 == to->buf+1);
1 by brian
clean slate
1778
1779
  return error;
1780
}
1781
1782
/* to=from1-from2.
1783
   if to==0, return -1/0/+1 - the result of the comparison */
1784
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1785
{
1786
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1787
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
398.1.4 by Monty Taylor
Renamed max/min.
1788
  int frac0=cmax(frac1, frac2), error;
1 by brian
clean slate
1789
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1790
1791
  /* let carry:=1 if from2 > from1 */
1792
  start1=buf1=from1->buf; stop1=buf1+intg1;
1793
  start2=buf2=from2->buf; stop2=buf2+intg2;
1794
  if (unlikely(*buf1 == 0))
1795
  {
1796
    while (buf1 < stop1 && *buf1 == 0)
1797
      buf1++;
1798
    start1=buf1;
1799
    intg1= (int) (stop1-buf1);
1800
  }
1801
  if (unlikely(*buf2 == 0))
1802
  {
1803
    while (buf2 < stop2 && *buf2 == 0)
1804
      buf2++;
1805
    start2=buf2;
1806
    intg2= (int) (stop2-buf2);
1807
  }
1808
  if (intg2 > intg1)
1809
    carry=1;
1810
  else if (intg2 == intg1)
1811
  {
1812
    dec1 *end1= stop1 + (frac1 - 1);
1813
    dec1 *end2= stop2 + (frac2 - 1);
1814
    while (unlikely((buf1 <= end1) && (*end1 == 0)))
1815
      end1--;
1816
    while (unlikely((buf2 <= end2) && (*end2 == 0)))
1817
      end2--;
1818
    frac1= (int) (end1 - stop1) + 1;
1819
    frac2= (int) (end2 - stop2) + 1;
1820
    while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
1821
      buf1++, buf2++;
1822
    if (buf1 <= end1)
1823
    {
1824
      if (buf2 <= end2)
1825
        carry= *buf2 > *buf1;
1826
      else
1827
        carry= 0;
1828
    }
1829
    else
1830
    {
1831
      if (buf2 <= end2)
1832
        carry=1;
1833
      else /* short-circuit everything: from1 == from2 */
1834
      {
1835
        if (to == 0) /* decimal_cmp() */
1836
          return 0;
1837
        decimal_make_zero(to);
1838
        return E_DEC_OK;
1839
      }
1840
    }
1841
  }
1842
1843
  if (to == 0) /* decimal_cmp() */
1844
    return carry == from1->sign ? 1 : -1;
1845
1846
  sanity(to);
1847
1848
  to->sign=from1->sign;
1849
1850
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
1851
  if (carry)
1852
  {
1853
    swap_variables(decimal_t *,from1,from1);
1854
    swap_variables(dec1 *,start1, start2);
1855
    swap_variables(int,intg1,intg2);
1856
    swap_variables(int,frac1,frac2);
1857
    to->sign= 1 - to->sign;
1858
  }
1859
1860
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
1861
  buf0=to->buf+intg1+frac0;
1862
398.1.4 by Monty Taylor
Renamed max/min.
1863
  to->frac=cmax(from1->frac, from2->frac);
1 by brian
clean slate
1864
  to->intg=intg1*DIG_PER_DEC1;
1865
  if (unlikely(error))
1866
  {
1867
    set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1868
    set_if_smaller(frac1, frac0);
1869
    set_if_smaller(frac2, frac0);
1870
    set_if_smaller(intg2, intg1);
1871
  }
1872
  carry=0;
1873
398.1.4 by Monty Taylor
Renamed max/min.
1874
  /* part 1 - cmax(frac) ... cmin(frac) */
1 by brian
clean slate
1875
  if (frac1 > frac2)
1876
  {
1877
    buf1=start1+intg1+frac1;
1878
    stop1=start1+intg1+frac2;
1879
    buf2=start2+intg2+frac2;
1880
    while (frac0-- > frac1)
1881
      *--buf0=0;
1882
    while (buf1 > stop1)
1883
      *--buf0=*--buf1;
1884
  }
1885
  else
1886
  {
1887
    buf1=start1+intg1+frac1;
1888
    buf2=start2+intg2+frac2;
1889
    stop2=start2+intg2+frac1;
1890
    while (frac0-- > frac2)
1891
      *--buf0=0;
1892
    while (buf2 > stop2)
1893
    {
1894
      SUB(*--buf0, 0, *--buf2, carry);
1895
    }
1896
  }
1897
398.1.4 by Monty Taylor
Renamed max/min.
1898
  /* part 2 - cmin(frac) ... intg2 */
1 by brian
clean slate
1899
  while (buf2 > start2)
1900
  {
1901
    SUB(*--buf0, *--buf1, *--buf2, carry);
1902
  }
1903
1904
  /* part 3 - intg2 ... intg1 */
1905
  while (carry && buf1 > start1)
1906
  {
1907
    SUB(*--buf0, *--buf1, 0, carry);
1908
  }
1909
1910
  while (buf1 > start1)
1911
    *--buf0=*--buf1;
1912
1913
  while (buf0 > to->buf)
1914
    *--buf0=0;
1915
1916
  return error;
1917
}
1918
1919
int decimal_intg(decimal_t *from)
1920
{
1921
  int res;
1922
  dec1 *tmp_res;
1923
  tmp_res= remove_leading_zeroes(from, &res);
1924
  return res;
1925
}
1926
1927
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1928
{
1929
  if (likely(from1->sign == from2->sign))
1930
    return do_add(from1, from2, to);
1931
  return do_sub(from1, from2, to);
1932
}
1933
1934
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1935
{
1936
  if (likely(from1->sign == from2->sign))
1937
    return do_sub(from1, from2, to);
1938
  return do_add(from1, from2, to);
1939
}
1940
1941
int decimal_cmp(decimal_t *from1, decimal_t *from2)
1942
{
1943
  if (likely(from1->sign == from2->sign))
1944
    return do_sub(from1, from2, 0);
1945
  return from1->sign > from2->sign ? -1 : 1;
1946
}
1947
1948
int decimal_is_zero(decimal_t *from)
1949
{
1950
  dec1 *buf1=from->buf,
1951
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
1952
  while (buf1 < end)
1953
    if (*buf1++)
1954
      return 0;
1955
  return 1;
1956
}
1957
1958
/*
1959
  multiply two decimals
1960
1961
  SYNOPSIS
1962
    decimal_mul()
1963
      from1, from2 - factors
1964
      to      - product
1965
1966
  RETURN VALUE
1967
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
1968
1969
  NOTES
1970
    in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
1971
    and 63-digit number will take only 7 dec1 words (basically a 7-digit
1972
    "base 999999999" number).  Thus there's no need in fast multiplication
1973
    algorithms, 7-digit numbers can be multiplied with a naive O(n*n)
1974
    method.
1975
1976
    XXX if this library is to be used with huge numbers of thousands of
1977
    digits, fast multiplication must be implemented.
1978
*/
1979
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
1980
{
1981
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1982
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1983
      intg0=ROUND_UP(from1->intg+from2->intg),
1984
      frac0=frac1+frac2, error, i, j, d_to_move;
1985
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
1986
       *start2, *stop2, *stop1, *start0, carry;
1987
1988
  sanity(to);
1989
1990
  i=intg0;
1991
  j=frac0;
1992
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1993
  to->sign=from1->sign != from2->sign;
1994
  to->frac=from1->frac+from2->frac;
1995
  to->intg=intg0*DIG_PER_DEC1;
1996
1997
  if (unlikely(error))
1998
  {
1999
    set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
2000
    set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
2001
    if (unlikely(i > intg0))
2002
    {
2003
      i-=intg0;
2004
      j=i >> 1;
2005
      intg1-= j;
2006
      intg2-=i-j;
2007
      frac1=frac2=0; /* frac0 is already 0 here */
2008
    }
2009
    else
2010
    {
2011
      j-=frac0;
2012
      i=j >> 1;
2013
      frac1-= i;
2014
      frac2-=j-i;
2015
    }
2016
  }
2017
  start0=to->buf+intg0+frac0-1;
2018
  start2=buf2+frac2-1;
2019
  stop1=buf1-intg1;
2020
  stop2=buf2-intg2;
2021
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
2022
  memset(to->buf, 0, (intg0+frac0)*sizeof(dec1));
1 by brian
clean slate
2023
2024
  for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
2025
  {
2026
    carry=0;
2027
    for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
2028
    {
2029
      dec1 hi, lo;
2030
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2031
      hi=(dec1)(p/DIG_BASE);
2032
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2033
      ADD2(*buf0, *buf0, lo, carry);
2034
      carry+=hi;
2035
    }
2036
    if (carry)
2037
    {
2038
      if (buf0 < to->buf)
2039
        return E_DEC_OVERFLOW;
2040
      ADD2(*buf0, *buf0, 0, carry);
2041
    }
2042
    for (buf0--; carry; buf0--)
2043
    {
2044
      if (buf0 < to->buf)
2045
        return E_DEC_OVERFLOW;
2046
      ADD(*buf0, *buf0, 0, carry);
2047
    }
2048
  }
2049
2050
  /* Now we have to check for -0.000 case */
2051
  if (to->sign)
2052
  {
2053
    dec1 *buf= to->buf;
2054
    dec1 *end= to->buf + intg0 + frac0;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2055
    assert(buf != end);
1 by brian
clean slate
2056
    for (;;)
2057
    {
2058
      if (*buf)
2059
        break;
2060
      if (++buf == end)
2061
      {
2062
        /* We got decimal zero */
2063
        decimal_make_zero(to);
2064
        break;
2065
      }
2066
    }
2067
  }
2068
  buf1= to->buf;
2069
  d_to_move= intg0 + ROUND_UP(to->frac);
2070
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2071
  {
2072
    buf1++;
2073
    to->intg-= DIG_PER_DEC1;
2074
    d_to_move--;
2075
  }
2076
  if (to->buf < buf1)
2077
  {
2078
    dec1 *cur_d= to->buf;
2079
    for (; d_to_move--; cur_d++, buf1++)
2080
      *cur_d= *buf1;
2081
  }
2082
  return error;
2083
}
2084
2085
/*
2086
  naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2087
  it's ok for short numbers
2088
  also we're using alloca() to allocate a temporary buffer
2089
2090
  XXX if this library is to be used with huge numbers of thousands of
2091
  digits, fast division must be implemented and alloca should be
2092
  changed to malloc (or at least fallback to malloc if alloca() fails)
2093
  but then, decimal_mul() should be rewritten too :(
2094
*/
2095
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2096
                       decimal_t *to, decimal_t *mod, int scale_incr)
2097
{
2098
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2099
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2100
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2101
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2102
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2103
  dec2 norm_factor, x, guess, y;
2104
2105
  if (mod)
2106
    to=mod;
2107
2108
  sanity(to);
2109
2110
  /* removing all the leading zeroes */
2111
  i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
2112
  while (prec2 > 0 && *buf2 == 0)
2113
  {
2114
    prec2-= i;
2115
    i= DIG_PER_DEC1;
2116
    buf2++;
2117
  }
2118
  if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
2119
    return E_DEC_DIV_ZERO;
2120
  for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2121
  assert(prec2 > 0);
1 by brian
clean slate
2122
2123
  i=((prec1-1) % DIG_PER_DEC1)+1;
2124
  while (prec1 > 0 && *buf1 == 0)
2125
  {
2126
    prec1-=i;
2127
    i=DIG_PER_DEC1;
2128
    buf1++;
2129
  }
2130
  if (prec1 <= 0)
2131
  { /* short-circuit everything: from1 == 0 */
2132
    decimal_make_zero(to);
2133
    return E_DEC_OK;
2134
  }
2135
  for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2136
  assert(prec1 > 0);
1 by brian
clean slate
2137
2138
  /* let's fix scale_incr, taking into account frac1,frac2 increase */
2139
  if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
2140
    scale_incr=0;
2141
2142
  dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
2143
  if (dintg < 0)
2144
  {
2145
    dintg/=DIG_PER_DEC1;
2146
    intg0=0;
2147
  }
2148
  else
2149
    intg0=ROUND_UP(dintg);
2150
  if (mod)
2151
  {
2152
    /* we're calculating N1 % N2.
2153
       The result will have
398.1.4 by Monty Taylor
Renamed max/min.
2154
         frac=cmax(frac1, frac2), as for subtraction
1 by brian
clean slate
2155
         intg=intg2
2156
    */
2157
    to->sign=from1->sign;
398.1.4 by Monty Taylor
Renamed max/min.
2158
    to->frac=cmax(from1->frac, from2->frac);
1 by brian
clean slate
2159
    frac0=0;
2160
  }
2161
  else
2162
  {
2163
    /*
2164
      we're calculating N1/N2. N1 is in the buf1, has prec1 digits
2165
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2166
      frac2 accordingly.
2167
      Thus, the result will have
2168
         frac = ROUND_UP(frac1+frac2+scale_incr)
2169
      and
2170
         intg = (prec1-frac1) - (prec2-frac2) + 1
2171
         prec = intg+frac
2172
    */
2173
    frac0=ROUND_UP(frac1+frac2+scale_incr);
2174
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2175
    to->sign=from1->sign != from2->sign;
2176
    to->intg=intg0*DIG_PER_DEC1;
2177
    to->frac=frac0*DIG_PER_DEC1;
2178
  }
2179
  buf0=to->buf;
2180
  stop0=buf0+intg0+frac0;
2181
  if (likely(div_mod))
2182
    while (dintg++ < 0)
2183
      *buf0++=0;
2184
2185
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2186
  set_if_bigger(len1, 3);
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
2187
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
1 by brian
clean slate
2188
    return E_DEC_OOM;
2189
  memcpy(tmp1, buf1, i*sizeof(dec1));
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
2190
  memset(tmp1+i, 0, (len1-i)*sizeof(dec1));
1 by brian
clean slate
2191
2192
  start1=tmp1;
2193
  stop1=start1+len1;
2194
  start2=buf2;
2195
  stop2=buf2+ROUND_UP(prec2)-1;
2196
2197
  /* removing end zeroes */
2198
  while (*stop2 == 0 && stop2 >= start2)
2199
    stop2--;
2200
  len2= (int) (stop2++ - start2);
2201
2202
  /*
2203
    calculating norm2 (normalized *start2) - we need *start2 to be large
2204
    (at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to
2205
    normalize input numbers (as we don't make a copy of the divisor).
2206
    Thus we normalize first dec1 of buf2 only, and we'll normalize *start1
2207
    on the fly for the purpose of guesstimation only.
2208
    It's also faster, as we're saving on normalization of buf2
2209
  */
2210
  norm_factor=DIG_BASE/(*start2+1);
2211
  norm2=(dec1)(norm_factor*start2[0]);
2212
  if (likely(len2>0))
2213
    norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
2214
2215
  if (*start1 < *start2)
2216
    dcarry=*start1++;
2217
  else
2218
    dcarry=0;
2219
2220
  /* main loop */
2221
  for (; buf0 < stop0; buf0++)
2222
  {
2223
    /* short-circuit, if possible */
2224
    if (unlikely(dcarry == 0 && *start1 < *start2))
2225
      guess=0;
2226
    else
2227
    {
2228
      /* D3: make a guess */
2229
      x=start1[0]+((dec2)dcarry)*DIG_BASE;
2230
      y=start1[1];
2231
      guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
2232
      if (unlikely(guess >= DIG_BASE))
2233
        guess=DIG_BASE-1;
2234
      if (likely(len2>0))
2235
      {
2236
        /* hmm, this is a suspicious trick - I removed normalization here */
2237
        if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
2238
          guess--;
2239
        if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
2240
          guess--;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2241
        assert(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
1 by brian
clean slate
2242
      }
2243
2244
      /* D4: multiply and subtract */
2245
      buf2=stop2;
2246
      buf1=start1+len2;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2247
      assert(buf1 < stop1);
1 by brian
clean slate
2248
      for (carry=0; buf2 > start2; buf1--)
2249
      {
2250
        dec1 hi, lo;
2251
        x=guess * (*--buf2);
2252
        hi=(dec1)(x/DIG_BASE);
2253
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2254
        SUB2(*buf1, *buf1, lo, carry);
2255
        carry+=hi;
2256
      }
2257
      carry= dcarry < carry;
2258
2259
      /* D5: check the remainder */
2260
      if (unlikely(carry))
2261
      {
2262
        /* D6: correct the guess */
2263
        guess--;
2264
        buf2=stop2;
2265
        buf1=start1+len2;
2266
        for (carry=0; buf2 > start2; buf1--)
2267
        {
2268
          ADD(*buf1, *buf1, *--buf2, carry);
2269
        }
2270
      }
2271
    }
2272
    if (likely(div_mod))
2273
      *buf0=(dec1)guess;
2274
    dcarry= *start1;
2275
    start1++;
2276
  }
2277
  if (mod)
2278
  {
2279
    /*
2280
      now the result is in tmp1, it has
2281
        intg=prec1-frac1
398.1.4 by Monty Taylor
Renamed max/min.
2282
        frac=cmax(frac1, frac2)=to->frac
1 by brian
clean slate
2283
    */
2284
    if (dcarry)
2285
      *--start1=dcarry;
2286
    buf0=to->buf;
2287
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2288
    frac0=ROUND_UP(to->frac);
2289
    error=E_DEC_OK;
2290
    if (unlikely(frac0==0 && intg0==0))
2291
    {
2292
      decimal_make_zero(to);
2293
      goto done;
2294
    }
2295
    if (intg0<=0)
2296
    {
2297
      if (unlikely(-intg0 >= to->len))
2298
      {
2299
        decimal_make_zero(to);
2300
        error=E_DEC_TRUNCATED;
2301
        goto done;
2302
      }
2303
      stop1=start1+frac0;
2304
      frac0+=intg0;
2305
      to->intg=0;
2306
      while (intg0++ < 0)
2307
        *buf0++=0;
2308
    }
2309
    else
2310
    {
2311
      if (unlikely(intg0 > to->len))
2312
      {
2313
        frac0=0;
2314
        intg0=to->len;
2315
        error=E_DEC_OVERFLOW;
2316
        goto done;
2317
      }
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2318
      assert(intg0 <= ROUND_UP(from2->intg));
1 by brian
clean slate
2319
      stop1=start1+frac0+intg0;
398.1.4 by Monty Taylor
Renamed max/min.
2320
      to->intg=cmin(intg0*DIG_PER_DEC1, from2->intg);
1 by brian
clean slate
2321
    }
2322
    if (unlikely(intg0+frac0 > to->len))
2323
    {
2324
      stop1-=frac0+intg0-to->len;
2325
      frac0=to->len-intg0;
2326
      to->frac=frac0*DIG_PER_DEC1;
2327
        error=E_DEC_TRUNCATED;
2328
    }
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2329
    assert(buf0 + (stop1 - start1) <= to->buf + to->len);
1 by brian
clean slate
2330
    while (start1 < stop1)
2331
        *buf0++=*start1++;
2332
  }
2333
done:
2334
  return error;
2335
}
2336
2337
/*
2338
  division of two decimals
2339
2340
  SYNOPSIS
2341
    decimal_div()
2342
      from1   - dividend
2343
      from2   - divisor
2344
      to      - quotient
2345
2346
  RETURN VALUE
2347
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2348
2349
  NOTES
2350
    see do_div_mod()
2351
*/
2352
2353
int
2354
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2355
{
2356
  return do_div_mod(from1, from2, to, 0, scale_incr);
2357
}
2358
2359
/*
2360
  modulus
2361
2362
  SYNOPSIS
2363
    decimal_mod()
2364
      from1   - dividend
2365
      from2   - divisor
2366
      to      - modulus
2367
2368
  RETURN VALUE
2369
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2370
2371
  NOTES
2372
    see do_div_mod()
2373
2374
  DESCRIPTION
2375
    the modulus R in    R = M mod N
2376
2377
   is defined as
2378
2379
     0 <= |R| < |M|
2380
     sign R == sign M
2381
     R = M - k*N, where k is integer
2382
2383
   thus, there's no requirement for M or N to be integers
2384
*/
2385
2386
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2387
{
2388
  return do_div_mod(from1, from2, 0, to, 0);
2389
}
2390
2391
#ifdef MAIN
2392
2393
int full= 0;
2394
decimal_t a, b, c;
2395
char buf1[100], buf2[100], buf3[100];
2396
2397
void dump_decimal(decimal_t *d)
2398
{
2399
  int i;
2400
  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2401
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2402
    printf("%09d, ", d->buf[i]);
2403
  printf("%09d} */ ", d->buf[i]);
2404
}
2405
2406
2407
void check_result_code(int actual, int want)
2408
{
2409
  if (actual != want)
2410
  {
2411
    printf("\n^^^^^^^^^^^^^ must return %d\n", want);
2412
    exit(1);
2413
  }
2414
}
2415
2416
2417
void print_decimal(decimal_t *d, const char *orig, int actual, int want)
2418
{
2419
  char s[100];
2420
  int slen=sizeof(s);
2421
2422
  if (full) dump_decimal(d);
2423
  decimal2string(d, s, &slen, 0, 0, 0);
2424
  printf("'%s'", s);
2425
  check_result_code(actual, want);
2426
  if (orig && strcmp(orig, s))
2427
  {
2428
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2429
    exit(1);
2430
  }
2431
}
2432
2433
void test_d2s()
2434
{
2435
  char s[100];
2436
  int slen, res;
2437
2438
  /***********************************/
2439
  printf("==== decimal2string ====\n");
2440
  a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
2441
  slen=sizeof(s);
2442
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2443
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2444
2445
  a.buf[1]=987000000; a.frac=3;
2446
  slen=sizeof(s);
2447
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2448
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2449
2450
  a.sign=1;
2451
  slen=sizeof(s);
2452
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2453
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2454
2455
  slen=8;
2456
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2457
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2458
2459
  slen=5;
2460
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2461
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2462
2463
  a.buf[0]=987000000; a.frac=3; a.intg=0;
2464
  slen=sizeof(s);
2465
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2466
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2467
}
2468
2469
void test_s2d(const char *s, const char *orig, int ex)
2470
{
2471
  char s1[100], *end;
2472
  int res;
2473
  sprintf(s1, "'%s'", s);
2474
  end= strend(s);
2475
  printf("len=%2d %-30s => res=%d    ", a.len, s1,
2476
         (res= string2decimal(s, &a, &end)));
2477
  print_decimal(&a, orig, res, ex);
2478
  printf("\n");
2479
}
2480
2481
void test_d2f(const char *s, int ex)
2482
{
2483
  char s1[100], *end;
2484
  double x;
2485
  int res;
2486
2487
  sprintf(s1, "'%s'", s);
2488
  end= strend(s);
2489
  string2decimal(s, &a, &end);
2490
  res=decimal2double(&a, &x);
2491
  if (full) dump_decimal(&a);
2492
  printf("%-40s => res=%d    %.*g\n", s1, res, a.intg+a.frac, x);
2493
  check_result_code(res, ex);
2494
}
2495
2496
void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
2497
{
2498
  char s1[100], buf[100], *end;
2499
  int res, i, size=decimal_bin_size(p, s);
2500
2501
  sprintf(s1, "'%s'", str);
2502
  end= strend(str);
2503
  string2decimal(str, &a, &end);
2504
  res=decimal2bin(&a, buf, p, s);
2505
  printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
2506
  if (full)
2507
  {
2508
    printf("0x");
2509
    for (i=0; i < size; i++)
481 by Brian Aker
Remove all of uchar.
2510
      printf("%02x", ((unsigned char *)buf)[i]);
1 by brian
clean slate
2511
  }
2512
  res=bin2decimal(buf, &a, p, s);
2513
  printf(" => res=%d ", res);
2514
  print_decimal(&a, orig, res, ex);
2515
  printf("\n");
2516
}
2517
2518
void test_f2d(double from, int ex)
2519
{
2520
  int res;
2521
2522
  res=double2decimal(from, &a);
2523
  printf("%-40.*f => res=%d    ", DBL_DIG-2, from, res);
2524
  print_decimal(&a, 0, res, ex);
2525
  printf("\n");
2526
}
2527
151 by Brian Aker
Ulonglong to uint64_t
2528
void test_ull2d(uint64_t from, const char *orig, int ex)
1 by brian
clean slate
2529
{
2530
  char s[100];
2531
  int res;
2532
151 by Brian Aker
Ulonglong to uint64_t
2533
  res=uint64_t2decimal(from, &a);
152 by Brian Aker
longlong replacement
2534
  int64_t10_to_str(from,s,10);
1 by brian
clean slate
2535
  printf("%-40s => res=%d    ", s, res);
2536
  print_decimal(&a, orig, res, ex);
2537
  printf("\n");
2538
}
2539
152 by Brian Aker
longlong replacement
2540
void test_ll2d(int64_t from, const char *orig, int ex)
1 by brian
clean slate
2541
{
2542
  char s[100];
2543
  int res;
2544
152 by Brian Aker
longlong replacement
2545
  res=int64_t2decimal(from, &a);
2546
  int64_t10_to_str(from,s,-10);
1 by brian
clean slate
2547
  printf("%-40s => res=%d    ", s, res);
2548
  print_decimal(&a, orig, res, ex);
2549
  printf("\n");
2550
}
2551
2552
void test_d2ull(const char *s, const char *orig, int ex)
2553
{
2554
  char s1[100], *end;
151 by Brian Aker
Ulonglong to uint64_t
2555
  uint64_t x;
1 by brian
clean slate
2556
  int res;
2557
2558
  end= strend(s);
2559
  string2decimal(s, &a, &end);
151 by Brian Aker
Ulonglong to uint64_t
2560
  res=decimal2uint64_t(&a, &x);
1 by brian
clean slate
2561
  if (full) dump_decimal(&a);
152 by Brian Aker
longlong replacement
2562
  int64_t10_to_str(x,s1,10);
1 by brian
clean slate
2563
  printf("%-40s => res=%d    %s\n", s, res, s1);
2564
  check_result_code(res, ex);
2565
  if (orig && strcmp(orig, s1))
2566
  {
2567
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2568
    exit(1);
2569
  }
2570
}
2571
2572
void test_d2ll(const char *s, const char *orig, int ex)
2573
{
2574
  char s1[100], *end;
152 by Brian Aker
longlong replacement
2575
  int64_t x;
1 by brian
clean slate
2576
  int res;
2577
2578
  end= strend(s);
2579
  string2decimal(s, &a, &end);
152 by Brian Aker
longlong replacement
2580
  res=decimal2int64_t(&a, &x);
1 by brian
clean slate
2581
  if (full) dump_decimal(&a);
152 by Brian Aker
longlong replacement
2582
  int64_t10_to_str(x,s1,-10);
1 by brian
clean slate
2583
  printf("%-40s => res=%d    %s\n", s, res, s1);
2584
  check_result_code(res, ex);
2585
  if (orig && strcmp(orig, s1))
2586
  {
2587
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2588
    exit(1);
2589
  }
2590
}
2591
2592
void test_da(const char *s1, const char *s2, const char *orig, int ex)
2593
{
2594
  char s[100], *end;
2595
  int res;
2596
  sprintf(s, "'%s' + '%s'", s1, s2);
2597
  end= strend(s1);
2598
  string2decimal(s1, &a, &end);
2599
  end= strend(s2);
2600
  string2decimal(s2, &b, &end);
2601
  res=decimal_add(&a, &b, &c);
2602
  printf("%-40s => res=%d    ", s, res);
2603
  print_decimal(&c, orig, res, ex);
2604
  printf("\n");
2605
}
2606
2607
void test_ds(const char *s1, const char *s2, const char *orig, int ex)
2608
{
2609
  char s[100], *end;
2610
  int res;
2611
  sprintf(s, "'%s' - '%s'", s1, s2);
2612
  end= strend(s1);
2613
  string2decimal(s1, &a, &end);
2614
  end= strend(s2);
2615
  string2decimal(s2, &b, &end);
2616
  res=decimal_sub(&a, &b, &c);
2617
  printf("%-40s => res=%d    ", s, res);
2618
  print_decimal(&c, orig, res, ex);
2619
  printf("\n");
2620
}
2621
2622
void test_dc(const char *s1, const char *s2, int orig)
2623
{
2624
  char s[100], *end;
2625
  int res;
2626
  sprintf(s, "'%s' <=> '%s'", s1, s2);
2627
  end= strend(s1);
2628
  string2decimal(s1, &a, &end);
2629
  end= strend(s2);
2630
  string2decimal(s2, &b, &end);
2631
  res=decimal_cmp(&a, &b);
2632
  printf("%-40s => res=%d\n", s, res);
2633
  if (orig != res)
2634
  {
2635
    printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
2636
    exit(1);
2637
  }
2638
}
2639
2640
void test_dm(const char *s1, const char *s2, const char *orig, int ex)
2641
{
2642
  char s[100], *end;
2643
  int res;
2644
  sprintf(s, "'%s' * '%s'", s1, s2);
2645
  end= strend(s1);
2646
  string2decimal(s1, &a, &end);
2647
  end= strend(s2);
2648
  string2decimal(s2, &b, &end);
2649
  res=decimal_mul(&a, &b, &c);
2650
  printf("%-40s => res=%d    ", s, res);
2651
  print_decimal(&c, orig, res, ex);
2652
  printf("\n");
2653
}
2654
2655
void test_dv(const char *s1, const char *s2, const char *orig, int ex)
2656
{
2657
  char s[100], *end;
2658
  int res;
2659
  sprintf(s, "'%s' / '%s'", s1, s2);
2660
  end= strend(s1);
2661
  string2decimal(s1, &a, &end);
2662
  end= strend(s2);
2663
  string2decimal(s2, &b, &end);
2664
  res=decimal_div(&a, &b, &c, 5);
2665
  printf("%-40s => res=%d    ", s, res);
2666
  check_result_code(res, ex);
2667
  if (res == E_DEC_DIV_ZERO)
2668
    printf("E_DEC_DIV_ZERO");
2669
  else
2670
    print_decimal(&c, orig, res, ex);
2671
  printf("\n");
2672
}
2673
2674
void test_md(const char *s1, const char *s2, const char *orig, int ex)
2675
{
2676
  char s[100], *end;
2677
  int res;
2678
  sprintf(s, "'%s' %% '%s'", s1, s2);
2679
  end= strend(s1);
2680
  string2decimal(s1, &a, &end);
2681
  end= strend(s2);
2682
  string2decimal(s2, &b, &end);
2683
  res=decimal_mod(&a, &b, &c);
2684
  printf("%-40s => res=%d    ", s, res);
2685
  check_result_code(res, ex);
2686
  if (res == E_DEC_DIV_ZERO)
2687
    printf("E_DEC_DIV_ZERO");
2688
  else
2689
    print_decimal(&c, orig, res, ex);
2690
  printf("\n");
2691
}
2692
2693
const char *round_mode[]=
2694
{"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
2695
2696
void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
2697
             int ex)
2698
{
2699
  char s[100], *end;
2700
  int res;
2701
  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2702
  end= strend(s1);
2703
  string2decimal(s1, &a, &end);
2704
  res=decimal_round(&a, &b, n, mode);
2705
  printf("%-40s => res=%d    ", s, res);
2706
  print_decimal(&b, orig, res, ex);
2707
  printf("\n");
2708
}
2709
2710
2711
void test_mx(int precision, int frac, const char *orig)
2712
{
2713
  char s[100];
2714
  sprintf(s, "%d, %d", precision, frac);
2715
  max_decimal(precision, frac, &a);
2716
  printf("%-40s =>          ", s);
2717
  print_decimal(&a, orig, 0, 0);
2718
  printf("\n");
2719
}
2720
2721
2722
void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
2723
             int ex)
2724
{
2725
  char s[100], *end;
2726
  char s2[100];
2727
  int slen= sizeof(s2);
2728
  int res;
2729
2730
  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2731
          s1, prec, dec, filler);
2732
  end= strend(s1);
2733
  string2decimal(s1, &a, &end);
2734
  res= decimal2string(&a, s2, &slen, prec, dec, filler);
2735
  printf("%-40s => res=%d    '%s'", s, res, s2);
2736
  check_result_code(res, ex);
2737
  if (orig && strcmp(orig, s2))
2738
  {
2739
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2740
    exit(1);
2741
  }
2742
  printf("\n");
2743
}
2744
2745
2746
void test_sh(const char *s1, int shift, const char *orig, int ex)
2747
{
2748
  char s[100], *end;
2749
  int res;
2750
  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2751
  end= strend(s1);
2752
  string2decimal(s1, &a, &end);
2753
  res= decimal_shift(&a, shift);
2754
  printf("%-40s => res=%d    ", s, res);
2755
  print_decimal(&a, orig, res, ex);
2756
  printf("\n");
2757
}
2758
2759
2760
void test_fr(const char *s1, const char *orig)
2761
{
2762
  char s[100], *end;
2763
  sprintf(s, "'%s'", s1);
2764
  printf("%-40s =>          ", s);
2765
  end= strend(s1);
2766
  string2decimal(s1, &a, &end);
2767
  a.frac= decimal_actual_fraction(&a);
2768
  print_decimal(&a, orig, 0, 0);
2769
  printf("\n");
2770
}
2771
2772
2773
int main()
2774
{
2775
  a.buf=(void*)buf1;
2776
  a.len=sizeof(buf1)/sizeof(dec1);
2777
  b.buf=(void*)buf2;
2778
  b.len=sizeof(buf2)/sizeof(dec1);
2779
  c.buf=(void*)buf3;
2780
  c.len=sizeof(buf3)/sizeof(dec1);
2781
2782
  if (full)
2783
    test_d2s();
2784
2785
  printf("==== string2decimal ====\n");
2786
  test_s2d("12345", "12345", 0);
2787
  test_s2d("12345.", "12345", 0);
2788
  test_s2d("123.45", "123.45", 0);
2789
  test_s2d("-123.45", "-123.45", 0);
2790
  test_s2d(".00012345000098765", "0.00012345000098765", 0);
2791
  test_s2d(".12345000098765", "0.12345000098765", 0);
2792
  test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
2793
  test_s2d("1234500009876.5", "1234500009876.5", 0);
2794
  a.len=1;
2795
  test_s2d("123450000098765", "98765", 2);
2796
  test_s2d("123450.000098765", "123450", 1);
2797
  a.len=sizeof(buf1)/sizeof(dec1);
2798
  test_s2d("123E5", "12300000", 0);
2799
  test_s2d("123E-2", "1.23", 0);
2800
2801
  printf("==== decimal2double ====\n");
2802
  test_d2f("12345", 0);
2803
  test_d2f("123.45", 0);
2804
  test_d2f("-123.45", 0);
2805
  test_d2f("0.00012345000098765", 0);
2806
  test_d2f("1234500009876.5", 0);
2807
2808
  printf("==== double2decimal ====\n");
2809
  test_f2d(12345, 0);
2810
  test_f2d(1.0/3, 0);
2811
  test_f2d(-123.45, 0);
2812
  test_f2d(0.00012345000098765, 0);
2813
  test_f2d(1234500009876.5, 0);
2814
151 by Brian Aker
Ulonglong to uint64_t
2815
  printf("==== uint64_t2decimal ====\n");
80.1.1 by Brian Aker
LL() cleanup
2816
  test_ull2d(12345ULL, "12345", 0);
2817
  test_ull2d(0ULL, "0", 0);
2818
  test_ull2d(18446744073709551615ULL, "18446744073709551615", 0);
1 by brian
clean slate
2819
151 by Brian Aker
Ulonglong to uint64_t
2820
  printf("==== decimal2uint64_t ====\n");
1 by brian
clean slate
2821
  test_d2ull("12345", "12345", 0);
2822
  test_d2ull("0", "0", 0);
2823
  test_d2ull("18446744073709551615", "18446744073709551615", 0);
2824
  test_d2ull("18446744073709551616", "18446744073", 2);
2825
  test_d2ull("-1", "0", 2);
2826
  test_d2ull("1.23", "1", 1);
2827
  test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
2828
152 by Brian Aker
longlong replacement
2829
  printf("==== int64_t2decimal ====\n");
80.1.1 by Brian Aker
LL() cleanup
2830
  test_ll2d(12345LL, "-12345", 0);
2831
  test_ll2d(1LL, "-1", 0);
2832
  test_ll2d(9223372036854775807LL, "-9223372036854775807", 0);
2833
  test_ll2d(9223372036854775808ULL, "-9223372036854775808", 0);
1 by brian
clean slate
2834
152 by Brian Aker
longlong replacement
2835
  printf("==== decimal2int64_t ====\n");
1 by brian
clean slate
2836
  test_d2ll("18446744073709551615", "18446744073", 2);
2837
  test_d2ll("-1", "-1", 0);
2838
  test_d2ll("-1.23", "-1", 1);
2839
  test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
2840
  test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
2841
  test_d2ll("9223372036854775808", "9223372036854775807", 2);
2842
2843
  printf("==== do_add ====\n");
2844
  test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
2845
  test_da(".1" ,".45", "0.55", 0);
2846
  test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
2847
  test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
2848
  test_da("99999999" ,"1", "100000000", 0);
2849
  test_da("989999999" ,"1", "990000000", 0);
2850
  test_da("999999999" ,"1", "1000000000", 0);
2851
  test_da("12345" ,"123.45", "12468.45", 0);
2852
  test_da("-12345" ,"-123.45", "-12468.45", 0);
2853
  test_ds("-12345" ,"123.45", "-12468.45", 0);
2854
  test_ds("12345" ,"-123.45", "12468.45", 0);
2855
2856
  printf("==== do_sub ====\n");
2857
  test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
2858
  test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
2859
  test_ds("9999900000000.5", ".555","9999899999999.945", 0);
2860
  test_ds("1111.5551", "1111.555","0.0001", 0);
2861
  test_ds(".555", ".555","0", 0);
2862
  test_ds("10000000", "1","9999999", 0);
2863
  test_ds("1000001000", ".1","1000000999.9", 0);
2864
  test_ds("1000000000", ".1","999999999.9", 0);
2865
  test_ds("12345", "123.45","12221.55", 0);
2866
  test_ds("-12345", "-123.45","-12221.55", 0);
2867
  test_da("-12345", "123.45","-12221.55", 0);
2868
  test_da("12345", "-123.45","12221.55", 0);
2869
  test_ds("123.45", "12345","-12221.55", 0);
2870
  test_ds("-123.45", "-12345","12221.55", 0);
2871
  test_da("123.45", "-12345","-12221.55", 0);
2872
  test_da("-123.45", "12345","12221.55", 0);
2873
  test_da("5", "-6.0","-1.0", 0);
2874
2875
  printf("==== decimal_mul ====\n");
2876
  test_dm("12", "10","120", 0);
2877
  test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
2878
  test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
2879
  test_dm("123456", "987654321","121931851853376", 0);
2880
  test_dm("123456", "9876543210","1219318518533760", 0);
2881
  test_dm("123", "0.01","1.23", 0);
2882
  test_dm("123", "0","0", 0);
2883
2884
  printf("==== decimal_div ====\n");
2885
  test_dv("120", "10","12.000000000", 0);
2886
  test_dv("123", "0.01","12300.000000000", 0);
2887
  test_dv("120", "100000000000.00000","0.000000001200000000", 0);
2888
  test_dv("123", "0","", 4);
2889
  test_dv("0", "0", "", 4);
2890
  test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
2891
  test_dv("121931851853376", "987654321","123456.000000000", 0);
2892
  test_dv("0", "987","0", 0);
2893
  test_dv("1", "3","0.333333333", 0);
2894
  test_dv("1.000000000000", "3","0.333333333333333333", 0);
2895
  test_dv("1", "1","1.000000000", 0);
2896
  test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
2897
  test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
2898
  test_dv("10.000000000060", "2","5.000000000030000000", 0);
2899
2900
  printf("==== decimal_mod ====\n");
2901
  test_md("234","10","4", 0);
2902
  test_md("234.567","10.555","2.357", 0);
2903
  test_md("-234.567","10.555","-2.357", 0);
2904
  test_md("234.567","-10.555","2.357", 0);
2905
  c.buf[1]=0x3ABECA;
2906
  test_md("99999999999999999999999999999999999999","3","0", 0);
2907
  if (c.buf[1] != 0x3ABECA)
2908
  {
2909
    printf("%X - overflow\n", c.buf[1]);
2910
    exit(1);
2911
  }
2912
2913
  printf("==== decimal2bin/bin2decimal ====\n");
2914
  test_d2b2d("-10.55", 4, 2,"-10.55", 0);
2915
  test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
2916
  test_d2b2d("12345", 5, 0,"12345", 0);
2917
  test_d2b2d("12345", 10, 3,"12345.000", 0);
2918
  test_d2b2d("123.45", 10, 3,"123.450", 0);
2919
  test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
2920
  test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
2921
  test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
2922
  test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
2923
  test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
2924
  test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
2925
  test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
2926
  test_d2b2d("000000000.01", 7, 3,"0.010", 0);
2927
  test_d2b2d("123.4", 10, 2, "123.40", 0);
2928
2929
2930
  printf("==== decimal_cmp ====\n");
2931
  test_dc("12","13",-1);
2932
  test_dc("13","12",1);
2933
  test_dc("-10","10",-1);
2934
  test_dc("10","-10",1);
2935
  test_dc("-12","-13",1);
2936
  test_dc("0","12",-1);
2937
  test_dc("-10","0",-1);
2938
  test_dc("4","4",0);
2939
2940
  printf("==== decimal_round ====\n");
2941
  test_ro("5678.123451",-4,TRUNCATE,"0", 0);
2942
  test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
2943
  test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
2944
  test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
2945
  test_ro("5678.123451",0,TRUNCATE,"5678", 0);
2946
  test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
2947
  test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
2948
  test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
2949
  test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
2950
  test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
2951
  test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
2952
  test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
2953
  memset(buf2, 33, sizeof(buf2));
2954
  test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
2955
  test_ro("15.1",0,HALF_UP,"15", 0);
2956
  test_ro("15.5",0,HALF_UP,"16", 0);
2957
  test_ro("15.9",0,HALF_UP,"16", 0);
2958
  test_ro("-15.1",0,HALF_UP,"-15", 0);
2959
  test_ro("-15.5",0,HALF_UP,"-16", 0);
2960
  test_ro("-15.9",0,HALF_UP,"-16", 0);
2961
  test_ro("15.1",1,HALF_UP,"15.1", 0);
2962
  test_ro("-15.1",1,HALF_UP,"-15.1", 0);
2963
  test_ro("15.17",1,HALF_UP,"15.2", 0);
2964
  test_ro("15.4",-1,HALF_UP,"20", 0);
2965
  test_ro("-15.4",-1,HALF_UP,"-20", 0);
2966
  test_ro("5.4",-1,HALF_UP,"10", 0);
2967
  test_ro(".999", 0, HALF_UP, "1", 0);
2968
  memset(buf2, 33, sizeof(buf2));
2969
  test_ro("999999999", -9, HALF_UP, "1000000000", 0);
2970
  test_ro("15.1",0,HALF_EVEN,"15", 0);
2971
  test_ro("15.5",0,HALF_EVEN,"16", 0);
2972
  test_ro("14.5",0,HALF_EVEN,"14", 0);
2973
  test_ro("15.9",0,HALF_EVEN,"16", 0);
2974
  test_ro("15.1",0,CEILING,"16", 0);
2975
  test_ro("-15.1",0,CEILING,"-15", 0);
2976
  test_ro("15.1",0,FLOOR,"15", 0);
2977
  test_ro("-15.1",0,FLOOR,"-16", 0);
2978
  test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
2979
  test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
2980
2981
  b.buf[0]=DIG_BASE+1;
2982
  b.buf++;
2983
  test_ro(".3", 0, HALF_UP, "0", 0);
2984
  b.buf--;
2985
  if (b.buf[0] != DIG_BASE+1)
2986
  {
2987
    printf("%d - underflow\n", b.buf[0]);
2988
    exit(1);
2989
  }
2990
2991
  printf("==== max_decimal ====\n");
2992
  test_mx(1,1,"0.9");
2993
  test_mx(1,0,"9");
2994
  test_mx(2,1,"9.9");
2995
  test_mx(4,2,"99.99");
2996
  test_mx(6,3,"999.999");
2997
  test_mx(8,4,"9999.9999");
2998
  test_mx(10,5,"99999.99999");
2999
  test_mx(12,6,"999999.999999");
3000
  test_mx(14,7,"9999999.9999999");
3001
  test_mx(16,8,"99999999.99999999");
3002
  test_mx(18,9,"999999999.999999999");
3003
  test_mx(20,10,"9999999999.9999999999");
3004
  test_mx(20,20,"0.99999999999999999999");
3005
  test_mx(20,0,"99999999999999999999");
3006
  test_mx(40,20,"99999999999999999999.99999999999999999999");
3007
3008
  printf("==== decimal2string ====\n");
3009
  test_pr("123.123", 0, 0, 0, "123.123", 0);
3010
  test_pr("123.123", 7, 3, '0', "123.123", 0);
3011
  test_pr("123.123", 9, 3, '0', "00123.123", 0);
3012
  test_pr("123.123", 9, 4, '0', "0123.1230", 0);
3013
  test_pr("123.123", 9, 5, '0', "123.12300", 0);
3014
  test_pr("123.123", 9, 2, '0', "000123.12", 1);
3015
  test_pr("123.123", 9, 6, '0', "23.123000", 2);
3016
3017
  printf("==== decimal_shift ====\n");
3018
  test_sh("123.123", 1, "1231.23", 0);
3019
  test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
3020
  test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
3021
  test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
3022
  test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
3023
  test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
3024
  test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
3025
  test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
3026
  test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
3027
  test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3028
  test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3029
  test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3030
  test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3031
  test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3032
  test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3033
  test_sh("123", 1, "1230", 0);
3034
  test_sh("123", 10, "1230000000000", 0);
3035
  test_sh(".123", 1, "1.23", 0);
3036
  test_sh(".123", 10, "1230000000", 0);
3037
  test_sh(".123", 14, "12300000000000", 0);
3038
  test_sh("000.000", 1000, "0", 0);
3039
  test_sh("000.", 1000, "0", 0);
3040
  test_sh(".000", 1000, "0", 0);
3041
  test_sh("1", 1000, "1", 2);
3042
  test_sh("123.123", -1, "12.3123", 0);
3043
  test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
3044
  test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
3045
  test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
3046
  test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
3047
  test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
3048
  test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
3049
  test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
3050
  test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
3051
  test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
3052
  test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
3053
  test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
3054
  a.len= 2;
3055
  test_sh("123.123", -2, "1.23123", 0);
3056
  test_sh("123.123", -3, "0.123123", 0);
3057
  test_sh("123.123", -6, "0.000123123", 0);
3058
  test_sh("123.123", -7, "0.0000123123", 0);
3059
  test_sh("123.123", -15, "0.000000000000123123", 0);
3060
  test_sh("123.123", -16, "0.000000000000012312", 1);
3061
  test_sh("123.123", -17, "0.000000000000001231", 1);
3062
  test_sh("123.123", -18, "0.000000000000000123", 1);
3063
  test_sh("123.123", -19, "0.000000000000000012", 1);
3064
  test_sh("123.123", -20, "0.000000000000000001", 1);
3065
  test_sh("123.123", -21, "0", 1);
3066
  test_sh(".000000000123", -1, "0.0000000000123", 0);
3067
  test_sh(".000000000123", -6, "0.000000000000000123", 0);
3068
  test_sh(".000000000123", -7, "0.000000000000000012", 1);
3069
  test_sh(".000000000123", -8, "0.000000000000000001", 1);
3070
  test_sh(".000000000123", -9, "0", 1);
3071
  test_sh(".000000000123", 1, "0.00000000123", 0);
3072
  test_sh(".000000000123", 8, "0.0123", 0);
3073
  test_sh(".000000000123", 9, "0.123", 0);
3074
  test_sh(".000000000123", 10, "1.23", 0);
3075
  test_sh(".000000000123", 17, "12300000", 0);
3076
  test_sh(".000000000123", 18, "123000000", 0);
3077
  test_sh(".000000000123", 19, "1230000000", 0);
3078
  test_sh(".000000000123", 20, "12300000000", 0);
3079
  test_sh(".000000000123", 21, "123000000000", 0);
3080
  test_sh(".000000000123", 22, "1230000000000", 0);
3081
  test_sh(".000000000123", 23, "12300000000000", 0);
3082
  test_sh(".000000000123", 24, "123000000000000", 0);
3083
  test_sh(".000000000123", 25, "1230000000000000", 0);
3084
  test_sh(".000000000123", 26, "12300000000000000", 0);
3085
  test_sh(".000000000123", 27, "123000000000000000", 0);
3086
  test_sh(".000000000123", 28, "0.000000000123", 2);
3087
  test_sh("123456789.987654321", -1, "12345678.998765432", 1);
3088
  test_sh("123456789.987654321", -2, "1234567.899876543", 1);
3089
  test_sh("123456789.987654321", -8, "1.234567900", 1);
3090
  test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
3091
  test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
3092
  test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
3093
  test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
3094
  test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
3095
  test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
3096
  test_sh("123456789.987654321", -27, "0", 1);
3097
  test_sh("123456789.987654321", 1, "1234567900", 1);
3098
  test_sh("123456789.987654321", 2, "12345678999", 1);
3099
  test_sh("123456789.987654321", 4, "1234567899877", 1);
3100
  test_sh("123456789.987654321", 8, "12345678998765432", 1);
3101
  test_sh("123456789.987654321", 9, "123456789987654321", 0);
3102
  test_sh("123456789.987654321", 10, "123456789.987654321", 2);
3103
  test_sh("123456789.987654321", 0, "123456789.987654321", 0);
3104
  a.len= sizeof(buf1)/sizeof(dec1);
3105
3106
  printf("==== decimal_actual_fraction ====\n");
3107
  test_fr("1.123456789000000000", "1.123456789");
3108
  test_fr("1.12345678000000000", "1.12345678");
3109
  test_fr("1.1234567000000000", "1.1234567");
3110
  test_fr("1.123456000000000", "1.123456");
3111
  test_fr("1.12345000000000", "1.12345");
3112
  test_fr("1.1234000000000", "1.1234");
3113
  test_fr("1.123000000000", "1.123");
3114
  test_fr("1.12000000000", "1.12");
3115
  test_fr("1.1000000000", "1.1");
3116
  test_fr("1.000000000", "1");
3117
  test_fr("1.0", "1");
3118
  test_fr("10000000000000000000.0", "10000000000000000000");
3119
3120
  return 0;
3121
}
3122
#endif