diff options
Diffstat (limited to 'libc')
-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 | 19 | ||||
-rw-r--r-- | libc/arch-x86/include/machine/ieee.h | 18 | ||||
-rw-r--r-- | libc/bionic/fpclassify.cpp | 138 | ||||
-rw-r--r-- | libc/stdio/vfprintf.c | 35 |
6 files changed, 175 insertions, 57 deletions
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..cf06580 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 $ */ /* @@ -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 __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 { 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/stdio/vfprintf.c b/libc/stdio/vfprintf.c index d2c315d..e33c105 100644 --- a/libc/stdio/vfprintf.c +++ b/libc/stdio/vfprintf.c @@ -154,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 */ @@ -543,14 +537,14 @@ 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; @@ -1331,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 */ |