~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/decimal.cc

  • Committer: Monty Taylor
  • Date: 2009-10-06 19:40:45 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20091006194045-ojptaq2sx6ck6q63
No more server_includes.h in headers.

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>
 
100
#include <drizzled/global.h>
107
101
 
108
 
#include <drizzled/definitions.h>
109
 
#include <drizzled/internal/m_string.h>
110
 
#include <drizzled/charset_info.h>
111
 
#include <drizzled/type/decimal.h>
 
102
#include "m_string.h"
 
103
#include "m_ctype.h"
 
104
#include "decimal.h"
112
105
 
113
106
#include <plugin/myisam/myisampack.h>
114
107
#include <drizzled/util/test.h>
118
111
#endif
119
112
 
120
113
#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
114
 
127
115
using namespace std;
128
116
 
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 type::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 class_decimal2string(const type::Decimal *d,
198
 
                         uint32_t fixed_dec, String *str)
199
 
{
200
 
  uint32_t mask= E_DEC_FATAL_ERROR;
201
 
 
202
 
  /*
203
 
    Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
204
 
    holds true iff the type is also ZEROFILL, which in turn implies
205
 
    UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
206
 
    the user requested, plus one for a possible decimal point, plus
207
 
    one if the user only wanted decimal places, but we force a leading
208
 
    zero on them. Because the type is implicitly UNSIGNED, we do not
209
 
    need to reserve a character for the sign. For all other cases,
210
 
    fixed_prec will be 0, and class_decimal_string_length() will be called
211
 
    instead to calculate the required size of the buffer.
212
 
  */
213
 
  int length= (int)(0
214
 
                    ? (uint32_t)(((0 == fixed_dec) ? 1 : 0) + 1)
215
 
                    : (uint32_t)d->string_length());
216
 
  int result;
217
 
  if (str->alloc(length))
218
 
    return check_result(mask, E_DEC_OOM);
219
 
 
220
 
  result= decimal2string((decimal_t*) d, (char*) str->ptr(),
221
 
                         &length, (int)0, fixed_dec,
222
 
                         '0');
223
 
  str->length(length);
224
 
  return check_result(mask, result);
225
 
}
226
 
 
227
 
 
228
 
/**
229
 
  @brief  Convert from decimal to binary representation
230
 
 
231
 
  @param[in]   mask        error processing mask
232
 
  @param[in]   d           number for conversion
233
 
  @param[out]  bin         pointer to buffer where to write result
234
 
  @param[in]   prec        overall number of decimal digits
235
 
  @param[in]   scale       number of decimal digits after decimal point
236
 
 
237
 
  @note
238
 
    Before conversion we round number if it need but produce truncation
239
 
    error in this case
240
 
 
241
 
  @return error code
242
 
   @retval E_DEC_OK
243
 
   @retval E_DEC_TRUNCATED
244
 
   @retval E_DEC_OVERFLOW
245
 
*/
246
 
 
247
 
namespace type {
248
 
 
249
 
int Decimal::val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const
250
 
{
251
 
  int err1= E_DEC_OK, err2;
252
 
  type::Decimal rounded;
253
 
  class_decimal2decimal(this, &rounded);
254
 
  rounded.frac= decimal_actual_fraction(&rounded);
255
 
  if (scale < rounded.frac)
256
 
  {
257
 
    err1= E_DEC_TRUNCATED;
258
 
    /* decimal_round can return only E_DEC_TRUNCATED */
259
 
    decimal_round(&rounded, &rounded, scale, HALF_UP);
260
 
  }
261
 
  err2= decimal2bin(&rounded, bin, prec, scale);
262
 
  if (!err2)
263
 
    err2= err1;
264
 
  return check_result(mask, err2);
265
 
}
266
 
 
267
 
} // namespace type
268
 
 
269
 
 
270
 
/**
271
 
  @brief Convert string for decimal when string can be in some multibyte charset
272
 
 
273
 
  @param  mask            error processing mask
274
 
  @param  from            string to process
275
 
  @param  length          length of given string
276
 
  @param  charset         charset of given string
277
 
 
278
 
  @return Error code
279
 
   @retval E_DEC_OK
280
 
   @retval E_DEC_TRUNCATED
281
 
   @retval E_DEC_OVERFLOW
282
 
   @retval E_DEC_BAD_NUM
283
 
   @retval E_DEC_OOM
284
 
*/
285
 
 
286
 
int type::Decimal::store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset)
287
 
{
288
 
  char *end, *from_end;
289
 
  int err;
290
 
  char buff[STRING_BUFFER_USUAL_SIZE];
291
 
  String tmp(buff, sizeof(buff), &my_charset_bin);
292
 
  if (charset->mbminlen > 1)
293
 
  {
294
 
    size_t dummy_errors;
295
 
    tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
296
 
    from= tmp.ptr();
297
 
    length=  tmp.length();
298
 
    charset= &my_charset_bin;
299
 
  }
300
 
  from_end= end= (char*) from+length;
301
 
  err= string2decimal((char *)from, (decimal_t*) this, &end);
302
 
  if (end != from_end && !err)
303
 
  {
304
 
    /* Give warning if there is something other than end space */
305
 
    for ( ; end < from_end; end++)
306
 
    {
307
 
      if (!my_isspace(&my_charset_utf8_general_ci, *end))
308
 
      {
309
 
        err= E_DEC_TRUNCATED;
310
 
        break;
311
 
      }
312
 
    }
313
 
  }
314
 
  check_result_and_overflow(mask, err);
315
 
  return err;
316
 
}
317
 
 
318
 
void type::Decimal::convert(double &result) const
319
 
{
320
 
  decimal2double(static_cast<const decimal_t*>(this), &result);
321
 
}
322
 
 
323
 
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec)
324
 
{
325
 
  int64_t date;
326
 
  date = (ltime->year*100L + ltime->month)*100L + ltime->day;
327
 
  if (ltime->time_type > type::DRIZZLE_TIMESTAMP_DATE)
328
 
    date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
329
 
 
330
 
  if (int2_class_decimal(E_DEC_FATAL_ERROR, date, false, dec))
331
 
    return dec;
332
 
 
333
 
  if (ltime->second_part)
334
 
  {
335
 
    dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
336
 
    dec->frac= 6;
337
 
  }
338
 
 
339
 
  return dec;
340
 
}
341
 
 
342
 
 
343
 
void class_decimal_trim(uint32_t *precision, uint32_t *scale)
344
 
{
345
 
  if (!(*precision) && !(*scale))
346
 
  {
347
 
    *precision= 10;
348
 
    *scale= 0;
349
 
    return;
350
 
  }
351
 
}
352
 
 
353
117
 
354
118
/*
355
119
  Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
373
137
#define DIG_MASK     100000000
374
138
#define DIG_BASE     1000000000
375
139
#define DIG_MAX      (DIG_BASE-1)
376
 
 
377
 
template<typename T> 
378
 
inline static T round_up(const T &x)
379
 
{
380
 
  return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
381
 
}
382
 
 
 
140
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
383
141
static const dec1 powers10[DIG_PER_DEC1+1]={
384
142
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
385
143
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
388
146
  999900000, 999990000, 999999000,
389
147
  999999900, 999999990 };
390
148
 
391
 
#ifdef HAVE_VALGRIND
 
149
#ifdef HAVE_purify
392
150
#define sanity(d) assert((d)->len > 0)
393
151
#else
394
152
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
395
153
                              (d)->buf[(d)->len-1] | 1))
396
154
#endif
397
155
 
398
 
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
399
 
{
400
 
  if (unlikely(intg1+frac1 > len))
401
 
  {
402
 
    if (unlikely(intg1 > len))
403
 
    {
404
 
      intg1=(len);
405
 
      frac1=0;
406
 
      error=E_DEC_OVERFLOW;
407
 
    }
408
 
    else
409
 
    {
410
 
      frac1=(len)-intg1;
411
 
      error=E_DEC_TRUNCATED;
412
 
    }
413
 
  }
414
 
  else
415
 
    error=E_DEC_OK;
416
 
}
417
 
 
418
 
/* assume carry <= 1 */
419
 
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
420
 
