~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/decimal.c

  • Committer: Brian Aker
  • Date: 2008-10-18 15:43:20 UTC
  • mto: (492.3.20 drizzle-clean-code)
  • mto: This revision was merged to the branch mainline in revision 530.
  • Revision ID: brian@tangent.org-20081018154320-jc9jyij3mdf08abp
Updating tests.

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