@@ -1518,6 +1518,51 @@ macro_rules! int_impl {
15181518 ( a as Self , b)
15191519 }
15201520
1521+ /// Calculates `self + rhs + carry` without the ability to overflow.
1522+ ///
1523+ /// Performs "signed ternary addition" which takes in an extra bit to add, and may return an
1524+ /// additional bit of overflow. This signed function is used only on the highest-ordered data,
1525+ /// for which the signed overflow result indicates whether the big integer overflowed or not.
1526+ ///
1527+ /// # Examples
1528+ ///
1529+ /// Basic usage:
1530+ ///
1531+ /// ```
1532+ /// #![feature(bigint_helper_methods)]
1533+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".carrying_add(2, false), (7, false));" ) ]
1534+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".carrying_add(2, true), (8, false));" ) ]
1535+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(1, false), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1536+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(0, true), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1537+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(1, true), (" , stringify!( $SelfT) , "::MIN + 1, true));" ) ]
1538+ #[ doc = concat!( "assert_eq!(" ,
1539+ stringify!( $SelfT) , "::MAX.carrying_add(" , stringify!( $SelfT) , "::MAX, true), " ,
1540+ "(-1, true));"
1541+ ) ]
1542+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MIN.carrying_add(-1, true), (" , stringify!( $SelfT) , "::MIN, false));" ) ]
1543+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".carrying_add(" , stringify!( $SelfT) , "::MAX, true), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1544+ /// ```
1545+ ///
1546+ /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
1547+ ///
1548+ /// ```
1549+ /// #![feature(bigint_helper_methods)]
1550+ #[ doc = concat!( "assert_eq!(5_" , stringify!( $SelfT) , ".carrying_add(2, false), 5_" , stringify!( $SelfT) , ".overflowing_add(2));" ) ]
1551+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(1, false), " , stringify!( $SelfT) , "::MAX.overflowing_add(1));" ) ]
1552+ /// ```
1553+ #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
1554+ #[ rustc_const_unstable( feature = "const_bigint_helper_methods" , issue = "85532" ) ]
1555+ #[ must_use = "this returns the result of the operation, \
1556+ without modifying the original"]
1557+ #[ inline]
1558+ pub const fn carrying_add( self , rhs: Self , carry: bool ) -> ( Self , bool ) {
1559+ // note: longer-term this should be done via an intrinsic.
1560+ // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946).
1561+ let ( a, b) = self . overflowing_add( rhs) ;
1562+ let ( c, d) = a. overflowing_add( carry as $SelfT) ;
1563+ ( c, b != d)
1564+ }
1565+
15211566 /// Calculates `self` + `rhs` with an unsigned `rhs`
15221567 ///
15231568 /// Returns a tuple of the addition along with a boolean indicating
@@ -1569,6 +1614,39 @@ macro_rules! int_impl {
15691614 ( a as Self , b)
15701615 }
15711616
1617+ /// Calculates `self - rhs - borrow` without the ability to overflow.
1618+ ///
1619+ /// Performs "signed ternary subtraction" which takes in an extra bit to subtract, and may return an
1620+ /// additional bit of overflow. This signed function is used only on the highest-ordered data,
1621+ /// for which the signed overflow result indicates whether the big integer overflowed or not.
1622+ ///
1623+ /// # Examples
1624+ ///
1625+ /// Basic usage:
1626+ ///
1627+ /// ```
1628+ /// #![feature(bigint_helper_methods)]
1629+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".borrowing_sub(2, false), (3, false));" ) ]
1630+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".borrowing_sub(2, true), (2, false));" ) ]
1631+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".borrowing_sub(1, false), (-1, false));" ) ]
1632+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".borrowing_sub(1, true), (-2, false));" ) ]
1633+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MIN.borrowing_sub(1, true), (" , stringify!( $SelfT) , "::MAX - 1, true));" ) ]
1634+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.borrowing_sub(-1, false), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1635+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.borrowing_sub(-1, true), (" , stringify!( $SelfT) , "::MAX, false));" ) ]
1636+ /// ```
1637+ #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
1638+ #[ rustc_const_unstable( feature = "const_bigint_helper_methods" , issue = "85532" ) ]
1639+ #[ must_use = "this returns the result of the operation, \
1640+ without modifying the original"]
1641+ #[ inline]
1642+ pub const fn borrowing_sub( self , rhs: Self , borrow: bool ) -> ( Self , bool ) {
1643+ // note: longer-term this should be done via an intrinsic.
1644+ // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946).
1645+ let ( a, b) = self . overflowing_sub( rhs) ;
1646+ let ( c, d) = a. overflowing_sub( borrow as $SelfT) ;
1647+ ( c, b != d)
1648+ }
1649+
15721650 /// Calculates `self` - `rhs` with an unsigned `rhs`
15731651 ///
15741652 /// Returns a tuple of the subtraction along with a boolean indicating
0 commit comments