# Fixnum arithmetic bug on Suns

```1+ and 1- don't do quite the right thing on a Sun:

> (1- most-negative-fixnum)
2147483647
> (1+ most-positive-fixnum)
-2147483648

The problem is subtle.  In the case of 1-, the code looks like

if (i < 0)
if (--i < 0)
/* still a fixnum */
else
/* a bignum now */

This looks fine, except that on a Sun the assembly code is

subql	\$1, i
bge	<else part>

Now, subtracting one from -2^31 sets the overflow flag
as well as clearing the sign bit, and bge won't branch
on that (because it's also supposed to work following a
compare instruction).  We can call this a compiler bug, but
there's a more conservative way to write this code that
should always work and is only a bit slower:

*** /tmp/d02691	Thu Nov  3 22:30:25 1988
--- num_arith.c	Wed Nov  2 16:16:54 1988
***************
*** 412,418
if(i == 0)
return(small_fixnum(1));
if(i > 0)
! 			if (++i > 0) {
if (-SMALL_FIXNUM_LIMIT <= i &&
i < SMALL_FIXNUM_LIMIT)
return(small_fixnum(i));

--- 412,419 -----
if(i == 0)
return(small_fixnum(1));
if(i > 0)
! 			if (i < MOST_POSITIVE_FIX) {
! 				i++;
if (-SMALL_FIXNUM_LIMIT <= i &&
i < SMALL_FIXNUM_LIMIT)
return(small_fixnum(i));
***************
*** 420,426
fix(z) = i;
return(z);
} else
else {
i++;
if (-SMALL_FIXNUM_LIMIT <= i &&

--- 421,427 -----
fix(z) = i;
return(z);
} else
! 				return(bignum2(1, 0));
else {
i++;
if (-SMALL_FIXNUM_LIMIT <= i &&
***************
*** 699,705
fix(z) = i;
return(z);
} else
! 			if (--i < 0) {
if (-SMALL_FIXNUM_LIMIT <= i &&
i < SMALL_FIXNUM_LIMIT)
return(small_fixnum(i));

--- 700,707 -----
fix(z) = i;
return(z);
} else
! 			if (i > MOST_NEGATIVE_FIX) {
! 				i--;
if (-SMALL_FIXNUM_LIMIT <= i &&
i < SMALL_FIXNUM_LIMIT)
return(small_fixnum(i));
***************
*** 707,713
fix(z) = i;
return(z);
} else