~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/decimal.cc

  • Committer: Stewart Smith
  • Date: 2010-11-03 03:30:27 UTC
  • mto: (1902.1.1 build) (1910.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1903.
  • Revision ID: stewart@flamingspork.com-20101103033027-lskb6gxwwforfz71
fix docs warning: underline/overline too short for replace.rst

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
15
 
 
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
 */
15
25
 
16
26
/*
17
27
=======================================================================
18
 
  NOTE: this library implements SQL standard "exact numeric" type
19
 
  and is not at all generic, but rather intentinally crippled to
20
 
  follow the standard :)
21
 
=======================================================================
22
28
  Quoting the standard
23
29
  (SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
24
30
 
97
103
      implementation-defined.
98
104
*/
99
105
 
100
 
#include <config.h>
 
106
#include "config.h"
 
107
 
 
108
#include "drizzled/definitions.h"
 
109
#include "drizzled/internal/m_string.h"
 
110
#include "drizzled/charset_info.h"
 
111
#include "drizzled/decimal.h"
 
112
 
 
113
#include <plugin/myisam/myisampack.h>
 
114
#include <drizzled/util/test.h>
 
115
 
 
116
#ifdef HAVE_ALLOCA_H
101
117
#include <alloca.h>
102
 
#include <m_string.h>
103
 
#include <m_ctype.h>
104
 
#include <storage/myisam/myisampack.h>
105
 
#include <mystrings/decimal.h>
106
 
 
107
 
#include <drizzled/util/test.h>
 
118
#endif
 
119
 
 
120
#include <algorithm>
 
121
#include <time.h>
 
122
#include "drizzled/current_session.h"
 
123
#include "drizzled/error.h"
 
124
#include "drizzled/field.h"
 
125
#include "drizzled/internal/my_sys.h"
 
126
 
 
127
using namespace std;
 
128
 
 
129
namespace drizzled
 
130
{
 
131
/**
 
132
  report result of decimal operation.
 
133
 
 
134
  @param result  decimal library return code (E_DEC_* see include/decimal.h)
 
135
 
 
136
  @todo
 
137
    Fix error messages
 
138
 
 
139
  @return
 
140
    result
 
141
*/
 
142
 
 
143
int decimal_operation_results(int result)
 
144
{
 
145
  switch (result) {
 
146
  case E_DEC_OK:
 
147
    break;
 
148
  case E_DEC_TRUNCATED:
 
149
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
150
                        ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
 
151
                        "", (long)-1);
 
152
    break;
 
153
  case E_DEC_OVERFLOW:
 
154
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
155
                        ER_TRUNCATED_WRONG_VALUE,
 
156
                        ER(ER_TRUNCATED_WRONG_VALUE),
 
157
                        "DECIMAL", "");
 
158
    break;
 
159
  case E_DEC_DIV_ZERO:
 
160
    my_error(ER_DIVISION_BY_ZERO, MYF(0));
 
161
    break;
 
162
  case E_DEC_BAD_NUM:
 
163
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
164
                        ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
 
165
                        ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
 
166
                        "decimal", "", "", (long)-1);
 
167
    break;
 
168
  case E_DEC_OOM:
 
169
    my_error(ER_OUT_OF_RESOURCES, MYF(0));
 
170
    break;
 
171
  default:
 
172
    assert(0);
 
173
  }
 
174
  return result;
 
175
}
 
176
 
 
177
 
 
178
/**
 
179
  @brief Converting decimal to string
 
180
 
 
181
  @details Convert given my_decimal to String; allocate buffer as needed.
 
182
 
 
183
  @param[in]   mask        what problems to warn on (mask of E_DEC_* values)
 
184
  @param[in]   d           the decimal to print
 
185
  @param[in]   fixed_prec  overall number of digits if ZEROFILL, 0 otherwise
 
186
  @param[in]   fixed_dec   number of decimal places (if fixed_prec != 0)
 
187
  @param[in]   filler      what char to pad with (ZEROFILL et al.)
 
188
  @param[out]  *str        where to store the resulting string
 
189
 
 
190
  @return error code
 
191
    @retval E_DEC_OK
 
192
    @retval E_DEC_TRUNCATED
 
193
    @retval E_DEC_OVERFLOW
 
194
    @retval E_DEC_OOM
 
195
*/
 
196
 
 
197
int my_decimal2string(uint32_t mask, const my_decimal *d,
 
198
                      uint32_t fixed_prec, uint32_t fixed_dec,
 
199
                      char filler, String *str)
 
200
{
 
201
  /*
 
202
    Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
 
203
    holds true iff the type is also ZEROFILL, which in turn implies
 
204
    UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
 
205
    the user requested, plus one for a possible decimal point, plus
 
206
    one if the user only wanted decimal places, but we force a leading
 
207
    zero on them. Because the type is implicitly UNSIGNED, we do not
 
208
    need to reserve a character for the sign. For all other cases,
 
209
    fixed_prec will be 0, and my_decimal_string_length() will be called
 
210
    instead to calculate the required size of the buffer.
 
211
  */
 
212
  int length= (int)(fixed_prec
 
213
                    ? (uint32_t)(fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
 
214
                    : (uint32_t)my_decimal_string_length(d));
 
215
  int result;
 
216
  if (str->alloc(length))
 
217
    return check_result(mask, E_DEC_OOM);
 
218
  result= decimal2string((decimal_t*) d, (char*) str->ptr(),
 
219
                         &length, (int)fixed_prec, fixed_dec,
 
220
                         filler);
 
221
  str->length(length);
 
222
  return check_result(mask, result);
 
223
}
 
224
 
 
225
 
 
226
/**
 
227
  @brief  Convert from decimal to binary representation
 
228
 
 
229
  @param[in]   mask        error processing mask
 
230
  @param[in]   d           number for conversion
 
231
  @param[out]  bin         pointer to buffer where to write result
 
232
  @param[in]   prec        overall number of decimal digits
 
233
  @param[in]   scale       number of decimal digits after decimal point
 
234
 
 
235
  @note
 
236
    Before conversion we round number if it need but produce truncation
 
237
    error in this case
 
238
 
 
239
  @return error code
 
240
   @retval E_DEC_OK
 
241
   @retval E_DEC_TRUNCATED
 
242
   @retval E_DEC_OVERFLOW
 
243
*/
 
244
 
 
245
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
 
246
                      int scale)
 
247
{
 
248
  int err1= E_DEC_OK, err2;
 
249
  my_decimal rounded;
 
250
  my_decimal2decimal(d, &rounded);
 
251
  rounded.frac= decimal_actual_fraction(&rounded);
 
252
  if (scale < rounded.frac)
 
253
  {
 
254
    err1= E_DEC_TRUNCATED;
 
255
    /* decimal_round can return only E_DEC_TRUNCATED */
 
256
    decimal_round(&rounded, &rounded, scale, HALF_UP);
 
257
  }
 
258
  err2= decimal2bin(&rounded, bin, prec, scale);
 
259
  if (!err2)
 
260
    err2= err1;
 
261
  return check_result(mask, err2);
 
262
}
 
263
 
 
264
 
 
265
/**
 
266
  @brief Convert string for decimal when string can be in some multibyte charset
 
267
 
 
268
  @param  mask            error processing mask
 
269
  @param  from            string to process
 
270
  @param  length          length of given string
 
271
  @param  charset         charset of given string
 
272
  @param  decimal_value   buffer for result storing
 
273
 
 
274
  @return Error code
 
275
   @retval E_DEC_OK
 
276
   @retval E_DEC_TRUNCATED
 
277
   @retval E_DEC_OVERFLOW
 
278
   @retval E_DEC_BAD_NUM
 
279
   @retval E_DEC_OOM
 
280
*/
 
281
 
 
282
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
 
283
                   const CHARSET_INFO * charset, my_decimal *decimal_value)
 
284
{
 
285
  char *end, *from_end;
 
286
  int err;
 
287
  char buff[STRING_BUFFER_USUAL_SIZE];
 
288
  String tmp(buff, sizeof(buff), &my_charset_bin);
 
289
  if (charset->mbminlen > 1)
 
290
  {
 
291
    size_t dummy_errors;
 
292
    tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
 
293
    from= tmp.ptr();
 
294
    length=  tmp.length();
 
295
    charset= &my_charset_bin;
 
296
  }
 
297
  from_end= end= (char*) from+length;
 
298
  err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
 
299
  if (end != from_end && !err)
 
300
  {
 
301
    /* Give warning if there is something other than end space */
 
302
    for ( ; end < from_end; end++)
 
303
    {
 
304
      if (!my_isspace(&my_charset_utf8_general_ci, *end))
 
305
      {
 
306
        err= E_DEC_TRUNCATED;
 
307
        break;
 
308
      }
 
309
    }
 
310
  }
 
311
  check_result_and_overflow(mask, err, decimal_value);
 
312
  return err;
 
313
}
 
