diff options
| -rw-r--r-- | benchmarks/math_benchmark.cpp | 109 | ||||
| -rw-r--r-- | libc/Android.mk | 3 | ||||
| -rw-r--r-- | libc/arch-arm/include/machine/ieee.h | 19 | ||||
| -rw-r--r-- | libc/arch-arm64/include/machine/ieee.h | 107 | ||||
| -rw-r--r-- | libc/arch-x86/include/machine/ieee.h | 18 | ||||
| -rw-r--r-- | libc/bionic/fpclassify.cpp | 138 | ||||
| -rw-r--r-- | libc/bionic/wchar.cpp | 1 | ||||
| -rw-r--r-- | libc/include/wchar.h | 1 | ||||
| -rw-r--r-- | libc/stdio/vfprintf.c | 57 | ||||
| -rw-r--r-- | libm/Android.mk | 8 | ||||
| -rw-r--r-- | libm/arm64/_fpmath.h | 13 | ||||
| -rw-r--r-- | libm/fake_long_double.c | 8 | ||||
| -rw-r--r-- | libm/fpclassify.c | 94 | ||||
| -rw-r--r-- | libm/fpmath.h | 23 | ||||
| -rw-r--r-- | libm/isinf.c | 68 | ||||
| -rw-r--r-- | libm/upstream-freebsd/lib/msun/src/s_isnan.c | 65 | ||||
| -rw-r--r-- | tests/math_test.cpp | 12 | ||||
| -rw-r--r-- | tests/stdio_test.cpp | 19 |
18 files changed, 336 insertions, 427 deletions
diff --git a/benchmarks/math_benchmark.cpp b/benchmarks/math_benchmark.cpp index a8c1cfa..3602de4 100644 --- a/benchmarks/math_benchmark.cpp +++ b/benchmarks/math_benchmark.cpp @@ -60,3 +60,112 @@ static void BM_math_logb(int iters) { StopBenchmarkTiming(); } BENCHMARK(BM_math_logb); + +static void BM_math_isinf_NORMAL(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = 1234.0; // FP_NORMAL + for (int i = 0; i < iters; ++i) { + d += (isinf)(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_isinf_NORMAL); + +static void BM_math_isinf_NAN(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = nan(""); // FP_NAN + for (int i = 0; i < iters; ++i) { + d += (isinf)(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_isinf_NAN); + +static void BM_math_isinf_INFINITE(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = HUGE_VAL; // FP_INFINITE + for (int i = 0; i < iters; ++i) { + d += (isinf)(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_isinf_INFINITE); + +static void BM_math_isinf_ZERO(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = 0.0; // FP_ZERO + for (int i = 0; i < iters; ++i) { + d += (isinf)(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_isinf_ZERO); + + + + + + +static void BM_math_fpclassify_NORMAL(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = 1234.0; // FP_NORMAL + for (int i = 0; i < iters; ++i) { + d += fpclassify(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_fpclassify_NORMAL); + +static void BM_math_fpclassify_NAN(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = nan(""); // FP_NAN + for (int i = 0; i < iters; ++i) { + d += fpclassify(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_fpclassify_NAN); + +static void BM_math_fpclassify_INFINITE(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = HUGE_VAL; // FP_INFINITE + for (int i = 0; i < iters; ++i) { + d += fpclassify(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_fpclassify_INFINITE); + +static void BM_math_fpclassify_ZERO(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = 0.0; // FP_ZERO + for (int i = 0; i < iters; ++i) { + d += fpclassify(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_fpclassify_ZERO); diff --git a/libc/Android.mk b/libc/Android.mk index beb2cb1..b94e573 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -132,6 +132,7 @@ libc_bionic_src_files := \ bionic/ffs.cpp \ bionic/flockfile.cpp \ bionic/fork.cpp \ + bionic/fpclassify.cpp \ bionic/futimens.cpp \ bionic/getauxval.cpp \ bionic/getcwd.cpp \ @@ -547,7 +548,7 @@ LOCAL_SRC_FILES := $(libc_upstream_freebsd_src_files) LOCAL_CFLAGS := \ $(libc_common_cflags) \ -I$(LOCAL_PATH)/upstream-freebsd \ - -I$(LOCAL_PATH)/upstream-freebsd/libc/include \ + -I$(LOCAL_PATH)/upstream-freebsd/lib/libc/include \ -include upstream-freebsd/freebsd-compat.h LOCAL_CONLYFLAGS := $(libc_common_conlyflags) LOCAL_CPPFLAGS := $(libc_common_cppflags) diff --git a/libc/arch-arm/include/machine/ieee.h b/libc/arch-arm/include/machine/ieee.h index 5f9b89e..cf06580 100644 --- a/libc/arch-arm/include/machine/ieee.h +++ b/libc/arch-arm/include/machine/ieee.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ +/* $OpenBSD: ieee.h,v 1.4 2011/11/08 17:06:51 deraadt Exp $ */ /* $NetBSD: ieee.h,v 1.2 2001/02/21 17:43:50 bjh21 Exp $ */ /* @@ -92,35 +92,36 @@ #define SNG_FRACBITS 23 #define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 #define DBL_FRACBITS 52 #ifndef __VFP_FP__ #define E80_EXPBITS 15 +#define E80_FRACHBITS 31 +#define E80_FRACLBITS 32 #define E80_FRACBITS 64 #define EXT_EXPBITS 15 +#define EXT_FRACHBITS 16 +#define EXT_FRACHMBITS 32 +#define EXT_FRACLMBITS 32 +#define EXT_FRACLBITS 32 #define EXT_FRACBITS 112 #endif struct ieee_single { u_int sng_frac:23; - u_int sng_exponent:8; + u_int sng_exp:8; u_int sng_sign:1; }; #ifdef __VFP_FP__ struct ieee_double { -#ifdef __ARMEB__ - u_int dbl_sign:1; - u_int dbl_exp:11; - u_int dbl_frach:20; - u_int dbl_fracl; -#else /* !__ARMEB__ */ u_int dbl_fracl; u_int dbl_frach:20; u_int dbl_exp:11; u_int dbl_sign:1; -#endif /* !__ARMEB__ */ }; #else /* !__VFP_FP__ */ struct ieee_double { diff --git a/libc/arch-arm64/include/machine/ieee.h b/libc/arch-arm64/include/machine/ieee.h index cf2c1fc..a6c024e 100644 --- a/libc/arch-arm64/include/machine/ieee.h +++ b/libc/arch-arm64/include/machine/ieee.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */ +/* $OpenBSD: ieee.h,v 1.4 2011/11/08 17:06:51 deraadt Exp $ */ /* $NetBSD: ieee.h,v 1.2 2001/02/21 17:43:50 bjh21 Exp $ */ /* @@ -50,111 +50,27 @@ * floating point. */ -/* - * Define the number of bits in each fraction and exponent. - * - * k k+1 - * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented - * - * (-exp_bias+1) - * as fractions that look like 0.fffff x 2 . This means that - * - * -126 - * the number 0.10000 x 2 , for instance, is the same as the normalized - * - * -127 -128 - * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero - * - * -129 - * in the fraction; to represent 2 , we need two, and so on. This - * - * (-exp_bias-fracbits+1) - * implies that the smallest denormalized number is 2 - * - * for whichever format we are talking about: for single precision, for - * - * -126 -149 - * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and - * - * -149 == -127 - 23 + 1. - */ - -/* - * The ARM has two sets of FP data formats. The FPA supports 32-bit, 64-bit - * and 96-bit IEEE formats, with the words in big-endian order. VFP supports - * 32-bin and 64-bit IEEE formats with the words in the CPU's native byte - * order. - * - * The FPA also has two packed decimal formats, but we ignore them here. - */ - #define SNG_EXPBITS 8 #define SNG_FRACBITS 23 #define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 #define DBL_FRACBITS 52 -#ifndef __VFP_FP__ -#define E80_EXPBITS 15 -#define E80_FRACBITS 64 - -#define EXT_EXPBITS 15 -#define EXT_FRACBITS 112 -#endif - struct ieee_single { u_int sng_frac:23; - u_int sng_exponent:8; + u_int sng_exp:8; u_int sng_sign:1; }; -#ifdef __VFP_FP__ struct ieee_double { -#ifdef __AARCH64EB__ - u_int dbl_sign:1; - u_int dbl_exp:11; - u_int dbl_frach:20; u_int dbl_fracl; -#else /* !__AARCH64EB__ */ - u_int dbl_fracl; - u_int dbl_frach:20; - u_int dbl_exp:11; - u_int dbl_sign:1; -#endif /* !__AARCH64EB__ */ -}; -#else /* !__VFP_FP__ */ -struct ieee_double { u_int dbl_frach:20; u_int dbl_exp:11; u_int dbl_sign:1; - u_int dbl_fracl; -}; - -union ieee_double_u { - double dblu_d; - struct ieee_double dblu_dbl; }; - -struct ieee_e80 { - u_int e80_exp:15; - u_int e80_zero:16; - u_int e80_sign:1; - u_int e80_frach:31; - u_int e80_j:1; - u_int e80_fracl; -}; - -struct ieee_ext { - u_int ext_frach:16; - u_int ext_exp:15; - u_int ext_sign:1; - u_int ext_frachm; - u_int ext_fraclm; - u_int ext_fracl; -}; -#endif /* !__VFP_FP__ */ - /* * Floats whose exponent is in [1..INFNAN) (of whatever type) are * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. @@ -166,26 +82,11 @@ struct ieee_ext { */ #define SNG_EXP_INFNAN 255 #define DBL_EXP_INFNAN 2047 -#ifndef __VFP_FP__ -#define E80_EXP_INFNAN 32767 #define EXT_EXP_INFNAN 32767 -#endif /* !__VFP_FP__ */ - -#if 0 -#define SNG_QUIETNAN (1 << 22) -#define DBL_QUIETNAN (1 << 19) -#ifndef __VFP_FP__ -#define E80_QUIETNAN (1 << 15) -#define EXT_QUIETNAN (1 << 15) -#endif /* !__VFP_FP__ */ -#endif /* * Exponent biases. */ #define SNG_EXP_BIAS 127 #define DBL_EXP_BIAS 1023 -#ifndef __VFP_FP__ -#define E80_EXP_BIAS 16383 #define EXT_EXP_BIAS 16383 -#endif /* !__VFP_FP__ */ diff --git a/libc/arch-x86/include/machine/ieee.h b/libc/arch-x86/include/machine/ieee.h index 55b3703..865fcb9 100644 --- a/libc/arch-x86/include/machine/ieee.h +++ b/libc/arch-x86/include/machine/ieee.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee.h,v 1.2 2003/06/02 23:27:47 millert Exp $ */ +/* $OpenBSD: ieee.h,v 1.3 2008/09/07 20:36:06 martynas Exp $ */ /* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ /* @@ -79,10 +79,19 @@ #define SNG_FRACBITS 23 #define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 #define DBL_FRACBITS 52 #define EXT_EXPBITS 15 -#define EXT_FRACBITS 112 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 64 + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ +} while(0) struct ieee_single { u_int sng_frac:23; @@ -99,11 +108,10 @@ struct ieee_double { struct ieee_ext { u_int ext_fracl; - u_int ext_fraclm; - u_int ext_frachm; - u_int ext_frach:16; + u_int ext_frach; u_int ext_exp:15; u_int ext_sign:1; + u_int ext_pad:16; }; /* diff --git a/libc/bionic/fpclassify.cpp b/libc/bionic/fpclassify.cpp new file mode 100644 index 0000000..8231093 --- /dev/null +++ b/libc/bionic/fpclassify.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * 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. + * * 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 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. + */ + +#include <sys/types.h> + +#include <math.h> +#include <machine/ieee.h> + +// These aren't declared in our <math.h>. +extern "C" int __isinf(double); +extern "C" int __isnan(double); + +union float_u { + float f; + ieee_single bits; +}; + +union double_u { + double d; + ieee_double bits; +}; + +int __fpclassifyd(double d) { + double_u u; + u.d = d; + if (u.bits.dbl_exp == 0) { + return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_ZERO : FP_SUBNORMAL; + } + if (u.bits.dbl_exp == DBL_EXP_INFNAN) { + return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_INFINITE : FP_NAN; + } + return FP_NORMAL; +} +__strong_alias(__fpclassify, __fpclassifyd); // glibc uses __fpclassify, BSD __fpclassifyd. + +int __fpclassifyf(float f) { + float_u u; + u.f = f; + if (u.bits.sng_exp == 0) { + return (u.bits.sng_frac == 0) ? FP_ZERO : FP_SUBNORMAL; + } + if (u.bits.sng_exp == SNG_EXP_INFNAN) { + return (u.bits.sng_frac == 0) ? FP_INFINITE : FP_NAN; + } + return FP_NORMAL; +} + +int __isinf(double d) { + return (__fpclassifyd(d) == FP_INFINITE); +} +__strong_alias(isinf, __isinf); + +int __isinff(float f) { + return (__fpclassifyf(f) == FP_INFINITE); +} +__strong_alias(isinff, __isinff); + +int __isnan(double d) { + return (__fpclassifyd(d) == FP_NAN); +} +__strong_alias(isnan, __isnan); + +int __isnanf(float f) { + return (__fpclassifyf(f) == FP_NAN); +} +__strong_alias(isnanf, __isnanf); + +#if __LP64__ + +// LP64 uses 128-bit long doubles. + +union long_double_u { + long double ld; + struct { + unsigned long fracl:64; + unsigned long frach:48; + unsigned int exp:15; + unsigned int sign:1; + } bits; +}; + +int __fpclassifyl(long double ld) { + long_double_u u; + u.ld = ld; + if (u.bits.exp == 0) { + return ((u.bits.fracl | u.bits.frach) == 0) ? FP_ZERO : FP_SUBNORMAL; + } + if (u.bits.exp == EXT_EXP_INFNAN) { + return ((u.bits.fracl | u.bits.frach) == 0) ? FP_INFINITE : FP_NAN; + } + return FP_NORMAL; +} + +int __isinfl(long double ld) { + return (__fpclassifyl(ld) == FP_INFINITE); +} + +int __isnanl(long double ld) { + return (__fpclassifyl(ld) == FP_NAN); +} + +#else + +// LP32 uses double as long double. + +__strong_alias(__fpclassifyl, __fpclassify); +__strong_alias(__isinfl, __isinf); +__strong_alias(__isnanl, __isnan); + +#endif + +__strong_alias(isinfl, __isinfl); +__strong_alias(isnanl, __isnanl); diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp index 8d56458..8367817 100644 --- a/libc/bionic/wchar.cpp +++ b/libc/bionic/wchar.cpp @@ -97,6 +97,7 @@ int swscanf(const wchar_t* /*s*/, const wchar_t* /*format*/, ... ) { int iswalnum(wint_t wc) { return isalnum(wc); } int iswalpha(wint_t wc) { return isalpha(wc); } +int iswblank(wint_t wc) { return isblank(wc); } int iswcntrl(wint_t wc) { return iscntrl(wc); } int iswdigit(wint_t wc) { return isdigit(wc); } int iswgraph(wint_t wc) { return isgraph(wc); } diff --git a/libc/include/wchar.h b/libc/include/wchar.h index 89c6fb6..04818b9 100644 --- a/libc/include/wchar.h +++ b/libc/include/wchar.h @@ -70,6 +70,7 @@ extern int fwprintf(FILE *, const wchar_t *, ...); extern int fwscanf(FILE *, const wchar_t *, ...); extern int iswalnum(wint_t); extern int iswalpha(wint_t); +extern int iswblank(wint_t); extern int iswcntrl(wint_t); extern int iswdigit(wint_t); extern int iswgraph(wint_t); diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c index efc8fd0..e33c105 100644 --- a/libc/stdio/vfprintf.c +++ b/libc/stdio/vfprintf.c @@ -146,6 +146,7 @@ __sbprintf(FILE *fp, const char *fmt, va_list ap) #define DEFPREC 6 static char *cvt(double, int, int, char *, int *, int, int *); +extern void freedtoa(char *); static int exponent(char *, int, int); #else /* no FLOATING_POINT */ #define BUF 40 @@ -153,12 +154,6 @@ static int exponent(char *, int, int); #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ -/* BIONIC: do not link libm for only two rather simple functions */ -#ifdef FLOATING_POINT -static int _my_isinf(double); -static int _my_isnan(double); -#endif - /* * Macros for converting digits to letters and vice versa */ @@ -201,7 +196,6 @@ __vfprintf(FILE *fp, const char *fmt0, __va_list ap) int ch; /* character from fmt */ int n, m, n2; /* handy integers (short term usage) */ char *cp; /* handy char pointer (short term usage) */ - char *cp_free = NULL; /* BIONIC: copy of cp to be freed after usage */ struct __siov *iovp; /* for PRINT macro */ int flags; /* flags as above */ int ret; /* return value accumulator */ @@ -218,6 +212,7 @@ __vfprintf(FILE *fp, const char *fmt0, __va_list ap) int expsize = 0; /* character count for expstr */ int ndig; /* actual number of digits returned by cvt */ char expstr[7]; /* buffer for exponent string */ + char *dtoaresult = NULL; #endif uintmax_t _umax; /* integer arguments %[diouxX] */ @@ -542,23 +537,23 @@ reswitch: switch (ch) { } /* do this before tricky precision changes */ - if (_my_isinf(_double)) { + if (isinf(_double)) { if (_double < 0) sign = '-'; cp = "Inf"; size = 3; break; } - if (_my_isnan(_double)) { + if (isnan(_double)) { cp = "NaN"; size = 3; break; } + if (dtoaresult != NULL) freedtoa(dtoaresult); flags |= FPT; - cp = cvt(_double, prec, flags, &softsign, + dtoaresult = cp = cvt(_double, prec, flags, &softsign, &expt, ch, &ndig); - cp_free = cp; if (ch == 'g' || ch == 'G') { if (expt <= -4 || expt > prec) ch = (ch == 'g') ? 'e' : 'E'; @@ -845,21 +840,14 @@ number: if ((dprec = prec) >= 0) ret += width > realsz ? width : realsz; FLUSH(); /* copy out the I/O vectors */ -#if 1 /* BIONIC: remove memory leak when printing doubles */ - if (cp_free) { - free(cp_free); - cp_free = NULL; - } -#endif } done: FLUSH(); error: -#if 1 /* BIONIC: remove memory leak when printing doubles */ - if (cp_free) { - free(cp_free); - cp_free = NULL; - } +#ifdef FLOATING_POINT + if (dtoaresult != NULL) { + freedtoa(dtoaresult); + } #endif if (argtable != NULL && argtable != statargtable) { munmap(argtable, argtablesiz); @@ -1337,29 +1325,4 @@ exponent(char *p0, int exp, int fmtch) return (p - p0); } - -/* BIONIC */ -#include <machine/ieee.h> -typedef union { - double d; - struct ieee_double i; -} ieee_u; - -static int -_my_isinf (double value) -{ - ieee_u u; - - u.d = value; - return (u.i.dbl_exp == 2047 && u.i.dbl_frach == 0 && u.i.dbl_fracl == 0); -} - -static int -_my_isnan (double value) -{ - ieee_u u; - - u.d = value; - return (u.i.dbl_exp == 2047 && (u.i.dbl_frach != 0 || u.i.dbl_fracl != 0)); -} #endif /* FLOATING_POINT */ diff --git a/libm/Android.mk b/libm/Android.mk index aea4662..1bd428d 100644 --- a/libm/Android.mk +++ b/libm/Android.mk @@ -1,10 +1,10 @@ LOCAL_PATH:= $(call my-dir) -# TODO: these come from from upstream's libc, not libm! +# TODO: this comes from from upstream's libc, not libm, but it's an +# implementation detail that should have hidden visibility, so it needs +# to be in whatever library the math code is in. libm_common_src_files := \ digittoint.c \ - fpclassify.c \ - isinf.c \ # TODO: this is not in the BSDs. libm_common_src_files += \ @@ -129,7 +129,6 @@ libm_common_src_files += \ 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_isnan.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 \ @@ -237,6 +236,7 @@ libm_common_cflags := \ -include $(LOCAL_PATH)/freebsd-compat.h \ libm_common_includes := $(LOCAL_PATH)/upstream-freebsd/lib/msun/src/ + libm_ld_includes := $(LOCAL_PATH)/upstream-freebsd/lib/msun/ld128/ # diff --git a/libm/arm64/_fpmath.h b/libm/arm64/_fpmath.h index 9f46640..560d53a 100644 --- a/libm/arm64/_fpmath.h +++ b/libm/arm64/_fpmath.h @@ -33,28 +33,15 @@ union IEEEl2bits { long double e; struct { -#ifndef __AARCH64EB__ unsigned long manl :64; unsigned long manh :48; unsigned int exp :15; unsigned int sign :1; -#else - unsigned int sign :1; - unsigned int exp :15; - unsigned long manh :48; - unsigned long manl :64; -#endif } bits; struct { -#ifndef __AARCH64EB__ unsigned long manl :64; unsigned long manh :48; unsigned int expsign :16; -#else - unsigned int expsign :16; - unsigned long manh :48; - unsigned long manl :64; -#endif } xbits; }; diff --git a/libm/fake_long_double.c b/libm/fake_long_double.c index b5b264b..611512a 100644 --- a/libm/fake_long_double.c +++ b/libm/fake_long_double.c @@ -17,11 +17,6 @@ #include <float.h> #include <math.h> -extern int __isinf(double); /* isinf.c */ -int (isinf)(double a1) { return __isinf(a1); } - -int (isnanf)(float a1) { return __isnanf(a1); } - /* * On LP64 sizeof(long double) > sizeof(double) so functions which fall back * to their double variants lose precision. Emit a warning whenever something @@ -58,10 +53,7 @@ WARN_IMPRECISE(powl) * that call the regular "double" function. */ -int __fpclassifyl(long double a1) { return __fpclassifyd(a1); } int __isfinitel(long double a1) { return __isfinite(a1); } -int __isinfl(long double a1) { return __isinf(a1); } -int __isnanl(long double a1) { return (isnan)(a1); } int __isnormall(long double a1) { return __isnormal(a1); } int __signbitl(long double a1) { return __signbit(a1); } diff --git a/libm/fpclassify.c b/libm/fpclassify.c deleted file mode 100644 index a039138..0000000 --- a/libm/fpclassify.c +++ /dev/null @@ -1,94 +0,0 @@ -/*- - * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org> - * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG> - * 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/gen/fpclassify.c,v 1.2 2005/02/06 03:23:31 das Exp $ - */ - -#include <sys/endian.h> - -#include <math.h> -#include <stdint.h> - -#include "fpmath.h" - -int -__fpclassifyf(float f) -{ - union IEEEf2bits u; - - u.f = f; - if (u.bits.exp == 0) { - if (u.bits.man == 0) - return (FP_ZERO); - return (FP_SUBNORMAL); - } - if (u.bits.exp == 255) { - if (u.bits.man == 0) - return (FP_INFINITE); - return (FP_NAN); - } - return (FP_NORMAL); -} - -int -__fpclassifyd(double d) -{ - union IEEEd2bits u; - - u.d = d; - if (u.bits.exp == 0) { - if ((u.bits.manl | u.bits.manh) == 0) - return (FP_ZERO); - return (FP_SUBNORMAL); - } - if (u.bits.exp == 2047) { - if ((u.bits.manl | u.bits.manh) == 0) - return (FP_INFINITE); - return (FP_NAN); - } - return (FP_NORMAL); -} - -int -__fpclassifyl(long double e) -{ - union IEEEl2bits u; - - u.e = e; - if (u.bits.exp == 0) { - if ((u.bits.manl | u.bits.manh) == 0) - return (FP_ZERO); - return (FP_SUBNORMAL); - } - mask_nbit_l(u); /* Mask normalization bit if applicable. */ - if (u.bits.exp == 32767) { - if ((u.bits.manl | u.bits.manh) == 0) - return (FP_INFINITE); - return (FP_NAN); - } - return (FP_NORMAL); -} - diff --git a/libm/fpmath.h b/libm/fpmath.h index a7c612c..e76771d 100644 --- a/libm/fpmath.h +++ b/libm/fpmath.h @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/include/fpmath.h,v 1.3 2005/02/06 03:23:31 das Exp $ + * $FreeBSD$ */ #ifndef _FPMATH_ @@ -33,10 +33,14 @@ #include <endian.h> #include "_fpmath.h" +#ifndef _IEEE_WORD_ORDER +#define _IEEE_WORD_ORDER _BYTE_ORDER +#endif + union IEEEf2bits { float f; struct { -#if __BYTE_ORDER == __LITTLE_ENDIAN +#if _BYTE_ORDER == _LITTLE_ENDIAN unsigned int man :23; unsigned int exp :8; unsigned int sign :1; @@ -54,18 +58,17 @@ union IEEEf2bits { union IEEEd2bits { double d; struct { -/* #ifdef __ARMEB__ */ -#if (__BYTE_ORDER == __BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__)) - unsigned int manh :20; - unsigned int exp :11; - unsigned int sign :1; - unsigned int manl :32; -#elif __BYTE_ORDER == __LITTLE_ENDIAN +#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; -#elif __BYTE_ORDER == __BIG_ENDIAN +#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; diff --git a/libm/isinf.c b/libm/isinf.c deleted file mode 100644 index c917f16..0000000 --- a/libm/isinf.c +++ /dev/null @@ -1,68 +0,0 @@ -/*- - * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG> - * 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$ - */ - -#include <math.h> -#include <sys/cdefs.h> -#include "fpmath.h" - -/* - * XXX These routines belong in libm, but they must remain in libc for - * binary compat until we can bump libm's major version number. - */ - -int -__isinf(double d) -{ - union IEEEd2bits u; - - u.d = d; - return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0); -} - -int -__isinff(float f) -{ - union IEEEf2bits u; - - u.f = f; - return (u.bits.exp == 255 && u.bits.man == 0); -} - -int -__isinfl(long double e) -{ - union IEEEl2bits u; - - u.e = e; - mask_nbit_l(u); -#ifndef __alpha__ - return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0); -#else - return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0); -#endif -} diff --git a/libm/upstream-freebsd/lib/msun/src/s_isnan.c b/libm/upstream-freebsd/lib/msun/src/s_isnan.c deleted file mode 100644 index a54ded3..0000000 --- a/libm/upstream-freebsd/lib/msun/src/s_isnan.c +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG> - * 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$ - */ - -#include <math.h> - -#include "fpmath.h" - -/* Provided by libc.so */ -#ifndef PIC -#undef isnan -int -isnan(double d) -{ - union IEEEd2bits u; - - u.d = d; - return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); -} -#endif /* !PIC */ - -int -__isnanf(float f) -{ - union IEEEf2bits u; - - u.f = f; - return (u.bits.exp == 255 && u.bits.man != 0); -} - -int -__isnanl(long double e) -{ - union IEEEl2bits u; - - u.e = e; - mask_nbit_l(u); - return (u.bits.exp == 32767 && (u.bits.manl != 0 || u.bits.manh != 0)); -} - -__weak_reference(__isnanf, isnanf); diff --git a/tests/math_test.cpp b/tests/math_test.cpp index 7734018..6758af1 100644 --- a/tests/math_test.cpp +++ b/tests/math_test.cpp @@ -239,6 +239,12 @@ TEST(math, finite) { ASSERT_FALSE(finite(HUGE_VAL)); } +TEST(math, isinf_function) { + // The isinf macro deals with all three types; the isinf function is for doubles. + ASSERT_FALSE((isinf)(123.0)); + ASSERT_TRUE((isinf)(HUGE_VAL)); +} + TEST(math, __isinff) { ASSERT_FALSE(__isinff(123.0f)); ASSERT_TRUE(__isinff(HUGE_VALF)); @@ -249,6 +255,12 @@ TEST(math, __isinfl) { ASSERT_TRUE(__isinfl(HUGE_VALL)); } +TEST(math, isnan_function) { + // The isnan macro deals with all three types; the isnan function is for doubles. + ASSERT_FALSE((isnan)(123.0)); + ASSERT_TRUE((isnan)(nan(""))); +} + TEST(math, __isnanf) { ASSERT_FALSE(__isnanf(123.0f)); ASSERT_TRUE(__isnanf(nanf(""))); diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index cc1fd85..0aa1d15 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -18,6 +18,7 @@ #include <errno.h> #include <limits.h> +#include <math.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> @@ -302,6 +303,24 @@ TEST(stdio, snprintf_smoke) { EXPECT_STREQ("print_me_twice print_me_twice", buf); } +TEST(stdio, snprintf_f_special) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%f", nanf("")); + EXPECT_STREQ("NaN", buf); + + snprintf(buf, sizeof(buf), "%f", HUGE_VALF); + EXPECT_STREQ("Inf", buf); +} + +TEST(stdio, snprintf_g_special) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%g", nan("")); + EXPECT_STREQ("NaN", buf); + + snprintf(buf, sizeof(buf), "%g", HUGE_VAL); + EXPECT_STREQ("Inf", buf); +} + TEST(stdio, snprintf_d_INT_MAX) { char buf[BUFSIZ]; snprintf(buf, sizeof(buf), "%d", INT_MAX); |
