1
1
use core:: mem;
2
- #[ cfg( test) ]
3
- use core:: fmt;
4
2
5
3
pub mod add;
6
4
pub mod pow;
@@ -16,22 +14,41 @@ pub trait Float: Sized + Copy {
16
14
/// Returns the bitwidth of the significand
17
15
fn significand_bits ( ) -> u32 ;
18
16
17
+ /// Returns the bitwidth of the exponent
18
+ fn exponent_bits ( ) -> u32 {
19
+ Self :: bits ( ) - Self :: significand_bits ( ) - 1
20
+ }
21
+
22
+ /// Returns a mask for the sign bit
23
+ fn sign_mask ( ) -> Self :: Int ;
24
+
25
+ /// Returns a mask for the significand
26
+ fn significand_mask ( ) -> Self :: Int ;
27
+
28
+ /// Returns a mask for the exponent
29
+ fn exponent_mask ( ) -> Self :: Int ;
30
+
19
31
/// Returns `self` transmuted to `Self::Int`
20
32
fn repr ( self ) -> Self :: Int ;
21
33
22
34
#[ cfg( test) ]
23
35
/// 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
36
+ /// represented in multiple different ways. This method returns `true` if two NaNs are
25
37
/// compared.
26
38
fn eq_repr ( self , rhs : Self ) -> bool ;
27
39
28
40
/// Returns a `Self::Int` transmuted back to `Self`
29
41
fn from_repr ( a : Self :: Int ) -> Self ;
30
42
43
+ /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
44
+ fn from_parts ( sign : bool , exponent : Self :: Int , significand : Self :: Int ) -> Self ;
45
+
31
46
/// Returns (normalized exponent, normalized significand)
32
47
fn normalize ( significand : Self :: Int ) -> ( i32 , Self :: Int ) ;
33
48
}
34
49
50
+ // FIXME: Some of this can be removed if RFC Issue #1424 is resolved
51
+ // https://github.com/rust-lang/rfcs/issues/1424
35
52
impl Float for f32 {
36
53
type Int = u32 ;
37
54
fn bits ( ) -> u32 {
@@ -40,6 +57,15 @@ impl Float for f32 {
40
57
fn significand_bits ( ) -> u32 {
41
58
23
42
59
}
60
+ fn sign_mask ( ) -> Self :: Int {
61
+ 1 << ( Self :: bits ( ) - 1 )
62
+ }
63
+ fn significand_mask ( ) -> Self :: Int {
64
+ ( 1 << Self :: significand_bits ( ) ) - 1
65
+ }
66
+ fn exponent_mask ( ) -> Self :: Int {
67
+ !( Self :: sign_mask ( ) | Self :: significand_mask ( ) )
68
+ }
43
69
fn repr ( self ) -> Self :: Int {
44
70
unsafe { mem:: transmute ( self ) }
45
71
}
@@ -54,6 +80,11 @@ impl Float for f32 {
54
80
fn from_repr ( a : Self :: Int ) -> Self {
55
81
unsafe { mem:: transmute ( a) }
56
82
}
83
+ fn from_parts ( sign : bool , exponent : Self :: Int , significand : Self :: Int ) -> Self {
84
+ Self :: from_repr ( ( ( sign as Self :: Int ) << ( Self :: bits ( ) - 1 ) ) |
85
+ ( ( exponent << Self :: significand_bits ( ) ) & Self :: exponent_mask ( ) ) |
86
+ ( significand & Self :: significand_mask ( ) ) )
87
+ }
57
88
fn normalize ( significand : Self :: Int ) -> ( i32 , Self :: Int ) {
58
89
let shift = significand. leading_zeros ( )
59
90
. wrapping_sub ( ( 1u32 << Self :: significand_bits ( ) ) . leading_zeros ( ) ) ;
@@ -68,6 +99,15 @@ impl Float for f64 {
68
99
fn significand_bits ( ) -> u32 {
69
100
52
70
101
}
102
+ fn sign_mask ( ) -> Self :: Int {
103
+ 1 << ( Self :: bits ( ) - 1 )
104
+ }
105
+ fn significand_mask ( ) -> Self :: Int {
106
+ ( 1 << Self :: significand_bits ( ) ) - 1
107
+ }
108
+ fn exponent_mask ( ) -> Self :: Int {
109
+ !( Self :: sign_mask ( ) | Self :: significand_mask ( ) )
110
+ }
71
111
fn repr ( self ) -> Self :: Int {
72
112
unsafe { mem:: transmute ( self ) }
73
113
}
@@ -82,36 +122,14 @@ impl Float for f64 {
82
122
fn from_repr ( a : Self :: Int ) -> Self {
83
123
unsafe { mem:: transmute ( a) }
84
124
}
125
+ fn from_parts ( sign : bool , exponent : Self :: Int , significand : Self :: Int ) -> Self {
126
+ Self :: from_repr ( ( ( sign as Self :: Int ) << ( Self :: bits ( ) - 1 ) ) |
127
+ ( ( exponent << Self :: significand_bits ( ) ) & Self :: exponent_mask ( ) ) |
128
+ ( significand & Self :: significand_mask ( ) ) )
129
+ }
85
130
fn normalize ( significand : Self :: Int ) -> ( i32 , Self :: Int ) {
86
131
let shift = significand. leading_zeros ( )
87
132
. wrapping_sub ( ( 1u64 << Self :: significand_bits ( ) ) . leading_zeros ( ) ) ;
88
133
( 1i32 . wrapping_sub ( shift as i32 ) , significand << shift as Self :: Int )
89
134
}
90
135
}
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