~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/decimal.cc

  • Committer: Monty Taylor
  • Date: 2009-12-14 22:00:27 UTC
  • mto: (1241.9.10 out-of-tree)
  • mto: This revision was merged to the branch mainline in revision 1250.
  • Revision ID: mordred@inaugust.com-20091214220027-kpmfbl452nctzc0g
pandora-build v0.85 - Fixed C++ standard setting.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
 
 
16
 
/** @file
17
 
 *
18
 
 * @brief  SQL standard-compliant decimal number handling
19
 
 *
20
 
 * @note
21
 
 * This library implements SQL standard "exact numeric" type
22
 
 * and is not at all generic, but rather intentinally crippled to
23
 
 * follow the standard :) 
24
 
 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
25
15
 
26
16
/*
27
17
=======================================================================
 
18
  NOTE: this library implements SQL standard "exact numeric" type
 
19
  and is not at all generic, but rather intentinally crippled to
 
20
  follow the standard :)
 
21
=======================================================================
28
22
  Quoting the standard
29
23
  (SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
30
24
 
103
97
      implementation-defined.
104
98
*/
105
99
 
106
 
#include "config.h"
 
100
#include <drizzled/global.h>
107
101
 
108
 
#include "drizzled/definitions.h"
109
 
#include "drizzled/internal/m_string.h"
110
 
#include "drizzled/charset_info.h"
111
 
#include "drizzled/decimal.h"
 
102
#include "m_string.h"
 
103
#include "m_ctype.h"
 
104
#include "decimal.h"
112
105
 
113
106
#include <plugin/myisam/myisampack.h>
114
107
#include <drizzled/util/test.h>
118
111
#endif
119
112
 
120
113
#include <algorithm>
121
 
#include <time.h>
122
 
#include "drizzled/current_session.h"
123
 
#include "drizzled/error.h"
124
 
#include "drizzled/field.h"
125
 
#include "drizzled/internal/my_sys.h"
126
114
 
127
115
using namespace std;
128
116
 
129
 
namespace drizzled
130
 
{
131
 
/**
132
 
  report result of decimal operation.
133
 
 
134
 
  @param result  decimal library return code (E_DEC_* see include/decimal.h)
135
 
 
136
 
  @todo
137
 
    Fix error messages
138
 
 
139
 
  @return
140
 
    result
141
 
*/
142
 
 
143
 
int decimal_operation_results(int result)
144
 
{
145
 
  switch (result) {
146
 
  case E_DEC_OK:
147
 
    break;
148
 
  case E_DEC_TRUNCATED:
149
 
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
150
 
                        ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
151
 
                        "", (long)-1);
152
 
    break;
153
 
  case E_DEC_OVERFLOW:
154
 
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
155
 
                        ER_TRUNCATED_WRONG_VALUE,
156
 
                        ER(ER_TRUNCATED_WRONG_VALUE),
157
 
                        "DECIMAL", "");
158
 
    break;
159
 
  case E_DEC_DIV_ZERO:
160
 
    my_error(ER_DIVISION_BY_ZERO, MYF(0));
161
 
    break;
162
 
  case E_DEC_BAD_NUM:
163
 
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
164
 
                        ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
165
 
                        ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
166
 
                        "decimal", "", "", (long)-1);
167
 
    break;
168
 
  case E_DEC_OOM:
169
 
    my_error(ER_OUT_OF_RESOURCES, MYF(0));
170
 
    break;
171
 
  default:
172
 
    assert(0);
173
 
  }
174
 
  return result;
175
 
}
176
 
 
177
 
 
178
 
/**
179
 
  @brief Converting decimal to string
180
 
 
181
 
  @details Convert given my_decimal to String; allocate buffer as needed.
182
 
 
183
 
  @param[in]   mask        what problems to warn on (mask of E_DEC_* values)
184
 
  @param[in]   d           the decimal to print
185
 
  @param[in]   fixed_prec  overall number of digits if ZEROFILL, 0 otherwise
186
 
  @param[in]   fixed_dec   number of decimal places (if fixed_prec != 0)
187
 
  @param[in]   filler      what char to pad with (ZEROFILL et al.)
188
 
  @param[out]  *str        where to store the resulting string
189
 
 
190
 
  @return error code
191
 
    @retval E_DEC_OK
192
 
    @retval E_DEC_TRUNCATED
193
 
    @retval E_DEC_OVERFLOW
194
 
    @retval E_DEC_OOM
195
 
*/
196
 
 
197
 
int my_decimal2string(uint32_t mask, const my_decimal *d,
198
 
                      uint32_t fixed_prec, uint32_t fixed_dec,
199
 
                      char filler, String *str)
200
 
{
201
 
  /*
202
 
    Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
203
 
    holds true iff the type is also ZEROFILL, which in turn implies
204
 
    UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
205
 
    the user requested, plus one for a possible decimal point, plus
206
 
    one if the user only wanted decimal places, but we force a leading
207
 
    zero on them. Because the type is implicitly UNSIGNED, we do not
208
 
    need to reserve a character for the sign. For all other cases,
209
 
    fixed_prec will be 0, and my_decimal_string_length() will be called
210
 
    instead to calculate the required size of the buffer.
211
 
  */
212
 
  int length= (int)(fixed_prec
213
 
                    ? (uint32_t)(fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
214
 
                    : (uint32_t)my_decimal_string_length(d));
215
 
  int result;
216
 
  if (str->alloc(length))
217
 
    return check_result(mask, E_DEC_OOM);
218
 
  result= decimal2string((decimal_t*) d, (char*) str->ptr(),
219
 
                         &length, (int)fixed_prec, fixed_dec,
220
 
                         filler);
221
 
  str->length(length);
222
 
  return check_result(mask, result);
223
 
}
224
 
 
225
 
 
226
 
/**
227
 
  @brief  Convert from decimal to binary representation
228
 
 
229
 
  @param[in]   mask        error processing mask
230
 
  @param[in]   d           number for conversion
231
 
  @param[out]  bin         pointer to buffer where to write result
232
 
  @param[in]   prec        overall number of decimal digits
233
 
  @param[in]   scale       number of decimal digits after decimal point
234
 
 
235
 
  @note
236
 
    Before conversion we round number if it need but produce truncation
237
 
    error in this case
238
 
 
239
 
  @return error code
240
 
   @retval E_DEC_OK
241
 
   @retval E_DEC_TRUNCATED
242
 
   @retval E_DEC_OVERFLOW
243
 
*/
244
 
 
245
 
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
246
 
                      int scale)
247
 
{
248
 
  int err1= E_DEC_OK, err2;
249
 
  my_decimal rounded;
250
 
  my_decimal2decimal(d, &rounded);
251
 
  rounded.frac= decimal_actual_fraction(&rounded);
252
 
  if (scale < rounded.frac)
253
 
  {
254
 
    err1= E_DEC_TRUNCATED;
255
 
    /* decimal_round can return only E_DEC_TRUNCATED */
256
 
    decimal_round(&rounded, &rounded, scale, HALF_UP);
257
 
  }
258
 
  err2= decimal2bin(&rounded, bin, prec, scale);
259
 
  if (!err2)
260
 
    err2= err1;
261
 
  return check_result(mask, err2);
262
 
}
263
 
 
264
 
 
265
 
/**
266
 
  @brief Convert string for decimal when string can be in some multibyte charset
267
 
 
268
 
  @param  mask            error processing mask
269
 
  @param  from            string to process
270
 
  @param  length          length of given string
271
 
  @param  charset         charset of given string
272
 
  @param  decimal_value   buffer for result storing
273
 
 
274
 
  @return Error code
275
 
   @retval E_DEC_OK
276
 
   @retval E_DEC_TRUNCATED
277
 
   @retval E_DEC_OVERFLOW
278
 
   @retval E_DEC_BAD_NUM
279
 
   @retval E_DEC_OOM
280
 
*/
281
 
 
282
 
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
283
 
                   const CHARSET_INFO * charset, my_decimal *decimal_value)
284
 
