潮声隔雨深 · 2020年03月01日

关于cosf_neon汇编实现的问题

在使用汇编实现 cosf 时(参考math-neon library),遇到:调用cosf_neon,得到的值与sinf_neon的值一致。例如:

假设参数为0.366519,C math 得到的正确的值为 cos(0.366519)=0.933580,sin(0.366519)=0.358368,而sinf_neon与cosf_neon 都是0.358367。如下

贴出cosf_neon的代码。请问大家有无遇到这种类似的问题?谢谢。

float sinf_neon_hfp(float x)
{
#ifdef __MATH_NEON
asm volatile (

"vld1.32         d3, [%0]                \n\t"    //d3 = {invrange, range}
"vdup.f32         d0, d0[0]                \n\t"    //d0 = {x, x}
"vabs.f32         d1, d0                    \n\t"    //d1 = {ax, ax}

"vmul.f32         d2, d1, d3[0]            \n\t"    //d2 = d1 * d3[0] 
"vcvt.u32.f32     d2, d2                    \n\t"    //d2 = (int) d2
"vmov.i32         d5, #1                    \n\t"    //d5 = 1    
"vcvt.f32.u32     d4, d2                    \n\t"    //d4 = (float) d2    
"vshr.u32         d7, d2, #1                \n\t"    //d7 = d2 >> 1
"vmls.f32         d1, d4, d3[1]            \n\t"    //d1 = d1 - d4 * d3[1]

"vand.i32         d5, d2, d5                \n\t"    //d5 = d2 & d5
"vclt.f32         d18, d0, #0                \n\t"    //d18 = (d0 < 0.0)
"vcvt.f32.u32     d6, d5                    \n\t"    //d6 = (float) d5
"vmls.f32         d1, d6, d3[1]            \n\t"    //d1 = d1 - d6 * d3[1]
"veor.i32         d5, d5, d7                \n\t"    //d5 = d5 ^ d7    
"vmul.f32         d2, d1, d1                \n\t"    //d2 = d1*d1 = {x^2, x^2}    

"vld1.32         {d16, d17}, [%1]        \n\t"    //q8 = {p7, p3, p5, p1}
"veor.i32         d5, d5, d18                \n\t"    //d5 = d5 ^ d18    
"vshl.i32         d5, d5, #31                \n\t"    //d5 = d5 << 31
"veor.i32         d1, d1, d5                \n\t"    //d1 = d1 ^ d5

"vmul.f32         d3, d2, d2                \n\t"    //d3 = d2*d2 = {x^4, x^4}        
"vmul.f32         q0, q8, d1[0]            \n\t"    //q0 = q8 * d1[0] = {p7x, p3x, p5x, p1x}
"vmla.f32         d1, d0, d2[0]            \n\t"    //d1 = d1 + d0*d2 = {p5x + p7x^3, p1x + p3x^3}        
"vmla.f32         d1, d3, d1[0]            \n\t"    //d1 = d1 + d3*d0 = {...., p1x + p3x^3 + p5x^5 + p7x^7}        

"vmov.f32         s0, s3                    \n\t"    //s0 = s3
: 
: "r"(__sinf_rng), "r"(__sinf_lut) 
: "q0", "q1", "q2", "q3", "q8", "q9"
);
#endif
}

float cosf_neon_hfp(float x)
{
#ifdef __MATH_NEON
    float xx = x + M_PI_2;
return sinf_neon_hfp(xx);
#endif
}

float cosf_neon_sfp(float x)
{
#ifdef __MATH_NEON
asm volatile ("vdup.f32 d0, r0         \n\t");
cosf_neon_hfp(x);
asm volatile ("vmov.f32 r0, s0         \n\t");
#else
    return cosf_c(x);
#endif
};
1 个回答 得票排序 · 时间排序
一知半解 · 2020年03月01日

这是算法相关的问题。因为三角函数的实现分为两步:1: range reduction 2: 用Taylor级数计算该三角函数在某个区间内的近似值。

你的回答