~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/decimal.h

  • Committer: Brian Aker
  • Date: 2010-12-19 06:20:54 UTC
  • mfrom: (2005.1.1 bug673105)
  • Revision ID: brian@tangent.org-20101219062054-1kt0l3dxs4z2z8md
Merge Dave.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
 
#ifndef DRIZZLED_TYPE_DECIMAL_H
17
 
#define DRIZZLED_TYPE_DECIMAL_H
 
16
#ifndef DRIZZLED_DECIMAL_H
 
17
#define DRIZZLED_DECIMAL_H
18
18
#include <assert.h>
19
19
#include <drizzled/sql_string.h>
20
20
#include "drizzled/definitions.h"
21
 
#include "drizzled/type/time.h"
 
21
#include "drizzled/drizzle_time.h"
22
22
namespace drizzled
23
23
{
24
24
 
25
25
typedef enum
26
 
{
27
 
  TRUNCATE= 0,
28
 
  HALF_EVEN,
29
 
  HALF_UP,
30
 
  CEILING,
31
 
  FLOOR
32
 
} decimal_round_mode;
 
26
{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR}
 
27
  decimal_round_mode;
33
28
typedef int32_t decimal_digit_t;
34
29
 
35
 
struct decimal_t {
 
30
typedef struct st_decimal_t {
36
31
  int    intg, frac, len;
37
32
  bool sign;
38
33
  decimal_digit_t *buf;
39
 
 
40
 
  /* set a decimal_t to zero */
41
 
  inline void set_zero()
42
 
  {                                                         
43
 
    buf[0]= 0;
44
 
    intg= 1;
45
 
    frac= 0;
46
 
    sign= 0; 
47
 
  }
48
 
 
49
 
  /* negate a decimal */
50
 
  inline void negate()
51
 
  {
52
 
    sign^=1;
53
 
  }
54
 
 
55
 
  int isZero() const;
56
 
 
57
 
};
 
34
} decimal_t;
58
35
 
59
36
int internal_str2dec(char *from, decimal_t *to, char **end,
60
37
                     bool fixed);
83
60
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
84
61
int decimal_round(const decimal_t *from, decimal_t *to, int new_scale,
85
62
                  decimal_round_mode mode);
 
63
int decimal_is_zero(const decimal_t *from);
86
64
void max_decimal(int precision, int frac, decimal_t *to);
87
65
 
88
66
inline int string2decimal(char *from, decimal_t *to, char **end)
90
68
  return internal_str2dec(from, to, end, false);
91
69
}
92
70
 
 
71
/* set a decimal_t to zero */
 
72
 
 
73
inline void decimal_make_zero(decimal_t *dec)
 
74
{                                                           
 
75
  dec->buf[0]=0;
 
76
  dec->intg=1;
 
77
  dec->frac=0;
 
78
  dec->sign=0; 
 
79
}
 
80
 
93
81
/*
94
82
  returns the length of the buffer to hold string representation
95
83
  of the decimal (including decimal dot, possible sign and \0)
100
88
  return (dec->intg ? dec->intg : 1) + dec->frac + (dec->frac > 0) + 2;
101
89
}
102
90
 
 
91
/* negate a decimal */
 
92
inline void decimal_neg(decimal_t *dec)
 
93
{
 
94
  dec->sign^=1;
 
95
}
 
96
 
103
97
/*
104
98
  conventions:
105
99
 
119
113
 
120
114
#define E_DEC_ERROR            31
121
115
#define E_DEC_FATAL_ERROR      30
122
 
 
123
 
 
124
116
#define DECIMAL_LONGLONG_DIGITS 22
125
117
#define DECIMAL_LONG_DIGITS 10
126
118
#define DECIMAL_LONG3_DIGITS 8
128
120
/** maximum length of buffer in our big digits (uint32_t). */
129
121
#define DECIMAL_BUFF_LENGTH 9
130
122
 
131
 
/* the number of digits that type::Decimal can possibly contain */
 
123
/* the number of digits that my_decimal can possibly contain */
132
124
#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
133
125
 
134
126
 
153
145
*/
154
146
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
155
147
 
156
 
namespace type {
157
 
class Decimal;
158
 
}
159
 
 
160
 
inline int class_decimal_int_part(uint32_t precision, uint32_t decimals)
 
