fast fractional part of floating point number - modf?

Is there a fast and reliable way to compute the fraction of a floating point number? I can implement fraction x = snd (properFraction x :: (Int, Double)) or fraction x = x - fromIntegral (truncate x :: Int) (actually I need 'floor' not 'truncate' but this is another issue) but these need considerably more time than fraction x = x - GHC.Float.int2Double (GHC.Float.double2Int x) Is there a fast 'fraction' built-in function? Or do I have to use FFI to modf ?

On Sun, Jan 13, 2008 at 01:08:49AM +0100, Henning Thielemann wrote:
Is there a fast and reliable way to compute the fraction of a floating point number?
no, and this has bothered me to the point I consider it a bug in the language spec that all 'rounding' style functions give back an integral type. These sort of operations are often used on floating point values when you want the same type out you put in, and in particular you want it to handle things like infinities and nan's properly which the conversion through integral does not (plus, these usually coorespond to a single machine instruction so are more 'primitive' in a sense and thus better building blocks for a RealFrac class). To alleviate this I added the following to the RealFrac class in jhc -- TODO Doubles class (Real a, Fractional a) => RealFrac a where .... ... -- new stuff added by jhc properFractionf :: a -> (a,a) truncatef, roundf :: a -> a ceilingf, floorf :: a -> a truncatef x = m where (m,_) = properFractionf x roundf x = fromInteger (round x) ceilingf x = if r > 0 then n + 1 else n where (n,r) = properFractionf x floorf x = if r < 0 then n - 1 else n where (n,r) = properFractionf x the meaning should be clear, they perform the same operation as their non f counterparts but maintain the same type. John -- John Meacham - ⑆repetae.net⑆john⑈

On Mon, 14 Jan 2008, John Meacham wrote:
On Sun, Jan 13, 2008 at 01:08:49AM +0100, Henning Thielemann wrote:
Is there a fast and reliable way to compute the fraction of a floating point number?
no, and this has bothered me to the point I consider it a bug in the language spec that all 'rounding' style functions give back an integral type.
I find returning an Integral is appropriate. The type expresses perfectly what kind of values you can expect. Sure, there should be some optimization rule like fromInteger (round x) = roundf x . However, the 'fraction' function gets a fraction and returns a fraction and doesn't care about the type of the integer part. As I see this is also missing from your RealFrac class extension.

On Tue, Jan 15, 2008 at 07:40:03AM +0100, Henning Thielemann wrote:
On Mon, 14 Jan 2008, John Meacham wrote:
On Sun, Jan 13, 2008 at 01:08:49AM +0100, Henning Thielemann wrote:
Is there a fast and reliable way to compute the fraction of a floating point number?
no, and this has bothered me to the point I consider it a bug in the language spec that all 'rounding' style functions give back an integral type.
I find returning an Integral is appropriate. The type expresses perfectly what kind of values you can expect. Sure, there should be some optimization rule like fromInteger (round x) = roundf x .
it is not that it isn't appropriate, it is that is isn't that useful nor is it equivalent. roundf NaN -> NaN fromInteger $ round NaN -> error roundf -0 -> -0 fromInteger $ round -0 -> 0 and how about fromInteger $ ceil (the highest represpentable number in a Double) you go from a 64 bit primitive value to one that takes up a substantial amount of memory when expressed as an Integer and back again. All of these tricky corner cases have been thought out by the IEEE. more importantly, all these things have well defined meanings in IEEE floating point specfications and they cannot be followed in haskell due to the integral constraint. Floating point numbers are odd beasts, we must be careful with them. John -- John Meacham - ⑆repetae.net⑆john⑈
participants (2)
-
Henning Thielemann
-
John Meacham