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#include <machine/ieee.h> 33 34// These aren't declared in our <math.h>. 35extern "C" int __isinf(double); 36extern "C" int __isnan(double); 37 38union float_u { 39 float f; 40 ieee_single bits; 41}; 42 43union double_u { 44 double d; 45 ieee_double bits; 46}; 47 48int __fpclassifyd(double d) { 49 double_u u; 50 u.d = d; 51 if (u.bits.dbl_exp == 0) { 52 return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_ZERO : FP_SUBNORMAL; 53 } 54 if (u.bits.dbl_exp == DBL_EXP_INFNAN) { 55 return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_INFINITE : FP_NAN; 56 } 57 return FP_NORMAL; 58} 59__strong_alias(__fpclassify, __fpclassifyd); // glibc uses __fpclassify, BSD __fpclassifyd. 60 61int __fpclassifyf(float f) { 62 float_u u; 63 u.f = f; 64 if (u.bits.sng_exp == 0) { 65 return (u.bits.sng_frac == 0) ? FP_ZERO : FP_SUBNORMAL; 66 } 67 if (u.bits.sng_exp == SNG_EXP_INFNAN) { 68 return (u.bits.sng_frac == 0) ? FP_INFINITE : FP_NAN; 69 } 70 return FP_NORMAL; 71} 72 73int __isinf(double d) { 74 return (__fpclassifyd(d) == FP_INFINITE); 75} 76__strong_alias(isinf, __isinf); 77 78int __isinff(float f) { 79 return (__fpclassifyf(f) == FP_INFINITE); 80} 81__strong_alias(isinff, __isinff); 82 83int __isnan(double d) { 84 return (__fpclassifyd(d) == FP_NAN); 85} 86__strong_alias(isnan, __isnan); 87 88int __isnanf(float f) { 89 return (__fpclassifyf(f) == FP_NAN); 90} 91__strong_alias(isnanf, __isnanf); 92 93int __isfinite(double d) { 94 int type = __fpclassifyd(d); 95 return ((type != FP_NAN) && (type != FP_INFINITE)); 96} 97__strong_alias(isfinite, __isfinite); 98 99int __isfinitef(float f) { 100 int type = __fpclassifyf(f); 101 return ((type != FP_NAN) && (type != FP_INFINITE)); 102} 103__strong_alias(isfinitef, __isfinitef); 104 105int __isnormal(double d) { 106 return (__fpclassifyd(d) == FP_NORMAL); 107} 108__strong_alias(isnormal, __isnormal); 109 110int __isnormalf(float f) { 111 return (__fpclassifyf(f) == FP_NORMAL); 112} 113__strong_alias(isnormalf, __isnormalf); 114 115#if __LP64__ 116 117// LP64 uses 128-bit long doubles. 118 119union long_double_u { 120 long double ld; 121 ieee_ext bits; 122}; 123 124#define zero_frac(b) ((b.ext_fracl | b.ext_fraclm | b.ext_frachm | b.ext_frach) == 0) 125 126int __fpclassifyl(long double ld) { 127 long_double_u u; 128 u.ld = ld; 129 if (u.bits.ext_exp == 0) { 130 return zero_frac(u.bits) ? FP_ZERO : FP_SUBNORMAL; 131 } 132 if (u.bits.ext_exp == EXT_EXP_INFNAN) { 133 return zero_frac(u.bits) ? FP_INFINITE : FP_NAN; 134 } 135 return FP_NORMAL; 136} 137 138int __isinfl(long double ld) { 139 return (__fpclassifyl(ld) == FP_INFINITE); 140} 141 142int __isnanl(long double ld) { 143 return (__fpclassifyl(ld) == FP_NAN); 144} 145 146int __isfinitel(long double ld) { 147 int type = __fpclassifyl(ld); 148 return ((type != FP_NAN) && (type != FP_INFINITE)); 149} 150 151int __isnormall(long double ld) { 152 return (__fpclassifyl(ld) == FP_NORMAL); 153} 154 155#else 156 157// LP32 uses double as long double. 158 159__strong_alias(__fpclassifyl, __fpclassify); 160__strong_alias(__isinfl, __isinf); 161__strong_alias(__isnanl, __isnan); 162__strong_alias(__isfinitel, __isfinite); 163__strong_alias(__isnormall, __isnormal); 164 165#endif 166 167__strong_alias(isinfl, __isinfl); 168__strong_alias(isnanl, __isnanl); 169__strong_alias(isfinitel, __isfinitel); 170__strong_alias(isnormall, __isnormall); 171