148
inline int my_decimal_int_part(uint32_t precision, uint32_t decimals)
161
149
{
162
150
  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
163
151
}
164
152
 
165
 
int decimal_operation_results(int result);
166
 
 
167
 
inline void max_Decimal(type::Decimal *to, int precision, int frac)
168
 
{
169
 
  assert((precision <= DECIMAL_MAX_PRECISION)&&
170
 
              (frac <= DECIMAL_MAX_SCALE));
171
 
  max_decimal(precision, frac, (decimal_t*) to);
172
 
}
173
 
 
174
 
inline void max_internal_decimal(type::Decimal *to)
175
 
{
176
 
  max_Decimal(to, DECIMAL_MAX_PRECISION, 0);
177
 
}
178
 
 
179
 
inline int check_result(uint32_t mask, int result)
180
 
{
181
 
  if (result & mask)
182
 
    decimal_operation_results(result);
183
 
  return result;
184
 
}
185
 
 
186
 
namespace type {
 
153
 
187
154
/**
188
 
  type Decimal class limits 'decimal_t' type to what we need in MySQL.
 
155
  my_decimal class limits 'decimal_t' type to what we need in MySQL.
189
156
 
190
157
  It contains internally all necessary space needed by the instance so
191
158
  no extra memory is needed. One should call fix_buffer_pointer() function
192
 
  when he moves type::Decimal objects in memory.
 
159
  when he moves my_decimal objects in memory.
193
160
*/
194
161
 
195
 
class Decimal : public decimal_t
 
162
class my_decimal :public decimal_t
196
163
{
197
164
  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
198
165
 
202
169
  {
203
170
    len= DECIMAL_BUFF_LENGTH;
204
171
    buf= buffer;
205
 
#if !defined (HAVE_VALGRIND)
206
 
    /* Set buffer to 'random' value to find wrong buffer usage */
207
 
    for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
208
 
      buffer[i]= i;
209
 
#endif
 
172
        #if !defined (HAVE_VALGRIND)
 
173
                /* Set buffer to 'random' value to find wrong buffer usage */
 
174
                for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
 
175
                  buffer[i]= i;
 
176
        #endif
210
177
  }
211
 
 
212
 
  Decimal()
 
178
  my_decimal()
213
179
  {
214
180
    init();
215
181
  }
216
 
 
217
182
  void fix_buffer_pointer() { buf= buffer; }
218
183
  bool sign() const { return decimal_t::sign; }
219
184
  void sign(bool s) { decimal_t::sign= s; }
220
185
  uint32_t precision() const { return intg + frac; }
221
 
 
222
 
  int val_int32(uint32_t mask, bool unsigned_flag, int64_t *l) const
223
 
  {
224
 
    type::Decimal rounded;
225
 
    /* decimal_round can return only E_DEC_TRUNCATED */
226
 
    decimal_round(static_cast<const decimal_t*>(this), &rounded, 0, HALF_UP);
227
 
    return check_result(mask, (unsigned_flag ?
228
 
                               decimal2uint64_t(&rounded, reinterpret_cast<uint64_t *>(l)) :
229
 
                               decimal2int64_t(&rounded, l)));
230
 
  }
231
 
 
232
 
  int string_length() const
233
 
  {
234
 
    return decimal_string_size(this);
235
 
  }
236
 
 
237
 
  int val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const;
238
 
 
239
 
  int store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset);
240
 
 
241
 
  int store(uint32_t mask, char *str, char **end)
242
 
  {
243
 
    return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(this), end));
244
 
  }
245
 
 
246
 
  int store(uint32_t mask, const String *str)
247
 
  {
248
 
    return store(mask, str->ptr(), str->length(), str->charset());
249
 
  }
250
 
 
251
 
  int check_result_and_overflow(uint32_t mask, int result)
252
 
  {
253
 
    if (check_result(mask, result) & E_DEC_OVERFLOW)
254
 
    {
255
 
      bool _sign= sign();
256
 
      fix_buffer_pointer();
257
 
      max_internal_decimal(this);
258
 
      sign(_sign);
259
 
    }
260
 
    return result;
261
 
  }
262
 
 
263
 
  void convert(double &value) const;
264
186
};
265
187
 
