From 1abc9ff6a5b5f8a9925f1b8d9d333bc5bc7d407f Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Thu, 17 Apr 2014 18:17:32 +0100 Subject: [PATCH] Clean-up _fpmath and fake_long_doubles - promoted IEEEld2bits to fpmath since most of the where the same for diffrent archs - removed _fpmath - reinstated weak_references - moved isfinite and isnormal to libc - clean up fake_long_doubles - clean up some useless ifdefs - added missing nexttoward* tests Bug: 14134235 Change-Id: I95639c4885653fe47fd7dc0570ee5bb3389bbc6b --- libc/bionic/fpclassify.cpp | 35 ++++++ libm/Android.mk | 17 ++- libm/amd64/_fpmath.h | 60 ----------- libm/arm/_fpmath.h | 67 ------------ libm/arm64/_fpmath.h | 60 ----------- libm/fake_long_double.c | 69 +----------- libm/fpmath.h | 100 +++++++++--------- libm/freebsd-compat.h | 7 +- libm/i386/_fpmath.h | 54 ---------- libm/mips/_fpmath.h | 83 --------------- .../lib/msun/src/s_signbit.c => signbit.c} | 31 +++--- .../msun/src/s_isfinite.c => significandl.c} | 34 +----- .../msun/src/{s_isnormal.c => imprecise.c} | 57 ++++++---- tests/math_test.cpp | 23 +++- 14 files changed, 173 insertions(+), 524 deletions(-) delete mode 100755 libm/amd64/_fpmath.h delete mode 100644 libm/arm/_fpmath.h delete mode 100644 libm/arm64/_fpmath.h delete mode 100644 libm/i386/_fpmath.h delete mode 100644 libm/mips/_fpmath.h rename libm/{upstream-freebsd/lib/msun/src/s_signbit.c => signbit.c} (80%) rename libm/{upstream-freebsd/lib/msun/src/s_isfinite.c => significandl.c} (78%) rename libm/upstream-freebsd/lib/msun/src/{s_isnormal.c => imprecise.c} (58%) diff --git a/libc/bionic/fpclassify.cpp b/libc/bionic/fpclassify.cpp index 82e1b037a..21ff946fb 100644 --- a/libc/bionic/fpclassify.cpp +++ b/libc/bionic/fpclassify.cpp @@ -90,6 +90,28 @@ int __isnanf(float f) { } __strong_alias(isnanf, __isnanf); +int __isfinite(double d) { + int type = __fpclassifyd(d); + return ((type != FP_NAN) && (type != FP_INFINITE)); +} +__strong_alias(isfinite, __isfinite); + +int __isfinitef(float f) { + int type = __fpclassifyf(f); + return ((type != FP_NAN) && (type != FP_INFINITE)); +} +__strong_alias(isfinitef, __isfinitef); + +int __isnormal(double d) { + return (__fpclassifyd(d) == FP_NORMAL); +} +__strong_alias(isnormal, __isnormal); + +int __isnormalf(float f) { + return (__fpclassifyf(f) == FP_NORMAL); +} +__strong_alias(isnormalf, __isnormalf); + #if __LP64__ // LP64 uses 128-bit long doubles. @@ -121,6 +143,15 @@ int __isnanl(long double ld) { return (__fpclassifyl(ld) == FP_NAN); } +int __isfinitel(long double ld) { + int type = __fpclassifyl(ld); + return ((type != FP_NAN) && (type != FP_INFINITE)); +} + +int __isnormall(long double ld) { + return (__fpclassifyl(ld) == FP_NORMAL); +} + #else // LP32 uses double as long double. @@ -128,8 +159,12 @@ int __isnanl(long double ld) { __strong_alias(__fpclassifyl, __fpclassify); __strong_alias(__isinfl, __isinf); __strong_alias(__isnanl, __isnan); +__strong_alias(__isfinitel, __isfinite); +__strong_alias(__isnormall, __isnormal); #endif __strong_alias(isinfl, __isinfl); __strong_alias(isnanl, __isnanl); +__strong_alias(isfinitel, __isfinitel); +__strong_alias(isnormall, __isnormall); diff --git a/libm/Android.mk b/libm/Android.mk index 1bd428db4..5f69d1ef1 100644 --- a/libm/Android.mk +++ b/libm/Android.mk @@ -8,6 +8,7 @@ libm_common_src_files := \ # TODO: this is not in the BSDs. libm_common_src_files += \ + significandl.c \ sincos.c \ libm_common_src_files += \ @@ -64,6 +65,7 @@ libm_common_src_files += \ upstream-freebsd/lib/msun/src/e_sinhf.c \ upstream-freebsd/lib/msun/src/e_sqrt.c \ upstream-freebsd/lib/msun/src/e_sqrtf.c \ + upstream-freebsd/lib/msun/src/imprecise.c \ upstream-freebsd/lib/msun/src/k_cos.c \ upstream-freebsd/lib/msun/src/k_cosf.c \ upstream-freebsd/lib/msun/src/k_exp.c \ @@ -128,8 +130,6 @@ libm_common_src_files += \ upstream-freebsd/lib/msun/src/s_frexpf.c \ upstream-freebsd/lib/msun/src/s_ilogb.c \ upstream-freebsd/lib/msun/src/s_ilogbf.c \ - upstream-freebsd/lib/msun/src/s_isfinite.c \ - upstream-freebsd/lib/msun/src/s_isnormal.c \ upstream-freebsd/lib/msun/src/s_llrint.c \ upstream-freebsd/lib/msun/src/s_llrintf.c \ upstream-freebsd/lib/msun/src/s_llround.c \ @@ -148,7 +148,6 @@ libm_common_src_files += \ upstream-freebsd/lib/msun/src/s_nearbyint.c \ upstream-freebsd/lib/msun/src/s_nextafter.c \ upstream-freebsd/lib/msun/src/s_nextafterf.c \ - upstream-freebsd/lib/msun/src/s_nexttowardf.c \ upstream-freebsd/lib/msun/src/s_remquo.c \ upstream-freebsd/lib/msun/src/s_remquof.c \ upstream-freebsd/lib/msun/src/s_rint.c \ @@ -158,7 +157,6 @@ libm_common_src_files += \ upstream-freebsd/lib/msun/src/s_scalbln.c \ upstream-freebsd/lib/msun/src/s_scalbn.c \ upstream-freebsd/lib/msun/src/s_scalbnf.c \ - upstream-freebsd/lib/msun/src/s_signbit.c \ upstream-freebsd/lib/msun/src/s_signgam.c \ upstream-freebsd/lib/msun/src/s_significand.c \ upstream-freebsd/lib/msun/src/s_significandf.c \ @@ -178,6 +176,7 @@ libm_common_src_files += \ libm_common_src_files += \ fake_long_double.c \ + signbit.c \ libm_ld_src_files = \ upstream-freebsd/lib/msun/src/e_acosl.c \ @@ -210,6 +209,7 @@ libm_ld_src_files = \ upstream-freebsd/lib/msun/src/s_lroundl.c \ upstream-freebsd/lib/msun/src/s_nextafterl.c \ upstream-freebsd/lib/msun/src/s_nexttoward.c \ + upstream-freebsd/lib/msun/src/s_nexttowardf.c \ upstream-freebsd/lib/msun/src/s_remquol.c \ upstream-freebsd/lib/msun/src/s_rintl.c \ upstream-freebsd/lib/msun/src/s_roundl.c \ @@ -255,21 +255,20 @@ LOCAL_SYSTEM_SHARED_LIBRARIES := libc LOCAL_C_INCLUDES_arm := $(LOCAL_PATH)/arm LOCAL_SRC_FILES_arm := arm/fenv.c -LOCAL_C_INCLUDES_arm64 := $(LOCAL_PATH)/arm64 $(libm_ld_includes) +LOCAL_C_INCLUDES_arm64 := $(libm_ld_includes) LOCAL_SRC_FILES_arm64 := arm64/fenv.c $(libm_ld_src_files) -LOCAL_C_INCLUDES_x86 := $(LOCAL_PATH)/i386 $(LOCAL_PATH)/i387 +LOCAL_C_INCLUDES_x86 := $(LOCAL_PATH)/i387 LOCAL_SRC_FILES_x86 := i387/fenv.c -LOCAL_C_INCLUDES_x86_64 := $(LOCAL_PATH)/amd64 $(libm_ld_includes) +LOCAL_C_INCLUDES_x86_64 := $(libm_ld_includes) LOCAL_SRC_FILES_x86_64 := amd64/fenv.c $(libm_ld_src_files) LOCAL_CFLAGS_mips := -fno-builtin-rintf -fno-builtin-rint -LOCAL_C_INCLUDES_mips := $(LOCAL_PATH)/mips LOCAL_SRC_FILES_mips := mips/fenv.c LOCAL_CFLAGS_mips64 := -fno-builtin-rintf -fno-builtin-rint -LOCAL_C_INCLUDES_mips64 := $(LOCAL_PATH)/mips $(libm_ld_includes) +LOCAL_C_INCLUDES_mips64 := $(libm_ld_includes) LOCAL_SRC_FILES_mips64 := mips/fenv.c $(libm_ld_src_files) include $(BUILD_STATIC_LIBRARY) diff --git a/libm/amd64/_fpmath.h b/libm/amd64/_fpmath.h deleted file mode 100755 index f8d5c85ac..000000000 --- a/libm/amd64/_fpmath.h +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 David Schultz - * 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, 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 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 AUTHOR 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. - * - * $FreeBSD$ - */ - -// ANDROID changed -// Android uses 128 bits long doubles for LP64, so the structure and macros -// were reworked for the quad precision ieee representation. - -union IEEEl2bits { - long double e; - struct { - unsigned long manl :64; - unsigned long manh :48; - unsigned int exp :15; - unsigned int sign :1; - } bits; - struct { - unsigned long manl :64; - unsigned long manh :48; - unsigned int expsign :16; - } xbits; -}; - -#define LDBL_NBIT 0 -#define LDBL_IMPLICIT_NBIT -#define mask_nbit_l(u) ((void)0) - -#define LDBL_MANH_SIZE 48 -#define LDBL_MANL_SIZE 64 - -#define LDBL_TO_ARRAY32(u, a) do { \ - (a)[0] = (uint32_t)(u).bits.manl; \ - (a)[1] = (uint32_t)((u).bits.manl >> 32); \ - (a)[2] = (uint32_t)(u).bits.manh; \ - (a)[3] = (uint32_t)((u).bits.manh >> 32); \ -} while(0) diff --git a/libm/arm/_fpmath.h b/libm/arm/_fpmath.h deleted file mode 100644 index 4c1894597..000000000 --- a/libm/arm/_fpmath.h +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 David Schultz - * 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, 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 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 AUTHOR 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. - * - * $FreeBSD$ - */ - -#if defined(__VFP_FP__) -#define _IEEE_WORD_ORDER _BYTE_ORDER -#else -#define _IEEE_WORD_ORDER _BIG_ENDIAN -#endif - -union IEEEl2bits { - long double e; - struct { -#if _BYTE_ORDER == _LITTLE_ENDIAN -#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN - unsigned int manl :32; -#endif - unsigned int manh :20; - unsigned int exp :11; - unsigned int sign :1; -#if _IEEE_WORD_ORDER == _BIG_ENDIAN - unsigned int manl :32; -#endif -#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ - unsigned int sign :1; - unsigned int exp :11; - unsigned int manh :20; - unsigned int manl :32; -#endif - } bits; -}; - -#define LDBL_NBIT 0 -#define LDBL_IMPLICIT_NBIT -#define mask_nbit_l(u) ((void)0) - -#define LDBL_MANH_SIZE 20 -#define LDBL_MANL_SIZE 32 - -#define LDBL_TO_ARRAY32(u, a) do { \ - (a)[0] = (uint32_t)(u).bits.manl; \ - (a)[1] = (uint32_t)(u).bits.manh; \ -} while(0) diff --git a/libm/arm64/_fpmath.h b/libm/arm64/_fpmath.h deleted file mode 100644 index 560d53ab6..000000000 --- a/libm/arm64/_fpmath.h +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 David Schultz - * 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, 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 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 AUTHOR 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. - * - * $FreeBSD: src/lib/libc/aarch64/_fpmath.h $ - */ - -// ANDROID changed -// Android uses 128 bits long doubles for LP64, so the structure and the macros -// were reworked for the quad precision ieee representation. - -union IEEEl2bits { - long double e; - struct { - unsigned long manl :64; - unsigned long manh :48; - unsigned int exp :15; - unsigned int sign :1; - } bits; - struct { - unsigned long manl :64; - unsigned long manh :48; - unsigned int expsign :16; - } xbits; -}; - -#define LDBL_NBIT 0 -#define LDBL_IMPLICIT_NBIT -#define mask_nbit_l(u) ((void)0) - -#define LDBL_MANH_SIZE 48 -#define LDBL_MANL_SIZE 64 - -#define LDBL_TO_ARRAY32(u, a) do { \ - (a)[0] = (uint32_t)(u).bits.manl; \ - (a)[1] = (uint32_t)((u).bits.manl >> 32); \ - (a)[2] = (uint32_t)(u).bits.manh; \ - (a)[3] = (uint32_t)((u).bits.manh >> 32); \ -} while(0) diff --git a/libm/fake_long_double.c b/libm/fake_long_double.c index 611512ad1..317a11572 100644 --- a/libm/fake_long_double.c +++ b/libm/fake_long_double.c @@ -17,35 +17,6 @@ #include #include -/* - * On LP64 sizeof(long double) > sizeof(double) so functions which fall back - * to their double variants lose precision. Emit a warning whenever something - * links against such functions. - * On LP32 sizeof(long double) == sizeof(double) so we don't need to warn. - */ -#ifdef __LP64__ -#define WARN_IMPRECISE(x) \ - __warn_references(x, # x " has lower than advertised precision"); -#else -#define WARN_IMPRECISE(x) -#endif //__LP64__ - -#define DECLARE_IMPRECISE(f) \ - long double f ## l(long double v) { return f(v); } \ - WARN_IMPRECISE(x) - -DECLARE_IMPRECISE(cosh); -DECLARE_IMPRECISE(erfc); -DECLARE_IMPRECISE(erf); -DECLARE_IMPRECISE(lgamma); -DECLARE_IMPRECISE(sinh); -DECLARE_IMPRECISE(tanh); -DECLARE_IMPRECISE(tgamma); -DECLARE_IMPRECISE(significand); - -long double powl(long double a1, long double a2) { return pow(a1, a2); } -WARN_IMPRECISE(powl) - #ifndef __LP64__ /* * The BSD "long double" functions are broken when sizeof(long double) == sizeof(double). @@ -53,56 +24,18 @@ WARN_IMPRECISE(powl) * that call the regular "double" function. */ -int __isfinitel(long double a1) { return __isfinite(a1); } -int __isnormall(long double a1) { return __isnormal(a1); } -int __signbitl(long double a1) { return __signbit(a1); } - -long double acoshl(long double a1) { return acosh(a1); } -long double acosl(long double a1) { return acos(a1); } -long double asinhl(long double a1) { return asinh(a1); } -long double asinl(long double a1) { return asin(a1); } -long double atan2l(long double a1, long double a2) { return atan2(a1, a2); } -long double atanhl(long double a1) { return atanh(a1); } -long double atanl(long double a1) { return atan(a1); } -long double cbrtl(long double a1) { return cbrt(a1); } -long double ceill(long double a1) { return ceil(a1); } long double copysignl(long double a1, long double a2) { return copysign(a1, a2); } - -long double cosl(long double a1) { return cos(a1); } - -long double exp2l(long double a1) { return exp2(a1); } -long double expl(long double a1) { return exp(a1); } -long double expm1l(long double a1) { return expm1(a1); } long double fabsl(long double a1) { return fabs(a1); } -long double floorl(long double a1) { return floor(a1); } -long double fmal(long double a1, long double a2, long double a3) { return fma(a1, a2, a3); } long double fmaxl(long double a1, long double a2) { return fmax(a1, a2); } long double fmodl(long double a1, long double a2) { return fmod(a1, a2); } long double fminl(long double a1, long double a2) { return fmin(a1, a2); } -long double frexpl(long double a1, int* a2) { return frexp(a1, a2); } -long double hypotl(long double a1, long double a2) { return hypot(a1, a2); } int ilogbl(long double a1) { return ilogb(a1); } -long double ldexpl(long double a1, int a2) { return ldexp(a1, a2); } long long llrintl(long double a1) { return llrint(a1); } -long double log10l(long double a1) { return log10(a1); } -long double log1pl(long double a1) { return log1p(a1); } -long double log2l(long double a1) { return log2(a1); } -long double logbl(long double a1) { return logb(a1); } -long double logl(long double a1) { return log(a1); } long lrintl(long double a1) { return lrint(a1); } long long llroundl(long double a1) { return llround(a1); } long lroundl(long double a1) { return lround(a1); } long double modfl(long double a1, long double* a2) { double i; double f = modf(a1, &i); *a2 = i; return f; } -long double nanl(const char* a1) { return nan(a1); } -long double nextafterl(long double a1, long double a2) { return nextafter(a1, a2); } -long double remainderl(long double a1, long double a2) { return remainder(a1, a2); } -long double remquol(long double a1, long double a2, int* a3) { return remquo(a1, a2, a3); } -long double rintl(long double a1) { return rint(a1); } +float nexttowardf(float a1, long double a2) { return nextafterf(a1, (float) a2); } long double roundl(long double a1) { return round(a1); } -long double scalbnl(long double a1, int a2) { return scalbn(a1, a2); } -long double sinl(long double a1) { return sin(a1); } -long double sqrtl(long double a1) { return sqrt(a1); } -long double tanl(long double a1) { return tan(a1); } -long double truncl(long double a1) { return trunc(a1); } #endif // __LP64__ diff --git a/libm/fpmath.h b/libm/fpmath.h index e76771de7..80420e5af 100644 --- a/libm/fpmath.h +++ b/libm/fpmath.h @@ -27,69 +27,69 @@ * $FreeBSD$ */ +// ANDROID changed: +// - keep only little endian variants as they're the only one supported. +// - add long double structures here instead of _fpmath.h. +// - android uses 128 bits long doubles for LP64, so the structure and macros +// were reworked for the quad precision ieee representation. + #ifndef _FPMATH_ #define _FPMATH_ #include -#include "_fpmath.h" - -#ifndef _IEEE_WORD_ORDER -#define _IEEE_WORD_ORDER _BYTE_ORDER -#endif union IEEEf2bits { - float f; - struct { -#if _BYTE_ORDER == _LITTLE_ENDIAN - unsigned int man :23; - unsigned int exp :8; - unsigned int sign :1; -#else /* _BIG_ENDIAN */ - unsigned int sign :1; - unsigned int exp :8; - unsigned int man :23; -#endif - } bits; + float f; + struct { + unsigned int man :23; + unsigned int exp :8; + unsigned int sign :1; + } bits; }; -#define DBL_MANH_SIZE 20 -#define DBL_MANL_SIZE 32 +#define DBL_MANH_SIZE 20 +#define DBL_MANL_SIZE 32 union IEEEd2bits { - double d; - struct { -#if _BYTE_ORDER == _LITTLE_ENDIAN -#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN - unsigned int manl :32; -#endif - unsigned int manh :20; - unsigned int exp :11; - unsigned int sign :1; -#if _IEEE_WORD_ORDER == _BIG_ENDIAN - unsigned int manl :32; -#endif -#else /* _BIG_ENDIAN */ - unsigned int sign :1; - unsigned int exp :11; - unsigned int manh :20; - unsigned int manl :32; -#endif - } bits; + double d; + struct { + unsigned int manl :32; + unsigned int manh :20; + unsigned int exp :11; + unsigned int sign :1; + } bits; }; -/* - * The BSD "long double" functions are broken when sizeof(long double) == sizeof(double). - * Android works around those cases by replacing the broken functions with our own trivial stubs - * that call the regular "double" function. - */ -#ifndef __LP64__ +#ifdef __LP64__ -#define __fpclassifyl __broken__fpclassify -#define __isfinitel __broken__isfinitel -#define __isinfl __broken__isinfl -#define __isnanl __broken__isnanl -#define __isnormall __broken__isnormall -#define __signbitl __broken_signbitl +union IEEEl2bits { + long double e; + struct { + unsigned long manl :64; + unsigned long manh :48; + unsigned int exp :15; + unsigned int sign :1; + } bits; + struct { + unsigned long manl :64; + unsigned long manh :48; + unsigned int expsign :16; + } xbits; +}; + +#define LDBL_NBIT 0 +#define LDBL_IMPLICIT_NBIT +#define mask_nbit_l(u) ((void)0) + +#define LDBL_MANH_SIZE 48 +#define LDBL_MANL_SIZE 64 + +#define LDBL_TO_ARRAY32(u, a) do { \ + (a)[0] = (uint32_t)(u).bits.manl; \ + (a)[1] = (uint32_t)((u).bits.manl >> 32); \ + (a)[2] = (uint32_t)(u).bits.manh; \ + (a)[3] = (uint32_t)((u).bits.manh >> 32); \ +} while(0) #endif // __LP64__ diff --git a/libm/freebsd-compat.h b/libm/freebsd-compat.h index c63d4072a..1481cc224 100644 --- a/libm/freebsd-compat.h +++ b/libm/freebsd-compat.h @@ -17,8 +17,11 @@ #ifndef _BIONIC_LIBM_FREEBSD_COMPAT_H_included #define _BIONIC_LIBM_FREEBSD_COMPAT_H_included -#define __weak_reference(sym,alias) \ - /* We don't use __weak_reference; see "fake_long_double.c". */ +#include + +#define __weak_reference(sym,alias) \ + __asm__(".weak " #alias); \ + __asm__(".equ " #alias ", " #sym) #define __strong_reference(sym,aliassym) \ extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym))) diff --git a/libm/i386/_fpmath.h b/libm/i386/_fpmath.h deleted file mode 100644 index 4f1f5f4a5..000000000 --- a/libm/i386/_fpmath.h +++ /dev/null @@ -1,54 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 David Schultz - * 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, 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 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 AUTHOR 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. - * - * $FreeBSD$ - */ - -union IEEEl2bits { - long double e; - struct { - unsigned int manl :32; - unsigned int manh :32; - unsigned int exp :15; - unsigned int sign :1; - unsigned int junk :16; - } bits; - struct { - unsigned long long man :64; - unsigned int expsign :16; - unsigned int junk :16; - } xbits; -}; - -#define LDBL_NBIT 0x80000000 -#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT) - -#define LDBL_MANH_SIZE 32 -#define LDBL_MANL_SIZE 32 - -#define LDBL_TO_ARRAY32(u, a) do { \ - (a)[0] = (uint32_t)(u).bits.manl; \ - (a)[1] = (uint32_t)(u).bits.manh; \ -} while (0) diff --git a/libm/mips/_fpmath.h b/libm/mips/_fpmath.h deleted file mode 100644 index f759639eb..000000000 --- a/libm/mips/_fpmath.h +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * Copyright (c) 2002, 2003 David Schultz - * 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, 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 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 AUTHOR 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. - * - * $FreeBSD$ - */ - -union IEEEl2bits { - long double e; - struct { -#ifndef __MIPSEB__ -#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) - unsigned long manl :64; - unsigned long manh :48; - unsigned int exp :15; - unsigned int sign :1; -#else - unsigned int manl :32; - unsigned int manh :20; - unsigned int exp :11; - unsigned int sign :1; -#endif -#else -#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) - unsigned int sign :1; - unsigned int exp :15; - unsigned long manh :48; - unsigned long manl :64; -#else - unsigned int sign :1; - unsigned int exp :11; - unsigned int manh :20; - unsigned int manl :32; -#endif -#endif - } bits; - -}; - -#define LDBL_NBIT 0 -#define mask_nbit_l(u) ((void)0) -#define LDBL_IMPLICIT_NBIT - -#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) -#define LDBL_MANH_SIZE 48 -#define LDBL_MANL_SIZE 64 - -#define LDBL_TO_ARRAY32(u, a) do { \ - (a)[0] = (uint32_t)(u).bits.manl; \ - (a)[1] = (uint32_t)((u).bits.manl >> 32); \ - (a)[2] = (uint32_t)(u).bits.manh; \ - (a)[3] = (uint32_t)((u).bits.manh >> 32); \ -} while(0) -#else -#define LDBL_MANH_SIZE 20 -#define LDBL_MANL_SIZE 32 - -#define LDBL_TO_ARRAY32(u, a) do { \ - (a)[0] = (uint32_t)(u).bits.manl; \ - (a)[1] = (uint32_t)(u).bits.manh; \ -} while(0) -#endif diff --git a/libm/upstream-freebsd/lib/msun/src/s_signbit.c b/libm/signbit.c similarity index 80% rename from libm/upstream-freebsd/lib/msun/src/s_signbit.c rename to libm/signbit.c index 01eb3ab8b..b98bf45c5 100644 --- a/libm/upstream-freebsd/lib/msun/src/s_signbit.c +++ b/libm/signbit.c @@ -30,29 +30,30 @@ #include "fpmath.h" -int -__signbit(double d) +int __signbit(double d) { - union IEEEd2bits u; + union IEEEd2bits u; - u.d = d; - return (u.bits.sign); + u.d = d; + return (u.bits.sign); } -int -__signbitf(float f) +int __signbitf(float f) { - union IEEEf2bits u; + union IEEEf2bits u; - u.f = f; - return (u.bits.sign); + u.f = f; + return (u.bits.sign); } -int -__signbitl(long double e) +#ifdef __LP64__ +int __signbitl(long double e) { - union IEEEl2bits u; + union IEEEl2bits u; - u.e = e; - return (u.bits.sign); + u.e = e; + return (u.bits.sign); } +#else // __LP32__ +__weak_reference(__signbit, __signbitl); +#endif // __LP64__ diff --git a/libm/upstream-freebsd/lib/msun/src/s_isfinite.c b/libm/significandl.c similarity index 78% rename from libm/upstream-freebsd/lib/msun/src/s_isfinite.c rename to libm/significandl.c index c9d1bd7a1..c5d7dd48b 100644 --- a/libm/upstream-freebsd/lib/msun/src/s_isfinite.c +++ b/libm/significandl.c @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2004 David Schultz +/* + * Copyright (C) 2014 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,36 +23,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ */ #include -#include "fpmath.h" - -int -__isfinite(double d) -{ - union IEEEd2bits u; - - u.d = d; - return (u.bits.exp != 2047); -} - -int -__isfinitef(float f) -{ - union IEEEf2bits u; - - u.f = f; - return (u.bits.exp != 255); -} - -int -__isfinitel(long double e) -{ - union IEEEl2bits u; - - u.e = e; - return (u.bits.exp != 32767); +long double significandl(long double x) { + return scalbnl(x, -ilogbl(x)); } diff --git a/libm/upstream-freebsd/lib/msun/src/s_isnormal.c b/libm/upstream-freebsd/lib/msun/src/imprecise.c similarity index 58% rename from libm/upstream-freebsd/lib/msun/src/s_isnormal.c rename to libm/upstream-freebsd/lib/msun/src/imprecise.c index 49f2a7434..a7503bf1c 100644 --- a/libm/upstream-freebsd/lib/msun/src/s_isnormal.c +++ b/libm/upstream-freebsd/lib/msun/src/imprecise.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004 David Schultz + * Copyright (c) 2013 David Chisnall * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,33 +26,44 @@ * $FreeBSD$ */ +#include #include -#include "fpmath.h" +/* + * If long double is not the same size as double, then these will lose + * precision and we should emit a warning whenever something links against + * them. + */ +#if (LDBL_MANT_DIG > 53) +#define WARN_IMPRECISE(x) \ + __warn_references(x, # x " has lower than advertised precision"); +#else +#define WARN_IMPRECISE(x) +#endif +/* + * Declare the functions as weak variants so that other libraries providing + * real versions can override them. + */ +#define DECLARE_WEAK(x)\ + __weak_reference(imprecise_## x, x);\ + WARN_IMPRECISE(x) -int -__isnormal(double d) +long double +imprecise_powl(long double x, long double y) { - union IEEEd2bits u; - u.d = d; - return (u.bits.exp != 0 && u.bits.exp != 2047); + return pow(x, y); } +DECLARE_WEAK(powl); -int -__isnormalf(float f) -{ - union IEEEf2bits u; +#define DECLARE_IMPRECISE(f) \ + long double imprecise_ ## f ## l(long double v) { return f(v); }\ + DECLARE_WEAK(f ## l) - u.f = f; - return (u.bits.exp != 0 && u.bits.exp != 255); -} - -int -__isnormall(long double e) -{ - union IEEEl2bits u; - - u.e = e; - return (u.bits.exp != 0 && u.bits.exp != 32767); -} +DECLARE_IMPRECISE(cosh); +DECLARE_IMPRECISE(erfc); +DECLARE_IMPRECISE(erf); +DECLARE_IMPRECISE(lgamma); +DECLARE_IMPRECISE(sinh); +DECLARE_IMPRECISE(tanh); +DECLARE_IMPRECISE(tgamma); diff --git a/tests/math_test.cpp b/tests/math_test.cpp index 6758af1be..0b98e40f3 100644 --- a/tests/math_test.cpp +++ b/tests/math_test.cpp @@ -1015,9 +1015,26 @@ TEST(math, nextafterl) { ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, -1.0L)); } -// TODO: nexttoward -// TODO: nexttowardf -// TODO: nexttowardl +TEST(math, nexttoward) { + ASSERT_DOUBLE_EQ(0.0, nexttoward(0.0, 0.0L)); + ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nexttoward(0.0, 1.0L)); + ASSERT_DOUBLE_EQ(0.0, nexttoward(0.0, -1.0L)); +} + +TEST(math, nexttowardf) { + ASSERT_FLOAT_EQ(0.0f, nexttowardf(0.0f, 0.0L)); + ASSERT_FLOAT_EQ(1.4012985e-45f, nexttowardf(0.0f, 1.0L)); + ASSERT_FLOAT_EQ(0.0f, nexttowardf(0.0f, -1.0L)); +} + +TEST(math, nexttowardl) { + ASSERT_DOUBLE_EQ(0.0L, nexttowardl(0.0L, 0.0L)); + // Use a runtime value to accomodate the case when + // sizeof(double) == sizeof(long double) + long double smallest_positive = ldexpl(1.0L, LDBL_MIN_EXP - LDBL_MANT_DIG); + ASSERT_DOUBLE_EQ(smallest_positive, nexttowardl(0.0L, 1.0L)); + ASSERT_DOUBLE_EQ(0.0L, nexttowardl(0.0L, -1.0L)); +} TEST(math, copysign) { ASSERT_DOUBLE_EQ(0.0, copysign(0.0, 1.0));