~ chicken-core (chicken-5) c47ac2643ca05600e7b3a0411e765e385358a6fe


commit c47ac2643ca05600e7b3a0411e765e385358a6fe
Author:     Peter Bex <peter.bex@xs4all.nl>
AuthorDate: Sat Jan 24 18:05:57 2015 +0100
Commit:     Peter Bex <peter@more-magic.net>
CommitDate: Sun May 31 14:10:15 2015 +0200

    Add a few predicates and teach existing ones about extended numbers; add complex constructors.
    
    Added:
    - cplxnum?
    - ratnum?
    - exact-integer?
    - imag-part
    - real-part
    - make-rectangular
    - make-polar
    - infinite?
    - nan?
    - ##sys#check-real
    
    Updated to understand new types:
    - exact? (and ##sys#check-exact)
    - inexact? (and ##sys#check-inexact)
    - integer? (and ##sys#check-integer)
    - real?
    - rational?
    - finite?
    - zero?
    - exact?
    - inexact?
    - negative?
    - positive?
    - odd?
    - even?

diff --git a/c-platform.scm b/c-platform.scm
index 31c0f200..501a2a47 100644
--- a/c-platform.scm
+++ b/c-platform.scm
@@ -145,7 +145,7 @@
     fx= fx> fx< fx>= fx<= fixnum? fxneg fxmax fxmin identity fp+ fp- fp* fp/ fpmin fpmax fpneg
     fp> fp< fp= fp>= fp<= fxand fxnot fxior fxxor fxshr fxshl bit-set? fxodd? fxeven?
     fpfloor fpceiling fptruncate fpround fpsin fpcos fptan fpasin fpacos fpatan
-    fpatan2 fpexp fpexpt fplog fpsqrt fpabs fpinteger?
+    fpatan2 fpexp fpexpt fplog fpsqrt fpabs fpinteger? exact-integer?
     arithmetic-shift void flush-output
     atom? print print* error call/cc
     blob-size u8vector->blob/shared s8vector->blob/shared u16vector->blob/shared
@@ -156,9 +156,8 @@
     blob->f32vector/shared blob->f64vector/shared
     block-ref block-set! number-of-slots substring-index substring-index-ci
     any? read-string substring=? substring-ci=? blob=? equal=?
-    alist-ref rassoc real-part imag-part
-    string->symbol symbol-append
-    make-record-instance foldl foldr
+    alist-ref rassoc make-polar make-rectangular real-part imag-part
+    string->symbol symbol-append make-record-instance foldl foldr
     u8vector-length s8vector-length u16vector-length s16vector-length u32vector-length 
     s32vector-length
     f32vector-length f64vector-length setter
@@ -166,7 +165,7 @@
     f32vector-ref f64vector-ref f32vector-set! f64vector-set!
     u8vector-set! s8vector-set! u16vector-set! s16vector-set! u32vector-set! s32vector-set!
     locative-ref locative-set! locative->object locative?
-    pointer->object flonum? finite? address->pointer pointer->address
+    pointer->object flonum? nan? finite? infinite? address->pointer pointer->address
     pointer+ pointer=?
     pointer-u8-ref pointer-s8-ref pointer-u16-ref pointer-s16-ref
     pointer-u32-ref pointer-s32-ref pointer-f32-ref pointer-f64-ref
@@ -574,20 +573,23 @@
 (rewrite 'number? 2 1 "C_i_numberp" #t)
 (rewrite 'complex? 2 1 "C_i_numberp" #t)
 (rewrite 'rational? 2 1 "C_i_rationalp" #t)
-(rewrite 'real? 2 1 "C_i_numberp" #t)
+(rewrite 'real? 2 1 "C_i_realp" #t)
 (rewrite 'integer? 2 1 "C_i_integerp" #t)
+(rewrite 'exact-integer? 2 1 "C_i_exact_integerp" #t)
 (rewrite 'flonum? 2 1 "C_i_flonump" #t)
 (rewrite 'fixnum? 2 1 "C_fixnump" #t)
 (rewrite 'bignum? 2 1 "C_i_bignump" #t)
+(rewrite 'cplxnum? 2 1 "C_i_cplxnump" #t)
+(rewrite 'ratnum? 2 1 "C_i_ratnump" #t)
+(rewrite 'nan? 2 1 "C_i_nanp" #f)
 (rewrite 'finite? 2 1 "C_i_finitep" #f)
+(rewrite 'infinite? 2 1 "C_i_infinitep" #f)
 (rewrite 'fpinteger? 2 1 "C_u_i_fpintegerp" #f)
 (rewrite '##sys#pointer? 2 1 "C_anypointerp" #t)
 (rewrite 'pointer? 2 1 "C_i_safe_pointerp" #t)
 (rewrite '##sys#generic-structure? 2 1 "C_structurep" #t)
-(rewrite 'exact? 2 1 "C_fixnump" #f)
 (rewrite 'exact? 2 1 "C_i_exactp" #t)
 (rewrite 'exact? 2 1 "C_u_i_exactp" #f)
-(rewrite 'inexact? 2 1 "C_nfixnump" #f)
 (rewrite 'inexact? 2 1 "C_i_inexactp" #t)
 (rewrite 'inexact? 2 1 "C_u_i_inexactp" #f)
 (rewrite 'list? 2 1 "C_i_listp" #t)
diff --git a/chicken.h b/chicken.h
index 2b6e274c..ca25047c 100644
--- a/chicken.h
+++ b/chicken.h
@@ -521,6 +521,7 @@ static inline int isinf_ld (long double x)
 #define C_SWIG_POINTER_TAG        (C_SWIG_POINTER_TYPE | (C_wordstobytes(C_SIZEOF_SWIG_POINTER - 1)))
 #define C_SYMBOL_TAG              (C_SYMBOL_TYPE | (C_SIZEOF_SYMBOL - 1))
 #define C_FLONUM_TAG              (C_FLONUM_TYPE | sizeof(double))
+#define C_STRUCTURE3_TAG          (C_STRUCTURE_TYPE | 3)
 
 /* Locative subtypes */
 #define C_SLOT_LOCATIVE           0
@@ -657,6 +658,9 @@ static inline int isinf_ld (long double x)
 #define C_FLOATING_POINT_EXCEPTION_ERROR              45
 #define C_ILLEGAL_INSTRUCTION_ERROR                   46
 #define C_BUS_ERROR                                   47
+#define C_BAD_ARGUMENT_TYPE_NO_EXACT_ERROR            48
+#define C_BAD_ARGUMENT_TYPE_NO_INEXACT_ERROR          49
+#define C_BAD_ARGUMENT_TYPE_NO_REAL_ERROR             50
 
 
 /* Platform information */
@@ -1157,6 +1161,7 @@ extern double trunc(double);
 
 #define C_isnan(f)                 isnan(f)
 #define C_isinf(f)                 isinf(f)
+#define C_isfinite(f)              isfinite(f)
 
 #ifdef C_STRESS_TEST
 # define C_STRESS_FAILURE          3
@@ -1226,8 +1231,6 @@ extern double trunc(double);
 #define C_eqp(x, y)               C_mk_bool((x) == (y))
 #define C_vemptyp(x)              C_mk_bool(C_header_size(x) == 0)
 #define C_notvemptyp(x)           C_mk_bool(C_header_size(x) > 0)
-#define C_u_i_exactp(x)           C_mk_bool((x) & C_FIXNUM_BIT)
-#define C_u_i_inexactp(x)         C_mk_bool(((x) & C_FIXNUM_BIT) == 0)
 
 #define C_slot(x, i)              C_block_item(x, C_unfix(i))
 #define C_subbyte(x, i)           C_fix(((C_byte *)C_data_pointer(x))[ C_unfix(i) ] & 0xff)
@@ -1408,6 +1411,8 @@ extern double trunc(double);
 #define C_i_equalp(x, y)                C_mk_bool(C_equalp((x), (y)))
 #define C_i_fixnumevenp(x)              C_mk_nbool((x) & 0x00000002)
 #define C_i_fixnumoddp(x)               C_mk_bool((x) & 0x00000002)
+#define C_i_fixnum_negativep(x)         C_mk_bool((x) & C_INT_SIGN_BIT)
+#define C_i_fixnum_positivep(x)         C_mk_bool(!((x) & C_INT_SIGN_BIT) && (x) != C_fix(0))
 #define C_i_nullp(x)                    C_mk_bool((x) == C_SCHEME_END_OF_LIST)
 #define C_i_structurep(x, s)            C_mk_bool(!C_immediatep(x) && C_header_bits(x) == C_STRUCTURE_TYPE && C_block_item(x, 0) == (s))
 
@@ -1659,6 +1664,9 @@ extern double trunc(double);
 #define C_a_i_flonum_log(ptr, c, x)     C_flonum(ptr, C_log(C_flonum_magnitude(x)))
 #define C_a_i_flonum_sqrt(ptr, c, x)    C_flonum(ptr, C_sqrt(C_flonum_magnitude(x)))
 #define C_a_i_flonum_abs(ptr, c, x)     C_flonum(ptr, C_fabs(C_flonum_magnitude(x)))
+#define C_u_i_flonum_nanp(x)            C_mk_bool(C_isnan(C_flonum_magnitude(x)))
+#define C_u_i_flonum_infinitep(x)       C_mk_bool(C_isinf(C_flonum_magnitude(x)))
+#define C_u_i_flonum_finitep(x)         C_mk_bool(C_isfinite(C_flonum_magnitude(x)))
 
 #define C_a_i_current_milliseconds(ptr, c, dummy) C_flonum(ptr, C_milliseconds())
 
@@ -1919,12 +1927,19 @@ C_fctexport C_word C_fcall C_i_set_cdr(C_word p, C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_vector_set(C_word v, C_word i, C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_exactp(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_inexactp(C_word x) C_regparm;
+C_fctexport C_word C_fcall C_i_nanp(C_word x) C_regparm;
+C_fctexport C_word C_fcall C_i_finitep(C_word x) C_regparm;
+C_fctexport C_word C_fcall C_i_infinitep(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_zerop(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_u_i_zerop(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_positivep(C_word x) C_regparm;
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_fctexport C_word C_fcall C_u_i_positivep(C_word x) C_regparm;
+C_fctexport C_word C_fcall C_i_integer_positivep(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_negativep(C_word x) C_regparm;
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_fctexport C_word C_fcall C_u_i_negativep(C_word x) C_regparm;
+C_fctexport C_word C_fcall C_i_integer_negativep(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_car(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_cdr(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_caar(C_word x) C_regparm;
@@ -1936,10 +1951,14 @@ C_fctexport C_word C_fcall C_i_cdddr(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_cadddr(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_cddddr(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_list_tail(C_word lst, C_word i) C_regparm;
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_fctexport C_word C_fcall C_i_evenp(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_u_i_evenp(C_word x) C_regparm;
+C_fctexport C_word C_fcall C_i_integer_evenp(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_oddp(C_word x) C_regparm;
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_fctexport C_word C_fcall C_u_i_oddp(C_word x) C_regparm;
+C_fctexport C_word C_fcall C_i_integer_oddp(C_word x) C_regparm;
 C_fctexport C_word C_fcall C_i_vector_ref(C_word v, C_word i) C_regparm;
 C_fctexport C_word C_fcall C_i_block_ref(C_word x, C_word i) C_regparm;
 C_fctexport C_word C_fcall C_i_string_set(C_word s, C_word i, C_word c) C_regparm;
@@ -2381,23 +2400,37 @@ C_inline C_word C_i_numberp(C_word x)
                    (!C_immediatep(x) && 
                     (C_block_header(x) == C_FLONUM_TAG ||
                      C_header_bits(x) == C_BIGNUM_TYPE ||
-                     (C_header_bits(x) == C_STRUCTURE_TYPE &&
+                     (C_block_header(x) == C_STRUCTURE3_TAG &&
                       (C_block_item(x, 0) == C_ratnum_type_tag ||
                        C_block_item(x, 0) == C_cplxnum_type_tag)))));
 }
 
+/* All numbers are real, except for cplxnums */
+C_inline C_word C_i_realp(C_word x)
+{
+  return C_mk_bool((x & C_FIXNUM_BIT) ||
+                   (!C_immediatep(x) && 
+                    (C_block_header(x) == C_FLONUM_TAG ||
+                     C_header_bits(x) == C_BIGNUM_TYPE ||
+                     (C_header_bits(x) == C_STRUCTURE_TYPE &&
+                      C_block_item(x, 0) == C_ratnum_type_tag))));
+}
 
+/* All finite real numbers are rational */
 C_inline C_word C_i_rationalp(C_word x)
 {
-  if((x & C_FIXNUM_BIT) != 0) return C_SCHEME_TRUE;
-
-  if((!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG)) {
+  if(x & C_FIXNUM_BIT) {
+    return C_SCHEME_TRUE;
+  } else if (C_immediatep(x)) {
+    return C_SCHEME_FALSE;
+  } else if(C_block_header(x) == C_FLONUM_TAG) {
     double n = C_flonum_magnitude(x);
-      
-    if(!C_isinf(n) && !C_isnan(n)) return C_SCHEME_TRUE;
+    return C_mk_bool(!C_isinf(n) && !C_isnan(n));
+  } else {
+    return C_mk_bool(C_header_bits(x) == C_BIGNUM_TYPE ||
+                     (C_header_bits(x) == C_STRUCTURE_TYPE &&
+                      C_block_item(x, 0) == C_ratnum_type_tag));
   }
-
-  return C_SCHEME_FALSE;
 }
 
 
@@ -2420,12 +2453,54 @@ C_inline int C_ub_i_fpintegerp(double x)
   return C_modf(x, &dummy) == 0.0;
 }
 
+C_inline C_word C_i_exact_integerp(C_word x)
+{
+  return C_mk_bool((x) & C_FIXNUM_BIT ||
+                   (!C_immediatep(x) && (C_header_bits(x) == C_BIGNUM_TYPE)));
+}
+
+C_inline C_word C_u_i_exactp(C_word x)
+{
+  if (C_truep(C_i_exact_integerp(x))) {
+    return C_SCHEME_TRUE;
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_SCHEME_FALSE;
+  } else if (C_block_header(x) != C_STRUCTURE3_TAG) {
+    return C_SCHEME_FALSE;
+  } else if (C_block_item(x, 0) == C_ratnum_type_tag) {
+    return C_SCHEME_TRUE;
+  } else if (C_block_item(x, 0) != C_cplxnum_type_tag) {
+    return C_SCHEME_FALSE;
+  } else {
+    x = C_block_item(x, 1);
+    /* r and i are always the same exactness, and we assume they
+     * always store a number.
+     */
+    return C_mk_bool(C_immediatep(x) || (C_block_header(x) != C_FLONUM_TAG));
+  }
+}
+
+C_inline C_word C_u_i_inexactp(C_word x)
+{
+  if (C_immediatep(x)) {
+    return C_SCHEME_FALSE;
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_SCHEME_TRUE;
+  } else if (C_block_header(x) != C_STRUCTURE3_TAG ||
+             C_block_item(x, 0) != C_cplxnum_type_tag) {
+    return C_SCHEME_FALSE;
+  } else {
+    x = C_block_item(x, 1); /* r and i are always the same exactness */
+    return C_mk_bool(!C_immediatep(x) && (C_block_header(x) == C_FLONUM_TAG));
+  }
+}
 
 C_inline C_word C_i_integerp(C_word x)
 {
   double dummy, val;
 
-  if (x & C_FIXNUM_BIT)
+  if (x & C_FIXNUM_BIT ||
+      (!C_immediatep(x) && (C_header_bits(x) == C_BIGNUM_TYPE)))
 	  return C_SCHEME_TRUE;
   if (C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
 	  return C_SCHEME_FALSE;
@@ -2442,16 +2517,18 @@ C_inline C_word C_i_flonump(C_word x)
   return C_mk_bool(!C_immediatep(x) && C_block_header(x) == C_FLONUM_TAG);
 }
 
+C_inline C_word C_i_cplxnump(C_word x)
+{
+  return C_mk_bool(!C_immediatep(x) &&
+                   C_block_header(x) == C_STRUCTURE3_TAG &&
+                   C_block_item(x, 0) == C_cplxnum_type_tag);
+}
 
-C_inline C_word C_i_finitep(C_word x)
+C_inline C_word C_i_ratnump(C_word x)
 {
-  double val;
-  
-  if((x & C_FIXNUM_BIT) != 0) return C_SCHEME_TRUE;
-  
-  val = C_flonum_magnitude(x);
-  if(C_isnan(val) || C_isinf(val)) return C_SCHEME_FALSE;
-  else return C_SCHEME_TRUE;
+  return C_mk_bool(!C_immediatep(x) &&
+                   C_block_header(x) == C_STRUCTURE3_TAG &&
+                   C_block_item(x, 0) == C_ratnum_type_tag);
 }
 
 
diff --git a/chicken.import.scm b/chicken.import.scm
index aea7d7f6..6cceb89c 100644
--- a/chicken.import.scm
+++ b/chicken.import.scm
@@ -73,6 +73,7 @@
    er-macro-transformer
    errno
    error
+   exact-integer?
    exit
    exit-handler
    expand
@@ -159,6 +160,7 @@
    get-properties
    getter-with-setter
    implicit-exit-handler
+   infinite?
    ir-macro-transformer
    keyword->string
    keyword-style
@@ -179,6 +181,7 @@
    module-environment
    most-negative-fixnum
    most-positive-fixnum
+   nan?
    on-exit
    open-input-string
    open-output-string
diff --git a/library.scm b/library.scm
index 269e05d9..5cda691c 100644
--- a/library.scm
+++ b/library.scm
@@ -314,6 +314,12 @@ EOF
      (foreign-value "C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR" int)
      (and (pair? loc) (car loc)) x) ) )
 
+(define (##sys#check-real x . loc)
+  (unless (##core#inline "C_i_realp" x) 
+    (##sys#error-hook
+     (foreign-value "C_BAD_ARGUMENT_TYPE_NO_REAL_ERROR" int)
+     (and (pair? loc) (car loc)) x) ) )
+
 (define (##sys#check-range i from to . loc)
   (##sys#check-exact i loc)
   (unless (and (fx<= from i) (fx< i to))
@@ -431,8 +437,11 @@ EOF
 
 (define (##sys#error-not-a-proper-list arg #!optional loc)
   (##sys#error-hook
-   (foreign-value "C_NOT_A_PROPER_LIST_ERROR" int) 
-   loc arg))
+   (foreign-value "C_NOT_A_PROPER_LIST_ERROR" int) loc arg))
+
+(define (##sys#error-bad-number arg #!optional loc)
+  (##sys#error-hook
+   (foreign-value "C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR" int) loc arg))
 
 (define (append . lsts)
   (if (eq? lsts '())
@@ -748,12 +757,12 @@ EOF
 
 (define (flonum? x) (##core#inline "C_i_flonump" x))
 (define (bignum? x) (##core#inline "C_i_bignump" x))
-(define (ratnum? x) (##sys#structure? x '##sys#ratnum))
-(define (cplxnum? x) (##sys#structure? x '##sys#cplxnum))
+(define (ratnum? x) (##core#inline "C_i_ratnump" x))
+(define (cplxnum? x) (##core#inline "C_i_cplxnump" x))
 
-(define (finite? x) 
-  (##sys#check-number x 'finite?)
-  (##core#inline "C_i_finitep" x) )
+(define (finite? x) (##core#inline "C_i_finitep" x))
+(define (infinite? x) (##core#inline "C_i_infinitep" x))
+(define (nan? x) (##core#inline "C_i_nanp" x))
 
 (define-inline (fp-check-flonum x loc)
   (unless (flonum? x)
@@ -904,9 +913,10 @@ EOF
 (define (number? x) (##core#inline "C_i_numberp" x))
 (define ##sys#number? number?)
 (define complex? number?)
-(define real? number?)
+(define (real? x) (##core#inline "C_i_realp" x))
 (define (rational? n) (##core#inline "C_i_rationalp" n))
 (define (integer? x) (##core#inline "C_i_integerp" x))
+(define (exact-integer? x) (##core#inline "C_i_exact_integerp" x))
 (define ##sys#integer? integer?)
 (define (exact? x) (##core#inline "C_i_exactp" x))
 (define (inexact? x) (##core#inline "C_i_inexactp" x))
@@ -921,19 +931,50 @@ EOF
 (define (negative? n) (##core#inline "C_i_negativep" n))
 (define (abs n) (##core#inline_allocate ("C_a_i_abs" 4) n))	; 4 => words-per-flonum
 
+;;; Complex numbers
+
+(define-inline (%cplxnum-real c) (##sys#slot c 1))
+(define-inline (%cplxnum-imag c) (##sys#slot c 2))
+
+(define-inline (%ratnum-numerator c) (##sys#slot c 1))
+(define-inline (%ratnum-denominator c) (##sys#slot c 2))
+
+(define (make-complex r i)
+  (if (or (eq? i 0) (and (##core#inline "C_i_flonump" i) (fp= i 0.0)))
+      r
+      (##sys#make-structure '##sys#cplxnum
+			    (if (inexact? i) (exact->inexact r) r)
+			    (if (inexact? r) (exact->inexact i) i)) ) )
+
+(define (make-rectangular r i)
+  (##sys#check-real r 'make-rectangular)
+  (##sys#check-real i 'make-rectangular)
+  (make-complex r i) )
+
+(define (make-polar r phi)
+  (##sys#check-real r 'make-polar)
+  (##sys#check-real phi 'make-polar)
+  (let ((fphi (exact->inexact phi)))
+    (make-complex (* r (##core#inline_allocate ("C_a_i_cos" 4) fphi))
+                  (* r (##core#inline_allocate ("C_a_i_sin" 4) fphi)))))
+
+(define (real-part x)
+  (cond ((cplxnum? x) (%cplxnum-real x))
+        ((number? x) x)
+        (else (##sys#error-bad-number x 'real-part))))
+
+(define (imag-part x)
+  (cond ((cplxnum? x) (%cplxnum-imag x))
+        ((##core#inline "C_i_flonump" x) 0.0)
+        ((number? x) 0)
+        (else (##sys#error-bad-number x 'imag-part))))
+
 (define (angle n)
   (##sys#check-number n 'angle)
   (if (< n 0) (fp* 2.0 (acos 0.0)) 0.0) )
 
-(define (real-part n)
-  (##sys#check-number n 'real-part)
-  n)
-
-(define (imag-part n)
-  (##sys#check-number n 'imag-part)
-  0)
 
-;;; Rationals
+;;; Rational numbers
 
 (define-inline (%ratnum-numerator c) (##sys#slot c 1))
 (define-inline (%ratnum-denominator c) (##sys#slot c 2))
@@ -4231,6 +4272,9 @@ EOF
 	((45) (apply ##sys#signal-hook #:arithmetic-error loc "floating-point exception" args))
 	((46) (apply ##sys#signal-hook #:runtime-error loc "illegal instruction" args))
 	((47) (apply ##sys#signal-hook #:memory-error loc "bus error" args))
+	((48) (apply ##sys#signal-hook #:type-error loc "bad argument type - not an exact number" args))
+	((49) (apply ##sys#signal-hook #:type-error loc "bad argument type - not an inexact number" args))
+	((50) (apply ##sys#signal-hook #:type-error loc "bad argument type - not a real" args))
 	(else (apply ##sys#signal-hook #:runtime-error loc "unknown internal error" args)) ) ) ) )
 
 
diff --git a/manual/C interface b/manual/C interface
index 21ef4c69..81caf6f5 100644
--- a/manual/C interface	
+++ b/manual/C interface	
@@ -225,12 +225,30 @@ Is {{x}} a number object (fixnum, bignum, flonum, ratnum, cplxnum)?
 
 Is {{x}} a Scheme bignum object?
 
+===== C_i_cplxnump
+
+ [C function] C_word C_i_cplxnump(C_word x)
+
+Is {{x}} a Scheme cplxnum object?
+
+===== C_i_ratnump
+
+ [C function] C_word C_i_ratnump(C_word x)
+
+Is {{x}} a Scheme ratnum object?
+
 ===== C_i_flonump
 
  [C function] C_word C_i_flonump(C_word x)
 
 Is {{x}} a flonum object?
 
+===== C_i_exact_integerp
+
+ [C macro] C_word C_i_exact_integerp(C_word x)
+
+Is {{x}} an exact integer (i.e., a fixnum or a bignum)?
+
 ===== C_pointerp
 
  [C macro] C_word C_pointerp(C_word x)
@@ -751,21 +769,21 @@ Is the (byte- or heterogenous) vector {{v}} nonempty?
 
 ==== Numbers
 
-These procedures accept any type of number, so you can pass in either
-a fixnum or a flonum.  You shouldn't pass in another type though,
-since that could crash your program.
+These procedures accept any type of number, so you can pass in a
+fixnum, a flonum, a bignum, a ratnum or a cplxnum.  You shouldn't pass
+in another type though, since that could crash your program.
 
 ===== C_u_i_exactp
 
  [C macro] C_word C_u_i_exactp(C_word x)
 
-Is {{x}} an exact number (i.e., a fixnum)?
+Is {{x}} an exact number (i.e., a fixnum, bignum, ratnum or exact cplxnum)?
 
 ===== C_u_i_inexactp
 
  [C macro] C_word C_u_i_inexactp(C_word x)
 
-Is {{x}} an inexact number (i.e., not a fixnum)?
+Is {{x}} an inexact number (i.e., a flonum or an inexact cplxnum)?
 
 ===== C_i_finitep
 
@@ -949,6 +967,20 @@ Returns {{C_SCHEME_TRUE}} when {{n1}} is less than {{n2}},
 Returns {{C_SCHEME_TRUE}} when {{n1}} is less than or equal to
 {{n2}}, {{C_SCHEME_FALSE}} if not.
 
+===== C_i_fixnum_positivep
+
+ [C macro] C_word C_i_fixnum_positivep(C_word n)
+
+Returns {{C_SCHEME_TRUE}} when {{n}} is a positive fixnum,
+{{C_SCHEME_FALSE}} if it is zero or negative.
+
+===== C_i_fixnum_negativep
+
+ [C macro] C_word C_i_fixnum_negativep(C_word n)
+
+Returns {{C_SCHEME_TRUE}} when {{n}} is a negative fixnum,
+{{C_SCHEME_FALSE}} if it is zero or positive.
+
 ===== C_fixnum_increase
 
  [C macro] C_word C_fixnum_increase(C_word n)
@@ -1209,6 +1241,58 @@ Calculates the square root of {{n}}.
 
 Calculates the absolute value of {{n}}.
 
+===== C_u_i_flonum_nanp
+
+ [C macro] C_word C_u_i_flonum_nanp(C_word n)
+
+Is {{n}} a flonum NaN value?
+
+===== C_u_i_flonum_finitep
+
+ [C macro] C_word C_u_i_flonum_finitep(C_word n)
+
+Is {{n}} a finite flonum (i.e., not NaN or one of the infinities)?
+
+===== C_u_i_flonum_infinitep
+
+ [C macro] C_word C_u_i_flonum_infinitep(C_word n)
+
+Is {{n}} an infinite flonum?
+
+==== Exact integers
+
+Often you know a value is an integer, but you don't know whether it's
+a fixnum or a bignum.  In those cases, there are some optimized C
+functions and macros to perform operations on them.
+
+===== C_i_integer_evenp
+
+ [C macro] C_word C_i_integer_evenp(C_word n)
+
+Returns {{C_SCHEME_TRUE}} when {{n}} is an even fixnum or bignum,
+{{C_SCHEME_FALSE}} if it is odd.
+
+===== C_i_integer_oddp
+
+ [C macro] C_word C_i_integer_oddp(C_word n)
+
+Returns {{C_SCHEME_TRUE}} when {{n}} is an odd fixnum or bignum,
+{{C_SCHEME_FALSE}} if it is even.
+
+===== C_i_integer_positivep
+
+ [C macro] C_word C_i_integer_positivep(C_word n)
+
+Returns {{C_SCHEME_TRUE}} when {{n}} is a positive fixnum or bignum,
+{{C_SCHEME_FALSE}} if it is zero or negative.
+
+===== C_i_integer_negativep
+
+ [C macro] C_word C_i_integer_negativep(C_word n)
+
+Returns {{C_SCHEME_TRUE}} when {{n}} is a negative fixnum or bignum,
+{{C_SCHEME_FALSE}} if it is zero or positive.
+
 
 ==== Pointers
 
diff --git a/manual/Deviations from the standard b/manual/Deviations from the standard
index 3be8e714..59570e4e 100644
--- a/manual/Deviations from the standard	
+++ b/manual/Deviations from the standard	
@@ -99,18 +99,6 @@ data other than pairs, strings and vectors.  However, R5RS does not
 dictate the treatment of data types that are not specified by R5RS
 
 
-=== No built-in support for bignums
-
-There is no built-in support for exact rationals, complex
-numbers or extended-precision integers (bignums). The routines
-{{complex?}}, {{real?}} and {{rational?}} are identical to
-the standard procedure {{number?}}. The procedures {{make-rectangular}}
-and {{make-polar}} are not implemented. Fixnums are limited to
-2^<nowiki><sup>30</sup></nowiki> (or 2^<nowiki><sup>62</sup></nowiki>
-on 64-bit hardware).  Support for the full numeric tower is available
-as a separate package (see the {{numbers}} package).
-
-
 === {{transcript-on}} and {{transcript-off}} are not implemented
 
 The {{transcript-on}} and {{transcript-off}} procedures are
diff --git a/manual/Unit library b/manual/Unit library
index 10944eee..c1beed5e 100644
--- a/manual/Unit library	
+++ b/manual/Unit library	
@@ -45,6 +45,13 @@ set, or {{#f}} otherwise. The rightmost/least-significant bit is bit 0.
 Returns {{#t}} if {{X}} is a bignum (integer larger than fits in a
 fixnum), or {{#f}} otherwise.
 
+==== exact-integer?
+
+<procedure>(exact-integer? X)</procedure>
+
+Returns {{#t}} if {{X}} is an exact integer (i.e., a fixnum or a
+bignum), or {{#f}} otherwise.
+
 ==== cplxnum?
 
 <procedure>(cplxnum? X)</procedure>
@@ -224,11 +231,30 @@ all floating-point numbers of a certain precision is given by the
 formula {{ceil(1+N*log10(2))}}, where N is the number of bits of
 precision; for double-precision, {{N=53}}.
 
+==== nan?
+
+<procedure>(nan? N)</procedure>
+
+Returns {{#t}} if {{N}} is not a number (a IEEE flonum NaN-value).  If
+{{N}} is a complex number, it's considered nan if it has a real or
+imaginary component that's nan.
+
+==== finite?
+
+<procedure>(infinite? N)</procedure>
+
+Returns {{#t}} if {{N}} is negative or positive infinity, and {{#f}}
+otherwise.  If {{N}} is a complex number, it's considered infinite if
+it has a real or imaginary component that's infinite.
+
 ==== finite?
 
 <procedure>(finite? N)</procedure>
 
-Returns {{#f}} if {{N}} is negative or positive infinity, and {{#t}} otherwise.
+Returns {{#t}} if {{N}} represents a finite number and {{#f}}
+otherwise.  Positive and negative infinity as well as NaNs are not
+considered finite.  If {{N}} is a complex number, it's considered
+finite if both the real and imaginary components are finite.
 
 ==== signum
 
diff --git a/manual/faq b/manual/faq
index 024e7944..6fb485db 100644
--- a/manual/faq
+++ b/manual/faq
@@ -464,6 +464,8 @@ and compiler settings:
 {{member}}
 {{memq}}
 {{memv}}
+{{make-polar}}
+{{make-rectangular}}
 {{negative?}}
 {{not}}
 {{null?}}
@@ -594,6 +596,7 @@ The following extended bindings are handled specially:
 {{fxshr}}
 {{fxxor}}
 {{identity}}
+{{infinite?}}
 {{list->string}}
 {{list->vector}}
 {{locative->object}}
@@ -601,6 +604,7 @@ The following extended bindings are handled specially:
 {{locative-set!}}
 {{locative?}}
 {{make-record-instance}}
+{{nan?}}
 {{number-of-slots}}
 {{o}}
 {{pointer+}}
diff --git a/modules.scm b/modules.scm
index 102fddc8..a9ee89f0 100644
--- a/modules.scm
+++ b/modules.scm
@@ -893,7 +893,8 @@
 	     close-input-port close-output-port load read eof-object? read-char
 	     peek-char write display write-char newline with-input-from-file
 	     with-output-to-file eval
-	     char-ready? imag-part real-part magnitude numerator denominator
+	     char-ready? imag-part real-part make-rectangular make-polar
+	     magnitude numerator denominator
 	     scheme-report-environment null-environment interaction-environment
 	     else))
       (r4rs-syntax
diff --git a/runtime.c b/runtime.c
index 41748117..627e6639 100644
--- a/runtime.c
+++ b/runtime.c
@@ -1758,6 +1758,21 @@ void barf(int code, char *loc, ...)
     c = 0;
     break;
 
+  case C_BAD_ARGUMENT_TYPE_NO_EXACT_ERROR:
+    msg = C_text("bad argument type - not an exact number");
+    c = 1;
+    break;
+
+  case C_BAD_ARGUMENT_TYPE_NO_INEXACT_ERROR:
+    msg = C_text("bad argument type - not an inexact number");
+    c = 1;
+    break;
+
+  case C_BAD_ARGUMENT_TYPE_NO_REAL_ERROR:
+    msg = C_text("bad argument type - not an real");
+    c = 1;
+    break;
+
   default: panic(C_text("illegal internal error code"));
   }
   
@@ -4663,136 +4678,280 @@ C_word C_fcall C_a_i_smart_mpointer(C_word **ptr, int c, C_word x)
   return (C_word)p0;
 }
 
+C_regparm C_word C_fcall C_i_nanp(C_word x)
+{
+  if (x & C_FIXNUM_BIT) {
+    return C_SCHEME_FALSE;
+  } else if (C_immediatep(x)) {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "nan?", x);
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_u_i_flonum_nanp(x);
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE) {
+    return C_SCHEME_FALSE;
+  } else if (C_block_header(x) == C_STRUCTURE3_TAG) {
+    if (C_block_item(x, 0) == C_ratnum_type_tag)
+      return C_SCHEME_FALSE;
+    else if (C_block_item(x, 0) == C_cplxnum_type_tag)
+      return C_mk_bool(C_truep(C_i_nanp(C_block_item(x, 1))) ||
+		       C_truep(C_i_nanp(C_block_item(x, 2))));
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "nan?", x);
+  } else {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "nan?", x);
+  }
+}
 
-C_regparm C_word C_fcall C_i_exactp(C_word x)
+C_regparm C_word C_fcall C_i_finitep(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_SCHEME_TRUE;
+  if (x & C_FIXNUM_BIT) {
+    return C_SCHEME_TRUE;
+  } else if (C_immediatep(x)) {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "finite?", x);
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_u_i_flonum_finitep(x);
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE) {
+    return C_SCHEME_TRUE;
+  } else if (C_block_header(x) == C_STRUCTURE3_TAG) {
+    if (C_block_item(x, 0) == C_ratnum_type_tag)
+      return C_SCHEME_TRUE;
+    else if (C_block_item(x, 0) == C_cplxnum_type_tag)
+      return C_and(C_i_finitep(C_block_item(x, 1)),
+		   C_i_finitep(C_block_item(x, 2)));
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "finite?", x);
+  } else {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "finite?", x);
+  }
+}
 
-  if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
-    barf(C_BAD_ARGUMENT_TYPE_ERROR, "exact?", x);
+C_regparm C_word C_fcall C_i_infinitep(C_word x)
+{
+  if (x & C_FIXNUM_BIT) {
+    return C_SCHEME_FALSE;
+  } else if (C_immediatep(x)) {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "infinite?", x);
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_u_i_flonum_infinitep(x);
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE) {
+    return C_SCHEME_FALSE;
+  } else if (C_block_header(x) == C_STRUCTURE3_TAG) {
+    if (C_block_item(x, 0) == C_ratnum_type_tag)
+      return C_SCHEME_FALSE;
+    else if (C_block_item(x, 0) == C_cplxnum_type_tag)
+      return C_mk_bool(C_truep(C_i_infinitep(C_block_item(x, 1))) ||
+                       C_truep(C_i_infinitep(C_block_item(x, 2))));
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "infinite?", x);
+  } else {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "infinite?", x);
+  }
+}
 
-  return C_SCHEME_FALSE;
+C_regparm C_word C_fcall C_i_exactp(C_word x)
+{
+  if (x & C_FIXNUM_BIT) {
+    return C_SCHEME_TRUE;
+  } else if (C_immediatep(x)) {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "exact?", x);
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_SCHEME_FALSE;
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE) {
+    return C_SCHEME_TRUE;
+  } else if (C_block_header(x) == C_STRUCTURE3_TAG) {
+    if (C_block_item(x, 0) == C_ratnum_type_tag)
+      return C_SCHEME_TRUE;
+    else if (C_block_item(x, 0) == C_cplxnum_type_tag)
+      return C_i_exactp(C_block_item(x, 1)); /* Exactness of i and r matches */
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "exact?", x);
+  } else {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "exact?", x);
+  }
 }
 
 
 C_regparm C_word C_fcall C_i_inexactp(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_SCHEME_FALSE;
-
-  if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
-    barf(C_BAD_ARGUMENT_TYPE_ERROR, "inexact?", x);
-
-  return C_SCHEME_TRUE;
+  if (x & C_FIXNUM_BIT) {
+    return C_SCHEME_FALSE;
+  } else if (C_immediatep(x)) {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "inexact?", x);
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_SCHEME_TRUE;
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE) {
+    return C_SCHEME_FALSE;
+  } else if (C_block_header(x) == C_STRUCTURE3_TAG) {
+    if (C_block_item(x, 0) == C_ratnum_type_tag)
+      return C_SCHEME_FALSE;
+    else if (C_block_item(x, 0) == C_cplxnum_type_tag)
+      return C_i_inexactp(C_block_item(x, 1)); /* Exactness of i and r matches */
+    else
+      barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "inexact?", x);
+  } else {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "inexact?", x);
+  }
 }
 
 
 C_regparm C_word C_fcall C_i_zerop(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_bool(x == C_fix(0));
-
-  if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
-    barf(C_BAD_ARGUMENT_TYPE_ERROR, "zero?", x);
-
-  return C_mk_bool(C_flonum_magnitude(x) == 0.0);
+  if (x & C_FIXNUM_BIT) {
+    return C_mk_bool(x == C_fix(0));
+  } else if (C_immediatep(x)) {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "zero?", x);
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    return C_mk_bool(C_flonum_magnitude(x) == 0.0);
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE ||
+	     (C_block_header(x) == C_STRUCTURE3_TAG &&
+	      (C_block_item(x, 0) == C_ratnum_type_tag ||
+	       C_block_item(x, 0) == C_cplxnum_type_tag))) {
+    return C_SCHEME_FALSE;
+  } else {
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "zero?", x);
+  }
 }
 
-
 /* I */
 C_regparm C_word C_fcall C_u_i_zerop(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_bool(x == C_fix(0));
-
-  return C_mk_bool(C_flonum_magnitude(x) == 0.0);
+  return C_mk_bool(x == C_fix(0) ||
+                   (!C_immediatep(x) &&
+                    C_block_header(x) == C_FLONUM_TAG &&
+                    C_flonum_magnitude(x) == 0.0));
 }
 
 
 C_regparm C_word C_fcall C_i_positivep(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_bool(C_unfix(x) > 0);
-
-  if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
-    barf(C_BAD_ARGUMENT_TYPE_ERROR, "positive?", x);
-
-  return C_mk_bool(C_flonum_magnitude(x) > 0.0);
+  if (x & C_FIXNUM_BIT)
+    return C_i_fixnum_positivep(x);
+  else if (C_immediatep(x))
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "positive?", x);
+  else if (C_block_header(x) == C_FLONUM_TAG)
+    return C_mk_bool(C_flonum_magnitude(x) > 0.0);
+  else if (C_header_bits(x) == C_BIGNUM_TYPE)
+    return C_mk_nbool(C_bignum_negativep(x));
+  else if (C_block_header(x) == C_STRUCTURE3_TAG &&
+           (C_block_item(x, 0) == C_ratnum_type_tag))
+    return C_i_integer_positivep(C_block_item(x, 1));
+  else if (C_block_header(x) == C_STRUCTURE3_TAG &&
+           (C_block_item(x, 0) == C_cplxnum_type_tag))
+    barf(C_BAD_ARGUMENT_TYPE_NO_REAL_ERROR, "positive?", x);
+  else
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "positive?", x);
 }
 
+C_regparm C_word C_fcall C_i_integer_positivep(C_word x)
+{
+  if (x & C_FIXNUM_BIT) return C_i_fixnum_positivep(x);
+  else return C_mk_nbool(C_bignum_negativep(x));
+}
 
-/* I */
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_regparm C_word C_fcall C_u_i_positivep(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_bool(C_unfix(x) > 0);
-
-  return C_mk_bool(C_flonum_magnitude(x) > 0.0);
+  return C_i_positivep(x);
 }
 
 
 C_regparm C_word C_fcall C_i_negativep(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_bool(C_unfix(x) < 0);
-
-  if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
-    barf(C_BAD_ARGUMENT_TYPE_ERROR, "negative?", x);
-
-  return C_mk_bool(C_flonum_magnitude(x) < 0.0);
+  if (x & C_FIXNUM_BIT)
+    return C_i_fixnum_negativep(x);
+  else if (C_immediatep(x))
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "negative?", x);
+  else if (C_block_header(x) == C_FLONUM_TAG)
+    return C_mk_bool(C_flonum_magnitude(x) < 0.0);
+  else if (C_header_bits(x) == C_BIGNUM_TYPE)
+    return C_mk_bool(C_bignum_negativep(x));
+  else if (C_block_header(x) == C_STRUCTURE3_TAG &&
+           (C_block_item(x, 0) == C_ratnum_type_tag))
+    return C_i_integer_negativep(C_block_item(x, 1));
+  else if (C_block_header(x) == C_STRUCTURE3_TAG &&
+           (C_block_item(x, 0) == C_cplxnum_type_tag))
+    barf(C_BAD_ARGUMENT_TYPE_NO_REAL_ERROR, "negative?", x);
+  else
+    barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, "negative?", x);
 }
 
 
-/* I */
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_regparm C_word C_fcall C_u_i_negativep(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_bool(C_unfix(x) < 0);
+  return C_i_negativep(x);
+}
 
-  return C_mk_bool(C_flonum_magnitude(x) < 0.0);
+C_regparm C_word C_fcall C_i_integer_negativep(C_word x)
+{
+  if (x & C_FIXNUM_BIT) return C_i_fixnum_negativep(x);
+  else return C_mk_bool(C_bignum_negativep(x));
 }
 
 
 C_regparm C_word C_fcall C_i_evenp(C_word x)
 {
-  double val, dummy;
-  if(x & C_FIXNUM_BIT) return C_mk_nbool(x & 0x02);
-
-  if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
-    barf(C_BAD_ARGUMENT_TYPE_ERROR, "even?", x);
-
-  val = C_flonum_magnitude(x);
-  if(C_isnan(val) || C_isinf(val) || C_modf(val, &dummy) != 0.0)
+  if(x & C_FIXNUM_BIT) {
+    return C_i_fixnumevenp(x);
+  } else if(C_immediatep(x)) {
     barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "even?", x);
-
-  return C_mk_bool(fmod(val, 2.0) == 0.0);
+  } else if (C_block_header(x) == C_FLONUM_TAG) {
+    double val, dummy;
+    val = C_flonum_magnitude(x);
+    if(C_isnan(val) || C_isinf(val) || C_modf(val, &dummy) != 0.0)
+      barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "even?", x);
+    else
+      return C_mk_bool(fmod(val, 2.0) == 0.0);
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE) {
+    return C_mk_nbool(C_bignum_digits(x)[0] & 1);
+  } else { /* No need to try extended number */
+    barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "even?", x);
+  }
 }
 
-
-/* I */
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_regparm C_word C_fcall C_u_i_evenp(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_nbool(x & 0x02);
+  return C_i_evenp(x);
+}
 
-  return C_mk_bool(fmod(C_flonum_magnitude(x), 2.0) == 0.0);
+C_regparm C_word C_fcall C_i_integer_evenp(C_word x)
+{
+  if (x & C_FIXNUM_BIT) return C_i_fixnumevenp(x);
+  return C_mk_nbool(C_bignum_digits(x)[0] & 1);
 }
 
 
 C_regparm C_word C_fcall C_i_oddp(C_word x)
 {
-  double val, dummy;
-  if(x & C_FIXNUM_BIT) return C_mk_bool(x & 0x02);
-
-  if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)
-    barf(C_BAD_ARGUMENT_TYPE_ERROR, "odd?", x);
-
-  val = C_flonum_magnitude(x);
-  if(C_isnan(val) || C_isinf(val) || C_modf(val, &dummy) != 0.0)
+  if(x & C_FIXNUM_BIT) {
+    return C_i_fixnumoddp(x);
+  } else if(C_immediatep(x)) {
     barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "odd?", x);
-
-  return C_mk_bool(fmod(val, 2.0) != 0.0);
+  } else if(C_block_header(x) == C_FLONUM_TAG) {
+    double val, dummy;
+    val = C_flonum_magnitude(x);
+    if(C_isnan(val) || C_isinf(val) || C_modf(val, &dummy) != 0.0)
+      barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "odd?", x);
+    else
+      return C_mk_bool(fmod(val, 2.0) != 0.0);
+  } else if (C_header_bits(x) == C_BIGNUM_TYPE) {
+    return C_mk_bool(C_bignum_digits(x)[0] & 1);
+  } else {
+    barf(C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR, "odd?", x);
+  }
 }
 
 
-/* I */
+/* XXX TODO OBSOLETE: This can be removed after recompiling c-platform.scm */
 C_regparm C_word C_fcall C_u_i_oddp(C_word x)
 {
-  if(x & C_FIXNUM_BIT) return C_mk_bool(x & 0x02);
+  return C_i_oddp(x);
+}
 
-  return C_mk_bool(fmod(C_flonum_magnitude(x), 2.0) != 0.0);
+C_regparm C_word C_fcall C_i_integer_oddp(C_word x)
+{
+  if (x & C_FIXNUM_BIT) return C_i_fixnumoddp(x);
+  return C_mk_bool(C_bignum_digits(x)[0] & 1);
 }
 
 
@@ -5559,9 +5718,9 @@ C_regparm C_word C_fcall C_i_check_closure_2(C_word x, C_word loc)
 
 C_regparm C_word C_fcall C_i_check_exact_2(C_word x, C_word loc)
 {
-  if((x & C_FIXNUM_BIT) == 0) {
+  if(C_u_i_exactp(x) == C_SCHEME_FALSE) {
     error_location = loc;
-    barf(C_BAD_ARGUMENT_TYPE_NO_FIXNUM_ERROR, NULL, x);
+    barf(C_BAD_ARGUMENT_TYPE_NO_EXACT_ERROR, NULL, x);
   }
 
   return C_SCHEME_UNDEFINED;
@@ -5572,7 +5731,7 @@ C_regparm C_word C_fcall C_i_check_inexact_2(C_word x, C_word loc)
 {
   if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG) {
     error_location = loc;
-    barf(C_BAD_ARGUMENT_TYPE_NO_FLONUM_ERROR, NULL, x);
+    barf(C_BAD_ARGUMENT_TYPE_NO_INEXACT_ERROR, NULL, x);
   }
 
   return C_SCHEME_UNDEFINED;
@@ -5592,7 +5751,7 @@ C_regparm C_word C_fcall C_i_check_char_2(C_word x, C_word loc)
 
 C_regparm C_word C_fcall C_i_check_number_2(C_word x, C_word loc)
 {
-  if((x & C_FIXNUM_BIT) == 0 && (C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG)) {
+  if (C_i_numberp(x) == C_SCHEME_FALSE) {
     error_location = loc;
     barf(C_BAD_ARGUMENT_TYPE_NO_NUMBER_ERROR, NULL, x);
   }
diff --git a/types.db b/types.db
index e192f488..8a1d30ce 100644
--- a/types.db
+++ b/types.db
@@ -233,36 +233,56 @@
 
 ;;XXX predicate?
 (integer? (#(procedure #:pure #:foldable) integer? (*) boolean)
-	  ((fixnum) (let ((#(tmp) #(1))) '#t))
-	  ((float) (##core#inline "C_u_i_fpintegerp" #(1))))
-
-(real? (#(procedure #:pure #:predicate number) real? (*) boolean))
+	  ((integer) (let ((#(tmp) #(1))) '#t))
+	  ((float) (##core#inline "C_u_i_fpintegerp" #(1)))
+	  ((*) (##core#inline "C_i_integerp" #(1))))
+(exact-integer? (#(procedure #:pure #:foldable) exact-integer? (*) boolean)
+		((integer) (let ((#(tmp) #(1))) '#t))
+		(((not integer)) (let ((#(tmp) #(1))) '#f))
+		((*) (##core#inline "C_i_exact_integerp" #(1))))
+
+(real? (#(procedure #:pure #:foldable) real? (*) boolean)
+       (((or fixnum float bignum ratnum)) (let ((#(tmp) #(1))) '#t))
+       ((cplxnum) (let ((#(tmp) #(1))) '#f))
+       ((*) (##core#inline "C_i_realp" #(1))))
 (complex? (#(procedure #:pure #:predicate number) complex? (*) boolean))
 (exact? (#(procedure #:clean #:enforce #:foldable) exact? (number) boolean)
-        ((fixnum) (let ((#(tmp) #(1))) '#t))
+        (((or integer ratnum)) (let ((#(tmp) #(1))) '#t))
         ((float) (let ((#(tmp) #(1))) '#f)))
 (inexact? (#(procedure #:clean #:enforce #:foldable) inexact? (number) boolean)
-          ((fixnum) (let ((#(tmp) #(1))) '#f))
+          (((or integer ratnum)) (let ((#(tmp) #(1))) '#f))
           ((float) (let ((#(tmp) #(1))) '#t)))
 
 ;;XXX predicate?
 (rational? (#(procedure #:pure #:foldable) rational? (*) boolean)
-	   ((fixnum) (let ((#(tmp) #(1))) '#t)))
+	   (((or fixnum bignum ratnum)) (let ((#(tmp) #(1))) '#t))
+	   ((cplxnum) (let ((#(tmp) #(1))) '#f))
+	   ((float) (##core#inline "C_u_i_flonum_finitep" #(1)))
+	   ((*) (##core#inline "C_i_rationalp" #(1))))
 
 (zero? (#(procedure #:clean #:enforce #:foldable) zero? (number) boolean)
-       ((fixnum) (eq? #(1) '0))
+       ((integer) (eq? #(1) '0))
+       (((or cplxnum ratnum)) '#f)
        ((number) (##core#inline "C_u_i_zerop" #(1))))
 
-(odd? (#(procedure #:clean #:enforce #:foldable) odd? (number) boolean) ((fixnum) (fxodd? #(1))))
-(even? (#(procedure #:clean #:enforce #:foldable) even? (number) boolean) ((fixnum) (fxeven? #(1))))
+(odd? (#(procedure #:clean #:enforce #:foldable) odd? (number) boolean)
+	       ((fixnum) (##core#inline "C_i_fixnumoddp" #(1)))
+               ((integer) (##core#inline "C_i_integer_oddp" #(1)))
+               ((*) (##core#inline "C_i_oddp" #(1))))
+(even? (#(procedure #:clean #:enforce #:foldable) even? (number) boolean)
+	       ((fixnum) (##core#inline "C_i_fixnumevenp" #(1)))
+               ((integer) (##core#inline "C_i_integer_evenp" #(1)))
+               ((*) (##core#inline "C_i_evenp" #(1))))
 
 (positive? (#(procedure #:clean #:enforce #:foldable) positive? (number) boolean)
-	   ((fixnum) (##core#inline "C_fixnum_greaterp" #(1) '0))
-	   ((number) (##core#inline "C_u_i_positivep" #(1))))
+	   ((fixnum) (##core#inline "C_i_fixnum_positivep" #(1)))
+	   ((integer) (##core#inline "C_i_integer_positivep" #(1)))
+	   ((*) (##core#inline "C_i_positivep" #(1))))
 
 (negative? (#(procedure #:clean #:enforce #:foldable) negative? (number) boolean)
-	   ((fixnum) (##core#inline "C_fixnum_lessp" #(1) '0))
-	   ((number) (##core#inline "C_u_i_negativep" #(1))))
+	   ((fixnum) (##core#inline "C_i_fixnum_negativep" #(1)))
+	   ((integer) (##core#inline "C_i_integer_negativep" #(1)))
+	   ((*) (##core#inline "C_i_negativep" #(1))))
 
 (max (#(procedure #:clean #:enforce #:foldable) max (#!rest number) number)
      ((fixnum fixnum) (fxmax #(1) #(2)))
@@ -704,11 +724,14 @@
 (eval (procedure eval (* #!optional (struct environment)) . *))
 (char-ready? (#(procedure #:enforce) char-ready? (#!optional input-port) boolean))
 
-(imag-part (#(procedure #:clean #:enforce #:foldable) imag-part (number) number)
-	   (((or fixnum float number)) (let ((#(tmp) #(1))) '0)))
+(real-part (#(procedure #:clean #:enforce #:foldable) real-part (number) (or integer float ratnum))
+	   (((or fixnum float bignum ratnum)) #(1))
+	   ((cplxnum) (##sys#slot #(1) '1)))
 
-(real-part (#(procedure #:clean #:enforce #:foldable) real-part (number) number)
-	   (((or fixnum float number)) #(1)))
+(imag-part (#(procedure #:clean #:enforce #:foldable) imag-part (number) (or integer float ratnum))
+	   (((or fixnum bignum ratnum)) (let ((#(tmp) #(1))) '0))
+	   ((float) (let ((#(tmp) #(1))) '0.0))
+	   ((cplxnum) (##sys#slot #(1) '2)))
 
 (magnitude (#(procedure #:clean #:enforce) magnitude (number) number)
 	   ((fixnum) (fixnum)
@@ -854,9 +877,20 @@
 (file-exists? (#(procedure #:clean #:enforce) file-exists? (string) (or false string)))
 (directory-exists? (#(procedure #:clean #:enforce) directory-exists? (string) (or false string)))
 
+(nan? (#(procedure #:clean #:enforce #:foldable) nan? (number) boolean)
+      (((or integer ratnum)) (let ((#(tmp) #(1))) '#f))
+      ((float) (##core#inline "C_u_i_flonum_nanp" #(1)))
+      ((*) (##core#inline "C_i_nanp" #(1))))
+
+(infinite? (#(procedure #:clean #:enforce #:foldable) infinite? (number) boolean)
+	   (((or integer ratnum)) (let ((#(tmp) #(1))) '#f))
+	   ((float) (##core#inline "C_u_i_flonum_infinitep" #(1)))
+	   ((*) (##core#inline "C_i_infinitep" #(1))))
+
 (finite? (#(procedure #:clean #:enforce #:foldable) finite? (number) boolean)
-	 ((fixnum) (let ((#(tmp) #(1))) '#t))
-	 (((or float number)) (##core#inline "C_i_finitep" #(1))))
+	 (((or integer ratnum)) (let ((#(tmp) #(1))) '#t))
+	 ((float) (##core#inline "C_u_i_flonum_finitep" #(1)))
+	 ((*) (##core#inline "C_i_finitep" #(1))))
 
 (fixnum-bits fixnum)
 (fixnum-precision fixnum)
Trap