目次

atan2

atan2, atan2f, atan2l
tanの逆関数,atanの拡張版,現実的にはこっちのほうが使う機会が多そう.
atanと異なり,象限による場合分けが考慮される.
一部の関数はC99から実装?

引数の型に応じて明示的に関数を変えないと大変な目に合うので注意,stm32マイコンの場合atan2atan2fの間で7kBくらい差があった.

高速化のためのいろいろ

三角関数を扱うのもあり,浮動小数点を使うことが大抵だと思う.
しかしCortex-M0などのFPUが載ってないマイコンにはあまり進んでやらせたくないので,なんとかして軽くできないのか考える.
実際の実装に必要な処理を考えてみる.
テーブルを持つ→多分一番楽,二次元配列で持つというのが最も楽だけど半端ない容量食いそう…
引数はy,xで渡されることが多い。近似式で高速化する場合、$y/x$の値が-1~+1、つまり求めたい角度の範囲を$-\pi/4$~$+\pi/4$で計算し、後はy,xの値の場合分けで象限を切り替えて補正する。高速化の実装をする論文も引数は$y/x=z$とかにして、$-1{\le}z{\le}+1$としているものが大半そう。

試す

Efficient Approximations for the Arctangent Function
何種類か試している。

$$ \text{arctan}(z) \approx \frac{\pi}{4}z -z(|z|-1) $$

引数$z$は前述の範囲。最大誤差は4E-3 rad(0.22 deg)ほど

$$ \text{arctan}(z) \approx \frac{\pi}{4}z + 0.273z(1-|z|)(2.447+0.0663|z|) $$

引数$z$は前述の範囲。最大誤差は1.5E-3 rad(0.086 deg)ほど

Approximations For Digital Computers
$$ \text{arctan}(z) \approx 0.995354z-0.288679z^5+0.079331z^5 $$

引数$z$は前述の範囲。最大誤差は6.1E-4 rad(0.035 deg)ほど。5次の多項式近似でこれだけ精度が出る。この本位は11次までの多項式近似が書いてある。
この近似は奇数のみ。ホーナー法というので計算がしやすくなる。

参考文献

How to Find a Fast Floating-Point atan2 Approximation
https://gist.github.com/volkansalma/2972237
DSP Trick: Fixed-Point Atan2 With Self Normalization
Fast & accurate atan/arctan approximation algorithm
Speeding up atan2f by 50x
CORDIC
Arctan(x) using CORDIC
固定小数点
Fixed-point atan2
メモリがたくさんあればルックアップテーブル(LUT)でやればいい例が結構でてくる.
https://github.com/xiezhq-hermann/atan_lookup/blob/master/atan.cpp
Fast computation of arctangent functions for embedded applications: A comparative analysis
CMSIS-DSPの実装もLUTみたい
https://github.com/ARM-software/CMSIS-DSP/blob/main/Source/FastMathFunctions/arm_atan2_f32.c