SICP 読み (86) 2.5.3 例: 記号代数

問題 2.90 の実装と試験を以下に。

lib/2.5.3.scm

(require "2.5.1")

(define (install-term-package)
  (define (make-term order coeff) (list order coeff))
  (define (order term) (car term))
  (define (coeff term) (cadr term))
  (define (tag t) (attach-tag 'term t))

  (put 'make 'term
       (lambda (order coeff) (tag (make-term order coeff))))
  (put 'order '(term)
       (lambda (t) (order t)))
  (put 'coeff '(term)
       (lambda (t) (coeff t)))
  'done)

(define (make-term order coeff)
  ((get 'make 'term) order coeff))
(define (order term) (apply-generic 'order term))
(define (coeff term) (apply-generic 'coeff term))

(define (install-sparse-termlist)
  (define (first-term term-list)
    (if (null? term-list)
	term-list
	(make-term (- (length term-list) 1) (car term-list))))
  (define (rest-terms term-list) (cdr term-list))
  (define (empty-termlist? term-list)
    (define (all-zero? term-list)
      (cond ((null? term-list) #t)
	    ((not (=zero? (car term-list))) #f)
	    (else
	     (all-zero? (cdr term-list))))
      )
    (or (null? term-list) (all-zero? term-list)))
  (define (the-empty-termlist) '())
  (define (adjoin-term term-list)
    (lambda (term)
      (let f ((term-list term-list))
	(if (> (order term) (length term-list))
	    (f (cons 0 term-list))
	    (tag (cons (coeff term) term-list))))))

  (define (tag t) (attach-tag 'sparse t))

  (put 'first-term '(sparse)
       (lambda (t) (first-term t)))
  (put 'rest-terms '(sparse)
       (lambda (t) (tag (rest-terms t))))
  (put 'empty-termlist? '(sparse)
       (lambda (t) (empty-termlist? t)))
  (put 'the-empty-termlist 'sparse
       (lambda () (tag (the-empty-termlist))))
  (put 'adjoin-term '(sparse)
       (lambda (t) (adjoin-term t)))
  'done)

(define (install-dense-termlist)
  (define (adjoin-term term-list)
    (lambda (term)
      (if (=zero? (coeff term))
	  (tag term-list)
	  (tag (cons (list (order term) (coeff term)) term-list)))))
  (define (first-term term-list) (make-term (car (car term-list))
					    (cadr (car term-list))))
  (define (rest-terms term-list) (cdr term-list))
  (define (the-empty-termlist) '())
  (define (empty-termlist? term-list) (null? term-list))

  (define (tag t) (attach-tag 'dense t))

  (put 'first-term '(dense)
       (lambda (t) (first-term t)))
  (put 'rest-terms '(dense)
       (lambda (t) (tag (rest-terms t))))
  (put 'empty-termlist? '(dense)
       (lambda (t) (empty-termlist? t)))
  (put 'the-empty-termlist 'dense
       (lambda () (tag (the-empty-termlist))))
  (put 'adjoin-term '(dense)
       (lambda (t) (adjoin-term t)))
 'done)

(define (install-polynomial-package)

  (define (first-term term-list) (apply-generic 'first-term term-list))
  (define (rest-terms term-list) (apply-generic 'rest-terms term-list))
  (define (empty-termlist? term-list)
    (apply-generic 'empty-termlist? term-list))
  (define (adjoin-term term-list) (apply-generic 'adjoin-term term-list))
  (define (sparse-empty-termlist) ((get 'the-empty-termlist 'sparse)))

  (define (make-poly variable term-list)
    (cons variable term-list))
  (define (variable p) (car p))
  (define (term-list p) (cdr p))

  (define (variable? x) (symbol? x))
  (define (same-variable? v1 v2)
    (and (variable? v1) (variable? v2) (eq? v1 v2)))

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

  (define (add-terms L1 L2)
    (cond ((empty-termlist? L1) L2)
	  ((empty-termlist? L2) L1)
	  (else
	   (let ((t1 (first-term L1)) (t2 (first-term L2)))
	     (cond ((> (order t1) (order t2))
		    ((adjoin-term (add-terms (rest-terms L1) L2)) t1))
		   ((< (order t1) (order t2))
		    ((adjoin-term (add-terms L1 (rest-terms L2))) t2))
		   (else
		    ((adjoin-term (add-terms (rest-terms L1)
					     (rest-terms L2)))
		     (make-term (order t1)
				(add (coeff t1) (coeff t2))))))))))

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

  (define (mul-terms L1 L2)
    (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)
    (if (empty-termlist? L)
	L
	(let ((t2 (first-term L)))
	  ((adjoin-term (mul-term-by-all-terms t1 (rest-terms L)))
	   (make-term (+ (order t1) (order t2))
		      (mul (coeff t1) (coeff t2)))))))

  (define (neg-poly p)
    (make-poly (variable p)
	       (neg-terms (term-list p))))

  (define (neg-terms L)
    (if (empty-termlist? L)
	L
	(let ((t (first-term L)))
	  ((adjoin-term (neg-terms (rest-terms L)))
	   (make-term (order t) (- (coeff t))))))
    )

  (define (tag p) (attach-tag 'polynomial p))

  (put '=zero? '(polynomial)
       (lambda (p) (empty-termlist? (term-list p))))
  (put 'neg '(polynomial)
       (lambda (p) (tag (neg-poly p))))
  (put 'add '(polynomial polynomial)
       (lambda (p1 p2) (tag (add-poly p1 p2))))
  (put 'mul '(polynomial polynomial)
       (lambda (p1 p2) (tag (mul-poly p1 p2))))
  (put 'make 'polynomial
       (lambda (var terms f) (tag (make-poly var (attach-tag f terms)))))
  'done)

(define (make-sparse-polynomial var terms)
  ((get 'make 'polynomial) var terms 'sparse))

(define (make-dense-polynomial var terms)
  ((get 'make 'polynomial) var terms 'dense))

(define (neg x) (apply-generic 'neg x))

lib/2.5.1.scm

(define (assoc key records)
  (cond ((null? records) #f)
	((equal? key (caar records)) (car records))
	(else (assoc key (cdr records)))))

(define (make-table)
  (let ((local-table (list '*table*)))
    (define (lookup key-1 key-2)
      (let ((subtable (assoc key-1 (cdr local-table))))
	(if subtable
	    (let ((record (assoc key-2 (cdr subtable))))
	      (if record
		  (cdr record)
		  #f))
	    #f)))
    (define (insert! key-1 key-2 value)
      (let ((subtable (assoc key-1 (cdr local-table))))
	(if subtable
	    (let ((record (assoc key-2 (cdr subtable))))
	      (if record
		  (set-cdr! record value)
		  (set-cdr! subtable
			    (cons (cons key-2 value) (cdr subtable)))))
	    (set-cdr! local-table
		      (cons (list key-1
				  (cons key-2 value))
			    (cdr local-table)))))
      'ok)
    (define (dispatch m)
      (cond ((eq? m 'lookup-proc) lookup)
	    ((eq? m 'insert-proc!) insert!)
	    (else (error "Unknown operation -- TABLE" m))))
    dispatch))

(define operation-table (make-table))
(define get (operation-table 'lookup-proc))
(define put (operation-table 'insert-proc!))

(define (attach-tag type-tag contents)
  (cons type-tag contents))
(define (type-tag datum)
  (cond ((number? datum) 'scheme-number)
	((pair? datum) (car datum))
	(else
	 (error "Bad tagged datum -- TYPE TAG" datum))))
(define (contents datum)
  (cond ((number? datum) datum)
	((pair? datum) (cdr datum))
	(else
	 (error "Bad tagged datum -- CONTENTS" datum))))

(define (apply-generic op . args)
  (let ((type-tags (map type-tag args)))
    (let ((proc (get op type-tags)))
      (if proc
	  (apply proc (map contents args))
	  (error
	   "No method for these types -- APPLY-GENERIC"
	   (list op type-tags))))))

(define (add x y) (apply-generic 'add x y))
(define (sub x y) (apply-generic 'sub x y))
(define (mul x y) (apply-generic 'mul x y))
(define (div x y) (apply-generic 'div x y))
(define (=zero? x) (apply-generic '=zero? x))

(define (install-scheme-number-package)
  (put 'add '(scheme-number scheme-number) +)

  (put 'sub '(scheme-number scheme-number) -)

  (put 'mul '(scheme-number scheme-number) *)

  (put 'div '(scheme-number scheme-number) /)

  (put '=zero? '(scheme-number) zero?)

  (put 'make 'scheme-number
       (lambda (x) x))
  'done)

(define (make-scheme-number n)
  ((get 'make 'scheme-number) n))

あと、試験が以下。

test/test-2.5.3.scm

#!/usr/bin/env gosh

(use test.unit)
(require "2.5.3")

(define-test-suite "2.5.3"
 ("install package"
  (setup (lambda () (install-scheme-number-package)))

  ("polynomial package"
   (assert-equal 'done (install-polynomial-package))
   )

  ("sparse termlist"
   (assert-equal 'done (install-sparse-termlist))
   )

  ("dense termlist"
   (assert-equal 'done (install-dense-termlist))
   )

  ("term"
   (assert-equal 'done (install-term-package))
   )
  )

 ("term"
  ("make-term"
   (assert-equal 'term (car (make-term 1 2)))
   (assert-equal 1 (cadr (make-term 1 2)))
   (assert-equal 2 (caddr (make-term 1 2)))
   )

  ("order"
   (assert-equal 2 (apply-generic 'order '(term 2 1)))
   )

  ("coeff"
   (assert-equal 1 (apply-generic 'coeff '(term 2 1)))
   )
  )

 ("make polynomial"
  ("make-sparse-polynomial"
   (assert-equal '(polynomial x sparse 1 2 3 4 5)
                 (make-sparse-polynomial 'x '(1 2 3 4 5)))
   )

  ("make-dense-polynomial"
   (assert-equal '(polynomial x dense (10 1) (0 1))
                 (make-dense-polynomial 'x '((10 1) (0 1))))
   )
  )

 ("sparse-termlist (first-term)"
  ("no element"
   (assert-equal '()
                 (apply-generic 'first-term '(sparse)))
   )

  ("1 element"
   (assert-equal '(term 0 5)
                 (apply-generic 'first-term '(sparse 5)))
   )

  ("6 elements"
   (assert-equal '(term 5 3)
                 (apply-generic 'first-term '(sparse 3 4 5 6 7 8)))
   )
  )

 ("sparse-termlist (rest-terms)"
  ("1 element"
   (assert-equal '(sparse) (apply-generic 'rest-terms '(sparse 5)))
   )
  
  ("6 elements"
   (assert-equal '(sparse 4 5 6 7 8)
                 (apply-generic 'rest-terms '(sparse 3 4 5 6 7 8)))
   )
  )

 ("sparse-termlist (empty-termlist?)"
  ("empty sparse-termlist"
   (assert-true (apply-generic 'empty-termlist? '(sparse)))
   )

  ("all zero"
   (assert-true (apply-generic 'empty-termlist? '(sparse 0 0 0)))
   )

  ("no empty"
   (assert-false (apply-generic 'empty-termlist? '(sparse 1)))
   )
  )

 ("sparse-termlist (the-empty-termlist) -- no use"
  ("..."
   (assert-true (apply-generic 'empty-termlist?
                               ((get 'the-empty-termlist 'sparse))))
   )

  ("..."
   (assert-equal '(sparse) ((get 'the-empty-termlist 'sparse)))
   )
  )

 ("sparse-termlist (adjoin-term)"
   ("3x+4 + 2x^2"
    (assert-equal '(sparse 2 3 4)
		  ((apply-generic 'adjoin-term '(sparse 3 4)) '(term 2 2)))
    )

   ("0 + 2x^2"
    (assert-equal '(sparse 2 0 0)
		  ((apply-generic 'adjoin-term '(sparse)) '(term 2 2)))
    )
   ("x + 2x^3"
    (assert-equal '(sparse 2 0 1 0)
		  ((apply-generic 'adjoin-term '(sparse 1 0)) '(term 3 2)))
    )
   )

 ("sparse polynomial operation (add)"
  ("different variable"
   (assert-error (lambda () (add (make-sparse-polynomial 'x '(0 5))
				 (make-sparse-polynomial 'y '(0 5)))))
   )

  ("add 0 to 5 (1)"
   (let ((test (add (make-sparse-polynomial 'x '(0))
		    (make-sparse-polynomial 'x '(5)))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(sparse 5) (cddr test)))
   )
  
  ("add 0 to 5 (2)"
   (let ((test (add (make-sparse-polynomial 'x '())
		    (make-sparse-polynomial 'x '(5)))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(sparse 5) (cddr test)))
   )

  ("add 5 to 0 (1)"
   (let ((test (add (make-sparse-polynomial 'x '(5))
		    (make-sparse-polynomial 'x '(0)))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(sparse 5) (cddr test)))
   )

  ("add 5 to 0 (2)"
   (let ((test (add (make-sparse-polynomial 'x '(5))
		    (make-sparse-polynomial 'x '()))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(sparse 5) (cddr test)))
   )

  ("normal"
   (assert-equal '(polynomial x sparse 3 2 4)
                 (add (make-sparse-polynomial 'x '(2 1 2))
                      (make-sparse-polynomial 'x '(1 1 2))))
   )

  ("x+2 + 2x^2+2x+2 -> 2x^2+3x+4"
   (assert-equal '(polynomial x sparse 2 3 4)
		 (add (make-sparse-polynomial 'x '(1 2))
		      (make-sparse-polynomial 'x '(2 2 2))))
   )

  ("2x^2+2x+2 + x+2 -> 2x^2+3x+4"
   (assert-equal '(polynomial x sparse 2 3 4)
		 (add (make-sparse-polynomial 'x '(2 2 2))
		      (make-sparse-polynomial 'x '(1 2))))
   )

  ("0x^3+0x^2+0x+0 + x^3+2x^2+3x+4 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x sparse 1 2 3 4)
		 (add (make-sparse-polynomial 'x '(0 0 0 0))
		      (make-sparse-polynomial 'x '(1 2 3 4))))
   )

  ("x^3+2x^2+3x+4 + 0x^3+0x^2+0x+0 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x sparse 1 2 3 4)
		 (add (make-sparse-polynomial 'x '(1 2 3 4))
		      (make-sparse-polynomial 'x '(0 0 0 0))))
   )

  ("0 + x^3+2x^2+3x+4 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x sparse 1 2 3 4)
		 (add (make-sparse-polynomial 'x '())
		      (make-sparse-polynomial 'x '(1 2 3 4))))
   )

  ("x^3+2x^2+3x+4 + 0 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x sparse 1 2 3 4)
		 (add (make-sparse-polynomial 'x '(1 2 3 4))
		      (make-sparse-polynomial 'x '())))
   )

  ("1 - 1 -> 0"
   (assert-equal '(polynomial x sparse 0)
		 (add (make-sparse-polynomial 'x '(1))
		      (make-sparse-polynomial 'x '(-1))))
   )
  )

 ("sparse polynomial operation (mul)"
  ("different variable"
   (assert-error (lambda () (mul (make-sparse-polynomial 'x '(5))
				 (make-sparse-polynomial 'y '(5)))))
   )

  ("p1 is not variable"
   (assert-error (lambda () (mul (make-sparse-polynomial 1 '(5))
				 (make-sparse-polynomial 'x '(5)))))
   )

  ("p2 is not variable"
   (assert-error (lambda () (mul (make-sparse-polynomial 'x '(5))
				 (make-sparse-polynomial 2 '(5)))))
   )

  ("1 * 1 -> 1"
   (assert-equal '(polynomial x sparse 1)
		 (mul (make-sparse-polynomial 'x '(1))
		      (make-sparse-polynomial 'x '(1))))
   )

;; !! it's not _the-empty-termlist_ !!
;; mmmm....

  ("0 * 1 -> 0"
   (assert-equal '(polynomial x sparse 0)
		 (mul (make-sparse-polynomial 'x '(0))
		      (make-sparse-polynomial 'x '(1))))
   )

  ("1 * 0 -> 0"
   (assert-equal '(polynomial x sparse)
		 (mul (make-sparse-polynomial 'x '(1))
		      (make-sparse-polynomial 'x '(0))))
   )

  ("0 * 1 -> 0"
   (assert-equal '(polynomial x sparse)
		 (mul (make-sparse-polynomial 'x '())
		      (make-sparse-polynomial 'x '(1))))
   )
  
  ("1 * 0 -> 0"
   (assert-equal '(polynomial x sparse)
		 (mul (make-sparse-polynomial 'x '(1))
		      (make-sparse-polynomial 'x '())))
   )

  ("6x+5 * 2x^2+3 -> 12x^3+10x^2+18x+15"
   (assert-equal '(polynomial x sparse 12 10 18 15)
		 (mul (make-sparse-polynomial 'x '(6 5))
		      (make-sparse-polynomial 'x '(2 0 3))))
   )
  )

 ("sparse polynomial operation (=zero?)"
  ("() is zero"
   (assert-true (=zero? (make-sparse-polynomial 'x '())))
   )

  ("() is zero (2)"
   (assert-true (=zero? '(polynomial x sparse)))
   )

  ("(0 0 0 0) is zero"
   (assert-true (=zero? '(polynomial x sparse 0 0 0 0)))
   )

  ("(y + 1)x + (-y - 1)x is zero"
   (let ((py1 (make-sparse-polynomial 'y '(1 1)))
	 (py2 (make-sparse-polynomial 'y '(-1 -1))))
     (assert-true (=zero? (add (make-sparse-polynomial 'x (list py1 0))
			       (make-sparse-polynomial 'x (list py2 0))))))
   )
  )

 ("sparse polynomial operation (neg)"
  ("first (1x - 1x = 0)"
   (assert-true (=zero? (add (make-sparse-polynomial 'x '(1 0))
			     (neg (make-sparse-polynomial 'x '(1 0))))))
   )

  ("2nd (1x - 0 = 1x)"
   (let ((p (make-sparse-polynomial 'x '(1 0))))
     (assert-equal p (add p (neg (make-sparse-polynomial 'x '())))))
   )

  ("3rd (1x - 0x = 1x)"
   (let ((p1 (make-sparse-polynomial 'x '(1 0)))
	 (p2 (make-sparse-polynomial 'x '(0 0))))
     (assert-equal p1 (add p1 (neg p2))))
   )

  ("4th polynomial neg"
   (let ((p1 (make-sparse-polynomial 'x '(1 2 3 4)))
	 (p2 (make-sparse-polynomial 'x '(-1 -2 -3 -4))))
     (assert-equal p1 (neg p2))
     (assert-equal p2 (neg p1)))
   )
  )

 ("dense-termlist (first-term)"
  ("1 element"
   (assert-equal '(term 0 5)
                 (apply-generic 'first-term '(dense (0 5))))
   )

  ("6 elements"
   (assert-equal '(term 5 3)
                 (apply-generic 'first-term 
				'(dense (5 3) (4 4) (3 5) (2 6) (1 7) (0 8))))
   )
  )

 ("dense-termlist (rest-terms)"
  ("1 element"
   (assert-equal '(dense) (apply-generic 'rest-terms '(dense (2 5))))
   )
  
  ("6 elements"
   (assert-equal '(dense (7 4) (6 5) (4 6) (2 7) (0 8))
                 (apply-generic 'rest-terms 
				'(dense (9 3) (7 4) (6 5) (4 6) (2 7) (0 8))))
   )
  )

 ("dense-termlist (empty-termlist?)"
  ("empty dense-termlist"
   (assert-true (apply-generic 'empty-termlist? '(dense)))
   )

  ("no empty"
   (assert-false (apply-generic 'empty-termlist? '(dense (0 1))))
   )
  )

 ("dense-termlist (the-empty-termlist) -- no use"
  ("..."
   (assert-true (apply-generic 'empty-termlist?
                               ((get 'the-empty-termlist 'dense))))
   )

  ("..."
   (assert-equal '(dense) ((get 'the-empty-termlist 'dense)))
   )
  )

 ("dense-termlist (adjoin-term)"
   ("3x+4 + 2x^2"
    (assert-equal '(dense (2 2) (1 3) (0 4))
		  ((apply-generic 'adjoin-term '(dense (1 3) (0 4))) '(term 2 2)))
    )

   ("0 + 2x^2"
    (assert-equal '(dense (2 2))
		  ((apply-generic 'adjoin-term '(dense)) '(term 2 2)))
    )
   ("x + 2x^3"
    (assert-equal '(dense (3 2) (1 1))
		  ((apply-generic 'adjoin-term '(dense (1 1))) '(term 3 2)))
    )
   )

 ("dense polynomial operation (add)"
  ("different variable"
   (assert-error (lambda () (add (make-dense-polynomial 'x '((0 5)))
				 (make-dense-polynomial 'y '((0 5))))))
   )

  ("add 0 to 5 (1)"
   (let ((test (add (make-dense-polynomial 'x '((0 0)))
		    (make-dense-polynomial 'x '((0 5))))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(dense (0 5)) (cddr test)))
   )
  
  ("add 0 to 5 (2)"
   (let ((test (add (make-dense-polynomial 'x '())
		    (make-dense-polynomial 'x '((0 5))))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(dense (0 5)) (cddr test)))
   )

  ("add 5 to 0 (1)"
   (let ((test (add (make-dense-polynomial 'x '((0 5)))
		    (make-dense-polynomial 'x '((0 0))))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(dense (0 5)) (cddr test)))
   )

  ("add 5 to 0 (2)"
   (let ((test (add (make-dense-polynomial 'x '((0 5)))
		    (make-dense-polynomial 'x '()))))
     (assert-equal 'polynomial (car test))
     (assert-equal 'x (cadr test))
     (assert-equal '(dense (0 5)) (cddr test)))
   )

  ("normal"
   (assert-equal '(polynomial x dense (5 3) (2 2) (0 4))
                 (add (make-dense-polynomial 'x '((5 2) (2 1) (0 2)))
                      (make-dense-polynomial 'x '((5 1) (2 1) (0 2)))))
   )

  ("x+2 + 2x^2+2x+2 -> 2x^2+3x+4"
   (assert-equal '(polynomial x dense (5 2) (3 3) (1 4))
		 (add (make-dense-polynomial 'x '((3 1) (1 2)))
		      (make-dense-polynomial 'x '((5 2) (3 2) (1 2)))))
   )

  ("2x^2+2x+2 + x+2 -> 2x^2+3x+4"
   (assert-equal '(polynomial x dense (2 2) (1 3) (0 4))
		 (add (make-dense-polynomial 'x '((2 2) (1 2) (0 2)))
		      (make-dense-polynomial 'x '((1 1) (0 2)))))
   )

  ("0x^3+0x^2+0x+0 + x^3+2x^2+3x+4 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x dense (3 1) (2 2) (1 3) (0 4))
		 (add (make-dense-polynomial 'x '((3 0) (2 0) (1 0) (0 0)))
		      (make-dense-polynomial 'x '((3 1) (2 2) (1 3) (0 4)))))
   )

  ("x^3+2x^2+3x+4 + 0x^3+0x^2+0x+0 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x dense (3 1) (2 2) (1 3) (0 4))
		 (add (make-dense-polynomial 'x '((3 1) (2 2) (1 3) (0 4)))
		      (make-dense-polynomial 'x '((3 0) (2 0) (1 0) (0 0)))))
   )

  ("0 + x^3+2x^2+3x+4 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x dense (3 1) (2 2) (1 3) (0 4))
		 (add (make-dense-polynomial 'x '())
		      (make-dense-polynomial 'x '((3 1) (2 2) (1 3) (0 4)))))
   )

  ("x^3+2x^2+3x+4 + 0 -> x^3+2x^2+3x+4"
   (assert-equal '(polynomial x dense (3 1) (2 2) (1 3) (0 4))
		 (add (make-dense-polynomial 'x '((3 1) (2 2) (1 3) (0 4)))
		      (make-dense-polynomial 'x '())))
   )

  ("1 - 1 -> 0"
   (assert-equal '(polynomial x dense)
		 (add (make-dense-polynomial 'x '((0 1)))
		      (make-dense-polynomial 'x '((0 -1)))))
   )
  )

 ("dense polynomial operation (mul)"
  ("different variable"
   (assert-error (lambda () (mul (make-dense-polynomial 'x '((0 5)))
				 (make-dense-polynomial 'y '((0 5))))))
   )

  ("p1 is not variable"
   (assert-error (lambda () (mul (make-dense-polynomial 1 '((0 5)))
				 (make-dense-polynomial 'x '((0 5))))))
   )

  ("p2 is not variable"
   (assert-error (lambda () (mul (make-dense-polynomial 'x '((0 5)))
				 (make-dense-polynomial 2 '((0 5))))))
   )

  ("1 * 1 -> 1"
   (assert-equal '(polynomial x dense (0 1))
		 (mul (make-dense-polynomial 'x '((0 1)))
		      (make-dense-polynomial 'x '((0 1)))))
   )

;; !! it's not _the-empty-termlist_ !!
;; mmmm....

  ("0 * 1 -> 0"
   (assert-equal '(polynomial x dense)
		 (mul (make-dense-polynomial 'x '())
		      (make-dense-polynomial 'x '((0 1)))))
   )

  ("1 * 0 -> 0"
   (assert-equal '(polynomial x dense)
		 (mul (make-dense-polynomial 'x '((0 1)))
		      (make-dense-polynomial 'x '())))
   )

  ("0 * 1 -> 0"
   (assert-equal '(polynomial x dense)
		 (mul (make-dense-polynomial 'x '((0 0)))
		      (make-dense-polynomial 'x '((0 1)))))
   )
  
  ("1 * 0 -> 0"
   (assert-equal '(polynomial x dense)
		 (mul (make-dense-polynomial 'x '((0 1)))
		      (make-dense-polynomial 'x '((0 0)))))
   )

  ("6x+5 * 2x^2+3 -> 12x^3+10x^2+18x+15"
   (assert-equal '(polynomial x dense (3 12) (2 10) (1 18) (0 15))
		 (mul (make-dense-polynomial 'x '((1 6) (0 5)))
		      (make-dense-polynomial 'x '((2 2) (0 3)))))
   )
  )

 ("dense polynomial operation (=zero?)"
  ("() is zero"
   (assert-true (=zero? (make-dense-polynomial 'x '())))
   )

  ("() is zero (2)"
   (assert-true (=zero? '(polynomial x dense)))
   )

  ("(y + 1)x + (-y - 1)x is zero"
   (let ((py1 (make-dense-polynomial 'y '((1 1) (0 1))))
	 (py2 (make-dense-polynomial 'y '((1 -1) (0 -1)))))
     (assert-true (=zero? (add (make-dense-polynomial 'x (list (list 1 py1) 
							       '(0 0)))
			       (make-dense-polynomial 'x (list (list 1 py2) 
							       '(0 0)))))))
   )
  )

 ("dense polynomial operation (neg)"
  ("first (1x - 1x = 0)"
   (assert-true (=zero? (add (make-dense-polynomial 'x '((1 1)))
			     (neg (make-dense-polynomial 'x '((1 1)))))))
   )

  ("2nd (1x - 0 = 1x)"
   (let ((p (make-dense-polynomial 'x '((1 1)))))
     (assert-equal p (add p (neg (make-dense-polynomial 'x '())))))
   )

  ("3rd (1x - 0x = 1x)"
   (let ((p1 (make-dense-polynomial 'x '((1 1))))
	 (p2 (make-dense-polynomial 'x '())))
     (assert-equal p1 (add p1 (neg p2))))
   )

  ("4th polynomial neg"
   (let ((p1 (make-dense-polynomial 'x '((5 1) (3 2) (1 3) (0 4))))
	 (p2 (make-dense-polynomial 'x '((5 -1) (3 -2) (1 -3) (0 -4)))))
     (assert-equal p1 (neg p2))
     (assert-equal p2 (neg p1)))
   )
  )

 )

微妙なままサラしてしまう、というのも無責任というか ....