[GHC] #2271: floor, ceiling, round :: Double -> Int are awesomely slow

GHC trac at galois.com
Wed May 7 20:28:53 EDT 2008


#2271: floor, ceiling, round :: Double -> Int are awesomely slow
------------------------------------------+---------------------------------
    Reporter:  dons                       |       Owner:  dons at galois.com
        Type:  bug                        |      Status:  new            
    Priority:  normal                     |   Component:  Compiler       
     Version:  6.8.2                      |    Severity:  normal         
    Keywords:  performance, math, double  |    Testcase:                 
Architecture:  Unknown                    |          Os:  Unknown        
------------------------------------------+---------------------------------
 We have super-naive implementations of the RealFrac class for Double.

 Consider:

 {{{

 {-# RULES "truncate/Double->Int" truncate = double2Int #-}
 instance  RealFrac Double  where

     properFraction x
       = case (decodeFloat x)      of { (m,n) ->
         let  b = floatRadix x     in
         if n >= 0 then
             (fromInteger m * fromInteger b ^ n, 0.0)
         else
             case (quotRem m (b^(negate n))) of { (w,r) ->
             (fromInteger w, encodeFloat r n)
             }
         }

     floor x     = case properFraction x of
                     (n,r) -> if r < 0.0 then n - 1 else n

 }}}

 So now, we *do* have a good rule for truncate, but floor, ceiling and
 round turn
 out to be awesomely slow.

 {{{
 main = print . sumU
              . mapU (floor :: Double -> Int)
              $ enumFromToFracU 0 100000000

 }}}

 Runs in 1 minute, 10 seconds:

 {{{
 $ time ./henning
 5000000050000000
 ./henning  70.25s user 0.17s system 99% cpu 1:10.99 total
 }}}

 Now, if we just replace that with a ccall to math.h:floor, we get:

 {{{

 main = print . sumU
              . mapU (floor' :: Double -> Int)
              $ enumFromToFracU 0 100000000

 floor' :: Double -> Int
 floor' x = (truncate :: Double -> Int) (c_floor x)
 {-# INLINE floor' #-}

 foreign import ccall unsafe "math.h floor"
     c_floor :: Double -> Double

 }}}

 Which runs in 1.8 seconds:

 {{{

 $ time ./henning
 5000000050000000
 ./henning  1.88s user 0.00s system 99% cpu 1.884 total

 }}}

 Similar results for ceiling and round (see the main ticket for RealFrac,
 http://hackage.haskell.org/trac/ghc/ticket/1434)

 == Action ==

 Use math.h versions of round, floor and ceiling for Double and Float?

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2271>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the Glasgow-haskell-bugs mailing list