Skip to content

Commit f2be097

Browse files
committed
Implement clamp_magnitude method for primtives floats & signed integers
Added feature gate, documentation and tests also.
1 parent ceb7df7 commit f2be097

File tree

12 files changed

+615
-0
lines changed

12 files changed

+615
-0
lines changed

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ declare_features! (
434434
(unstable, cfg_version, "1.45.0", Some(64796)),
435435
/// Allows to use the `#[cfi_encoding = ""]` attribute.
436436
(unstable, cfi_encoding, "1.71.0", Some(89653)),
437+
/// Allows using the `clamp_magnitude` method on float and signed integer primitives
438+
(unstable, clamp_magnitude, "CURRENT_RUSTC_VERSION", Some(148519)),
437439
/// Allows `for<...>` on closures and coroutines.
438440
(unstable, closure_lifetime_binder, "1.64.0", Some(97362)),
439441
/// Allows `#[track_caller]` on closures and coroutines.

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ symbols! {
661661
char_to_digit,
662662
child_id,
663663
child_kill,
664+
clamp_magnitude,
664665
client,
665666
clippy,
666667
clobber_abi,

library/core/src/num/f128.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,38 @@ impl f128 {
12761276
self
12771277
}
12781278

1279+
/// Clamps this number to a symmetric range centered around zero.
1280+
///
1281+
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
1282+
///
1283+
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
1284+
/// explicit about the intent.
1285+
///
1286+
/// # Panics
1287+
///
1288+
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
1289+
///
1290+
/// # Examples
1291+
///
1292+
/// ```
1293+
/// #![feature(f128)]
1294+
/// #![feature(clamp_magnitude)]
1295+
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1296+
/// assert_eq!(5.0f128.clamp_magnitude(3.0), 3.0);
1297+
/// assert_eq!((-5.0f128).clamp_magnitude(3.0), -3.0);
1298+
/// assert_eq!(2.0f128.clamp_magnitude(3.0), 2.0);
1299+
/// assert_eq!((-2.0f128).clamp_magnitude(3.0), -2.0);
1300+
/// # }
1301+
/// ```
1302+
#[inline]
1303+
#[unstable(feature = "clamp_magnitude", issue = "148519")]
1304+
#[must_use = "this returns the clamped value and does not modify the original"]
1305+
pub fn clamp_magnitude(self, limit: f128) -> f128 {
1306+
assert!(limit >= 0.0, "limit must be non-negative");
1307+
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
1308+
self.clamp(-limit, limit)
1309+
}
1310+
12791311
/// Computes the absolute value of `self`.
12801312
///
12811313
/// This function always returns the precise result.

library/core/src/num/f16.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,38 @@ impl f16 {
12541254
self
12551255
}
12561256

1257+
/// Clamps this number to a symmetric range centered around zero.
1258+
///
1259+
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
1260+
///
1261+
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
1262+
/// explicit about the intent.
1263+
///
1264+
/// # Panics
1265+
///
1266+
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
1267+
///
1268+
/// # Examples
1269+
///
1270+
/// ```
1271+
/// #![feature(f16)]
1272+
/// #![feature(clamp_magnitude)]
1273+
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1274+
/// assert_eq!(5.0f16.clamp_magnitude(3.0), 3.0);
1275+
/// assert_eq!((-5.0f16).clamp_magnitude(3.0), -3.0);
1276+
/// assert_eq!(2.0f16.clamp_magnitude(3.0), 2.0);
1277+
/// assert_eq!((-2.0f16).clamp_magnitude(3.0), -2.0);
1278+
/// # }
1279+
/// ```
1280+
#[inline]
1281+
#[unstable(feature = "clamp_magnitude", issue = "148519")]
1282+
#[must_use = "this returns the clamped value and does not modify the original"]
1283+
pub fn clamp_magnitude(self, limit: f16) -> f16 {
1284+
assert!(limit >= 0.0, "limit must be non-negative");
1285+
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
1286+
self.clamp(-limit, limit)
1287+
}
1288+
12571289
/// Computes the absolute value of `self`.
12581290
///
12591291
/// This function always returns the precise result.

library/core/src/num/f32.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,35 @@ impl f32 {
14311431
self
14321432
}
14331433

1434+
/// Clamps this number to a symmetric range centered around zero.
1435+
///
1436+
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
1437+
///
1438+
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
1439+
/// explicit about the intent.
1440+
///
1441+
/// # Panics
1442+
///
1443+
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
1444+
///
1445+
/// # Examples
1446+
///
1447+
/// ```
1448+
/// #![feature(clamp_magnitude)]
1449+
/// assert_eq!(5.0f32.clamp_magnitude(3.0), 3.0);
1450+
/// assert_eq!((-5.0f32).clamp_magnitude(3.0), -3.0);
1451+
/// assert_eq!(2.0f32.clamp_magnitude(3.0), 2.0);
1452+
/// assert_eq!((-2.0f32).clamp_magnitude(3.0), -2.0);
1453+
/// ```
1454+
#[must_use = "this returns the clamped value and does not modify the original"]
1455+
#[unstable(feature = "clamp_magnitude", issue = "148519")]
1456+
#[inline]
1457+
pub fn clamp_magnitude(self, limit: f32) -> f32 {
1458+
assert!(limit >= 0.0, "limit must be non-negative");
1459+
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
1460+
self.clamp(-limit, limit)
1461+
}
1462+
14341463
/// Computes the absolute value of `self`.
14351464
///
14361465
/// This function always returns the precise result.

library/core/src/num/f64.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,35 @@ impl f64 {
14291429
self
14301430
}
14311431

1432+
/// Clamps this number to a symmetric range centered around zero.
1433+
///
1434+
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
1435+
///
1436+
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
1437+
/// explicit about the intent.
1438+
///
1439+
/// # Panics
1440+
///
1441+
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
1442+
///
1443+
/// # Examples
1444+
///
1445+
/// ```
1446+
/// #![feature(clamp_magnitude)]
1447+
/// assert_eq!(5.0f64.clamp_magnitude(3.0), 3.0);
1448+
/// assert_eq!((-5.0f64).clamp_magnitude(3.0), -3.0);
1449+
/// assert_eq!(2.0f64.clamp_magnitude(3.0), 2.0);
1450+
/// assert_eq!((-2.0f64).clamp_magnitude(3.0), -2.0);
1451+
/// ```
1452+
#[must_use = "this returns the clamped value and does not modify the original"]
1453+
#[unstable(feature = "clamp_magnitude", issue = "148519")]
1454+
#[inline]
1455+
pub fn clamp_magnitude(self, limit: f64) -> f64 {
1456+
assert!(limit >= 0.0, "limit must be non-negative");
1457+
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
1458+
self.clamp(-limit, limit)
1459+
}
1460+
14321461
/// Computes the absolute value of `self`.
14331462
///
14341463
/// This function always returns the precise result.

library/core/src/num/int_macros.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,5 +3855,33 @@ macro_rules! int_impl {
38553855
pub const fn max_value() -> Self {
38563856
Self::MAX
38573857
}
3858+
3859+
/// Clamps this number to a symmetric range centred around zero.
3860+
///
3861+
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
3862+
///
3863+
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
3864+
/// explicit about the intent.
3865+
///
3866+
/// # Examples
3867+
///
3868+
/// ```
3869+
/// #![feature(clamp_magnitude)]
3870+
#[doc = concat!("assert_eq!(120", stringify!($SelfT), ".clamp_magnitude(100), 100);")]
3871+
#[doc = concat!("assert_eq!(-120", stringify!($SelfT), ".clamp_magnitude(100), -100);")]
3872+
#[doc = concat!("assert_eq!(80", stringify!($SelfT), ".clamp_magnitude(100), 80);")]
3873+
#[doc = concat!("assert_eq!(-80", stringify!($SelfT), ".clamp_magnitude(100), -80);")]
3874+
/// ```
3875+
#[must_use = "this returns the clamped value and does not modify the original"]
3876+
#[unstable(feature = "clamp_magnitude", issue = "148519")]
3877+
#[inline]
3878+
pub fn clamp_magnitude(self, limit: $UnsignedT) -> Self {
3879+
// Use try_into to handle cases where `limit` is larger than `Self::MAX`.
3880+
let positive_limit = limit.try_into().unwrap_or(Self::MAX);
3881+
// By capping `positive_limit` at `Self::MAX`, we ensure the range is symmetric.
3882+
// `-positive_limit` is thus always representable.
3883+
let negative_limit = -positive_limit;
3884+
self.clamp(negative_limit, positive_limit)
3885+
}
38583886
}
38593887
}

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#![feature(cfg_target_has_reliable_f16_f128)]
1616
#![feature(char_internals)]
1717
#![feature(char_max_len)]
18+
#![feature(clamp_magnitude)]
1819
#![feature(clone_to_uninit)]
1920
#![feature(const_cell_traits)]
2021
#![feature(const_cmp)]

0 commit comments

Comments
 (0)