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

`///

`