@@ -1512,6 +1512,53 @@ macro_rules! int_impl {
15121512 ( a as Self , b)
15131513 }
15141514
1515+ /// Calculates `self + rhs + carry` without the ability to overflow.
1516+ ///
1517+ /// Performs "ternary addition" which takes in an extra bit to add, and may return an
1518+ /// additional bit of overflow. This allows for chaining together multiple additions
1519+ /// to create "big integers" which represent larger values.
1520+ ///
1521+ #[ doc = concat!( "This can be thought of as a " , stringify!( $BITS) , "-bit \" full adder\" , in the electronics sense." ) ]
1522+ ///
1523+ /// # Examples
1524+ ///
1525+ /// Basic usage
1526+ ///
1527+ /// ```
1528+ /// #![feature(bigint_helper_methods)]
1529+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".carrying_add(2, false), (7, false));" ) ]
1530+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".carrying_add(2, true), (8, false));" ) ]
1531+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(1, false), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1532+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(0, true), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1533+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(1, true), (" , stringify!( $SelfT) , "::MIN + 1, true));" ) ]
1534+ #[ doc = concat!( "assert_eq!(" ,
1535+ stringify!( $SelfT) , "::MAX.carrying_add(" , stringify!( $SelfT) , "::MAX, true), " ,
1536+ "(-1, true));"
1537+ ) ]
1538+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MIN.carrying_add(-1, true), (" , stringify!( $SelfT) , "::MIN, false));" ) ]
1539+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".carrying_add(" , stringify!( $SelfT) , "::MAX, true), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1540+ /// ```
1541+ ///
1542+ /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
1543+ ///
1544+ /// ```
1545+ /// #![feature(bigint_helper_methods)]
1546+ #[ doc = concat!( "assert_eq!(5_" , stringify!( $SelfT) , ".carrying_add(2, false), 5_" , stringify!( $SelfT) , ".overflowing_add(2));" ) ]
1547+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.carrying_add(1, false), " , stringify!( $SelfT) , "::MAX.overflowing_add(1));" ) ]
1548+ /// ```
1549+ #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
1550+ #[ rustc_const_unstable( feature = "const_bigint_helper_methods" , issue = "85532" ) ]
1551+ #[ must_use = "this returns the result of the operation, \
1552+ without modifying the original"]
1553+ #[ inline]
1554+ pub const fn carrying_add( self , rhs: Self , carry: bool ) -> ( Self , bool ) {
1555+ // note: longer-term this should be done via an intrinsic.
1556+ // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946).
1557+ let ( a, b) = self . overflowing_add( rhs) ;
1558+ let ( c, d) = a. overflowing_add( carry as $SelfT) ;
1559+ ( c, b != d)
1560+ }
1561+
15151562 /// Calculates `self` + `rhs` with an unsigned `rhs`
15161563 ///
15171564 /// Returns a tuple of the addition along with a boolean indicating
@@ -1563,6 +1610,39 @@ macro_rules! int_impl {
15631610 ( a as Self , b)
15641611 }
15651612
1613+ /// Calculates `self - rhs - borrow` without the ability to overflow.
1614+ ///
1615+ /// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return
1616+ /// an additional bit of overflow. This allows for chaining together multiple subtractions
1617+ /// to create "big integers" which represent larger values.
1618+ ///
1619+ /// # Examples
1620+ ///
1621+ /// Basic usage
1622+ ///
1623+ /// ```
1624+ /// #![feature(bigint_helper_methods)]
1625+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".borrowing_sub(2, false), (3, false));" ) ]
1626+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".borrowing_sub(2, true), (2, false));" ) ]
1627+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".borrowing_sub(1, false), (-1, false));" ) ]
1628+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".borrowing_sub(1, true), (-2, false));" ) ]
1629+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MIN.borrowing_sub(1, true), (" , stringify!( $SelfT) , "::MAX - 1, true));" ) ]
1630+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.borrowing_sub(-1, false), (" , stringify!( $SelfT) , "::MIN, true));" ) ]
1631+ #[ doc = concat!( "assert_eq!(" , stringify!( $SelfT) , "::MAX.borrowing_sub(-1, true), (" , stringify!( $SelfT) , "::MAX, false));" ) ]
1632+ /// ```
1633+ #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
1634+ #[ rustc_const_unstable( feature = "const_bigint_helper_methods" , issue = "85532" ) ]
1635+ #[ must_use = "this returns the result of the operation, \
1636+ without modifying the original"]
1637+ #[ inline]
1638+ pub const fn borrowing_sub( self , rhs: Self , borrow: bool ) -> ( Self , bool ) {
1639+ // note: longer-term this should be done via an intrinsic.
1640+ // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946).
1641+ let ( a, b) = self . overflowing_sub( rhs) ;
1642+ let ( c, d) = a. overflowing_sub( borrow as $SelfT) ;
1643+ ( c, b != d)
1644+ }
1645+
15661646 /// Calculates `self` - `rhs` with an unsigned `rhs`
15671647 ///
15681648 /// Returns a tuple of the subtraction along with a boolean indicating
0 commit comments