Drizzled Public API Documentation

decimal.h
1 /* Copyright (C) 2000 MySQL AB
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
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 */
15 
16 #pragma once
17 #include <assert.h>
18 #include <drizzled/sql_string.h>
19 #include <drizzled/definitions.h>
20 #include <drizzled/type/time.h>
21 
22 namespace drizzled {
23 
24 typedef enum
25 {
26  TRUNCATE= 0,
27  HALF_EVEN,
28  HALF_UP,
29  CEILING,
30  FLOOR
31 } decimal_round_mode;
32 typedef int32_t decimal_digit_t;
33 
34 struct decimal_t {
35  int intg, frac, len;
36  bool sign;
37  decimal_digit_t *buf;
38 
39  /* set a decimal_t to zero */
40  inline void set_zero()
41  {
42  buf[0]= 0;
43  intg= 1;
44  frac= 0;
45  sign= 0;
46  }
47 
48  /* negate a decimal */
49  inline void negate()
50  {
51  sign^=1;
52  }
53 
54  int isZero() const;
55 
56 };
57 
58 int internal_str2dec(char *from, decimal_t *to, char **end,
59  bool fixed);
60 int decimal2string(const decimal_t *from, char *to, int *to_len,
61  int fixed_precision, int fixed_decimals,
62  char filler);
63 int decimal2uint64_t(const decimal_t *from, uint64_t *to);
64 int uint64_t2decimal(const uint64_t from, decimal_t *to);
65 int decimal2int64_t(const decimal_t *from, int64_t *to);
66 int int64_t2decimal(const int64_t from, decimal_t *to);
67 int decimal2double(const decimal_t *from, double *to);
68 int double2decimal(const double from, decimal_t *to);
70 int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int scale);
71 int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale);
72 
73 int decimal_bin_size(int precision, int scale);
74 
75 int decimal_intg(const decimal_t *from);
76 int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
77 int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
78 int decimal_cmp(const decimal_t *from1, const decimal_t *from2);
79 int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
80 int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to,
81  int scale_incr);
82 int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
83 int decimal_round(const decimal_t *from, decimal_t *to, int new_scale,
84  decimal_round_mode mode);
85 void max_decimal(int precision, int frac, decimal_t *to);
86 
87 inline int string2decimal(char *from, decimal_t *to, char **end)
88 {
89  return internal_str2dec(from, to, end, false);
90 }
91 
92 /*
93  returns the length of the buffer to hold string representation
94  of the decimal (including decimal dot, possible sign and \0)
95 */
96 
97 inline int decimal_string_size(const decimal_t *dec)
98 {
99  return (dec->intg ? dec->intg : 1) + dec->frac + (dec->frac > 0) + 2;
100 }
101 
102 /*
103  conventions:
104 
105  decimal_smth() == 0 -- everything's ok
106  decimal_smth() <= 1 -- result is usable, but precision loss is possible
107  decimal_smth() <= 2 -- result can be unusable, most significant digits
108  could've been lost
109  decimal_smth() > 2 -- no result was generated
110 */
111 
112 #define E_DEC_OK 0
113 #define E_DEC_TRUNCATED 1
114 #define E_DEC_OVERFLOW 2
115 #define E_DEC_DIV_ZERO 4
116 #define E_DEC_BAD_NUM 8
117 #define E_DEC_OOM 16
118 
119 #define E_DEC_ERROR 31
120 #define E_DEC_FATAL_ERROR 30
121 
122 
123 #define DECIMAL_LONGLONG_DIGITS 22
124 
126 #define DECIMAL_BUFF_LENGTH 9
127 
128 /* the number of digits that type::Decimal can possibly contain */
129 #define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
130 
131 
138 #define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
139 #define DECIMAL_MAX_SCALE 30
140 #define DECIMAL_NOT_SPECIFIED 31
141 
146 #define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
147 
148 inline int class_decimal_int_part(uint32_t precision, uint32_t decimals)
149 {
150  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
151 }
152 
153 int decimal_operation_results(int result);
154 
155 inline void max_Decimal(type::Decimal *to, int precision, int frac)
156 {
157  assert((precision <= DECIMAL_MAX_PRECISION)&&
158  (frac <= DECIMAL_MAX_SCALE));
159  max_decimal(precision, frac, (decimal_t*) to);
160 }
161 
162 inline void max_internal_decimal(type::Decimal *to)
163 {
164  max_Decimal(to, DECIMAL_MAX_PRECISION, 0);
165 }
166 
167 inline int check_result(uint32_t mask, int result)
168 {
169  if (result & mask)
171  return result;
172 }
173 
174 namespace type {
183 class Decimal : public decimal_t
184 {
185  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
186 
187 public:
188 
189  void init()
190  {
191  len= DECIMAL_BUFF_LENGTH;
192  buf= buffer;
193 #if !defined (HAVE_VALGRIND)
194  /* Set buffer to 'random' value to find wrong buffer usage */
195  for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
196  buffer[i]= i;
197 #endif
198  }
199 
200  Decimal()
201  {
202  init();
203  }
204 
205  void fix_buffer_pointer() { buf= buffer; }
206  bool sign() const { return decimal_t::sign; }
207  void sign(bool s) { decimal_t::sign= s; }
208  uint32_t precision() const { return intg + frac; }
209 
210  int val_int32(uint32_t mask, bool unsigned_flag, int64_t *l) const
211  {
212  type::Decimal rounded;
213  /* decimal_round can return only E_DEC_TRUNCATED */
214  decimal_round(static_cast<const decimal_t*>(this), &rounded, 0, HALF_UP);
215  return check_result(mask, (unsigned_flag ?
216  decimal2uint64_t(&rounded, reinterpret_cast<uint64_t *>(l)) :
217  decimal2int64_t(&rounded, l)));
218  }
219 
220  int string_length() const
221  {
222  return decimal_string_size(this);
223  }
224 
225  int val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const;
226 
227  int store(uint32_t mask, const char *from, uint32_t length, const charset_info_st * charset);
228 
229  int store(uint32_t mask, char *str, char **end)
230  {
231  return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(this), end));
232  }
233 
234  int store(uint32_t mask, const String *str)
235  {
236  return store(mask, str->ptr(), str->length(), str->charset());
237  }
238 
239  int check_result_and_overflow(uint32_t mask, int result)
240  {
241  if (check_result(mask, result) & E_DEC_OVERFLOW)
242  {
243  bool _sign= sign();
244  fix_buffer_pointer();
245  max_internal_decimal(this);
246  sign(_sign);
247  }
248  return result;
249  }
250 
251  void convert(double &value) const;
252 };
253 
254 } // type
255 
256 std::ostream& operator<<(std::ostream& output, const type::Decimal &dec);
257 
258 inline uint32_t class_decimal_length_to_precision(uint32_t length, uint32_t scale,
259  bool unsigned_flag)
260 {
261  return (uint32_t) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
262 }
263 
264 inline uint32_t class_decimal_precision_to_length(uint32_t precision, uint8_t scale,
265  bool unsigned_flag)
266 {
267  set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
268  return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
269 }
270 
271 
272 inline
273 int class_decimal_max_length(const type::Decimal *d)
274 {
275  /* -1 because we do not count \0 */
276  return decimal_string_size(d) - 1;
277 }
278 
279 
280 inline
281 int class_decimal_get_binary_size(uint32_t precision, uint32_t scale)
282 {
283  return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
284 }
285 
286 
287 inline
288 void class_decimal2decimal(const type::Decimal *from, type::Decimal *to)
289 {
290  *to= *from;
291  to->fix_buffer_pointer();
292 }
293 
294 
295 inline
296 int binary2_class_decimal(uint32_t mask, const unsigned char *bin, type::Decimal *d, int prec,
297  int scale)
298 {
299  return check_result(mask, bin2decimal(bin, static_cast<decimal_t*>(d), prec, scale));
300 }
301 
302 
303 inline
304 int class_decimal_round(uint32_t mask, const type::Decimal *from, int scale,
305  bool truncate, type::Decimal *to)
306 {
307  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
308  (truncate ? TRUNCATE : HALF_UP)));
309 }
310 
311 
312 inline
313 int class_decimal_floor(uint32_t mask, const type::Decimal *from, type::Decimal *to)
314 {
315  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, FLOOR));
316 }
317 
318 
319 inline
320 int class_decimal_ceiling(uint32_t mask, const type::Decimal *from, type::Decimal *to)
321 {
322  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, CEILING));
323 }
324 
325 
326 int class_decimal2string(const type::Decimal *d,
327  uint32_t fixed_dec, String *str);
328 
329 
330 inline
331 int class_decimal2double(uint32_t, const type::Decimal *d, double *result)
332 {
333  /* No need to call check_result as this will always succeed */
334  return decimal2double(static_cast<const decimal_t*>(d), result);
335 }
336 
337 
338 type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec);
339 
340 
341 inline
342 int double2_class_decimal(uint32_t mask, double val, type::Decimal *d)
343 {
344  return d->check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)));
345 }
346 
347 
348 inline
349 int int2_class_decimal(uint32_t mask, int64_t i, bool unsigned_flag, type::Decimal *d)
350 {
351  return check_result(mask, (unsigned_flag ?
352  uint64_t2decimal(static_cast<uint64_t>(i), d) :
353  int64_t2decimal(i, d)));
354 }
355 
356 
357 inline
358 void class_decimal_neg(decimal_t *arg)
359 {
360  if (arg->isZero())
361  {
362  arg->sign= 0;
363  return;
364  }
365  arg->negate();
366 }
367 
368 
369 inline
370 int class_decimal_add(uint32_t mask, type::Decimal *res, const type::Decimal *a,
371  const type::Decimal *b)
372 {
373  return res->check_result_and_overflow(mask,
374  decimal_add(static_cast<const decimal_t*>(a),
375  static_cast<const decimal_t*>(b), res));
376 }
377 
378 
379 inline
380 int class_decimal_sub(uint32_t mask, type::Decimal *res, const type::Decimal *a,
381  const type::Decimal *b)
382 {
383  return res->check_result_and_overflow(mask,
384  decimal_sub(static_cast<const decimal_t*>(a),
385  static_cast<const decimal_t*>(b), res));
386 }
387 
388 
389 inline
390 int class_decimal_mul(uint32_t mask, type::Decimal *res, const type::Decimal *a,
391  const type::Decimal *b)
392 {
393  return res->check_result_and_overflow(mask,
394  decimal_mul(static_cast<const decimal_t*>(a),
395  static_cast<const decimal_t*>(b),res));
396 }
397 
398 
399 inline
400 int class_decimal_div(uint32_t mask, type::Decimal *res, const type::Decimal *a,
401  const type::Decimal *b, int div_scale_inc)
402 {
403  return res->check_result_and_overflow(mask,
404  decimal_div(static_cast<const decimal_t*>(a),
405  static_cast<const decimal_t*>(b),res,
406  div_scale_inc));
407 }
408 
409 
410 inline
411 int class_decimal_mod(uint32_t mask, type::Decimal *res, const type::Decimal *a,
412  const type::Decimal *b)
413 {
414  return res->check_result_and_overflow(mask,
415  decimal_mod(static_cast<const decimal_t*>(a),
416  static_cast<const decimal_t*>(b),res));
417 }
418 
419 
424 inline
426 {
427  return decimal_cmp(static_cast<const decimal_t*>(a),
428  static_cast<const decimal_t*>(b));
429 }
430 
431 
432 inline
433 int class_decimal_intg(const type::Decimal *a)
434 {
435  return decimal_intg(static_cast<const decimal_t*>(a));
436 }
437 
438 
439 void class_decimal_trim(uint32_t *precision, uint32_t *scale);
440 
441 inline type::Decimal &decimal_zero_const()
442 {
443  static type::Decimal _decimal_zero;
444  return _decimal_zero;
445 }
446 
447 double my_double_round(double value, int64_t dec, bool dec_unsigned,
448  bool truncate);
449 
450 
451 #define decimal_zero decimal_zero_const()
452 
453 } /* namespace drizzled */
454 
455 
int decimal_round(const decimal_t *from, decimal_t *to, int scale, decimal_round_mode mode)
Rounds the decimal to "scale" digits.
Definition: decimal.cc:1666
int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
division of two decimals
Definition: decimal.cc:2514
TODO: Rename this file - func.h is stupid.
int class_decimal_cmp(const type::Decimal *a, const type::Decimal *b)
Definition: decimal.h:425
void max_decimal(int precision, int frac, decimal_t *to)
Get maximum value for given precision and scale.
Definition: decimal.cc:470
int store(uint32_t mask, const char *from, uint32_t length, const charset_info_st *charset)
Convert string for decimal when string can be in some multibyte charset.
Definition: decimal.cc:285
int internal_str2dec(char *from, decimal_t *to, char **end, bool fixed)
Convert string to decimal.
Definition: decimal.cc:1021
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int frac)
Convert decimal to its binary fixed-length representation (suitable for comparing with memcmp) ...
Definition: decimal.cc:1399
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
modulus
Definition: decimal.cc:2544
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
multiply two decimals
Definition: decimal.cc:2141
int decimal_actual_fraction(decimal_t *from)
Count actual length of fraction part (without ending zeroes)
Definition: decimal.cc:526
int class_decimal2string(const type::Decimal *d, uint32_t fixed_dec, String *str)
Converting decimal to string.
Definition: decimal.cc:197
int decimal_operation_results(int result)
Definition: decimal.cc:143
int double2decimal(const double from, decimal_t *to)
Definition: decimal.cc:1200
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale)
Restores decimal from its binary fixed-length representation.
Definition: decimal.cc:1532
int decimal_bin_size(int precision, int scale)
Returns the size of array to hold a binary representation of a decimal.
Definition: decimal.cc:1639
int decimal2double(const decimal_t *from, double *to)
Definition: decimal.cc:1179
int decimal2string(const decimal_t *from, char *to, int *to_len, int fixed_precision, int fixed_decimals, char filler)
Convert decimal to its printable string representation.
Definition: decimal.cc:570