~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/decimal.h

Merge in Monty's rename patch.

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
 
#include <drizzled/definitions.h>
21
 
#include <drizzled/type/time.h>
 
20
#include "drizzled/definitions.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
 
117
#define DECIMAL_LONG_DIGITS 10
 
118
#define DECIMAL_LONG3_DIGITS 8
125
119
 
126
120
/** maximum length of buffer in our big digits (uint32_t). */
127
121
#define DECIMAL_BUFF_LENGTH 9
128
122
 
129
 
/* the number of digits that type::Decimal can possibly contain */
 
123
/* the number of digits that my_decimal can possibly contain */
130
124
#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
131
125
 
132
126
 
146
140
*/
147
141
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
148
142
 
149
 
namespace type {
150
 
class Decimal;
151
 
}
 
143
/**
 
144
  maximum size of packet length.
 
145
*/
 
146
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
152
147
 
153
 
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)
154
149
{
155
150
  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
156
151
}
157
152
 
158
 
int decimal_operation_results(int result);
159
 
 
160
 
inline void max_Decimal(type::Decimal *to, int precision, int frac)
161
 
{
162
 
  assert((precision <= DECIMAL_MAX_PRECISION)&&
163
 
              (frac <= DECIMAL_MAX_SCALE));
164
 
  max_decimal(precision, frac, (decimal_t*) to);
165
 
}
166
 
 
167
 
inline void max_internal_decimal(type::Decimal *to)
168
 
{
169
 
  max_Decimal(to, DECIMAL_MAX_PRECISION, 0);
170
 
}
171
 
 
172
 
inline int check_result(uint32_t mask, int result)
173
 
{
174
 
  if (result & mask)
175
 
    decimal_operation_results(result);
176
 
  return result;
177
 
}
178
 
 
179
 
namespace type {
 
153
 
180
154
/**
181
 
  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.
182
156
 
183
157
  It contains internally all necessary space needed by the instance so
184
158
  no extra memory is needed. One should call fix_buffer_pointer() function
185
 
  when he moves type::Decimal objects in memory.
 
159
  when he moves my_decimal objects in memory.
186
160
*/
187
161
 
188
 
class Decimal : public decimal_t
 
162
class my_decimal :public decimal_t
189
163
{
190
164
  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
191
165
 
195
169
  {
196
170
    len= DECIMAL_BUFF_LENGTH;
197
171
    buf= buffer;
198
 
#if !defined (HAVE_VALGRIND)
199
 
    /* Set buffer to 'random' value to find wrong buffer usage */
200
 
    for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
201
 
      buffer[i]= i;
202
 
#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
203
177
  }
204
178
 
205
 
  Decimal()
 
179
  my_decimal()
206
180
  {
207
181
    init();
208
182
  }
209
 
 
210
183
  void fix_buffer_pointer() { buf= buffer; }
211
184
  bool sign() const { return decimal_t::sign; }
212
185
  void sign(bool s) { decimal_t::sign= s; }
213
186
  uint32_t precision() const { return intg + frac; }
214
 
 
215
 
  int val_int32(uint32_t mask, bool unsigned_flag, int64_t *l) const
216
 
  {
217
 
    type::Decimal rounded;
218
 
    /* decimal_round can return only E_DEC_TRUNCATED */
219
 
    decimal_round(static_cast<const decimal_t*>(this), &rounded, 0, HALF_UP);
220
 
    return check_result(mask, (unsigned_flag ?
221
 
                               decimal2uint64_t(&rounded, reinterpret_cast<uint64_t *>(l)) :
222
 
                               decimal2int64_t(&rounded, l)));
223
 
  }
224
 
 
225
 
  int string_length() const
226
 
  {
227
 
    return decimal_string_size(this);
228
 
  }
229
 
 
230
 
  int val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const;
231
 
 
232
 
  int store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset);
233
 
 
234
 
  int store(uint32_t mask, char *str, char **end)
235
 
  {
236
 
    return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(this), end));
237
 
  }
238
 
 
239
 
  int store(uint32_t mask, const String *str)
240
 
  {
241
 
    return store(mask, str->ptr(), str->length(), str->charset());
242
 
  }
243
 
 
244
 
  int check_result_and_overflow(uint32_t mask, int result)
