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