From b9e7cd9a846cf584049a719bbd0e4cabe3c50bea Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 6 Feb 2015 16:14:04 +0000 Subject: [PATCH] * libc/include/complex.h (cabsl): Add prototype. (cimagl): Add prototype. (creall): Add prototype. * libc/include/ieeefp.h: Include float.h. (EXT_EXPBITS, EXT_FRACHBITS, EXT_FRACLBITS) (EXT_EXP_INFNAN. EXT_EXP_BIAS, EXT_FRACBITS): Define. (struct ieee_ext, union ieee_ext_u): New types for long double support. * libc/include/math.h (finitel): Add prototype. (hypotl): Add prototype. (sqrtl): Add prototype. * libm/common/Makefile.am (lsrc): Add sl_finite.c. * libm/common/Makefile.in: Regenerate. * libm/common/fdlibm.h (__ieee754_hypotl): Add prototype. * libm/common/hypotl.c (hypotl): Add implementation for when long double is larger than double. * libm/common/sqrtl.c (sqrtl): Likewise. * libm/common/sl_finite.c: New file. Adds implementation of the finitel function. * libm/complex/Makefile.am (lsrc): Define. (libcomplex_la_SOURCES): Add lsrc. (lib_a_SOURCES): Add lsrc. * libm/complex/Makefile.in: Regenerate. * libm/complex/cabs.c: Add documentation of cabsl function. * libm/complex/cimag.c: Add documentation of cimagl function. * libm/complex/creall.c: Add documentation of creall function. * libm/complex/cabsl.c: New file. Adds implementation of the cabsl function. * libm/complex/cimagl.c: New file. Adds implementation of the cimagl function. * libm/complex/creall.c: New file. Adds implementation of the creall function. * libm/math/Makefile.am (lsrc): Define. (libmath_la_SOURCES): Add lsrc. (lib_a_SOURCES): Add lsrc. * libm/math/Makefile.in: Regenerate. * libm/math/el_hypot.c: New file. Adds implementation of the __ieee754_hypotl function. --- newlib/ChangeLog | 41 ++++++++ newlib/libc/include/complex.h | 5 +- newlib/libc/include/ieeefp.h | 73 +++++++++++-- newlib/libc/include/math.h | 6 ++ newlib/libc/include/string.h | 5 +- newlib/libc/machine/msp430/setjmp.S | 2 + newlib/libm/common/Makefile.am | 4 +- newlib/libm/common/Makefile.in | 13 ++- newlib/libm/common/fdlibm.h | 2 + newlib/libm/common/hypotl.c | 59 +++++++++-- newlib/libm/common/sl_finite.c | 25 +++++ newlib/libm/common/sqrtl.c | 155 +++++++++++++++++++++++++++- newlib/libm/complex/Makefile.am | 7 +- newlib/libm/complex/Makefile.in | 36 ++++++- newlib/libm/complex/cabs.c | 16 ++- newlib/libm/complex/cabsl.c | 18 ++++ newlib/libm/complex/cimag.c | 16 ++- newlib/libm/complex/cimagl.c | 16 +++ newlib/libm/complex/creal.c | 18 ++-- newlib/libm/complex/creall.c | 16 +++ newlib/libm/math/Makefile.am | 6 +- newlib/libm/math/Makefile.in | 20 +++- newlib/libm/math/el_hypot.c | 18 ++++ 23 files changed, 525 insertions(+), 52 deletions(-) create mode 100644 newlib/libm/common/sl_finite.c create mode 100644 newlib/libm/complex/cabsl.c create mode 100644 newlib/libm/complex/cimagl.c create mode 100644 newlib/libm/complex/creall.c create mode 100644 newlib/libm/math/el_hypot.c diff --git a/newlib/ChangeLog b/newlib/ChangeLog index eaf5ae8f3..c7a2f1b78 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,44 @@ +2015-02-06 Nick Clifton + + * libc/include/complex.h (cabsl): Add prototype. + (cimagl): Add prototype. + (creall): Add prototype. + * libc/include/ieeefp.h: Include float.h. + (EXT_EXPBITS, EXT_FRACHBITS, EXT_FRACLBITS) + (EXT_EXP_INFNAN. EXT_EXP_BIAS, EXT_FRACBITS): Define. + (struct ieee_ext, union ieee_ext_u): New types for long double + support. + * libc/include/math.h (finitel): Add prototype. + (hypotl): Add prototype. + (sqrtl): Add prototype. + * libm/common/Makefile.am (lsrc): Add sl_finite.c. + * libm/common/Makefile.in: Regenerate. + * libm/common/fdlibm.h (__ieee754_hypotl): Add prototype. + * libm/common/hypotl.c (hypotl): Add implementation for when long + double is larger than double. + * libm/common/sqrtl.c (sqrtl): Likewise. + * libm/common/sl_finite.c: New file. Adds implementation of the + finitel function. + * libm/complex/Makefile.am (lsrc): Define. + (libcomplex_la_SOURCES): Add lsrc. + (lib_a_SOURCES): Add lsrc. + * libm/complex/Makefile.in: Regenerate. + * libm/complex/cabs.c: Add documentation of cabsl function. + * libm/complex/cimag.c: Add documentation of cimagl function. + * libm/complex/creall.c: Add documentation of creall function. + * libm/complex/cabsl.c: New file. Adds implementation of the + cabsl function. + * libm/complex/cimagl.c: New file. Adds implementation of the + cimagl function. + * libm/complex/creall.c: New file. Adds implementation of the + creall function. + * libm/math/Makefile.am (lsrc): Define. + (libmath_la_SOURCES): Add lsrc. + (lib_a_SOURCES): Add lsrc. + * libm/math/Makefile.in: Regenerate. + * libm/math/el_hypot.c: New file. Adds implementation of the + __ieee754_hypotl function. + 2015-02-04 Corinna Vinschen * libc/include/wchar.h (wcstold): Drop _LDBL_EQ_DBL requirement for diff --git a/newlib/libc/include/complex.h b/newlib/libc/include/complex.h index 969b20e5f..c3ae3cff8 100644 --- a/newlib/libc/include/complex.h +++ b/newlib/libc/include/complex.h @@ -83,6 +83,7 @@ float complex clogf(float complex); float cabsf(float complex) __RENAME(__c99_cabsf); #endif */ +long double cabsl(long double complex) ; double cabs(double complex) ; float cabsf(float complex) ; @@ -102,7 +103,7 @@ float cargf(float complex); /* 7.3.9.2 The cimag functions */ double cimag(double complex); float cimagf(float complex); -/*long double cimagl(long double complex); */ +long double cimagl(long double complex); /* 7.3.9.3 The conj functions */ double complex conj(double complex); @@ -117,7 +118,7 @@ float complex cprojf(float complex); /* 7.3.9.5 The creal functions */ double creal(double complex); float crealf(float complex); -/*long double creall(long double complex); */ +long double creall(long double complex); __END_DECLS diff --git a/newlib/libc/include/ieeefp.h b/newlib/libc/include/ieeefp.h index 0b06fb786..9eb274d86 100644 --- a/newlib/libc/include/ieeefp.h +++ b/newlib/libc/include/ieeefp.h @@ -4,11 +4,12 @@ #include "_ansi.h" #include +#include _BEGIN_STD_C /* FIXME FIXME FIXME: - Neither of __ieee_{float,double}_shape_tape seem to be used anywhere + Neither of __ieee_{float,double}_shape_type seem to be used anywhere except in libm/test. If that is the case, please delete these from here. If that is not the case, please insert documentation here describing why they're needed. */ @@ -46,9 +47,7 @@ typedef union long aslong[2]; } __ieee_double_shape_type; -#endif - -#ifdef __IEEE_LITTLE_ENDIAN +#elif defined __IEEE_LITTLE_ENDIAN typedef union { @@ -92,7 +91,7 @@ typedef union } __ieee_double_shape_type; -#endif +#endif /* __IEEE_LITTLE_ENDIAN */ #ifdef __IEEE_BIG_ENDIAN @@ -118,9 +117,7 @@ typedef union } __ieee_float_shape_type; -#endif - -#ifdef __IEEE_LITTLE_ENDIAN +#elif defined __IEEE_LITTLE_ENDIAN typedef union { @@ -144,10 +141,70 @@ typedef union } __ieee_float_shape_type; +#endif /* __IEEE_LITTLE_ENDIAN */ + +#ifndef _LDBL_EQ_DBL + +#ifndef LDBL_MANT_DIG +#error "LDBL_MANT_DIG not defined - should be found in float.h" + +#elif LDBL_MANT_DIG == DBL_MANT_DIG +#error "double and long double are the same size but LDBL_EQ_DBL is not defined" + +#elif LDBL_MANT_DIG == 53 +/* This happens when doubles are 32-bits and long doubles are 64-bits. */ +#define EXT_EXPBITS 11 +#define EXT_FRACHBITS 20 +#define EXT_FRACLBITS 32 +#define __ieee_ext_field_type unsigned long + +#elif LDBL_MANT_DIG == 64 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define __ieee_ext_field_type unsigned int + +#elif LDBL_MANT_DIG == 65 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define __ieee_ext_field_type unsigned int + +#elif LDBL_MANT_DIG == 112 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 48 +#define EXT_FRACLBITS 64 +#define __ieee_ext_field_type unsigned long long + +#elif LDBL_MANT_DIG == 113 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 48 +#define EXT_FRACLBITS 64 +#define __ieee_ext_field_type unsigned long long + +#else +#error Unsupported value for LDBL_MANT_DIG #endif +#define EXT_EXP_INFNAN ((1 << EXT_EXPBITS) - 1) /* 32767 */ +#define EXT_EXP_BIAS ((1 << (EXT_EXPBITS - 1)) - 1) /* 16383 */ +#define EXT_FRACBITS (EXT_FRACLBITS + EXT_FRACHBITS) +typedef struct ieee_ext +{ + __ieee_ext_field_type ext_fracl : EXT_FRACLBITS; + __ieee_ext_field_type ext_frach : EXT_FRACHBITS; + __ieee_ext_field_type ext_exp : EXT_EXPBITS; + __ieee_ext_field_type ext_sign : 1; +} ieee_ext; +typedef union ieee_ext_u +{ + long double extu_ld; + struct ieee_ext extu_ext; +} ieee_ext_u; + +#endif /* ! _LDBL_EQ_DBL */ /* FLOATING ROUNDING */ diff --git a/newlib/libc/include/math.h b/newlib/libc/include/math.h index d16ce3074..3f6766ab8 100644 --- a/newlib/libc/include/math.h +++ b/newlib/libc/include/math.h @@ -254,6 +254,10 @@ extern int __signbitd (double x); (__extension__ ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \ fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;})) +/* Non ANSI long double precision functions. */ + +extern int finitel _PARAMS((long double)); + /* Non ANSI double precision functions. */ extern double infinity _PARAMS((void)); @@ -454,6 +458,8 @@ extern long double erfl _PARAMS((long double)); extern long double erfcl _PARAMS((long double)); #endif /* ! defined (_REENT_ONLY) */ #else /* !_LDBL_EQ_DBL */ +extern long double hypotl _PARAMS((long double, long double)); +extern long double sqrtl _PARAMS((long double)); #ifdef __i386__ /* Other long double precision functions. */ extern _LONG_DOUBLE rintl _PARAMS((_LONG_DOUBLE)); diff --git a/newlib/libc/include/string.h b/newlib/libc/include/string.h index af5c9da4d..43b36267d 100644 --- a/newlib/libc/include/string.h +++ b/newlib/libc/include/string.h @@ -104,7 +104,10 @@ char *_EXFUN(strerror_r,(int, char *, size_t)); #else # ifdef __GNUC__ int _EXFUN(strerror_r,(int, char *, size_t)) - __asm__ (__ASMNAME ("__xpg_strerror_r")); +#ifdef __ASMNAME + __asm__ (__ASMNAME ("__xpg_strerror_r")) +#endif + ; # else int _EXFUN(__xpg_strerror_r,(int, char *, size_t)); # define strerror_r __xpg_strerror_r diff --git a/newlib/libc/machine/msp430/setjmp.S b/newlib/libc/machine/msp430/setjmp.S index 6684f8acb..f3deefae5 100644 --- a/newlib/libc/machine/msp430/setjmp.S +++ b/newlib/libc/machine/msp430/setjmp.S @@ -60,6 +60,7 @@ setjmp: clr r12 ret #endif + .size setjmp , . - setjmp .global longjmp @@ -102,4 +103,5 @@ longjmp: add.w #2, r1 mov.w r14, r0 #endif + .size longjmp , . - longjmp diff --git a/newlib/libm/common/Makefile.am b/newlib/libm/common/Makefile.am index b370b2e09..d5e0ef959 100644 --- a/newlib/libm/common/Makefile.am +++ b/newlib/libm/common/Makefile.am @@ -31,8 +31,8 @@ lsrc = atanl.c cosl.c sinl.c tanl.c tanhl.c frexpl.c modfl.c ceill.c fabsl.c \ scalbnl.c exp2l.c scalblnl.c tgammal.c nearbyintl.c lrintl.c llrintl.c \ roundl.c lroundl.c llroundl.c truncl.c remquol.c fdiml.c fmaxl.c fminl.c \ fmal.c acoshl.c atanhl.c remainderl.c lgammal.c erfl.c erfcl.c \ - logbl.c nexttowardf.c nexttoward.c nexttowardl.c log2l.c - + logbl.c nexttowardf.c nexttoward.c nexttowardl.c log2l.c \ + sl_finite.c libcommon_la_LDFLAGS = -Xcompiler -nostdlib diff --git a/newlib/libm/common/Makefile.in b/newlib/libm/common/Makefile.in index af3c88d71..ae5949a48 100644 --- a/newlib/libm/common/Makefile.in +++ b/newlib/libm/common/Makefile.in @@ -139,7 +139,7 @@ am__objects_3 = lib_a-atanl.$(OBJEXT) lib_a-cosl.$(OBJEXT) \ lib_a-erfl.$(OBJEXT) lib_a-erfcl.$(OBJEXT) \ lib_a-logbl.$(OBJEXT) lib_a-nexttowardf.$(OBJEXT) \ lib_a-nexttoward.$(OBJEXT) lib_a-nexttowardl.$(OBJEXT) \ - lib_a-log2l.$(OBJEXT) + lib_a-log2l.$(OBJEXT) lib_a-sl_finite.$(OBJEXT) @HAVE_LONG_DOUBLE_TRUE@@USE_LIBTOOL_FALSE@am__objects_4 = \ @HAVE_LONG_DOUBLE_TRUE@@USE_LIBTOOL_FALSE@ $(am__objects_3) @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) \ @@ -173,7 +173,7 @@ am__objects_7 = atanl.lo cosl.lo sinl.lo tanl.lo tanhl.lo frexpl.lo \ lroundl.lo llroundl.lo truncl.lo remquol.lo fdiml.lo fmaxl.lo \ fminl.lo fmal.lo acoshl.lo atanhl.lo remainderl.lo lgammal.lo \ erfl.lo erfcl.lo logbl.lo nexttowardf.lo nexttoward.lo \ - nexttowardl.lo log2l.lo + nexttowardl.lo log2l.lo sl_finite.lo @HAVE_LONG_DOUBLE_TRUE@@USE_LIBTOOL_TRUE@am__objects_8 = \ @HAVE_LONG_DOUBLE_TRUE@@USE_LIBTOOL_TRUE@ $(am__objects_7) @USE_LIBTOOL_TRUE@am_libcommon_la_OBJECTS = $(am__objects_5) \ @@ -360,7 +360,8 @@ lsrc = atanl.c cosl.c sinl.c tanl.c tanhl.c frexpl.c modfl.c ceill.c fabsl.c \ scalbnl.c exp2l.c scalblnl.c tgammal.c nearbyintl.c lrintl.c llrintl.c \ roundl.c lroundl.c llroundl.c truncl.c remquol.c fdiml.c fmaxl.c fminl.c \ fmal.c acoshl.c atanhl.c remainderl.c lgammal.c erfl.c erfcl.c \ - logbl.c nexttowardf.c nexttoward.c nexttowardl.c log2l.c + logbl.c nexttowardf.c nexttoward.c nexttowardl.c log2l.c \ + sl_finite.c libcommon_la_LDFLAGS = -Xcompiler -nostdlib @USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = libcommon.la @@ -1238,6 +1239,12 @@ lib_a-log2l.o: log2l.c lib_a-log2l.obj: log2l.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-log2l.obj `if test -f 'log2l.c'; then $(CYGPATH_W) 'log2l.c'; else $(CYGPATH_W) '$(srcdir)/log2l.c'; fi` +lib_a-sl_finite.o: sl_finite.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sl_finite.o `test -f 'sl_finite.c' || echo '$(srcdir)/'`sl_finite.c + +lib_a-sl_finite.obj: sl_finite.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sl_finite.obj `if test -f 'sl_finite.c'; then $(CYGPATH_W) 'sl_finite.c'; else $(CYGPATH_W) '$(srcdir)/sl_finite.c'; fi` + mostlyclean-libtool: -rm -f *.lo diff --git a/newlib/libm/common/fdlibm.h b/newlib/libm/common/fdlibm.h index a4b7fffe7..821e4dedb 100644 --- a/newlib/libm/common/fdlibm.h +++ b/newlib/libm/common/fdlibm.h @@ -146,6 +146,8 @@ extern double scalb __P((double, double)); #endif extern double significand __P((double)); +extern long double __ieee754_hypotl __P((long double, long double)); + /* ieee style elementary functions */ extern double __ieee754_sqrt __P((double)); extern double __ieee754_acos __P((double)); diff --git a/newlib/libm/common/hypotl.c b/newlib/libm/common/hypotl.c index 3934b8ecc..cf67ccf58 100644 --- a/newlib/libm/common/hypotl.c +++ b/newlib/libm/common/hypotl.c @@ -29,14 +29,61 @@ POSSIBILITY OF SUCH DAMAGE. */ #include -#include "local.h" +#include +#include "fdlibm.h" -/* On platforms where long double is as wide as double. */ -#ifdef _LDBL_EQ_DBL long double hypotl (long double x, long double y) { - return hypot(x, y); -} -#endif +#ifdef _LDBL_EQ_DBL + /* On platforms where long double is as wide as double. */ + return hypot(x, y); + +#else + + long double z; + + z = __ieee754_hypotl (x, y); + + if (_LIB_VERSION == _IEEE_) + return z; + + if ((! finitel (z)) && finitel (x) && finitel (y)) + { + /* hypot (finite, finite) overflow. */ + struct exception exc; + + exc.type = OVERFLOW; + exc.name = "hypotl"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + { +#ifndef HUGE_VAL +#define HUGE_VAL inf + double inf = 0.0; + + SET_HIGH_WORD (inf, 0x7ff00000); /* Set inf to infinite. */ +#endif + exc.retval = HUGE_VAL; + } + + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (! matherr (& exc)) + errno = ERANGE; + + if (exc.err != 0) + errno = exc.err; + + return (long double) exc.retval; + } + + return z; +#endif /* ! _LDBL_EQ_DBL */ +} diff --git a/newlib/libm/common/sl_finite.c b/newlib/libm/common/sl_finite.c new file mode 100644 index 000000000..0c27b4fae --- /dev/null +++ b/newlib/libm/common/sl_finite.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2015 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +/* finitel(x) returns 1 is x is finite, else 0; */ + +#include + +int +finitel (long double x) +{ +#ifdef _LDBL_EQ_DBL + return finite (x); +#else + /* Let the compiler do this for us. + Note - we do not know how many bits there are in a long double. + Some architectures for example have an 80-bit long double whereas + others use 128-bits. We use macros and comiler builtin functions + to avoid specific knowledge of the long double format. */ + return __builtin_isinf_sign (x) == 0; +#endif +} + diff --git a/newlib/libm/common/sqrtl.c b/newlib/libm/common/sqrtl.c index 1e7d7c1d6..8cd717e19 100644 --- a/newlib/libm/common/sqrtl.c +++ b/newlib/libm/common/sqrtl.c @@ -31,12 +31,165 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "local.h" -/* On platforms where long double is as wide as double. */ #ifdef _LDBL_EQ_DBL +/* On platforms where long double is as wide as double. */ long double sqrtl (long double x) { return sqrt(x); } + +#else + + /* This code is based upon the version in the BSD math's library. + That code is... + * + * Copyright (c) 2007 Steven G. Kargl + * All rights reserved. + * + * 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 unmodified, 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ +#include +#include "ieeefp.h" + +#ifndef LDBL_NBIT +#define LDBL_NBIT 0 #endif +#ifndef LDBL_MAX_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#endif + +/* Return (x + ulp) for normal positive x. Assumes no overflow. */ + +static inline long double +inc (long double x) +{ + union ieee_ext_u ux = { .extu_ld = x, }; + + if (++ux.extu_ext.ext_fracl == 0) + { + if (++ux.extu_ext.ext_frach == 0) + { + ux.extu_ext.ext_exp++; + ux.extu_ext.ext_frach |= LDBL_NBIT; + } + } + + return ux.extu_ld; +} + +/* Return (x - ulp) for normal positive x. Assumes no underflow. */ + +static inline long double +dec (long double x) +{ + union ieee_ext_u ux = { .extu_ld = x, }; + + if (ux.extu_ext.ext_fracl-- == 0) + { + if (ux.extu_ext.ext_frach-- == LDBL_NBIT) + { + ux.extu_ext.ext_exp--; + ux.extu_ext.ext_frach |= LDBL_NBIT; + } + } + + return ux.extu_ld; +} + +/* This is slow, but simple and portable. */ + +long double +sqrtl (long double x) +{ + union ieee_ext_u ux = { .extu_ld = x, }; + int k, r; + long double lo, xn; + + /* If x = NaN, then sqrt(x) = NaN. */ + /* If x = Inf, then sqrt(x) = Inf. */ + /* If x = -Inf, then sqrt(x) = NaN. */ + if (ux.extu_ext.ext_exp == LDBL_MAX_EXP * 2 - 1) + return (x * x + x); + + /* If x = +-0, then sqrt(x) = +-0. */ + if (x == 0.0L || x == -0.0L) + return x; + + /* If x < 0, then raise invalid and return NaN. */ + if (ux.extu_ext.ext_sign) + return ((x - x) / (x - x)); + + if (ux.extu_ext.ext_exp == 0) + { + /* Adjust subnormal numbers. */ + ux.extu_ld *= 0x1.0p514; + k = -514; + } + else + k = 0; + + /* ux.extu_ld is a normal number, so break it into ux.extu_ld = e*2^n where + ux.extu_ld = (2*e)*2^2k for odd n and ux.extu_ld = (4*e)*2^2k for even n. */ + + if ((ux.extu_ext.ext_exp - EXT_EXP_BIAS) & 1) + { + /* n is even. */ + k += ux.extu_ext.ext_exp - EXT_EXP_BIAS - 1; /* 2k = n - 2. */ + ux.extu_ext.ext_exp = EXT_EXP_BIAS + 1; /* ux.extu_ld in [2,4). */ + } + else + { + k += ux.extu_ext.ext_exp - EXT_EXP_BIAS; /* 2k = n - 1. */ + ux.extu_ext.ext_exp = EXT_EXP_BIAS; /* ux.extu_ld in [1,2). */ + } + + /* Newton's iteration. + Split ux.extu_ld into a high and low part to achieve additional precision. */ + + xn = sqrt ((double) ux.extu_ld); /* 53-bit estimate of sqrtl(x). */ + +#if LDBL_MANT_DIG > 100 + xn = (xn + (ux.extu_ld / xn)) * 0.5; /* 106-bit estimate. */ +#endif + + lo = ux.extu_ld; + ux.extu_ext.ext_fracl = 0; /* Zero out lower bits. */ + lo = (lo - ux.extu_ld) / xn; /* Low bits divided by xn. */ + xn = xn + (ux.extu_ld / xn); /* High portion of estimate. */ + ux.extu_ld = xn + lo; /* Combine everything. */ + ux.extu_ext.ext_exp += (k >> 1) - 1; + + xn = x / ux.extu_ld; /* Chopped quotient (inexact?). */ + + /* For simplicity we round to nearest. */ + xn = inc (xn); /* xn = xn + ulp. */ + + ux.extu_ld = ux.extu_ld + xn; /* Chopped sum. */ + ux.extu_ext.ext_exp--; + + return ux.extu_ld; +} +#endif /* ! _LDBL_EQ_DBL */ + + diff --git a/newlib/libm/complex/Makefile.am b/newlib/libm/complex/Makefile.am index dbbe759be..1c4a50255 100644 --- a/newlib/libm/complex/Makefile.am +++ b/newlib/libm/complex/Makefile.am @@ -9,7 +9,8 @@ src = cabs.c cacos.c cacosh.c carg.c casin.c casinh.c \ cexp.c cimag.c clog.c conj.c \ cpow.c cproj.c creal.c \ csin.c csinh.c csqrt.c ctan.c ctanh.c - + +lsrc = cabsl.c creall.c cimagl.c fsrc = cabsf.c casinf.c ccosf.c cimagf.c cprojf.c \ csqrtf.c cacosf.c casinhf.c ccoshf.c clogf.c \ @@ -21,11 +22,11 @@ libcomplex_la_LDFLAGS = -Xcompiler -nostdlib if USE_LIBTOOL noinst_LTLIBRARIES = libcomplex.la -libcomplex_la_SOURCES = $(src) $(fsrc) +libcomplex_la_SOURCES = $(src) $(fsrc) $(lsrc) noinst_DATA = objectlist.awk.in else noinst_LIBRARIES = lib.a -lib_a_SOURCES = $(src) $(fsrc) +lib_a_SOURCES = $(src) $(fsrc) $(lsrc) lib_a_CFLAGS = $(AM_CFLAGS) noinst_DATA = endif # USE_LIBTOOL diff --git a/newlib/libm/complex/Makefile.in b/newlib/libm/complex/Makefile.in index 8a0d4b468..cf731e72f 100644 --- a/newlib/libm/complex/Makefile.in +++ b/newlib/libm/complex/Makefile.in @@ -79,8 +79,11 @@ am__objects_2 = lib_a-cabsf.$(OBJEXT) lib_a-casinf.$(OBJEXT) \ lib_a-cargf.$(OBJEXT) lib_a-catanhf.$(OBJEXT) \ lib_a-cexpf.$(OBJEXT) lib_a-cpowf.$(OBJEXT) \ lib_a-csinhf.$(OBJEXT) +am__objects_5 = lib_a-cabsl.$(OBJEXT) lib_a-creall.$(OBJEXT) \ + lib_a-cimagl.$(OBJEXT) @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) \ -@USE_LIBTOOL_FALSE@ $(am__objects_2) +@USE_LIBTOOL_FALSE@ $(am__objects_2) \ +@USE_LIBTOOL_FALSE@ $(am__objects_5) lib_a_OBJECTS = $(am_lib_a_OBJECTS) LTLIBRARIES = $(noinst_LTLIBRARIES) libcomplex_la_LIBADD = @@ -93,8 +96,10 @@ am__objects_4 = cabsf.lo casinf.lo ccosf.lo cimagf.lo cprojf.lo \ ctanf.lo cacoshf.lo catanf.lo cephes_subrf.lo conjf.lo \ csinf.lo ctanhf.lo cargf.lo catanhf.lo cexpf.lo cpowf.lo \ csinhf.lo +am__objects_6 = cabsl.lo creall.lo ciamgl.lo @USE_LIBTOOL_TRUE@am_libcomplex_la_OBJECTS = $(am__objects_3) \ -@USE_LIBTOOL_TRUE@ $(am__objects_4) +@USE_LIBTOOL_TRUE@ $(am__objects_4) \ +@USE_LIBTOOL_TRUE@ $(am__objects_6) libcomplex_la_OBJECTS = $(am_libcomplex_la_OBJECTS) libcomplex_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -249,6 +254,8 @@ src = cabs.c cacos.c cacosh.c carg.c casin.c casinh.c \ cpow.c cproj.c creal.c \ csin.c csinh.c csqrt.c ctan.c ctanh.c +lsrc = cabsl.c creall.c cimagl.c + fsrc = cabsf.c casinf.c ccosf.c cimagf.c cprojf.c \ csqrtf.c cacosf.c casinhf.c ccoshf.c clogf.c \ crealf.c ctanf.c cacoshf.c catanf.c \ @@ -257,11 +264,11 @@ fsrc = cabsf.c casinf.c ccosf.c cimagf.c cprojf.c \ libcomplex_la_LDFLAGS = -Xcompiler -nostdlib @USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = libcomplex.la -@USE_LIBTOOL_TRUE@libcomplex_la_SOURCES = $(src) $(fsrc) +@USE_LIBTOOL_TRUE@libcomplex_la_SOURCES = $(src) $(fsrc) $(lsrc) @USE_LIBTOOL_FALSE@noinst_DATA = @USE_LIBTOOL_TRUE@noinst_DATA = objectlist.awk.in @USE_LIBTOOL_FALSE@noinst_LIBRARIES = lib.a -@USE_LIBTOOL_FALSE@lib_a_SOURCES = $(src) $(fsrc) +@USE_LIBTOOL_FALSE@lib_a_SOURCES = $(src) $(fsrc) $(lsrc) @USE_LIBTOOL_FALSE@lib_a_CFLAGS = $(AM_CFLAGS) chobj = cabs.def cacos.def cacosh.def carg.def \ casin.def casinh.def catan.def catanh.def \ @@ -617,6 +624,27 @@ lib_a-csinhf.o: csinhf.c lib_a-csinhf.obj: csinhf.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-csinhf.obj `if test -f 'csinhf.c'; then $(CYGPATH_W) 'csinhf.c'; else $(CYGPATH_W) '$(srcdir)/csinhf.c'; fi` +lib_a-cabsl.o: cabsl.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-cabsl.o `test -f 'cabsl.c' || echo '$(srcdir)/'`cabsl.c + +lib_a-cabsl.obj: cabsl.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-cabsl.obj `if test -f 'cabsl.c'; then $(CYGPATH_W) 'cabsl.c'; else $(CYGPATH_W) '$(srcdir)/cabsl.c'; fi` + +lib_a-creall.o: creall.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-creall.o `test -f 'creall.c' || echo '$(srcdir)/'`creall.c + +lib_a-creall.obj: creall.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-creall.obj `if test -f 'creall.c'; then $(CYGPATH_W) 'creall.c'; else $(CYGPATH_W) '$(srcdir)/creall.c'; fi` + +lib_a-cimagl.o: cimagl.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-cimagl.o `test -f 'cimagl.c' || echo '$(srcdir)/'`cimagl.c + +lib_a-cimagl.obj: cimagl.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-cimagl.obj `if test -f 'cimagl.c'; then $(CYGPATH_W) 'cimagl.c'; else $(CYGPATH_W) '$(srcdir)/cimagl.c'; fi` + + + + mostlyclean-libtool: -rm -f *.lo diff --git a/newlib/libm/complex/cabs.c b/newlib/libm/complex/cabs.c index 2750fab9a..69091d71a 100644 --- a/newlib/libm/complex/cabs.c +++ b/newlib/libm/complex/cabs.c @@ -10,17 +10,20 @@ /* FUNCTION - <>, <>---complex absolute-value + <>, <>, <>---complex absolute-value INDEX cabs INDEX cabsf +INDEX + cabsl ANSI_SYNOPSIS #include double cabs(double complex <[z]>); float cabsf(float complex <[z]>); + long double cabsl(long double complex <[z]>); DESCRIPTION @@ -28,16 +31,19 @@ DESCRIPTION (also called norm, modulus, or magnitude) of <[z]>. <> is identical to <>, except that it performs - its calculations on <>. + its calculations on <>. + + <> is identical to <>, except that it performs + its calculations on <>. RETURNS - The cabs functions return the complex absolute value. + The cabs* functions return the complex absolute value. PORTABILITY - <> and <> are ISO C99 + <>, <> and <> are ISO C99 QUICKREF - <> and <> are ISO C99 + <>, <> and <> are ISO C99 */ diff --git a/newlib/libm/complex/cabsl.c b/newlib/libm/complex/cabsl.c new file mode 100644 index 000000000..091f2cd53 --- /dev/null +++ b/newlib/libm/complex/cabsl.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2015 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include +#include + +long double +cabsl (long double complex z) +{ +#ifdef _LDBL_EQ_DBL + return cabs (z); +#else + return hypotl (creall (z), cimagl (z)); +#endif +} diff --git a/newlib/libm/complex/cimag.c b/newlib/libm/complex/cimag.c index 1d2d77414..959dbc9a4 100644 --- a/newlib/libm/complex/cimag.c +++ b/newlib/libm/complex/cimag.c @@ -10,33 +10,39 @@ /* FUNCTION - <>, <>---imaginary part + <>, <>, <>---imaginary part INDEX cimag INDEX cimagf +INDEX + cimagl ANSI_SYNOPSIS #include double cimag(double complex <[z]>); float cimagf(float complex <[z]>); + long double cimagl(long double complex <[z]>); DESCRIPTION These functions compute the imaginary part of <[z]>. <> is identical to <>, except that it performs - its calculations on <>. + its calculations on <>. + + <> is identical to <>, except that it performs + its calculations on <>. RETURNS - The cimag functions return the imaginary part value (as a real). + The cimag* functions return the imaginary part value (as a real). PORTABILITY - <> and <> are ISO C99 + <>, <> and <> are ISO C99 QUICKREF - <> and <> are ISO C99 + <>, <> and <> are ISO C99 */ diff --git a/newlib/libm/complex/cimagl.c b/newlib/libm/complex/cimagl.c new file mode 100644 index 000000000..a5afdc456 --- /dev/null +++ b/newlib/libm/complex/cimagl.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2015 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include +#include "../common/fdlibm.h" + +long double +cimagl (long double complex z) +{ + long_double_complex w = { .z = z }; + + return IMAG_PART (w); +} diff --git a/newlib/libm/complex/creal.c b/newlib/libm/complex/creal.c index c621561ae..1652a5f8e 100644 --- a/newlib/libm/complex/creal.c +++ b/newlib/libm/complex/creal.c @@ -10,33 +10,39 @@ /* FUNCTION - <>, <>---real part + <>, <>, <>---real part INDEX creal INDEX crealf +INDEX + creall ANSI_SYNOPSIS #include double creal(double complex <[z]>); float crealf(float complex <[z]>); + double long creall(long double complex <[z]>); - + DESCRIPTION These functions compute the real part of <[z]>. <> is identical to <>, except that it performs - its calculations on <>. + its calculations on <>. + + <> is identical to <>, except that it performs + its calculations on <>. RETURNS - The creal functions return the real part value. + The creal* functions return the real part value. PORTABILITY - <> and <> are ISO C99 + <>, <> and <> are ISO C99 QUICKREF - <> and <> are ISO C99 + <>, <> and <> are ISO C99 */ diff --git a/newlib/libm/complex/creall.c b/newlib/libm/complex/creall.c new file mode 100644 index 000000000..7aa88c272 --- /dev/null +++ b/newlib/libm/complex/creall.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2015 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include +#include "../common/fdlibm.h" + +long double +creall (long double complex z) +{ + long_double_complex w = { .z = z }; + + return (REAL_PART(w)); +} diff --git a/newlib/libm/math/Makefile.am b/newlib/libm/math/Makefile.am index a4589ada2..2616ada1f 100644 --- a/newlib/libm/math/Makefile.am +++ b/newlib/libm/math/Makefile.am @@ -50,15 +50,17 @@ fsrc = kf_rem_pio2.c \ sf_tan.c sf_tanh.c \ wf_exp2.c wf_tgamma.c +lsrc = el_hypot.c + libmath_la_LDFLAGS = -Xcompiler -nostdlib if USE_LIBTOOL noinst_LTLIBRARIES = libmath.la -libmath_la_SOURCES = $(src) $(fsrc) +libmath_la_SOURCES = $(src) $(fsrc) $(lsrc) noinst_DATA = objectlist.awk.in else noinst_LIBRARIES = lib.a -lib_a_SOURCES = $(src) $(fsrc) +lib_a_SOURCES = $(src) $(fsrc) $(lsrc) lib_a_CFLAGS = $(AM_CFLAGS) noinst_DATA = endif # USE_LIBTOOL diff --git a/newlib/libm/math/Makefile.in b/newlib/libm/math/Makefile.in index 10f6ca563..233c7c257 100644 --- a/newlib/libm/math/Makefile.in +++ b/newlib/libm/math/Makefile.in @@ -138,8 +138,10 @@ am__objects_2 = lib_a-kf_rem_pio2.$(OBJEXT) lib_a-kf_cos.$(OBJEXT) \ lib_a-sf_signif.$(OBJEXT) lib_a-sf_sin.$(OBJEXT) \ lib_a-sf_tan.$(OBJEXT) lib_a-sf_tanh.$(OBJEXT) \ lib_a-wf_exp2.$(OBJEXT) lib_a-wf_tgamma.$(OBJEXT) +am__objects_5 = lib_a-el_hypot.$(OBJEXT) @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) \ -@USE_LIBTOOL_FALSE@ $(am__objects_2) +@USE_LIBTOOL_FALSE@ $(am__objects_2) \ +@USE_LIBTOOL_FALSE@ $(am__objects_5) lib_a_OBJECTS = $(am_lib_a_OBJECTS) LTLIBRARIES = $(noinst_LTLIBRARIES) libmath_la_LIBADD = @@ -169,8 +171,10 @@ am__objects_4 = kf_rem_pio2.lo kf_cos.lo kf_sin.lo kf_tan.lo \ sf_cos.lo sf_erf.lo sf_fabs.lo sf_floor.lo sf_frexp.lo \ sf_ldexp.lo sf_signif.lo sf_sin.lo sf_tan.lo sf_tanh.lo \ wf_exp2.lo wf_tgamma.lo +am__objects_6 = el_hypot.lo @USE_LIBTOOL_TRUE@am_libmath_la_OBJECTS = $(am__objects_3) \ -@USE_LIBTOOL_TRUE@ $(am__objects_4) +@USE_LIBTOOL_TRUE@ $(am__objects_4) \ +@USE_LIBTOOL_TRUE@ $(am__objects_6) libmath_la_OBJECTS = $(am_libmath_la_OBJECTS) libmath_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -372,13 +376,15 @@ fsrc = kf_rem_pio2.c \ sf_tan.c sf_tanh.c \ wf_exp2.c wf_tgamma.c +lsrc = el_hypot.c + libmath_la_LDFLAGS = -Xcompiler -nostdlib @USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = libmath.la -@USE_LIBTOOL_TRUE@libmath_la_SOURCES = $(src) $(fsrc) +@USE_LIBTOOL_TRUE@libmath_la_SOURCES = $(src) $(fsrc) $(lsrc) @USE_LIBTOOL_FALSE@noinst_DATA = @USE_LIBTOOL_TRUE@noinst_DATA = objectlist.awk.in @USE_LIBTOOL_FALSE@noinst_LIBRARIES = lib.a -@USE_LIBTOOL_FALSE@lib_a_SOURCES = $(src) $(fsrc) +@USE_LIBTOOL_FALSE@lib_a_SOURCES = $(src) $(fsrc) $(lsrc) @USE_LIBTOOL_FALSE@lib_a_CFLAGS = $(AM_CFLAGS) chobj = w_acos.def w_acosh.def w_asin.def s_asinh.def \ s_atan.def w_atan2.def w_atanh.def w_j0.def \ @@ -1260,6 +1266,12 @@ lib_a-wf_tgamma.o: wf_tgamma.c lib_a-wf_tgamma.obj: wf_tgamma.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wf_tgamma.obj `if test -f 'wf_tgamma.c'; then $(CYGPATH_W) 'wf_tgamma.c'; else $(CYGPATH_W) '$(srcdir)/wf_tgamma.c'; fi` +lib_a-el_hypot.o: el_hypot.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-el_hypot.o `test -f 'el_hypot.c' || echo '$(srcdir)/'`el_hypot.c + +lib_a-el_hypot.obj: el_hypot.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-el_hypot.obj `if test -f 'el_hypot.c'; then $(CYGPATH_W) 'el_hypot.c'; else $(CYGPATH_W) '$(srcdir)/el_hypot.c'; fi` + mostlyclean-libtool: -rm -f *.lo diff --git a/newlib/libm/math/el_hypot.c b/newlib/libm/math/el_hypot.c new file mode 100644 index 000000000..737cde36b --- /dev/null +++ b/newlib/libm/math/el_hypot.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2015 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include "fdlibm.h" + +long double +__ieee754_hypotl (long double x, long double y) +{ +#ifdef _LDBL_EQ_DBL + return __ieee754_hypot (x, y); +#else + /* Keep it simple for now... */ + return sqrtl ((x * x) + (y * y)); +#endif +}