314
 
 
315
 
 
316
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
 
317
{
 
318
  int64_t date;
 
319
  date = (ltime->year*100L + ltime->month)*100L + ltime->day;
 
320
  if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
 
321
    date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
 
322
  if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
 
323
    return dec;
 
324
  if (ltime->second_part)
 
325
  {
 
326
    dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
 
327
    dec->frac= 6;
 
328
  }
 
329
  return dec;
 
330
}
 
331
 
 
332
 
 
333
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
 
334
{
 
335
  if (!(*precision) && !(*scale))
 
336
  {
 
337
    *precision= 10;
 
338
    *scale= 0;
 
339
    return;
 
340
  }
 
341
}
 
342
 
 
343
 
108
344
/*
109
345
  Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
110
346
  So one variable of type decimal_digit_t is limited:
127
363
#define DIG_MASK     100000000
128
364
#define DIG_BASE     1000000000
129
365
#define DIG_MAX      (DIG_BASE-1)
130
 
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
 
366
 
 
367
template<typename T> 
 
368
inline static T round_up(const T &x)
 
369
{
 
370
  return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
 
371
}
 
372
 
131
373
static const dec1 powers10[DIG_PER_DEC1+1]={
132
374
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
133
375
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
136
378
  999900000, 999990000, 999999000,
137
379
  999999900, 999999990 };
138
380
 
139
 
#ifdef HAVE_purify
 
381
#ifdef HAVE_VALGRIND
140
382
#define sanity(d) assert((d)->len > 0)
141
383
#else
142
384
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
143
385
                              (d)->buf[(d)->len-1] | 1))
144
386
#endif
145
387
 
146
 
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error)                   \
147
 
        do                                                              \
148
 
        {                                                               \
149
 
          if (unlikely(intg1+frac1 > (len)))                            \
150
 
          {                                                             \
151
 
            if (unlikely(intg1 > (len)))                                \
152
 
            {                                                           \
153
 
              intg1=(len);                                              \
154
 
              frac1=0;                                                  \
155
 
              error=E_DEC_OVERFLOW;                                     \
156
 
            }                                                           \
157
 
            else                                                        \
158
 
            {                                                           \
159
 
              frac1=(len)-intg1;                                        \
160
 
              error=E_DEC_TRUNCATED;                                    \
161
 
            }                                                           \
162
 
          }                                                             \
163
 
          else                                                          \
164
 
            error=E_DEC_OK;                                             \
165
 
        } while(0)
166
 
 
167
 
#define ADD(to, from1, from2, carry)  /* assume carry <= 1 */           \
168
 
        do                                                              \
169
 
        {                                                               \
170
 
          dec1 a=(from1)+(from2)+(carry);                               \
171
 
          assert((carry) <= 1);                                    \
172
 
          if (((carry)= a >= DIG_BASE)) /* no division here! */         \
173
 
            a-=DIG_BASE;                                                \
174
 
          (to)=a;                                                       \
175
 
        } while(0)
176
 
 
177
 
#define ADD2(to, from1, from2, carry)                                   \
178
 
        do                                                              \
179
 
        {                                                               \
180
 
          dec2 a=((dec2)(from1))+(from2)+(carry);                       \
181
 
          if (((carry)= a >= DIG_BASE))                                 \
182
 
            a-=DIG_BASE;                                                \
183
 
          if (unlikely(a >= DIG_BASE))                                  \
184
 
          {                                                             \
185
 
            a-=DIG_BASE;                                                \
186
 
            carry++;                                                    \
187
 
          }                                                             \
188
 
          (to)=(dec1) a;                                                \
189
 
        } while(0)
190
 
 
191
 
#define SUB(to, from1, from2, carry) /* to=from1-from2 */               \
192
 
        do                                                              \
193
 
        {                                                               \
194
 
          dec1 a=(from1)-(from2)-(carry);                               \
195
 
          if (((carry)= a < 0))                                         \
196
 
            a+=DIG_BASE;                                                \
197
 
          (to)=a;                                                       \
198
 
        } while(0)
199
 
 
200
 
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */              \
201
 
        do                                                              \
202
 
        {                                                               \
203
 
          dec1 a=(from1)-(from2)-(carry);                               \
204
 
          if (((carry)= a < 0))                                         \
205
 
            a+=DIG_BASE;                                                \
206
 
          if (unlikely(a < 0))                                          \
207
 
          {                                                             \
208
 
            a+=DIG_BASE;                                                \
209
 
            carry++;                                                    \
210
 
          }                                                             \
211
 
          (to)=a;                                                       \
212
 
        } while(0)
 
388
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
 
389
{
 
390
  if (unlikely(intg1+frac1 > len))
 
391
  {
 
392
    if (unlikely(intg1 > len))
 
393
    {
 
394
      intg1=(len);
 
395
      frac1=0;
 
396
      error=E_DEC_OVERFLOW;
 
397
    }
 
398
    else
 
399
    {
 
400
      frac1=(len)-intg1;
 
401
      error=E_DEC_TRUNCATED;
 
402
    }
 
403
  }
 
404
  else
 
405
    error=E_DEC_OK;
 
406
}
 
407
 
 
408
/* assume carry <= 1 */
 
409
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
 
410
{
 
411
  dec1 a=from1+from2+carry;
 
412
  assert(carry <= 1);
 
413
  if ((carry= (a >= DIG_BASE))) /* no division here! */
 
414
    a-=DIG_BASE;
 
415
  to=a;
 
416
}
 
417
 
 
418
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
 
419
{
 
420
  dec2 a=dec2(from1)+from2+carry;
 
421
  if ((carry= (a >= DIG_BASE)))
 
422
    a-=DIG_BASE;
 
423
  if (unlikely(a >= DIG_BASE))
 
424
  {
 
425
    a-=DIG_BASE;
 
426
    carry++;
 
427
  }
 
428
  to=dec1(a);
 
429
}
 
430
 
 
431
/* to=from1-from2 */
 
432
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
 
433
{
 
434
  dec1 a=from1-from2-carry;
 
435
  if ((carry= (a < 0)))
 
436
    a+=DIG_BASE;
 
437
  to=a;
 
438
}
 
439
 
 
440
/* to=from1-from2 */
 
441
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
 
442
{
 
443
  dec1 a=from1-from2-carry;
 
444
  if ((carry= (a < 0)))
 
445
    a+=DIG_BASE;
 
446
  if (unlikely(a < 0))
 
447
  {
 
448
    a+=DIG_BASE;
 
449
    carry++;
 
450
  }
 
451
  to=a;
 
452
}
213
453
 
214
454
/**
215
 
  Swap the contents of two variables.
216
 
 */
217
 
#define swap_variables(TYPE, a, b) \
218
 
  do {                             \
219
 
    TYPE dummy;                    \
220
 
    dummy= a;                      \
221
 
    a= b;                          \
222
 
    b= dummy;                      \
223
 
  } while (0)
224
 
 
225
 
 
226
 
/*
227
 
  Get maximum value for given precision and scale
228
 
 
229
 
  SYNOPSIS
230
 
    max_decimal()
231
 
    precision/scale - see decimal_bin_size() below
232
 
    to              - decimal where where the result will be stored
 
455
  @brief  Get maximum value for given precision and scale
 
456
 
 
457
  @param  precision/scale  see decimal_bin_size() below
 
458
  @param  to              decimal where where the result will be stored
233
459
                      to->buf and to->len must be set.
234
460
*/
235
461
 
260
486
}
261
487
 
262
488
 
263
 
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
 
489
static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
264
490
{
265
491
  int intg= from->intg, i;
266
492
  dec1 *buf0= from->buf;
283
509
}
284
510
 
285
511
 
286
 
/*
287
 
  Count actual length of fraction part (without ending zeroes)
 
512
/**
 
513
 @brief Count actual length of fraction part (without ending zeroes)
288
514
 
289
 
  SYNOPSIS
290
 
    decimal_actual_fraction()
291
 
    from    number for processing
 
515
 @param from    number for processing
292
516
*/
293
517
 
294
518
int decimal_actual_fraction(decimal_t *from)
295
519
{
296
520
  int frac= from->frac, i;
297
 
  dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
 
521
  dec1 *buf0= from->buf + round_up(from->intg) + round_up(frac) - 1;
298
522
 
299
523
  if (frac == 0)
300
524
    return 0;
314
538
}
315
539
 
316
540
 
317
 
