@@ -117,63 +117,9 @@ namespace generic {
117
117
// be implemented in another handler.
118
118
// Signaling NaN converted to quiet NaN with FE_INVALID exception.
119
119
// https://www.open-std.org/JTC1/SC22/WG14/www/docs/n1011.htm
120
- template <typename T> struct FModExceptionalInputHandler {
121
-
122
- static_assert (cpp::is_floating_point_v<T>,
123
- " FModCStandardWrapper instantiated with invalid type." );
124
-
125
- LIBC_INLINE static bool pre_check (T x, T y, T &out) {
126
- using FPB = fputil::FPBits<T>;
127
- const T quiet_nan = FPB::quiet_nan ().get_val ();
128
- FPB sx (x), sy (y);
129
- if (LIBC_LIKELY (!sy.is_zero () && !sy.is_inf_or_nan () &&
130
- !sx.is_inf_or_nan ())) {
131
- return false ;
132
- }
133
-
134
- if (sx.is_nan () || sy.is_nan ()) {
135
- if ((sx.is_nan () && !sx.is_quiet_nan ()) ||
136
- (sy.is_nan () && !sy.is_quiet_nan ()))
137
- fputil::raise_except_if_required (FE_INVALID);
138
- out = quiet_nan;
139
- return true ;
140
- }
141
-
142
- if (sx.is_inf () || sy.is_zero ()) {
143
- fputil::raise_except_if_required (FE_INVALID);
144
- fputil::set_errno_if_required (EDOM);
145
- out = quiet_nan;
146
- return true ;
147
- }
148
-
149
- if (sy.is_inf ()) {
150
- out = x;
151
- return true ;
152
- }
153
-
154
- // case where x == 0
155
- out = x;
156
- return true ;
157
- }
158
- };
159
-
160
- template <typename T> struct FModFastMathWrapper {
161
-
162
- static_assert (cpp::is_floating_point_v<T>,
163
- " FModFastMathWrapper instantiated with invalid type." );
164
-
165
- static bool pre_check (T, T, T &) { return false ; }
166
- };
167
-
168
- template <typename T> class FModDivisionSimpleHelper {
169
- private:
170
- using StorageType = typename FPBits<T>::StorageType;
171
-
172
- public:
173
- LIBC_INLINE constexpr static StorageType execute (int exp_diff,
174
- int sides_zeroes_count,
175
- StorageType m_x,
176
- StorageType m_y) {
120
+ template <typename T> struct FModDivisionSimpleHelper {
121
+ LIBC_INLINE constexpr static T execute (int exp_diff, int sides_zeroes_count,
122
+ T m_x, T m_y) {
177
123
while (exp_diff > sides_zeroes_count) {
178
124
exp_diff -= sides_zeroes_count;
179
125
m_x <<= sides_zeroes_count;
@@ -185,28 +131,21 @@ template <typename T> class FModDivisionSimpleHelper {
185
131
}
186
132
};
187
133
188
- template <typename T> class FModDivisionInvMultHelper {
189
- private:
190
- using FPB = FPBits<T>;
191
- using StorageType = typename FPB::StorageType;
192
-
193
- public:
194
- LIBC_INLINE constexpr static StorageType execute (int exp_diff,
195
- int sides_zeroes_count,
196
- StorageType m_x,
197
- StorageType m_y) {
134
+ template <typename T> struct FModDivisionInvMultHelper {
135
+ LIBC_INLINE constexpr static T execute (int exp_diff, int sides_zeroes_count,
136
+ T m_x, T m_y) {
137
+ constexpr int LENGTH = sizeof (T) * CHAR_BIT;
198
138
if (exp_diff > sides_zeroes_count) {
199
- StorageType inv_hy = (cpp::numeric_limits<StorageType >::max () / m_y);
139
+ T inv_hy = (cpp::numeric_limits<T >::max () / m_y);
200
140
while (exp_diff > sides_zeroes_count) {
201
141
exp_diff -= sides_zeroes_count;
202
- StorageType hd =
203
- (m_x * inv_hy) >> (FPB::TOTAL_LEN - sides_zeroes_count);
142
+ T hd = (m_x * inv_hy) >> (LENGTH - sides_zeroes_count);
204
143
m_x <<= sides_zeroes_count;
205
144
m_x -= hd * m_y;
206
145
while (LIBC_UNLIKELY (m_x > m_y))
207
146
m_x -= m_y;
208
147
}
209
- StorageType hd = (m_x * inv_hy) >> (FPB::TOTAL_LEN - exp_diff);
148
+ T hd = (m_x * inv_hy) >> (LENGTH - exp_diff);
210
149
m_x <<= exp_diff;
211
150
m_x -= hd * m_y;
212
151
while (LIBC_UNLIKELY (m_x > m_y))
@@ -219,22 +158,57 @@ template <typename T> class FModDivisionInvMultHelper {
219
158
}
220
159
};
221
160
222
- template <typename T, class Wrapper = FModExceptionalInputHandler <T>,
223
- class DivisionHelper = FModDivisionSimpleHelper<T >>
161
+ template <typename T, typename U = typename FPBits <T>::StorageType ,
162
+ typename DivisionHelper = FModDivisionSimpleHelper<U >>
224
163
class FMod {
225
- static_assert (cpp::is_floating_point_v<T>,
164
+ static_assert (cpp::is_floating_point_v<T> && cpp::is_unsigned_v<U> &&
165
+ (sizeof (U) * CHAR_BIT > FPBits<T>::FRACTION_LEN),
226
166
" FMod instantiated with invalid type." );
227
167
228
168
private:
229
169
using FPB = FPBits<T>;
230
170
using StorageType = typename FPB::StorageType;
231
171
172
+ LIBC_INLINE static bool pre_check (T x, T y, T &out) {
173
+ using FPB = fputil::FPBits<T>;
174
+ const T quiet_nan = FPB::quiet_nan ().get_val ();
175
+ FPB sx (x), sy (y);
176
+ if (LIBC_LIKELY (!sy.is_zero () && !sy.is_inf_or_nan () &&
177
+ !sx.is_inf_or_nan ())) {
178
+ return false ;
179
+ }
180
+
181
+ if (sx.is_nan () || sy.is_nan ()) {
182
+ if ((sx.is_nan () && !sx.is_quiet_nan ()) ||
183
+ (sy.is_nan () && !sy.is_quiet_nan ()))
184
+ fputil::raise_except_if_required (FE_INVALID);
185
+ out = quiet_nan;
186
+ return true ;
187
+ }
188
+
189
+ if (sx.is_inf () || sy.is_zero ()) {
190
+ fputil::raise_except_if_required (FE_INVALID);
191
+ fputil::set_errno_if_required (EDOM);
192
+ out = quiet_nan;
193
+ return true ;
194
+ }
195
+
196
+ if (sy.is_inf ()) {
197
+ out = x;
198
+ return true ;
199
+ }
200
+
201
+ // case where x == 0
202
+ out = x;
203
+ return true ;
204
+ }
205
+
232
206
LIBC_INLINE static constexpr FPB eval_internal (FPB sx, FPB sy) {
233
207
234
208
if (LIBC_LIKELY (sx.uintval () <= sy.uintval ())) {
235
209
if (sx.uintval () < sy.uintval ())
236
210
return sx; // |x|<|y| return x
237
- return FPB ( FPB ::zero ()); // |x|=|y| return 0.0
211
+ return FPB::zero (); // |x|=|y| return 0.0
238
212
}
239
213
240
214
int e_x = sx.get_biased_exponent ();
@@ -247,27 +221,29 @@ class FMod {
247
221
StorageType m_y = sy.get_explicit_mantissa ();
248
222
StorageType d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
249
223
if (d == 0 )
250
- return FPB ( FPB ::zero () );
224
+ return FPB::zero ();
251
225
// iy - 1 because of "zero power" for number with power 1
252
226
return FPB::make_value (d, e_y - 1 );
253
227
}
254
- /* Both subnormal special case. */
228
+ // Both subnormal special case.
255
229
if (LIBC_UNLIKELY (e_x == 0 && e_y == 0 )) {
256
230
FPB d;
257
231
d.set_mantissa (sx.uintval () % sy.uintval ());
258
232
return d;
259
233
}
260
234
261
235
// Note that hx is not subnormal by conditions above.
262
- StorageType m_x = sx.get_explicit_mantissa ();
236
+ U m_x = static_cast <U>( sx.get_explicit_mantissa () );
263
237
e_x--;
264
238
265
- StorageType m_y = sy.get_explicit_mantissa ();
266
- int lead_zeros_m_y = FPB::EXP_LEN;
239
+ U m_y = static_cast <U>(sy.get_explicit_mantissa ());
240
+ constexpr int DEFAULT_LEAD_ZEROS =
241
+ sizeof (U) * CHAR_BIT - FPB::FRACTION_LEN - 1 ;
242
+ int lead_zeros_m_y = DEFAULT_LEAD_ZEROS;
267
243
if (LIBC_LIKELY (e_y > 0 )) {
268
244
e_y--;
269
245
} else {
270
- m_y = sy.get_mantissa ();
246
+ m_y = static_cast <U>( sy.get_mantissa () );
271
247
lead_zeros_m_y = cpp::countl_zero (m_y);
272
248
}
273
249
@@ -286,26 +262,27 @@ class FMod {
286
262
287
263
{
288
264
// Shift hx left until the end or n = 0
289
- int left_shift = exp_diff < int (FPB::EXP_LEN) ? exp_diff : FPB::EXP_LEN;
265
+ int left_shift =
266
+ exp_diff < DEFAULT_LEAD_ZEROS ? exp_diff : DEFAULT_LEAD_ZEROS;
290
267
m_x <<= left_shift;
291
268
exp_diff -= left_shift;
292
269
}
293
270
294
271
m_x %= m_y;
295
272
if (LIBC_UNLIKELY (m_x == 0 ))
296
- return FPB ( FPB ::zero () );
273
+ return FPB::zero ();
297
274
298
275
if (exp_diff == 0 )
299
- return FPB::make_value (m_x, e_y);
276
+ return FPB::make_value (static_cast <StorageType>( m_x) , e_y);
300
277
301
- /* hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0 */
278
+ // hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0
302
279
m_x = DivisionHelper::execute (exp_diff, sides_zeroes_count, m_x, m_y);
303
- return FPB::make_value (m_x, e_y);
280
+ return FPB::make_value (static_cast <StorageType>( m_x) , e_y);
304
281
}
305
282
306
283
public:
307
284
LIBC_INLINE static T eval (T x, T y) {
308
- if (T out; Wrapper:: pre_check (x, y, out))
285
+ if (T out; LIBC_UNLIKELY ( pre_check (x, y, out) ))
309
286
return out;
310
287
FPB sx (x), sy (y);
311
288
Sign sign = sx.sign ();
0 commit comments