[Swift]快速反向平方根 | Fast inverse square root

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
?微信公眾號:山青詠芝(shanqingyongzhi)
?博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
?GitHub地址:https://github.com/strengthen/LeetCode
?原文地址:https://www.cnblogs.com/strengthen/p/10989143.html?
?如果鏈接不是山青詠芝的博客園地址,則可能是爬取作者的文章。
?原文已修改更新!強烈建議點擊原文地址閱讀!支持作者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★?

曲面法線廣泛用于光照和陰影計算,需要計算矢量的范數。這里顯示了垂直于表面的矢量場。

?

使用法線C從入射角求出反射角的二維例子;?

在這種情況下,在從曲面鏡反射的光上。快速反平方根用于將該計算推廣到三維空間。

? ? ? ?浮點數的倒數平方根用于計算標準化向量。程序可以使用標準化向量來確定入射角和反射角。3D圖形程序必須每秒執行數百萬次這些計算以模擬光照。當代碼在20世紀90年代早期開發時,大多數浮點處理能力都落后于整數處理的速度。在專門用于處理變換和照明的硬件出現之前,這對3D圖形程序來說很麻煩。

? ? ? ?通過計算其歐幾里德范數:矢量分量的平方和的平方根來確定矢量的長度。當向量的每個分量除以該長度時,新向量將是指向相同方向的單位向量。在3D圖形程序,所有的載體在三維空間中,所以v將是一個向量(v?1,v?2,v?3)。?

  • \ | {\ boldsymbol {v}} \ | = {\ sqrt {v_ {1} ^ {2} + v_ {2} ^ {2} + v_ {3} ^ {2}}}

是向量的歐幾里德范數。?

  • {\ displaystyle {\ boldsymbol {\ hat {v}}} = {\ frac {\ boldsymbol {v}} {\ left \ | {\ boldsymbol {v}} \ right \ |}}}

是使用||的歸一化(單位)向量?||v||?2代表v1^2?+?v2^2?+?v3^2。?

  • {\ displaystyle {\ boldsymbol {\ hat {v}}} = {\ frac {\ boldsymbol {v}} {\ sqrt {\ left \ | {\ boldsymbol {v}} \ right \ | ^ {2}}} }}

它將單位矢量與距離分量的平方根相關聯。反平方根可用于計算v,因為該等式等價于?

  • {\ displaystyle {\ boldsymbol {\ hat {v}}} = {\ boldsymbol {v}} \,{\ frac {1} {\ sqrt {\ left \ | {\ boldsymbol {v}} \ right \ | ^ {2}}}}}

其中分數項是平方根?||v||?2當時,與乘法相比,浮點除法通常很昂貴;?快速逆平方根算法繞過了除法步驟,賦予其性能優勢。

? ? ? ?為了計算平方根倒數的一般方法是計算一個近似為1?x,然后通過另一種方法修改該近似直到它來實際結果的可接受的誤差范圍之內。20世紀90年代早期的常用軟件方法從查找表中得出近似值。快速平方根的關鍵是通過利用浮點數的結構直接計算近似,證明比表查找更快。該算法比使用另一種方法計算平方根并計算倒數通過浮點除法快大約四倍。該算法的設計考慮了IEEE 754-1985?32位浮點規范,但研究表明它可以在其他浮點規范中實現。

? ? ? ?快速反平方根的速度優勢來自于將包含浮點數的長字視為整數,然后從特定常數0x5F3759DF中減去它。查看代碼的人不會立即清楚常量的目的,因此,與代碼中的其他此類常量一樣,它通常被稱為幻數。該整數減法和位移產生長字,當作為浮點數處理時,該長字是輸入數的反平方根的粗略近似。執行牛頓方法的一次迭代以獲得一定的準確性,并且代碼完成。該算法使用Newton方法的唯一第一近似值生成相當準確的結果;?然而,它比在1999年發布的rsqrtss x86處理器上使用SSE指令要慢得多且準確度低得多。

Talk is cheap.Show me your code:

(1)、平方根函數:方法1-牛頓迭代法

 
 1 func sqrt1(_ x: Float) -> Float {
 2     //判斷x是否為0
 3     if x == 0 {return 0}
 4     let high:Float = Float(x)
 5     let mid:Float = high/2
 6     var y:Float = (mid>1) ? mid : 1
 7     while(true)
 8     {
 9         let dy:Float = (y * y + high) / Float(y)/2
10         //處理float類型的取絕對值fabsf(float i)
11         if fabsf(y - dy) <= 0.00000001
12         {
13             return dy
14         }
15         else
16         {
17             y = dy
18         }
19     }
20 }

