Primitive ratnum operations implemented.
[scheme.forth.jl.git] / src / scheme-library.scm
index 484f500..85580fd 100644 (file)
@@ -2,10 +2,11 @@
 ;; Standard Library Procedures and Macros ;; 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 ;; Standard Library Procedures and Macros ;; 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;; LISTS
+;; MISC
+
+(define (not x) (if x #f #t))
 
 
-(define (null? args)
-  (eq? args ()))
+(define (list . args) args)
 
 (define (caar l) (car (car l)))
 (define (cadr l) (car (cdr l)))
 
 (define (caar l) (car (car l)))
 (define (cadr l) (car (cdr l)))
 (define (cddr l) (cdr (cdr l)))
 (define (cadar l) (car (cdr (car l))))
 
 (define (cddr l) (cdr (cdr l)))
 (define (cadar l) (car (cdr (car l))))
 
+
+;; NUMBERS
+
+; Rational primitives
+
+(define (numerator x)
+  (if (ratnum? x)
+    (rat:numerator x)
+    x))
+
+(define (denominator x)
+  (if (ratnum? x)
+    (rat:denominator x)
+    (if (fixnum? x)
+      1
+      1.0)))
+
+(define (rat:+ x y)
+  (make-rational (fix:+ (fix:* (numerator x) (denominator y))
+                        (fix:* (denominator x) (numerator y)))
+                 (fix:* (denominator x) (denominator y))))
+
+(define (rat:- x y)
+  (make-rational (fix:- (fix:* (numerator x) (denominator y))
+                        (fix:* (denominator x) (numerator y)))
+                 (fix:* (denominator x) (denominator y))))
+
+(define (rat:* x y)
+  (make-rational (fix:* (numerator x) (numerator y))
+                 (fix:* (denominator x) (denominator y))))
+
+(define (rat:/ x y)
+  (make-rational (fix:* (numerator x) (denominator y))
+                 (fix:* (denominator x) (numerator y))))
+
+(define (rat:1/ x)
+  (make-rational (denominator x) (numerator x)))
+
+; Type dispatch and promotion
+
+(define (type-dispatch ops x)
+  (if (flonum? x)
+    ((cdr ops) x)
+    ((car ops) x)))
+
+(define (promote-dispatch ops x y)
+  (if (flonum? x)
+    (if (flonum? y)
+      ((cdr ops) x y)
+      ((cdr ops) x (fixnum->flonum y)))
+    (if (flonum? y)
+      ((cdr ops) (fixnum->flonum x) y)
+      ((car ops) x y))))
+
+; Unary ops
+
+(define (neg x)
+  (type-dispatch (cons fix:neg flo:neg) x))
+
+(define (abs x)
+  (type-dispatch (cons fix:abs flo:abs) x))
+
+(define (flo:1+ x) (flo:+ x 1.0))
+(define (flo:1- x) (flo:- x 1.0))
+
+(define (1+ n)
+  (type-dispatch (cons fix:1+ flo:1+) n))
+
+(define (1- n)
+  (type-dispatch (cons fix:1- flo:1-) n))
+
+(define (apply-to-flonum op x)
+  (if (flonum? x) (op x) x))
+
+(define (round x)
+  (apply-to-flonum flo:round x))
+(define (floor x)
+  (apply-to-flonum flo:floor x))
+(define (ceiling x)
+  (apply-to-flonum flo:ceiling x))
+(define (truncate x)
+  (apply-to-flonum flo:truncate x))
+
+; Binary operations
+
+(define (fix:/ x y) ; Non-standard definition while we don't have rationals
+  (if (fix:= 0 (fix:remainder x y))
+    (fix:quotient x y)
+    (flo:/ (fixnum->flonum x) (fixnum->flonum y))))
+
+(define (pair+ x y) (promote-dispatch (cons fix:+ flo:+) x y))
+(define (pair- x y) (promote-dispatch (cons fix:- flo:-) x y))
+(define (pair* x y) (promote-dispatch (cons fix:* flo:*) x y))
+(define (pair/ x y) (promote-dispatch (cons fix:/ flo:/) x y))
+
+(define (pair> x y) (promote-dispatch (cons fix:> flo:>) x y))
+(define (pair< x y) (promote-dispatch (cons fix:< flo:<) x y))
+(define (pair>= x y) (promote-dispatch (cons fix:>= flo:>=) x y))
+(define (pair<= x y) (promote-dispatch (cons fix:<= flo:<=) x y))
+(define (pair= x y) (promote-dispatch (cons fix:= flo:=) x y))
+
+(define (null? arg)
+  (eq? arg '()))
+
+(define (fold-left proc init l)
+  (if (null? l)
+    init
+    (fold-left proc (proc init (car l)) (cdr l))))
+
+(define (reduce-left proc init l)
+  (if (null? l)
+    init
+    (if (null? (cdr l))
+      (car l)
+      (fold-left proc (proc (car l) (car (cdr l))) (cdr (cdr l))))))
+
+(define (+ . args)
+  (fold-left pair+ 0 args))
+
+(define (- first . rest)
+  (if (null? rest)
+    (neg first)
+    (pair- first (apply + rest))))
+
+(define (* . args)
+  (fold-left pair* 1 args))
+
+(define (/ first . rest)
+  (if (null? rest)
+    (pair/ 1 first)
+    (pair/ first (apply * rest))))
+
+(define (quotient n1 n2)
+  (fix:quotient n1 n2))
+
+(define (remainder n1 n2)
+  (fix:remainder n1 n2))
+
+(define modulo remainder)
+
+; Relations
+
+(define (test-relation rel l)
+  (if (null? l)
+    #t
+    (if (null? (cdr l))
+      #t
+      (if (rel (car l) (car (cdr l)))
+        (test-relation rel (cdr l))
+        #f))))
+
+(define (= . args)
+  (test-relation pair= args))
+
+(define (> . args)
+  (test-relation pair> args))
+
+(define (< . args)
+  (test-relation pair< args))
+
+(define (>= . args)
+  (test-relation pair>= args))
+
+(define (<= . args)
+  (test-relation pair<= args))
+
+; Numeric tests 
+
+(define (zero? x) (pair= x 0.0))
+(define (positive x) (pair> x 0.0))
+(define (odd? n) (pair= (remainder n 2) 0))
+(define (odd? n) (not (pair= (remainder n 2) 0)))
+
+
+; Current state of the numerical tower
+(define (complex? x) #f)
+(define (real? x) #t)
+(define (rational? x) #t)
+(define (integer? x) (= x (round x)))
+(define (exact? x) (fixnum? x))
+(define (inexact? x) (flonum? x))
+
+;; LISTS
+
 ; Return number of items in list
 (define (length l)
   (define (iter a count)
 ; Return number of items in list
 (define (length l)
   (define (iter a count)