平方根の逆数を取るための高速アルゴリズム - 組込みARM復刻

する#include <stdio.hに> 
する#include <string.hの> 
する#include <STDLIB.H> / * atof * / 


/ * 
计算= 1 / SQRT(N)
* / 
float型Q_rsqrt(浮動小数点数)
{ 
    長いI。
    フロートX2、Y。
    constのフロートthreehalfs = 1.5F; 
    X2 =数* 0.5F。
    Y =番号。
    I = *(長い*)&Y。
    //悪浮動小数点ビットレベルハッキング
    I = 0x5f3759df - (I >> 1)。//何ファック?
    Y = *(フロート*)&I。
    Y = Y *(threehalfs - (X2 *のYの*のY))。
    //第一反復
    // Y = Y *(threehalfs - (×2 * yをする* yを)); 
    //第二の繰り返し、これを除去することができる 
Q3_VM #ifndefを
__linux__ #ifdefの 
    のassert(!ISNAN(Y)); 
    // bk010122 - FPE?
#endifのは
#endifの
    Yを返します。
} 


int型のmain(int型ARGC、チャーCONST * ARGV [])
{ 
	F9 = 81.0fフロート。
	F9 = Q_rsqrt(F9)。

	printf( "F9 =%Fを\ n"、F9)。

	0を返します。
}

  結果:

F9 = 0.111086

1/9 = 0.111111に非常に近いコンピュータと1 / SQRT(81)

 

SQRT()関数を比較すると、このアルゴリズムは、ほぼ4倍の速さで、あなたが知っている、それはコンパイラの機能が付属していますが、厳格かつ慎重な組み立てに最適化されたああて!

ニュートン反復法の原理は、値を推測し、この値から反復を作ることです。したがって、準推測値、反復数が少ないです。カーマックが一緒後者変位アルゴリズムを用いて、結果としてこの値を推測0x5f3759df選ん、Y得られ、1 / SQRT(N)に非常に近いです。このように、我々は唯一の私たちに必要な精度を達成することができます2回のニュートン反復法を必要としています。

 

関数が1 / SQRT(X)を返し、SQRT(X)よりも画像処理関数は、より有用です。

 

この正一度だけの繰り返し!(実際には、不使用の繰り返し、直接操作)することに注意してください。コンパイル、テストは、よくこれが4倍速くだけワーキンググループの数、および標準SQRT()関数の比ではありません!

この単純な数は、性交が文をマークされているものを、最も中心と最も不可解を与えられたI = 0x5f3759df - (I >> 1 ); プラスY = Yの*(threehalfs - ( ×2 *のy * yを))。

 

2つの文平方根計算を完了するために!また、フレーズが速く、コアシフト演算であることに注意してください!具体的には、命令を掛けていない多くのRISCアーキテクチャのCPUは、これは非常に効率的です。

 

アルゴリズムの原理は、(X)/ F「(x)が連続的に近似F(x)がルート= XFを使用して、ニュートン反復法を使用することです。

 

平方根を取る:Fを(X)= X ^ 2 = A、F '(x)= 2 * X、F(X)/ F'(X)= X / 2、(x)はXFに置換されているF(X)/ F「(X)/ 2(X + A / X)を有し、

 

今、私たちは= 5を選択し、その後、私たちは5/2 = 2.5を数えることができる、など2として、推測を選択し、(2.5 + 2)/ 2 = 2.25; 5 / 2.25 = ......この繰り返しが続く、結果はに収束しますSQRT(5)。

 

しかし、カーマックの作者は本当に彼は神秘的な定数0x5f375a86計算その夢「値、選択した強力な場所である

ことは、我々は1 / SQRT(N)に非常に近い計算値を行コメントを追加しましたラインであるが、我々は唯一の2倍を必要としますニュートン反復は、私たちに必要な精度を達成することができます。

おすすめ

転載: www.cnblogs.com/CodeWorkerLiMing/p/11776369.html