|
1 |
| -use super::super::fenv::{ |
2 |
| - FE_INEXACT, FE_TONEAREST, FE_UNDERFLOW, feclearexcept, fegetround, feraiseexcept, fetestexcept, |
3 |
| -}; |
4 |
| -use super::super::{CastFrom, CastInto, DFloat, Float, HFloat, Int, IntTy, MinInt}; |
| 1 | +use super::super::fenv::{FE_TONEAREST, fegetround}; |
| 2 | +use super::super::{CastFrom, CastInto, DFloat, Float, HFloat, IntTy, MinInt}; |
5 | 3 |
|
6 | 4 | /// FMA implementation when a hardware-backed larger float type is available.
|
7 | 5 | pub fn fma_big<F, B>(x: F, y: F, z: F) -> F
|
8 | 6 | where
|
9 | 7 | F: Float + HFloat<D = B>,
|
10 | 8 | B: Float + DFloat<H = F>,
|
11 |
| - // F: Float + CastInto<B>, |
12 |
| - // B: Float + CastInto<F> + CastFrom<F>, |
13 | 9 | B::Int: CastInto<i32>,
|
14 | 10 | i32: CastFrom<i32>,
|
15 | 11 | {
|
16 | 12 | let one = IntTy::<B>::ONE;
|
17 | 13 |
|
18 |
| - let xy: B; |
19 |
| - let mut result: B; |
20 |
| - let mut ui: B::Int; |
21 |
| - let e: i32; |
22 |
| - |
23 |
| - xy = x.widen() * y.widen(); |
24 |
| - result = xy + z.widen(); |
25 |
| - ui = result.to_bits(); |
26 |
| - e = result.exp().signed(); |
| 14 | + let xy: B = x.widen() * y.widen(); |
| 15 | + let result: B = xy + z.widen(); |
| 16 | + let mut ui: B::Int = result.to_bits(); |
| 17 | + let re = result.exp(); |
27 | 18 | let zb: B = z.widen();
|
28 | 19 |
|
29 | 20 | let prec_diff = B::SIG_BITS - F::SIG_BITS;
|
30 | 21 | let excess_prec = ui & ((one << prec_diff) - one);
|
31 |
| - let x = one << (prec_diff - 1); |
32 |
| - |
33 |
| - // Common case: the larger precision is fine |
34 |
| - if excess_prec != x |
35 |
| - || e == i32::cast_from(F::EXP_MAX) |
| 22 | + let halfway = one << (prec_diff - 1); |
| 23 | + |
| 24 | + // Common case: the larger precision is fine if... |
| 25 | + // This is not a halfway case |
| 26 | + if excess_prec != halfway |
| 27 | + // Or the result is NaN |
| 28 | + || re == B::EXP_MAX |
| 29 | + // Or the result is exact |
36 | 30 | || (result - xy == zb && result - zb == xy)
|
| 31 | + // Or the mode is something other than round to nearest |
37 | 32 | || fegetround() != FE_TONEAREST
|
38 | 33 | {
|
39 | 34 | // TODO: feclearexcept
|
|
0 commit comments