У меня небольшая проблема с округлением SSE. Код не требует пояснений, я пытаюсь получить число 0,0001 с в 293,05694580, включая некоторое округление (например, 52 в 5,21) …
#include <xmmintrin.h>
#include <emmintrin.h>
int main(void)
{
float val = (float) 293.05694580;
float tickSize = (float) 0.0001;
__m128 _val = _mm_set_ps1( val );
__m128 _shift = _mm_set_ps1( 1 / tickSize );
/* 293.0569480 * 10000 should be 2930569.480 */
__m128 _mul = _mm_mul_ps(_val, _shift);
/* Rounding 2930569.480 should get 2930569, but returns 2930570 instead. Why? */
__m128i _ticks = _mm_cvtps_epi32( _mul );
}
Наконец, как я могу изменить порядок результатов в _ticks?
Большое спасибо,
Даниил
проверьте промежуточный результат, не принимайте его
проверить / установить режим округления
для подсчета чего-либо используйте целые числа
Окончательный код, если кого-то волнует, это
inline void QTickCalcer::tickCountsFromDoubleArray(
const double * src, int * dest, const unsigned int elemCount) const
{
/* src and dest need to be align_malloced */
__m128i * r = (__m128i*)dest;
__m128i r1;
__m128i r2;
__m128i rTot;
__m128d * d1 = (__m128d*) & src[0];
__m128d * d2 = (__m128d*) & src[2];
__m128d tmp1;
__m128d tmp2;
for ( register unsigned int i = 0; i < elemCount/4; i++ )
{
tmp1 = _mm_mul_pd( *d1, this->_dshiftor);
tmp2 = _mm_mul_pd( *d2, this->_dshiftor);
/* Interleave - http://msdn.microsoft.com/en-us/library/c8c5hx3b(v=vs.71).aspx */
r1 = _mm_cvtpd_epi32 ( tmp1 );
r2 = _mm_cvtpd_epi32 ( tmp2 );
rTot = _mm_unpacklo_epi32 ( r1, r2 );
/* Shuffle to match the ordering in src - http://software.intel.com/en-us/forums/topic/309988 */
*r = _mm_shuffle_epi32( rTot, _MM_SHUFFLE(3,1,2,0));
d1 += 2;
d2 += 2;
r++;
}
};
Спасибо за все комментарии.
Для производительности и точности, возможно, вы могли бы: