Yay!!!<div><br></div><div>I made a small change in Types.chs and got my original cairo-binding-based program to be just as blazing fast. The only problem I have with this is that I used multiparameter type classes.</div><div>
<br></div><div>Dear gtk2hs team! Is it possible to incorporate my changes? I&#39;m pretty sure people will be happy by an order-of-magnitude speedup. Probably the stuff could be wrapped in #define&#39;s for those who aren&#39;t using GHC and can&#39;t use multiparameter type classes?</div>
<div><br></div><div>I am pretty sure I could have done the same with rewrite rules, but I tried for a while and to no avail.</div><div><br></div><div>FAILED SOLUTION: rewrite rules</div><div><div>cFloatConv :: (RealFloat a, RealFloat b) =&gt; a -&gt; b</div>
<div>cFloatConv  = realToFrac</div><div>{-# NOINLINE cFloatConv #-}</div><div>{-# RULES &quot;cFloatConv/float2Double&quot; cFloatConv = float2Double #-}</div><div>{-# RULES &quot;cFloatConv/double2Float&quot; cFloatConv = double2Float #-}</div>
<div>{-# RULES &quot;cFloatConv/self&quot;         cFloatConv = id           #-}</div></div><div><br></div><div>For some reason, the rules don&#39;t fire. Anyone got an idea why?</div><div><br></div><div>SUCCEEDED SOLUTION: multiparameter type classes</div>
<div><br></div><div>I rewrote cFloatConv like this:</div><div><br></div><div><div>import GHC.Float</div><div>class (RealFloat a, RealFloat b) =&gt; CFloatConv a b where</div><div>  cFloatConv :: a -&gt; b</div><div>  cFloatConv = realToFrac</div>
<div><br></div><div>instance CFloatConv Double Double where cFloatConv = id</div><div>instance CFloatConv Double CDouble</div><div>instance CFloatConv CDouble Double</div><div>instance CFloatConv Float Float where cFloatConv = id</div>
<div>instance CFloatConv Float Double where cFloatConv = float2Double</div><div>instance CFloatConv Double Float where cFloatConv = double2Float</div></div><div><br></div><div>and replaced a couple of constraints in functions below by usage of CFloatConv.</div>
<div><br></div><div><br><div class="gmail_quote">On Wed, Nov 2, 2011 at 2:25 PM, Felipe Almeida Lessa <span dir="ltr">&lt;<a href="mailto:felipe.lessa@gmail.com">felipe.lessa@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+gtk2hs-devel<br>
<div class="HOEnZb"><div class="h5"><br>
On Wed, Nov 2, 2011 at 8:15 AM, Eugene Kirpichov &lt;<a href="mailto:ekirpichov@gmail.com">ekirpichov@gmail.com</a>&gt; wrote:<br>
&gt; Any idea how to debug why all the GMP calls?<br>
&gt; I&#39;m looking at even the auto-generated source for cairo bindings, but I<br>
&gt; don&#39;t see anything at all that could lead to *thousands* of them.<br>
<br>
Found them.  Look at the Types module and you&#39;ll see<br>
<br>
 cFloatConv :: (RealFloat a, RealFloat b) =&gt; a -&gt; b<br>
 cFloatConv  = realToFrac<br>
<br>
This function (or its cousins peekFloatConv, withFloatConv...) are<br>
used *everywhere*.<br>
<br>
Looking at this module with ghc-core we see that GHC compiled a<br>
generic version of cFloatConv:<br>
<br>
Graphics.Rendering.Cairo.Types.$wcFloatConv<br>
 :: forall a_a3TN b_a3TO.<br>
    (RealFloat a_a3TN, RealFrac b_a3TO) =&gt;<br>
    a_a3TN -&gt; b_a3TO<br>
[GblId,<br>
 Arity=3,<br>
<br>
 Unf=Unf{Src=&lt;vanilla&gt;, TopLvl=True, Arity=3, Value=True,<br>
        ConLike=True, Cheap=True, Expandable=True,<br>
        Guidance=IF_ARGS [3 3 0] 12 0}]<br>
Graphics.Rendering.Cairo.Types.$wcFloatConv =<br>
 \ (@ a_a3TN)<br>
   (@ b_a3TO)<br>
   (w_s5zg :: RealFloat a_a3TN)<br>
   (ww_s5zj :: RealFrac b_a3TO)<br>
   (w1_s5zA :: a_a3TN) -&gt;<br>
   fromRational<br>
     @ b_a3TO<br>
     ($p2RealFrac @ b_a3TO ww_s5zj)<br>
     (toRational<br>
        @ a_a3TN<br>
        ($p1RealFrac<br>
           @ a_a3TN ($p1RealFloat @ a_a3TN w_s5zg))<br>
        w1_s5zA)<br>
<br>
Note that this is basically cFloatConv = fromRational . toRational.<br>
<br>
*However*, GHC also compiled a Double -&gt; Double specialization:<br>
<br>
Graphics.Rendering.Cairo.Types.cFloatConv1<br>
 :: Double -&gt; Double<br>
[GblId,<br>
 Arity=1,<br>
<br>
 Unf=Unf{Src=InlineStable, TopLvl=True, Arity=1, Value=True,<br>
        ConLike=True, Cheap=True, Expandable=True,<br>
        Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=False)<br>
        Tmpl= \ (eta_B1 [Occ=Once!] :: Double) -&gt;<br>
                case eta_B1 of _ { D# ww_a5v3 [Occ=Once] -&gt;<br>
                case $w$ctoRational ww_a5v3<br>
                of _ { (# ww2_a5v8 [Occ=Once], ww3_a5v9 [Occ=Once] #) -&gt;<br>
                $wfromRat ww2_a5v8 ww3_a5v9<br>
                }<br>
                }}]<br>
Graphics.Rendering.Cairo.Types.cFloatConv1 =<br>
 \ (eta_B1 :: Double) -&gt;<br>
   case eta_B1 of _ { D# ww_a5v3 -&gt;<br>
   case $w$ctoRational ww_a5v3<br>
   of _ { (# ww2_a5v8, ww3_a5v9 #) -&gt;<br>
   $wfromRat ww2_a5v8 ww3_a5v9<br>
   }<br>
   }<br>
<br>
...which is also equivalent to fromRational . toRational however with<br>
the type class inlined!  Oh, god...<br>
<br>
Cheers,<br>
<br>
--<br>
Felipe.<br>
<br>
</div></div><div class="HOEnZb"><div class="h5">_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>Eugene Kirpichov<br>Principal Engineer, Mirantis Inc. <a href="http://www.mirantis.com/" target="_blank">http://www.mirantis.com/</a><br>Editor, <a href="http://fprog.ru/" target="_blank">http://fprog.ru/</a><br>

</div>