round to nearest integer even
| 291 | |
| 292 | // round to nearest integer even |
| 293 | NPY_FINLINE npyv_f64 npyv_rint_f64(npyv_f64 a) |
| 294 | { |
| 295 | #ifdef NPY_HAVE_SSE41 |
| 296 | return _mm_round_pd(a, _MM_FROUND_TO_NEAREST_INT); |
| 297 | #else |
| 298 | const __m128d szero = _mm_set1_pd(-0.0); |
| 299 | const __m128d two_power_52 = _mm_set1_pd(0x10000000000000); |
| 300 | __m128d nan_mask = _mm_cmpunord_pd(a, a); |
| 301 | // eliminate nans to avoid invalid fp errors within cmpge |
| 302 | __m128d abs_x = npyv_abs_f64(_mm_xor_pd(nan_mask, a)); |
| 303 | // round by add magic number 2^52 |
| 304 | // assuming that MXCSR register is set to rounding |
| 305 | __m128d round = _mm_sub_pd(_mm_add_pd(two_power_52, abs_x), two_power_52); |
| 306 | // copysign |
| 307 | round = _mm_or_pd(round, _mm_and_pd(a, szero)); |
| 308 | // a if |a| >= 2^52 or a == NaN |
| 309 | __m128d mask = _mm_cmpge_pd(abs_x, two_power_52); |
| 310 | mask = _mm_or_pd(mask, nan_mask); |
| 311 | return npyv_select_f64(_mm_castpd_si128(mask), a, round); |
| 312 | #endif |
| 313 | } |
| 314 | // ceil |
| 315 | #ifdef NPY_HAVE_SSE41 |
| 316 | #define npyv_ceil_f32 _mm_ceil_ps |
nothing calls this directly
no test coverage detected