From 9e32991a6d04b51905d48c77d0a886b1ad53f4d2 Mon Sep 17 00:00:00 2001 From: Olaf Barthel Date: Sun, 8 May 2005 08:51:30 +0000 Subject: [PATCH] - For the printf() "%a" conversion the exponent now comes out as a binary number rather than a decimal one. Now how odd is that? - strtod() and strtof() now support "inf"/"infinity"/"nan"/"nan(..)" and hexadecimal floating point numbers, for C99. - Added the fpclassify(), isfinite(), isnormal() and signbit() macros for C99. - Reimplemented isnan() and isinf() as macros for C99. The corresponding functions will be dropped from the library. Note that the isinf() macro does not return -1, 0 or 1 like the old function did, but only 0 or 1 depending upon whether the parameter represents +/- infinity or not. - Added fabsf() for C99. git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@14935 87f5fb63-7c3d-0410-a384-fd976d0f7a62 --- library/GNUmakefile.68k | 10 +- library/GNUmakefile.os4 | 10 +- library/changes | 17 +- library/include/math.h | 49 +++++- library/math_fabsf.c | 142 +++++++++++++++++ library/math_fpclassify.c | 97 ++++++++++++ library/math_isfinite.c | 89 +++++++++++ library/math_logb.c | 9 +- library/math_nan.c | 63 ++++++++ library/math_nanf.c | 62 ++++++++ library/math_signbit.c | 79 ++++++++++ library/smakefile | 10 +- library/stdio_vfprintf.c | 21 +-- library/stdlib_strtod.c | 321 ++++++++++++++++++++++---------------- library/stdlib_strtof.c | 319 +++++++++++++++++++++---------------- 15 files changed, 1007 insertions(+), 291 deletions(-) create mode 100644 library/math_fabsf.c create mode 100644 library/math_fpclassify.c create mode 100644 library/math_isfinite.c create mode 100644 library/math_nan.c create mode 100644 library/math_nanf.c create mode 100644 library/math_signbit.c diff --git a/library/GNUmakefile.68k b/library/GNUmakefile.68k index 237ee71..b1eb9a9 100644 --- a/library/GNUmakefile.68k +++ b/library/GNUmakefile.68k @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.68k,v 1.51 2005-05-07 17:03:55 obarthel Exp $ +# $Id: GNUmakefile.68k,v 1.52 2005-05-08 08:51:29 obarthel Exp $ # # :ts=8 # @@ -523,20 +523,24 @@ MATH_LIB = \ math_cosh.o \ math_exp.o \ math_fabs.o \ + math_fabsf.o \ math_floor.o \ math_fmod.o \ + math_fpclassify.o \ + math_isfinite.o \ + math_signbit.o \ math_frexp.o \ math_huge_val.o \ math_huge_valf.o \ math_hypot.o \ math_init_exit.o \ - math_isinf.o \ - math_isnan.o \ math_ldexp.o \ math_log.o \ math_log10.o \ math_logb.o \ math_modf.o \ + math_nan.o \ + math_nanf.o \ math_pow.o \ math_rint.o \ math_rintf.o \ diff --git a/library/GNUmakefile.os4 b/library/GNUmakefile.os4 index d1329f8..aa7aeec 100644 --- a/library/GNUmakefile.os4 +++ b/library/GNUmakefile.os4 @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.os4,v 1.54 2005-05-07 17:03:55 obarthel Exp $ +# $Id: GNUmakefile.os4,v 1.55 2005-05-08 08:51:29 obarthel Exp $ # # :ts=8 # @@ -523,20 +523,24 @@ MATH_LIB = \ math_cosh.o \ math_exp.o \ math_fabs.o \ + math_fabsf.o \ math_floor.o \ math_fmod.o \ + math_fpclassify.o \ + math_isfinite.o \ + math_signbit.o \ math_frexp.o \ math_huge_val.o \ math_huge_valf.o \ math_hypot.o \ math_init_exit.o \ - math_isnan.o \ - math_isinf.o \ math_ldexp.o \ math_log.o \ math_log10.o \ math_logb.o \ math_modf.o \ + math_nan.o \ + math_nanf.o \ math_pow.o \ math_rint.o \ math_rintf.o \ diff --git a/library/changes b/library/changes index d30c930..5fbf8a1 100644 --- a/library/changes +++ b/library/changes @@ -29,12 +29,27 @@ And it ignores the E and O modifiers. - The printf() family now supports the %hh, %j, %t and %z modifiers and the - %a/%A conversions for C99. The %j is treated like %ll, %t and %z are treated + %a/%A conversions for C99. The %j is treated like %ll; %t and %z are treated like %l. Also, the "infinity"/"not a number" signals now come out as the strings "inf" and "nan". - Added HUGE_VALF to . +- For the printf() "%a" conversion the exponent now comes out as a binary + number rather than a decimal one. Now how odd is that? + +- strtod() and strtof() now support "inf"/"infinity"/"nan"/"nan(..)" and + hexadecimal floating point numbers, for C99. + +- Added the fpclassify(), isfinite(), isnormal() and signbit() macros for C99. + +- Reimplemented isnan() and isinf() as macros for C99. The corresponding + functions will be dropped from the library. Note that the isinf() macro + does not return -1, 0 or 1 like the old function did, but only 0 or 1 + depending upon whether the parameter represents +/- infinity or not. + +- Added fabsf() for C99. + c.lib 1.191 (9.4.2005) diff --git a/library/include/math.h b/library/include/math.h index b81874b..178c76b 100644 --- a/library/include/math.h +++ b/library/include/math.h @@ -1,5 +1,5 @@ /* - * $Id: math.h,v 1.7 2005-05-07 17:04:07 obarthel Exp $ + * $Id: math.h,v 1.8 2005-05-08 08:51:30 obarthel Exp $ * * :ts=4 * @@ -103,8 +103,6 @@ extern double tanh(double x); extern double rint(double x); extern float rintf(float x); -extern int isinf(double x); -extern int isnan(double x); extern double logb(double x); extern double hypot(double x,double y); @@ -123,6 +121,51 @@ extern float __huge_val_float; /****************************************************************************/ +#define FP_INFINITE 0 /* -/+ infinity */ +#define FP_NAN 1 /* not a number */ +#define FP_NORMAL 2 /* normalized floating point number */ +#define FP_SUBNORMAL 3 /* very small floating point number; special + case of IEEE 754 */ +#define FP_ZERO 4 /* exponent/fraction are zero */ + +/****************************************************************************/ + +extern int __fpclassify_float(float x); +extern int __fpclassify_double(double x); +extern int __isfinite_float(float x); +extern int __isfinite_double(double x); +extern int __signbit_float(float x); +extern int __signbit_double(double x); + +#define fpclassify(x) \ + ((sizeof(x) == sizeof(float)) ? __fpclassify_float(x) : __fpclassify_double(x)) + +#define isfinite(x) \ + ((sizeof(x) == sizeof(float)) ? __isfinite_single(x) : __isfinite_double(x)) + +#define isinf(x) \ + (((sizeof(x) == sizeof(float)) ? __fpclassify_float(x) : __fpclassify_double(x)) == FP_INFINITE) + +#define isnan(x) \ + (((sizeof(x) == sizeof(float)) ? __fpclassify_float(x) : __fpclassify_double(x)) == FP_NAN) + +#define isnormal(x) \ + (((sizeof(x) == sizeof(float)) ? __fpclassify_float(x) : __fpclassify_double(x)) == FP_NORMAL) + +#define signbit(x) \ + ((sizeof(x) == sizeof(float)) ? __signbit_single(x) : __signbit_double(x)) + +/****************************************************************************/ + +extern float fabsf(float x); + +/****************************************************************************/ + +extern float nanf(const char *tagp); +extern double nan(const char *tagp); + +/****************************************************************************/ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/library/math_fabsf.c b/library/math_fabsf.c new file mode 100644 index 0000000..5268313 --- /dev/null +++ b/library/math_fabsf.c @@ -0,0 +1,142 @@ +/* + * $Id: math_fabsf.c,v 1.1 2005-05-08 08:51:29 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of 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. + */ + +#ifndef _MATH_HEADERS_H +#include "math_headers.h" +#endif /* _MATH_HEADERS_H */ + +/****************************************************************************/ + +#if defined(FLOATING_POINT_SUPPORT) + +/****************************************************************************/ + +#if defined(IEEE_FLOATING_POINT_SUPPORT) + +/****************************************************************************/ + +#if defined(__GNUC__) + +/****************************************************************************/ + +#if defined(SMALL_DATA) +#define A4(x) "a4@(" #x ":W)" +#elif defined(SMALL_DATA32) +#define A4(x) "a4@(" #x ":L)" +#else +#define A4(x) #x +#endif /* SMALL_DATA */ + +/****************************************************************************/ + +extern float __fabsf(float x); + +/****************************************************************************/ + +asm(" + + .text + .even + + .globl _MathIeeeSingBasBase + .globl ___fabsf + +___fabsf: + + movel a6,sp@- + movel "A4(_MathIeeeSingBasBase)",a6 + moveml sp@(8),d0/d1 + jsr a6@(-54:W) + movel sp@+,a6 + rts + +"); + +/****************************************************************************/ + +#else + +/****************************************************************************/ + +INLINE STATIC const float +__fabsf(float x) +{ + float result; + + result = IEEESPAbs(x); + + return(result); +} + +/****************************************************************************/ + +#endif /* __GNUC__ */ + +/****************************************************************************/ + +#else + +/****************************************************************************/ + +INLINE STATIC const float +__fabsf(float number) +{ + union ieee_single x; + + x.value = number; + + /* Knock off the sign bit. */ + x.raw[0] &= 0x7fffffff; + + return(x.value); +} + +/****************************************************************************/ + +#endif /* IEEE_FLOATING_POINT_SUPPORT */ + +/****************************************************************************/ + +float +fabsf(float x) +{ + float result; + + result = __fabsf(x); + + return(result); +} + +/****************************************************************************/ + +#endif /* FLOATING_POINT_SUPPORT */ diff --git a/library/math_fpclassify.c b/library/math_fpclassify.c new file mode 100644 index 0000000..2b1b06e --- /dev/null +++ b/library/math_fpclassify.c @@ -0,0 +1,97 @@ +/* + * $Id: math_fpclassify.c,v 1.1 2005-05-08 08:51:29 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of 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. + */ + +#ifndef _STDIO_HEADERS_H +#include "stdio_headers.h" +#endif /* _STDIO_HEADERS_H */ + +/****************************************************************************/ + +#if defined (FLOATING_POINT_SUPPORT) + +/****************************************************************************/ + +/* The following is not part of the ISO 'C' (1994) standard, but it should + be part of ISO/IEC 9899:1999, also known as "C99". */ + +/****************************************************************************/ + +int +__fpclassify_float(float number) +{ + union ieee_single x; + int result; + + x.value = number; + + if((x.raw[0] & 0x7f800000) == 0x7f800000 && (x.raw[0] & 0x007fffff) != 0) + result = FP_NAN; /* Exponent = 255 and fraction != 0.0 -> not a number */ + else if ((x.raw[0] & 0x7fffffff) == 0x7f800000) + result = FP_INFINITE; /* Exponent = 255 and fraction = 0.0 -> infinity */ + else if (x.raw[0] == 0) /* ZZZ test against epsilon? */ + result = FP_ZERO; /* Both exponent and fraction are zero -> zero */ + else if ((x.raw[0] & 0x7f800000) == 0) + result = FP_SUBNORMAL; /* Exponent = 0 -> subnormal */ + else + result = FP_NORMAL; + + return(result); +} + +/****************************************************************************/ + +int +__fpclassify_double(double number) +{ + union ieee_double x; + int result; + + x.value = number; + + if(((x.raw[0] & 0x7ff00000) == 0x7ff00000) && ((x.raw[0] & 0x000fffff) != 0 || (x.raw[1] != 0))) + result = FP_NAN; /* Exponent = 2047 and fraction != 0.0 -> not a number */ + else if (((x.raw[0] & 0x7fffffff) == 0x7ff00000) && (x.raw[1] == 0)) + result = FP_INFINITE; /* Exponent = 2047 and fraction = 0.0 -> infinity */ + else if (x.raw[0] == 0 && x.raw[1] == 0) /* ZZZ test against epsilon? */ + result = FP_ZERO; /* Both exponent and fraction are zero -> zero */ + else if ((x.raw[0] & 0x7fff0000) == 0) + result = FP_SUBNORMAL; /* Exponent = 0 -> subnormal */ + else + result = FP_NORMAL; + + return(result); +} + +/****************************************************************************/ + +#endif /* FLOATING_POINT_SUPPORT */ diff --git a/library/math_isfinite.c b/library/math_isfinite.c new file mode 100644 index 0000000..2ace98f --- /dev/null +++ b/library/math_isfinite.c @@ -0,0 +1,89 @@ +/* + * $Id: math_isfinite.c,v 1.1 2005-05-08 08:51:29 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of 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. + */ + +#ifndef _STDIO_HEADERS_H +#include "stdio_headers.h" +#endif /* _STDIO_HEADERS_H */ + +/****************************************************************************/ + +#if defined (FLOATING_POINT_SUPPORT) + +/****************************************************************************/ + +/* The following is not part of the ISO 'C' (1994) standard, but it should + be part of ISO/IEC 9899:1999, also known as "C99". */ + +/****************************************************************************/ + +int +__isfinite_float(float number) +{ + union ieee_single x; + int result; + + x.value = number; + + if((x.raw[0] & 0x7f800000) == 0x7f800000 && (x.raw[0] & 0x007fffff) != 0) + result = 0; /* Exponent = 255 and fraction != 0.0 -> not a number */ + else if ((x.raw[0] & 0x7fffffff) == 0x7f800000) + result = 0; /* Exponent = 255 and fraction = 0.0 -> infinity */ + else + result = 1; + + return(result); +} + +/****************************************************************************/ + +int +__isfinite_double(double number) +{ + union ieee_double x; + int result; + + x.value = number; + + if(((x.raw[0] & 0x7ff00000) == 0x7ff00000) && ((x.raw[0] & 0x000fffff) != 0 || (x.raw[1] != 0))) + result = 0; /* Exponent = 2047 and fraction != 0.0 -> not a number */ + else if (((x.raw[0] & 0x7fffffff) == 0x7ff00000) && (x.raw[1] == 0)) + result = 0; /* Exponent = 2047 and fraction = 0.0 -> infinity */ + else + result = 1; + + return(result); +} + +/****************************************************************************/ + +#endif /* FLOATING_POINT_SUPPORT */ diff --git a/library/math_logb.c b/library/math_logb.c index 3e212a3..23ee8d1 100644 --- a/library/math_logb.c +++ b/library/math_logb.c @@ -1,5 +1,5 @@ /* - * $Id: math_logb.c,v 1.5 2005-02-25 10:14:21 obarthel Exp $ + * $Id: math_logb.c,v 1.6 2005-05-08 08:51:29 obarthel Exp $ * * :ts=4 * @@ -99,8 +99,6 @@ logb(double x) { double result; - int sign; - if(x == 0.0) { result = -__get_huge_val(); @@ -113,10 +111,9 @@ logb(double x) goto out; } - sign = isinf(x); - if(sign != 0) + if(isinf(x)) { - if(sign < 0) + if(x < 0) result = (-x); else result = x; diff --git a/library/math_nan.c b/library/math_nan.c new file mode 100644 index 0000000..5950c66 --- /dev/null +++ b/library/math_nan.c @@ -0,0 +1,63 @@ +/* + * $Id: math_nan.c,v 1.1 2005-05-08 08:51:29 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of 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. + */ + +#ifndef _STDIO_HEADERS_H +#include "stdio_headers.h" +#endif /* _STDIO_HEADERS_H */ + +/****************************************************************************/ + +#if defined (FLOATING_POINT_SUPPORT) + +/****************************************************************************/ + +/* The following is not part of the ISO 'C' (1994) standard, but it should + be part of ISO/IEC 9899:1999, also known as "C99". */ + +/****************************************************************************/ + +double +nan(const char * UNUSED tagp) +{ + union ieee_double x; + + /* Exponent = 2047 and fraction != 0.0 */ + x.raw[0] = 0x7ff00000; + x.raw[1] = 0x00000001; + + return(x.value); +} + +/****************************************************************************/ + +#endif /* FLOATING_POINT_SUPPORT */ diff --git a/library/math_nanf.c b/library/math_nanf.c new file mode 100644 index 0000000..e92b84a --- /dev/null +++ b/library/math_nanf.c @@ -0,0 +1,62 @@ +/* + * $Id: math_nanf.c,v 1.1 2005-05-08 08:51:29 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of 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. + */ + +#ifndef _STDIO_HEADERS_H +#include "stdio_headers.h" +#endif /* _STDIO_HEADERS_H */ + +/****************************************************************************/ + +#if defined (FLOATING_POINT_SUPPORT) + +/****************************************************************************/ + +/* The following is not part of the ISO 'C' (1994) standard, but it should + be part of ISO/IEC 9899:1999, also known as "C99". */ + +/****************************************************************************/ + +float +nanf(const char * UNUSED tagp) +{ + union ieee_single x; + + /* Exponent = 255 and fraction != 0.0 */ + x.raw[0] = 0x7f800001; + + return(x.value); +} + +/****************************************************************************/ + +#endif /* FLOATING_POINT_SUPPORT */ diff --git a/library/math_signbit.c b/library/math_signbit.c new file mode 100644 index 0000000..6b53f03 --- /dev/null +++ b/library/math_signbit.c @@ -0,0 +1,79 @@ +/* + * $Id: math_signbit.c,v 1.1 2005-05-08 08:51:29 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of 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. + */ + +#ifndef _STDIO_HEADERS_H +#include "stdio_headers.h" +#endif /* _STDIO_HEADERS_H */ + +/****************************************************************************/ + +#if defined (FLOATING_POINT_SUPPORT) + +/****************************************************************************/ + +/* The following is not part of the ISO 'C' (1994) standard, but it should + be part of ISO/IEC 9899:1999, also known as "C99". */ + +/****************************************************************************/ + +int +__signbit_float(float number) +{ + union ieee_single x; + int result; + + x.value = number; + + result = ((x.raw[0] = 0x80000000) != 0); + + return(result); +} + +/****************************************************************************/ + +int +__signbit_double(double number) +{ + union ieee_double x; + int result; + + x.value = number; + + result = ((x.raw[0] = 0x80000000) != 0); + + return(result); +} + +/****************************************************************************/ + +#endif /* FLOATING_POINT_SUPPORT */ diff --git a/library/smakefile b/library/smakefile index 73675bc..7150dad 100644 --- a/library/smakefile +++ b/library/smakefile @@ -1,5 +1,5 @@ # -# $Id: smakefile,v 1.39 2005-05-07 17:03:55 obarthel Exp $ +# $Id: smakefile,v 1.40 2005-05-08 08:51:29 obarthel Exp $ # # :ts=8 # @@ -187,20 +187,24 @@ MATH_OBJ = \ math_cosh.o \ math_exp.o \ math_fabs.o \ + math_fabsf.o \ math_floor.o \ math_fmod.o \ + math_fpclassify.o \ + math_isfinite.o \ + math_signbit.o \ math_frexp.o \ math_huge_val.o \ math_huge_valf.o \ math_hypot.o \ math_init_exit.o \ - math_isinf.o \ - math_isnan.o \ math_ldexp.o \ math_log.o \ math_log10.o \ math_logb.o \ math_modf.o \ + math_nan.o \ + math_nanf.o \ math_pow.o \ math_rint.o \ math_rintf.o \ diff --git a/library/stdio_vfprintf.c b/library/stdio_vfprintf.c index a609e53..8e27041 100644 --- a/library/stdio_vfprintf.c +++ b/library/stdio_vfprintf.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_vfprintf.c,v 1.14 2005-05-07 17:03:55 obarthel Exp $ + * $Id: stdio_vfprintf.c,v 1.15 2005-05-08 08:51:29 obarthel Exp $ * * :ts=4 * @@ -703,7 +703,6 @@ vfprintf(FILE * stream,const char * format, va_list arg) const char * digit_encoding; __long_double_t v; int radix; - int sign; if(conversion_type == 'a') { @@ -730,14 +729,14 @@ vfprintf(FILE * stream,const char * format, va_list arg) else v = va_arg(arg, double); - if((sign = isinf(v)) != 0) + if(isinf(v)) { SHOWMSG("infinity"); strcpy(output_buffer,"inf"); output_len = 3; - if(sign < 0) + if(v < 0) SET_FLAG(format_flags,FORMATF_IsNegative); fill_character = ' '; @@ -996,13 +995,15 @@ vfprintf(FILE * stream,const char * format, va_list arg) if(conversion_type == 'e' || conversion_type == 'a') { - /* For 'long double' the exponent is 15 bits in size, which - allows for a minimum of -16384 to be used. Eight digits - for the exponent should be plenty. */ - char exponent_string[8]; + char exponent_string[40]; size_t exponent_string_len,j; int exponent_sign; + /* For the '%a' conversion the exponent is given in + binary notation rather than decimal. */ + if(conversion_type == 'a') + radix = 2; + /* Build the exponent string in reverse order. */ exponent_string_len = 0; @@ -1019,9 +1020,9 @@ vfprintf(FILE * stream,const char * format, va_list arg) while(exponent > 0 && exponent_string_len < sizeof(exponent_string)) { - exponent_string[exponent_string_len++] = '0' + (exponent % 10); + exponent_string[exponent_string_len++] = '0' + (exponent % radix); - exponent /= 10; + exponent /= radix; } /* Minimum length of the exponent is two digits. */ diff --git a/library/stdlib_strtod.c b/library/stdlib_strtod.c index 5d7a017..2c5b4ce 100644 --- a/library/stdlib_strtod.c +++ b/library/stdlib_strtod.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtod.c,v 1.4 2005-02-27 21:58:21 obarthel Exp $ + * $Id: stdlib_strtod.c,v 1.5 2005-05-08 08:51:29 obarthel Exp $ * * :ts=4 * @@ -67,11 +67,8 @@ double strtod(const char *str, char ** ptr) { double sum = 0.0; - double new_sum; double result; - int decimal_point_matches; int is_negative; - int error = 0; char c; ENTER(); @@ -118,187 +115,250 @@ strtod(const char *str, char ** ptr) is_negative = 0; /* But there may be a sign we will choose to - * ignore. - */ + ignore. */ if((*str) == '+') str++; } - /* We begin by trying to convert all the digits - * preceding the decimal point. - */ - while((c = (*str)) != '\0') + /* We begin by checking for the "inf" and "nan" strings. */ + if(strcasecmp(str,"inf") == SAME || strcasecmp(str,"infinity") == SAME) { - if('0' <= c && c <= '9') + union ieee_double * x = (union ieee_double *)∑ + + str += strlen(str); + + /* Exponent = 2047 and fraction = 0.0 */ + x->raw[0] = 0x7ff00000; + x->raw[1] = 0x00000000; + } + else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0')) + { + union ieee_double * x = (union ieee_double *)∑ + + str += 3; + + /* Does NaN data follow the header? If so, skip it. */ + if((*str) == '(') { + while((*str) != '\0' && (*str) != ')') + str++; + + if((*str) == ')') + str++; + } + + /* Exponent = 2047 and fraction != 0.0 */ + x->raw[0] = 0x7ff00000; + x->raw[1] = 0x00000001; + } + else + { + int decimal_point_matches; + double new_sum; + int error = 0; + int radix; + + /* Check for the hex prefix. */ + if(strncasecmp(str,"0x",2) == SAME) + { + str += 2; + + radix = 16; + } + else + { + radix = 10; + } + + /* Convert all the digits preceding the decimal point. */ + while((c = (*str)) != '\0') + { + if ('0' <= c && c <= '9') + c = c - '0'; + else if ('a' <= c && c <= 'f') + c = c - 'a' + 10; + else if ('A' <= c && c <= 'F') + c = c - 'A' + 10; + else + c = radix; + + if(c >= radix) + break; + str++; if(error == 0) { - new_sum = (10 * sum) + (c - '0'); + new_sum = (radix * sum) + c; if(new_sum < sum) /* overflow? */ error = ERANGE; else sum = new_sum; } } - else + + /* Did we find the decimal point? We accept both the + locale configured decimal point and the plain old + dot. */ + decimal_point_matches = 0; + + __locale_lock(); + + if(__locale_table[LC_NUMERIC] != NULL) { - break; - } - } + char * point; - /* Did we find the decimal point? We accept both the - * locale configured decimal point and the plain old - * dot. - */ - decimal_point_matches = 0; - - __locale_lock(); - - if(__locale_table[LC_NUMERIC] != NULL) - { - char * point; - - point = (char *)__locale_table[LC_NUMERIC]->loc_DecimalPoint; - if((*point) == (*str)) - { - decimal_point_matches = 1; - - /* Skip the decimal point. */ - str++; - } - } - - __locale_unlock(); - - if(NOT decimal_point_matches) - { - if((*str) == '.') - { - decimal_point_matches = 1; - - /* Skip the decimal point. */ - str++; - } - } - - if(decimal_point_matches) - { - double divisor = 0.1; - - /* Process all digits following the decimal point. */ - while((c = (*str)) != '\0') - { - if('0' <= c && c <= '9') + point = (char *)__locale_table[LC_NUMERIC]->loc_DecimalPoint; + if((*point) == (*str)) { + decimal_point_matches = 1; + + /* Skip the decimal point. */ + str++; + } + } + + __locale_unlock(); + + if(NOT decimal_point_matches) + { + if((*str) == '.') + { + decimal_point_matches = 1; + + /* Skip the decimal point. */ + str++; + } + } + + if(decimal_point_matches) + { + double divisor = 1.0 / radix; + + /* Process all digits following the decimal point. */ + while((c = (*str)) != '\0') + { + if ('0' <= c && c <= '9') + c = c - '0'; + else if ('a' <= c && c <= 'f') + c = c - 'a' + 10; + else if ('A' <= c && c <= 'F') + c = c - 'A' + 10; + else + c = radix; + + if(c >= radix) + break; + str++; if(error == 0 && divisor != 0.0) { - new_sum = sum + (c - '0') * divisor; + new_sum = sum + c * divisor; if(new_sum < sum) /* overflow? */ error = ERANGE; else sum = new_sum; - divisor = divisor / 10.0; + divisor = divisor / radix; } } + } + + /* If there is a scale indicator attached, process it. */ + if((radix == 10 && ((*str) == 'e' || (*str) == 'E')) || + (radix == 16 && ((*str) == 'p' || (*str) == 'P'))) + { + int exponent_is_negative; + int new_exponent; + int exponent = 0; + + /* If we are processing a hexadecimal encoded + floating point number, switch to a binary + exponent. */ + if(radix == 16) + radix = 2; + + /* Skip the indicator. */ + str++; + + /* Take care of the exponent's sign. */ + if((*str) == '-') + { + exponent_is_negative = 1; + str++; + } else { - break; + exponent_is_negative = 0; + + if((*str) == '+') + str++; } - } - } - /* If there is a scale indicator attached, process it. */ - if((*str) == 'e' || (*str) == 'E') - { - int exponent_is_negative; - int new_exponent; - int exponent = 0; - - /* Skip the indicator. */ - str++; - - /* Take care of the exponent's sign. */ - if((*str) == '-') - { - exponent_is_negative = 1; - str++; - } - else - { - exponent_is_negative = 0; - - if((*str) == '+') - str++; - } - - /* Again, process all digits to follow. */ - while((c = (*str)) != '\0') - { - if('0' <= c && c <= '9') + /* Again, process all digits to follow. */ + while((c = (*str)) != '\0') { + if('0' <= c && c <= '9') + c -= '0'; + else + c = radix; + + if(c >= radix) + break; + str++; if(error == 0) { - new_exponent = (10 * exponent) + (c - '0'); + new_exponent = (radix * exponent) + c; if(new_exponent < exponent) /* overflow? */ error = ERANGE; else exponent = new_exponent; } } - else - { - break; - } - } - /* If the exponent is valid, scale the number - * accordingly. - */ - if(exponent != 0) - { - if(exponent_is_negative) + /* If the exponent is valid, scale the number accordingly. */ + if(exponent != 0) { - double divisor; - - /* A negative exponent means division. */ - divisor = pow(10.0,(double)exponent); - if(divisor != 0.0) + if(exponent_is_negative) { - new_sum = sum / divisor; - if(new_sum == 0.0 && sum != 0.0) + double divisor; + + /* A negative exponent means division. */ + divisor = pow(radix,(double)exponent); + if(divisor != 0.0) + { + new_sum = sum / divisor; + if(new_sum == 0.0 && sum != 0.0) + error = ERANGE; + else + sum = new_sum; + } + else + { + error = ERANGE; + } + } + else + { + /* A positive exponent means multiplication. */ + new_sum = sum * pow(radix,(double)exponent); + if(new_sum < sum) error = ERANGE; else sum = new_sum; } - else - { - error = ERANGE; - } - } - else - { - /* A positive exponent means multiplication. */ - new_sum = sum * pow(10.0,(double)exponent); - if(new_sum < sum) - error = ERANGE; - else - sum = new_sum; } } - } - if(error != 0) - { - __set_errno(error); + if(error != 0) + { + __set_errno(error); - sum = __get_huge_val(); + sum = __get_huge_val(); + } } if(is_negative) @@ -307,8 +367,7 @@ strtod(const char *str, char ** ptr) result = sum; /* If desired, remember where we stopped reading the - * number from the buffer. - */ + number from the buffer. */ if(ptr != NULL) (*ptr) = (char *)str; diff --git a/library/stdlib_strtof.c b/library/stdlib_strtof.c index 12f7488..68457de 100644 --- a/library/stdlib_strtof.c +++ b/library/stdlib_strtof.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtof.c,v 1.2 2005-05-07 17:03:55 obarthel Exp $ + * $Id: stdlib_strtof.c,v 1.3 2005-05-08 08:51:29 obarthel Exp $ * * :ts=4 * @@ -67,11 +67,8 @@ float strtof(const char *str, char ** ptr) { float sum = 0.0; - float new_sum; float result; - int decimal_point_matches; int is_negative; - int error = 0; char c; ENTER(); @@ -118,187 +115,248 @@ strtof(const char *str, char ** ptr) is_negative = 0; /* But there may be a sign we will choose to - * ignore. - */ + ignore. */ if((*str) == '+') str++; } - /* We begin by trying to convert all the digits - * preceding the decimal point. - */ - while((c = (*str)) != '\0') + /* We begin by checking for the "inf" and "nan" strings. */ + if(strcasecmp(str,"inf") == SAME || strcasecmp(str,"infinity") == SAME) { - if('0' <= c && c <= '9') + union ieee_single * x = (union ieee_single *)∑ + + str += strlen(str); + + /* Exponent = 255 and fraction = 0.0 */ + x->raw[0] = 0x7f800000; + } + else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0')) + { + union ieee_single * x = (union ieee_single *)∑ + + str += 3; + + /* Does NaN data follow the header? If so, skip it. */ + if((*str) == '(') { + while((*str) != '\0' && (*str) != ')') + str++; + + if((*str) == ')') + str++; + } + + /* Exponent = 255 and fraction != 0.0 */ + x->raw[0] = 0x7f800001; + } + else + { + int decimal_point_matches; + float new_sum; + int error = 0; + int radix; + + /* Check for the hex prefix. */ + if(strncasecmp(str,"0x",2) == SAME) + { + str += 2; + + radix = 16; + } + else + { + radix = 10; + } + + /* Convert all the digits preceding the decimal point. */ + while((c = (*str)) != '\0') + { + if ('0' <= c && c <= '9') + c = c - '0'; + else if ('a' <= c && c <= 'f') + c = c - 'a' + 10; + else if ('A' <= c && c <= 'F') + c = c - 'A' + 10; + else + c = radix; + + if(c >= radix) + break; + str++; if(error == 0) { - new_sum = (10 * sum) + (c - '0'); + new_sum = (radix * sum) + c; if(new_sum < sum) /* overflow? */ error = ERANGE; else sum = new_sum; } } - else + + /* Did we find the decimal point? We accept both the + locale configured decimal point and the plain old + dot. */ + decimal_point_matches = 0; + + __locale_lock(); + + if(__locale_table[LC_NUMERIC] != NULL) { - break; - } - } + char * point; - /* Did we find the decimal point? We accept both the - * locale configured decimal point and the plain old - * dot. - */ - decimal_point_matches = 0; - - __locale_lock(); - - if(__locale_table[LC_NUMERIC] != NULL) - { - char * point; - - point = (char *)__locale_table[LC_NUMERIC]->loc_DecimalPoint; - if((*point) == (*str)) - { - decimal_point_matches = 1; - - /* Skip the decimal point. */ - str++; - } - } - - __locale_unlock(); - - if(NOT decimal_point_matches) - { - if((*str) == '.') - { - decimal_point_matches = 1; - - /* Skip the decimal point. */ - str++; - } - } - - if(decimal_point_matches) - { - float divisor = 0.1; - - /* Process all digits following the decimal point. */ - while((c = (*str)) != '\0') - { - if('0' <= c && c <= '9') + point = (char *)__locale_table[LC_NUMERIC]->loc_DecimalPoint; + if((*point) == (*str)) { + decimal_point_matches = 1; + + /* Skip the decimal point. */ + str++; + } + } + + __locale_unlock(); + + if(NOT decimal_point_matches) + { + if((*str) == '.') + { + decimal_point_matches = 1; + + /* Skip the decimal point. */ + str++; + } + } + + if(decimal_point_matches) + { + float divisor = 1.0 / radix; + + /* Process all digits following the decimal point. */ + while((c = (*str)) != '\0') + { + if ('0' <= c && c <= '9') + c = c - '0'; + else if ('a' <= c && c <= 'f') + c = c - 'a' + 10; + else if ('A' <= c && c <= 'F') + c = c - 'A' + 10; + else + c = radix; + + if(c >= radix) + break; + str++; if(error == 0 && divisor != 0.0) { - new_sum = sum + (c - '0') * divisor; + new_sum = sum + c * divisor; if(new_sum < sum) /* overflow? */ error = ERANGE; else sum = new_sum; - divisor = divisor / 10.0; + divisor = divisor / radix; } } + } + + /* If there is a scale indicator attached, process it. */ + if((radix == 10 && ((*str) == 'e' || (*str) == 'E')) || + (radix == 16 && ((*str) == 'p' || (*str) == 'P'))) + { + int exponent_is_negative; + int new_exponent; + int exponent = 0; + + /* If we are processing a hexadecimal encoded + floating point number, switch to a binary + exponent. */ + if(radix == 16) + radix = 2; + + /* Skip the indicator. */ + str++; + + /* Take care of the exponent's sign. */ + if((*str) == '-') + { + exponent_is_negative = 1; + str++; + } else { - break; + exponent_is_negative = 0; + + if((*str) == '+') + str++; } - } - } - /* If there is a scale indicator attached, process it. */ - if((*str) == 'e' || (*str) == 'E') - { - int exponent_is_negative; - int new_exponent; - int exponent = 0; - - /* Skip the indicator. */ - str++; - - /* Take care of the exponent's sign. */ - if((*str) == '-') - { - exponent_is_negative = 1; - str++; - } - else - { - exponent_is_negative = 0; - - if((*str) == '+') - str++; - } - - /* Again, process all digits to follow. */ - while((c = (*str)) != '\0') - { - if('0' <= c && c <= '9') + /* Again, process all digits to follow. */ + while((c = (*str)) != '\0') { + if('0' <= c && c <= '9') + c -= '0'; + else + c = radix; + + if(c >= radix) + break; + str++; if(error == 0) { - new_exponent = (10 * exponent) + (c - '0'); + new_exponent = (radix * exponent) + c; if(new_exponent < exponent) /* overflow? */ error = ERANGE; else exponent = new_exponent; } } - else - { - break; - } - } - /* If the exponent is valid, scale the number - * accordingly. - */ - if(exponent != 0) - { - if(exponent_is_negative) + /* If the exponent is valid, scale the number accordingly. */ + if(exponent != 0) { - float divisor; - - /* A negative exponent means division. */ - divisor = pow(10.0,(float)exponent); - if(divisor != 0.0) + if(exponent_is_negative) { - new_sum = sum / divisor; - if(new_sum == 0.0 && sum != 0.0) + float divisor; + + /* A negative exponent means division. */ + divisor = pow(radix,(float)exponent); + if(divisor != 0.0) + { + new_sum = sum / divisor; + if(new_sum == 0.0 && sum != 0.0) + error = ERANGE; + else + sum = new_sum; + } + else + { + error = ERANGE; + } + } + else + { + /* A positive exponent means multiplication. */ + new_sum = sum * pow(radix,(float)exponent); + if(new_sum < sum) error = ERANGE; else sum = new_sum; } - else - { - error = ERANGE; - } - } - else - { - /* A positive exponent means multiplication. */ - new_sum = sum * pow(10.0,(float)exponent); - if(new_sum < sum) - error = ERANGE; - else - sum = new_sum; } } - } - if(error != 0) - { - __set_errno(error); + if(error != 0) + { + __set_errno(error); - sum = __get_huge_valf(); + sum = __get_huge_valf(); + } } if(is_negative) @@ -307,8 +365,7 @@ strtof(const char *str, char ** ptr) result = sum; /* If desired, remember where we stopped reading the - * number from the buffer. - */ + number from the buffer. */ if(ptr != NULL) (*ptr) = (char *)str;