@@ -550,7 +550,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
550550 }
551551}
552552
553- /// Applies a random 16ULP floating point error to `val` and returns the new value.
553+ /// Applies a random ULP floating point error to `val` and returns the new value.
554+ /// So if you want an X ULP error, `ulp_exponent` should be log2(X).
554555/// Will fail if `val` is not a floating point number.
555556fn apply_random_float_error_to_imm < ' tcx > (
556557 ecx : & mut MiriInterpCx < ' tcx > ,
@@ -573,24 +574,19 @@ fn apply_random_float_error_to_imm<'tcx>(
573574 interp_ok ( ImmTy :: from_scalar_int ( res, val. layout ) )
574575}
575576
576- // TODO(lorrens): This can be moved to `helpers` when we implement the other intrinsics.
577577/// For the intrinsics:
578578/// - sinf32, sinf64
579579/// - cosf32, cosf64
580580/// - expf32, expf64, exp2f32, exp2f64
581581/// - logf32, logf64, log2f32, log2f64, log10f32, log10f64
582582/// - powf32, powf64
583583///
584- /// Returns Some(`output`) if the operation results in a defined fixed `output` specified in the C standard when given `args`
584+ /// Returns Some(`output`) if the `intrinsic` results in a defined fixed `output` specified in the C standard when given `args`
585585/// as arguments, else None.
586586fn fixed_float_value < S : Semantics > (
587587 intrinsic_name : & str ,
588588 args : & [ IeeeFloat < S > ] ,
589589) -> Option < IeeeFloat < S > > {
590- // TODO: not sure about this pattern matching stuff. It's definitly cleaner than if-else chains
591- // Error code 0158 explains this: https://doc.rust-lang.org/stable/error_codes/E0158.html
592- // The only reason I did this is to use the same function for powf as for sin/cos/exp/log
593- // TODO: I can't fit powi logic in this because of the exponent being a i32 -> seperate fn "fixed_powi_float_value" for now
594590 let one = IeeeFloat :: < S > :: one ( ) ;
595591 match ( intrinsic_name, args) {
596592 // sin(+- 0) = +- 0.
@@ -620,21 +616,22 @@ fn fixed_float_value<S: Semantics>(
620616 // x^(±0) = 1 for any x, even a NaN
621617 ( "powf32" | "powf64" , [ _, exp] ) if exp. is_zero ( ) => Some ( one) ,
622618
623- // C standard doesn't specify or invalid combination
619+ // C standard doesn't specify any fixed outputs for other combinations of `intrinsic_name` and `args`,
620+ // or an invalid combination was given.
624621 _ => None ,
625622 }
626623}
627624
628- /// Returns Some(`output`) if powi results in a fixed value specified in the C standard when doing `base^exp` else None.
625+ /// Returns Some(`output`) if ` powi` results in a fixed value specified in the C standard when doing `base^exp` else None.
629626fn fixed_powi_float_value < S : Semantics > ( base : IeeeFloat < S > , exp : i32 ) -> Option < IeeeFloat < S > > {
630627 match ( base. category ( ) , exp) {
631628 // ±0^x = ±0 with x an odd integer.
632- ( Category :: Zero , x) if x % 2 != 0 => Some ( base) , // preserve sign of zero.
629+ ( Category :: Zero , x) if x % 2 != 0 => Some ( base) , // preserve sign of zero
633630
634631 // ±0^x = +0 with x an even integer.
635632 ( Category :: Zero , x) if x % 2 == 0 => Some ( IeeeFloat :: < S > :: ZERO ) ,
636633
637- // x^y = 1, if y is not a Signaling NaN
634+ // x^0 = 1, if x is not a Signaling NaN
638635 ( _, 0 ) if !base. is_signaling ( ) => Some ( IeeeFloat :: < S > :: one ( ) ) ,
639636
640637 _ => None ,
@@ -653,40 +650,3 @@ fn clamp_float_value<S: Semantics>(intrinsic_name: &str, val: IeeeFloat<S>) -> I
653650 _ => val,
654651 }
655652}
656-
657- // TODO: clean up when I'm sure this is not needed, because powf is now included in fixed_float_value
658- // fn powf_impl<'tcx, S: Semantics, Op>(
659- // ecx: &mut MiriInterpCx<'tcx>,
660- // base: IeeeFloat<S>,
661- // exp: IeeeFloat<S>,
662- // op: Op,
663- // ) -> IeeeFloat<S>
664- // where
665- // IeeeFloat<S>: ToHost,
666- // Op: Fn(IeeeFloat<S>, IeeeFloat<S>) -> IeeeFloat<S>,
667- // {
668- // let one = IeeeFloat::<S>::one();
669- // let fixed_res = match (base.category(), exp.category()) {
670- // // 1^y = 1 for any y, even a NaN.
671- // (Category::Normal, _) if base == one => Some(one),
672-
673- // // (-1)^(±INF) = 1
674- // (Category::Normal, Category::Infinity) if base == -one => Some(one),
675-
676- // // x^(±0) = 1 for any x, even a NaN
677- // (_, Category::Zero) => Some(one),
678-
679- // // TODO: pow has a lot of "edge" cases which mostly result in ±0 or ±INF
680- // // do we have to catch them all?
681- // _ => None,
682- // };
683-
684- // fixed_res.unwrap_or_else(|| {
685- // let res = op(base, exp);
686- // // Apply a relative error of 4ULP to introduce some non-determinism
687- // // simulating imprecise implementations and optimizations.
688- // apply_random_float_error_ulp(
689- // ecx, res, 2, // log2(4)
690- // )
691- // })
692- // }
0 commit comments