+ else if (SCM_BIGP (x))
+ {
+ if (SCM_I_INUMP (y))
+ return SCM_BOOL_F;
+ else if (SCM_BIGP (y))
+ {
+ int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
+ scm_remember_upto_here_2 (x, y);
+ return scm_from_bool (0 == cmp);
+ }
+ else if (SCM_REALP (y))
+ {
+ int cmp;
+ if (xisnan (SCM_REAL_VALUE (y)))
+ return SCM_BOOL_F;
+ cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
+ scm_remember_upto_here_1 (x);
+ return scm_from_bool (0 == cmp);
+ }
+ else if (SCM_COMPLEXP (y))
+ {
+ int cmp;
+ if (0.0 != SCM_COMPLEX_IMAG (y))
+ return SCM_BOOL_F;
+ if (xisnan (SCM_COMPLEX_REAL (y)))
+ return SCM_BOOL_F;
+ cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_COMPLEX_REAL (y));
+ scm_remember_upto_here_1 (x);
+ return scm_from_bool (0 == cmp);
+ }
+ else if (SCM_FRACTIONP (y))
+ return SCM_BOOL_F;
+ else
+ SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
+ }
+ else if (SCM_REALP (x))
+ {
+ double xx = SCM_REAL_VALUE (x);
+ if (SCM_I_INUMP (y))
+ {
+ /* see comments with inum/real above */
+ long yy = SCM_I_INUM (y);
+ return scm_from_bool (xx == (double) yy
+ && (DBL_MANT_DIG >= SCM_I_FIXNUM_BIT-1
+ || (long) xx == yy));
+ }
+ else if (SCM_BIGP (y))
+ {
+ int cmp;
+ if (xisnan (SCM_REAL_VALUE (x)))
+ return SCM_BOOL_F;
+ cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
+ scm_remember_upto_here_1 (y);
+ return scm_from_bool (0 == cmp);
+ }
+ else if (SCM_REALP (y))
+ return scm_from_bool (SCM_REAL_VALUE (x) == SCM_REAL_VALUE (y));
+ else if (SCM_COMPLEXP (y))
+ return scm_from_bool ((SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y))
+ && (0.0 == SCM_COMPLEX_IMAG (y)));
+ else if (SCM_FRACTIONP (y))
+ {
+ double xx = SCM_REAL_VALUE (x);
+ if (xisnan (xx))
+ return SCM_BOOL_F;
+ if (xisinf (xx))
+ return scm_from_bool (xx < 0.0);
+ x = scm_inexact_to_exact (x); /* with x as frac or int */
+ goto again;
+ }
+ else
+ SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
+ }
+ else if (SCM_COMPLEXP (x))
+ {
+ if (SCM_I_INUMP (y))
+ return scm_from_bool ((SCM_COMPLEX_REAL (x) == (double) SCM_I_INUM (y))
+ && (SCM_COMPLEX_IMAG (x) == 0.0));
+ else if (SCM_BIGP (y))
+ {
+ int cmp;
+ if (0.0 != SCM_COMPLEX_IMAG (x))
+ return SCM_BOOL_F;
+ if (xisnan (SCM_COMPLEX_REAL (x)))
+ return SCM_BOOL_F;
+ cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_COMPLEX_REAL (x));
+ scm_remember_upto_here_1 (y);
+ return scm_from_bool (0 == cmp);
+ }
+ else if (SCM_REALP (y))
+ return scm_from_bool ((SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y))
+ && (SCM_COMPLEX_IMAG (x) == 0.0));
+ else if (SCM_COMPLEXP (y))
+ return scm_from_bool ((SCM_COMPLEX_REAL (x) == SCM_COMPLEX_REAL (y))
+ && (SCM_COMPLEX_IMAG (x) == SCM_COMPLEX_IMAG (y)));
+ else if (SCM_FRACTIONP (y))
+ {
+ double xx;
+ if (SCM_COMPLEX_IMAG (x) != 0.0)
+ return SCM_BOOL_F;
+ xx = SCM_COMPLEX_REAL (x);
+ if (xisnan (xx))
+ return SCM_BOOL_F;
+ if (xisinf (xx))
+ return scm_from_bool (xx < 0.0);
+ x = scm_inexact_to_exact (x); /* with x as frac or int */
+ goto again;
+ }
+ else
+ SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
+ }
+ else if (SCM_FRACTIONP (x))
+ {
+ if (SCM_I_INUMP (y))
+ return SCM_BOOL_F;
+ else if (SCM_BIGP (y))
+ return SCM_BOOL_F;
+ else if (SCM_REALP (y))
+ {
+ double yy = SCM_REAL_VALUE (y);
+ if (xisnan (yy))
+ return SCM_BOOL_F;
+ if (xisinf (yy))
+ return scm_from_bool (0.0 < yy);
+ y = scm_inexact_to_exact (y); /* with y as frac or int */
+ goto again;
+ }
+ else if (SCM_COMPLEXP (y))
+ {
+ double yy;
+ if (SCM_COMPLEX_IMAG (y) != 0.0)
+ return SCM_BOOL_F;
+ yy = SCM_COMPLEX_REAL (y);
+ if (xisnan (yy))
+ return SCM_BOOL_F;
+ if (xisinf (yy))
+ return scm_from_bool (0.0 < yy);
+ y = scm_inexact_to_exact (y); /* with y as frac or int */
+ goto again;
+ }
+ else if (SCM_FRACTIONP (y))
+ return scm_i_fraction_equalp (x, y);
+ else
+ SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARGn, s_eq_p);
+ }
+ else
+ SCM_WTA_DISPATCH_2 (g_eq_p, x, y, SCM_ARG1, s_eq_p);
+}
+
+
+/* OPTIMIZE-ME: For int/frac and frac/frac compares, the multiplications
+ done are good for inums, but for bignums an answer can almost always be
+ had by just examining a few high bits of the operands, as done by GMP in
+ mpq_cmp. flonum/frac compares likewise, but with the slight complication
+ of the float exponent to take into account. */
+
+SCM_GPROC1 (s_less_p, "<", scm_tc7_rpsubr, scm_less_p, g_less_p);
+/* "Return @code{#t} if the list of parameters is monotonically\n"
+ * "increasing."
+ */
+SCM
+scm_less_p (SCM x, SCM y)
+{
+ again:
+ if (SCM_I_INUMP (x))
+ {
+ long xx = SCM_I_INUM (x);
+ if (SCM_I_INUMP (y))
+ {
+ long yy = SCM_I_INUM (y);
+ return scm_from_bool (xx < yy);
+ }
+ else if (SCM_BIGP (y))
+ {
+ int sgn = mpz_sgn (SCM_I_BIG_MPZ (y));
+ scm_remember_upto_here_1 (y);
+ return scm_from_bool (sgn > 0);
+ }
+ else if (SCM_REALP (y))
+ return scm_from_bool ((double) xx < SCM_REAL_VALUE (y));
+ else if (SCM_FRACTIONP (y))
+ {
+ /* "x < a/b" becomes "x*b < a" */
+ int_frac:
+ x = scm_product (x, SCM_FRACTION_DENOMINATOR (y));
+ y = SCM_FRACTION_NUMERATOR (y);
+ goto again;
+ }
+ else
+ SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
+ }
+ else if (SCM_BIGP (x))
+ {
+ if (SCM_I_INUMP (y))
+ {
+ int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
+ scm_remember_upto_here_1 (x);
+ return scm_from_bool (sgn < 0);
+ }
+ else if (SCM_BIGP (y))
+ {
+ int cmp = mpz_cmp (SCM_I_BIG_MPZ (x), SCM_I_BIG_MPZ (y));
+ scm_remember_upto_here_2 (x, y);
+ return scm_from_bool (cmp < 0);
+ }
+ else if (SCM_REALP (y))
+ {
+ int cmp;
+ if (xisnan (SCM_REAL_VALUE (y)))
+ return SCM_BOOL_F;
+ cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (x), SCM_REAL_VALUE (y));
+ scm_remember_upto_here_1 (x);
+ return scm_from_bool (cmp < 0);
+ }
+ else if (SCM_FRACTIONP (y))
+ goto int_frac;
+ else
+ SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
+ }
+ else if (SCM_REALP (x))
+ {
+ if (SCM_I_INUMP (y))
+ return scm_from_bool (SCM_REAL_VALUE (x) < (double) SCM_I_INUM (y));
+ else if (SCM_BIGP (y))
+ {
+ int cmp;
+ if (xisnan (SCM_REAL_VALUE (x)))
+ return SCM_BOOL_F;
+ cmp = xmpz_cmp_d (SCM_I_BIG_MPZ (y), SCM_REAL_VALUE (x));
+ scm_remember_upto_here_1 (y);
+ return scm_from_bool (cmp > 0);
+ }
+ else if (SCM_REALP (y))
+ return scm_from_bool (SCM_REAL_VALUE (x) < SCM_REAL_VALUE (y));
+ else if (SCM_FRACTIONP (y))
+ {
+ double xx = SCM_REAL_VALUE (x);
+ if (xisnan (xx))
+ return SCM_BOOL_F;
+ if (xisinf (xx))
+ return scm_from_bool (xx < 0.0);
+ x = scm_inexact_to_exact (x); /* with x as frac or int */
+ goto again;
+ }
+ else
+ SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
+ }
+ else if (SCM_FRACTIONP (x))
+ {
+ if (SCM_I_INUMP (y) || SCM_BIGP (y))
+ {
+ /* "a/b < y" becomes "a < y*b" */
+ y = scm_product (y, SCM_FRACTION_DENOMINATOR (x));
+ x = SCM_FRACTION_NUMERATOR (x);
+ goto again;
+ }
+ else if (SCM_REALP (y))
+ {
+ double yy = SCM_REAL_VALUE (y);
+ if (xisnan (yy))
+ return SCM_BOOL_F;
+ if (xisinf (yy))
+ return scm_from_bool (0.0 < yy);
+ y = scm_inexact_to_exact (y); /* with y as frac or int */
+ goto again;
+ }
+ else if (SCM_FRACTIONP (y))
+ {
+ /* "a/b < c/d" becomes "a*d < c*b" */
+ SCM new_x = scm_product (SCM_FRACTION_NUMERATOR (x),
+ SCM_FRACTION_DENOMINATOR (y));
+ SCM new_y = scm_product (SCM_FRACTION_NUMERATOR (y),
+ SCM_FRACTION_DENOMINATOR (x));
+ x = new_x;
+ y = new_y;
+ goto again;
+ }
+ else
+ SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARGn, s_less_p);
+ }
+ else
+ SCM_WTA_DISPATCH_2 (g_less_p, x, y, SCM_ARG1, s_less_p);
+}
+
+
+SCM_GPROC1 (s_scm_gr_p, ">", scm_tc7_rpsubr, scm_gr_p, g_gr_p);
+/* "Return @code{#t} if the list of parameters is monotonically\n"
+ * "decreasing."
+ */
+#define FUNC_NAME s_scm_gr_p
+SCM
+scm_gr_p (SCM x, SCM y)
+{