~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/decimal.c

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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/type/decimal.h>
112
 
 
113
 
#include <plugin/myisam/myisampack.h>
114
 
#include <drizzled/util/test.h>
115
 
 
116
 
#ifdef HAVE_ALLOCA_H
117
100
#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 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
 
 
 
101
#include <m_string.h>
 
102
#include <m_ctype.h>
 
103
#include <storage/myisam/myisampack.h>
 
104
#include <mystrings/decimal.h>
353
105
 
354
106
/*
355
107
  Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
373
125
#define DIG_MASK     100000000
374
126
#define DIG_BASE     1000000000
375
127
#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
 
 
 
128
#define DIG_BASE2    ((dec2)DIG_BASE * (dec2)DIG_BASE)
 
129
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
383
130
static const dec1 powers10[DIG_PER_DEC1+1]={
384
131
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
385
132
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
388
135
  999900000, 999990000, 999999000,
389
136
  999999900, 999999990 };
390
137
 
391
 
#ifdef HAVE_VALGRIND
 
138
#ifdef HAVE_purify
392
139
#define sanity(d) assert((d)->len > 0)
393
140
#else
394
141
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
395
142
                              (d)->buf[(d)->len-1] | 1))
396
143
#endif
397
144
 
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
 
}
 
145
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error)                   \
 
146
        do                                                              \
 
147
        {                                                               \
 
148
          if (unlikely(intg1+frac1 > (len)))                            \
 
149
          {                                                             \
 
150
            if (unlikely(intg1 > (len)))                                \
 
151
            {                                                           \
 
152
              intg1=(len);                                              \
 
153
              frac1=0;                                                  \
 
154
              error=E_DEC_OVERFLOW;                                     \
 
155
            }                                                           \
 
156
            else                                                        \
 
157
            {                                                           \
 
158
              frac1=(len)-intg1;                                        \
 
159
              error=E_DEC_TRUNCATED;                                    \
 
160
            }                                                           \
 
161
          }                                                             \
 
162
          else                                                          \
 
163
            error=E_DEC_OK;                                             \
 
164
        } while(0)
 
165
 
 
166
#define ADD(to, from1, from2, carry)  /* assume carry <= 1 */           \
 
167
        do                                                              \
 
168
        {                                                               \
 
169
          dec1 a=(from1)+(from2)+(carry);                               \
 
170
          assert((carry) <= 1);                                    \
 
171
          if (((carry)= a >= DIG_BASE)) /* no division here! */         \
 
172
            a-=DIG_BASE;                                                \
 
173
          (to)=a;                                                       \
 
174
        } while(0)
 
175
 
 
176
#define ADD2(to, from1, from2, carry)                                   \
 
177
        do                                                              \
 
178
        {                                                               \
 
179
          dec2 a=((dec2)(from1))+(from2)+(carry);                       \
 
180
          if (((carry)= a >= DIG_BASE))                                 \
 
181
            a-=DIG_BASE;                                                \
 
182
          if (unlikely(a >= DIG_BASE))                                  \
 
183
          {                                                             \
 
184
            a-=DIG_BASE;                                                \
 
185
            carry++;                                                    \
 
186
          }                                                             \
 
187
          (to)=(dec1) a;                                                \
 
188
        } while(0)
 
189
 
 
190
#define SUB(to, from1, from2, carry) /* to=from1-from2 */               \
 
191
        do                                                              \
 
192
        {                                                               \
 
193
          dec1 a=(from1)-(from2)-(carry);                               \
 
194
          if (((carry)= a < 0))                                         \
 
195
            a+=DIG_BASE;                                                \
 
196
          (to)=a;                                                       \
 
197
        } while(0)
 
198
 
 
199
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */              \
 
200
        do                                                              \
 
201
        {                                                               \
 
202
          dec1 a=(from1)-(from2)-(carry);                               \
 
203
          if (((carry)= a < 0))                                         \
 
204
            a+=DIG_BASE;                                                \
 
205
          if (unlikely(a < 0))                                          \
 
206
          {                                                             \
 
207
            a+=DIG_BASE;                                                \
 
208
            carry++;                                                    \
 
209
          }                                                             \
 
210
          (to)=a;                                                       \
 
211
        } while(0)
463
212
 
464
213
/**
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
 
214
  Swap the contents of two variables.
 
215
 */
 
216
#define swap_variables(TYPE, a, b) \
 
217
  do {                             \
 
218
    TYPE dummy;                    \
 
219
    dummy= a;                      \
 
220
    a= b;                          \
 
221
    b= dummy;                      \
 
222
  } while (0)
 
223
 
 
224
 
 
225
/*
 
226
  Get maximum value for given precision and scale
 
227
 
 
228
  SYNOPSIS
 
229
    max_decimal()
 
230
    precision/scale - see decimal_bin_size() below
 
231
    to              - decimal where where the result will be stored
469
232
                      to->buf and to->len must be set.
470
233
*/
471
234
 
496
259
}
497
260
 
498
261
 
499
 
static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
 
262
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
500
263
{
501
264
  int intg= from->intg, i;
502
265
  dec1 *buf0= from->buf;
519
282
}
520
283
 
521
284
 
522
 
/**
523
 
 @brief Count actual length of fraction part (without ending zeroes)
 
285
/*
 
286
  Count actual length of fraction part (without ending zeroes)
524
287
 
525
 
 @param from    number for processing
 
288
  SYNOPSIS
 
289
    decimal_actual_fraction()
 
290
    from    number for processing
526
291
*/
527
292
 
528
293
int decimal_actual_fraction(decimal_t *from)
529
294
{
530
295
  int frac= from->frac, i;
531
 
  dec1 *buf0= from->buf + round_up(from->intg) + round_up(frac) - 1;
 
296
  dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
532
297
 
533
298
  if (frac == 0)
534
299
    return 0;
548
313
}
549
314
 
550
315
 
551
 
/**
552
 
 @brief  Convert decimal to its printable string representation
 
316
/*
 
317
  Convert decimal to its printable string representation
553
318
 
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
 
319
  SYNOPSIS
 
320
    decimal2string()
 
321
      from            - value to convert
 
322
      to              - points to buffer where string representation
 
323
                        should be stored
 
324
      *to_len         - in:  size of to buffer
 
325
                        out: length of the actually written string
 
326
      fixed_precision - 0 if representation can be variable length and
560
327
                        fixed_decimals will not be checked in this case.
561
328
                        Put number as with fixed point position with this
562
329
                        number of digits (sign counted and decimal point is
563
330
                        counted)
564
 
 @param  fixed_decimals  number digits after point.
565
 
 @param  filler          character to fill gaps in case of fixed_precision > 0
 
331
      fixed_decimals  - number digits after point.
 
332
      filler          - character to fill gaps in case of fixed_precision > 0
566
333
 
567
 
 @return error code
568
 
   @retval E_DEC_OK
569
 
   @retval E_DEC_TRUNCATED
570
 
   @retval E_DEC_OVERFLOW
 
334
  RETURN VALUE
 
335
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
571
336
*/
572
 
