summaryrefslogtreecommitdiff
path: root/nuttx/lib/lib_strtod.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-03-14 15:10:16 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2010-03-14 15:10:16 +0000
commit322c1c68cb1ccd33f4a24a662bc5189fc581d7b9 (patch)
treebfade4c353f0dd68580fa16aad25b09df64f2ef9 /nuttx/lib/lib_strtod.c
parentb62bf38e67060b929bbf443977339f244ef1438c (diff)
downloadpx4-nuttx-322c1c68cb1ccd33f4a24a662bc5189fc581d7b9.tar.gz
px4-nuttx-322c1c68cb1ccd33f4a24a662bc5189fc581d7b9.tar.bz2
px4-nuttx-322c1c68cb1ccd33f4a24a662bc5189fc581d7b9.zip
Add strtod
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2541 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/lib/lib_strtod.c')
-rwxr-xr-xnuttx/lib/lib_strtod.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/nuttx/lib/lib_strtod.c b/nuttx/lib/lib_strtod.c
new file mode 100755
index 000000000..777eb6ded
--- /dev/null
+++ b/nuttx/lib/lib_strtod.c
@@ -0,0 +1,228 @@
+/****************************************************************************
+ * lib/lib_strtod.c
+ *
+ * Convert string to double
+ *
+ * Copyright (C) 2002 Michael Ringgaard. All rights reserved.
+ * Copyright (C) 2006-2007 H. Peter Anvin.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+/* These are predefined with GCC, but could be issues for other compilers. If
+ * not defined, an arbitrary big number is put in for now. These should be
+ * added to nuttx/compiler for your compiler.
+ */
+
+#if !defined(__DBL_MIN_EXP__) || !defined(__DBL_MAX_EXP__)
+# ifdef CONFIG_CPP_HAVE_WARNING
+# warning "Size of exponent is unknown"
+# endif
+# undef __DBL_MIN_EXP__
+# define __DBL_MIN_EXP__ (-1021)
+# undef __DBL_MAX_EXP__
+# define __DBL_MAX_EXP__ (1024)
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline int is_real(double x)
+{
+ const double_t infinite = 1.0/0.0;
+ return (x < infinite) && (x >= -infinite);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/***************************************************(************************
+ * Name: strtod
+ *
+ * Description:
+ * Convert a string to a double value
+ *
+ ****************************************************************************/
+
+double_t strtod(const char *str, char **endptr)
+{
+ double_t number;
+ int exponent;
+ int negative;
+ char *p = (char *) str;
+ double p10;
+ int n;
+ int num_digits;
+ int num_decimals;
+ const double_t infinite = 1.0/0.0;
+
+ /* Skip leading whitespace */
+
+ while (isspace(*p))
+ {
+ p++;
+ }
+
+ /* Handle optional sign */
+
+ negative = 0;
+ switch (*p)
+ {
+ case '-':
+ negative = 1; /* Fall through to increment position */
+ case '+':
+ p++;
+ }
+
+ number = 0.;
+ exponent = 0;
+ num_digits = 0;
+ num_decimals = 0;
+
+ /* Process string of digits */
+
+ while (isdigit(*p))
+ {
+ number = number * 10. + (*p - '0');
+ p++;
+ num_digits++;
+ }
+
+ /* Process decimal part */
+
+ if (*p == '.')
+ {
+ p++;
+
+ while (isdigit(*p))
+ {
+ number = number * 10. + (*p - '0');
+ p++;
+ num_digits++;
+ num_decimals++;
+ }
+
+ exponent -= num_decimals;
+ }
+
+ if (num_digits == 0)
+ {
+ errno = ERANGE;
+ return 0.0;
+ }
+
+ /* Correct for sign */
+
+ if (negative)
+ {
+ number = -number;
+ }
+
+ /* Process an exponent string */
+
+ if (*p == 'e' || *p == 'E')
+ {
+ /* Handle optional sign */
+
+ negative = 0;
+ switch(*++p)
+ {
+ case '-':
+ negative = 1; /* Fall through to increment pos */
+ case '+':
+ p++;
+ }
+
+ /* Process string of digits */
+
+ n = 0;
+ while (isdigit(*p))
+ {
+ n = n * 10 + (*p - '0');
+ p++;
+ }
+
+ if (negative)
+ {
+ exponent -= n;
+ }
+ else
+ {
+ exponent += n;
+ }
+ }
+
+ if (exponent < __DBL_MIN_EXP__ ||
+ exponent > __DBL_MAX_EXP__)
+ {
+ errno = ERANGE;
+ return infinite;
+ }
+
+ /* Scale the result */
+
+ p10 = 10.;
+ n = exponent;
+ if (n < 0) n = -n;
+ while (n)
+ {
+ if (n & 1)
+ {
+ if (exponent < 0)
+ {
+ number /= p10;
+ }
+ else
+ {
+ number *= p10;
+ }
+ }
+ n >>= 1;
+ p10 *= p10;
+ }
+
+ if (!is_real(number)) errno = ERANGE;
+ if (endptr) *endptr = p;
+
+ return number;
+}
+