diff options
author | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2009-12-22 19:23:13 +0300 |
---|---|---|
committer | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2009-12-22 19:23:13 +0300 |
commit | f02525be8346b7426f1640fb168a7451d38b1641 (patch) | |
tree | 40437c602d2a9ddaa03a54742cec4884f0974253 /include | |
parent | 5bce1e06429c3d58457051f0c439f130609df375 (diff) | |
download | mariadb-git-f02525be8346b7426f1640fb168a7451d38b1641.tar.gz |
Backport of WL #2934: Make/find library for doing float/double
to string conversions and vice versa"
Initial import of the dtoa.c code and custom wrappers around it
to allow its usage from the server code.
Conversion of FLOAT/DOUBLE values to DECIMAL ones or strings
and vice versa has been significantly reworked. As the new
algoritms are more precise than the older ones, results of such
conversions may not always match those obtained from older
server versions. This in turn may break compatibility for some
applications.
This patch also fixes the following bugs:
- bug #12860 "Difference in zero padding of exponent between
Unix and Windows"
- bug #21497 "DOUBLE truncated to unusable value"
- bug #26788 "mysqld (debug) aborts when inserting specific
numbers into char fields"
- bug #24541 "Data truncated..." on decimal type columns
without any good reason"
Diffstat (limited to 'include')
-rw-r--r-- | include/m_string.h | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/include/m_string.h b/include/m_string.h index a6a36f32ca4..45801ff85b7 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -92,9 +92,6 @@ extern char *stpcpy(char *, const char *); /* For AIX with gcc 2.95.3 */ extern char NEAR _dig_vec_upper[]; extern char NEAR _dig_vec_lower[]; -/* Defined in strtod.c */ -extern const double log_10[309]; - #ifdef BAD_STRING_COMPILER #define strmov(A,B) (memccpy(A,B,0,INT_MAX)-1) #else @@ -199,8 +196,42 @@ extern char *strstr(const char *, const char *); extern int is_prefix(const char *, const char *); /* Conversion routines */ +typedef enum { + MY_GCVT_ARG_FLOAT, + MY_GCVT_ARG_DOUBLE +} my_gcvt_arg_type; + double my_strtod(const char *str, char **end, int *error); double my_atof(const char *nptr); +size_t my_fcvt(double x, int precision, char *to, my_bool *error); +size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to, + my_bool *error); + +#define NOT_FIXED_DEC 31 + +/* + The longest string my_fcvt can return is 311 + "precision" bytes. + Here we assume that we never cal my_fcvt() with precision >= NOT_FIXED_DEC + (+ 1 byte for the terminating '\0'). +*/ +#define FLOATING_POINT_BUFFER (311 + NOT_FIXED_DEC) + +/* + We want to use the 'e' format in some cases even if we have enough space + for the 'f' one just to mimic sprintf("%.15g") behavior for large integers, + and to improve it for numbers < 10^(-4). + That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require + it to be integer and be <= 10^DBL_DIG for the 'f' format to be used. + We don't lose precision, but make cases like "1e200" or "0.00001" look nicer. +*/ +#define MAX_DECPT_FOR_F_FORMAT DBL_DIG + +/* + The maximum possible field width for my_gcvt() conversion. + (DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or + MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used). +*/ +#define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + max(5, MAX_DECPT_FOR_F_FORMAT)) \ extern char *llstr(longlong value,char *buff); extern char *ullstr(longlong value,char *buff); |