Skip to content

Commit

Permalink
refactor out matrix decomp/factorization methods into smaller chunks.
Browse files Browse the repository at this point in the history
Signed-off-by: AJ Rossini <blindglobe@gmail.com>
  • Loading branch information
blindglobe committed Feb 28, 2009
1 parent b6a26f5 commit 445cfc2
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 156 deletions.
11 changes: 10 additions & 1 deletion lisp-matrix.asd
Expand Up @@ -56,10 +56,19 @@
:components
((:file "matrix-lisp-array")
(:file "matrix-foreign-array")
;; probably should move the remainder into a numerical linear
;; algebra place.
(:file "lapack-utils" :depends-on ("matrix-foreign-array"
"matrix-lisp-array"))
(:file "lapack-methods" :depends-on ("lapack-utils"))
(:file "matrix-operations" :depends-on ("lapack-methods"))))
(:file "lapack-cholesky" :depends-on ("lapack-utils"))
(:file "lapack-lu" :depends-on ("lapack-utils"))
(:file "lapack-qr" :depends-on ("lapack-utils"))

(:file "matrix-operations" :depends-on ("lapack-methods"
"lapack-cholesky"
"lapack-lu"
"lapack-qr"))))

(:module
"testing"
Expand Down
74 changes: 74 additions & 0 deletions src/lapack-cholesky.lisp
@@ -0,0 +1,74 @@

(in-package :lisp-matrix)

;;; CHOLESKY

;;; POTRF - compute the Cholesky Factorization of a real sym pos-def
;;; matrix A.
;;; Returns Matrix, upper/lower triang char, info
(def-lapack-method potrf ((a !matrix-type))
(let ((info (make-fnv-int32 1 :initial-value 0)))
(assert (<= (ncols a) (nrows a))) ; make sure A supports options
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
(list a
"U"
(check-info (fnv-int32-ref info 0) "POTRF"))
(!function "U" ; store in Upper section
(ncols a) ; N
a ; matrix (in/out)
(real-nrows a) ; LDA
info)))) ; info

