如何实现快速逆sqrt没有未定义的行为? [英] How to implement fast inverse sqrt without undefined behavior?

查看:150
本文介绍了如何实现快速逆sqrt没有未定义的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我对严格别名规则的了解,此代码< a href =http://en.wikipedia.org/wiki/Fast_inverse_square_root>快速反向平方根将导致C ++中未定义的行为:

  float Q_rsqrt(float number)
{
long i;
float x2,y;
const float threehalfs = 1.5F;

x2 = number * 0.5F;
y = number;
i = *(long *)& y; // type punning
i = 0x5f3759df - (i>> 1);
y = *(float *)& i;
y = y *(threehalfs - (x2 * y * y));

return y;
}

这段代码是否确实导致UB?如果是,如何以标准兼容的方式重新实现?

假设:在调用此函数之前,我们以某种方式检查了浮点数是否为IEEE 754 32位格式, code> sizeof(long)== sizeof(float)并且平台是little-endian。

解决方案

您应该使用 memcpy 。 AFAIK这是唯一符合标准的方式,编译器足够聪明,可以用单个字移动指令替换调用。有关这些声明的说明,请参阅此问题


From what I understood about strict aliasing rule, this code for fast inverse square root will result in undefined behavior in C++:

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y; // type punning
    i  = 0x5f3759df - ( i >> 1 );
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );

    return y;
}

Does this code indeed cause UB? If yes, how can it be reimplemented in standard compliant way? If not, why not?

Assumptions: before calling this function we have somehow checked that floats are in IEEE 754 32-bit format, sizeof(long)==sizeof(float) and the platform is little-endian.

解决方案

You should use memcpy. AFAIK this is the only standard compliant way and compilers are smart enough to replace the call with a single word move instruction. See this question for reasoning behind these claims.

这篇关于如何实现快速逆sqrt没有未定义的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