diff --git a/runtime.c b/runtime.c
index cf7351e7..56e91c9e 100644
--- a/runtime.c
+++ b/runtime.c
@@ -269,16 +269,24 @@ static C_TLS int timezone;
 #define C_thread_id(x)   C_block_item((x), 14)
 
 
+#ifdef C_SIXTY_FOUR
+# define C_TYPE_HASH_SHIFT           48
+#else
+# define C_TYPE_HASH_SHIFT           16
+#endif
+
 /* A numeric type hash packs the type bits into the bottom 12 bits (regardless of immediate/block type). */
 /* NOTE: Only fixnum-immediates are currently distinguished - to make this more generic one would need to use one more test */
-#define C_type_hash(x)               (((x) & C_IMMEDIATE_MARK_BITS) ? ((x) & C_FIXNUM_BIT) : C_header_bits(x))
+#define C_type_hash(x)               (((x) & C_IMMEDIATE_MARK_BITS) ? ((x) & C_FIXNUM_BIT) : (C_header_bits(x) >> C_TYPE_HASH_SHIFT))
+/* For dyadic procedures (with two arguments), combine both type hashes */
+#define C_dyadic_hash(x, y)          ((x << 16) | y)
 
 /* We only care about numeric type hashes currently */
 #define C_FIXNUM_TYPE_HASH           C_FIXNUM_BIT
-#define C_FLONUM_TYPE_HASH           C_FLONUM_TYPE
-#define C_BIGNUM_TYPE_HASH           C_BIGNUM_TYPE
-#define C_RATNUM_TYPE_HASH           C_RATNUM_TYPE
-#define C_CPLXNUM_TYPE_HASH          C_CPLXNUM_TYPE
+#define C_FLONUM_TYPE_HASH           (C_FLONUM_TYPE >> C_TYPE_HASH_SHIFT)
+#define C_BIGNUM_TYPE_HASH           (C_BIGNUM_TYPE >> C_TYPE_HASH_SHIFT)
+#define C_RATNUM_TYPE_HASH           (C_RATNUM_TYPE >> C_TYPE_HASH_SHIFT)
+#define C_CPLXNUM_TYPE_HASH          (C_CPLXNUM_TYPE >> C_TYPE_HASH_SHIFT)
 
 
 /* Type definitions: */
