Make sure the float comparison output is consistent with the expected

behavior when NaN is involved.
This commit is contained in:
kennytm 2018-05-17 04:24:10 +08:00
parent ed9a29a976
commit 50bc72df44
No known key found for this signature in database
GPG key ID: FEF6C8051D0E013C
2 changed files with 71 additions and 7 deletions

View file

@ -1,7 +1,6 @@
use rustc::mir;
use rustc::ty::{self, Ty};
use syntax::ast::FloatTy;
use std::cmp::Ordering;
use rustc::ty::layout::LayoutOf;
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
@ -181,12 +180,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
let l = <$ty>::from_bits(l);
let r = <$ty>::from_bits(r);
let val = match bin_op {
Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Equal),
Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Equal),
Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Less),
Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Greater),
Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Greater),
Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Less),
Eq => PrimVal::from_bool(l == r),
Ne => PrimVal::from_bool(l != r),
Lt => PrimVal::from_bool(l < r),
Le => PrimVal::from_bool(l <= r),
Gt => PrimVal::from_bool(l > r),
Ge => PrimVal::from_bool(l >= r),
Add => PrimVal::Bytes((l + r).value.to_bits()),
Sub => PrimVal::Bytes((l - r).value.to_bits()),
Mul => PrimVal::Bytes((l * r).value.to_bits()),

View file

@ -0,0 +1,65 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(test)]
extern crate test;
use std::f64::{NAN, NEG_INFINITY, INFINITY, MAX};
use std::mem::size_of;
use test::black_box;
// Ensure the const-eval result and runtime result of float comparison are equivalent.
macro_rules! compare {
($op:tt) => {
compare!(
[NEG_INFINITY, -MAX, -1.0, -0.0, 0.0, 1.0, MAX, INFINITY, NAN],
$op
);
};
([$($lhs:expr),+], $op:tt) => {
$(compare!(
$lhs,
$op,
[NEG_INFINITY, -MAX, -1.0, -0.0, 0.0, 1.0, MAX, INFINITY, NAN]
);)+
};
($lhs:expr, $op:tt, [$($rhs:expr),+]) => {
$({
// Wrap the check in its own function to reduce time needed to borrowck.
fn check() {
static CONST_EVAL: bool = $lhs $op $rhs;
let runtime_eval = black_box($lhs) $op black_box($rhs);
assert_eq!(CONST_EVAL, runtime_eval, stringify!($lhs $op $rhs));
assert_eq!(
size_of::<[u8; ($lhs $op $rhs) as usize]>(),
runtime_eval as usize,
stringify!($lhs $op $rhs (forced const eval))
);
}
check();
})+
};
}
fn main() {
assert_eq!(0.0/0.0 < 0.0/0.0, false);
assert_eq!(0.0/0.0 > 0.0/0.0, false);
assert_eq!(NAN < NAN, false);
assert_eq!(NAN > NAN, false);
compare!(==);
compare!(!=);
compare!(<);
compare!(<=);
compare!(>);
compare!(>=);
}