1 /* 2 * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23 /****************************************************************************** 24 * * 25 * File: fenv.h * 26 * * 27 * Contains: typedefs and prototypes for C99 floating point environment. * 28 * * 29 * A collection of functions designed to provide access to the floating * 30 * point environment for numerical programming. It is compliant with the * 31 * floating-point requirements in C99. * 32 * * 33 * The file <fenv.h> declares many functions in support of numerical * 34 * programming. Programs that test flags or run under non-default mode * 35 * must do so under the effect of an enabling "fenv_access" pragma: * 36 * * 37 * #pragma STDC FENV_ACCESS on * 38 * * 39 ******************************************************************************/ 40 41 #ifndef __FENV_H__ 42 #define __FENV_H__ 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 /****************************************************************************** 49 * * 50 * Architecture-specific types and macros. * 51 * * 52 * fenv_t a type for representing the entire floating-point * 53 * environment in a single object. * 54 * * 55 * fexcept_t a type for representing the floating-point * 56 * exception flag state collectively. * 57 * * 58 * FE_INEXACT macros representing the various floating-point * 59 * FE_UNDERFLOW exceptions. * 60 * FE_OVERFLOW * 61 * FE_DIVBYZERO * 62 * FE_INVALID * 63 * FE_ALL_EXCEPT * 64 * * 65 * FE_TONEAREST macros representing the various floating-point * 66 * FE_UPWARD rounding modes * 67 * FE_DOWNWARD * 68 * FE_TOWARDZERO * 69 * * 70 * FE_DFL_ENV a macro expanding to a pointer to an object * 71 * representing the default floating-point environemnt * 72 * * 73 ******************************************************************************/ 74 75 /****************************************************************************** 76 * ARM definitions of architecture-specific types and macros. * 77 ******************************************************************************/ 78 79 #if defined __arm__ && !defined __SOFTFP__ 80 81 typedef struct { 82 unsigned int __fpscr; 83 unsigned int __reserved0; 84 unsigned int __reserved1; 85 unsigned int __reserved2; 86 } fenv_t; 87 88 typedef unsigned short fexcept_t; 89 90 #define FE_INEXACT 0x0010 91 #define FE_UNDERFLOW 0x0008 92 #define FE_OVERFLOW 0x0004 93 #define FE_DIVBYZERO 0x0002 94 #define FE_INVALID 0x0001 95 /* FE_FLUSHTOZERO 96 An ARM-specific flag that is raised when a denormal is flushed to zero. 97 This is also called the "input denormal exception" */ 98 #define FE_FLUSHTOZERO 0x0080 99 #define FE_ALL_EXCEPT 0x009f 100 101 #define FE_TONEAREST 0x00000000 102 #define FE_UPWARD 0x00400000 103 #define FE_DOWNWARD 0x00800000 104 #define FE_TOWARDZERO 0x00C00000 105 106 /* Masks for values that may be controlled in the FPSCR. Modifying any other 107 bits invokes undefined behavior. */ 108 enum { 109 __fpscr_trap_invalid = 0x00000100, 110 __fpscr_trap_divbyzero = 0x00000200, 111 __fpscr_trap_overflow = 0x00000400, 112 __fpscr_trap_underflow = 0x00000800, 113 __fpscr_trap_inexact = 0x00001000, 114 __fpscr_trap_denormal = 0x00008000, 115 __fpscr_flush_to_zero = 0x01000000, 116 __fpscr_default_nan = 0x02000000, 117 __fpscr_saturation = 0x08000000, 118 }; 119 120 extern const fenv_t _FE_DFL_ENV; 121 #define FE_DFL_ENV &_FE_DFL_ENV 122 123 /****************************************************************************** 124 * ARM64 definitions of architecture-specific types and macros. * 125 ******************************************************************************/ 126 127 #elif defined __arm64__ 128 129 typedef struct { 130 unsigned long long __fpsr; 131 unsigned long long __fpcr; 132 } fenv_t; 133 134 typedef unsigned short fexcept_t; 135 136 #define FE_INEXACT 0x0010 137 #define FE_UNDERFLOW 0x0008 138 #define FE_OVERFLOW 0x0004 139 #define FE_DIVBYZERO 0x0002 140 #define FE_INVALID 0x0001 141 /* FE_FLUSHTOZERO 142 An ARM-specific flag that is raised when a denormal is flushed to zero. 143 This is also called the "input denormal exception" */ 144 #define FE_FLUSHTOZERO 0x0080 145 #define FE_ALL_EXCEPT 0x009f 146 147 #define FE_TONEAREST 0x00000000 148 #define FE_UPWARD 0x00400000 149 #define FE_DOWNWARD 0x00800000 150 #define FE_TOWARDZERO 0x00C00000 151 152 /* Masks for values that may be controlled in the FPCR. Modifying any other 153 bits invokes undefined behavior. */ 154 enum { 155 __fpcr_trap_invalid = 0x00000100, 156 __fpcr_trap_divbyzero = 0x00000200, 157 __fpcr_trap_overflow = 0x00000400, 158 __fpcr_trap_underflow = 0x00000800, 159 __fpcr_trap_inexact = 0x00001000, 160 __fpcr_trap_denormal = 0x00008000, 161 __fpcr_flush_to_zero = 0x01000000, 162 }; 163 164 /* Mask for the QC bit of the FPSR */ 165 enum { __fpsr_saturation = 0x08000000 }; 166 167 extern const fenv_t _FE_DFL_ENV; 168 #define FE_DFL_ENV &_FE_DFL_ENV 169 170 /* FE_DFL_DISABLE_DENORMS_ENV 171 172 A pointer to a fenv_t object with the default floating-point state modified 173 to set the FZ (flush to zero) bit in the FPCR. When using this environment 174 denormals encountered by floating-point calculations will be treated as 175 zero. Denormal results of floating-point operations will also be treated 176 as zero. This calculation mode is not IEEE-754 compliant, but it may 177 prevent lengthy stalls that occur in code that encounters denormals. It is 178 suggested that you do not use this mode unless you have established that 179 denormals are the source of measurable performance problems. 180 181 Note that the math library, and other system libraries, are not guaranteed 182 to do the right thing if called in this mode. Edge cases may be incorrect. 183 Use at your own risk. */ 184 extern const fenv_t _FE_DFL_DISABLE_DENORMS_ENV; 185 #define FE_DFL_DISABLE_DENORMS_ENV &_FE_DFL_DISABLE_DENORMS_ENV 186 187 /****************************************************************************** 188 * x86 definitions of architecture-specific types and macros. * 189 ******************************************************************************/ 190 191 #elif defined __i386__ || defined __x86_64__ 192 193 typedef struct { 194 unsigned short __control; /* x87 control word */ 195 unsigned short __status; /* x87 status word */ 196 unsigned int __mxcsr; /* SSE status/control register */ 197 char __reserved[8]; /* Reserved for future expansion */ 198 } fenv_t; 199 200 typedef unsigned short fexcept_t; 201 202 #define FE_INEXACT 0x0020 203 #define FE_UNDERFLOW 0x0010 204 #define FE_OVERFLOW 0x0008 205 #define FE_DIVBYZERO 0x0004 206 #define FE_INVALID 0x0001 207 /* FE_DENORMALOPERAND 208 An Intel-specific flag that is raised when an operand to a floating-point 209 arithmetic operation is denormal, or a single- or double-precision denormal 210 value is loaded on the x87 stack. This flag is not raised by SSE 211 arithmetic when the DAZ control bit is set. */ 212 #define FE_DENORMALOPERAND 0x0002 213 #define FE_ALL_EXCEPT 0x003f 214 215 #define FE_TONEAREST 0x0000 216 #define FE_DOWNWARD 0x0400 217 #define FE_UPWARD 0x0800 218 #define FE_TOWARDZERO 0x0c00 219 220 extern const fenv_t _FE_DFL_ENV; 221 #define FE_DFL_ENV &_FE_DFL_ENV 222 223 /* FE_DFL_DISABLE_SSE_DENORMS_ENV 224 225 A pointer to a fenv_t object with the default floating-point state modifed 226 to set the DAZ and FZ bits in the SSE status/control register. When using 227 this environment, denormals encountered by SSE based calculation (which 228 normally should be all single and double precision scalar floating point 229 calculations, and all SSE/SSE2/SSE3 computation) will be treated as zero. 230 Calculation results that are denormals will also be truncated to zero. 231 This calculation mode is not IEEE-754 compliant, but may prevent lengthy 232 stalls that occur in code that encounters denormals. It is suggested that 233 you do not use this mode unless you have established that denormals are 234 causing trouble for your code. Please use wisely. 235 236 CAUTION: The math library currently is not architected to do the right 237 thing in the face of DAZ + FZ mode. For example, ceil( +denormal) might 238 return +denormal rather than 1.0 in some versions of MacOS X. In some 239 circumstances this may lead to unexpected application behavior. Use at 240 your own risk. 241 242 It is not possible to disable denormal stalls for calculations performed 243 on the x87 FPU */ 244 extern const fenv_t _FE_DFL_DISABLE_SSE_DENORMS_ENV; 245 #define FE_DFL_DISABLE_SSE_DENORMS_ENV &_FE_DFL_DISABLE_SSE_DENORMS_ENV 246 247 /****************************************************************************** 248 * Totally generic definitions and macros if we don't know anything about * 249 * the target platform, or if the platform does not have hardware floating- * 250 * point support. * 251 ******************************************************************************/ 252 253 #else /* Unknown architectures */ 254 255 typedef int fenv_t; 256 typedef unsigned short fexcept_t; 257 #define FE_ALL_EXCEPT 0 258 #define FE_TONEAREST 0 259 extern const fenv_t _FE_DFL_ENV; 260 #define FE_DFL_ENV &_FE_DFL_ENV 261 262 #endif 263 264 /****************************************************************************** 265 * The following functions provide high level access to the exception flags. * 266 * The "int" input argument can be constructed by bitwise ORs of the * 267 * exception macros: for example: FE_OVERFLOW | FE_INEXACT. * 268 * * 269 * The function "feclearexcept" clears the supported floating point * 270 * exceptions represented by its argument. * 271 * * 272 * The function "fegetexceptflag" stores a implementation-defined * 273 * representation of the states of the floating-point status flags indicated * 274 * by its integer argument excepts in the object pointed to by the argument, * 275 * flagp. * 276 * * 277 * The function "feraiseexcept" raises the supported floating-point * 278 * exceptions represented by its argument. The order in which these * 279 * floating-point exceptions are raised is unspecified. * 280 * * 281 * The function "fesetexceptflag" sets or clears the floating point status * 282 * flags indicated by the argument excepts to the states stored in the * 283 * object pointed to by flagp. The value of the *flagp shall have been set * 284 * by a previous call to fegetexceptflag whose second argument represented * 285 * at least those floating-point exceptions represented by the argument * 286 * excepts. This function does not raise floating-point exceptions; it just * 287 * sets the state of the flags. * 288 * * 289 * The function "fetestexcept" determines which of the specified subset of * 290 * the floating-point exception flags are currently set. The excepts * 291 * argument specifies the floating-point status flags to be queried. This * 292 * function returns the value of the bitwise OR of the floating-point * 293 * exception macros corresponding to the currently set floating-point * 294 * exceptions included in excepts. * 295 ******************************************************************************/ 296 297 extern int feclearexcept(int /* excepts */); 298 extern int fegetexceptflag(fexcept_t * /* flagp */, int /* excepts */); 299 extern int feraiseexcept(int /* excepts */); 300 extern int fesetexceptflag(const fexcept_t * /* flagp */, int /* excepts */); 301 extern int fetestexcept(int /* excepts */); 302 303 /****************************************************************************** 304 * The following functions provide control of rounding direction modes. * 305 * * 306 * The function "fegetround" returns the value of the rounding direction * 307 * macro which represents the current rounding direction, or a negative * 308 * if there is no such rounding direction macro or the current rounding * 309 * direction is not determinable. * 310 * * 311 * The function "fesetround" establishes the rounding direction represented * 312 * by its argument "round". If the argument is not equal to the value of a * 313 * rounding direction macro, the rounding direction is not changed. It * 314 * returns zero if and only if the argument is equal to a rounding * 315 * direction macro. * 316 ******************************************************************************/ 317 318 extern int fegetround(void); 319 extern int fesetround(int /* round */); 320 321 /****************************************************************************** 322 * The following functions manage the floating-point environment, exception * 323 * flags and dynamic modes, as one entity. * 324 * * 325 * The fegetenv function stores the current floating-point enviornment in * 326 * the object pointed to by envp. * 327 * * 328 * The feholdexcept function saves the current floating-point environment in * 329 * the object pointed to by envp, clears the floating-point status flags, * 330 * and then installs a non-stop (continue on floating-point exceptions) * 331 * mode, if available, for all floating-point exceptions. The feholdexcept * 332 * function returns zero if and only if non-stop floating-point exceptions * 333 * handling was successfully installed. * 334 * * 335 * The fesetnv function establishes the floating-point environment * 336 * represented by the object pointed to by envp. The argument envp shall * 337 * point to an object set by a call to fegetenv or feholdexcept, or equal to * 338 * a floating-point environment macro to be C99 standard compliant and * 339 * portable to other architectures. Note that fesetnv merely installs the * 340 * state of the floating-point status flags represented through its * 341 * argument, and does not raise these floating-point exceptions. * 342 * * 343 * The feupdateenv function saves the currently raised floating-point * 344 * exceptions in its automatic storage, installs the floating-point * 345 * environment represented by the object pointed to by envp, and then raises * 346 * the saved floating-point exceptions. The argument envp shall point to an * 347 * object set by a call to feholdexcept or fegetenv or equal a * 348 * floating-point environment macro. * 349 ******************************************************************************/ 350 351 extern int fegetenv(fenv_t * /* envp */); 352 extern int feholdexcept(fenv_t * /* envp */); 353 extern int fesetenv(const fenv_t * /* envp */); 354 extern int feupdateenv(const fenv_t * /* envp */); 355 356 #ifdef __cplusplus 357 } 358 #endif 359 360 #endif /* __FENV_H__ */