Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #lang racket
- ;;;;;;;;;;;
- ;; NOTES ;;
- ;;;;;;;;;;;
- ;; The generic arithmetic program through exercise 2.86, using type coercion, type
- ;; simplification, and generic components for complex numbers.
- ;; Note that integers are represented as un-tagged Racket exact integers like 1,
- ;; and reals are represented as un-tagged Racket inexact numbers like 1.0.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; OP, RAISE, AND PROJECT TABLES ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (define op-table (make-hash))
- (define (put op tag-list procedure) (hash-set! op-table (list op tag-list) procedure))
- (define (can-apply? op tag-list) (member (list op tag-list) (hash-keys op-table)))
- (define (get op tag-list) (hash-ref op-table (list op tag-list)))
- (define project-table (make-hash))
- (define (put-project type procedure) (hash-set! project-table type procedure))
- (define (can-project? arg) (member (type-tag arg) (hash-keys project-table)))
- (define (project arg) ((hash-ref project-table (type-tag arg)) arg))
- (define raise-table (make-hash))
- (define (put-raise type procedure) (hash-set! raise-table type procedure))
- (define (can-raise? arg) (member (type-tag arg) (hash-keys raise-table)))
- (define (raise arg) ((hash-ref raise-table (type-tag arg)) arg))
- ;;;;;;;;;;;;;;;;;;;;;;;;
- ;; GENERIC OPERATIONS ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;
- (define (attach-tag type-tag contents)
- (cond [(exact-integer? contents) contents]
- [(inexact-real? contents) contents]
- [else (list type-tag contents)]))
- (define (type-tag datum)
- (cond [(exact-integer? datum) 'integer]
- [(inexact-real? datum) 'real]
- [(pair? datum) (first datum)]
- [else (error "bad tagged-datum -- TYPE-TAG" datum)]))
- (define (contents datum)
- (cond [(exact-integer? datum) datum]
- [(inexact-real? datum) datum]
- [(pair? datum) (second datum)]
- [else (error "bad tagged datum -- CONTENTS" datum)]))
- (define (simplify arg)
- (cond [(can-project? arg)
- (define projected-arg (project arg))
- (if (equ? arg (raise projected-arg))
- (simplify projected-arg)
- arg)]
- [else arg]))
- (define (highest-type tag-list)
- ;; Raise 0 through all the types. Keep the highest type found in tag-list.
- (define (loop type arg)
- (cond [(can-raise? arg)
- (define new-arg (raise arg))
- (define new-type (type-tag new-arg))
- (if (member new-type tag-list)
- (loop new-type new-arg)
- (loop type new-arg))]
- [else type]))
- (loop 'integer 0))
- (define (coerce args target-type)
- (define (coerce-one arg)
- (if (eq? (type-tag arg) target-type)
- arg
- (coerce-one (raise arg))))
- (map coerce-one args))
- (define (all-same? symbols)
- (or (< (length symbols) 2)
- (andmap (lambda (s) (eq? s (first symbols)))
- (rest symbols))))
- (define (apply-generic op . args)
- (define type-tags (map type-tag args))
- (cond [(can-apply? op type-tags)
- (apply (get op type-tags) (map contents args))]
- [(not (all-same? type-tags))
- (define new-args (coerce args (highest-type type-tags)))
- (apply apply-generic (cons op new-args))]
- [else (error "no method for this op -- APPLY-GENERIC" op)]))
- ;; Only simplify the numerical operations and the complex selectors.
- ;; Do not simplify predicates or constructors.
- ;; arithmetic
- (define (add x y) (simplify (apply-generic 'add x y)))
- (define (sub x y) (simplify (apply-generic 'sub x y)))
- (define (mul x y) (simplify (apply-generic 'mul x y)))
- (define (div x y) (simplify (apply-generic 'div x y)))
- ;; predicates
- (define (=zero? x) (apply-generic '=zero? x))
- (define (equ? x y) (apply-generic 'equ? x y))
- ;; complex number selectors
- (define (re-part z) (simplify (apply-generic 're-part z)))
- (define (im-part z) (simplify (apply-generic 'im-part z)))
- (define (mag-part z) (simplify (apply-generic 'mag-part z)))
- (define (ang-part z) (simplify (apply-generic 'ang-part z)))
- ;; numerical operations needed for generic complex number components
- (define (absolute x) (apply-generic 'absolute x))
- (define (expo x y) (simplify (apply-generic 'expo x y)))
- (define (arctan y x) (simplify (apply-generic 'arctan y x)))
- (define (cosine x) (simplify (apply-generic 'cosine x)))
- (define (sine x) (simplify (apply-generic 'sine x)))
- (define (square x) (simplify (apply-generic 'square x)))
- (define (square-root x) (simplify (apply-generic 'square-root x)))
- ;; constructors
- (define (make-integer a) ((get 'make 'integer) a))
- (define (make-rational n d) ((get 'make 'rational) n d))
- (define (make-real x) ((get 'make 'real) x))
- (define (make-complex-from-real-imag x y) ((get 'make-from-real-imag 'complex) x y))
- (define (make-complex-from-mag-ang r a) ((get 'make-from-mag-ang 'complex) r a))
- ;; Note that we cannot simply define make-integer as (get 'make 'integer)
- ;; because that procedure has not been stored in the op-table yet.
- ;;;;;;;;;;;;;;
- ;; INTEGERS ;;
- ;;;;;;;;;;;;;;
- (define (install-integer-package)
- ;; internal procedures
- (define (make-integer a)
- (define flr (floor a))
- (if (exact? flr) flr (inexact->exact flr)))
- (define (arctan-int b a) (make-real (atan b a)))
- (define (cosine-int a) (make-real (cos a)))
- (define (sine-int a) (make-real (sin a)))
- (define (square-root-int a) (make-real (sqrt a)))
- (define (raise-int datum)
- (define a (contents datum))
- (make-rational a 1))
- ;; interface to the rest of the system
- (put '=zero? '(integer) zero?)
- (put 'absolute '(integer) abs)
- (put 'add '(integer integer) +)
- (put 'arctan '(integer integer) arctan-int)
- (put 'cosine '(integer) cosine-int)
- (put 'div '(integer integer) make-rational)
- (put 'equ? '(integer integer) =)
- (put 'expo '(integer integer) expt)
- (put 'make 'integer make-integer)
- (put 'mul '(integer integer) *)
- (put 'sine '(integer) sine-int)
- (put 'square-root '(integer) square-root-int)
- (put 'square '(integer) sqr)
- (put 'sub '(integer integer) -)
- (put-raise 'integer raise-int)
- 'done-installing-integers)
- (install-integer-package)
- ;;;;;;;;;;;;;;;;;;;;;;
- ;; RATIONAL NUMBERS ;;
- ;;;;;;;;;;;;;;;;;;;;;;
- (define (install-rational-package)
- ;; internal procedures
- (define (make-rat n d)
- (let ([g (gcd n d)])
- (list (make-integer (/ n g)) (make-integer (/ d g)))))
- (define (numer x) (first x))
- (define (denom x) (second x))
- (define (=zero-rat? x) (zero? (numer x)))
- (define (equ-rat? x y)
- (= (* (numer x) (denom y))
- (* (denom x) (numer y))))
- (define (absolute-rat x) (make-real (abs (/ (numer x) (denom x)))))
- (define (add-rat x y)
- (make-rat (+ (* (numer x) (denom y))
- (* (numer y) (denom x)))
- (* (denom x) (denom y))))
- (define (sub-rat x y)
- (make-rat (- (* (numer x) (denom y))
- (* (numer y) (denom x)))
- (* (denom x) (denom y))))
- (define (mul-rat x y)
- (make-rat (* (numer x) (numer y))
- (* (denom x) (denom y))))
- (define (div-rat x y)
- (make-rat (* (numer x) (denom y))
- (* (denom x) (numer y))))
- (define (expo-rat x y) (make-real (expt (/ (* (numer x) 1.0) (denom x))
- (/ (* (numer y) 1.0) (denom y)))))
- (define (arctan-rat y x) (make-real (atan (/ (numer y) (denom y))
- (/ (numer x) (denom x)))))
- (define (cosine-rat x) (make-real (cos (/ (numer x) (denom x)))))
- (define (sine-rat x) (make-real (sin (/ (numer x) (denom x)))))
- (define (square-root-rat x) (make-real (sqrt (/ (numer x) (denom x)))))
- (define (square-rat x) (make-rat (sqr (numer x)) (sqr (denom x))))
- (define (project-rat datum)
- (define x (contents datum))
- (make-integer (floor (/ (numer x) (denom x)))))
- (define (raise-rat datum)
- (define x (contents datum))
- (make-real (/ (numer x) (denom x))))
- ;; interface to the rest of the system
- (define (tag x) (attach-tag 'rational x))
- (put 'make 'rational (compose tag make-rat))
- (put '=zero? '(rational) =zero-rat?)
- (put 'equ? '(rational rational) equ-rat?)
- (put 'absolute '(rational) absolute-rat)
- (put 'add '(rational rational) (compose tag add-rat))
- (put 'sub '(rational rational) (compose tag sub-rat))
- (put 'mul '(rational rational) (compose tag mul-rat))
- (put 'div '(rational rational) (compose tag div-rat))
- (put 'expo '(rational rational) expo-rat)
- (put 'arctan '(rational rational) arctan-rat)
- (put 'cosine '(rational) cosine-rat)
- (put 'sine '(rational) sine-rat)
- (put 'square-root '(rational) square-root-rat)
- (put 'square '(rational) (compose tag square-rat))
- (put-project 'rational project-rat)
- (put-raise 'rational raise-rat)
- 'done-installing-rationals)
- (install-rational-package)
- ;;;;;;;;;;;;;;;;;;
- ;; REAL NUMBERS ;;
- ;;;;;;;;;;;;;;;;;;
- (define (install-real-package)
- ;; internal procedures
- (define (make-real x) (if (inexact? x) x (exact->inexact x)))
- (define (project-real datum)
- (define x (contents datum))
- (make-rational (floor (* x 1000000)) 1000000))
- (define (raise-real datum)
- (define x (contents datum))
- (make-complex-from-real-imag x 0))
- ;; interface to the rest of the system
- (put '=zero? '(real) zero?)
- (put 'absolute '(real) abs)
- (put 'add '(real real) +)
- (put 'arctan '(real real) atan)
- (put 'cosine '(real) cos)
- (put 'div '(real real) /)
- (put 'equ? '(real real) =)
- (put 'expo '(real real) expt)
- (put 'make 'real make-real)
- (put 'mul '(real real) *)
- (put 'sine '(real) sin)
- (put 'square-root '(real) sqrt)
- (put 'square '(real) sqr)
- (put 'sub '(real real) -)
- (put-project 'real project-real)
- (put-raise 'real raise-real)
- 'done-installing-reals)
- (install-real-package)
- ;;;;;;;;;;;;;;;;;;;;;
- ;; COMPLEX NUMBERS ;;
- ;;;;;;;;;;;;;;;;;;;;;
- (define (install-complex-package)
- ;;; rectangular complex numbers
- (define (install-rectangular-package)
- ;; internal procedures
- (define (make-from-real-imag-rect x y) (list x y))
- (define (re-part-rect z) (first z))
- (define (im-part-rect z) (second z))
- (define (make-from-mag-ang-rect r a)
- (list (mul r (cosine a))
- (mul r (sine a))))
- (define (mag-part-rect z)
- (square-root (add (square (re-part-rect z))
- (square (im-part-rect z)))))
- (define (ang-part-rect z)
- (arctan (im-part-rect z) (re-part-rect z)))
- ;; interface to the rest of the system
- (define (tag z) (attach-tag 'rectangular z))
- (put 're-part '(rectangular) re-part-rect)
- (put 'im-part '(rectangular) im-part-rect)
- (put 'mag-part '(rectangular) mag-part-rect)
- (put 'ang-part '(rectangular) ang-part-rect)
- (put 'make-from-real-imag 'rectangular (compose tag make-from-real-imag-rect))
- (put 'make-from-mag-ang 'rectangular (compose tag make-from-mag-ang-rect))
- 'done)
- (install-rectangular-package)
- ;;; polar complex numbers
- (define (install-polar-package)
- ;; internal procedures
- (define (make-from-mag-ang-polar r a) (list r a))
- (define (mag-part-polar z) (first z))
- (define (ang-part-polar z) (second z))
- (define (make-from-real-imag-polar x y)
- (list (square-root (add (square x) (square y)))
- (arctan y x)))
- (define (re-part-polar z)
- (mul (mag-part-polar z) (cosine (ang-part-polar z))))
- (define (im-part-polar z)
- (mul (mag-part-polar z) (sine (ang-part-polar z))))
- ;; interface to the rest of the system
- (define (tag x) (attach-tag 'polar x))
- (put 're-part '(polar) re-part-polar)
- (put 'im-part '(polar) im-part-polar)
- (put 'mag-part '(polar) mag-part-polar)
- (put 'ang-part '(polar) ang-part-polar)
- (put 'make-from-real-imag 'polar (compose tag make-from-real-imag-polar))
- (put 'make-from-mag-ang 'polar (compose tag make-from-mag-ang-polar))
- 'done)
- (install-polar-package)
- ;;; generic complex numbers
- ;; internal procedures
- ; constructors
- (define (make-from-real-imag x y)
- ((get 'make-from-real-imag 'rectangular) x y))
- (define (make-from-mag-ang r a)
- ((get 'make-from-mag-ang 'polar) r a))
- ; predicates
- (define (equ-complex? z1 z2)
- (and (< (absolute (sub (re-part z1) (re-part z2))) 0.000001)
- (< (absolute (sub (im-part z1) (im-part z2))) 0.000001)))
- (define (=zero-complex? z)
- (or (=zero? (mag-part z))
- (and (< (absolute (re-part z)) 0.000001)
- (< (absolute (im-part z)) 0.000001))))
- ; arithmetic
- (define (add-complex z1 z2)
- (make-from-real-imag (add (re-part z1) (re-part z2))
- (add (im-part z1) (im-part z2))))
- (define (sub-complex z1 z2)
- (make-from-real-imag (sub (re-part z1) (re-part z2))
- (sub (im-part z1) (im-part z2))))
- (define (mul-complex z1 z2)
- (make-from-mag-ang (mul (mag-part z1) (mag-part z2))
- (add (ang-part z1) (ang-part z2))))
- (define (div-complex z1 z2)
- (make-from-mag-ang (div (mag-part z1) (mag-part z2))
- (sub (ang-part z1) (ang-part z2))))
- (define (expo-complex z1 z2)
- (define w (expt (+ (make-real (re-part z1))
- (* (make-real (im-part z1)) 0+i))
- (+ (make-real (re-part z2))
- (* (make-real (im-part z2)) 0+i))))
- (make-from-real-imag (real-part w) (imag-part w)))
- (define (project-complex datum)
- (define z (contents datum))
- (make-real (re-part z)))
- ;; interface to the rest of the system
- (define (tag z) (attach-tag 'complex z))
- (put 'make-from-real-imag 'complex (compose tag make-from-real-imag))
- (put 'make-from-mag-ang 'complex (compose tag make-from-mag-ang))
- (put '=zero? '(complex) =zero-complex?)
- (put 'equ? '(complex complex) equ-complex?)
- (put 're-part '(complex) re-part)
- (put 'im-part '(complex) im-part)
- (put 'mag-part '(complex) mag-part)
- (put 'ang-part '(complex) ang-part)
- (put 'add '(complex complex) (compose tag add-complex))
- (put 'sub '(complex complex) (compose tag sub-complex))
- (put 'mul '(complex complex) (compose tag mul-complex))
- (put 'div '(complex complex) (compose tag div-complex))
- (put 'expo '(complex complex) (compose tag expo-complex))
- (put-project 'complex project-complex)
- 'done-installing-complex-numbers)
- (install-complex-package)
- ;;;;;;;;;;;
- ;; TESTS ;;
- ;;;;;;;;;;;
- (define q1 (make-rational 1 2))
- (define q2 (make-rational 3 4))
- (add q1 q2)
- ;; '(rational (5 4))
- (sub q1 q2)
- ;; '(rational (-1 4))
- (mul q1 q2)
- ;; '(rational (3 8))
- (div q1 q2)
- ;; '(rational (2 3))
- (define z1 (make-complex-from-real-imag 3 4))
- (define z2 (make-complex-from-mag-ang 1 pi))
- (add z1 z2)
- ;; '(complex (rectangular (2 4)))
- (sub z1 z2)
- ;; '(complex (rectangular (4 4)))
- (mul z1 z2)
- ;; '(complex (polar (5 4.068887871591405)))
- (div z1 z2)
- ;; '(complex (polar (5 -2.214297435588181)))
- (define w (make-complex-from-real-imag 0.5 (make-rational 3 4)))
- (re-part w)
- ;; '(rational (1 2))
- (im-part w)
- ;; '(rational (3 4))
- (=zero? (sub w (make-complex-from-real-imag (make-rational 1 2) 0.75)))
- ;; #t
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement