commit
a5eb61a4ad
2 changed files with 31 additions and 14 deletions
|
|
@ -1,3 +1,6 @@
|
|||
use std::convert::TryInto;
|
||||
|
||||
use rustc_apfloat::Float;
|
||||
use rustc::ty::layout::{Align, LayoutOf, Size};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir;
|
||||
|
|
@ -577,7 +580,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
};
|
||||
this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?;
|
||||
}
|
||||
// underscore case for windows
|
||||
// underscore case for windows, here and below
|
||||
// (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
|
||||
"_hypot" | "hypot" | "atan2" => {
|
||||
// FIXME: Using host floats.
|
||||
let f1 = f64::from_bits(this.read_scalar(args[0])?.to_u64()?);
|
||||
|
|
@ -589,16 +593,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
};
|
||||
this.write_scalar(Scalar::from_u64(n.to_bits()), dest)?;
|
||||
}
|
||||
// underscore case for windows
|
||||
"_ldexp" | "ldexp" => {
|
||||
// FIXME: Using host floats.
|
||||
let x = f64::from_bits(this.read_scalar(args[0])?.to_u64()?);
|
||||
// For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
|
||||
"_ldexp" | "ldexp" | "scalbn" => {
|
||||
let x = this.read_scalar(args[0])?.to_f64()?;
|
||||
let exp = this.read_scalar(args[1])?.to_i32()?;
|
||||
extern {
|
||||
fn ldexp(x: f64, n: i32) -> f64;
|
||||
}
|
||||
let n = unsafe { ldexp(x, exp) };
|
||||
this.write_scalar(Scalar::from_u64(n.to_bits()), dest)?;
|
||||
|
||||
// Saturating cast to i16. Even those are outside the valid exponent range to
|
||||
// `scalbn` below will do its over/underflow handling.
|
||||
let exp = if exp > i16::max_value() as i32 {
|
||||
i16::max_value()
|
||||
} else if exp < i16::min_value() as i32 {
|
||||
i16::min_value()
|
||||
} else {
|
||||
exp.try_into().unwrap()
|
||||
};
|
||||
|
||||
let res = x.scalbn(exp);
|
||||
this.write_scalar(Scalar::from_f64(res), dest)?;
|
||||
}
|
||||
|
||||
// Some things needed for `sys::thread` initialization to go through.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@ macro_rules! assert_approx_eq {
|
|||
})
|
||||
}
|
||||
|
||||
fn ldexp(a: f64, b: i32) -> f64 {
|
||||
extern {
|
||||
fn ldexp(x: f64, n: i32) -> f64;
|
||||
}
|
||||
unsafe { ldexp(a, b) }
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
use std::f32;
|
||||
use std::f64;
|
||||
|
|
@ -88,8 +95,7 @@ pub fn main() {
|
|||
assert_eq!(3.3_f32.round(), 3.0);
|
||||
assert_eq!(3.3_f64.round(), 3.0);
|
||||
|
||||
extern {
|
||||
fn ldexp(x: f64, n: i32) -> f64;
|
||||
}
|
||||
unsafe { assert_approx_eq!(ldexp(0.65f64, 3i32), 5.2f64); }
|
||||
assert_eq!(ldexp(0.65f64, 3i32), 5.2f64);
|
||||
assert_eq!(ldexp(1.42, 0xFFFF), f64::INFINITY);
|
||||
assert_eq!(ldexp(1.42, -0xFFFF), 0f64);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue