scm_t_inum xx = SCM_I_INUM (x);
if (xx == 0)
- return scm_i_clonebig (y, 0);
+ {
+ /* Must scm_i_normbig here because -SCM_MOST_NEGATIVE_FIXNUM is a
+ bignum, but negating that gives a fixnum. */
+ return scm_i_normbig (scm_i_clonebig (y, 0));
+ }
else
{
int sgn_y = mpz_sgn (SCM_I_BIG_MPZ (y));
{
case 0: return x; break;
case 1: return y; break;
+ /*
+ * The following case (x = -1) is important for more than
+ * just optimization. It handles the case of negating
+ * (+ 1 most-positive-fixnum) aka (- most-negative-fixnum),
+ * which is a bignum that must be changed back into a fixnum.
+ * Failure to do so will cause the following to return #f:
+ * (= most-negative-fixnum (* -1 (- most-negative-fixnum)))
+ */
+ case -1:
+ return scm_difference(y, SCM_UNDEFINED);
+ break;
}
if (SCM_LIKELY (SCM_I_INUMP (y)))
(with-test-prefix/c&e "-"
+ (pass-if "double-negation of fixnum-min: ="
+ (= fixnum-min (- (- fixnum-min))))
+ (pass-if "double-negation of fixnum-min: eqv?"
+ (eqv? fixnum-min (- (- fixnum-min))))
+ (pass-if "double-negation of fixnum-min: equal?"
+ (equal? fixnum-min (- (- fixnum-min))))
+
+ (pass-if "binary double-negation of fixnum-min: ="
+ (= fixnum-min (- 0 (- 0 fixnum-min))))
+ (pass-if "binary double-negation of fixnum-min: eqv?"
+ (eqv? fixnum-min (- 0 (- 0 fixnum-min))))
+ (pass-if "binary double-negation of fixnum-min: equal?"
+ (equal? fixnum-min (- 0 (- 0 fixnum-min))))
+
(pass-if "-inum - +bignum"
(= #x-100000000000000000000000000000001
(- -1 #x100000000000000000000000000000000)))
(with-test-prefix "*"
+ (with-test-prefix "double-negation of fixnum-min"
+ (pass-if (= fixnum-min (* -1 (* -1 fixnum-min))))
+ (pass-if (eqv? fixnum-min (* -1 (* -1 fixnum-min))))
+ (pass-if (equal? fixnum-min (* -1 (* -1 fixnum-min))))
+ (pass-if (= fixnum-min (* (* fixnum-min -1) -1)))
+ (pass-if (eqv? fixnum-min (* (* fixnum-min -1) -1)))
+ (pass-if (equal? fixnum-min (* (* fixnum-min -1) -1))))
+
(with-test-prefix "inum * bignum"
(pass-if "0 * 2^256 = 0"
(with-test-prefix "/"
+ (with-test-prefix "double-negation of fixnum-min"
+ (pass-if (= fixnum-min (/ (/ fixnum-min -1) -1)))
+ (pass-if (eqv? fixnum-min (/ (/ fixnum-min -1) -1)))
+ (pass-if (equal? fixnum-min (/ (/ fixnum-min -1) -1))))
+
(pass-if "documented?"
(documented? /))