Hi Massimiliano,
On Tue, Jan 27, 2015 at 11:38 PM, Massimiliano Ghilardi < massimiliano.ghilardi+abcl@gmail.com> wrote:
On 01/26/15 07:40, Mark Evenson wrote:
On 25 Jan 2015, at 20:19, Massimiliano Ghilardi <
massimiliano.ghilardi+abcl@gmail.com> wrote:
Massimiliano Ghilardi
Nice fix. Promoted as [14749][].
Need to release a abcl-1.3.2 real soon now…
Thanks Mark.
My patch stops EQUALP from signaling errors on "impossible" bignum-to-float comparisons, i.e. between floats and bignums larger than the biggest representable floats.
Anyway, it does not fix an existing bug for "possible" comparisons, i.e. between floats and bignums in the range representable by floats.
The usual CLHS file:///home/max/SW/lisp/docs-lisp/HyperSpec/Body/f_equalp.htm#equalp tells that EQUALP on two numbers is the same as =.
There are cases where ABCL does not follow it:
CL-USER> (= most-positive-single-float 340282346638528859811704183484 516925440) T
CL-USER> (equalp most-positive-single-float 340282346638528859811704183484 516925440) T ;; correct :)
CL-USER> (= most-positive-single-float 340282346638528859811704183484 516925439) NIL
EQUALP behaves differently from =, because (EQUALP bignum float) converts the bignum to float, losing precision:
CL-USER> (equalp most-positive-single-float 340282346638528859811704183484 516925439) T ;; incorrect :(
Digging more reveals further inconsistencies...
CL-USER> (= 1.0 #C(1.0 0.0)) T
CL-USER> (equalp 1.0 #C(1.0 0.0)) NIL ;; again :(
The fix is conceptually simple: for all the number tower, EQUALP must use the same algorithm as =, with the only difference that it must never throw.
I am not sure which Java method implements the function = so I don't dare yet to write a patch. Maybe isEqualTo() ?
Right on the mark! See Primitives.java#L1235 and compiler-pass2.lisp:p2-numeric-comparison ; the former for interpreted code, the latter for compiled code.
Thanks for taking the time to submit patches!