266
 
} // type
267
 
 
268
 
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec);
269
 
 
270
 
inline uint32_t class_decimal_length_to_precision(uint32_t length, uint32_t scale,
271
 
                                                  bool unsigned_flag)
 
188
int decimal_operation_results(int result);
 
189
 
 
190
inline void max_my_decimal(my_decimal *to, int precision, int frac)
 
191
{
 
192
  assert((precision <= DECIMAL_MAX_PRECISION)&&
 
193
              (frac <= DECIMAL_MAX_SCALE));
 
194
  max_decimal(precision, frac, (decimal_t*) to);
 
195
}
 
196
 
 
197
inline void max_internal_decimal(my_decimal *to)
 
198
{
 
199
  max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
 
200
}
 
201
 
 
202
inline int check_result(uint32_t mask, int result)
 
203
{
 
204
  if (result & mask)
 
205
    decimal_operation_results(result);
 
206
  return result;
 
207
}
 
208
 
 
209
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
 
210
{
 
211
  if (check_result(mask, result) & E_DEC_OVERFLOW)
 
212
  {
 
213
    bool sign= val->sign();
 
214
    val->fix_buffer_pointer();
 
215
    max_internal_decimal(val);
 
216
    val->sign(sign);
 
217
  }
 
218
  return result;
 
219
}
 
220
 
 
221
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
 
222
                                           bool unsigned_flag)
272
223
{
273
224
  return (uint32_t) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
274
225
}
275
226
 
276
 
inline uint32_t class_decimal_precision_to_length(uint32_t precision, uint8_t scale,
277
 
                                                  bool unsigned_flag)
 
227
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
 
228
                                             bool unsigned_flag)
278
229
{
279
230
  set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
280
231
  return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
281
232
}
282
233
 
283
 
 
284
 
inline
285
 
int class_decimal_max_length(const type::Decimal *d)
 
234
inline
 
235
int my_decimal_string_length(const my_decimal *d)
 
236
{
 
237
  return decimal_string_size(d);
 
238
}
 
239
 
 
240
 
 
241
inline
 
242
int my_decimal_max_length(const my_decimal *d)
286
243
{
287
244
  /* -1 because we do not count \0 */
288
245
  return decimal_string_size(d) - 1;
290
247
 
291
248
 
292
249
inline
293
 
int class_decimal_get_binary_size(uint32_t precision, uint32_t scale)
 
250
int my_decimal_get_binary_size(uint32_t precision, uint32_t scale)
294
251
{
295
252
  return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
296
253
}
297
254
 
298
255
 
299
256
inline
300
 
void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
 
257
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
301
258
{
302
259
  *to= *from;
303
260
  to->fix_buffer_pointer();
304
261
}
305
262
 
306
263
 
 
264
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
 
265
                      int scale);
 
266
 
 
267
 
307
268
inline
308
 
int binary2_class_decimal(uint32_t mask, const unsigned char *bin, type::Decimal *d, int prec,
 
269
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
309
270
                      int scale)
310
271
{
311
272
  return check_result(mask, bin2decimal(bin, static_cast<decimal_t*>(d), prec, scale));
313
274
 
314
275
 
315
276
inline
316
 
int class_decimal_round(uint32_t mask, const type::Decimal *from, int scale,
317
 
                     bool truncate, type::Decimal *to)
 
277
int my_decimal_set_zero(my_decimal *d)
 
278
{
 
279
  decimal_make_zero(static_cast<decimal_t*> (d));
 
280
  return 0;
 
281
}
 
282
 
 
283
 
 
284
inline
 
285
bool my_decimal_is_zero(const my_decimal *decimal_value)
 
286
{
 
287
  return decimal_is_zero(static_cast<const decimal_t*>(decimal_value));
 
288
}
 
289
 
 
290
 
 
291
inline
 
292
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
 
293
                     bool truncate, my_decimal *to)
318
294
{
319
295
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
320
296
                                          (truncate ? TRUNCATE : HALF_UP)));
322
298
 
323
299
 
324
300
inline
325
 
int class_decimal_floor(uint32_t mask, const type::Decimal *from, type::Decimal *to)
 
301
int my_decimal_floor(uint32_t mask, const my_decimal *from, my_decimal *to)
326
302
{
327
303
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, FLOOR));
328
304
}
329
305
 
