\documentstyle[6.001-ps]{article}
\begin{document}
\header{5}{March 17, 1989}
\part{1: Homework exercises}
\exercise{5.1}
\bv
(define (make-polar r t)
  (define (dispatch m)
    (cond ((eq? m 'real-part) (* r (cos t)))
          ((eq? m 'imag-part) (* r (sin t)))
          ((eq? m 'magnitude) r)
          ((eq? m 'angle) t)
          (else (error "Unknown op -- MAKE-POLAR" m))))
  dispatch)
\end{verbatim}
\exercise{5.2}
\bv
(define (type datum)
  (cond ((number? datum) 'number)
        ((not (atom? datum)) (car datum))
        (else (error "Bad typed datum -- TYPE" datum))))

(define (attach-type type contents)
  (if (and ((eq? type 'number) (number? contents)))
      contents
      (cons type contents)))

(define (contents datum)
  (cond ((number? datum) datum)
        ((not (atom? datum)) (cdr datum))
        (else (error "Bat typed datum -- CONTENTS" datum))))
\end{verbatim}
\exercise{5.3}
The actual arguments sent to \verb|+c| are \verb+(rectangular 3 . 4)+ and
\verb+(polar 5 . 1)+.  The symbol \verb+complex+ is stripped off by
\verb+operate-2+ before it passes the contents of its parameters to
the procedure retrieved from the table.
\exercise{5.4}
\bv
(define z (make-complex (make-rectangular 3 4)))

(magnitude z)
(operate 'magnitude '(complex rectangular 3 . 4))
; The get called in operate will return the procedure originally defined
; as magnitude, which operated on a complex number (not a generic object).
; Because magnitude is now bound to a function which is defined over a
; normal generic object, I am calling it magnitude-complex for the sake
; of a reasonable representation.  The Scheme interpreter would give
; it a name like #[COMPOUND-PROCEDURE #x123456].
(magnitude-complex '(rectangular 3 . 4))
(operate 'magnitude '(rectangular 3 . 4))
(magnitude-rectangular '(3 . 4))
(sqrt (+ (square 3) (square 4)))
; Final return value is:
5
\end{verbatim}
\part{2: Symbolic Manipulation of Rational Functions}
\problem{5.1}
\bv
(create-rational 7 12)

(make-polynomial 'x '((5 1) (3 7) (1 -4) (0 2)))

(make-polynomial 'x (adjoin-term (make-term 4 (create-rational 2 3))
                     (adjoin-term (make-term 2 (create-rational 4 5))
                      (adjoin-term (make-term 1 (create-rational 1 3))
                       '((0 1))))))
; This is correct, but for square to work, all the coefficients must be
; of the same type, so:
(make-polynomial 'x (adjoin-term (make-term 4 (create-rational 2 3))
                     (adjoin-term (make-term 2 (create-rational 4 5))
                      (adjoin-term (make-term 1 (create-rational 1 3))
                       (adjoin-term (make-term 0 (create-rational 1 1))
                        (the-empty-termlist)))))))
\end{verbatim}
\problem{5.2}
\bv
(define (negate-poly poly)
    (make-polynomial (variable poly) (negate-terms (term-list poly))))

(define (negate-terms terms)
  (if (empty-termlist? terms)
      (the-empty-termlist)
      (adjoin-term (make-term (order (first-term terms))
                                (negate (coeff (first-term terms))))
                     (negate-terms (rest-terms terms)))))

(put 'polynomial 'negate negate-poly)
\end{verbatim}
\problem{5.3}
\bv
(define (-terms L1 L2)
  (+terms L1 (negate-terms L2)))

(define (-poly p1 p2)
  (if (same-variable? (variable p1) (variable p2))
      (make-polynomial (variable p1)
                       (-terms (term-list p1) (term-list p2)))
      (error "Polys not in same variable -- -POLY" (list p1 p2))))

(put 'polynomial 'sub -poly)
\end{verbatim}
\problem{5.4}
\bv
(define (/poly p1 p2)
  (if (same-variable? (variable p1) (variable p2))
      (let ((quotient-remainder (/terms (term-list p1) (term-list p2))))
        (list (make-polynomial (variable p1) (car quotient-remainder))
              (make-polynomial (variable p1) (cadr quotient-remainder))))
      (error "Polys not in same variable -- /POLY" (list p1 p2))))

(define (/terms L1 L2)
  (if (empty-termlist? L1)
      (list (the-empty-termlist) (the-empty-termlist))
      (let ((t1 (first-term L1))
            (t2 (first-term L2)))
        (if (> (order t2) (order t1))
            (list (the-empty-termlist) L1)
            (let ((new-c (div (coeff t1) (coeff t2)))
                  (new-o (- (order t1) (order t2))))
              (let ((rest-of-result
                     (/terms (-terms L1 
                                     (*-term-by-all-terms (make-term new-o new-c)
                                                          L2))
                             L2)))
                (list
                 (adjoin-term (make-term new-c new-o) (car rest-of-result))
                 (cadr rest-of-result))))))))

(put 'polynomial 'div /poly)
\end{verbatim}
\problem{5.5}
\bv
(define (gcd-poly p1 p2)
  (if (same-variable? (variable p1) (variable p2))
      (make-polynomial (variable p1) 
                       (gcd-terms (term-list p1) (term-list p2)))
      (error "Polys not in same variable -- /POLY" (list p1 p2))))

(define (gcd-terms a b)
  (if (empty-termlist? b)
      a
      (gcd-terms b (remainder-terms a b))))

(define (remainder-terms L1 L2)
  (cadr (/terms L1 L2)))

(define (gcd a b)
  (if (= b 0)
      a
      (gcd b (remainder a b))))

(put 'polynomial 'greatest-common-divisor gcd-poly)
(put 'number 'greatest-common-divisor gcd)
\end{verbatim}
\problem{5.6}
\bv
; A special "debugging" version of remainder-terms
(define (remainder-terms L1 L2)
  (print (cadr (/terms L1 L2)))
  (cadr (/terms L1 L2)))

(define p1 '(x (2 1) (1 -2) (0 1)))
;Value: P1

(define p2 '(x (2 11) (0 7)))
;Value: P2

(define p3 '(x (1 13) (0 5)))
;Value: P3

(define q1 (*poly p1 p2))
;Value: Q1

(define q2 (*poly p1 p3))
;Value: Q2

(define (ggcd a b) (operate-2 'greatest-common-divisor a b))
;Value: GGCD
(ggcd q1 q2)
((2 8.627218934911) (1 -17.25443786982) (0 8.627218934911)) 
((1 1.554312234475e-15) (0 -9.992007221626e-16)) 
((0 1.100410578433)) 
() 
;Value: (POLYNOMIAL X (0 1.100410578433))

(/ -17.2544378698 8.627218934911)
;Value: -1.999999999997
\end{verbatim}

The program is losing because the real-number division does not have
infinite precision.  In the second recursion of \verb+gcd-terms+, 
a term list with integer coefficients is divided by a term list with
real coefficients.  The result is a polynomial with coefficients very
close to, but not quite, zero.  Because the computer does not maintain
infinite precision, it thinks this is another polynomial, rather than 
zero, and does not stop at this level.  A simple test shows that the
polynomial returned the first time is, within the computer's margin
of error, the same as \verb+p1+, just off by a constant factor.
\part{3: Finally}
I spent about four hours on Athena doing this assignment, and about
five hours total.
\end{document}
