www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Compile time float binary representation

reply Jeremie Pelletier <jeremiep gmail.com> writes:
Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?

I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
"Error: 'R' is not of integral type, it is a real" is the error I get.

The usual *cast(uint*)&value wont work either at compile time.

Any suggestions?
Jul 31 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jeremie Pelletier wrote:
 Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?
 
 I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
 "Error: 'R' is not of integral type, it is a real" is the error I get.
 
 The usual *cast(uint*)&value wont work either at compile time.
 
 Any suggestions?

I got this to work, would it be applicable to your need? void main(string[] args) { union A { double x; int y; } enum A a = A(0.3); writeln(a.x); writeln(a.y); } Andrei
Jul 31 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Andrei Alexandrescu Wrote:

 Jeremie Pelletier wrote:
 Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?
 
 I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
 "Error: 'R' is not of integral type, it is a real" is the error I get.
 
 The usual *cast(uint*)&value wont work either at compile time.
 
 Any suggestions?

I got this to work, would it be applicable to your need? void main(string[] args) { union A { double x; int y; } enum A a = A(0.3); writeln(a.x); writeln(a.y); } Andrei

Good suggestion, however it doesnt work the way I need it: --- template FloatParts(real R) { union A { real theReal; struct { ushort hi; ulong lo; } } A a = cast(A)R; // Error: cannot cast real to immutable(A) enum A a = A(R); // members cannot be used at runtime } --- I need to gather .sign, .exp and .mantissa among others (possibly a .radix too) and use them at compile time (generic metaprogramming, or else i would just fallback to runtime). Unless there are arithmetic methods to get these, I dont see how it can be done without changes in the compiler first. To Walter: is this something possible for DMD2.32?
Jul 31 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Jeremie Pelletier Wrote:

 Andrei Alexandrescu Wrote:
 
 Jeremie Pelletier wrote:
 Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?
 
 I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
 "Error: 'R' is not of integral type, it is a real" is the error I get.
 
 The usual *cast(uint*)&value wont work either at compile time.
 
 Any suggestions?

I got this to work, would it be applicable to your need? void main(string[] args) { union A { double x; int y; } enum A a = A(0.3); writeln(a.x); writeln(a.y); } Andrei

Good suggestion, however it doesnt work the way I need it: --- template FloatParts(real R) { union A { real theReal; struct { ushort hi; ulong lo; } } A a = cast(A)R; // Error: cannot cast real to immutable(A) enum A a = A(R); // members cannot be used at runtime } --- I need to gather .sign, .exp and .mantissa among others (possibly a .radix too) and use them at compile time (generic metaprogramming, or else i would just fallback to runtime). Unless there are arithmetic methods to get these, I dont see how it can be done without changes in the compiler first. To Walter: is this something possible for DMD2.32?

After some toying around, I managed to get some results: --- import std.metastrings; immutable union A { double x; int y; } pragma(msg, ToString!(A(5.2).y)); --- but it crashed dmd (2.031) instead of printing 3435973837 to stdout.
Jul 31 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jeremie Pelletier wrote:
 Jeremie Pelletier Wrote:
 
 Andrei Alexandrescu Wrote:

 Jeremie Pelletier wrote:
 Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?

 I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
 "Error: 'R' is not of integral type, it is a real" is the error I get.

 The usual *cast(uint*)&value wont work either at compile time.

 Any suggestions?

void main(string[] args) { union A { double x; int y; } enum A a = A(0.3); writeln(a.x); writeln(a.y); } Andrei

--- template FloatParts(real R) { union A { real theReal; struct { ushort hi; ulong lo; } } A a = cast(A)R; // Error: cannot cast real to immutable(A) enum A a = A(R); // members cannot be used at runtime } --- I need to gather .sign, .exp and .mantissa among others (possibly a .radix too) and use them at compile time (generic metaprogramming, or else i would just fallback to runtime). Unless there are arithmetic methods to get these, I dont see how it can be done without changes in the compiler first. To Walter: is this something possible for DMD2.32?

After some toying around, I managed to get some results: --- import std.metastrings; immutable union A { double x; int y; } pragma(msg, ToString!(A(5.2).y)); --- but it crashed dmd (2.031) instead of printing 3435973837 to stdout.

Yah, I crashed it a couple of times with similar code now too. Could you please do the bugzilla honors. (Also you may want to check std.numeric.CustomFloat. It doesn't help with this particular problem, but it allows defining floating point types with specific mantissa and exponent sizes.) Andrei
Jul 31 2009
parent Jeremie Pelletier <jeremiep gmail.com> writes:
Andrei Alexandrescu Wrote:

 Jeremie Pelletier wrote:
 Jeremie Pelletier Wrote:
 
 Andrei Alexandrescu Wrote:

 Jeremie Pelletier wrote:
 Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?

 I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
 "Error: 'R' is not of integral type, it is a real" is the error I get.

 The usual *cast(uint*)&value wont work either at compile time.

 Any suggestions?

void main(string[] args) { union A { double x; int y; } enum A a = A(0.3); writeln(a.x); writeln(a.y); } Andrei

--- template FloatParts(real R) { union A { real theReal; struct { ushort hi; ulong lo; } } A a = cast(A)R; // Error: cannot cast real to immutable(A) enum A a = A(R); // members cannot be used at runtime } --- I need to gather .sign, .exp and .mantissa among others (possibly a .radix too) and use them at compile time (generic metaprogramming, or else i would just fallback to runtime). Unless there are arithmetic methods to get these, I dont see how it can be done without changes in the compiler first. To Walter: is this something possible for DMD2.32?

After some toying around, I managed to get some results: --- import std.metastrings; immutable union A { double x; int y; } pragma(msg, ToString!(A(5.2).y)); --- but it crashed dmd (2.031) instead of printing 3435973837 to stdout.

Yah, I crashed it a couple of times with similar code now too. Could you please do the bugzilla honors. (Also you may want to check std.numeric.CustomFloat. It doesn't help with this particular problem, but it allows defining floating point types with specific mantissa and exponent sizes.) Andrei

Thanks again for the quick reply Andrei, however, as useful as the CustomFloat template may be, I need a reverse algorithm usable entirely at compile time. If you know a way to extract this information without resorting to bitwise logic, please let me know, for the moment I'm adding a static assert(0) to my template until dmd supports compile time binary casts. Also I created http://d.puremagic.com/issues/show_bug.cgi?id=3220.
Jul 31 2009
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Jeremie Pelletier wrote:
 Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?
 
 I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
 "Error: 'R' is not of integral type, it is a real" is the error I get.
 
 The usual *cast(uint*)&value wont work either at compile time.
 
 Any suggestions?

There's currently no way to do that.
Jul 31 2009
prev sibling parent Don <nospam nospam.com> writes:
Jeremie Pelletier wrote:
 Is there a way to convert a float (or double/real) to an integral number
without changing its binary representation at compile time?
 
 I need to extract the sign, exponent and mantissa yet I cant use bit shifting.
 "Error: 'R' is not of integral type, it is a real" is the error I get.

and parse the .mangleof it! Not recommended, but it does work. The other way is to do it with CTFE, subtracting powers of 2 until the residual is < 1. Not great either.
 
 The usual *cast(uint*)&value wont work either at compile time.
 
 Any suggestions?

Aug 01 2009