diff --git a/ex-2_77-97.scm b/ex-2_77-97.scm index 750897f..a7f4260 100644 --- a/ex-2_77-97.scm +++ b/ex-2_77-97.scm @@ -59,6 +59,10 @@ (define (tag x) x) (define (scheme->rational x) (make-rational x 1)) + (define (gcd-scheme a b) + (if (and (integer? a) (integer? b)) + (if (= b 0) (abs a) (gcd-scheme b (remainder a b))) + 'nogcd)) (put 'add '(scheme-number scheme-number) (lambda (x y) (tag (+ x y)))) (put 'sub '(scheme-number scheme-number) @@ -81,6 +85,7 @@ (lambda (x y) (atan x y))) (put 'square-root '(scheme-number) sqrt) (put 'raise 'scheme-number scheme->rational) + (put 'gcd '(scheme-number scheme-number) gcd-scheme) (display "[install-scheme-number-package]\n") 'done) @@ -89,33 +94,44 @@ (define (numer x) (car x)) (define (denom x) (cdr x)) (define (make-rat n d) - (if (and (integer? n) (integer? d)) - (let ((g (gcd n d))) - (cons (/ n g) (/ d g))) - (cons n d))) + (let ((g (gcd n d))) + (if (eq? g 'nogcd) + (cons n d) + (cons (/ n g) (/ d g))))) (define (add-rat x y) - (make-rat (+ (* (numer x) (denom y)) - (* (numer y) (denom x))) - (* (denom x) (denom y)))) + (let ((new-n (add (mul (numer x) (denom y)) + (mul (numer y) (denom x)))) + (new-d (mul (denom x) (denom y)))) + (make-rat new-n new-d))) (define (sub-rat x y) - (make-rat (- (* (numer x) (denom y)) - (* (numer y) (denom x))) - (* (denom x) (denom y)))) + (make-rat (sub (mul (numer x) (denom y)) + (mul (numer y) (denom x))) + (mul (denom x) (denom y)))) (define (mul-rat x y) - (make-rat (* (numer x) (numer y)) - (* (denom x) (denom y)))) + (make-rat (mul (numer x) (numer y)) + (mul (denom x) (denom y)))) (define (div-rat x y) - (make-rat (* (numer x) (denom y)) - (* (denom x) (numer y)))) + (make-rat (mul (numer x) (denom y)) + (mul (denom x) (numer y)))) (define (add3-rat x y z) (add-rat (add-rat x y) z)) - (define (equ? x y) - (= (* (numer x) (denom y)) - (* (numer y) (denom x)))) + (define (equ?-rat x y) + (equ? (mul (numer x) (denom y)) + (mul (numer y) (denom x)))) (define (rational->real x) - (make-real (/ (numer x) (denom x)))) + (let ((n (numer x)) + (d (denom x))) + (cond + ((and (number? n) (number? d)) + (make-real (/ (numer x) (denom x)))) + (else 'invalid)))) (define (rational->scheme x) - (make-scheme-number (inexact->exact (round (/ (numer x) (denom x)))))) + (let ((n (numer x)) (d (denom x))) + (cond + ((and (number? n) (number? d)) + (make-scheme-number (inexact->exact (round (/ (numer x) (denom x)))))) + (else 'invalid)))) + ;; interface to rest of the system (define (tag x) (attach-tag 'rational x)) (put 'add '(rational rational) @@ -128,7 +144,7 @@ (lambda (x y) (tag (mul-rat x y)))) (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y)))) - (put 'equ? '(rational rational) equ?) + (put 'equ? '(rational rational) equ?-rat) (put '=zero? '(rational) (lambda (x) (= (numer x) 0))) (put 'negate '(rational) @@ -316,6 +332,10 @@ (define (arctan x y) (apply-generic 'arctan x y)) (define (square-root x) (apply-generic 'square-root x)) (define (negate x) (apply-generic 'negate x)) +(define (gcd x y) + (if (procedure? (get 'gcd (list (type-tag x) (type-tag y)))) + (apply-generic 'gcd x y) + 'nogcd)) (install-scheme-number-package) (install-rational-package) @@ -468,13 +488,15 @@ ; All we have to do is update coerce-args to do consecutive raises ; to reach the target type. (define (coerce-args target-type args) + ; (display "COERCE-ARGS ") (display target-type) (display " ") (display args) (newline) (define (coerce-arg arg) + ; (display "COERCE-ARG ") (display arg) (newline) (if (eq? (type-tag arg) target-type) arg (let ((raise (get 'raise (type-tag arg)))) - (if (procedure? raise) - (raise (contents arg)) - arg)))) + (if (procedure? raise) + (raise (contents arg)) + arg)))) (let ((coerced-args (map coerce-arg args))) (if (equal? args coerced-args) coerced-args ; no more raising possible @@ -501,14 +523,15 @@ ; Implement drop to transform number to lowest possible representation (define (drop x) - ;(display "---------\ndrop ") (display x) (newline) + ; (display "DROP ") (display x) (newline) (if (has-tag? x) (let ((project (get 'project (type-tag x)))) (if (procedure? project) (let ((projected (project (contents x)))) - (if (equ? projected x) - (drop projected) - x)) + (cond + ((eq? projected 'invalid) x) + ((equ? projected x) (drop projected)) + (else x))) x)) x)) @@ -517,7 +540,7 @@ ;(assert (drop (make-complex-from-real-imag 3 0)) (make-scheme-number 3)) (define (apply-generic op . args) - ;(display "-----\napply-generic ") (display op) (display " ") (display args) (newline) + ; (display "APPLY-GENERIC ") (display op) (display " ") (display args) (newline) (define (try-args args-list) (if (null? args-list) (error "No method for these types" (list op (map type-tag args))) @@ -527,6 +550,7 @@ (drop (apply proc args-contents)) (try-args (cdr args-list)))))) (define (coerce-to-arg arg) + ; (display "COERCE-TO-ARG ") (display arg) (newline) (coerce-args (type-tag arg) args)) (try-args (cons args (map coerce-to-arg args)))) @@ -728,52 +752,50 @@ ((get 'first-term (type-tag term-list)) (contents term-list))) (define (adjoin-term term term-list) - ; (display "ADJOIN-TERM ") (display term) (display term-list) (newline) ((get 'adjoin-term (type-tag term-list)) term (contents term-list))) - ;; sparse implementations - (define (tag-sparse p) (attach-tag 'sparse p)) - (define (make-poly-sparse variable term-list) - (cons variable (tag-sparse term-list))) - - (define (first-term-sparse term-list) - ;(display "first-term-sparse ") (display term-list) (newline) - (make-term (- (length term-list) 1) - (car term-list))) - - (define (adjoin-term-sparse term term-list) - (let ((coeff-term (coeff term)) - (order-term (order term)) - (length-terms (length term-list))) - (cond - ((= order-term length-terms) (tag-sparse (cons coeff-term term-list))) - ((< order-term length-terms) (error "Cannot adjoin lower-order term to terms")) - (else (tag-sparse - (cons - coeff-term - (contents (adjoin-term-sparse - (make-term (- order-term 1) 0) - term-list)))))))) - - (put 'first-term 'sparse first-term-sparse) - (put 'adjoin-term 'sparse adjoin-term-sparse) - ;; dense implementations (define (tag-dense p) (attach-tag 'dense p)) (define (make-poly-dense variable term-list) (cons variable (tag-dense term-list))) - (define (adjoin-term-dense term term-list) - (if (=zero? (coeff term)) - (tag-dense term-list) - (tag-dense (cons term term-list)))) + (define (first-term-dense term-list) + ; (display "FIRST-TERM-DENSE ") (display term-list) (newline) + (make-term (- (length term-list) 1) + (car term-list))) - (define (first-term-dense term-list) (car term-list)) + (define (adjoin-term-dense term term-list) + (let ((coeff-term (coeff term)) + (order-term (order term)) + (length-terms (length term-list))) + (cond + ((= order-term length-terms) (tag-dense (cons coeff-term term-list))) + ((< order-term length-terms) (error "Cannot adjoin lower-order term to terms")) + (else (tag-dense + (cons + coeff-term + (contents (adjoin-term-dense + (make-term (- order-term 1) 0) + term-list)))))))) (put 'first-term 'dense first-term-dense) (put 'adjoin-term 'dense adjoin-term-dense) - (define (the-empty-termlist) (tag-sparse '())) + ;; sparse implementations + (define (tag-sparse p) (attach-tag 'sparse p)) + (define (make-poly-sparse variable term-list) + (cons variable (tag-sparse term-list))) + + (define (adjoin-term-sparse term term-list) + (if (=zero? (coeff term)) + (tag-sparse term-list) + (tag-sparse (cons term term-list)))) + + (define (first-term-sparse term-list) (car term-list)) + + (put 'first-term 'sparse first-term-sparse) + (put 'adjoin-term 'sparse adjoin-term-sparse) + (define (empty-termlist t) (attach-tag (type-tag t) '())) (define (rest-terms term-list) @@ -837,17 +859,17 @@ ; (display "COERCE-TERM ") (display t) (newline) (let ((c (coeff t)) (o (order t)) - (new-poly (tag (make-poly-dense + (new-poly (tag (make-poly-sparse source-var (list (list (order t) 1)))))) ; (display "NEW-POLY ") (display new-poly) (newline) (if (eq? (type-tag c) 'polynomial) - (let ((new-poly (tag (make-poly-dense source-var (list (list o 1)))))) + (let ((new-poly (tag (make-poly-sparse source-var (list (list o 1)))))) (scale-terms new-poly (contents (term-list c)))) - (let ((sub-poly (tag (make-poly-dense + (let ((sub-poly (tag (make-poly-sparse source-var (list (list o c)))))) - (cons 'dense (list (list 0 sub-poly))))))) + (cons 'sparse (list (list 0 sub-poly))))))) (if (empty-termlist? terms) terms (add-terms (coerce-term (first-term terms)) @@ -855,7 +877,7 @@ (define (coerce-poly p target-var) - ; (display "COERCE-POLY ") (display p) (newline) + ; (display "COERCE-POLY ") (display p) (display " TARGET ") (display target-var) (newline) (if (eq? (variable p) target-var) p (let ((coercion-result (coerce-terms (term-list p) (variable p) target-var))) @@ -863,6 +885,7 @@ (make-poly target-var coercion-result)))) (define (coerce-polys p1 p2) + ; (display "COERCE-POLYS ") (display p1) (display p2) (newline) (let ((coercion-target-variable (get-coercion-target p1 p2))) (if coercion-target-variable (list (coerce-poly p1 coercion-target-variable) @@ -892,21 +915,25 @@ (list p1 p2)))) (define (mul-terms L1 L2) + ; (display "MUL-TERMS") (display L1) (display L2) (newline) (if (empty-termlist? L1) L1 (add-terms (mul-term-by-all-terms (first-term L1) L2) (mul-terms (rest-terms L1) L2)))) (define (mul-term-by-all-terms t1 L) + ; (display "MUL-TERM-BY-ALL-TERMS ") (display t1) (display L) (newline) (if (empty-termlist? L) L (let ((t2 (first-term L))) + ; (display "T1 ") (display t1) (display " T2 ") (display t2) (newline) (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2))) (mul-term-by-all-terms t1 (rest-terms L)))))) (define (mul-poly p1 p2) + ; (display "MUL-POLY ") (display p1) (display p2) (newline) (if (same-variable? (variable p1) (variable p2)) (make-poly (variable p1) (mul-terms (term-list p1) @@ -986,52 +1013,61 @@ ((get 'make 'poly-dense) var terms)) -(define p1 (make-poly-sparse 'x (list 5 1))) +(define p1 (make-poly-dense 'x (list 5 1))) (display p1) (newline) (display (add p1 p1)) (newline) -(assert (add p1 p1) (make-poly-sparse 'x (list 10 2))) -(assert (add (make-poly-sparse 'x (list 2 2 0 1)) - (make-poly-sparse 'x (list 1 2 3 2 3 6 6))) - (make-poly-sparse 'x (list 1 2 3 4 5 6 7))) -(assert (mul (make-poly-sparse 'x (list 1 1)) - (make-poly-sparse 'x (list 1 1))) - (make-poly-sparse 'x (list 1 2 1))) +(assert (add p1 p1) (make-poly-dense 'x (list 10 2))) +(assert (add (make-poly-dense 'x (list 2 2 0 1)) + (make-poly-dense 'x (list 1 2 3 2 3 6 6))) + (make-poly-dense 'x (list 1 2 3 4 5 6 7))) +(assert (mul (make-poly-dense 'x (list 1 1)) + (make-poly-dense 'x (list 1 1))) + (make-poly-dense 'x (list 1 2 1))) (display "\nex-2.90 - support sparse and dense polynomials\n") -(define p (make-poly-dense 'x '((100 2) (1 2)))) +(define p (make-poly-sparse 'x '((100 2) (1 2)))) (display p) (newline) -(assert (add p p) (make-poly-dense 'x '((100 4) (1 4)))) +(assert (add p p) (make-poly-sparse 'x '((100 4) (1 4)))) (assert (mul p p) - (make-poly-dense 'x '((200 4) (101 8) (2 4)))) + (make-poly-sparse 'x '((200 4) (101 8) (2 4)))) (display "\nex-2.91 - divide\n") -(define p1 (make-poly-dense 'x '((5 1) (0 -1)))) -(define p2 (make-poly-dense 'x '((2 1) (0 -1)))) -(assert (mul p1 p1) (make-poly-dense 'x '((10 1) (5 -2) (0 1)))) -(assert (mul p1 p2) (make-poly-dense 'x '((7 1) (5 -1) (2 -1) (0 1)))) +(define p1 (make-poly-sparse 'x '((5 1) (0 -1)))) +(define p2 (make-poly-sparse 'x '((2 1) (0 -1)))) +(assert (mul p1 p1) (make-poly-sparse 'x '((10 1) (5 -2) (0 1)))) +(assert (mul p1 p2) (make-poly-sparse 'x '((7 1) (5 -1) (2 -1) (0 1)))) (let ((result (div p1 p2))) - (assert (car result) (make-poly-dense 'x '((3 1) (1 1)))) - (assert (cadr result) (make-poly-dense 'x '((1 1) (0 -1))))) + (assert (car result) (make-poly-sparse 'x '((3 1) (1 1)))) + (assert (cadr result) (make-poly-sparse 'x '((1 1) (0 -1))))) (display "\nex-2.92 - coerce polynomials\n") -(define p1 (make-poly-dense +(define p1 (make-poly-sparse 'x - (list (list 1 (make-poly-dense + (list (list 1 (make-poly-sparse 'y '((2 1) (0 1))))))) -(define p2 (make-poly-dense +(define p2 (make-poly-sparse 'y (list (list 4 3) - (list 2 (make-poly-dense 'x '((2 1) (0 8))))))) + (list 2 (make-poly-sparse 'x '((2 1) (0 8))))))) (display (add p1 p2)) (newline) -(display "\nex-2.93\n") +(display "\nex-2.93 - polynomial rationals\n") + +(define p1 (make-poly-sparse 'x '((2 1)(0 1)))) +(define p2 (make-poly-sparse 'x '((3 1)(0 1)))) +(define rf (make-rational p2 p1)) + +(display rf) (newline) +(display (add rf rf)) (newline) + +(display "\nex-2.94 - polynomial gcd\n")