{
285
 
  char *end, *from_end;
286
 
  int err;
287
 
  char buff[STRING_BUFFER_USUAL_SIZE];
288
 
  String tmp(buff, sizeof(buff), &my_charset_bin);
289
 
  if (charset->mbminlen > 1)
290
 
  {
291
 
    size_t dummy_errors;
292
 
    tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
293
 
    from= tmp.ptr();
294
 
    length=  tmp.length();
295
 
    charset= &my_charset_bin;
296
 
  }
297
 
  from_end= end= (char*) from+length;
298
 
  err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
299
 
  if (end != from_end && !err)
300
 
  {
301
 
    /* Give warning if there is something other than end space */
302
 
    for ( ; end < from_end; end++)
303
 
    {
304
 
      if (!my_isspace(&my_charset_utf8_general_ci, *end))
305
 
      {
306
 
        err= E_DEC_TRUNCATED;
307
 
        break;
308
 
      }
309
 
    }
310
 
  }
311
 
  check_result_and_overflow(mask, err, decimal_value);
312
 
  return err;
313
 
}
314
 
 
315
 
 
316
 
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
317
 
{
318
 
  int64_t date;
319
 
  date = (ltime->year*100L + ltime->month)*100L + ltime->day;
320
 
  if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
321
 
    date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
322
 
  if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
323
 
    return dec;
324
 
  if (ltime->second_part)
325
 
  {
326
 
    dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
327
 
    dec->frac= 6;
328
 
  }
329
 
  return dec;
330
 
}
331
 
 
332
 
 
333
 
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
334
 
{
335
 
  if (!(*precision) && !(*scale))
336
 
  {
337
 
    *precision= 10;
338
 
    *scale= 0;
339
 
    return;
340
 
  }
341
 
}
342
 
 
343
117
 
344
118
/*
345
119
  Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
363
137
#define DIG_MASK     100000000
364
138
#define DIG_BASE     1000000000
365
139
#define DIG_MAX      (DIG_BASE-1)
366
 
 
367
 
template<typename T> 
368
 
inline static T round_up(const T &x)
369
 
{
370
 
  return (x+DIG_PER_DEC1-1)/DIG_PER_DEC1;
371
 
}
372
 
 
 
140
#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
373
141
static const dec1 powers10[DIG_PER_DEC1+1]={
374
142
  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
375
143
static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
378
146
  999900000, 999990000, 999999000,
379
147
  999999900, 999999990 };
380
148
 
381
 
#ifdef HAVE_VALGRIND
 
149
#ifdef HAVE_purify
382
150
#define sanity(d) assert((d)->len > 0)
383
151
#else
384
152
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
385
153
                              (d)->buf[(d)->len-1] | 1))
386
154
#endif
387
155
 
388
 
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
389
 
{
390
 
  if (unlikely(intg1+frac1 > len))
391
 
  {
392
 
    if (unlikely(intg1 > len))
393
 
    {
394
 
      intg1=(len);
395
 
      frac1=0;
396
 
      error=E_DEC_OVERFLOW;
397
 
    }
398
 
    else
399
 
    {
400
 
      frac1=(len)-intg1;
401
 
      error=E_DEC_TRUNCATED;
402
 
    }
403
 
  }
404
 
  else
405
 
    error=E_DEC_OK;
406
 
}
407
 
 
408
 
/* assume carry <= 1 */
409
 
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
410
 
{
411
 
  dec1 a=from1+from2+carry;
412
 
  assert(carry <= 1);
413
 
  if ((carry= (a >= DIG_BASE))) /* no division here! */
414
 
    a-=DIG_BASE;
415
 
  to=a;
416
 
}
417
 
 
418
 
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
419
 
{
420
 
  dec2 a=dec2(from1)+from2+carry;
421
 
  if ((carry= (a >= DIG_BASE)))
422
 
    a-=DIG_BASE;
423
 
  if (unlikely(a >= DIG_BASE))
424
 
  {
425
 
    a-=DIG_BASE;
426
 
    carry++;
427
 
  }
428
 
  to=dec1(a);
429
 
}
430
 
 
431
 
/* to=from1-from2 */
432
 
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
433
 
{
434
 
  dec1 a=from1-from2-carry;
435
 
  if ((carry= (a < 0)))
436
 
    a+=DIG_BASE;
437
 
  to=a;
438
 
}
439
 
 
440
 
/* to=from1-from2 */
441
 
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
442
 
{
443
 
  dec1 a=from1-from2-carry;
444
 
  if ((carry= (a < 0)))
445
 
    a+=DIG_BASE;
446
 
  if (unlikely(a < 0))
447
 
  {
448
 
    a+=DIG_BASE;
449
 
    carry++;
450
 
  }
451
 
  to=a;
452
 
}
 
156
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error)                   \
 
157
        do                                                              \
 
158
        {                                                               \
 
159
          if (unlikely(intg1+frac1 > (len)))                            \
 
160
          {                                                             \
 
161
            if (unlikely(intg1 > (len)))                                \
 
162
            {                                                           \
 
163
              intg1=(len);                                              \
 
164
              frac1=0;                                                  \
 
165
              error=E_DEC_OVERFLOW;                                     \
 
166
            }                                                           \
 
167
            else                                                        \
 
168
            {                                                           \
 
169
              frac1=(len)-intg1;                                        \
 
170
              error=E_DEC_TRUNCATED;                                    \
 
171
            }                                                           \
 
172
          }                                                             \
 
173
          else                                                          \
 
174
            error=E_DEC_OK;                                             \
 
175
        } while(0)
 
176
 
 
177
#define ADD(to, from1, from2, carry)  /* assume carry <= 1 */           \
 
178
        do                                                              \
 
179
        {                                                               \
 
180
          dec1 a=(from1)+(from2)+(carry);                               \
 
181
          assert((carry) <= 1);                                    \
 
182
          if (((carry)= a >= DIG_BASE)) /* no division here! */         \
 
183
            a-=DIG_BASE;                                                \
 
184
          (to)=a;                                                       \
 
185
        } while(0)
 
186
 
 
187
#define ADD2(to, from1, from2, carry)                                   \
 
188
        do                                                              \
 
189
        {                                                               \
 
190
          dec2 a=((dec2)(from1))+(from2)+(carry);                       \
 
191
          if (((carry)= a >= DIG_BASE))                                 \
 
192
            a-=DIG_BASE;                                                \
 
193
          if (unlikely(a >= DIG_BASE))                                  \
 
194
          {                                                             \
 
195
            a-=DIG_BASE;                                                \
 
196
            carry++;                                                    \
 
197
          }                                                             \
 
198
          (to)=(dec1) a;                                                \
 
199
        } while(0)
 
200
 
 
201
#define SUB(to, from1, from2, carry) /* to=from1-from2 */               \
 
202
        do                                                              \
 
203
        {                                                               \
 
204
          dec1 a=(from1)-(from2)-(carry);                               \
 
205
          if (((carry)= a < 0))                                         \
 
206
            a+=DIG_BASE;                                                \
 
207
          (to)=a;                                                       \
 
208
        } while(0)
 
209
 
 
210
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */              \
 
211
        do                                                              \
 
212
        {                                                               \
 
213
          dec1 a=(from1)-(from2)-(carry);                               \
 
214
          if (((carry)= a < 0))                                         \
 
215
            a+=DIG_BASE;                                                \
 
216
          if (unlikely(a < 0))                                          \
 
217
          {                                                             \
 
218
            a+=DIG_BASE;                                                \
 
219
            carry++;                                                    \
 
220
          }                                                             \
 
221
          (to)=a;                                                       \
 
222
        } while(0)
453
223
 
454
224
/**
455
 
  @brief  Get maximum value for given precision and scale
456
 
 
457
 
  @param  precision/scale  see decimal_bin_size() below
458
 
  @param  to              decimal where where the result will be stored
 
225
  Swap the contents of two variables.
 
226
 */
 
227
#define swap_variables(TYPE, a, b) \
 
228
  do {                             \
 
229
    TYPE dummy;                    \
 
230
    dummy= a;                      \
 
231
    a= b;                          \
 
232
    b= dummy;                      \
 
233
  } while (0)
 
