digitalmars.D.learn - D equivalent of C++ reinterpret cast?
- Bradley Mitchell (50/50) Sep 19 2010 Hello,
- orgoton baberek (10/60) Sep 19 2010 Use a union, which is the correct and safe way.
- bearophile (4/5) Sep 19 2010 C standard say that's not safe. You can force that to be safe in C-GCC i...
- Jonathan M Davis (9/19) Sep 19 2010 I'd have to go digging in old posts, but I'm pretty sure that that's ess...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/29) Sep 19 2010 D acts
- bearophile (5/10) Sep 20 2010 I have just written a post about this topic:
- Juanjo Alvarez (8/9) Sep 19 2010 C-GCC if you explicitly disable a compiler optimization. I think D
- Jonathan M Davis (3/15) Sep 19 2010 Well, it's not like reintepret_cast is the safest thing either.
- Kagamin (2/4) Sep 20 2010 They're safer in this particular case. Note how original poster forgot a...
- Simen kjaeraas (35/37) Sep 19 2010 The simple solution (seeing as how x is an lvalue) is
- Bradley Mitchell (2/2) Sep 19 2010 Yes, that did it exactly!
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, BradUse 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
On Sunday 19 September 2010 17:07:38 bearophile wrote:orgoton baberek: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 DavisUse 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:C-GCC iforgoton 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 inD actsyou explicitly disable a compiler optimization. I think D docs don't say anything about this. And Walter has said that regarding such thingsessentiallyas C. So I am not sure that will be safe in future D. Bye, bearophileI'd have to go digging in old posts, but I'm pretty sure that that'show you're supposed to do it in D. I haven't ever done it because Ithink thatthat sort of casting is pretty evil and only should be used as a lastresort,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 inC-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.
Sep 19 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:Well, it's not like reintepret_cast is the safest thing either. - Jonathan M DavisC standard say that's not safe. You can force that to be safe inC-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.
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
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