id,summary,reporter,owner,description,type,status,priority,milestone,component,version,resolution,keywords,cc,os,architecture,failure,testcase,blockedby,blocking,related,differential,wikipage
2251,Missing conversion rules for realToFrac causing slowdowns in Int->Double conversions,dons,dons,"GHC.Real and GHC.Float currently have:
{{{
-- | general coercion from integral types
fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral = fromInteger . toInteger
{-# RULES
""fromIntegral/Int->Int"" fromIntegral = id :: Int -> Int
#-}
-- | general coercion to fractional types
realToFrac :: (Real a, Fractional b) => a -> b
realToFrac = fromRational . toRational
{-# RULES
""realToFrac/Int->Int"" realToFrac = id :: Int -> Int
#-}
}}}
But these avoid some primops that can make these conversions
more efficient.
{{{
{-# RULES
""realToFrac/Int->Double"" realToFrac = i2d :: Int -> Double
#-}
int2Double :: Int -> Double
int2Double (I# x) = D# (int2Double# x)
}}}
A rule to use the in2Double# primop over realToFrac directly, improves
the running time of this program:
{{{
import Data.Array.Parallel.Unlifted
main = do
let c = replicateU n (2::Double)
a = mapU realToFrac (enumFromToU 0 (n-1) ) :: UArr Double
print (sumU (zipWithU (*) c a))
}}}
From 113 seconds, to 0.194s! A massive speedup.
We should fill out the rules here with at least those for which GHC
has primitives:
{{{
{-# RULES
""realToFrac/Int->Double"" realToFrac = int2Double :: Int -> Double
""realToFrac/Int->Float"" realToFrac = int2Float :: Int -> Float
#-}
}}}
to the realToFrac and fromIntegral rules in GHC.Float",bug,closed,normal,,Runtime System,6.8.2,fixed,"floating point, performance",dons@…,Unknown/Multiple,Unknown/Multiple,,,,,,,