245
 
  {
246
 
    if (check_result(mask, result) & E_DEC_OVERFLOW)
247
 
    {
248
 
      bool _sign= sign();
249
 
      fix_buffer_pointer();
250
 
      max_internal_decimal(this);
251
 
      sign(_sign);
252
 
    }
253
 
    return result;
254
 
  }
255
 
 
256
 
  void convert(double &value) const;
257
187
};
258
188
 
259
 
} // type
260
 
 
261
 
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec);
262
 
 
263
 
inline uint32_t class_decimal_length_to_precision(uint32_t length, uint32_t scale,
264
 
                                                  bool unsigned_flag)
 
189
std::ostream& operator<<(std::ostream& output, const my_decimal &dec);
 
190
 
 
191
int decimal_operation_results(int result);
 
192
 
 
193
inline void max_my_decimal(my_decimal *to, int precision, int frac)
 
194
{
 
195
  assert((precision <= DECIMAL_MAX_PRECISION)&&
 
196
              (frac <= DECIMAL_MAX_SCALE));
 
197
  max_decimal(precision, frac, (decimal_t*) to);
 
198
}
 
199
 
 
200
inline void max_internal_decimal(my_decimal *to)
 
201
{
 
202
  max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
 
203
}
 
204
 
 
205
inline int check_result(uint32_t mask, int result)
 
206
{
 
207
  if (result & mask)
 
208
    decimal_operation_results(result);
 
209
  return result;
 
210
}
 
211
 
 
212
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
 
213
{
 
214
  if (check_result(mask, result) & E_DEC_OVERFLOW)
 
215
  {
 
216
    bool sign= val->sign();
 
217
    val->fix_buffer_pointer();
 
218
    max_internal_decimal(val);
 
219
    val->sign(sign);
 
220
  }
 
221
  return result;
 
222
}
 
223
 
 
224
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
 
225
                                           bool unsigned_flag)
265
226
{
266
227
  return (uint32_t) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
267
228
}
268
229
 
269
 
inline uint32_t class_decimal_precision_to_length(uint32_t precision, uint8_t scale,
270
 
                                                  bool unsigned_flag)
 
230
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
 
231
                                             bool unsigned_flag)
271
232
{
272
233
  set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
273
234
  return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
274
235
}
275
236
 
276
 
 
277
 
inline
278
 
int class_decimal_max_length(const type::Decimal *d)
 
237
inline
 
238
int my_decimal_string_length(const my_decimal *d)
 
239
{
 
240
  return decimal_string_size(d);
 
241
}
 
242
 
 
243
 
 
244
inline
 
245
int my_decimal_max_length(const my_decimal *d)
279
246
{
280
247
  /* -1 because we do not count \0 */
281
248
  return decimal_string_size(d) - 1;
283
250
 
284
251
 
285
252
inline
286
 
int class_decimal_get_binary_size(uint32_t precision, uint32_t scale)
 
253
int my_decimal_get_binary_size(uint32_t precision, uint32_t scale)
287
254
{
288
255
  return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
289
256
}
290
257
 
291
258
 
292
259
inline
293
 
void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
 
260
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
294
261
{
295
262
  *to= *from;
296
263
  to->fix_buffer_pointer();
297
264
}
298
265
 
299
266
 
 
267
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
 
268
                      int scale);
 
269
 
 
270
 
300
271
inline
301
 
int binary2_class_decimal(uint32_t mask, const unsigned char *bin, type::Decimal *d, int prec,
 
272
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
302
273
                      int scale)
303
274
{
304
275
  return check_result(mask, bin2decimal(bin, static_cast<decimal_t*>(d), prec, scale));
306
277
 
307
278
 
308
279
inline
309
 
int class_decimal_round(uint32_t mask, const type::Decimal *from, int scale,
310
 
                     bool truncate, type::Decimal *to)
 
280
int my_decimal_set_zero(my_decimal *d)
 
281
{
 
282
  decimal_make_zero(static_cast<decimal_t*> (d));
 
283
  return 0;
 
284
}
 
285
 
 
286
 
 
287
inline
 
288
bool my_decimal_is_zero(const my_decimal *decimal_value)
 
289
{
 
290
  return decimal_is_zero(static_cast<const decimal_t*>(decimal_value));
 
291
}
 
292
 
 
293
 
 
294
inline
 
295
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
 
296
                     bool truncate, my_decimal *to)
311
297
{
312
298
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
313
299
                                          (truncate ? TRUNCATE : HALF_UP)));
315
301
 
316
302
 
317
303
inline
318
 
