digitalmars.D.learn - D equivalent of C++ reinterpret cast?
- Bradley Mitchell <abstractant1 gmail.com> Sep 19 2010
- orgoton baberek <sdf sa.com> Sep 19 2010
- bearophile <bearophileHUGS lycos.com> Sep 19 2010
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> Sep 19 2010
- bearophile <bearophileHUGS lycos.com> Sep 20 2010
- Juanjo Alvarez <fake fakeemail.com> Sep 19 2010
- Kagamin <spam here.lot> Sep 20 2010
- Jonathan M Davis <jmdavisProg gmx.com> Sep 19 2010
- Jonathan M Davis <jmdavisProg gmx.com> Sep 19 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Sep 19 2010
- Bradley Mitchell <abstractant1 gmail.com> Sep 19 2010
Hello,
I'm trying to implement the Quake 3 fast inverse square root algorithm which
requires casting from int to float without modifying the stored bits. A C++
reinterpret cast seems to accomplish this just fine but so far I have had no
success in D after trying quite a few different things. Here is the C++ I've
written that currently works:
#include <iostream>
float fastInvSqrt( float x )
{
const int INV_SQRT_N = 1597292357;
const float MULT = 1.000363245811462f;
float const mx = 0.5f * MULT * x;
int xi = *reinterpret_cast<int *>( &x );
xi = INV_SQRT_N - (xi >> 1);
x = *reinterpret_cast<float *>( &xi );
return x * (1.5f * MULT - mx * x * x);
}
int main()
{
float a = fastInvSqrt( 9.0f );
std::cout << a << std::endl;
}
And here is my D code that doesn't work yet:
module test;
import std.stdio;
float fastInvSqrt( float x )
{
const int INV_SQRT_N = 1597292357;
const float MULT = 1.000363245811462f;
float mx = 0.5f * MULT * x;
int xi = cast(int)cast(void*)x;
xi = INV_SQRT_N - (xi >> 1);
x = xi;
x = cast(float)cast(void*)xi;
return x * (1.5f * MULT - mx * x * x);
}
void main(string[] args)
{
float a = fastInvSqrt( 9.0f );
writefln("%f", a);
}
For further reference, the wikipedia article on this algorithm can be found
here:
http://en.wikipedia.org/wiki/Fast_inverse_square_root
and my C++ code is based on a slightly modified version described here:
http://www.ece.uwaterloo.ca/~dwharder/Algorithms_and_Data_Structures/Algorithms/Inverse_square_root/
As you can see, I'm not trying to convert an integer to an equivalent floating
point value but rather trying to coerce the variable to a float without
modifying the underlying bit sequence. Any help would be greatly appreciated!!
Thank you for your time,
Brad
Sep 19 2010
On 19/09/2010 18:39, Bradley Mitchell wrote:Hello, I'm trying to implement the Quake 3 fast inverse square root algorithm which requires casting from int to float without modifying the stored bits. A C++ reinterpret cast seems to accomplish this just fine but so far I have had no success in D after trying quite a few different things. Here is the C++ I've written that currently works: #include<iostream> float fastInvSqrt( float x ) { const int INV_SQRT_N = 1597292357; const float MULT = 1.000363245811462f; float const mx = 0.5f * MULT * x; int xi = *reinterpret_cast<int *>(&x ); xi = INV_SQRT_N - (xi>> 1); x = *reinterpret_cast<float *>(&xi ); return x * (1.5f * MULT - mx * x * x); } int main() { float a = fastInvSqrt( 9.0f ); std::cout<< a<< std::endl; } And here is my D code that doesn't work yet: module test; import std.stdio; float fastInvSqrt( float x ) { const int INV_SQRT_N = 1597292357; const float MULT = 1.000363245811462f; float mx = 0.5f * MULT * x; int xi = cast(int)cast(void*)x; xi = INV_SQRT_N - (xi>> 1); x = xi; x = cast(float)cast(void*)xi; return x * (1.5f * MULT - mx * x * x); } void main(string[] args) { float a = fastInvSqrt( 9.0f ); writefln("%f", a); } For further reference, the wikipedia article on this algorithm can be found here: http://en.wikipedia.org/wiki/Fast_inverse_square_root and my C++ code is based on a slightly modified version described here: http://www.ece.uwaterloo.ca/~dwharder/Algorithms_and_Data_Structures/Algorithms/Inverse_square_root/ As you can see, I'm not trying to convert an integer to an equivalent floating point value but rather trying to coerce the variable to a float without modifying the underlying bit sequence. Any help would be greatly appreciated!! Thank you for your time, Brad
Use a union, which is the correct and safe way. union convert { float f; uint i; } convert.f = 1.0f; writeln(convert.i); will print 1065353216 (0x3f800000)
Sep 19 2010
orgoton baberek:Use a union, which is the correct and safe way.
C standard say that's not safe. You can force that to be safe in C-GCC if you explicitly disable a compiler optimization. I think D docs don't say anything about this. And Walter has said that regarding such things D acts as C. So I am not sure that will be safe in future D. Bye, bearophile
Sep 19 2010
Jonathan M Davis wrote:On Sunday 19 September 2010 17:07:38 bearophile wrote:orgoton baberek:Use a union, which is the correct and safe way.
you explicitly disable a compiler optimization. I think D docs don't say anything about this. And Walter has said that regarding such things
as C. So I am not sure that will be safe in future D. Bye, bearophile
I'd have to go digging in old posts, but I'm pretty sure that that's
how you're supposed to do it in D. I haven't ever done it because I
that sort of casting is pretty evil and only should be used as a last
but I believe that unions are the correct way to handle it in D.
I remember being a part of a discussion where D'is unions were told to be exactly the same as C's. That means, results of using a union is only specified when it's used through one its members. Writing to one member and reading from another is unspecified. It is clear that endianness and padding should complicate matters. But it's still used in C in low level code. That must be because programs are not as portable as thought; and if they are, compile time checks and macro magic are possible to obtain expected behavior. Ali
Sep 19 2010
Ali Çehreli:I remember being a part of a discussion where D'is unions were told to be exactly the same as C's. That means, results of using a union is only specified when it's used through one its members. Writing to one member and reading from another is unspecified. It is clear that endianness and padding should complicate matters.
I have just written a post about this topic: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=117675 Bye and thank you, bearophile
Sep 20 2010
On Sun, 19 Sep 2010 20:07:38 -0400, bearophile <bearophileHUGS lycos.com> wrote:C standard say that's not safe. You can force that to be safe in
docs don't say anything about this. And Walter has said that regarding such things D acts as C. So I am not sure that will be safe in future D. Unions are not allowed in SafeD, so I guess they are considered unsafe in D.
Sep 19 2010
Juanjo Alvarez Wrote:Unions are not allowed in SafeD, so I guess they are considered unsafe in D.
They're safer in this particular case. Note how original poster forgot about taking and address.
Sep 20 2010
On Sunday 19 September 2010 18:19:25 Juanjo Alvarez wrote:On Sun, 19 Sep 2010 20:07:38 -0400, bearophile <bearophileHUGS lycos.com> wrote:C standard say that's not safe. You can force that to be safe in
C-GCC if you explicitly disable a compiler optimization. I think D docs don't say anything about this. And Walter has said that regarding such things D acts as C. So I am not sure that will be safe in future D. Unions are not allowed in SafeD, so I guess they are considered unsafe in D.
Well, it's not like reintepret_cast is the safest thing either. - Jonathan M Davis
Sep 19 2010
On Sunday 19 September 2010 17:07:38 bearophile wrote:orgoton baberek:Use a union, which is the correct and safe way.
C standard say that's not safe. You can force that to be safe in C-GCC if you explicitly disable a compiler optimization. I think D docs don't say anything about this. And Walter has said that regarding such things D acts as C. So I am not sure that will be safe in future D. Bye, bearophile
I'd have to go digging in old posts, but I'm pretty sure that that's essentially how you're supposed to do it in D. I haven't ever done it because I think that that sort of casting is pretty evil and only should be used as a last resort, but I believe that unions are the correct way to handle it in D. It's been discussed before, I'm fairly certain, though I think that the last place that I saw it was buried in a topic on a specific problem rather than anything necessarily particularly searchable in the archives. - Jonathan M Davis
Sep 19 2010
Bradley Mitchell <abstractant1 gmail.com> wrote:int xi = cast(int)cast(void*)x;
x = cast(float)cast(void*)xi;
The simple solution (seeing as how x is an lvalue) is int xi = *cast(int*)&x; [...] x = *cast(float*)ξ Function version: T reinterpret( T, U )( U value ) { return *cast( T* )&value; } There may be situations in which this will not work (though I know of none, OTOH), and where using a union will: T reinterpret( T, U )( U value ) { union Uni { U u; T t; } return Uni(value).t; } Of course, these are general solutions, and the easy solution to your problem is to use a union directly: float fastInvSqrt( float x ) { enum int INV_SQRT_N = 1597292357; enum float MULT = 1.000363245811462f; float mx = 0.5f * MULT * x; union Xu { float f; int i; } Xu xu = Xu(x); xu.i = INV_SQRT_N - (xu.i >> 1); return xu.f * (1.5f * MULT - mx * xu.f * xu.f); } -- Simen
Sep 19 2010
Yes, that did it exactly! Thank you, Simen, and Orgoton.
Sep 19 2010









bearophile <bearophileHUGS lycos.com> 