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
20
#include "drizzled/definitions.h"
21
#include "drizzled/type/time.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)
154
137
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
160
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)
162
141
return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
165
int decimal_operation_results(int result);
167
inline void max_Decimal(type::Decimal *to, int precision, int frac)
169
assert((precision <= DECIMAL_MAX_PRECISION)&&
170
(frac <= DECIMAL_MAX_SCALE));
171
max_decimal(precision, frac, (decimal_t*) to);
174
inline void max_internal_decimal(type::Decimal *to)
176
max_Decimal(to, DECIMAL_MAX_PRECISION, 0);
179
inline int check_result(uint32_t mask, int result)
182
decimal_operation_results(result);
188
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.
190
148
It contains internally all necessary space needed by the instance so
191
149
no extra memory is needed. One should call fix_buffer_pointer() function
192
when he moves type::Decimal objects in memory.
150
when he moves my_decimal objects in memory.
195
class Decimal : public decimal_t
153
class my_decimal :public decimal_t
197
155
decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
203
161
len= DECIMAL_BUFF_LENGTH;
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++)
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++)
217
173
void fix_buffer_pointer() { buf= buffer; }
218
174
bool sign() const { return decimal_t::sign; }
219
175
void sign(bool s) { decimal_t::sign= s; }
220
176
uint32_t precision() const { return intg + frac; }
222
int val_int32(uint32_t mask, bool unsigned_flag, int64_t *l) const
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)));
232
int string_length() const
234
return decimal_string_size(this);
237
int val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const;
239
int store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset);
241
int store(uint32_t mask, char *str, char **end)
243
return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(this), end));
246
int store(uint32_t mask, const String *str)
248
return store(mask, str->ptr(), str->length(), str->charset());
251
int check_result_and_overflow(uint32_t mask, int result)
253
if (check_result(mask, result) & E_DEC_OVERFLOW)
256
fix_buffer_pointer();
257
max_internal_decimal(this);
263
void convert(double &value) const;
268
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec);
270
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,
273
215
return (uint32_t) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
276
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,
279
221
set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
280
222
return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
285
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)
287
235
/* -1 because we do not count \0 */
288
236
return decimal_string_size(d) - 1;
293
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)
295
243
return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
300
void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
248
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
303
251
to->fix_buffer_pointer();
255
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
308
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,
311
263
return check_result(mask, bin2decimal(bin, static_cast<decimal_t*>(d), prec, scale));
316
int class_decimal_round(uint32_t mask, const type::Decimal *from, int scale,
317
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)
319
286
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
320
287
(truncate ? TRUNCATE : HALF_UP)));
325
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)
327
294
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, FLOOR));
332
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)
334
301
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, CEILING));
338
int class_decimal2string(const type::Decimal *d,
339
uint32_t fixed_dec, String *str);
343
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)
345
324
/* No need to call check_result as this will always succeed */
346
325
return decimal2double(static_cast<const decimal_t*>(d), result);
350
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec);
354
int double2_class_decimal(uint32_t mask, double val, type::Decimal *d)
356
return d->check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)));
361
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)
363
360
return check_result(mask, (unsigned_flag ?
364
361
uint64_t2decimal(static_cast<uint64_t>(i), d) :
370
void class_decimal_neg(decimal_t *arg)
367
void my_decimal_neg(decimal_t *arg)
369
if (decimal_is_zero(arg))
382
int class_decimal_add(uint32_t mask, type::Decimal *res, const type::Decimal *a,
383
const type::Decimal *b)
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));
392
int class_decimal_sub(uint32_t mask, type::Decimal *res, const type::Decimal *a,
393
const type::Decimal *b)
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));
402
int class_decimal_mul(uint32_t mask, type::Decimal *res, const type::Decimal *a,
403
const type::Decimal *b)
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));
412
int class_decimal_div(uint32_t mask, type::Decimal *res, const type::Decimal *a,
413
const type::Decimal *b, int div_scale_inc)
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,
423
int class_decimal_mod(uint32_t mask, type::Decimal *res, const type::Decimal *a,
424
const type::Decimal *b)
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));
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),
445
int class_decimal_intg(const type::Decimal *a)
447
int my_decimal_intg(const my_decimal *a)
447
449
return decimal_intg(static_cast<const decimal_t*>(a));
451
void class_decimal_trim(uint32_t *precision, uint32_t *scale);
453
inline type::Decimal &decimal_zero_const()
455
static type::Decimal _decimal_zero;
456
return _decimal_zero;
459
double my_double_round(double value, int64_t dec, bool dec_unsigned,
463
#define decimal_zero decimal_zero_const()
453
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
465
455
} /* namespace drizzled */
467
#endif /* DRIZZLED_TYPE_DECIMAL_H */
457
#endif /* DRIZZLED_DECIMAL_H */