iPhone(Swift,不是 ObjectC)上的最快平方根反比

Fastest Inverse Square Root on iPhone (Swift, not ObjectC)

参考 Fastest Inverse Square Root on iPhone

我需要在 iPhone iOS Swift 上做一个 "Fastest Inverse Square Root",这应该比 1/sqrt(float) 快。 我该怎么做?

在嵌入式C编程中,是:

// Fast inverse square-root
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
func invSqrt(x: Float) -> Float {
    var halfx : Float = 0.5 * x
    var y : Float = x
    long i = *(long*)&y

    i = 0x5f3759df - (i>>1)
    y = *(float*)&i
    y = y * (1.5 - (halfx * y * y))

    return y
}

唯一棘手的部分是如何在浮动之间进行强制转换 点数和整数类型,最简单的方法是使用 memcpy():

// Fast inverse square-root
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
func invSqrt(x: Float) -> Float {
    let halfx = 0.5 * x
    var y = x
    var i : Int32 = 0
    memcpy(&i, &y, 4)
    i = 0x5f3759df - (i >> 1)
    memcpy(&y, &i, 4)
    y = y * (1.5 - (halfx * y * y))
    return y
}

我用 1.000.000 随机数对 iPhone 6s 进行了一些性能测试 0 ... 1000 范围内的浮点数,结果 invSqrt(x)1.0/sqrt(x).

快 40%

最大相对误差低于 0.176%,证实了在 维基百科文章。

我也用 vvrsqrtf 从 加速框架,但这实际上比 调用 1.0/sqrt(x),至少在使用单浮动调用时 点数。


Swift 3 开始, memcpy() 可以替换为 bitPattern: Float 的方法和 UInt32 的相应构造函数:

func invSqrt(x: Float) -> Float {
    let halfx = 0.5 * x
    var i = x.bitPattern
    i = 0x5f3759df - (i >> 1)
    var y = Float(bitPattern: i)
    y = y * (1.5 - (halfx * y * y))
    return y
}