int decimal2string(const decimal_t *from, char *to, int *to_len,
 
337
 
 
338
int decimal2string(decimal_t *from, char *to, int *to_len,
573
339
                   int fixed_precision, int fixed_decimals,
574
340
                   char filler)
575
341
{
633
399
  {
634
400
    char *s1= s + intg_len;
635
401
    fill= frac_len - frac;
636
 
    buf=buf0+round_up(intg);
 
402
    buf=buf0+ROUND_UP(intg);
637
403
    *s1++='.';
638
404
    for (; frac>0; frac-=DIG_PER_DEC1)
639
405
    {
641
407
      for (i=min(frac, DIG_PER_DEC1); i; i--)
642
408
      {
643
409
        dec1 y=x/DIG_MASK;
644
 
        *s1++='0'+(unsigned char)y;
 
410
        *s1++='0'+(uchar)y;
645
411
        x-=y*DIG_MASK;
646
412
        x*=10;
647
413
      }
658
424
  if (intg)
659
425
  {
660
426
    s+=intg;
661
 
    for (buf=buf0+round_up(intg); intg>0; intg-=DIG_PER_DEC1)
 
427
    for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
662
428
    {
663
429
      dec1 x=*--buf;
664
430
      for (i=min(intg, DIG_PER_DEC1); i; i--)
665
431
      {
666
432
        dec1 y=x/10;
667
 
        *--s='0'+(unsigned char)(x-y*10);
 
433
        *--s='0'+(uchar)(x-y*10);
668
434
        x=y;
669
435
      }
670
436
    }
675
441
}
676
442
 
677
443
 
678
 
/**
679
 
 @brief  Return bounds of decimal digits in the number
 
444
/*
 
445
  Return bounds of decimal digits in the number
680
446
 
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
 
447
  SYNOPSIS
 
448
    digits_bounds()
 
449
      from         - decimal number for processing
 
450
      start_result - index (from 0 ) of first decimal digits will
 
451
                     be written by this address
 
452
      end_result   - index of position just after last decimal digit
685
453
                     be written by this address
686
454
*/
 
455
 
687
456
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
688
457
{
689
458
  int start, stop, i;
690
459
  dec1 *buf_beg= from->buf;
691
 
  dec1 *end= from->buf + round_up(from->intg) + round_up(from->frac);
 
460
  dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
692
461
  dec1 *buf_end= end - 1;
693
462
 
694
463
  /* find non-zero digit from number begining */
737
506
}
738
507
 
739
508
 
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'?
 
509
/*
 
510
  Left shift for alignment of data in buffer
 
511
 
 
512
  SYNOPSIS
 
513
    do_mini_left_shift()
 
514
    dec     pointer to decimal number which have to be shifted
 
515
    shift   number of decimal digits on which it should be shifted
 
516
    beg/end bounds of decimal digits (see digits_bounds())
 
517
 
 
518
  NOTE
 
519
    Result fitting in the buffer should be garanted.
 
520
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
754
521
*/
 
522
 
755
523
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
756
524
{
757
 
  dec1 *from= dec->buf + round_up(beg + 1) - 1;
758
 
  dec1 *end= dec->buf + round_up(last) - 1;
 
525
  dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
 
526
  dec1 *end= dec->buf + ROUND_UP(last) - 1;
759
527
  int c_shift= DIG_PER_DEC1 - shift;
760
528
  assert(from >= dec->buf);
761
529
  assert(end < dec->buf + dec->len);
768
536
}
769
537
 
770
538
 
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
 
539
/*
 
540
  Right shift for alignment of data in buffer
 
541
 
 
542
  SYNOPSIS
 
543
    do_mini_left_shift()
 
544
    dec     pointer to decimal number which have to be shifted
 
545
    shift   number of decimal digits on which it should be shifted
 
546
    beg/end bounds of decimal digits (see digits_bounds())
 
547
 
 
548
  NOTE
780
549
    Result fitting in the buffer should be garanted.
781
550
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
782
551
*/
 
552
 
783
553
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
784
554
{
785
 
  dec1 *from= dec->buf + round_up(last) - 1;
786
 
  dec1 *end= dec->buf + round_up(beg + 1) - 1;
 
555
  dec1 *from= dec->buf + ROUND_UP(last) - 1;
 
556
  dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
787
557
  int c_shift= DIG_PER_DEC1 - shift;
788
558
  assert(from < dec->buf + dec->len);
789
559
  assert(end >= dec->buf);
796
566
}
797
567
 
798
568
 
799
 
/**
800
 
  @brief  Shift of decimal digits in given number (with rounding if it need)
 
569
/*
 
570
  Shift of decimal digits in given number (with rounding if it need)
801
571
 
802
 
  @param  dec       number to be shifted
803
 
  @param  shift     number of decimal positions
 
572
  SYNOPSIS
 
573
    decimal_shift()
 
574
    dec       number to be shifted
 
575
    shift     number of decimal positions
804
576
              shift > 0 means shift to left shift
805
577
              shift < 0 meand right shift
806
 
 
807
 
  @note
 
578
  NOTE
808
579
    In fact it is multipling on 10^shift.
 
580
  RETURN
 
581
    E_DEC_OK          OK
 
582
    E_DEC_OVERFLOW    operation lead to overflow, number is untoched
 
583
    E_DEC_TRUNCATED   number was rounded to fit into buffer
 
584
*/
809
585
 
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
586
static int decimal_shift(decimal_t *dec, int shift)
816
587
{
817
588
  /* index of first non zero digit (all indexes from 0) */
819
590
  /* index of position after last decimal digit */
820
591
  int end;
821
592
  /* index of digit position just after point */
822
 
  int point= round_up(dec->intg) * DIG_PER_DEC1;
 
593
  int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
823
594
  /* new point position */
824
595
  int new_point= point + shift;
825
596
  /* number of digits in result */
837
608
 
838
609
  if (beg == end)
839
610
  {
840
 
    dec->set_zero();
 
611
    decimal_make_zero(dec);
841
612
    return E_DEC_OK;
842
613
  }
843
614
 
846
617
  digits_frac= end - new_point;
847
618
  set_if_bigger(digits_frac, 0);
848
619
 
849
 
  if ((new_len= round_up(digits_int) + (new_frac_len= round_up(digits_frac))) >
 
620
  if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
850
621
      dec->len)
851
622
  {
852
623
    int lack= new_len - dec->len;
870
641
        we lost all digits (they will be shifted out of buffer), so we can
871
642
        just return 0
872
643
      */
873
 
      dec->set_zero();
874
 
 
 
644
      decimal_make_zero(dec);
875
645
      return E_DEC_TRUNCATED;
876
646
    }
877
647
  }
907
677
    if (do_left)
908
678
    {
909
679
      do_mini_left_shift(dec, l_mini_shift, beg, end);
910
 
      mini_shift= (-l_mini_shift);
 
680
      mini_shift=- l_mini_shift;
911
681
    }
912
682
    else
913
683
    {
940
710
    {
941
711
      /* move left */
942
712
      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);
 
713
      to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
 
714
      barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
945
715
      assert(to >= dec->buf);
946
716
      assert(barier + d_shift < dec->buf + dec->len);
947
717
      for(; to <= barier; to++)
954
724
    {
955
725
      /* move right */
956
726
      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;
 
727
      to= dec->buf + ROUND_UP(end) - 1 + d_shift;
 
728
      barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
959
729
      assert(to < dec->buf + dec->len);
960
730
      assert(barier - d_shift >= dec->buf);
961
731
      for(; to >= barier; to--)
974
744
 
975
745
    Only one of following 'for' loops will work becouse beg <= end
976
746
  */
977
 
  beg= round_up(beg + 1) - 1;
978
 
  end= round_up(end) - 1;
 
747
  beg= ROUND_UP(beg + 1) - 1;
 
748
  end= ROUND_UP(end) - 1;
979
749
  assert(new_point >= 0);
980
 
 
 
750
  
981
751
  /* We don't want negative new_point below */
982
752
  if (new_point != 0)
983
 
    new_point= round_up(new_point) - 1;
 
753
    new_point= ROUND_UP(new_point) - 1;
984
754
 
985
755
  if (new_point > end)
986
756
  {
1000
770
}
1001
771
 
1002
772
 
1003
 
/**
1004
 
  @brief  Convert string to decimal
 
773
/*
 
774
  Convert string to decimal
1005
775
 
1006
 
  @param  from    value to convert. Doesn't have to be \0 terminated!
1007
 
  @param  to      decimal where where the result will be stored
 
776
  SYNOPSIS
 
777
    internal_str2decl()
 
778
      from    - value to convert. Doesn't have to be \0 terminated!
 
779
      to      - decimal where where the result will be stored
1008
780
                to->buf and to->len must be set.
1009
 
  @param  end     Pointer to pointer to end of string. Will on return be
 
781
      end     - Pointer to pointer to end of string. Will on return be
1010
782
                set to the char after the last used character
1011
 
  @param  fixed   use to->intg, to->frac as limits for input number
 
783
      fixed   - use to->intg, to->frac as limits for input number
1012
784
 
1013
 
  @note
 
785
  NOTE
1014
786
    to->intg and to->frac can be modified even when fixed=1
1015
787
    (but only decreased, in this case)
1016
788
 
1017
 
  @return
 
789
  RETURN VALUE
1018
790
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
1019
791
    In case of E_DEC_FATAL_ERROR *to is set to decimal zero
1020
792
    (to make error handling easier)
1021
793
*/
 
794
 
1022
795
int
1023
796
internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
1024
797
{
1030
803
  sanity(to);
1031
804
 
1032
805
  error= E_DEC_BAD_NUM;                         /* In case of bad number */
1033
 
  while (s < end_of_string && my_isspace(&my_charset_utf8_general_ci, *s))
 
806
  while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
1034
807
    s++;
1035
808
  if (s == end_of_string)
1036
809
    goto fatal_error;
1041
814
    s++;
1042
815
 
1043
816
  s1=s;
1044
 
  while (s < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *s))
 
817
  while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
1045
818
    s++;
1046
819
  intg= (int) (s-s1);
1047
820
  if (s < end_of_string && *s=='.')
1048
821
  {
1049
822
    endp= s+1;
1050
 
    while (endp < end_of_string && my_isdigit(&my_charset_utf8_general_ci, *endp))
 
823
    while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
1051
824
      endp++;
1052
825
    frac= (int) (endp - s - 1);
1053
826
  }
1075
848
      error=E_DEC_OVERFLOW;
1076
849
      intg=to->intg;
1077
850
    }
1078
 
    intg1=round_up(intg);
1079
 
    frac1=round_up(frac);
 
851
    intg1=ROUND_UP(intg);
 
852
    frac1=ROUND_UP(frac);
1080
853
    if (intg1+frac1 > to->len)
1081
854
    {
1082
855
      error= E_DEC_OOM;
1085
858
  }
1086
859
  else
1087
860
  {
1088
 
    intg1=round_up(intg);
1089
 
    frac1=round_up(frac);
1090
 
    fix_intg_frac_error(to->len, intg1, frac1, error);
 
861
    intg1=ROUND_UP(intg);
 
862
    frac1=ROUND_UP(frac);
 
863
    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1091
864
    if (unlikely(error))
1092
865
    {
1093
866
      frac=frac1*DIG_PER_DEC1;
1135
908
  if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
1136
909
  {
1137
910
    int str_error;
1138
 
    const int64_t exponent= internal::my_strtoll10(endp+1, (char**) &end_of_string,
1139
 
                                                   &str_error);
 
911
    const int64_t exponent= my_strtoll10(endp+1, (char**) &end_of_string,
 
912
                                    &str_error);
1140
913
 
1141
914
    if (end_of_string != endp +1)               /* If at least one digit */
1142
915
    {
1163
936
  return error;
1164
937
 
1165
938
fatal_error:
1166
 
  to->set_zero();
 
939
  decimal_make_zero(to);
1167
940
  return error;
1168
941
}
1169
942
 
1170
943
 
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
 
944
/*
 
945
  Convert decimal to double
 
946
 
 
947
  SYNOPSIS
 
948
    decimal2double()
 
949
      from    - value to convert
 
950
      to      - result will be stored there
 
951
 
 
952
  RETURN VALUE
1178
953
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1179
954
*/
1180
955
 
1181
 
int decimal2double(const decimal_t *from, double *to)
 
956
int decimal2double(decimal_t *from, double *to)
1182
957
{
1183
958
  char strbuf[FLOATING_POINT_BUFFER], *end;
1184
959
  int len= sizeof(strbuf);
1186
961
 
1187
962
  rc = decimal2string(from, strbuf, &len, 0, 0, 0);
1188
963
  end= strbuf + len;
1189
 
 
1190
 
  *to= internal::my_strtod(strbuf, &end, &error);
1191
 
 
 
964
  
 
965
  *to= my_strtod(strbuf, &end, &error);
 
966
             
1192
967
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
1193
968
}
1194
969
 
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
 
970
/*
 
971
  Convert double to decimal
 
972
 
 
973
  SYNOPSIS
 
974
    double2decimal()
 
975
      from    - value to convert
 
976
      to      - result will be stored there
 
977
 
 
978
  RETURN VALUE
1202
979
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1203
980
*/
1204
981
 
1205
 
int double2decimal(const double from, decimal_t *to)
 
982
int double2decimal(double from, decimal_t *to)
1206
983
{
1207
984
  char buff[FLOATING_POINT_BUFFER], *end;
1208
985
  int res;
1209
 
  end= buff + internal::my_gcvt(from,
1210
 
                                internal::MY_GCVT_ARG_DOUBLE,
1211
 
                                sizeof(buff) - 1, buff, NULL);
 
986
  end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
1212
987
  res= string2decimal(buff, to, &end);
1213
988
  return(res);
1214
989
}
1240
1015
  return error;
1241
1016
}
1242
1017
 
1243
 
int uint64_t2decimal(const uint64_t from, decimal_t *to)
 
1018
int uint64_t2decimal(uint64_t from, decimal_t *to)
1244
1019
{
1245
1020
  to->sign=0;
1246
1021
  return ull2dec(from, to);
1247
1022
}
1248
1023
 
1249
 
int int64_t2decimal(const int64_t from, decimal_t *to)
 
1024
int int64_t2decimal(int64_t from, decimal_t *to)
1250
1025
{
1251
1026
  if ((to->sign= from < 0))
1252
1027
    return ull2dec(-from, to);
1253
1028
  return ull2dec(from, to);
1254
1029
}
1255
1030
 
1256
 
int decimal2uint64_t(const decimal_t *from, uint64_t *to)
 
1031
int decimal2uint64_t(decimal_t *from, uint64_t *to)
1257
1032
{
1258
1033
  dec1 *buf=from->buf;
1259
1034
  uint64_t x=0;
1282
1057
  return E_DEC_OK;
1283
1058
}
1284
1059
 
1285
 
int decimal2int64_t(const decimal_t *from, int64_t *to)
 
1060
int decimal2int64_t(decimal_t *from, int64_t *to)
1286
1061
{
1287
1062
  dec1 *buf=from->buf;
1288
1063
  int64_t x=0;
1322
1097
  return E_DEC_OK;
1323
1098
}
1324
1099
 
1325
 
/**
1326
 
 @brief
1327
 
  Convert decimal to its binary fixed-length representation (suitable for
1328
 
  comparing with memcmp)
1329
 
 
 
1100
/*
 
1101
  Convert decimal to its binary fixed-length representation
 
1102
  two representations of the same length can be compared with memcmp
 
1103
  with the correct -1/0/+1 result
 
1104
 
 
1105
  SYNOPSIS
 
1106
    decimal2bin()
 
1107
      from    - value to convert
 
1108
      to      - points to buffer where string representation should be stored
 
1109
      precision/scale - see decimal_bin_size() below
 
1110
 
 
1111
  NOTE
 
1112
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
 
1113
 
 
1114
  RETURN VALUE
 
1115
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
 
1116
 
 
1117
  DESCRIPTION
1330
1118
    for storage decimal numbers are converted to the "binary" format.
1331
1119
 
1332
1120
    This format has the following properties:
1387
1175
    And for -1234567890.1234 it would be
1388
1176
 
1389
1177
                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
1178
*/
1404
 
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
 
1179
int decimal2bin(decimal_t *from, uchar *to, int precision, int frac)
1405
1180
{
1406
1181
  dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1407
1182
  int error=E_DEC_OK, intg=precision-frac,
1417
1192
      fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
1418
1193
  const int orig_isize0= isize0;
1419
1194
  const int orig_fsize0= fsize0;
1420
 
  unsigned char *orig_to= to;
 
1195
  uchar *orig_to= to;
1421
1196
 
1422
1197
  buf1= remove_leading_zeroes(from, &from_intg);
1423
1198
 
1507
1282
  }
1508
1283
  if (fsize0 > fsize1)
1509
1284
  {
1510
 
    unsigned char *to_end= orig_to + orig_fsize0 + orig_isize0;
 
1285
    uchar *to_end= orig_to + orig_fsize0 + orig_isize0;
1511
1286
 
1512
1287
    while (fsize0-- > fsize1 && to < to_end)
1513
 
      *to++= (unsigned char)mask;
 
1288
      *to++= (uchar)mask;
1514
1289
  }
1515
1290
  orig_to[0]^= 0x80;
1516
1291
 
1519
1294
  return error;
1520
1295
}
1521
1296
 
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
 
1297
/*
 
1298
  Restores decimal from its binary fixed-length representation
 
1299
 
 
1300
  SYNOPSIS
 
1301
    bin2decimal()
 
1302
      from    - value to convert
 
1303
      to      - result
 
1304
      precision/scale - see decimal_bin_size() below
 
1305
 
 
1306
  NOTE
1531
1307
    see decimal2bin()
1532
1308
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1533
1309
 
1534
 
 @return
 
1310
  RETURN VALUE
1535
1311
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1536
1312
*/
1537
 
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
 
1313
 
 
1314
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale)
1538
1315
{
1539
1316
  int error=E_DEC_OK, intg=precision-scale,
1540
1317
      intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
1541
1318
      intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
1542
1319
      intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
1543
1320
  dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
1544
 
  const unsigned char *stop;
1545
 
  unsigned char *d_copy;
 
1321
  const uchar *stop;
 
1322
  uchar *d_copy;
1546
1323
  int bin_size= decimal_bin_size(precision, scale);
1547
1324
 
1548
1325
  sanity(to);
1549
 
  d_copy= (unsigned char*) alloca(bin_size);
 
1326
  d_copy= (uchar*) alloca(bin_size);
1550
1327
  memcpy(d_copy, from, bin_size);
1551
1328
  d_copy[0]^= 0x80;
1552
1329
  from= d_copy;
1553
1330
 
1554
 
  fix_intg_frac_error(to->len, intg1, frac1, error);
 
1331
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1555
1332
  if (unlikely(error))
1556
1333
  {
1557
1334
    if (intg1 < intg0+(intg0x>0))
1632
1409
  return error;
1633
1410
 
1634
1411
err:
1635
 
  to->set_zero();
 
1412
  decimal_make_zero(((decimal_t*) to));
1636
1413
  return(E_DEC_BAD_NUM);
1637
1414
}
1638
1415
 
1639
 
/**
1640
 
 @brief  Returns the size of array to hold a binary representation of a decimal
1641
 
 
1642
 
 @return  Size in bytes
1643
 
*/
 
1416
/*
 
1417
  Returns the size of array to hold a decimal with given precision and scale
 
1418
 
 
1419
  RETURN VALUE
 
1420
    size in dec1
 
1421
    (multiply by sizeof(dec1) to get the size if bytes)
 
1422
*/
 
1423
 
 
1424
int decimal_size(int precision, int scale)
 
1425
{
 
1426
  assert(scale >= 0 && precision > 0 && scale <= precision);
 
1427
  return ROUND_UP(precision-scale)+ROUND_UP(scale);
 
1428
}
 
1429
 
 
1430
/*
 
1431
  Returns the size of array to hold a binary representation of a decimal
 
1432
 
 
1433
  RETURN VALUE
 
1434
    size in bytes
 
1435
*/
 
1436
 
1644
1437
int decimal_bin_size(int precision, int scale)
1645
1438
{
1646
1439
  int intg=precision-scale,
1652
1445
         frac0*sizeof(dec1)+dig2bytes[frac0x];
1653
1446
}
1654
1447
 
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
 
1448
/*
 
1449
  Rounds the decimal to "scale" digits
 
1450
 
 
1451
  SYNOPSIS
 
1452
    decimal_round()
 
1453
      from    - decimal to round,
 
1454
      to      - result buffer. from==to is allowed
 
1455
      scale   - to what position to round. can be negative!
 
1456
      mode    - round to nearest even or truncate
 
1457
 
 
1458
  NOTES
1664
1459
    scale can be negative !
1665
1460
    one TRUNCATED error (line XXX below) isn't treated very logical :(
1666
1461
 
1667
 
 @return
 
1462
  RETURN VALUE
1668
1463
    E_DEC_OK/E_DEC_TRUNCATED
1669
1464
*/
 
1465
 
1670
1466
int
1671
 
decimal_round(const decimal_t *from, decimal_t *to, int scale,
 
1467
decimal_round(decimal_t *from, decimal_t *to, int scale,
1672
1468
              decimal_round_mode mode)
1673
1469
{
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 +
 
1470
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
 
1471
      frac1=ROUND_UP(from->frac), round_digit= 0,
 
1472
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
 
1473
      intg1=ROUND_UP(from->intg +
1678
1474
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1679
1475
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1680
1476
  int first_dig;
1699
1495
 
1700
1496
  if (scale+from->intg < 0)
1701
1497
  {
1702
 
    to->set_zero();
 
1498
    decimal_make_zero(to);
1703
1499
    return E_DEC_OK;
1704
1500
  }
1705
1501
 
1770
1566
    }
1771
1567
    else if (frac0+intg0==0)
1772
1568
    {
1773
 
      to->set_zero();
 
1569
      decimal_make_zero(to);
1774
1570
      return E_DEC_OK;
1775
1571
    }
1776
1572
  }
1777
1573
  else
1778
1574
  {
1779
 
  /** @todo fix this code as it won't work for CEILING mode */
 
1575
    /* TODO - fix this code as it won't work for CEILING mode */
1780
1576
    int pos=frac0*DIG_PER_DEC1-scale-1;
1781
1577
    assert(frac0+intg0 > 0);
1782
1578
    x=*buf1 / powers10[pos];
1809
1605
    carry=1;
1810
1606
    *buf1-=DIG_BASE;
1811
1607
    while (carry && --buf1 >= to->buf)
1812
 
      add(*buf1, *buf1, 0, carry);
 
1608
      ADD(*buf1, *buf1, 0, carry);
1813
1609
    if (unlikely(carry))
1814
1610
    {
1815
1611
      /* shifting the number to create space for new digit */
1860
1656
  return error;
1861
1657
}
1862
1658
 
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),
 
1659
/*
 
1660
  Returns the size of the result of the operation
 
1661
 
 
1662
  SYNOPSIS
 
1663
    decimal_result_size()
 
1664
      from1   - operand of the unary operation or first operand of the
 
1665
                binary operation
 
1666
      from2   - second operand of the binary operation
 
1667
      op      - operation. one char '+', '-', '*', '/' are allowed
 
1668
                others may be added later
 
1669
      param   - extra param to the operation. unused for '+', '-', '*'
 
1670
                scale increment for '/'
 
1671
 
 
1672
  NOTE
 
1673
    returned valued may be larger than the actual buffer requred
 
1674
    in the operation, as decimal_result_size, by design, operates on
 
1675
    precision/scale values only and not on the actual decimal number
 
1676
 
 
1677
  RETURN VALUE
 
1678
    size of to->buf array in dec1 elements. to get size in bytes
 
1679
    multiply by sizeof(dec1)
 
1680
*/
 
1681
 
 
1682
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
 
1683
{
 
1684
  switch (op) {
 
1685
  case '-':
 
1686
    return ROUND_UP(max(from1->intg, from2->intg)) +
 
1687
           ROUND_UP(max(from1->frac, from2->frac));
 
1688
  case '+':
 
1689
    return ROUND_UP(max(from1->intg, from2->intg)+1) +
 
1690
           ROUND_UP(max(from1->frac, from2->frac));
 
1691
  case '*':
 
1692
    return ROUND_UP(from1->intg+from2->intg)+
 
1693
           ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
 
1694
  case '/':
 
1695
    return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
 
1696
  default: assert(0);
 
1697
  }
 
1698
  return -1; /* shut up the warning */
 
1699
}
 
1700
 
 
1701
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
 
1702
{
 
1703
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1704
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1867
1705
      frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1868
1706
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1869
1707
 
1879
1717
    to->buf[0]=0; /* safety */
1880
1718
  }
1881
1719
 
1882
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
1720
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1883
1721
  if (unlikely(error == E_DEC_OVERFLOW))
1884
1722
  {
1885
1723
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1900
1738
    set_if_smaller(intg2, intg0);
1901
1739
  }
1902
1740
 
1903
 
  /* part 1 - cmax(frac) ... cmin(frac) */
 
1741
  /* part 1 - max(frac) ... min (frac) */
1904
1742
  if (frac1 > frac2)
1905
1743
  {
1906
1744
    buf1=from1->buf+intg1+frac1;
1918
1756
  while (buf1 > stop)
1919
1757
    *--buf0=*--buf1;
1920
1758
 
1921
 
  /* part 2 - cmin(frac) ... cmin(intg) */
 
1759
  /* part 2 - min(frac) ... min(intg) */
1922
1760
  carry=0;
1923
1761
  while (buf1 > stop2)
1924
1762
  {
1925
 
    add(*--buf0, *--buf1, *--buf2, carry);
 
1763
    ADD(*--buf0, *--buf1, *--buf2, carry);
1926
1764
  }
1927
1765
 
1928
 
  /* part 3 - cmin(intg) ... cmax(intg) */
 
1766
  /* part 3 - min(intg) ... max(intg) */
1929
1767
  buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
1930
1768
                        ((stop=from2->buf)+intg2-intg1) ;
1931
1769
  while (buf1 > stop)
1932
1770
  {
1933
 
    add(*--buf0, *--buf1, 0, carry);
 
1771
    ADD(*--buf0, *--buf1, 0, carry);
1934
1772
  }
1935
1773
 
1936
1774
  if (unlikely(carry))
1942
1780
 
1943
1781
/* to=from1-from2.
1944
1782
   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)
 
1783
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1946
1784
{
1947
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1948
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac);
 
1785
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1786
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1949
1787
  int frac0=max(frac1, frac2), error;
1950
1788
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1951
1789
 
1995
1833
      {
1996
1834
        if (to == 0) /* decimal_cmp() */
1997
1835
          return 0;
1998
 
 
1999
 
        to->set_zero();
2000
 
 
 
1836
        decimal_make_zero(to);
2001
1837
        return E_DEC_OK;
2002
1838
      }
2003
1839
    }
2013
1849
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
2014
1850
  if (carry)
2015
1851
  {
2016
 
    swap(from1, from2);
2017
 
    swap(start1, start2);
2018
 
    swap(intg1, intg2);
2019
 
    swap(frac1, frac2);
 
1852
    swap_variables(decimal_t *,from1,from1);
 
1853
    swap_variables(dec1 *,start1, start2);
 
1854
    swap_variables(int,intg1,intg2);
 
1855
    swap_variables(int,frac1,frac2);
2020
1856
    to->sign= 1 - to->sign;
2021
1857
  }
2022
1858
 
2023
 
  fix_intg_frac_error(to->len, intg1, frac0, error);
 
1859
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
2024
1860
  buf0=to->buf+intg1+frac0;
2025
1861
 
2026
1862
  to->frac=max(from1->frac, from2->frac);
2034
1870
  }
2035
1871
  carry=0;
2036
1872
 
2037
 
  /* part 1 - cmax(frac) ... cmin(frac) */
 
1873
  /* part 1 - max(frac) ... min (frac) */
2038
1874
  if (frac1 > frac2)
2039
1875
  {
2040
1876
    buf1=start1+intg1+frac1;
2054
1890
      *--buf0=0;
2055
1891
    while (buf2 > stop2)
2056
1892
    {
2057
 
      sub(*--buf0, 0, *--buf2, carry);
 
1893
      SUB(*--buf0, 0, *--buf2, carry);
2058
1894
    }
2059
1895
  }
2060
1896
 
2061
 
  /* part 2 - cmin(frac) ... intg2 */
 
1897
  /* part 2 - min(frac) ... intg2 */
2062
1898
  while (buf2 > start2)
2063
1899
  {
2064
 
    sub(*--buf0, *--buf1, *--buf2, carry);
 
1900
    SUB(*--buf0, *--buf1, *--buf2, carry);
2065
1901
  }
2066
1902
 
2067
1903
  /* part 3 - intg2 ... intg1 */
2068
1904
  while (carry && buf1 > start1)
2069
1905
  {
2070
 
    sub(*--buf0, *--buf1, 0, carry);
 
1906
    SUB(*--buf0, *--buf1, 0, carry);
2071
1907
  }
2072
1908
 
2073
1909
  while (buf1 > start1)
2079
1915
  return error;
2080
1916
}
2081
1917
 
2082
 
int decimal_intg(const decimal_t *from)
 
1918
int decimal_intg(decimal_t *from)
2083
1919
{
2084
1920
  int res;
2085
1921
  dec1 *tmp_res;
2087
1923
  return res;
2088
1924
}
2089
1925
 
2090
 
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1926
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
2091
1927
{
2092
1928
  if (likely(from1->sign == from2->sign))
2093
1929
    return do_add(from1, from2, to);
2094
1930
  return do_sub(from1, from2, to);
2095
1931
}
2096
1932
 
2097
 
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1933
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
2098
1934
{
2099
1935
  if (likely(from1->sign == from2->sign))
2100
1936
    return do_sub(from1, from2, to);
2101
1937
  return do_add(from1, from2, to);
2102
1938
}
2103
1939
 
2104
 
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
 
1940
int decimal_cmp(decimal_t *from1, decimal_t *from2)
2105
1941
{
2106
1942
  if (likely(from1->sign == from2->sign))
2107
1943
    return do_sub(from1, from2, 0);
2108
1944
  return from1->sign > from2->sign ? -1 : 1;
2109
1945
}
2110
1946
 
2111
 
int decimal_t::isZero() const
 
1947
int decimal_is_zero(decimal_t *from)
2112
1948
{
2113
 
  dec1 *buf1= buf,
2114
 
       *end= buf1 +round_up(intg) +round_up(frac);
2115
 
 
 
1949
  dec1 *buf1=from->buf,
 
1950
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2116
1951
  while (buf1 < end)
2117
 
  {
2118
1952
    if (*buf1++)
2119
 
    {
2120
1953
      return 0;
2121
 
    }
2122
 
  }
2123
 
 
2124
1954
  return 1;
2125
1955
}
2126
1956
 
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
 
1957
/*
 
1958
  multiply two decimals
 
1959
 
 
1960
  SYNOPSIS
 
1961
    decimal_mul()
 
1962
      from1, from2 - factors
 
1963
      to      - product
 
1964
 
 
1965
  RETURN VALUE
2135
1966
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
2136
1967
 
2137
 
 @note
 
1968
  NOTES
2138
1969
    in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
2139
1970
    and 63-digit number will take only 7 dec1 words (basically a 7-digit
2140
1971
    "base 999999999" number).  Thus there's no need in fast multiplication
2144
1975
    XXX if this library is to be used with huge numbers of thousands of
2145
1976
    digits, fast multiplication must be implemented.
2146
1977
*/
2147
 
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1978
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
2148
1979
{
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),
 
1980
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1981
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
 
1982
      intg0=ROUND_UP(from1->intg+from2->intg),
2152
1983
      frac0=frac1+frac2, error, i, j, d_to_move;
2153
1984
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2154
1985
       *start2, *stop2, *stop1, *start0, carry;
2157
1988
 
2158
1989
  i=intg0;
2159
1990
  j=frac0;
2160
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
1991
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2161
1992
  to->sign=from1->sign != from2->sign;
2162
1993
  to->frac=from1->frac+from2->frac;
2163
1994
  to->intg=intg0*DIG_PER_DEC1;
2198
2029
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2199
2030
      hi=(dec1)(p/DIG_BASE);
2200
2031
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2201
 
      add2(*buf0, *buf0, lo, carry);
 
2032
      ADD2(*buf0, *buf0, lo, carry);
2202
2033
      carry+=hi;
2203
2034
    }
2204
2035
    if (carry)
2205
2036
    {
2206
2037
      if (buf0 < to->buf)
2207
2038
        return E_DEC_OVERFLOW;
2208
 
      add2(*buf0, *buf0, 0, carry);
 
2039
      ADD2(*buf0, *buf0, 0, carry);
2209
2040
    }
2210
2041
    for (buf0--; carry; buf0--)
2211
2042
    {
2212
2043
      if (buf0 < to->buf)
2213
2044
        return E_DEC_OVERFLOW;
2214
 
      add(*buf0, *buf0, 0, carry);
 
2045
      ADD(*buf0, *buf0, 0, carry);
2215
2046
    }
2216
2047
  }
2217
2048
 
2228
2059
      if (++buf == end)
2229
2060
      {
2230
2061
        /* We got decimal zero */
2231
 
        to->set_zero();
 
2062
        decimal_make_zero(to);
2232
2063
        break;
2233
2064
      }
2234
2065
    }
2235
2066
  }
