~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/my_decimal.h

  • Committer: Brian Aker
  • Date: 2010-05-27 01:25:56 UTC
  • mfrom: (1567.1.4 new-staging)
  • Revision ID: brian@gaz-20100527012556-5zgkirkl7swbigd6
Merge of Brian, Paul. PBXT compile issue, and test framework cleanup. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2005-2006 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
/**
17
 
  @file
18
 
 
19
 
  It is interface module to fixed precision decimals library.
20
 
 
21
 
  Most functions use 'uint mask' as parameter, if during operation error
22
 
  which fit in this mask is detected then it will be processed automatically
23
 
  here. (errors are E_DEC_* constants, see include/decimal.h)
24
 
 
25
 
  Most function are just inline wrappers around library calls
26
 
*/
27
 
 
28
 
#ifndef my_decimal_h
29
 
#define my_decimal_h
30
 
 
31
 
C_MODE_START
32
 
#include <mystrings/decimal.h>
33
 
C_MODE_END
34
 
 
35
 
#define DECIMAL_LONGLONG_DIGITS 22
36
 
#define DECIMAL_LONG_DIGITS 10
37
 
#define DECIMAL_LONG3_DIGITS 8
38
 
 
39
 
/** maximum length of buffer in our big digits (uint32_t). */
40
 
#define DECIMAL_BUFF_LENGTH 9
41
 
 
42
 
/* the number of digits that my_decimal can possibly contain */
43
 
#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
44
 
 
45
 
 
46
 
/**
47
 
  maximum guaranteed precision of number in decimal digits (number of our
48
 
  digits * number of decimal digits in one our big digit - number of decimal
49
 
  digits in one our big digit decreased by 1 (because we always put decimal
50
 
  point on the border of our big digits))
51
 
*/
52
 
#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
53
 
#define DECIMAL_MAX_SCALE 30
54
 
#define DECIMAL_NOT_SPECIFIED 31
55
 
 
56
 
/**
57
 
  maximum length of string representation (number of maximum decimal
58
 
  digits + 1 position for sign + 1 position for decimal point)
59
 
*/
60
 
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
61
 
 
62
 
/**
63
 
  maximum size of packet length.
64
 
*/
65
 
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
66
 
 
67
 
 
68
 
inline uint my_decimal_size(uint precision, uint scale)
69
 
{
70
 
  /*
71
 
    Always allocate more space to allow library to put decimal point
72
 
    where it want
73
 
  */
74
 
  return decimal_size(precision, scale) + 1;
75
 
}
76
 
 
77
 
 
78
 
inline int my_decimal_int_part(uint precision, uint decimals)
79
 
{
80
 
  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
81
 
}
82
 
 
83
 
 
84
 
/**
85
 
  my_decimal class limits 'decimal_t' type to what we need in MySQL.
86
 
 
87
 
  It contains internally all necessary space needed by the instance so
88
 
  no extra memory is needed. One should call fix_buffer_pointer() function
89
 
  when he moves my_decimal objects in memory.
90
 
*/
91
 
 
92
 
class my_decimal :public decimal_t
93
 
{
94
 
  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
95
 
 
96
 
public:
97
 
 
98
 
  void init()
99
 
  {
100
 
    len= DECIMAL_BUFF_LENGTH;
101
 
    buf= buffer;
102
 
#if !defined (HAVE_purify) 
103
 
    /* Set buffer to 'random' value to find wrong buffer usage */
104
 
    for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
105
 
      buffer[i]= i;
106
 
#endif
107
 
  }
108
 
  my_decimal()
109
 
  {
110
 
    init();
111
 
  }
112
 
  void fix_buffer_pointer() { buf= buffer; }
113
 
 
114
 
  bool sign() const { return decimal_t::sign; }
115
 
  void sign(bool s) { decimal_t::sign= s; }
116
 
  uint precision() const { return intg + frac; }
117
 
};
118
 
 
119
 
#ifndef DRIZZLE_CLIENT
120
 
int decimal_operation_results(int result);
121
 
#else
122
 
inline int decimal_operation_results(int result)
123
 
{
124
 
  return result;
125
 
}
126
 
#endif /*DRIZZLE_CLIENT*/
127
 
 
128
 
inline
129
 
void max_my_decimal(my_decimal *to, int precision, int frac)
130
 
