From: Sebastien Bourdeauducq Date: Fri, 25 May 2012 21:26:17 +0000 (+0200) Subject: software/libbase: strtod X-Git-Tag: 24jan2021_ls180~3159 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a481db612a13e9b31c350a65620de59cf64dc419;p=litex.git software/libbase: strtod --- diff --git a/software/libbase/Makefile b/software/libbase/Makefile index ddb3f5cf..cf07ad2f 100644 --- a/software/libbase/Makefile +++ b/software/libbase/Makefile @@ -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 index 19075c9d..00000000 --- a/software/libbase/atof.c +++ /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 -#include - -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 index 00000000..e79a1eeb --- /dev/null +++ b/software/libbase/strtod.c @@ -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 +#include +#include + +/**************************************************************************** + * 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; +} +