@@ -9,27 +9,27 @@ macro_rules! add {
9
9
#[ allow( unused_parens) ]
10
10
#[ cfg_attr( not( test) , no_mangle) ]
11
11
pub extern fn $intrinsic( a: $ty, b: $ty) -> $ty {
12
- let one = Wrapping ( 1 as <$ty as Float >:: Int ) ;
13
- let zero = Wrapping ( 0 as <$ty as Float >:: Int ) ;
14
-
15
- let bits = Wrapping ( <$ty>:: bits( ) as <$ty as Float >:: Int ) ;
16
- let significand_bits = Wrapping ( <$ty>:: significand_bits( ) as <$ty as Float >:: Int ) ;
17
- let exponent_bits = Wrapping ( <$ty> :: exponent_bits ( ) as <$ty as Float > :: Int ) ;
18
- let max_exponent = ( one << exponent_bits. 0 as usize ) - one;
19
-
20
- let implicit_bit = one << significand_bits. 0 as usize ;
21
- let significand_mask = implicit_bit - one;
22
- let sign_bit = one << ( significand_bits + exponent_bits) . 0 as usize ;
23
- let abs_mask = sign_bit - one;
24
- let exponent_mask = abs_mask ^ significand_mask;
25
- let inf_rep = exponent_mask;
26
- let quiet_bit = implicit_bit >> 1 ;
27
- let qnan_rep = exponent_mask | quiet_bit;
28
-
29
- let mut a_rep = Wrapping ( a. repr( ) ) ;
30
- let mut b_rep = Wrapping ( b. repr( ) ) ;
31
- let a_abs = a_rep & abs_mask;
32
- let b_abs = b_rep & abs_mask;
12
+ let one = Wrapping ( 1 as <$ty as Float >:: Int ) ;
13
+ let zero = Wrapping ( 0 as <$ty as Float >:: Int ) ;
14
+
15
+ let bits = Wrapping ( <$ty>:: bits( ) as <$ty as Float >:: Int ) ;
16
+ let significand_bits = Wrapping ( <$ty>:: significand_bits( ) as <$ty as Float >:: Int ) ;
17
+ let exponent_bits = bits - significand_bits - one ;
18
+ let max_exponent = ( one << exponent_bits. 0 as usize ) - one;
19
+
20
+ let implicit_bit = one << significand_bits. 0 as usize ;
21
+ let significand_mask = implicit_bit - one;
22
+ let sign_bit = one << ( significand_bits + exponent_bits) . 0 as usize ;
23
+ let abs_mask = sign_bit - one;
24
+ let exponent_mask = abs_mask ^ significand_mask;
25
+ let inf_rep = exponent_mask;
26
+ let quiet_bit = implicit_bit >> 1 ;
27
+ let qnan_rep = exponent_mask | quiet_bit;
28
+
29
+ let mut a_rep = Wrapping ( a. repr( ) ) ;
30
+ let mut b_rep = Wrapping ( b. repr( ) ) ;
31
+ let a_abs = a_rep & abs_mask;
32
+ let b_abs = b_rep & abs_mask;
33
33
34
34
// Detect if a or b is zero, infinity, or NaN.
35
35
if a_abs - one >= inf_rep - one ||
@@ -188,7 +188,7 @@ mod tests {
188
188
use core:: { f32, f64} ;
189
189
190
190
use float:: Float ;
191
- use qc:: { F32 , F64 } ;
191
+ use qc:: { U32 , U64 } ;
192
192
193
193
// NOTE The tests below have special handing for NaN values.
194
194
// Because NaN != NaN, the floating-point representations must be used
@@ -212,18 +212,107 @@ mod tests {
212
212
}
213
213
}
214
214
215
+ // TODO: Add F32/F64 to qc so that they print the right values (at the very least)
215
216
check ! {
216
217
fn __addsf3( f: extern fn ( f32 , f32 ) -> f32 ,
217
- a: F32 ,
218
- b: F32 )
218
+ a: U32 ,
219
+ b: U32 )
219
220
-> Option <FRepr <f32 > > {
220
- Some ( FRepr ( f( a. 0 , b. 0 ) ) )
221
+ let ( a, b) = ( f32 :: from_repr( a. 0 ) , f32 :: from_repr( b. 0 ) ) ;
222
+ Some ( FRepr ( f( a, b) ) )
221
223
}
222
224
223
225
fn __adddf3( f: extern fn ( f64 , f64 ) -> f64 ,
224
- a: F64 ,
225
- b: F64 ) -> Option <FRepr <f64 > > {
226
- Some ( FRepr ( f( a. 0 , b. 0 ) ) )
226
+ a: U64 ,
227
+ b: U64 ) -> Option <FRepr <f64 > > {
228
+ let ( a, b) = ( f64 :: from_repr( a. 0 ) , f64 :: from_repr( b. 0 ) ) ;
229
+ Some ( FRepr ( f( a, b) ) )
227
230
}
228
231
}
232
+
233
+ // More tests for special float values
234
+
235
+ #[ test]
236
+ fn test_float_tiny_plus_tiny ( ) {
237
+ let tiny = f32:: from_repr ( 1 ) ;
238
+ let r = super :: __addsf3 ( tiny, tiny) ;
239
+ assert ! ( r. eq_repr( tiny + tiny) ) ;
240
+ }
241
+
242
+ #[ test]
243
+ fn test_double_tiny_plus_tiny ( ) {
244
+ let tiny = f64:: from_repr ( 1 ) ;
245
+ let r = super :: __adddf3 ( tiny, tiny) ;
246
+ assert ! ( r. eq_repr( tiny + tiny) ) ;
247
+ }
248
+
249
+ #[ test]
250
+ fn test_float_small_plus_small ( ) {
251
+ let a = f32:: from_repr ( 327 ) ;
252
+ let b = f32:: from_repr ( 256 ) ;
253
+ let r = super :: __addsf3 ( a, b) ;
254
+ assert ! ( r. eq_repr( a + b) ) ;
255
+ }
256
+
257
+ #[ test]
258
+ fn test_double_small_plus_small ( ) {
259
+ let a = f64:: from_repr ( 327 ) ;
260
+ let b = f64:: from_repr ( 256 ) ;
261
+ let r = super :: __adddf3 ( a, b) ;
262
+ assert ! ( r. eq_repr( a + b) ) ;
263
+ }
264
+
265
+ #[ test]
266
+ fn test_float_one_plus_one ( ) {
267
+ let r = super :: __addsf3 ( 1f32 , 1f32 ) ;
268
+ assert ! ( r. eq_repr( 1f32 + 1f32 ) ) ;
269
+ }
270
+
271
+ #[ test]
272
+ fn test_double_one_plus_one ( ) {
273
+ let r = super :: __adddf3 ( 1f64 , 1f64 ) ;
274
+ assert ! ( r. eq_repr( 1f64 + 1f64 ) ) ;
275
+ }
276
+
277
+ #[ test]
278
+ fn test_float_different_nan ( ) {
279
+ let a = f32:: from_repr ( 1 ) ;
280
+ let b = f32:: from_repr ( 0b11111111100100010001001010101010 ) ;
281
+ let x = super :: __addsf3 ( a, b) ;
282
+ let y = a + b;
283
+ assert ! ( x. eq_repr( y) ) ;
284
+ }
285
+
286
+ #[ test]
287
+ fn test_double_different_nan ( ) {
288
+ let a = f64:: from_repr ( 1 ) ;
289
+ let b = f64:: from_repr ( 0b1111111111110010001000100101010101001000101010000110100011101011 ) ;
290
+ let x = super :: __adddf3 ( a, b) ;
291
+ let y = a + b;
292
+ assert ! ( x. eq_repr( y) ) ;
293
+ }
294
+
295
+ #[ test]
296
+ fn test_float_nan ( ) {
297
+ let r = super :: __addsf3 ( f32:: NAN , 1.23 ) ;
298
+ assert_eq ! ( r. repr( ) , f32 :: NAN . repr( ) ) ;
299
+ }
300
+
301
+ #[ test]
302
+ fn test_double_nan ( ) {
303
+ let r = super :: __adddf3 ( f64:: NAN , 1.23 ) ;
304
+ assert_eq ! ( r. repr( ) , f64 :: NAN . repr( ) ) ;
305
+ }
306
+
307
+ #[ test]
308
+ fn test_float_inf ( ) {
309
+ let r = super :: __addsf3 ( f32:: INFINITY , -123.4 ) ;
310
+ assert_eq ! ( r, f32 :: INFINITY ) ;
311
+ }
312
+
313
+ #[ test]
314
+ fn test_double_inf ( ) {
315
+ let r = super :: __adddf3 ( f64:: INFINITY , -123.4 ) ;
316
+ assert_eq ! ( r, f64 :: INFINITY ) ;
317
+ }
229
318
}
0 commit comments