~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 decimal with given precision and scale
1429
1430
  RETURN VALUE
1431
    size in dec1
1432
    (multiply by sizeof(dec1) to get the size if bytes)
1433
*/
1434
1435
int decimal_size(int precision, int scale)
1436
{
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1437
  assert(scale >= 0 && precision > 0 && scale <= precision);
1 by brian
clean slate
1438
  return ROUND_UP(precision-scale)+ROUND_UP(scale);
1439
}
1440
1441
/*
1442
  Returns the size of array to hold a binary representation of a decimal
1443
1444
  RETURN VALUE
1445
    size in bytes
1446
*/
1447
1448
int decimal_bin_size(int precision, int scale)
1449
{
1450
  int intg=precision-scale,
1451
      intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1452
      intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
1453
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1454
  assert(scale >= 0 && precision > 0 && scale <= precision);
1 by brian
clean slate
1455
  return intg0*sizeof(dec1)+dig2bytes[intg0x]+
1456
         frac0*sizeof(dec1)+dig2bytes[frac0x];
1457
}
1458
1459
/*
1460
  Rounds the decimal to "scale" digits
1461
1462
  SYNOPSIS
1463
    decimal_round()
1464
      from    - decimal to round,
1465
      to      - result buffer. from==to is allowed
1466
      scale   - to what position to round. can be negative!
1467
      mode    - round to nearest even or truncate
1468
1469
  NOTES
1470
    scale can be negative !
1471
    one TRUNCATED error (line XXX below) isn't treated very logical :(
1472
1473
  RETURN VALUE
1474
    E_DEC_OK/E_DEC_TRUNCATED
1475
*/
1476
1477
int
1478
decimal_round(decimal_t *from, decimal_t *to, int scale,
1479
              decimal_round_mode mode)
