~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
66
#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0)
67
68
/* set a decimal_t to zero */
69
70
#define decimal_make_zero(dec)        do {                \
71
                                        (dec)->buf[0]=0;    \
72
                                        (dec)->intg=1;      \
73
                                        (dec)->frac=0;      \
74
                                        (dec)->sign=0;      \
75
                                      } while(0)
76
77
/*
78
  returns the length of the buffer to hold string representation
79
  of the decimal (including decimal dot, possible sign and \0)
80
*/
81
82
#define decimal_string_size(dec) (((dec)->intg ? (dec)->intg : 1) + \
83
				  (dec)->frac + ((dec)->frac > 0) + 2)
84
85
/* negate a decimal */
86
#define decimal_neg(dec) do { (dec)->sign^=1; } while(0)
87
88
/*
89
  conventions:
90
91
    decimal_smth() == 0     -- everything's ok
92
    decimal_smth() <= 1     -- result is usable, but precision loss is possible
93
    decimal_smth() <= 2     -- result can be unusable, most significant digits
94
                               could've been lost
95
    decimal_smth() >  2     -- no result was generated
96
*/
97
98
#define E_DEC_OK                0
99
#define E_DEC_TRUNCATED         1
100
#define E_DEC_OVERFLOW          2
101
#define E_DEC_DIV_ZERO          4
102
#define E_DEC_BAD_NUM           8
103
#define E_DEC_OOM              16
104
105
#define E_DEC_ERROR            31
106
#define E_DEC_FATAL_ERROR      30
1410.3.1 by Djellel E. Difallah
merge my_decimal and decimal
107
#define DECIMAL_LONGLONG_DIGITS 22
108
#define DECIMAL_LONG_DIGITS 10
109
#define DECIMAL_LONG3_DIGITS 8
110
111
/** maximum length of buffer in our big digits (uint32_t). */
112
#define DECIMAL_BUFF_LENGTH 9
113
114
/* the number of digits that my_decimal can possibly contain */
115
#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
116
117
118
/**
119
  maximum guaranteed precision of number in decimal digits (number of our
120
  digits * number of decimal digits in one our big digit - number of decimal
121
  digits in one our big digit decreased by 1 (because we always put decimal
122
  point on the border of our big digits))
123
*/
124
#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
125
#define DECIMAL_MAX_SCALE 30
126
#define DECIMAL_NOT_SPECIFIED 31
127
128
/**
129
  maximum length of string representation (number of maximum decimal
130
  digits + 1 position for sign + 1 position for decimal point)
131
*/
132
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
133
134
/**
135
  maximum size of packet length.
136
*/
137
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
138
139
inline int my_decimal_int_part(uint32_t precision, uint32_t decimals)
140
{
141
  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
142
}
143
144
145
/**
146
  my_decimal class limits 'decimal_t' type to what we need in MySQL.
147
148
  It contains internally all necessary space needed by the instance so
149
  no extra memory is needed. One should call fix_buffer_pointer() function
150
  when he moves my_decimal objects in memory.
151
*/
152
153
class my_decimal :public decimal_t
154
{
155
  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
156
157
public:
158
159
  void init()
160
  {
161
    len= DECIMAL_BUFF_LENGTH;
162
    buf= buffer;
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++)
166
		  buffer[i]= i;
167
	#endif
168
  }
169
  my_decimal()
170
  {
171
    init();
172
  }
173
  void fix_buffer_pointer() { buf= buffer; }
174
  bool sign() const { return decimal_t::sign; }
175
  void sign(bool s) { decimal_t::sign= s; }
176
  uint32_t precision() const { return intg + frac; }
177
};
178
179
int decimal_operation_results(int result);
180
181
inline void max_my_decimal(my_decimal *to, int precision, int frac)
182
{
183
  assert((precision <= DECIMAL_MAX_PRECISION)&&
184
              (frac <= DECIMAL_MAX_SCALE));
185
  max_decimal(precision, frac, (decimal_t*) to);
186
}
187
188
inline void max_internal_decimal(my_decimal *to)
189
{
190
  max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
191
}
192
193
inline int check_result(uint32_t mask, int result)
194
{
195
  if (result & mask)
196
    decimal_operation_results(result);
197
  return result;
198
}
199
200
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
201
{
202
  if (check_result(mask, result) & E_DEC_OVERFLOW)
203
  {
204
    bool sign= val->sign();
205
    val->fix_buffer_pointer();
206
    max_internal_decimal(val);
207
    val->sign(sign);
208
  }
209
  return result;
210
}
211
212
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
213
                                           bool unsigned_flag)
214
{
215
  return (uint32_t) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
216
}
217
218
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
219
                                             bool unsigned_flag)
220
{
221
  set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
222
  return static_cast<uint32_t>(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
223
}
224
225
inline
226
int my_decimal_string_length(const my_decimal *d)
227
{
228
  return decimal_string_size(d);
229
}
230
231
232
inline
233
int my_decimal_max_length(const my_decimal *d)
234
{
235
  /* -1 because we do not count \0 */
236
  return decimal_string_size(d) - 1;
237
}
238
239
240
inline
241
int my_decimal_get_binary_size(uint32_t precision, uint32_t scale)
242
{
243
  return decimal_bin_size(static_cast<int>(precision), static_cast<int>(scale));
244
}
245
246
247
inline
248
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
249
{
250
  *to= *from;
251
  to->fix_buffer_pointer();
252
}
253
254
255
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
256
		      int scale);