{
421
 
  dec1 a=from1+from2+carry;
422
 
  assert(carry <= 1);
423
 
  if ((carry= (a >= DIG_BASE))) /* no division here! */
424
 
    a-=DIG_BASE;
425
 
  to=a;
426
 
}
427
 
 
428
 
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
429
 
{
430
 
  dec2 a=dec2(from1)+from2+carry;
431
 
  if ((carry= (a >= DIG_BASE)))
432
 
    a-=DIG_BASE;
433
 
  if (unlikely(a >= DIG_BASE))
434
 
  {
435
 
    a-=DIG_BASE;
436
 
    carry++;
437
 
  }
438
 
  to=dec1(a);
439
 
}
440
 
 
441
 
/* to=from1-from2 */
442
 
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
443
 
{
444
 
  dec1 a=from1-from2-carry;
445
 
  if ((carry= (a < 0)))
446
 
    a+=DIG_BASE;
447
 
  to=a;
448
 
}
449
 
 
450
 
/* to=from1-from2 */
451
 
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
452
 
{
453
 
  dec1 a=from1-from2-carry;
454
 
  if ((carry= (a < 0)))
455
 
    a+=DIG_BASE;
456
 
  if (unlikely(a < 0))
457
 
  {
458
 
    a+=DIG_BASE;
459
 
    carry++;
460
 
  }
461
 
  to=a;
462
 
}
 
156
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error)                   \
 
157
        do                                                              \
 
158
        {                                                               \
 
159
          if (unlikely(intg1+frac1 > (len)))                            \
 
160
          {                                                             \
 
161
            if (unlikely(intg1 > (len)))                                \
 
162
            {                                                           \
 
163
              intg1=(len);                                              \
 
164
              frac1=0;                                                  \
 
165
              error=E_DEC_OVERFLOW;                                     \
 
166
            }                                                           \
 
167
            else                                                        \
 
168
            {                                                           \
 
169
              frac1=(len)-intg1;                                        \
 
170
              error=E_DEC_TRUNCATED;                                    \
 
171
            }                                                           \
 
172
          }                                                             \
 
173
          else                                                          \
 
174
            error=E_DEC_OK;                                             \
 
175
        } while(0)
 
176
 
 
177
#define ADD(to, from1, from2, carry)  /* assume carry <= 1 */           \
 
178
        do                                                              \
 
179
        {                                                               \
 
180
          dec1 a=(from1)+(from2)+(carry);                               \
 
181
          assert((carry) <= 1);                                    \
 
182
          if (((carry)= a >= DIG_BASE)) /* no division here! */         \
 
183
            a-=DIG_BASE;                                                \
 
184
          (to)=a;                                                       \
 
185
        } while(0)
 
186
 
 
187
#define ADD2(to, from1, from2, carry)                                   \
 
188
        do                                                              \
 
189
        {                                                               \
 
190
          dec2 a=((dec2)(from1))+(from2)+(carry);                       \
 
191
          if (((carry)= a >= DIG_BASE))                                 \
 
192
            a-=DIG_BASE;                                                \
 
193
          if (unlikely(a >= DIG_BASE))                                  \
 
194
          {                                                             \
 
195
            a-=DIG_BASE;                                                \
 
196
            carry++;                                                    \
 
197
          }                                                             \
 
198
          (to)=(dec1) a;                                                \
 
199
        } while(0)
 
200
 
 
201
#define SUB(to, from1, from2, carry) /* to=from1-from2 */               \
 
202
        do                                                              \
 
203
        {                                                               \
 
204
          dec1 a=(from1)-(from2)-(carry);                               \
 
205
          if (((carry)= a < 0))                                         \
 
206
            a+=DIG_BASE;                                                \
 
207
          (to)=a;                                                       \
 
208
        } while(0)
 
209
 
 
210
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */              \
 
211
        do                                                              \
 
212
        {                                                               \
 
213
          dec1 a=(from1)-(from2)-(carry);                               \
 
214
          if (((carry)= a < 0))                                         \
 
215
            a+=DIG_BASE;                                                \
 
216
          if (unlikely(a < 0))                                          \
 
217
          {                                                             \
 
218
            a+=DIG_BASE;                                                \
 
219
            carry++;                                                    \
 
220
          }                                                             \
 
221
          (to)=a;                                                       \
 
222
        } while(0)
463
223
 
464
224
/**
465
 
  @brief  Get maximum value for given precision and scale
466
 
 
467
 
  @param  precision/scale  see decimal_bin_size() below
468
 
  @param  to              decimal where where the result will be stored
 
225
  Swap the contents of two variables.
 
226
 */
 
227
#define swap_variables(TYPE, a, b) \
 
228
  do {                             \
 
229
    TYPE dummy;                    \
 
230
    dummy= a;                      \
 
231
    a= b;                          \
 
232
    b= dummy;                      \
 
233
  } while (0)
 
234
 
 
235
 
 
236
/*
 
237
  Get maximum value for given precision and scale
 
238
 
 
239
  SYNOPSIS
 
240
    max_decimal()
 
241
    precision/scale - see decimal_bin_size() below
 
242
    to              - decimal where where the result will be stored
469
243
                      to->buf and to->len must be set.
470
244
*/
471
245
 
496
270
}
497
271
 
498
272
 
499
 
static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
 
273
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
500
274
{
501
275
  int intg= from->intg, i;
502
276
  dec1 *buf0= from->buf;
519
293
}
520
294
 
521
295
 
522
 
/**
523
 
 @brief Count actual length of fraction part (without ending zeroes)
 
296
/*
 
297
  Count actual length of fraction part (without ending zeroes)
524
298
 
525
 
 @param from    number for processing
 
299
  SYNOPSIS
 
300
    decimal_actual_fraction()
 
301
    from    number for processing
526
302
*/
527
303
 
528
304
int decimal_actual_fraction(decimal_t *from)
529
305
{
530
306
  int frac= from->frac, i;
531
 
  dec1 *buf0= from->buf + round_up(from->intg) + round_up(frac) - 1;
 
307
  dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
532
308
 
533
309
  if (frac == 0)
534
310
    return 0;
548
324
}
549
325
 
550
326
 
551
 
/**
552
 
 @brief  Convert decimal to its printable string representation
 
327
/*
 
328
  Convert decimal to its printable string representation
553
329
 
554
 
 @param  from       value to convert
555
 
 @param  to         points to buffer where string representation
556
 
                    should be stored
557
 
 @param  to_len     in:  size of to buffer
558
 
                    out: length of the actually written string
559
 
 @param  fixed_precision 0 if representation can be variable length and
 
330
  SYNOPSIS
 
331
    decimal2string()
 
332
      from            - value to convert
 
333
      to              - points to buffer where string representation
 
334
                        should be stored
 
335
      *to_len         - in:  size of to buffer
 
336
                        out: length of the actually written string
 
337
      fixed_precision - 0 if representation can be variable length and
560
338
                        fixed_decimals will not be checked in this case.
561
339
                        Put number as with fixed point position with this
562
340
                        number of digits (sign counted and decimal point is
563
341
                        counted)
564
 
 @param  fixed_decimals  number digits after point.
565
 
 @param  filler          character to fill gaps in case of fixed_precision > 0
 
342
      fixed_decimals  - number digits after point.
 
343
      filler          - character to fill gaps in case of fixed_precision > 0
566
344
 
567
 
 @return error code
568
 
   @retval E_DEC_OK
569
 
   @retval E_DEC_TRUNCATED
570
 
   @retval E_DEC_OVERFLOW
 
345
  RETURN VALUE
 
346
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
571
347
*/
572
 