{
131
 
  assert((precision <= DECIMAL_MAX_PRECISION)&&
132
 
              (frac <= DECIMAL_MAX_SCALE));
133
 
  max_decimal(precision, frac, (decimal_t*) to);
134
 
}
135
 
 
136
 
inline void max_internal_decimal(my_decimal *to)
137
 
{
138
 
  max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
139
 
}
140
 
 
141
 
inline int check_result(uint mask, int result)
142
 
{
143
 
  if (result & mask)
144
 
    decimal_operation_results(result);
145
 
  return result;
146
 
}
147
 
 
148
 
inline int check_result_and_overflow(uint mask, int result, my_decimal *val)
149
 
{
150
 
  if (check_result(mask, result) & E_DEC_OVERFLOW)
151
 
  {
152
 
    bool sign= val->sign();
153
 
    val->fix_buffer_pointer();
154
 
    max_internal_decimal(val);
155
 
    val->sign(sign);
156
 
  }
157
 
  return result;
158
 
}
159
 
 
160
 
inline uint my_decimal_length_to_precision(uint length, uint scale,
161
 
                                           bool unsigned_flag)
162
 
{
163
 
  return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
164
 
}
165
 
 
166
 
inline uint32_t my_decimal_precision_to_length(uint precision, uint8_t scale,
167
 
                                             bool unsigned_flag)
168
 
{
169
 
  set_if_smaller(precision, DECIMAL_MAX_PRECISION);
170
 
  return (uint32_t)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
171
 
}
172
 
 
173
 
inline
174
 
int my_decimal_string_length(const my_decimal *d)
175
 
{
176
 
  return decimal_string_size(d);
177
 
}
178
 
 
179
 
 
180
 
inline
181
 
int my_decimal_max_length(const my_decimal *d)
182
 
{
183
 
  /* -1 because we do not count \0 */
184
 
  return decimal_string_size(d) - 1;
185
 
}
186
 
 
187
 
 
188
 
inline
189
 
int my_decimal_get_binary_size(uint precision, uint scale)
190
 
{
191
 
  return decimal_bin_size((int)precision, (int)scale);
192
 
}
193
 
 
194
 
 
195
 
inline
196
 
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
197
 
{
198
 
  *to= *from;
199
 
  to->fix_buffer_pointer();
200
 
}
201
 
 
202
 
 
203
 
int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec,
204
 
                      int scale);
205
 
 
206
 
 
207
 
inline
208
 
int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec,
209
 
                      int scale)
210
 
{
211
 
  return check_result(mask, bin2decimal(bin, (decimal_t*) d, prec, scale));
212
 
}
213
 
 
214
 
 
215
 
inline
216
 
int my_decimal_set_zero(my_decimal *d)
217
 
{
218
 
  decimal_make_zero(((decimal_t*) d));
219
 
  return 0;
220
 
}
221
 
 
222
 
 
223
 
inline
224
 
bool my_decimal_is_zero(const my_decimal *decimal_value)
225
 
{
226
 
  return decimal_is_zero((decimal_t*) decimal_value);
227
 
}
228
 
 
229
 
 
230
 
inline
231
 
int my_decimal_round(uint mask, const my_decimal *from, int scale,
232
 
                     bool truncate, my_decimal *to)
233
 
{
234
 
  return check_result(mask, decimal_round((decimal_t*) from, to, scale,
235
 
                                          (truncate ? TRUNCATE : HALF_UP)));
236
 
}
237
 
 
238
 
 
239
 
inline
240
 
int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
241
 
{
242
 
  return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR));
243
 
}
244
 
 
245
 
 
246
 
inline
247
 
int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
248
 
{
249
 
  return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING));
250
 
}
251
 
 
252
 
 
253
 
#ifndef DRIZZLE_CLIENT
254
 
int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
255
 
                      uint fixed_dec, char filler, String *str);
256
 
#endif
257
 
 
258
 
inline
259
 
int my_decimal2int(uint mask, const my_decimal *d, bool unsigned_flag,
260
 
                   int64_t *l)
261
 
{
262
 
  my_decimal rounded;
263
 
  /* decimal_round can return only E_DEC_TRUNCATED */
264
 
  decimal_round((decimal_t*)d, &rounded, 0, HALF_UP);
265
 
  return check_result(mask, (unsigned_flag ?
266
 
                             decimal2uint64_t(&rounded, (uint64_t *)l) :
267
 
                             decimal2int64_t(&rounded, l)));
268
 
}
269
 
 
270
 
 
271
 
