Skip to content

Commit 038c707

Browse files
committed
Extended invariants
1 parent 8ccd693 commit 038c707

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

library/core/src/num/dec2flt/decimal_seq.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion",
1010
//! available online: <https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html>.
1111
12+
use safety::ensures;
13+
1214
#[cfg(kani)]
1315
use crate::forall;
1416
#[cfg(kani)]
@@ -139,7 +141,7 @@ impl DecimalSeq {
139141
#[cfg_attr(kani, kani::loop_invariant(read_index <= Self::MAX_DIGITS &&
140142
write_index == read_index + num_new_digits &&
141143
n < 10u64 << (shift - 1) &&
142-
(n == 0 || write_index > 0) &&
144+
(n == 0 || (shift & 63) <= 3 || (shift & 63) >= 61 || write_index > 0) &&
143145
self.num_digits <= Self::MAX_DIGITS &&
144146
self.decimal_point <= self.num_digits as i32 &&
145147
forall!(|i in (0,DecimalSeq::MAX_DIGITS)| self.digits[i] <= 9)
@@ -158,10 +160,14 @@ impl DecimalSeq {
158160
n = quotient;
159161
}
160162

161-
#[cfg_attr(kani, kani::loop_invariant(self.num_digits <= Self::MAX_DIGITS && self.decimal_point <= self.num_digits as i32 && (write_index > 0 || prev(write_index) == 1)))]
163+
#[cfg_attr(kani, kani::loop_invariant(self.num_digits <= Self::MAX_DIGITS && self.decimal_point <= self.num_digits as i32))]
164+
// TODO: should add invariant along the lines of
165+
// (n == 0 || write_index > 0) && (prev(n) as usize + 9) / 10 <= prev(write_index))]
166+
// to avoid the below kani::assume
162167
while n > 0 {
163-
//true but hard to write proof with kani currently
164-
// kani::assume(write_index > 0);
168+
// true but hard to write proof with kani currently
169+
#[cfg(kani)]
170+
kani::assume(write_index > 0);
165171
write_index -= 1;
166172
let quotient = n / 10;
167173
let remainder = n - (10 * quotient);
@@ -321,6 +327,7 @@ pub fn parse_decimal_seq(mut s: &[u8]) -> DecimalSeq {
321327
d
322328
}
323329

330+
#[safety::ensures(|result| (shift & 63) <= 3 || (shift & 63) >= 61 || *result > 0)]
324331
fn number_of_digits_decimal_left_shift(d: &DecimalSeq, mut shift: usize) -> usize {
325332
#[rustfmt::skip]
326333
const TABLE: [u16; 65] = [
@@ -387,7 +394,7 @@ fn number_of_digits_decimal_left_shift(d: &DecimalSeq, mut shift: usize) -> usiz
387394
let pow5_b = (0x7FF & x_b) as usize;
388395
let pow5 = &TABLE_POW5[pow5_a..];
389396

390-
#[cfg_attr(kani, kani::loop_invariant(true))]
397+
#[cfg_attr(kani, kani::loop_invariant(num_new_digits > 1 || shift <= 3 || shift >= 61))]
391398
for (i, &p5) in pow5.iter().enumerate().take(pow5_b - pow5_a) {
392399
if i >= d.num_digits {
393400
return num_new_digits - 1;

0 commit comments

Comments
 (0)