This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: long double (was "strtold?")
On Tuesday 10 March 2009 20:57:53 Howland Craig D (Craig) wrote:
> I've been wondering about the general long double issue recently
> because I was doing some preliminary work on adding some long double
> functions to the math library. (I hadn't stumbled across ldtoa.c, yet,
> so
> it's interesting to learn of its existence.)
> A question that I have had is, do long double functions need to
> have a configure check for long double for conditional inclusion?
> (I had gotten as far as finding out that configure has a built in check
> for it and that AC_TYPE_LONG_DOUBLE can be used to generate a define for
> HAVE_LONG_DOUBLE. There's also AC_TYPE_LONG_DOUBLE_WIDER to generate
> HAVE_LONG_DOUBLE_WIDER so that we could know not to bother with
> separate routines from double. I hadn't gotten far enough along to ask
> the mailing list. But since you've brought up the general topic, this
> seems like a good time to ask.)
Hi,
What about mapping the long double functions to their counterparts on
platforms where a double is as wide as a long double? The attached patch
introduces a flag defined in sys/features.h. You mentioned
HAVE_LONG_DOUBLE_WIDER but the user may not define this flag. Do you want to
generate a header file that exposes this flag? Wouldn't that result in something
like config.h to be shipped with newlib or am I missing something?
Thanks
Ken
newlib/ChangeLog:
2009-03-11 Ken Werner <ken.werner@de.ibm.com>
* include/sys/features.h: Define _DOUBLE_EQUALS_LONG_DOUBL for SPU.
* libc/include/stdlib.h: Include sys/features.h.
* libc/include/stdlib.h (strtold): Declare.
* libc/include/math.h: Include sys/features.h and machine/math.h.
(atanl, cosl, sinl, tanl, tanhl, frexpl, modfl, ceill, fabsl, floorl,
log1pl, expm1l, acosl, asinl, atan2l, coshl, sinhl, expl, ldexpl,
logl, log10l, powl, sqrtl, fmodl, hypotl, copysignl, nanl, ilogbl,
asinhl, cbrt, nextafterl, rintl, scalbnl, exp2l, scalblnl, tgammal,
nearbyintl, lrintl, llrintl, roundl, lroundl, truncl, remquol, fdiml,
fmaxl, fminl, fmal, acoshl, atanhl, remainderl, lgammal, erfl, erfcl):
Declare.
Remove duplicate copysign prototype.
Fix __math_68881 define typo.
* libc/include/machine/math.h (llround, llroundl): Declare.
Index: src/newlib/libc/include/machine/math.h
===================================================================
--- /dev/null
+++ src/newlib/libc/include/machine/math.h
@@ -0,0 +1,20 @@
+#ifndef _MACHMATH_H_
+#define _MACHMATH_H_
+
+#include <_ansi.h>
+
+_BEGIN_STD_C
+
+/* This header allows platforms to add math.h extensions. */
+
+#ifdef __SPU__
+/* The llround prototype is missing in math.h because the common code provides
+ no implementation. Since there is SPU code for that we decare it here. */
+extern _LONG_LONG_TYPE int llround _PARAMS((double));
+extern _LONG_LONG_TYPE int llroundl _PARAMS((long double)) asm ("llround");
+#endif /* __SPU__ */
+
+_END_STD_C
+
+#endif /* _MACHMATH_H_ */
+
Index: src/newlib/libc/include/math.h
===================================================================
--- src.orig/newlib/libc/include/math.h
+++ src/newlib/libc/include/math.h
@@ -5,6 +5,8 @@
#include <sys/reent.h>
#include <machine/ieeefp.h>
#include "_ansi.h"
+#include <sys/features.h>
+#include <machine/math.h>
_BEGIN_STD_C
@@ -97,7 +99,7 @@ extern double floor _PARAMS((double));
/* Non reentrant ANSI C functions. */
#ifndef _REENT_ONLY
-#ifndef __math_6881
+#ifndef __math_68881
extern double acos _PARAMS((double));
extern double asin _PARAMS((double));
extern double atan2 _PARAMS((double, double));
@@ -231,7 +233,6 @@ extern double round _PARAMS((double));
extern long int lround _PARAMS((double));
extern double trunc _PARAMS((double));
extern double remquo _PARAMS((double, double, int *));
-extern double copysign _PARAMS((double, double));
extern double fdim _PARAMS((double, double));
extern double fmax _PARAMS((double, double));
extern double fmin _PARAMS((double, double));
@@ -332,10 +333,82 @@ extern float erfcf _PARAMS((float));
extern float hypotf _PARAMS((float, float));
#endif /* ! defined (_REENT_ONLY) */
+/* On platforms where a long double is as wide as a double. */
+#ifdef _DOUBLE_EQUALS_LONG_DOUBLE
+/* Reentrant ANSI C functions. */
+#ifndef __math_68881
+extern long double atanl _PARAMS((long double)) asm ("atan");
+extern long double cosl _PARAMS((long double)) asm ("cos");
+extern long double sinl _PARAMS((long double)) asm ("sin");
+extern long double tanl _PARAMS((long double)) asm ("tan");
+extern long double tanhl _PARAMS((long double)) asm ("tanh");
+extern long double frexpl _PARAMS((long double value, int *)) asm ("frexp");
+extern long double modfl _PARAMS((long double, long double *)) asm ("modf");
+extern long double ceill _PARAMS((long double)) asm ("ceil");
+extern long double fabsl _PARAMS((long double)) asm ("fabs");
+extern long double floorl _PARAMS((long double)) asm ("floor");
+extern long double log1pl _PARAMS((long double)) asm ("log1p");
+extern long double expm1l _PARAMS((long double)) asm ("expm1");
+#endif /* ! defined (__math_68881) */
+/* Non reentrant ANSI C functions. */
+#ifndef _REENT_ONLY
+#ifndef __math_68881
+extern long double acosl _PARAMS((long double)) asm ("acos");
+extern long double asinl _PARAMS((long double)) asm ("asin");
+extern long double atan2l _PARAMS((long double, long double)) asm ("atan2");
+extern long double coshl _PARAMS((long double)) asm ("cosh");
+extern long double sinhl _PARAMS((long double)) asm ("sinh");
+extern long double expl _PARAMS((long double)) asm ("exp");
+extern long double ldexpl _PARAMS((long double, int)) asm ("ldexp");
+extern long double logl _PARAMS((long double)) asm ("log");
+extern long double log10l _PARAMS((long double)) asm ("log10");
+extern long double powl _PARAMS((long double, long double)) asm ("pow");
+extern long double sqrtl _PARAMS((long double)) asm ("sqrt");
+extern long double fmodl _PARAMS((long double, long double)) asm ("fmod");
+extern long double hypotl _PARAMS((long double, long double)) asm ("hypot");
+#endif /* ! defined (__math_68881) */
+#endif /* ! defined (_REENT_ONLY) */
+extern long double copysignl _PARAMS((long double, long double))
+ asm ("copysign");
+extern long double nanl _PARAMS((const char *)) asm ("nan");
+extern int ilogbl _PARAMS((long double)) asm ("ilogb");
+extern long double asinhl _PARAMS((long double)) asm ("asinh");
+extern long double cbrtl _PARAMS((long double)) asm ("cbrt");
+extern long double nextafterl _PARAMS((long double, long double))
+ asm ("nextafter");
+extern long double rintl _PARAMS((long double)) asm ("rint");
+extern long double scalbnl _PARAMS((long double, int)) asm ("scalbn");
+extern long double exp2l _PARAMS((long double)) asm ("exp2");
+extern long double scalblnl _PARAMS((long double, long)) asm ("scalbln");
+extern long double tgammal _PARAMS((long double)) asm ("tgamma");
+extern long double nearbyintl _PARAMS((long double)) asm ("nearbyint");
+extern long int lrintl _PARAMS((long double)) asm ("lrint");
+extern _LONG_LONG_TYPE int llrintl _PARAMS((long double)) asm ("llrint");
+extern long double roundl _PARAMS((long double)) asm ("round");
+extern long lroundl _PARAMS((long double)) asm ("lround");
+extern long double truncl _PARAMS((long double)) asm ("trunc");
+extern long double remquol _PARAMS((long double, long double, int *))
+ asm ("remquo");
+extern long double fdiml _PARAMS((long double, long double)) asm ("fdim");
+extern long double fmaxl _PARAMS((long double, long double)) asm ("fmax");
+extern long double fminl _PARAMS((long double, long double)) asm ("fmin");
+extern long double fmal _PARAMS((long double, long double, long double))
+ asm ("fma");
+#ifndef _REENT_ONLY
+extern long double acoshl _PARAMS((long double)) asm ("acosh");
+extern long double atanhl _PARAMS((long double)) asm ("atanh");
+extern long double remainderl _PARAMS((long double, long double))
+ asm ("remainder");
+extern long double lgammal _PARAMS((long double)) asm ("lgamma");
+extern long double erfl _PARAMS((long double)) asm ("erf");
+extern long double erfcl _PARAMS((long double)) asm ("erfc");
+#endif /* ! defined (_REENT_ONLY) */
+#else /* _DOUBLE_EQUALS_LONG_DOUBLE */
/* Other long double precision functions. */
extern _LONG_DOUBLE rintl _PARAMS((_LONG_DOUBLE));
extern long int lrintl _PARAMS((_LONG_DOUBLE));
extern _LONG_LONG_TYPE llrintl _PARAMS((_LONG_DOUBLE));
+#endif /* _DOUBLE_EQUALS_LONG_DOUBLE */
#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L */
Index: src/newlib/libc/include/stdlib.h
===================================================================
--- src.orig/newlib/libc/include/stdlib.h
+++ src/newlib/libc/include/stdlib.h
@@ -12,7 +12,7 @@
#define __need_size_t
#define __need_wchar_t
#include <stddef.h>
-
+#include <sys/features.h>
#include <sys/reent.h>
#include <machine/stdlib.h>
#ifndef __STRICT_ANSI__
@@ -192,6 +192,11 @@ int _EXFUN(_system_r,(struct _reent *, c
_VOID _EXFUN(__eprintf,(const char *, const char *, unsigned int, const char *));
+#ifdef _DOUBLE_EQUALS_LONG_DOUBLE
+/* On platforms where a long double is as wide as a double. */
+extern long double strtold (const char *, char **) asm ("strtod");
+#endif
+
_END_STD_C
#endif /* _STDLIB_H_ */
Index: src/newlib/libc/include/sys/features.h
===================================================================
--- src.orig/newlib/libc/include/sys/features.h
+++ src/newlib/libc/include/sys/features.h
@@ -172,6 +172,8 @@ extern "C" {
#ifdef __SPU__
/* Not much for now! */
#define _POSIX_TIMERS 1
+/* On the SPU the size of long double equals the size of double. */
+#define _DOUBLE_EQUALS_LONG_DOUBLE 1
#endif
#ifdef __cplusplus