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