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 */
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"
26
{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR}
33
28
typedef int32_t decimal_digit_t;
30
typedef struct st_decimal_t {
36
31
int intg, frac, len;
38
33
decimal_digit_t *buf;
40
/* set a decimal_t to zero */
41
inline void set_zero()
49
/* negate a decimal */
59
36
int internal_str2dec(char *from, decimal_t *to, char **end,
147
141
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
144
maximum size of packet length.
146
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
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)
155
150
return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
158
int decimal_operation_results(int result);
160
inline void max_Decimal(type::Decimal *to, int precision, int frac)
162
assert((precision <= DECIMAL_MAX_PRECISION)&&
163
(frac <= DECIMAL_MAX_SCALE));
164
max_decimal(precision, frac, (decimal_t*) to);
167
inline void max_internal_decimal(type::Decimal *to)
169
max_Decimal(to, DECIMAL_MAX_PRECISION, 0);
172
inline int check_result(uint32_t mask, int result)
175
decimal_operation_results(result);
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.
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.
188
class Decimal : public decimal_t
162
class my_decimal :public decimal_t
190
164
decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
196
170
len= DECIMAL_BUFF_LENGTH;
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++)
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++)
210
182
void fix_buffer_pointer() { buf= buffer; }
211
183
bool sign() const { return decimal_t::sign; }
212
184
void sign(bool s) { decimal_t::sign= s; }
213
185
uint32_t precision() const { return intg + frac; }
215
int val_int32(uint32_t mask, bool unsigned_flag, int64_t *l) const
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)));
225
int string_length() const
227
return decimal_string_size(this);
230
int val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const;
232
int store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset);
234
int store(uint32_t mask, char *str, char **end)
236
return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(this), end));
239
int store(uint32_t mask, const String *str)
241
return store(mask, str->ptr(), str->length(), str->charset());
244
int check_result_and_overflow(uint32_t mask, int result)
246
if (check_result(mask, result) & E_DEC_OVERFLOW)
249
fix_buffer_pointer();
250
max_internal_decimal(this);
256
void convert(double &value) const;
261
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec);
263
inline uint32_t class_decimal_length_to_precision(uint32_t length, uint32_t scale,
188
int decimal_operation_results(int result);
190
inline void max_my_decimal(my_decimal *to, int precision, int frac)
192
assert((precision <= DECIMAL_MAX_PRECISION)&&
193
(frac <= DECIMAL_MAX_SCALE));
194
max_decimal(precision, frac, (decimal_t*) to);
197
inline void max_internal_decimal(my_decimal *to)
199
max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
202
inline int check_result(uint32_t mask, int result)
205
decimal_operation_results(result);
209
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
211
if (check_result(mask, result) & E_DEC_OVERFLOW)
213
bool sign= val->sign();
214
val->fix_buffer_pointer();
215
max_internal_decimal(val);
221
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
266
224
return (uint32_t) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
269
inline uint32_t class_decimal_precision_to_length(uint32_t precision, uint8_t scale,
227
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
272
230
set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
273
231
return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
278
int class_decimal_max_length(const type::Decimal *d)
235
int my_decimal_string_length(const my_decimal *d)
237
return decimal_string_size(d);
242
int my_decimal_max_length(const my_decimal *d)
280
244
/* -1 because we do not count \0 */
281
245
return decimal_string_size(d) - 1;
286
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)
288
252
return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
293
void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
257
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
296
260
to->fix_buffer_pointer();
264
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
301
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,
304
272
return check_result(mask, bin2decimal(bin, static_cast<decimal_t*>(d), prec, scale));
309
int class_decimal_round(uint32_t mask, const type::Decimal *from, int scale,
310
bool truncate, type::Decimal *to)
277
int my_decimal_set_zero(my_decimal *d)
279
decimal_make_zero(static_cast<decimal_t*> (d));
285
bool my_decimal_is_zero(const my_decimal *decimal_value)
287
return decimal_is_zero(static_cast<const decimal_t*>(decimal_value));
292
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
293
bool truncate, my_decimal *to)
312
295
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
313
296
(truncate ? TRUNCATE : HALF_UP)));
318
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)
320
303
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, FLOOR));
325
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)
327
310
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, CEILING));
331
int class_decimal2string(const type::Decimal *d,
332
uint32_t fixed_dec, String *str);
336
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);
318
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
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)));
331
int my_decimal2double(uint32_t, const my_decimal *d, double *result)
338
333
/* No need to call check_result as this will always succeed */
339
334
return decimal2double(static_cast<const decimal_t*>(d), result);
343
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec);
347
int double2_class_decimal(uint32_t mask, double val, type::Decimal *d)
349
return d->check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)));
354
int int2_class_decimal(uint32_t mask, int64_t i, bool unsigned_flag, type::Decimal *d)
339
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
341
return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(d),end),
346
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
347
const CHARSET_INFO * charset, my_decimal *decimal_value);
350
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
352
return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
356
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
360
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
362
return check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)), d);
367
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
356
369
return check_result(mask, (unsigned_flag ?
357
370
uint64_t2decimal(static_cast<uint64_t>(i), d) :
363
void class_decimal_neg(decimal_t *arg)
376
void my_decimal_neg(decimal_t *arg)
378
if (decimal_is_zero(arg))
375
int class_decimal_add(uint32_t mask, type::Decimal *res, const type::Decimal *a,
376
const type::Decimal *b)
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));
385
int class_decimal_sub(uint32_t mask, type::Decimal *res, const type::Decimal *a,
386
const type::Decimal *b)
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));
395
int class_decimal_mul(uint32_t mask, type::Decimal *res, const type::Decimal *a,
396
const type::Decimal *b)
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));
405
int class_decimal_div(uint32_t mask, type::Decimal *res, const type::Decimal *a,
406
const type::Decimal *b, int div_scale_inc)
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,
416
int class_decimal_mod(uint32_t mask, type::Decimal *res, const type::Decimal *a,
417
const type::Decimal *b)
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));
388
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
391
return check_result_and_overflow(mask,
392
decimal_add(static_cast<const decimal_t*>(a),
393
static_cast<const decimal_t*>(b), res),
399
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
402
return check_result_and_overflow(mask,
403
decimal_sub(static_cast<const decimal_t*>(a),
404
static_cast<const decimal_t*>(b), res),
410
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
413
return check_result_and_overflow(mask,
414
decimal_mul(static_cast<const decimal_t*>(a),
415
static_cast<const decimal_t*>(b),res),
421
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
422
const my_decimal *b, int div_scale_inc)
424
return check_result_and_overflow(mask,
425
decimal_div(static_cast<const decimal_t*>(a),
426
static_cast<const decimal_t*>(b),res,
433
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
436
return check_result_and_overflow(mask,
437
decimal_mod(static_cast<const decimal_t*>(a),
438
static_cast<const decimal_t*>(b),res),
438
int class_decimal_intg(const type::Decimal *a)
456
int my_decimal_intg(const my_decimal *a)
440
458
return decimal_intg(static_cast<const decimal_t*>(a));
444
void class_decimal_trim(uint32_t *precision, uint32_t *scale);
446
inline type::Decimal &decimal_zero_const()
448
static type::Decimal _decimal_zero;
449
return _decimal_zero;
452
double my_double_round(double value, int64_t dec, bool dec_unsigned,
456
#define decimal_zero decimal_zero_const()
462
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
458
464
} /* namespace drizzled */
460
#endif /* DRIZZLED_TYPE_DECIMAL_H */
466
#endif /* DRIZZLED_DECIMAL_H */