我试图将臭名昭着的fast inverse square root技术从C转换为D编程语言。必要的步骤是将长位存储在整数中:
i = * ( long * ) &y;
在评论部分,Andrew建议将此操作称为类型惩罚。 有人知道如何在D中执行打字操作吗?
对于那些好奇的人,这里是代码的完整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; // the part in question
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i; // again, but for floating points
y = y * ( threehalfs - ( x2 * y * y ) );
return y;
}
答案 0 :(得分:3)
你真正需要做的就是使用D风格的演员 - 这是D代码与C代码不同的唯一地方。
以下是工作计划:
import std.stdio;
float Q_rsqrt(float number) {
int i; // we use int here because int.sizeof == float.sizeof
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * cast(int*) &y;
i = 0x5f3759df - ( i >> 1 );
y = * cast(float*) &i;
y = y * ( threehalfs - ( x2 * y * y ) );
y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration
return y;
}
int main() {
writeln(Q_rsqrt(0.15625f));
// Output: 2.52981
return 0;
}
答案 1 :(得分:2)
使用union
可以实现同样的效果,现在可以制作@safe
并且在眼睛上更容易一些:[/ p>
float Q_rsqrt(float number) @safe {
union V {
int i;
float y;
}
V v;
float x2;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
with (v) {
y = number;
i = 0x5f3759df - ( i >> 1 );
y = y * ( threehalfs - ( x2 * y * y ) );
y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration
return y;
}
}
int main() {
writeln(Q_rsqrt(0.15625f));
// Output: 2.52981
return 0;
}
通过优化,它会生成与使用指针强制转换的实现相同的程序集(至少在LDC和GDC中)。