X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Futil%2Frounding.h;h=e329d438244579ab1596b48ba7d5bd713cc8662b;hb=76a1fb3b42c245a425fde55b97a393d3e1984112;hp=c8be45057b6f21e93ed5df5ff1ded8d6eb8c0f91;hpb=dd0d3a2c0fb388745519c8a3be800720541eccfe;p=mesa.git diff --git a/src/util/rounding.h b/src/util/rounding.h index c8be45057b6..e329d438244 100644 --- a/src/util/rounding.h +++ b/src/util/rounding.h @@ -21,7 +21,22 @@ * IN THE SOFTWARE. */ -#include +#ifndef _ROUNDING_H +#define _ROUNDING_H + +#include "c99_math.h" + +#include +#include + +#if defined(__SSE__) || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1)) || defined(_M_X64) +#include +#include +#endif + +#ifdef __SSE4_1__ +#include +#endif /* The C standard library has functions round()/rint()/nearbyint() that round * their arguments according to the rounding mode set in the floating-point @@ -45,7 +60,15 @@ static inline float _mesa_roundevenf(float x) { +#ifdef __SSE4_1__ + float ret; + __m128 m = _mm_load_ss(&x); + m = _mm_round_ss(m, m, _MM_FROUND_CUR_DIRECTION | _MM_FROUND_NO_EXC); + _mm_store_ss(&ret, m); + return ret; +#else return rintf(x); +#endif } /** @@ -54,5 +77,72 @@ _mesa_roundevenf(float x) static inline double _mesa_roundeven(double x) { +#ifdef __SSE4_1__ + double ret; + __m128d m = _mm_load_sd(&x); + m = _mm_round_sd(m, m, _MM_FROUND_CUR_DIRECTION | _MM_FROUND_NO_EXC); + _mm_store_sd(&ret, m); + return ret; +#else return rint(x); +#endif } + +/** + * \brief Rounds \c x to the nearest integer, with ties to the even integer, + * and returns the value as a long int. + */ +static inline long +_mesa_lroundevenf(float x) +{ +#if defined(__SSE__) || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1)) || defined(_M_X64) +#if LONG_MAX == INT64_MAX + return _mm_cvtss_si64(_mm_load_ss(&x)); +#elif LONG_MAX == INT32_MAX + return _mm_cvtss_si32(_mm_load_ss(&x)); +#else +#error "Unsupported long size" +#endif +#else + return lrintf(x); +#endif +} + + +/** + * \brief Rounds \c x to the nearest integer, with ties to the even integer, + * and returns the value as a long int. + */ +static inline long +_mesa_lroundeven(double x) +{ +#if defined(__SSE2__) || (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(_M_X64) +#if LONG_MAX == INT64_MAX + return _mm_cvtsd_si64(_mm_load_sd(&x)); +#elif LONG_MAX == INT32_MAX + return _mm_cvtsd_si32(_mm_load_sd(&x)); +#else +#error "Unsupported long size" +#endif +#else + return lrint(x); +#endif +} + +/** + * \brief Rounds \c x to the nearest integer, with ties to the even integer, + * and returns the value as an int64_t. + */ +static inline int64_t +_mesa_i64roundevenf(float x) +{ +#if LONG_MAX == INT64_MAX + return _mesa_lroundevenf(x); +#elif LONG_MAX == INT32_MAX + return llrintf(x); +#else +#error "Unsupported long size" +#endif +} + +#endif