2236
2067
  buf1= to->buf;
2237
 
  d_to_move= intg0 + round_up(to->frac);
 
2068
  d_to_move= intg0 + ROUND_UP(to->frac);
2238
2069
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2239
2070
  {
2240
2071
    buf1++;
2250
2081
  return error;
2251
2082
}
2252
2083
 
2253
 
/**
 
2084
/*
2254
2085
  naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2255
2086
  it's ok for short numbers
2256
2087
  also we're using alloca() to allocate a temporary buffer
2257
2088
 
2258
 
  @todo
2259
 
  If this library is to be used with huge numbers of thousands of
 
2089
  XXX if this library is to be used with huge numbers of thousands of
2260
2090
  digits, fast division must be implemented and alloca should be
2261
2091
  changed to malloc (or at least fallback to malloc if alloca() fails)
2262
2092
  but then, decimal_mul() should be rewritten too :(
2263
2093
*/
2264
 
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
 
2094
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2265
2095
                       decimal_t *to, decimal_t *mod, int scale_incr)
2266
2096
{
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,
 
2097
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
 
2098
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2269
2099
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2270
2100
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2271
2101
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2298
2128
  }
2299
2129
  if (prec1 <= 0)
2300
2130
  { /* short-circuit everything: from1 == 0 */
2301
 
    to->set_zero();
 
2131
    decimal_make_zero(to);
2302
2132
    return E_DEC_OK;
2303
2133
  }
