| 317 | #define npyv_ceil_f64 _mm_ceil_pd |
| 318 | #else |
| 319 | NPY_FINLINE npyv_f32 npyv_ceil_f32(npyv_f32 a) |
| 320 | { |
| 321 | const __m128 one = _mm_set1_ps(1.0f); |
| 322 | const __m128 szero = _mm_set1_ps(-0.0f); |
| 323 | const __m128i exp_mask = _mm_set1_epi32(0xff000000); |
| 324 | |
| 325 | __m128i nfinite_mask = _mm_slli_epi32(_mm_castps_si128(a), 1); |
| 326 | nfinite_mask = _mm_and_si128(nfinite_mask, exp_mask); |
| 327 | nfinite_mask = _mm_cmpeq_epi32(nfinite_mask, exp_mask); |
| 328 | |
| 329 | // eliminate nans/inf to avoid invalid fp errors |
| 330 | __m128 x = _mm_xor_ps(a, _mm_castsi128_ps(nfinite_mask)); |
| 331 | __m128i roundi = _mm_cvtps_epi32(x); |
| 332 | __m128 round = _mm_cvtepi32_ps(roundi); |
| 333 | __m128 ceil = _mm_add_ps(round, _mm_and_ps(_mm_cmplt_ps(round, x), one)); |
| 334 | // respect signed zero |
| 335 | ceil = _mm_or_ps(ceil, _mm_and_ps(a, szero)); |
| 336 | // if overflow return a |
| 337 | __m128i overflow_mask = _mm_cmpeq_epi32(roundi, _mm_castps_si128(szero)); |
| 338 | // a if a overflow or nonfinite |
| 339 | return npyv_select_f32(_mm_or_si128(nfinite_mask, overflow_mask), a, ceil); |
| 340 | } |
| 341 | NPY_FINLINE npyv_f64 npyv_ceil_f64(npyv_f64 a) |
| 342 | { |
| 343 | const __m128d one = _mm_set1_pd(1.0); |
nothing calls this directly
no test coverage detected