c ++ SSE内在函数atan2

时间:2015-07-31 08:25:17

标签: c++ trigonometry intrinsics

我需要一个非常快速的atan2来获得sobel值的渐变(我正在实施canny edge algo。)。有没有人知道一个非常快的实现,最好是内在函数(SIMD)或非常快速的近似。 (我认为近似值就足够了,因为这些值是四舍五入到0°,45°,90°,135°)

提前致谢

ADD:我知道SVML中的intel的IPP atan2很遗憾我无法使用它。

2 个答案:

答案 0 :(得分:2)

您似乎希望舍入到八进制数字,大概从-22.5°337.5°45°为增量。

通过等式

将八分音线通过原点分开
Y = X tan(Θ),

a.Y - b.X = 0.

有适当的缩放因子。

通过计算四个所需角度的这些表达式的符号,您将找到八分圆。通过巧妙的组合,您可以限制为三个符号评估,因为有8=2³种可能性。

这可以通过计算判别式表达式,它们的符号以及它们的符号的合适组合来使用SIMD指令进行评估,但这并非易事。

可能不需要转换为45°的倍数,甚至不需要顺序编号。这一切都取决于你对八分圆信息的处理方式。

其他SIMD建议:

使用预加载系数,您可以使用16位整数运算(可能使用乘法和加法)计算(X,Y)对中的所有四个线方程。然后获取符号并使用_mm_movemask_epi8将它们打包到四位。使用四位值作为小型查找表的输入。

答案 1 :(得分:-1)

如上所述here atan2()已经是单个FPU指令:x87 FPU操作码FPATAN。只需看一下调用std::atan2()时编译器生成的反汇编。如果它不是单个FPU指令,那么您可以在GCC内联汇编中尝试this

inline double my_atan2 (double y, double x) { 
  double result; 
  asm (
     "fpatan\n\t" 
     : "=t" (result)       // outputs; t = top of fpu stack
     : "0" (x),            // inputs; 0 = same as result
       "u" (y)             //         u = 2nd floating point register
     );   
  return result; 
}