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>. 35 extern "C" int __isinf(double); 36 extern "C" int __isnan(double); 37 38 union float_u { 39 float f; 40 ieee_single bits; 41 }; 42 43 union double_u { 44 double d; 45 ieee_double bits; 46 }; 47 48 int __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 61 int __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 73 int __isinf(double d) { 74 return (__fpclassifyd(d) == FP_INFINITE); 75 } 76 __strong_alias(isinf, __isinf); 77 78 int __isinff(float f) { 79 return (__fpclassifyf(f) == FP_INFINITE); 80 } 81 __strong_alias(isinff, __isinff); 82 83 int __isnan(double d) { 84 return (__fpclassifyd(d) == FP_NAN); 85 } 86 __strong_alias(isnan, __isnan); 87 88 int __isnanf(float f) { 89 return (__fpclassifyf(f) == FP_NAN); 90 } 91 __strong_alias(isnanf, __isnanf); 92 93 int __isfinite(double d) { 94 int type = __fpclassifyd(d); 95 return ((type != FP_NAN) && (type != FP_INFINITE)); 96 } 97 __strong_alias(isfinite, __isfinite); 98 99 int __isfinitef(float f) { 100 int type = __fpclassifyf(f); 101 return ((type != FP_NAN) && (type != FP_INFINITE)); 102 } 103 __strong_alias(isfinitef, __isfinitef); 104 105 int __isnormal(double d) { 106 return (__fpclassifyd(d) == FP_NORMAL); 107 } 108 __strong_alias(isnormal, __isnormal); 109 110 int __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 119 union 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 126 int __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 138 int __isinfl(long double ld) { 139 return (__fpclassifyl(ld) == FP_INFINITE); 140 } 141 142 int __isnanl(long double ld) { 143 return (__fpclassifyl(ld) == FP_NAN); 144 } 145 146 int __isfinitel(long double ld) { 147 int type = __fpclassifyl(ld); 148 return ((type != FP_NAN) && (type != FP_INFINITE)); 149 } 150 151 int __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