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 */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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,
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);
88
inline int string2decimal(char *from, decimal_t *to, char **end)
90
return internal_str2dec(from, to, end, false);
66
#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0)
68
/* set a decimal_t to zero */
70
#define decimal_make_zero(dec) do { \
94
78
returns the length of the buffer to hold string representation
95
79
of the decimal (including decimal dot, possible sign and \0)
98
inline int decimal_string_size(const decimal_t *dec)
100
return (dec->intg ? dec->intg : 1) + dec->frac + (dec->frac > 0) + 2;
82
#define decimal_string_size(dec) (((dec)->intg ? (dec)->intg : 1) + \
83
(dec)->frac + ((dec)->frac > 0) + 2)
85
/* negate a decimal */
86
#define decimal_neg(dec) do { (dec)->sign^=1; } while(0)
147
132
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
135
maximum size of packet length.
137
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
153
inline int class_decimal_int_part(uint32_t precision, uint32_t decimals)
139
inline int my_decimal_int_part(uint32_t precision, uint32_t decimals)
155
141
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.
146
my_decimal class limits 'decimal_t' type to what we need in MySQL.
183
148
It contains internally all necessary space needed by the instance so
184
149
no extra memory is needed. One should call fix_buffer_pointer() function
185
when he moves type::Decimal objects in memory.
150
when he moves my_decimal objects in memory.
188
class Decimal : public decimal_t
153
class my_decimal :public decimal_t
190
155
decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
196
161
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++)
163
#if !defined (HAVE_purify)
164
/* Set buffer to 'random' value to find wrong buffer usage */
165
for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
210
173
void fix_buffer_pointer() { buf= buffer; }
211
174
bool sign() const { return decimal_t::sign; }
212
175
void sign(bool s) { decimal_t::sign= s; }
213
176
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,
179
int decimal_operation_results(int result);
181
inline void max_my_decimal(my_decimal *to, int precision, int frac)
183
assert((precision <= DECIMAL_MAX_PRECISION)&&
184
(frac <= DECIMAL_MAX_SCALE));
185
max_decimal(precision, frac, (decimal_t*) to);
188
inline void max_internal_decimal(my_decimal *to)
190
max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
193
inline int check_result(uint32_t mask, int result)
196
decimal_operation_results(result);
200
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
202
if (check_result(mask, result) & E_DEC_OVERFLOW)
204
bool sign= val->sign();
205
val->fix_buffer_pointer();
206
max_internal_decimal(val);
212
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
266
215
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,
218
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
272
221
set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
273
222
return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
278
int class_decimal_max_length(const type::Decimal *d)
226
int my_decimal_string_length(const my_decimal *d)
228
return decimal_string_size(d);
233
int my_decimal_max_length(const my_decimal *d)
280
235
/* -1 because we do not count \0 */
281
236
return decimal_string_size(d) - 1;
286
int class_decimal_get_binary_size(uint32_t precision, uint32_t scale)
241
int my_decimal_get_binary_size(uint32_t precision, uint32_t scale)
288
243
return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
293
void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
248
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
296
251
to->fix_buffer_pointer();
255
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,
260
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
304
263
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)
268
int my_decimal_set_zero(my_decimal *d)
270
decimal_make_zero(static_cast<decimal_t*> (d));
276
bool my_decimal_is_zero(const my_decimal *decimal_value)
278
return decimal_is_zero(static_cast<const decimal_t*>(decimal_value));
283
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
284
bool truncate, my_decimal *to)
312
286
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
313
287
(truncate ? TRUNCATE : HALF_UP)));
318
int class_decimal_floor(uint32_t mask, const type::Decimal *from, type::Decimal *to)
292
int my_decimal_floor(uint32_t mask, const my_decimal *from, my_decimal *to)
320
294
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)
299
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
327
301
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)
305
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
306
uint32_t fixed_dec, char filler, String *str);
309
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
313
/* decimal_round can return only E_DEC_TRUNCATED */
314
decimal_round(static_cast<const decimal_t*>(d), &rounded, 0, HALF_UP);
315
return check_result(mask, (unsigned_flag ?
316
decimal2uint64_t(&rounded, reinterpret_cast<uint64_t *>(l)) :
317
decimal2int64_t(&rounded, l)));
322
int my_decimal2double(uint32_t, const my_decimal *d, double *result)
338
324
/* No need to call check_result as this will always succeed */
339
325
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)
330
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
332
return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(d),end),
337
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
338
const CHARSET_INFO * charset, my_decimal *decimal_value);
341
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
343
return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
347
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
351
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
353
return check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)), d);
358
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
356
360
return check_result(mask, (unsigned_flag ?
357
361
uint64_t2decimal(static_cast<uint64_t>(i), d) :
363
void class_decimal_neg(decimal_t *arg)
367
void my_decimal_neg(decimal_t *arg)
369
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));
379
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
382
return check_result_and_overflow(mask,
383
decimal_add(static_cast<const decimal_t*>(a),
384
static_cast<const decimal_t*>(b), res),
390
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
393
return check_result_and_overflow(mask,
394
decimal_sub(static_cast<const decimal_t*>(a),
395
static_cast<const decimal_t*>(b), res),
401
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
404
return check_result_and_overflow(mask,
405
decimal_mul(static_cast<const decimal_t*>(a),
406
static_cast<const decimal_t*>(b),res),
412
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
413
const my_decimal *b, int div_scale_inc)
415
return check_result_and_overflow(mask,
416
decimal_div(static_cast<const decimal_t*>(a),
417
static_cast<const decimal_t*>(b),res,
424
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
427
return check_result_and_overflow(mask,
428
decimal_mod(static_cast<const decimal_t*>(a),
429
static_cast<const decimal_t*>(b),res),
438
int class_decimal_intg(const type::Decimal *a)
447
int my_decimal_intg(const my_decimal *a)
440
449
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()
453
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
458
455
} /* namespace drizzled */
460
#endif /* DRIZZLED_TYPE_DECIMAL_H */
457
#endif /* DRIZZLED_DECIMAL_H */