@@ -3,192 +3,190 @@ use core::num::Wrapping;
3
3
4
4
use float:: Float ;
5
5
6
+ /// Returns `a + b`
6
7
macro_rules! add {
7
- ( $abi: tt, $intrinsic: ident: $ty: ty) => {
8
- /// Returns `a + b`
9
- #[ allow( unused_parens) ]
10
- #[ cfg_attr( not( test) , no_mangle) ]
11
- pub extern $abi 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 = 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
-
34
- // Detect if a or b is zero, infinity, or NaN.
35
- if a_abs - one >= inf_rep - one ||
36
- b_abs - one >= inf_rep - one {
37
- // NaN + anything = qNaN
38
- if a_abs > inf_rep {
39
- return ( <$ty as Float >:: from_repr( ( a_abs | quiet_bit) . 0 ) ) ;
40
- }
41
- // anything + NaN = qNaN
42
- if b_abs > inf_rep {
43
- return ( <$ty as Float >:: from_repr( ( b_abs | quiet_bit) . 0 ) ) ;
44
- }
45
-
46
- if a_abs == inf_rep {
47
- // +/-infinity + -/+infinity = qNaN
48
- if ( a. repr( ) ^ b. repr( ) ) == sign_bit. 0 {
49
- return ( <$ty as Float >:: from_repr( qnan_rep. 0 ) ) ;
50
- } else {
51
- // +/-infinity + anything remaining = +/- infinity
52
- return a;
53
- }
54
- }
8
+ ( $a: expr, $b: expr, $ty: ty) => ( {
9
+ let a = $a;
10
+ let b = $b;
11
+ let one = Wrapping ( 1 as <$ty as Float >:: Int ) ;
12
+ let zero = Wrapping ( 0 as <$ty as Float >:: Int ) ;
13
+
14
+ let bits = Wrapping ( <$ty>:: bits( ) as <$ty as Float >:: Int ) ;
15
+ let significand_bits = Wrapping ( <$ty>:: significand_bits( ) as <$ty as Float >:: Int ) ;
16
+ let exponent_bits = bits - significand_bits - one;
17
+ let max_exponent = ( one << exponent_bits. 0 as usize ) - one;
18
+
19
+ let implicit_bit = one << significand_bits. 0 as usize ;
20
+ let significand_mask = implicit_bit - one;
21
+ let sign_bit = one << ( significand_bits + exponent_bits) . 0 as usize ;
22
+ let abs_mask = sign_bit - one;
23
+ let exponent_mask = abs_mask ^ significand_mask;
24
+ let inf_rep = exponent_mask;
25
+ let quiet_bit = implicit_bit >> 1 ;
26
+ let qnan_rep = exponent_mask | quiet_bit;
27
+
28
+ let mut a_rep = Wrapping ( a. repr( ) ) ;
29
+ let mut b_rep = Wrapping ( b. repr( ) ) ;
30
+ let a_abs = a_rep & abs_mask;
31
+ let b_abs = b_rep & abs_mask;
32
+
33
+ // Detect if a or b is zero, infinity, or NaN.
34
+ if a_abs - one >= inf_rep - one ||
35
+ b_abs - one >= inf_rep - one {
36
+ // NaN + anything = qNaN
37
+ if a_abs > inf_rep {
38
+ return <$ty as Float >:: from_repr( ( a_abs | quiet_bit) . 0 ) ;
39
+ }
40
+ // anything + NaN = qNaN
41
+ if b_abs > inf_rep {
42
+ return <$ty as Float >:: from_repr( ( b_abs | quiet_bit) . 0 ) ;
43
+ }
55
44
56
- // anything remaining + +/-infinity = +/-infinity
57
- if b_abs == inf_rep {
58
- return b;
45
+ if a_abs == inf_rep {
46
+ // +/-infinity + -/+infinity = qNaN
47
+ if ( a. repr( ) ^ b. repr( ) ) == sign_bit. 0 {
48
+ return <$ty as Float >:: from_repr( qnan_rep. 0 ) ;
49
+ } else {
50
+ // +/-infinity + anything remaining = +/- infinity
51
+ return a;
59
52
}
53
+ }
60
54
61
- // zero + anything = anything
62
- if a_abs. 0 == 0 {
63
- // but we need to get the sign right for zero + zero
64
- if b_abs. 0 == 0 {
65
- return ( <$ty as Float >:: from_repr( a. repr( ) & b. repr( ) ) ) ;
66
- } else {
67
- return b;
68
- }
69
- }
55
+ // anything remaining + +/-infinity = +/-infinity
56
+ if b_abs == inf_rep {
57
+ return b;
58
+ }
70
59
71
- // anything + zero = anything
60
+ // zero + anything = anything
61
+ if a_abs. 0 == 0 {
62
+ // but we need to get the sign right for zero + zero
72
63
if b_abs. 0 == 0 {
73
- return a;
64
+ return <$ty as Float >:: from_repr( a. repr( ) & b. repr( ) ) ;
65
+ } else {
66
+ return b;
74
67
}
75
68
}
76
69
77
- // Swap a and b if necessary so that a has the larger absolute value.
78
- if b_abs > a_abs {
79
- mem :: swap ( & mut a_rep , & mut b_rep ) ;
70
+ // anything + zero = anything
71
+ if b_abs. 0 == 0 {
72
+ return a ;
80
73
}
74
+ }
81
75
82
- // Extract the exponent and significand from the (possibly swapped) a and b.
83
- let mut a_exponent = Wrapping ( ( a_rep >> significand_bits. 0 as usize & max_exponent) . 0 as i32 ) ;
84
- let mut b_exponent = Wrapping ( ( b_rep >> significand_bits. 0 as usize & max_exponent) . 0 as i32 ) ;
85
- let mut a_significand = a_rep & significand_mask;
86
- let mut b_significand = b_rep & significand_mask;
87
-
88
- // normalize any denormals, and adjust the exponent accordingly.
89
- if a_exponent. 0 == 0 {
90
- let ( exponent, significand) = <$ty>:: normalize( a_significand. 0 ) ;
91
- a_exponent = Wrapping ( exponent) ;
92
- a_significand = Wrapping ( significand) ;
93
- }
94
- if b_exponent. 0 == 0 {
95
- let ( exponent, significand) = <$ty>:: normalize( b_significand. 0 ) ;
96
- b_exponent = Wrapping ( exponent) ;
97
- b_significand = Wrapping ( significand) ;
98
- }
76
+ // Swap a and b if necessary so that a has the larger absolute value.
77
+ if b_abs > a_abs {
78
+ mem:: swap( & mut a_rep, & mut b_rep) ;
79
+ }
99
80
100
- // The sign of the result is the sign of the larger operand, a. If they
101
- // have opposite signs, we are performing a subtraction; otherwise addition.
102
- let result_sign = a_rep & sign_bit;
103
- let subtraction = ( ( a_rep ^ b_rep) & sign_bit) != zero;
104
-
105
- // Shift the significands to give us round, guard and sticky, and or in the
106
- // implicit significand bit. (If we fell through from the denormal path it
107
- // was already set by normalize(), but setting it twice won't hurt
108
- // anything.)
109
- a_significand = ( a_significand | implicit_bit) << 3 ;
110
- b_significand = ( b_significand | implicit_bit) << 3 ;
111
-
112
- // Shift the significand of b by the difference in exponents, with a sticky
113
- // bottom bit to get rounding correct.
114
- let align = Wrapping ( ( a_exponent - b_exponent) . 0 as <$ty as Float >:: Int ) ;
115
- if align. 0 != 0 {
116
- if align < bits {
117
- let sticky = ( ( b_significand << ( bits - align) . 0 as usize ) . 0 != 0 ) as <$ty as Float >:: Int ;
118
- b_significand = ( b_significand >> align. 0 as usize ) | Wrapping ( sticky) ;
119
- } else {
120
- b_significand = one; // sticky; b is known to be non-zero.
121
- }
122
- }
123
- if subtraction {
124
- a_significand -= b_significand;
125
- // If a == -b, return +zero.
126
- if a_significand. 0 == 0 {
127
- return ( <$ty as Float >:: from_repr( 0 ) ) ;
128
- }
81
+ // Extract the exponent and significand from the (possibly swapped) a and b.
82
+ let mut a_exponent = Wrapping ( ( a_rep >> significand_bits. 0 as usize & max_exponent) . 0 as i32 ) ;
83
+ let mut b_exponent = Wrapping ( ( b_rep >> significand_bits. 0 as usize & max_exponent) . 0 as i32 ) ;
84
+ let mut a_significand = a_rep & significand_mask;
85
+ let mut b_significand = b_rep & significand_mask;
86
+
87
+ // normalize any denormals, and adjust the exponent accordingly.
88
+ if a_exponent. 0 == 0 {
89
+ let ( exponent, significand) = <$ty>:: normalize( a_significand. 0 ) ;
90
+ a_exponent = Wrapping ( exponent) ;
91
+ a_significand = Wrapping ( significand) ;
92
+ }
93
+ if b_exponent. 0 == 0 {
94
+ let ( exponent, significand) = <$ty>:: normalize( b_significand. 0 ) ;
95
+ b_exponent = Wrapping ( exponent) ;
96
+ b_significand = Wrapping ( significand) ;
97
+ }
129
98
130
- // If partial cancellation occured, we need to left-shift the result
131
- // and adjust the exponent:
132
- if a_significand < implicit_bit << 3 {
133
- let shift = a_significand. 0 . leading_zeros( ) as i32
134
- - ( implicit_bit << 3 ) . 0 . leading_zeros( ) as i32 ;
135
- a_significand <<= shift as usize ;
136
- a_exponent -= Wrapping ( shift) ;
137
- }
138
- } else /* addition */ {
139
- a_significand += b_significand;
140
-
141
- // If the addition carried up, we need to right-shift the result and
142
- // adjust the exponent:
143
- if ( a_significand & implicit_bit << 4 ) . 0 != 0 {
144
- let sticky = ( ( a_significand & one) . 0 != 0 ) as <$ty as Float >:: Int ;
145
- a_significand = a_significand >> 1 | Wrapping ( sticky) ;
146
- a_exponent += Wrapping ( 1 ) ;
147
- }
99
+ // The sign of the result is the sign of the larger operand, a. If they
100
+ // have opposite signs, we are performing a subtraction; otherwise addition.
101
+ let result_sign = a_rep & sign_bit;
102
+ let subtraction = ( ( a_rep ^ b_rep) & sign_bit) != zero;
103
+
104
+ // Shift the significands to give us round, guard and sticky, and or in the
105
+ // implicit significand bit. (If we fell through from the denormal path it
106
+ // was already set by normalize(), but setting it twice won't hurt
107
+ // anything.)
108
+ a_significand = ( a_significand | implicit_bit) << 3 ;
109
+ b_significand = ( b_significand | implicit_bit) << 3 ;
110
+
111
+ // Shift the significand of b by the difference in exponents, with a sticky
112
+ // bottom bit to get rounding correct.
113
+ let align = Wrapping ( ( a_exponent - b_exponent) . 0 as <$ty as Float >:: Int ) ;
114
+ if align. 0 != 0 {
115
+ if align < bits {
116
+ let sticky = ( ( b_significand << ( bits - align) . 0 as usize ) . 0 != 0 ) as <$ty as Float >:: Int ;
117
+ b_significand = ( b_significand >> align. 0 as usize ) | Wrapping ( sticky) ;
118
+ } else {
119
+ b_significand = one; // sticky; b is known to be non-zero.
148
120
}
149
-
150
- // If we have overflowed the type, return +/- infinity:
151
- if a_exponent >= Wrapping ( max_exponent. 0 as i32 ) {
152
- return ( <$ty>:: from_repr( ( inf_rep | result_sign) . 0 ) ) ;
121
+ }
122
+ if subtraction {
123
+ a_significand -= b_significand;
124
+ // If a == -b, return +zero.
125
+ if a_significand. 0 == 0 {
126
+ return <$ty as Float >:: from_repr( 0 ) ;
153
127
}
154
128
155
- if a_exponent . 0 <= 0 {
156
- // Result is denormal before rounding; the exponent is zero and we
157
- // need to shift the significand.
158
- let shift = Wrapping ( ( Wrapping ( 1 ) - a_exponent ) . 0 as <$ty as Float > :: Int ) ;
159
- let sticky = ( ( a_significand << ( bits - shift ) . 0 as usize ) . 0 != 0 ) as <$ty as Float > :: Int ;
160
- a_significand = a_significand >> shift. 0 as usize | Wrapping ( sticky ) ;
161
- a_exponent = Wrapping ( 0 ) ;
129
+ // If partial cancellation occured, we need to left-shift the result
130
+ // and adjust the exponent:
131
+ if a_significand < implicit_bit << 3 {
132
+ let shift = a_significand . 0 . leading_zeros ( ) as i32
133
+ - ( implicit_bit << 3 ) . 0 . leading_zeros ( ) as i32 ;
134
+ a_significand <<= shift as usize ;
135
+ a_exponent - = Wrapping ( shift ) ;
162
136
}
137
+ } else /* addition */ {
138
+ a_significand += b_significand;
139
+
140
+ // If the addition carried up, we need to right-shift the result and
141
+ // adjust the exponent:
142
+ if ( a_significand & implicit_bit << 4 ) . 0 != 0 {
143
+ let sticky = ( ( a_significand & one) . 0 != 0 ) as <$ty as Float >:: Int ;
144
+ a_significand = a_significand >> 1 | Wrapping ( sticky) ;
145
+ a_exponent += Wrapping ( 1 ) ;
146
+ }
147
+ }
163
148
164
- // Low three bits are round, guard, and sticky.
165
- let round_guard_sticky: i32 = ( a_significand. 0 & 0x7 ) as i32 ;
149
+ // If we have overflowed the type, return +/- infinity:
150
+ if a_exponent >= Wrapping ( max_exponent. 0 as i32 ) {
151
+ return <$ty>:: from_repr( ( inf_rep | result_sign) . 0 ) ;
152
+ }
166
153
167
- // Shift the significand into place, and mask off the implicit bit.
168
- let mut result = a_significand >> 3 & significand_mask;
154
+ if a_exponent. 0 <= 0 {
155
+ // Result is denormal before rounding; the exponent is zero and we
156
+ // need to shift the significand.
157
+ let shift = Wrapping ( ( Wrapping ( 1 ) - a_exponent) . 0 as <$ty as Float >:: Int ) ;
158
+ let sticky = ( ( a_significand << ( bits - shift) . 0 as usize ) . 0 != 0 ) as <$ty as Float >:: Int ;
159
+ a_significand = a_significand >> shift. 0 as usize | Wrapping ( sticky) ;
160
+ a_exponent = Wrapping ( 0 ) ;
161
+ }
169
162
170
- // Insert the exponent and sign.
171
- result |= Wrapping ( a_exponent. 0 as <$ty as Float >:: Int ) << significand_bits. 0 as usize ;
172
- result |= result_sign;
163
+ // Low three bits are round, guard, and sticky.
164
+ let round_guard_sticky: i32 = ( a_significand. 0 & 0x7 ) as i32 ;
173
165
174
- // Final rounding. The result may overflow to infinity, but that is the
175
- // correct result in that case.
176
- if round_guard_sticky > 0x4 { result += one; }
177
- if round_guard_sticky == 0x4 { result += result & one; }
166
+ // Shift the significand into place, and mask off the implicit bit.
167
+ let mut result = a_significand >> 3 & significand_mask;
178
168
179
- <$ty>:: from_repr( result. 0 )
180
- }
181
- }
182
- }
169
+ // Insert the exponent and sign.
170
+ result |= Wrapping ( a_exponent. 0 as <$ty as Float >:: Int ) << significand_bits. 0 as usize ;
171
+ result |= result_sign;
183
172
184
- #[ cfg( target_arch = "arm" ) ]
185
- add ! ( "aapcs" , __addsf3: f32 ) ;
173
+ // Final rounding. The result may overflow to infinity, but that is the
174
+ // correct result in that case.
175
+ if round_guard_sticky > 0x4 { result += one; }
176
+ if round_guard_sticky == 0x4 { result += result & one; }
186
177
187
- #[ cfg( not( target_arch = "arm" ) ) ]
188
- add ! ( "C" , __addsf3: f32 ) ;
178
+ <$ty>:: from_repr( result. 0 )
179
+ } )
180
+ }
189
181
190
- #[ cfg( target_arch = "arm" ) ]
191
- add ! ( "aapcs" , __adddf3: f64 ) ;
182
+ intrinsics ! {
183
+ #[ aapcs_on_arm]
184
+ pub extern "C" fn __addsf3( a: f32 , b: f32 ) -> f32 {
185
+ add!( a, b, f32 )
186
+ }
192
187
193
- #[ cfg( not( target_arch = "arm" ) ) ]
194
- add ! ( "C" , __adddf3: f64 ) ;
188
+ #[ aapcs_on_arm]
189
+ pub extern "C" fn __adddf3( a: f64 , b: f64 ) -> f64 {
190
+ add!( a, b, f64 )
191
+ }
192
+ }
0 commit comments