/*
318
 
  Convert decimal to its printable string representation
 
541
/**
 
542
 @brief  Convert decimal to its printable string representation
319
543
 
320
 
  SYNOPSIS
321
 
    decimal2string()
322
 
      from            - value to convert
323
 
      to              - points to buffer where string representation
324
 
                        should be stored
325
 
      *to_len         - in:  size of to buffer
326
 
                        out: length of the actually written string
327
 
      fixed_precision - 0 if representation can be variable length and
 
544
 @param  from       value to convert
 
545
 @param  to         points to buffer where string representation
 
546
                    should be stored
 
547
 @param  to_len     in:  size of to buffer
 
548
                    out: length of the actually written string
 
549
 @param  fixed_precision 0 if representation can be variable length and
328
550
                        fixed_decimals will not be checked in this case.
329
551
                        Put number as with fixed point position with this
330
552
                        number of digits (sign counted and decimal point is
331
553
                        counted)
332
 
      fixed_decimals  - number digits after point.
333
 
      filler          - character to fill gaps in case of fixed_precision > 0
 
554
 @param  fixed_decimals  number digits after point.
 
555
 @param  filler          character to fill gaps in case of fixed_precision > 0
334
556
 
335
 
  RETURN VALUE
336
 
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
 
557
 @return error code
 
558
   @retval E_DEC_OK
 
559
   @retval E_DEC_TRUNCATED
 
560
   @retval E_DEC_OVERFLOW
337
561
*/
338
 
 
339
 
