Make (^) INLINE
The current definition of GHC.Real.(^)
(and (^^)
) is lazy in the base (as specified in Haskell2010):
(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0 = errorWithoutStackTrace "Negative exponent"
| y0 == 0 = 1
| otherwise = f x0 y0
where -- f : x0 ^ y0 = x ^ y
f x y | even y = f (x * x) (y `quot` 2)
| y == 1 = x
| otherwise = g (x * x) (y `quot` 2) x -- See Note [Half of y - 1]
-- g : x0 ^ y0 = (x ^ y) * z
g x y z | even y = g (x * x) (y `quot` 2) z
| y == 1 = x * z
| otherwise = g (x * x) (y `quot` 2) (x * z) -- See Note [Half of y - 1]
That leads to the serious downside that the specialisation of (^)
for, e.g., Complex Double
will not unbox the argument. Thus we rely on it being inlined at all call sites, so that boxed Complex Double
passed as x0
can cancel away.
By contrast, f
and g
are strict in x
, it would be good to INLINE (^)
but move f
and g
to the top-level and mark them as INLINABLE (so that they can be specialised).