int class_decimal_floor(uint32_t mask, const type::Decimal *from, type::Decimal *to)
 
304
int my_decimal_floor(uint32_t mask, const my_decimal *from, my_decimal *to)
319
305
{
320
306
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, FLOOR));
321
307
}
322
308
 
323
309
 
324
310
inline
325
 
int class_decimal_ceiling(uint32_t mask, const type::Decimal *from, type::Decimal *to)
 
311
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
326
312
{
327
313
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, CEILING));
328
314
}
329
315
 
330
316
 
331
 
int class_decimal2string(const type::Decimal *d,
332
 
                         uint32_t fixed_dec, String *str);
333
 
 
334
 
 
335
 
inline
336
 
int class_decimal2double(uint32_t, const type::Decimal *d, double *result)
 
317
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
 
318
                      uint32_t fixed_dec, char filler, String *str);
 
319
 
 
320
inline
 
321
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
 
322
                   int64_t *l)
 
323
{
 
324
  my_decimal rounded;
 
325
  /* decimal_round can return only E_DEC_TRUNCATED */
 
326
  decimal_round(static_cast<const decimal_t*>(d), &rounded, 0, HALF_UP);
 
327
  return check_result(mask, (unsigned_flag ?
 
328
                             decimal2uint64_t(&rounded, reinterpret_cast<uint64_t *>(l)) :
 
329
                             decimal2int64_t(&rounded, l)));
 
330
}
 
331
 
 
332
 
 
333
inline
 
334
int my_decimal2double(uint32_t, const my_decimal *d, double *result)
337
335
{
338
336
  /* No need to call check_result as this will always succeed */
339
337
  return decimal2double(static_cast<const decimal_t*>(d), result);
340
338
}
341
339
 
342
340
 
343
 
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec);
344
 
 
345
 
 
346
 
inline
347
 
int double2_class_decimal(uint32_t mask, double val, type::Decimal *d)
348
 
{
349
 
  return d->check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)));
350
 
}
351
 
 
352
 
 
353
 
inline
354
 
int int2_class_decimal(uint32_t mask, int64_t i, bool unsigned_flag, type::Decimal *d)
 
341
inline
 
342
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
 
343
{
 
344
  return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(d),end),
 
345
                                   d);
 
346
}
 
347
 
 
348
 
 
349
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
 
350
                   const CHARSET_INFO * charset, my_decimal *decimal_value);
 
351
 
 
352
inline
 
353
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
 
354
{
 
355
  return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
 
356
}
 
357
 
 
358
 
 
359
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
 
360
 
 
361
 
 
362
inline
 
363
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
 
364
{
 
365
  return check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)), d);
 
366
}
 
367
 
 
368
 
 
369
inline
 
