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
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; }
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,
189
std::ostream& operator<<(std::ostream& output, const my_decimal &dec);
191
int decimal_operation_results(int result);
193
inline void max_my_decimal(my_decimal *to, int precision, int frac)
195
assert((precision <= DECIMAL_MAX_PRECISION)&&
196
(frac <= DECIMAL_MAX_SCALE));
197
max_decimal(precision, frac, (decimal_t*) to);
200
inline void max_internal_decimal(my_decimal *to)
202
max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
205
inline int check_result(uint32_t mask, int result)
208
decimal_operation_results(result);
212
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
214
if (check_result(mask, result) & E_DEC_OVERFLOW)
216
bool sign= val->sign();
217
val->fix_buffer_pointer();
218
max_internal_decimal(val);
224
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
266
227
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,
230
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
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));
278
int class_decimal_max_length(const type::Decimal *d)
238
int my_decimal_string_length(const my_decimal *d)
240
return decimal_string_size(d);
245
int my_decimal_max_length(const my_decimal *d)
280
247
/* -1 because we do not count \0 */
281
248
return decimal_string_size(d) - 1;
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)
288
255
return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
293
void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
260
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
296
263
to->fix_buffer_pointer();
267
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,
272
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
304
275
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)
280
int my_decimal_set_zero(my_decimal *d)
282
decimal_make_zero(static_cast<decimal_t*> (d));
288
bool my_decimal_is_zero(const my_decimal *decimal_value)
290
return decimal_is_zero(static_cast<const decimal_t*>(decimal_value));
295
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
296
bool truncate, my_decimal *to)
312
298
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
313
299
(truncate ? TRUNCATE : HALF_UP)));
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)
320
306
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)
311
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
327
313
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)
317
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
318
uint32_t fixed_dec, char filler, String *str);
321
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
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)));
334
int my_decimal2double(uint32_t, const my_decimal *d, double *result)
338
336
/* No need to call check_result as this will always succeed */
339
337
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)
342
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
344
return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(d),end),
349
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
350
const CHARSET_INFO * charset, my_decimal *decimal_value);
353
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
355
return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
359
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
363
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
365
return check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)), d);
370
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
356
372
return check_result(mask, (unsigned_flag ?
357
373
uint64_t2decimal(static_cast<uint64_t>(i), d) :
363
void class_decimal_neg(decimal_t *arg)
379
void my_decimal_neg(decimal_t *arg)
381
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));
391
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
394
return check_result_and_overflow(mask,
395
decimal_add(static_cast<const decimal_t*>(a),
396
static_cast<const decimal_t*>(b), res),
402
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
405
return check_result_and_overflow(mask,
406
decimal_sub(static_cast<const decimal_t*>(a),
407
static_cast<const decimal_t*>(b), res),
413
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
416
return check_result_and_overflow(mask,
417
decimal_mul(static_cast<const decimal_t*>(a),
418
static_cast<const decimal_t*>(b),res),
424
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
425
const my_decimal *b, int div_scale_inc)
427
return check_result_and_overflow(mask,
428
decimal_div(static_cast<const decimal_t*>(a),
429
static_cast<const decimal_t*>(b),res,
436
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
439
return check_result_and_overflow(mask,
440
decimal_mod(static_cast<const decimal_t*>(a),
441
static_cast<const decimal_t*>(b),res),
438
int class_decimal_intg(const type::Decimal *a)
459
int my_decimal_intg(const my_decimal *a)
440
461
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()
465
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
458
467
} /* namespace drizzled */
460
#endif /* DRIZZLED_TYPE_DECIMAL_H */
469
#endif /* DRIZZLED_DECIMAL_H */