inline
272
 
int my_decimal2double(uint mask __attribute__((unused)), 
273
 
                      const my_decimal *d, double *result)
274
 
{
275
 
  /* No need to call check_result as this will always succeed */
276
 
  return decimal2double((decimal_t*) d, result);
277
 
}
278
 
 
279
 
 
280
 
inline
281
 
int str2my_decimal(uint mask, char *str, my_decimal *d, char **end)
282
 
{
283
 
  return check_result_and_overflow(mask, string2decimal(str,(decimal_t*)d,end),
284
 
                                   d);
285
 
}
286
 
 
287
 
 
288
 
int str2my_decimal(uint mask, const char *from, uint length,
289
 
                   const CHARSET_INFO * charset, my_decimal *decimal_value);
290
 
 
291
 
#if defined(DRIZZLE_SERVER)
292
 
inline
293
 
int string2my_decimal(uint mask, const String *str, my_decimal *d)
294
 
{
295
 
  return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
296
 
}
297
 
 
298
 
 
299
 
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
300
 
 
301
 
 
302
 
#endif /*defined(DRIZZLE_SERVER) */
303
 
 
304
 
inline
305
 
int double2my_decimal(uint mask, double val, my_decimal *d)
306
 
{
307
 
  return check_result_and_overflow(mask, double2decimal(val, (decimal_t*)d), d);
308
 
}
309
 
 
310
 
 
311
 
inline
312
 
int int2my_decimal(uint mask, int64_t i, bool unsigned_flag, my_decimal *d)
313
 
{
314
 
  return check_result(mask, (unsigned_flag ?
315
 
                             uint64_t2decimal((uint64_t)i, d) :
316
 
                             int64_t2decimal(i, d)));
317
 
}
318
 
 
319
 
 
320
 
inline
321
 
void my_decimal_neg(decimal_t *arg)
322
 
{
323
 
  if (decimal_is_zero(arg))
324
 
  {
325
 
    arg->sign= 0;
326
 
    return;
327
 
  }
328
 
  decimal_neg(arg);
329
 
}
330
 
 
331
 
 
332
 
inline
333
 
int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
334
 
                   const my_decimal *b)
335
 
{
336
 
  return check_result_and_overflow(mask,
337
 
                                   decimal_add((decimal_t*)a,(decimal_t*)b,res),
338
 
                                   res);
339
 
}
340
 
 
341
 
 
342
 
inline
343
 
int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
344
 
                   const my_decimal *b)
345
 
{
346
 
  return check_result_and_overflow(mask,
347
 
                                   decimal_sub((decimal_t*)a,(decimal_t*)b,res),
348
 
                                   res);
349
 
}
350
 
 
351
 
 
352
 
inline
353
 
int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
354
 
                   const my_decimal *b)
355
 
{
356
 
  return check_result_and_overflow(mask,
357
 
                                   decimal_mul((decimal_t*)a,(decimal_t*)b,res),
358
 
                                   res);
359
 
}
360
 
 
361
 
 
362
 
inline
363
 
int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
364
 
                   const my_decimal *b, int div_scale_inc)
365
 
{
366
 
  return check_result_and_overflow(mask,
367
 
                                   decimal_div((decimal_t*)a,(decimal_t*)b,res,
368
 
                                               div_scale_inc),
369
 
                                   res);
370
 
}
371
 
 
372
 
 
373
 
inline
374
 
int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
375
 
                   const my_decimal *b)
376
 
{
377
 
  return check_result_and_overflow(mask,
378
 
                                   decimal_mod((decimal_t*)a,(decimal_t*)b,res),
379
 
                                   res);
380
 
}
381
 
 
382
 
 
383
 
/**
384
 
  @return
385
 
    -1 if a<b, 1 if a>b and 0 if a==b
386
 
*/
387
 
inline
388
 
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
389
 
{
390
 
  return decimal_cmp((decimal_t*) a, (decimal_t*) b);
391
 
}
392
 
 
393
 
 
394
 
inline
395
 
int my_decimal_intg(const my_decimal *a)
396
 
{
397
 
  return decimal_intg((decimal_t*) a);
398
 
}
399
 
 
400
 
 
401
 
void my_decimal_trim(uint32_t *precision, uint *scale);
402
 
 
403
 
 
404
 
#endif /*my_decimal_h*/
405