234
 
 
235
 
 
236
/*
 
237
  Get maximum value for given precision and scale
 
238
 
 
239
  SYNOPSIS
 
240
    max_decimal()
 
241
    precision/scale - see decimal_bin_size() below
 
242
    to              - decimal where where the result will be stored
459
243
                      to->buf and to->len must be set.
460
244
*/
461
245
 
486
270
}
487
271
 
488
272
 
489
 
static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
 
273
static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
490
274
{
491
275
  int intg= from->intg, i;
492
276
  dec1 *buf0= from->buf;
509
293
}
510
294
 
511
295
 
512
 
/**
513
 
 @brief Count actual length of fraction part (without ending zeroes)
 
296
/*
 
297
  Count actual length of fraction part (without ending zeroes)
514
298
 
515
 
 @param from    number for processing
 
299
  SYNOPSIS
 
300
    decimal_actual_fraction()
 
301
    from    number for processing
516
302
*/
517
303
 
518
304
int decimal_actual_fraction(decimal_t *from)
519
305
{
520
306
  int frac= from->frac, i;
521
 
  dec1 *buf0= from->buf + round_up(from->intg) + round_up(frac) - 1;
 
307
  dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
522
308
 
523
309
  if (frac == 0)
524
310
    return 0;
538
324
}
539
325
 
540
326
 
541
 
/**
542
 
 @brief  Convert decimal to its printable string representation
 
327
/*
 
328
  Convert decimal to its printable string representation
543
329
 
544
 
 @param  from       value to convert
545
 
 @param  to         points to buffer where string representation
546
 
                    should be stored
547
 
 @param  to_len     in:  size of to buffer
548
 
                    out: length of the actually written string
549
 
 @param  fixed_precision 0 if representation can be variable length and
 
330
  SYNOPSIS
 
331
    decimal2string()
 
332
      from            - value to convert
 
333
      to              - points to buffer where string representation
 
334
                        should be stored
 
335
      *to_len         - in:  size of to buffer
 
336
                        out: length of the actually written string
 
337
      fixed_precision - 0 if representation can be variable length and
550
338
                        fixed_decimals will not be checked in this case.
551
339
                        Put number as with fixed point position with this
552
340
                        number of digits (sign counted and decimal point is
553
341
                        counted)
554
 
 @param  fixed_decimals  number digits after point.
555
 
 @param  filler          character to fill gaps in case of fixed_precision > 0
 
342
      fixed_decimals  - number digits after point.
 
343
      filler          - character to fill gaps in case of fixed_precision > 0
556
344
 
557
 
 @return error code
558
 
   @retval E_DEC_OK
559
 
   @retval E_DEC_TRUNCATED
560
 
   @retval E_DEC_OVERFLOW
 
345
  RETURN VALUE
 
346
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
561
347
*/
562
 
