|
| 1 | +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 2 | +// SPDX-License-Identifier: Apache-2.0 OR MIT |
| 3 | + |
| 4 | +// Check that `ctpop` is supported and returns the expected results |
| 5 | +// (the number of bits equal to one in a value) |
| 6 | +#![feature(core_intrinsics)] |
| 7 | +use std::intrinsics::ctpop; |
| 8 | + |
| 9 | +// Define a function for counting like `ctpop` and assert that their results are |
| 10 | +// the same for any value |
| 11 | +macro_rules! test_ctpop { |
| 12 | + ( $fn_name:ident, $ty:ty ) => { |
| 13 | + fn $fn_name(x: $ty) -> $ty { |
| 14 | + let mut count = 0; |
| 15 | + let num_bits = <$ty>::BITS; |
| 16 | + for i in 0..num_bits { |
| 17 | + // Get value at index `i` |
| 18 | + let bitmask = 1 << i; |
| 19 | + let bit = x & bitmask; |
| 20 | + if bit != 0 { |
| 21 | + count += 1; |
| 22 | + } |
| 23 | + // The assertion below mitigates a low performance issue in this |
| 24 | + // test due to the loop having a conditional jump at the end, |
| 25 | + // see https://github.com/model-checking/kani/issues/1046 for |
| 26 | + // more details. |
| 27 | + assert!(count >= 0); |
| 28 | + } |
| 29 | + count |
| 30 | + } |
| 31 | + let var: $ty = kani::any(); |
| 32 | + // Check that the result is correct |
| 33 | + assert!($fn_name(var) == ctpop(var)); |
| 34 | + |
| 35 | + // Check that the stable version returns the same value |
| 36 | + assert!(ctpop(var) as u32 == var.count_ones()); |
| 37 | + }; |
| 38 | +} |
| 39 | + |
| 40 | +#[kani::proof] |
| 41 | +fn test_ctpop_u8() { |
| 42 | + test_ctpop!(my_ctpop_u8, u8); |
| 43 | +} |
| 44 | + |
| 45 | +#[kani::proof] |
| 46 | +fn test_ctpop_u16() { |
| 47 | + test_ctpop!(my_ctpop_u16, u16); |
| 48 | +} |
| 49 | + |
| 50 | +#[kani::proof] |
| 51 | +fn test_ctpop_u32() { |
| 52 | + test_ctpop!(my_ctpop_u32, u32); |
| 53 | +} |
| 54 | + |
| 55 | +#[kani::proof] |
| 56 | +fn test_ctpop_u64() { |
| 57 | + test_ctpop!(my_ctpop_u64, u64); |
| 58 | +} |
| 59 | + |
| 60 | +// We do not run the test for u128 because it takes too long |
| 61 | +fn test_ctpop_u128() { |
| 62 | + test_ctpop!(my_ctpop_u128, u128); |
| 63 | +} |
| 64 | + |
| 65 | +#[kani::proof] |
| 66 | +fn test_ctpop_usize() { |
| 67 | + test_ctpop!(my_ctpop_usize, usize); |
| 68 | +} |
| 69 | + |
| 70 | +// `ctpop` also works with signed integer types, but this causes overflows |
| 71 | +// unless we restrict their values considerably (due to the conversions in |
| 72 | +// `count_ones`), making the signed versions not very interesting to test here. |
| 73 | +// https://github.com/model-checking/kani/issues/934 |
0 commit comments