summaryrefslogtreecommitdiffstats
path: root/library/core/src/num/uint_macros.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/core/src/num/uint_macros.rs189
1 files changed, 83 insertions, 106 deletions
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 733655442..335cc5124 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -474,13 +474,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -688,104 +687,69 @@ macro_rules! uint_impl {
/// rounded down.
///
/// This method might not be optimized owing to implementation details;
- /// `log2` can produce results more efficiently for base 2, and `log10`
+ /// `ilog2` can produce results more efficiently for base 2, and `ilog10`
/// can produce results more efficiently for base 10.
///
/// # Panics
///
- /// When the number is zero, or if the base is not at least 2;
- /// it panics in debug mode and the return value is 0 in release mode.
+ /// This function will panic if `self` is zero, or if `base` is less then 2.
///
/// # Examples
///
/// ```
/// #![feature(int_log)]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")]
+ #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")]
/// ```
#[unstable(feature = "int_log", issue = "70887")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
- pub const fn log(self, base: Self) -> u32 {
- match self.checked_log(base) {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ pub const fn ilog(self, base: Self) -> u32 {
+ assert!(base >= 2, "base of integer logarithm must be at least 2");
+ self.checked_ilog(base).expect("argument of integer logarithm must be positive")
}
/// Returns the base 2 logarithm of the number, rounded down.
///
/// # Panics
///
- /// When the number is zero it panics in debug mode and
- /// the return value is 0 in release mode.
+ /// This function will panic if `self` is zero.
///
/// # Examples
///
/// ```
/// #![feature(int_log)]
- #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")]
+ #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")]
/// ```
#[unstable(feature = "int_log", issue = "70887")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
- pub const fn log2(self) -> u32 {
- match self.checked_log2() {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ pub const fn ilog2(self) -> u32 {
+ self.checked_ilog2().expect("argument of integer logarithm must be positive")
}
/// Returns the base 10 logarithm of the number, rounded down.
///
/// # Panics
///
- /// When the number is zero it panics in debug mode and the
- /// return value is 0 in release mode.
+ /// This function will panic if `self` is zero.
///
/// # Example
///
/// ```
/// #![feature(int_log)]
- #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")]
/// ```
#[unstable(feature = "int_log", issue = "70887")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
- pub const fn log10(self) -> u32 {
- match self.checked_log10() {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ pub const fn ilog10(self) -> u32 {
+ self.checked_ilog10().expect("argument of integer logarithm must be positive")
}
/// Returns the logarithm of the number with respect to an arbitrary base,
@@ -794,20 +758,20 @@ macro_rules! uint_impl {
/// Returns `None` if the number is zero, or if the base is not at least 2.
///
/// This method might not be optimized owing to implementation details;
- /// `checked_log2` can produce results more efficiently for base 2, and
- /// `checked_log10` can produce results more efficiently for base 10.
+ /// `checked_ilog2` can produce results more efficiently for base 2, and
+ /// `checked_ilog10` can produce results more efficiently for base 10.
///
/// # Examples
///
/// ```
/// #![feature(int_log)]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")]
+ #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")]
/// ```
#[unstable(feature = "int_log", issue = "70887")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log(self, base: Self) -> Option<u32> {
+ pub const fn checked_ilog(self, base: Self) -> Option<u32> {
if self <= 0 || base <= 1 {
None
} else {
@@ -816,7 +780,7 @@ macro_rules! uint_impl {
// Optimization for 128 bit wide integers.
if Self::BITS == 128 {
- let b = Self::log2(self) / (Self::log2(base) + 1);
+ let b = Self::ilog2(self) / (Self::ilog2(base) + 1);
n += b;
r /= base.pow(b as u32);
}
@@ -837,15 +801,15 @@ macro_rules! uint_impl {
///
/// ```
/// #![feature(int_log)]
- #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")]
+ #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")]
/// ```
#[unstable(feature = "int_log", issue = "70887")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log2(self) -> Option<u32> {
+ pub const fn checked_ilog2(self) -> Option<u32> {
if let Some(x) = <$NonZeroT>::new(self) {
- Some(x.log2())
+ Some(x.ilog2())
} else {
None
}
@@ -859,15 +823,15 @@ macro_rules! uint_impl {
///
/// ```
/// #![feature(int_log)]
- #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")]
/// ```
#[unstable(feature = "int_log", issue = "70887")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log10(self) -> Option<u32> {
+ pub const fn checked_ilog10(self) -> Option<u32> {
if let Some(x) = <$NonZeroT>::new(self) {
- Some(x.log10())
+ Some(x.ilog10())
} else {
None
}
@@ -1026,7 +990,7 @@ macro_rules! uint_impl {
// squaring the base afterwards is not necessary and may cause a
// needless overflow.
- Some(try_opt!(acc.checked_mul(base)))
+ acc.checked_mul(base)
}
/// Saturating integer addition. Computes `self + rhs`, saturating at
@@ -1057,13 +1021,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1198,13 +1161,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1494,7 +1456,6 @@ macro_rules! uint_impl {
/// Basic usage
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));")]
/// ```
@@ -1508,37 +1469,42 @@ macro_rules! uint_impl {
(a as Self, b)
}
- /// Calculates `self + rhs + carry` without the ability to overflow.
+ /// Calculates `self` + `rhs` + `carry` and returns a tuple containing
+ /// the sum and the output carry.
///
- /// Performs "ternary addition" which takes in an extra bit to add, and may return an
- /// additional bit of overflow. This allows for chaining together multiple additions
- /// to create "big integers" which represent larger values.
+ /// Performs "ternary addition" of two integer operands and a carry-in
+ /// bit, and returns an output integer and a carry-out bit. This allows
+ /// chaining together multiple additions to create a wider addition, and
+ /// can be useful for bignum addition.
///
#[doc = concat!("This can be thought of as a ", stringify!($BITS), "-bit \"full adder\", in the electronics sense.")]
///
- /// # Examples
+ /// If the input carry is false, this method is equivalent to
+ /// [`overflowing_add`](Self::overflowing_add), and the output carry is
+ /// equal to the overflow flag. Note that although carry and overflow
+ /// flags are similar for unsigned integers, they are different for
+ /// signed integers.
///
- /// Basic usage
+ /// # Examples
///
/// ```
/// #![feature(bigint_helper_methods)]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (0, true));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")]
- #[doc = concat!("assert_eq!(",
- stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
- "(", stringify!($SelfT), "::MAX, true));"
- )]
- /// ```
///
- /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
+ #[doc = concat!("// 3 MAX (a = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
+ #[doc = concat!("// + 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")]
+ /// // ---------
+ #[doc = concat!("// 9 6 (sum = 9 × 2^", stringify!($BITS), " + 6)")]
///
- /// ```
- /// #![feature(bigint_helper_methods)]
- #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
+ #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (3, ", stringify!($SelfT), "::MAX);")]
+ #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (5, 7);")]
+ /// let carry0 = false;
+ ///
+ /// let (sum0, carry1) = a0.carrying_add(b0, carry0);
+ /// assert_eq!(carry1, true);
+ /// let (sum1, carry2) = a1.carrying_add(b1, carry1);
+ /// assert_eq!(carry2, false);
+ ///
+ /// assert_eq!((sum1, sum0), (9, 6));
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
@@ -1564,13 +1530,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1590,7 +1555,6 @@ macro_rules! uint_impl {
/// Basic usage
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")]
/// ```
@@ -1604,22 +1568,35 @@ macro_rules! uint_impl {
(a as Self, b)
}
- /// Calculates `self - rhs - borrow` without the ability to overflow.
+ /// Calculates `self` &minus; `rhs` &minus; `borrow` and returns a tuple
+ /// containing the difference and the output borrow.
///
- /// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return
- /// an additional bit of overflow. This allows for chaining together multiple subtractions
- /// to create "big integers" which represent larger values.
+ /// Performs "ternary subtraction" by subtracting both an integer
+ /// operand and a borrow-in bit from `self`, and returns an output
+ /// integer and a borrow-out bit. This allows chaining together multiple
+ /// subtractions to create a wider subtraction, and can be useful for
+ /// bignum subtraction.
///
/// # Examples
///
- /// Basic usage
- ///
/// ```
/// #![feature(bigint_helper_methods)]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
- #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, false), (", stringify!($SelfT), "::MAX, true));")]
- #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, true));")]
+ ///
+ #[doc = concat!("// 9 6 (a = 9 × 2^", stringify!($BITS), " + 6)")]
+ #[doc = concat!("// - 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")]
+ /// // ---------
+ #[doc = concat!("// 3 MAX (diff = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
+ ///
+ #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (9, 6);")]
+ #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (5, 7);")]
+ /// let borrow0 = false;
+ ///
+ /// let (diff0, borrow1) = a0.borrowing_sub(b0, borrow0);
+ /// assert_eq!(borrow1, true);
+ /// let (diff1, borrow2) = a1.borrowing_sub(b1, borrow1);
+ /// assert_eq!(borrow2, false);
+ ///
+ #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")]
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]