# fenv

***

**1. Setting and Getting the Floating-Point Control Word**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__cw |= FE_DOWNWARD;
  fesetenv(&env);
  return 0;
}
```

Sets the floating-point control word to enable downward rounding.

**2. Checking the Floating-Point Status**

```c
#include <fenv.h>

int main() {
  if (fetestexcept(FE_INVALID)) {
    // Ignore invalid operation
  }
  return 0;
}
```

Checks for an invalid floating-point operation and takes appropriate action.

**3. Raising Floating-Point Exceptions**

```c
#include <fenv.h>

int main() {
  feclearexcept(FE_ALL_EXCEPT);
  int x = 1 / 0; // Division by zero raises FE_DIVBYZERO
  if (fetestexcept(FE_DIVBYZERO)) {
    // Handle division by zero
  }
  return 0;
}
```

Raises a floating-point division by zero exception and handles it.

**4. Setting the Precision for Floating-Point Arithmetic**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__precision = FE_DOUBLE;
  fesetenv(&env);
  return 0;
}
```

Sets the floating-point precision to double precision.

**5. Rounding Floating-Point Numbers**

```c
#include <fenv.h>
#include <math.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__rounding = FE_ROUND_TOWARD_ZERO;
  fesetenv(&env);
  double x = round(1.5); // Rounds 1.5 to 1.0
  return 0;
}
```

Rounds floating-point numbers toward zero.

**6. Comparing Floating-Point Numbers**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__cmp = FE_COMPARELESS;
  fesetenv(&env);
  double x = 1.0, y = 1.0000000000001;
  int result = fpclassify(x - y); // Returns FE_COMPARELESS
  return 0;
}
```

Compares floating-point numbers without considering sign.

**7. Classifying Floating-Point Numbers**

```c
#include <fenv.h>

int main() {
  double x = 0.0;
  int result = fpclassify(x); // Returns FE_ZERO
  return 0;
}
```

Classifies a floating-point number into categories such as zero, infinity, or NaN.

**8. Setting the Default Exception Handling**

```c
#include <fenv.h>

int main() {
  fedefault(FE_INEXACT, FE_IGNORE);
  double x = sqrt(-1.0); // Ignore invalid square root result
  return 0;
}
```

Sets the default exception handling for inexact results to ignore them.

**9. Handling Exceptions with Floating-Point Instructions**

```c
#include <fenv.h>

int main() {
  feclearexcept(FE_ALL_EXCEPT);
  double x = sqrt(-1.0); // Raise FE_INVALID
  if (fetestexcept(FE_INVALID)) {
    // Handle invalid square root
  }
  return 0;
}
```

Handles an invalid square root exception raised by a floating-point instruction.

**10. Using the Floating-Point Unit**

```c
#include <fenv.h>
#include <math.h>

int main() {
  fpu_control_t fpucw;
  fpucw.word = 0;
  fpucw.common = FPUCW_DEFAULT;
  _FPU_SETCW(fpucw);
  double x = sin(1.0); // Use the FPU for trigonometric calculations
  return 0;
}
```

Configures and uses the floating-point unit for efficient trigonometric calculations.

**11. Managing Floating-Point Context**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  // Modify env here
  fesetenv(&env);
  return 0;
}
```

Saves and restores the floating-point context to manipulate floating-point settings in a controlled manner.

**12. Enabling Fast Math**

```c
#include <fenv.h>
#include <math.h>

int main() {
  fpu_control_t fpucw;
  fpucw.word = 0;
  fpucw.fast = 1;
  _FPU_SETCW(fpucw);
  double x = sqrt(2.0); // Use faster but less accurate sqrt() implementation
  return 0;
}
```

Enables fast math mode for faster but less accurate floating-point calculations.

**13. Preventing Floating-Point Exceptions**

```c
#include <fenv.h>
#include <math.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__control |= FE_ALL_EXCEPT;
  fesetenv(&env);
  double x = sqrt(-1.0); // Suppress invalid square root exception
  return 0;
}
```

Prevents the raising of all floating-point exceptions.