2304
2134
  for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2315
2145
    intg0=0;
2316
2146
  }
2317
2147
  else
2318
 
    intg0=round_up(dintg);
 
2148
    intg0=ROUND_UP(dintg);
2319
2149
  if (mod)
2320
2150
  {
2321
2151
    /* we're calculating N1 % N2.
2322
2152
       The result will have
2323
 
         frac=cmax(frac1, frac2), as for subtraction
 
2153
         frac=max(frac1, frac2), as for subtraction
2324
2154
         intg=intg2
2325
2155
    */
2326
2156
    to->sign=from1->sign;
2334
2164
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2335
2165
      frac2 accordingly.
2336
2166
      Thus, the result will have
2337
 
         frac = round_up(frac1+frac2+scale_incr)
 
2167
         frac = ROUND_UP(frac1+frac2+scale_incr)
2338
2168
      and
2339
2169
         intg = (prec1-frac1) - (prec2-frac2) + 1
2340
2170
         prec = intg+frac
2341
2171
    */
2342
 
    frac0=round_up(frac1+frac2+scale_incr);
2343
 
    fix_intg_frac_error(to->len, intg0, frac0, error);
 
2172
    frac0=ROUND_UP(frac1+frac2+scale_incr);
 
2173
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2344
2174
    to->sign=from1->sign != from2->sign;
2345
2175
    to->intg=intg0*DIG_PER_DEC1;
2346
2176
    to->frac=frac0*DIG_PER_DEC1;
2351
2181
    while (dintg++ < 0)
2352
2182
      *buf0++=0;
2353
2183
 
2354
 
  len1=(i=round_up(prec1))+round_up(2*frac2+scale_incr+1) + 1;
 
2184
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2355
2185
  set_if_bigger(len1, 3);
2356
2186
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
2357
2187
    return E_DEC_OOM;
2361
2191
  start1=tmp1;
2362
2192
  stop1=start1+len1;
2363
2193
  start2=buf2;
2364
 
  stop2=buf2+round_up(prec2)-1;
 
2194
  stop2=buf2+ROUND_UP(prec2)-1;
2365
2195
 
2366
2196
  /* removing end zeroes */
2367
2197
  while (*stop2 == 0 && stop2 >= start2)
2420
2250
        x=guess * (*--buf2);
2421
2251
        hi=(dec1)(x/DIG_BASE);
2422
2252
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2423
 
        sub2(*buf1, *buf1, lo, carry);
 
2253
        SUB2(*buf1, *buf1, lo, carry);
2424
2254
        carry+=hi;
2425
2255
      }
