9
9
//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion",
10
10
//! available online: <https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html>.
11
11
12
+ use safety:: ensures;
13
+
12
14
#[ cfg( kani) ]
13
15
use crate :: forall;
14
16
#[ cfg( kani) ]
@@ -139,7 +141,7 @@ impl DecimalSeq {
139
141
#[ cfg_attr( kani, kani:: loop_invariant( read_index <= Self :: MAX_DIGITS &&
140
142
write_index == read_index + num_new_digits &&
141
143
n < 10u64 << ( shift - 1 ) &&
142
- ( n == 0 || write_index > 0 ) &&
144
+ ( n == 0 || ( shift & 63 ) <= 3 || ( shift & 63 ) >= 61 || write_index > 0 ) &&
143
145
self . num_digits <= Self :: MAX_DIGITS &&
144
146
self . decimal_point <= self . num_digits as i32 &&
145
147
forall!( |i in ( 0 , DecimalSeq :: MAX_DIGITS ) | self . digits[ i] <= 9 )
@@ -158,10 +160,14 @@ impl DecimalSeq {
158
160
n = quotient;
159
161
}
160
162
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
162
167
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 ) ;
165
171
write_index -= 1 ;
166
172
let quotient = n / 10 ;
167
173
let remainder = n - ( 10 * quotient) ;
@@ -321,6 +327,7 @@ pub fn parse_decimal_seq(mut s: &[u8]) -> DecimalSeq {
321
327
d
322
328
}
323
329
330
+ #[ safety:: ensures( |result| ( shift & 63 ) <= 3 || ( shift & 63 ) >= 61 || * result > 0 ) ]
324
331
fn number_of_digits_decimal_left_shift ( d : & DecimalSeq , mut shift : usize ) -> usize {
325
332
#[ rustfmt:: skip]
326
333
const TABLE : [ u16 ; 65 ] = [
@@ -387,7 +394,7 @@ fn number_of_digits_decimal_left_shift(d: &DecimalSeq, mut shift: usize) -> usiz
387
394
let pow5_b = ( 0x7FF & x_b) as usize ;
388
395
let pow5 = & TABLE_POW5 [ pow5_a..] ;
389
396
390
- #[ cfg_attr( kani, kani:: loop_invariant( true ) ) ]
397
+ #[ cfg_attr( kani, kani:: loop_invariant( num_new_digits > 1 || shift <= 3 || shift >= 61 ) ) ]
391
398
for ( i, & p5) in pow5. iter ( ) . enumerate ( ) . take ( pow5_b - pow5_a) {
392
399
if i >= d. num_digits {
393
400
return num_new_digits - 1 ;
0 commit comments