round to nearest integer even
| 265 | |
| 266 | // round to nearest integer even |
| 267 | NPY_FINLINE npyv_f32 npyv_rint_f32(npyv_f32 a) |
| 268 | { |
| 269 | #ifdef NPY_HAVE_SSE41 |
| 270 | return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); |
| 271 | #else |
| 272 | const __m128 szero = _mm_set1_ps(-0.0f); |
| 273 | const __m128i exp_mask = _mm_set1_epi32(0xff000000); |
| 274 | |
| 275 | __m128i nfinite_mask = _mm_slli_epi32(_mm_castps_si128(a), 1); |
| 276 | nfinite_mask = _mm_and_si128(nfinite_mask, exp_mask); |
| 277 | nfinite_mask = _mm_cmpeq_epi32(nfinite_mask, exp_mask); |
| 278 | |
| 279 | // eliminate nans/inf to avoid invalid fp errors |
| 280 | __m128 x = _mm_xor_ps(a, _mm_castsi128_ps(nfinite_mask)); |
| 281 | __m128i roundi = _mm_cvtps_epi32(x); |
| 282 | __m128 round = _mm_cvtepi32_ps(roundi); |
| 283 | // respect signed zero |
| 284 | round = _mm_or_ps(round, _mm_and_ps(a, szero)); |
| 285 | // if overflow return a |
| 286 | __m128i overflow_mask = _mm_cmpeq_epi32(roundi, _mm_castps_si128(szero)); |
| 287 | // a if a overflow or nonfinite |
| 288 | return npyv_select_f32(_mm_or_si128(nfinite_mask, overflow_mask), a, round); |
| 289 | #endif |
| 290 | } |
| 291 | |
| 292 | // round to nearest integer even |
| 293 | NPY_FINLINE npyv_f64 npyv_rint_f64(npyv_f64 a) |