<< Back to previous view

[CLJS-747] Numerical inconsistency between Clojure and ClojureScript (running in Rhino) Created: 11/Jan/14  Updated: 16/Jan/14  Resolved: 16/Jan/14

Status: Closed
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Jim Pivarski Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: integer-overflow
Environment:

Clojure (1.5.1) on JVM vs. ClojureScript (cloned from GitHub today) in Rhino on JVM



 Description   

In Clojure, the maximum long value throws an ArithmeticException when incremented with + and rolls over to a BigInt when incremented with +'

user=> (+ 9223372036854775807 1)
ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)
user=> (+' 9223372036854775807 1)
9223372036854775808N

But ClojureScript rolls over to BigInt with + and does not have a +' function

ClojureScript:cljs.user> (+ 9223372036854775807 1)
9223372036854776000N
ClojureScript:cljs.user> (+' 9223372036854775807 1)
WARNING: Use of undeclared Var cljs.user/+' at line 1 
"Error evaluating:" (+' 9223372036854775807 1) :as "cljs.user._PLUS__SINGLEQUOTE_.call(null,9223372036854775807,1)"
org.mozilla.javascript.EcmaError: TypeError: Cannot call method "call" of undefined (<cljs repl>#1)
        at <cljs repl>:1 (anonymous)
        at <cljs repl>:1

In fact, the inexactness of 9223372036854776000N suggests the reason: it's actually a double, presented as though it were a BigInt. (Perhaps that's a limitation of JavaScript? If so, at least it should be presented as a double, as very large numbers are: e.g. (* 9223372036854775807 9223372036854775807) --> 8.507059173023462E37.) From http://stackoverflow.com/questions/8664093/not-getting-integer-overflow-in-clojure , it is my understanding that this behavior was defined in Clojure version 1.3--- is ClojureScript a few versions behind in that it attempts roll-over and does not have a +' function?



 Comments   
Comment by Jim Pivarski [ 11/Jan/14 3:53 AM ]

That is, ClojureScript doesn't implement http://dev.clojure.org/display/design/Documentation+for+1.3+Numerics

Comment by Jozef Wagner [ 11/Jan/14 5:54 AM ]

If I understand your description correctly, the issue is that Clojurescript does not have BigInts and precise/unchecked variants of arithmetic functions. Please read this bigint discussion and design page for some background information about this.

Comment by Jim Pivarski [ 11/Jan/14 1:43 PM ]

You're right--- I misunderstood ClojureScript's interoperability policy. I'm considering Clojure/ClojureCLR/ClojureScript/ClojureC/Clojure-Py for cross-platform numeric processing, so I've started testing them for numerical compatibility at the edge cases. At first, this looked like a serious bug (no exception, inexact result) until I figured out that it's just double precision. For my purposes, I could say that the largest integer with cross-platform support is 9223372036854775000, and above that, Clojure* may throw an exception, roll over to BigInt, or inexactly represent it as a double, depending on platform.

I'd like to convert this into a minor feature request for BigInt and +' functions or close this ticket and open a new one, but it doesn't look like I have permission to change its resolution state.

I researched the problem before submitting this ticket, but I didn't find the references that you sent (very helpful, thanks!). Should I continue to report edge cases of incompatibility between Clojure and ClojureScript? For my own purposes, I need to know the ranges within which to expect compatibility, so I'm building up a test suite with an emphasis on numerical processing. (And I'm only checking Clojure, ClojureScript, and Clojure-py for now.) If it's helpful, I'll submit bug reports here; if it's annoying, I won't.

Comment by Jozef Wagner [ 12/Jan/14 4:12 AM ]

Numbers are one of few things which are not consistent in Clojure across hosts. This is a design decision in order to provide fast numerics for hosts which have one. A host independent numeric API would preclude many optimizations. Another outcome of this design decision is that the number types are not user extensible. Even basic arithmetic functions may behave differently in edge cases in different hosts. ClojureScript may get BigInt if someone finds time to implement them, but I doubt they will behave exactly the same as in JVM. You'd better accept that numbers will always be host dependent and code according to that.

Comment by David Nolen [ 16/Jan/14 5:23 PM ]

This will require a considerable amount of design work. Until that happens there's not much point opening tickets.

Generated at Fri Aug 29 09:03:33 CDT 2014 using JIRA 4.4#649-r158309.