Skip to content

Commit 528b115

Browse files
authored
Audit for roundf* (rust-lang#1266)
* Restore `roundf*` intrinsics * Remove negative tests * Add tests for `roundf*`
1 parent 28be0d7 commit 528b115

File tree

5 files changed

+146
-32
lines changed

5 files changed

+146
-32
lines changed

kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -573,12 +573,8 @@ impl<'tcx> GotocCtx<'tcx> {
573573
),
574574
"rotate_left" => codegen_intrinsic_binop!(rol),
575575
"rotate_right" => codegen_intrinsic_binop!(ror),
576-
"roundf32" => codegen_unimplemented_intrinsic!(
577-
"https://github.com/model-checking/kani/issues/1025"
578-
),
579-
"roundf64" => codegen_unimplemented_intrinsic!(
580-
"https://github.com/model-checking/kani/issues/1025"
581-
),
576+
"roundf32" => codegen_simple_intrinsic!(Roundf),
577+
"roundf64" => codegen_simple_intrinsic!(Round),
582578
"saturating_add" => codegen_intrinsic_binop_with_mm!(saturating_add),
583579
"saturating_sub" => codegen_intrinsic_binop_with_mm!(saturating_sub),
584580
"sinf32" => codegen_simple_intrinsic!(Sinf),
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
// Checks that `roundf32` does return:
5+
// * The nearest integer to the argument for some concrete cases.
6+
// * A value that is closer to one of the limits (zero, infinity or negative
7+
// infinity, based on the fractional part of the argument) in all cases.
8+
// * A value such that the difference between it and the argument is between
9+
// zero and 0.5.
10+
#![feature(core_intrinsics)]
11+
use std::intrinsics::roundf32;
12+
13+
#[kani::proof]
14+
fn test_one() {
15+
let one = 1.0;
16+
let result = unsafe { roundf32(one) };
17+
assert!(result == 1.0);
18+
}
19+
20+
#[kani::proof]
21+
fn test_one_frac() {
22+
let one_frac = 1.9;
23+
let result = unsafe { roundf32(one_frac) };
24+
assert!(result == 2.0);
25+
}
26+
27+
#[kani::proof]
28+
fn test_conc() {
29+
let conc = -42.6;
30+
let result = unsafe { roundf32(conc) };
31+
assert!(result == -43.0);
32+
}
33+
34+
#[kani::proof]
35+
fn test_conc_sci() {
36+
let conc = 5.4e-2;
37+
let result = unsafe { roundf32(conc) };
38+
assert!(result == 0.0);
39+
}
40+
41+
#[kani::proof]
42+
fn test_towards_closer() {
43+
let x: f32 = kani::any();
44+
kani::assume(!x.is_nan());
45+
kani::assume(!x.is_infinite());
46+
let result = unsafe { roundf32(x) };
47+
let frac = x.fract().abs();
48+
if x.is_sign_positive() {
49+
if frac >= 0.5 {
50+
assert!(result > x);
51+
} else {
52+
assert!(result <= x);
53+
}
54+
} else {
55+
if frac >= 0.5 {
56+
assert!(result < x);
57+
} else {
58+
assert!(result >= x);
59+
}
60+
}
61+
}
62+
63+
#[kani::proof]
64+
fn test_diff_one() {
65+
let x: f32 = kani::any();
66+
kani::assume(!x.is_nan());
67+
kani::assume(!x.is_infinite());
68+
let result = unsafe { roundf32(x) };
69+
let diff = (x - result).abs();
70+
assert!(diff <= 0.5);
71+
assert!(diff >= 0.0);
72+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
// Checks that `roundf64` does return:
5+
// * The nearest integer to the argument for some concrete cases.
6+
// * A value that is closer to one of the limits (zero, infinity or negative
7+
// infinity, based on the fractional part of the argument) in all cases.
8+
// * A value such that the difference between it and the argument is between
9+
// zero and 0.5.
10+
#![feature(core_intrinsics)]
11+
use std::intrinsics::roundf64;
12+
13+
#[kani::proof]
14+
fn test_one() {
15+
let one = 1.0;
16+
let result = unsafe { roundf64(one) };
17+
assert!(result == 1.0);
18+
}
19+
20+
#[kani::proof]
21+
fn test_one_frac() {
22+
let one_frac = 1.9;
23+
let result = unsafe { roundf64(one_frac) };
24+
assert!(result == 2.0);
25+
}
26+
27+
#[kani::proof]
28+
fn test_conc() {
29+
let conc = -42.6;
30+
let result = unsafe { roundf64(conc) };
31+
assert!(result == -43.0);
32+
}
33+
34+
#[kani::proof]
35+
fn test_conc_sci() {
36+
let conc = 5.4e-2;
37+
let result = unsafe { roundf64(conc) };
38+
assert!(result == 0.0);
39+
}
40+
41+
#[kani::proof]
42+
fn test_towards_closer() {
43+
let x: f64 = kani::any();
44+
kani::assume(!x.is_nan());
45+
kani::assume(!x.is_infinite());
46+
let result = unsafe { roundf64(x) };
47+
let frac = x.fract().abs();
48+
if x.is_sign_positive() {
49+
if frac >= 0.5 {
50+
assert!(result > x);
51+
} else {
52+
assert!(result <= x);
53+
}
54+
} else {
55+
if frac >= 0.5 {
56+
assert!(result < x);
57+
} else {
58+
assert!(result >= x);
59+
}
60+
}
61+
}
62+
63+
#[kani::proof]
64+
fn test_diff_one() {
65+
let x: f64 = kani::any();
66+
kani::assume(!x.is_nan());
67+
kani::assume(!x.is_infinite());
68+
let result = unsafe { roundf64(x) };
69+
let diff = (x - result).abs();
70+
assert!(diff <= 0.5);
71+
assert!(diff >= 0.0);
72+
}

tests/kani/Intrinsics/Math/Rounding/roundf32.rs

Lines changed: 0 additions & 13 deletions
This file was deleted.

tests/kani/Intrinsics/Math/Rounding/roundf64.rs

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)