Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit a668d27

Browse files
committed
More work toward generic
1 parent 537ce80 commit a668d27

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

src/math/fma.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
/// Floating multiply add (f64)
1+
/// Fused multiply add (f64)
22
///
3-
/// Computes `(x*y)+z`, rounded as one ternary operation:
4-
/// Computes the value (as if) to infinite precision and rounds once to the result format,
5-
/// according to the rounding mode characterized by the value of FLT_ROUNDS.
3+
/// Computes `(x*y)+z`, rounded as one ternary operation (i.e. calculated with infinite precision).
64
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
75
pub fn fma(x: f64, y: f64, z: f64) -> f64 {
86
return super::generic::fma(x, y, z);

src/math/generic/fma.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
use core::{f32, f64};
22

33
use super::super::support::{DInt, HInt, IntTy};
4-
use super::super::{Float, Int, MinInt, scalbn};
4+
use super::super::{CastFrom, Float, Int, MinInt};
55

66
const ZEROINFNAN: i32 = 0x7ff - 0x3ff - 52 - 1;
77

88
type F = f64;
99

10-
/// Floating multiply add (f64)
11-
///
12-
/// Computes `(x*y)+z`, rounded as one ternary operation:
13-
/// Computes the value (as if) to infinite precision and rounds once to the result format,
14-
/// according to the rounding mode characterized by the value of FLT_ROUNDS.
10+
/// Fused multiply-add.
1511
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
1612
pub fn fma(x: f64, y: f64, z: f64) -> f64 {
1713
// let x1p63: f64 = f64::from_bits(0x43e0000000000000); // 0x1p63 === 2 ^ 63
@@ -125,7 +121,8 @@ pub fn fma(x: f64, y: f64, z: f64) -> f64 {
125121
if neg {
126122
i = -i;
127123
}
128-
let mut r: f64 = i as f64; /* |r| is in [0x1p62,0x1p63] */
124+
125+
let mut r: f64 = f64::cast_from_lossy(i); /* |r| is in [0x1p62,0x1p63] */
129126

130127
if e < -(F::EXP_BIAS as i32 - 1) - (sbits - 2) {
131128
/* result is subnormal before rounding */
@@ -143,11 +140,11 @@ pub fn fma(x: f64, y: f64, z: f64) -> f64 {
143140
/* one bit is lost when scaled, add another top bit to
144141
* only round once at conversion if it is inexact */
145142
if (rhi << F::SIG_BITS) != 0 {
146-
i = ((rhi >> 1) | (rhi & 1) | (1 << 62)) as i64;
143+
i = ((rhi >> 1) | (rhi & 1) | (1 << 62)).signed();
147144
if neg {
148145
i = -i;
149146
}
150-
r = i as f64;
147+
r = F::cast_from(i);
151148
r = 2.0 * r - c; /* remove top bit */
152149

153150
/* raise underflow portably, such that it
@@ -161,10 +158,11 @@ pub fn fma(x: f64, y: f64, z: f64) -> f64 {
161158
if neg {
162159
i = -i;
163160
}
164-
r = i as f64;
161+
r = f64::cast_from(i);
165162
}
166163
}
167-
scalbn(r, e)
164+
165+
F::scalbn(r, e)
168166
}
169167

170168
struct Norm<F: Float> {
@@ -202,6 +200,7 @@ impl<F: Float> Norm<F> {
202200
trait RaiseUnderflow {
203201
fn raise_underflow(self) -> Self;
204202
fn raise_underflow2(self) -> Self;
203+
fn scalbn(self, n: i32) -> Self;
205204
}
206205

207206
impl RaiseUnderflow for f64 {
@@ -217,4 +216,8 @@ impl RaiseUnderflow for f64 {
217216
let tiny: f64 = f64::MIN_POSITIVE / f32::MIN_POSITIVE as f64 * self;
218217
(tiny * tiny) * (self - self)
219218
}
219+
220+
fn scalbn(self, n: i32) -> Self {
221+
super::super::scalbn(self, n)
222+
}
220223
}

src/math/support/int_traits.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,30 @@ macro_rules! cast_into {
400400
)*};
401401
}
402402

403+
macro_rules! cast_into_float {
404+
($ty:ty) => {
405+
#[cfg(f16_enabled)]
406+
cast_into_float!($ty; f16);
407+
408+
cast_into_float!($ty; f32, f64);
409+
410+
#[cfg(f128_enabled)]
411+
cast_into_float!($ty; f128);
412+
};
413+
($ty:ty; $($into:ty),*) => {$(
414+
impl CastInto<$into> for $ty {
415+
fn cast(self) -> $into {
416+
debug_assert_eq!(self as $into as $ty, self, "inexact float cast");
417+
self as $into
418+
}
419+
420+
fn cast_lossy(self) -> $into {
421+
self as $into
422+
}
423+
}
424+
)*};
425+
}
426+
403427
cast_into!(usize);
404428
cast_into!(isize);
405429
cast_into!(u8);
@@ -412,3 +436,8 @@ cast_into!(u64);
412436
cast_into!(i64);
413437
cast_into!(u128);
414438
cast_into!(i128);
439+
440+
cast_into_float!(i16);
441+
cast_into_float!(i32);
442+
cast_into_float!(i64);
443+
cast_into_float!(i128);

0 commit comments

Comments
 (0)