GNU bug report logs - #13031
large numbers

Previous Next

Package: guile;

Reported by: Jozef Chraplewski <jozef <at> applicake.com>

Date: Thu, 29 Nov 2012 17:51:02 UTC

Severity: normal

Done: Mark H Weaver <mhw <at> netris.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Mark H Weaver <mhw <at> netris.org>
To: Jozef Chraplewski <jozef <at> applicake.com>
Cc: 13031 <at> debbugs.gnu.org
Subject: bug#13031: large numbers
Date: Mon, 03 Dec 2012 19:13:48 -0500
[Message part 1 (text/plain, inline)]
Hi Jozef,

I guess that on your system, (* 65536 65536) evaluates to 0.
Is that right?

If so, I believe the problem is caused by an aggressive optimization in
recent versions of Clang, which breaks Guile's logic for detecting
overflow when multiplying two fixnums.

Currently, Guile computes kk = xx * yy and checks for overflow by
verifying that kk / xx == yy.

I believe that Clang is optimizing out the check, because recent C
standards permit C implementations to assume that signed integer
arithmetic will never overflow.  For details, see:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html

One solution is to compile with the "-fwrapv" option, which should
disable the optimization.

Another solution is to apply the following patch.

Jozef, would you be willing to test this patch and tell me if it fixes
the problem?

   Many thanks,
      Mark


[FIXNUM_PRODUCT_OVERFLOW_FIX.patch (text/x-diff, inline)]
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 52e227f..66c95db 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -7640,10 +7640,16 @@ scm_product (SCM x, SCM y)
       if (SCM_LIKELY (SCM_I_INUMP (y)))
 	{
 	  scm_t_inum yy = SCM_I_INUM (y);
-	  scm_t_inum kk = xx * yy;
-	  SCM k = SCM_I_MAKINUM (kk);
-	  if ((kk == SCM_I_INUM (k)) && (kk / xx == yy))
-	    return k;
+#if SCM_I_FIXNUM_BIT < 32 && SCM_HAVE_T_INT64
+          scm_t_int64 kk = xx * (scm_t_int64) yy;
+          if (SCM_FIXABLE (kk))
+            return SCM_I_MAKINUM (kk);
+#else
+          scm_t_inum axx = (xx > 0) ? xx : -xx;
+          scm_t_inum ayy = (yy > 0) ? yy : -yy;
+          if (SCM_MOST_POSITIVE_FIXNUM / axx >= ayy)
+            return SCM_I_MAKINUM (xx * yy);
+#endif
 	  else
 	    {
 	      SCM result = scm_i_inum2big (xx);

This bug report was last modified 12 years and 164 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.