**14. Setting the Direction of Rounding**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__rounding = FE_ROUND_TO_WARD_NEG_INF;
  fesetenv(&env);
  double x = 1.5;
  int result = rint(x); // Rounds 1.5 to 1.0 toward negative infinity
  return 0;
}
```

Sets the direction of rounding to round toward negative infinity.

**15. Handling Multiple Floating-Point Exceptions**

```c
#include <fenv.h>

int main() {
  feclearexcept(FE_ALL_EXCEPT);
  double x = sqrt(-1.0); // Raise FE_INVALID and FE_DIVBYZERO
  if (fetestexcept(FE_INVALID | FE_DIVBYZERO)) {
    // Handle both invalid square root and division by zero
  }
  return 0;
}
```

Handles multiple floating-point exceptions raised by a single operation.

**16. Using the x86 Floating-Point Unit**

```c
#include <fenv.h>
#include <xmmintrin.h>

int main() {
  __m128 x = _mm_set_ps(1.0, 2.0, 3.0, 4.0); // SIMD vector of floats
  __m128 y = _mm_sqrt_ps(x); // Calculate square roots using SIMD instructions
  return 0;
}
```

Utilizes the x86 floating-point unit for parallel floating-point calculations.

**17. Optimizing Floating-Point Code**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__optimize = FE_FAST;
  fesetenv(&env);
  return 0;
}
```

Enables floating-point optimizations to improve the performance of floating-point calculations.

**18. Controlling Floating-Point Errors**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__mxcsr |= FE_INVALID | FE_DIVBYZERO;
  fesetenv(&env);
  return 0;
}
```

Controls the mask of floating-point exceptions to allow or prevent specific exceptions from being raised.

**19. Getting the Last Floating-Point Error**

```c
#include <fenv.h>

int main() {
  int error = fegetround(); // Get the current rounding mode
  return 0;
}
```

Retrieves the last floating-point error code.

**20. Saving and Restoring the Floating-Point Unit State**

```c
#include <fenv.h>

int main() {
  fpu_control_t fpucw;
  fpucw = _FPU_GETCW(); // Save the current FPU control word
  _FPU_SETCW(fpucw); // Restore the FPU control word
  return 0;
}
```

Saves and restores the state of the floating-point unit.

**21. Checking for IEEE Floating-Point Compliance**

```c
#include <fenv.h>

int main() {
  if (fegetexceptflag(FE_INVALID, FE_EXACT)) {
    // IEEE floating-point invalid operation is supported
  }
  return 0;
}
```

Checks for specific IEEE floating-point features.

**22. Setting the Floating-Point Unit Control Word**

```c
#include <fenv.h>

int main() {
  fpu_control_t fpucw;
  fpucw = _FPU_GETCW();
  fpucw.word = 0;
  fpucw.precision = FPUCW_PRECISION_53;
  _FPU_SETCW(fpucw); // Set the 53-bit precision for floating-point calculations
  return 0;
}
```

Sets the floating-point unit control word to customize the behavior of the floating-point unit.

**23. Rounding to the Nearest Integer**

```c
#include <fenv.h>
#include <math.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__rounding = FE_ROUND_TO_INT;
  fesetenv(&env);
  double x = 1.5;
  int result = round(x); // Rounds 1.5 to 2
  return 0;
}
```

Sets the rounding mode to round to the nearest integer.

**24. Trapping Floating-Point Exceptions**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__control |= FE_TRAP_INVALID | FE_TRAP_DIVBYZERO;
  fesetenv(&env);
  return 0;
}
```

Traps specific floating-point exceptions to handle them explicitly.

**25. Managing Floating-Point Rounding**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__rounding = FE_TONEAREST;
  fesetenv(&env);
  double x = 1.5;
  double y = round(x); // Rounds 1.5 to 2.0
  return 0;
}
```

Sets the rounding mode to round to the nearest value.

**26. Detecting and Handling Floating-Point Underflow**

```c
#include <fenv.h>

int main() {
  feclearexcept(FE_ALL_EXCEPT);
  double x = 0.0 / 0.0; // Raise FE_UNDERFLOW
  if (fetestexcept(FE_UNDERFLOW)) {
    // Handle underflow
  }
  return 0;
}
```

Detects and handles floating-point underflow.

**27. Controlling Floating-Point Division by Zero**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__dividebyzero_mode = FE_INVALID;
  fesetenv(&env);
  double x = 1.0 / 0.0; // Raises FE_INVALID instead of FLT_INIFINITY
  return 0;
}
```

Controls the behavior of floating-point division by zero.

**28. Setting the Floating-Point Status Flag**

```c
#include <fenv.h>

int main() {
  fesetstatus(FE_INEXACT);
  return 0;
}
```

Sets the floating-point status flag to indicate an inexact result.

**29. Getting the Floating-Point Exception Mask**

```c
#include <fenv.h>

int main() {
  int mask = fegetexceptmask(); // Get the current exception mask
  return 0;
}
```

Retrieves the mask of floating-point exceptions.

**30. Handling Floating-Point Exceptions in a Signal Handler**

```c
#include <fenv.h>
#include <signal.h>

void signal_handler(int signum) {
  int exception = fetestexcept(FE_ALL_EXCEPT); // Get the floating-point exception
  // Handle the exception
}

int main() {
  signal(SIGFPE, signal_handler);
  double x = 1.0 / 0.0; // Trigger a division by zero exception
  return 0;
}
```

Handles floating-point exceptions in a signal handler.

**31. Checking for Floating-Point Exceptions in a Loop**

```c
#include <fenv.h>

int main() {
  for (int i = 0; i < 1000; i++) {
    double x = i / 0.0; // Potentially raise FE_DIVBYZERO
    fetestexcept(FE_ALL_EXCEPT); // Check for floating-point exceptions
  }
  return 0;
}
```

Checks for floating-point exceptions after each iteration of a loop.

**32. Setting the Default Floating-Point Control Word**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fedefaultcontrol(&env);
  fesetenv(&env); // Set the default floating-point control word
  return 0;
}
```

Resets the floating-point control word to its default value.

**33. Manipulating the Floating-Point Status Word**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__status |= FE_INVALID;
  fesetenv(&env); // Set the invalid flag in the floating-point status word
  return 0;
}
```

Manipulates the floating-point status word to set or clear specific flags.

**34. Comparing Floating-Point Numbers with Predicates**

```c
#include <fenv.h>
#include <math.h>

int main() {
  double x = 1.0, y = 1.0000000000001;
  int result = feq(x, y); // Check if x and y are equal
  return 0;
}
```

Compares floating-point numbers using predicates like feq(), flt(), fgt(), fle(), and fge().

**35. Disabling Floating-Point Exceptions**

```c
#include <fenv.h>

int main() {
  feenableexcept(FE_ALL_EXCEPT); // Enable all floating-point exceptions
  feclearexcept(FE_ALL_EXCEPT); // Disable all floating-point exceptions
  return 0;
}
```

Disables floating-point exceptions to prevent them from interrupting program execution.

**36. Using the FP80 Floating-Point Format**

```c
#include <fenv.h>
#include <xmmintrin.h>

int main() {
  __m128d x = _mm_set_pd(1.0, 2.0); // SIMD vector of FP80 numbers
  __m128d y = _mm_sqrt_pd(x); // Calculate square roots using the FP80 format
  return 0;
}
```

Utilizes the FP80 floating-point format for higher precision calculations.

**37. Customizing Floating-Point Exceptions**

```c
#include <fenv.h>

int main() {
  feenableexcept(FE_INVALID); // Enable invalid floating-point exceptions
  fedisableexcept(FE_DIVBYZERO); // Disable division by zero exceptions
  return 0;
}
```

Customizes which floating-point exceptions are enabled or disabled.

**38. Getting the Floating-Point Environment**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env); // Get the current floating-point environment
  return 0;
}
```

Retrieves the current floating-point environment, including control and status words.

**39. Setting the Floating-Point Rounding Mode**

```c
#include <fenv.h>

