1. 04 5月, 2020 2 次提交
  2. 21 4月, 2020 1 次提交
  3. 05 4月, 2020 1 次提交
  4. 03 4月, 2020 1 次提交
  5. 29 3月, 2020 1 次提交
    • M
      Stabilize float::to_int_unchecked · 56147219
      Mark Rousskov 提交于
      This renames and stabilizes unsafe floating point to integer casts, which are
      intended to be the substitute for the currently unsound `as` behavior, once that
      changes to safe-but-slower saturating casts.
      56147219
  6. 17 2月, 2020 1 次提交
  7. 13 2月, 2020 4 次提交
  8. 24 1月, 2020 1 次提交
  9. 26 12月, 2019 1 次提交
  10. 20 12月, 2019 1 次提交
  11. 19 12月, 2019 1 次提交
  12. 07 12月, 2019 1 次提交
  13. 06 12月, 2019 1 次提交
    • S
      Add `{f32,f64}::approx_unchecked_to<Int>` unsafe methods · cba479f7
      Simon Sapin 提交于
      As discussed in https://github.com/rust-lang/rust/issues/10184
      
      Currently, casting a floating point number to an integer with `as` is Undefined Behavior if the value is out of range. `-Z saturating-float-casts` fixes this soundness hole by making `as` “saturate” to the maximum or minimum value of the integer type (or zero for `NaN`), but has measurable negative performance impact in some benchmarks. There is some consensus in that thread for enabling saturation by default anyway, but provide an `unsafe fn` alternative for users who know through some other mean that their values are in range.
      cba479f7
  14. 28 11月, 2019 1 次提交
  15. 26 11月, 2019 2 次提交
  16. 06 11月, 2019 1 次提交
  17. 01 11月, 2019 1 次提交
  18. 22 8月, 2019 1 次提交
  19. 08 8月, 2019 1 次提交
  20. 08 7月, 2019 2 次提交
  21. 07 6月, 2019 1 次提交
  22. 18 4月, 2019 1 次提交
  23. 11 2月, 2019 1 次提交
  24. 07 1月, 2019 1 次提交
    • H
      Optimise floating point `is_finite` (2x) and `is_infinite` (1.6x). · 6e742dbb
      Huon Wilson 提交于
      These can both rely on IEEE754 semantics to be made faster, by folding
      away the sign with an abs (left private for now), and then comparing
      to infinity, letting the NaN semantics of a direct float comparison
      handle NaN input properly.
      
      The `abs` bit-fiddling is simple (a single and), and so these new
      forms compile down to a few instructions, without branches, e.g. for
      f32:
      
      ```asm
      is_infinite:
              andps   xmm0, xmmword ptr [rip + .LCPI2_0] ; 0x7FFF_FFFF
              ucomiss xmm0, dword ptr [rip + .LCPI2_1]   ; 0x7F80_0000
              setae   al
              ret
      
      is_finite:
              andps   xmm0, xmmword ptr [rip + .LCPI1_0] ; 0x7FFF_FFFF
              movss   xmm1, dword ptr [rip + .LCPI1_1]   ; 0x7F80_0000
              ucomiss xmm1, xmm0
              seta    al
              ret
      ```
      
      When used in loops/repeatedly, they get even better: the memory
      operations (loading the mask 0x7FFFFFFF for abs, and infinity
      0x7F80_0000) are likely to be hoisted out of the individual calls, to
      be shared, and the `seta`/`setae` are likely to be collapsed into
      conditional jumps or moves (or similar).
      
      The old `is_infinite` did two comparisons, and the old `is_finite` did
      three (with a branch), and both of them had to check the flags after
      every one of those comparison. These functions have had that old
      implementation since they were added in
      https://github.com/rust-lang/rust/commit/6284190ef9918e05cb9147a2a81100ddcb06fea8
      7 years ago.
      
      Benchmark (`abs` is the new form, `std` is the old):
      
      ```
      test f32_is_finite_abs            ... bench:          55 ns/iter (+/- 10)
      test f32_is_finite_std            ... bench:         118 ns/iter (+/- 5)
      
      test f32_is_infinite_abs          ... bench:          53 ns/iter (+/- 1)
      test f32_is_infinite_std          ... bench:          84 ns/iter (+/- 6)
      
      test f64_is_finite_abs            ... bench:          52 ns/iter (+/- 12)
      test f64_is_finite_std            ... bench:         128 ns/iter (+/- 25)
      
      test f64_is_infinite_abs          ... bench:          54 ns/iter (+/- 5)
      test f64_is_infinite_std          ... bench:          93 ns/iter (+/- 23)
      ```
      
      ```rust
       #![feature(test)]
      extern crate test;
      
      use std::{f32, f64};
      use test::Bencher;
      
      const VALUES_F32: &[f32] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
      
       #[bench]
      fn f32_is_infinite_std(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.is_infinite()));
      }
       #[bench]
      fn f32_is_infinite_abs(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.abs()== f32::INFINITY));
      }
       #[bench]
      fn f32_is_finite_std(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.is_finite()));
      }
       #[bench]
      fn f32_is_finite_abs(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.abs() < f32::INFINITY));
      }
      
      const VALUES_F64: &[f64] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
      
       #[bench]
      fn f64_is_infinite_std(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.is_infinite()));
      }
       #[bench]
      fn f64_is_infinite_abs(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.abs() == f64::INFINITY));
      }
       #[bench]
      fn f64_is_finite_std(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.is_finite()));
      }
       #[bench]
      fn f64_is_finite_abs(b: &mut Bencher) {
          b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.abs() < f64::INFINITY));
      }
      ```
      6e742dbb
  25. 26 12月, 2018 1 次提交
  26. 28 5月, 2018 1 次提交
  27. 23 5月, 2018 1 次提交
  28. 17 5月, 2018 1 次提交
  29. 10 5月, 2018 1 次提交
  30. 09 5月, 2018 1 次提交
  31. 21 4月, 2018 2 次提交
  32. 02 2月, 2018 1 次提交
    • V
      Use constant for 180/π in to_degrees · e34c31bf
      varkor 提交于
      The current `f32|f64.to_degrees` implementation uses a division to calculate 180/π, which causes a loss of precision. Using a constant is still not perfect (implementing a maximally-precise algorithm would come with a high performance cost), but improves precision with a minimal change.
      e34c31bf
  33. 31 12月, 2017 1 次提交