簡體   English   中英

模 2*Pi 使用 SSE/SSE2

[英]Modulo 2*Pi using SSE/SSE2

我對使用 SSE 還是很陌生,我正在嘗試為1e8階的雙精度輸入實現2*Pi的模(其結果將被輸入到一些向量化的三角計算中)。

我目前對代碼的嘗試是基於mod(x, 2*Pi) = x - floor(x/(2*Pi))*2*Pi的想法,看起來像:

#define _PD_CONST(Name, Val)                                            \
static const double _pd_##Name[2] __attribute__((aligned(16))) = { Val, Val }  

_PD_CONST(2Pi, 6.283185307179586);  /* = 2*pi  */  
_PD_CONST(recip_2Pi, 0.159154943091895); /* = 1/(2*pi)  */

void vec_mod_2pi(const double * vec, int Size, double * modAns)
{
    __m128d sse_a, sse_b, sse_c;
    int i;
    int k = 0;
    double t = 0;

    unsigned int initial_mode;
    initial_mode = _MM_GET_ROUNDING_MODE();

    _MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN);

    for (i = 0; i < Size; i += 2)
    {
        sse_a = _mm_loadu_pd(vec+i);
        sse_b = _mm_mul_pd( _mm_cvtepi32_pd( _mm_cvtpd_epi32( _mm_mul_pd(sse_a, *(__m128d*)_pd_recip_2Pi) ) ), *(__m128d*)_pd_2Pi);
        sse_c = _mm_sub_pd(sse_a, sse_b);
        _mm_storeu_pd(modAns+i,sse_c);
    }

    k = i-2;
    for (i = 0; i < Size%2; i++)
    {
        t = (double)((int)(vec[k+i] * 0.159154943091895)) * 6.283185307179586;
        modAns[k+i] = vec[k+i] - t;
    }

    _MM_SET_ROUNDING_MODE(initial_mode);
}

不幸的是,這目前返回了很多NaN1.128e119的幾個答案(有些超出了我的目標0 -> 2*Pi的范圍!)。 我懷疑我出錯的地方是我試圖用來做floor的 double-to-int-to-double 轉換。

誰能建議我哪里出了問題以及如何改進它?

PS對該代碼的格式感到抱歉,這是我第一次在這里發布問題,似乎無法讓它在代碼塊中給我空行以使其可讀。

如果您想要任何類型的准確性,那么簡單的算法就非常糟糕。 有關准確的范圍縮減算法,請參見Ng 等人,ARGUMENT REDUCTION FOR HUGE ARGUMENTS:Good to the Last Bit (現在可通過 Wayback Machine 獲得: 2012-12-24

對於較大的參數,通常使用Hayne-Panek 算法 但是,Hayne-Panek 的論文很難閱讀,我建議您查看Handbook of Floating-Point Arithmetic 的第 11 章以獲得更易於理解的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM