1 /************************************************************************** 2 * 3 * Copyright 2007-2015 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /** 29 * Wrapper for math.h which makes sure we have definitions of all the c99 30 * functions. 31 */ 32 33 34 #ifndef _C99_MATH_H_ 35 #define _C99_MATH_H_ 36 37 #include <math.h> 38 #include "c99_compat.h" 39 40 41 /* This is to ensure that we get M_PI, etc. definitions */ 42 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES) 43 #error _USE_MATH_DEFINES define required when building with MSVC 44 #endif 45 46 47 #if !defined(_MSC_VER) && \ 48 __STDC_VERSION__ < 199901L && \ 49 (!defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600) && \ 50 !defined(__cplusplus) 51 52 static inline long int 53 lrint(double d) 54 { 55 long int rounded = (long int)(d + 0.5); 56 57 if (d - floor(d) == 0.5) { 58 if (rounded % 2 != 0) 59 rounded += (d > 0) ? -1 : 1; 60 } 61 62 return rounded; 63 } 64 65 static inline long int 66 lrintf(float f) 67 { 68 long int rounded = (long int)(f + 0.5f); 69 70 if (f - floorf(f) == 0.5f) { 71 if (rounded % 2 != 0) 72 rounded += (f > 0) ? -1 : 1; 73 } 74 75 return rounded; 76 } 77 78 static inline long long int 79 llrint(double d) 80 { 81 long long int rounded = (long long int)(d + 0.5); 82 83 if (d - floor(d) == 0.5) { 84 if (rounded % 2 != 0) 85 rounded += (d > 0) ? -1 : 1; 86 } 87 88 return rounded; 89 } 90 91 static inline long long int 92 llrintf(float f) 93 { 94 long long int rounded = (long long int)(f + 0.5f); 95 96 if (f - floorf(f) == 0.5f) { 97 if (rounded % 2 != 0) 98 rounded += (f > 0) ? -1 : 1; 99 } 100 101 return rounded; 102 } 103 104 static inline float 105 exp2f(float f) 106 { 107 return powf(2.0f, f); 108 } 109 110 static inline double 111 exp2(double d) 112 { 113 return pow(2.0, d); 114 } 115 116 #endif /* C99 */ 117 118 119 /* 120 * signbit() is a macro on Linux. Not available on Windows. 121 */ 122 #ifndef signbit 123 #define signbit(x) ((x) < 0.0f) 124 #endif 125 126 127 #ifndef M_PI 128 #define M_PI (3.14159265358979323846) 129 #endif 130 131 #ifndef M_E 132 #define M_E (2.7182818284590452354) 133 #endif 134 135 #ifndef M_LOG2E 136 #define M_LOG2E (1.4426950408889634074) 137 #endif 138 139 #ifndef FLT_MAX_EXP 140 #define FLT_MAX_EXP 128 141 #endif 142 143 144 #if defined(fpclassify) 145 /* ISO C99 says that fpclassify is a macro. Assume that any implementation 146 * of fpclassify, whether it's in a C99 compiler or not, will be a macro. 147 */ 148 #elif defined(__cplusplus) 149 /* For C++, fpclassify() should be defined in <cmath> */ 150 #elif defined(_MSC_VER) 151 /* Not required on VS2013 and above. Oddly, the fpclassify() function 152 * doesn't exist in such a form on MSVC. This is an implementation using 153 * slightly different lower-level Windows functions. 154 */ 155 #include <float.h> 156 157 static inline enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL} 158 fpclassify(double x) 159 { 160 switch(_fpclass(x)) { 161 case _FPCLASS_SNAN: /* signaling NaN */ 162 case _FPCLASS_QNAN: /* quiet NaN */ 163 return FP_NAN; 164 case _FPCLASS_NINF: /* negative infinity */ 165 case _FPCLASS_PINF: /* positive infinity */ 166 return FP_INFINITE; 167 case _FPCLASS_NN: /* negative normal */ 168 case _FPCLASS_PN: /* positive normal */ 169 return FP_NORMAL; 170 case _FPCLASS_ND: /* negative denormalized */ 171 case _FPCLASS_PD: /* positive denormalized */ 172 return FP_SUBNORMAL; 173 case _FPCLASS_NZ: /* negative zero */ 174 case _FPCLASS_PZ: /* positive zero */ 175 return FP_ZERO; 176 default: 177 /* Should never get here; but if we do, this will guarantee 178 * that the pattern is not treated like a number. 179 */ 180 return FP_NAN; 181 } 182 } 183 #else 184 #error "Need to include or define an fpclassify function" 185 #endif 186 187 188 /* Since C++11, the following functions are part of the std namespace. Their C 189 * counteparts should still exist in the global namespace, however cmath 190 * undefines those functions, which in glibc 2.23, are defined as macros rather 191 * than functions as in glibc 2.22. 192 */ 193 #if __cplusplus >= 201103L && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 23)) 194 #include <cmath> 195 196 using std::fpclassify; 197 using std::isfinite; 198 using std::isinf; 199 using std::isnan; 200 using std::isnormal; 201 using std::signbit; 202 using std::isgreater; 203 using std::isgreaterequal; 204 using std::isless; 205 using std::islessequal; 206 using std::islessgreater; 207 using std::isunordered; 208 #endif 209 210 211 #endif /* #define _C99_MATH_H_ */ 212