| 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); |
| 443 | const __m128d szero = _mm_set1_pd(-0.0f); |
| 444 | const __m128d two_power_52 = _mm_set1_pd(0x10000000000000); |
| 445 | __m128d nan_mask = _mm_cmpunord_pd(a, a); |
| 446 | // eliminate nans to avoid invalid fp errors within cmpge |
| 447 | __m128d x = _mm_xor_pd(nan_mask, a); |
| 448 | __m128d abs_x = npyv_abs_f64(x); |
| 449 | __m128d sign_x = _mm_and_pd(x, szero); |
| 450 | // round by add magic number 2^52 |
| 451 | // assuming that MXCSR register is set to rounding |
| 452 | __m128d round = _mm_sub_pd(_mm_add_pd(two_power_52, abs_x), two_power_52); |
| 453 | // copysign |
| 454 | round = _mm_or_pd(round, sign_x); |
| 455 | __m128d floor = _mm_sub_pd(round, _mm_and_pd(_mm_cmpgt_pd(round, x), one)); |
| 456 | // a if |a| >= 2^52 or a == NaN |
| 457 | __m128d mask = _mm_cmpge_pd(abs_x, two_power_52); |
| 458 | mask = _mm_or_pd(mask, nan_mask); |
| 459 | return npyv_select_f64(_mm_castpd_si128(mask), a, floor); |
| 460 | } |
| 461 | #endif // NPY_HAVE_SSE41 |
| 462 | |
| 463 | #endif // _NPY_SIMD_SSE_MATH_H |
nothing calls this directly
no test coverage detected