1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/types.h> 30 31#include <math.h> 32 33#include "private/bionic_ieee.h" 34 35// These aren't declared in our <math.h>. 36extern "C" int __isinf(double); 37extern "C" int __isnan(double); 38 39union float_u { 40 float f; 41 ieee_single bits; 42}; 43 44union double_u { 45 double d; 46 ieee_double bits; 47}; 48 49int __fpclassifyd(double d) { 50 double_u u; 51 u.d = d; 52 if (u.bits.dbl_exp == 0) { 53 return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_ZERO : FP_SUBNORMAL; 54 } 55 if (u.bits.dbl_exp == DBL_EXP_INFNAN) { 56 return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_INFINITE : FP_NAN; 57 } 58 return FP_NORMAL; 59} 60__strong_alias(__fpclassify, __fpclassifyd); // glibc uses __fpclassify, BSD __fpclassifyd. 61 62int __fpclassifyf(float f) { 63 float_u u; 64 u.f = f; 65 if (u.bits.sng_exp == 0) { 66 return (u.bits.sng_frac == 0) ? FP_ZERO : FP_SUBNORMAL; 67 } 68 if (u.bits.sng_exp == SNG_EXP_INFNAN) { 69 return (u.bits.sng_frac == 0) ? FP_INFINITE : FP_NAN; 70 } 71 return FP_NORMAL; 72} 73 74int __isinf(double d) { 75 return (__fpclassifyd(d) == FP_INFINITE); 76} 77__strong_alias(isinf, __isinf); 78 79int __isinff(float f) { 80 return (__fpclassifyf(f) == FP_INFINITE); 81} 82__strong_alias(isinff, __isinff); 83 84int __isnan(double d) { 85 return (__fpclassifyd(d) == FP_NAN); 86} 87__strong_alias(isnan, __isnan); 88 89int __isnanf(float f) { 90 return (__fpclassifyf(f) == FP_NAN); 91} 92__strong_alias(isnanf, __isnanf); 93 94int __isfinite(double d) { 95 int type = __fpclassifyd(d); 96 return ((type != FP_NAN) && (type != FP_INFINITE)); 97} 98__strong_alias(isfinite, __isfinite); 99 100int __isfinitef(float f) { 101 int type = __fpclassifyf(f); 102 return ((type != FP_NAN) && (type != FP_INFINITE)); 103} 104__strong_alias(isfinitef, __isfinitef); 105 106int __isnormal(double d) { 107 return (__fpclassifyd(d) == FP_NORMAL); 108} 109__strong_alias(isnormal, __isnormal); 110 111int __isnormalf(float f) { 112 return (__fpclassifyf(f) == FP_NORMAL); 113} 114__strong_alias(isnormalf, __isnormalf); 115 116#if defined(__LP64__) 117 118// LP64 uses 128-bit long doubles. 119 120union long_double_u { 121 long double ld; 122 ieee_ext bits; 123}; 124 125#define zero_frac(b) ((b.ext_fracl | b.ext_fraclm | b.ext_frachm | b.ext_frach) == 0) 126 127int __fpclassifyl(long double ld) { 128 long_double_u u; 129 u.ld = ld; 130 if (u.bits.ext_exp == 0) { 131 return zero_frac(u.bits) ? FP_ZERO : FP_SUBNORMAL; 132 } 133 if (u.bits.ext_exp == EXT_EXP_INFNAN) { 134 return zero_frac(u.bits) ? FP_INFINITE : FP_NAN; 135 } 136 return FP_NORMAL; 137} 138 139int __isinfl(long double ld) { 140 return (__fpclassifyl(ld) == FP_INFINITE); 141} 142 143int __isnanl(long double ld) { 144 return (__fpclassifyl(ld) == FP_NAN); 145} 146 147int __isfinitel(long double ld) { 148 int type = __fpclassifyl(ld); 149 return ((type != FP_NAN) && (type != FP_INFINITE)); 150} 151 152int __isnormall(long double ld) { 153 return (__fpclassifyl(ld) == FP_NORMAL); 154} 155 156#else 157 158// LP32 uses double as long double. 159 160__strong_alias(__fpclassifyl, __fpclassify); 161__strong_alias(__isinfl, __isinf); 162__strong_alias(__isnanl, __isnan); 163__strong_alias(__isfinitel, __isfinite); 164__strong_alias(__isnormall, __isnormal); 165 166#endif 167 168__strong_alias(isinfl, __isinfl); 169__strong_alias(isnanl, __isnanl); 170__strong_alias(isfinitel, __isfinitel); 171__strong_alias(isnormall, __isnormall); 172