int decimal2string(const decimal_t *from, char *to, int *to_len,
 
348
 
 
349
int decimal2string(decimal_t *from, char *to, int *to_len,
563
350
                   int fixed_precision, int fixed_decimals,
564
351
                   char filler)
565
352
{
623
410
  {
624
411
    char *s1= s + intg_len;
625
412
    fill= frac_len - frac;
626
 
    buf=buf0+round_up(intg);
 
413
    buf=buf0+ROUND_UP(intg);
627
414
    *s1++='.';
628
415
    for (; frac>0; frac-=DIG_PER_DEC1)
629
416
    {
648
435
  if (intg)
649
436
  {
650
437
    s+=intg;
651
 
    for (buf=buf0+round_up(intg); intg>0; intg-=DIG_PER_DEC1)
 
438
    for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
652
439
    {
653
440
      dec1 x=*--buf;
654
441
      for (i=min(intg, DIG_PER_DEC1); i; i--)
665
452
}
666
453
 
667
454
 
668
 
/**
669
 
 @brief  Return bounds of decimal digits in the number
 
455
/*
 
456
  Return bounds of decimal digits in the number
670
457
 
671
 
 @param  from  decimal number for processing
672
 
 @param  start_result  index (from 0 ) of first decimal digits will
673
 
                       be written by this address
674
 
 @param  end_result   index of position just after last decimal digit
 
458
  SYNOPSIS
 
459
    digits_bounds()
 
460
      from         - decimal number for processing
 
461
      start_result - index (from 0 ) of first decimal digits will
 
462
                     be written by this address
 
463
      end_result   - index of position just after last decimal digit
675
464
                     be written by this address
676
465
*/
 
466
 
677
467
static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
678
468
{
679
469
  int start, stop, i;
680
470
  dec1 *buf_beg= from->buf;
681
 
  dec1 *end= from->buf + round_up(from->intg) + round_up(from->frac);
 
471
  dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
682
472
  dec1 *buf_end= end - 1;
683
473
 
684
474
  /* find non-zero digit from number begining */
727
517
}
728
518
 
729
519
 
730
 
/**
731
 
 @param Left shift for alignment of data in buffer
732
 
 
733
 
 @param  dec     pointer to decimal number which have to be shifted
734
 
 @param  shift   number of decimal digits on which it should be shifted
735
 
 @param  beg     beginning of decimal digits (see digits_bounds())
736
 
 @param  end     end of decimal digits (see digits_bounds())
737
 
 
738
 
 @note
739
 
   Result fitting in the buffer should be garanted.
740
 
   'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
741
 
   
742
 
 @todo  Above note is unclear - is 'garanted' a typo for 'guaranteed'
743
 
 or 'granted'?
 
520
/*
 
521
  Left shift for alignment of data in buffer
 
522
 
 
523
  SYNOPSIS
 
524
    do_mini_left_shift()
 
525
    dec     pointer to decimal number which have to be shifted
 
526
    shift   number of decimal digits on which it should be shifted
 
527
    beg/end bounds of decimal digits (see digits_bounds())
 
528
 
 
529
  NOTE
 
530
    Result fitting in the buffer should be garanted.
 
531
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
744
532
*/
 
533
 
745
534
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
746
535
{
747
 
  dec1 *from= dec->buf + round_up(beg + 1) - 1;
748
 
  dec1 *end= dec->buf + round_up(last) - 1;
 
536
  dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
 
537
  dec1 *end= dec->buf + ROUND_UP(last) - 1;
749
538
  int c_shift= DIG_PER_DEC1 - shift;
750
539
  assert(from >= dec->buf);
751
540
  assert(end < dec->buf + dec->len);
758
547
}
759
548
 
760
549
 
761
 
/**
762
 
  @brief Right shift for alignment of data in buffer
763
 
 
764
 
  @param  dec     pointer to decimal number which have to be shifted
765
 
  @param  shift   number of decimal digits on which it should be shifted
766
 
  @param  beg     beginning of decimal digits (see digits_bounds())
767
 
  @param  end     end of decimal digits (see digits_bounds())
768
 
 
769
 
  @note
 
550
/*
 
551
  Right shift for alignment of data in buffer
 
552
 
 
553
  SYNOPSIS
 
554
    do_mini_left_shift()
 
555
    dec     pointer to decimal number which have to be shifted
 
556
    shift   number of decimal digits on which it should be shifted
 
557
    beg/end bounds of decimal digits (see digits_bounds())
 
558
 
 
559
  NOTE
770
560
    Result fitting in the buffer should be garanted.
771
561
    'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
772
562
*/
 
563
 
773
564
static void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
774
565
{
775
 
  dec1 *from= dec->buf + round_up(last) - 1;
776
 
  dec1 *end= dec->buf + round_up(beg + 1) - 1;
 
566
  dec1 *from= dec->buf + ROUND_UP(last) - 1;
 
567
  dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
777
568
  int c_shift= DIG_PER_DEC1 - shift;
778
569
  assert(from < dec->buf + dec->len);
779
570
  assert(end >= dec->buf);
786
577
}
787
578
 
788
579
 
789
 
/**
790
 
  @brief  Shift of decimal digits in given number (with rounding if it need)
 
580
/*
 
581
  Shift of decimal digits in given number (with rounding if it need)
791
582
 
792
 
  @param  dec       number to be shifted
793
 
  @param  shift     number of decimal positions
 
583
  SYNOPSIS
 
584
    decimal_shift()
 
585
    dec       number to be shifted
 
586
    shift     number of decimal positions
794
587
              shift > 0 means shift to left shift
795
588
              shift < 0 meand right shift
796
 
 
797
 
  @note
 
589
  NOTE
798
590
    In fact it is multipling on 10^shift.
 
591
  RETURN
 
592
    E_DEC_OK          OK
 
593
    E_DEC_OVERFLOW    operation lead to overflow, number is untoched
 
594
    E_DEC_TRUNCATED   number was rounded to fit into buffer
 
595
*/
799
596
 
800
 
  @return  Error code
801
 
   @retval E_DEC_OK          OK
802
 
   @retval E_DEC_OVERFLOW    operation lead to overflow, number is untoched
803
 
   @retval E_DEC_TRUNCATED   number was rounded to fit into buffer
804
 
*/
805
597
static int decimal_shift(decimal_t *dec, int shift)
806
598
{
807
599
  /* index of first non zero digit (all indexes from 0) */
809
601
  /* index of position after last decimal digit */
810
602
  int end;
811
603
  /* index of digit position just after point */
812
 
  int point= round_up(dec->intg) * DIG_PER_DEC1;
 
604
  int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
813
605
  /* new point position */
814
606
  int new_point= point + shift;
815
607
  /* number of digits in result */
836
628
  digits_frac= end - new_point;
837
629
  set_if_bigger(digits_frac, 0);
838
630
 
839
 
  if ((new_len= round_up(digits_int) + (new_frac_len= round_up(digits_frac))) >
 
631
  if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
840
632
      dec->len)
841
633
  {
842
634
    int lack= new_len - dec->len;
896
688
    if (do_left)
897
689
    {
898
690
      do_mini_left_shift(dec, l_mini_shift, beg, end);
899
 
      mini_shift= (-l_mini_shift);
 
691
      mini_shift=- l_mini_shift;
900
692
    }
901
693
    else
902
694
    {
929
721
    {
930
722
      /* move left */
931
723
      d_shift= new_front / DIG_PER_DEC1;
932
 
      to= dec->buf + (round_up(beg + 1) - 1 - d_shift);
933
 
      barier= dec->buf + (round_up(end) - 1 - d_shift);
 
724
      to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
 
725
      barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
934
726
      assert(to >= dec->buf);
935
727
      assert(barier + d_shift < dec->buf + dec->len);
936
728
      for(; to <= barier; to++)
943
735
    {
944
736
      /* move right */
945
737
      d_shift= (1 - new_front) / DIG_PER_DEC1;
946
 
      to= dec->buf + round_up(end) - 1 + d_shift;
947
 
      barier= dec->buf + round_up(beg + 1) - 1 + d_shift;
 
738
      to= dec->buf + ROUND_UP(end) - 1 + d_shift;
 
739
      barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
948
740
      assert(to < dec->buf + dec->len);
949
741
      assert(barier - d_shift >= dec->buf);
950
742
      for(; to >= barier; to--)
963
755
 
964
756
    Only one of following 'for' loops will work becouse beg <= end
965
757
  */
966
 
  beg= round_up(beg + 1) - 1;
967
 
  end= round_up(end) - 1;
 
758
  beg= ROUND_UP(beg + 1) - 1;
 
759
  end= ROUND_UP(end) - 1;
968
760
  assert(new_point >= 0);
969
761
 
970
762
  /* We don't want negative new_point below */
971
763
  if (new_point != 0)
972
 
    new_point= round_up(new_point) - 1;
 
764
    new_point= ROUND_UP(new_point) - 1;
973
765
 
974
766
  if (new_point > end)
975
767
  {
989
781
}
990
782
 
991
783
 
992
 
/**
993
 
  @brief  Convert string to decimal
 
784
/*
 
785
  Convert string to decimal
994
786
 
995
 
  @param  from    value to convert. Doesn't have to be \0 terminated!
996
 
  @param  to      decimal where where the result will be stored
 
787
  SYNOPSIS
 
788
    internal_str2decl()
 
789
      from    - value to convert. Doesn't have to be \0 terminated!
 
790
      to      - decimal where where the result will be stored
997
791
                to->buf and to->len must be set.
998
 
  @param  end     Pointer to pointer to end of string. Will on return be
 
792
      end     - Pointer to pointer to end of string. Will on return be
999
793
                set to the char after the last used character
1000
 
  @param  fixed   use to->intg, to->frac as limits for input number
 
794
      fixed   - use to->intg, to->frac as limits for input number
1001
795
 
1002
 
  @note
 
796
  NOTE
1003
797
    to->intg and to->frac can be modified even when fixed=1
1004
798
    (but only decreased, in this case)
1005
799
 
1006
 
  @return
 
800
  RETURN VALUE
1007
801
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
1008
802
    In case of E_DEC_FATAL_ERROR *to is set to decimal zero
1009
803
    (to make error handling easier)
1010
804
*/
 
805
 
1011
806
int
1012
807
internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
1013
808
{
1064
859
      error=E_DEC_OVERFLOW;
1065
860
      intg=to->intg;
1066
861
    }
1067
 
    intg1=round_up(intg);
1068
 
    frac1=round_up(frac);
 
862
    intg1=ROUND_UP(intg);
 
863
    frac1=ROUND_UP(frac);
1069
864
    if (intg1+frac1 > to->len)
1070
865
    {
1071
866
      error= E_DEC_OOM;
1074
869
  }
1075
870
  else
1076
871
  {
1077
 
    intg1=round_up(intg);
1078
 
    frac1=round_up(frac);
1079
 
    fix_intg_frac_error(to->len, intg1, frac1, error);
 
872
    intg1=ROUND_UP(intg);
 
873
    frac1=ROUND_UP(frac);
 
874
    FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1080
875
    if (unlikely(error))
1081
876
    {
1082
877
      frac=frac1*DIG_PER_DEC1;
1124
919
  if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
1125
920
  {
1126
921
    int str_error;
1127
 
    const int64_t exponent= internal::my_strtoll10(endp+1, (char**) &end_of_string,
1128
 
                                                   &str_error);
 
922
    const int64_t exponent= my_strtoll10(endp+1, (char**) &end_of_string,
 
923
                                    &str_error);
1129
924
 
1130
925
    if (end_of_string != endp +1)               /* If at least one digit */
1131
926
    {
1157
952
}
1158
953
 
1159
954
 
1160
 
/**
1161
 
  @param Convert decimal to double
1162
 
 
1163
 
  @param[in]   from   value to convert
1164
 
  @param[out]  to     result will be stored there
1165
 
 
1166
 
  @return
 
955
/*
 
956
  Convert decimal to double
 
957
 
 
958
  SYNOPSIS
 
959
    decimal2double()
 
960
      from    - value to convert
 
961
      to      - result will be stored there
 
962
 
 
963
  RETURN VALUE
1167
964
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1168
965
*/
1169
966
 
1170
 
int decimal2double(const decimal_t *from, double *to)
 
967
int decimal2double(decimal_t *from, double *to)
1171
968
{
1172
969
  char strbuf[FLOATING_POINT_BUFFER], *end;
1173
970
  int len= sizeof(strbuf);
1176
973
  rc = decimal2string(from, strbuf, &len, 0, 0, 0);
1177
974
  end= strbuf + len;
1178
975
 
1179
 
  *to= internal::my_strtod(strbuf, &end, &error);
 
976
  *to= my_strtod(strbuf, &end, &error);
1180
977
 
1181
978
  return (rc != E_DEC_OK) ? rc : (error ? E_DEC_OVERFLOW : E_DEC_OK);
1182
979
}
1183
980
 
1184
 
/**
1185
 
 @param  Convert double to decimal
1186
 
 
1187
 
 @param[in]  from    value to convert
1188
 
 @param[out] to      result will be stored there
1189
 
 
1190
 
 @return
 
981
/*
 
982
  Convert double to decimal
 
983
 
 
984
  SYNOPSIS
 
985
    double2decimal()
 
986
      from    - value to convert
 
987
      to      - result will be stored there
 
988
 
 
989
  RETURN VALUE
1191
990
    E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
1192
991
*/
1193
992
 
1194
 
int double2decimal(const double from, decimal_t *to)
 
993
int double2decimal(double from, decimal_t *to)
1195
994
{
1196
995
  char buff[FLOATING_POINT_BUFFER], *end;
1197
996
  int res;
1198
 
  end= buff + internal::my_gcvt(from,
1199
 
                                internal::MY_GCVT_ARG_DOUBLE,
1200
 
                                sizeof(buff) - 1, buff, NULL);
 
997
  end= buff + my_gcvt(from, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
1201
998
  res= string2decimal(buff, to, &end);
1202
999
  return(res);
1203
1000
}
1229
1026
  return error;
1230
1027
}
1231
1028
 
1232
 
int uint64_t2decimal(const uint64_t from, decimal_t *to)
 
1029
int uint64_t2decimal(uint64_t from, decimal_t *to)
1233
1030
{
1234
1031
  to->sign=0;
1235
1032
  return ull2dec(from, to);
1236
1033
}
1237
1034
 
1238
 
int int64_t2decimal(const int64_t from, decimal_t *to)
 
1035
int int64_t2decimal(int64_t from, decimal_t *to)
1239
1036
{
1240
1037
  if ((to->sign= from < 0))
1241
1038
    return ull2dec(-from, to);
1242
1039
  return ull2dec(from, to);
1243
1040
}
1244
1041
 
1245
 
int decimal2uint64_t(const decimal_t *from, uint64_t *to)
 
1042
int decimal2uint64_t(decimal_t *from, uint64_t *to)
1246
1043
{
1247
1044
  dec1 *buf=from->buf;
1248
1045
  uint64_t x=0;
1271
1068
  return E_DEC_OK;
1272
1069
}
1273
1070
 
1274
 
int decimal2int64_t(const decimal_t *from, int64_t *to)
 
1071
int decimal2int64_t(decimal_t *from, int64_t *to)
1275
1072
{
1276
1073
  dec1 *buf=from->buf;
1277
1074
  int64_t x=0;
1311
1108
  return E_DEC_OK;
1312
1109
}
1313
1110
 
1314
 
/**
1315
 
 @brief
1316
 
  Convert decimal to its binary fixed-length representation (suitable for
1317
 
  comparing with memcmp)
1318
 
 
 
1111
/*
 
1112
  Convert decimal to its binary fixed-length representation
 
1113
  two representations of the same length can be compared with memcmp
 
1114
  with the correct -1/0/+1 result
 
1115
 
 
1116
  SYNOPSIS
 
1117
    decimal2bin()
 
1118
      from    - value to convert
 
1119
      to      - points to buffer where string representation should be stored
 
1120
      precision/scale - see decimal_bin_size() below
 
1121
 
 
1122
  NOTE
 
1123
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
 
1124
 
 
1125
  RETURN VALUE
 
1126
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
 
1127
 
 
1128
  DESCRIPTION
1319
1129
    for storage decimal numbers are converted to the "binary" format.
1320
1130
 
1321
1131
    This format has the following properties:
1376
1186
    And for -1234567890.1234 it would be
1377
1187
 
1378
1188
                7E F2 04 37 2D FB 2D
1379
 
 
1380
 
 
1381
 
  @param from      value to convert
1382
 
  @param to        points to buffer where string representation should be stored
1383
 
  @param precision see decimal_bin_size() below
1384
 
  @param frac      see decimal_bin_size() below
1385
 
 
1386
 
  @note
1387
 
    The buffer is assumed to be of the size decimal_bin_size(precision, scale)
1388
 
 
1389
 
  @return
1390
 
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1391
 
 
1392
1189
*/
1393
 
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
 
1190
int decimal2bin(decimal_t *from, unsigned char *to, int precision, int frac)
1394
1191
{
1395
1192
  dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
1396
1193
  int error=E_DEC_OK, intg=precision-frac,
1508
1305
  return error;
1509
1306
}
1510
1307
 
1511
 
/**
1512
 
 @brief Restores decimal from its binary fixed-length representation
1513
 
 
1514
 
 @param  from    value to convert
1515
 
 @param  to      result
1516
 
 @param  precision see decimal_bin_size() below
1517
 
 @param  scale     see decimal_bin_size() below
1518
 
 
1519
 
 @note
 
1308
/*
 
1309
  Restores decimal from its binary fixed-length representation
 
1310
 
 
1311
  SYNOPSIS
 
1312
    bin2decimal()
 
1313
      from    - value to convert
 
1314
      to      - result
 
1315
      precision/scale - see decimal_bin_size() below
 
1316
 
 
1317
  NOTE
1520
1318
    see decimal2bin()
1521
1319
    the buffer is assumed to be of the size decimal_bin_size(precision, scale)
1522
1320
 
1523
 
 @return
 
1321
  RETURN VALUE
1524
1322
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
1525
1323
*/
 
1324
 
1526
1325
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
1527
1326
{
1528
1327
  int error=E_DEC_OK, intg=precision-scale,
1540
1339
  d_copy[0]^= 0x80;
1541
1340
  from= d_copy;
1542
1341
 
1543
 
  fix_intg_frac_error(to->len, intg1, frac1, error);
 
1342
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
1544
1343
  if (unlikely(error))
1545
1344
  {
1546
1345
    if (intg1 < intg0+(intg0x>0))
1625
1424
  return(E_DEC_BAD_NUM);
1626
1425
}
1627
1426
 
1628
 
/**
1629
 
 @brief  Returns the size of array to hold a binary representation of a decimal
 
1427
/*
 
1428
  Returns the size of array to hold a binary representation of a decimal
1630
1429
 
1631
 
 @return  Size in bytes
 
1430
  RETURN VALUE
 
1431
    size in bytes
1632
1432
*/
 
1433
 
1633
1434
int decimal_bin_size(int precision, int scale)
1634
1435
{
1635
1436
  int intg=precision-scale,
1641
1442
         frac0*sizeof(dec1)+dig2bytes[frac0x];
1642
1443
}
1643
1444
 
1644
 
/**
1645
 
 @brief  Rounds the decimal to "scale" digits
1646
 
 
1647
 
 @param from    - decimal to round,
1648
 
 @param to      - result buffer. from==to is allowed
1649
 
 @param scale   - to what position to round. can be negative!
1650
 
 @param mode    - round to nearest even or truncate
1651
 
 
1652
 
 @note
 
1445
/*
 
1446
  Rounds the decimal to "scale" digits
 
1447
 
 
1448
  SYNOPSIS
 
1449
    decimal_round()
 
1450
      from    - decimal to round,
 
1451
      to      - result buffer. from==to is allowed
 
1452
      scale   - to what position to round. can be negative!
 
1453
      mode    - round to nearest even or truncate
 
1454
 
 
1455
  NOTES
1653
1456
    scale can be negative !
1654
1457
    one TRUNCATED error (line XXX below) isn't treated very logical :(
1655
1458
 
1656
 
 @return
 
1459
  RETURN VALUE
1657
1460
    E_DEC_OK/E_DEC_TRUNCATED
1658
1461
*/
 
1462
 
1659
1463
int
1660
 
decimal_round(const decimal_t *from, decimal_t *to, int scale,
 
1464
decimal_round(decimal_t *from, decimal_t *to, int scale,
1661
1465
              decimal_round_mode mode)
1662
1466
{
1663
 
  int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
1664
 
      frac1=round_up(from->frac), round_digit= 0,
1665
 
      intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
1666
 
      intg1=round_up(from->intg +
 
1467
  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
 
1468
      frac1=ROUND_UP(from->frac), round_digit= 0,
 
1469
      intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
 
1470
      intg1=ROUND_UP(from->intg +
1667
1471
                     (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1668
1472
  dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
1669
1473
  int first_dig;
1765
1569
  }
1766
1570
  else
1767
1571
  {
1768
 
  /** @todo fix this code as it won't work for CEILING mode */
 
1572
    /* TODO - fix this code as it won't work for CEILING mode */
1769
1573
    int pos=frac0*DIG_PER_DEC1-scale-1;
1770
1574
    assert(frac0+intg0 > 0);
1771
1575
    x=*buf1 / powers10[pos];
1798
1602
    carry=1;
1799
1603
    *buf1-=DIG_BASE;
1800
1604
    while (carry && --buf1 >= to->buf)
1801
 
      add(*buf1, *buf1, 0, carry);
 
1605
      ADD(*buf1, *buf1, 0, carry);
1802
1606
    if (unlikely(carry))
1803
1607
    {
1804
1608
      /* shifting the number to create space for new digit */
1849
1653
  return error;
1850
1654
}
1851
1655
 
1852
 
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1656
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1853
1657
{
1854
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1855
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
 
1658
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1659
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1856
1660
      frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1857
1661
  dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
1858
1662
 
1868
1672
    to->buf[0]=0; /* safety */
1869
1673
  }
1870
1674
 
1871
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
1675
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
1872
1676
  if (unlikely(error == E_DEC_OVERFLOW))
1873
1677
  {
1874
1678
    max_decimal(to->len * DIG_PER_DEC1, 0, to);
1911
1715
  carry=0;
1912
1716
  while (buf1 > stop2)
1913
1717
  {
1914
 
    add(*--buf0, *--buf1, *--buf2, carry);
 
1718
    ADD(*--buf0, *--buf1, *--buf2, carry);
1915
1719
  }
1916
1720
 
1917
1721
  /* part 3 - cmin(intg) ... cmax(intg) */
1919
1723
                        ((stop=from2->buf)+intg2-intg1) ;
1920
1724
  while (buf1 > stop)
1921
1725
  {
1922
 
    add(*--buf0, *--buf1, 0, carry);
 
1726
    ADD(*--buf0, *--buf1, 0, carry);
1923
1727
  }
1924
1728
 
1925
1729
  if (unlikely(carry))
1931
1735
 
1932
1736
/* to=from1-from2.
1933
1737
   if to==0, return -1/0/+1 - the result of the comparison */
1934
 
static int do_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1738
static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
1935
1739
{
1936
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
1937
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac);
 
1740
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1741
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
1938
1742
  int frac0=max(frac1, frac2), error;
1939
1743
  dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
1940
1744
 
2000
1804
  /* ensure that always from1 > from2 (and intg1 >= intg2) */
2001
1805
  if (carry)
2002
1806
  {
2003
 
    swap(from1, from2);
2004
 
    swap(start1, start2);
2005
 
    swap(intg1, intg2);
2006
 
    swap(frac1, frac2);
 
1807
    swap_variables(decimal_t *,from1,from1);
 
1808
    swap_variables(dec1 *,start1, start2);
 
1809
    swap_variables(int,intg1,intg2);
 
1810
    swap_variables(int,frac1,frac2);
2007
1811
    to->sign= 1 - to->sign;
2008
1812
  }
2009
1813
 
2010
 
  fix_intg_frac_error(to->len, intg1, frac0, error);
 
1814
  FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
2011
1815
  buf0=to->buf+intg1+frac0;
2012
1816
 
2013
1817
  to->frac=max(from1->frac, from2->frac);
2041
1845
      *--buf0=0;
2042
1846
    while (buf2 > stop2)
2043
1847
    {
2044
 
      sub(*--buf0, 0, *--buf2, carry);
 
1848
      SUB(*--buf0, 0, *--buf2, carry);
2045
1849
    }
2046
1850
  }
2047
1851
 
2048
1852
  /* part 2 - cmin(frac) ... intg2 */
2049
1853
  while (buf2 > start2)
2050
1854
  {
2051
 
    sub(*--buf0, *--buf1, *--buf2, carry);
 
1855
    SUB(*--buf0, *--buf1, *--buf2, carry);
2052
1856
  }
2053
1857
 
2054
1858
  /* part 3 - intg2 ... intg1 */
2055
1859
  while (carry && buf1 > start1)
2056
1860
  {
2057
 
    sub(*--buf0, *--buf1, 0, carry);
 
1861
    SUB(*--buf0, *--buf1, 0, carry);
2058
1862
  }
2059
1863
 
2060
1864
  while (buf1 > start1)
2066
1870
  return error;
2067
1871
}
2068
1872
 
2069
 
int decimal_intg(const decimal_t *from)
 
1873
int decimal_intg(decimal_t *from)
2070
1874
{
2071
1875
  int res;
2072
1876
  dec1 *tmp_res;
2074
1878
  return res;
2075
1879
}
2076
1880
 
2077
 
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1881
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
2078
1882
{
2079
1883
  if (likely(from1->sign == from2->sign))
2080
1884
    return do_add(from1, from2, to);
2081
1885
  return do_sub(from1, from2, to);
2082
1886
}
2083
1887
 
2084
 
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1888
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
2085
1889
{
2086
1890
  if (likely(from1->sign == from2->sign))
2087
1891
    return do_sub(from1, from2, to);
2088
1892
  return do_add(from1, from2, to);
2089
1893
}
2090
1894
 
2091
 
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
 
1895
int decimal_cmp(decimal_t *from1, decimal_t *from2)
2092
1896
{
2093
1897
  if (likely(from1->sign == from2->sign))
2094
1898
    return do_sub(from1, from2, 0);
2095
1899
  return from1->sign > from2->sign ? -1 : 1;
2096
1900
}
2097
1901
 
2098
 
int decimal_is_zero(const decimal_t *from)
 
1902
int decimal_is_zero(decimal_t *from)
2099
1903
{
2100
1904
  dec1 *buf1=from->buf,
2101
 
       *end=buf1+round_up(from->intg)+round_up(from->frac);
 
1905
       *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
2102
1906
  while (buf1 < end)
2103
1907
    if (*buf1++)
2104
1908
      return 0;
2105
1909
  return 1;
2106
1910
}
2107
1911
 
2108
 
/**
2109
 
 @brief multiply two decimals
2110
 
 
2111
 
 @param[in]   from1  First factor
2112
 
 @param[in]   from2  Second factor
2113
 
 @param[out]  to     product
2114
 
 
2115
 
 @return
 
1912
/*
 
1913
  multiply two decimals
 
1914
 
 
1915
  SYNOPSIS
 
1916
    decimal_mul()
 
1917
      from1, from2 - factors
 
1918
      to      - product
 
1919
 
 
1920
  RETURN VALUE
2116
1921
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
2117
1922
 
2118
 
 @note
 
1923
  NOTES
2119
1924
    in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
2120
1925
    and 63-digit number will take only 7 dec1 words (basically a 7-digit
2121
1926
    "base 999999999" number).  Thus there's no need in fast multiplication
2125
1930
    XXX if this library is to be used with huge numbers of thousands of
2126
1931
    digits, fast multiplication must be implemented.
2127
1932
*/
2128
 
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
1933
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
2129
1934
{
2130
 
  int intg1=round_up(from1->intg), intg2=round_up(from2->intg),
2131
 
      frac1=round_up(from1->frac), frac2=round_up(from2->frac),
2132
 
      intg0=round_up(from1->intg+from2->intg),
 
1935
  int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
 
1936
      frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
 
1937
      intg0=ROUND_UP(from1->intg+from2->intg),
2133
1938
      frac0=frac1+frac2, error, i, j, d_to_move;
2134
1939
  dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
2135
1940
       *start2, *stop2, *stop1, *start0, carry;
2138
1943
 
2139
1944
  i=intg0;
2140
1945
  j=frac0;
2141
 
  fix_intg_frac_error(to->len, intg0, frac0, error);
 
1946
  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2142
1947
  to->sign=from1->sign != from2->sign;
2143
1948
  to->frac=from1->frac+from2->frac;
2144
1949
  to->intg=intg0*DIG_PER_DEC1;
2179
1984
      dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
2180
1985
      hi=(dec1)(p/DIG_BASE);
2181
1986
      lo=(dec1)(p-((dec2)hi)*DIG_BASE);
2182
 
      add2(*buf0, *buf0, lo, carry);
 
1987
      ADD2(*buf0, *buf0, lo, carry);
2183
1988
      carry+=hi;
2184
1989
    }
2185
1990
    if (carry)
2186
1991
    {
2187
1992
      if (buf0 < to->buf)
2188
1993
        return E_DEC_OVERFLOW;
2189
 
      add2(*buf0, *buf0, 0, carry);
 
1994
      ADD2(*buf0, *buf0, 0, carry);
2190
1995
    }
2191
1996
    for (buf0--; carry; buf0--)
2192
1997
    {
2193
1998
      if (buf0 < to->buf)
2194
1999
        return E_DEC_OVERFLOW;
2195
 
      add(*buf0, *buf0, 0, carry);
 
2000
      ADD(*buf0, *buf0, 0, carry);
2196
2001
    }
2197
2002
  }
2198
2003
 
2215
2020
    }
2216
2021
  }
2217
2022
  buf1= to->buf;
2218
 
  d_to_move= intg0 + round_up(to->frac);
 
2023
  d_to_move= intg0 + ROUND_UP(to->frac);
2219
2024
  while (!*buf1 && (to->intg > DIG_PER_DEC1))
2220
2025
  {
2221
2026
    buf1++;
2231
2036
  return error;
2232
2037
}
2233
2038
 
2234
 
/**
 
2039
/*
2235
2040
  naive division algorithm (Knuth's Algorithm D in 4.3.1) -
2236
2041
  it's ok for short numbers
2237
2042
  also we're using alloca() to allocate a temporary buffer
2238
2043
 
2239
 
  @todo
2240
 
  If this library is to be used with huge numbers of thousands of
 
2044
  XXX if this library is to be used with huge numbers of thousands of
2241
2045
  digits, fast division must be implemented and alloca should be
2242
2046
  changed to malloc (or at least fallback to malloc if alloca() fails)
2243
2047
  but then, decimal_mul() should be rewritten too :(
2244
2048
*/
2245
 
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
 
2049
static int do_div_mod(decimal_t *from1, decimal_t *from2,
2246
2050
                       decimal_t *to, decimal_t *mod, int scale_incr)
2247
2051
{
2248
 
  int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2249
 
      frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
 
2052
  int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
 
2053
      frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2250
2054
      error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2251
2055
  dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2252
2056
       *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2296
2100
    intg0=0;
2297
2101
  }
2298
2102
  else
2299
 
    intg0=round_up(dintg);
 
2103
    intg0=ROUND_UP(dintg);
2300
2104
  if (mod)
2301
2105
  {
2302
2106
    /* we're calculating N1 % N2.
2315
2119
      N2 is in the buf2, has prec2 digits. Scales are frac1 and
2316
2120
      frac2 accordingly.
2317
2121
      Thus, the result will have
2318
 
         frac = round_up(frac1+frac2+scale_incr)
 
2122
         frac = ROUND_UP(frac1+frac2+scale_incr)
2319
2123
      and
2320
2124
         intg = (prec1-frac1) - (prec2-frac2) + 1
2321
2125
         prec = intg+frac
2322
2126
    */
2323
 
    frac0=round_up(frac1+frac2+scale_incr);
2324
 
    fix_intg_frac_error(to->len, intg0, frac0, error);
 
2127
    frac0=ROUND_UP(frac1+frac2+scale_incr);
 
2128
    FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
2325
2129
    to->sign=from1->sign != from2->sign;
2326
2130
    to->intg=intg0*DIG_PER_DEC1;
2327
2131
    to->frac=frac0*DIG_PER_DEC1;
2332
2136
    while (dintg++ < 0)
2333
2137
      *buf0++=0;
2334
2138
 
2335
 
  len1=(i=round_up(prec1))+round_up(2*frac2+scale_incr+1) + 1;
 
2139
  len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
2336
2140
  set_if_bigger(len1, 3);
2337
2141
  if (!(tmp1=(dec1 *)alloca(len1*sizeof(dec1))))
2338
2142
    return E_DEC_OOM;
2342
2146
  start1=tmp1;
2343
2147
  stop1=start1+len1;
2344
2148
  start2=buf2;
2345
 
  stop2=buf2+round_up(prec2)-1;
 
2149
  stop2=buf2+ROUND_UP(prec2)-1;
2346
2150
 
2347
2151
  /* removing end zeroes */
2348
2152
  while (*stop2 == 0 && stop2 >= start2)
2401
2205
        x=guess * (*--buf2);
2402
2206
        hi=(dec1)(x/DIG_BASE);
2403
2207
        lo=(dec1)(x-((dec2)hi)*DIG_BASE);
2404
 
        sub2(*buf1, *buf1, lo, carry);
 
2208
        SUB2(*buf1, *buf1, lo, carry);
2405
2209
        carry+=hi;
2406
2210
      }
2407
2211
      carry= dcarry < carry;
2415
2219
        buf1=start1+len2;
2416
2220
        for (carry=0; buf2 > start2; buf1--)
2417
2221
        {
2418
 
          add(*buf1, *buf1, *--buf2, carry);
 
2222
          ADD(*buf1, *buf1, *--buf2, carry);
2419
2223
        }
2420
2224
      }
2421
2225
    }
2434
2238
    if (dcarry)
2435
2239
      *--start1=dcarry;
2436
2240
    buf0=to->buf;
2437
 
    intg0=(int) (round_up(prec1-frac1)-(start1-tmp1));
2438
 
    frac0=round_up(to->frac);
 
2241
    intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
 
2242
    frac0=ROUND_UP(to->frac);
2439
2243
    error=E_DEC_OK;
2440
2244
    if (unlikely(frac0==0 && intg0==0))
2441
2245
    {
2465
2269
        error=E_DEC_OVERFLOW;
2466
2270
        goto done;
2467
2271
      }
2468
 
      assert(intg0 <= round_up(from2->intg));
 
2272
      assert(intg0 <= ROUND_UP(from2->intg));
2469
2273
      stop1=start1+frac0+intg0;
2470
2274
      to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
2471
2275
    }
2484
2288
  return error;
2485
2289
}
2486
2290
 
2487
 
/**
2488
 
 @brief  division of two decimals
2489
 
 
2490
 
 @param[in]  from1   dividend
2491
 
 @param[in]  from2   divisor
2492
 
 @param[out] to      quotient
2493
 
 
2494
 
 @return
 
2291
/*
 
2292
  division of two decimals
 
2293
 
 
2294
  SYNOPSIS
 
2295
    decimal_div()
 
2296
      from1   - dividend
 
2297
      from2   - divisor
 
2298
      to      - quotient
 
2299
 
 
2300
  RETURN VALUE
2495
2301
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2496
2302
 
2497
 
 @note
 
2303
  NOTES
2498
2304
    see do_div_mod()
2499
2305
*/
 
2306
 
2500
2307
int
2501
 
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
 
2308
decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
2502
2309
{
2503
2310
  return do_div_mod(from1, from2, to, 0, scale_incr);
2504
2311
}
2505
2312
 
2506
 
/**
2507
 
 @brief modulus
2508
 
 
2509
 
 the modulus R in    R = M mod N
2510
 
 
2511
 
 is defined as
2512
 
 
2513
 
 0 <= |R| < |M|
2514
 
 sign R == sign M
2515
 
 R = M - k*N, where k is integer
2516
 
 
2517
 
 thus, there's no requirement for M or N to be integers
2518
 
 
2519
 
 
2520
 
 @param from1   dividend
2521
 
 @param from2   divisor
2522
 
 @param to      modulus
2523
 
 
2524
 
 @return
 
2313
/*
 
2314
  modulus
 
2315
 
 
2316
  SYNOPSIS
 
2317
    decimal_mod()
 
2318
      from1   - dividend
 
2319
      from2   - divisor
 
2320
      to      - modulus
 
2321
 
 
2322
  RETURN VALUE
2525
2323
    E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2526
2324
 
2527
 
 @note
 
2325
  NOTES
2528
2326
    see do_div_mod()
2529
2327
 
 
2328
  DESCRIPTION
 
2329
    the modulus R in    R = M mod N
 
2330
 
 
2331
   is defined as
 
2332
 
 
2333
     0 <= |R| < |M|
 
2334
     sign R == sign M
 
2335
     R = M - k*N, where k is integer
 
2336
 
 
2337
   thus, there's no requirement for M or N to be integers
2530
2338
*/
2531
 
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
 
2339
 
 
2340
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
2532
2341
{
2533
2342
  return do_div_mod(from1, from2, 0, to, 0);
2534
2343
}
2535
2344
 
2536
 
} /* namespace drizzled */
2537
 
 
2538
2345
#ifdef MAIN
2539
2346
 
2540
2347
int full= 0;
2545
2352
{
2546
2353
  int i;
2547
2354
  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
2548
 
  for (i=0; i < round_up(d->frac)+round_up(d->intg)-1; i++)
 
2355
  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
2549
2356
    printf("%09d, ", d->buf[i]);
2550
2357
  printf("%09d} */ ", d->buf[i]);
2551
2358
}
2617
2424
{
2618
2425
  char s1[100], *end;
2619
2426
  int res;
2620
 
  snprintf(s1, sizeof(s1), "'%s'", s);
 
2427
  sprintf(s1, "'%s'", s);
2621
2428
  end= strend(s);
2622
2429
  printf("len=%2d %-30s => res=%d    ", a.len, s1,
2623
2430
         (res= string2decimal(s, &a, &end)));
2631
2438
  double x;
2632
2439
  int res;
2633
2440
 
2634
 
  snprintf(s1, sizeof(s1), "'%s'", s);
 
2441
  sprintf(s1, "'%s'", s);
2635
2442
  end= strend(s);
2636
2443
  string2decimal(s, &a, &end);
2637
2444
  res=decimal2double(&a, &x);
2645
2452
  char s1[100], buf[100], *end;
2646
2453
  int res, i, size=decimal_bin_size(p, s);
2647
2454
 
2648
 
  snprintf(s1, sizeof(s1), "'%s'", str);
 
2455
  sprintf(s1, "'%s'", str);
2649
2456
  end= strend(str);
2650
2457
  string2decimal(str, &a, &end);
2651
2458
  res=decimal2bin(&a, buf, p, s);
2678
2485
  int res;
2679
2486
 
2680
2487
  res=uint64_t2decimal(from, &a);
2681
 
  internal::int64_t10_to_str(from,s,10);
 
2488
  int64_t10_to_str(from,s,10);
2682
2489
  printf("%-40s => res=%d    ", s, res);
2683
2490
  print_decimal(&a, orig, res, ex);
2684
2491
  printf("\n");
2690
2497
  int res;
2691
2498
 
2692
2499
  res=int64_t2decimal(from, &a);
2693
 
  internal::int64_t10_to_str(from,s,-10);
 
2500
  int64_t10_to_str(from,s,-10);
2694
2501
  printf("%-40s => res=%d    ", s, res);
2695
2502
  print_decimal(&a, orig, res, ex);
2696
2503
  printf("\n");
2706
2513
  string2decimal(s, &a, &end);
2707
2514
  res=decimal2uint64_t(&a, &x);
2708
2515
  if (full) dump_decimal(&a);
2709
 
  internal::int64_t10_to_str(x,s1,10);
 
2516
  int64_t10_to_str(x,s1,10);
2710
2517
  printf("%-40s => res=%d    %s\n", s, res, s1);
2711
2518
  check_result_code(res, ex);
2712
2519
  if (orig && strcmp(orig, s1))
2726
2533
  string2decimal(s, &a, &end);
2727
2534
  res=decimal2int64_t(&a, &x);
2728
2535
  if (full) dump_decimal(&a);
2729
 
  internal::int64_t10_to_str(x,s1,-10);
 
2536
  int64_t10_to_str(x,s1,-10);
2730
2537
  printf("%-40s => res=%d    %s\n", s, res, s1);
2731
2538
  check_result_code(res, ex);
2732
2539
  if (orig && strcmp(orig, s1))
2740
2547
{
2741
2548
  char s[100], *end;
2742
2549
  int res;
2743
 
  snprintf(s, sizeof(s), "'%s' + '%s'", s1, s2);
 
2550
  sprintf(s, "'%s' + '%s'", s1, s2);
2744
2551
  end= strend(s1);
2745
2552
  string2decimal(s1, &a, &end);
2746
2553
  end= strend(s2);
2755
2562
{
2756
2563
  char s[100], *end;
2757
2564
  int res;
2758
 
  snprintf(s, sizeof(s), "'%s' - '%s'", s1, s2);
 
2565
  sprintf(s, "'%s' - '%s'", s1, s2);
2759
2566
  end= strend(s1);
2760
2567
  string2decimal(s1, &a, &end);
2761
2568
  end= strend(s2);
2770
2577
{
2771
2578
  char s[100], *end;
2772
2579
  int res;
2773
 
  snprintf(s, sizeof(s), "'%s' <=> '%s'", s1, s2);
 
2580
  sprintf(s, "'%s' <=> '%s'", s1, s2);
2774
2581
  end= strend(s1);
2775
2582
  string2decimal(s1, &a, &end);
2776
2583
  end= strend(s2);
2788
2595
{
2789
2596
  char s[100], *end;
2790
2597
  int res;
2791
 
  snprintf(s, sizeof(s), "'%s' * '%s'", s1, s2);
 
2598
  sprintf(s, "'%s' * '%s'", s1, s2);
2792
2599
  end= strend(s1);
2793
2600
  string2decimal(s1, &a, &end);
2794
2601
  end= strend(s2);
2803
2610
{
2804
2611
  char s[100], *end;
2805
2612
  int res;
2806
 
  snprintf(s, sizeof(s), "'%s' / '%s'", s1, s2);
 
2613
  sprintf(s, "'%s' / '%s'", s1, s2);
2807
2614
  end= strend(s1);
2808
2615
  string2decimal(s1, &a, &end);
2809
2616
  end= strend(s2);
2822
2629
{
2823
2630
  char s[100], *end;
2824
2631
  int res;
2825
 
  snprintf(s, sizeof(s), "'%s' %% '%s'", s1, s2);
 
2632
  sprintf(s, "'%s' %% '%s'", s1, s2);
2826
2633
  end= strend(s1);
2827
2634
  string2decimal(s1, &a, &end);
2828
2635
  end= strend(s2);
2845
2652
{
2846
2653
  char s[100], *end;
2847
2654
  int res;
2848
 
  snprintf(s, sizeof(s), "'%s', %d, %s", s1, n, round_mode[mode]);
 
2655
  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
2849
2656
  end= strend(s1);
2850
2657
  string2decimal(s1, &a, &end);
2851
2658
  res=decimal_round(&a, &b, n, mode);
2858
2665
void test_mx(int precision, int frac, const char *orig)
2859
2666
{
2860
2667
  char s[100];
2861
 
  snprintf(s, sizeof(s), "%d, %d", precision, frac);
 
2668
  sprintf(s, "%d, %d", precision, frac);
2862
2669
  max_decimal(precision, frac, &a);
2863
2670
  printf("%-40s =>          ", s);
2864
2671
  print_decimal(&a, orig, 0, 0);
2874
2681
  int slen= sizeof(s2);
2875
2682
  int res;
2876
2683
 
2877
 
  snprintf(s, sizeof(s), filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
 
2684
  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
2878
2685
          s1, prec, dec, filler);
2879
2686
  end= strend(s1);
2880
2687
  string2decimal(s1, &a, &end);
2894
2701
{
2895
2702
  char s[100], *end;
2896
2703
  int res;
2897
 
  snprintf(s, sizeof(s), "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
 
2704
  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
2898
2705
  end= strend(s1);
2899
2706
  string2decimal(s1, &a, &end);
2900
2707
  res= decimal_shift(&a, shift);
2907
2714
void test_fr(const char *s1, const char *orig)
2908
2715
{
2909
2716
  char s[100], *end;
2910
 
  snprintf(s, sizeof(s), "'%s'", s1);
 
2717
  sprintf(s, "'%s'", s1);
2911
2718
  printf("%-40s =>          ", s);
2912
2719
  end= strend(s1);
2913
2720
  string2decimal(s1, &a, &end);