unsafeCoerce# between integral and floating point types

The docs for unsafeCoerce# say: "The following uses of unsafeCoerce# are supposed to work (i.e. not lead to spurious compile-time or run-time crashes): # Casting any lifted type to Any # Casting Any back to the real type # Casting an unboxed type to another unboxed type of the same size (but not coercions between floating-point and integral types) ..." My experience so far is consistent with the assumption that e.g. unsafeCoerce# :: Word64 -> Double is like a cast from (uint64_t *) to (double *), i.e. a bit-pattern- preserving transformation (although by the docs, that use is undefined). Would that assumption generally hold for unsafeCoerce :: a -> b where a and b are single constructor data types wrapping unboxed types of the same bit-size and hence the use of unsafeCoerce# between such types would produce reliable results *on the same machine with the same OS (and GHC version?)* ? And what about e.g. unsafeCoerce# :: Word64# -> Double# ? By the docs, that isn't supposed to work. Is it not supposed to work only because it's not value-preserving (unsafeCoerce# 1## /=## 1.0##) or are there more pitfalls? If there are more pitfalls, is there any chance of getting a function which reinterprets the bit-patterns? Thanks, Daniel

On Thu, Jul 08, 2010 at 04:49:00PM +0200, Daniel Fischer wrote:
unsafeCoerce# :: Word64# -> Double# ?
By the docs, that isn't supposed to work. Is it not supposed to work only because it's not value-preserving (unsafeCoerce# 1## /=## 1.0##) or are there more pitfalls?
It can fail to compile, even; see http://hackage.haskell.org/trac/ghc/ticket/2209
If there are more pitfalls, is there any chance of getting a function which reinterprets the bit-patterns?
There's a feature request for that here: http://hackage.haskell.org/trac/ghc/ticket/4092 Thanks Ian

On Thursday 08 July 2010 18:15:44, Ian Lynagh wrote:
On Thu, Jul 08, 2010 at 04:49:00PM +0200, Daniel Fischer wrote:
unsafeCoerce# :: Word64# -> Double# ?
By the docs, that isn't supposed to work. Is it not supposed to work only because it's not value-preserving (unsafeCoerce# 1## /=## 1.0##) or are there more pitfalls?
It can fail to compile, even; see http://hackage.haskell.org/trac/ghc/ticket/2209
Yeah, tried that myself, with optimisations: [2 of 2] Compiling Main ( testUCastD.hs, testUCastD.o ) ghc: panic! (the 'impossible' happened) (GHC version 6.12.3 for i386-unknown-linux): getRegister(x86) I64[R1 + 3] Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug But without optimisations, it compiles and seems to work (I won't rely on that, was just curious). Should I report it or is the panic okay since unsafeCoerce# isn't supposed to work for those types?

On 08/07/2010 17:56, Daniel Fischer wrote:
On Thursday 08 July 2010 18:15:44, Ian Lynagh wrote:
On Thu, Jul 08, 2010 at 04:49:00PM +0200, Daniel Fischer wrote:
unsafeCoerce# :: Word64# -> Double# ?
By the docs, that isn't supposed to work. Is it not supposed to work only because it's not value-preserving (unsafeCoerce# 1## /=## 1.0##) or are there more pitfalls?
It can fail to compile, even; see http://hackage.haskell.org/trac/ghc/ticket/2209
Yeah, tried that myself, with optimisations:
[2 of 2] Compiling Main ( testUCastD.hs, testUCastD.o ) ghc: panic! (the 'impossible' happened) (GHC version 6.12.3 for i386-unknown-linux): getRegister(x86) I64[R1 + 3]
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
But without optimisations, it compiles and seems to work (I won't rely on that, was just curious).
Should I report it or is the panic okay since unsafeCoerce# isn't supposed to work for those types?
The panic is to be expected. Basically this use of unsafeCoerce# can break some assumptions in the code generator, so it gets into a state where it was expecting an integer and it finds a float. I think -dcmm-lint will catch it. It's fixable; we have to add some explicit coercions, and extend the code generator to handle them. Cheers, Simon

On Thu, Jul 08, 2010 at 04:49:00PM +0200, Daniel Fischer wrote:
If there are more pitfalls, is there any chance of getting a function which reinterprets the bit-patterns?
Hi, you can do something like this (untested): castWordToFloat :: Word32 -> Float castWordToFloat w = unsafePerformIO $ do alloca w $ \pw -> do peek (castPtr pw) John -- John Meacham - ⑆repetae.net⑆john⑈ - http://notanumber.net/
participants (4)
-
Daniel Fischer
-
Ian Lynagh
-
John Meacham
-
Simon Marlow