@@ -1657,6 +1657,51 @@ mod verify {
16571657 }
16581658 }
16591659 }
1660+
1661+ /// A macro to generate Kani proof harnesses for the `carrying_mul` method,
1662+ ///
1663+ /// The macro creates multiple harnesses for different ranges of input values,
1664+ /// allowing testing of both small and large inputs.
1665+ ///
1666+ /// # Parameters:
1667+ /// - `$type`: The integer type (e.g., u8, u16) for which the `carrying_mul` function is being tested.
1668+ /// - `$wide_type`: A wider type to simulate the multiplication (e.g., u16 for u8, u32 for u16).
1669+ /// - `$harness_name`: The name of the Kani harness to be generated.
1670+ /// - `$min`: The minimum value for the range of inputs for `lhs`, `rhs`, and `carry_in`.
1671+ /// - `$max`: The maximum value for the range of inputs for `lhs`, `rhs`, and `carry_in`.
1672+ macro_rules! generate_carrying_mul_intervals {
1673+ ( $type: ty, $wide_type: ty, $( $harness_name: ident, $min: expr, $max: expr) ,+) => {
1674+ $(
1675+ #[ kani:: proof]
1676+ pub fn $harness_name( ) {
1677+ let lhs: $type = kani:: any:: <$type>( ) ;
1678+ let rhs: $type = kani:: any:: <$type>( ) ;
1679+ let carry_in: $type = kani:: any:: <$type>( ) ;
1680+
1681+ kani:: assume( lhs >= $min && lhs <= $max) ;
1682+ kani:: assume( rhs >= $min && rhs <= $max) ;
1683+ kani:: assume( carry_in >= $min && carry_in <= $max) ;
1684+
1685+ // Perform the carrying multiplication
1686+ let ( result, carry_out) = lhs. carrying_mul( rhs, carry_in) ;
1687+
1688+ // Manually compute the expected result and carry using wider type
1689+ let wide_result = ( lhs as $wide_type)
1690+ . wrapping_mul( rhs as $wide_type)
1691+ . wrapping_add( carry_in as $wide_type) ;
1692+
1693+ let expected_result = wide_result as $type;
1694+ let expected_carry = ( wide_result >> <$type>:: BITS ) as $type;
1695+
1696+ // Assert the result and carry are correct
1697+ assert_eq!( result, expected_result) ;
1698+ assert_eq!( carry_out, expected_carry) ;
1699+ }
1700+ ) +
1701+ }
1702+ }
1703+
1704+
16601705
16611706 // Part 2 : Nested unsafe functions Generation Macros --> https://github.com/verify-rust-std/blob/main/doc/src/challenges/0011-floats-ints.md
16621707
@@ -1687,6 +1732,19 @@ mod verify {
16871732 }
16881733 }
16891734
1735+ // Verify `wrapping_{shl, shr}` which internally uses `unchecked_{shl,shr}`
1736+ macro_rules! generate_wrapping_shift_harness {
1737+ ( $type: ty, $method: ident, $harness_name: ident) => {
1738+ #[ kani:: proof_for_contract( $type:: $method) ]
1739+ pub fn $harness_name( ) {
1740+ let num1: $type = kani:: any:: <$type>( ) ;
1741+ let num2: u32 = kani:: any:: <u32 >( ) ;
1742+
1743+ let _ = num1. $method( num2) ;
1744+ }
1745+ }
1746+ }
1747+
16901748 // `unchecked_add` proofs
16911749 //
16921750 // Target types:
@@ -1728,7 +1786,7 @@ mod verify {
17281786 generate_unchecked_neg_harness ! ( i128 , checked_unchecked_neg_i128) ;
17291787 generate_unchecked_neg_harness ! ( isize , checked_unchecked_neg_isize) ;
17301788
1731- // unchecked_mul proofs
1789+ // ` unchecked_mul` proofs
17321790 //
17331791 // Target types:
17341792 // i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total, with different interval checks for each.
@@ -1879,8 +1937,37 @@ mod verify {
18791937 generate_unchecked_math_harness ! ( u128 , unchecked_sub, checked_unchecked_sub_u128) ;
18801938 generate_unchecked_math_harness ! ( usize , unchecked_sub, checked_unchecked_sub_usize) ;
18811939
1940+
1941+ // Part_2 `carrying_mul` proofs
1942+ //
1943+ // ====================== u8 Harnesses ======================
1944+ /// Kani proof harness for `carrying_mul` on `u8` type with full range of values.
1945+ generate_carrying_mul_intervals ! ( u8 , u16 ,
1946+ carrying_mul_u8_full_range, 0u8 , u8 :: MAX
1947+ ) ;
1948+
1949+ // ====================== u16 Harnesses ======================
1950+ /// Kani proof harness for `carrying_mul` on `u16` type with full range of values.
1951+ generate_carrying_mul_intervals ! ( u16 , u32 ,
1952+ carrying_mul_u16_full_range, 0u16 , u16 :: MAX
1953+ ) ;
1954+
1955+ // ====================== u32 Harnesses ======================
1956+ generate_carrying_mul_intervals ! ( u32 , u64 ,
1957+ carrying_mul_u32_small, 0u32 , 10u32 ,
1958+ carrying_mul_u32_large, u32 :: MAX - 10u32 , u32 :: MAX ,
1959+ carrying_mul_u32_mid_edge, ( u32 :: MAX / 2 ) - 10u32 , ( u32 :: MAX / 2 ) + 10u32
1960+ ) ;
1961+
1962+ // ====================== u64 Harnesses ======================
1963+ generate_carrying_mul_intervals ! ( u64 , u128 ,
1964+ carrying_mul_u64_small, 0u64 , 10u64 ,
1965+ carrying_mul_u64_large, u64 :: MAX - 10u64 , u64 :: MAX ,
1966+ carrying_mul_u64_mid_edge, ( u64 :: MAX / 2 ) - 10u64 , ( u64 :: MAX / 2 ) + 10u64
1967+ ) ;
1968+
18821969
1883- // Part 2 : Proof harnesses
1970+ // Part_2 `widening_mul` proofs
18841971
18851972 // ====================== u8 Harnesses ======================
18861973 generate_widening_mul_intervals ! ( u8 , u16 , widening_mul_u8, 0u8 , u8 :: MAX ) ;
@@ -1905,4 +1992,55 @@ mod verify {
19051992 widening_mul_u64_large, u64 :: MAX - 10u64 , u64 :: MAX ,
19061993 widening_mul_u64_mid_edge, ( u64 :: MAX / 2 ) - 10u64 , ( u64 :: MAX / 2 ) + 10u64
19071994 ) ;
1995+
1996+ // Part_2 `wrapping_shl` proofs
1997+ //
1998+ // Target types:
1999+ // i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
2000+ //
2001+ // Target contracts:
2002+ // #[ensures(|result| *result == self << (rhs & (Self::BITS - 1)))]
2003+ //
2004+ // Target function:
2005+ // pub const fn wrapping_shl(self, rhs: u32) -> Self
2006+ //
2007+ // This function performs an panic-free bitwise left shift operation.
2008+ generate_wrapping_shift_harness ! ( i8 , wrapping_shl, checked_wrapping_shl_i8) ;
2009+ generate_wrapping_shift_harness ! ( i16 , wrapping_shl, checked_wrapping_shl_i16) ;
2010+ generate_wrapping_shift_harness ! ( i32 , wrapping_shl, checked_wrapping_shl_i32) ;
2011+ generate_wrapping_shift_harness ! ( i64 , wrapping_shl, checked_wrapping_shl_i64) ;
2012+ generate_wrapping_shift_harness ! ( i128 , wrapping_shl, checked_wrapping_shl_i128) ;
2013+ generate_wrapping_shift_harness ! ( isize , wrapping_shl, checked_wrapping_shl_isize) ;
2014+ generate_wrapping_shift_harness ! ( u8 , wrapping_shl, checked_wrapping_shl_u8) ;
2015+ generate_wrapping_shift_harness ! ( u16 , wrapping_shl, checked_wrapping_shl_u16) ;
2016+ generate_wrapping_shift_harness ! ( u32 , wrapping_shl, checked_wrapping_shl_u32) ;
2017+ generate_wrapping_shift_harness ! ( u64 , wrapping_shl, checked_wrapping_shl_u64) ;
2018+ generate_wrapping_shift_harness ! ( u128 , wrapping_shl, checked_wrapping_shl_u128) ;
2019+ generate_wrapping_shift_harness ! ( usize , wrapping_shl, checked_wrapping_shl_usize) ;
2020+
2021+ // Part_2 `wrapping_shr` proofs
2022+ //
2023+ // Target types:
2024+ // i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
2025+ //
2026+ // Target contracts:
2027+ // #[ensures(|result| *result == self >> (rhs & (Self::BITS - 1)))]
2028+ // Target function:
2029+ // pub const fn wrapping_shr(self, rhs: u32) -> Self {
2030+ //
2031+ // This function performs an panic-free bitwise right shift operation.
2032+ generate_wrapping_shift_harness ! ( i8 , wrapping_shr, checked_wrapping_shr_i8) ;
2033+ generate_wrapping_shift_harness ! ( i16 , wrapping_shr, checked_wrapping_shr_i16) ;
2034+ generate_wrapping_shift_harness ! ( i32 , wrapping_shr, checked_wrapping_shr_i32) ;
2035+ generate_wrapping_shift_harness ! ( i64 , wrapping_shr, checked_wrapping_shr_i64) ;
2036+ generate_wrapping_shift_harness ! ( i128 , wrapping_shr, checked_wrapping_shr_i128) ;
2037+ generate_wrapping_shift_harness ! ( isize , wrapping_shr, checked_wrapping_shr_isize) ;
2038+ generate_wrapping_shift_harness ! ( u8 , wrapping_shr, checked_wrapping_shr_u8) ;
2039+ generate_wrapping_shift_harness ! ( u16 , wrapping_shr, checked_wrapping_shr_u16) ;
2040+ generate_wrapping_shift_harness ! ( u32 , wrapping_shr, checked_wrapping_shr_u32) ;
2041+ generate_wrapping_shift_harness ! ( u64 , wrapping_shr, checked_wrapping_shr_u64) ;
2042+ generate_wrapping_shift_harness ! ( u128 , wrapping_shr, checked_wrapping_shr_u128) ;
2043+ generate_wrapping_shift_harness ! ( usize , wrapping_shr, checked_wrapping_shr_usize) ;
2044+
19082045}
2046+
0 commit comments