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