上交所内在函数atan2

问题描述 投票:0回答:2

我需要一个非常快的

atan2
来从索贝尔值中获取梯度(我正在实现精明的边缘算法)。有谁知道一个非常快速的实现,最好是内在函数(SIMD)或非常快速的近似。 (我认为近似值就足够了,因为这些值四舍五入为 0°、45°、90°、135°)

添加:我知道 SVML 中的英特尔 IPP atan2,不幸的是我无法使用它。

c++ trigonometry simd sse intrinsics
2个回答
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
投票

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; 
}
© www.soinside.com 2019 - 2024. All rights reserved.