[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当时,与乘法相比,浮点除法通常很昂贵; 快速逆平方根算法绕过了除法步骤,赋予其性能优势。

       为了计算平方根倒数的一般方法是计算一个近似为1x,然后通过另一种方法修改该近似直到它来实际结果的可接受的误差范围之内。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 × 23
2 0_00111110_00100000000000000000000  1.125 × 265
3 0_10111110_01101110101100111011111  1.432430... × 263
4 0_10000000_01001110101100111011111  1.307430... × 21

将该最后一位模式重新解释为浮点数给出近似值y = 2.61486,其具有大约3.4%的误差。在牛顿方法的一次迭代之后,最终结果是y = 2.52549,误差仅为0.17%。

算法描述:快速反向平方根算法计算1x,通过执行以下步骤。

(1)、将参数x别名为整数,作为计算 log2(x)近似值的方法

(2)、使用这种近似计算的近似对数log2(1x)= −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.mzph.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;需要具有高吞吐量、高可用等特点。而谈到消息系统的设计&…

使用 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…

超简单:解析 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 通用运算的第一…

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 …

java 复制文件

2019独角兽企业重金招聘Python工程师标准>>> public class copyFIle { public static void main(String[] args) throws IOException { File source new File("d:/test/1.xml");File des new File("d:/test/ma.txt");InputStream input null;…

Docker最全教程之MySQL容器化 (二十四)

Docker最全教程之MySQL容器化 &#xff08;二十四&#xff09; 原文:Docker最全教程之MySQL容器化 &#xff08;二十四&#xff09;前言 MySQL是目前最流行的开源的关系型数据库&#xff0c;MySQL的容器化之前有朋友投稿并且写过此块&#xff0c;本篇仅从笔者角…

CODING 受邀参加《腾讯全球数字生态大会》

近日&#xff0c;腾讯全年最重要的一场活动——《腾讯全球数字生态大会》于昆明滇池国际会展中心正式举办。此次全球数字生态大会是腾讯战略升级后&#xff0c;整合互联网数字经济峰会、云未来峰会、腾讯全球合作伙伴三大行业大会&#xff0c;全新升级打造的行业创新大会。大会…

第二章:08运算符[比较运算符]

①比较运算符②实例/* 运算符之三&#xff1a;比较运算符 ! > < > < instanceof 结论&#xff1a; 1.比较运算符的结果是boolean类型 2.区分 和 */ class CompareTest { public static void main(String[] args) { int i 10; int j 20; System.out.pr…

Apache版本兼容性问题

Apache 版本2.2.31 版本对于谷歌浏览器不兼容、IE8版本可以正常使用 当使用了Apache 高版本的话就解决了 出现以下现象 转载于:https://www.cnblogs.com/tzhyy/p/10931084.html

米尔电子Zynq UltraScale MPSoC核心板资料介绍

米尔Zynq UltraScale MPSoC核心板&#xff08;MYC-CZU3EG&#xff09;是采用Xilinx新一代Zynq处理器。该核心板是业界最小尺寸Zynq UltraScale 核心板&#xff0c;采用16纳米制程&#xff0c;相比Znyq7000系列每瓦性能提升5倍&#xff0c;且单芯片融合4核心Cortex-A53&#xff…