@@ -550,7 +550,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
550
550
}
551
551
}
552
552
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).
554
555
/// Will fail if `val` is not a floating point number.
555
556
fn apply_random_float_error_to_imm < ' tcx > (
556
557
ecx : & mut MiriInterpCx < ' tcx > ,
@@ -573,24 +574,19 @@ fn apply_random_float_error_to_imm<'tcx>(
573
574
interp_ok ( ImmTy :: from_scalar_int ( res, val. layout ) )
574
575
}
575
576
576
- // TODO(lorrens): This can be moved to `helpers` when we implement the other intrinsics.
577
577
/// For the intrinsics:
578
578
/// - sinf32, sinf64
579
579
/// - cosf32, cosf64
580
580
/// - expf32, expf64, exp2f32, exp2f64
581
581
/// - logf32, logf64, log2f32, log2f64, log10f32, log10f64
582
582
/// - powf32, powf64
583
583
///
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`
585
585
/// as arguments, else None.
586
586
fn fixed_float_value < S : Semantics > (
587
587
intrinsic_name : & str ,
588
588
args : & [ IeeeFloat < S > ] ,
589
589
) -> 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
594
590
let one = IeeeFloat :: < S > :: one ( ) ;
595
591
match ( intrinsic_name, args) {
596
592
// sin(+- 0) = +- 0.
@@ -620,21 +616,22 @@ fn fixed_float_value<S: Semantics>(
620
616
// x^(±0) = 1 for any x, even a NaN
621
617
( "powf32" | "powf64" , [ _, exp] ) if exp. is_zero ( ) => Some ( one) ,
622
618
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.
624
621
_ => None ,
625
622
}
626
623
}
627
624
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.
629
626
fn fixed_powi_float_value < S : Semantics > ( base : IeeeFloat < S > , exp : i32 ) -> Option < IeeeFloat < S > > {
630
627
match ( base. category ( ) , exp) {
631
628
// ±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
633
630
634
631
// ±0^x = +0 with x an even integer.
635
632
( Category :: Zero , x) if x % 2 == 0 => Some ( IeeeFloat :: < S > :: ZERO ) ,
636
633
637
- // x^y = 1, if y is not a Signaling NaN
634
+ // x^0 = 1, if x is not a Signaling NaN
638
635
( _, 0 ) if !base. is_signaling ( ) => Some ( IeeeFloat :: < S > :: one ( ) ) ,
639
636
640
637
_ => None ,
@@ -653,40 +650,3 @@ fn clamp_float_value<S: Semantics>(intrinsic_name: &str, val: IeeeFloat<S>) -> I
653
650
_ => val,
654
651
}
655
652
}
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