@@ -8035,110 +8043,95 @@ cplx_times(C_word **ptr, C_word rx, C_word ix, C_word ry, C_word iy)
 C_regparm C_word C_fcall
 C_s_a_i_times(C_word **ptr, C_word n, C_word x, C_word y)
 {
-  switch(C_type_hash(x)) { /* TODO: Use dyadic_hash? */
-  case C_FIXNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return C_a_i_fixnum_times(ptr, 2, x, y);
+  switch(C_dyadic_hash(C_type_hash(x), C_type_hash(y))) {
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_a_i_fixnum_times(ptr, 2, x, y);
 
-    case C_FLONUM_TYPE_HASH:
-      return C_flonum(ptr, (double)C_unfix(x) * C_flonum_magnitude(y));
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_flonum(ptr, (double)C_unfix(x) * C_flonum_magnitude(y));
 
-    case C_BIGNUM_TYPE_HASH:
-      return C_s_a_u_i_integer_times(ptr, 2, x, y);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_times(ptr, 2, x, y);
 
-    case C_RATNUM_TYPE_HASH:
-      return rat_times_integer(ptr, y, x);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return rat_times_integer(ptr, y, x);
 
-    case C_CPLXNUM_TYPE_HASH:
-      return cplx_times(ptr, x, C_fix(0),
-                        C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    return cplx_times(ptr, x, C_fix(0),
+                      C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "*", y);
-    }
 
-    case C_FLONUM_TYPE_HASH:
-      switch(C_type_hash(y)) {
-      case C_FIXNUM_TYPE_HASH:
-        return C_flonum(ptr, C_flonum_magnitude(x) * (double)C_unfix(y));
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_flonum(ptr, C_flonum_magnitude(x) * (double)C_unfix(y));
 
-      case C_FLONUM_TYPE_HASH:
-        return C_a_i_flonum_times(ptr, 2, x, y);
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_a_i_flonum_times(ptr, 2, x, y);
 
-      case C_BIGNUM_TYPE_HASH:
-        return C_flonum(ptr, C_flonum_magnitude(x) * C_bignum_to_double(y));
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_flonum(ptr, C_flonum_magnitude(x) * C_bignum_to_double(y));
 
-      case C_RATNUM_TYPE_HASH:
-        return C_s_a_i_times(ptr, 2, x, C_a_i_exact_to_inexact(ptr, 1, y));
-
-      case C_CPLXNUM_TYPE_HASH:
-      {
-        C_word ab[C_SIZEOF_FLONUM], *a = ab;
-        return cplx_times(ptr, x, C_flonum(&a, 0.0),
-                          C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
-      }
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return C_s_a_i_times(ptr, 2, x, C_a_i_exact_to_inexact(ptr, 1, y));
 
-      default:
-        barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "*", y);
-      }
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word ab[C_SIZEOF_FLONUM], *a = ab;
+    return cplx_times(ptr, x, C_flonum(&a, 0.0),
+                      C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
+  }
 
-    case C_BIGNUM_TYPE_HASH:
-      switch(C_type_hash(y)) {
-      case C_FIXNUM_TYPE_HASH:
-        return C_s_a_u_i_integer_times(ptr, 2, x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_times(ptr, 2, x, y);
 
-      case C_FLONUM_TYPE_HASH:
-        return C_flonum(ptr, C_bignum_to_double(x) * C_flonum_magnitude(y));
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_flonum(ptr, C_bignum_to_double(x) * C_flonum_magnitude(y));
 
-      case C_BIGNUM_TYPE_HASH:
-        return C_s_a_u_i_integer_times(ptr, 2, x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_times(ptr, 2, x, y);
 
-      case C_RATNUM_TYPE_HASH:
-        return rat_times_integer(ptr, y, x);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return rat_times_integer(ptr, y, x);
 
-      case C_CPLXNUM_TYPE_HASH:
-        return cplx_times(ptr, x, C_fix(0),
-                          C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    return cplx_times(ptr, x, C_fix(0),
+                      C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
 
-      default:
-        barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "*", y);
-      }
 
-    case C_RATNUM_TYPE_HASH:
-      switch(C_type_hash(y)) {
-      case C_FIXNUM_TYPE_HASH:
-        return rat_times_integer(ptr, x, y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return rat_times_integer(ptr, x, y);
 
-      case C_FLONUM_TYPE_HASH:
-        return C_s_a_i_times(ptr, 2, C_a_i_exact_to_inexact(ptr, 1, x), y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_s_a_i_times(ptr, 2, C_a_i_exact_to_inexact(ptr, 1, x), y);
 
-      case C_BIGNUM_TYPE_HASH:
-        return rat_times_integer(ptr, x, y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return rat_times_integer(ptr, x, y);
 
-      case C_RATNUM_TYPE_HASH:
-        return rat_times_rat(ptr, x, y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return rat_times_rat(ptr, x, y);
 
-      case C_CPLXNUM_TYPE_HASH:
-        return cplx_times(ptr, x, C_fix(0),
-                          C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    return cplx_times(ptr, x, C_fix(0),
+                      C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
 
-      default:
-        barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "*", y);
-      }
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    return cplx_times(ptr, C_u_i_cplxnum_real(x), C_u_i_cplxnum_imag(x),
+                      C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
 
-    case C_CPLXNUM_TYPE_HASH:
-      if (!C_immediatep(y) && C_block_header(y) == C_CPLXNUM_TAG) {
-        return cplx_times(ptr, C_u_i_cplxnum_real(x), C_u_i_cplxnum_imag(x),
-                          C_u_i_cplxnum_real(y), C_u_i_cplxnum_imag(y));
-      } else {
-        C_word ab[C_SIZEOF_FLONUM], *a = ab, yi;
-        yi = C_truep(C_i_flonump(y)) ? C_flonum(&a,0) : C_fix(0);
-        return cplx_times(ptr, C_u_i_ratnum_num(x), C_u_i_ratnum_denom(x), y, yi);
-      }
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+  {
+    C_word ab[C_SIZEOF_FLONUM], *a = ab, yi;
+    yi = C_truep(C_i_flonump(y)) ? C_flonum(&a,0) : C_fix(0);
+    return cplx_times(ptr, C_u_i_ratnum_num(x), C_u_i_ratnum_denom(x), y, yi);
+  }
 
   default:
-    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "*", x);
+    if (!C_truep(C_i_numberp(x)))
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "*", x);
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "*", y);
   }
 }
 
@@ -8452,129 +8445,115 @@ static C_word rat_plusmin_rat(C_word **ptr, C_word x, C_word y, integer_plusmin_
 C_regparm C_word C_fcall
 C_s_a_i_plus(C_word **ptr, C_word n, C_word x, C_word y)
 {
-  switch(C_type_hash(x)) { /* TODO: Use dyadic_hash? */
-  case C_FIXNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return C_a_i_fixnum_plus(ptr, 2, x, y);
+  switch(C_dyadic_hash(C_type_hash(x), C_type_hash(y))) {
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_a_i_fixnum_plus(ptr, 2, x, y);
 
-    case C_FLONUM_TYPE_HASH:
-      return C_flonum(ptr, (double)C_unfix(x) + C_flonum_magnitude(y));
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_flonum(ptr, (double)C_unfix(x) + C_flonum_magnitude(y));
 
-    case C_BIGNUM_TYPE_HASH:
-      return C_s_a_u_i_integer_plus(ptr, 2, x, y);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_plus(ptr, 2, x, y);
 
-    case C_RATNUM_TYPE_HASH:
-      return rat_plusmin_integer(ptr, y, x, C_s_a_u_i_integer_plus);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return rat_plusmin_integer(ptr, y, x, C_s_a_u_i_integer_plus);
 
-    case C_CPLXNUM_TYPE_HASH:
-    {
-      C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-             imag = C_u_i_cplxnum_imag(y);
-      if (C_truep(C_u_i_inexactp(real_sum)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_sum, imag);
-    }
-
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "+", y);
-    }
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_u_i_cplxnum_imag(y);
+    if (C_truep(C_u_i_inexactp(real_sum)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_sum, imag);
+  }
 
-    case C_FLONUM_TYPE_HASH:
-      switch(C_type_hash(y)) {
-      case C_FIXNUM_TYPE_HASH:
-        return C_flonum(ptr, C_flonum_magnitude(x) + (double)C_unfix(y));
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_flonum(ptr, C_flonum_magnitude(x) + (double)C_unfix(y));
 
-      case C_FLONUM_TYPE_HASH:
-        return C_a_i_flonum_plus(ptr, 2, x, y);
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_a_i_flonum_plus(ptr, 2, x, y);
 
-      case C_BIGNUM_TYPE_HASH:
-        return C_flonum(ptr, C_flonum_magnitude(x)+C_bignum_to_double(y));
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_flonum(ptr, C_flonum_magnitude(x)+C_bignum_to_double(y));
 
-      case C_RATNUM_TYPE_HASH:
-        return C_s_a_i_plus(ptr, 2, x, C_a_i_exact_to_inexact(ptr, 1, y));
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return C_s_a_i_plus(ptr, 2, x, C_a_i_exact_to_inexact(ptr, 1, y));
 
-      case C_CPLXNUM_TYPE_HASH:
-      {
-        C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-          imag = C_u_i_cplxnum_imag(y);
-        if (C_truep(C_u_i_inexactp(real_sum)))
-          imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-        return C_cplxnum(ptr, real_sum, imag);
-      }
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_u_i_cplxnum_imag(y);
+    if (C_truep(C_u_i_inexactp(real_sum)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_sum, imag);
+  }
 
-      default:
-        barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "+", y);
-    }
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_plus(ptr, 2, x, y);
 
-  case C_BIGNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return C_s_a_u_i_integer_plus(ptr, 2, x, y);
-    case C_FLONUM_TYPE_HASH:
-      return C_flonum(ptr, C_bignum_to_double(x)+C_flonum_magnitude(y));
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_flonum(ptr, C_bignum_to_double(x)+C_flonum_magnitude(y));
 
-    case C_BIGNUM_TYPE_HASH:
-      return C_s_a_u_i_integer_plus(ptr, 2, x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_plus(ptr, 2, x, y);
 
-    case C_RATNUM_TYPE_HASH:
-      return rat_plusmin_integer(ptr, y, x, C_s_a_u_i_integer_plus);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return rat_plusmin_integer(ptr, y, x, C_s_a_u_i_integer_plus);
 
-    case C_CPLXNUM_TYPE_HASH:
-    {
-      C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-        imag = C_u_i_cplxnum_imag(y);
-      if (C_truep(C_u_i_inexactp(real_sum)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_sum, imag);
-    }
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_u_i_cplxnum_imag(y);
+    if (C_truep(C_u_i_inexactp(real_sum)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_sum, imag);
+  }
       
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "+", y);
-    }
-
-  case C_RATNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-    case C_BIGNUM_TYPE_HASH:
-      return rat_plusmin_integer(ptr, x, y, C_s_a_u_i_integer_plus);
-
-    case C_FLONUM_TYPE_HASH:
-      return C_s_a_i_plus(ptr, 2, C_a_i_exact_to_inexact(ptr, 1, x), y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return rat_plusmin_integer(ptr, x, y, C_s_a_u_i_integer_plus);
 
-    case C_RATNUM_TYPE_HASH:
-      return rat_plusmin_rat(ptr, x, y, C_s_a_u_i_integer_plus);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_s_a_i_plus(ptr, 2, C_a_i_exact_to_inexact(ptr, 1, x), y);
 
-    case C_CPLXNUM_TYPE_HASH:
-    {
-      C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-        imag = C_u_i_cplxnum_imag(y);
-      if (C_truep(C_u_i_inexactp(real_sum)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_sum, imag);
-    }
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return rat_plusmin_rat(ptr, x, y, C_s_a_u_i_integer_plus);
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "+", y);
-    }
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_sum = C_s_a_i_plus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_u_i_cplxnum_imag(y);
+    if (C_truep(C_u_i_inexactp(real_sum)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_sum, imag);
+  }
 
-  case C_CPLXNUM_TYPE_HASH:
-    if (!C_immediatep(y) && C_block_header(y) == C_CPLXNUM_TAG) {
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
       C_word real_sum, imag_sum;
       real_sum = C_s_a_i_plus(ptr, 2, C_u_i_cplxnum_real(x), C_u_i_cplxnum_real(y));
       imag_sum = C_s_a_i_plus(ptr, 2, C_u_i_cplxnum_imag(x), C_u_i_cplxnum_imag(y));
       if (C_truep(C_u_i_zerop2(imag_sum))) return real_sum;
       else return C_cplxnum(ptr, real_sum, imag_sum);
-    } else {
-      C_word real_sum = C_s_a_i_plus(ptr, 2, C_u_i_cplxnum_real(x), y),
-        imag = C_u_i_cplxnum_imag(x);
-      if (C_truep(C_u_i_inexactp(real_sum)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_sum, imag);
-    }
+  }
+
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+  {
+    C_word real_sum = C_s_a_i_plus(ptr, 2, C_u_i_cplxnum_real(x), y),
+      imag = C_u_i_cplxnum_imag(x);
+    if (C_truep(C_u_i_inexactp(real_sum)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_sum, imag);
+  }
 
   default:
-    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "+", x);
+    if (!C_truep(C_i_numberp(x)))
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "+", x);
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "+", y);
   }
 }
 
@@ -8688,132 +8667,117 @@ static C_word bignum_minus_unsigned(C_word **ptr, C_word x, C_word y)
 C_regparm C_word C_fcall
 C_s_a_i_minus(C_word **ptr, C_word n, C_word x, C_word y)
 {
-  switch(C_type_hash(x)) { /* TODO: Use dyadic_hash? */
-  case C_FIXNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return C_a_i_fixnum_difference(ptr, 2, x, y);
-
-    case C_FLONUM_TYPE_HASH:
-      return C_flonum(ptr, (double)C_unfix(x) - C_flonum_magnitude(y));
-
-    case C_BIGNUM_TYPE_HASH:
-      return C_s_a_u_i_integer_minus(ptr, 2, x, y);
+  switch(C_dyadic_hash(C_type_hash(x), C_type_hash(y))) {
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_a_i_fixnum_difference(ptr, 2, x, y);
 
-    case C_RATNUM_TYPE_HASH:
-      return integer_minus_rat(ptr, x, y);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_flonum(ptr, (double)C_unfix(x) - C_flonum_magnitude(y));
 
-    case C_CPLXNUM_TYPE_HASH:
-    {
-      C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-             imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
-      if (C_truep(C_u_i_inexactp(real_diff)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_diff, imag);
-    }
-
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "-", y);
-    }
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_minus(ptr, 2, x, y);
 
-  case C_FLONUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return C_flonum(ptr, C_flonum_magnitude(x) - (double)C_unfix(y));
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return integer_minus_rat(ptr, x, y);
 
-    case C_FLONUM_TYPE_HASH:
-      return C_a_i_flonum_difference(ptr, 2, x, y);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
+    if (C_truep(C_u_i_inexactp(real_diff)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_diff, imag);
+  }
 
-    case C_BIGNUM_TYPE_HASH:
-      return C_flonum(ptr, C_flonum_magnitude(x)-C_bignum_to_double(y));
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_flonum(ptr, C_flonum_magnitude(x) - (double)C_unfix(y));
 
-    case C_RATNUM_TYPE_HASH:
-      return C_s_a_i_minus(ptr, 2, x, C_a_i_exact_to_inexact(ptr, 1, y));
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_a_i_flonum_difference(ptr, 2, x, y);
 
-    case C_CPLXNUM_TYPE_HASH:
-    {
-      C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-             imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
-      if (C_truep(C_u_i_inexactp(real_diff)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_diff, imag);
-    }
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_flonum(ptr, C_flonum_magnitude(x)-C_bignum_to_double(y));
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "-", y);
-    }
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return C_s_a_i_minus(ptr, 2, x, C_a_i_exact_to_inexact(ptr, 1, y));
 
-  case C_BIGNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return C_s_a_u_i_integer_minus(ptr, 2, x, y);
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
+    if (C_truep(C_u_i_inexactp(real_diff)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_diff, imag);
+  }
 
-    case C_FLONUM_TYPE_HASH:
-      return C_flonum(ptr, C_bignum_to_double(x)-C_flonum_magnitude(y));
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_minus(ptr, 2, x, y);
 
-    case C_BIGNUM_TYPE_HASH:
-      return C_s_a_u_i_integer_minus(ptr, 2, x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_flonum(ptr, C_bignum_to_double(x)-C_flonum_magnitude(y));
 
-    case C_RATNUM_TYPE_HASH:
-      return integer_minus_rat(ptr, x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_s_a_u_i_integer_minus(ptr, 2, x, y);
 
-    case C_CPLXNUM_TYPE_HASH:
-    {
-      C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-             imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
-      if (C_truep(C_u_i_inexactp(real_diff)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_diff, imag);
-    }
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return integer_minus_rat(ptr, x, y);
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "-", y);
-    }
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
+    if (C_truep(C_u_i_inexactp(real_diff)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_diff, imag);
+  }
 
-  case C_RATNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return rat_plusmin_integer(ptr, x, y, C_s_a_u_i_integer_minus);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return rat_plusmin_integer(ptr, x, y, C_s_a_u_i_integer_minus);
 
-    case C_FLONUM_TYPE_HASH:
-      return C_s_a_i_minus(ptr, 2, C_a_i_exact_to_inexact(ptr, 1, x), y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return C_s_a_i_minus(ptr, 2, C_a_i_exact_to_inexact(ptr, 1, x), y);
 
-    case C_BIGNUM_TYPE_HASH:
-      return rat_plusmin_integer(ptr, x, y, C_s_a_u_i_integer_minus);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return rat_plusmin_integer(ptr, x, y, C_s_a_u_i_integer_minus);
 
-    case C_RATNUM_TYPE_HASH:
-      return rat_plusmin_rat(ptr, x, y, C_s_a_u_i_integer_minus);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return rat_plusmin_rat(ptr, x, y, C_s_a_u_i_integer_minus);
 
-    case C_CPLXNUM_TYPE_HASH:
-    {
-      C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
-             imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
-      if (C_truep(C_u_i_inexactp(real_diff)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_diff, imag);
-    }
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_diff = C_s_a_i_minus(ptr, 2, x, C_u_i_cplxnum_real(y)),
+      imag = C_s_a_i_negate(ptr, 1, C_u_i_cplxnum_imag(y));
+    if (C_truep(C_u_i_inexactp(real_diff)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_diff, imag);
+  }
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "-", y);
-    }
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+  {
+    C_word real_diff, imag_diff;
+    real_diff = C_s_a_i_minus(ptr,2,C_u_i_cplxnum_real(x),C_u_i_cplxnum_real(y));
+    imag_diff = C_s_a_i_minus(ptr,2,C_u_i_cplxnum_imag(x),C_u_i_cplxnum_imag(y));
+    if (C_truep(C_u_i_zerop2(imag_diff))) return real_diff;
+    else return C_cplxnum(ptr, real_diff, imag_diff);
+  }
 
-  case C_CPLXNUM_TYPE_HASH:
-    if (!C_immediatep(y) && C_block_header(y) == C_CPLXNUM_TAG) {
-      C_word real_diff, imag_diff;
-      real_diff = C_s_a_i_minus(ptr,2,C_u_i_cplxnum_real(x),C_u_i_cplxnum_real(y));
-      imag_diff = C_s_a_i_minus(ptr,2,C_u_i_cplxnum_imag(x),C_u_i_cplxnum_imag(y));
-      if (C_truep(C_u_i_zerop2(imag_diff))) return real_diff;
-      else return C_cplxnum(ptr, real_diff, imag_diff);
-    } else {
-      C_word real_diff = C_s_a_i_minus(ptr, 2, C_u_i_cplxnum_real(x), y),
-             imag = C_u_i_cplxnum_imag(x);
-      if (C_truep(C_u_i_inexactp(real_diff)))
-        imag = C_a_i_exact_to_inexact(ptr, 1, imag);
-      return C_cplxnum(ptr, real_diff, imag);
-    }
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+  {
+    C_word real_diff = C_s_a_i_minus(ptr, 2, C_u_i_cplxnum_real(x), y),
+      imag = C_u_i_cplxnum_imag(x);
+    if (C_truep(C_u_i_inexactp(real_diff)))
+      imag = C_a_i_exact_to_inexact(ptr, 1, imag);
+    return C_cplxnum(ptr, real_diff, imag);
+  }
 
   default:
-    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "-", x);
+    if (!C_truep(C_i_numberp(x)))
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "-", x);
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "-", y);
   }
 }
 
@@ -9722,139 +9686,117 @@ static C_word flo_rat_cmp(C_word flonum, C_word ratnum)
  */
 static C_word basic_cmp(C_word x, C_word y, char *loc, int eqp)
 {
-  switch(C_type_hash(x)) { /* TODO: Use dyadic_hash? */
-  case C_FIXNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return C_fix((x < y) ? -1 : ((x > y) ? 1 : 0));
+  switch(C_dyadic_hash(C_type_hash(x), C_type_hash(y))) {
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return C_fix((x < y) ? -1 : ((x > y) ? 1 : 0));
 
-    case C_FLONUM_TYPE_HASH:
-      return int_flo_cmp(x, y);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return int_flo_cmp(x, y);
 
-    case C_BIGNUM_TYPE_HASH:
-    {
-      C_word ab[C_SIZEOF_FIX_BIGNUM], *a = ab;
-      return C_i_bignum_cmp(C_a_u_i_fix_to_big(&a, x), y);
-    }
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+  {
+    C_word ab[C_SIZEOF_FIX_BIGNUM], *a = ab;
+    return C_i_bignum_cmp(C_a_u_i_fix_to_big(&a, x), y);
+  }
 
-    case C_RATNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else return rat_cmp(x, y);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else return rat_cmp(x, y);
 
-    case C_CPLXNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
+  case C_dyadic_hash(C_FIXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, y);
-    }
-
-  case C_FLONUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      return flo_int_cmp(x, y);
 
-    case C_FLONUM_TYPE_HASH:
-    {
-      double a = C_flonum_magnitude(x), b = C_flonum_magnitude(y);
-      if (C_isnan(a) || C_isnan(b)) return C_SCHEME_FALSE; /* "mu" */
-      else return C_fix((a < b) ? -1 : ((a > b) ? 1 : 0));
-    }
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    return flo_int_cmp(x, y);
 
-    case C_BIGNUM_TYPE_HASH:
-      return flo_int_cmp(x, y);
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+  {
+    double a = C_flonum_magnitude(x), b = C_flonum_magnitude(y);
+    if (C_isnan(a) || C_isnan(b)) return C_SCHEME_FALSE; /* "mu" */
+    else return C_fix((a < b) ? -1 : ((a > b) ? 1 : 0));
+  }
 
-    case C_RATNUM_TYPE_HASH:
-      return flo_rat_cmp(x, y);
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return flo_int_cmp(x, y);
 
-    case C_CPLXNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    return flo_rat_cmp(x, y);
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, y);
-    }
+  case C_dyadic_hash(C_FLONUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
 
-  case C_BIGNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-    {
-      C_word ab[C_SIZEOF_FIX_BIGNUM], *a = ab;
-      return C_i_bignum_cmp(x, C_a_u_i_fix_to_big(&a, y));
-    }
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+  {
+    C_word ab[C_SIZEOF_FIX_BIGNUM], *a = ab;
+    return C_i_bignum_cmp(x, C_a_u_i_fix_to_big(&a, y));
+  }
 
-    case C_FLONUM_TYPE_HASH:
-      return int_flo_cmp(x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return int_flo_cmp(x, y);
 
-    case C_BIGNUM_TYPE_HASH:
-      return C_i_bignum_cmp(x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    return C_i_bignum_cmp(x, y);
 
-    case C_RATNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else return rat_cmp(x, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else return rat_cmp(x, y);
 
-    case C_CPLXNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
+  case C_dyadic_hash(C_BIGNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, y);
-    }
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else return rat_cmp(x, y);
 
-  case C_RATNUM_TYPE_HASH:
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else return rat_cmp(x, y);
-
-    case C_FLONUM_TYPE_HASH:
-      return rat_flo_cmp(x, y);
-
-    case C_BIGNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else return rat_cmp(x, y);
-
-    case C_RATNUM_TYPE_HASH:
-      if (eqp) {
-        return C_and(C_and(C_i_integer_equalp(C_u_i_ratnum_num(x),
-                                              C_u_i_ratnum_num(y)),
-                           C_i_integer_equalp(C_u_i_ratnum_denom(x),
-                                              C_u_i_ratnum_denom(y))),
-                     C_fix(0));
-      } else {
-        return rat_cmp(x, y);
-      }
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+    return rat_flo_cmp(x, y);
 
-    case C_CPLXNUM_TYPE_HASH:
-      if (eqp) return C_SCHEME_FALSE;
-      else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else return rat_cmp(x, y);
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, y);
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
+    if (eqp) {
+      return C_and(C_and(C_i_integer_equalp(C_u_i_ratnum_num(x),
+                                            C_u_i_ratnum_num(y)),
+                         C_i_integer_equalp(C_u_i_ratnum_denom(x),
+                                            C_u_i_ratnum_denom(y))),
+                   C_fix(0));
+    } else {
+      return rat_cmp(x, y);
     }
 
-  case C_CPLXNUM_TYPE_HASH:
+  case C_dyadic_hash(C_RATNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    if (eqp) return C_SCHEME_FALSE;
+    else barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, y);
+
+
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FIXNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_FLONUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_BIGNUM_TYPE_HASH):
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_RATNUM_TYPE_HASH):
     if (!eqp)
       barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, x);
-
-    switch(C_type_hash(y)) {
-    case C_FIXNUM_TYPE_HASH:
-    case C_FLONUM_TYPE_HASH:
-    case C_BIGNUM_TYPE_HASH:
-    case C_RATNUM_TYPE_HASH:
+    else
       return C_SCHEME_FALSE;
 
-    case C_CPLXNUM_TYPE_HASH:
+  case C_dyadic_hash(C_CPLXNUM_TYPE_HASH, C_CPLXNUM_TYPE_HASH):
+    if (!eqp)
+      barf(C_BAD_ARGUMENT_TYPE_COMPLEX_NO_ORDERING_ERROR, loc, x);
+    else
       return C_and(C_and(C_i_nequalp(C_u_i_cplxnum_real(x), C_u_i_cplxnum_real(y)),
                          C_i_nequalp(C_u_i_cplxnum_imag(x), C_u_i_cplxnum_imag(y))),
                    C_fix(0));
 
-    default:
-      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, y);
-    }
-
   default:
-    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, x);
+    if (!C_truep(C_i_numberp(x)))
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, x);
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, loc, y);
   }
 }
 
