add exact bitshifts · rust-lang/rust@cefa74f (original) (raw)
`@@ -1413,6 +1413,66 @@ macro_rules! int_impl {
`
1413
1413
`}
`
1414
1414
`}
`
1415
1415
``
``
1416
`` +
/// Exact shift left. Computes self << rhs as long as it can be reversed losslessly.
``
``
1417
`+
///
`
``
1418
`` +
/// Returns None if any bits that would be shifted out differ from the resulting sign bit
``
``
1419
`` +
/// or if rhs >=
``
``
1420
`` +
#[doc = concat!("", stringify!($SelfT), "::BITS.")]
``
``
1421
`` +
/// Otherwise, returns Some(self << rhs).
``
``
1422
`+
///
`
``
1423
`+
/// # Examples
`
``
1424
`+
///
`
``
1425
/// ```
``
1426
`+
/// #![feature(exact_bitshifts)]
`
``
1427
`+
///
`
``
1428
`+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(4), Some(0x10));")]
`
``
1429
`+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 2), Some(1 << ", stringify!($SelfT), "::BITS - 2));")]
`
``
1430
`+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
`
``
1431
`+
#[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 2), Some(-0x2 << ", stringify!($SelfT), "::BITS - 2));")]
`
``
1432
`+
#[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
`
``
1433
/// ```
``
1434
`+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
`
``
1435
`+
#[must_use = "this returns the result of the operation, \
`
``
1436
`+
without modifying the original"]
`
``
1437
`+
#[inline]
`
``
1438
`+
pub const fn exact_shl(self, rhs: u32) -> Option<$SelfT> {
`
``
1439
`+
if rhs < self.leading_zeros() || rhs < self.leading_ones() {
`
``
1440
`+
// SAFETY: rhs is checked above
`
``
1441
`+
Some(unsafe { self.unchecked_shl(rhs) })
`
``
1442
`+
} else {
`
``
1443
`+
None
`
``
1444
`+
}
`
``
1445
`+
}
`
``
1446
+
``
1447
`` +
/// Unchecked exact shift left. Computes self << rhs, assuming the operation can be
``
``
1448
`` +
/// losslessly reversed and rhs cannot be larger than
``
``
1449
`` +
#[doc = concat!("", stringify!($SelfT), "::BITS.")]
``
``
1450
`+
///
`
``
1451
`+
/// # Safety
`
``
1452
`+
///
`
``
1453
`` +
/// This results in undefined behavior when `rhs >= self.leading_zeros() && rhs >=
``
``
1454
`` +
/// self.leading_ones()` i.e. when
``
``
1455
`` +
#[doc = concat!("[", stringify!($SelfT), "::exact_shl]")]
``
``
1456
`` +
/// would return None.
``
``
1457
`+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
`
``
1458
`+
#[must_use = "this returns the result of the operation, \
`
``
1459
`+
without modifying the original"]
`
``
1460
`+
#[inline]
`
``
1461
`+
pub const unsafe fn unchecked_exact_shl(self, rhs: u32) -> $SelfT {
`
``
1462
`+
assert_unsafe_precondition!(
`
``
1463
`+
check_language_ub,
`
``
1464
`+
concat!(stringify!($SelfT), "::unchecked_exact_shl cannot shift out non-zero bits"),
`
``
1465
`+
(
`
``
1466
`+
zeros: u32 = self.leading_zeros(),
`
``
1467
`+
ones: u32 = self.leading_ones(),
`
``
1468
`+
rhs: u32 = rhs,
`
``
1469
`+
) => rhs < zeros || rhs < ones,
`
``
1470
`+
);
`
``
1471
+
``
1472
`+
// SAFETY: this is guaranteed to be safe by the caller
`
``
1473
`+
unsafe { self.unchecked_shl(rhs) }
`
``
1474
`+
}
`
``
1475
+
1416
1476
`` /// Checked shift right. Computes self >> rhs, returning None if rhs is
``
1417
1477
`` /// larger than or equal to the number of bits in self.
``
1418
1478
`///
`
`@@ -1534,6 +1594,63 @@ macro_rules! int_impl {
`
1534
1594
`}
`
1535
1595
`}
`
1536
1596
``
``
1597
`` +
/// Exact shift right. Computes self >> rhs as long as it can be reversed losslessly.
``
``
1598
`+
///
`
``
1599
`` +
/// Returns None if any non-zero bits would be shifted out or if rhs >=
``
``
1600
`` +
#[doc = concat!("", stringify!($SelfT), "::BITS.")]
``
``
1601
`` +
/// Otherwise, returns Some(self >> rhs).
``
``
1602
`+
///
`
``
1603
`+
/// # Examples
`
``
1604
`+
///
`
``
1605
/// ```
``
1606
`+
/// #![feature(exact_bitshifts)]
`
``
1607
`+
///
`
``
1608
`+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(4), Some(0x1));")]
`
``
1609
`+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(5), None);")]
`
``
1610
/// ```
``
1611
`+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
`
``
1612
`+
#[must_use = "this returns the result of the operation, \
`
``
1613
`+
without modifying the original"]
`
``
1614
`+
#[inline]
`
``
1615
`+
pub const fn exact_shr(self, rhs: u32) -> Option<$SelfT> {
`
``
1616
`+
if rhs <= self.trailing_zeros() && rhs < <$SelfT>::BITS {
`
``
1617
`+
// SAFETY: rhs is checked above
`
``
1618
`+
Some(unsafe { self.unchecked_shr(rhs) })
`
``
1619
`+
} else {
`
``
1620
`+
None
`
``
1621
`+
}
`
``
1622
`+
}
`
``
1623
+
``
1624
`` +
/// Unchecked exact shift right. Computes self >> rhs, assuming the operation can be
``
``
1625
`` +
/// losslessly reversed and rhs cannot be larger than
``
``
1626
`` +
#[doc = concat!("", stringify!($SelfT), "::BITS.")]
``
``
1627
`+
///
`
``
1628
`+
/// # Safety
`
``
1629
`+
///
`
``
1630
`` +
/// This results in undefined behavior when `rhs > self.trailing_zeros() || rhs >=
``
``
1631
`` +
#[doc = concat!(stringify!($SelfT), "::BITS`")]
``
``
1632
`+
/// i.e. when
`
``
1633
`` +
#[doc = concat!("[", stringify!($SelfT), "::exact_shr]")]
``
``
1634
`` +
/// would return None.
``
``
1635
`+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
`
``
1636
`+
#[must_use = "this returns the result of the operation, \
`
``
1637
`+
without modifying the original"]
`
``
1638
`+
#[inline]
`
``
1639
`+
pub const unsafe fn unchecked_exact_shr(self, rhs: u32) -> $SelfT {
`
``
1640
`+
assert_unsafe_precondition!(
`
``
1641
`+
check_language_ub,
`
``
1642
`+
concat!(stringify!($SelfT), "::unchecked_exact_shr cannot shift out non-zero bits"),
`
``
1643
`+
(
`
``
1644
`+
zeros: u32 = self.trailing_zeros(),
`
``
1645
`+
bits: u32 = <$SelfT>::BITS,
`
``
1646
`+
rhs: u32 = rhs,
`
``
1647
`+
) => rhs <= zeros && rhs < bits,
`
``
1648
`+
);
`
``
1649
+
``
1650
`+
// SAFETY: this is guaranteed to be safe by the caller
`
``
1651
`+
unsafe { self.unchecked_shr(rhs) }
`
``
1652
`+
}
`
``
1653
+
1537
1654
`` /// Checked absolute value. Computes self.abs(), returning None if
``
1538
1655
`` /// self == MIN.
``
1539
1656
`///
`