share sqrt implemention across float types
This commit is contained in:
parent
f19b560fa9
commit
77f2d86554
2 changed files with 25 additions and 39 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use rand::Rng;
|
||||
use rustc_apfloat::{self, Float, Round};
|
||||
use rustc_apfloat::{self, Float, FloatConvert, Round};
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::{self, FloatTy};
|
||||
|
||||
|
|
@ -7,6 +7,20 @@ use self::helpers::{ToHost, ToSoft};
|
|||
use super::check_intrinsic_arg_count;
|
||||
use crate::*;
|
||||
|
||||
fn sqrt<'tcx, F: Float + FloatConvert<F> + Into<Scalar>>(
|
||||
this: &mut MiriInterpCx<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let [f] = check_intrinsic_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?;
|
||||
let f: F = f.to_float()?;
|
||||
// Sqrt is specified to be fully precise.
|
||||
let res = math::sqrt(f);
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)
|
||||
}
|
||||
|
||||
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
|
||||
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
fn emulate_math_intrinsic(
|
||||
|
|
@ -20,38 +34,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
match intrinsic_name {
|
||||
// Operations we can do with soft-floats.
|
||||
"sqrtf16" => {
|
||||
let [f] = check_intrinsic_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f16()?;
|
||||
// Sqrt is specified to be fully precise.
|
||||
let res = math::sqrt(f);
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"sqrtf32" => {
|
||||
let [f] = check_intrinsic_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f32()?;
|
||||
// Sqrt is specified to be fully precise.
|
||||
let res = math::sqrt(f);
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"sqrtf64" => {
|
||||
let [f] = check_intrinsic_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f64()?;
|
||||
// Sqrt is specified to be fully precise.
|
||||
let res = math::sqrt(f);
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"sqrtf128" => {
|
||||
let [f] = check_intrinsic_arg_count(args)?;
|
||||
let f = this.read_scalar(f)?.to_f128()?;
|
||||
// Sqrt is specified to be fully precise.
|
||||
let res = math::sqrt(f);
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"sqrtf16" => sqrt::<rustc_apfloat::ieee::Half>(this, args, dest)?,
|
||||
"sqrtf32" => sqrt::<rustc_apfloat::ieee::Single>(this, args, dest)?,
|
||||
"sqrtf64" => sqrt::<rustc_apfloat::ieee::Double>(this, args, dest)?,
|
||||
"sqrtf128" => sqrt::<rustc_apfloat::ieee::Quad>(this, args, dest)?,
|
||||
|
||||
"fmaf32" => {
|
||||
let [a, b, c] = check_intrinsic_arg_count(args)?;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::ops::Neg;
|
|||
use std::{f32, f64};
|
||||
|
||||
use rand::Rng as _;
|
||||
use rustc_apfloat::Float as _;
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, Semantics, SingleS};
|
||||
use rustc_middle::ty::{self, FloatTy, ScalarInt};
|
||||
|
||||
|
|
@ -317,19 +317,19 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sqrt<S: rustc_apfloat::ieee::Semantics>(x: IeeeFloat<S>) -> IeeeFloat<S> {
|
||||
pub(crate) fn sqrt<F: Float>(x: F) -> F {
|
||||
match x.category() {
|
||||
// preserve zero sign
|
||||
rustc_apfloat::Category::Zero => x,
|
||||
// propagate NaN
|
||||
rustc_apfloat::Category::NaN => x,
|
||||
// sqrt of negative number is NaN
|
||||
_ if x.is_negative() => IeeeFloat::NAN,
|
||||
_ if x.is_negative() => F::NAN,
|
||||
// sqrt(∞) = ∞
|
||||
rustc_apfloat::Category::Infinity => IeeeFloat::INFINITY,
|
||||
rustc_apfloat::Category::Infinity => F::INFINITY,
|
||||
rustc_apfloat::Category::Normal => {
|
||||
// Floating point precision, excluding the integer bit
|
||||
let prec = i32::try_from(S::PRECISION).unwrap() - 1;
|
||||
let prec = i32::try_from(F::PRECISION).unwrap() - 1;
|
||||
|
||||
// x = 2^(exp - prec) * mant
|
||||
// where mant is an integer with prec+1 bits
|
||||
|
|
@ -394,7 +394,7 @@ pub(crate) fn sqrt<S: rustc_apfloat::ieee::Semantics>(x: IeeeFloat<S>) -> IeeeFl
|
|||
res = (res + 1) >> 1;
|
||||
|
||||
// Build resulting value with res as mantissa and exp/2 as exponent
|
||||
IeeeFloat::from_u128(res).value.scalbn(exp / 2 - prec)
|
||||
F::from_u128(res).value.scalbn(exp / 2 - prec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue