[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Fixnum 1+ 1- fix
The patch I posted last time was the minimal-change fix.
Upon looking it over I realized that there's a much
cleaner way to do it that's clearer and faster than
the original code, whether it had a bug or not.
Simply, for (1+ i) if i is most-positive-fixnum,
then the result is the smallest positive bignum,
otherwise it's still a fixnum, likewise for (1- i)
and most-negative-fixnum. The code doesn't depend
on machine arithmetic (as long as an int can hold
a fixnum), and is shorter and faster.
------- num_arith.c -------
412,432c412,419
< 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));
< z = alloc_object(t_fixnum);
< fix(z) = i;
< return(z);
< } else
< return(bignum2(1, i & MASK));
< else {
< i++;
< if (-SMALL_FIXNUM_LIMIT <= i &&
< i < SMALL_FIXNUM_LIMIT)
< return(small_fixnum(i));
< z = alloc_object(t_fixnum);
< fix(z) = i;
< return(z);
< }
---
> if (i == MOST_POSITIVE_FIX)
> return(bignum2(1, 0));
> i++;
> if (-SMALL_FIXNUM_LIMIT <= i && i < SMALL_FIXNUM_LIMIT)
> return(small_fixnum(i));
> z = alloc_object(t_fixnum);
> fix(z) = i;
> return(z);
691,710c678,685
< if(i == 0)
< return(small_fixnum(-1));
< if(i > 0) {
< i--;
< if (-SMALL_FIXNUM_LIMIT <= i &&
< i < SMALL_FIXNUM_LIMIT)
< return(small_fixnum(i));
< z = alloc_object(t_fixnum);
< fix(z) = i;
< return(z);
< } else
< if (--i < 0) {
< if (-SMALL_FIXNUM_LIMIT <= i &&
< i < SMALL_FIXNUM_LIMIT)
< return(small_fixnum(i));
< z = alloc_object(t_fixnum);
< fix(z) = i;
< return(z);
< } else
< return(bignum2(-2, i & MASK));
---
> if (i == MOST_NEGATIVE_FIX)
> return(bignum2(-2, MOST_POSITIVE_FIX));
> i--;
> if (-SMALL_FIXNUM_LIMIT <= i && i < SMALL_FIXNUM_LIMIT)
> return(small_fixnum(i));
> z = alloc_object(t_fixnum);
> fix(z) = i;
> return(z);