diff options
author | unknown <serg@serg.mylan> | 2004-02-13 15:27:21 +0100 |
---|---|---|
committer | unknown <serg@serg.mylan> | 2004-02-13 15:27:21 +0100 |
commit | 1515c12191bcb50c49512475a72c04a47c963a07 (patch) | |
tree | e72eb3285c6d77bd43ee040603595ce715626551 /strings/strtod.c | |
parent | c5bc73e9a7d2f4ed2c7602fc6a028e227c08b9f4 (diff) | |
download | mariadb-git-1515c12191bcb50c49512475a72c04a47c963a07.tar.gz |
my_atof is deleted
strtod from mit-threads is restored and cleaned up
BitKeeper/deleted/.del-atof.c~d3edf47a9884080:
Delete: strings/atof.c
configure.in:
atod() is no longer used in MySQL
isinf() now is
include/m_string.h:
my_strtod, my_atof
include/my_global.h:
my_atof is deleted
define isinf()
libmysql/Makefile.shared:
use internal strtod
sql/gstream.cc:
use internal strtod
sql/init.cc:
my_atof is deleted
sql/item.h:
use internal strtod
sql/item_func.cc:
use internal strtod
sql/item_sum.h:
use internal strtod
sql/sql_analyse.cc:
use internal strtod
strings/Makefile.am:
use internal strtod
strings/ctype-simple.c:
use internal strtod
strings/ctype-ucs2.c:
use internal strtod
strings/strtod.c:
cleanup
stricter input checks (e.g. ".E10" is no longer a number)
don't return an "inf"
Diffstat (limited to 'strings/strtod.c')
-rw-r--r-- | strings/strtod.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/strings/strtod.c b/strings/strtod.c new file mode 100644 index 00000000000..ea6acbac6c4 --- /dev/null +++ b/strings/strtod.c @@ -0,0 +1,140 @@ +/* + An alternative implementation of "strtod()" that is both + simplier, and thread-safe. + + From mit-threads as bundled with MySQL 3.22 + + SQL:2003 specifies a number as + +<signed numeric literal> ::= [ <sign> ] <unsigned numeric literal> + +<unsigned numeric literal> ::= + <exact numeric literal> + | <approximate numeric literal> + +<exact numeric literal> ::= + <unsigned integer> [ <period> [ <unsigned integer> ] ] + | <period> <unsigned integer> + +<approximate numeric literal> ::= <mantissa> E <exponent> + +<mantissa> ::= <exact numeric literal> + +<exponent> ::= <signed integer> + + So do we. + + */ + +#include "my_base.h" +#include "m_ctype.h" + +static double scaler10[] = { + 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 +}; +static double scaler1[] = { + 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 +}; + +// let's use a static array for not to accumulate the error +static double pastpoint[] = { + 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, + 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19, + 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29, + 1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38, 1e-39, + 1e-40, 1e-41, 1e-42, 1e-43, 1e-44, 1e-45, 1e-46, 1e-47, 1e-48, 1e-49, + 1e-50, 1e-51, 1e-52, 1e-53, 1e-54, 1e-55, 1e-56, 1e-57, 1e-58, 1e-59, +}; + +double my_strtod(const char *str, char **end) +{ + double result= 0.0; + int negative, ndigits; + const char *old_str; + + while (my_isspace(&my_charset_latin1, *str)) + str++; + + if ((negative= (*str == '-')) || *str=='+') + str++; + + old_str= str; + while (my_isdigit (&my_charset_latin1, *str)) + { + result= result*10.0 + (*str - '0'); + str++; + } + ndigits= str-old_str; + + if (*str == '.') + { + int n= 0; + str++; + old_str= str; + while (my_isdigit (&my_charset_latin1, *str)) + { + if (n < sizeof(pastpoint)/sizeof(pastpoint[0])) + { + result+= pastpoint[n] * (*str - '0'); + n++; + } + str++; + } + ndigits+= str-old_str; + if (!ndigits) str--; + } + if (ndigits && (*str=='e' || *str=='E')) + { + int exp= 0; + int neg= 0; + const char *old_str= str++; + + if ((neg= (*str == '-')) || *str == '+') + str++; + + if (!my_isdigit (&my_charset_latin1, *str)) + str= old_str; + else + { + double scaler= 1.0; + while (my_isdigit (&my_charset_latin1, *str)) + { + exp= exp*10 + *str - '0'; + str++; + } + if (exp >= 1000) + { + if (neg) + result= 0.0; + else + result= DBL_MAX; + goto done; + } + while (exp >= 100) + { + scaler*= 1.0e100; + exp-= 100; + } + scaler*= scaler10[exp/10]*scaler1[exp%10]; + if (neg) + result/= scaler; + else + result*= scaler; + } + } + +done: + if (end) + *end = (char *)str; + + if (isinf(result)) + result=DBL_MAX; + + return negative ? -result : result; +} + +double my_atof(const char *nptr) +{ + return (strtod(nptr, 0)); +} + |