| 416 | #define npyv_floor_f64 _mm_floor_pd |
| 417 | #else |
| 418 | NPY_FINLINE npyv_f32 npyv_floor_f32(npyv_f32 a) |
| 419 | { |
| 420 | const __m128 one = _mm_set1_ps(1.0f); |
| 421 | const __m128 szero = _mm_set1_ps(-0.0f); |
| 422 | const __m128i exp_mask = _mm_set1_epi32(0xff000000); |
| 423 | |
| 424 | __m128i nfinite_mask = _mm_slli_epi32(_mm_castps_si128(a), 1); |
| 425 | nfinite_mask = _mm_and_si128(nfinite_mask, exp_mask); |
| 426 | nfinite_mask = _mm_cmpeq_epi32(nfinite_mask, exp_mask); |
| 427 | |
| 428 | // eliminate nans/inf to avoid invalid fp errors |
| 429 | __m128 x = _mm_xor_ps(a, _mm_castsi128_ps(nfinite_mask)); |
| 430 | __m128i roundi = _mm_cvtps_epi32(x); |
| 431 | __m128 round = _mm_cvtepi32_ps(roundi); |
| 432 | __m128 floor = _mm_sub_ps(round, _mm_and_ps(_mm_cmpgt_ps(round, x), one)); |
| 433 | // respect signed zero |
| 434 | floor = _mm_or_ps(floor, _mm_and_ps(a, szero)); |
| 435 | // if overflow return a |
| 436 | __m128i overflow_mask = _mm_cmpeq_epi32(roundi, _mm_castps_si128(szero)); |
| 437 | // a if a overflow or nonfinite |
| 438 | return npyv_select_f32(_mm_or_si128(nfinite_mask, overflow_mask), a, floor); |
| 439 | } |
| 440 | NPY_FINLINE npyv_f64 npyv_floor_f64(npyv_f64 a) |
| 441 | { |
| 442 | const __m128d one = _mm_set1_pd(1.0f); |
nothing calls this directly
no test coverage detected