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