int decimal2string(const decimal_t *from, char *to, int *to_len,
 
348
 
 
349
int decimal2string(decimal_t *from, char *to, int *to_len,
573
350
                   int fixed_precision, int fixed_decimals,
574
351
                   char filler)
575
352
{
633
410
  {
634
411
    char *s1= s + intg_len;
635
412
    fill= frac_len - frac;
636
 
    buf=buf0+round_up(intg);
 
413
    buf=buf0+ROUND_UP(intg);
637
414
    *s1++='.';
638
415
    for (; frac>0; frac-=DIG_PER_DEC1)
639
416
    {
658
435
  if (intg)
659
436
  {
660
437
    s+=intg;
661
 
    for (buf=buf0+round_up(intg); intg>0; intg-=DIG_PER_DEC1)
 
438
    for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
662
439
    {
663
440
      dec1 x=*--buf;
664
441
      for (i=min(intg, DIG_PER_DEC1); i; i--)
675
452
}
676
453
 
677
454
 
678
 
/**
679
 
 @brief  Return bounds of decimal digits in the number
 
455
/*
 
456
  Return bounds of decimal digits in the number
680
457
 
681
 
 @param  from  decimal number for processing
682
 
 @param  start_result  index (from 0 ) of first decimal digits will
683
 
                       be written by this address
684
 
 @param  end_result   index of position just after last decimal digit
 
458
  SYNOPSIS
 
459
    digits_bounds()
 
460
      from         - decimal number for processing
 
461
      start_result - index (from 0 ) of first decimal digits will
 
462
                     be written by this address
 
463
      end_result   - index of position just after last decimal digit
685
464
                     be written by this address
686
465
*/
 
466
 
687
467
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
688
468
{
689
469
  int start, stop, i;
690
470
  dec1 *buf_beg= from->buf;
691
 
  dec1 *end= from->buf + round_up(from->intg) + round_up(from->frac);
 
471
  dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
692
472
  dec1 *buf_end= end - 1;
693
473
 
694
474
  /* find non-zero digit from number begining */
737
517
}
738
518
 
739
519
 
740
 
/**
741
 
 @param Left shift for alignment of data in buffer
742
 
 
743
 
 @param  dec     pointer to decimal number which have to be shifted
744
 
 @param  shift   number of decimal digits on which it should be shifted
745
 
 @param  beg     beginning of decimal digits (see digits_bounds())
746
 
 @param  end     end of decimal digits (see digits_bounds())
747
 
 
748
 
 @note
749
 
   Result fitting in the buffer should be garanted.
750
 
   'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
751
 
   
752
 
 @todo  Above note is unclear - is 'garanted' a typo for 'guaranteed'
753
 
 or 'granted'?
 
520
/*
 
521
  Left shift for alignment of data in buffer
 
522
 
 
523
  SYNOPSIS
 
524
    do_mini_left_shift()
 
525
    dec     pointer to decimal number which have to be shifted
 
526
    shift   number of decimal digits on which it should be shifted
 
527
    beg/end bounds of decimal digits (see digits_bounds())
 
528
 
 
529
  NOTE
 
530
    Result fitting in the buffer should be garanted.
 
531
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
754
532
*/
 
533
 
755
534
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
756
535
{
757
 
  dec1 *from= dec->buf + round_up(beg + 1) - 1;
758
 
  dec1 *end= dec->buf + round_up(last) - 1;
 
536
  dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
 
537
  dec1 *end= dec->buf + ROUND_UP(last) - 1;
759
538
  int c_shift= DIG_PER_DEC1 - shift;
760
539
  assert(from >= dec->buf);
761
540
  assert(end < dec->buf + dec->len);
768
547
}
769
548
 
770
549
 
771
 
/**
772
 
  @brief Right shift for alignment of data in buffer
773
 
 
774
 
  @param  dec     pointer to decimal number which have to be shifted
775
 
  @param  shift   number of decimal digits on which it should be shifted
776
 
  @param  beg     beginning of decimal digits (see digits_bounds())
777
 
  @param  end     end of decimal digits (see digits_bounds())
778
 
 
779
 
  @note
 
550
/*
 
551
  Right shift for alignment of data in buffer
 
552
 
 
553
  SYNOPSIS
 
554
    do_mini_left_shift()
 
555
    dec     pointer to decimal number which have to be shifted
 
556
    shift   number of decimal digits on which it should be shifted
 
557
    beg/end bounds of decimal digits (see digits_bounds())
 
558
 
 
559
  NOTE
780
560
    Result fitting in the buffer should be garanted.
781
561
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
782
562
*/
 
563
 
783
564
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
784
565
{
785
 
  dec1 *from= dec->buf + round_up(last) - 1;
786
 
  dec1 *end= dec->buf + round_up(beg + 1) - 1;
 
566
  dec1 *from= dec->buf + ROUND_UP(last) - 1;
 
567
  dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
787
568
  int c_shift= DIG_PER_DEC1 - shift;
788
569
  assert(from < dec->buf + dec->len);
789
570
  assert(end >= dec->buf);
796
577
}
797
578
 
798
579
 
799
 
/**
800
 
  @brief  Shift of decimal digits in given number (with rounding if it need)
 
580
/*
 
581
  Shift of decimal digits in given number (with rounding if it need)
801
582
 
802
 
  @param  dec       number to be shifted
803
 
  @param  shift     number of decimal positions
 
583
  SYNOPSIS
 
584
    decimal_shift()
 
585
    dec       number to be shifted
 
586
    shift     number of decimal positions
804
587
              shift > 0 means shift to left shift
805
588
              shift < 0 meand right shift
806
 
 
807
 
  @note
 
589
  NOTE
808
590
    In fact it is multipling on 10^shift.
 
591
  RETURN
 
592
    E_DEC_OK          OK
 
593
    E_DEC_OVERFLOW    operation lead to overflow, number is untoched
 
594
    E_DEC_TRUNCATED   number was rounded to fit into buffer
 
595
*/
809
596
 
810
 
  @return  Error code
811
 
   @retval E_DEC_OK          OK
812
 
   @retval E_DEC_OVERFLOW    operation lead to overflow, number is untoched
813
 
   @retval E_DEC_TRUNCATED   number was rounded to fit into buffer
814
 
*/
815
597
static int decimal_shift(decimal_t *dec, int shift)
816
598
{
817
599
  /* index of first non zero digit (all indexes from 0) */
819
601
  /* index of position after last decimal digit */
820
602
  int end;
821
603
  /* index of digit position just after point */
822
 
  int point= round_up(dec->intg) * DIG_PER_DEC1;
 
604
  int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
823
605
  /* new point position */
824
606
  int new_point= point + shift;
825
607
  /* number of digits in result */
837
619
 
838
620
  if (beg == end)
839
621
  {
840
 
    dec->set_zero();
 
622
    decimal_make_zero(dec);
841
623
    return E_DEC_OK;
842
624
  }
843
625
 
846
628
  digits_frac= end - new_point;
847
629
  set_if_bigger(digits_frac, 0);
848
630
 
849
 
  if ((new_len= round_up(digits_int) + (new_frac_len= round_up(digits_frac))) >
 
631
  if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
850
632
      dec->len)
851
633
  {
852
634
    int lack= new_len - dec->len;
870
652
        we lost all digits (they will be shifted out of buffer), so we can
871
653
        just return 0
872
654
      */
873
 
      dec->set_zero();
874
 
 
 
655
      decimal_make_zero(dec);
875
656
      return E_DEC_TRUNCATED;
876
657
    }
877
658
  }
907
688
    if (do_left)
908
689
    {
909
690
      do_mini_left_shift(dec, l_mini_shift, beg, end);
910
 
      mini_shift= (-l_mini_shift);
 
691
      mini_shift=- l_mini_shift;
911
692
    }
912
693
    else
913
694
    {
940
721
    {
941
722
      /* move left */
942
723
      d_shift= new_front / DIG_PER_DEC1;
943
 
      to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
944
 
      barier= dec->buf + (round_up(end) - 1 - d_shift);
 
724
      to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
 
725
      barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
945
726
      assert(to >= dec->buf);
946
727
      assert(barier + d_shift < dec->buf + dec->len);
947
728
      for(; to <= barier; to++)
954
735
    {
955
736
      /* move right */
956
737
      d_shift= (1 - new_front) / DIG_PER_DEC1;
957
 
      to= dec->buf + round_up(end) - 1 + d_shift;
958
 
      barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
 
738
      to= dec->buf + ROUND_UP(end) - 1 + d_shift;
 
739
      barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
959
740
      assert(to < dec->buf + dec->len);
960
741
      assert(barier - d_shift >= dec->buf);
961
742
      for(; to >= barier; to--)
974
755
 
975
756
    Only one of following 'for' loops will work becouse beg <= end
976
757
  */
977
 
  beg= round_up(beg + 1) - 1;
978
 
  end= round_up(end) - 1;
 
758
  beg= ROUND_UP(beg + 1) - 1;
 
759
  end= ROUND_UP(end) - 1;
979
760
  assert(new_point >= 0);
980
761
 
981
762
  /* We don't want negative new_point below */
982
763
  if (new_point != 0)
983
 
    new_point= round_up(new_point) - 1;
 
764
    new_point= ROUND_UP(new_point) - 1;
984
765
 
985
766
  if (new_point > end)
986
767
  {
1000
781
}
1001
782
 
1002
783
 
1003
 
/**
1004
 
  @brief  Convert string to decimal
 
784
/*
 
785
  Convert string to decimal
1005
786
 
1006
 
  @param  from    value to convert. Doesn't have to be \0 terminated!
1007
 
  @param  to      decimal where where the result will be stored
 
787
  SYNOPSIS
 
788
    internal_str2decl()
 
789
      from    - value to convert. Doesn't have to be \0 terminated!
 
790
      to      - decimal where where the result will be stored
1008
791
                to->buf and to->len must be set.
1009
 
  @param  end     Pointer to pointer to end of string. Will on return be
 
792
      end     - Pointer to pointer to end of string. Will on return be
1010
793
                set to the char after the last used character
1011
 
  @param  fixed   use to->intg, to->frac as limits for input number
 
794
      fixed   - use to->intg, to->frac as limits for input number
1012
795
 
1013
 
  @note
 
796
  NOTE
1014
797
    to->intg and to->frac can be modified even when fixed=1
1015
798
    (but only decreased, in this case)
1016
799
 
1017
 
  @return
 
800
  RETURN VALUE
1018
801
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
1019
802
    In case of E_DEC_FATAL_ERROR *to is set to decimal zero
1020
803
    (to make error handling easier)
1021
804
*/
 
805
 
1022
806
int
1023
807
internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
1024
808
{
1075
859
      error=E_DEC_OVERFLOW;
1076
860
      intg=to->intg;
1077
861
    }
1078
 
    intg1=round_up(intg);
1079
 
    frac1=round_up(frac);
 
862
    intg1=ROUND_UP(intg);
 
863
    frac1=ROUND_UP(frac);
1080
864
    if (intg1+frac1 > to->len)
1081
865
    {
1082
866
      error= E_DEC_OOM;
1085
869
  }
1086
870
  else
1087
871
  {
1088
 
    intg1=round_up(intg);
1089
 
    frac1=round_up(frac);
1090
 
    fix_intg_frac_error(to->len, intg1, frac1, error);
 
872
    intg1=ROUND_UP(intg);
 
873
    frac1=ROUND_UP(frac);
 
874
    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1091
875
    if (unlikely(error))
1092
876
    {
1093
877
      frac=frac1*DIG_PER_DEC1;
1135
919
  if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
1136
920
  {
1137
921
    int str_error;
1138
 
    const int64_t exponent= internal::my_strtoll10(endp+1, (char**) &end_of_string,
1139
 
                                                   &str_error);
 
922
    const int64_t exponent= my_strtoll10(endp+1, (char**) &end_of_string,
 
923
                                    &str_error);
1140
924
 
1141
925
    if (end_of_string != endp +1)               /* If at least one digit */
1142
926
    {
1163
947
  return error;
1164
948
 
1165
949
fatal_error:
1166
 
  to->set_zero();
 
950
  decimal_make_zero(to);
1167
951
  return error;
1168
952
}
1169
953
 
1170
954
 
1171
 
/**
1172
 
  @param Convert decimal to double
1173
 
 
1174
 
  @param[in]   from   value to convert
1175
 
  @param[out]  to     result will be stored there
1176
 
 
1177
 
  @return
 
955
/*
 
956
  Convert decimal to double
 
957
 
 
958
  SYNOPSIS
 
959
    decimal2double()
 
960
      from    - value to convert
 
961
      to      - result will be stored there
 
962
 
 
963
  RETURN VALUE
1178
964
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1179
965
*/
1180
966
 
1181
 
int decimal2double(const decimal_t *from, double *to)
 
967
int decimal2double(decimal_t *from, double *to)
1182
968
{
1183
969
  char strbuf[FLOATING_POINT_BUFFER], *end;
1184
970
  int len= sizeof(strbuf);
1187
973
  rc = decimal2string(from, strbuf, &len, 0, 0, 0);
1188
974
  end= strbuf + len;
1189
975
 
1190
 
  *to= internal::my_strtod(strbuf, &end, &error);
 
976
  *to= my_strtod(strbuf, &end, &error);
1191
977
 
1192
978
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
1193
979
}
1194
980
 
1195
 
/**
1196
 
 @param  Convert double to decimal
1197
 
 
1198
 
 @param[in]  from    value to convert
1199
 
 @param[out] to      result will be stored there
1200
 
 
1201
 
 @return
 
981
/*
 
982
  Convert double to decimal
 
983
 
 
984
  SYNOPSIS
 
985
    double2decimal()
 
986
      from    - value to convert
 
987
      to      - result will be stored there
 
988
 
 
989
  RETURN VALUE
1202
990
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1203
991
*/
1204
992
 
1205
 
int double2decimal(const double from, decimal_t *to)
 
993
int double2decimal(double from, decimal_t *to)
1206
994
{
1207
995
  char buff[FLOATING_POINT_BUFFER], *end;
1208
996
  int res;
1209
 
  end= buff + internal::my_gcvt(from,
1210
 
                                internal::MY_GCVT_ARG_DOUBLE,
1211
 
                                sizeof(buff) - 1, buff, NULL);
 
997
  end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
1212
998
  res= string2decimal(buff, to, &end);
1213
999
  return(res);
1214
1000
}
1240
1026
  return error;
1241
1027
}
1242
1028
 
1243
 
int uint64_t2decimal(const uint64_t from, decimal_t *to)
 
1029
int uint64_t2decimal(uint64_t from, decimal_t *to)
1244
1030
{
1245
1031
  to->sign=0;
1246
1032
  return ull2dec(from, to);
1247
1033
}
1248
1034
 
1249
 
int int64_t2decimal(const int64_t from, decimal_t *to)
 
1035
int int64_t2decimal(int64_t from, decimal_t *to)
1250
1036
{
1251
1037
  if ((to->sign= from < 0))
1252
1038
    return ull2dec(-from, to);
1253
1039
  return ull2dec(from, to);
1254
1040
}
1255
1041
 
1256
 
int decimal2uint64_t(const decimal_t *from, uint64_t *to)
 
1042
int decimal2uint64_t(decimal_t *from, uint64_t *to)
1257
1043
{
1258
1044
  dec1 *buf=from->buf;
1259
1045
  uint64_t x=0;
1282
1068
  return E_DEC_OK;
1283
1069
}
1284
1070
 
1285
 
int decimal2int64_t(const decimal_t *from, int64_t *to)
 
1071
int decimal2int64_t(decimal_t *from, int64_t *to)
1286
1072
{
1287
1073
  dec1 *buf=from->buf;
1288
1074
  int64_t x=0;
1322
1108
  return E_DEC_OK;
1323
1109
}
1324
1110
 
1325
 
/**
1326
 
 @brief
1327
 
  Convert decimal to its binary fixed-length representation (suitable for
1328
 
  comparing with memcmp)
1329
 
 
 
1111
/*
 
1112
  Convert decimal to its binary fixed-length representation
 
1113
  two representations of the same length can be compared with memcmp
 
1114
  with the correct -1/0/+1 result
 
1115
 
 
1116
  SYNOPSIS
 
1117
    decimal2bin()
 
1118
      from    - value to convert
 
1119
      to      - points to buffer where string representation should be stored
 
1120
      precision/scale - see decimal_bin_size() below
 
1121
 
 
1122
  NOTE
 
1123
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
 
1124
 
 
1125
  RETURN VALUE
 
1126
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
 
1127
 
 
1128
  DESCRIPTION
1330
1129
    for storage decimal numbers are converted to the "binary" format.
1331
1130
 
1332
1131
    This format has the following properties:
1387
1186
    And for -1234567890.1234 it would be
1388
1187
 
1389
1188
                7E F2 04 37 2D FB 2D
1390
 
 
1391
 
 
1392
 
  @param from      value to convert
1393
 
  @param to        points to buffer where string representation should be stored
1394
 
  @param precision see decimal_bin_size() below
1395
 
  @param frac      see decimal_bin_size() below
1396
 
 
1397
 
  @note
1398
 
    The buffer is assumed to be of the size decimal_bin_size(precision, scale)
1399
 
 
1400
 
  @return
1401
 
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1402
 
 
1403
1189
*/
1404
 
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
 
1190
int decimal2bin(decimal_t *from, unsigned char *to, int precision, int frac)
1405
1191
{
1406
1192
  dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1407
1193
  int error=E_DEC_OK, intg=precision-frac,
1519
1305
  return error;
1520
1306
}
1521
1307
 
1522
 
/**
1523
 
 @brief Restores decimal from its binary fixed-length representation
1524
 
 
1525
 
 @param  from    value to convert
1526
 
 @param  to      result
1527
 
 @param  precision see decimal_bin_size() below
1528
 
 @param  scale     see decimal_bin_size() below
1529
 
 
1530
 
 @note
 
1308
/*
 
1309
  Restores decimal from its binary fixed-length representation
 
1310
 
 
1311
  SYNOPSIS
 
1312
    bin2decimal()
 
1313
      from    - value to convert
 
1314
      to      - result
 
1315
      precision/scale - see decimal_bin_size() below
 
1316
 
 
1317
  NOTE
1531
1318
    see decimal2bin()
1532
1319
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1533
1320
 
1534
 
 @return
 
1321
  RETURN VALUE
1535
1322
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1536
1323
*/
 
1324
 
1537
1325
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1538
1326
{
1539
1327
  int error=E_DEC_OK, intg=precision-scale,
1551
1339
  d_copy[0]^= 0x80;
1552
1340
  from= d_copy;
1553
1341
 
1554
 
  fix_intg_frac_error(to->len, intg1, frac1, error);
 
1342
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1555
1343
  if (unlikely(error))
1556
1344
  {
1557
1345
    if (intg1 < intg0+(intg0x>0))
1632
1420
  return error;
1633
1421
 
1634
1422
err:
1635
 
  to->set_zero();
 
1423
  decimal_make_zero(((decimal_t*) to));
1636
1424
  return(E_DEC_BAD_NUM);
1637
1425
}
1638
1426
 
1639
 
/**
1640
 
 @brief  Returns the size of array to hold a binary representation of a decimal
1641
 
 
1642
 
 @return  Size in bytes
1643
 
*/
 
1427
/*
 
1428
  Returns the size of array to hold a decimal with given precision and scale
 
1429
 
 
1430
  RETURN VALUE
 
1431
    size in dec1
 
1432
    (multiply by sizeof(dec1) to get the size if bytes)
 
1433
*/
 
1434
 
 
1435
int decimal_size(int precision, int scale)
 
1436
{
 
1437
  assert(scale >= 0 && precision > 0 && scale <= precision);
 
1438
  return ROUND_UP(precision-scale)+ROUND_UP(scale);
 
1439
}
 
1440
 
 
1441
/*
 
1442
  Returns the size of array to hold a binary representation of a decimal
 
1443
 
 
1444
  RETURN VALUE
 
1445
    size in bytes
 
1446
*/
 
1447
 
1644
1448
int decimal_bin_size(int precision, int scale)
1645
1449
{
1646
1450
  int intg=precision-scale,
1652
1456
         frac0*sizeof(dec1)+dig2bytes[frac0x];
1653
1457
}
1654
1458
 
1655
 
/**
1656
 
 @brief  Rounds the decimal to "scale" digits
1657
 
 
1658
 
 @param from    - decimal to round,
1659
 
 @param to      - result buffer. from==to is allowed
1660
 
 @param scale   - to what position to round. can be negative!
1661
 
 @param mode    - round to nearest even or truncate
1662
 
 
1663
 
 @note
 
1459
/*
 
1460
  Rounds the decimal to "scale" digits
 
1461
 
 
1462
  SYNOPSIS
 
1463
    decimal_round()
 
1464
      from    - decimal to round,
 
1465
      to      - result buffer. from==to is allowed
 
1466
      scale   - to what position to round. can be negative!
 
1467
      mode    - round to nearest even or truncate
 
1468
 
 
1469
  NOTES
1664
1470
    scale can be negative !
1665
1471
    one TRUNCATED error (line XXX below) isn't treated very logical :(
1666
1472
 
1667
 
 @return
 
1473
  RETURN VALUE
1668
1474
    E_DEC_OK/E_DEC_TRUNCATED
1669
1475
*/
 
1476
 
1670
1477
int
1671
 
decimal_round(const decimal_t *from, decimal_t *to, int scale,
 
1478
decimal_round(decimal_t *from, decimal_t *to, int scale,
1672
1479
              decimal_round_mode mode)
1673
1480
{
1674
 
  int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
1675
 
      frac1=round_up(from->frac), round_digit= 0,
1676
 
      intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
1677
 
      intg1=round_up(from->intg +
 
1481
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
 
1482
      frac1=ROUND_UP(from->frac), round_digit= 0,
 
1483
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
 
1484
      intg1=ROUND_UP(from->intg +
1678
1485
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1679
1486
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1680
1487
  int first_dig;
1699
1506
 
1700
1507
  if (scale+from->intg < 0)
1701
1508
  {
1702
 
    to->set_zero();
 
1509
    decimal_make_zero(to);
1703
1510
    return E_DEC_OK;
1704
1511
  }
1705
1512
 
1770
1577
    }
1771
1578
    else if (frac0+intg0==0)
1772
1579
    {
1773
 
      to->set_zero();
 
1580
      decimal_make_zero(to);
1774
1581
      return E_DEC_OK;
1775
1582
    }
1776
1583
  }
1777
1584
  else
1778
1585
  {
1779
 
  /** @todo fix this code as it won't work for CEILING mode */
 
1586
    /* TODO - fix this code as it won't work for CEILING mode */
1780
1587
    int pos=frac0*DIG_PER_DEC1-scale-1;
1781
1588
    assert(frac0+intg0 > 0);
1782
1589
    x=*buf1 / powers10[pos];
1809
1616
    carry=1;
1810
1617
    *buf1-=DIG_BASE;
1811
1618
    while (carry && --buf1 >= to->buf)
1812
 
      add(*buf1, *buf1, 0, carry);
 
1619
      ADD(*buf1, *buf1, 0, carry);
1813
1620
    if (unlikely(carry))
1814
1621
    {
1815
1622
      /* shifting the number to create space for new digit */
1860
1667
  return error;
1861
1668
}
1862
1669
 
1863
 
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1864
 
{
1865
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1866
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
 
1670
/*
 
1671
  Returns the size of the result of the operation
 
1672
 
 
1673
  SYNOPSIS
 
1674
    decimal_result_size()
 
1675
      from1   - operand of the unary operation or first operand of the
 
1676
                binary operation
 
1677
      from2   - second operand of the binary operation
 
1678
      op      - operation. one char '+', '-', '*', '/' are allowed
 
1679
                others may be added later
 
1680
      param   - extra param to the operation. unused for '+', '-', '*'
 
1681
                scale increment for '/'
 
1682
 
 
1683
  NOTE
 
1684
    returned valued may be larger than the actual buffer requred
 
1685
    in the operation, as decimal_result_size, by design, operates on
 
1686
    precision/scale values only and not on the actual decimal number
 
1687
 
 
1688
  RETURN VALUE
 
1689
    size of to->buf array in dec1 elements. to get size in bytes
 
1690
    multiply by sizeof(dec1)
 
1691
*/
 
1692
 
 
1693
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
 
1694
{
 
1695
  switch (op) {
 
1696
  case '-':
 
1697
    return ROUND_UP(max(from1->intg, from2->intg)) +
 
1698
           ROUND_UP(max(from1->frac, from2->frac));
 
1699
  case '+':
 
1700
    return ROUND_UP(max(from1->intg, from2->intg)+1) +
 
1701
           ROUND_UP(max(from1->frac, from2->frac));
 
1702
  case '*':
 
1703
    return ROUND_UP(from1->intg+from2->intg)+
 
1704
           ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
 
1705
  case '/':
 
1706
    return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
 
1707
  default: assert(0);
 
1708
  }
 
1709
  return -1; /* shut up the warning */
 
1710
}
 
1711
 
 
1712
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
 
1713
{
 
1714
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1715
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1867
1716
      frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1868
1717
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1869
1718
 
1879
1728
    to->buf[0]=0; /* safety */
1880
1729
  }
1881
1730
 
1882
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
1731
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1883
1732
  if (unlikely(error == E_DEC_OVERFLOW))
1884
1733
  {
1885
1734
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1922
1771
  carry=0;
1923
1772
  while (buf1 > stop2)
1924
1773
  {
1925
 
    add(*--buf0, *--buf1, *--buf2, carry);
 
1774
    ADD(*--buf0, *--buf1, *--buf2, carry);
1926
1775
  }
1927
1776
 
1928
1777
  /* part 3 - cmin(intg) ... cmax(intg) */
1930
1779
                        ((stop=from2->buf)+intg2-intg1) ;
1931
1780
  while (buf1 > stop)
1932
1781
  {
1933
 
    add(*--buf0, *--buf1, 0, carry);
 
1782
    ADD(*--buf0, *--buf1, 0, carry);
1934
1783
  }
1935
1784
 
1936
1785
  if (unlikely(carry))
1942
1791
 
1943
1792
/* to=from1-from2.
1944
1793
   if to==0, return -1/0/+1 - the result of the comparison */
1945
 
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1794
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1946
1795
{
1947
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1948
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac);
 
1796
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1797
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1949
1798
  int frac0=max(frac1, frac2), error;
1950
1799
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1951
1800
 
1995
1844
      {
1996
1845
        if (to == 0) /* decimal_cmp() */
1997
1846
          return 0;
1998
 
 
1999
 
        to->set_zero();
2000
 
 
 
1847
        decimal_make_zero(to);
2001
1848
        return E_DEC_OK;
2002
1849
      }
2003
1850
    }
2013
1860
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
2014
1861
  if (carry)
2015
1862
  {
2016
 
    swap(from1, from2);
2017
 
    swap(start1, start2);
2018
 
    swap(intg1, intg2);
2019
 
    swap(frac1, frac2);
 
1863
    swap_variables(decimal_t *,from1,from1);
 
1864
    swap_variables(dec1 *,start1, start2);
 
1865
    swap_variables(int,intg1,intg2);
 
1866
    swap_variables(int,frac1,frac2);
2020
1867
    to->sign= 1 - to->sign;
2021
1868
  }
2022
1869
 
2023
 
  fix_intg_frac_error(to->len, intg1, frac0, error);
 
1870
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
2024
1871
  buf0=to->buf+intg1+frac0;
2025
1872
 
2026
1873
  to->frac=max(from1->frac, from2->frac);
2054
1901
      *--buf0=0;
2055
1902
    while (buf2 > stop2)
2056
1903
    {
2057
 
      sub(*--buf0, 0, *--buf2, carry);
 
1904
      SUB(*--buf0, 0, *--buf2, carry);
2058
1905
    }
2059
1906
  }
2060
1907
 
2061
1908
  /* part 2 - cmin(frac) ... intg2 */
2062
1909
  while (buf2 > start2)
2063
1910
  {
2064
 
    sub(*--buf0, *--buf1, *--buf2, carry);
 
1911
    SUB(*--buf0, *--buf1, *--buf2, carry);
2065
1912
  }
2066
1913
 
2067
1914
  /* part 3 - intg2 ... intg1 */
2068
1915
  while (carry && buf1 > start1)
2069
1916
  {
2070
 
    sub(*--buf0, *--buf1, 0, carry);
 
1917
    SUB(*--buf0, *--buf1, 0, carry);
2071
1918
  }
2072
1919
 
2073
1920
  while (buf1 > start1)
2079
1926
  return error;
2080
1927
}
2081
1928
 
2082
 
int decimal_intg(const decimal_t *from)
 
1929
int decimal_intg(decimal_t *from)
2083
1930
{
2084
1931
  int res;
2085
1932
  dec1 *tmp_res;
2087
1934
  return res;
2088
1935
}
2089
1936
 
2090
 
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1937
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
2091
1938
{
2092
1939
  if (likely(from1->sign == from2->sign))
2093
1940
    return do_add(from1, from2, to);
2094
1941
  return do_sub(from1, from2, to);
2095
1942
}
2096
1943
 
2097
 
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1944
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
2098
1945
{
2099
1946
  if (likely(from1->sign == from2->sign))
2100
1947
    return do_sub(from1, from2, to);
2101
1948
  return do_add(from1, from2, to);
2102
1949
}
2103
1950
 
2104
 
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
 
1951
int decimal_cmp(decimal_t *from1, decimal_t *from2)
2105
1952
{
2106
1953
  if (likely(from1->sign == from2->sign))
2107
1954
    return do_sub(from1, from2, 0);
2108
1955
  return from1->sign > from2->sign ? -1 : 1;
2109
1956
}
2110
1957
 
2111
 
int decimal_t::isZero() const
 
1958
int decimal_is_zero(decimal_t *from)
2112
1959
{
2113
 
  dec1 *buf1= buf,
2114
 
       *end= buf1 +round_up(intg) +round_up(frac);
2115
 
 
 
1960
  dec1 *buf1=from->buf,
 
1961
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2116
1962
  while (buf1 < end)
2117
 
  {
2118
1963
    if (*buf1++)
2119
 
    {
2120
1964
      return 0;
2121
 
    }
2122
 
  }
2123
 
 
2124
1965
  return 1;
2125
1966
}
2126
1967
 
2127
 
/**
2128
 
 @brief multiply two decimals
2129
 
 
2130
 
 @param[in]   from1  First factor
2131
 
 @param[in]   from2  Second factor
2132
 
 @param[out]  to     product
2133
 
 
2134
 
 @return
 
1968
/*
 
1969
  multiply two decimals
 
1970
 
 
1971
  SYNOPSIS
 
1972
    decimal_mul()
 
1973
      from1, from2 - factors
 
1974
      to      - product
 
1975
 
 
1976
  RETURN VALUE
2135
1977
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
2136
1978
 
2137
 
 @note
 
1979
  NOTES
2138
1980
    in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
2139
1981
    and 63-digit number will take only 7 dec1 words (basically a 7-digit
2140
1982
    "base 999999999" number).  Thus there's no need in fast multiplication
2144
1986
    XXX if this library is to be used with huge numbers of thousands of
2145
1987
    digits, fast multiplication must be implemented.
2146
1988
*/
2147
 
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1989
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
2148
1990
{
2149
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
2150
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
2151
 
      intg0=round_up(from1->intg+from2->intg),
 
1991
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1992
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
 
1993
      intg0=ROUND_UP(from1->intg+from2->intg),
2152
1994
      frac0=frac1+frac2, error, i, j, d_to_move;
2153
1995
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2154
1996
       *start2, *stop2, *stop1, *start0, carry;
2157
1999
 
2158
2000
  i=intg0;
2159
2001
  j=frac0;
2160
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
2002
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2161
2003
  to->sign=from1->sign != from2->sign;
2162
2004
  to->frac=from1->frac+from2->frac;
2163
2005
  to->intg=intg0*DIG_PER_DEC1;
2198
2040
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2199
2041
      hi=(dec1)(p/DIG_BASE);
2200
2042
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2201
 
      add2(*buf0, *buf0, lo, carry);
 
2043
      ADD2(*buf0, *buf0, lo, carry);
2202
2044
      carry+=hi;
2203
2045
    }
2204
2046
    if (carry)
2205
2047
    {
2206
2048
      if (buf0 < to->buf)
2207
2049
        return E_DEC_OVERFLOW;
2208
 
      add2(*buf0, *buf0, 0, carry);
 
2050
      ADD2(*buf0, *buf0, 0, carry);
2209
2051
    }
2210
2052
    for (buf0--; carry; buf0--)
2211
2053
    {
2212
2054
      if (buf0 < to->buf)
2213
2055
        return E_DEC_OVERFLOW;
2214
 
      add(*buf0, *buf0, 0, carry);
 
2056
      ADD(*buf0, *buf0, 0, carry);
2215
2057
    }
2216
2058
  }
2217
2059
 
2228
2070
      if (++buf == end)
2229
2071
      {
2230
2072
        /* We got decimal zero */
2231
 
        to->set_zero();
 
2073
        decimal_make_zero(to);
2232
2074
        break;
2233
2075
      }
2234
2076
    }
2235
2077
  }
2236
2078
  buf1= to->buf;
2237
 
  d_to_move= intg0 + round_up(to->frac);
 
2079
  d_to_move= intg0 + ROUND_UP(to->frac);
2238
2080
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2239
2081
  {
2240
2082
    buf1++;
2250
2092
  return error;
2251
2093
}
2252
2094
 
2253
 
/**
 
2095
/*
2254
2096
  naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2255
2097
  it's ok for short numbers
2256
2098
  also we're using alloca() to allocate a temporary buffer
2257
2099
 
2258
 
  @todo
2259
 
  If this library is to be used with huge numbers of thousands of
 
2100
  XXX if this library is to be used with huge numbers of thousands of
2260
2101
  digits, fast division must be implemented and alloca should be
2261
2102
  changed to malloc (or at least fallback to malloc if alloca() fails)
2262
2103
  but then, decimal_mul() should be rewritten too :(
2263
2104
*/
2264
 
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
 
2105
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2265
2106
                       decimal_t *to, decimal_t *mod, int scale_incr)
2266
2107
{
2267
 
  int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2268
 
      frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
 
2108
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
 
2109
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2269
2110
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2270
2111
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2271
2112
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2298
2139
  }
2299
2140
  if (prec1 <= 0)
2300
2141
  { /* short-circuit everything: from1 == 0 */
2301
 
    to->set_zero();
 
2142
    decimal_make_zero(to);
2302
2143
    return E_DEC_OK;
2303
2144
  }
2304
2145
  for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2315
2156
    intg0=0;
2316
2157
  }
2317
2158
  else
2318
 
    intg0=round_up(dintg);
 
2159
    intg0=ROUND_UP(dintg);
2319
2160
  if (mod)
2320
2161
  {
2321
2162
    /* we're calculating N1 % N2.
2334
2175
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2335
2176
      frac2 accordingly.
2336
2177
      Thus, the result will have
2337
 
         frac = round_up(frac1+frac2+scale_incr)
 
2178
         frac = ROUND_UP(frac1+frac2+scale_incr)
2338
2179
      and
2339
2180
         intg = (prec1-frac1) - (prec2-frac2) + 1
2340
2181
         prec = intg+frac
2341
2182
    */
2342
 
    frac0=round_up(frac1+frac2+scale_incr);
2343
 
    fix_intg_frac_error(to->len, intg0, frac0, error);
 
2183
    frac0=ROUND_UP(frac1+frac2+scale_incr);
 
2184
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2344
2185
    to->sign=from1->sign != from2->sign;
2345
2186
    to->intg=intg0*DIG_PER_DEC1;
2346
2187
    to->frac=frac0*DIG_PER_DEC1;
2351
2192
    while (dintg++ < 0)
2352
2193
      *buf0++=0;
2353
2194
 
2354
 
  len1=(i=round_up(prec1))+round_up(2*frac2+scale_incr+1) + 1;
 
2195
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2355
2196
  set_if_bigger(len1, 3);
2356
2197
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
2357
2198
    return E_DEC_OOM;
2361
2202
  start1=tmp1;
2362
2203
  stop1=start1+len1;
2363
2204
  start2=buf2;
2364
 
  stop2=buf2+round_up(prec2)-1;
 
2205
  stop2=buf2+ROUND_UP(prec2)-1;
2365
2206
 
2366
2207
  /* removing end zeroes */
2367
2208
  while (*stop2 == 0 && stop2 >= start2)
2420
2261
        x=guess * (*--buf2);
2421
2262
        hi=(dec1)(x/DIG_BASE);
2422
2263
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2423
 
        sub2(*buf1, *buf1, lo, carry);
 
2264
        SUB2(*buf1, *buf1, lo, carry);
2424
2265
        carry+=hi;
2425
2266
      }
2426
2267
      carry= dcarry < carry;
2434
2275
        buf1=start1+len2;
2435
2276
        for (carry=0; buf2 > start2; buf1--)
2436
2277
        {
2437
 
          add(*buf1, *buf1, *--buf2, carry);
 
2278
          ADD(*buf1, *buf1, *--buf2, carry);
2438
2279
        }
2439
2280
      }
2440
2281
    }
2453
2294
    if (dcarry)
2454
2295
      *--start1=dcarry;
2455
2296
    buf0=to->buf;
2456
 
    intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
2457
 
    frac0=round_up(to->frac);
 
2297
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
 
2298
    frac0=ROUND_UP(to->frac);
2458
2299
    error=E_DEC_OK;
2459
2300
    if (unlikely(frac0==0 && intg0==0))
2460
2301
    {
2461
 
      to->set_zero();
 
2302
      decimal_make_zero(to);
2462
2303
      goto done;
2463
2304
    }
2464
2305
    if (intg0<=0)
2465
2306
    {
2466
2307
      if (unlikely(-intg0 >= to->len))
2467
2308
      {
2468
 
        to->set_zero();
 
2309
        decimal_make_zero(to);
2469
2310
        error=E_DEC_TRUNCATED;
2470
2311
        goto done;
2471
2312
      }
2484
2325
        error=E_DEC_OVERFLOW;
2485
2326
        goto done;
2486
2327
      }
2487
 
      assert(intg0 <= round_up(from2->intg));
 
2328
      assert(intg0 <= ROUND_UP(from2->intg));
2488
2329
      stop1=start1+frac0+intg0;
2489
2330
      to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2490
2331
    }
2503
2344
  return error;
2504
2345
}
2505
2346
 
2506
 
/**
2507
 
 @brief  division of two decimals
2508
 
 
2509
 
 @param[in]  from1   dividend
2510
 
 @param[in]  from2   divisor
2511
 
 @param[out] to      quotient
2512
 
 
2513
 
 @return
 
2347
/*
 
2348
  division of two decimals
 
2349
 
 
2350
  SYNOPSIS
 
2351
    decimal_div()
 
2352
      from1   - dividend
 
2353
      from2   - divisor
 
2354
      to      - quotient
 
2355
 
 
2356
  RETURN VALUE
2514
2357
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2515
2358
 
2516
 
 @note
 
2359
  NOTES
2517
2360
    see do_div_mod()
2518
2361
*/
 
2362
 
2519
2363
int
2520
 
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
 
2364
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2521
2365
{
2522
2366
  return do_div_mod(from1, from2, to, 0, scale_incr);
2523
2367
}
2524
2368
 
2525
 
/**
2526
 
 @brief modulus
2527
 
 
2528
 
 the modulus R in    R = M mod N
2529
 
 
2530
 
 is defined as
2531
 
 
2532
 
 0 <= |R| < |M|
2533
 
 sign R == sign M
2534
 
 R = M - k*N, where k is integer
2535
 
 
2536
 
 thus, there's no requirement for M or N to be integers
2537
 
 
2538
 
 
2539
 
 @param from1   dividend
2540
 
 @param from2   divisor
2541
 
 @param to      modulus
2542
 
 
2543
 
 @return
 
2369
/*
 
2370
  modulus
 
2371
 
 
2372
  SYNOPSIS
 
2373
    decimal_mod()
 
2374
      from1   - dividend
 
2375
      from2   - divisor
 
2376
      to      - modulus
 
2377
 
 
2378
  RETURN VALUE
2544
2379
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2545
2380
 
2546
 
 @note
 
2381
  NOTES
2547
2382
    see do_div_mod()
2548
2383
 
 
2384
  DESCRIPTION
 
2385
    the modulus R in    R = M mod N
 
2386
 
 
2387
   is defined as
 
2388
 
 
2389
     0 <= |R| < |M|
 
2390
     sign R == sign M
 
2391
     R = M - k*N, where k is integer
 
2392
 
 
2393
   thus, there's no requirement for M or N to be integers
2549
2394
*/
2550
 
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
2395
 
 
2396
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2551
2397
{
2552
2398
  return do_div_mod(from1, from2, 0, to, 0);
2553
2399
}
2554
2400
 
2555
 
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec)
2556
 
{
2557
 
  drizzled::String str;
2558
 
 
2559
 
  class_decimal2string(&dec, 0, &str);
2560
 
 
2561
 
  output << "type::Decimal:(";
2562
 
  output <<  str.c_ptr();
2563
 
  output << ")";
2564
 
 
2565
 
  return output;  // for multiple << operators.
2566
 
}
2567
 
 
2568
 
} /* namespace drizzled */
2569
 
 
2570
2401
#ifdef MAIN
2571
2402
 
2572
2403
int full= 0;
2577
2408
{
2578
2409
  int i;
2579
2410
  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2580
 
  for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
 
2411
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2581
2412
    printf("%09d, ", d->buf[i]);
2582
2413
  printf("%09d} */ ", d->buf[i]);
2583
2414
}
2649
2480
{
2650
2481
  char s1[100], *end;
2651
2482
  int res;
2652
 
  snprintf(s1, sizeof(s1), "'%s'", s);
 
2483
  sprintf(s1, "'%s'", s);
2653
2484
  end= strend(s);
2654
2485
  printf("len=%2d %-30s => res=%d    ", a.len, s1,
2655
2486
         (res= string2decimal(s, &a, &end)));
2663
2494
  double x;
2664
2495
  int res;
2665
2496
 
2666
 
  snprintf(s1, sizeof(s1), "'%s'", s);
 
2497
  sprintf(s1, "'%s'", s);
2667
2498
  end= strend(s);
2668
2499
  string2decimal(s, &a, &end);
2669
2500
  res=decimal2double(&a, &x);
2677
2508
  char s1[100], buf[100], *end;
2678
2509
  int res, i, size=decimal_bin_size(p, s);
2679
2510
 
2680
 
  snprintf(s1, sizeof(s1), "'%s'", str);
 
2511
  sprintf(s1, "'%s'", str);
2681
2512
  end= strend(str);
2682
2513
  string2decimal(str, &a, &end);
2683
2514
  res=decimal2bin(&a, buf, p, s);
2710
2541
  int res;
2711
2542
 
2712
2543
  res=uint64_t2decimal(from, &a);
2713
 
  internal::int64_t10_to_str(from,s,10);
 
2544
  int64_t10_to_str(from,s,10);
2714
2545
  printf("%-40s => res=%d    ", s, res);
2715
2546
  print_decimal(&a, orig, res, ex);
2716
2547
  printf("\n");
2722
2553
  int res;
2723
2554
 
2724
2555
  res=int64_t2decimal(from, &a);
2725
 
  internal::int64_t10_to_str(from,s,-10);
 
2556
  int64_t10_to_str(from,s,-10);
2726
2557
  printf("%-40s => res=%d    ", s, res);
2727
2558
  print_decimal(&a, orig, res, ex);
2728
2559
  printf("\n");
2738
2569
  string2decimal(s, &a, &end);
2739
2570
  res=decimal2uint64_t(&a, &x);
2740
2571
  if (full) dump_decimal(&a);
2741
 
  internal::int64_t10_to_str(x,s1,10);
 
2572
  int64_t10_to_str(x,s1,10);
2742
2573
  printf("%-40s => res=%d    %s\n", s, res, s1);
2743
2574
  check_result_code(res, ex);
2744
2575
  if (orig && strcmp(orig, s1))
2758
2589
  string2decimal(s, &a, &end);
2759
2590
  res=decimal2int64_t(&a, &x);
2760
2591
  if (full) dump_decimal(&a);
2761
 
  internal::int64_t10_to_str(x,s1,-10);
 
2592
  int64_t10_to_str(x,s1,-10);
2762
2593
  printf("%-40s => res=%d    %s\n", s, res, s1);
2763
2594
  check_result_code(res, ex);
2764
2595
  if (orig && strcmp(orig, s1))
2772
2603
{
2773
2604
  char s[100], *end;
2774
2605
  int res;
2775
 
  snprintf(s, sizeof(s), "'%s' + '%s'", s1, s2);
 
2606
  sprintf(s, "'%s' + '%s'", s1, s2);
2776
2607
  end= strend(s1);
2777
2608
  string2decimal(s1, &a, &end);
2778
2609
  end= strend(s2);
2787
2618
{
2788
2619
  char s[100], *end;
2789
2620
  int res;
2790
 
  snprintf(s, sizeof(s), "'%s' - '%s'", s1, s2);
 
2621
  sprintf(s, "'%s' - '%s'", s1, s2);
2791
2622
  end= strend(s1);
2792
2623
  string2decimal(s1, &a, &end);
2793
2624
  end= strend(s2);
2802
2633
{
2803
2634
  char s[100], *end;
2804
2635
  int res;
2805
 
  snprintf(s, sizeof(s), "'%s' <=> '%s'", s1, s2);
 
2636
  sprintf(s, "'%s' <=> '%s'", s1, s2);
2806
2637
  end= strend(s1);
2807
2638
  string2decimal(s1, &a, &end);
2808
2639
  end= strend(s2);
2820
2651
{
2821
2652
  char s[100], *end;
2822
2653
  int res;
2823
 
  snprintf(s, sizeof(s), "'%s' * '%s'", s1, s2);
 
2654
  sprintf(s, "'%s' * '%s'", s1, s2);
2824
2655
  end= strend(s1);
2825
2656
  string2decimal(s1, &a, &end);
2826
2657
  end= strend(s2);
2835
2666
{
2836
2667
  char s[100], *end;
2837
2668
  int res;
2838
 
  snprintf(s, sizeof(s), "'%s' / '%s'", s1, s2);
 
2669
  sprintf(s, "'%s' / '%s'", s1, s2);
2839
2670
  end= strend(s1);
2840
2671
  string2decimal(s1, &a, &end);
2841
2672
  end= strend(s2);
2854
2685
{
2855
2686
  char s[100], *end;
2856
2687
  int res;
2857
 
  snprintf(s, sizeof(s), "'%s' %% '%s'", s1, s2);
 
2688
  sprintf(s, "'%s' %% '%s'", s1, s2);
2858
2689
  end= strend(s1);
2859
2690
  string2decimal(s1, &a, &end);
2860
2691
  end= strend(s2);
2877
2708
{
2878
2709
  char s[100], *end;
2879
2710
  int res;
2880
 
  snprintf(s, sizeof(s), "'%s', %d, %s", s1, n, round_mode[mode]);
 
2711
  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2881
2712
  end= strend(s1);
2882
2713
  string2decimal(s1, &a, &end);
2883
2714
  res=decimal_round(&a, &b, n, mode);
2890
2721
void test_mx(int precision, int frac, const char *orig)
2891
2722
{
2892
2723
  char s[100];
2893
 
  snprintf(s, sizeof(s), "%d, %d", precision, frac);
 
2724
  sprintf(s, "%d, %d", precision, frac);
2894
2725
  max_decimal(precision, frac, &a);
2895
2726
  printf("%-40s =>          ", s);
2896
2727
  print_decimal(&a, orig, 0, 0);
2906
2737
  int slen= sizeof(s2);
2907
2738
  int res;
2908
2739
 
2909
 
  snprintf(s, sizeof(s), filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
 
2740
  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2910
2741
          s1, prec, dec, filler);
2911
2742
  end= strend(s1);
2912
2743
  string2decimal(s1, &a, &end);
2926
2757
{
2927
2758
  char s[100], *end;
2928
2759
  int res;
2929
 
  snprintf(s, sizeof(s), "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
 
2760
  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2930
2761
  end= strend(s1);
2931
2762
  string2decimal(s1, &a, &end);
2932
2763
  res= decimal_shift(&a, shift);
2939
2770
void test_fr(const char *s1, const char *orig)
2940
2771
{
2941
2772
  char s[100], *end;
2942
 
  snprintf(s, sizeof(s), "'%s'", s1);
 
2773
  sprintf(s, "'%s'", s1);
2943
2774
  printf("%-40s =>          ", s);
2944
2775
  end= strend(s1);
2945
2776
  string2decimal(s1, &a, &end);
3298
3129
 
3299
3130
  return 0;
3300
3131
}
3301
 
 
3302
3132
#endif