lu-decomp.scm 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. ; Copyright (c) 1993-2007 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; LU Decomposition (a rewriting of a Pascal program from `Numerical Recipes
  3. ; in Pascal'; look there for a detailed description of what is going on).
  4. ; A is an NxN matrix that is updated in place.
  5. ; This returns a row permutation vector and the sign of that vector.
  6. (define *lu-decomposition-epsilon* 1.0e-20)
  7. (define (lu-decomposition a)
  8. (let* ((n (car (array-shape a)))
  9. (indx (make-vector n))
  10. (sign 1.0)
  11. (vv (make-vector n)))
  12. (do ((i 0 (+ i 1)))
  13. ((>= i n))
  14. (do ((j 0 (+ j 1))
  15. (big 0.0 (max big (abs (array-ref a i j)))))
  16. ((>= j n)
  17. (if (= big 0.0)
  18. (error "lu-decomposition matrix has a zero row" a i))
  19. (vector-set! vv i (/ big)))))
  20. (do ((j 0 (+ j 1)))
  21. ((>= j n))
  22. (let ()
  23. (define (sum-elts i end)
  24. (do ((k 0 (+ k 1))
  25. (sum (array-ref a i j)
  26. (- sum (* (array-ref a i k)
  27. (array-ref a k j)))))
  28. ((>= k end)
  29. sum)))
  30. (do ((i 0 (+ i 1)))
  31. ((>= i j))
  32. (array-set! a (sum-elts i i) i j))
  33. (receive (big imax)
  34. (let loop ((i j) (big 0.0) (imax 0))
  35. (if (>= i n)
  36. (values big imax)
  37. (let ((sum (sum-elts i j)))
  38. (array-set! a sum i j)
  39. (let ((temp (* (vector-ref vv i) (abs sum))))
  40. (if (>= temp big)
  41. (loop (+ i 1) temp i)
  42. (loop (+ i 1) big imax))))))
  43. (if (not (= j imax))
  44. (begin
  45. (do ((k 0 (+ k 1)))
  46. ((>= k n))
  47. (let ((temp (array-ref a imax k)))
  48. (array-set! a (array-ref a j k) imax k)
  49. (array-set! a temp j k)))
  50. (set! sign (- sign))
  51. (vector-set! vv imax (vector-ref vv j))))
  52. (vector-set! indx j imax)
  53. (if (= (array-ref a j j) 0.0)
  54. (array-set! a *lu-decomposition-epsilon* j j))
  55. (if (not (= j (- n 1)))
  56. (let ((temp (/ (array-ref a j j))))
  57. (do ((i (+ j 1) (+ i 1)))
  58. ((>= i n))
  59. (array-set! a (* (array-ref a i j) temp) i j)))))))
  60. (values indx sign)))
  61. (define (lu-back-substitute a indx b)
  62. (let ((n (car (array-shape a))))
  63. (let loop ((i 0) (ii #f))
  64. (if (< i n)
  65. (let* ((ip (vector-ref indx i))
  66. (temp (vector-ref b ip)))
  67. (vector-set! b ip (vector-ref b i))
  68. (let ((new (if ii
  69. (do ((j ii (+ j 1))
  70. (sum temp (- sum (* (array-ref a i j)
  71. (vector-ref b j)))))
  72. ((>= j i)
  73. sum))
  74. temp)))
  75. (vector-set! b i new)
  76. (loop (+ i 1)
  77. (if (or ii (= temp 0.0)) ii i))))))
  78. (do ((i (- n 1) (- i 1)))
  79. ((< i 0))
  80. (do ((j (+ i 1) (+ j 1))
  81. (sum (vector-ref b i) (- sum (* (array-ref a i j)
  82. (vector-ref b j)))))
  83. ((>= j n)
  84. (vector-set! b i (/ sum (array-ref a i i))))))))
  85. ;(define m
  86. ; (array '(4 4)
  87. ; 1.0 2.0 3.0 -2.0
  88. ; 8.0 -6.0 6.0 1.0
  89. ; 3.0 -2.0 0.0 -7.0
  90. ; 4.0 7.0 2.0 -1.0))
  91. ;
  92. ;(define b '#(2.0 1.0 3.0 -2.0))
  93. ;
  94. ;(define (test m b)
  95. ; (let* ((a (copy-array m))
  96. ; (n (car (array-shape m)))
  97. ; (x (make-vector n)))
  98. ;
  99. ; (do ((i 0 (+ i 1)))
  100. ; ((>= i n))
  101. ; (vector-set! x i (vector-ref b i)))
  102. ;
  103. ; (display "b = ")
  104. ; (display b)
  105. ; (newline)
  106. ;
  107. ; (call-with-values
  108. ; (lambda ()
  109. ; (lu-decomposition a))
  110. ; (lambda (indx sign)
  111. ; (lu-back-substitute a indx x)
  112. ;
  113. ; (display "x = ")
  114. ; (display x)
  115. ; (newline)
  116. ;
  117. ; (let ((y (make-vector (vector-length b))))
  118. ; (do ((i 0 (+ i 1)))
  119. ; ((>= i n))
  120. ; (do ((j 0 (+ j 1))
  121. ; (t 0.0 (+ t (* (array-ref m i j) (vector-ref x j)))))
  122. ; ((>= j n)
  123. ; (vector-set! y i t))))
  124. ;
  125. ; (display "a * x =")
  126. ; (display y)
  127. ; (newline))))))