aboutsummaryrefslogtreecommitdiff
path: root/src/utils.rs
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2021-06-02 17:26:47 +0200
committerGitHub <noreply@github.com>2021-06-02 17:26:47 +0200
commit8a3103a35b2ee5773dda6bb92870d9bfadc6ba70 (patch)
tree91f32796670d519cc1b60a1afdfc0c3701513b07 /src/utils.rs
parentd3d998e91e39e64b9bdd9060ba7904218fd8cfbe (diff)
parent6356dca1d5a753768bbb479aa9491805223e1c60 (diff)
downloadrapier-8a3103a35b2ee5773dda6bb92870d9bfadc6ba70.tar.gz
rapier-8a3103a35b2ee5773dda6bb92870d9bfadc6ba70.tar.bz2
rapier-8a3103a35b2ee5773dda6bb92870d9bfadc6ba70.zip
Merge pull request #195 from tpdickso/ungenerate-nans
Add feature flag to disable floating point exceptions in unexceptional code
Diffstat (limited to 'src/utils.rs')
-rw-r--r--src/utils.rs46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/utils.rs b/src/utils.rs
index c1eb31d..84ed250 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -670,6 +670,52 @@ impl Drop for FlushToZeroDenormalsAreZeroFlags {
}
}
+// This is an RAII structure that disables floating point exceptions while
+// it is alive, so that operations which generate NaNs and infinite values
+// intentionally will not trip an exception when debugging problematic
+// code that is generating NaNs and infinite values erroneously.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub(crate) struct DisableFloatingPointExceptionsFlags {
+ #[cfg(feature = "avoid-fe-exceptions")]
+ // We can't get a precise size for this, because it's of type
+ // `fenv_t`, which is a definition that doesn't exist in rust
+ // (not even in the libc crate, as of the time of writing.)
+ // But since the state is intended to be stored on the stack,
+ // 256 bytes should be more than enough.
+ original_flags: [u8; 256],
+}
+
+#[cfg(feature = "avoid-fe-exceptions")]
+extern "C" {
+ fn feholdexcept(env: *mut std::ffi::c_void);
+ fn fesetenv(env: *const std::ffi::c_void);
+}
+
+impl DisableFloatingPointExceptionsFlags {
+ #[cfg(not(feature = "avoid-fe-exceptions"))]
+ pub fn disable_floating_point_exceptions() -> Self {
+ Self { }
+ }
+
+ #[cfg(feature = "avoid-fe-exceptions")]
+ pub fn disable_floating_point_exceptions() -> Self {
+ unsafe {
+ let mut original_flags = [0; 256];
+ feholdexcept(original_flags.as_mut_ptr() as *mut _);
+ Self { original_flags }
+ }
+ }
+}
+
+#[cfg(feature = "avoid-fe-exceptions")]
+impl Drop for DisableFloatingPointExceptionsFlags {
+ fn drop(&mut self) {
+ unsafe {
+ fesetenv(self.original_flags.as_ptr() as *const _);
+ }
+ }
+}
+
pub(crate) fn select_other<T: PartialEq>(pair: (T, T), elt: T) -> T {
if pair.0 == elt {
pair.1