~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to strings/decimal.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

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