Fast inverse square of double in C/C++

前端 未结 3 1766
一个人的身影
一个人的身影 2021-02-06 02:27

Recently I was profiling a program in which the hotspot is definitely this

double d = somevalue();
double d2=d*d;
double c = 1.0/d2   // HOT SPOT
3条回答
  •  日久生厌
    2021-02-06 02:44

    Yes, you can certainly try and work something out. Let me just give you some general ideas, you can fill in the details.

    First, let's see why Carmack's root works:

    We write x = M × 2E in the usual way. Now recall that the IEEE float stores the exponent offset by a bias: If e denoted the exponent field, we have e = Bias + E ≥ 0. Rearranging, we get E = e − Bias.

    Now for the inverse square root: x−1/2 = M-1/2 × 2E/2. The new exponent field is:

           e' = Bias − E/2 = 3/2 Bias − e/2

    With bit fiddling, we can get the value e/2 from e by shifting, and 3/2 Bias is just a constant.

    Moreover, the mantissa M is stored as 1.0 + x with x < 1, and we can approximate M-1/2 as 1 + x/2. Again, the fact that only x is stored in binary means that we get the division by two by simple bit shifting.


    Now we look at x−2: this is equal to M−2 × 2−2 E, and we are looking for an exponent field:

           e' = Bias − 2 E = 3 Bias − 2 e

    Again, 3 Bias is just a constant, and you can get 2 e from e by bitshifting. As for the mantissa, you can approximate (1 + x)−2 by 1 − 2 x, and so the problem reduces to obtaining 2 x from x.


    Note that Carmack's magic floating point fiddling doesn't actually compute the result right aaway: Rather, it produces a remarkably accurate estimate, which is used as the starting point for a traditional, iterative computation. But because the estimate is so good, you only need very few rounds of subsequent iteration to get an acceptable result.

提交回复
热议问题