diff options
| author | Ralf Jung <post@ralfj.de> | 2025-09-18 22:13:15 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2025-09-18 22:17:29 +0200 |
| commit | 77f2d865549e8f2e1ad656c8202de9bfa6d2e354 (patch) | |
| tree | 7fd3bb1562c3d55c1ac0ae3c6b06efdbdd38efb5 /src | |
| parent | f19b560fa96ca8dd4352db6372f662fa32942a9f (diff) | |
| download | rust-77f2d865549e8f2e1ad656c8202de9bfa6d2e354.tar.gz rust-77f2d865549e8f2e1ad656c8202de9bfa6d2e354.zip | |
share sqrt implemention across float types
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/miri/src/intrinsics/math.rs | 52 | ||||
| -rw-r--r-- | src/tools/miri/src/math.rs | 12 |
2 files changed, 25 insertions, 39 deletions
diff --git a/src/tools/miri/src/intrinsics/math.rs b/src/tools/miri/src/intrinsics/math.rs index ca81454a98c..b9c99f28594 100644 --- a/src/tools/miri/src/intrinsics/math.rs +++ b/src/tools/miri/src/intrinsics/math.rs @@ -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)?; diff --git a/src/tools/miri/src/math.rs b/src/tools/miri/src/math.rs index 401e6dd7aab..50472ed3638 100644 --- a/src/tools/miri/src/math.rs +++ b/src/tools/miri/src/math.rs @@ -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) } } } |
