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
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,
154
146
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
160
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)
162
150
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.
155
my_decimal class limits 'decimal_t' type to what we need in MySQL.
190
157
It contains internally all necessary space needed by the instance so
191
158
no extra memory is needed. One should call fix_buffer_pointer() function
192
when he moves type::Decimal objects in memory.
159
when he moves my_decimal objects in memory.
195
class Decimal : public decimal_t
162
class my_decimal :public decimal_t
197
164
decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
203
170
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++)
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++)
217
182
void fix_buffer_pointer() { buf= buffer; }
218
183
bool sign() const { return decimal_t::sign; }
219
184
void sign(bool s) { decimal_t::sign= s; }
220
185
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,
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,
273
224
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,
227
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
279
230
set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
280
231
return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
285
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)
287
244
/* -1 because we do not count \0 */
288
245
return decimal_string_size(d) - 1;
293
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)
295
252
return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
300
void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
257
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
303
260
to->fix_buffer_pointer();
264
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,
269
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
311
272
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)
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)
319
295
return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
320
296
(truncate ? TRUNCATE : HALF_UP)));
325
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)
327
303
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)
308
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
334
310
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)
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)
345
333
/* No need to call check_result as this will always succeed */
346
334
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)
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)
363
369
return check_result(mask, (unsigned_flag ?
364
370
uint64_t2decimal(static_cast<uint64_t>(i), d) :
370
void class_decimal_neg(decimal_t *arg)
376
void my_decimal_neg(decimal_t *arg)
378
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));
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),
445
int class_decimal_intg(const type::Decimal *a)
456
int my_decimal_intg(const my_decimal *a)
447
458
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()
462
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
465
464
} /* namespace drizzled */
467
#endif /* DRIZZLED_TYPE_DECIMAL_H */
466
#endif /* DRIZZLED_DECIMAL_H */