about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark Simulacrum <mark.simulacrum@gmail.com>2017-09-06 18:27:45 -0600
committerGitHub <noreply@github.com>2017-09-06 18:27:45 -0600
commit44351edb64b596d9111414bff591cbae60bb29e0 (patch)
treef9d71d87cce148a5f23cfdbca73d0220e3a4827c
parent3681220877771954fa923e50f227e632aabe8bbc (diff)
parentb762283e57ff71f6763effb9cfc7fc0c7967b6b0 (diff)
downloadrust-44351edb64b596d9111414bff591cbae60bb29e0.tar.gz
rust-44351edb64b596d9111414bff591cbae60bb29e0.zip
Rollup merge of #44097 - Xaeroxe:clamp, r=burntsushi
Add clamp functions

Implementation of clamp feature:

Tracking issue: https://github.com/rust-lang/rust/issues/44095
RFC: https://github.com/rust-lang/rfcs/pull/1961
-rw-r--r--src/libcore/cmp.rs24
-rw-r--r--src/libstd/f32.rs44
-rw-r--r--src/libstd/f64.rs44
-rw-r--r--src/libstd/lib.rs1
4 files changed, 113 insertions, 0 deletions
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index ec6525485f7..dc1f2981a50 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -481,6 +481,30 @@ pub trait Ord: Eq + PartialOrd<Self> {
     where Self: Sized {
         if self <= other { self } else { other }
     }
+
+    /// Returns max if self is greater than max, and min if self is less than min.
+    /// Otherwise this will return self.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(clamp)]
+    ///
+    /// assert!((-3).clamp(-2, 1) == -2);
+    /// assert!(0.clamp(-2, 1) == 0);
+    /// assert!(2.clamp(-2, 1) == 1);
+    /// ```
+    ///
+    /// # Panics
+    /// Panics if min > max.
+    #[unstable(feature = "clamp", issue = "44095")]
+    fn clamp(self, min: Self, max: Self) -> Self
+    where Self: Sized {
+        assert!(min <= max);
+        if self < min { min }
+        else if self > max { max }
+        else { self }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 0135cd0a588..69ca77f54b4 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -1080,6 +1080,32 @@ impl f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
+    /// Returns max if self is greater than max, and min if self is less than min.
+    /// Otherwise this returns self.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(clamp)]
+    /// use std::f32::NAN;
+    /// assert!((-3.0f32).clamp(-2.0f32, 1.0f32) == -2.0f32);
+    /// assert!((0.0f32).clamp(-2.0f32, 1.0f32) == 0.0f32);
+    /// assert!((2.0f32).clamp(-2.0f32, 1.0f32) == 1.0f32);
+    /// assert!((NAN).clamp(-2.0f32, 1.0f32).is_nan());
+    /// ```
+    ///
+    /// # Panics
+    /// Panics if min > max, min is NaN, or max is NaN.
+    #[unstable(feature = "clamp", issue = "44095")]
+    #[inline]
+    pub fn clamp(self, min: f32, max: f32) -> f32 {
+        assert!(min <= max);
+        let mut x = self;
+        if x < min { x = min; }
+        if x > max { x = max; }
+        x
+    }
+
     /// Raw transmutation to `u32`.
     ///
     /// Converts the `f32` into its raw memory representation,
@@ -1751,4 +1777,22 @@ mod tests {
         assert_ne!(nan_masked & QNAN_MASK, 0);
         assert!(nan_masked_fl.is_nan());
     }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_greater_than_max() {
+        1.0f32.clamp(3.0, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_is_nan() {
+        1.0f32.clamp(NAN, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_max_is_nan() {
+        1.0f32.clamp(3.0, NAN);
+    }
 }
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index d73d7cd2c7b..6ec633bfaaa 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -970,6 +970,32 @@ impl f64 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
+    /// Returns max if self is greater than max, and min if self is less than min.
+    /// Otherwise this returns self.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(clamp)]
+    /// use std::f64::NAN;
+    /// assert!((-3.0f64).clamp(-2.0f64, 1.0f64) == -2.0f64);
+    /// assert!((0.0f64).clamp(-2.0f64, 1.0f64) == 0.0f64);
+    /// assert!((2.0f64).clamp(-2.0f64, 1.0f64) == 1.0f64);
+    /// assert!((NAN).clamp(-2.0f64, 1.0f64).is_nan());
+    /// ```
+    ///
+    /// # Panics
+    /// Panics if min > max, min is NaN, or max is NaN.
+    #[unstable(feature = "clamp", issue = "44095")]
+    #[inline]
+    pub fn clamp(self, min: f64, max: f64) -> f64 {
+        assert!(min <= max);
+        let mut x = self;
+        if x < min { x = min; }
+        if x > max { x = max; }
+        x
+    }
+
     // Solaris/Illumos requires a wrapper around log, log2, and log10 functions
     // because of their non-standard behavior (e.g. log(-n) returns -Inf instead
     // of expected NaN).
@@ -1642,4 +1668,22 @@ mod tests {
         assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
         assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
     }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_greater_than_max() {
+        1.0f64.clamp(3.0, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_is_nan() {
+        1.0f64.clamp(NAN, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_max_is_nan() {
+        1.0f64.clamp(3.0, NAN);
+    }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 33bf0d68126..433499a90a4 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -249,6 +249,7 @@
 #![feature(cfg_target_vendor)]
 #![feature(char_error_internals)]
 #![feature(char_internals)]
+#![feature(clamp)]
 #![feature(collections_range)]
 #![feature(compiler_builtins_lib)]
 #![feature(const_fn)]