But writing proof by hand is hard
#[inline]
#[verus_spec(ret =>
requires
(is_pow2(align as int) && align >= 2) || may_panic(),
ensures
align >= 2,
is_pow2(align as int),
ret <= self,
ret % align == 0,
ret == nat_align_down(self as nat, align as nat),
forall |n: nat| !(n<=self && #[trigger] (n % align as nat) == 0) || (ret >= n),
)]
fn align_down(self, align: Self) -> Self {
vstd_extra::assert!(align.is_power_of_two() && align >= 2);
proof!{
is_pow2_equiv(align as int);
lemma_low_bits_mask_values();
let mask = (align - 1) as Self;
let e = choose |e: nat| pow(2, e) == align;
lemma_pow2(e);
assert(e < $uint_type::BITS) by {
if e >= $uint_type::BITS {
lemma_pow2_strictly_increases($uint_type::BITS as nat, e);
lemma2_to64();
}
}
call_lemma_low_bits_mask_is_mod!($uint_type, self, e);
assert(self == (self & mask) + (self & !mask)) by (bit_vector);
assert((self & !mask) as nat == nat_align_down(self as nat, align as nat));
lemma_nat_align_down_sound(self as nat, align as nat);
}
self & !(align - 1)
}