There are currently two ways to compute the ulp of double numbers with GHC :
Calling a C function, which requires to allocate a pointer. This is way too expensive when using interval arithmetic (for instance), that compute two ULPs at each arithmetic operations.
Programming it by hand in haskell with GHC primitive operations, which requires using unsafeCoerce# : this does not work in GHC 6.12.2.
unsafeCoerce# should work, and there should be a primitive ulp# function in GHC, operating on Doubles at least.
By the way, here is my haskell code using C for computing it :
By the way, you can do this without the FFI right now, by poking the Double into memory, and then peeking it out as a Word64. Not terribly efficient, but better than using the FFI.
partial patch for this attached. I ran into difficulty because there's no way to allocate temporary memory for the conversion in the native code generator. There are various ways to hack around this (use a spare slot in StgReg, allocate a new word in the data segment) but none are very nice. We really just want to allocate a slot from the spill area, but that requires cooperation from the register allocator.
Wait, unsafecoerce# doesn't work here? Oh, is this because we (in general) need to move things between the registers used for floating point vs word values
In the meantime, in the absence of primops, this is the best I can manage. I suggest we add this or similar to GHC.Float:
{-# INLINE castWord2Float #-}castWord2Float :: Word32 -> FloatcastWord2Float (W32# w#) = F# (castWord2Float# w#){-# NOINLINE castWord2Float# #-}castWord2Float# :: Word# -> Float#castWord2Float# w# = case newByteArray# 4# realWorld# of (# s', mba# #) -> case writeWord32Array# mba# 0# w# s' of s'' -> case readFloatArray# mba# 0# s'' of (# _, f# #) -> f#{-# INLINE castWord2Double #-}castWord2Double :: Word64 -> DoublecastWord2Double (W64# w#) = D# (castWord2Double# w#){-# NOINLINE castWord2Double# #-}castWord2Double# :: Word# -> Double#castWord2Double# w# = case newByteArray# 8# realWorld# of (# s', mba# #) -> case writeWord64Array# mba# 0# w# s' of s'' -> case readDoubleArray# mba# 0# s'' of (# _, f# #) -> f#
This is similar to the "cast STUArray" method, but avoids the extra call and closure allocation due to the runSTRep. For the "cast STUArray" method, see:
commit aa206346e6f12c9f88fdf051185741761ea88fbbAuthor: Erik de Castro Lopo <erikd@mega-nerd.com>Date: Wed Apr 12 14:09:49 2017 -0400 base: Implement bit casts between word and float types Test Plan: Test on x86 and x86_64 Reviewers: duncan, trofi, simonmar, tibbe, hvr, austin, rwbarton, bgamari Reviewed By: duncan Subscribers: Phyx, DemiMarie, rwbarton, thomie Differential Revision: https://phabricator.haskell.org/D3358
Unfortunately too late for the ghc-8.2 release, but it will make the ghc-8.4 release.