software/libbase: strtod
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 25 May 2012 21:26:17 +0000 (23:26 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 25 May 2012 21:26:17 +0000 (23:26 +0200)
software/libbase/Makefile
software/libbase/atof.c [deleted file]
software/libbase/strtod.c [new file with mode: 0644]

index ddb3f5cffb63effb7e7bada1e49af62d2f3f5767..cf07ad2fc5f99fac2117b2de7793b63928ce5e35 100644 (file)
@@ -1,7 +1,7 @@
 M2DIR=../..
 include $(M2DIR)/software/common.mak
 
-OBJECTS=divsi3.o setjmp.o libc.o crc16.o crc32.o console.o timer.o system.o board.o uart.o softfloat.o softfloat-glue.o vsnprintf.o atof.o
+OBJECTS=divsi3.o setjmp.o libc.o crc16.o crc32.o console.o timer.o system.o board.o uart.o softfloat.o softfloat-glue.o vsnprintf.o strtod.o
 
 all: libbase.a
 
diff --git a/software/libbase/atof.c b/software/libbase/atof.c
deleted file mode 100644 (file)
index 19075c9..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*  atof.c: converts an ASCII string to float
-
-    Copyright (C) 2003  Jesus Calvino-Fraga, jesusc@ieee.org
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
-
-#include <stdlib.h>
-#include <ctype.h>
-
-float atof(const char * s)
-{
-       float value, fraction;
-       char iexp;
-       char sign;
-
-       //Skip leading blanks
-       while (isspace(*s)) s++;
-
-       //Get the sign
-       if (*s == '-')
-       {
-               sign=1;
-               s++;
-       }
-       else
-       {
-               sign=0;
-               if (*s == '+') s++;
-       }
-
-       //Get the integer part
-       for (value=0.0f; isdigit(*s); s++)
-       {
-               value=10.0f*value+(*s-'0');
-       }
-
-       //Get the fraction
-       if (*s == '.')
-       {
-               s++;
-               for (fraction=0.1f; isdigit(*s); s++)
-               {
-                       value+=(*s-'0')*fraction;
-                       fraction*=0.1f;
-               }
-       }
-
-       //Finally, the exponent (not very efficient, but enough for now)
-       if (toupper(*s)=='E')
-       {
-               s++;
-               iexp=(char)atoi(s);
-               {
-                       while(iexp!=0)
-                       {
-                               if(iexp<0)
-                               {
-                                       value*=0.1f;
-                                       iexp++;
-                               }
-                               else
-                               {
-                                       value*=10.0f;
-                                       iexp--;
-                               }
-                       }
-               }
-       }
-
-       if(sign) value*=-1.0f;
-       return (value);
-}
diff --git a/software/libbase/strtod.c b/software/libbase/strtod.c
new file mode 100644 (file)
index 0000000..e79a1ee
--- /dev/null
@@ -0,0 +1,234 @@
+/****************************************************************************
+ * lib/string/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 infinite = 1.0/0.0;
+  return (x < infinite) && (x >= -infinite);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/***************************************************(************************
+ * Name: strtod
+ *
+ * Description:
+ *   Convert a string to a double value
+ *
+ ****************************************************************************/
+
+double strtod(const char *str, char **endptr)
+{
+  double number;
+  int exponent;
+  int negative;
+  char *p = (char *) str;
+  double p10;
+  int n;
+  int num_digits;
+  int num_decimals;
+  const double 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;
+}
+