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