| 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 | #elif defined __riscv |
| 254 | |
| 255 | typedef struct { |
| 256 | unsigned int __fpsr; |
| 257 | unsigned int __fpcr; |
| 258 | } fenv_t; |
| 259 | |
| 260 | typedef unsigned short fexcept_t; |
| 261 | |
| 262 | #define FE_INEXACT (1) |
| 263 | #define FE_UNDERFLOW (1 << 1) |
| 264 | #define FE_OVERFLOW (1 << 2) |
| 265 | #define FE_DIVBYZERO (1 << 3) |
| 266 | #define FE_INVALID (1 << 4) |
| 267 | |
| 268 | #define FE_ALL_EXCEPT (31) |
| 269 | |
| 270 | #define FE_TONEAREST (0) |
| 271 | #define FE_TOWARDZERO (1 << 5) |
| 272 | #define FE_DOWNWARD (2 << 5) |
| 273 | #define FE_UPWARD (3 << 5) |
| 274 | #define FE_TONEAREST_MAX_MAGNITUDE (4 << 5) |
| 275 | // Reserved: (5 << 5) |
| 276 | // Reserved: (6 << 5) |
| 277 | #define FE_DYNAMIC (7 << 5) |
| 278 | |
| 279 | #else /* Unknown architectures */ |
| 280 | |
| 281 | typedef int fenv_t; |
| 282 | typedef unsigned short fexcept_t; |
| 283 | #define FE_ALL_EXCEPT 0 |
| 284 | #define FE_TONEAREST 0 |
| 285 | extern const fenv_t _FE_DFL_ENV; |
| 286 | #define FE_DFL_ENV &_FE_DFL_ENV |
| 287 | |
| 288 | #endif |
| 289 | |
| 290 | /****************************************************************************** |
| 291 | * The following functions provide high level access to the exception flags. * |
| 292 | * The "int" input argument can be constructed by bitwise ORs of the * |
| 293 | * exception macros: for example: FE_OVERFLOW | FE_INEXACT. * |
| 294 | * * |
| 295 | * The function "feclearexcept" clears the supported floating point * |
| 296 | * exceptions represented by its argument. * |
| 297 | * * |
| 298 | * The function "fegetexceptflag" stores a implementation-defined * |
| 299 | * representation of the states of the floating-point status flags indicated * |
| 300 | * by its integer argument excepts in the object pointed to by the argument, * |
| 301 | * flagp. * |
| 302 | * * |
| 303 | * The function "feraiseexcept" raises the supported floating-point * |
| 304 | * exceptions represented by its argument. The order in which these * |
| 305 | * floating-point exceptions are raised is unspecified. * |
| 306 | * * |
| 307 | * The function "fesetexceptflag" sets or clears the floating point status * |
| 308 | * flags indicated by the argument excepts to the states stored in the * |
| 309 | * object pointed to by flagp. The value of the *flagp shall have been set * |
| 310 | * by a previous call to fegetexceptflag whose second argument represented * |
| 311 | * at least those floating-point exceptions represented by the argument * |
| 312 | * excepts. This function does not raise floating-point exceptions; it just * |
| 313 | * sets the state of the flags. * |
| 314 | * * |
| 315 | * The function "fetestexcept" determines which of the specified subset of * |
| 316 | * the floating-point exception flags are currently set. The excepts * |
| 317 | * argument specifies the floating-point status flags to be queried. This * |
| 318 | * function returns the value of the bitwise OR of the floating-point * |
| 319 | * exception macros corresponding to the currently set floating-point * |
| 320 | * exceptions included in excepts. * |
| 321 | ******************************************************************************/ |
| 322 | |
| 323 | extern int feclearexcept(int /* excepts */); |
| 324 | extern int fegetexceptflag(fexcept_t * /* flagp */, int /* excepts */); |
| 325 | extern int feraiseexcept(int /* excepts */); |
| 326 | extern int fesetexceptflag(const fexcept_t * /* flagp */, int /* excepts */); |
| 327 | extern int fetestexcept(int /* excepts */); |
| 328 | |
| 329 | /****************************************************************************** |
| 330 | * The following functions provide control of rounding direction modes. * |
| 331 | * * |
| 332 | * The function "fegetround" returns the value of the rounding direction * |
| 333 | * macro which represents the current rounding direction, or a negative * |
| 334 | * if there is no such rounding direction macro or the current rounding * |
| 335 | * direction is not determinable. * |
| 336 | * * |
| 337 | * The function "fesetround" establishes the rounding direction represented * |
| 338 | * by its argument "round". If the argument is not equal to the value of a * |
| 339 | * rounding direction macro, the rounding direction is not changed. It * |
| 340 | * returns zero if and only if the argument is equal to a rounding * |
| 341 | * direction macro. * |
| 342 | ******************************************************************************/ |
| 343 | |
| 344 | extern int fegetround(void); |
| 345 | extern int fesetround(int /* round */); |
| 346 | |
| 347 | /****************************************************************************** |
| 348 | * The following functions manage the floating-point environment, exception * |
| 349 | * flags and dynamic modes, as one entity. * |
| 350 | * * |
| 351 | * The fegetenv function stores the current floating-point enviornment in * |
| 352 | * the object pointed to by envp. * |
| 353 | * * |
| 354 | * The feholdexcept function saves the current floating-point environment in * |
| 355 | * the object pointed to by envp, clears the floating-point status flags, * |
| 356 | * and then installs a non-stop (continue on floating-point exceptions) * |
| 357 | * mode, if available, for all floating-point exceptions. The feholdexcept * |
| 358 | * function returns zero if and only if non-stop floating-point exceptions * |
| 359 | * handling was successfully installed. * |
| 360 | * * |
| 361 | * The fesetnv function establishes the floating-point environment * |
| 362 | * represented by the object pointed to by envp. The argument envp shall * |
| 363 | * point to an object set by a call to fegetenv or feholdexcept, or equal to * |
| 364 | * a floating-point environment macro to be C99 standard compliant and * |
| 365 | * portable to other architectures. Note that fesetnv merely installs the * |
| 366 | * state of the floating-point status flags represented through its * |
| 367 | * argument, and does not raise these floating-point exceptions. * |
| 368 | * * |
| 369 | * The feupdateenv function saves the currently raised floating-point * |
| 370 | * exceptions in its automatic storage, installs the floating-point * |
| 371 | * environment represented by the object pointed to by envp, and then raises * |
| 372 | * the saved floating-point exceptions. The argument envp shall point to an * |
| 373 | * object set by a call to feholdexcept or fegetenv or equal a * |
| 374 | * floating-point environment macro. * |
| 375 | ******************************************************************************/ |
| 376 | |
| 377 | extern int fegetenv(fenv_t * /* envp */); |
| 378 | extern int feholdexcept(fenv_t * /* envp */); |
| 379 | extern int fesetenv(const fenv_t * /* envp */); |
| 380 | extern int feupdateenv(const fenv_t * /* envp */); |
| 381 | |
| 382 | #ifdef __cplusplus |
| 383 | } |
| 384 | #endif |
| 385 | |
| 386 | #endif /* __FENV_H__ */ |
| 387 | |