1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
It is interface module to fixed precision decimals library.
25
Most functions use 'uint32_t mask' as parameter, if during operation error
26
which fit in this mask is detected then it will be processed automatically
27
here. (errors are E_DEC_* constants, see include/decimal.h)
29
Most function are just inline wrappers around library calls
39
#include <mystrings/decimal.h>
46
#define DECIMAL_LONGLONG_DIGITS 22
47
#define DECIMAL_LONG_DIGITS 10
48
#define DECIMAL_LONG3_DIGITS 8
50
/** maximum length of buffer in our big digits (uint32_t). */
51
#define DECIMAL_BUFF_LENGTH 9
53
/* the number of digits that my_decimal can possibly contain */
54
#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
58
maximum guaranteed precision of number in decimal digits (number of our
59
digits * number of decimal digits in one our big digit - number of decimal
60
digits in one our big digit decreased by 1 (because we always put decimal
61
point on the border of our big digits))
63
#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
64
#define DECIMAL_MAX_SCALE 30
65
#define DECIMAL_NOT_SPECIFIED 31
68
maximum length of string representation (number of maximum decimal
69
digits + 1 position for sign + 1 position for decimal point)
71
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
74
maximum size of packet length.
76
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
79
inline uint32_t my_decimal_size(uint32_t precision, uint32_t scale)
82
Always allocate more space to allow library to put decimal point
85
return decimal_size(precision, scale) + 1;
89
inline int my_decimal_int_part(uint32_t precision, uint32_t decimals)
91
return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
96
my_decimal class limits 'decimal_t' type to what we need in MySQL.
98
It contains internally all necessary space needed by the instance so
99
no extra memory is needed. One should call fix_buffer_pointer() function
100
when he moves my_decimal objects in memory.
103
class my_decimal :public decimal_t
105
decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
111
len= DECIMAL_BUFF_LENGTH;
113
#if !defined (HAVE_purify)
114
/* Set buffer to 'random' value to find wrong buffer usage */
115
for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
123
void fix_buffer_pointer() { buf= buffer; }
125
bool sign() const { return decimal_t::sign; }
126
void sign(bool s) { decimal_t::sign= s; }
127
uint32_t precision() const { return intg + frac; }
130
int decimal_operation_results(int result);
133
void max_my_decimal(my_decimal *to, int precision, int frac)
135
assert((precision <= DECIMAL_MAX_PRECISION)&&
136
(frac <= DECIMAL_MAX_SCALE));
137
max_decimal(precision, frac, (decimal_t*) to);
140
inline void max_internal_decimal(my_decimal *to)
142
max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
145
inline int check_result(uint32_t mask, int result)
148
decimal_operation_results(result);
152
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
154
if (check_result(mask, result) & E_DEC_OVERFLOW)
156
bool sign= val->sign();
157
val->fix_buffer_pointer();
158
max_internal_decimal(val);
164
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
167
return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
170
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
173
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
174
return (uint32_t)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
178
int my_decimal_string_length(const my_decimal *d)
180
return decimal_string_size(d);
185
int my_decimal_max_length(const my_decimal *d)
187
/* -1 because we do not count \0 */
188
return decimal_string_size(d) - 1;
193
int my_decimal_get_binary_size(uint32_t precision, uint32_t scale)
195
return decimal_bin_size((int)precision, (int)scale);
200
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
203
to->fix_buffer_pointer();
207
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
212
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
215
return check_result(mask, bin2decimal(bin, (decimal_t*) d, prec, scale));
220
int my_decimal_set_zero(my_decimal *d)
222
decimal_make_zero(((decimal_t*) d));
228
bool my_decimal_is_zero(const my_decimal *decimal_value)
230
return decimal_is_zero((decimal_t*) decimal_value);
235
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
236
bool truncate, my_decimal *to)
238
return check_result(mask, decimal_round((decimal_t*) from, to, scale,
239
(truncate ? TRUNCATE : HALF_UP)));
244
int my_decimal_floor(uint32_t mask, const my_decimal *from, my_decimal *to)
246
return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR));
251
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
253
return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING));
257
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
258
uint32_t fixed_dec, char filler, String *str);
261
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
265
/* decimal_round can return only E_DEC_TRUNCATED */
266
decimal_round((decimal_t*)d, &rounded, 0, HALF_UP);
267
return check_result(mask, (unsigned_flag ?
268
decimal2uint64_t(&rounded, (uint64_t *)l) :
269
decimal2int64_t(&rounded, l)));
274
int my_decimal2double(uint32_t mask __attribute__((unused)),
275
const my_decimal *d, double *result)
277
/* No need to call check_result as this will always succeed */
278
return decimal2double((decimal_t*) d, result);
283
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
285
return check_result_and_overflow(mask, string2decimal(str,(decimal_t*)d,end),
290
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
291
const CHARSET_INFO * charset, my_decimal *decimal_value);
293
#if defined(DRIZZLE_SERVER)
295
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
297
return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
301
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
304
#endif /*defined(DRIZZLE_SERVER) */
307
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
309
return check_result_and_overflow(mask, double2decimal(val, (decimal_t*)d), d);
314
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
316
return check_result(mask, (unsigned_flag ?
317
uint64_t2decimal((uint64_t)i, d) :
318
int64_t2decimal(i, d)));
323
void my_decimal_neg(decimal_t *arg)
325
if (decimal_is_zero(arg))
335
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
338
return check_result_and_overflow(mask,
339
decimal_add((decimal_t*)a,(decimal_t*)b,res),
345
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
348
return check_result_and_overflow(mask,
349
decimal_sub((decimal_t*)a,(decimal_t*)b,res),
355
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
358
return check_result_and_overflow(mask,
359
decimal_mul((decimal_t*)a,(decimal_t*)b,res),
365
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
366
const my_decimal *b, int div_scale_inc)
368
return check_result_and_overflow(mask,
369
decimal_div((decimal_t*)a,(decimal_t*)b,res,
376
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
379
return check_result_and_overflow(mask,
380
decimal_mod((decimal_t*)a,(decimal_t*)b,res),
387
-1 if a<b, 1 if a>b and 0 if a==b
390
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
392
return decimal_cmp((decimal_t*) a, (decimal_t*) b);
397
int my_decimal_intg(const my_decimal *a)
399
return decimal_intg((decimal_t*) a);
403
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
406
#endif /*my_decimal_h*/