~drizzle-trunk/drizzle/development

1 by brian
clean slate
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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
1241.9.60 by Monty Taylor
Moved decimal code into drizzled.
16
#ifndef DRIZZLED_DECIMAL_H
17
#define DRIZZLED_DECIMAL_H
1410.3.1 by Djellel E. Difallah
merge my_decimal and decimal
18
#include <assert.h>
19
#include <drizzled/sql_string.h>
20
#include "drizzled/definitions.h"
1410.3.4 by Djellel E. Difallah
update references to old my_'s
21
#include "drizzled/drizzle_time.h"
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
22
namespace drizzled
23
{
575.1.11 by Monty Taylor
Coupla little fixes.
24
1 by brian
clean slate
25
typedef enum
26
{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR}
27
  decimal_round_mode;
205 by Brian Aker
uint32 -> uin32_t
28
typedef int32_t decimal_digit_t;
1 by brian
clean slate
29
30
typedef struct st_decimal_t {
31
  int    intg, frac, len;
276 by Brian Aker
Cleaned out my_bool from strings.
32
  bool sign;
1 by brian
clean slate
33
  decimal_digit_t *buf;
34
} decimal_t;
35
287.3.10 by Monty Taylor
Const correctness change.
36
int internal_str2dec(char *from, decimal_t *to, char **end,
276 by Brian Aker
Cleaned out my_bool from strings.
37
                     bool fixed);
1241.3.1 by Trond Norbye
cleanup: const'd mystrings/decimal.h and use new style const in drizzled/my_decimal.h
38
int decimal2string(const decimal_t *from, char *to, int *to_len,
1 by brian
clean slate
39
                   int fixed_precision, int fixed_decimals,
40
                   char filler);
1241.3.1 by Trond Norbye
cleanup: const'd mystrings/decimal.h and use new style const in drizzled/my_decimal.h
41
int decimal2uint64_t(const decimal_t *from, uint64_t *to);
42
int uint64_t2decimal(const uint64_t from, decimal_t *to);
43
int decimal2int64_t(const decimal_t *from, int64_t *to);
44
int int64_t2decimal(const int64_t from, decimal_t *to);
45
int decimal2double(const decimal_t *from, double *to);
46
int double2decimal(const double from, decimal_t *to);
1 by brian
clean slate
47
int decimal_actual_fraction(decimal_t *from);
1241.3.1 by Trond Norbye
cleanup: const'd mystrings/decimal.h and use new style const in drizzled/my_decimal.h
48
int decimal2bin(const decimal_t *from, unsigned char *to, int precision, int scale);
481 by Brian Aker
Remove all of uchar.
49
int bin2decimal(const unsigned char *from, decimal_t *to, int precision, int scale);
1 by brian
clean slate
50
51
int decimal_bin_size(int precision, int scale);
52
1241.3.1 by Trond Norbye
cleanup: const'd mystrings/decimal.h and use new style const in drizzled/my_decimal.h
53
int decimal_intg(const decimal_t *from);
54
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
55
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
56
int decimal_cmp(const decimal_t *from1, const decimal_t *from2);
57
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
58
int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to,
1 by brian
clean slate
59
                int scale_incr);
1241.3.1 by Trond Norbye
cleanup: const'd mystrings/decimal.h and use new style const in drizzled/my_decimal.h
60
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
61
int decimal_round(const decimal_t *from, decimal_t *to, int new_scale,
1 by brian
clean slate
62
                  decimal_round_mode mode);