;;; POTRI - compute the inverse of a real symmetric positive definite
;;; matrix A using the Cholesky factorization A = U**T*U or A = L*L**T
(def-lapack-method potri ((a !matrix-type))
(assert (= (ncols a) (nrows a))) ;; only works with square matrices
(let ((info (make-fnv-int32 1 :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
;; Returning:
;; - inverse,
;; - "U" since upper format trangular,
;; - info, for correctness of results.
;; Should we put INFO first?!
(list a
"U" ; not useful until we add option for lowercase.
(check-info (fnv-int32-ref info 0) "POTRI"))
(!function "U" ; "L" (in) is lower an option?
(ncols a) ; N (in) (order of matrix, columns, 2nd index
a ; a (in/out) matrix
(nrows a) ; LDA (in) leading dimension, LDA >= max(1,N)
; above was "(real-nrows a)" ?
info)))) ; info (out)



;;; CHOLESKY
;;
;; POTRI - compute the inverse of a real symmetric positive definite
;; matrix A using the Cholesky factorization A = U**T*U or A = L*L**T
(def-lapack-method potri ((a !matrix-type))
(assert (= (ncols a) (nrows a))) ; only square matrices
(let ((info (make-fnv-int32 1 :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
;; Returning:
;; - inverse,
;; - "U" since upper format trangular,
;; - info, for correctness of results.
;; Should we put INFO first?!
(list a
"U" ; not useful until we add option for lowercase.
(check-info (fnv-int32-ref info 0) "POTRI"))
(!function "U" ; "L" (in) is lower an option?
(ncols a) ; N (in) (order of matrix, columns, 2nd index
a ; a (in/out) matrix
(nrows a) ; LDA (in) leading dimension, LDA >= max(1,N)
; above was "(real-nrows a)" ?
info)))) ; info (out)


26 changes: 26 additions & 0 deletions src/lapack-lu.lisp
@@ -0,0 +1,26 @@


;;; LU

;;; GETRF - compute the LU Factorization of a matrix.
;;; Returns Matrix, upper/lower triang char, info
(def-lapack-method getrf ((a !matrix-type))
(let ((info (make-fnv-int32 1 :initial-value 0)))
(assert (<= (ncols a) (nrows a))) ; make sure A supports options
(unless ipvt ; make it the bigger of # cols/ # rows
(setf ipvt (make-fnv-int32 (nrows a) :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
(list a
(check-info (fnv-int32-ref info 0) "GETRF"))
(call-with-work (lwork work !data-type)
(!function (nrows a) ; N
(ncols a) ; M
a ; A
(max 1 (ncols a)); LDA
ipiv
;; IPIV (output) INTEGER array, dimension (min(M,N))
;; The pivot indices; for 1 <= i <= min(M,N), row i of
;; the matrix was interchanged with row IPIV(i).
info))))); info
156 changes: 1 addition & 155 deletions src/lapack-methods.lisp
@@ -1,6 +1,6 @@
;;; -*- mode: lisp -*-

;;; Time-stamp: <2009-02-21 14:50:58 tony>
;;; Time-stamp: <2009-02-28 18:15:51 tony>
;;; Creation: <2009-02-05 11:18:51 tony>
;;; File: lapack-methods.lisp
;;; Author: Mark H. < @ >
Expand Down Expand Up @@ -279,157 +279,3 @@
(orig-b (copy b))
(orig-x (copy x)))
(list x (gelsy a b rcond)))))



;;; LU

;;; GETRF - compute the LU Factorization of a matrix.
;;; Returns Matrix, upper/lower triang char, info
(def-lapack-method getrf ((a !matrix-type))
(let ((info (make-fnv-int32 1 :initial-value 0)))
(assert (<= (ncols a) (nrows a))) ; make sure A supports options
(unless ipvt
(setf ipvt (make-fnv-int32 (ncols a) :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
(list a
(check-info (fnv-int32-ref info 0) "GETRF"))
(call-with-work (lwork work !data-type)
(!function (nrows a) ; N
(ncols a) ; M
a ; A
(max 1 (ncols a)); LDA
ipiv
;; IPIV (output) INTEGER array, dimension (min(M,N))
;; The pivot indices; for 1 <= i <= min(M,N), row i of
;; the matrix was interchanged with row IPIV(i).
info))))); info

;;; POTRI - compute the inverse of a real symmetric positive definite
;;; matrix A using the Cholesky factorization A = U**T*U or A = L*L**T
(def-lapack-method potri ((a !matrix-type))
(assert (= (ncols a) (nrows a))) ;; only works with square matrices
(let ((info (make-fnv-int32 1 :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
;; Returning:
;; - inverse,
;; - "U" since upper format trangular,
;; - info, for correctness of results.
;; Should we put INFO first?!
(list a
"U" ; not useful until we add option for lowercase.
(check-info (fnv-int32-ref info 0) "POTRI"))
(!function "U" ; "L" (in) is lower an option?
(ncols a) ; N (in) (order of matrix, columns, 2nd index
a ; a (in/out) matrix
(nrows a) ; LDA (in) leading dimension, LDA >= max(1,N)
; above was "(real-nrows a)" ?
info)))) ; info (out)




;;; CHOLESKY

;;; POTRF - compute the Cholesky Factorization of a real sym pos-def
;;; matrix A.
;;; Returns Matrix, upper/lower triang char, info
(def-lapack-method potrf ((a !matrix-type))
(let ((info (make-fnv-int32 1 :initial-value 0)))
(assert (<= (ncols a) (nrows a))) ; make sure A supports options
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
(list a
"U"
(check-info (fnv-int32-ref info 0) "POTRF"))
(!function "U" ; store in Upper section
(ncols a) ; N
a
(real-nrows a) ; LDA
info)))) ; info

;;; POTRI - compute the inverse of a real symmetric positive definite
;;; matrix A using the Cholesky factorization A = U**T*U or A = L*L**T
(def-lapack-method potri ((a !matrix-type))
(assert (= (ncols a) (nrows a))) ;; only works with square matrices
(let ((info (make-fnv-int32 1 :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t))
;; Returning:
;; - inverse,
;; - "U" since upper format trangular,
;; - info, for correctness of results.
;; Should we put INFO first?!
(list a
"U" ; not useful until we add option for lowercase.
(check-info (fnv-int32-ref info 0) "POTRI"))
(!function "U" ; "L" (in) is lower an option?
(ncols a) ; N (in) (order of matrix, columns, 2nd index
a ; a (in/out) matrix
(nrows a) ; LDA (in) leading dimension, LDA >= max(1,N)
; above was "(real-nrows a)" ?
info)))) ; info (out)

;;; QR decomposition. Need one more front end to provide appropriate
;;; processing. A and TAU will have different values at the end, more
;;; appropriate to the transformation (i.e. will be the QR, but stored
;;; in common compact form).
;;;
;; M (input) INTEGER
;; The number of rows of the matrix A. M >= 0.
;; N (input) INTEGER
;; The number of columns of the matrix A. N >= 0.
;; A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
;; On entry, the M-by-N matrix A. On exit, the elements on and
;; above the diagonal of the array contain the min(M,N)-by-N upper
;; trapezoidal matrix R (R is upper triangular if m >= n); the
;; elements below the diagonal, with the array TAU, represent the
;; orthogonal matrix Q as a product of min(m,n) elementary reflec‐
;; tors (see Further Details).
;; LDA (input) INTEGER
;; The leading dimension of the array A. LDA >= max(1,M).
;; TAU (output) DOUBLE PRECISION array, dimension (min(M,N))
;; The scalar factors of the elementary reflectors (see Further
;; Details).
;; WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)
;; On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
;; LWORK (input) INTEGER
;; The dimension of the array WORK. LWORK >= max(1,N). For opti‐
;; mum performance LWORK >= N*NB, where NB is the optimal block‐
;; size.
;; If LWORK = -1, then a workspace query is assumed; the routine
;; only calculates the optimal size of the WORK array, returns
;; this value as the first entry of the WORK array, and no error
;; message related to LWORK is issued by XERBLA.
;; INFO (output) INTEGER
;; = 0: successful exit
;; < 0: if INFO = -i, the i-th argument had an illegal value

(def-lapack-method geqrf ((a !matrix-type)
(tau !matrix-type)) ; tau is for output
(assert (<= (ncols a) (nrows a))) ; make sure A supports options
(let ((info (make-fnv-int32 1 :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t)
(tau (or (not unit-strides-p)
transposed-p)
t))
(list a
tau
(check-info (fnv-int32-ref info 0) "GEQRF"))
(call-with-work (lwork work !data-type)
(!function (nrows a)
(ncols a)
a
(max 1 (nrows a))
(data tau)
(data work)
lwork
info)))))
64 changes: 64 additions & 0 deletions src/lapack-qr.lisp
@@ -0,0 +1,64 @@

(in-package :lisp-matrix)

;;; QR



;;; QR decomposition. Need one more front end to provide appropriate
;;; processing. A and TAU will have different values at the end, more
;;; appropriate to the transformation (i.e. will be the QR, but stored
;;; in common compact form).
;;;
;; M (input) INTEGER
;; The number of rows of the matrix A. M >= 0.
;; N (input) INTEGER
;; The number of columns of the matrix A. N >= 0.
;; A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
;; On entry, the M-by-N matrix A. On exit, the elements on and
;; above the diagonal of the array contain the min(M,N)-by-N upper
;; trapezoidal matrix R (R is upper triangular if m >= n); the
;; elements below the diagonal, with the array TAU, represent the
;; orthogonal matrix Q as a product of min(m,n) elementary reflec‐
;; tors (see Further Details).
;; LDA (input) INTEGER
;; The leading dimension of the array A. LDA >= max(1,M).
;; TAU (output) DOUBLE PRECISION array, dimension (min(M,N))
;; The scalar factors of the elementary reflectors (see Further
;; Details).
;; WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)
;; On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
;; LWORK (input) INTEGER
;; The dimension of the array WORK. LWORK >= max(1,N). For opti‐
;; mum performance LWORK >= N*NB, where NB is the optimal block‐
;; size.
;; If LWORK = -1, then a workspace query is assumed; the routine
;; only calculates the optimal size of the WORK array, returns
;; this value as the first entry of the WORK array, and no error
;; message related to LWORK is issued by XERBLA.
;; INFO (output) INTEGER
;; = 0: successful exit
;; < 0: if INFO = -i, the i-th argument had an illegal value

(def-lapack-method geqrf ((a !matrix-type)
(tau !matrix-type)) ; tau is for output
(assert (<= (ncols a) (nrows a))) ; make sure A supports options
(let ((info (make-fnv-int32 1 :initial-value 0)))
(with-copies ((a (or (not unit-strides-p)
transposed-p)
t)
(tau (or (not unit-strides-p)
transposed-p)
t))
(list a
tau
(check-info (fnv-int32-ref info 0) "GEQRF"))
(call-with-work (lwork work !data-type)
(!function (nrows a)
(ncols a)
a
(max 1 (nrows a))
(data tau)
(data work)
lwork
info)))))

0 comments on commit 445cfc2

Please sign in to comment.