1 | /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. |
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 | #ifndef _decimal_h |
17 | #define _decimal_h |
18 | |
19 | #ifdef __cplusplus |
20 | extern "C" { |
21 | #endif |
22 | |
23 | typedef enum |
24 | {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} |
25 | decimal_round_mode; |
26 | typedef int32 decimal_digit_t; |
27 | |
28 | /** |
29 | intg is the number of *decimal* digits (NOT number of decimal_digit_t's !) |
30 | before the point |
31 | frac is the number of decimal digits after the point |
32 | len is the length of buf (length of allocated space) in decimal_digit_t's, |
33 | not in bytes |
34 | sign false means positive, true means negative |
35 | buf is an array of decimal_digit_t's |
36 | */ |
37 | typedef struct st_decimal_t { |
38 | int intg, frac, len; |
39 | my_bool sign; |
40 | decimal_digit_t *buf; |
41 | } decimal_t; |
42 | |
43 | int internal_str2dec(const char *from, decimal_t *to, char **end, |
44 | my_bool fixed); |
45 | int decimal2string(const decimal_t *from, char *to, int *to_len, |
46 | int fixed_precision, int fixed_decimals, |
47 | char filler); |
48 | int decimal2ulonglong(const decimal_t *from, ulonglong *to); |
49 | int ulonglong2decimal(ulonglong from, decimal_t *to); |
50 | int decimal2longlong(const decimal_t *from, longlong *to); |
51 | int longlong2decimal(longlong from, decimal_t *to); |
52 | int decimal2double(const decimal_t *from, double *to); |
53 | int double2decimal(double from, decimal_t *to); |
54 | int decimal_actual_fraction(const decimal_t *from); |
55 | int decimal2bin(const decimal_t *from, uchar *to, int precision, int scale); |
56 | int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale); |
57 | |
58 | int decimal_size(int precision, int scale); |
59 | int decimal_bin_size(int precision, int scale); |
60 | int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, |
61 | int param); |
62 | |
63 | int decimal_intg(const decimal_t *from); |
64 | int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to); |
65 | int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to); |
66 | int decimal_cmp(const decimal_t *from1, const decimal_t *from2); |
67 | int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to); |
68 | int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, |
69 | int scale_incr); |
70 | int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to); |
71 | int decimal_round(const decimal_t *from, decimal_t *to, int new_scale, |
72 | decimal_round_mode mode); |
73 | int decimal_is_zero(const decimal_t *from); |
74 | void max_decimal(int precision, int frac, decimal_t *to); |
75 | |
76 | #define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0) |
77 | #define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1) |
78 | |
79 | /* set a decimal_t to zero */ |
80 | |
81 | #define decimal_make_zero(dec) do { \ |
82 | (dec)->buf[0]=0; \ |
83 | (dec)->intg=1; \ |
84 | (dec)->frac=0; \ |
85 | (dec)->sign=0; \ |
86 | } while(0) |
87 | |
88 | /* |
89 | returns the length of the buffer to hold string representation |
90 | of the decimal (including decimal dot, possible sign and \0) |
91 | */ |
92 | |
93 | #define decimal_string_size(dec) (((dec)->intg ? (dec)->intg : 1) + \ |
94 | (dec)->frac + ((dec)->frac > 0) + 2) |
95 | |
96 | /* negate a decimal */ |
97 | #define decimal_neg(dec) do { (dec)->sign^=1; } while(0) |
98 | |
99 | /* |
100 | conventions: |
101 | |
102 | decimal_smth() == 0 -- everything's ok |
103 | decimal_smth() <= 1 -- result is usable, but precision loss is possible |
104 | decimal_smth() <= 2 -- result can be unusable, most significant digits |
105 | could've been lost |
106 | decimal_smth() > 2 -- no result was generated |
107 | */ |
108 | |
109 | #define E_DEC_OK 0 |
110 | #define E_DEC_TRUNCATED 1 |
111 | #define E_DEC_OVERFLOW 2 |
112 | #define E_DEC_DIV_ZERO 4 |
113 | #define E_DEC_BAD_NUM 8 |
114 | #define E_DEC_OOM 16 |
115 | |
116 | #define E_DEC_ERROR 31 |
117 | #define E_DEC_FATAL_ERROR 30 |
118 | |
119 | #ifdef __cplusplus |
120 | } |
121 | #endif |
122 | |
123 | #endif |
124 | |
125 | |