Boost C++ Libraries: Ticket #3408: gamma distribution's quantile performance https://svn.boost.org/trac10/ticket/3408 <p> Hi there, I have created a test which times the performance of boost::math::quantile( ... ) when using a gamma distribution. I ran it against source code we use here at work, for ages. It can be found here: </p> <p> <a class="ext-link" href="http://people.sc.fsu.edu/~burkardt/cpp_src/dcdflib/dcdflib.html"><span class="icon">​</span>http://people.sc.fsu.edu/~burkardt/cpp_src/dcdflib/dcdflib.html</a> </p> <p> The old source code is about 2x times faster than the boost version. </p> <p> MS Visual Studio 2005: boost: 35.4sec att_bell:19sec </p> <p> Intel 11.1: boost: 21.4sec att_bell: 11.2sec </p> <p> Question is if there is a way to incorporate such a function into boost::math? As far, as I can tell the results are almost identical. </p> <p> Here the code: </p> <p> #include &lt;dcdflib.h&gt; </p> <p> #include &lt;boost/math/distributions/gamma.hpp&gt; </p> <p> #include &lt;boost/timer.hpp&gt; </p> <p> double min_mean = 2000; <em> 2,000 double max_mean = 500000000; </em>500,000,000 </p> <p> double min_std = 10000; <em> 10,000 double max_std = 100000000; </em> 100,000,000 </p> <p> double min_max = 600000000; <em> 600,000,000 double max_max = 1000000000; </em> 1,000,000,000 </p> <p> const std::size_t max_year = 5000000; <em> 5,000,000 </em></p> <p> const double right = 0.999; const double left = 0.001; </p> <p> inline double get_rand() { </p> <blockquote> <p> return static_cast&lt; double &gt;( std::rand() ) </p> <blockquote> <p> / static_cast&lt; double &gt;( RAND_MAX ); </p> </blockquote> </blockquote> <p> } </p> <p> inline void boost_( boost::math::gamma_distribution&lt;&gt;&amp; d, double q ) { </p> <blockquote> <p> double value = boost::math::quantile( d, q ); </p> </blockquote> <p> } </p> <p> inline void att_bell( double alpha, double beta, double q ) { </p> <blockquote> <p> double q_Minus1 = 1 - q; double value = 0.0; double bound = 0.0; </p> </blockquote> <blockquote> <p> int which = 2; int status = 0; </p> </blockquote> <blockquote> <p> cdfgam( &amp;which </p> <blockquote> <p> , &amp;q , &amp;q_Minus1 , &amp;value , &amp;alpha , &amp;beta , &amp;status , &amp;bound ); </p> </blockquote> </blockquote> <p> } </p> <p> int main() { </p> <blockquote> <p> <em> boost { </em></p> <blockquote> <p> std::srand( 0 ); </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> boost::timer timer; for( std::size_t y = 0; y &lt; max_year; ++y ) { </p> <blockquote> <p> if(( y % 100000 ) == 0 ) </p> <blockquote> <p> std::cout &lt;&lt; y &lt;&lt; std::endl; </p> </blockquote> </blockquote> </blockquote> </blockquote> <blockquote> <blockquote> <blockquote> <p> double mean = get_rand() * ( max_mean - min_mean ) + min_mean; double std = get_rand() * ( max_std - min_std ) + min_std; </p> </blockquote> </blockquote> </blockquote> <blockquote> <blockquote> <blockquote> <p> double alpha = mean * mean / std / std; <em> shape parameter double beta = mean / alpha; </em> scale parameter </p> </blockquote> </blockquote> </blockquote> <blockquote> <blockquote> <blockquote> <p> boost::math::gamma_distribution&lt;&gt; d( alpha, beta ); boost_( d, right ); boost_( d, left ); </p> </blockquote> <p> } </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> std::cout &lt;&lt; "Boost - Time elapsed: " &lt;&lt; timer.elapsed() &lt;&lt; " </p> </blockquote> </blockquote> <p> sec" &lt;&lt; std::endl; </p> <blockquote> <p> } </p> </blockquote> <blockquote> <p> <em> att bell { </em></p> <blockquote> <p> std::srand( 0 ); </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> boost::timer timer; for( std::size_t y = 0; y &lt; max_year; ++y ) { </p> <blockquote> <p> if(( y % 100000 ) == 0 ) </p> <blockquote> <p> std::cout &lt;&lt; y &lt;&lt; std::endl; </p> </blockquote> </blockquote> </blockquote> </blockquote> <blockquote> <blockquote> <blockquote> <p> double mean = get_rand() * ( max_mean - min_mean ) + min_mean; double std = get_rand() * ( max_std - min_std ) + min_std; </p> </blockquote> </blockquote> </blockquote> <blockquote> <blockquote> <blockquote> <p> double alpha = mean * mean / std / std; <em> shape parameter double beta = mean / alpha; </em> scale parameter </p> </blockquote> </blockquote> </blockquote> <blockquote> <blockquote> <blockquote> <p> att_bell( alpha, beta, right ); att_bell( alpha, beta, left ); </p> </blockquote> <p> } </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> std::cout &lt;&lt; "ATT Bell - Time elapsed: " &lt;&lt; timer.elapsed() &lt;&lt; </p> </blockquote> </blockquote> <p> " sec" &lt;&lt; std::endl; </p> <blockquote> <p> } </p> </blockquote> <blockquote> <p> return 0; </p> </blockquote> <p> } </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3408 Trac 1.4.3 Steven Watanabe Sun, 06 Sep 2009 22:48:47 GMT <link>https://svn.boost.org/trac10/ticket/3408#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:1</guid> <description> <p> This doesn't seem to affect the timings for me, but you're not computing the same thing with Boost that you are with dcdflib in this test case, since boost::math::gamma_distribution takes a parameter 1/beta instead of beta. </p> </description> <category>Ticket</category> </item> <item> <author>chhenning@…</author> <pubDate>Wed, 09 Sep 2009 18:47:22 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:2</guid> <description> <p> Steven, are you saying both test running at the same speed on your machine? </p> <p> Also, I'm not sure about the 1/beta parameter. My code results in the same values when using boost and ATT Bell. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Wed, 09 Sep 2009 18:59:22 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:3</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3408#comment:2" title="Comment 2">chhenning@…</a>: </p> <blockquote class="citation"> <p> Steven, are you saying both test running at the same speed on your machine? </p> </blockquote> <p> Actually Boost.Math is about 4 times slower on my machine with msvc 9.0. I was just saying that usign 1/beta vs. beta didn't affect the timings. </p> <blockquote class="citation"> <p> Also, I'm not sure about the 1/beta parameter. My code results in the same values when using boost and ATT Bell. </p> </blockquote> <p> I'll check again. All I did was to change att_bell and boost_ to return value and compare the results for the same arguments. They were totally different until I switched boost_ to 1/beta. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Fri, 18 Sep 2009 12:04:07 GMT</pubDate> <title>status changed https://svn.boost.org/trac10/ticket/3408#comment:4 https://svn.boost.org/trac10/ticket/3408#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> <p> Thanks for reminding me about this, I'm back now (sort of anyway!) so I'll try and investigate soon. Your test showed about a 2x difference on my machine BTW. </p> <p> As for integrating the dcd lib code into Boost... there would likely be licence issues preventing that... in any case the two libraries implement *the same algorithm* so it's a question of trying to track down why they're showing a difference. </p> <p> John. </p> Ticket John Maddock Thu, 24 Sep 2009 11:53:10 GMT <link>https://svn.boost.org/trac10/ticket/3408#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:5</guid> <description> <p> I thought I'd add a short update: I'm concentrating on the igamma and it's inverse functions at this stage, as ultimately these are what the stats functions of both libraries depend upon. </p> <p> Accuracy wise the two libries are broadly similar: </p> <p> Tests run with Microsoft Visual C++ version 9.0, Dinkumware standard library version 505, Win32 Testing tgamma(a, z) medium values with type double <del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del> boost::math::gamma_q&lt;double&gt; Max = 23.69 RMS Mean=3.955 </del></p> <blockquote> <p> worst case at row: 600 { 91.615684509277344, 183.23136901855469, 6.0094745549395681e+125, 2.5194958887453263e-014, 2.3851892681325433e+139, 0.9999999999999748 } </p> </blockquote> <p> other::gamma_q(double) Max = 125.1 RMS Mean=9.671 </p> <blockquote> <p> worst case at row: 27 { 4.053, 405.3, 8.563e-169, 1.334e-169, 6.418, 1 } </p> </blockquote> <p> boost::math::gamma_p&lt;double&gt; Max = 35.09 RMS Mean=6.961 </p> <blockquote> <p> worst case at row: 651 { 96.78564453125, 0.96785646677017212, 3.7245981312945362e+149, 1, 0.00016783328089080209, 4.5060775679568222e-154 } </p> </blockquote> <p> other::gamma_p(double) Max = 426.3 RMS Mean=46.18 </p> <blockquote> <p> worst case at row: 518 { 80.13, 0.8013, 1.566e+117, 1, 1.104e-010, 7.05e-128 } </p> </blockquote> <p> Testing tgamma(a, z) small values with type double <del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del> boost::math::gamma_q&lt;double&gt; Max = 2.898 RMS Mean=1.05 </del></p> <blockquote> <p> worst case at row: 73 { 1.0221641311147778e-009, 1.0221641311147778e-009, 20.124127878209329, 2.0570161699209098e-008, 978316444.88368392, 0.99999997942983831 } </p> </blockquote> <p> other::gamma_q(double) Max = 31.86 RMS Mean=7.103 </p> <blockquote> <p> worst case at row: 223 { 0.001962, 100, 3.717e-046, 7.303e-049, 509, 1 } </p> </blockquote> <p> boost::math::gamma_p&lt;double&gt; Max = 0.5133 RMS Mean=0.03234 </p> <blockquote> <p> worst case at row: 226 { 0.0055537549778819084, 0.0049983793869614601, 4.6545082571173033, 0.025932342985794662, 174.83209885998627, 0.97406765701420539 } </p> </blockquote> <p> other::gamma_p(double) Max = 0.7172 RMS Mean=0.2328 </p> <blockquote> <p> worst case at row: 245 { 0.05124, 0.0005124, 5.75, 0.3029, 13.24, 0.6971 } </p> </blockquote> <p> Testing tgamma(a, z) large values with type double <del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del> boost::math::gamma_q&lt;double&gt; Max = 469.8 RMS Mean=31.51 </del></p> <blockquote> <p> worst case at row: 222 { 2057.796630859375, 4115.59326171875, 0.1184802275824791, 5.1589245564542783e-277, 0.22966070987459913, 1 } </p> </blockquote> <p> other::gamma_q(double) Max = 310.7 RMS Mean=35.14 </p> <blockquote> <p> worst case at row: 277 { 7.884e+005, 7.884e+005, 0.1624, 0.499, 0.1631, 0.501 } </p> </blockquote> <p> boost::math::gamma_p&lt;double&gt; Max = 244.4 RMS Mean=19.38 </p> <blockquote> <p> worst case at row: 211 { 1169.2916259765625, 584.64581298828125, 0.22117898880238315, 1, 0.42515811737132952, 1.9222355598668354e-100 } </p> </blockquote> <p> other::gamma_p(double) Max = 310.3 RMS Mean=36.91 </p> <blockquote> <p> worst case at row: 277 { 7.884e+005, 7.884e+005, 0.1624, 0.499, 0.1631, 0.501 } </p> </blockquote> <p> Testing tgamma(a, z) integer and half integer values with type double <del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del> boost::math::gamma_q&lt;double&gt; Max = 8.485 RMS Mean=1.351 </del></p> <blockquote> <p> worst case at row: 138 { 37, 74, 2.7177865101844111e+035, 7.306008776118165e-007, 3.7199305501125022e+041, 0.99999926939912243 } </p> </blockquote> <p> other::gamma_q(double) Max = 103.1 RMS Mean=12.59 </p> <blockquote> <p> worst case at row: 20 { 4.5, 450, 7.196e-187, 6.187e-188, 11.63, 1 } </p> </blockquote> <p> boost::math::gamma_p&lt;double&gt; Max = 13.03 RMS Mean=2.932 </p> <blockquote> <p> worst case at row: 133 { 37, 0.37000000476837158, 3.7199332678990125e+041, 1, 1.9898558488031992e-018, 5.3491708197417564e-060 } </p> </blockquote> <p> other::gamma_p(double) Max = 123.4 RMS Mean=20.06 </p> <blockquote> <p> worst case at row: 91 { 25, 0.25, 6.204e+023, 1, 2.794e-017, 4.503e-041 } </p> </blockquote> <p> So for the most part the Boost version can be a bit more accurate. </p> <p> And for the inverse: </p> <p> Tests run with Microsoft Visual C++ version 9.0, Dinkumware standard library version 505, Win32 Testing incomplete gamma inverse(a, z) medium values with type double <del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del> boost::math::gamma_p_inv&lt;double&gt; Max = 1.652 RMS Mean=0.3353 </del></p> <blockquote> <p> worst case at row: 2 { 9.7540397644042969, 0.22103404998779297, 7.2622991072035479, 11.97587613793354 } </p> </blockquote> <p> boost::math::gamma_q_inv&lt;double&gt; Max = 2.254 RMS Mean=0.3822 </p> <blockquote> <p> worst case at row: 49 { 22.103404998779297, 0.96886777877807617, 31.653035526093614, 14.199388115898186 } </p> </blockquote> <p> other::gamma_p_inv&lt;double&gt; Max = 9.755 RMS Mean=2.085 </p> <blockquote> <p> worst case at row: 23 { 13.547700881958008, 0.30816704034805298, 11.480744407137443, 15.117986636057008 } </p> </blockquote> <p> other::gamma_q_inv&lt;double&gt; Max = 24.23 RMS Mean=2.871 </p> <blockquote> <p> worst case at row: 49 { 22.103404998779297, 0.96886777877807617, 31.653035526093614, 14.199388115898186 } </p> </blockquote> <p> Testing incomplete gamma inverse(a, z) large values with type double <del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del> boost::math::gamma_p_inv&lt;double&gt; Max = 0.9242 RMS Mean=0.1082 </del></p> <blockquote> <p> worst case at row: 10 { 581.3642578125, 0.12698681652545929, 553.96697937820386, 608.96241888374834 } </p> </blockquote> <p> boost::math::gamma_q_inv&lt;double&gt; Max = 0.8143 RMS Mean=0.1072 </p> <blockquote> <p> worst case at row: 70 { 40010.84375, 0.12698681652545929, 39782.764004009827, 40239.124371052443 } </p> </blockquote> <p> other::gamma_p_inv&lt;double&gt; Max = 1.22 RMS Mean=0.4401 </p> <blockquote> <p> worst case at row: 88 { 106978.296875, 0.9133758544921875, 107424.0055670203, 106533.15792214176 } </p> </blockquote> <p> other::gamma_q_inv&lt;double&gt; Max = 1.07 RMS Mean=0.4135 </p> <blockquote> <p> worst case at row: 30 { 3758.09765625, 0.12698681652545929, 3688.2692219050818, 3828.1269667349475 } </p> </blockquote> <p> Testing incomplete gamma inverse(a, z) small values with type double <del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del></del><del> boost::math::gamma_p_inv&lt;double&gt; Max = 1163 RMS Mean=103.7 </del></p> <blockquote> <p> worst case at row: 86 { 0.000398525211494416, 0.83500856161117554, 1.7877325072629434e-197, 0 } </p> </blockquote> <p> boost::math::gamma_q_inv&lt;double&gt; Max = 962.6 RMS Mean=82.05 </p> <blockquote> <p> worst case at row: 82 { 0.000398525211494416, 0.22103404998779297, 0, 3.4835777677025903e-273 } </p> </blockquote> <p> other::gamma_p_inv&lt;double&gt; Max = 1229 RMS Mean=108 </p> <blockquote> <p> worst case at row: 86 { 0.000398525211494416, 0.83500856161117554, 1.7877325072629434e-197, 0 } </p> </blockquote> <p> other::gamma_q_inv&lt;double&gt; Max = 1145 RMS Mean=135.6 </p> <blockquote> <p> worst case at row: 80 { 0.000398525211494416, 0.12698681652545929, 0, 5.6992492776090963e-149 } </p> </blockquote> <p> So broadly similar again. </p> <p> Time wise, I've modified our performance tests to test dcdflib as well and get: </p> <p> Testing igamma 8.611e-007 Testing igamma-dcd 5.849e-007 Testing igamma_inv 3.626e-006 Testing igamma_inv-dcd 1.810e-006 </p> <p> which confirms what you're seeing. </p> <p> After the first round of changes/optimisations (now in Trunk) I get: </p> <p> Testing igamma 7.067e-007 Testing igamma-dcd 5.849e-007 Testing igamma_inv 3.003e-006 Testing igamma_inv-dcd 1.855e-006 </p> <p> So a bit better, but still some way to go, unfortunately many of the remaining differences appear to come from either: </p> <ul><li>Not such good optimisations when calling boilerplate code (external "inline" routines) as compared to the declared-all-inline spagetti code of the original fortran. </li><li>Apparently a lower overhead in calling the functions and going through the algorithm-selection logic in the dcd code. </li></ul><p> However, I'm not particularly keen to replace the current, almost readable, structured code, with a bunch of goto's and spagetti code :-( </p> <p> Still looking for more low hanging fruit yours, John. </p> </description> <category>Ticket</category> </item> <item> <author>chhenning@…</author> <pubDate>Thu, 24 Sep 2009 15:03:36 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:6</guid> <description> <p> John, some quick questions. </p> <ol><li>Are the underlying algorithms for the two functions the same? </li><li>Is it possible to change the internal function variables to static storage? </li><li>How about using <span class="underline">forceinline on Windows? Dunno what it's on Linux. </span></li></ol><p> Thanks for your work on this. </p> <p> Christian </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Thu, 24 Sep 2009 16:02:22 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:7</guid> <description> <blockquote class="citation"> <ol><li>Are the underlying algorithms for the two functions the same? </li></ol></blockquote> <p> Yes. However, there may be detail differences that make one version or the other slightly faster. </p> <blockquote class="citation"> <ol start="2"><li>Is it possible to change the internal function variables to static storage? </li></ol></blockquote> <p> No, that wouldn't be thread safe (obviously constants are already static). </p> <blockquote class="citation"> <ol start="3"><li>How about using forceinline on Windows? Dunno what it's on Linux. </li></ol></blockquote> <p> Maybe, that's sort of a last resort, there are still plenty of other things to work on first! </p> <p> John. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Thu, 01 Oct 2009 16:08:39 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:8</guid> <description> <p> OK another round of changes and now I see: </p> <p> Testing igamma 5.849e-007<br /> Testing igamma-dcd 5.857e-007<br /> Testing igamma_inv 2.651e-006<br /> Testing igamma_inv-dcd 1.855e-006 </p> <p> So still some work to do on the inverse, but the forward function is looking pretty healthy now. These changes effect some of the underlying boilerplate code, and so should improve times right throughout the library :-) </p> <p> BTW, these times were obtained with -Ox and -DNDEBUG, the latter is particularly important, as there are quite a few asserts in our code! </p> <p> Committed to trunk with revision <a class="missing ticket">#56503</a>. </p> <p> Onwards to work on the inverse now.... John. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Mon, 05 Oct 2009 17:52:09 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:9</guid> <description> <p> Another update to Trunk and I think this is almost fixed now: </p> <pre class="wiki">Testing igamma 5.849e-007 Testing igamma-dcd 5.857e-007 Testing igamma_inv 1.943e-006 Testing igamma_inv-dcd 1.855e-006 </pre><p> The Boost inverse is somewhat slower as it computes more digits; changing the policy to 10 decimal places (which is what the Didonato and Morris code promises) then gives: </p> <pre class="wiki">Testing igamma_inv 1.459e-006 Testing igamma_inv-dcd 1.855e-006 </pre><p> And your original test code gives: </p> <pre class="wiki">Boost 30.5s Boost (10 digits) 21.3s DCDFLIB 27s </pre><p> Unfortunately, I've found a few other functions that appear to be slower than they should be, and the speedup achieved on Linux is very disappointing so far :-( </p> <p> So still more to do, but this basically fixes the original issue I believe. If you're able to give the new code in Trunk a test on your machine that would be much appreciated, as results will vary from machine to machine a bit... </p> <p> HTH, John. </p> </description> <category>Ticket</category> </item> <item> <author>chhenning@…</author> <pubDate>Tue, 06 Oct 2009 15:40:06 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:10</guid> <description> <p> John, thanks for all of your work. I did update my boost trunk and rerun my test. Both boost and ATT are pretty much on par with each other. Att still being slightly a faster. </p> <p> Test is to compare boost's gamma quantile function vs. Att's cdfgam function. </p> <p> Boost - 19.968sec Att - 18.547sec </p> <p> This is very good! I have used VS2005 producing 64bit code. </p> <p> Can you summaries how you almost doubled the boost performance? </p> <p> Thanks again for your great work. I can now propose to use boost::math at my work. </p> <p> Christian </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Tue, 06 Oct 2009 17:13:28 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3408#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3408#comment:11</guid> <description> <blockquote class="citation"> <p> Can you summaries how you almost doubled the boost performance? </p> </blockquote> <p> Lot's of very small tweeks :-) </p> <p> To the forward function: </p> <p> Look for opportunities to better reuse intermediate results so there are fewer special-function calls made. </p> <p> To the inverse (and hence quantile): </p> <ul><li>Adjust/fine tune iteration limits so that fewer Halley iterations are used to find the inverse. </li><li>Fixed a couple of bugs in the evaluation of the the "guess" used for inital Halley iteration. </li><li>Improved re-use of intermediate results (fewer function calls). </li></ul><p> Regards, John. </p> </description> <category>Ticket</category> </item> </channel> </rss>