257
258
259
inline
260
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
261
		      int scale)
262
{
263
  return check_result(mask, bin2decimal(bin, static_cast<decimal_t*>(d), prec, scale));
264
}
265
266
267
inline
268
int my_decimal_set_zero(my_decimal *d)
269
{
270
  decimal_make_zero(static_cast<decimal_t*> (d));
271
  return 0;
272
}
273
274
275
inline
276
bool my_decimal_is_zero(const my_decimal *decimal_value)
277
{
278
  return decimal_is_zero(static_cast<const decimal_t*>(decimal_value));
279
}
280
281
282
inline
283
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
284
                     bool truncate, my_decimal *to)
285
{
286
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, scale,
287
                                          (truncate ? TRUNCATE : HALF_UP)));
288
}
289
290
291
inline
292
int my_decimal_floor(uint32_t mask, const my_decimal *from, my_decimal *to)
293
{
294
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, FLOOR));
295
}
296
297
298
inline
299
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
300
{
301
  return check_result(mask, decimal_round(static_cast<const decimal_t*>(from), to, 0, CEILING));
302
}
303
304
305
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
306
                      uint32_t fixed_dec, char filler, String *str);
307
308
inline
309
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
310
                   int64_t *l)
311
{
312
  my_decimal rounded;
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)));
318
}
319
320
321
inline
322
int my_decimal2double(uint32_t, const my_decimal *d, double *result)
323
{
324
  /* No need to call check_result as this will always succeed */
325
  return decimal2double(static_cast<const decimal_t*>(d), result);
326
}
327
328
329
inline
330
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
331
{
332
  return check_result_and_overflow(mask, string2decimal(str, static_cast<decimal_t*>(d),end),
333
                                   d);
334
}
335
336
337
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
338
                   const CHARSET_INFO * charset, my_decimal *decimal_value);
339
340
inline
341
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
342
{
343
  return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
344
}
345
346
347
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
348
349
350
inline
351
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
352
{
353
  return check_result_and_overflow(mask, double2decimal(val, static_cast<decimal_t*>(d)), d);
354
}
355
356
357
inline
358
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
359
{
360
  return check_result(mask, (unsigned_flag ?
361
			     uint64_t2decimal(static_cast<uint64_t>(i), d) :
362
			     int64_t2decimal(i, d)));
363
}
364
365
366
inline
367
void my_decimal_neg(decimal_t *arg)
368
{
369
  if (decimal_is_zero(arg))
370
  {
371
    arg->sign= 0;
372
    return;
373
  }
374
  decimal_neg(arg);
375
}
376
377
378
inline
379
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
380
		   const my_decimal *b)
381
{
382
  return check_result_and_overflow(mask,
383
                                   decimal_add(static_cast<const decimal_t*>(a),
384
                                               static_cast<const decimal_t*>(b), res),
385
                                   res);
386
}
387
388
389
inline
390
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
391
		   const my_decimal *b)
392
{
393
  return check_result_and_overflow(mask,
394
                                   decimal_sub(static_cast<const decimal_t*>(a),
395
                                               static_cast<const decimal_t*>(b), res),
396
                                   res);
397
}
398
399
400
inline
401
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
402
		   const my_decimal *b)
403
{
404
  return check_result_and_overflow(mask,
405
                                   decimal_mul(static_cast<const decimal_t*>(a),
406
                                               static_cast<const decimal_t*>(b),res),
407
                                   res);
408
}
409
410
411
inline
412
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
413
		   const my_decimal *b, int div_scale_inc)
414
{
415
  return check_result_and_overflow(mask,
416
                                   decimal_div(static_cast<const decimal_t*>(a),
417
                                               static_cast<const decimal_t*>(b),res,
418
                                               div_scale_inc),
419
                                   res);
420
}
421
422
423
inline
424
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
425
		   const my_decimal *b)
426
{
427
  return check_result_and_overflow(mask,
428
                                   decimal_mod(static_cast<const decimal_t*>(a),
429
                                               static_cast<const decimal_t*>(b),res),
430
                                   res);
431
}
432
433
434
/**
435
  @return
436
    -1 if a<b, 1 if a>b and 0 if a==b
437
*/
438
inline
439
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
440
{
441
  return decimal_cmp(static_cast<const decimal_t*>(a),
442
                     static_cast<const decimal_t*>(b));
443
}
444
445
446
inline
447
int my_decimal_intg(const my_decimal *a)
448
{
449
  return decimal_intg(static_cast<const decimal_t*>(a));
450
}
451
452
453
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
1 by brian
clean slate
454
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
455
} /* namespace drizzled */
575.1.11 by Monty Taylor
Coupla little fixes.
456
1241.9.60 by Monty Taylor
Moved decimal code into drizzled.
457
#endif /* DRIZZLED_DECIMAL_H */
1 by brian
clean slate
458