Skip to content

Commit a6d1ba7

Browse files
committed
Add Quickcheck types for float tests
1 parent 29ca0a3 commit a6d1ba7

File tree

3 files changed

+136
-139
lines changed

3 files changed

+136
-139
lines changed

src/float/add.rs

+11-104
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ macro_rules! add {
8989
if a_exponent.0 == 0 {
9090
let (exponent, significand) = <$ty>::normalize(a_significand.0);
9191
a_exponent = Wrapping(exponent);
92-
a_significand = Wrapping(significand);
92+
a_significand = Wrapping(significand);
9393
}
9494
if b_exponent.0 == 0 {
9595
let (exponent, significand) = <$ty>::normalize(b_significand.0);
9696
b_exponent = Wrapping(exponent);
97-
b_significand = Wrapping(significand);
97+
b_significand = Wrapping(significand);
9898
}
9999

100100
// The sign of the result is the sign of the larger operand, a. If they
@@ -123,8 +123,8 @@ macro_rules! add {
123123
if subtraction {
124124
a_significand -= b_significand;
125125
// If a == -b, return +zero.
126-
if a_significand.0 == 0 {
127-
return (<$ty as Float>::from_repr(0));
126+
if a_significand.0 == 0 {
127+
return (<$ty as Float>::from_repr(0));
128128
}
129129

130130
// If partial cancellation occured, we need to left-shift the result
@@ -148,7 +148,7 @@ macro_rules! add {
148148
}
149149

150150
// If we have overflowed the type, return +/- infinity:
151-
if a_exponent >= Wrapping(max_exponent.0 as i32) {
151+
if a_exponent >= Wrapping(max_exponent.0 as i32) {
152152
return (<$ty>::from_repr((inf_rep | result_sign).0));
153153
}
154154

@@ -198,20 +198,18 @@ pub extern fn __aeabi_fadd(a: f32, b: f32) -> f32 {
198198

199199
#[cfg(test)]
200200
mod tests {
201-
use core::{f32, f64};
202-
use qc::{U32, U64};
203201
use float::Float;
202+
use qc::{F32, F64};
204203

205204
// NOTE The tests below have special handing for NaN values.
206-
// Because NaN != NaN, the floating-point representations must be used
205+
// Because NaN != NaN, the representations are compared
207206
// Because there are many diffferent values of NaN, and the implementation
208207
// doesn't care about calculating the 'correct' one, if both values are NaN
209208
// the values are considered equivalent.
210209

211-
// TODO: Add F32/F64 to qc so that they print the right values (at the very least)
212210
quickcheck! {
213-
fn addsf3(a: U32, b: U32) -> bool {
214-
let (a, b) = (f32::from_repr(a.0), f32::from_repr(b.0));
211+
fn addsf3(a: F32, b: F32) -> bool {
212+
let (a, b) = (a.0, b.0);
215213
let x = super::__addsf3(a, b);
216214
let y = a + b;
217215
if !(x.is_nan() && y.is_nan()) {
@@ -221,8 +219,8 @@ mod tests {
221219
}
222220
}
223221

224-
fn adddf3(a: U64, b: U64) -> bool {
225-
let (a, b) = (f64::from_repr(a.0), f64::from_repr(b.0));
222+
fn adddf3(a: F64, b: F64) -> bool {
223+
let (a, b) = (a.0, b.0);
226224
let x = super::__adddf3(a, b);
227225
let y = a + b;
228226
if !(x.is_nan() && y.is_nan()) {
@@ -232,95 +230,4 @@ mod tests {
232230
}
233231
}
234232
}
235-
236-
// More tests for special float values
237-
238-
#[test]
239-
fn test_float_tiny_plus_tiny() {
240-
let tiny = f32::from_repr(1);
241-
let r = super::__addsf3(tiny, tiny);
242-
assert_eq!(r, tiny + tiny);
243-
}
244-
245-
#[test]
246-
fn test_double_tiny_plus_tiny() {
247-
let tiny = f64::from_repr(1);
248-
let r = super::__adddf3(tiny, tiny);
249-
assert_eq!(r, tiny + tiny);
250-
}
251-
252-
#[test]
253-
fn test_float_small_plus_small() {
254-
let a = f32::from_repr(327);
255-
let b = f32::from_repr(256);
256-
let r = super::__addsf3(a, b);
257-
assert_eq!(r, a + b);
258-
}
259-
260-
#[test]
261-
fn test_double_small_plus_small() {
262-
let a = f64::from_repr(327);
263-
let b = f64::from_repr(256);
264-
let r = super::__adddf3(a, b);
265-
assert_eq!(r, a + b);
266-
}
267-
268-
#[test]
269-
fn test_float_one_plus_one() {
270-
let r = super::__addsf3(1f32, 1f32);
271-
assert_eq!(r, 1f32 + 1f32);
272-
}
273-
274-
#[test]
275-
fn test_double_one_plus_one() {
276-
let r = super::__adddf3(1f64, 1f64);
277-
assert_eq!(r, 1f64 + 1f64);
278-
}
279-
280-
#[test]
281-
fn test_float_different_nan() {
282-
let a = f32::from_repr(1);
283-
let b = f32::from_repr(0b11111111100100010001001010101010);
284-
let x = super::__addsf3(a, b);
285-
let y = a + b;
286-
if !(x.is_nan() && y.is_nan()) {
287-
assert_eq!(x.repr(), y.repr());
288-
}
289-
}
290-
291-
#[test]
292-
fn test_double_different_nan() {
293-
let a = f64::from_repr(1);
294-
let b = f64::from_repr(
295-
0b1111111111110010001000100101010101001000101010000110100011101011);
296-
let x = super::__adddf3(a, b);
297-
let y = a + b;
298-
if !(x.is_nan() && y.is_nan()) {
299-
assert_eq!(x.repr(), y.repr());
300-
}
301-
}
302-
303-
#[test]
304-
fn test_float_nan() {
305-
let r = super::__addsf3(f32::NAN, 1.23);
306-
assert_eq!(r.repr(), f32::NAN.repr());
307-
}
308-
309-
#[test]
310-
fn test_double_nan() {
311-
let r = super::__adddf3(f64::NAN, 1.23);
312-
assert_eq!(r.repr(), f64::NAN.repr());
313-
}
314-
315-
#[test]
316-
fn test_float_inf() {
317-
let r = super::__addsf3(f32::INFINITY, -123.4);
318-
assert_eq!(r, f32::INFINITY);
319-
}
320-
321-
#[test]
322-
fn test_double_inf() {
323-
let r = super::__adddf3(f64::INFINITY, -123.4);
324-
assert_eq!(r, f64::INFINITY);
325-
}
326233
}

src/float/mod.rs

+51-13
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub mod add;
66
pub trait Float: Sized {
77
/// A uint of the same with as the float
88
type Int;
9-
9+
1010
/// Returns the bitwidth of the float type
1111
fn bits() -> u32;
1212

@@ -16,11 +16,14 @@ pub trait Float: Sized {
1616
/// Returns the bitwidth of the significand
1717
fn significand_bits() -> u32;
1818

19-
/// Returns `self` transmuted to `Self::Int`
20-
fn repr(self) -> Self::Int;
19+
/// Returns a mask for the sign bit of `self`
20+
fn sign_mask() -> Self::Int;
2121

22-
/// Returns a `Self::Int` transmuted back to `Self`
23-
fn from_repr(a: Self::Int) -> Self;
22+
/// Returns a mask for the exponent portion of `self`
23+
fn exponent_mask() -> Self::Int;
24+
25+
/// Returns a mask for the significand portion of `self`
26+
fn significand_mask() -> Self::Int;
2427

2528
/// Returns the sign bit of `self`
2629
fn sign(self) -> bool;
@@ -31,6 +34,15 @@ pub trait Float: Sized {
3134
/// Returns the significand portion of `self`
3235
fn significand(self) -> Self::Int;
3336

37+
/// Returns `self` transmuted to `Self::Int`
38+
fn repr(self) -> Self::Int;
39+
40+
/// Returns a `Self::Int` transmuted back to `Self`
41+
fn from_repr(a: Self::Int) -> Self;
42+
43+
/// Constructs a `Self` from its parts
44+
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self;
45+
3446
/// Returns (normalized exponent, normalized significand)
3547
fn normalize(significand: Self::Int) -> (i32, Self::Int);
3648
}
@@ -46,21 +58,34 @@ impl Float for f32 {
4658
fn significand_bits() -> u32 {
4759
23
4860
}
61+
fn sign_mask() -> Self::Int {
62+
1 << (Self::bits() - 1)
63+
}
64+
fn exponent_mask() -> Self::Int {
65+
((1 << Self::exponent_bits()) - 1) << Self::significand_bits()
66+
}
67+
fn significand_mask() -> Self::Int {
68+
(1 << Self::significand_bits()) - 1
69+
}
4970
fn repr(self) -> Self::Int {
5071
unsafe { mem::transmute(self) }
5172
}
5273
fn from_repr(a: Self::Int) -> Self {
5374
unsafe { mem::transmute(a) }
5475
}
76+
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
77+
Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) |
78+
exponent & Self::exponent_mask() |
79+
significand & Self::significand_mask())
80+
}
5581
fn sign(self) -> bool {
56-
(self.repr() & 1 << Self::bits()) != 0
82+
(self.repr() & Self::sign_mask()) != 0
5783
}
5884
fn exponent(self) -> Self::Int {
59-
self.repr() >> Self::significand_bits()
60-
& ((1 << Self::exponent_bits()) - 1)
85+
self.repr() >> Self::significand_bits() & Self::exponent_mask()
6186
}
6287
fn significand(self) -> Self::Int {
63-
self.repr() & ((1 << Self::significand_bits()) - 1)
88+
self.repr() & Self::significand_mask()
6489
}
6590
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
6691
let shift = significand.leading_zeros()
@@ -79,21 +104,34 @@ impl Float for f64 {
79104
fn significand_bits() -> u32 {
80105
52
81106
}
107+
fn sign_mask() -> Self::Int {
108+
1 << (Self::bits() - 1)
109+
}
110+
fn exponent_mask() -> Self::Int {
111+
((1 << Self::exponent_bits()) - 1) << Self::significand_bits()
112+
}
113+
fn significand_mask() -> Self::Int {
114+
(1 << Self::significand_bits()) - 1
115+
}
82116
fn repr(self) -> Self::Int {
83117
unsafe { mem::transmute(self) }
84118
}
85119
fn from_repr(a: Self::Int) -> Self {
86120
unsafe { mem::transmute(a) }
87121
}
122+
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
123+
Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) |
124+
exponent & Self::exponent_mask() |
125+
significand & Self::significand_mask())
126+
}
88127
fn sign(self) -> bool {
89-
(self.repr() & 1 << Self::bits()) != 0
128+
(self.repr() & Self::sign_mask()) != 0
90129
}
91130
fn exponent(self) -> Self::Int {
92-
self.repr() >> Self::significand_bits()
93-
& ((1 << Self::exponent_bits()) - 1)
131+
self.repr() >> Self::significand_bits() & Self::exponent_mask()
94132
}
95133
fn significand(self) -> Self::Int {
96-
self.repr() & ((1 << Self::significand_bits()) - 1)
134+
self.repr() & Self::significand_mask()
97135
}
98136
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
99137
let shift = significand.leading_zeros()

0 commit comments

Comments
 (0)