1241.3.1 by Trond Norbye
cleanup: const'd mystrings/decimal.h and use new style const in drizzled/my_decimal.h
63
int decimal_is_zero(const decimal_t *from);
1 by brian
clean slate
64
void max_decimal(int precision, int frac, decimal_t *to);
65
1883.4.1 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
66
inline int string2decimal(char *from, decimal_t *to, char **end)
67
{
68
  return internal_str2dec(from, to, end, false);
69
}
1 by brian
clean slate
70
71
/* set a decimal_t to zero */
72
1883.4.1 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
73
inline void decimal_make_zero(decimal_t *dec)
74
{							    
75
  dec->buf[0]=0;
76
  dec->intg=1;
77
  dec->frac=0;
78
  dec->sign=0; 
79
}
1 by brian
clean slate
80
81
/*
82
  returns the length of the buffer to hold string representation
83
  of the decimal (including decimal dot, possible sign and \0)
84
*/
85
1883.4.1 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
86
inline int decimal_string_size(const decimal_t *dec)
87
{
88
  return (dec->intg ? dec->intg : 1) + dec->frac + (dec->frac > 0) + 2;
89
}
1 by brian
clean slate
90
91
/* negate a decimal */
1883.4.1 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
92
inline void decimal_neg(decimal_t *dec)
93
{
94
  dec->sign^=1;
95
}
1 by brian
clean slate
96
97
/*
98
  conventions:
99
100
    decimal_smth() == 0     -- everything's ok
101
    decimal_smth() <= 1     -- result is usable, but precision loss is possible
102
    decimal_smth() <= 2     -- result can be unusable, most significant digits
103
                               could've been lost
104
    decimal_smth() >  2     -- no result was generated
105
*/
106
107
#define E_DEC_OK                0
108
#define E_DEC_TRUNCATED         1
109
#define E_DEC_OVERFLOW          2
110
#define E_DEC_DIV_ZERO          4
111
#define E_DEC_BAD_NUM           8
112
#define E_DEC_OOM              16
113
114
#define E_DEC_ERROR            31
115
#define E_DEC_FATAL_ERROR      30
1410.3.1 by Djellel E. Difallah
merge my_decimal and decimal
116
#define DECIMAL_LONGLONG_DIGITS 22
117
#define DECIMAL_LONG_DIGITS 10
118
#define DECIMAL_LONG3_DIGITS 8
119
120
/** maximum length of buffer in our big digits (uint32_t). */
121
#define DECIMAL_BUFF_LENGTH 9
122
123
/* the number of digits that my_decimal can possibly contain */
124
#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
125
126
127
/**
128
  maximum guaranteed precision of number in decimal digits (number of our
129
  digits * number of decimal digits in one our big digit - number of decimal
130
  digits in one our big digit decreased by 1 (because we always put decimal
131
  point on the border of our big digits))
132
*/
133
#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
134
#define DECIMAL_MAX_SCALE 30
135
#define DECIMAL_NOT_SPECIFIED 31
136
137
/**
138
  maximum length of string representation (number of maximum decimal
139
  digits + 1 position for sign + 1 position for decimal point)
140
*/
141
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
142
143
/**
144
  maximum size of packet length.
145
*/
146
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
147
148
inline int my_decimal_int_part(uint32_t precision, uint32_t decimals)
149
{
150
  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
151
}
152
153
154
/**
155
  my_decimal class limits 'decimal_t' type to what we need in MySQL.
156
157
  It contains internally all necessary space needed by the instance so
158
  no extra memory is needed. One should call fix_buffer_pointer() function
159
  when he moves my_decimal objects in memory.
160
*/
161
162
class my_decimal :public decimal_t
163
{
164
  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
165
166
public:
167
168
  void init()
169
  {
170
    len= DECIMAL_BUFF_LENGTH;
171
    buf= buffer;
1859.2.14 by Brian Aker
Add support for --with-valgrind
172
	#if !defined (HAVE_VALGRIND)
1410.3.1 by Djellel E. Difallah
merge my_decimal and decimal
173
		/* Set buffer to 'random' value to find wrong buffer usage */
174
		for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
175
		  buffer[i]= i;
176
	#endif
177
  }
178
  my_decimal()
179
  {
180
    init();
181
  }
182
  void fix_buffer_pointer() { buf= buffer; }
183
  bool sign() const { return decimal_t::sign; }
184
  void sign(bool s) { decimal_t::sign= s; }
185
  uint32_t precision() const { return intg + frac; }
186
};
187
188
int decimal_operation_results(int result);
189
190
inline void max_my_decimal(my_decimal *to, int precision, int frac)
191
{
192
  assert((precision <= DECIMAL_MAX_PRECISION)&&
193
              (frac <= DECIMAL_MAX_SCALE));
194
  max_decimal(precision, frac, (decimal_t*) to);
195
}
196
197
inline void max_internal_decimal(my_decimal *to)
198
{
199
  max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
200
}
201
202
inline int check_result(uint32_t mask, int result)
203
{
204
  if (result & mask)
205
    decimal_operation_results(result);
206
  return result;
207
}
208
209
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
210
{
211
  if (check_result(mask, result) & E_DEC_OVERFLOW)
212
  {
213
    bool sign= val->sign();
214
    val->fix_buffer_pointer();
215
    max_internal_decimal(val);
216
    val->sign(sign);
217
  }
218
  return result;
219
}
220
221
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
222
                                           bool unsigned_flag)
223
{
224
  return (uint32_t) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
225
}
226
227
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
228
                                             bool unsigned_flag)
229
{
230
  set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
231
  return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
232
}
233
234
inline
235
int my_decimal_string_length(const my_decimal *d)
236
{
237
  return decimal_string_size(d);
238
}
239
240
241
inline
242
int my_decimal_max_length(const my_decimal *d)
243
{
244
  /* -1 because we do not count \0 */
245
  return decimal_string_size(d) - 1;
246
}
247
248
249
inline
250
int my_decimal_get_binary_size(uint32_t precision, uint32_t scale)
251
{
252
  return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
253
}
254
255
256
inline
257
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
258
{
259
  *to= *from;
260
  to->fix_buffer_pointer();
261
}
262
263
264
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
265
		      int scale);
