~drizzle-trunk/drizzle/development

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