int main() {
  feround(FE_ROUND_TO_INT); // Set the rounding mode to round to the nearest integer
  return 0;
}
```

Sets the rounding mode for floating-point operations.

**40. Detecting Denormalized Numbers**

```c
#include <fenv.h>

int main() {
  double x = 0.00000000000000000001; // Small denormalized number
  int result = fisdenormal(x); // Check if x is denormalized
  return 0;
}
```

Detects denormalized floating-point numbers, which represent very small values.

**41. Comparing Floating-Point Numbers with Tolerances**

```c
#include <fenv.h>
#include <math.h>

int main() {
  double x = 1.0, y = 1.0000000000001;
  int result = fetestexcept(FE_INEXACT); // Check for inexact result
  if (!result) {
    // If the result is exact
    if (fabs(x - y) < 0.000001) {
      // Consider x and y as equal with a tolerance of 0.000001
    }
  }
  return 0;
}
```

Compares floating-point numbers with a specified tolerance to account for rounding errors.

**42. Managing Floating-Point Overflow**

```c
#include <fenv.h>

int main() {
  fesetexceptflag(FE_OVERFLOW, FE_INVALID); // Set overflow to raise FE_INVALID
  double x = HUGE_VAL * HUGE_VAL; // Potentially cause overflow
  if (fetestexcept(FE_INVALID)) {
    // Handle overflow
  }
  return 0;
}
```

Manages floating-point overflow by changing its behavior to raise FE\_INVALID instead of FLT\_INFINITY.

**43. Using the Rounding Direction Macro**

```c
#include <fenv.h>

int main() {
  double x = 1.5;
  int result = rint(x); // Round x to the nearest integer using the rounding direction macro
  return 0;
}
```

Uses the rint() function to round a floating-point number based on the rounding direction specified by the rounding direction macro.

**44. Setting the Floating-Point Precision**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__precision = FE_SINGLE;
  fesetenv(&env); // Set the floating-point precision to single precision
  return 0;
}
```

Sets the floating-point precision to single or double precision.

**45. Checking for Invalid Floating-Point Values**

```c
#include <fenv.h>

int main() {
  double x = NAN; // NaN value
  int result = isnan(x); // Check if x is NaN
  return 0;
}
```

Checks for invalid floating-point values, such as NaN or infinity.

**46. Getting the Floating-Point Status Register**

```c
#include <fenv.h>

int main() {
  fpu_status_registers_t status;
  _FPU_GETSTATUS(&status); // Get the floating-point status register
  return 0;
}
```

Retrieves the floating-point status register, which contains information about the current state of the floating-point unit.

**47. Using the Floating-Point Stack**

```c
#include <fenv.h>
#include <xmmintrin.h>

int main() {
  __m128d stack[8]; // 8-element floating-point stack
  _mm_store_pd(stack, _mm_set_pd(1.0, 2.0)); // Push a double-precision value onto the stack
  return 0;
}
```

Utilizes the floating-point stack to store and manipulate floating-point values in a memory-efficient manner.

**48. Setting the Floating-Point Control Word**

```c
#include <fenv.h>

int main() {
  fenv_t env;
  fegetenv(&env);
  env.__control = FE_DONTSAVE;
  fesetenv(&env); // Set the floating-point control word
  return 0;
}
```

Sets the floating-point control word to specify how floating-point calculations are performed.

**49. Detecting and Handling Floating-Point Errors**

```c
#include <fenv.h>

int main() {
  double x = 1.0 / 0.0; // Divide by zero
  if (fetestexcept(FE_DIVBYZERO)) {
    // Handle the division by zero error
  }
  return 0;
}
```

Detects and handles floating-point errors, such as division by zero, overflow, and underflow.

**50. Using the Floating-Point Environment Variables**

```c
#include <fenv.h>

int main() {
  char *envvar;
  envvar = getenv("FE_ROUND"); // Get the current floating-point rounding mode
  return 0;
}
```

Retrieves and sets floating-point environment variables to control the behavior of floating-point calculations.