1480
{
1481
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1482
      frac1=ROUND_UP(from->frac), round_digit= 0,
1483
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1484
      intg1=ROUND_UP(from->intg +
1485
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1486
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1487
  int first_dig;
1488
1489
  sanity(to);
1490
1491
  switch (mode) {
1492
  case HALF_UP:
1493
  case HALF_EVEN:       round_digit=5; break;
1494
  case CEILING:         round_digit= from->sign ? 10 : 0; break;
1495
  case FLOOR:           round_digit= from->sign ? 0 : 10; break;
1496
  case TRUNCATE:        round_digit=10; break;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1497
  default: assert(0);
1 by brian
clean slate
1498
  }
1499
1500
  if (unlikely(frac0+intg0 > len))
1501
  {
1502
    frac0=len-intg0;
1503
    scale=frac0*DIG_PER_DEC1;
1504
    error=E_DEC_TRUNCATED;
1505
  }
1506
1507
  if (scale+from->intg < 0)
1508
  {
1509
    decimal_make_zero(to);
1510
    return E_DEC_OK;
1511
  }
1512
1513
  if (to != from || intg1>intg0)
1514
  {
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1515
    dec1 *p0= buf0+intg0+max(frac1, frac0);
1516
    dec1 *p1= buf1+intg1+max(frac1, frac0);
1 by brian
clean slate
1517
1518
    while (buf0 < p0)
1519
      *(--p1) = *(--p0);
1520
    if (unlikely(intg1 > intg0))
1521
      to->buf[0]= 0;
1522
1523
    intg0= intg1;
1524
    buf0=to->buf;
1525
    buf1=to->buf;
1526
    to->sign=from->sign;
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1527
    to->intg=min(intg0, len)*DIG_PER_DEC1;
1 by brian
clean slate
1528
  }
1529
1530
  if (frac0 > frac1)
1531
  {
1532
    buf1+=intg0+frac1;
1533
    while (frac0-- > frac1)
1534
      *buf1++=0;
1535
    goto done;
1536
  }
1537
1538
  if (scale >= from->frac)
1539
    goto done; /* nothing to do */
1540
1541
  buf0+=intg0+frac0-1;
1542
  buf1+=intg0+frac0-1;
1543
  if (scale == frac0*DIG_PER_DEC1)
1544
  {
163 by Brian Aker
Merge Monty's code.
1545
    int do_inc= false;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1546
    assert(frac0+intg0 >= 0);
1 by brian
clean slate
1547
    switch (round_digit) {
1548
    case 0:
1549
    {
1550
      dec1 *p0= buf0 + (frac1-frac0);
1551
      for (; p0 > buf0; p0--)
1552
      {
1553
        if (*p0)
1554
        {
163 by Brian Aker
Merge Monty's code.
1555
          do_inc= true;
1 by brian
clean slate
1556
          break;
1557
        }
1558
      }
1559
      break;
1560
    }
1561
    case 5:
1562
    {
1563
      x= buf0[1]/DIG_MASK;
1564
      do_inc= (x>5) || ((x == 5) &&
1565
                        (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
1566
      break;
1567
    }
1568
    default:
1569
      break;
1570
    }
1571
    if (do_inc)
1572
    {
1573
      if (frac0+intg0>0)
1574
        (*buf1)++;
1575
      else
1576
        *(++buf1)=DIG_BASE;
1577
    }
1578
    else if (frac0+intg0==0)
1579
    {
1580
      decimal_make_zero(to);
1581
      return E_DEC_OK;
1582
    }
1583
  }
1584
  else
1585
  {
1586
    /* TODO - fix this code as it won't work for CEILING mode */
1587
    int pos=frac0*DIG_PER_DEC1-scale-1;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1588
    assert(frac0+intg0 > 0);
1 by brian
clean slate
1589
    x=*buf1 / powers10[pos];
1590
    y=x % 10;
1591
    if (y > round_digit ||
1592
        (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
1593
      x+=10;
1594
    *buf1=powers10[pos]*(x-y);
1595
  }
1596
  /*
1597
    In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal_digit_t's inside
1598
    the buffer are as follows.
1599
1600
    Before <1, 5e8>
1601
    After  <2, 5e8>
1602
1603
    Hence we need to set the 2nd field to 0.
1604
    The same holds if we round 1.5e-9 to 2e-9.
1605
   */
1606
  if (frac0 < frac1)
1607
  {
1608
    dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0);
1609
    dec1 *end= to->buf + len;
1610
1611
    while (buf < end)
1612
      *buf++=0;
1613
  }
1614
  if (*buf1 >= DIG_BASE)
1615
  {
1616
    carry=1;
1617
    *buf1-=DIG_BASE;
1618
    while (carry && --buf1 >= to->buf)
1619
      ADD(*buf1, *buf1, 0, carry);
1620
    if (unlikely(carry))
1621
    {
1622
      /* shifting the number to create space for new digit */
1623
      if (frac0+intg0 >= len)
1624
      {
1625
        frac0--;
1626
        scale=frac0*DIG_PER_DEC1;
1627
        error=E_DEC_TRUNCATED; /* XXX */
1628
      }
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1629
      for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--)
1 by brian
clean slate
1630
      {
1631
        buf1[0]=buf1[-1];
1632
      }
1633
      *buf1=1;
1634
      to->intg++;
1635
    }
1636
  }
1637
  else
1638
  {
1639
    for (;;)
1640
    {
1641
      if (likely(*buf1))
1642
        break;
1643
      if (buf1-- == to->buf)
1644
      {
1645
        /* making 'zero' with the proper scale */
1646
        dec1 *p0= to->buf + frac0 + 1;
1647
        to->intg=1;
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1648
        to->frac= max(scale, 0);
1 by brian
clean slate
1649
        to->sign= 0;
1650
        for (buf1= to->buf; buf1<p0; buf1++)
1651
          *buf1= 0;
1652
        return E_DEC_OK;
1653
      }
1654
    }
1655
  }
1656
1657
  /* Here we  check 999.9 -> 1000 case when we need to increase intg */
1658
  first_dig= to->intg % DIG_PER_DEC1;
1659
  if (first_dig && (*buf1 >= powers10[first_dig]))
1660
    to->intg++;
1661
1662
  if (scale<0)
1663
    scale=0;
1664
1665
done:
1666
  to->frac=scale;
1667
  return error;
1668
}
1669
1670
/*
1671
  Returns the size of the result of the operation
1672
1673
  SYNOPSIS
1674
    decimal_result_size()
1675
      from1   - operand of the unary operation or first operand of the
1676
                binary operation
1677
      from2   - second operand of the binary operation
1678
      op      - operation. one char '+', '-', '*', '/' are allowed
1679
                others may be added later
1680
      param   - extra param to the operation. unused for '+', '-', '*'
1681
                scale increment for '/'
1682
1683
  NOTE
1684
    returned valued may be larger than the actual buffer requred
1685
    in the operation, as decimal_result_size, by design, operates on
1686
    precision/scale values only and not on the actual decimal number
1687
1688
  RETURN VALUE
1689
    size of to->buf array in dec1 elements. to get size in bytes
1690
    multiply by sizeof(dec1)
1691
*/
1692
1693
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1694
{
1695
  switch (op) {
1696
  case '-':
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1697
    return ROUND_UP(max(from1->intg, from2->intg)) +
1698
           ROUND_UP(max(from1->frac, from2->frac));
1 by brian
clean slate
1699
  case '+':
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1700
    return ROUND_UP(max(from1->intg, from2->intg)+1) +
1701
           ROUND_UP(max(from1->frac, from2->frac));
1 by brian
clean slate
1702
  case '*':
1703
    return ROUND_UP(from1->intg+from2->intg)+
1704
           ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1705
  case '/':
1706
    return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1707
  default: assert(0);
1 by brian
clean slate
1708
  }
1709
  return -1; /* shut up the warning */
1710
}
1711
1712
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1713
{
1714
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1715
      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
1716
      frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1 by brian
clean slate
1717
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1718
1719
  sanity(to);
1720
1721
  /* is there a need for extra word because of carry ? */
1722
  x=intg1 > intg2 ? from1->buf[0] :
1723
    intg2 > intg1 ? from2->buf[0] :
1724
    from1->buf[0] + from2->buf[0] ;
1725
  if (unlikely(x > DIG_MAX-1)) /* yes, there is */
1726
  {
1727
    intg0++;
1728
    to->buf[0]=0; /* safety */
1729
  }
1730
1731
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1732
  if (unlikely(error == E_DEC_OVERFLOW))
1733
  {
1734
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1735
    return error;
1736
  }
1737
1738
  buf0=to->buf+intg0+frac0;
1739
1740
  to->sign=from1->sign;
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1741
  to->frac=max(from1->frac, from2->frac);
1 by brian
clean slate
1742
  to->intg=intg0*DIG_PER_DEC1;
1743
  if (unlikely(error))
1744
  {
1745
    set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1746
    set_if_smaller(frac1, frac0);
1747
    set_if_smaller(frac2, frac0);
1748
    set_if_smaller(intg1, intg0);
1749
    set_if_smaller(intg2, intg0);
1750
  }
1751
398.1.4 by Monty Taylor
Renamed max/min.
1752
  /* part 1 - cmax(frac) ... cmin(frac) */
1 by brian
clean slate
1753
  if (frac1 > frac2)
1754
  {
1755
    buf1=from1->buf+intg1+frac1;
1756
    stop=from1->buf+intg1+frac2;
1757
    buf2=from2->buf+intg2+frac2;
1758
    stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
1759
  }
1760
  else
1761
  {
1762
    buf1=from2->buf+intg2+frac2;
1763
    stop=from2->buf+intg2+frac1;
1764
    buf2=from1->buf+intg1+frac1;
1765
    stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
1766
  }
1767
  while (buf1 > stop)
1768
    *--buf0=*--buf1;
1769
398.1.4 by Monty Taylor
Renamed max/min.
1770
  /* part 2 - cmin(frac) ... cmin(intg) */
1 by brian
clean slate
1771
  carry=0;
1772
  while (buf1 > stop2)
1773
  {
1774
    ADD(*--buf0, *--buf1, *--buf2, carry);
1775
  }
1776
398.1.4 by Monty Taylor
Renamed max/min.
1777
  /* part 3 - cmin(intg) ... cmax(intg) */
1 by brian
clean slate
1778
  buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1779
                        ((stop=from2->buf)+intg2-intg1) ;
1780
  while (buf1 > stop)
1781
  {
1782
    ADD(*--buf0, *--buf1, 0, carry);
1783
  }
1784
1785
  if (unlikely(carry))
1786
    *--buf0=1;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
1787
  assert(buf0 == to->buf || buf0 == to->buf+1);
1 by brian
clean slate
1788
1789
  return error;
1790
}
1791
1792
/* to=from1-from2.
1793
   if to==0, return -1/0/+1 - the result of the comparison */
1794
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1795
{
1796
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1797
      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
1798
  int frac0=max(frac1, frac2), error;
1 by brian
clean slate
1799
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1800
1801
  /* let carry:=1 if from2 > from1 */
1802
  start1=buf1=from1->buf; stop1=buf1+intg1;
1803
  start2=buf2=from2->buf; stop2=buf2+intg2;
1804
  if (unlikely(*buf1 == 0))
1805
  {
1806
    while (buf1 < stop1 && *buf1 == 0)
1807
      buf1++;
1808
    start1=buf1;
1809
    intg1= (int) (stop1-buf1);
1810
  }
1811
  if (unlikely(*buf2 == 0))
1812
  {
1813
    while (buf2 < stop2 && *buf2 == 0)
1814
      buf2++;
1815
    start2=buf2;
1816
    intg2= (int) (stop2-buf2);
1817
  }
1818
  if (intg2 > intg1)
1819
    carry=1;
1820
  else if (intg2 == intg1)
1821
  {
1822
    dec1 *end1= stop1 + (frac1 - 1);
1823
    dec1 *end2= stop2 + (frac2 - 1);
1824
    while (unlikely((buf1 <= end1) && (*end1 == 0)))
1825
      end1--;
1826
    while (unlikely((buf2 <= end2) && (*end2 == 0)))
1827
      end2--;
1828
    frac1= (int) (end1 - stop1) + 1;
1829
    frac2= (int) (end2 - stop2) + 1;
1830
    while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
1831
      buf1++, buf2++;
1832
    if (buf1 <= end1)
1833
    {
1834
      if (buf2 <= end2)
1835
        carry= *buf2 > *buf1;
1836
      else
1837
        carry= 0;
1838
    }
1839
    else
1840
    {
1841
      if (buf2 <= end2)
1842
        carry=1;
1843
      else /* short-circuit everything: from1 == from2 */
1844
      {
1845
        if (to == 0) /* decimal_cmp() */
1846
          return 0;
1847
        decimal_make_zero(to);
1848
        return E_DEC_OK;
1849
      }
1850
    }
1851
  }
1852
1853
  if (to == 0) /* decimal_cmp() */
1854
    return carry == from1->sign ? 1 : -1;
1855
1856
  sanity(to);
1857
1858
  to->sign=from1->sign;
1859
1860
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
1861
  if (carry)
1862
  {
1863
    swap_variables(decimal_t *,from1,from1);
1864
    swap_variables(dec1 *,start1, start2);
1865
    swap_variables(int,intg1,intg2);
1866
    swap_variables(int,frac1,frac2);
1867
    to->sign= 1 - to->sign;
1868
  }
1869
1870
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
1871
  buf0=to->buf+intg1+frac0;
1872
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
1873
  to->frac=max(from1->frac, from2->frac);
1 by brian
clean slate
1874
  to->intg=intg1*DIG_PER_DEC1;
1875
  if (unlikely(error))
1876
  {
1877
    set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
1878
    set_if_smaller(frac1, frac0);
1879
    set_if_smaller(frac2, frac0);
1880
    set_if_smaller(intg2, intg1);
1881
  }
1882
  carry=0;
1883
398.1.4 by Monty Taylor
Renamed max/min.
1884
  /* part 1 - cmax(frac) ... cmin(frac) */
1 by brian
clean slate
1885
  if (frac1 > frac2)
1886
  {
1887
    buf1=start1+intg1+frac1;
1888
    stop1=start1+intg1+frac2;
1889
    buf2=start2+intg2+frac2;
1890
    while (frac0-- > frac1)
1891
      *--buf0=0;
1892
    while (buf1 > stop1)
1893
      *--buf0=*--buf1;
1894
  }
1895
  else
1896
  {
1897
    buf1=start1+intg1+frac1;
1898
    buf2=start2+intg2+frac2;
1899
    stop2=start2+intg2+frac1;
1900
    while (frac0-- > frac2)
1901
      *--buf0=0;
1902
    while (buf2 > stop2)
1903
    {
1904
      SUB(*--buf0, 0, *--buf2, carry);
1905
    }
1906
  }
1907
398.1.4 by Monty Taylor
Renamed max/min.
1908
  /* part 2 - cmin(frac) ... intg2 */
1 by brian
clean slate
1909
  while (buf2 > start2)
1910
  {
1911
    SUB(*--buf0, *--buf1, *--buf2, carry);
1912
  }
1913
1914
  /* part 3 - intg2 ... intg1 */
1915
  while (carry && buf1 > start1)
1916
  {
1917
    SUB(*--buf0, *--buf1, 0, carry);
1918
  }
1919
1920
  while (buf1 > start1)
1921
    *--buf0=*--buf1;
1922
1923
  while (buf0 > to->buf)
1924
    *--buf0=0;
1925
1926
  return error;
1927
}
1928
1929
int decimal_intg(decimal_t *from)
1930
{
1931
  int res;
1932
  dec1 *tmp_res;
1933
  tmp_res= remove_leading_zeroes(from, &res);
1934
  return res;
1935
}
1936
1937
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1938
{
1939
  if (likely(from1->sign == from2->sign))
1940
    return do_add(from1, from2, to);
1941
  return do_sub(from1, from2, to);
1942
}
1943
1944
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1945
{
1946
  if (likely(from1->sign == from2->sign))
1947
    return do_sub(from1, from2, to);
1948
  return do_add(from1, from2, to);
1949
}
1950
1951
int decimal_cmp(decimal_t *from1, decimal_t *from2)
1952
{
1953
  if (likely(from1->sign == from2->sign))
1954
    return do_sub(from1, from2, 0);
1955
  return from1->sign > from2->sign ? -1 : 1;
1956
}
1957
1958
int decimal_is_zero(decimal_t *from)
1959
{
1960
  dec1 *buf1=from->buf,
1961
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
1962
  while (buf1 < end)
1963
    if (*buf1++)
1964
      return 0;
1965
  return 1;
1966
}
1967
1968
/*
1969
  multiply two decimals
1970
1971
  SYNOPSIS
1972
    decimal_mul()
1973
      from1, from2 - factors
1974
      to      - product
1975
1976
  RETURN VALUE
1977
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
1978
1979
  NOTES
1980
    in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
1981
    and 63-digit number will take only 7 dec1 words (basically a 7-digit
1982
    "base 999999999" number).  Thus there's no need in fast multiplication
1983
    algorithms, 7-digit numbers can be multiplied with a naive O(n*n)
1984
    method.
1985
1986
    XXX if this library is to be used with huge numbers of thousands of
1987
    digits, fast multiplication must be implemented.
1988
*/
1989
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
1990
{
1991
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1992
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1993
      intg0=ROUND_UP(from1->intg+from2->intg),
1994
      frac0=frac1+frac2, error, i, j, d_to_move;
1995
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
1996
       *start2, *stop2, *stop1, *start0, carry;
1997
1998
  sanity(to);
1999
2000
  i=intg0;
2001
  j=frac0;
2002
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2003
  to->sign=from1->sign != from2->sign;
2004
  to->frac=from1->frac+from2->frac;
2005
  to->intg=intg0*DIG_PER_DEC1;
2006
2007
  if (unlikely(error))
2008
  {
2009
    set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
2010
    set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
2011
    if (unlikely(i > intg0))
2012
    {
2013
      i-=intg0;
2014
      j=i >> 1;
2015
      intg1-= j;
2016
      intg2-=i-j;
2017
      frac1=frac2=0; /* frac0 is already 0 here */
2018
    }
2019
    else
2020
    {
2021
      j-=frac0;
2022
      i=j >> 1;
2023
      frac1-= i;
2024
      frac2-=j-i;
2025
    }
2026
  }
2027
  start0=to->buf+intg0+frac0-1;
2028
  start2=buf2+frac2-1;
2029
  stop1=buf1-intg1;
2030
  stop2=buf2-intg2;
2031
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
2032
  memset(to->buf, 0, (intg0+frac0)*sizeof(dec1));
1 by brian
clean slate
2033
2034
  for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
2035
  {
2036
    carry=0;
2037
    for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
2038
    {
2039
      dec1 hi, lo;
2040
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2041
      hi=(dec1)(p/DIG_BASE);
2042
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2043
      ADD2(*buf0, *buf0, lo, carry);
2044
      carry+=hi;
2045
    }
2046
    if (carry)
2047
    {
2048
      if (buf0 < to->buf)
2049
        return E_DEC_OVERFLOW;
2050
      ADD2(*buf0, *buf0, 0, carry);
2051
    }
2052
    for (buf0--; carry; buf0--)
2053
    {
2054
      if (buf0 < to->buf)
2055
        return E_DEC_OVERFLOW;
2056
      ADD(*buf0, *buf0, 0, carry);
2057
    }
2058
  }
2059
2060
  /* Now we have to check for -0.000 case */
2061
  if (to->sign)
2062
  {
2063
    dec1 *buf= to->buf;
2064
    dec1 *end= to->buf + intg0 + frac0;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2065
    assert(buf != end);
1 by brian
clean slate
2066
    for (;;)
2067
    {
2068
      if (*buf)
2069
        break;
2070
      if (++buf == end)
2071
      {
2072
        /* We got decimal zero */
2073
        decimal_make_zero(to);
2074
        break;
2075
      }
2076
    }
2077
  }
2078
  buf1= to->buf;
2079
  d_to_move= intg0 + ROUND_UP(to->frac);
2080
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2081
  {
2082
    buf1++;
2083
    to->intg-= DIG_PER_DEC1;
2084
    d_to_move--;
2085
  }
2086
  if (to->buf < buf1)
2087
  {
2088
    dec1 *cur_d= to->buf;
2089
    for (; d_to_move--; cur_d++, buf1++)
2090
      *cur_d= *buf1;
2091
  }
2092
  return error;
2093
}
2094
2095
/*
2096
  naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2097
  it's ok for short numbers
2098
  also we're using alloca() to allocate a temporary buffer
2099
2100
  XXX if this library is to be used with huge numbers of thousands of
2101
  digits, fast division must be implemented and alloca should be
2102
  changed to malloc (or at least fallback to malloc if alloca() fails)
2103
  but then, decimal_mul() should be rewritten too :(
2104
*/
2105
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2106
                       decimal_t *to, decimal_t *mod, int scale_incr)
2107
{
2108
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2109
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2110
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2111
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2112
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2113
  dec2 norm_factor, x, guess, y;
2114
2115
  if (mod)
2116
    to=mod;
2117
2118
  sanity(to);
2119
2120
  /* removing all the leading zeroes */
2121
  i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
2122
  while (prec2 > 0 && *buf2 == 0)
2123
  {
2124
    prec2-= i;
2125
    i= DIG_PER_DEC1;
2126
    buf2++;
2127
  }
2128
  if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
2129
    return E_DEC_DIV_ZERO;
2130
  for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2131
  assert(prec2 > 0);
1 by brian
clean slate
2132
2133
  i=((prec1-1) % DIG_PER_DEC1)+1;
2134
  while (prec1 > 0 && *buf1 == 0)
2135
  {
2136
    prec1-=i;
2137
    i=DIG_PER_DEC1;
2138
    buf1++;
2139
  }
2140
  if (prec1 <= 0)
2141
  { /* short-circuit everything: from1 == 0 */
2142
    decimal_make_zero(to);
2143
    return E_DEC_OK;
2144
  }
2145
  for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2146
  assert(prec1 > 0);
1 by brian
clean slate
2147
2148
  /* let's fix scale_incr, taking into account frac1,frac2 increase */
2149
  if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
2150
    scale_incr=0;
2151
2152
  dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
2153
  if (dintg < 0)
2154
  {
2155
    dintg/=DIG_PER_DEC1;
2156
    intg0=0;
2157
  }
2158
  else
2159
    intg0=ROUND_UP(dintg);
2160
  if (mod)
2161
  {
2162
    /* we're calculating N1 % N2.
2163
       The result will have
398.1.4 by Monty Taylor
Renamed max/min.
2164
         frac=cmax(frac1, frac2), as for subtraction
1 by brian
clean slate
2165
         intg=intg2
2166
    */
2167
    to->sign=from1->sign;
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
2168
    to->frac=max(from1->frac, from2->frac);
1 by brian
clean slate
2169
    frac0=0;
2170
  }
2171
  else
2172
  {
2173
    /*
2174
      we're calculating N1/N2. N1 is in the buf1, has prec1 digits
2175
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2176
      frac2 accordingly.
2177
      Thus, the result will have
2178
         frac = ROUND_UP(frac1+frac2+scale_incr)
2179
      and
2180
         intg = (prec1-frac1) - (prec2-frac2) + 1
2181
         prec = intg+frac
2182
    */
2183
    frac0=ROUND_UP(frac1+frac2+scale_incr);
2184
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2185
    to->sign=from1->sign != from2->sign;
2186
    to->intg=intg0*DIG_PER_DEC1;
2187
    to->frac=frac0*DIG_PER_DEC1;
2188
  }
2189
  buf0=to->buf;
2190
  stop0=buf0+intg0+frac0;
2191
  if (likely(div_mod))
2192
    while (dintg++ < 0)
2193
      *buf0++=0;
2194
2195
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2196
  set_if_bigger(len1, 3);
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
2197
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
1 by brian
clean slate
2198
    return E_DEC_OOM;
2199
  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.
2200
  memset(tmp1+i, 0, (len1-i)*sizeof(dec1));
1 by brian
clean slate
2201
2202
  start1=tmp1;
2203
  stop1=start1+len1;
2204
  start2=buf2;
2205
  stop2=buf2+ROUND_UP(prec2)-1;
2206
2207
  /* removing end zeroes */
2208
  while (*stop2 == 0 && stop2 >= start2)
2209
    stop2--;
2210
  len2= (int) (stop2++ - start2);
2211
2212
  /*
2213
    calculating norm2 (normalized *start2) - we need *start2 to be large
2214
    (at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to
2215
    normalize input numbers (as we don't make a copy of the divisor).
2216
    Thus we normalize first dec1 of buf2 only, and we'll normalize *start1
2217
    on the fly for the purpose of guesstimation only.
2218
    It's also faster, as we're saving on normalization of buf2
2219
  */
2220
  norm_factor=DIG_BASE/(*start2+1);
2221
  norm2=(dec1)(norm_factor*start2[0]);
2222
  if (likely(len2>0))
2223
    norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
2224
2225
  if (*start1 < *start2)
2226
    dcarry=*start1++;
2227
  else
2228
    dcarry=0;
2229
2230
  /* main loop */
2231
  for (; buf0 < stop0; buf0++)
2232
  {
2233
    /* short-circuit, if possible */
2234
    if (unlikely(dcarry == 0 && *start1 < *start2))
2235
      guess=0;
2236
    else
2237
    {
2238
      /* D3: make a guess */
2239
      x=start1[0]+((dec2)dcarry)*DIG_BASE;
2240
      y=start1[1];
2241
      guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
2242
      if (unlikely(guess >= DIG_BASE))
2243
        guess=DIG_BASE-1;
2244
      if (likely(len2>0))
2245
      {
2246
        /* hmm, this is a suspicious trick - I removed normalization here */
2247
        if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
2248
          guess--;
2249
        if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
2250
          guess--;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2251
        assert(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
1 by brian
clean slate
2252
      }
2253
2254
      /* D4: multiply and subtract */
2255
      buf2=stop2;
2256
      buf1=start1+len2;
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2257
      assert(buf1 < stop1);
1 by brian
clean slate
2258
      for (carry=0; buf2 > start2; buf1--)
2259
      {
2260
        dec1 hi, lo;
2261
        x=guess * (*--buf2);
2262
        hi=(dec1)(x/DIG_BASE);
2263
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2264
        SUB2(*buf1, *buf1, lo, carry);
2265
        carry+=hi;
2266
      }
2267
      carry= dcarry < carry;
2268
2269
      /* D5: check the remainder */
2270
      if (unlikely(carry))
2271
      {
2272
        /* D6: correct the guess */
2273
        guess--;
2274
        buf2=stop2;
2275
        buf1=start1+len2;
2276
        for (carry=0; buf2 > start2; buf1--)
2277
        {
2278
          ADD(*buf1, *buf1, *--buf2, carry);
2279
        }
2280
      }
2281
    }
2282
    if (likely(div_mod))
2283
      *buf0=(dec1)guess;
2284
    dcarry= *start1;
2285
    start1++;
2286
  }
2287
  if (mod)
2288
  {
2289
    /*
2290
      now the result is in tmp1, it has
2291
        intg=prec1-frac1
398.1.4 by Monty Taylor
Renamed max/min.
2292
        frac=cmax(frac1, frac2)=to->frac
1 by brian
clean slate
2293
    */
2294
    if (dcarry)
2295
      *--start1=dcarry;
2296
    buf0=to->buf;
2297
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2298
    frac0=ROUND_UP(to->frac);
2299
    error=E_DEC_OK;
2300
    if (unlikely(frac0==0 && intg0==0))
2301
    {
2302
      decimal_make_zero(to);
2303
      goto done;
2304
    }
2305
    if (intg0<=0)
2306
    {
2307
      if (unlikely(-intg0 >= to->len))
2308
      {
2309
        decimal_make_zero(to);
2310
        error=E_DEC_TRUNCATED;
2311
        goto done;
2312
      }
2313
      stop1=start1+frac0;
2314
      frac0+=intg0;
2315
      to->intg=0;
2316
      while (intg0++ < 0)
2317
        *buf0++=0;
2318
    }
2319
    else
2320
    {
2321
      if (unlikely(intg0 > to->len))
2322
      {
2323
        frac0=0;
2324
        intg0=to->len;
2325
        error=E_DEC_OVERFLOW;
2326
        goto done;
2327
      }
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2328
      assert(intg0 <= ROUND_UP(from2->intg));
1 by brian
clean slate
2329
      stop1=start1+frac0+intg0;
1067.4.9 by Nathan Williams
Converted all usages of cmin/cmax in mystrings directory to use std::min/max
2330
      to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
1 by brian
clean slate
2331
    }
2332
    if (unlikely(intg0+frac0 > to->len))
2333
    {
2334
      stop1-=frac0+intg0-to->len;
2335
      frac0=to->len-intg0;
2336
      to->frac=frac0*DIG_PER_DEC1;
2337
        error=E_DEC_TRUNCATED;
2338
    }
51.3.9 by Jay Pipes
Removal of DBUG from strings/ library
2339
    assert(buf0 + (stop1 - start1) <= to->buf + to->len);
1 by brian
clean slate
2340
    while (start1 < stop1)
2341
        *buf0++=*start1++;
2342
  }
2343
done:
2344
  return error;
2345
}
2346
2347
/*
2348
  division of two decimals
2349
2350
  SYNOPSIS
2351
    decimal_div()
2352
      from1   - dividend
2353
      from2   - divisor
2354
      to      - quotient
2355
2356
  RETURN VALUE
2357
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2358
2359
  NOTES
2360
    see do_div_mod()
2361
*/
2362
2363
int
2364
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2365
{
2366
  return do_div_mod(from1, from2, to, 0, scale_incr);
2367
}
2368
2369
/*
2370
  modulus
2371
2372
  SYNOPSIS
2373
    decimal_mod()
2374
      from1   - dividend
2375
      from2   - divisor
2376
      to      - modulus
2377
2378
  RETURN VALUE
2379
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2380
2381
  NOTES
2382
    see do_div_mod()
2383
2384
  DESCRIPTION
2385
    the modulus R in    R = M mod N
2386
2387
   is defined as
2388
2389
     0 <= |R| < |M|
2390
     sign R == sign M
2391
     R = M - k*N, where k is integer
2392
2393
   thus, there's no requirement for M or N to be integers
2394
*/
2395
2396
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2397
{
2398
  return do_div_mod(from1, from2, 0, to, 0);
2399
}
2400
2401
#ifdef MAIN
2402
2403
int full= 0;
2404
decimal_t a, b, c;
2405
char buf1[100], buf2[100], buf3[100];
2406
2407
void dump_decimal(decimal_t *d)
2408
{
2409
  int i;
2410
  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2411
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2412
    printf("%09d, ", d->buf[i]);
2413
  printf("%09d} */ ", d->buf[i]);
2414
}
2415
2416
2417
void check_result_code(int actual, int want)
2418
{
2419
  if (actual != want)
2420
  {
2421
    printf("\n^^^^^^^^^^^^^ must return %d\n", want);
2422
    exit(1);
2423
  }
2424
}
2425
2426
2427
void print_decimal(decimal_t *d, const char *orig, int actual, int want)
2428
{
2429
  char s[100];
2430
  int slen=sizeof(s);
2431
2432
  if (full) dump_decimal(d);
2433
  decimal2string(d, s, &slen, 0, 0, 0);
2434
  printf("'%s'", s);
2435
  check_result_code(actual, want);
2436
  if (orig && strcmp(orig, s))
2437
  {
2438
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2439
    exit(1);
2440
  }
2441
}
2442
2443
void test_d2s()
2444
{
2445
  char s[100];
2446
  int slen, res;
2447
2448
  /***********************************/
2449
  printf("==== decimal2string ====\n");
2450
  a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
2451
  slen=sizeof(s);
2452
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2453
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2454
2455
  a.buf[1]=987000000; a.frac=3;
2456
  slen=sizeof(s);
2457
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2458
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2459
2460
  a.sign=1;
2461
  slen=sizeof(s);
2462
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2463
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2464
2465
  slen=8;
2466
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2467
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2468
2469
  slen=5;
2470
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2471
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2472
2473
  a.buf[0]=987000000; a.frac=3; a.intg=0;
2474
  slen=sizeof(s);
2475
  res=decimal2string(&a, s, &slen, 0, 0, 0);
2476
  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
2477
}
2478
2479
void test_s2d(const char *s, const char *orig, int ex)
2480
{
2481
  char s1[100], *end;
2482
  int res;
2483
  sprintf(s1, "'%s'", s);
2484
  end= strend(s);
2485
  printf("len=%2d %-30s => res=%d    ", a.len, s1,
2486
         (res= string2decimal(s, &a, &end)));
2487
  print_decimal(&a, orig, res, ex);
2488
  printf("\n");
2489
}
2490
2491
void test_d2f(const char *s, int ex)
2492
{
2493
  char s1[100], *end;
2494
  double x;
2495
  int res;
2496
2497
  sprintf(s1, "'%s'", s);
2498
  end= strend(s);
2499
  string2decimal(s, &a, &end);
2500
  res=decimal2double(&a, &x);
2501
  if (full) dump_decimal(&a);
2502
  printf("%-40s => res=%d    %.*g\n", s1, res, a.intg+a.frac, x);
2503
  check_result_code(res, ex);
2504
}
2505
2506
void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
2507
{
2508
  char s1[100], buf[100], *end;
2509
  int res, i, size=decimal_bin_size(p, s);
2510
2511
  sprintf(s1, "'%s'", str);
2512
  end= strend(str);
2513
  string2decimal(str, &a, &end);
2514
  res=decimal2bin(&a, buf, p, s);
2515
  printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
2516
  if (full)
2517
  {
2518
    printf("0x");
2519
    for (i=0; i < size; i++)
481 by Brian Aker
Remove all of uchar.
2520
      printf("%02x", ((unsigned char *)buf)[i]);
1 by brian
clean slate
2521
  }
2522
  res=bin2decimal(buf, &a, p, s);
2523
  printf(" => res=%d ", res);
2524
  print_decimal(&a, orig, res, ex);
2525
  printf("\n");
2526
}
2527
2528
void test_f2d(double from, int ex)
2529
{
2530
  int res;
2531
2532
  res=double2decimal(from, &a);
2533
  printf("%-40.*f => res=%d    ", DBL_DIG-2, from, res);
2534
  print_decimal(&a, 0, res, ex);
2535
  printf("\n");
2536
}
2537
151 by Brian Aker
Ulonglong to uint64_t
2538
void test_ull2d(uint64_t from, const char *orig, int ex)
1 by brian
clean slate
2539
{
2540
  char s[100];
2541
  int res;
2542
151 by Brian Aker
Ulonglong to uint64_t
2543
  res=uint64_t2decimal(from, &a);
152 by Brian Aker
longlong replacement
2544
  int64_t10_to_str(from,s,10);
1 by brian
clean slate
2545
  printf("%-40s => res=%d    ", s, res);
2546
  print_decimal(&a, orig, res, ex);
2547
  printf("\n");
2548
}
2549
152 by Brian Aker
longlong replacement
2550
void test_ll2d(int64_t from, const char *orig, int ex)
1 by brian
clean slate
2551
{
2552
  char s[100];
2553
  int res;
2554
152 by Brian Aker
longlong replacement
2555
  res=int64_t2decimal(from, &a);
2556
  int64_t10_to_str(from,s,-10);
1 by brian
clean slate
2557
  printf("%-40s => res=%d    ", s, res);
2558
  print_decimal(&a, orig, res, ex);
2559
  printf("\n");
2560
}
2561
2562
void test_d2ull(const char *s, const char *orig, int ex)
2563
{
2564
  char s1[100], *end;
151 by Brian Aker
Ulonglong to uint64_t
2565
  uint64_t x;
1 by brian
clean slate
2566
  int res;
2567
2568
  end= strend(s);
2569
  string2decimal(s, &a, &end);
151 by Brian Aker
Ulonglong to uint64_t
2570
  res=decimal2uint64_t(&a, &x);
1 by brian
clean slate
2571
  if (full) dump_decimal(&a);
152 by Brian Aker
longlong replacement
2572
  int64_t10_to_str(x,s1,10);
1 by brian
clean slate
2573
  printf("%-40s => res=%d    %s\n", s, res, s1);
2574
  check_result_code(res, ex);
2575
  if (orig && strcmp(orig, s1))
2576
  {
2577
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2578
    exit(1);
2579
  }
2580
}
2581
2582
void test_d2ll(const char *s, const char *orig, int ex)
2583
{
2584
  char s1[100], *end;
152 by Brian Aker
longlong replacement
2585
  int64_t x;
1 by brian
clean slate
2586
  int res;
2587
2588
  end= strend(s);
2589
  string2decimal(s, &a, &end);
152 by Brian Aker
longlong replacement
2590
  res=decimal2int64_t(&a, &x);
1 by brian
clean slate
2591
  if (full) dump_decimal(&a);
152 by Brian Aker
longlong replacement
2592
  int64_t10_to_str(x,s1,-10);
1 by brian
clean slate
2593
  printf("%-40s => res=%d    %s\n", s, res, s1);
2594
  check_result_code(res, ex);
2595
  if (orig && strcmp(orig, s1))
2596
  {
2597
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2598
    exit(1);
2599
  }
2600
}
2601
2602
void test_da(const char *s1, const char *s2, const char *orig, int ex)
2603
{
2604
  char s[100], *end;
2605
  int res;
2606
  sprintf(s, "'%s' + '%s'", s1, s2);
2607
  end= strend(s1);
2608
  string2decimal(s1, &a, &end);
2609
  end= strend(s2);
2610
  string2decimal(s2, &b, &end);
2611
  res=decimal_add(&a, &b, &c);
2612
  printf("%-40s => res=%d    ", s, res);
2613
  print_decimal(&c, orig, res, ex);
2614
  printf("\n");
2615
}
2616
2617
void test_ds(const char *s1, const char *s2, const char *orig, int ex)
2618
{
2619
  char s[100], *end;
2620
  int res;
2621
  sprintf(s, "'%s' - '%s'", s1, s2);
2622
  end= strend(s1);
2623
  string2decimal(s1, &a, &end);
2624
  end= strend(s2);
2625
  string2decimal(s2, &b, &end);
2626
  res=decimal_sub(&a, &b, &c);
2627
  printf("%-40s => res=%d    ", s, res);
2628
  print_decimal(&c, orig, res, ex);
2629
  printf("\n");
2630
}
2631
2632
void test_dc(const char *s1, const char *s2, int orig)
2633
{
2634
  char s[100], *end;
2635
  int res;
2636
  sprintf(s, "'%s' <=> '%s'", s1, s2);
2637
  end= strend(s1);
2638
  string2decimal(s1, &a, &end);
2639
  end= strend(s2);
2640
  string2decimal(s2, &b, &end);
2641
  res=decimal_cmp(&a, &b);
2642
  printf("%-40s => res=%d\n", s, res);
2643
  if (orig != res)
2644
  {
2645
    printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
2646
    exit(1);
2647
  }
2648
}
2649
2650
void test_dm(const char *s1, const char *s2, const char *orig, int ex)
2651
{
2652
  char s[100], *end;
2653
  int res;
2654
  sprintf(s, "'%s' * '%s'", s1, s2);
2655
  end= strend(s1);
2656
  string2decimal(s1, &a, &end);
2657
  end= strend(s2);
2658
  string2decimal(s2, &b, &end);
2659
  res=decimal_mul(&a, &b, &c);
2660
  printf("%-40s => res=%d    ", s, res);
2661
  print_decimal(&c, orig, res, ex);
2662
  printf("\n");
2663
}
2664
2665
void test_dv(const char *s1, const char *s2, const char *orig, int ex)
2666
{
2667
  char s[100], *end;
2668
  int res;
2669
  sprintf(s, "'%s' / '%s'", s1, s2);
2670
  end= strend(s1);
2671
  string2decimal(s1, &a, &end);
2672
  end= strend(s2);
2673
  string2decimal(s2, &b, &end);
2674
  res=decimal_div(&a, &b, &c, 5);
2675
  printf("%-40s => res=%d    ", s, res);
2676
  check_result_code(res, ex);
2677
  if (res == E_DEC_DIV_ZERO)
2678
    printf("E_DEC_DIV_ZERO");
2679
  else
2680
    print_decimal(&c, orig, res, ex);
2681
  printf("\n");
2682
}
2683
2684
void test_md(const char *s1, const char *s2, const char *orig, int ex)
2685
{
2686
  char s[100], *end;
2687
  int res;
2688
  sprintf(s, "'%s' %% '%s'", s1, s2);
2689
  end= strend(s1);
2690
  string2decimal(s1, &a, &end);
2691
  end= strend(s2);
2692
  string2decimal(s2, &b, &end);
2693
  res=decimal_mod(&a, &b, &c);
2694
  printf("%-40s => res=%d    ", s, res);
2695
  check_result_code(res, ex);
2696
  if (res == E_DEC_DIV_ZERO)
2697
    printf("E_DEC_DIV_ZERO");
2698
  else
2699
    print_decimal(&c, orig, res, ex);
2700
  printf("\n");
2701
}
2702
2703
const char *round_mode[]=
2704
{"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
2705
2706
void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
2707
             int ex)
2708
{
2709
  char s[100], *end;
2710
  int res;
2711
  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2712
  end= strend(s1);
2713
  string2decimal(s1, &a, &end);
2714
  res=decimal_round(&a, &b, n, mode);
2715
  printf("%-40s => res=%d    ", s, res);
2716
  print_decimal(&b, orig, res, ex);
2717
  printf("\n");
2718
}
2719
2720
2721
void test_mx(int precision, int frac, const char *orig)
2722
{
2723
  char s[100];
2724
  sprintf(s, "%d, %d", precision, frac);
2725
  max_decimal(precision, frac, &a);
2726
  printf("%-40s =>          ", s);
2727
  print_decimal(&a, orig, 0, 0);
2728
  printf("\n");
2729
}
2730
2731
2732
void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
2733
             int ex)
2734
{
2735
  char s[100], *end;
2736
  char s2[100];
2737
  int slen= sizeof(s2);
2738
  int res;
2739
2740
  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2741
          s1, prec, dec, filler);
2742
  end= strend(s1);
2743
  string2decimal(s1, &a, &end);
2744
  res= decimal2string(&a, s2, &slen, prec, dec, filler);
2745
  printf("%-40s => res=%d    '%s'", s, res, s2);
2746
  check_result_code(res, ex);
2747
  if (orig && strcmp(orig, s2))
2748
  {
2749
    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
2750
    exit(1);
2751
  }
2752
  printf("\n");
2753
}
2754
2755
2756
void test_sh(const char *s1, int shift, const char *orig, int ex)
2757
{
2758
  char s[100], *end;
2759
  int res;
2760
  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2761
  end= strend(s1);
2762
  string2decimal(s1, &a, &end);
2763
  res= decimal_shift(&a, shift);
2764
  printf("%-40s => res=%d    ", s, res);
2765
  print_decimal(&a, orig, res, ex);
2766
  printf("\n");
2767
}
2768
2769
2770
void test_fr(const char *s1, const char *orig)
2771
{
2772
  char s[100], *end;
2773
  sprintf(s, "'%s'", s1);
2774
  printf("%-40s =>          ", s);
2775
  end= strend(s1);
2776
  string2decimal(s1, &a, &end);
2777
  a.frac= decimal_actual_fraction(&a);
2778
  print_decimal(&a, orig, 0, 0);
2779
  printf("\n");
2780
}
2781
2782
2783
int main()
2784
{
2785
  a.buf=(void*)buf1;
2786
  a.len=sizeof(buf1)/sizeof(dec1);
2787
  b.buf=(void*)buf2;
2788
  b.len=sizeof(buf2)/sizeof(dec1);
2789
  c.buf=(void*)buf3;
2790
  c.len=sizeof(buf3)/sizeof(dec1);
2791
2792
  if (full)
2793
    test_d2s();
2794
2795
  printf("==== string2decimal ====\n");
2796
  test_s2d("12345", "12345", 0);
2797
  test_s2d("12345.", "12345", 0);
2798
  test_s2d("123.45", "123.45", 0);
2799
  test_s2d("-123.45", "-123.45", 0);
2800
  test_s2d(".00012345000098765", "0.00012345000098765", 0);
2801
  test_s2d(".12345000098765", "0.12345000098765", 0);
2802
  test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
2803
  test_s2d("1234500009876.5", "1234500009876.5", 0);
2804
  a.len=1;
2805
  test_s2d("123450000098765", "98765", 2);
2806
  test_s2d("123450.000098765", "123450", 1);
2807
  a.len=sizeof(buf1)/sizeof(dec1);
2808
  test_s2d("123E5", "12300000", 0);
2809
  test_s2d("123E-2", "1.23", 0);
2810
2811
  printf("==== decimal2double ====\n");
2812
  test_d2f("12345", 0);
2813
  test_d2f("123.45", 0);
2814
  test_d2f("-123.45", 0);
2815
  test_d2f("0.00012345000098765", 0);
2816
  test_d2f("1234500009876.5", 0);
2817
2818
  printf("==== double2decimal ====\n");
2819
  test_f2d(12345, 0);
2820
  test_f2d(1.0/3, 0);
2821
  test_f2d(-123.45, 0);
2822
  test_f2d(0.00012345000098765, 0);
2823
  test_f2d(1234500009876.5, 0);
2824
151 by Brian Aker
Ulonglong to uint64_t
2825
  printf("==== uint64_t2decimal ====\n");
80.1.1 by Brian Aker
LL() cleanup
2826
  test_ull2d(12345ULL, "12345", 0);
2827
  test_ull2d(0ULL, "0", 0);
2828
  test_ull2d(18446744073709551615ULL, "18446744073709551615", 0);
1 by brian
clean slate
2829
151 by Brian Aker
Ulonglong to uint64_t
2830
  printf("==== decimal2uint64_t ====\n");
1 by brian
clean slate
2831
  test_d2ull("12345", "12345", 0);
2832
  test_d2ull("0", "0", 0);
2833
  test_d2ull("18446744073709551615", "18446744073709551615", 0);
2834
  test_d2ull("18446744073709551616", "18446744073", 2);
2835
  test_d2ull("-1", "0", 2);
2836
  test_d2ull("1.23", "1", 1);
2837
  test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
2838
152 by Brian Aker
longlong replacement
2839
  printf("==== int64_t2decimal ====\n");
80.1.1 by Brian Aker
LL() cleanup
2840
  test_ll2d(12345LL, "-12345", 0);
2841
  test_ll2d(1LL, "-1", 0);
2842
  test_ll2d(9223372036854775807LL, "-9223372036854775807", 0);
2843
  test_ll2d(9223372036854775808ULL, "-9223372036854775808", 0);
1 by brian
clean slate
2844
152 by Brian Aker
longlong replacement
2845
  printf("==== decimal2int64_t ====\n");
1 by brian
clean slate
2846
  test_d2ll("18446744073709551615", "18446744073", 2);
2847
  test_d2ll("-1", "-1", 0);
2848
  test_d2ll("-1.23", "-1", 1);
2849
  test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
2850
  test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
2851
  test_d2ll("9223372036854775808", "9223372036854775807", 2);
2852
2853
  printf("==== do_add ====\n");
2854
  test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
2855
  test_da(".1" ,".45", "0.55", 0);
2856
  test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
2857
  test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
2858
  test_da("99999999" ,"1", "100000000", 0);
2859
  test_da("989999999" ,"1", "990000000", 0);
2860
  test_da("999999999" ,"1", "1000000000", 0);
2861
  test_da("12345" ,"123.45", "12468.45", 0);
2862
  test_da("-12345" ,"-123.45", "-12468.45", 0);
2863
  test_ds("-12345" ,"123.45", "-12468.45", 0);
2864
  test_ds("12345" ,"-123.45", "12468.45", 0);
2865
2866
  printf("==== do_sub ====\n");
2867
  test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
2868
  test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
2869
  test_ds("9999900000000.5", ".555","9999899999999.945", 0);
2870
  test_ds("1111.5551", "1111.555","0.0001", 0);
2871
  test_ds(".555", ".555","0", 0);
2872
  test_ds("10000000", "1","9999999", 0);
2873
  test_ds("1000001000", ".1","1000000999.9", 0);
2874
  test_ds("1000000000", ".1","999999999.9", 0);
2875
  test_ds("12345", "123.45","12221.55", 0);
2876
  test_ds("-12345", "-123.45","-12221.55", 0);
2877
  test_da("-12345", "123.45","-12221.55", 0);
2878
  test_da("12345", "-123.45","12221.55", 0);
2879
  test_ds("123.45", "12345","-12221.55", 0);
2880
  test_ds("-123.45", "-12345","12221.55", 0);
2881
  test_da("123.45", "-12345","-12221.55", 0);
2882
  test_da("-123.45", "12345","12221.55", 0);
2883
  test_da("5", "-6.0","-1.0", 0);
2884
2885
  printf("==== decimal_mul ====\n");
2886
  test_dm("12", "10","120", 0);
2887
  test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
2888
  test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
2889
  test_dm("123456", "987654321","121931851853376", 0);
2890
  test_dm("123456", "9876543210","1219318518533760", 0);
2891
  test_dm("123", "0.01","1.23", 0);
2892
  test_dm("123", "0","0", 0);
2893
2894
  printf("==== decimal_div ====\n");
2895
  test_dv("120", "10","12.000000000", 0);
2896
  test_dv("123", "0.01","12300.000000000", 0);
2897
  test_dv("120", "100000000000.00000","0.000000001200000000", 0);
2898
  test_dv("123", "0","", 4);
2899
  test_dv("0", "0", "", 4);
2900
  test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
2901
  test_dv("121931851853376", "987654321","123456.000000000", 0);
2902
  test_dv("0", "987","0", 0);
2903
  test_dv("1", "3","0.333333333", 0);
2904
  test_dv("1.000000000000", "3","0.333333333333333333", 0);
2905
  test_dv("1", "1","1.000000000", 0);
2906
  test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
2907
  test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
2908
  test_dv("10.000000000060", "2","5.000000000030000000", 0);
2909
2910
  printf("==== decimal_mod ====\n");
2911
  test_md("234","10","4", 0);
2912
  test_md("234.567","10.555","2.357", 0);
2913
  test_md("-234.567","10.555","-2.357", 0);
2914
  test_md("234.567","-10.555","2.357", 0);
2915
  c.buf[1]=0x3ABECA;
2916
  test_md("99999999999999999999999999999999999999","3","0", 0);
2917
  if (c.buf[1] != 0x3ABECA)
2918
  {
2919
    printf("%X - overflow\n", c.buf[1]);
2920
    exit(1);
2921
  }
2922
2923
  printf("==== decimal2bin/bin2decimal ====\n");
2924
  test_d2b2d("-10.55", 4, 2,"-10.55", 0);
2925
  test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
2926
  test_d2b2d("12345", 5, 0,"12345", 0);
2927
  test_d2b2d("12345", 10, 3,"12345.000", 0);
2928
  test_d2b2d("123.45", 10, 3,"123.450", 0);
2929
  test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
2930
  test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
2931
  test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
2932
  test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
2933
  test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
2934
  test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
2935
  test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
2936
  test_d2b2d("000000000.01", 7, 3,"0.010", 0);
2937
  test_d2b2d("123.4", 10, 2, "123.40", 0);
2938
2939
2940
  printf("==== decimal_cmp ====\n");
2941
  test_dc("12","13",-1);
2942
  test_dc("13","12",1);
2943
  test_dc("-10","10",-1);
2944
  test_dc("10","-10",1);
2945
  test_dc("-12","-13",1);
2946
  test_dc("0","12",-1);
2947
  test_dc("-10","0",-1);
2948
  test_dc("4","4",0);
2949
2950
  printf("==== decimal_round ====\n");
2951
  test_ro("5678.123451",-4,TRUNCATE,"0", 0);
2952
  test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
2953
  test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
2954
  test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
2955
  test_ro("5678.123451",0,TRUNCATE,"5678", 0);
2956
  test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
2957
  test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
2958
  test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
2959
  test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
2960
  test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
2961
  test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
2962
  test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
2963
  memset(buf2, 33, sizeof(buf2));
2964
  test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
2965
  test_ro("15.1",0,HALF_UP,"15", 0);
2966
  test_ro("15.5",0,HALF_UP,"16", 0);
2967
  test_ro("15.9",0,HALF_UP,"16", 0);
2968
  test_ro("-15.1",0,HALF_UP,"-15", 0);
2969
  test_ro("-15.5",0,HALF_UP,"-16", 0);
2970
  test_ro("-15.9",0,HALF_UP,"-16", 0);
2971
  test_ro("15.1",1,HALF_UP,"15.1", 0);
2972
  test_ro("-15.1",1,HALF_UP,"-15.1", 0);
2973
  test_ro("15.17",1,HALF_UP,"15.2", 0);
2974
  test_ro("15.4",-1,HALF_UP,"20", 0);
2975
  test_ro("-15.4",-1,HALF_UP,"-20", 0);
2976
  test_ro("5.4",-1,HALF_UP,"10", 0);
2977
  test_ro(".999", 0, HALF_UP, "1", 0);
2978
  memset(buf2, 33, sizeof(buf2));
2979
  test_ro("999999999", -9, HALF_UP, "1000000000", 0);
2980
  test_ro("15.1",0,HALF_EVEN,"15", 0);
2981
  test_ro("15.5",0,HALF_EVEN,"16", 0);
2982
  test_ro("14.5",0,HALF_EVEN,"14", 0);
2983
  test_ro("15.9",0,HALF_EVEN,"16", 0);
2984
  test_ro("15.1",0,CEILING,"16", 0);
2985
  test_ro("-15.1",0,CEILING,"-15", 0);
2986
  test_ro("15.1",0,FLOOR,"15", 0);
2987
  test_ro("-15.1",0,FLOOR,"-16", 0);
2988
  test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
2989
  test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
2990
2991
  b.buf[0]=DIG_BASE+1;
2992
  b.buf++;
2993
  test_ro(".3", 0, HALF_UP, "0", 0);
2994
  b.buf--;
2995
  if (b.buf[0] != DIG_BASE+1)
2996
  {
2997
    printf("%d - underflow\n", b.buf[0]);
2998
    exit(1);
2999
  }
3000
3001
  printf("==== max_decimal ====\n");
3002
  test_mx(1,1,"0.9");
3003
  test_mx(1,0,"9");
3004
  test_mx(2,1,"9.9");
3005
  test_mx(4,2,"99.99");
3006
  test_mx(6,3,"999.999");
3007
  test_mx(8,4,"9999.9999");
3008
  test_mx(10,5,"99999.99999");
3009
  test_mx(12,6,"999999.999999");
3010
  test_mx(14,7,"9999999.9999999");
3011
  test_mx(16,8,"99999999.99999999");
3012
  test_mx(18,9,"999999999.999999999");
3013
  test_mx(20,10,"9999999999.9999999999");
3014
  test_mx(20,20,"0.99999999999999999999");
3015
  test_mx(20,0,"99999999999999999999");
3016
  test_mx(40,20,"99999999999999999999.99999999999999999999");
3017
3018
  printf("==== decimal2string ====\n");
3019
  test_pr("123.123", 0, 0, 0, "123.123", 0);
3020
  test_pr("123.123", 7, 3, '0', "123.123", 0);
3021
  test_pr("123.123", 9, 3, '0', "00123.123", 0);
3022
  test_pr("123.123", 9, 4, '0', "0123.1230", 0);
3023
  test_pr("123.123", 9, 5, '0', "123.12300", 0);
3024
  test_pr("123.123", 9, 2, '0', "000123.12", 1);
3025
  test_pr("123.123", 9, 6, '0', "23.123000", 2);
3026
3027
  printf("==== decimal_shift ====\n");
3028
  test_sh("123.123", 1, "1231.23", 0);
3029
  test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
3030
  test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
3031
  test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
3032
  test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
3033
  test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
3034
  test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
3035
  test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
3036
  test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
3037
  test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3038
  test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3039
  test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3040
  test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
3041
  test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
3042
  test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
3043
  test_sh("123", 1, "1230", 0);
3044
  test_sh("123", 10, "1230000000000", 0);
3045
  test_sh(".123", 1, "1.23", 0);
3046
  test_sh(".123", 10, "1230000000", 0);
3047
  test_sh(".123", 14, "12300000000000", 0);
3048
  test_sh("000.000", 1000, "0", 0);
3049
  test_sh("000.", 1000, "0", 0);
3050
  test_sh(".000", 1000, "0", 0);
3051
  test_sh("1", 1000, "1", 2);
3052
  test_sh("123.123", -1, "12.3123", 0);
3053
  test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
3054
  test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
3055
  test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
3056
  test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
3057
  test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
3058
  test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
3059
  test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
3060
  test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
3061
  test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
3062
  test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
3063
  test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
3064
  a.len= 2;
3065
  test_sh("123.123", -2, "1.23123", 0);
3066
  test_sh("123.123", -3, "0.123123", 0);
3067
  test_sh("123.123", -6, "0.000123123", 0);
3068
  test_sh("123.123", -7, "0.0000123123", 0);
3069
  test_sh("123.123", -15, "0.000000000000123123", 0);
3070
  test_sh("123.123", -16, "0.000000000000012312", 1);
3071
  test_sh("123.123", -17, "0.000000000000001231", 1);
3072
  test_sh("123.123", -18, "0.000000000000000123", 1);
3073
  test_sh("123.123", -19, "0.000000000000000012", 1);
3074
  test_sh("123.123", -20, "0.000000000000000001", 1);
3075
  test_sh("123.123", -21, "0", 1);
3076
  test_sh(".000000000123", -1, "0.0000000000123", 0);
3077
  test_sh(".000000000123", -6, "0.000000000000000123", 0);
3078
  test_sh(".000000000123", -7, "0.000000000000000012", 1);
3079
  test_sh(".000000000123", -8, "0.000000000000000001", 1);
3080
  test_sh(".000000000123", -9, "0", 1);
3081
  test_sh(".000000000123", 1, "0.00000000123", 0);
3082
  test_sh(".000000000123", 8, "0.0123", 0);
3083
  test_sh(".000000000123", 9, "0.123", 0);
3084
  test_sh(".000000000123", 10, "1.23", 0);
3085
  test_sh(".000000000123", 17, "12300000", 0);
3086
  test_sh(".000000000123", 18, "123000000", 0);
3087
  test_sh(".000000000123", 19, "1230000000", 0);
3088
  test_sh(".000000000123", 20, "12300000000", 0);
3089
  test_sh(".000000000123", 21, "123000000000", 0);
3090
  test_sh(".000000000123", 22, "1230000000000", 0);
3091
  test_sh(".000000000123", 23, "12300000000000", 0);
3092
  test_sh(".000000000123", 24, "123000000000000", 0);
3093
  test_sh(".000000000123", 25, "1230000000000000", 0);
3094
  test_sh(".000000000123", 26, "12300000000000000", 0);
3095
  test_sh(".000000000123", 27, "123000000000000000", 0);
3096
  test_sh(".000000000123", 28, "0.000000000123", 2);
3097
  test_sh("123456789.987654321", -1, "12345678.998765432", 1);
3098
  test_sh("123456789.987654321", -2, "1234567.899876543", 1);
3099
  test_sh("123456789.987654321", -8, "1.234567900", 1);
3100
  test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
3101
  test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
3102
  test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
3103
  test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
3104
  test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
3105
  test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
3106
  test_sh("123456789.987654321", -27, "0", 1);
3107
  test_sh("123456789.987654321", 1, "1234567900", 1);
3108
  test_sh("123456789.987654321", 2, "12345678999", 1);
3109
  test_sh("123456789.987654321", 4, "1234567899877", 1);
3110
  test_sh("123456789.987654321", 8, "12345678998765432", 1);
3111
  test_sh("123456789.987654321", 9, "123456789987654321", 0);
3112
  test_sh("123456789.987654321", 10, "123456789.987654321", 2);
3113
  test_sh("123456789.987654321", 0, "123456789.987654321", 0);
3114
  a.len= sizeof(buf1)/sizeof(dec1);
3115
3116
  printf("==== decimal_actual_fraction ====\n");
3117
  test_fr("1.123456789000000000", "1.123456789");
3118
  test_fr("1.12345678000000000", "1.12345678");
3119
  test_fr("1.1234567000000000", "1.1234567");
3120
  test_fr("1.123456000000000", "1.123456");
3121
  test_fr("1.12345000000000", "1.12345");
3122
  test_fr("1.1234000000000", "1.1234");
3123
  test_fr("1.123000000000", "1.123");
3124
  test_fr("1.12000000000", "1.12");
3125
  test_fr("1.1000000000", "1.1");
3126
  test_fr("1.000000000", "1");
3127
  test_fr("1.0", "1");
3128
  test_fr("10000000000000000000.0", "10000000000000000000");
3129
3130
  return 0;
3131
}
3132
#endif