~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/my_decimal.h

MergingĀ mainline

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
5
 
 *
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.
9
 
 *
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.
14
 
 *
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
18
 
 */
 
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 */
19
15
 
20
16
/**
21
17
  @file
22
18
 
23
19
  It is interface module to fixed precision decimals library.
24
20
 
25
 
  Most functions use 'uint32_t mask' as parameter, if during operation error
 
21
  Most functions use 'uint mask' as parameter, if during operation error
26
22
  which fit in this mask is detected then it will be processed automatically
27
23
  here. (errors are E_DEC_* constants, see include/decimal.h)
28
24
 
32
28
#ifndef my_decimal_h
33
29
#define my_decimal_h
34
30
 
35
 
#ifdef __cplusplus
36
 
extern "C" {
37
 
#endif
38
 
 
39
 
#include <mystrings/decimal.h>
40
 
 
41
 
#ifdef __cplusplus
42
 
}
43
 
#endif
44
 
 
 
31
C_MODE_START
 
32
#include <decimal.h>
 
33
C_MODE_END
45
34
 
46
35
#define DECIMAL_LONGLONG_DIGITS 22
47
36
#define DECIMAL_LONG_DIGITS 10
48
37
#define DECIMAL_LONG3_DIGITS 8
49
38
 
50
 
/** maximum length of buffer in our big digits (uint32_t). */
 
39
/** maximum length of buffer in our big digits (uint32). */
51
40
#define DECIMAL_BUFF_LENGTH 9
52
41
 
53
42
/* the number of digits that my_decimal can possibly contain */
76
65
#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
77
66
 
78
67
 
79
 
inline uint32_t my_decimal_size(uint32_t precision, uint32_t scale)
 
68
inline uint my_decimal_size(uint precision, uint scale)
80
69
{
81
70
  /*
82
71
    Always allocate more space to allow library to put decimal point
86
75
}
87
76
 
88
77
 
89
 
inline int my_decimal_int_part(uint32_t precision, uint32_t decimals)
 
78
inline int my_decimal_int_part(uint precision, uint decimals)
90
79
{
91
80
  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
92
81
}
112
101
    buf= buffer;
113
102
#if !defined (HAVE_purify) 
114
103
    /* Set buffer to 'random' value to find wrong buffer usage */
115
 
    for (uint32_t i= 0; i < DECIMAL_BUFF_LENGTH; i++)
 
104
    for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
116
105
      buffer[i]= i;
117
106
#endif
118
107
  }
124
113
 
125
114
  bool sign() const { return decimal_t::sign; }
126
115
  void sign(bool s) { decimal_t::sign= s; }
127
 
  uint32_t precision() const { return intg + frac; }
 
116
  uint precision() const { return intg + frac; }
128
117
};
129
118
 
 
119
 
 
120
void print_decimal(const my_decimal *dec);
 
121
void print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length);
 
122
const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
 
123
 
 
124
#ifndef MYSQL_CLIENT
130
125
int decimal_operation_results(int result);
 
126
#else
 
127
inline int decimal_operation_results(int result)
 
128
{
 
129
  return result;
 
130
}
 
131
#endif /*MYSQL_CLIENT*/
131
132
 
132
133
inline
133
134
void max_my_decimal(my_decimal *to, int precision, int frac)
142
143
  max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
143
144
}
144
145
 
145
 
inline int check_result(uint32_t mask, int result)
 
146
inline int check_result(uint mask, int result)
146
147
{
147
148
  if (result & mask)
148
149
    decimal_operation_results(result);
149
150
  return result;
150
151
}
151
152
 
152
 
inline int check_result_and_overflow(uint32_t mask, int result, my_decimal *val)
 
153
inline int check_result_and_overflow(uint mask, int result, my_decimal *val)
153
154
{
154
155
  if (check_result(mask, result) & E_DEC_OVERFLOW)
155
156
  {
161
162
  return result;
162
163
}
163
164
 
164
 
inline uint32_t my_decimal_length_to_precision(uint32_t length, uint32_t scale,
 
165
inline uint my_decimal_length_to_precision(uint length, uint scale,
165
166
                                           bool unsigned_flag)
166
167
{
167
168
  return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
168
169
}
169
170
 
170
 
inline uint32_t my_decimal_precision_to_length(uint32_t precision, uint8_t scale,
 
171
inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
171
172
                                             bool unsigned_flag)
172
173
{
173
174
  set_if_smaller(precision, DECIMAL_MAX_PRECISION);
174
 
  return (uint32_t)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
 
175
  return (uint32)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
175
176
}
176
177
 
177
178
inline
190
191
 
191
192
 
192
193
inline
193
 
int my_decimal_get_binary_size(uint32_t precision, uint32_t scale)
 
194
int my_decimal_get_binary_size(uint precision, uint scale)
194
195
{
195
196
  return decimal_bin_size((int)precision, (int)scale);
196
197
}
204
205
}
205
206
 
206
207
 
207
 
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
 
208
int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec,
208
209
                      int scale);
209
210
 
210
211
 
211
212
inline
212
 
int binary2my_decimal(uint32_t mask, const unsigned char *bin, my_decimal *d, int prec,
 
213
int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec,
213
214
                      int scale)