330
306
 
331
307
inline
332
 
int class_decimal_ceiling(uint32_t mask, const type::Decimal *from, type::Decimal *to)
 
308
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
333
309
{
334
310
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, CEILING));
335
311
}
336
312
 
337
313
 
338
 
int class_decimal2string(const type::Decimal *d,
339
 
                         uint32_t fixed_dec, String *str);
340
 
 
341
 
 
342
 
inline
343
 
int class_decimal2double(uint32_t, const type::Decimal *d, double *result)
 
314
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
 
315
                      uint32_t fixed_dec, char filler, String *str);
 
316
 
 
317
inline
 
318
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
 
319
                   int64_t *l)
 
320
{
 
321
  my_decimal rounded;
 
322
  /* decimal_round can return only E_DEC_TRUNCATED */
 
323
  decimal_round(static_cast<const decimal_t*>(d), &rounded, 0, HALF_UP);
 
324
  return check_result(mask, (unsigned_flag ?
 
325
                             decimal2uint64_t(&rounded, reinterpret_cast<uint64_t *>(l)) :
 
326
                             decimal2int64_t(&rounded, l)));
 
327
}
 
328
 
 
329
 
 
330
inline
 
331
int my_decimal2double(uint32_t, const my_decimal *d, double *result)
344
332
{
345
333
  /* No need to call check_result as this will always succeed */
346
334
  return decimal2double(static_cast<const decimal_t*>(d), result);
347
335
}
348
336
 
349
337
 
350
 
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec);
351
 
 
352
 
 
353
 
inline
354
 
int double2_class_decimal(uint32_t mask, double val, type::Decimal *d)
355
 
{
356
 
  return d->check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)));
357
 
}
358
 
 
359
 
 
360
 
inline
361
 
int int2_class_decimal(uint32_t mask, int64_t i, bool unsigned_flag, type::Decimal *d)
 
338
inline
 
339
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
 
340
{
 
341
  return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(d),end),
 
342
                                   d);
 
343
}
 
344
 
 
345
 
 
346
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
 
347
                   const CHARSET_INFO * charset, my_decimal *decimal_value);
 
348
 
 
349
inline
 
350
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
 
351
{
 
352
  return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
 
353
}
 
354
 
 
355
 
 
356
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
 
357
 
 
358
 
 
359
inline
 
360
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
 
361
{
 
362
  return check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)), d);
 
363
}
 
364
 
 
365
 
 
366
inline
 