(2)、平方根函數:方法2?

 1 func sqrt2(_ x:Float) -> Float
 2 {
 3     var y:Float
 4     var delta:Float
 5     var maxError:Float
 6     if x <= 0 {return 0}
 7     // initial guess
 8     y = x / 2
 9     // refine
10     maxError = x * 0.00000001
11     repeat {
12         delta = ( y * y ) - x
13         y -= delta / ( 2 * y )
14     } while ( delta > maxError || delta < -maxError )
15     return y
16 }

(3)、快速反向平方根:方法1-使用memcpy()

注意開頭的導入:import Foundation。

invSqrt(x)比1.0/sqrt(x)快速增加了約40%,

最大相對誤差低于0.176%?

 1 import Foundation
 2 func invSqrt1(_ x: Float) -> Float {
 3     let halfx = 0.5 * x
 4     var y = x
 5     var i : Int32 = 0
 6     memcpy(&i, &y, 4)
 7     i = 0x5f3759df - (i >> 1)
 8     memcpy(&y, &i, 4)
 9     y = y * (1.5 - (halfx * y * y))
10     return y
11 }

(4)、快速反向平方根:方法2-bitPattern()

從Swift3開始,memcpy()可以用bitPattern:方法替換Float相應的構造函數UInt32:

1 func invSqrt2(_ x: Float) -> Float {
2     let halfx = 0.5 * x
3     var i = x.bitPattern
4     i = 0x5f3759df - (i >> 1)
5     var y = Float(bitPattern: i)
6     y = y * (1.5 - (halfx * y * y))
7     return y
8 }

綜合(1)~(4)測試:?

 1 let x:Float = 10.0
 2 let ans1:Float = sqrt1(x)
 3 let ans2:Float = sqrt2(x)
 4 let ans3:Float = invSqrt1(x)
 5 let ans4:Float = invSqrt2(x)
 6 print(1.0/ans1)
 7 //Print 0.31622776
 8 print(1.0/ans2)
 9 //Print 0.31622776
10 print(ans3)
11 //Print 0.31568578
12 print(ans4)
13 //Print 0.31568578

常量0x5f3759df來自哪里?為什么代碼有效?

快速逆平方根:有時被稱為快速InvSqrt()或由十六進制常數0x5F3759DF的估計1?√x算法的倒數(或乘法逆)的的平方根的32位的浮點數X在IEEE 754浮點格式。此操作用于數字信號處理以標準化矢量,即將其縮放為長度1.例如,計算機圖形程序使用反平方根來計算入射角和反射對照明和陰影。

? ? ? ?該算法接受32位浮點數作為輸入,并存儲一半的值供以后使用。然后處理代表浮點數作為一個32位的整數的比特,一個邏輯移位一個位權執行,并且結果從減去幻數 0X 5F3759DF,這是一個近似的浮點表示√2127。這導致輸入的平方根的第一近似。再次將這些位作為浮點數處理,它運行牛頓方法的一次迭代,產生更精確的近似。

一個有效例子:作為一個例子,數x = 0.15625可用于計算1?√x ≈ 2.52982.。該算法的第一步如下所示:?

1 0011_1110_0010_0000_0000_0000_0000_0000  Bit pattern of both x and i
2 0001_1111_0001_0000_0000_0000_0000_0000  Shift right one position: (i >> 1)
3 0101_1111_0011_0111_0101_1001_1101_1111  The magic number 0x5F3759DF
4 0100_0000_0010_0111_0101_1001_1101_1111  The result of 0x5F3759DF - (i >> 1)

使用IEEE 32位表示:?

1 0_01111100_01000000000000000000000  1.25 × 2?3
2 0_00111110_00100000000000000000000  1.125 × 2?65
3 0_10111110_01101110101100111011111  1.432430... × 263
4 0_10000000_01001110101100111011111  1.307430... × 21

將該最后一位模式重新解釋為浮點數給出近似值y?= 2.61486,其具有大約3.4%的誤差。在牛頓方法的一次迭代之后,最終結果是y?= 2.52549,誤差僅為0.17%。

