Clojure JIRAhttp://dev.clojure.org/jira
This file is an XML representation of an issueen-us4.464925-07-2011[MTOWER-3] BigDecimal: unnecessary reflection used in math functions for coercion (bigint)http://dev.clojure.org/jira/browse/MTOWER-3
math.numeric-tower<p>This improves performance, because no reflection has to be used (bigint):</p>
<p>Patched:<br/>
clojure.math.numeric-tower&gt; (time (let <span class="error">&#91;b (BigDecimal. &quot;2.2&quot;)&#93;</span> (dotimes <span class="error">&#91;x 10000000&#93;</span> (round b))))<br/>
"Elapsed time: 1640.177041 msecs" <br/>
Orig: <br/>
clojure.math.numeric-tower&gt; (time (let <span class="error">&#91;b (BigDecimal. &quot;2.2&quot;)&#93;</span> (dotimes <span class="error">&#91;x 10000000&#93;</span> (round b))))<br/>
"Elapsed time: 3498.339271 msecs"</p>
MTOWER-3BigDecimal: unnecessary reflection used in math functions for coercion (bigint)EnhancementMinorClosedDeclinedMark EngelbergJürgen Hötzelpatch,Mon, 13 May 2013 14:48:19 -0500Thu, 2 Jan 2014 00:39:29 -0600Thu, 2 Jan 2014 00:39:28 -060001<p>Andy, thanks for letting me know about this issue. I had no idea it's been sitting here in JIRA for months.</p>
<p>1. These numbers really do need to be converted to BigInt, not BigInteger.</p>
<p>2. There's nothing inherently problematic with the call to bigint. In my tests, it appears that this patch doesn't meaningfully improve the performance of floor or ceiling, only round. That's because it's not the call to bigint that is slow, but in round, you've used a call to .setScale with ROUND_HALF_UP, and that's faster than the method used in the code (adding 0.5M and then flooring).</p>
<p>3. Even though .setScale with ROUND_HALF_UP is faster than the current code, it <b>does not return the correct results</b> for negative numbers like -4.5M. The goal is to make the behavior match Math/round on doubles. For some reason, BigDecimal's ROUND_HALF_UP does the wrong thing for negative numbers (rounding up in magnitude, rather than rounding up in the sense of making it more positive).</p>
<p>So this patch is a no-go. The changes to floor and ceiling return BigInteger rather than BigInt and when modified to return BigInt, do not yield speed benefits. The change to round does yield a speed benefit, but the results are incorrect for negative numbers halfway between integers.</p>
<p>If you find a faster way to round decimal numbers than the existing mechanism that yields the correct results for negative numbers, let me know.</p>Global RankPatchCode