2426
2256
      carry= dcarry < carry;
2434
2264
        buf1=start1+len2;
2435
2265
        for (carry=0; buf2 > start2; buf1--)
2436
2266
        {
2437
 
          add(*buf1, *buf1, *--buf2, carry);
 
2267
          ADD(*buf1, *buf1, *--buf2, carry);
2438
2268
        }
2439
2269
      }
2440
2270
    }
2448
2278
    /*
2449
2279
      now the result is in tmp1, it has
2450
2280
        intg=prec1-frac1
2451
 
        frac=cmax(frac1, frac2)=to->frac
 
2281
        frac=max(frac1, frac2)=to->frac
2452
2282
    */
2453
2283
    if (dcarry)
2454
2284
      *--start1=dcarry;
2455
2285
    buf0=to->buf;
2456
 
    intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
2457
 
    frac0=round_up(to->frac);
 
2286
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
 
2287
    frac0=ROUND_UP(to->frac);
2458
2288
    error=E_DEC_OK;
2459
2289
    if (unlikely(frac0==0 && intg0==0))
2460
2290
    {
2461
 
      to->set_zero();
 
2291
      decimal_make_zero(to);
2462
2292
      goto done;
2463
2293
    }
2464
2294
    if (intg0<=0)
2465
2295
    {
2466
2296
      if (unlikely(-intg0 >= to->len))
2467
2297
      {
2468
 
        to->set_zero();
 
2298
        decimal_make_zero(to);
2469
2299
        error=E_DEC_TRUNCATED;
2470
2300
        goto done;
2471
2301
      }
2484
2314
        error=E_DEC_OVERFLOW;
2485
2315
        goto done;
2486
2316
      }
