Skip to content

Commit ba2275c

Browse files
refactor fixed_float_int_value into fixed_powi_value and fixed_scalbn_value
1 parent 10c988b commit ba2275c

File tree

3 files changed

+42
-46
lines changed

3 files changed

+42
-46
lines changed

src/tools/miri/src/intrinsics/mod.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -347,17 +347,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
347347
let f = this.read_scalar(f)?.to_f32()?;
348348
let i = this.read_scalar(i)?.to_i32()?;
349349

350-
let res =
351-
math::fixed_float_int_value(this, intrinsic_name, f, i).unwrap_or_else(|| {
352-
// Using host floats (but it's fine, this operation does not have guaranteed precision).
353-
let res = f.to_host().powi(i).to_soft();
350+
let res = math::fixed_powi_value(this, f, i).unwrap_or_else(|| {
351+
// Using host floats (but it's fine, this operation does not have guaranteed precision).
352+
let res = f.to_host().powi(i).to_soft();
354353

355-
// Apply a relative error of 4ULP to introduce some non-determinism
356-
// simulating imprecise implementations and optimizations.
357-
math::apply_random_float_error_ulp(
358-
this, res, 2, // log2(4)
359-
)
360-
});
354+
// Apply a relative error of 4ULP to introduce some non-determinism
355+
// simulating imprecise implementations and optimizations.
356+
math::apply_random_float_error_ulp(
357+
this, res, 2, // log2(4)
358+
)
359+
});
361360
let res = this.adjust_nan(res, &[f]);
362361
this.write_scalar(res, dest)?;
363362
}
@@ -366,17 +365,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
366365
let f = this.read_scalar(f)?.to_f64()?;
367366
let i = this.read_scalar(i)?.to_i32()?;
368367

369-
let res =
370-
math::fixed_float_int_value(this, intrinsic_name, f, i).unwrap_or_else(|| {
371-
// Using host floats (but it's fine, this operation does not have guaranteed precision).
372-
let res = f.to_host().powi(i).to_soft();
368+
let res = math::fixed_powi_value(this, f, i).unwrap_or_else(|| {
369+
// Using host floats (but it's fine, this operation does not have guaranteed precision).
370+
let res = f.to_host().powi(i).to_soft();
373371

374-
// Apply a relative error of 4ULP to introduce some non-determinism
375-
// simulating imprecise implementations and optimizations.
376-
math::apply_random_float_error_ulp(
377-
this, res, 2, // log2(4)
378-
)
379-
});
372+
// Apply a relative error of 4ULP to introduce some non-determinism
373+
// simulating imprecise implementations and optimizations.
374+
math::apply_random_float_error_ulp(
375+
this, res, 2, // log2(4)
376+
)
377+
});
380378
let res = this.adjust_nan(res, &[f]);
381379
this.write_scalar(res, dest)?;
382380
}

src/tools/miri/src/math.rs

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -260,44 +260,42 @@ where
260260
})
261261
}
262262

263-
/// # Return
264-
///
265-
/// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard
266-
/// (specifically, C23 annex F.10) when given f (as a float) and int (as a i32) as arguments. Outputs that are
267-
/// unaffected by a relative error (such as INF and zero) are not handled here, they are assumed to be handled by the underlying
268-
/// implementation. Returns `None` if no specific value is guaranteed.
269-
///
270-
/// # Note
271-
///
272-
/// For `powif*` operations of the form `(SNaN)^(±0)` we follow the same behaviour as `powf*`, see [`fixed_float_value`].
273-
pub(crate) fn fixed_float_int_value<S: Semantics>(
263+
/// Returns `Some(output)` if `powi` (called `pown` in C) results in a fixed value specified in the
264+
/// C standard (specifically, C23 annex F.10.4.6) when doing `base^exp`. Otherwise, returns `None`.
265+
pub(crate) fn fixed_powi_value<S: Semantics>(
274266
ecx: &mut MiriInterpCx<'_>,
275-
operation: &str,
276-
f: IeeeFloat<S>,
277-
int: i32,
267+
base: IeeeFloat<S>,
268+
exp: i32,
278269
) -> Option<IeeeFloat<S>>
279270
where
280271
IeeeFloat<S>: IeeeExt,
281272
{
282-
let this = ecx.eval_context_mut();
283-
284-
Some(match (operation, f, int) {
285-
("powif32" | "powif64", x, 0) => {
273+
match exp {
274+
0 => {
286275
let one = IeeeFloat::<S>::one();
287-
let rng = this.machine.rng.get_mut();
288-
let return_nan = this.machine.float_nondet && rng.random() && x.is_signaling();
276+
let rng = ecx.machine.rng.get_mut();
277+
let return_nan = ecx.machine.float_nondet && rng.random() && base.is_signaling();
289278
// For SNaN treatment, we are consistent with `powf`above.
290279
// (We wouldn't have two, unlike powf all implementations seem to agree for powi,
291280
// but for now we are maximally conservative.)
292-
if return_nan { this.generate_nan(&[x]) } else { one }
281+
Some(if return_nan { ecx.generate_nan(&[base]) } else { one })
293282
}
294283

295-
// For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
296-
// scalbn(x, 0) = x.
297-
("_ldexp" | "ldexp" | "scalbn", x, 0) => x,
284+
_ => return None,
285+
}
286+
}
298287

288+
/// Returns `Some(output)` if `scalbn` (called `ldexp` in C) results in a fixed value specified in the
289+
/// C standard (specifically, C23 annex F.10.3.19) when doing `arg`*(2^`exp`). Otherwise, returns `None`.
290+
pub(crate) fn fixed_scalbn_value<S: Semantics>(
291+
arg: IeeeFloat<S>,
292+
exp: i32,
293+
) -> Option<IeeeFloat<S>> {
294+
match exp {
295+
// ldexp(x, 0) = x.
296+
0 => Some(arg),
299297
_ => return None,
300-
})
298+
}
301299
}
302300

303301
pub(crate) fn sqrt<S: rustc_apfloat::ieee::Semantics>(x: IeeeFloat<S>) -> IeeeFloat<S> {

src/tools/miri/src/shims/foreign_items.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
933933
let exp = this.read_scalar(exp)?.to_i32()?;
934934

935935
let res =
936-
math::fixed_float_int_value(this, link_name.as_str(), x, exp).unwrap_or_else(|| {
936+
math::fixed_scalbn_value(x, exp).unwrap_or_else(|| {
937937
let res = x.scalbn(exp);
938938
// Apply a relative error of 4ULP to introduce some non-determinism
939939
// simulating imprecise implementations and optimizations.

0 commit comments

Comments
 (0)