Skip to content

Commit e9ed765

Browse files
committed
Implement clamp_to
1 parent 31010ca commit e9ed765

6 files changed

Lines changed: 262 additions & 0 deletions

File tree

library/core/src/cmp.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
#![stable(feature = "rust1", since = "1.0.0")]
2727

2828
mod bytewise;
29+
mod clamp;
2930
pub(crate) use bytewise::BytewiseEq;
31+
#[unstable(feature = "clamp_bounds", issue = "147781")]
32+
pub use clamp::ClampBounds;
3033

3134
use self::Ordering::*;
3235
use crate::marker::{Destruct, PointeeSized};
@@ -1096,6 +1099,35 @@ pub const trait Ord: [const] Eq + [const] PartialOrd<Self> + PointeeSized {
10961099
self
10971100
}
10981101
}
1102+
1103+
/// Restrict a value to a certain range.
1104+
///
1105+
/// This is equal to `max`, `min`, or `clamp`, depending on whether the range is `min..`,
1106+
/// `..=max`, or `min..=max`, respectively. Exclusive ranges are not permitted.
1107+
///
1108+
/// # Panics
1109+
///
1110+
/// Panics on `min..=max` if `min > max`.
1111+
///
1112+
/// # Examples
1113+
///
1114+
/// ```
1115+
/// #![feature(clamp_to)]
1116+
/// assert_eq!((-3).clamp_to(-2..=1), -2);
1117+
/// assert_eq!(0.clamp_to(-2..=1), 0);
1118+
/// assert_eq!(2.clamp_to(..=1), 1);
1119+
/// assert_eq!(5.clamp_to(7..), 7);
1120+
/// ```
1121+
#[must_use]
1122+
#[inline]
1123+
#[unstable(feature = "clamp_to", issue = "147781")]
1124+
fn clamp_to<R>(self, range: R) -> Self
1125+
where
1126+
Self: Sized + [const] Destruct,
1127+
R: [const] ClampBounds<Self>,
1128+
{
1129+
range.clamp(self)
1130+
}
10991131
}
11001132

11011133
/// Derive macro generating an impl of the trait [`Ord`].

library/core/src/cmp/clamp.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use crate::marker::Destruct;
2+
use crate::ops::{RangeFrom, RangeFull, RangeInclusive, RangeToInclusive};
3+
4+
/// Trait for ranges supported by [`Ord::clamp_to`].
5+
#[unstable(feature = "clamp_bounds", issue = "147781")]
6+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
7+
pub const trait ClampBounds<T>: Sized {
8+
/// The implementation of [`Ord::clamp_to`].
9+
fn clamp(self, value: T) -> T
10+
where
11+
T: [const] Destruct;
12+
}
13+
14+
#[unstable(feature = "clamp_bounds", issue = "147781")]
15+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
16+
impl<T> const ClampBounds<T> for RangeFrom<T>
17+
where
18+
T: [const] Ord,
19+
{
20+
fn clamp(self, value: T) -> T
21+
where
22+
T: [const] Destruct,
23+
{
24+
value.max(self.start)
25+
}
26+
}
27+
28+
#[unstable(feature = "clamp_bounds", issue = "147781")]
29+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
30+
impl<T> const ClampBounds<T> for RangeToInclusive<T>
31+
where
32+
T: [const] Ord,
33+
{
34+
fn clamp(self, value: T) -> T
35+
where
36+
T: [const] Destruct,
37+
{
38+
value.min(self.end)
39+
}
40+
}
41+
42+
#[unstable(feature = "clamp_bounds", issue = "147781")]
43+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
44+
impl<T> const ClampBounds<T> for RangeInclusive<T>
45+
where
46+
T: [const] Ord,
47+
{
48+
fn clamp(self, value: T) -> T
49+
where
50+
T: [const] Destruct,
51+
{
52+
let (start, end) = self.into_inner();
53+
value.clamp(start, end)
54+
}
55+
}
56+
57+
#[unstable(feature = "clamp_bounds", issue = "147781")]
58+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
59+
impl<T> const ClampBounds<T> for RangeFull {
60+
fn clamp(self, value: T) -> T {
61+
value
62+
}
63+
}
64+
65+
macro impl_for_float($t:ty) {
66+
#[unstable(feature = "clamp_bounds", issue = "147781")]
67+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
68+
impl const ClampBounds<$t> for RangeFrom<$t> {
69+
fn clamp(self, value: $t) -> $t {
70+
value.max(self.start)
71+
}
72+
}
73+
74+
#[unstable(feature = "clamp_bounds", issue = "147781")]
75+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
76+
impl const ClampBounds<$t> for RangeToInclusive<$t> {
77+
fn clamp(self, value: $t) -> $t {
78+
value.min(self.end)
79+
}
80+
}
81+
82+
#[unstable(feature = "clamp_bounds", issue = "147781")]
83+
#[rustc_const_unstable(feature = "clamp_bounds", issue = "147781")]
84+
impl const ClampBounds<$t> for RangeInclusive<$t> {
85+
fn clamp(self, value: $t) -> $t {
86+
let (start, end) = self.into_inner();
87+
// Deliberately avoid using `clamp` to handle NaN consistently
88+
value.max(start).min(end)
89+
}
90+
}
91+
}
92+
93+
// #[unstable(feature = "f16", issue = "116909")]
94+
impl_for_float!(f16);
95+
impl_for_float!(f32);
96+
impl_for_float!(f64);
97+
// #[unstable(feature = "f128", issue = "116909")]
98+
impl_for_float!(f128);

