| 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 | |