* @brief Return a float rounded to the nearest integer value. */
| 814 | * @brief Return a float rounded to the nearest integer value. |
| 815 | */ |
| 816 | ASTCENC_SIMD_INLINE vfloat4 round(vfloat4 a) |
| 817 | { |
| 818 | #if ASTCENC_SSE >= 41 |
| 819 | constexpr int flags = _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC; |
| 820 | return vfloat4(_mm_round_ps(a.m, flags)); |
| 821 | #else |
| 822 | __m128 v = a.m; |
| 823 | __m128 neg_zero = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000))); |
| 824 | __m128 no_fraction = _mm_set1_ps(8388608.0f); |
| 825 | __m128 abs_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF)); |
| 826 | __m128 sign = _mm_and_ps(v, neg_zero); |
| 827 | __m128 s_magic = _mm_or_ps(no_fraction, sign); |
| 828 | __m128 r1 = _mm_add_ps(v, s_magic); |
| 829 | r1 = _mm_sub_ps(r1, s_magic); |
| 830 | __m128 r2 = _mm_and_ps(v, abs_mask); |
| 831 | __m128 mask = _mm_cmple_ps(r2, no_fraction); |
| 832 | r2 = _mm_andnot_ps(mask, v); |
| 833 | r1 = _mm_and_ps(r1, mask); |
| 834 | return vfloat4(_mm_xor_ps(r1, r2)); |
| 835 | #endif |
| 836 | } |
| 837 | |
| 838 | /** |
| 839 | * @brief Return the horizontal minimum of a vector. |