~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/decimal.cc

  • Committer: Brian Aker
  • Date: 2009-03-12 14:38:12 UTC
  • mfrom: (910.4.20 sparc)
  • Revision ID: brian@tangent.org-20090312143812-g02zsr6krx54nxjp
Merge from Stewart.

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