367
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
362
368
{
363
369
  return check_result(mask, (unsigned_flag ?
364
370
                             uint64_t2decimal(static_cast<uint64_t>(i), d) :
367
373
 
368
374
 
369
375
inline
370
 
void class_decimal_neg(decimal_t *arg)
 
376
void my_decimal_neg(decimal_t *arg)
371
377
{
372
 
  if (arg->isZero())
 
378
  if (decimal_is_zero(arg))
373
379
  {
374
380
    arg->sign= 0;
375
381
    return;
376
382
  }
377
 
  arg->negate();
378
 
}
379
 
 
380
 
 
381
 
inline
382
 
int class_decimal_add(uint32_t mask, type::Decimal *res, const type::Decimal *a,
383
 
                   const type::Decimal *b)
384
 
{
385
 
  return res->check_result_and_overflow(mask,
386
 
                                        decimal_add(static_cast<const decimal_t*>(a),
387
 
                                                    static_cast<const decimal_t*>(b), res));
388
 
}
389
 
 
390
 
 
391
 
inline
392
 
int class_decimal_sub(uint32_t mask, type::Decimal *res, const type::Decimal *a,
393
 
                   const type::Decimal *b)
394
 
{
395
 
  return res->check_result_and_overflow(mask,
396
 
                                        decimal_sub(static_cast<const decimal_t*>(a),
397
 
                                                    static_cast<const decimal_t*>(b), res));
398
 
}
399
 
 
400
 
 
401
 
inline
402
 
int class_decimal_mul(uint32_t mask, type::Decimal *res, const type::Decimal *a,
403
 
                   const type::Decimal *b)
404
 
{
405
 
  return res->check_result_and_overflow(mask,
406
 
                                        decimal_mul(static_cast<const decimal_t*>(a),
407
 
                                                    static_cast<const decimal_t*>(b),res));
408
 
}
409
 
 
410
 
 
411
 
inline
412
 
int class_decimal_div(uint32_t mask, type::Decimal *res, const type::Decimal *a,
413
 
                   const type::Decimal *b, int div_scale_inc)
414
 
{
415
 
  return res->check_result_and_overflow(mask,
416
 
                                        decimal_div(static_cast<const decimal_t*>(a),
417
 
                                                    static_cast<const decimal_t*>(b),res,
418
 
                                                    div_scale_inc));
419
 
}
420
 
 
421
 
 
422
 
inline
423
 
int class_decimal_mod(uint32_t mask, type::Decimal *res, const type::Decimal *a,
424
 
                   const type::Decimal *b)
425
 
{
426
 
  return res->check_result_and_overflow(mask,
427
 
                                        decimal_mod(static_cast<const decimal_t*>(a),
428
 
                                                    static_cast<const decimal_t*>(b),res));
 
383
  decimal_neg(arg);
 
384
}
 
385
 
 
386
 
 
387
inline
 
388
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
 
389
                   const my_decimal *b)
 
390
{
 
391
  return check_result_and_overflow(mask,
 
392
                                   decimal_add(static_cast<const decimal_t*>(a),
 
393
                                               static_cast<const decimal_t*>(b), res),
 
394
                                   res);
 
395
}
 
396
 
 
397
 
 
398
inline
 
399
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
 
400
                   const my_decimal *b)
 
401
{
 
402
  return check_result_and_overflow(mask,
 
403
                                   decimal_sub(static_cast<const decimal_t*>(a),
 
404
                                               static_cast<const decimal_t*>(b), res),
 
405
                                   res);
 
406
}
 
407
 
 
408
 
 
409
inline
 
410
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
 
411
                   const my_decimal *b)
 
412
{
 
413
  return check_result_and_overflow(mask,
 
414
                                   decimal_mul(static_cast<const decimal_t*>(a),
 
415
                                               static_cast<const decimal_t*>(b),res),
 
416
                                   res);
 
417
}
 
418
 
 
419
 
 
420
inline
 
421
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
 
422
                   const my_decimal *b, int div_scale_inc)
 
423
{
 
424
  return check_result_and_overflow(mask,
 
425
                                   decimal_div(static_cast<const decimal_t*>(a),
 
426
                                               static_cast<const decimal_t*>(b),res,
 
427
                                               div_scale_inc),
 
428
                                   res);
 
429
}
 
430
 
 
431
 
 
432
inline
 
433
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
 
434
                   const my_decimal *b)
 
435
{
 
436
  return check_result_and_overflow(mask,
 
437
                                   decimal_mod(static_cast<const decimal_t*>(a),
 
438
                                               static_cast<const decimal_t*>(b),res),
 
439
                                   res);
429
440
}
430
441
 
431
442
 
434
445
    -1 if a<b, 1 if a>b and 0 if a==b
435
446
*/
436
447
inline
437
 
int class_decimal_cmp(const type::Decimal *a, const type::Decimal *b)
 
448
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
438
449
{
439
450
  return decimal_cmp(static_cast<const decimal_t*>(a),
440
451
                     static_cast<const decimal_t*>(b));
442
453
 
443
454
 
444
455
inline
445
 
int class_decimal_intg(const type::Decimal *a)
 
456
int my_decimal_intg(const my_decimal *a)
446
457
{
447
458
  return decimal_intg(static_cast<const decimal_t*>(a));
448
459
}
449
460
 
450
461
 
451
 
void class_decimal_trim(uint32_t *precision, uint32_t *scale);
452
 
 
453
 
inline type::Decimal &decimal_zero_const()
454
 
{
455
 
  static type::Decimal _decimal_zero;
456
 
  return _decimal_zero;
457
 
}
458
 
 
459
 
double my_double_round(double value, int64_t dec, bool dec_unsigned,
460
 
                       bool truncate);
461
 
 
462
 
 
463
 
#define decimal_zero decimal_zero_const()
 
462
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
464
463
 
465
464
} /* namespace drizzled */
466
465
 
467
 
#endif /* DRIZZLED_TYPE_DECIMAL_H */
 
466
#endif /* DRIZZLED_DECIMAL_H */
468
467