算法描述:快速反向平方根算法計算1?x,通過執行以下步驟。

(1)、將參數x別名為整數,作為計算?log2(x)近似值的方法

(2)、使用這種近似計算的近似對數log2(1?x)= ?1/2 log2(x)

(3)、別名返回浮點數,作為計算base-2指數近似值的方法

(4)、使用牛頓方法的單次迭代來細化近似。

準確度:下圖顯示啟發式快速反平方根與libstdc提供的平方根直接反轉之間差異的圖表。注意兩個軸上的對數刻度。如上所述,近似值令人驚訝地準確。右邊的圖表描繪了函數的誤差(即,通過運行牛頓方法的一次迭代后的近似值的誤差),對于從0.01開始的輸入,其中標準庫給出10.0作為結果,而InvSqrt()給出9.982522,使差值為0.017479,即真值的0.175%。絕對誤差僅從此開始下降,而相對誤差保持在所有數量級的相同范圍內。

?

轉載于:https://www.cnblogs.com/strengthen/p/10989143.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448770.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448770.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448770.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

適用于ATI卡的GPU計算MD5的小程序源碼,基于AMD APP SDK開發

以下代碼在win7 home basic , ati hd 5450平臺測試通過&#xff0c;處理速度為每秒100萬次。 程序很簡單&#xff0c;只有一個main.cpp程序。Device端只有一個md5.cl文件。 下面我把代碼貼出來&#xff0c;因為不能上傳附件&#xff0c;我把完整工程包放到了242337476的群共享里…

【CentOS 7筆記11】,目錄權限,所有者與所有組,隱藏權限#171022

2019獨角獸企業重金招聘Python工程師標準>>> shallow丿ove 一. 文件或目錄權限change mode r4&#xff0c;w2&#xff0c;x1 selinux開啟則權限后面會有個. 更改SElinux配置文件&#xff0c;將永久關閉SElinux [rootlocalhost ~]# vi /etc/selinux/config #將默認…

python字符編碼與轉碼

詳細文章: http://www.cnblogs.com/yuanchenqi/articles/5956943.html http://www.diveintopython3.net/strings.html 需知: 1.在python2默認編碼是ASCII, python3里默認是unicode 2.unicode 分為 utf-32(占4個字節),utf-16(占兩個字節)&#xff0c;utf-8(占1-4個字節)&#xf…

IntelliJ IDEA 詳細圖解最常用的配置

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 剛剛使用IntelliJ IDEA 編輯器的時候&#xff0c;會有很多設置&#xff0c;會方便以后的開發&#xff0c;磨刀不誤砍柴工。 比如&#x…

OpenCL快速入門教程

OpenCL快速入門教程 原文地址&#xff1a;http://opencl.codeplex.com/wikipage?titleOpenCL%20Tutorials%20-%201 翻譯日期&#xff1a;2012年6月4日星期一 這是第一篇真正的OpenCL教程。這篇文章不會從GPU結構的技術概念和性能指標入手。我們將會從OpenCL的基礎API開始&…

Git使用教程-idea系列中git使用教程

一、新建項目 新建項目后記得復制git倉庫的地址。 二、上傳項目到git倉庫 在你的idea里新建git倉庫&#xff0c;這是新建本地倉庫&#xff0c;等會會同步到線上git倉庫 新建后如果代碼不是文件名不是綠色的表示沒有加入到git索引中 將需要上傳的文件按照下圖方式add 添加后&…

分布式開放 消息系統 (RocketMQ) 的原理與實踐

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 分布式消息系統作為實現分布式系統可擴展、可伸縮性的關鍵組件&#xff0c;需要具有高吞吐量、高可用等特點。而談到消息系統的設計&…

日本企業RPA導入風險分析和解決對策

日本企業RPA導入風險分析和解決對策 文/馬磊 【UiBot東京特約觀察 第三期】 RPA作為一種能將定型業務完全自動化的技術&#xff0c;在老齡化、少子化和勞動力不足的日本備受矚目。上一期我們談到了關于日本工作方式改革法案的實施以及RPA導入后帶來的積極影響。但是任何事物都會…

使用 OpenCL.Net 進行 C# GPU 并行編程

