123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- ; Copyright (c) 1993-2007 by Richard Kelsey and Jonathan Rees. See file COPYING.
- ; LU Decomposition (a rewriting of a Pascal program from `Numerical Recipes
- ; in Pascal'; look there for a detailed description of what is going on).
- ; A is an NxN matrix that is updated in place.
- ; This returns a row permutation vector and the sign of that vector.
- (define *lu-decomposition-epsilon* 1.0e-20)
- (define (lu-decomposition a)
- (let* ((n (car (array-shape a)))
- (indx (make-vector n))
- (sign 1.0)
- (vv (make-vector n)))
- (do ((i 0 (+ i 1)))
- ((>= i n))
- (do ((j 0 (+ j 1))
- (big 0.0 (max big (abs (array-ref a i j)))))
- ((>= j n)
- (if (= big 0.0)
- (error "lu-decomposition matrix has a zero row" a i))
- (vector-set! vv i (/ big)))))
- (do ((j 0 (+ j 1)))
- ((>= j n))
- (let ()
- (define (sum-elts i end)
- (do ((k 0 (+ k 1))
- (sum (array-ref a i j)
- (- sum (* (array-ref a i k)
- (array-ref a k j)))))
- ((>= k end)
- sum)))
- (do ((i 0 (+ i 1)))
- ((>= i j))
- (array-set! a (sum-elts i i) i j))
- (receive (big imax)
- (let loop ((i j) (big 0.0) (imax 0))
- (if (>= i n)
- (values big imax)
- (let ((sum (sum-elts i j)))
- (array-set! a sum i j)
- (let ((temp (* (vector-ref vv i) (abs sum))))
- (if (>= temp big)
- (loop (+ i 1) temp i)
- (loop (+ i 1) big imax))))))
-
- (if (not (= j imax))
- (begin
- (do ((k 0 (+ k 1)))
- ((>= k n))
- (let ((temp (array-ref a imax k)))
- (array-set! a (array-ref a j k) imax k)
- (array-set! a temp j k)))
- (set! sign (- sign))
- (vector-set! vv imax (vector-ref vv j))))
-
- (vector-set! indx j imax)
-
- (if (= (array-ref a j j) 0.0)
- (array-set! a *lu-decomposition-epsilon* j j))
-
- (if (not (= j (- n 1)))
- (let ((temp (/ (array-ref a j j))))
- (do ((i (+ j 1) (+ i 1)))
- ((>= i n))
- (array-set! a (* (array-ref a i j) temp) i j)))))))
-
- (values indx sign)))
- (define (lu-back-substitute a indx b)
- (let ((n (car (array-shape a))))
-
- (let loop ((i 0) (ii #f))
- (if (< i n)
- (let* ((ip (vector-ref indx i))
- (temp (vector-ref b ip)))
- (vector-set! b ip (vector-ref b i))
- (let ((new (if ii
- (do ((j ii (+ j 1))
- (sum temp (- sum (* (array-ref a i j)
- (vector-ref b j)))))
- ((>= j i)
- sum))
- temp)))
- (vector-set! b i new)
- (loop (+ i 1)
- (if (or ii (= temp 0.0)) ii i))))))
- (do ((i (- n 1) (- i 1)))
- ((< i 0))
- (do ((j (+ i 1) (+ j 1))
- (sum (vector-ref b i) (- sum (* (array-ref a i j)
- (vector-ref b j)))))
- ((>= j n)
- (vector-set! b i (/ sum (array-ref a i i))))))))
- ;(define m
- ; (array '(4 4)
- ; 1.0 2.0 3.0 -2.0
- ; 8.0 -6.0 6.0 1.0
- ; 3.0 -2.0 0.0 -7.0
- ; 4.0 7.0 2.0 -1.0))
- ;
- ;(define b '#(2.0 1.0 3.0 -2.0))
- ;
- ;(define (test m b)
- ; (let* ((a (copy-array m))
- ; (n (car (array-shape m)))
- ; (x (make-vector n)))
- ;
- ; (do ((i 0 (+ i 1)))
- ; ((>= i n))
- ; (vector-set! x i (vector-ref b i)))
- ;
- ; (display "b = ")
- ; (display b)
- ; (newline)
- ;
- ; (call-with-values
- ; (lambda ()
- ; (lu-decomposition a))
- ; (lambda (indx sign)
- ; (lu-back-substitute a indx x)
- ;
- ; (display "x = ")
- ; (display x)
- ; (newline)
- ;
- ; (let ((y (make-vector (vector-length b))))
- ; (do ((i 0 (+ i 1)))
- ; ((>= i n))
- ; (do ((j 0 (+ j 1))
- ; (t 0.0 (+ t (* (array-ref m i j) (vector-ref x j)))))
- ; ((>= j n)
- ; (vector-set! y i t))))
- ;
- ; (display "a * x =")
- ; (display y)
- ; (newline))))))
|