summaryrefslogtreecommitdiff
path: root/strings/strtod.c
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2004-02-13 15:27:21 +0100
committerunknown <serg@serg.mylan>2004-02-13 15:27:21 +0100
commit1515c12191bcb50c49512475a72c04a47c963a07 (patch)
treee72eb3285c6d77bd43ee040603595ce715626551 /strings/strtod.c
parentc5bc73e9a7d2f4ed2c7602fc6a028e227c08b9f4 (diff)
downloadmariadb-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.c140
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));
+}
+