int decimal2string(decimal_t *from, char *to, int *to_len,
 
562
int decimal2string(const decimal_t *from, char *to, int *to_len,
340
563
                   int fixed_precision, int fixed_decimals,
341
564
                   char filler)
342
565
{
400
623
  {
401
624
    char *s1= s + intg_len;
402
625
    fill= frac_len - frac;
403
 
    buf=buf0+ROUND_UP(intg);
 
626
    buf=buf0+round_up(intg);
404
627
    *s1++='.';
405
628
    for (; frac>0; frac-=DIG_PER_DEC1)
406
629
    {
407
630
      dec1 x=*buf++;
408
 
      for (i=cmin(frac, DIG_PER_DEC1); i; i--)
 
631
      for (i=min(frac, DIG_PER_DEC1); i; i--)
409
632
      {
410
633
        dec1 y=x/DIG_MASK;
411
634
        *s1++='0'+(unsigned char)y;
425
648
  if (intg)
426
649
  {
427
650
    s+=intg;
428
 
    for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
 
651
    for (buf=buf0+round_up(intg); intg>0; intg-=DIG_PER_DEC1)
429
652
    {
430
653
      dec1 x=*--buf;
431
 
      for (i=cmin(intg, DIG_PER_DEC1); i; i--)
 
654
      for (i=min(intg, DIG_PER_DEC1); i; i--)
432
655
      {
433
656
        dec1 y=x/10;
434
657
        *--s='0'+(unsigned char)(x-y*10);
442
665
}
443
666
 
444
667
 
445
 
/*
446
 
  Return bounds of decimal digits in the number
 
668
/**
 
669
 @brief  Return bounds of decimal digits in the number
447
670
 
448
 
  SYNOPSIS
449
 
    digits_bounds()
450
 
      from         - decimal number for processing
451
 
      start_result - index (from 0 ) of first decimal digits will
452
 
                     be written by this address
453
 
      end_result   - index of position just after last decimal digit
 
671
 @param  from  decimal number for processing
 
672
 @param  start_result  index (from 0 ) of first decimal digits will
 
673
                       be written by this address
 
674
 @param  end_result   index of position just after last decimal digit
454
675
                     be written by this address
455
676
*/
456
 
 
457
677
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
458
678
{
459
679
  int start, stop, i;
460
680
  dec1 *buf_beg= from->buf;
461
 
  dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
 
681
  dec1 *end= from->buf + round_up(from->intg) + round_up(from->frac);
462
682
  dec1 *buf_end= end - 1;
463
683
 
464
684
  /* find non-zero digit from number begining */
507
727
}
508
728
 
509
729
 
510
 
/*
511
 
  Left shift for alignment of data in buffer
512
 
 
513
 
  SYNOPSIS
514
 
    do_mini_left_shift()
515
 
    dec     pointer to decimal number which have to be shifted
516
 
    shift   number of decimal digits on which it should be shifted
517
 
    beg/end bounds of decimal digits (see digits_bounds())
518
 
 
519
 
  NOTE
520
 
    Result fitting in the buffer should be garanted.
521
 
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
 
730
/**
 
731
 @param Left shift for alignment of data in buffer
 
732
 
 
733
 @param  dec     pointer to decimal number which have to be shifted
 
734
 @param  shift   number of decimal digits on which it should be shifted
 
735
 @param  beg     beginning of decimal digits (see digits_bounds())
 
736
 @param  end     end of decimal digits (see digits_bounds())
 
737
 
 
738
 @note
 
739
   Result fitting in the buffer should be garanted.
 
740
   'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
 
741
   
 
742
 @todo  Above note is unclear - is 'garanted' a typo for 'guaranteed'
 
743
 or 'granted'?
522
744
*/
523
 
 
524
745
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
525
746
{
526
 
  dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
527
 
  dec1 *end= dec->buf + ROUND_UP(last) - 1;
 
747
  dec1 *from= dec->buf + round_up(beg + 1) - 1;
 
748
  dec1 *end= dec->buf + round_up(last) - 1;
528
749
  int c_shift= DIG_PER_DEC1 - shift;
529
750
  assert(from >= dec->buf);
530
751
  assert(end < dec->buf + dec->len);
537
758
}
538
759
 
539
760
 
540
 
/*
541
 
  Right shift for alignment of data in buffer
542
 
 
543
 
  SYNOPSIS
544
 
    do_mini_left_shift()
545
 
    dec     pointer to decimal number which have to be shifted
546
 
    shift   number of decimal digits on which it should be shifted
547
 
    beg/end bounds of decimal digits (see digits_bounds())
548
 
 
549
 
  NOTE
 
761
/**
 
762
  @brief Right shift for alignment of data in buffer
 
763
 
 
764
  @param  dec     pointer to decimal number which have to be shifted
 
765
  @param  shift   number of decimal digits on which it should be shifted
 
766
  @param  beg     beginning of decimal digits (see digits_bounds())
 
767
  @param  end     end of decimal digits (see digits_bounds())
 
768
 
 
769
  @note
550
770
    Result fitting in the buffer should be garanted.
551
771
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
552
772
*/
553
 
 
554
773
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
555
774
{
556
 
  dec1 *from= dec->buf + ROUND_UP(last) - 1;
557
 
  dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
 
775
  dec1 *from= dec->buf + round_up(last) - 1;
 
776
  dec1 *end= dec->buf + round_up(beg + 1) - 1;
558
777
  int c_shift= DIG_PER_DEC1 - shift;
559
778
  assert(from < dec->buf + dec->len);
560
779
  assert(end >= dec->buf);
567
786
}
568
787
 
569
788
 
570
 
/*
571
 
  Shift of decimal digits in given number (with rounding if it need)
 
789
/**
 
790
  @brief  Shift of decimal digits in given number (with rounding if it need)
572
791
 
573
 
  SYNOPSIS
574
 
    decimal_shift()
575
 
    dec       number to be shifted
576
 
    shift     number of decimal positions
 
792
  @param  dec       number to be shifted
 
793
  @param  shift     number of decimal positions
577
794
              shift > 0 means shift to left shift
578
795
              shift < 0 meand right shift
579
 
  NOTE
 
796
 
 
797
  @note
580
798
    In fact it is multipling on 10^shift.
581
 
  RETURN
582
 
    E_DEC_OK          OK
583
 
    E_DEC_OVERFLOW    operation lead to overflow, number is untoched
584
 
    E_DEC_TRUNCATED   number was rounded to fit into buffer
 
799
 
 
800
  @return  Error code
 
801
   @retval E_DEC_OK          OK
 
802
   @retval E_DEC_OVERFLOW    operation lead to overflow, number is untoched
 
803
   @retval E_DEC_TRUNCATED   number was rounded to fit into buffer
585
804
*/
586
 
 
587
805
static int decimal_shift(decimal_t *dec, int shift)
588
806
{
589
807
  /* index of first non zero digit (all indexes from 0) */
591
809
  /* index of position after last decimal digit */
592
810
  int end;
593
811
  /* index of digit position just after point */
594
 
  int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
 
812
  int point= round_up(dec->intg) * DIG_PER_DEC1;
595
813
  /* new point position */
596
814
  int new_point= point + shift;
597
815
  /* number of digits in result */
618
836
  digits_frac= end - new_point;
619
837
  set_if_bigger(digits_frac, 0);
620
838
 
621
 
  if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
 
839
  if ((new_len= round_up(digits_int) + (new_frac_len= round_up(digits_frac))) >
622
840
      dec->len)
623
841
  {
624
842
    int lack= new_len - dec->len;
678
896
    if (do_left)
679
897
    {
680
898
      do_mini_left_shift(dec, l_mini_shift, beg, end);
681
 
      mini_shift=- l_mini_shift;
 
899
      mini_shift= (-l_mini_shift);
682
900
    }
683
901
    else
684
902
    {
711
929
    {
712
930
      /* move left */
713
931
      d_shift= new_front / DIG_PER_DEC1;
714
 
      to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
715
 
      barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
 
932
      to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
 
933
      barier= dec->buf + (round_up(end) - 1 - d_shift);
716
934
      assert(to >= dec->buf);
717
935
      assert(barier + d_shift < dec->buf + dec->len);
718
936
      for(; to <= barier; to++)
725
943
    {
726
944
      /* move right */
727
945
      d_shift= (1 - new_front) / DIG_PER_DEC1;
728
 
      to= dec->buf + ROUND_UP(end) - 1 + d_shift;
729
 
      barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
 
946
      to= dec->buf + round_up(end) - 1 + d_shift;
 
947
      barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
730
948
      assert(to < dec->buf + dec->len);
731
949
      assert(barier - d_shift >= dec->buf);
732
950
      for(; to >= barier; to--)
745
963
 
746
964
    Only one of following 'for' loops will work becouse beg <= end
747
965
  */
748
 
  beg= ROUND_UP(beg + 1) - 1;
749
 
  end= ROUND_UP(end) - 1;
 
966
  beg= round_up(beg + 1) - 1;
 
967
  end= round_up(end) - 1;
750
968
  assert(new_point >= 0);
751
 
  
 
969
 
752
970
  /* We don't want negative new_point below */
753
971
  if (new_point != 0)
754
 
    new_point= ROUND_UP(new_point) - 1;
 
972
    new_point= round_up(new_point) - 1;
755
973
 
756
974
  if (new_point > end)
757
975
  {
771
989
}
772
990
 
773
991
 
774
 
/*
775
 
  Convert string to decimal
 
992
/**
 
993
  @brief  Convert string to decimal
776
994
 
777
 
  SYNOPSIS
778
 
    internal_str2decl()
779
 
      from    - value to convert. Doesn't have to be \0 terminated!
780
 
      to      - decimal where where the result will be stored
 
995
  @param  from    value to convert. Doesn't have to be \0 terminated!
 
996
  @param  to      decimal where where the result will be stored
781
997
                to->buf and to->len must be set.
782
 
      end     - Pointer to pointer to end of string. Will on return be
 
998
  @param  end     Pointer to pointer to end of string. Will on return be
783
999
                set to the char after the last used character
784
 
      fixed   - use to->intg, to->frac as limits for input number
 
1000
  @param  fixed   use to->intg, to->frac as limits for input number
785
1001
 
786
 
  NOTE
 
1002
  @note
787
1003
    to->intg and to->frac can be modified even when fixed=1
788
1004
    (but only decreased, in this case)
789
1005
 
790
 
  RETURN VALUE
 
1006
  @return
791
1007
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
792
1008
    In case of E_DEC_FATAL_ERROR *to is set to decimal zero
793
1009
    (to make error handling easier)
794
1010
*/
795
 
 
796
1011
int
797
1012
internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
798
1013
{
849
1064
      error=E_DEC_OVERFLOW;
850
1065
      intg=to->intg;
851
1066
    }
852
 
    intg1=ROUND_UP(intg);
853
 
    frac1=ROUND_UP(frac);
 
1067
    intg1=round_up(intg);
 
1068
    frac1=round_up(frac);
854
1069
    if (intg1+frac1 > to->len)
855
1070
    {
856
1071
      error= E_DEC_OOM;
859
1074
  }
860
1075
  else
861
1076
  {
862
 
    intg1=ROUND_UP(intg);
863
 
    frac1=ROUND_UP(frac);
864
 
    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
 
1077
    intg1=round_up(intg);
 
1078
    frac1=round_up(frac);
 
1079
    fix_intg_frac_error(to->len, intg1, frac1, error);
865
1080
    if (unlikely(error))
866
1081
    {
867
1082
      frac=frac1*DIG_PER_DEC1;
909
1124
  if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
910
1125
  {
911
1126
    int str_error;
912
 
    const int64_t exponent= my_strtoll10(endp+1, (char**) &end_of_string,
913
 
                                    &str_error);
 
1127
    const int64_t exponent= internal::my_strtoll10(endp+1, (char**) &end_of_string,
 
1128
                                                   &str_error);
914
1129
 
915
1130
    if (end_of_string != endp +1)               /* If at least one digit */
916
1131
    {
942
1157
}
943
1158
 
944
1159
 
945
 
/*
946
 
  Convert decimal to double
947
 
 
948
 
  SYNOPSIS
949
 
    decimal2double()
950
 
      from    - value to convert
951
 
      to      - result will be stored there
952
 
 
953
 
  RETURN VALUE
 
1160
/**
 
1161
  @param Convert decimal to double
 
1162
 
 
1163
  @param[in]   from   value to convert
 
1164
  @param[out]  to     result will be stored there
 
1165
 
 
1166
  @return
954
1167
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
955
1168
*/
956
1169
 
957
 
int decimal2double(decimal_t *from, double *to)
 
1170
int decimal2double(const decimal_t *from, double *to)
958
1171
{
959
1172
  char strbuf[FLOATING_POINT_BUFFER], *end;
960
1173
  int len= sizeof(strbuf);
962
1175
 
963
1176
  rc = decimal2string(from, strbuf, &len, 0, 0, 0);
964
1177
  end= strbuf + len;
965
 
  
966
 
  *to= my_strtod(strbuf, &end, &error);
967
 
             
 
1178
 
 
1179
  *to= internal::my_strtod(strbuf, &end, &error);
 
1180
 
968
1181
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
969
1182
}
970
1183
 
971
 
/*
972
 
  Convert double to decimal
973
 
 
974
 
  SYNOPSIS
975
 
    double2decimal()
976
 
      from    - value to convert
977
 
      to      - result will be stored there
978
 
 
979
 
  RETURN VALUE
 
1184
/**
 
1185
 @param  Convert double to decimal
 
1186
 
 
1187
 @param[in]  from    value to convert
 
1188
 @param[out] to      result will be stored there
 
1189
 
 
1190
 @return
980
1191
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
981
1192
*/
982
1193
 
983
 
int double2decimal(double from, decimal_t *to)
 
1194
int double2decimal(const double from, decimal_t *to)
984
1195
{
985
1196
  char buff[FLOATING_POINT_BUFFER], *end;
986
1197
  int res;
987
 
  end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
 
1198
  end= buff + internal::my_gcvt(from,
 
1199
                                internal::MY_GCVT_ARG_DOUBLE,
 
1200
                                sizeof(buff) - 1, buff, NULL);
988
1201
  res= string2decimal(buff, to, &end);
989
1202
  return(res);
990
1203
}
1016
1229
  return error;
1017
1230
}
1018
1231
 
1019
 
int uint64_t2decimal(uint64_t from, decimal_t *to)
 
1232
int uint64_t2decimal(const uint64_t from, decimal_t *to)
1020
1233
{
1021
1234
  to->sign=0;
1022
1235
  return ull2dec(from, to);
1023
1236
}
1024
1237
 
1025
 
int int64_t2decimal(int64_t from, decimal_t *to)
 
1238
int int64_t2decimal(const int64_t from, decimal_t *to)
1026
1239
{
1027
1240
  if ((to->sign= from < 0))
1028
1241
    return ull2dec(-from, to);
1029
1242
  return ull2dec(from, to);
1030
1243
}
1031
1244
 
1032
 
int decimal2uint64_t(decimal_t *from, uint64_t *to)
 
1245
int decimal2uint64_t(const decimal_t *from, uint64_t *to)
1033
1246
{
1034
1247
  dec1 *buf=from->buf;
1035
1248
  uint64_t x=0;
1058
1271
  return E_DEC_OK;
1059
1272
}
1060
1273
 
1061
 
int decimal2int64_t(decimal_t *from, int64_t *to)
 
1274
int decimal2int64_t(const decimal_t *from, int64_t *to)
1062
1275
{
1063
1276
  dec1 *buf=from->buf;
1064
1277
  int64_t x=0;
1098
1311
  return E_DEC_OK;
1099
1312
}
1100
1313
 
1101
 
/*
1102
 
  Convert decimal to its binary fixed-length representation
1103
 
  two representations of the same length can be compared with memcmp
1104
 
  with the correct -1/0/+1 result
1105
 
 
1106
 
  SYNOPSIS
1107
 
    decimal2bin()
1108
 
      from    - value to convert
1109
 
      to      - points to buffer where string representation should be stored
1110
 
      precision/scale - see decimal_bin_size() below
1111
 
 
1112
 
  NOTE
1113
 
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1114
 
 
1115
 
  RETURN VALUE
1116
 
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1117
 
 
1118
 
  DESCRIPTION
 
1314
/**
 
1315
 @brief
 
1316
  Convert decimal to its binary fixed-length representation (suitable for
 
1317
  comparing with memcmp)
 
1318
 
1119
1319
    for storage decimal numbers are converted to the "binary" format.
1120
1320
 
1121
1321
    This format has the following properties:
1176
1376
    And for -1234567890.1234 it would be
1177
1377
 
1178
1378
                7E F2 04 37 2D FB 2D
 
1379
 
 
1380
 
 
1381
  @param from      value to convert
 
1382
  @param to        points to buffer where string representation should be stored
 
1383
  @param precision see decimal_bin_size() below
 
1384
  @param frac      see decimal_bin_size() below
 
1385
 
 
1386
  @note
 
1387
    The buffer is assumed to be of the size decimal_bin_size(precision, scale)
 
1388
 
 
1389
  @return
 
1390
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
 
1391
 
1179
1392
*/
1180
 
int decimal2bin(decimal_t *from, unsigned char *to, int precision, int frac)
 
1393
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
1181
1394
{
1182
1395
  dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1183
1396
  int error=E_DEC_OK, intg=precision-frac,
1295
1508
  return error;
1296
1509
}
1297
1510
 
1298
 
/*
1299
 
  Restores decimal from its binary fixed-length representation
1300
 
 
1301
 
  SYNOPSIS
1302
 
    bin2decimal()
1303
 
      from    - value to convert
1304
 
      to      - result
1305
 
      precision/scale - see decimal_bin_size() below
1306
 
 
1307
 
  NOTE
 
1511
/**
 
1512
 @brief Restores decimal from its binary fixed-length representation
 
1513
 
 
1514
 @param  from    value to convert
 
1515
 @param  to      result
 
1516
 @param  precision see decimal_bin_size() below
 
1517
 @param  scale     see decimal_bin_size() below
 
1518
 
 
1519
 @note
1308
1520
    see decimal2bin()
1309
1521
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1310
1522
 
1311
 
  RETURN VALUE
 
1523
 @return
1312
1524
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1313
1525
*/
1314
 
 
1315
1526
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1316
1527
{
1317
1528
  int error=E_DEC_OK, intg=precision-scale,
1329
1540
  d_copy[0]^= 0x80;
1330
1541
  from= d_copy;
1331
1542
 
1332
 
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
 
1543
  fix_intg_frac_error(to->len, intg1, frac1, error);
1333
1544
  if (unlikely(error))
1334
1545
  {
1335
1546
    if (intg1 < intg0+(intg0x>0))
1414
1625
  return(E_DEC_BAD_NUM);
1415
1626
}
1416
1627
 
1417
 
/*
1418
 
  Returns the size of array to hold a decimal with given precision and scale
1419
 
 
1420
 
  RETURN VALUE
1421
 
    size in dec1
1422
 
    (multiply by sizeof(dec1) to get the size if bytes)
1423
 
*/
1424
 
 
1425
 
int decimal_size(int precision, int scale)
1426
 
{
1427
 
  assert(scale >= 0 && precision > 0 && scale <= precision);
1428
 
  return ROUND_UP(precision-scale)+ROUND_UP(scale);
1429
 
}
1430
 
 
1431
 
/*
1432
 
  Returns the size of array to hold a binary representation of a decimal
1433
 
 
1434
 
  RETURN VALUE
1435
 
    size in bytes
1436
 
*/
1437
 
 
 
1628
/**
 
1629
 @brief  Returns the size of array to hold a binary representation of a decimal
 
1630
 
 
1631
 @return  Size in bytes
 
1632
*/
1438
1633
int decimal_bin_size(int precision, int scale)
1439
1634
{
1440
1635
  int intg=precision-scale,
1446
1641
         frac0*sizeof(dec1)+dig2bytes[frac0x];
1447
1642
}
1448
1643
 
1449
 
/*
1450
 
  Rounds the decimal to "scale" digits
1451
 
 
1452
 
  SYNOPSIS
1453
 
    decimal_round()
1454
 
      from    - decimal to round,
1455
 
      to      - result buffer. from==to is allowed
1456
 
      scale   - to what position to round. can be negative!
1457
 
      mode    - round to nearest even or truncate
1458
 
 
1459
 
  NOTES
 
1644
/**
 
1645
 @brief  Rounds the decimal to "scale" digits
 
1646
 
 
1647
 @param from    - decimal to round,
 
1648
 @param to      - result buffer. from==to is allowed
 
1649
 @param scale   - to what position to round. can be negative!
 
1650
 @param mode    - round to nearest even or truncate
 
1651
 
 
1652
 @note
1460
1653
    scale can be negative !
1461
1654
    one TRUNCATED error (line XXX below) isn't treated very logical :(
1462
1655
 
1463
 
  RETURN VALUE
 
1656
 @return
1464
1657
    E_DEC_OK/E_DEC_TRUNCATED
1465
1658
*/
1466
 
 
1467
1659
int
1468
 
decimal_round(decimal_t *from, decimal_t *to, int scale,
 
1660
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1469
1661
              decimal_round_mode mode)
1470
1662
{
1471
 
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1472
 
      frac1=ROUND_UP(from->frac), round_digit= 0,
1473
 
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1474
 
      intg1=ROUND_UP(from->intg +
 
1663
  int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
 
1664
      frac1=round_up(from->frac), round_digit= 0,
 
1665
      intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
 
1666
      intg1=round_up(from->intg +
1475
1667
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1476
1668
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1477
1669
  int first_dig;
1502
1694
 
1503
1695
  if (to != from || intg1>intg0)
1504
1696
  {
1505
 
    dec1 *p0= buf0+intg0+cmax(frac1, frac0);
1506
 
    dec1 *p1= buf1+intg1+cmax(frac1, frac0);
 
1697
    dec1 *p0= buf0+intg0+max(frac1, frac0);
 
1698
    dec1 *p1= buf1+intg1+max(frac1, frac0);
1507
1699
 
1508
1700
    while (buf0 < p0)
1509
1701
      *(--p1) = *(--p0);
1514
1706
    buf0=to->buf;
1515
1707
    buf1=to->buf;
1516
1708
    to->sign=from->sign;
1517
 
    to->intg=cmin(intg0, len)*DIG_PER_DEC1;
 
1709
    to->intg=min(intg0, len)*DIG_PER_DEC1;
1518
1710
  }
1519
1711
 
1520
1712
  if (frac0 > frac1)
1573
1765
  }
1574
1766
  else
1575
1767
  {
1576
 
    /* TODO - fix this code as it won't work for CEILING mode */
 
1768
  /** @todo fix this code as it won't work for CEILING mode */
1577
1769
    int pos=frac0*DIG_PER_DEC1-scale-1;
1578
1770
    assert(frac0+intg0 > 0);
1579
1771
    x=*buf1 / powers10[pos];
1606
1798
    carry=1;
1607
1799
    *buf1-=DIG_BASE;
1608
1800
    while (carry && --buf1 >= to->buf)
1609
 
      ADD(*buf1, *buf1, 0, carry);
 
1801
      add(*buf1, *buf1, 0, carry);
1610
1802
    if (unlikely(carry))
1611
1803
    {
1612
1804
      /* shifting the number to create space for new digit */
1616
1808
        scale=frac0*DIG_PER_DEC1;
1617
1809
        error=E_DEC_TRUNCATED; /* XXX */
1618
1810
      }
1619
 
      for (buf1=to->buf+intg0+cmax(frac0,0); buf1 > to->buf; buf1--)
 
1811
      for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--)
1620
1812
      {
1621
1813
        buf1[0]=buf1[-1];
1622
1814
      }
1635
1827
        /* making 'zero' with the proper scale */
1636
1828
        dec1 *p0= to->buf + frac0 + 1;
1637
1829
        to->intg=1;
1638
 
        to->frac= cmax(scale, 0);
 
1830
        to->frac= max(scale, 0);
1639
1831
        to->sign= 0;
1640
1832
        for (buf1= to->buf; buf1<p0; buf1++)
1641
1833
          *buf1= 0;
1657
1849
  return error;
1658
1850
}
1659
1851
 
1660
 
/*
1661
 
  Returns the size of the result of the operation
1662
 
 
1663
 
  SYNOPSIS
1664
 
    decimal_result_size()
1665
 
      from1   - operand of the unary operation or first operand of the
1666
 
                binary operation
1667
 
      from2   - second operand of the binary operation
1668
 
      op      - operation. one char '+', '-', '*', '/' are allowed
1669
 
                others may be added later
1670
 
      param   - extra param to the operation. unused for '+', '-', '*'
1671
 
                scale increment for '/'
1672
 
 
1673
 
  NOTE
1674
 
    returned valued may be larger than the actual buffer requred
1675
 
    in the operation, as decimal_result_size, by design, operates on
1676
 
    precision/scale values only and not on the actual decimal number
1677
 
 
1678
 
  RETURN VALUE
1679
 
    size of to->buf array in dec1 elements. to get size in bytes
1680
 
    multiply by sizeof(dec1)
1681
 
*/
1682
 
 
1683
 
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1684
 
{
1685
 
  switch (op) {
1686
 
  case '-':
1687
 
    return ROUND_UP(cmax(from1->intg, from2->intg)) +
1688
 
           ROUND_UP(cmax(from1->frac, from2->frac));
1689
 
  case '+':
1690
 
    return ROUND_UP(cmax(from1->intg, from2->intg)+1) +
1691
 
           ROUND_UP(cmax(from1->frac, from2->frac));
1692
 
  case '*':
1693
 
    return ROUND_UP(from1->intg+from2->intg)+
1694
 
           ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1695
 
  case '/':
1696
 
    return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1697
 
  default: assert(0);
1698
 
  }
1699
 
  return -1; /* shut up the warning */
1700
 
}
1701
 
 
1702
 
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1703
 
{
1704
 
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1705
 
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1706
 
      frac0=cmax(frac1, frac2), intg0=cmax(intg1, intg2), error;
 
1852
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1853
{
 
1854
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
 
1855
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
 
1856
      frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1707
1857
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1708
1858
 
1709
1859
  sanity(to);
1718
1868
    to->buf[0]=0; /* safety */
1719
1869
  }
1720
1870
 
1721
 
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
 
1871
  fix_intg_frac_error(to->len, intg0, frac0, error);
1722
1872
  if (unlikely(error == E_DEC_OVERFLOW))
1723
1873
  {
1724
1874
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1728
1878
  buf0=to->buf+intg0+frac0;
1729
1879
 
1730
1880
  to->sign=from1->sign;
1731
 
  to->frac=cmax(from1->frac, from2->frac);
 
1881
  to->frac=max(from1->frac, from2->frac);
1732
1882
  to->intg=intg0*DIG_PER_DEC1;
1733
1883
  if (unlikely(error))
1734
1884
  {
1761
1911
  carry=0;
1762
1912
  while (buf1 > stop2)
1763
1913
  {
1764
 
    ADD(*--buf0, *--buf1, *--buf2, carry);
 
1914
    add(*--buf0, *--buf1, *--buf2, carry);
1765
1915
  }
1766
1916
 
1767
1917
  /* part 3 - cmin(intg) ... cmax(intg) */
1769
1919
                        ((stop=from2->buf)+intg2-intg1) ;
1770
1920
  while (buf1 > stop)
1771
1921
  {
1772
 
    ADD(*--buf0, *--buf1, 0, carry);
 
1922
    add(*--buf0, *--buf1, 0, carry);
1773
1923
  }
1774
1924
 
1775
1925
  if (unlikely(carry))
1781
1931
 
1782
1932
/* to=from1-from2.
1783
1933
   if to==0, return -1/0/+1 - the result of the comparison */
1784
 
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
 
1934
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1785
1935
{
1786
 
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1787
 
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1788
 
  int frac0=cmax(frac1, frac2), error;
 
1936
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
 
1937
      frac1=round_up(from1->frac), frac2=round_up(from2->frac);
 
1938
  int frac0=max(frac1, frac2), error;
1789
1939
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1790
1940
 
1791
1941
  /* let carry:=1 if from2 > from1 */
1850
2000
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
1851
2001
  if (carry)
1852
2002
  {
1853
 
    swap_variables(decimal_t *,from1,from1);
1854
 
    swap_variables(dec1 *,start1, start2);
1855
 
    swap_variables(int,intg1,intg2);
1856
 
    swap_variables(int,frac1,frac2);
 
2003
    swap(from1, from2);
 
2004
    swap(start1, start2);
 
2005
    swap(intg1, intg2);
 
2006
    swap(frac1, frac2);
1857
2007
    to->sign= 1 - to->sign;
1858
2008
  }
1859
2009
 
1860
 
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
 
2010
  fix_intg_frac_error(to->len, intg1, frac0, error);
1861
2011
  buf0=to->buf+intg1+frac0;
1862
2012
 
1863
 
  to->frac=cmax(from1->frac, from2->frac);
 
2013
  to->frac=max(from1->frac, from2->frac);
1864
2014
  to->intg=intg1*DIG_PER_DEC1;
1865
2015
  if (unlikely(error))
1866
2016
  {
1891
2041
      *--buf0=0;
1892
2042
    while (buf2 > stop2)
1893
2043
    {
1894
 
      SUB(*--buf0, 0, *--buf2, carry);
 
2044
      sub(*--buf0, 0, *--buf2, carry);
1895
2045
    }
1896
2046
  }
1897
2047
 
1898
2048
  /* part 2 - cmin(frac) ... intg2 */
1899
2049
  while (buf2 > start2)
1900
2050
  {
1901
 
    SUB(*--buf0, *--buf1, *--buf2, carry);
 
2051
    sub(*--buf0, *--buf1, *--buf2, carry);
1902
2052
  }
1903
2053
 
1904
2054
  /* part 3 - intg2 ... intg1 */
1905
2055
  while (carry && buf1 > start1)
1906
2056
  {
1907
 
    SUB(*--buf0, *--buf1, 0, carry);
 
2057
    sub(*--buf0, *--buf1, 0, carry);
1908
2058
  }
1909
2059
 
1910
2060
  while (buf1 > start1)
1916
2066
  return error;
1917
2067
}
1918
2068
 
1919
 
int decimal_intg(decimal_t *from)
 
2069
int decimal_intg(const decimal_t *from)
1920
2070
{
1921
2071
  int res;
1922
2072
  dec1 *tmp_res;
1924
2074
  return res;
1925
2075
}
1926
2076
 
1927
 
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
 
2077
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1928
2078
{
1929
2079
  if (likely(from1->sign == from2->sign))
1930
2080
    return do_add(from1, from2, to);
1931
2081
  return do_sub(from1, from2, to);
1932
2082
}
1933
2083
 
1934
 
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
 
2084
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1935
2085
{
1936
2086
  if (likely(from1->sign == from2->sign))
1937
2087
    return do_sub(from1, from2, to);
1938
2088
  return do_add(from1, from2, to);
1939
2089
}
1940
2090
 
1941
 
int decimal_cmp(decimal_t *from1, decimal_t *from2)
 
2091
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
1942
2092
{
1943
2093
  if (likely(from1->sign == from2->sign))
1944
2094
    return do_sub(from1, from2, 0);
1945
2095
  return from1->sign > from2->sign ? -1 : 1;
1946
2096
}
1947
2097
 
1948
 
int decimal_is_zero(decimal_t *from)
 
2098
int decimal_is_zero(const decimal_t *from)
1949
2099
{
1950
2100
  dec1 *buf1=from->buf,
1951
 
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
 
2101
       *end=buf1+round_up(from->intg)+round_up(from->frac);
1952
2102
  while (buf1 < end)
1953
2103
    if (*buf1++)
1954
2104
      return 0;
1955
2105
  return 1;
1956
2106
}
1957
2107
 
1958
 
/*
1959
 
  multiply two decimals
1960
 
 
1961
 
  SYNOPSIS
1962
 
    decimal_mul()
1963
 
      from1, from2 - factors
1964
 
      to      - product
1965
 
 
1966
 
  RETURN VALUE
 
2108
/**
 
2109
 @brief multiply two decimals
 
2110
 
 
2111
 @param[in]   from1  First factor
 
2112
 @param[in]   from2  Second factor
 
2113
 @param[out]  to     product
 
2114
 
 
2115
 @return
1967
2116
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
1968
2117
 
1969
 
  NOTES
 
2118
 @note
1970
2119
    in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
1971
2120
    and 63-digit number will take only 7 dec1 words (basically a 7-digit
1972
2121
    "base 999999999" number).  Thus there's no need in fast multiplication
1976
2125
    XXX if this library is to be used with huge numbers of thousands of
1977
2126
    digits, fast multiplication must be implemented.
1978
2127
*/
1979
 
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
 
2128
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1980
2129
{
1981
 
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1982
 
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1983
 
      intg0=ROUND_UP(from1->intg+from2->intg),
 
2130
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
 
2131
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
 
2132
      intg0=round_up(from1->intg+from2->intg),
1984
2133
      frac0=frac1+frac2, error, i, j, d_to_move;
1985
2134
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
1986
2135
       *start2, *stop2, *stop1, *start0, carry;
1989
2138
 
1990
2139
  i=intg0;
1991
2140
  j=frac0;
1992
 
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
 
2141
  fix_intg_frac_error(to->len, intg0, frac0, error);
1993
2142
  to->sign=from1->sign != from2->sign;
1994
2143
  to->frac=from1->frac+from2->frac;
1995
2144
  to->intg=intg0*DIG_PER_DEC1;
2030
2179
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2031
2180
      hi=(dec1)(p/DIG_BASE);
2032
2181
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2033
 
      ADD2(*buf0, *buf0, lo, carry);
 
2182
      add2(*buf0, *buf0, lo, carry);
2034
2183
      carry+=hi;
2035
2184
    }
2036
2185
    if (carry)
2037
2186
    {
2038
2187
      if (buf0 < to->buf)
2039
2188
        return E_DEC_OVERFLOW;
2040
 
      ADD2(*buf0, *buf0, 0, carry);
 
2189
      add2(*buf0, *buf0, 0, carry);
2041
2190
    }
2042
2191
    for (buf0--; carry; buf0--)
2043
2192
    {
2044
2193
      if (buf0 < to->buf)
2045
2194
        return E_DEC_OVERFLOW;
2046
 
      ADD(*buf0, *buf0, 0, carry);
 
2195
      add(*buf0, *buf0, 0, carry);
2047
2196
    }
2048
2197
  }
2049
2198
 
2066
2215
    }
2067
2216
  }
2068
2217
  buf1= to->buf;
2069
 
  d_to_move= intg0 + ROUND_UP(to->frac);
 
2218
  d_to_move= intg0 + round_up(to->frac);
2070
2219
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2071
2220
  {
2072
2221
    buf1++;
2082
2231
  return error;
2083
2232
}
2084
2233
 
2085
 
/*
 
2234
/**
2086
2235
  naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2087
2236
  it's ok for short numbers
2088
2237
  also we're using alloca() to allocate a temporary buffer
2089
2238
 
2090
 
  XXX if this library is to be used with huge numbers of thousands of
 
2239
  @todo
 
2240
  If this library is to be used with huge numbers of thousands of
2091
2241
  digits, fast division must be implemented and alloca should be
2092
2242
  changed to malloc (or at least fallback to malloc if alloca() fails)
2093
2243
  but then, decimal_mul() should be rewritten too :(
2094
2244
*/
2095
 
static int do_div_mod(decimal_t *from1, decimal_t *from2,
 
2245
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2096
2246
                       decimal_t *to, decimal_t *mod, int scale_incr)
2097
2247
{
2098
 
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2099
 
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
 
2248
  int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
 
2249
      frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2100
2250
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2101
2251
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2102
2252
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2146
2296
    intg0=0;
2147
2297
  }
2148
2298
  else
2149
 
    intg0=ROUND_UP(dintg);
 
2299
    intg0=round_up(dintg);
2150
2300
  if (mod)
2151
2301
  {
2152
2302
    /* we're calculating N1 % N2.
2155
2305
         intg=intg2
2156
2306
    */
2157
2307
    to->sign=from1->sign;
2158
 
    to->frac=cmax(from1->frac, from2->frac);
 
2308
    to->frac=max(from1->frac, from2->frac);
2159
2309
    frac0=0;
2160
2310
  }
2161
2311
  else
2165
2315
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2166
2316
      frac2 accordingly.
2167
2317
      Thus, the result will have
2168
 
         frac = ROUND_UP(frac1+frac2+scale_incr)
 
2318
         frac = round_up(frac1+frac2+scale_incr)
2169
2319
      and
2170
2320
         intg = (prec1-frac1) - (prec2-frac2) + 1
2171
2321
         prec = intg+frac
2172
2322
    */
2173
 
    frac0=ROUND_UP(frac1+frac2+scale_incr);
2174
 
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
 
2323
    frac0=round_up(frac1+frac2+scale_incr);
 
2324
    fix_intg_frac_error(to->len, intg0, frac0, error);
2175
2325
    to->sign=from1->sign != from2->sign;
2176
2326
    to->intg=intg0*DIG_PER_DEC1;
2177
2327
    to->frac=frac0*DIG_PER_DEC1;
2182
2332
    while (dintg++ < 0)
2183
2333
      *buf0++=0;
2184
2334
 
2185
 
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
 
2335
  len1=(i=round_up(prec1))+round_up(2*frac2+scale_incr+1) + 1;
2186
2336
  set_if_bigger(len1, 3);
2187
2337
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
2188
2338
    return E_DEC_OOM;
2192
2342
  start1=tmp1;
2193
2343
  stop1=start1+len1;
2194
2344
  start2=buf2;
2195
 
  stop2=buf2+ROUND_UP(prec2)-1;
 
2345
  stop2=buf2+round_up(prec2)-1;
2196
2346
 
2197
2347
  /* removing end zeroes */
2198
2348
  while (*stop2 == 0 && stop2 >= start2)
2251
2401
        x=guess * (*--buf2);
2252
2402
        hi=(dec1)(x/DIG_BASE);
2253
2403
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2254
 
        SUB2(*buf1, *buf1, lo, carry);
 
2404
        sub2(*buf1, *buf1, lo, carry);
2255
2405
        carry+=hi;
2256
2406
      }
2257
2407
      carry= dcarry < carry;
2265
2415
        buf1=start1+len2;
2266
2416
        for (carry=0; buf2 > start2; buf1--)
2267
2417
        {
2268
 
          ADD(*buf1, *buf1, *--buf2, carry);
 
2418
          add(*buf1, *buf1, *--buf2, carry);
2269
2419
        }
2270
2420
      }
2271
2421
    }
2284
2434
    if (dcarry)
2285
2435
      *--start1=dcarry;
2286
2436
    buf0=to->buf;
2287
 
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
2288
 
    frac0=ROUND_UP(to->frac);
 
2437
    intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
 
2438
    frac0=round_up(to->frac);
2289
2439
    error=E_DEC_OK;
2290
2440
    if (unlikely(frac0==0 && intg0==0))
2291
2441
    {
2315
2465
        error=E_DEC_OVERFLOW;
2316
2466
        goto done;
2317
2467
      }
2318
 
      assert(intg0 <= ROUND_UP(from2->intg));
 
2468
      assert(intg0 <= round_up(from2->intg));
2319
2469
      stop1=start1+frac0+intg0;
2320
 
      to->intg=cmin(intg0*DIG_PER_DEC1, from2->intg);
 
2470
      to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2321
2471
    }
2322
2472
    if (unlikely(intg0+frac0 > to->len))
2323
2473
    {
2334
2484
  return error;
2335
2485
}
2336
2486
 
2337
 
/*
2338
 
  division of two decimals
2339
 
 
2340
 
  SYNOPSIS
2341
 
    decimal_div()
2342
 
      from1   - dividend
2343
 
      from2   - divisor
2344
 
      to      - quotient
2345
 
 
2346
 
  RETURN VALUE
 
2487
/**
 
2488
 @brief  division of two decimals
 
2489
 
 
2490
 @param[in]  from1   dividend
 
2491
 @param[in]  from2   divisor
 
2492
 @param[out] to      quotient
 
2493
 
 
2494
 @return
2347
2495
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2348
2496
 
2349
 
  NOTES
 
2497
 @note
2350
2498
    see do_div_mod()
2351
2499
*/
2352
 
 
2353
2500
int
2354
 
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
 
2501
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
2355
2502
{
2356
2503
  return do_div_mod(from1, from2, to, 0, scale_incr);
2357
2504
}
2358
2505
 
2359
 
/*
2360
 
  modulus
2361
 
 
2362
 
  SYNOPSIS
2363
 
    decimal_mod()
2364
 
      from1   - dividend
2365
 
      from2   - divisor
2366
 
      to      - modulus
2367
 
 
2368
 
  RETURN VALUE
 
2506
/**
 
2507
 @brief modulus
 
2508
 
 
2509
 the modulus R in    R = M mod N
 
2510
 
 
2511
 is defined as
 
2512
 
 
2513
 0 <= |R| < |M|
 
2514
 sign R == sign M
 
2515
 R = M - k*N, where k is integer
 
2516
 
 
2517
 thus, there's no requirement for M or N to be integers
 
2518
 
 
2519
 
 
2520
 @param from1   dividend
 
2521
 @param from2   divisor
 
2522
 @param to      modulus
 
2523
 
 
2524
 @return
2369
2525
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2370
2526
 
2371
 
  NOTES
 
2527
 @note
2372
2528
    see do_div_mod()
2373
2529
 
2374
 
  DESCRIPTION
2375
 
    the modulus R in    R = M mod N
2376
 
 
2377
 
   is defined as
2378
 
 
2379
 
     0 <= |R| < |M|
2380
 
     sign R == sign M
2381
 
     R = M - k*N, where k is integer
2382
 
 
2383
 
   thus, there's no requirement for M or N to be integers
2384
2530
*/
2385
 
 
2386
 
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
 
2531
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2387
2532
{
2388
2533
  return do_div_mod(from1, from2, 0, to, 0);
2389
2534
}
2390
2535
 
 
2536
} /* namespace drizzled */
 
2537
 
2391
2538
#ifdef MAIN
2392
2539
 
2393
2540
int full= 0;
2398
2545
{
2399
2546
  int i;
2400
2547
  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2401
 
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
 
2548
  for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
2402
2549
    printf("%09d, ", d->buf[i]);
2403
2550
  printf("%09d} */ ", d->buf[i]);
2404
2551
}
2470
2617
{
2471
2618
  char s1[100], *end;
2472
2619
  int res;
2473
 
  sprintf(s1, "'%s'", s);
 
2620
  snprintf(s1, sizeof(s1), "'%s'", s);
2474
2621
  end= strend(s);
2475
2622
  printf("len=%2d %-30s => res=%d    ", a.len, s1,
2476
2623
         (res= string2decimal(s, &a, &end)));
2484
2631
  double x;
2485
2632
  int res;
2486
2633
 
2487
 
  sprintf(s1, "'%s'", s);
 
2634
  snprintf(s1, sizeof(s1), "'%s'", s);
2488
2635
  end= strend(s);
2489
2636
  string2decimal(s, &a, &end);
2490
2637
  res=decimal2double(&a, &x);
2498
2645
  char s1[100], buf[100], *end;
2499
2646
  int res, i, size=decimal_bin_size(p, s);
2500
2647
 
2501
 
  sprintf(s1, "'%s'", str);
 
2648
  snprintf(s1, sizeof(s1), "'%s'", str);
2502
2649
  end= strend(str);
2503
2650
  string2decimal(str, &a, &end);
2504
2651
  res=decimal2bin(&a, buf, p, s);
2531
2678
  int res;
2532
2679
 
2533
2680
  res=uint64_t2decimal(from, &a);
2534
 
  int64_t10_to_str(from,s,10);
 
2681
  internal::int64_t10_to_str(from,s,10);
2535
2682
  printf("%-40s => res=%d    ", s, res);
2536
2683
  print_decimal(&a, orig, res, ex);
2537
2684
  printf("\n");
2543
2690
  int res;
2544
2691
 
2545
2692
  res=int64_t2decimal(from, &a);
2546
 
  int64_t10_to_str(from,s,-10);
 
2693
  internal::int64_t10_to_str(from,s,-10);
2547
2694
  printf("%-40s => res=%d    ", s, res);
2548
2695
  print_decimal(&a, orig, res, ex);
2549
2696
  printf("\n");
2559
2706
  string2decimal(s, &a, &end);
2560
2707
  res=decimal2uint64_t(&a, &x);
2561
2708
  if (full) dump_decimal(&a);
2562
 
  int64_t10_to_str(x,s1,10);
 
2709
  internal::int64_t10_to_str(x,s1,10);
2563
2710
  printf("%-40s => res=%d    %s\n", s, res, s1);
2564
2711
  check_result_code(res, ex);
2565
2712
  if (orig && strcmp(orig, s1))
2579
2726
  string2decimal(s, &a, &end);
2580
2727
  res=decimal2int64_t(&a, &x);
2581
2728
  if (full) dump_decimal(&a);
2582
 
  int64_t10_to_str(x,s1,-10);
 
2729
  internal::int64_t10_to_str(x,s1,-10);
2583
2730
  printf("%-40s => res=%d    %s\n", s, res, s1);
2584
2731
  check_result_code(res, ex);
2585
2732
  if (orig && strcmp(orig, s1))
2593
2740
{
2594
2741
  char s[100], *end;
2595
2742
  int res;
2596
 
  sprintf(s, "'%s' + '%s'", s1, s2);
 
2743
  snprintf(s, sizeof(s), "'%s' + '%s'", s1, s2);
2597
2744
  end= strend(s1);
2598
2745
  string2decimal(s1, &a, &end);
2599
2746
  end= strend(s2);
2608
2755
{
2609
2756
  char s[100], *end;
2610
2757
  int res;
2611
 
  sprintf(s, "'%s' - '%s'", s1, s2);
 
2758
  snprintf(s, sizeof(s), "'%s' - '%s'", s1, s2);
2612
2759
  end= strend(s1);
2613
2760
  string2decimal(s1, &a, &end);
2614
2761
  end= strend(s2);
2623
2770
{
2624
2771
  char s[100], *end;
2625
2772
  int res;
2626
 
  sprintf(s, "'%s' <=> '%s'", s1, s2);
 
2773
  snprintf(s, sizeof(s), "'%s' <=> '%s'", s1, s2);
2627
2774
  end= strend(s1);
2628
2775
  string2decimal(s1, &a, &end);
2629
2776
  end= strend(s2);
2641
2788
{
2642
2789
  char s[100], *end;
2643
2790
  int res;
2644
 
  sprintf(s, "'%s' * '%s'", s1, s2);
 
2791
  snprintf(s, sizeof(s), "'%s' * '%s'", s1, s2);
2645
2792
  end= strend(s1);
2646
2793
  string2decimal(s1, &a, &end);
2647
2794
  end= strend(s2);
2656
2803
{
2657
2804
  char s[100], *end;
2658
2805
  int res;
2659
 
  sprintf(s, "'%s' / '%s'", s1, s2);
 
2806
  snprintf(s, sizeof(s), "'%s' / '%s'", s1, s2);
2660
2807
  end= strend(s1);
2661
2808
  string2decimal(s1, &a, &end);
2662
2809
  end= strend(s2);
2675
2822
{
2676
2823
  char s[100], *end;
2677
2824
  int res;
2678
 
  sprintf(s, "'%s' %% '%s'", s1, s2);
 
2825
  snprintf(s, sizeof(s), "'%s' %% '%s'", s1, s2);
2679
2826
  end= strend(s1);
2680
2827
  string2decimal(s1, &a, &end);
2681
2828
  end= strend(s2);
2698
2845
{
2699
2846
  char s[100], *end;
2700
2847
  int res;
2701
 
  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
 
2848
  snprintf(s, sizeof(s), "'%s', %d, %s", s1, n, round_mode[mode]);
2702
2849
  end= strend(s1);
2703
2850
  string2decimal(s1, &a, &end);
2704
2851
  res=decimal_round(&a, &b, n, mode);
2711
2858
void test_mx(int precision, int frac, const char *orig)
2712
2859
{
2713
2860
  char s[100];
2714
 
  sprintf(s, "%d, %d", precision, frac);
 
2861
  snprintf(s, sizeof(s), "%d, %d", precision, frac);
2715
2862
  max_decimal(precision, frac, &a);
2716
2863
  printf("%-40s =>          ", s);
2717
2864
  print_decimal(&a, orig, 0, 0);
2727
2874
  int slen= sizeof(s2);
2728
2875
  int res;
2729
2876
 
2730
 
  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
 
2877
  snprintf(s, sizeof(s), filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2731
2878
          s1, prec, dec, filler);
2732
2879
  end= strend(s1);
2733
2880
  string2decimal(s1, &a, &end);
2747
2894
{
2748
2895
  char s[100], *end;
2749
2896
  int res;
2750
 
  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
 
2897
  snprintf(s, sizeof(s), "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2751
2898
  end= strend(s1);
2752
2899
  string2decimal(s1, &a, &end);
2753
2900
  res= decimal_shift(&a, shift);
2760
2907
void test_fr(const char *s1, const char *orig)
2761
2908
{
2762
2909
  char s[100], *end;
2763
 
  sprintf(s, "'%s'", s1);
 
2910
  snprintf(s, sizeof(s), "'%s'", s1);
2764
2911
  printf("%-40s =>          ", s);
2765
2912
  end= strend(s1);
2766
2913
  string2decimal(s1, &a, &end);