Skip to content

Commit b8c2585

Browse files
authored
Merge pull request #384 from AaronKutch/issue-367
2 parents c975b0e + c2ff1b3 commit b8c2585

24 files changed

+1334
-451
lines changed

src/float/cmp.rs

+4-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![allow(unreachable_code)]
22

33
use float::Float;
4-
use int::{CastInto, Int};
4+
use int::Int;
55

66
#[derive(Clone, Copy)]
77
enum Result {
@@ -31,13 +31,7 @@ impl Result {
3131
}
3232
}
3333

34-
fn cmp<F: Float>(a: F, b: F) -> Result
35-
where
36-
u32: CastInto<F::Int>,
37-
F::Int: CastInto<u32>,
38-
i32: CastInto<F::Int>,
39-
F::Int: CastInto<i32>,
40-
{
34+
fn cmp<F: Float>(a: F, b: F) -> Result {
4135
let one = F::Int::ONE;
4236
let zero = F::Int::ZERO;
4337
let szero = F::SignedInt::ZERO;
@@ -90,13 +84,8 @@ where
9084
}
9185
}
9286
}
93-
fn unord<F: Float>(a: F, b: F) -> bool
94-
where
95-
u32: CastInto<F::Int>,
96-
F::Int: CastInto<u32>,
97-
i32: CastInto<F::Int>,
98-
F::Int: CastInto<i32>,
99-
{
87+
88+
fn unord<F: Float>(a: F, b: F) -> bool {
10089
let one = F::Int::ONE;
10190

10291
let sign_bit = F::SIGN_MASK as F::Int;

src/float/conv.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ macro_rules! int_to_float {
1111
let mant_dig = <$fty>::SIGNIFICAND_BITS + 1;
1212
let exponent_bias = <$fty>::EXPONENT_BIAS;
1313

14-
let n = <$ity>::BITS;
14+
let n = <$ity as Int>::BITS;
1515
let (s, a) = i.extract_sign();
1616
let mut a = a;
1717

@@ -21,7 +21,7 @@ macro_rules! int_to_float {
2121
// exponent
2222
let mut e = sd - 1;
2323

24-
if <$ity>::BITS < mant_dig {
24+
if <$ity as Int>::BITS < mant_dig {
2525
return <$fty>::from_parts(
2626
s,
2727
(e + exponent_bias) as <$fty as Float>::Int,
@@ -165,7 +165,7 @@ macro_rules! float_to_int {
165165
let f = $f;
166166
let fixint_min = <$ity>::min_value();
167167
let fixint_max = <$ity>::max_value();
168-
let fixint_bits = <$ity>::BITS as usize;
168+
let fixint_bits = <$ity as Int>::BITS as usize;
169169
let fixint_unsigned = fixint_min == 0;
170170

171171
let sign_bit = <$fty>::SIGN_MASK;

src/float/div.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use float::Float;
2-
use int::{CastInto, Int, WideInt};
2+
use int::{CastInto, DInt, HInt, Int};
33

44
fn div32<F: Float>(a: F, b: F) -> F
55
where
66
u32: CastInto<F::Int>,
77
F::Int: CastInto<u32>,
88
i32: CastInto<F::Int>,
99
F::Int: CastInto<i32>,
10-
F::Int: WideInt,
10+
F::Int: HInt,
1111
{
1212
let one = F::Int::ONE;
1313
let zero = F::Int::ZERO;
@@ -156,7 +156,7 @@ where
156156
// is the error in the reciprocal of b scaled by the maximum
157157
// possible value of a. As a consequence of this error bound,
158158
// either q or nextafter(q) is the correctly rounded
159-
let (mut quotient, _) = <F::Int as WideInt>::wide_mul(a_significand << 1, reciprocal.cast());
159+
let mut quotient = (a_significand << 1).widen_mul(reciprocal.cast()).hi();
160160

161161
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
162162
// In either case, we are going to compute a residual of the form
@@ -211,7 +211,7 @@ where
211211
F::Int: CastInto<u64>,
212212
i64: CastInto<F::Int>,
213213
F::Int: CastInto<i64>,
214-
F::Int: WideInt,
214+
F::Int: HInt,
215215
{
216216
let one = F::Int::ONE;
217217
let zero = F::Int::ZERO;
@@ -394,7 +394,7 @@ where
394394

395395
// We need a 64 x 64 multiply high to compute q, which isn't a basic
396396
// operation in C, so we need to be a little bit fussy.
397-
let (mut quotient, _) = <F::Int as WideInt>::wide_mul(a_significand << 2, reciprocal.cast());
397+
let mut quotient = (a_significand << 2).widen_mul(reciprocal.cast()).hi();
398398

399399
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
400400
// In either case, we are going to compute a residual of the form

src/float/mod.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use core::mem;
21
use core::ops;
32

43
use super::int::Int;
@@ -13,7 +12,8 @@ pub mod pow;
1312
pub mod sub;
1413

1514
/// Trait for some basic operations on floats
16-
pub(crate) trait Float:
15+
#[doc(hidden)]
16+
pub trait Float:
1717
Copy
1818
+ PartialEq
1919
+ PartialOrd
@@ -66,7 +66,6 @@ pub(crate) trait Float:
6666
/// Returns `self` transmuted to `Self::SignedInt`
6767
fn signed_repr(self) -> Self::SignedInt;
6868

69-
#[cfg(test)]
7069
/// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
7170
/// represented in multiple different ways. This method returns `true` if two NaNs are
7271
/// compared.
@@ -80,10 +79,11 @@ pub(crate) trait Float:
8079

8180
/// Returns (normalized exponent, normalized significand)
8281
fn normalize(significand: Self::Int) -> (i32, Self::Int);
82+
83+
/// Returns if `self` is subnormal
84+
fn is_subnormal(&self) -> bool;
8385
}
8486

85-
// FIXME: Some of this can be removed if RFC Issue #1424 is resolved
86-
// https://github.com/rust-lang/rfcs/issues/1424
8787
macro_rules! float_impl {
8888
($ty:ident, $ity:ident, $sity:ident, $bits:expr, $significand_bits:expr) => {
8989
impl Float for $ty {
@@ -101,12 +101,11 @@ macro_rules! float_impl {
101101
const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);
102102

103103
fn repr(self) -> Self::Int {
104-
unsafe { mem::transmute(self) }
104+
self.to_bits()
105105
}
106106
fn signed_repr(self) -> Self::SignedInt {
107-
unsafe { mem::transmute(self) }
107+
self.to_bits() as Self::SignedInt
108108
}
109-
#[cfg(test)]
110109
fn eq_repr(self, rhs: Self) -> bool {
111110
if self.is_nan() && rhs.is_nan() {
112111
true
@@ -115,7 +114,7 @@ macro_rules! float_impl {
115114
}
116115
}
117116
fn from_repr(a: Self::Int) -> Self {
118-
unsafe { mem::transmute(a) }
117+
Self::from_bits(a)
119118
}
120119
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
121120
Self::from_repr(
@@ -133,6 +132,9 @@ macro_rules! float_impl {
133132
significand << shift as Self::Int,
134133
)
135134
}
135+
fn is_subnormal(&self) -> bool {
136+
(self.repr() & Self::EXPONENT_MASK) == Self::Int::ZERO
137+
}
136138
}
137139
};
138140
}

src/float/mul.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use float::Float;
2-
use int::{CastInto, Int, WideInt};
2+
use int::{CastInto, DInt, HInt, Int};
33

44
fn mul<F: Float>(a: F, b: F) -> F
55
where
66
u32: CastInto<F::Int>,
77
F::Int: CastInto<u32>,
88
i32: CastInto<F::Int>,
99
F::Int: CastInto<i32>,
10-
F::Int: WideInt,
10+
F::Int: HInt,
1111
{
1212
let one = F::Int::ONE;
1313
let zero = F::Int::ZERO;
@@ -112,8 +112,9 @@ where
112112
// have (exponentBits + 2) integral digits, all but two of which must be
113113
// zero. Normalizing this result is just a conditional left-shift by one
114114
// and bumping the exponent accordingly.
115-
let (mut product_high, mut product_low) =
116-
<F::Int as WideInt>::wide_mul(a_significand, b_significand << exponent_bits);
115+
let (mut product_low, mut product_high) = a_significand
116+
.widen_mul(b_significand << exponent_bits)
117+
.lo_hi();
117118

118119
let a_exponent_i32: i32 = a_exponent.cast();
119120
let b_exponent_i32: i32 = b_exponent.cast();
@@ -126,7 +127,8 @@ where
126127
if (product_high & implicit_bit) != zero {
127128
product_exponent = product_exponent.wrapping_add(1);
128129
} else {
129-
<F::Int as WideInt>::wide_shift_left(&mut product_high, &mut product_low, 1);
130+
product_high = (product_high << 1) | (product_low >> (bits - 1));
131+
product_low <<= 1;
130132
}
131133

132134
// If we have overflowed the type, return +/- infinity.
@@ -142,17 +144,23 @@ where
142144
// handle this case separately, but we make it a special case to
143145
// simplify the shift logic.
144146
let shift = one.wrapping_sub(product_exponent.cast()).cast();
145-
if shift >= bits as i32 {
147+
if shift >= bits {
146148
return F::from_repr(product_sign);
147149
}
148150

149151
// Otherwise, shift the significand of the result so that the round
150152
// bit is the high bit of productLo.
151-
<F::Int as WideInt>::wide_shift_right_with_sticky(
152-
&mut product_high,
153-
&mut product_low,
154-
shift,
155-
)
153+
if shift < bits {
154+
let sticky = product_low << (bits - shift);
155+
product_low = product_high << (bits - shift) | product_low >> shift | sticky;
156+
product_high >>= shift;
157+
} else if shift < (2 * bits) {
158+
let sticky = product_high << (2 * bits - shift) | product_low;
159+
product_low = product_high >> (shift - bits) | sticky;
160+
product_high = zero;
161+
} else {
162+
product_high = zero;
163+
}
156164
} else {
157165
// Result is normal before rounding; insert the exponent.
158166
product_high &= significand_mask;

src/int/addsub.rs

+23-61
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
1-
use int::Int;
2-
use int::LargeInt;
1+
use int::{DInt, Int};
32

4-
trait UAddSub: LargeInt {
3+
trait UAddSub: DInt {
54
fn uadd(self, other: Self) -> Self {
6-
let (low, carry) = self.low().overflowing_add(other.low());
7-
let high = self.high().wrapping_add(other.high());
8-
let carry = if carry {
9-
Self::HighHalf::ONE
10-
} else {
11-
Self::HighHalf::ZERO
12-
};
13-
Self::from_parts(low, high.wrapping_add(carry))
5+
let (lo, carry) = self.lo().overflowing_add(other.lo());
6+
let hi = self.hi().wrapping_add(other.hi());
7+
let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
8+
Self::from_lo_hi(lo, hi.wrapping_add(carry))
149
}
1510
fn uadd_one(self) -> Self {
16-
let (low, carry) = self.low().overflowing_add(Self::LowHalf::ONE);
17-
let carry = if carry {
18-
Self::HighHalf::ONE
19-
} else {
20-
Self::HighHalf::ZERO
21-
};
22-
Self::from_parts(low, self.high().wrapping_add(carry))
11+
let (lo, carry) = self.lo().overflowing_add(Self::H::ONE);
12+
let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
13+
Self::from_lo_hi(lo, self.hi().wrapping_add(carry))
2314
}
2415
fn usub(self, other: Self) -> Self {
2516
let uneg = (!other).uadd_one();
@@ -48,19 +39,9 @@ trait Addo: AddSub
4839
where
4940
<Self as Int>::UnsignedInt: UAddSub,
5041
{
51-
fn addo(self, other: Self, overflow: &mut i32) -> Self {
52-
*overflow = 0;
53-
let result = AddSub::add(self, other);
54-
if other >= Self::ZERO {
55-
if result < self {
56-
*overflow = 1;
57-
}
58-
} else {
59-
if result >= self {
60-
*overflow = 1;
61-
}
62-
}
63-
result
42+
fn addo(self, other: Self) -> (Self, bool) {
43+
let sum = AddSub::add(self, other);
44+
(sum, (other < Self::ZERO) != (sum < self))
6445
}
6546
}
6647

@@ -71,19 +52,9 @@ trait Subo: AddSub
7152
where
7253
<Self as Int>::UnsignedInt: UAddSub,
7354
{
74-
fn subo(self, other: Self, overflow: &mut i32) -> Self {
75-
*overflow = 0;
76-
let result = AddSub::sub(self, other);
77-
if other >= Self::ZERO {
78-
if result > self {
79-
*overflow = 1;
80-
}
81-
} else {
82-
if result <= self {
83-
*overflow = 1;
84-
}
85-
}
86-
result
55+
fn subo(self, other: Self) -> (Self, bool) {
56+
let sum = AddSub::sub(self, other);
57+
(sum, (other < Self::ZERO) != (self < sum))
8758
}
8859
}
8960

@@ -92,43 +63,34 @@ impl Subo for u128 {}
9263

9364
intrinsics! {
9465
pub extern "C" fn __rust_i128_add(a: i128, b: i128) -> i128 {
95-
__rust_u128_add(a as _, b as _) as _
66+
AddSub::add(a,b)
9667
}
9768

9869
pub extern "C" fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
99-
let mut oflow = 0;
100-
let r = a.addo(b, &mut oflow);
101-
(r, oflow != 0)
70+
a.addo(b)
10271
}
10372

10473
pub extern "C" fn __rust_u128_add(a: u128, b: u128) -> u128 {
105-
a.add(b)
74+
AddSub::add(a,b)
10675
}
10776

10877
pub extern "C" fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
109-
let mut oflow = 0;
110-
let r = a.addo(b, &mut oflow);
111-
(r, oflow != 0)
78+
a.addo(b)
11279
}
11380

114-
11581
pub extern "C" fn __rust_i128_sub(a: i128, b: i128) -> i128 {
116-
__rust_u128_sub(a as _, b as _) as _
82+
AddSub::sub(a,b)
11783
}
11884

11985
pub extern "C" fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
120-
let mut oflow = 0;
121-
let r = a.subo(b, &mut oflow);
122-
(r, oflow != 0)
86+
a.subo(b)
12387
}
12488

12589
pub extern "C" fn __rust_u128_sub(a: u128, b: u128) -> u128 {
126-
a.sub(b)
90+
AddSub::sub(a,b)
12791
}
12892

12993
pub extern "C" fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
130-
let mut oflow = 0;
131-
let r = a.subo(b, &mut oflow);
132-
(r, oflow != 0)
94+
a.subo(b)
13395
}
13496
}

0 commit comments

Comments
 (0)