370
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
355
371
{
356
372
  return check_result(mask, (unsigned_flag ?
357
373
                             uint64_t2decimal(static_cast<uint64_t>(i), d) :
360
376
 
361
377
 
362
378
inline
363
 
void class_decimal_neg(decimal_t *arg)
 
379
void my_decimal_neg(decimal_t *arg)
364
380
{
365
 
  if (arg->isZero())
 
381
  if (decimal_is_zero(arg))
366
382
  {
367
383
    arg->sign= 0;
368
384
    return;
369
385
  }
370
 
  arg->negate();
371
 
}
372
 
 
373
 
 
374
 
inline
375
 
int class_decimal_add(uint32_t mask, type::Decimal *res, const type::Decimal *a,
376
 
                   const type::Decimal *b)
377
 
{
378
 
  return res->check_result_and_overflow(mask,
379
 
                                        decimal_add(static_cast<const decimal_t*>(a),
380
 
                                                    static_cast<const decimal_t*>(b), res));
381
 
}
382
 
 
383
 
 
384
 
inline
385
 
int class_decimal_sub(uint32_t mask, type::Decimal *res, const type::Decimal *a,
386
 
                   const type::Decimal *b)
387
 
{
388
 
  return res->check_result_and_overflow(mask,
389
 
                                        decimal_sub(static_cast<const decimal_t*>(a),
390
 
                                                    static_cast<const decimal_t*>(b), res));
391
 
}
392
 
 
393
 
 
394
 
inline
395
 
int class_decimal_mul(uint32_t mask, type::Decimal *res, const type::Decimal *a,
396
 
                   const type::Decimal *b)
397
 
{
398
 
  return res->check_result_and_overflow(mask,
399
 
                                        decimal_mul(static_cast<const decimal_t*>(a),
400
 
                                                    static_cast<const decimal_t*>(b),res));
401
 
}
402
 
 
403
 
 
404
 
inline
405
 
int class_decimal_div(uint32_t mask, type::Decimal *res, const type::Decimal *a,
406
 
                   const type::Decimal *b, int div_scale_inc)
407
 
{
408
 
  return res->check_result_and_overflow(mask,
409
 
                                        decimal_div(static_cast<const decimal_t*>(a),
410
 
                                                    static_cast<const decimal_t*>(b),res,
411
 
                                                    div_scale_inc));
412
 
}
413
 
 
414
 
 
415
 
inline
416
 
int class_decimal_mod(uint32_t mask, type::Decimal *res, const type::Decimal *a,
417
 
                   const type::Decimal *b)
418
 
{
419
 
  return res->check_result_and_overflow(mask,
420
 
                                        decimal_mod(static_cast<const decimal_t*>(a),
421
 
                                                    static_cast<const decimal_t*>(b),res));
 
386
  decimal_neg(arg);
 
387
}
 
388
 
 
389
 
 
390
inline
 
391
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
 
392
                   const my_decimal *b)
 
393
{
 
394
  return check_result_and_overflow(mask,
 
395
                                   decimal_add(static_cast<const decimal_t*>(a),
 
396
                                               static_cast<const decimal_t*>(b), res),
 
397
                                   res);
 
398
}
 
399
 
 
400
 
 
401
inline
 
402
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
 
403
                   const my_decimal *b)
 
404
{
 
405
  return check_result_and_overflow(mask,
 
406
                                   decimal_sub(static_cast<const decimal_t*>(a),
 
407
                                               static_cast<const decimal_t*>(b), res),
 
408
                                   res);
 
409
}
 
410
 
 
411
 
 
412
inline
 
413
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
 
414
                   const my_decimal *b)
 
415
{
 
416
  return check_result_and_overflow(mask,
 
417
                                   decimal_mul(static_cast<const decimal_t*>(a),
 
418
                                               static_cast<const decimal_t*>(b),res),
 
419
                                   res);
 
420
}
 
421
 
 
422
 
 
423
inline
 
424
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
 
425
                   const my_decimal *b, int div_scale_inc)
 
426
{
 
427
  return check_result_and_overflow(mask,
 
428
                                   decimal_div(static_cast<const decimal_t*>(a),
 
429
                                               static_cast<const decimal_t*>(b),res,
 
430
                                               div_scale_inc),
 
431
                                   res);
 
432
}
 
433
 
 
434
 
 
435
inline
 
436
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
 
437
                   const my_decimal *b)
 
438
{
 
439
  return check_result_and_overflow(mask,
 
440
                                   decimal_mod(static_cast<const decimal_t*>(a),
 
441
                                               static_cast<const decimal_t*>(b),res),
 
442
                                   res);
422
443
}
423
444
 
424
445
 
427
448
    -1 if a<b, 1 if a>b and 0 if a==b
428
449
*/
429
450
inline
430
 
int class_decimal_cmp(const type::Decimal *a, const type::Decimal *b)
 
451
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
431
452
{
432
453
  return decimal_cmp(static_cast<const decimal_t*>(a),
433
454
                     static_cast<const decimal_t*>(b));
435
456
 
436
457
 
437
458
inline
438
 
int class_decimal_intg(const type::Decimal *a)
 
459
int my_decimal_intg(const my_decimal *a)
439
460
{
440
461
  return decimal_intg(static_cast<const decimal_t*>(a));
441
462
}
442
463
 
443
464
 
444
 
void class_decimal_trim(uint32_t *precision, uint32_t *scale);
445
 
 
446
 
inline type::Decimal &decimal_zero_const()
447
 
{
448
 
  static type::Decimal _decimal_zero;
449
 
  return _decimal_zero;
450
 
}
451
 
 
452
 
double my_double_round(double value, int64_t dec, bool dec_unsigned,
453
 
                       bool truncate);
454
 
 
455
 
 
456
 
#define decimal_zero decimal_zero_const()
 
465
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
457
466
 
458
467
} /* namespace drizzled */
459
468
 
460
 
#endif /* DRIZZLED_TYPE_DECIMAL_H */
 
469
#endif /* DRIZZLED_DECIMAL_H */
461
470