| 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); |
| 344 | const __m128d szero = _mm_set1_pd(-0.0); |
| 345 | const __m128d two_power_52 = _mm_set1_pd(0x10000000000000); |
| 346 | __m128d nan_mask = _mm_cmpunord_pd(a, a); |
| 347 | // eliminate nans to avoid invalid fp errors within cmpge |
| 348 | __m128d x = _mm_xor_pd(nan_mask, a); |
| 349 | __m128d abs_x = npyv_abs_f64(x); |
| 350 | __m128d sign_x = _mm_and_pd(x, szero); |
| 351 | // round by add magic number 2^52 |
| 352 | // assuming that MXCSR register is set to rounding |
| 353 | __m128d round = _mm_sub_pd(_mm_add_pd(two_power_52, abs_x), two_power_52); |
| 354 | // copysign |
| 355 | round = _mm_or_pd(round, sign_x); |
| 356 | __m128d ceil = _mm_add_pd(round, _mm_and_pd(_mm_cmplt_pd(round, x), one)); |
| 357 | // respects sign of 0.0 |
| 358 | ceil = _mm_or_pd(ceil, sign_x); |
| 359 | // a if |a| >= 2^52 or a == NaN |
| 360 | __m128d mask = _mm_cmpge_pd(abs_x, two_power_52); |
| 361 | mask = _mm_or_pd(mask, nan_mask); |
| 362 | return npyv_select_f64(_mm_castpd_si128(mask), a, ceil); |
| 363 | } |
| 364 | #endif |
| 365 | |
| 366 | // trunc |
nothing calls this directly
no test coverage detected