ブーストの erf 関数の背後にあるアルゴリズムについて利用可能な詳細はありますか? モジュールのドキュメントはあまり正確ではありません。私が見つけたのは、いくつかの方法が混在していることだけです。私には、Abramowitz と Stegun のバリエーションのように見えます。
- どの方法が混在していますか?
- メソッドはどのように混在していますか?
- erf 関数 (一定時間) の複雑さは?
セバスチャン
ブーストの erf 関数の背後にあるアルゴリズムについて利用可能な詳細はありますか? モジュールのドキュメントはあまり正確ではありません。私が見つけたのは、いくつかの方法が混在していることだけです。私には、Abramowitz と Stegun のバリエーションのように見えます。
セバスチャン
Boost Math Toolkitのドキュメントには、 AbramowitzとStegunを含むリファレンスの長いリストがあります。erf-functionインターフェイスには、数値の精度(したがって実行時の複雑さ)を制御するために使用できるポリシーテンプレートパラメーターが含まれています。
#include <boost/math/special_functions/erf.hpp>
namespace boost{ namespace math{
template <class T>
calculated-result-type erf(T z);
template <class T, class Policy>
calculated-result-type erf(T z, const Policy&);
template <class T>
calculated-result-type erfc(T z);
template <class T, class Policy>
calculated-result-type erfc(T z, const Policy&);
}} // namespaces
更新:
以前に提供されたerf関数への参照の「実装」セクションの逐語的なコピーの下に:
実装
これらの関数のすべてのバージョンは、最初に通常の反射式を使用して、引数を正にします。
erf(-z) = 1 - erf(z);
erfc(-z) = 2 - erfc(z); // preferred when -z < -0.5
erfc(-z) = 1 + erf(z); // preferred when -0.5 <= -z < 0
これらの関数の汎用バージョンは、不完全ガンマ関数の観点から実装されています。
仮数(仮数)サイズが認識されると(現在、53、64、および113ビットの実数に加えて、doubleへの昇格によって処理される単精度24ビット)、JMによって考案された一連の有理近似が使用されます。
z <= 0.5の場合、erfは奇関数であるため、erfは次の式を使用して計算されるという観察に基づいて、erfの有理近似が使用されます。
erf(z) = z * (C + R(z*z));
ここで、有理近似R(z * z)は絶対誤差に対して最適化されます。その絶対誤差が定数Cと比較して十分に小さい限り、R(z * z)の計算中に発生する丸め誤差は効果的になります。結果から消えます。その結果、この領域のerfとerfcのエラーは非常に低くなります。最後のビットが正しくないのは、ごく少数の場合だけです。
z> 0.5の場合、短い間隔[a、b)で次のことがわかります。
erfc(z) * exp(z*z) * z ~ c
一定の定数c。
したがって、z> 0.5の場合、以下を使用してerfcを計算します。
erfc(z) = exp(-z*z) * (C + R(z - B)) / z;
ここでも、R(z --B)は絶対誤差に対して最適化されており、定数Cは範囲の端点で取得されたerfc(z)* exp(z * z)*zの平均です。繰り返しになりますが、R(z --B)の絶対誤差がcと比較して小さい限り、c + R(z --B)は正しく丸められ、結果の誤差はexpの精度にのみ依存します。働き。実際には、ごく少数の場合を除いて、エラーは結果の最後のビットに限定されます。定数Bは、有理近似の範囲の左端が0になるように選択されます。
範囲[a、+∞]にわたる大きなzの場合、上記の近似は次のように変更されます。
erfc(z) = exp(-z*z) * (C + R(1 / z)) / z;