Skip to content

Commit 700af56

Browse files
committed
feat(core): Add implementations for unbounded_shl/unbounded_shr
1 parent d37ebfe commit 700af56

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

Diff for: core/src/num/int_macros.rs

+60
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,33 @@ macro_rules! int_impl {
13121312
}
13131313
}
13141314

1315+
/// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`
1316+
///
1317+
/// If `rhs` is larger or equal to the number of bits in `self`,
1318+
/// the entire value is shifted out, and `0` is returned.
1319+
///
1320+
/// # Examples
1321+
///
1322+
/// Basic usage:
1323+
/// ```
1324+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")]
1325+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")]
1326+
/// ```
1327+
#[unstable(feature = "unbounded_shifts", issue = "129375")]
1328+
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
1329+
#[must_use = "this returns the result of the operation, \
1330+
without modifying the original"]
1331+
#[inline]
1332+
pub const fn unbounded_shl(self, v: u32) -> $SelfT{
1333+
if v < Self::BITS{
1334+
// SAFETY:
1335+
// v is just checked to be in-range above
1336+
unsafe{self.unchecked_shl(v)}
1337+
}else{
1338+
0
1339+
}
1340+
}
1341+
13151342
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
13161343
/// larger than or equal to the number of bits in `self`.
13171344
///
@@ -1410,6 +1437,39 @@ macro_rules! int_impl {
14101437
}
14111438
}
14121439

1440+
/// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`
1441+
///
1442+
/// If `rhs` is larger or equal to the number of bits in `self`,
1443+
/// the entire value is shifted out, which yields `0` for a positive number,
1444+
/// and `-1` for a negative number.
1445+
///
1446+
/// # Examples
1447+
///
1448+
/// Basic usage:
1449+
/// ```
1450+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shl(4), 0x1);")]
1451+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")]
1452+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.unbounded_shr(129), -1);")]
1453+
/// ```
1454+
#[unstable(feature = "unbounded_shifts", issue = "129375")]
1455+
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
1456+
#[must_use = "this returns the result of the operation, \
1457+
without modifying the original"]
1458+
#[inline]
1459+
pub const fn unbounded_shr(self, v: u32) -> $SelfT{
1460+
if v < Self::BITS{
1461+
// SAFETY:
1462+
// v is just checked to be in-range above
1463+
unsafe{self.unchecked_shr(v)}
1464+
}else{
1465+
// A shift by `Self::BITS-1` suffices for signed integers, because the sign bit is copied for each of the shifted bits.
1466+
1467+
// SAFETY:
1468+
// `Self::BITS-1` is guaranteed to be less than `Self::BITS`
1469+
unsafe{self.unchecked_shr(Self::BITS - 1)}
1470+
}
1471+
}
1472+
14131473
/// Checked absolute value. Computes `self.abs()`, returning `None` if
14141474
/// `self == MIN`.
14151475
///

Diff for: core/src/num/uint_macros.rs

+54
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,33 @@ macro_rules! uint_impl {
15011501
}
15021502
}
15031503

1504+
/// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`
1505+
///
1506+
/// If `rhs` is larger or equal to the number of bits in `self`,
1507+
/// the entire value is shifted out, and `0` is returned.
1508+
///
1509+
/// # Examples
1510+
///
1511+
/// Basic usage:
1512+
/// ```
1513+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")]
1514+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")]
1515+
/// ```
1516+
#[unstable(feature = "unbounded_shifts", issue = "129375")]
1517+
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
1518+
#[must_use = "this returns the result of the operation, \
1519+
without modifying the original"]
1520+
#[inline]
1521+
pub const fn unbounded_shl(self, v: u32) -> $SelfT{
1522+
if v < Self::BITS{
1523+
// SAFETY:
1524+
// v is just checked to be in-range above
1525+
unsafe{self.unchecked_shl(v)}
1526+
}else{
1527+
0
1528+
}
1529+
}
1530+
15041531
/// Checked shift right. Computes `self >> rhs`, returning `None`
15051532
/// if `rhs` is larger than or equal to the number of bits in `self`.
15061533
///
@@ -1599,6 +1626,33 @@ macro_rules! uint_impl {
15991626
}
16001627
}
16011628

1629+
/// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`
1630+
///
1631+
/// If `rhs` is larger or equal to the number of bits in `self`,
1632+
/// the entire value is shifted out, and `0` is returned.
1633+
///
1634+
/// # Examples
1635+
///
1636+
/// Basic usage:
1637+
/// ```
1638+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x10);")]
1639+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")]
1640+
/// ```
1641+
#[unstable(feature = "unbounded_shifts", issue = "129375")]
1642+
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
1643+
#[must_use = "this returns the result of the operation, \
1644+
without modifying the original"]
1645+
#[inline]
1646+
pub const fn unbounded_shr(self, v: u32) -> $SelfT{
1647+
if v < Self::BITS{
1648+
// SAFETY:
1649+
// v is just checked to be in-range above
1650+
unsafe{self.unchecked_shr(v)}
1651+
}else{
1652+
0
1653+
}
1654+
}
1655+
16021656
/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
16031657
/// overflow occurred.
16041658
///

0 commit comments

Comments
 (0)