2487
 
      assert(intg0 <= round_up(from2->intg));
 
2317
      assert(intg0 <= ROUND_UP(from2->intg));
2488
2318
      stop1=start1+frac0+intg0;
2489
2319
      to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2490
2320
    }
2503
2333
  return error;
2504
2334
}
2505
2335
 
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
 
2336
/*
 
2337
  division of two decimals
 
2338
 
 
2339
  SYNOPSIS
 
2340
    decimal_div()
 
2341
      from1   - dividend
 
2342
      from2   - divisor
 
2343
      to      - quotient
 
2344
 
 
2345
  RETURN VALUE
2514
2346
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2515
2347
 
2516
 
 @note
 
2348
  NOTES
2517
2349
    see do_div_mod()
2518
2350
*/
 
2351
 
2519
2352
int
2520
 
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
 
2353
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2521
2354
{
2522
2355
  return do_div_mod(from1, from2, to, 0, scale_incr);
2523
2356
}
2524
2357
 
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
 
2358
/*
 
2359
  modulus
 
2360
 
 
2361
  SYNOPSIS
 
2362
    decimal_mod()
 
2363
      from1   - dividend
 
2364
      from2   - divisor
 
2365
      to      - modulus
 
2366
 
 
2367
  RETURN VALUE
2544
2368
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2545
2369
 
2546
 
 @note
 
2370
  NOTES
2547
2371
    see do_div_mod()
2548
2372
 
 
2373
  DESCRIPTION
 
2374
    the modulus R in    R = M mod N
 
2375
 
 
2376
   is defined as
 
2377
 
 
2378
     0 <= |R| < |M|
 
2379
     sign R == sign M
 
2380
     R = M - k*N, where k is integer
 
2381
 
 
2382
   thus, there's no requirement for M or N to be integers
2549
2383
*/
2550
 
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
2384
 
 
2385
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2551
2386
{
2552
2387
  return do_div_mod(from1, from2, 0, to, 0);
2553
2388
}
2554
2389
 
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
2390
#ifdef MAIN
2571
2391
 
