From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Kevin Ryde Newsgroups: gmane.lisp.guile.devel Subject: Re: min, max and nans Date: Fri, 30 May 2003 10:20:29 +1000 Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Message-ID: <87smqxl1yq.fsf@zip.com.au> References: <87ade1t1p7.fsf@zip.com.au> <87d6ih5okm.fsf@zagadka.ping.de> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: main.gmane.org 1054254174 9945 80.91.224.249 (30 May 2003 00:22:54 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Fri, 30 May 2003 00:22:54 +0000 (UTC) Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Fri May 30 02:22:49 2003 Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 19LXez-0002Yx-00 for ; Fri, 30 May 2003 02:22:17 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.20) id 19LXfy-0004Zc-3Z for guile-devel@m.gmane.org; Thu, 29 May 2003 20:23:18 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.20) id 19LXdt-0003tz-Ie for guile-devel@gnu.org; Thu, 29 May 2003 20:21:09 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.20) id 19LXdi-0003YL-4o for guile-devel@gnu.org; Thu, 29 May 2003 20:21:02 -0400 Original-Received: from snoopy.pacific.net.au ([61.8.0.36]) by monty-python.gnu.org with esmtp (Exim 4.20) id 19LXdS-00034B-Cc for guile-devel@gnu.org; Thu, 29 May 2003 20:20:42 -0400 Original-Received: from sunny.pacific.net.au (sunny.pacific.net.au [203.2.228.40]) h4U0KePB016079 for ; Fri, 30 May 2003 10:20:40 +1000 Original-Received: from wisma.pacific.net.au (wisma.pacific.net.au [210.23.129.72]) by sunny.pacific.net.au with ESMTP id h4U0KeQg014825 for ; Fri, 30 May 2003 10:20:40 +1000 (EST) Original-Received: from localhost (ppp16.dyn228.pacific.net.au [203.143.228.16]) by wisma.pacific.net.au (8.12.9/8.12.9) with ESMTP id h4U0KbYZ013350 for ; Fri, 30 May 2003 10:20:38 +1000 (EST) Original-Received: from gg by localhost with local (Exim 3.35 #1 (Debian)) id 19LXdF-0000uM-00; Fri, 30 May 2003 10:20:29 +1000 Original-To: guile-devel@gnu.org User-Agent: Gnus/5.090019 (Oort Gnus v0.19) Emacs/21.2 (gnu/linux) X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Developers list for Guile, the GNU extensibility library List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: main.gmane.org gmane.lisp.guile.devel:2453 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.devel:2453 --=-=-= Marius Vollmer writes: > > That's what I think, too. * numbers.c (scm_max, scm_min): For inum, bignum and real, if other operand is NaN, then return NaN. Also avoid passing NaN to mpz_cmp_d. * tests/numbers.test (max, min): Add tests involving NaNs. Some cases just need the sense of the > or < test put the right way to allow for it being false when involving a NaN. A couple are right already. For bignums and for real/real an actual isnan is necessary. --=-=-= Content-Disposition: attachment; filename=numbers.c.min-max-nan.diff --- numbers.c.~1.188.~ 2003-05-13 09:14:53.000000000 +1000 +++ numbers.c 2003-05-26 17:42:15.000000000 +1000 @@ -2806,7 +2806,8 @@ return (sgn < 0) ? x : y; } else if (SCM_REALP (y)) { double z = xx; - return (z <= SCM_REAL_VALUE (y)) ? y : scm_make_real (z); + /* if y==NaN then ">" is false and we return NaN */ + return (z > SCM_REAL_VALUE (y)) ? scm_make_real (z) : y; } else { SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max); } @@ -2820,7 +2821,11 @@ scm_remember_upto_here_2 (x, y); return (cmp > 0) ? x : y; } else if (SCM_REALP (y)) { - int cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y)); + double yy = SCM_REAL_VALUE (y); + int cmp; + if (xisnan (yy)) + return y; + cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), yy); scm_remember_upto_here_1 (x); return (cmp > 0) ? x : y; } else { @@ -2829,13 +2834,23 @@ } else if (SCM_REALP (x)) { if (SCM_INUMP (y)) { double z = SCM_INUM (y); + /* if x==NaN then "<" is false and we return NaN */ return (SCM_REAL_VALUE (x) < z) ? scm_make_real (z) : x; } else if (SCM_BIGP (y)) { - int cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x)); + double xx = SCM_REAL_VALUE (x); + int cmp; + if (xisnan (xx)) + return x; + cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x)); scm_remember_upto_here_1 (y); return (cmp < 0) ? x : y; } else if (SCM_REALP (y)) { - return (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y)) ? y : x; + /* if x==NaN then our explicit check means we return NaN + if y==NaN then ">" is false and we return NaN + a call to isnan is unavoidable, since it's the only way to know + which of x or y causes any compares to be false */ + double xx = SCM_REAL_VALUE (x); + return (xisnan (xx) || xx > SCM_REAL_VALUE (y)) ? x : y; } else { SCM_WTA_DISPATCH_2 (g_max, x, y, SCM_ARGn, s_max); } @@ -2872,6 +2887,7 @@ return (sgn < 0) ? y : x; } else if (SCM_REALP (y)) { double z = xx; + /* if y==NaN then "<" is false and we return NaN */ return (z < SCM_REAL_VALUE (y)) ? scm_make_real (z) : y; } else { SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min); @@ -2886,7 +2902,11 @@ scm_remember_upto_here_2 (x, y); return (cmp > 0) ? y : x; } else if (SCM_REALP (y)) { - int cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y)); + double yy = SCM_REAL_VALUE (y); + int cmp; + if (xisnan (yy)) + return y; + cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), yy); scm_remember_upto_here_1 (x); return (cmp > 0) ? y : x; } else { @@ -2895,13 +2915,23 @@ } else if (SCM_REALP (x)) { if (SCM_INUMP (y)) { double z = SCM_INUM (y); - return (SCM_REAL_VALUE (x) <= z) ? x : scm_make_real (z); + /* if x==NaN then ">" is false and we return NaN */ + return (SCM_REAL_VALUE (x) > z) ? scm_make_real (z) : x; } else if (SCM_BIGP (y)) { - int cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x)); + double xx = SCM_REAL_VALUE (x); + int cmp; + if (xisnan (xx)) + return x; + cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), xx); scm_remember_upto_here_1 (y); return (cmp < 0) ? y : x; } else if (SCM_REALP (y)) { - return (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y)) ? x : y; + /* if x==NaN then our explicit check means we return NaN + if y==NaN then "<" is false and we return NaN + a call to isnan is unavoidable, since it's the only way to know + which of x or y causes any compares to be false */ + double xx = SCM_REAL_VALUE (x); + return (xisnan (xx) || xx < SCM_REAL_VALUE (y)) ? x : y; } else { SCM_WTA_DISPATCH_2 (g_min, x, y, SCM_ARGn, s_min); } --=-=-= Content-Disposition: attachment; filename=numbers.test.min-max-nan.diff --- numbers.test.~1.23.~ 2003-05-10 13:01:51.000000000 +1000 +++ numbers.test 2003-05-26 17:45:08.000000000 +1000 @@ -1646,6 +1646,9 @@ ;;; (with-test-prefix "max" + (pass-if (= 456.0 (max 123.0 456.0))) + (pass-if (= 456.0 (max 456.0 123.0))) + (let ((big*2 (* fixnum-max 2)) (big*3 (* fixnum-max 3)) (big*4 (* fixnum-max 4)) @@ -1654,7 +1657,15 @@ (pass-if (= +inf.0 (max big*5 +inf.0))) (pass-if (= +inf.0 (max +inf.0 big*5))) (pass-if (= big*5 (max big*5 -inf.0))) - (pass-if (= big*5 (max -inf.0 big*5)))) + (pass-if (= big*5 (max -inf.0 big*5))) + + (pass-if (nan? (max 123 +nan.0))) + (pass-if (nan? (max big*5 +nan.0))) + (pass-if (nan? (max 123.0 +nan.0))) + (pass-if (nan? (max +nan.0 123))) + (pass-if (nan? (max +nan.0 big*5))) + (pass-if (nan? (max +nan.0 123.0))) + (pass-if (nan? (max +nan.0 +nan.0)))) ;; in gmp prior to 4.2, mpz_cmp_d ended up treating Inf as 2^1024, make ;; sure we've avoided that @@ -1672,7 +1683,12 @@ (1+ (ash 1 1024)) (- (1- (ash 1 1024))) (- (ash 1 1024)) - (- (1+ (ash 1 1024)))))) + (- (1+ (ash 1 1024))))) + + ;; in gmp prior to 4.2, mpz_cmp_d ended up treating NaN as 3*2^1023, make + ;; sure we've avoided that + (pass-if (nan? (max (ash 1 2048) +nan.0))) + (pass-if (nan? (max +nan.0 (ash 1 2048))))) ;;; ;;; min @@ -1681,6 +1697,9 @@ ;; FIXME: unfinished... (with-test-prefix "min" + (pass-if (= 123.0 (min 123.0 456.0))) + (pass-if (= 123.0 (min 456.0 123.0))) + (let ((big*2 (* fixnum-max 2)) (big*3 (* fixnum-max 3)) (big*4 (* fixnum-max 4)) @@ -1706,7 +1725,15 @@ (pass-if (= big*5 (min big*5 +inf.0))) (pass-if (= big*5 (min +inf.0 big*5))) (pass-if (= -inf.0 (min big*5 -inf.0))) - (pass-if (= -inf.0 (min -inf.0 big*5)))) + (pass-if (= -inf.0 (min -inf.0 big*5))) + + (pass-if (nan? (min 123 +nan.0))) + (pass-if (nan? (min big*5 +nan.0))) + (pass-if (nan? (min 123.0 +nan.0))) + (pass-if (nan? (min +nan.0 123))) + (pass-if (nan? (min +nan.0 big*5))) + (pass-if (nan? (min +nan.0 123.0))) + (pass-if (nan? (min +nan.0 +nan.0)))) ;; in gmp prior to 4.2, mpz_cmp_d ended up treating Inf as 2^1024, make ;; sure we've avoided that @@ -1724,7 +1751,12 @@ (1+ (ash 1 1024)) (- (1- (ash 1 1024))) (- (ash 1 1024)) - (- (1+ (ash 1 1024)))))) + (- (1+ (ash 1 1024))))) + + ;; in gmp prior to 4.2, mpz_cmp_d ended up treating NaN as 3*2^1023, make + ;; sure we've avoided that + (pass-if (nan? (min (- (ash 1 2048)) (- +nan.0)))) + (pass-if (nan? (min (- +nan.0) (- (ash 1 2048)))))) ;;; ;;; + --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://mail.gnu.org/mailman/listinfo/guile-devel --=-=-=--