在 初探 C# GPU 通用計算技術 中&#xff0c;我使用 Accelerator 編寫了一個簡單的 GPU 計算程序。也簡單看了一些 Brahma 的代碼&#xff0c;從它的 SVN 最新代碼看&#xff0c;Brahma 要轉移到使用 OpenCL.Net 作為底層了&#xff0c;于是也去網上搜索了一下&#xff0c;發現…

模擬真實環境之內網漫游

0x00 前言 目標ip&#xff1a;192.168.31.55&#xff08;模擬外網&#xff09; 目的&#xff1a;通過一個站點滲透至內網&#xff0c;發現并控制內網全部主機 0x01 信息收集 用nmap進行端口探測 瀏覽站點時查看元素發現該站點是DotNetCMS v2.0 該版本cms存在SQL注入漏洞&#x…

iOS開發之普通網絡異步請求與文件下載方法

先來說說普通異步下載方法&#xff0c;分為POST、GET兩種 /** GET請求獲取數據*/(void)getDataWithUrl:(NSString *)strUrl finishBlock:(ECGNCNSDictionaryAndNSErrorBlock)finishBlock {if (strUrl.length 0) {return;}NSURL *url [NSURL URLWithString:strUrl];NSMutableU…

超簡單:解析 yml 類型(application.yml)配置文件 、springboot 工程讀取 yml 文件中的值

方法三是我覺得最簡單的。 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 工程結構&#xff1a; 2. 我要讀取 application.yml 中屬性 &#xff1a;spring.rocketmq.namesrvAddr …

初探 C# GPU 通用計算技術

GPU 的并行計算能力高于 CPU&#xff0c;所以最近也有很多利用 GPU 的項目出現在我們的視野中&#xff0c;在 InfoQ 上看到這篇介紹 Accelerator-V2 的文章&#xff0c;它是微軟研究院的研究項目&#xff0c;需要注冊后才能下載&#xff0c;感覺作為我接觸 GPU 通用運算的第一…

d3代碼如何改造成update結構(恰當處理enter和exit)

d3的enter和exit 網上有很多blog講解。說的還湊合的見&#xff1a;https://blog.csdn.net/nicolecc/article/details/50786661 如何把自己的rude繪圖代碼&#xff0c;進行精致化&#xff08;update&#xff09; 不多比比&#xff0c;上代碼示例&#xff1a; d3.selectAll(.circ…

退居二線VS在深圳發展,一個十年IT人的選擇之難

有的人一直以來&#xff0c;身體里彷佛住著兩個靈魂。一個靈魂說&#xff1a;人就要拼搏&#xff0c;要奮斗&#xff0c;要實現理想&#xff0c;要留在中國最繁華的城市&#xff0c;感受大都市的生活&#xff0c;實現個人價值&#xff0c;走上人生巔峰&#xff01;另一個靈魂說…

Jenkins 詳細安裝、構建部署 使用教程

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Jenkins是一個開源軟件項目&#xff0c;是基于Java開發的一種持續集成工具&#xff0c;用于監控持續重復的工作&#xff0c;功能包括&…

GPU并行計算版函數圖像生成器

前幾天技術大牛Vczh同學開發了一個函數圖像繪制程序&#xff0c;可以畫出方程f(x,y)0的圖像。他的原理是用圖像上每一點的坐標帶入函數f得到針對x和y的兩個方程&#xff0c;再用牛頓迭代法求解得到一組點集&#xff0c;然后畫到圖像上。用他的程序可以畫出各種各樣令人驚嘆的方…

完全平方公式、平方差公式、一個數負次方

1.完全平方公式&#xff1a; 兩數和&#xff08;或差&#xff09;的平方&#xff0c;等于它們的平方和&#xff0c;加上&#xff08;或減去&#xff09;它們的積的2倍即完全平方公式 (ab)2a2b22ab 兩數和的完全平方公式&#xff08;完全平方和&#xff09; 與(a-b)2a2b2-2ab …

WSS連接服務器端報錯

錯誤&#xff1a; 1. Firefox 和 Chrome 瀏覽器對SSL證書拒絕的錯誤提示是不一樣的&#xff1a; &#xff08;1&#xff09; Chrome報錯&#xff1a;WebSocket connection failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID &#xff08;2&#xff…

LogBack 入門實踐

一、簡介 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 LogBack是一個日志框架&#xff0c;它是Log4j作者Ceki的又一個日志組件。 LogBack,Slf4j,Log4j之間的關系 slf4j是The Simp…