2572
2392
int full= 0;
2577
2397
{
2578
2398
  int i;
2579
2399
  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++)
 
2400
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2581
2401
    printf("%09d, ", d->buf[i]);
2582
2402
  printf("%09d} */ ", d->buf[i]);
2583
2403
}
2649
2469
{
2650
2470
  char s1[100], *end;
2651
2471
  int res;
2652
 
  snprintf(s1, sizeof(s1), "'%s'", s);
 
2472
  sprintf(s1, "'%s'", s);
2653
2473
  end= strend(s);
2654
2474
  printf("len=%2d %-30s => res=%d    ", a.len, s1,
2655
2475
         (res= string2decimal(s, &a, &end)));
2663
2483
  double x;
2664
2484
  int res;
2665
2485
 
2666
 
  snprintf(s1, sizeof(s1), "'%s'", s);
 
2486
  sprintf(s1, "'%s'", s);
2667
2487
  end= strend(s);
2668
2488
  string2decimal(s, &a, &end);
2669
2489
  res=decimal2double(&a, &x);
2677
2497
  char s1[100], buf[100], *end;
2678
2498
  int res, i, size=decimal_bin_size(p, s);
2679
2499
 
2680
 
  snprintf(s1, sizeof(s1), "'%s'", str);
 
2500
  sprintf(s1, "'%s'", str);
2681
2501
  end= strend(str);
2682
2502
  string2decimal(str, &a, &end);
2683
2503
  res=decimal2bin(&a, buf, p, s);
2686
2506
  {
2687
2507
    printf("0x");
2688
2508
    for (i=0; i < size; i++)
2689
 
      printf("%02x", ((unsigned char *)buf)[i]);
 
2509
      printf("%02x", ((uchar *)buf)[i]);
2690
2510
  }
2691
2511
  res=bin2decimal(buf, &a, p, s);
2692
2512
  printf(" => res=%d ", res);
2710
2530
  int res;
2711
2531
 
2712
2532
  res=uint64_t2decimal(from, &a);
2713
 
  internal::int64_t10_to_str(from,s,10);
 
2533
  int64_t10_to_str(from,s,10);
2714
2534
  printf("%-40s => res=%d    ", s, res);
2715
2535
  print_decimal(&a, orig, res, ex);
2716
2536
  printf("\n");
2722
2542
  int res;
2723
2543
 
2724
2544
  res=int64_t2decimal(from, &a);
2725
 
  internal::int64_t10_to_str(from,s,-10);
 
2545
  int64_t10_to_str(from,s,-10);
2726
2546
  printf("%-40s => res=%d    ", s, res);
2727
2547
  print_decimal(&a, orig, res, ex);
2728
2548
  printf("\n");
2738
2558
  string2decimal(s, &a, &end);
2739
2559
  res=decimal2uint64_t(&a, &x);
2740
2560
  if (full) dump_decimal(&a);
2741
 
  internal::int64_t10_to_str(x,s1,10);
 
2561
  int64_t10_to_str(x,s1,10);
2742
2562
  printf("%-40s => res=%d    %s\n", s, res, s1);
2743
2563
  check_result_code(res, ex);
2744
2564
  if (orig && strcmp(orig, s1))
2758
2578
  string2decimal(s, &a, &end);
2759
2579
  res=decimal2int64_t(&a, &x);
2760
2580
  if (full) dump_decimal(&a);
2761
 
  internal::int64_t10_to_str(x,s1,-10);
 
2581
  int64_t10_to_str(x,s1,-10);
2762
2582
  printf("%-40s => res=%d    %s\n", s, res, s1);
2763
2583
  check_result_code(res, ex);
2764
2584
  if (orig && strcmp(orig, s1))
2772
2592
{
2773
2593
  char s[100], *end;
2774
2594
  int res;
2775
 
  snprintf(s, sizeof(s), "'%s' + '%s'", s1, s2);
 
2595
  sprintf(s, "'%s' + '%s'", s1, s2);
2776
2596
  end= strend(s1);
2777
2597
  string2decimal(s1, &a, &end);
2778
2598
  end= strend(s2);
2787
2607
{
2788
2608
  char s[100], *end;
2789
2609
  int res;
2790
 
  snprintf(s, sizeof(s), "'%s' - '%s'", s1, s2);
 
2610
  sprintf(s, "'%s' - '%s'", s1, s2);
2791
2611
  end= strend(s1);
2792
2612
  string2decimal(s1, &a, &end);
2793
2613
  end= strend(s2);
2802
2622
{
2803
2623
  char s[100], *end;
2804
2624
  int res;
2805
 
  snprintf(s, sizeof(s), "'%s' <=> '%s'", s1, s2);
 
2625
  sprintf(s, "'%s' <=> '%s'", s1, s2);
2806
2626
  end= strend(s1);
2807
2627
  string2decimal(s1, &a, &end);
2808
2628
  end= strend(s2);
2820
2640
{
2821
2641
  char s[100], *end;
2822
2642
  int res;
2823
 
  snprintf(s, sizeof(s), "'%s' * '%s'", s1, s2);
 
2643
  sprintf(s, "'%s' * '%s'", s1, s2);
2824
2644
  end= strend(s1);
2825
2645
  string2decimal(s1, &a, &end);
2826
2646
  end= strend(s2);
2835
2655
{
2836
2656
  char s[100], *end;
2837
2657
  int res;
2838
 
  snprintf(s, sizeof(s), "'%s' / '%s'", s1, s2);
 
2658
  sprintf(s, "'%s' / '%s'", s1, s2);
2839
2659
  end= strend(s1);
2840
2660
  string2decimal(s1, &a, &end);
2841
2661
  end= strend(s2);
2854
2674
{
2855
2675
  char s[100], *end;
2856
2676
  int res;
2857
 
  snprintf(s, sizeof(s), "'%s' %% '%s'", s1, s2);
 
2677
  sprintf(s, "'%s' %% '%s'", s1, s2);
2858
2678
  end= strend(s1);
2859
2679
  string2decimal(s1, &a, &end);
2860
2680
  end= strend(s2);
2877
2697
{
2878
2698
  char s[100], *end;
2879
2699
  int res;
2880
 
  snprintf(s, sizeof(s), "'%s', %d, %s", s1, n, round_mode[mode]);
 
2700
  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2881
2701
  end= strend(s1);
2882
2702
  string2decimal(s1, &a, &end);
2883
2703
  res=decimal_round(&a, &b, n, mode);
2890
2710
void test_mx(int precision, int frac, const char *orig)
2891
2711
{
2892
2712
  char s[100];
2893
 
  snprintf(s, sizeof(s), "%d, %d", precision, frac);
 
2713
  sprintf(s, "%d, %d", precision, frac);
2894
2714
  max_decimal(precision, frac, &a);
2895
2715
  printf("%-40s =>          ", s);
2896
2716
  print_decimal(&a, orig, 0, 0);
2906
2726
  int slen= sizeof(s2);
2907
2727
  int res;
2908
2728
 
2909
 
  snprintf(s, sizeof(s), filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
 
2729
  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2910
2730
          s1, prec, dec, filler);
2911
2731
  end= strend(s1);
2912
2732
  string2decimal(s1, &a, &end);
2926
2746
{
2927
2747
  char s[100], *end;
2928
2748
  int res;
2929
 
  snprintf(s, sizeof(s), "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
 
2749
  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2930
2750
  end= strend(s1);
2931
2751
  string2decimal(s1, &a, &end);
2932
2752
  res= decimal_shift(&a, shift);
2939
2759
void test_fr(const char *s1, const char *orig)
2940
2760
{
2941
2761
  char s[100], *end;
2942
 
  snprintf(s, sizeof(s), "'%s'", s1);
 
2762
  sprintf(s, "'%s'", s1);
2943
2763
  printf("%-40s =>          ", s);
2944
2764
  end= strend(s1);
2945
2765
  string2decimal(s1, &a, &end);
3298
3118
 
3299
3119
  return 0;
3300
3120
}
3301
 
 
3302
3121
#endif