214
215
{
215
216
  return check_result(mask, bin2decimal(bin, (decimal_t*) d, prec, scale));
232
233
 
233
234
 
234
235
inline
235
 
int my_decimal_round(uint32_t mask, const my_decimal *from, int scale,
 
236
int my_decimal_round(uint mask, const my_decimal *from, int scale,
236
237
                     bool truncate, my_decimal *to)
237
238
{
238
239
  return check_result(mask, decimal_round((decimal_t*) from, to, scale,
241
242
 
242
243
 
243
244
inline
244
 
int my_decimal_floor(uint32_t mask, const my_decimal *from, my_decimal *to)
 
245
int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
245
246
{
246
247
  return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR));
247
248
}
248
249
 
249
250
 
250
251
inline
251
 
int my_decimal_ceiling(uint32_t mask, const my_decimal *from, my_decimal *to)
 
252
int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
252
253
{
253
254
  return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING));
254
255
}
255
256
 
256
257
 
257
 
int my_decimal2string(uint32_t mask, const my_decimal *d, uint32_t fixed_prec,
258
 
                      uint32_t fixed_dec, char filler, String *str);
 
258
#ifndef MYSQL_CLIENT
 
259
int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
 
260
                      uint fixed_dec, char filler, String *str);
 
261
#endif
259
262
 
260
263
inline
261
 
int my_decimal2int(uint32_t mask, const my_decimal *d, bool unsigned_flag,
262
 
                   int64_t *l)
 
264
int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
 
265
                   longlong *l)
263
266
{
264
267
  my_decimal rounded;
265
268
  /* decimal_round can return only E_DEC_TRUNCATED */
266
269
  decimal_round((decimal_t*)d, &rounded, 0, HALF_UP);
267
270
  return check_result(mask, (unsigned_flag ?
268
 
                             decimal2uint64_t(&rounded, (uint64_t *)l) :
269
 
                             decimal2int64_t(&rounded, l)));
 
271
                             decimal2ulonglong(&rounded, (ulonglong *)l) :
 
272
                             decimal2longlong(&rounded, l)));
270
273
}
271
274
 
272
275
 
273
276
inline
274
 
int my_decimal2double(uint32_t mask __attribute__((unused)), 
 
277
int my_decimal2double(uint mask __attribute__((__unused__)), 
275
278
                      const my_decimal *d, double *result)
276
279
{
277
280
  /* No need to call check_result as this will always succeed */
280
283
 
281
284
 
282
285
inline
283
 
int str2my_decimal(uint32_t mask, char *str, my_decimal *d, char **end)
 
286
int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end)
284
287
{
285
288
  return check_result_and_overflow(mask, string2decimal(str,(decimal_t*)d,end),
286
289
                                   d);
287
290
}
288
291
 
289
292
 
290
 
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
291
 
                   const CHARSET_INFO * charset, my_decimal *decimal_value);
 
293
int str2my_decimal(uint mask, const char *from, uint length,
 
294
                   CHARSET_INFO *charset, my_decimal *decimal_value);
292
295
 
293
 
#if defined(DRIZZLE_SERVER)
 
296
#if defined(MYSQL_SERVER)
294
297
inline
295
 
int string2my_decimal(uint32_t mask, const String *str, my_decimal *d)
 
298
int string2my_decimal(uint mask, const String *str, my_decimal *d)
296
299
{
297
300
  return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
298
301
}
299
302
 
300
303
 
301
 
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec);
302
 
 
303
 
 
304
 
#endif /*defined(DRIZZLE_SERVER) */
 
304
my_decimal *date2my_decimal(MYSQL_TIME *ltime, my_decimal *dec);
 
305
 
 
306
 
 
307
#endif /*defined(MYSQL_SERVER) */
305
308
 
306
309
inline
307
 
int double2my_decimal(uint32_t mask, double val, my_decimal *d)
 
310
int double2my_decimal(uint mask, double val, my_decimal *d)
308
311
{
309
312
  return check_result_and_overflow(mask, double2decimal(val, (decimal_t*)d), d);
310
313
}
311
314
 
312
315
 
313
316
inline
314
 
int int2my_decimal(uint32_t mask, int64_t i, bool unsigned_flag, my_decimal *d)
 
317
int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d)
315
318
{
316
319
  return check_result(mask, (unsigned_flag ?
317
 
                             uint64_t2decimal((uint64_t)i, d) :
318
 
                             int64_t2decimal(i, d)));
 
320
                             ulonglong2decimal((ulonglong)i, d) :
 
321
                             longlong2decimal(i, d)));
319
322
}
320
323
 
321
324
 
332
335
 
333
336
 
334
337
inline
335
 
int my_decimal_add(uint32_t mask, my_decimal *res, const my_decimal *a,
 
338
int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
336
339
                   const my_decimal *b)
337
340
{
338
341
  return check_result_and_overflow(mask,
342
345
 
343
346
 
344
347
inline
345
 
int my_decimal_sub(uint32_t mask, my_decimal *res, const my_decimal *a,
 
348
int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
346
349
                   const my_decimal *b)
347
350
{
348
351
  return check_result_and_overflow(mask,
352
355
 
353
356
 
354
357
inline
355
 
int my_decimal_mul(uint32_t mask, my_decimal *res, const my_decimal *a,
 
358
int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
356
359
                   const my_decimal *b)
357
360
{
358
361
  return check_result_and_overflow(mask,
362
365
 
363
366
 
364
367
inline
365
 
int my_decimal_div(uint32_t mask, my_decimal *res, const my_decimal *a,
 
368
int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
366
369
                   const my_decimal *b, int div_scale_inc)
367
370
{
368
371
  return check_result_and_overflow(mask,
373
376
 
374
377
 
375
378
inline
376
 
int my_decimal_mod(uint32_t mask, my_decimal *res, const my_decimal *a,
 
379
int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
377
380
                   const my_decimal *b)
378
381
{
379
382
  return check_result_and_overflow(mask,
400
403
}
401
404
 
402
405
 
403
 
void my_decimal_trim(uint32_t *precision, uint32_t *scale);
 
406
void my_decimal_trim(ulong *precision, uint *scale);
404
407
 
405
408
 
406
409
#endif /*my_decimal_h*/