1
1
use core:: mem;
2
- #[ cfg( test) ]
3
- use core:: fmt;
4
2
3
+ // NOTE(cfg) add is disabled for gnueabi due to
4
+ // https://github.com/rust-lang-nursery/compiler-builtins/issues/90
5
+
6
+ #[ cfg( not( gnueabi) ) ]
5
7
pub mod add;
6
8
pub mod pow;
7
9
@@ -16,22 +18,41 @@ pub trait Float: Sized + Copy {
16
18
/// Returns the bitwidth of the significand
17
19
fn significand_bits ( ) -> u32 ;
18
20
21
+ /// Returns the bitwidth of the exponent
22
+ fn exponent_bits ( ) -> u32 {
23
+ Self :: bits ( ) - Self :: significand_bits ( ) - 1
24
+ }
25
+
26
+ /// Returns a mask for the sign bit
27
+ fn sign_mask ( ) -> Self :: Int ;
28
+
29
+ /// Returns a mask for the significand
30
+ fn significand_mask ( ) -> Self :: Int ;
31
+
32
+ /// Returns a mask for the exponent
33
+ fn exponent_mask ( ) -> Self :: Int ;
34
+
19
35
/// Returns `self` transmuted to `Self::Int`
20
36
fn repr ( self ) -> Self :: Int ;
21
37
22
38
#[ cfg( test) ]
23
39
/// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
24
- /// represented in multiple different ways. This methods returns `true` if two NaNs are
40
+ /// represented in multiple different ways. This method returns `true` if two NaNs are
25
41
/// compared.
26
42
fn eq_repr ( self , rhs : Self ) -> bool ;
27
43
28
44
/// Returns a `Self::Int` transmuted back to `Self`
29
45
fn from_repr ( a : Self :: Int ) -> Self ;
30
46
47
+ /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
48
+ fn from_parts ( sign : bool , exponent : Self :: Int , significand : Self :: Int ) -> Self ;
49
+
31
50
/// Returns (normalized exponent, normalized significand)
32
51
fn normalize ( significand : Self :: Int ) -> ( i32 , Self :: Int ) ;
33
52
}
34
53
54
+ // FIXME: Some of this can be removed if RFC Issue #1424 is resolved
55
+ // https://github.com/rust-lang/rfcs/issues/1424
35
56
impl Float for f32 {
36
57
type Int = u32 ;
37
58
fn bits ( ) -> u32 {
@@ -40,6 +61,15 @@ impl Float for f32 {
40
61
fn significand_bits ( ) -> u32 {
41
62
23
42
63
}
64
+ fn sign_mask ( ) -> Self :: Int {
65
+ 1 << ( Self :: bits ( ) - 1 )
66
+ }
67
+ fn significand_mask ( ) -> Self :: Int {
68
+ ( 1 << Self :: significand_bits ( ) ) - 1
69
+ }
70
+ fn exponent_mask ( ) -> Self :: Int {
71
+ !( Self :: sign_mask ( ) | Self :: significand_mask ( ) )
72
+ }
43
73
fn repr ( self ) -> Self :: Int {
44
74
unsafe { mem:: transmute ( self ) }
45
75
}
@@ -54,6 +84,11 @@ impl Float for f32 {
54
84
fn from_repr ( a : Self :: Int ) -> Self {
55
85
unsafe { mem:: transmute ( a) }
56
86
}
87
+ fn from_parts ( sign : bool , exponent : Self :: Int , significand : Self :: Int ) -> Self {
88
+ Self :: from_repr ( ( ( sign as Self :: Int ) << ( Self :: bits ( ) - 1 ) ) |
89
+ ( ( exponent << Self :: significand_bits ( ) ) & Self :: exponent_mask ( ) ) |
90
+ ( significand & Self :: significand_mask ( ) ) )
91
+ }
57
92
fn normalize ( significand : Self :: Int ) -> ( i32 , Self :: Int ) {
58
93
let shift = significand. leading_zeros ( )
59
94
. wrapping_sub ( ( 1u32 << Self :: significand_bits ( ) ) . leading_zeros ( ) ) ;
@@ -68,6 +103,15 @@ impl Float for f64 {
68
103
fn significand_bits ( ) -> u32 {
69
104
52
70
105
}
106
+ fn sign_mask ( ) -> Self :: Int {
107
+ 1 << ( Self :: bits ( ) - 1 )
108
+ }
109
+ fn significand_mask ( ) -> Self :: Int {
110
+ ( 1 << Self :: significand_bits ( ) ) - 1
111
+ }
112
+ fn exponent_mask ( ) -> Self :: Int {
113
+ !( Self :: sign_mask ( ) | Self :: significand_mask ( ) )
114
+ }
71
115
fn repr ( self ) -> Self :: Int {
72
116
unsafe { mem:: transmute ( self ) }
73
117
}
@@ -82,36 +126,14 @@ impl Float for f64 {
82
126
fn from_repr ( a : Self :: Int ) -> Self {
83
127
unsafe { mem:: transmute ( a) }
84
128
}
129
+ fn from_parts ( sign : bool , exponent : Self :: Int , significand : Self :: Int ) -> Self {
130
+ Self :: from_repr ( ( ( sign as Self :: Int ) << ( Self :: bits ( ) - 1 ) ) |
131
+ ( ( exponent << Self :: significand_bits ( ) ) & Self :: exponent_mask ( ) ) |
132
+ ( significand & Self :: significand_mask ( ) ) )
133
+ }
85
134
fn normalize ( significand : Self :: Int ) -> ( i32 , Self :: Int ) {
86
135
let shift = significand. leading_zeros ( )
87
136
. wrapping_sub ( ( 1u64 << Self :: significand_bits ( ) ) . leading_zeros ( ) ) ;
88
137
( 1i32 . wrapping_sub ( shift as i32 ) , significand << shift as Self :: Int )
89
138
}
90
139
}
91
-
92
- // TODO: Move this to F32/F64 in qc.rs
93
- #[ cfg( test) ]
94
- #[ derive( Copy , Clone ) ]
95
- pub struct FRepr < F > ( F ) ;
96
-
97
- #[ cfg( test) ]
98
- impl < F : Float > PartialEq for FRepr < F > {
99
- fn eq ( & self , other : & FRepr < F > ) -> bool {
100
- // NOTE(cfg) for some reason, on hard float targets, our implementation doesn't
101
- // match the output of its gcc_s counterpart. Until we investigate further, we'll
102
- // just avoid testing against gcc_s on those targets. Do note that our
103
- // implementation matches the output of the FPU instruction on *hard* float targets
104
- // and matches its gcc_s counterpart on *soft* float targets.
105
- if cfg ! ( gnueabihf) {
106
- return true
107
- }
108
- self . 0 . eq_repr ( other. 0 )
109
- }
110
- }
111
-
112
- #[ cfg( test) ]
113
- impl < F : fmt:: Debug > fmt:: Debug for FRepr < F > {
114
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
115
- self . 0 . fmt ( f)
116
- }
117
- }
0 commit comments