266
267
268
inline
269
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
270
		      int scale)
271
{
272
  return check_result(mask, bin2decimal(bin, static_cast<decimal_t*>(d), prec, scale));
273
}
274
275
276
inline
277
int my_decimal_set_zero(my_decimal *d)
278
{
279
  decimal_make_zero(static_cast<decimal_t*> (d));
280
  return 0;
281
}
282
283
284
inline
285
bool my_decimal_is_zero(const my_decimal *decimal_value)
286
{
287
  return decimal_is_zero(static_cast<const decimal_t*>(decimal_value));
288
}
289
290
291
inline
292
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
293
                     bool truncate, my_decimal *to)
294
{
295
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
296
                                          (truncate ? TRUNCATE : HALF_UP)));
297
}
298
299
300
inline
301
int my_decimal_floor(uint32_t mask, const my_decimal *from, my_decimal *to)
302
{
303
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, FLOOR));
304
}
305
306
307
inline
308
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
309
{
310
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, CEILING));
311
}
312
313
314
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
315
                      uint32_t fixed_dec, char filler, String *str);
316
317
inline
318
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
319
                   int64_t *l)
320
{
321
  my_decimal rounded;
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)));
327
}
328
329
330
inline
331
int my_decimal2double(uint32_t, const my_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
inline
339
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
340
{
341
  return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(d),end),
342
                                   d);
343
}
344
345
346
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
347
                   const CHARSET_INFO * charset, my_decimal *decimal_value);
348
349
inline
350
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
351
{
352
  return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
353
}
354
355
356
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
357
358
359
inline
360
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
361
{
362
  return check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)), d);
363
}
364
365
366
inline
367
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
368
{
369
  return check_result(mask, (unsigned_flag ?
370
			     uint64_t2decimal(static_cast<uint64_t>(i), d) :
371
			     int64_t2decimal(i, d)));
372
}
373
374
375
inline
376
void my_decimal_neg(decimal_t *arg)
377
{
378
  if (decimal_is_zero(arg))
379
  {
380
    arg->sign= 0;
381
    return;
382
  }
383
  decimal_neg(arg);
384
}
385
386
387
inline
388
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
389
		   const my_decimal *b)
390
{
391
  return check_result_and_overflow(mask,
392
                                   decimal_add(static_cast<const decimal_t*>(a),
393
                                               static_cast<const decimal_t*>(b), res),
394
                                   res);
395
}
396
397
398
inline
399
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
400
		   const my_decimal *b)
401
{
402
  return check_result_and_overflow(mask,
403
                                   decimal_sub(static_cast<const decimal_t*>(a),
404
                                               static_cast<const decimal_t*>(b), res),
405
                                   res);
406
}
407
408
409
inline
410
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
411
		   const my_decimal *b)
412
{
413
  return check_result_and_overflow(mask,
414
                                   decimal_mul(static_cast<const decimal_t*>(a),
415
                                               static_cast<const decimal_t*>(b),res),
416
                                   res);
417
}
418
419
420
inline
421
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
422
		   const my_decimal *b, int div_scale_inc)
423
{
424
  return check_result_and_overflow(mask,
425
                                   decimal_div(static_cast<const decimal_t*>(a),
426
                                               static_cast<const decimal_t*>(b),res,
427
                                               div_scale_inc),
428
                                   res);
429
}
430
431
432
inline
433
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
434
		   const my_decimal *b)
435
{
436
  return check_result_and_overflow(mask,
437
                                   decimal_mod(static_cast<const decimal_t*>(a),
438
                                               static_cast<const decimal_t*>(b),res),
439
                                   res);
440
}
441
442
443
/**
444
  @return
445
    -1 if a<b, 1 if a>b and 0 if a==b
446
*/
447
inline
448
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
449
{
450
  return decimal_cmp(static_cast<const decimal_t*>(a),
451
                     static_cast<const decimal_t*>(b));
452
}
453
454
455
inline
456
int my_decimal_intg(const my_decimal *a)
457
{
458
  return decimal_intg(static_cast<const decimal_t*>(a));
459
}
460
461
462
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
1 by brian
clean slate
463
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
464
} /* namespace drizzled */
575.1.11 by Monty Taylor
Coupla little fixes.
465
1241.9.60 by Monty Taylor
Moved decimal code into drizzled.
466
#endif /* DRIZZLED_DECIMAL_H */
1 by brian
clean slate
467