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