Clojure Q&A - Recent questions tagged ratio
https://ask.clojure.org/index.php/tag/ratio
Some corner cases that might be considered bugs in Ratio implementation
https://ask.clojure.org/index.php/11521/some-corner-cases-that-might-considered-ratio-implementation
<p>I was looking through the new <code>clojure.core/abs</code> implementation on type Ratio, and it seemed that there is an assumption in the code that uses the internal details of type clojure.lang.Ratio that the denominator is always positive (e.g. see the definitions of isNeg and isPos methods for type Ratio).</p>
<p>I started looking for cases where that assumption might be violated, and found the following, all of which might be distinctive to values of type Ratio produced by an expression with Long/MIN_VALUE as the denominator and an integer with type Long or smaller as the numerator:</p>
<pre><code>$ clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.11.0-alpha4"}}}'
Clojure 1.11.0-alpha4
user=> (/ 1 Long/MIN_VALUE)
-1/-9223372036854775808
user=> (< (/ 1 Long/MIN_VALUE) 0) ;; This gives correct numerical answer
true
user=> (< (* 1 (/ 1 Long/MIN_VALUE)) 0) ;; This does not
false
user=> (abs (/ 1 Long/MIN_VALUE)) ;; Gives incorrect numerical answer
1/-9223372036854775808
user=> (< (abs (/ 1 Long/MIN_VALUE)) 0) ;; correct numerical answer
false
user=> (< (* 1 (abs (/ 1 Long/MIN_VALUE))) 0) ;; incorrect numerical answer
true
</code></pre>
<p>I have carefully checked other occurrences of Ratio in source file Numbers.java in Clojure's implementation, and as far as I can tell the only issue is with the method named divide in the LongOps class. If that method avoided this problem by checking for the special case when the numerator and/or denominator is equal to Long/MIN_VALUE and behaved a little differently in that case, I do not see any other bugs.</p>
<p>Here is another issue if the numerator is equal to Long/MIN_VALUE, where the root cause is in the same LongOps divide method:</p>
<pre><code>user=> (/ Long/MIN_VALUE -3) ;; should return positive value, but returns negative value
-9223372036854775808/3
user=> (< (/ Long/MIN_VALUE -3) 0)
true
</code></pre>
Clojurehttps://ask.clojure.org/index.php/11521/some-corner-cases-that-might-considered-ratio-implementationSun, 30 Jan 2022 02:24:18 +0000