in common/checksum/sse2neon.h [7550:7613]
FORCE_INLINE __m128d _mm_round_pd(__m128d a, int rounding)
{
#if defined(__aarch64__) || defined(_M_ARM64)
switch (rounding) {
case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC):
return vreinterpretq_m128d_f64(vrndnq_f64(vreinterpretq_f64_m128d(a)));
case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC):
return _mm_floor_pd(a);
case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC):
return _mm_ceil_pd(a);
case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC):
return vreinterpretq_m128d_f64(vrndq_f64(vreinterpretq_f64_m128d(a)));
default: //_MM_FROUND_CUR_DIRECTION
return vreinterpretq_m128d_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)));
}
#else
double *v_double = (double *) &a;
if (rounding == (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC) ||
(rounding == _MM_FROUND_CUR_DIRECTION &&
_MM_GET_ROUNDING_MODE() == _MM_ROUND_NEAREST)) {
double res[2], tmp;
for (int i = 0; i < 2; i++) {
tmp = (v_double[i] < 0) ? -v_double[i] : v_double[i];
double roundDown = floor(tmp); // Round down value
double roundUp = ceil(tmp); // Round up value
double diffDown = tmp - roundDown;
double diffUp = roundUp - tmp;
if (diffDown < diffUp) {
/* If it's closer to the round down value, then use it */
res[i] = roundDown;
} else if (diffDown > diffUp) {
/* If it's closer to the round up value, then use it */
res[i] = roundUp;
} else {
/* If it's equidistant between round up and round down value,
* pick the one which is an even number */
double half = roundDown / 2;
if (half != floor(half)) {
/* If the round down value is odd, return the round up value
*/
res[i] = roundUp;
} else {
/* If the round up value is odd, return the round down value
*/
res[i] = roundDown;
}
}
res[i] = (v_double[i] < 0) ? -res[i] : res[i];
}
return _mm_set_pd(res[1], res[0]);
} else if (rounding == (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC) ||
(rounding == _MM_FROUND_CUR_DIRECTION &&
_MM_GET_ROUNDING_MODE() == _MM_ROUND_DOWN)) {
return _mm_floor_pd(a);
} else if (rounding == (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) ||
(rounding == _MM_FROUND_CUR_DIRECTION &&
_MM_GET_ROUNDING_MODE() == _MM_ROUND_UP)) {
return _mm_ceil_pd(a);
}
return _mm_set_pd(v_double[1] > 0 ? floor(v_double[1]) : ceil(v_double[1]),
v_double[0] > 0 ? floor(v_double[0]) : ceil(v_double[0]));
#endif
}