home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-04-27 | 6.2 KB | 232 lines | [TEXT/????] |
- ;;; $Header: matrix.scm,v 1.2 87/08/28 00:57:38 GMT gjs Exp $
- ;;;; Matrix Package
-
- (if-mit
- (declare (usual-integrations = + - * /
- zero? 1+ -1+
- ;; truncate round floor ceiling
- sqrt exp log sin cos)))
-
- ;;; A matrix is represented as a vector of rows, where each row
- ;;; is a vector of field elements.
-
- (define ((matrix-elementwise f) . matrices)
- (generate-matrix
- (num-rows (car matrices))
- (num-cols (car matrices))
- (lambda (i j)
- (apply f (map (lambda (m) (matrix-ref m i j)) matrices)))))
-
- (define (make-matrix n m . optional)
- (let ((ans (make-vector n))
- (filler (if optional (car optional) '())))
- (let loop ((i 0))
- (if (= i n)
- ans
- (begin (vector-set! ans i
- (make-vector m filler))
- (loop (+ i 1)))))))
-
- (define (matrix-by-rows M)
- (apply vector (map list->vector M)))
-
- (define (matrix-by-cols M)
- (transpose (matrix-by-rows M)))
-
- (define (generate-matrix rows cols proc)
- (let ((ans (make-matrix rows cols)))
- (let loop-rows ((i 0))
- (if (= i rows)
- ans
- (begin (let loop-columns ((j 0))
- (if (= j cols)
- 'done
- (begin (matrix-set! ans i j (proc i j))
- (loop-columns (+ j 1)))))
- (loop-rows (+ i 1)))))))
-
- (define (num-rows m) (vector-length m))
- (define (num-cols m) (vector-length (vector-ref m 0)))
-
- (define (matrix-ref m i j)
- (vector-ref (vector-ref m i) j))
-
- (define (matrix-set! m i j v)
- (vector-set! (vector-ref m i) j v))
-
- (define (vector->row-matrix v)
- (vector v))
-
- (define (vector->col-matrix v)
- (transpose (vector->row-matrix v)))
-
- (define (outer-product v1 v2)
- (matrix*matrix (vector->col-matrix v1)
- (vector->row-matrix v2)))
-
- (define (nth-row M n) ;return as a vector
- (vector-ref M n))
-
- (define (nth-col M n)
- (nth-row (transpose M) n))
-
- (define (copy-matrix m)
- (generate-matrix (num-rows m) (num-cols m)
- (lambda (i j) (matrix-ref m i j))))
-
-
- (define add-matrices
- (vector-elementwise add-vectors))
-
- (define sub-matrices
- (vector-elementwise sub-vectors))
-
- (define (mul-matrices . m)
- (let loop ((remaining m) (prod (identity-matrix (num-rows (car m)))))
- (if (null? remaining)
- prod
- (loop (cdr remaining) (matrix*matrix prod (car remaining))))))
-
- (define (matrix*matrix m1 m2)
- (let ((m1r (num-rows m1))
- (m1c (num-cols m1))
- (m2r (num-rows m2))
- (m2c (num-cols m2)))
- (if (not (and (= m1c m2r)))
- (error "matrix sizes do not match -- MATRIX*MATRIX" m1 m2)
- (let ((tm2 (transpose m2)))
- (generate-matrix m1r
- m2c
- (lambda (i j)
- (dot-product (vector-ref m1 i)
- (vector-ref tm2 j))))))))
-
-
- (define (transpose m)
- (generate-matrix (num-cols m)
- (num-rows m)
- (lambda (i j) (matrix-ref m j i))))
-
- (define (matrix*scalar m k)
- (generate-matrix (num-rows m)
- (num-cols m)
- (lambda (i j) (* k (matrix-ref m i j)))))
-
- (define (scale-matrix k)
- (lambda (m) (matrix*scalar m k)))
-
- (define matrix*vector
- (lambda (mat vec)
- (if (not (= (vector-length vec) (num-cols mat)))
- (error "Not conformable for multiplication" mat vec)
- (generate-vector (num-rows mat)
- (lambda (i)
- (dot-product (nth-row mat i) vec))))))
-
- (define vector*matrix
- (lambda (vec mat)
- (if (not (= (vector-length vec) (num-rows mat)))
- (error "Not conformable for multiplication" vec mat)
- (generate-vector (num-cols mat)
- (lambda (i)
- (dot-product vec (nth-col mat i)))))))
-
-
- (define (zero-matrix n)
- (make-vector n (make-vector n 0)))
-
- (define (identity-matrix n)
- (generate-vector
- n
- (lambda (i) (unit-vector n i))))
-
- (define (general-determinant zero add sub mul)
- (define (internal-determinant m)
- (let ((size (num-cols m)))
- (if (= size 1)
- (matrix-ref m 0 0)
- (let colloop ((i 0) (ans zero) (sgn 1))
- (if (= i size)
- ans
- (colloop (1+ i)
- (add ans
- (mul sgn
- (matrix-ref m 0 i)
- (internal-determinant (cofactor m 0 i))))
- (sub zero sgn)))))))
- internal-determinant)
-
- (define (cofactor m i j)
- (generate-matrix
- (-1+ (num-rows m))
- (-1+ (num-cols m))
- (lambda (a b)
- (matrix-ref
- m
- (if (< a i) a (1+ a))
- (if (< b j) b (1+ b))))))
-
- (define determinant (general-determinant 0 + - *))
-
- (define (det M)
- (let ((lu (lu-decompose M allow-zero-pivot))
- (n (num-rows M)))
- (let ((a (car lu)) ; the matrix part
- (p (cadr lu)) ; the permutation, as a vector
- (s (caddr lu))) ; sign of permutation
- (if (< (lu-rank a) n)
- 0
- (let loop ((i 0) (prod s))
- (if (= i n)
- prod
- (loop (+ i 1) (* prod (matrix-ref a i i)))))))))
-
- (define (diagonal m)
- (if (not (= (num-rows m) (num-cols m)))
- (error "diagonal of a non-square matrix" m))
- (let loop ((i 0))
- (if (= i (num-rows m))
- '()
- (cons (matrix-ref m i i)
- (loop (1+ i))))))
-
- (define (make-diagonal-matrix diag)
- (let ((n (vector-length diag)))
- (generate-matrix n n
- (lambda (i j)
- (if (not (= i j))
- 0
- (vector-ref diag i))))))
-
- (define (matrix-trace m)
- (apply + (diagonal m)))
-
-
- (define (matinv a)
- (let ((n (num-rows a))
- (lu (lu-decompose a)))
- (let ((lumat (car lu)) (luperm (cadr lu)))
- (let ((m (generate-vector
- n
- (lambda (i)
- (let ((e (unit-vector n i)))
- (lu-backsubstitute lumat luperm e))))))
- (transpose m)))))
-
- (define (matrix^nth M p)
- (let ((n (round p)))
- (cond ((not (= n p))
- (error "Only integer powers allowed -- MATRIX^NTH"))
- ((< n 0)
- (matrix^nth (matinv M) (- n)))
- ((zero? n)
- (identity-matrix (num-rows M)))
- (else
- (let loop ((count n))
- (cond ((= count 1) M)
- ((even? count)
- (let ((a (loop (quotient count 2))))
- (matrix*matrix a a)))
- (else
- (matrix*matrix M (loop (-1+ count))))))))))
-