library/core/src/num/f128.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,39 @@ impl f128 {
13251325
self.clamp(-limit, limit)
13261326
}
13271327

1328+
/// Restrict a value to a certain range.
1329+
///
1330+
/// This is largely equal to `max`, `min`, or `clamp`, depending on whether the range is
1331+
/// `min..`, `..=max`, or `min..=max`, respectively. However, whereas `clamp` panics on NaN
1332+
/// values, this function treats them as unbounded, like `max` and `min`.
1333+
///
1334+
/// Exclusive ranges are not permitted.
1335+
///
1336+
/// # Panics
1337+
///
1338+
/// Panics on `min..=max` if `min > max`.
1339+
///
1340+
/// # Examples
1341+
///
1342+
/// ```
1343+
/// #![feature(f128, clamp_to)]
1344+
/// assert_eq!((-3.0f128).clamp_to(-2.0..=1.0), -2.0);
1345+
/// assert_eq!(0.0f128.clamp_to(-2.0..=1.0), 0.0);
1346+
/// assert_eq!(2.0f128.clamp_to(..=1.0), 1.0);
1347+
/// assert_eq!(5.0f128.clamp_to(7.0..), 7.0);
1348+
/// assert_eq!(4.0f128.clamp_to(1.0..=f128::NAN), 4.0);
1349+
/// ```
1350+
#[must_use]
1351+
#[inline]
1352+
#[unstable(feature = "clamp_to", issue = "147781")]
1353+
pub fn clamp_to<R>(self, range: R) -> Self
1354+
where
1355+
Self: Sized,
1356+
R: crate::cmp::ClampBounds<Self>,
1357+
{
1358+
range.clamp(self)
1359+
}
1360+
13281361
/// Computes the absolute value of `self`.
13291362
///
13301363
/// This function always returns the precise result.

library/core/src/num/f16.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,39 @@ impl f16 {
13031303
self.clamp(-limit, limit)
13041304
}
13051305

1306+
/// Restrict a value to a certain range.
1307+
///
1308+
/// This is largely equal to `max`, `min`, or `clamp`, depending on whether the range is
1309+
/// `min..`, `..=max`, or `min..=max`, respectively. However, whereas `clamp` panics on NaN
1310+
/// values, this function treats them as unbounded, like `max` and `min`.
1311+
///
1312+
/// Exclusive ranges are not permitted.
1313+
///
1314+
/// # Panics
1315+
///
1316+
/// Panics on `min..=max` if `min > max`.
1317+
///
1318+
/// # Examples
1319+
///
1320+
/// ```
1321+
/// #![feature(f16, clamp_to)]
1322+
/// assert_eq!((-3.0f16).clamp_to(-2.0..=1.0), -2.0);
1323+
/// assert_eq!(0.0f16.clamp_to(-2.0..=1.0), 0.0);
1324+
/// assert_eq!(2.0f16.clamp_to(..=1.0), 1.0);
1325+
/// assert_eq!(5.0f16.clamp_to(7.0..), 7.0);
1326+
/// assert_eq!(4.0f16.clamp_to(1.0..=f16::NAN), 4.0);
1327+
/// ```
1328+
#[must_use]
1329+
#[inline]
1330+
#[unstable(feature = "clamp_to", issue = "147781")]
1331+
pub fn clamp_to<R>(self, range: R) -> Self
1332+
where
1333+
Self: Sized,
1334+
R: crate::cmp::ClampBounds<Self>,
1335+
{
1336+
range.clamp(self)
1337+
}
1338+
13061339
/// Computes the absolute value of `self`.
13071340
///
13081341
/// This function always returns the precise result.

library/core/src/num/f32.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,39 @@ impl f32 {
14771477
self.clamp(-limit, limit)
14781478
}
14791479

1480+
/// Restrict a value to a certain range.
1481+
///
1482+
/// This is largely equal to `max`, `min`, or `clamp`, depending on whether the range is
1483+
/// `min..`, `..=max`, or `min..=max`, respectively. However, whereas `clamp` panics on NaN
1484+
/// values, this function treats them as unbounded, like `max` and `min`.
1485+
///
1486+
/// Exclusive ranges are not permitted.
1487+
///
1488+
/// # Panics
1489+
///
1490+
/// Panics on `min..=max` if `min > max`.
1491+
///
1492+
/// # Examples
1493+
///
1494+
/// ```
1495+
/// #![feature(clamp_to)]
1496+
/// assert_eq!((-3.0f32).clamp_to(-2.0..=1.0), -2.0);
1497+
/// assert_eq!(0.0f32.clamp_to(-2.0..=1.0), 0.0);
1498+
/// assert_eq!(2.0f32.clamp_to(..=1.0), 1.0);
1499+
/// assert_eq!(5.0f32.clamp_to(7.0..), 7.0);
1500+
/// assert_eq!(4.0f32.clamp_to(1.0..=f32::NAN), 4.0);
1501+
/// ```
1502+
#[must_use]
1503+
#[inline]
1504+
#[unstable(feature = "clamp_to", issue = "147781")]
1505+
pub fn clamp_to<R>(self, range: R) -> Self
1506+
where
1507+
Self: Sized,
1508+
R: crate::cmp::ClampBounds<Self>,
1509+
{
1510+
range.clamp(self)
1511+
}
1512+
14801513
/// Computes the absolute value of `self`.
14811514
///
14821515
/// This function always returns the precise result.

library/core/src/num/f64.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,39 @@ impl f64 {
14751475
self.clamp(-limit, limit)
14761476
}
14771477

1478+
/// Restrict a value to a certain range.
1479+
///
1480+
/// This is largely equal to `max`, `min`, or `clamp`, depending on whether the range is
1481+
/// `min..`, `..=max`, or `min..=max`, respectively. However, whereas `clamp` panics on NaN
1482+
/// values, this function treats them as unbounded, like `max` and `min`.
1483+
///
1484+
/// Exclusive ranges are not permitted.
1485+
///
1486+
/// # Panics
1487+
///
1488+
/// Panics on `min..=max` if `min > max`.
1489+
///
1490+
/// # Examples
1491+
///
1492+
/// ```
1493+
/// #![feature(clamp_to)]
1494+
/// assert_eq!((-3.0f64).clamp_to(-2.0..=1.0), -2.0);
1495+
/// assert_eq!(0.0f64.clamp_to(-2.0..=1.0), 0.0);
1496+
/// assert_eq!(2.0f64.clamp_to(..=1.0), 1.0);
1497+
/// assert_eq!(5.0f64.clamp_to(7.0..), 7.0);
1498+
/// assert_eq!(4.0f64.clamp_to(1.0..=f64::NAN), 4.0);
1499+
/// ```
1500+
#[must_use]
1501+
#[inline]
1502+
#[unstable(feature = "clamp_to", issue = "147781")]
1503+
pub fn clamp_to<R>(self, range: R) -> Self
1504+
where
1505+
Self: Sized,
1506+
R: crate::cmp::ClampBounds<Self>,
1507+
{
1508+
range.clamp(self)
1509+
}
1510+
14781511
/// Computes the absolute value of `self`.
14791512
///
14801513
/// This function always returns the precise result.

0 commit comments

Comments
 (0)