Mercurial > hg > octave-nkf
changeset 8547:d66c9b6e506a
imported patch qrupdate.diff
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Tue, 20 Jan 2009 21:16:42 +0100 |
parents | 3d8a914c580e |
children | 193bf0e6c567 |
files | Makeconf.in configure.in libcruft/Makefile.in libcruft/qrupdate/Makefile.in libcruft/qrupdate/cch1dn.f libcruft/qrupdate/cch1up.f libcruft/qrupdate/cchdex.f libcruft/qrupdate/cchinx.f libcruft/qrupdate/cqhqr.f libcruft/qrupdate/cqr1up.f libcruft/qrupdate/cqrdec.f libcruft/qrupdate/cqrder.f libcruft/qrupdate/cqrinc.f libcruft/qrupdate/cqrinr.f libcruft/qrupdate/cqrqhu.f libcruft/qrupdate/cqrqhv.f libcruft/qrupdate/cqrshc.f libcruft/qrupdate/dch1dn.f libcruft/qrupdate/dch1up.f libcruft/qrupdate/dchdex.f libcruft/qrupdate/dchinx.f libcruft/qrupdate/dqhqr.f libcruft/qrupdate/dqr1up.f libcruft/qrupdate/dqrdec.f libcruft/qrupdate/dqrder.f libcruft/qrupdate/dqrinc.f libcruft/qrupdate/dqrinr.f libcruft/qrupdate/dqrqhu.f libcruft/qrupdate/dqrqhv.f libcruft/qrupdate/dqrshc.f libcruft/qrupdate/sch1dn.f libcruft/qrupdate/sch1up.f libcruft/qrupdate/schdex.f libcruft/qrupdate/schinx.f libcruft/qrupdate/sqhqr.f libcruft/qrupdate/sqr1up.f libcruft/qrupdate/sqrdec.f libcruft/qrupdate/sqrder.f libcruft/qrupdate/sqrinc.f libcruft/qrupdate/sqrinr.f libcruft/qrupdate/sqrqhu.f libcruft/qrupdate/sqrqhv.f libcruft/qrupdate/sqrshc.f libcruft/qrupdate/zch1dn.f libcruft/qrupdate/zch1up.f libcruft/qrupdate/zchdex.f libcruft/qrupdate/zchinx.f libcruft/qrupdate/zqhqr.f libcruft/qrupdate/zqr1up.f libcruft/qrupdate/zqrdec.f libcruft/qrupdate/zqrder.f libcruft/qrupdate/zqrinc.f libcruft/qrupdate/zqrinr.f libcruft/qrupdate/zqrqhu.f libcruft/qrupdate/zqrqhv.f libcruft/qrupdate/zqrshc.f liboctave/ChangeLog liboctave/CmplxCHOL.cc liboctave/CmplxCHOL.h liboctave/CmplxQR.cc liboctave/CmplxQR.h liboctave/dbleCHOL.cc liboctave/dbleCHOL.h liboctave/dbleQR.cc liboctave/dbleQR.h liboctave/fCmplxCHOL.cc liboctave/fCmplxCHOL.h liboctave/fCmplxQR.cc liboctave/fCmplxQR.h liboctave/floatCHOL.cc liboctave/floatCHOL.h liboctave/floatQR.cc liboctave/floatQR.h src/ChangeLog src/DLD-FUNCTIONS/chol.cc src/DLD-FUNCTIONS/qr.cc src/Makefile.in |
diffstat | 77 files changed, 1346 insertions(+), 4625 deletions(-) [+] |
line wrap: on
line diff
--- a/Makeconf.in +++ b/Makeconf.in @@ -239,6 +239,7 @@ CHOLMOD_LIBS = @CHOLMOD_LIBS@ CXSPARSE_LIBS = @CXSPARSE_LIBS@ OPENGL_LIBS = @OPENGL_LIBS@ +QRUPDATE_LIBS = @QRUPDATE_LIBS@ ARPACK_LIBS = @ARPACK_LIBS@ LIBS = @LIBS@
--- a/configure.in +++ b/configure.in @@ -865,6 +865,34 @@ AC_MSG_WARN($warn_blas_f77_incompatible) fi +QRUPDATE_LIBS= +AC_SUBST(QRUPDATE_LIBS) + +# Check for the qrupdate library +AC_ARG_WITH(qrupdate, + [AS_HELP_STRING([--without-qrupdate], + [don't use qrupdate, disable QR & Cholesky updating functions])], + with_qrupdate=$withval, with_qrupdate=yes) + +warn_qrupdate="qrupdate not found. The QR & Cholesky updating function will not be available." +if test "$with_qrupdate" = yes; then + with_qrupdate=no + if $have_fortran_compiler; then + AC_F77_FUNC(sqr1up) + elif $have_f2c; then + sqr1up=sqr1up_ + fi + AC_CHECK_LIB(qrupdate, $sqr1up, + [QRUPDATE_LIBS="-lqrupdate"; with_qrupdate=yes], [], [$BLAS_LIBS $FLIBS]) + if test "$with_qrupdate" = yes; then + AC_DEFINE(HAVE_QRUPDATE, 1, [Define if the qrupdate library is used.]) + warn_qrupdate= + fi +fi +if test -n "$warn_qrupdate"; then + AC_MSG_WARN($warn_qrupdate) +fi + # Check for AMD library AMD_LIBS= AC_SUBST(AMD_LIBS) @@ -1997,7 +2025,6 @@ libcruft/lapack/Makefile libcruft/misc/Makefile libcruft/odepack/Makefile libcruft/ordered-qz/Makefile libcruft/quadpack/Makefile - libcruft/qrupdate/Makefile libcruft/ranlib/Makefile libcruft/slatec-fn/Makefile libcruft/slatec-err/Makefile libcruft/villad/Makefile libcruft/blas-xtra/Makefile libcruft/lapack-xtra/Makefile]) @@ -2034,6 +2061,7 @@ CHOLMOD libraries: $CHOLMOD_LIBS CXSPARSE libraries: $CXSPARSE_LIBS ARPACK libraries: $ARPACK_LIBS + QRUPDATE libraries: $QRUPDATE_LIBS HDF5 libraries: $HDF5_LIBS CURL libraries: $CURL_LIBS REGEX libraries: $REGEX_LIBS @@ -2120,6 +2148,11 @@ warn_msg_printed=true fi +if test -n "$warn_qrupdate"; then + AC_MSG_WARN($warn_qrupdate) + warn_msg_printed=true +fi + if test -n "$warn_amd"; then AC_MSG_WARN($warn_amd) warn_msg_printed=true
--- a/libcruft/Makefile.in +++ b/libcruft/Makefile.in @@ -43,7 +43,7 @@ CRUFT_DIRS = amos @BLAS_DIR@ blas-xtra daspk dasrt dassl \ @FFT_DIR@ @LAPACK_DIR@ lapack-xtra \ - misc odepack ordered-qz quadpack qrupdate ranlib \ + misc odepack ordered-qz quadpack ranlib \ slatec-err slatec-fn villad SUBDIRS = $(CRUFT_DIRS)
deleted file mode 100644 --- a/libcruft/qrupdate/Makefile.in +++ /dev/null @@ -1,58 +0,0 @@ -# Makefile for octave's libcruft/factupd directory -# -# Copyright (C) 2008 VZLU, a.s. -# -# This file is part of Octave. -# -# Octave is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at -# your option) any later version. -# -# Octave is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License -# along with Octave; see the file COPYING. If not, see -# <http://www.gnu.org/licenses/>. - -TOPDIR = ../.. - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ - -EXTERNAL_DISTFILES = $(DISTFILES) - -FSRC = dqr1up.f zqr1up.f \ - dqrinc.f zqrinc.f \ - dqrdec.f zqrdec.f \ - dqrinr.f zqrinr.f \ - dqrder.f zqrder.f \ - dqrshc.f zqrshc.f \ - dch1up.f zch1up.f \ - dch1dn.f zch1dn.f \ - dchinx.f zchinx.f \ - dchdex.f zchdex.f \ - dqrqhu.f zqrqhu.f \ - dqrqhv.f zqrqhv.f \ - dqhqr.f zqhqr.f \ - sch1up.f cch1up.f \ - sqrinc.f cqrinc.f \ - sqrdec.f cqrdec.f \ - sqrinr.f cqrinr.f \ - sqrder.f cqrder.f \ - sqrshc.f cqrshc.f \ - sqr1up.f cqr1up.f \ - sch1dn.f cch1dn.f \ - schinx.f cchinx.f \ - schdex.f cchdex.f \ - sqrqhu.f cqrqhu.f \ - sqrqhv.f cqrqhv.f \ - sqhqr.f cqhqr.f - -include $(TOPDIR)/Makeconf - -include ../Makerules
deleted file mode 100644 --- a/libcruft/qrupdate/cch1dn.f +++ /dev/null @@ -1,81 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cch1dn(n,R,u,w,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a hermitian positive definite matrix A, i.e. -c A = R'*R, this subroutine downdates R -> R1 so that -c R1'*R1 = A - u*u' -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n,info - complex R(n,n),u(n) - real w(n) - external ctrsv,clartg,scnrm2 - real rho,scnrm2 - complex crho,rr,ui,t - integer i,j - -c quick return if possible - if (n <= 0) return -c check for singularity of R - do i = 1,n - if (R(i,i) == 0e0) then - info = 2 - return - end if - end do -c form R' \ u - call ctrsv('U','C','N',n,R,n,u,1) - rho = scnrm2(n,u,1) -c check positive definiteness - rho = 1 - rho**2 - if (rho <= 0e0) then - info = 1 - return - end if - crho = sqrt(rho) -c eliminate R' \ u - do i = n,1,-1 - ui = u(i) -c generate next rotation - call clartg(crho,ui,w(i),u(i),rr) - crho = rr - end do -c apply rotations - do i = n,1,-1 - ui = 0e0 - do j = i,1,-1 - t = w(j)*ui + u(j)*R(j,i) - R(j,i) = w(j)*R(j,i) - conjg(u(j))*ui - ui = t - end do - end do - - info = 0 - end
deleted file mode 100644 --- a/libcruft/qrupdate/cch1up.f +++ /dev/null @@ -1,56 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cch1up(n,R,u,w) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a hermitian positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A + u*u' or A - u*u' -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a real workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n - complex R(n,n),u(n) - real w(n) - external clartg - complex rr,ui,t - integer i,j - - do i = 1,n -c apply stored rotations, column-wise - ui = conjg(u(i)) - do j = 1,i-1 - t = w(j)*R(j,i) + u(j)*ui - ui = w(j)*ui - conjg(u(j))*R(j,i) - R(j,i) = t - end do -c generate next rotation - call clartg(R(i,i),ui,w(i),u(i),rr) - R(i,i) = rr - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/cchdex.f +++ /dev/null @@ -1,62 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine cchdex(n,R,R1,j) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A(jj,jj), where jj = [1:j-1,j+1:n+1]. -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the deleted row/column - integer n,j,info - complex R(n,n),R1(n-1,n-1) - real c - complex Qdum,s,rr - external xerbla,clacpy,cqhqr,clartg - -c quick return if possible - if (n == 1) return - -c check arguments - info = 0 - if (n <= 0) then - info = 1 - else if (j < 1 .or. j > n) then - info = 4 - end if - if (info /= 0) then - call xerbla('CCHDEX',info) - end if - -c setup the new matrix R1 - if (j > 1) then - call clacpy('0',n-1,j-1,R(1,1),n,R1(1,1),n-1) - end if - if (j < n) then - call clacpy('0',n-1,n-j,R(1,j+1),n,R1(1,j),n-1) - call cqhqr(0,n-j,n-j,Qdum,1,R1(j,j),n-1) -c eliminate R(n,n) - call clartg(R1(n-1,n-1),R(n,n),c,s,rr) - R1(n-1,n-1) = rr - endif - end
deleted file mode 100644 --- a/libcruft/qrupdate/cchinx.f +++ /dev/null @@ -1,109 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine cchinx(n,R,R1,j,u,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A1, A1(jj,jj) = A, A(j,:) = u', A(:,j) = u, -c jj = [1:j-1,j+1:n+1]. -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the inserted row/column -c u (in) the vector (n+1) determining the rank-1 update -c info (out) on exit, if info = 1, the -c definiteness. - - integer n,j,info - complex R(n,n),R1(n+1,n+1),u(n+1) - real rho,scnrm2 - complex Qdum,w - external xerbla,ccopy,clacpy,ctrsv,scnrm2,cqrqhu - integer jj - -c quick return if possible - if (n == 0) then - if (real(u(1)) <= 0) then - info = 1 - return - else - R(1,1) = sqrt(real(u(1))) - end if - end if - -c check arguments - info = 0 - if (n < 0) then - info = 1 - else if (j < 1 .or. j > n+1) then - info = 4 - end if - if (info /= 0) then - call xerbla('CCHINX',info) - end if - -c copy shifted vector - if (j > 1) then - call ccopy(j-1,u,1,R1(1,j),1) - end if - w = u(j) - if (j < n+1) then - call ccopy(n-j+1,u(j+1),1,R1(j,j),1) - end if - -c check for singularity of R - do i = 1,n - if (R(i,i) == 0e0) then - info = 2 - return - end if - end do -c form R' \ u - call ctrsv('U','T','N',n,R,n,R1(1,j),1) - rho = scnrm2(n,R1(1,j),1) -c check positive definiteness - rho = u(j) - rho**2 - if (rho <= 0e0) then - info = 1 - return - end if - R1(n+1,n+1) = sqrt(rho) - -c setup the new matrix R1 - do i = 1,n+1 - R1(n+1,i) = 0e0 - end do - if (j > 1) then - call clacpy('0',j-1,n,R(1,1),n,R1(1,1),n+1) - end if - if (j <= n) then - call clacpy('0',n,n-j+1,R(1,j),n,R1(1,j+1),n+1) -c retriangularize - jj = min(j+1,n) - call cqrqhu(0,n+1-j,n-j,Qdum,1,R1(j,jj),n+1,R1(j,j),w) - R1(j,j) = w - do jj = j+1,n - R1(jj,j) = 0e0 - end do - end if - - end
deleted file mode 100644 --- a/libcruft/qrupdate/cqhqr.f +++ /dev/null @@ -1,69 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqhqr(m,n,k,Q,ldq,R,ldr) -c purpose: given an k-by-n upper Hessenberg matrix R and -c an m-by-k matrix Q, this subroutine updates -c R -> R1 and Q -> Q1 so that R1 is upper -c trapezoidal, R1 = G*R and Q1 = Q*G', where -c G is an unitary matrix, giving Q1*R1 = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q -c n (in) number of columns of the matrix R -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the unitary matrix Q -c on exit, the updated matrix Q1 -c ldq (in) leading dimension of Q -c R (io) on entry, the upper triangular matrix R -c on exit, the updated upper Hessenberg matrix R1 -c ldr (in) leading dimension of R -c - integer m,n,k,ldq,ldr - complex Q(ldq,*),R(ldr,*) - real c - complex s,rr - external xerbla,clartg,crot - integer info,i -c quick return if possible. - if (n <= 0 .or. k <= 1) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('CQHQR',info) - end if -c triangularize - do i = 1,min(k-1,n) - call clartg(R(i,i),R(i+1,i),c,s,rr) - R(i,i) = rr - R(i+1,i) = 0e0 - if (i < n) then - call crot(n-i,R(i,i+1),ldr,R(i+1,i+1),ldr,c,s) - end if -c apply rotation to Q - if (m > 0) then - call crot(m,Q(1,i),1,Q(1,i+1),1,c,conjg(s)) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/cqr1up.f +++ /dev/null @@ -1,53 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqr1up(m,n,k,Q,R,u,v) -c purpose: updates a QR factorization after rank-1 modification -c i.e., given a m-by-k unitary Q and m-by-n upper -c trapezoidal R, an m-vector u and n-vector v, -c this subroutine updates Q -> Q1 and R -> R1 so that -c Q1*R1 = Q*R + Q*Q'u*v', and Q1 is again unitary -c and R1 upper trapezoidal. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the unitary m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (io) on entry, the upper trapezoidal m-by-n matrix R. -c on exit, the updated matrix R1. -c u (in) the left m-vector. -c v (in) the right n-vector. -c - integer m,n,k - complex Q(m,k),R(k,n),u(m),v(n) - complex w - external cqrqhv,cqhqr - integer i -c quick return if possible - if (m <= 0 .or. n <= 0) return -c eliminate tail of Q'*u - call cqrqhv(m,n,k,Q,m,R,m,u,w) -c update R - do i = 1,n - R(1,i) = R(1,i) + w*conjg(v(i)) - end do -c retriangularize R - call cqhqr(m,n,k,Q,m,R,k) - end
deleted file mode 100644 --- a/libcruft/qrupdate/cqrdec.f +++ /dev/null @@ -1,66 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqrdec(m,n,k,Q,R,R1,j) -c purpose: updates a QR factorization after deleting -c a column. -c i.e., given an m-by-k unitary matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n-1) matrix R1 so that Q1 remains -c unitary, R1 is upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1) A(:,j+1:n)], where A = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the unitary m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (in) the original upper trapezoidal matrix R. -c R1 (out) the updated matrix R1. -c j (in) the position of the deleted column in R. -c 1 <= j <= n. -c - integer m,n,k,j - complex Q(m,k),R(k,n),R1(k,n-1) - external xerbla,ccopy,cqhqr - integer info -c quick return if possible - if (m <= 0 .or. k <= 0 .or. n == 1) return -c check arguments - info = 0 - if (n < 1) then - info = 2 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('CQRDEC',info) - end if -c copy leading portion - call ccopy(k*(j-1),R,1,R1,1) - if (j < n) then -c copy trailing portion of R - call ccopy(k*(n-j),R(1,j+1),1,R1(1,j),1) -c if necessary, retriangularize R1(j:k,j:n-1) and update Q(:,j:k) - if (j < k) then - call cqhqr(m,n-j,k-j+1,Q(1,j),m,R1(j,j),k) - end if - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/cqrder.f +++ /dev/null @@ -1,93 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqrder(m,n,Q,Q1,R,R1,j) -c purpose: updates a QR factorization after deleting a row. -c i.e., given an m-by-m unitary matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m, this subroutine forms the (m-1)-by-(m-1) matrix -c Q1 and an (m-1)-by-n matrix R1 so that Q1 is again -c unitary, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); A(j+1:m,:)], where A = Q*R. -c (complex version) -c -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the unitary matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c - integer m,n,j - complex Q(m,m),Q1(m-1,m-1),R(m,n),R1(m-1,n) - real c - complex s,rr,w - external xerbla,clacpy,clartg,crot,csscal,caxpy - integer i -c quick return if possible - if (m == 1) return -c check arguments - info = 0 - if (m < 1) then - info = 1 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('CQRDER',info) - end if -c setup the new matrix Q1 -c permute the columns of Q and rows of R so that the deleted row ends -c up being the topmost row. - if (j > 1) then - call clacpy('0',j-1,m-1,Q(1,2),m,Q1(1,1),m-1) - end if - if (j < m) then - call clacpy('0',m-j,m-1,Q(j+1,2),m,Q1(j,1),m-1) - end if -c setup the new matrix R1 - call clacpy('0',m-1,n,R(2,1),m,R1(1,1),m-1) -c eliminate Q(j,2:m) - w = Q(j,m) - do i = m-1,2,-1 - call clartg(Q(j,i),w,c,s,rr) - w = rr -c apply rotation to rows of R1 - if (i <= n) then - call crot(n-i+1,R1(i-1,i),m-1,R1(i,i),m-1,c,conjg(s)) - end if -c apply rotation to columns of Q1 - call crot(m-1,Q1(1,i-1),1,Q1(1,i),1,c,s) - end do -c the last iteration is special, as we don't have the first row of -c R and first column of Q - call clartg(Q(j,1),w,c,s,rr) - w = rr - call csscal(n,c,R1(1,1),m-1) - call caxpy(n,-s,R(1,1),m,R1(1,1),m-1) -c apply rotation to columns of Q1 - call csscal(m-1,c,Q1(1,1),1) - if (j > 1) then - call caxpy(j-1,-conjg(s),Q(1,1),1,Q1(1,1),1) - end if - if (j < m) then - call caxpy(m-j,-conjg(s),Q(j+1,1),1,Q1(j,1),1) - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/cqrinc.f +++ /dev/null @@ -1,74 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqrinc(m,n,k,Q,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c column. -c i.e., given an m-by-k unitary matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n+1) matrix R1 so that Q1 is again unitary, -c R1 upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1); Q*Q'*x; A(:,j:n-1)], where A = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the unitary matrix Q. -c on exit, the updated matrix Q1 -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new column in R1 -c x (in) the column being inserted -c - integer m,n,k,j - complex Q(m,k),R(k,n),R1(k,n+1),x(m) - complex w - external xerbla,ccopy,cqrqhv,cgemv - integer info,i,jj -c quick return if possible - if (m <= 0) return -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > n+1) then - info = 6 - end if - if (info /= 0) then - call xerbla('CQRINC',info) - end if -c copy leading portion of R - call ccopy(k*(j-1),R,1,R1,1) - if (j <= n) then - call ccopy(k*(n+1-j),R(1,j),1,R1(1,j+1),1) - end if - call cgemv('C',m,min(k,j-1),cmplx(1e0),Q,m,x,1, - + cmplx(0e0),R1(1,j),1) - if (j < k) then -c eliminate tail, updating Q(:,j:k) and R1(j:k,j+1:n+1) - jj = min(j,n)+1 - call cqrqhv(m,n+1-j,k-j+1,Q(1,j),m,R1(j,jj),m,x,w) -c assemble inserted column - R1(j,j) = w - do i = j+1,k - R1(i,j) = 0e0 - end do - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/cqrinr.f +++ /dev/null @@ -1,73 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqrinr(m,n,Q,Q1,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c row. -c i.e., given an m-by-m unitary matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m+1, this subroutine forms the (m+1)-by-(m+1) matrix -c Q1 and an (m+1)-by-n matrix R1 so that Q1 is again -c unitary, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); x; A(j:m,:)], where A = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the orthogonal matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c x (in) the row being added -c - integer m,n,j - complex Q(m,m),Q1(m+1,m+1),R(m,n),R1(m+1,n),x(n) - external xerbla,clacpy,ccopy,cqhqr - integer i -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > m+1) then - info = 7 - end if - if (info /= 0) then - call xerbla('CQRINR',info) - end if -c setup the new matrix Q1 -c permute the columns of Q1 and rows of R1 so that c the new row ends -c up being the topmost row. - if (j > 1) then - call clacpy('0',j-1,m,Q(1,1),m,Q1(1,2),m+1) - end if - if (j <= m) then - call clacpy('0',m-j+1,m,Q(j,1),m,Q1(j+1,2),m+1) - end if -c zero the rest of Q1 - do i = 1,m+1 - Q1(i,1) = 0e0 - Q1(j,i) = 0e0 - end do - Q1(j,1) = 1e0 -c setup the new matrix R1 - call ccopy(n,x,1,R1(1,1),m+1) - call clacpy('0',m,n,R(1,1),m,R1(2,1),m+1) -c rotate to form proper QR - call cqhqr(m+1,n,m+1,Q1,m+1,R1,m+1) - end
deleted file mode 100644 --- a/libcruft/qrupdate/cqrqhu.f +++ /dev/null @@ -1,78 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqrqhu(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and a k-vector u, -c this subroutine updates the matrices Q -> Q1 and -c R -> R1 so that Q1 = Q*G', R1 = G*R, u1(2:k) = 0 -c with G unitary, R1 upper Hessenberg, and u1 = G*u. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the unitary matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the k-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is unitary, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - complex Q(ldq,*),R(ldr,*),u(*),rr - real c - complex s,w - external xerbla,clartg,crot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('CQRQHU',info) - end if - rr = u(k) - do i = k-1,1,-1 - w = rr - if (w /= cmplx(0e0,0e0)) then - call clartg(u(i),w,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call crot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q if necessary - if (m > 0) then - call crot(m,Q(1,i),1,Q(1,i+1),1,c,conjg(s)) - end if - else -c no rotation necessary - rr = u(i) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/cqrqhv.f +++ /dev/null @@ -1,75 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqrqhv(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and an m-vector u, this subroutine -c updates the matrices Q -> Q1 and R -> R1 so that -c Q1 = Q*G', R1 = G*R, w1(2:m) = 0 with G unitary, -c R1 upper Hessenberg, and w1 = Q1'*u. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. k <= m. -c Q (io) on entry, the unitary matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the m-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is unitary, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - complex Q(ldq,*),R(ldr,*),u(*),rr - real c - complex s,w,w1,cdotc - external xerbla,cdotc,clartg,crot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (k > m) then - info = 3 - else if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('CQRQHV',info) - end if -c form each element of w = Q'*u when necessary. - rr = cdotc(m,Q(1,k),1,u,1) - do i = k-1,1,-1 - w1 = rr - w = cdotc(m,Q(1,i),1,u,1) - call clartg(w,w1,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call crot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q - call crot(m,Q(1,i),1,Q(1,i+1),1,c,conjg(s)) - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/cqrshc.f +++ /dev/null @@ -1,97 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine cqrshc(m,n,k,Q,R,i,j) -c purpose: updates a QR factorization after circular shift of -c columns. -c i.e., given an m-by-k unitary matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c R -> R1 so that Q1 is again unitary, R1 upper trapezoidal, -c and -c Q1*R1 = A(:,p), where A = Q*R and p is the permutation -c [1:i-1,shift(i:j,-1),j+1:n] if i < j or -c [1:j-1,shift(j:i,+1),i+1:n] if j > i. -c if m == 0, the matrix Q is ignored. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q, or 0 if Q is not needed. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the (unitary) matrix Q. -c on exit, the updated matrix Q1 -c R (io) on entry, the upper trapezoidal m-by-n matrix R. -c on exit, the updated matrix R1. -c i (in) the first index determining the range (see above) -c j (in) the second index determining the range (see above) -c - integer m,n,k,i,j - complex Q(m,k),R(k,n) - external xerbla,cswap,cqhqr,cqrqhu - complex w - integer l,jj,kk,info - -c quick return if possible - if (k <= 0 .or. n <= 1) return - info = 0 - if (m /= 0 .and. k > m) then - info = 3 - else if (i < 1 .or. i > n) then - info = 6 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('CQRSHC',info) - end if - - if (i < j) then -c shift columns - do l = i,j-1 - call cswap(min(k,l+1),R(1,l),1,R(1,l+1),1) - end do -c retriangularize - if (i < k) then - kk = min(k,j) - if (m > 0) then - call cqhqr(m,n+1-i,kk+1-i,Q(1,i),m,R(i,i),k) - else - call cqhqr(0,n+1-i,kk+1-i,Q,1,R(i,i),k) - endif - end if - else if (j < i) then -c shift columns - do l = i,j+1,-1 - call cswap(min(k,i),R(1,l),1,R(1,l-1),1) - end do -c retriangularize - if (j < k) then - jj = min(j+1,n) - kk = min(k,i) - if (m > 0) then - call cqrqhu(m,n-j,kk+1-j,Q(1,j),m,R(j,jj),k,R(j,j),w) - else - call cqrqhu(0,n-j,kk+1-j,Q,1,R(j,jj),k,R(j,j),w) - end if - R(j,j) = w - do jj = j+1,kk - R(jj,j) = 0 - end do - end if - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/dch1dn.f +++ /dev/null @@ -1,81 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dch1dn(n,R,u,w,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine downdates R -> R1 so that -c R1'*R1 = A - u*u' -c (real version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n,info - double precision R(n,n),u(n) - double precision w(n) - external dtrsv,dlartg,dnrm2 - double precision rho,dnrm2 - double precision rr,ui,t - integer i,j - -c quick return if possible - if (n <= 0) return -c check for singularity of R - do i = 1,n - if (R(i,i) == 0d0) then - info = 2 - return - end if - end do -c form R' \ u - call dtrsv('U','T','N',n,R,n,u,1) - rho = dnrm2(n,u,1) -c check positive definiteness - rho = 1 - rho**2 - if (rho <= 0d0) then - info = 1 - return - end if - rho = sqrt(rho) -c eliminate R' \ u - do i = n,1,-1 - ui = u(i) -c generate next rotation - call dlartg(rho,ui,w(i),u(i),rr) - rho = rr - end do -c apply rotations - do i = n,1,-1 - ui = 0d0 - do j = i,1,-1 - t = w(j)*ui + u(j)*R(j,i) - R(j,i) = w(j)*R(j,i) - u(j)*ui - ui = t - end do - end do - - info = 0 - end
deleted file mode 100644 --- a/libcruft/qrupdate/dch1up.f +++ /dev/null @@ -1,57 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine dch1up(n,R,u,w) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A + u*u' -c (real version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n - double precision R(n,n),u(n) - double precision w(n) - external dlartg - double precision rr,ui,t - integer i,j - - do i = 1,n -c apply stored rotations, column-wise - ui = u(i) - do j = 1,i-1 - t = w(j)*R(j,i) + u(j)*ui - ui = w(j)*ui - u(j)*R(j,i) - R(j,i) = t - end do -c generate next rotation - call dlartg(R(i,i),ui,w(i),u(i),rr) - R(i,i) = rr - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/dchdex.f +++ /dev/null @@ -1,61 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine dchdex(n,R,R1,j) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A(jj,jj), where jj = [1:j-1,j+1:n+1]. -c (real version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the deleted row/column - integer n,j,info - double precision R(n,n),R1(n-1,n-1) - double precision Qdum,c,s,rr - external xerbla,dlacpy,dqhqr,dlartg - -c quick return if possible - if (n == 1) return - -c check arguments - info = 0 - if (n <= 0) then - info = 1 - else if (j < 1 .or. j > n) then - info = 4 - end if - if (info /= 0) then - call xerbla('DCHDEX',info) - end if - -c setup the new matrix R1 - if (j > 1) then - call dlacpy('0',n-1,j-1,R(1,1),n,R1(1,1),n-1) - end if - if (j < n) then - call dlacpy('0',n-1,n-j,R(1,j+1),n,R1(1,j),n-1) - call dqhqr(0,n-j,n-j,Qdum,1,R1(j,j),n-1) -c eliminate R(n,n) - call dlartg(R1(n-1,n-1),R(n,n),c,s,rr) - R1(n-1,n-1) = rr - endif - end
deleted file mode 100644 --- a/libcruft/qrupdate/dchinx.f +++ /dev/null @@ -1,108 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine dchinx(n,R,R1,j,u,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A1, A1(jj,jj) = A, A(j,:) = u', A(:,j) = u, -c jj = [1:j-1,j+1:n+1]. -c (real version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the inserted row/column -c u (in) the vector (n+1) determining the rank-1 update -c info (out) on exit, if info = 1, the -c definiteness. - - integer n,j,info - double precision R(n,n),R1(n+1,n+1),u(n+1) - double precision rho,Qdum,w,dnrm2 - external xerbla,dcopy,dlacpy,dtrsv,dnrm2,dqrqhu - integer jj - -c quick return if possible - if (n == 0) then - if (u(1) <= 0) then - info = 1 - return - else - R(1,1) = sqrt(u(1)) - end if - end if - -c check arguments - info = 0 - if (n < 0) then - info = 1 - else if (j < 1 .or. j > n+1) then - info = 4 - end if - if (info /= 0) then - call xerbla('DCHINX',info) - end if - -c copy shifted vector - if (j > 1) then - call dcopy(j-1,u,1,R1(1,j),1) - end if - w = u(j) - if (j < n+1) then - call dcopy(n-j+1,u(j+1),1,R1(j,j),1) - end if - -c check for singularity of R - do i = 1,n - if (R(i,i) == 0d0) then - info = 2 - return - end if - end do -c form R' \ u - call dtrsv('U','T','N',n,R,n,R1(1,j),1) - rho = dnrm2(n,R1(1,j),1) -c check positive definiteness - rho = u(j) - rho**2 - if (rho <= 0d0) then - info = 1 - return - end if - R1(n+1,n+1) = sqrt(rho) - -c setup the new matrix R1 - do i = 1,n+1 - R1(n+1,i) = 0d0 - end do - if (j > 1) then - call dlacpy('0',n,j-1,R(1,1),n,R1(1,1),n+1) - end if - if (j <= n) then - call dlacpy('0',n,n-j+1,R(1,j),n,R1(1,j+1),n+1) -c retriangularize - jj = min(j+1,n) - call dqrqhu(0,n+1-j,n-j,Qdum,1,R1(j,jj),n+1,R1(j,j),w) - R1(j,j) = w - do jj = j+1,n - R1(jj,j) = 0d0 - end do - end if - - end
deleted file mode 100644 --- a/libcruft/qrupdate/dqhqr.f +++ /dev/null @@ -1,69 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqhqr(m,n,k,Q,ldq,R,ldr) -c purpose: given an k-by-n upper Hessenberg matrix R and -c an m-by-k matrix Q, this subroutine updates -c R -> R1 and Q -> Q1 so that R1 is upper -c trapezoidal, R1 = G*R and Q1 = Q*G', where -c G is an orthogonal matrix, giving Q1*R1 = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q -c n (in) number of columns of the matrix R -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the orthogonal matrix Q -c on exit, the updated matrix Q1 -c ldq (in) leading dimension of Q -c R (io) on entry, the upper triangular matrix R -c on exit, the updated upper Hessenberg matrix R1 -c ldr (in) leading dimension of R -c - integer m,n,k,ldq,ldr - double precision Q(ldq,*),R(ldr,*) - double precision c - double precision s,rr - external xerbla,dlartg,drot - integer info,i -c quick return if possible. - if (n <= 0 .or. k <= 1) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('DQHQR',info) - end if -c triangularize - do i = 1,min(k-1,n) - call dlartg(R(i,i),R(i+1,i),c,s,rr) - R(i,i) = rr - R(i+1,i) = 0d0 - if (i < n) then - call drot(n-i,R(i,i+1),ldr,R(i+1,i+1),ldr,c,s) - end if -c apply rotation to Q - if (m > 0) then - call drot(m,Q(1,i),1,Q(1,i+1),1,c,s) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/dqr1up.f +++ /dev/null @@ -1,52 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqr1up(m,n,k,Q,R,u,v) -c purpose: updates a QR factorization after rank-1 modification -c i.e., given a m-by-k orthogonal Q and m-by-n upper -c trapezoidal R, an m-vector u and n-vector v, -c this subroutine updates Q -> Q1 and R -> R1 so that -c Q1*R1 = Q*R + Q*Q'u*v', and Q1 is again orthonormal -c and R1 upper trapezoidal. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the orthogonal m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (io) on entry, the upper trapezoidal m-by-n matrix R.. -c on exit, the updated matrix R1. -c u (in) the left m-vector. -c v (in) the right n-vector. -c - integer m,n,k - double precision Q(m,k),R(k,n),u(m),v(n) - double precision w - external dqrqhv,dqhqr,daxpy -c quick return if possible - if (m <= 0 .or. n <= 0) return -c eliminate tail of Q'*u - call dqrqhv(m,n,k,Q,m,R,m,u,w) -c update R - - call daxpy(n,w,v,1,R(1,1),m) - -c retriangularize R - call dqhqr(m,n,k,Q,m,R,k) - end
deleted file mode 100644 --- a/libcruft/qrupdate/dqrdec.f +++ /dev/null @@ -1,66 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqrdec(m,n,k,Q,R,R1,j) -c purpose: updates a QR factorization after deleting -c a column. -c i.e., given an m-by-k orthogonal matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n-1) matrix R1 so that Q1 remains -c orthogonal, R1 is upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1) A(:,j+1:n)], where A = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the orthogonal m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (in) the original upper trapezoidal matrix R. -c R1 (out) the updated matrix R1. -c j (in) the position of the deleted column in R. -c 1 <= j <= n. -c - integer m,n,k,j - double precision Q(m,k),R(k,n),R1(k,n-1) - external xerbla,dcopy,dqhqr - integer info -c quick return if possible - if (m <= 0 .or. k <= 0 .or. n == 1) return -c check arguments - info = 0 - if (n < 1) then - info = 2 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('DQRDEC',info) - end if -c copy leading portion - call dcopy(k*(j-1),R,1,R1,1) - if (j < n) then -c copy trailing portion of R - call dcopy(k*(n-j),R(1,j+1),1,R1(1,j),1) -c if necessary, retriangularize R1(j:k,j:n-1) and update Q(:,j:k) - if (j < k) then - call dqhqr(m,n-j,k-j+1,Q(1,j),m,R1(j,j),k) - end if - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/dqrder.f +++ /dev/null @@ -1,93 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqrder(m,n,Q,Q1,R,R1,j) -c purpose: updates a QR factorization after deleting a row. -c i.e., given an m-by-m orthogonal matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m, this subroutine forms the (m-1)-by-(m-1) matrix -c Q1 and an (m-1)-by-n matrix R1 so that Q1 is again -c orthogonal, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); A(j+1:m,:)], where A = Q*R. -c (real version) -c -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the orthogonal matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c - integer m,n,j - double precision Q(m,m),Q1(m-1,m-1),R(m,n),R1(m-1,n) - double precision c - double precision s,rr,w - external xerbla,dlacpy,dlartg,drot,dscal,daxpy - integer i -c quick return if possible - if (m == 1) return -c check arguments - info = 0 - if (m < 1) then - info = 1 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('DQRDER',info) - end if -c setup the new matrix Q1 -c permute the columns of Q and rows of R so that the deleted row ends -c up being the topmost row. - if (j > 1) then - call dlacpy('0',j-1,m-1,Q(1,2),m,Q1(1,1),m-1) - end if - if (j < m) then - call dlacpy('0',m-j,m-1,Q(j+1,2),m,Q1(j,1),m-1) - end if -c setup the new matrix R1 - call dlacpy('0',m-1,n,R(2,1),m,R1(1,1),m-1) -c eliminate Q(j,2:m) - w = Q(j,m) - do i = m-1,2,-1 - call dlartg(Q(j,i),w,c,s,rr) - w = rr -c apply rotation to rows of R1 - if (i <= n) then - call drot(n-i+1,R1(i-1,i),m-1,R1(i,i),m-1,c,s) - end if -c apply rotation to columns of Q1 - call drot(m-1,Q1(1,i-1),1,Q1(1,i),1,c,s) - end do -c the last iteration is special, as we don't have the first row of -c R and first column of Q - call dlartg(Q(j,1),w,c,s,rr) - w = rr - call dscal(n,c,R1(1,1),m-1) - call daxpy(n,-s,R(1,1),m,R1(1,1),m-1) -c apply rotation to columns of Q1 - call dscal(m-1,c,Q1(1,1),1) - if (j > 1) then - call daxpy(j-1,-s,Q(1,1),1,Q1(1,1),1) - end if - if (j < m) then - call daxpy(m-j,-s,Q(j+1,1),1,Q1(j,1),1) - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/dqrinc.f +++ /dev/null @@ -1,73 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqrinc(m,n,k,Q,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c column. -c i.e., given an m-by-k orthogonal matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n+1) matrix R1 so that Q1 is again -c orthogonal, R1 upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1); Q*Q'*x; A(:,j:n-1)], where A = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the orthogonal matrix Q. -c on exit, the updated matrix Q1 -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new column in R1 -c x (in) the column being inserted -c - integer m,n,k,j - double precision Q(m,k),R(k,n),R1(k,n+1),x(m) - double precision w - external xerbla,dcopy,dqrqhv,dgemv - integer info,i,jj -c quick return if possible - if (m <= 0) return -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > n+1) then - info = 6 - end if - if (info /= 0) then - call xerbla('DQRINC',info) - end if -c copy leading portion of R - call dcopy(k*(j-1),R,1,R1,1) - if (j <= n) then - call dcopy(k*(n+1-j),R(1,j),1,R1(1,j+1),1) - end if - call dgemv('T',m,min(k,j-1),1d0,Q,m,x,1,0d0,R1(1,j),1) - if (j < k) then -c eliminate tail, updating Q(:,j:k) and R1(j:k,j+1:n+1) - jj = min(j,n)+1 - call dqrqhv(m,n+1-j,k-j+1,Q(1,j),m,R1(j,jj),m,x,w) -c assemble inserted column - R1(j,j) = w - do i = j+1,k - R1(i,j) = 0d0 - end do - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/dqrinr.f +++ /dev/null @@ -1,73 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqrinr(m,n,Q,Q1,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c row. -c i.e., given an m-by-m orthogonal matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m+1, this subroutine forms the (m+1)-by-(m+1) matrix -c Q1 and an (m+1)-by-n matrix R1 so that Q1 is again -c orthogonal, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); x; A(j:m,:)], where A = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the orthogonal matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c x (in) the row being added -c - integer m,n,j - double precision Q(m,m),Q1(m+1,m+1),R(m,n),R1(m+1,n),x(n) - external xerbla,dlacpy,dcopy,dqhqr - integer i -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > m+1) then - info = 7 - end if - if (info /= 0) then - call xerbla('DQRINR',info) - end if -c setup the new matrix Q1 -c permute the columns of Q1 and rows of R1 so that c the new row ends -c up being the topmost row. - if (j > 1) then - call dlacpy('0',j-1,m,Q(1,1),m,Q1(1,2),m+1) - end if - if (j <= m) then - call dlacpy('0',m-j+1,m,Q(j,1),m,Q1(j+1,2),m+1) - end if -c zero the rest of Q1 - do i = 1,m+1 - Q1(i,1) = 0d0 - Q1(j,i) = 0d0 - end do - Q1(j,1) = 1d0 -c setup the new matrix R1 - call dcopy(n,x,1,R1(1,1),m+1) - call dlacpy('0',m,n,R(1,1),m,R1(2,1),m+1) -c rotate to form proper QR - call dqhqr(m+1,n,m+1,Q1,m+1,R1,m+1) - end
deleted file mode 100644 --- a/libcruft/qrupdate/dqrqhu.f +++ /dev/null @@ -1,78 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqrqhu(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and a k-vector u, -c this subroutine updates the matrices Q -> Q1 and -c R -> R1 so that Q1 = Q*G', R1 = G*R, u1(2:k) = 0 -c with G orthogonal, R1 upper Hessenberg, and u1 = G*u. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the orthogonal matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the k-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is orthogonal, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - double precision Q(ldq,*),R(ldr,*),u(*),rr - double precision c - double precision s,w - external xerbla,dlartg,drot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('DQRQHU',info) - end if - rr = u(k) - do i = k-1,1,-1 - w = rr - if (w /= 0d0) then - call dlartg(u(i),w,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call drot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q if necessary - if (m > 0) then - call drot(m,Q(1,i),1,Q(1,i+1),1,c,s) - end if - else -c no rotation necessary - rr = u(i) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/dqrqhv.f +++ /dev/null @@ -1,75 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqrqhv(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and an m-vector u, this subroutine -c updates the matrices Q -> Q1 and R -> R1 so that -c Q1 = Q*G', R1 = G*R, w1(2:m) = 0 with G orthogonal, -c R1 upper Hessenberg, and w1 = Q1'*u. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. k <= m. -c Q (io) on entry, the orthogonal matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the m-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is orthogonal, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - double precision Q(ldq,*),R(ldr,*),u(*),rr - double precision c - double precision s,w,w1,ddot - external xerbla,ddot,dlartg,drot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (k > m) then - info = 3 - else if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('DQRQHV',info) - end if -c form each element of w = Q'*u when necessary. - rr = ddot(m,Q(1,k),1,u,1) - do i = k-1,1,-1 - w1 = rr - w = ddot(m,Q(1,i),1,u,1) - call dlartg(w,w1,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call drot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q - call drot(m,Q(1,i),1,Q(1,i+1),1,c,s) - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/dqrshc.f +++ /dev/null @@ -1,97 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine dqrshc(m,n,k,Q,R,i,j) -c purpose: updates a QR factorization after circular shift of -c columns. -c i.e., given an m-by-k orthogonal matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c R -> R1 so that Q1 is again orthogonal, R1 upper -c trapezoidal, and -c Q1*R1 = A(:,p), where A = Q*R and p is the permutation -c [1:i-1,shift(i:j,-1),j+1:n] if i < j or -c [1:j-1,shift(j:i,+1),i+1:n] if j > i. -c if m == 0, the matrix Q is ignored. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q, or 0 if Q is not needed. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the (orthogonal) matrix Q. -c on exit, the updated matrix Q1 -c R (io) on entry, the upper trapezoidal m-by-n matrix R. -c on exit, the updated matrix R1. -c i (in) the first index determining the range (see above) -c j (in) the second index determining the range (see above) -c - integer m,n,k,i,j - double precision Q(m,k),R(k,n) - external xerbla,dswap,dqhqr,dqrqhu - double precision w - integer l,jj,kk,info - -c quick return if possible - if (k <= 0 .or. n <= 1) return - info = 0 - if (m /= 0 .and. k > m) then - info = 3 - else if (i < 1 .or. i > n) then - info = 6 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('DQRSHC',info) - end if - - if (i < j) then -c shift columns - do l = i,j-1 - call dswap(min(k,l+1),R(1,l),1,R(1,l+1),1) - end do -c retriangularize - if (i < k) then - kk = min(k,j) - if (m > 0) then - call dqhqr(m,n+1-i,kk+1-i,Q(1,i),m,R(i,i),k) - else - call dqhqr(0,n+1-i,kk+1-i,Q,1,R(i,i),k) - endif - end if - else if (j < i) then -c shift columns - do l = i,j+1,-1 - call dswap(min(k,i),R(1,l),1,R(1,l-1),1) - end do -c retriangularize - if (j < k) then - jj = min(j+1,n) - kk = min(k,i) - if (m > 0) then - call dqrqhu(m,n-j,kk+1-j,Q(1,j),m,R(j,jj),k,R(j,j),w) - else - call dqrqhu(0,n-j,kk+1-j,Q,1,R(j,jj),k,R(j,j),w) - end if - R(j,j) = w - do jj = j+1,kk - R(jj,j) = 0 - end do - end if - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/sch1dn.f +++ /dev/null @@ -1,81 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sch1dn(n,R,u,w,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine downdates R -> R1 so that -c R1'*R1 = A - u*u' -c (real version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n,info - real R(n,n),u(n) - real w(n) - external strsv,slartg,snrm2 - real rho,snrm2 - real rr,ui,t - integer i,j - -c quick return if possible - if (n <= 0) return -c check for singularity of R - do i = 1,n - if (R(i,i) == 0e0) then - info = 2 - return - end if - end do -c form R' \ u - call strsv('U','T','N',n,R,n,u,1) - rho = snrm2(n,u,1) -c check positive definiteness - rho = 1 - rho**2 - if (rho <= 0e0) then - info = 1 - return - end if - rho = sqrt(rho) -c eliminate R' \ u - do i = n,1,-1 - ui = u(i) -c generate next rotation - call slartg(rho,ui,w(i),u(i),rr) - rho = rr - end do -c apply rotations - do i = n,1,-1 - ui = 0e0 - do j = i,1,-1 - t = w(j)*ui + u(j)*R(j,i) - R(j,i) = w(j)*R(j,i) - u(j)*ui - ui = t - end do - end do - - info = 0 - end
deleted file mode 100644 --- a/libcruft/qrupdate/sch1up.f +++ /dev/null @@ -1,57 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine sch1up(n,R,u,w) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A + u*u' -c (real version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n - real R(n,n),u(n) - real w(n) - external slartg - real rr,ui,t - integer i,j - - do i = 1,n -c apply stored rotations, column-wise - ui = u(i) - do j = 1,i-1 - t = w(j)*R(j,i) + u(j)*ui - ui = w(j)*ui - u(j)*R(j,i) - R(j,i) = t - end do -c generate next rotation - call slartg(R(i,i),ui,w(i),u(i),rr) - R(i,i) = rr - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/schdex.f +++ /dev/null @@ -1,61 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine schdex(n,R,R1,j) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A(jj,jj), where jj = [1:j-1,j+1:n+1]. -c (real version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the deleted row/column - integer n,j,info - real R(n,n),R1(n-1,n-1) - real Qdum,c,s,rr - external xerbla,slacpy,sqhqr,slartg - -c quick return if possible - if (n == 1) return - -c check arguments - info = 0 - if (n <= 0) then - info = 1 - else if (j < 1 .or. j > n) then - info = 4 - end if - if (info /= 0) then - call xerbla('SQRDEX',info) - end if - -c setup the new matrix R1 - if (j > 1) then - call slacpy('0',n-1,j-1,R(1,1),n,R1(1,1),n-1) - end if - if (j < n) then - call slacpy('0',n-1,n-j,R(1,j+1),n,R1(1,j),n-1) - call sqhqr(0,n-j,n-j,Qdum,1,R1(j,j),n-1) -c eliminate R(n,n) - call slartg(R1(n-1,n-1),R(n,n),c,s,rr) - R1(n-1,n-1) = rr - endif - end
deleted file mode 100644 --- a/libcruft/qrupdate/schinx.f +++ /dev/null @@ -1,108 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine schinx(n,R,R1,j,u,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A1, A1(jj,jj) = A, A(j,:) = u', A(:,j) = u, -c jj = [1:j-1,j+1:n+1]. -c (real version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the inserted row/column -c u (in) the vector (n+1) determining the rank-1 update -c info (out) on exit, if info = 1, the -c definiteness. - - integer n,j,info - real R(n,n),R1(n+1,n+1),u(n+1) - real rho,Qdum,w,snrm2 - external xerbla,scopy,slacpy,strsv,snrm2,sqrqhu - integer jj - -c quick return if possible - if (n == 0) then - if (u(1) <= 0) then - info = 1 - return - else - R(1,1) = sqrt(u(1)) - end if - end if - -c check arguments - info = 0 - if (n < 0) then - info = 1 - else if (j < 1 .or. j > n+1) then - info = 4 - end if - if (info /= 0) then - call xerbla('SCHINX',info) - end if - -c copy shifted vector - if (j > 1) then - call scopy(j-1,u,1,R1(1,j),1) - end if - w = u(j) - if (j < n+1) then - call scopy(n-j+1,u(j+1),1,R1(j,j),1) - end if - -c check for singularity of R - do i = 1,n - if (R(i,i) == 0e0) then - info = 2 - return - end if - end do -c form R' \ u - call strsv('U','T','N',n,R,n,R1(1,j),1) - rho = snrm2(n,R1(1,j),1) -c check positive definiteness - rho = u(j) - rho**2 - if (rho <= 0e0) then - info = 1 - return - end if - R1(n+1,n+1) = sqrt(rho) - -c setup the new matrix R1 - do i = 1,n+1 - R1(n+1,i) = 0e0 - end do - if (j > 1) then - call slacpy('0',n,j-1,R(1,1),n,R1(1,1),n+1) - end if - if (j <= n) then - call slacpy('0',n,n-j+1,R(1,j),n,R1(1,j+1),n+1) -c retriangularize - jj = min(j+1,n) - call sqrqhu(0,n+1-j,n-j,Qdum,1,R1(j,jj),n+1,R1(j,j),w) - R1(j,j) = w - do jj = j+1,n - R1(jj,j) = 0e0 - end do - end if - - end
deleted file mode 100644 --- a/libcruft/qrupdate/sqhqr.f +++ /dev/null @@ -1,69 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqhqr(m,n,k,Q,ldq,R,ldr) -c purpose: given an k-by-n upper Hessenberg matrix R and -c an m-by-k matrix Q, this subroutine updates -c R -> R1 and Q -> Q1 so that R1 is upper -c trapezoidal, R1 = G*R and Q1 = Q*G', where -c G is an orthogonal matrix, giving Q1*R1 = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q -c n (in) number of columns of the matrix R -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the orthogonal matrix Q -c on exit, the updated matrix Q1 -c ldq (in) leading dimension of Q -c R (io) on entry, the upper triangular matrix R -c on exit, the updated upper Hessenberg matrix R1 -c ldr (in) leading dimension of R -c - integer m,n,k,ldq,ldr - real Q(ldq,*),R(ldr,*) - real c - real s,rr - external xerbla,slartg,srot - integer info,i -c quick return if possible. - if (n <= 0 .or. k <= 1) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('SQHQR',info) - end if -c triangularize - do i = 1,min(k-1,n) - call slartg(R(i,i),R(i+1,i),c,s,rr) - R(i,i) = rr - R(i+1,i) = 0e0 - if (i < n) then - call srot(n-i,R(i,i+1),ldr,R(i+1,i+1),ldr,c,s) - end if -c apply rotation to Q - if (m > 0) then - call srot(m,Q(1,i),1,Q(1,i+1),1,c,s) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/sqr1up.f +++ /dev/null @@ -1,52 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqr1up(m,n,k,Q,R,u,v) -c purpose: updates a QR factorization after rank-1 modification -c i.e., given a m-by-k orthogonal Q and m-by-n upper -c trapezoidal R, an m-vector u and n-vector v, -c this subroutine updates Q -> Q1 and R -> R1 so that -c Q1*R1 = Q*R + Q*Q'u*v', and Q1 is again orthonormal -c and R1 upper trapezoidal. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the orthogonal m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (io) on entry, the upper trapezoidal m-by-n matrix R.. -c on exit, the updated matrix R1. -c u (in) the left m-vector. -c v (in) the right n-vector. -c - integer m,n,k - real Q(m,k),R(k,n),u(m),v(n) - real w - external sqrqhv,sqhqr,saxpy -c quick return if possible - if (m <= 0 .or. n <= 0) return -c eliminate tail of Q'*u - call sqrqhv(m,n,k,Q,m,R,m,u,w) -c update R - - call saxpy(n,w,v,1,R(1,1),m) - -c retriangularize R - call sqhqr(m,n,k,Q,m,R,k) - end
deleted file mode 100644 --- a/libcruft/qrupdate/sqrdec.f +++ /dev/null @@ -1,66 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqrdec(m,n,k,Q,R,R1,j) -c purpose: updates a QR factorization after deleting -c a column. -c i.e., given an m-by-k orthogonal matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n-1) matrix R1 so that Q1 remains -c orthogonal, R1 is upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1) A(:,j+1:n)], where A = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the orthogonal m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (in) the original upper trapezoidal matrix R. -c R1 (out) the updated matrix R1. -c j (in) the position of the deleted column in R. -c 1 <= j <= n. -c - integer m,n,k,j - real Q(m,k),R(k,n),R1(k,n-1) - external xerbla,scopy,sqhqr - integer info -c quick return if possible - if (m <= 0 .or. k <= 0 .or. n == 1) return -c check arguments - info = 0 - if (n < 1) then - info = 2 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('SQRDEC',info) - end if -c copy leading portion - call scopy(k*(j-1),R,1,R1,1) - if (j < n) then -c copy trailing portion of R - call scopy(k*(n-j),R(1,j+1),1,R1(1,j),1) -c if necessary, retriangularize R1(j:k,j:n-1) and update Q(:,j:k) - if (j < k) then - call sqhqr(m,n-j,k-j+1,Q(1,j),m,R1(j,j),k) - end if - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/sqrder.f +++ /dev/null @@ -1,93 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqrder(m,n,Q,Q1,R,R1,j) -c purpose: updates a QR factorization after deleting a row. -c i.e., given an m-by-m orthogonal matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m, this subroutine forms the (m-1)-by-(m-1) matrix -c Q1 and an (m-1)-by-n matrix R1 so that Q1 is again -c orthogonal, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); A(j+1:m,:)], where A = Q*R. -c (real version) -c -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the orthogonal matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c - integer m,n,j - real Q(m,m),Q1(m-1,m-1),R(m,n),R1(m-1,n) - real c - real s,rr,w - external xerbla,slacpy,slartg,srot,sscal,saxpy - integer i -c quick return if possible - if (m == 1) return -c check arguments - info = 0 - if (m < 1) then - info = 1 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('SQRDER',info) - end if -c setup the new matrix Q1 -c permute the columns of Q and rows of R so that the deleted row ends -c up being the topmost row. - if (j > 1) then - call slacpy('0',j-1,m-1,Q(1,2),m,Q1(1,1),m-1) - end if - if (j < m) then - call slacpy('0',m-j,m-1,Q(j+1,2),m,Q1(j,1),m-1) - end if -c setup the new matrix R1 - call slacpy('0',m-1,n,R(2,1),m,R1(1,1),m-1) -c eliminate Q(j,2:m) - w = Q(j,m) - do i = m-1,2,-1 - call slartg(Q(j,i),w,c,s,rr) - w = rr -c apply rotation to rows of R1 - if (i <= n) then - call srot(n-i+1,R1(i-1,i),m-1,R1(i,i),m-1,c,s) - end if -c apply rotation to columns of Q1 - call srot(m-1,Q1(1,i-1),1,Q1(1,i),1,c,s) - end do -c the last iteration is special, as we don't have the first row of -c R and first column of Q - call slartg(Q(j,1),w,c,s,rr) - w = rr - call sscal(n,c,R1(1,1),m-1) - call saxpy(n,-s,R(1,1),m,R1(1,1),m-1) -c apply rotation to columns of Q1 - call sscal(m-1,c,Q1(1,1),1) - if (j > 1) then - call saxpy(j-1,-s,Q(1,1),1,Q1(1,1),1) - end if - if (j < m) then - call saxpy(m-j,-s,Q(j+1,1),1,Q1(j,1),1) - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/sqrinc.f +++ /dev/null @@ -1,75 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqrinc(m,n,k,Q,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c column. -c i.e., given an m-by-k orthogonal matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n+1) matrix R1 so that Q1 is again -c orthogonal, R1 upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1); Q*Q'*x; A(:,j:n-1)], where A = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the orthogonal matrix Q. -c on exit, the updated matrix Q1 -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new column in R1 -c x (in) the column being inserted -c - integer m,n,k,j - real Q(m,k),R(k,n),R1(k,n+1),x(m) - - - real w - external xerbla,scopy,sqrqhv,sgemv - integer info,i,jj -c quick return if possible - if (m <= 0) return -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > n+1) then - info = 6 - end if - if (info /= 0) then - call xerbla('SQRINC',info) - end if -c copy leading portion of R - call scopy(k*(j-1),R,1,R1,1) - if (j <= n) then - call scopy(k*(n+1-j),R(1,j),1,R1(1,j+1),1) - end if - call sgemv('T',m,min(k,j-1),1e0,Q,m,x,1,0e0,R1(1,j),1) - if (j < k) then -c eliminate tail, updating Q(:,j:k) and R1(j:k,j+1:n+1) - jj = min(j,n)+1 - call sqrqhv(m,n+1-j,k-j+1,Q(1,j),m,R1(j,jj),m,x,w) -c assemble inserted column - R1(j,j) = w - do i = j+1,k - R1(i,j) = 0e0 - end do - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/sqrinr.f +++ /dev/null @@ -1,73 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqrinr(m,n,Q,Q1,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c row. -c i.e., given an m-by-m orthogonal matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m+1, this subroutine forms the (m+1)-by-(m+1) matrix -c Q1 and an (m+1)-by-n matrix R1 so that Q1 is again -c orthogonal, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); x; A(j:m,:)], where A = Q*R. -c (real version) -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the orthogonal matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c x (in) the row being added -c - integer m,n,j - real Q(m,m),Q1(m+1,m+1),R(m,n),R1(m+1,n),x(n) - external xerbla,slacpy,scopy,sqhqr - integer i -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > m+1) then - info = 7 - end if - if (info /= 0) then - call xerbla('SQRINR',info) - end if -c setup the new matrix Q1 -c permute the columns of Q1 and rows of R1 so that c the new row ends -c up being the topmost row. - if (j > 1) then - call slacpy('0',j-1,m,Q(1,1),m,Q1(1,2),m+1) - end if - if (j <= m) then - call slacpy('0',m-j+1,m,Q(j,1),m,Q1(j+1,2),m+1) - end if -c zero the rest of Q1 - do i = 1,m+1 - Q1(i,1) = 0e0 - Q1(j,i) = 0e0 - end do - Q1(j,1) = 1e0 -c setup the new matrix R1 - call scopy(n,x,1,R1(1,1),m+1) - call slacpy('0',m,n,R(1,1),m,R1(2,1),m+1) -c rotate to form proper QR - call sqhqr(m+1,n,m+1,Q1,m+1,R1,m+1) - end
deleted file mode 100644 --- a/libcruft/qrupdate/sqrqhu.f +++ /dev/null @@ -1,78 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqrqhu(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and a k-vector u, -c this subroutine updates the matrices Q -> Q1 and -c R -> R1 so that Q1 = Q*G', R1 = G*R, u1(2:k) = 0 -c with G orthogonal, R1 upper Hessenberg, and u1 = G*u. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the orthogonal matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the k-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is orthogonal, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - real Q(ldq,*),R(ldr,*),u(*),rr - real c - real s,w - external xerbla,slartg,srot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('SQRQHU',info) - end if - rr = u(k) - do i = k-1,1,-1 - w = rr - if (w /= 0e0) then - call slartg(u(i),w,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call srot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q if necessary - if (m > 0) then - call srot(m,Q(1,i),1,Q(1,i+1),1,c,s) - end if - else -c no rotation necessary - rr = u(i) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/sqrqhv.f +++ /dev/null @@ -1,75 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqrqhv(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and an m-vector u, this subroutine -c updates the matrices Q -> Q1 and R -> R1 so that -c Q1 = Q*G', R1 = G*R, w1(2:m) = 0 with G orthogonal, -c R1 upper Hessenberg, and w1 = Q1'*u. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. k <= m. -c Q (io) on entry, the orthogonal matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the m-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is orthogonal, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - real Q(ldq,*),R(ldr,*),u(*),rr - real c - real s,w,w1,sdot - external xerbla,sdot,slartg,srot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (k > m) then - info = 3 - else if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('SQRQHV',info) - end if -c form each element of w = Q'*u when necessary. - rr = sdot(m,Q(1,k),1,u,1) - do i = k-1,1,-1 - w1 = rr - w = sdot(m,Q(1,i),1,u,1) - call slartg(w,w1,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call srot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q - call srot(m,Q(1,i),1,Q(1,i+1),1,c,s) - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/sqrshc.f +++ /dev/null @@ -1,97 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine sqrshc(m,n,k,Q,R,i,j) -c purpose: updates a QR factorization after circular shift of -c columns. -c i.e., given an m-by-k orthogonal matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c R -> R1 so that Q1 is again orthogonal, R1 upper -c trapezoidal, and -c Q1*R1 = A(:,p), where A = Q*R and p is the permutation -c [1:i-1,shift(i:j,-1),j+1:n] if i < j or -c [1:j-1,shift(j:i,+1),i+1:n] if j > i. -c if m == 0, the matrix Q is ignored. -c (real version) -c arguments: -c m (in) number of rows of the matrix Q, or 0 if Q is not needed. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the (orthogonal) matrix Q. -c on exit, the updated matrix Q1 -c R (io) on entry, the upper trapezoidal m-by-n matrix R. -c on exit, the updated matrix R1. -c i (in) the first index determining the range (see above) -c j (in) the second index determining the range (see above) -c - integer m,n,k,i,j - real Q(m,k),R(k,n) - external xerbla,sswap,sqhqr,sqrqhu - real w - integer l,jj,kk,info - -c quick return if possible - if (k <= 0 .or. n <= 1) return - info = 0 - if (m /= 0 .and. k > m) then - info = 3 - else if (i < 1 .or. i > n) then - info = 6 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('SQRSHC',info) - end if - - if (i < j) then -c shift columns - do l = i,j-1 - call sswap(min(k,l+1),R(1,l),1,R(1,l+1),1) - end do -c retriangularize - if (i < k) then - kk = min(k,j) - if (m > 0) then - call sqhqr(m,n+1-i,kk+1-i,Q(1,i),m,R(i,i),k) - else - call sqhqr(0,n+1-i,kk+1-i,Q,1,R(i,i),k) - endif - end if - else if (j < i) then -c shift columns - do l = i,j+1,-1 - call sswap(min(k,i),R(1,l),1,R(1,l-1),1) - end do -c retriangularize - if (j < k) then - jj = min(j+1,n) - kk = min(k,i) - if (m > 0) then - call sqrqhu(m,n-j,kk+1-j,Q(1,j),m,R(j,jj),k,R(j,j),w) - else - call sqrqhu(0,n-j,kk+1-j,Q,1,R(j,jj),k,R(j,j),w) - end if - R(j,j) = w - do jj = j+1,kk - R(jj,j) = 0 - end do - end if - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/zch1dn.f +++ /dev/null @@ -1,81 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zch1dn(n,R,u,w,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a hermitian positive definite matrix A, i.e. -c A = R'*R, this subroutine downdates R -> R1 so that -c R1'*R1 = A - u*u' -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n,info - double complex R(n,n),u(n) - double precision w(n) - external ztrsv,zlartg,dznrm2 - double precision rho,dznrm2 - double complex crho,rr,ui,t - integer i,j - -c quick return if possible - if (n <= 0) return -c check for singularity of R - do i = 1,n - if (R(i,i) == 0d0) then - info = 2 - return - end if - end do -c form R' \ u - call ztrsv('U','C','N',n,R,n,u,1) - rho = dznrm2(n,u,1) -c check positive definiteness - rho = 1 - rho**2 - if (rho <= 0d0) then - info = 1 - return - end if - crho = sqrt(rho) -c eliminate R' \ u - do i = n,1,-1 - ui = u(i) -c generate next rotation - call zlartg(crho,ui,w(i),u(i),rr) - crho = rr - end do -c apply rotations - do i = n,1,-1 - ui = 0d0 - do j = i,1,-1 - t = w(j)*ui + u(j)*R(j,i) - R(j,i) = w(j)*R(j,i) - conjg(u(j))*ui - ui = t - end do - end do - - info = 0 - end
deleted file mode 100644 --- a/libcruft/qrupdate/zch1up.f +++ /dev/null @@ -1,56 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zch1up(n,R,u,w) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a hermitian positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A + u*u' or A - u*u' -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (io) on entry, the upper triangular matrix R -c on exit, the updated matrix R1 -c u (io) the vector determining the rank-1 update -c on exit, u is destroyed. -c w (w) a real workspace vector of size n -c -c NOTE: the workspace vector is used to store the rotations -c so that R does not need to be traversed by rows. -c - integer n - double complex R(n,n),u(n) - double precision w(n) - external zlartg - double complex rr,ui,t - integer i,j - - do i = 1,n -c apply stored rotations, column-wise - ui = conjg(u(i)) - do j = 1,i-1 - t = w(j)*R(j,i) + u(j)*ui - ui = w(j)*ui - conjg(u(j))*R(j,i) - R(j,i) = t - end do -c generate next rotation - call zlartg(R(i,i),ui,w(i),u(i),rr) - R(i,i) = rr - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/zchdex.f +++ /dev/null @@ -1,62 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine zchdex(n,R,R1,j) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A(jj,jj), where jj = [1:j-1,j+1:n+1]. -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the deleted row/column - integer n,j,info - double complex R(n,n),R1(n-1,n-1) - double precision c - double complex Qdum,s,rr - external xerbla,zlacpy,zqhqr,zlartg - -c quick return if possible - if (n == 1) return - -c check arguments - info = 0 - if (n <= 0) then - info = 1 - else if (j < 1 .or. j > n) then - info = 4 - end if - if (info /= 0) then - call xerbla('ZCHDEX',info) - end if - -c setup the new matrix R1 - if (j > 1) then - call zlacpy('0',n-1,j-1,R(1,1),n,R1(1,1),n-1) - end if - if (j < n) then - call zlacpy('0',n-1,n-j,R(1,j+1),n,R1(1,j),n-1) - call zqhqr(0,n-j,n-j,Qdum,1,R1(j,j),n-1) -c eliminate R(n,n) - call zlartg(R1(n-1,n-1),R(n,n),c,s,rr) - R1(n-1,n-1) = rr - endif - end
deleted file mode 100644 --- a/libcruft/qrupdate/zchinx.f +++ /dev/null @@ -1,109 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - - subroutine zchinx(n,R,R1,j,u,info) -c purpose: given an upper triangular matrix R that is a Cholesky -c factor of a symmetric positive definite matrix A, i.e. -c A = R'*R, this subroutine updates R -> R1 so that -c R1'*R1 = A1, A1(jj,jj) = A, A(j,:) = u', A(:,j) = u, -c jj = [1:j-1,j+1:n+1]. -c (complex version) -c arguments: -c n (in) the order of matrix R -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the inserted row/column -c u (in) the vector (n+1) determining the rank-1 update -c info (out) on exit, if info = 1, the -c definiteness. - - integer n,j,info - double complex R(n,n),R1(n+1,n+1),u(n+1) - double precision rho,dznrm2 - double complex Qdum,w - external xerbla,zcopy,zlacpy,ztrsv,dznrm2,zqrqhu - integer jj - -c quick return if possible - if (n == 0) then - if (dble(u(1)) <= 0) then - info = 1 - return - else - R(1,1) = sqrt(dble(u(1))) - end if - end if - -c check arguments - info = 0 - if (n < 0) then - info = 1 - else if (j < 1 .or. j > n+1) then - info = 4 - end if - if (info /= 0) then - call xerbla('ZCHINX',info) - end if - -c copy shifted vector - if (j > 1) then - call zcopy(j-1,u,1,R1(1,j),1) - end if - w = u(j) - if (j < n+1) then - call zcopy(n-j+1,u(j+1),1,R1(j,j),1) - end if - -c check for singularity of R - do i = 1,n - if (R(i,i) == 0d0) then - info = 2 - return - end if - end do -c form R' \ u - call ztrsv('U','T','N',n,R,n,R1(1,j),1) - rho = dznrm2(n,R1(1,j),1) -c check positive definiteness - rho = u(j) - rho**2 - if (rho <= 0d0) then - info = 1 - return - end if - R1(n+1,n+1) = sqrt(rho) - -c setup the new matrix R1 - do i = 1,n+1 - R1(n+1,i) = 0d0 - end do - if (j > 1) then - call zlacpy('0',j-1,n,R(1,1),n,R1(1,1),n+1) - end if - if (j <= n) then - call zlacpy('0',n,n-j+1,R(1,j),n,R1(1,j+1),n+1) -c retriangularize - jj = min(j+1,n) - call zqrqhu(0,n+1-j,n-j,Qdum,1,R1(j,jj),n+1,R1(j,j),w) - R1(j,j) = w - do jj = j+1,n - R1(jj,j) = 0d0 - end do - end if - - end
deleted file mode 100644 --- a/libcruft/qrupdate/zqhqr.f +++ /dev/null @@ -1,69 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqhqr(m,n,k,Q,ldq,R,ldr) -c purpose: given an k-by-n upper Hessenberg matrix R and -c an m-by-k matrix Q, this subroutine updates -c R -> R1 and Q -> Q1 so that R1 is upper -c trapezoidal, R1 = G*R and Q1 = Q*G', where -c G is an unitary matrix, giving Q1*R1 = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q -c n (in) number of columns of the matrix R -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the unitary matrix Q -c on exit, the updated matrix Q1 -c ldq (in) leading dimension of Q -c R (io) on entry, the upper triangular matrix R -c on exit, the updated upper Hessenberg matrix R1 -c ldr (in) leading dimension of R -c - integer m,n,k,ldq,ldr - double complex Q(ldq,*),R(ldr,*) - double precision c - double complex s,rr - external xerbla,zlartg,zrot - integer info,i -c quick return if possible. - if (n <= 0 .or. k <= 1) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('ZQHQR',info) - end if -c triangularize - do i = 1,min(k-1,n) - call zlartg(R(i,i),R(i+1,i),c,s,rr) - R(i,i) = rr - R(i+1,i) = 0d0 - if (i < n) then - call zrot(n-i,R(i,i+1),ldr,R(i+1,i+1),ldr,c,s) - end if -c apply rotation to Q - if (m > 0) then - call zrot(m,Q(1,i),1,Q(1,i+1),1,c,conjg(s)) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/zqr1up.f +++ /dev/null @@ -1,53 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqr1up(m,n,k,Q,R,u,v) -c purpose: updates a QR factorization after rank-1 modification -c i.e., given a m-by-k unitary Q and m-by-n upper -c trapezoidal R, an m-vector u and n-vector v, -c this subroutine updates Q -> Q1 and R -> R1 so that -c Q1*R1 = Q*R + Q*Q'u*v', and Q1 is again unitary -c and R1 upper trapezoidal. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the unitary m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (io) on entry, the upper trapezoidal m-by-n matrix R. -c on exit, the updated matrix R1. -c u (in) the left m-vector. -c v (in) the right n-vector. -c - integer m,n,k - double complex Q(m,k),R(k,n),u(m),v(n) - double complex w - external zqrqhv,zqhqr - integer i -c quick return if possible - if (m <= 0 .or. n <= 0) return -c eliminate tail of Q'*u - call zqrqhv(m,n,k,Q,m,R,m,u,w) -c update R - do i = 1,n - R(1,i) = R(1,i) + w*conjg(v(i)) - end do -c retriangularize R - call zqhqr(m,n,k,Q,m,R,k) - end
deleted file mode 100644 --- a/libcruft/qrupdate/zqrdec.f +++ /dev/null @@ -1,66 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqrdec(m,n,k,Q,R,R1,j) -c purpose: updates a QR factorization after deleting -c a column. -c i.e., given an m-by-k unitary matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n-1) matrix R1 so that Q1 remains -c unitary, R1 is upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1) A(:,j+1:n)], where A = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the unitary m-by-k matrix Q. -c on exit, the updated matrix Q1. -c R (in) the original upper trapezoidal matrix R. -c R1 (out) the updated matrix R1. -c j (in) the position of the deleted column in R. -c 1 <= j <= n. -c - integer m,n,k,j - double complex Q(m,k),R(k,n),R1(k,n-1) - external xerbla,zcopy,zqhqr - integer info -c quick return if possible - if (m <= 0 .or. k <= 0 .or. n == 1) return -c check arguments - info = 0 - if (n < 1) then - info = 2 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('ZQRDEC',info) - end if -c copy leading portion - call zcopy(k*(j-1),R,1,R1,1) - if (j < n) then -c copy trailing portion of R - call zcopy(k*(n-j),R(1,j+1),1,R1(1,j),1) -c if necessary, retriangularize R1(j:k,j:n-1) and update Q(:,j:k) - if (j < k) then - call zqhqr(m,n-j,k-j+1,Q(1,j),m,R1(j,j),k) - end if - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/zqrder.f +++ /dev/null @@ -1,93 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqrder(m,n,Q,Q1,R,R1,j) -c purpose: updates a QR factorization after deleting a row. -c i.e., given an m-by-m unitary matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m, this subroutine forms the (m-1)-by-(m-1) matrix -c Q1 and an (m-1)-by-n matrix R1 so that Q1 is again -c unitary, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); A(j+1:m,:)], where A = Q*R. -c (complex version) -c -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the unitary matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c - integer m,n,j - double complex Q(m,m),Q1(m-1,m-1),R(m,n),R1(m-1,n) - double precision c - double complex s,rr,w - external xerbla,zlacpy,zlartg,zrot,zdscal,zaxpy - integer i -c quick return if possible - if (m == 1) return -c check arguments - info = 0 - if (m < 1) then - info = 1 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('ZQRDER',info) - end if -c setup the new matrix Q1 -c permute the columns of Q and rows of R so that the deleted row ends -c up being the topmost row. - if (j > 1) then - call zlacpy('0',j-1,m-1,Q(1,2),m,Q1(1,1),m-1) - end if - if (j < m) then - call zlacpy('0',m-j,m-1,Q(j+1,2),m,Q1(j,1),m-1) - end if -c setup the new matrix R1 - call zlacpy('0',m-1,n,R(2,1),m,R1(1,1),m-1) -c eliminate Q(j,2:m) - w = Q(j,m) - do i = m-1,2,-1 - call zlartg(Q(j,i),w,c,s,rr) - w = rr -c apply rotation to rows of R1 - if (i <= n) then - call zrot(n-i+1,R1(i-1,i),m-1,R1(i,i),m-1,c,conjg(s)) - end if -c apply rotation to columns of Q1 - call zrot(m-1,Q1(1,i-1),1,Q1(1,i),1,c,s) - end do -c the last iteration is special, as we don't have the first row of -c R and first column of Q - call zlartg(Q(j,1),w,c,s,rr) - w = rr - call zdscal(n,c,R1(1,1),m-1) - call zaxpy(n,-s,R(1,1),m,R1(1,1),m-1) -c apply rotation to columns of Q1 - call zdscal(m-1,c,Q1(1,1),1) - if (j > 1) then - call zaxpy(j-1,-conjg(s),Q(1,1),1,Q1(1,1),1) - end if - if (j < m) then - call zaxpy(m-j,-conjg(s),Q(j+1,1),1,Q1(j,1),1) - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/zqrinc.f +++ /dev/null @@ -1,74 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqrinc(m,n,k,Q,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c column. -c i.e., given an m-by-k unitary matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c forms an m-by-(n+1) matrix R1 so that Q1 is again unitary, -c R1 upper trapezoidal, and -c Q1*R1 = [A(:,1:j-1); Q*Q'*x; A(:,j:n-1)], where A = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. k <= m. -c Q (io) on entry, the unitary matrix Q. -c on exit, the updated matrix Q1 -c R (in) the original upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new column in R1 -c x (in) the column being inserted -c - integer m,n,k,j - double complex Q(m,k),R(k,n),R1(k,n+1),x(m) - double complex w - external xerbla,zcopy,zqrqhv,zgemv - integer info,i,jj -c quick return if possible - if (m <= 0) return -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > n+1) then - info = 6 - end if - if (info /= 0) then - call xerbla('ZQRINC',info) - end if -c copy leading portion of R - call zcopy(k*(j-1),R,1,R1,1) - if (j <= n) then - call zcopy(k*(n+1-j),R(1,j),1,R1(1,j+1),1) - end if - call zgemv('C',m,min(k,j-1),dcmplx(1d0),Q,m,x,1, - + dcmplx(0d0),R1(1,j),1) - if (j < k) then -c eliminate tail, updating Q(:,j:k) and R1(j:k,j+1:n+1) - jj = min(j,n)+1 - call zqrqhv(m,n+1-j,k-j+1,Q(1,j),m,R1(j,jj),m,x,w) -c assemble inserted column - R1(j,j) = w - do i = j+1,k - R1(i,j) = 0d0 - end do - end if - end
deleted file mode 100644 --- a/libcruft/qrupdate/zqrinr.f +++ /dev/null @@ -1,73 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqrinr(m,n,Q,Q1,R,R1,j,x) -c purpose: updates a QR factorization after inserting a new -c row. -c i.e., given an m-by-m unitary matrix Q, an m-by-n -c upper trapezoidal matrix R and index j in the range -c 1:m+1, this subroutine forms the (m+1)-by-(m+1) matrix -c Q1 and an (m+1)-by-n matrix R1 so that Q1 is again -c unitary, R1 upper trapezoidal, and -c Q1*R1 = [A(1:j-1,:); x; A(j:m,:)], where A = Q*R. -c (complex version) -c arguments: -c m (in) number of rows of the matrix R. -c n (in) number of columns of the matrix R -c Q (in) the unitary matrix Q -c Q1 (out) the updated matrix Q1 -c R (in) the upper trapezoidal matrix R -c R1 (out) the updated matrix R1 -c j (in) the position of the new row in R1 -c x (in) the row being added -c - integer m,n,j - double complex Q(m,m),Q1(m+1,m+1),R(m,n),R1(m+1,n),x(n) - external xerbla,zlacpy,zcopy,zqhqr - integer i -c check arguments - info = 0 - if (n < 0) then - info = 2 - else if (j < 1 .or. j > m+1) then - info = 7 - end if - if (info /= 0) then - call xerbla('ZQRINR',info) - end if -c setup the new matrix Q1 -c permute the columns of Q1 and rows of R1 so that c the new row ends -c up being the topmost row. - if (j > 1) then - call zlacpy('0',j-1,m,Q(1,1),m,Q1(1,2),m+1) - end if - if (j <= m) then - call zlacpy('0',m-j+1,m,Q(j,1),m,Q1(j+1,2),m+1) - end if -c zero the rest of Q1 - do i = 1,m+1 - Q1(i,1) = 0d0 - Q1(j,i) = 0d0 - end do - Q1(j,1) = 1d0 -c setup the new matrix R1 - call zcopy(n,x,1,R1(1,1),m+1) - call zlacpy('0',m,n,R(1,1),m,R1(2,1),m+1) -c rotate to form proper QR - call zqhqr(m+1,n,m+1,Q1,m+1,R1,m+1) - end
deleted file mode 100644 --- a/libcruft/qrupdate/zqrqhu.f +++ /dev/null @@ -1,78 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqrqhu(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and a k-vector u, -c this subroutine updates the matrices Q -> Q1 and -c R -> R1 so that Q1 = Q*G', R1 = G*R, u1(2:k) = 0 -c with G unitary, R1 upper Hessenberg, and u1 = G*u. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. -c Q (io) on entry, the unitary matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the k-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is unitary, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - double complex Q(ldq,*),R(ldr,*),u(*),rr - double precision c - double complex s,w - external xerbla,zlartg,zrot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('ZQRQHU',info) - end if - rr = u(k) - do i = k-1,1,-1 - w = rr - if (w /= dcmplx(0d0,0d0)) then - call zlartg(u(i),w,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call zrot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q if necessary - if (m > 0) then - call zrot(m,Q(1,i),1,Q(1,i+1),1,c,conjg(s)) - end if - else -c no rotation necessary - rr = u(i) - end if - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/zqrqhv.f +++ /dev/null @@ -1,75 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqrqhv(m,n,k,Q,ldq,R,ldr,u,rr) -c purpose: given an m-by-k matrix Q, an upper trapezoidal -c k-by-n matrix R, and an m-vector u, this subroutine -c updates the matrices Q -> Q1 and R -> R1 so that -c Q1 = Q*G', R1 = G*R, w1(2:m) = 0 with G unitary, -c R1 upper Hessenberg, and w1 = Q1'*u. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q and rows of R. k <= m. -c Q (io) on entry, the unitary matrix Q. -c on exit, the updated matrix Q1. -c ldq (in) leading dimension of Q. -c R (io) on entry, the upper triangular matrix R. -c on exit, the updated upper Hessenberg matrix R1. -c ldr (in) leading dimension of R. -c u (in) the m-vector u. -c rr (out) the first element of Q1'*u on exit. -c -c if Q is unitary, so is Q1. It is not strictly -c necessary, however. - integer m,n,k,ldq,ldr - double complex Q(ldq,*),R(ldr,*),u(*),rr - double precision c - double complex s,w,w1,zdotc - external xerbla,zdotc,zlartg,zrot - integer i,info -c quick return if possible. - if (k <= 0) return -c check arguments. - info = 0 - if (k > m) then - info = 3 - else if (ldq < 1) then - info = 5 - else if (ldr < 1) then - info = 7 - end if - if (info /= 0) then - call xerbla('ZQRQHV',info) - end if -c form each element of w = Q'*u when necessary. - rr = zdotc(m,Q(1,k),1,u,1) - do i = k-1,1,-1 - w1 = rr - w = zdotc(m,Q(1,i),1,u,1) - call zlartg(w,w1,c,s,rr) -c apply rotation to rows of R if necessary - if (i <= n) then - call zrot(n+1-i,R(i,i),ldr,R(i+1,i),ldr,c,s) - end if -c apply rotation to columns of Q - call zrot(m,Q(1,i),1,Q(1,i+1),1,c,conjg(s)) - end do - end -
deleted file mode 100644 --- a/libcruft/qrupdate/zqrshc.f +++ /dev/null @@ -1,97 +0,0 @@ -c Copyright (C) 2008 VZLU Prague, a.s., Czech Republic -c -c Author: Jaroslav Hajek <highegg@gmail.com> -c -c This source is free software; you can redistribute it and/or modify -c it under the terms of the GNU General Public License as published by -c the Free Software Foundation; either version 2 of the License, or -c (at your option) any later version. -c -c This program is distributed in the hope that it will be useful, -c but WITHOUT ANY WARRANTY; without even the implied warranty of -c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -c GNU General Public License for more details. -c -c You should have received a copy of the GNU General Public License -c along with this software; see the file COPYING. If not, see -c <http://www.gnu.org/licenses/>. -c - subroutine zqrshc(m,n,k,Q,R,i,j) -c purpose: updates a QR factorization after circular shift of -c columns. -c i.e., given an m-by-k unitary matrix Q, an k-by-n -c upper trapezoidal matrix R and index j in the range -c 1:n+1, this subroutine updates the matrix Q -> Q1 and -c R -> R1 so that Q1 is again unitary, R1 upper trapezoidal, -c and -c Q1*R1 = A(:,p), where A = Q*R and p is the permutation -c [1:i-1,shift(i:j,-1),j+1:n] if i < j or -c [1:j-1,shift(j:i,+1),i+1:n] if j > i. -c if m == 0, the matrix Q is ignored. -c (complex version) -c arguments: -c m (in) number of rows of the matrix Q, or 0 if Q is not needed. -c n (in) number of columns of the matrix R. -c k (in) number of columns of Q, and rows of R. -c Q (io) on entry, the (unitary) matrix Q. -c on exit, the updated matrix Q1 -c R (io) on entry, the upper trapezoidal m-by-n matrix R. -c on exit, the updated matrix R1. -c i (in) the first index determining the range (see above) -c j (in) the second index determining the range (see above) -c - integer m,n,k,i,j - double complex Q(m,k),R(k,n) - external xerbla,zswap,zqhqr,zqrqhu - double complex w - integer l,jj,kk,info - -c quick return if possible - if (k <= 0 .or. n <= 1) return - info = 0 - if (m /= 0 .and. k > m) then - info = 3 - else if (i < 1 .or. i > n) then - info = 6 - else if (j < 1 .or. j > n) then - info = 7 - end if - if (info /= 0) then - call xerbla('ZQRSHC',info) - end if - - if (i < j) then -c shift columns - do l = i,j-1 - call zswap(min(k,l+1),R(1,l),1,R(1,l+1),1) - end do -c retriangularize - if (i < k) then - kk = min(k,j) - if (m > 0) then - call zqhqr(m,n+1-i,kk+1-i,Q(1,i),m,R(i,i),k) - else - call zqhqr(0,n+1-i,kk+1-i,Q,1,R(i,i),k) - endif - end if - else if (j < i) then -c shift columns - do l = i,j+1,-1 - call zswap(min(k,i),R(1,l),1,R(1,l-1),1) - end do -c retriangularize - if (j < k) then - jj = min(j+1,n) - kk = min(k,i) - if (m > 0) then - call zqrqhu(m,n-j,kk+1-j,Q(1,j),m,R(j,jj),k,R(j,j),w) - else - call zqrqhu(0,n-j,kk+1-j,Q,1,R(j,jj),k,R(j,j),w) - end if - R(j,j) = w - do jj = j+1,kk - R(jj,j) = 0 - end do - end if - end if - end
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,71 @@ +2009-01-17 Jaroslav Hajek <highegg@gmail.com> + + * floatQR.h (FloatQR::update, FloatQR::insert_col, + FloatQR::insert_row, FloatQR::delete_col, FloatQR::delete_row, + FloatQR::shift_col): Update interfaces. + + * floatQR.cc: Update external decls for qrupdate routines. + (FloatQR::update, FloatQR::insert_col, FloatQR::insert_row, + FloatQR::delete_col, FloatQR::delete_row, FloatQR::shift_col): Reflect + changes in qrupdate interfaces, implement batch updates. + + * dbleQR.h (QR::update, QR::insert_col, QR::insert_row, + QR::delete_col, QR::delete_row, QR::shift_col): Update interfaces. + + * dbleQR.cc: Update external decls for qrupdate routines. + (QR::update, QR::insert_col, QR::insert_row, QR::delete_col, + QR::delete_row, QR::shift_col): Reflect changes in qrupdate + interfaces, implement batch updates. + + * fCmplxQR.h (FloatComplexQR::update, FloatComplexQR::insert_col, + FloatComplexQR::insert_row, FloatComplexQR::delete_col, + FloatComplexQR::delete_row, FloatComplexQR::shift_col): Update + interfaces. + + * fCmplxQR.cc: Update external decls for qrupdate routines. + (FloatComplexQR::update, FloatComplexQR::insert_col, + FloatComplexQR::insert_row, FloatComplexQR::delete_col, + FloatComplexQR::delete_row, FloatComplexQR::shift_col): Reflect + changes in qrupdate interfaces, + implement batch updates. + + * CmplxQR.h (ComplexQR::update, ComplexQR::insert_col, + ComplexQR::insert_row, ComplexQR::delete_col, ComplexQR::delete_row, + ComplexQR::shift_col): Update interfaces. + + * CmplxQR.cc: Update external decls for qrupdate routines. + (ComplexQR::update, ComplexQR::insert_col, + ComplexQR::insert_row, ComplexQR::delete_col, ComplexQR::delete_row, + ComplexQR::shift_col): Reflect changes in qrupdate interfaces, + implement batch updates. + + * floatCHOL.h (FloatCHOL::update, FloatCHOL::downdate, + FloatCHOL::insert_sym): Update interfaces. + * floatCHOL.cc: Update external decls for qrupdate routines. + (FloatCHOL::update, FloatCHOL::downdate, FloatCHOL::insert_sym, + FloatCHOL::delete_sym, FloatCHOL::shift_sym): Reflect changes in + qrupdate interfaces, + + * CHOL.h (CHOL::update, CHOL::downdate, CHOL::insert_sym): Update + interfaces. + * CHOL.cc: Update external decls for qrupdate routines. + (CHOL::update, CHOL::downdate, CHOL::insert_sym, CHOL::delete_sym, + CHOL::shift_sym): Reflect changes in qrupdate interfaces, + + * fCmplxCHOL.h (FloatComplexCHOL::update, FloatComplexCHOL::downdate, + FloatComplexCHOL::insert_sym): Update interfaces. + * fCmplxCHOL.cc: Update external decls for qrupdate routines. + (FloatComplexCHOL::update, FloatComplexCHOL::downdate, + FloatComplexCHOL::insert_sym, FloatComplexCHOL::delete_sym, + FloatComplexCHOL::shift_sym): Reflect changes in qrupdate interfaces, + + * CmplxCHOL.h (ComplexCHOL::update, ComplexCHOL::downdate, + ComplexCHOL::insert_sym): Update interfaces. + * CmplxCHOL.cc: Update external decls for qrupdate routines. + (ComplexCHOL::update, ComplexCHOL::downdate, ComplexCHOL::insert_sym, + ComplexCHOL::delete_sym, ComplexCHOL::shift_sym): Reflect changes in + qrupdate interfaces, + 2009-01-17 Jaroslav Hajek <highegg@gmail.com> * Array.h (Array<T>): Document internal use of slice_data and
--- a/liboctave/CmplxCHOL.cc +++ b/liboctave/CmplxCHOL.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -52,23 +51,30 @@ Complex*, const octave_idx_type&, const double&, double&, Complex*, double*, octave_idx_type& F77_CHAR_ARG_LEN_DECL); +#ifdef HAVE_QRUPDATE + F77_RET_T - F77_FUNC (zch1up, ZCH1UP) (const octave_idx_type&, Complex*, Complex*, double*); + F77_FUNC (zch1up, ZCH1UP) (const octave_idx_type&, Complex*, const octave_idx_type&, + Complex*, double*); F77_RET_T - F77_FUNC (zch1dn, ZCH1DN) (const octave_idx_type&, Complex*, Complex*, double*, + F77_FUNC (zch1dn, ZCH1DN) (const octave_idx_type&, Complex*, const octave_idx_type&, + Complex*, double*, octave_idx_type&); + + F77_RET_T + F77_FUNC (zchinx, ZCHINX) (const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, Complex*, double*, octave_idx_type&); F77_RET_T - F77_FUNC (zqrshc, ZQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - Complex*, Complex*, const octave_idx_type&, const octave_idx_type&); + F77_FUNC (zchdex, ZCHDEX) (const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, double*); F77_RET_T - F77_FUNC (zchinx, ZCHINX) (const octave_idx_type&, const Complex*, Complex*, const octave_idx_type&, - const Complex*, octave_idx_type&); - - F77_RET_T - F77_FUNC (zchdex, ZCHDEX) (const octave_idx_type&, const Complex*, Complex*, const octave_idx_type&); + F77_FUNC (zchshx, ZCHSHX) (const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + Complex*, double*); +#endif } octave_idx_type @@ -182,26 +188,28 @@ (*current_liboctave_error_handler) ("CHOL requires square matrix"); } +#ifdef HAVE_QRUPDATE + void -ComplexCHOL::update (const ComplexMatrix& u) +ComplexCHOL::update (const ComplexColumnVector& u) { octave_idx_type n = chol_mat.rows (); if (u.length () == n) { - ComplexMatrix tmp = u; + ComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, w, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zch1up, ZCH1UP, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w)); + F77_XFCN (zch1up, ZCH1UP, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), rw)); } else - (*current_liboctave_error_handler) ("CHOL update dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); } octave_idx_type -ComplexCHOL::downdate (const ComplexMatrix& u) +ComplexCHOL::downdate (const ComplexColumnVector& u) { octave_idx_type info = -1; @@ -209,38 +217,40 @@ if (u.length () == n) { - ComplexMatrix tmp = u; + ComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, w, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zch1dn, ZCH1DN, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w, info)); + F77_XFCN (zch1dn, ZCH1DN, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), rw, info)); } else - (*current_liboctave_error_handler) ("CHOL downdate dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); return info; } octave_idx_type -ComplexCHOL::insert_sym (const ComplexMatrix& u, octave_idx_type j) +ComplexCHOL::insert_sym (const ComplexColumnVector& u, octave_idx_type j) { octave_idx_type info = -1; octave_idx_type n = chol_mat.rows (); - if (u.length () != n+1) - (*current_liboctave_error_handler) ("CHOL insert dimension mismatch"); + if (u.length () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("CHOL insert index out of range"); + (*current_liboctave_error_handler) ("cholinsert: index out of range"); else { - ComplexMatrix chol_mat1 (n+1, n+1); + ComplexColumnVector utmp = u; + + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zchinx, ZCHINX, (n, chol_mat.data (), chol_mat1.fortran_vec (), - j+1, u.data (), info)); + chol_mat.resize (n+1, n+1); - chol_mat = chol_mat1; + F77_XFCN (zchinx, ZCHINX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, utmp.fortran_vec (), rw, info)); } return info; @@ -252,14 +262,15 @@ octave_idx_type n = chol_mat.rows (); if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("CHOL delete index out of range"); + (*current_liboctave_error_handler) ("choldelete: index out of range"); else { - ComplexMatrix chol_mat1 (n-1, n-1); + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zchdex, ZCHDEX, (n, chol_mat.data (), chol_mat1.fortran_vec (), j+1)); + F77_XFCN (zchdex, ZCHDEX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, rw)); - chol_mat = chol_mat1; + chol_mat.resize (n-1, n-1); } } @@ -267,14 +278,21 @@ ComplexCHOL::shift_sym (octave_idx_type i, octave_idx_type j) { octave_idx_type n = chol_mat.rows (); - Complex dummy; if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("CHOL shift index out of range"); + (*current_liboctave_error_handler) ("cholshift: index out of range"); else - F77_XFCN (zqrshc, ZQRSHC, (0, n, n, &dummy, chol_mat.fortran_vec (), i+1, j+1)); + { + OCTAVE_LOCAL_BUFFER (Complex, w, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); + + F77_XFCN (zchshx, ZCHSHX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + i + 1, j + 1, w, rw)); + } } +#endif + ComplexMatrix chol2inv (const ComplexMatrix& r) {
--- a/liboctave/CmplxCHOL.h +++ b/liboctave/CmplxCHOL.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,14 +22,13 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #if !defined (octave_ComplexCHOL_h) #define octave_ComplexCHOL_h 1 #include <iostream> #include "CMatrix.h" +#include "CColVector.h" class OCTAVE_API @@ -67,16 +67,20 @@ void set (const ComplexMatrix& R); - void update (const ComplexMatrix& u); +#ifdef HAVE_QRUPDATE + + void update (const ComplexColumnVector& u); - octave_idx_type downdate (const ComplexMatrix& u); + octave_idx_type downdate (const ComplexColumnVector& u); - octave_idx_type insert_sym (const ComplexMatrix& u, octave_idx_type j); + octave_idx_type insert_sym (const ComplexColumnVector& u, octave_idx_type j); void delete_sym (octave_idx_type j); void shift_sym (octave_idx_type i, octave_idx_type j); +#endif + friend OCTAVE_API std::ostream& operator << (std::ostream& os, const ComplexCHOL& a); private:
--- a/liboctave/CmplxQR.cc +++ b/liboctave/CmplxQR.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -32,6 +31,7 @@ #include "lo-error.h" #include "Range.h" #include "idx-vector.h" +#include "oct-locbuf.h" extern "C" { @@ -45,33 +45,40 @@ Complex*, const octave_idx_type&, Complex*, Complex*, const octave_idx_type&, octave_idx_type&); - // these come from qrupdate +#ifdef HAVE_QRUPDATE F77_RET_T F77_FUNC (zqr1up, ZQR1UP) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - Complex*, Complex*, const Complex*, const Complex*); + Complex*, const octave_idx_type&, Complex*, const octave_idx_type&, + Complex*, Complex*, Complex*, double*); F77_RET_T F77_FUNC (zqrinc, ZQRINC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - Complex*, const Complex*, Complex*, const octave_idx_type&, const Complex*); + Complex*, const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, const Complex*, double*); F77_RET_T F77_FUNC (zqrdec, ZQRDEC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - Complex*, const Complex*, Complex*, const octave_idx_type&); + Complex*, const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, double*); F77_RET_T F77_FUNC (zqrinr, ZQRINR) (const octave_idx_type&, const octave_idx_type&, - const Complex*, Complex*, const Complex*, Complex*, - const octave_idx_type&, const Complex*); + Complex*, const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, const Complex*, double*); F77_RET_T F77_FUNC (zqrder, ZQRDER) (const octave_idx_type&, const octave_idx_type&, - const Complex*, Complex*, const Complex*, Complex *, - const octave_idx_type&); + Complex*, const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, Complex*, double*); F77_RET_T F77_FUNC (zqrshc, ZQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - Complex*, Complex*, const octave_idx_type&, const octave_idx_type&); + Complex*, const octave_idx_type&, Complex*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + Complex*, double*); + +#endif } ComplexQR::ComplexQR (const ComplexMatrix& a, QR::type qr_type) @@ -171,6 +178,27 @@ this->r = r_arg; } +#ifdef HAVE_QRUPDATE + +void +ComplexQR::update (const ComplexColumnVector& u, const ComplexColumnVector& v) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + if (u.length () == m && v.length () == n) + { + ComplexColumnVector utmp = u, vtmp = v; + OCTAVE_LOCAL_BUFFER (Complex, w, k); + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqr1up, ZQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w, rw)); + } + else + (*current_liboctave_error_handler) ("QR update dimensions mismatch"); +} + void ComplexQR::update (const ComplexMatrix& u, const ComplexMatrix& v) { @@ -178,32 +206,94 @@ octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); - if (u.length () == m && v.length () == n) - F77_XFCN (zqr1up, ZQR1UP, (m, n, k, q.fortran_vec (), r.fortran_vec (), - u.data (), v.data ())); + if (u.rows () == m && v.rows () == n && u.cols () == v.cols ()) + { + OCTAVE_LOCAL_BUFFER (Complex, w, k); + OCTAVE_LOCAL_BUFFER (double, rw, k); + for (octave_idx_type i = 0; i < u.cols (); i++) + { + ComplexColumnVector utmp = u.column (i), vtmp = v.column (i); + F77_XFCN (zqr1up, ZQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w, rw)); + } + } else - (*current_liboctave_error_handler) ("QR update dimensions mismatch"); + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); } void -ComplexQR::insert_col (const ComplexMatrix& u, octave_idx_type j) +ComplexQR::insert_col (const ComplexColumnVector& u, octave_idx_type j) { octave_idx_type m = q.rows (); octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); if (u.length () != m) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - ComplexMatrix r1 (m,n+1); + if (k < m) + { + q.resize (m, k+1); + r.resize (k+1, n+1); + } + else + { + r.resize (k, n+1); + } + + ComplexColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrinc, ZQRINC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + utmp.data (), rw)); + } +} + +void +ComplexQR::insert_col (const ComplexMatrix& u, const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); - F77_XFCN (zqrinc, ZQRINC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1, u.data ())); + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, ASCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); - r = r1; + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (u.length () != m || u.columns () != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + else if (nj > 0 && (js(0) < 0 || js(nj-1) > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + octave_idx_type kmax = std::min (k + nj, m); + if (k < m) + { + q.resize (m, kmax); + r.resize (kmax, n + nj); + } + else + { + r.resize (k, n + nj); + } + + OCTAVE_LOCAL_BUFFER (double, rw, kmax); + for (octave_idx_type i = 0; i < js.length (); i++) + { + ComplexColumnVector utmp = u.column (jsi(i)); + F77_XFCN (zqrinc, ZQRINC, (m, n + i, std::min (kmax, k + i), + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, + utmp.data (), rw)); + } } } @@ -214,41 +304,87 @@ octave_idx_type k = r.rows (); octave_idx_type n = r.columns (); - if (k < m && k < n) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); - else if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - ComplexMatrix r1 (k, n-1); + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrdec, ZQRDEC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, rw)); - F77_XFCN (zqrdec, ZQRDEC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1)); - - r = r1; + if (k < m) + { + q.resize (m, k-1); + r.resize (k-1, n-1); + } + else + { + r.resize (k, n-1); + } } } void -ComplexQR::insert_row (const ComplexMatrix& u, octave_idx_type j) +ComplexQR::delete_col (const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, DESCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + OCTAVE_LOCAL_BUFFER (double, rw, k); + for (octave_idx_type i = 0; i < js.length (); i++) + { + F77_XFCN (zqrdec, ZQRDEC, (m, n - i, k == m ? k : k - i, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, rw)); + } + if (k < m) + { + q.resize (m, k - nj); + r.resize (k - nj, n - nj); + } + else + { + r.resize (k, n - nj); + } + + } +} + +void +ComplexQR::insert_row (const ComplexRowVector& u, octave_idx_type j) { octave_idx_type m = r.rows (); octave_idx_type n = r.columns (); + octave_idx_type k = std::min (m, n); if (! q.is_square () || u.length () != n) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > m) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - ComplexMatrix q1 (m+1, m+1); - ComplexMatrix r1 (m+1, n); + q.resize (m + 1, m + 1); + r.resize (m + 1, n); + ComplexRowVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrinr, ZQRINR, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + j + 1, utmp.fortran_vec (), rw)); - F77_XFCN (zqrinr, ZQRINR, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1, u.data ())); - - q = q1; - r = r1; } } @@ -259,19 +395,19 @@ octave_idx_type n = r.columns (); if (! q.is_square ()) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); else if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - ComplexMatrix q1 (m-1, m-1); - ComplexMatrix r1 (m-1, n); + OCTAVE_LOCAL_BUFFER (Complex, w, m); + OCTAVE_LOCAL_BUFFER (double, rw, m); + F77_XFCN (zqrder, ZQRDER, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + w, rw)); - F77_XFCN (zqrder, ZQRDER, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1 )); - - q = q1; - r = r1; + q.resize (m - 1, m - 1); + r.resize (m - 1, n); } } @@ -283,22 +419,19 @@ octave_idx_type n = r.columns (); if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR shift index out of range"); + (*current_liboctave_error_handler) ("qrshift: index out of range"); else - F77_XFCN (zqrshc, ZQRSHC, (m, n, k, q.fortran_vec (), r.fortran_vec (), i+1, j+1)); + { + OCTAVE_LOCAL_BUFFER (Complex, w, k); + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrshc, ZQRSHC, (m, n, k, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + i + 1, j + 1, w, rw)); + } } -void -ComplexQR::economize (void) -{ - octave_idx_type r_nc = r.columns (); - - if (r.rows () > r_nc) - { - q.resize (q.rows (), r_nc); - r.resize (r_nc, r_nc); - } -} +#endif /* ;;; Local Variables: ***
--- a/liboctave/CmplxQR.h +++ b/liboctave/CmplxQR.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #if !defined (octave_ComplexQR_h) #define octave_ComplexQR_h 1 @@ -66,19 +65,27 @@ ComplexMatrix R (void) const { return r; } +#ifdef HAVE_QRUPDATE + + void update (const ComplexColumnVector& u, const ComplexColumnVector& v); + void update (const ComplexMatrix& u, const ComplexMatrix& v); - void insert_col (const ComplexMatrix& u, octave_idx_type j); + void insert_col (const ComplexColumnVector& u, octave_idx_type j); + + void insert_col (const ComplexMatrix& u, const Array<octave_idx_type>& j); void delete_col (octave_idx_type j); - void insert_row (const ComplexMatrix& u, octave_idx_type j); + void delete_col (const Array<octave_idx_type>& j); + + void insert_row (const ComplexRowVector& u, octave_idx_type j); void delete_row (octave_idx_type j); void shift_cols (octave_idx_type i, octave_idx_type j); - void economize(); +#endif friend std::ostream& operator << (std::ostream&, const ComplexQR&);
--- a/liboctave/dbleCHOL.cc +++ b/liboctave/dbleCHOL.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -52,23 +51,30 @@ double*, const octave_idx_type&, const double&, double&, double*, octave_idx_type*, octave_idx_type& F77_CHAR_ARG_LEN_DECL); +#ifdef HAVE_QRUPDATE + F77_RET_T - F77_FUNC (dch1up, DCH1UP) (const octave_idx_type&, double*, double*, double*); + F77_FUNC (dch1up, DCH1UP) (const octave_idx_type&, double*, const octave_idx_type&, + double*, double*); F77_RET_T - F77_FUNC (dch1dn, DCH1DN) (const octave_idx_type&, double*, double*, double*, + F77_FUNC (dch1dn, DCH1DN) (const octave_idx_type&, double*, const octave_idx_type&, + double*, double*, octave_idx_type&); + + F77_RET_T + F77_FUNC (dchinx, DCHINX) (const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, double*, double*, octave_idx_type&); F77_RET_T - F77_FUNC (dqrshc, DQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - double*, double*, const octave_idx_type&, const octave_idx_type&); + F77_FUNC (dchdex, DCHDEX) (const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, double*); F77_RET_T - F77_FUNC (dchinx, DCHINX) (const octave_idx_type&, const double*, double*, const octave_idx_type&, - const double*, octave_idx_type&); - - F77_RET_T - F77_FUNC (dchdex, DCHDEX) (const octave_idx_type&, const double*, double*, const octave_idx_type&); + F77_FUNC (dchshx, DCHSHX) (const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + double*); +#endif } octave_idx_type @@ -186,26 +192,28 @@ (*current_liboctave_error_handler) ("CHOL requires square matrix"); } +#ifdef HAVE_QRUPDATE + void -CHOL::update (const Matrix& u) +CHOL::update (const ColumnVector& u) { octave_idx_type n = chol_mat.rows (); if (u.length () == n) { - Matrix tmp = u; + ColumnVector utmp = u; OCTAVE_LOCAL_BUFFER (double, w, n); - F77_XFCN (dch1up, DCH1UP, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w)); + F77_XFCN (dch1up, DCH1UP, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), w)); } else - (*current_liboctave_error_handler) ("CHOL update dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); } octave_idx_type -CHOL::downdate (const Matrix& u) +CHOL::downdate (const ColumnVector& u) { octave_idx_type info = -1; @@ -213,38 +221,40 @@ if (u.length () == n) { - Matrix tmp = u; + ColumnVector utmp = u; OCTAVE_LOCAL_BUFFER (double, w, n); - F77_XFCN (dch1dn, DCH1DN, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w, info)); + F77_XFCN (dch1dn, DCH1DN, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), w, info)); } else - (*current_liboctave_error_handler) ("CHOL downdate dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); return info; } octave_idx_type -CHOL::insert_sym (const Matrix& u, octave_idx_type j) +CHOL::insert_sym (const ColumnVector& u, octave_idx_type j) { octave_idx_type info = -1; octave_idx_type n = chol_mat.rows (); - if (u.length () != n+1) - (*current_liboctave_error_handler) ("CHOL insert dimension mismatch"); + if (u.length () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("CHOL insert index out of range"); + (*current_liboctave_error_handler) ("cholinsert: index out of range"); else { - Matrix chol_mat1 (n+1, n+1); + ColumnVector utmp = u; + + OCTAVE_LOCAL_BUFFER (double, w, n); - F77_XFCN (dchinx, DCHINX, (n, chol_mat.data (), chol_mat1.fortran_vec (), - j+1, u.data (), info)); + chol_mat.resize (n+1, n+1); - chol_mat = chol_mat1; + F77_XFCN (dchinx, DCHINX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, utmp.fortran_vec (), w, info)); } return info; @@ -256,14 +266,15 @@ octave_idx_type n = chol_mat.rows (); if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("CHOL delete index out of range"); + (*current_liboctave_error_handler) ("choldelete: index out of range"); else { - Matrix chol_mat1 (n-1, n-1); + OCTAVE_LOCAL_BUFFER (double, w, n); - F77_XFCN (dchdex, DCHDEX, (n, chol_mat.data (), chol_mat1.fortran_vec (), j+1)); + F77_XFCN (dchdex, DCHDEX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, w)); - chol_mat = chol_mat1; + chol_mat.resize (n-1, n-1); } } @@ -271,14 +282,20 @@ CHOL::shift_sym (octave_idx_type i, octave_idx_type j) { octave_idx_type n = chol_mat.rows (); - double dummy; if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("CHOL shift index out of range"); + (*current_liboctave_error_handler) ("cholshift: index out of range"); else - F77_XFCN (dqrshc, DQRSHC, (0, n, n, &dummy, chol_mat.fortran_vec (), i+1, j+1)); + { + OCTAVE_LOCAL_BUFFER (double, w, 2*n); + + F77_XFCN (dchshx, DCHSHX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + i + 1, j + 1, w)); + } } +#endif + Matrix chol2inv (const Matrix& r) {
--- a/liboctave/dbleCHOL.h +++ b/liboctave/dbleCHOL.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,14 +22,13 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #if !defined (octave_CHOL_h) #define octave_CHOL_h 1 #include <iostream> #include "dMatrix.h" +#include "dColVector.h" class OCTAVE_API @@ -64,16 +64,20 @@ void set (const Matrix& R); - void update (const Matrix& u); +#ifdef HAVE_QRUPDATE + + void update (const ColumnVector& u); - octave_idx_type downdate (const Matrix& u); + octave_idx_type downdate (const ColumnVector& u); - octave_idx_type insert_sym (const Matrix& u, octave_idx_type j); + octave_idx_type insert_sym (const ColumnVector& u, octave_idx_type j); void delete_sym (octave_idx_type j); void shift_sym (octave_idx_type i, octave_idx_type j); +#endif + friend OCTAVE_API std::ostream& operator << (std::ostream& os, const CHOL& a); private:
--- a/liboctave/dbleQR.cc +++ b/liboctave/dbleQR.cc @@ -2,7 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton -Copyright (C) 2008 Jaroslav Hajek +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -31,6 +31,7 @@ #include "lo-error.h" #include "Range.h" #include "idx-vector.h" +#include "oct-locbuf.h" extern "C" { @@ -42,33 +43,40 @@ F77_FUNC (dorgqr, DORGQR) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, double*, const octave_idx_type&, double*, double*, const octave_idx_type&, octave_idx_type&); - // these come from qrupdate +#ifdef HAVE_QRUPDATE F77_RET_T F77_FUNC (dqr1up, DQR1UP) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - double*, double*, const double*, const double*); + double*, const octave_idx_type&, double*, const octave_idx_type&, + double*, double*, double*); F77_RET_T F77_FUNC (dqrinc, DQRINC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - double*, const double*, double*, const octave_idx_type&, const double*); + double*, const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, const double*, double*); F77_RET_T F77_FUNC (dqrdec, DQRDEC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - double*, const double*, double*, const octave_idx_type&); + double*, const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, double*); F77_RET_T F77_FUNC (dqrinr, DQRINR) (const octave_idx_type&, const octave_idx_type&, - const double*, double*, const double*, double*, - const octave_idx_type&, const double*); + double*, const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, const double*, double*); F77_RET_T F77_FUNC (dqrder, DQRDER) (const octave_idx_type&, const octave_idx_type&, - const double*, double*, const double*, double *, - const octave_idx_type&); + double*, const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, double*); F77_RET_T F77_FUNC (dqrshc, DQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - double*, double*, const octave_idx_type&, const octave_idx_type&); + double*, const octave_idx_type&, double*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + double*); + +#endif } QR::QR (const Matrix& a, QR::type qr_type) @@ -161,6 +169,26 @@ this->r = r_arg; } +#ifdef HAVE_QRUPDATE + +void +QR::update (const ColumnVector& u, const ColumnVector& v) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + if (u.length () == m && v.length () == n) + { + ColumnVector utmp = u, vtmp = v; + OCTAVE_LOCAL_BUFFER (double, w, 2*k); + F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w)); + } + else + (*current_liboctave_error_handler) ("QR update dimensions mismatch"); +} + void QR::update (const Matrix& u, const Matrix& v) { @@ -168,32 +196,93 @@ octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); - if (u.length () == m && v.length () == n) - F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), r.fortran_vec (), - u.data (), v.data ())); + if (u.rows () == m && v.rows () == n && u.cols () == v.cols ()) + { + OCTAVE_LOCAL_BUFFER (double, w, 2*k); + for (octave_idx_type i = 0; i < u.cols (); i++) + { + ColumnVector utmp = u.column (i), vtmp = v.column (i); + F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w)); + } + } else - (*current_liboctave_error_handler) ("QR update dimensions mismatch"); + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); } void -QR::insert_col (const Matrix& u, octave_idx_type j) +QR::insert_col (const ColumnVector& u, octave_idx_type j) { octave_idx_type m = q.rows (); octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); if (u.length () != m) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - Matrix r1 (m, n+1); + if (k < m) + { + q.resize (m, k+1); + r.resize (k+1, n+1); + } + else + { + r.resize (k, n+1); + } + + ColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, w, k); + F77_XFCN (dqrinc, DQRINC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + utmp.data (), w)); + } +} + +void +QR::insert_col (const Matrix& u, const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); - F77_XFCN (dqrinc, DQRINC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1, u.data ())); + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, ASCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); - r = r1; + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (u.length () != m || u.columns () != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + else if (nj > 0 && (js(0) < 0 || js(nj-1) > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + octave_idx_type kmax = std::min (k + nj, m); + if (k < m) + { + q.resize (m, kmax); + r.resize (kmax, n + nj); + } + else + { + r.resize (k, n + nj); + } + + OCTAVE_LOCAL_BUFFER (double, w, kmax); + for (octave_idx_type i = 0; i < js.length (); i++) + { + ColumnVector utmp = u.column (jsi(i)); + F77_XFCN (dqrinc, DQRINC, (m, n + i, std::min (kmax, k + i), + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, + utmp.data (), w)); + } } } @@ -204,41 +293,87 @@ octave_idx_type k = r.rows (); octave_idx_type n = r.columns (); - if (k < m && k < n) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); - else if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - Matrix r1 (k, n-1); + OCTAVE_LOCAL_BUFFER (double, w, k); + F77_XFCN (dqrdec, DQRDEC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, w)); - F77_XFCN (dqrdec, DQRDEC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1)); - - r = r1; + if (k < m) + { + q.resize (m, k-1); + r.resize (k-1, n-1); + } + else + { + r.resize (k, n-1); + } } } void -QR::insert_row (const Matrix& u, octave_idx_type j) +QR::delete_col (const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, DESCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + OCTAVE_LOCAL_BUFFER (double, w, k); + for (octave_idx_type i = 0; i < js.length (); i++) + { + F77_XFCN (dqrdec, DQRDEC, (m, n - i, k == m ? k : k - i, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, w)); + } + if (k < m) + { + q.resize (m, k - nj); + r.resize (k - nj, n - nj); + } + else + { + r.resize (k, n - nj); + } + + } +} + +void +QR::insert_row (const RowVector& u, octave_idx_type j) { octave_idx_type m = r.rows (); octave_idx_type n = r.columns (); + octave_idx_type k = std::min (m, n); if (! q.is_square () || u.length () != n) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > m) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - Matrix q1 (m+1, m+1); - Matrix r1 (m+1, n); + q.resize (m + 1, m + 1); + r.resize (m + 1, n); + RowVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, w, k); + F77_XFCN (dqrinr, DQRINR, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + j + 1, utmp.fortran_vec (), w)); - F77_XFCN (dqrinr, DQRINR, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1, u.data ())); - - q = q1; - r = r1; } } @@ -249,19 +384,18 @@ octave_idx_type n = r.columns (); if (! q.is_square ()) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); else if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - Matrix q1 (m-1, m-1); - Matrix r1 (m-1, n); + OCTAVE_LOCAL_BUFFER (double, w, 2*m); + F77_XFCN (dqrder, DQRDER, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + w)); - F77_XFCN (dqrder, DQRDER, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1 )); - - q = q1; - r = r1; + q.resize (m - 1, m - 1); + r.resize (m - 1, n); } } @@ -273,23 +407,18 @@ octave_idx_type n = r.columns (); if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR shift index out of range"); + (*current_liboctave_error_handler) ("qrshift: index out of range"); else - F77_XFCN (dqrshc, DQRSHC, (m, n, k, q.fortran_vec (), r.fortran_vec (), i+1, j+1)); -} - -void -QR::economize (void) -{ - octave_idx_type r_nc = r.columns (); - - if (r.rows () > r_nc) { - q.resize (q.rows (), r_nc); - r.resize (r_nc, r_nc); + OCTAVE_LOCAL_BUFFER (double, w, 2*k); + F77_XFCN (dqrshc, DQRSHC, (m, n, k, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + i + 1, j + 1, w)); } } +#endif /* ;;; Local Variables: ***
--- a/liboctave/dbleQR.h +++ b/liboctave/dbleQR.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #if !defined (octave_QR_h) #define octave_QR_h 1 @@ -71,19 +70,27 @@ Matrix R (void) const { return r; } +#ifdef HAVE_QRUPDATE + + void update (const ColumnVector& u, const ColumnVector& v); + void update (const Matrix& u, const Matrix& v); - void insert_col (const Matrix& u, octave_idx_type j); + void insert_col (const ColumnVector& u, octave_idx_type j); + + void insert_col (const Matrix& u, const Array<octave_idx_type>& j); void delete_col (octave_idx_type j); - void insert_row (const Matrix& u, octave_idx_type j); + void delete_col (const Array<octave_idx_type>& j); + + void insert_row (const RowVector& u, octave_idx_type j); void delete_row (octave_idx_type j); void shift_cols (octave_idx_type i, octave_idx_type j); - void economize (void); +#endif friend std::ostream& operator << (std::ostream&, const QR&);
--- a/liboctave/fCmplxCHOL.cc +++ b/liboctave/fCmplxCHOL.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -52,23 +51,30 @@ FloatComplex*, const octave_idx_type&, const float&, float&, FloatComplex*, float*, octave_idx_type& F77_CHAR_ARG_LEN_DECL); +#ifdef HAVE_QRUPDATE + F77_RET_T - F77_FUNC (cch1up, CCH1UP) (const octave_idx_type&, FloatComplex*, FloatComplex*, float*); + F77_FUNC (cch1up, CCH1UP) (const octave_idx_type&, FloatComplex*, const octave_idx_type&, + FloatComplex*, float*); F77_RET_T - F77_FUNC (cch1dn, CCH1DN) (const octave_idx_type&, FloatComplex*, FloatComplex*, float*, + F77_FUNC (cch1dn, CCH1DN) (const octave_idx_type&, FloatComplex*, const octave_idx_type&, + FloatComplex*, float*, octave_idx_type&); + + F77_RET_T + F77_FUNC (cchinx, CCHINX) (const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, FloatComplex*, float*, octave_idx_type&); F77_RET_T - F77_FUNC (cqrshc, CQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - FloatComplex*, FloatComplex*, const octave_idx_type&, const octave_idx_type&); + F77_FUNC (cchdex, CCHDEX) (const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, float*); F77_RET_T - F77_FUNC (cchinx, CCHINX) (const octave_idx_type&, const FloatComplex*, FloatComplex*, const octave_idx_type&, - const FloatComplex*, octave_idx_type&); - - F77_RET_T - F77_FUNC (cchdex, CCHDEX) (const octave_idx_type&, const FloatComplex*, FloatComplex*, const octave_idx_type&); + F77_FUNC (cchshx, CCHSHX) (const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + FloatComplex*, float*); +#endif } octave_idx_type @@ -182,26 +188,28 @@ (*current_liboctave_error_handler) ("CHOL requires square matrix"); } +#ifdef HAVE_QRUPDATE + void -FloatComplexCHOL::update (const FloatComplexMatrix& u) +FloatComplexCHOL::update (const FloatComplexColumnVector& u) { octave_idx_type n = chol_mat.rows (); if (u.length () == n) { - FloatComplexMatrix tmp = u; + FloatComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, w, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cch1up, CCH1UP, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w)); + F77_XFCN (cch1up, CCH1UP, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), rw)); } else - (*current_liboctave_error_handler) ("CHOL update dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); } octave_idx_type -FloatComplexCHOL::downdate (const FloatComplexMatrix& u) +FloatComplexCHOL::downdate (const FloatComplexColumnVector& u) { octave_idx_type info = -1; @@ -209,38 +217,40 @@ if (u.length () == n) { - FloatComplexMatrix tmp = u; + FloatComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, w, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cch1dn, CCH1DN, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w, info)); + F77_XFCN (cch1dn, CCH1DN, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), rw, info)); } else - (*current_liboctave_error_handler) ("CHOL downdate dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); return info; } octave_idx_type -FloatComplexCHOL::insert_sym (const FloatComplexMatrix& u, octave_idx_type j) +FloatComplexCHOL::insert_sym (const FloatComplexColumnVector& u, octave_idx_type j) { octave_idx_type info = -1; octave_idx_type n = chol_mat.rows (); - if (u.length () != n+1) - (*current_liboctave_error_handler) ("CHOL insert dimension mismatch"); + if (u.length () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("CHOL insert index out of range"); + (*current_liboctave_error_handler) ("cholinsert: index out of range"); else { - FloatComplexMatrix chol_mat1 (n+1, n+1); + FloatComplexColumnVector utmp = u; + + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cchinx, CCHINX, (n, chol_mat.data (), chol_mat1.fortran_vec (), - j+1, u.data (), info)); + chol_mat.resize (n+1, n+1); - chol_mat = chol_mat1; + F77_XFCN (cchinx, CCHINX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, utmp.fortran_vec (), rw, info)); } return info; @@ -252,14 +262,15 @@ octave_idx_type n = chol_mat.rows (); if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("CHOL delete index out of range"); + (*current_liboctave_error_handler) ("choldelete: index out of range"); else { - FloatComplexMatrix chol_mat1 (n-1, n-1); + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cchdex, CCHDEX, (n, chol_mat.data (), chol_mat1.fortran_vec (), j+1)); + F77_XFCN (cchdex, CCHDEX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, rw)); - chol_mat = chol_mat1; + chol_mat.resize (n-1, n-1); } } @@ -267,14 +278,21 @@ FloatComplexCHOL::shift_sym (octave_idx_type i, octave_idx_type j) { octave_idx_type n = chol_mat.rows (); - FloatComplex dummy; if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("CHOL shift index out of range"); + (*current_liboctave_error_handler) ("cholshift: index out of range"); else - F77_XFCN (cqrshc, CQRSHC, (0, n, n, &dummy, chol_mat.fortran_vec (), i+1, j+1)); + { + OCTAVE_LOCAL_BUFFER (FloatComplex, w, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); + + F77_XFCN (cchshx, CCHSHX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + i + 1, j + 1, w, rw)); + } } +#endif + FloatComplexMatrix chol2inv (const FloatComplexMatrix& r) {
--- a/liboctave/fCmplxCHOL.h +++ b/liboctave/fCmplxCHOL.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,14 +22,13 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #if !defined (octave_FloatComplexCHOL_h) #define octave_FloatComplexCHOL_h 1 #include <iostream> #include "fCMatrix.h" +#include "fCColVector.h" class OCTAVE_API @@ -67,16 +67,20 @@ void set (const FloatComplexMatrix& R); - void update (const FloatComplexMatrix& u); +#ifdef HAVE_QRUPDATE + + void update (const FloatComplexColumnVector& u); - octave_idx_type downdate (const FloatComplexMatrix& u); + octave_idx_type downdate (const FloatComplexColumnVector& u); - octave_idx_type insert_sym (const FloatComplexMatrix& u, octave_idx_type j); + octave_idx_type insert_sym (const FloatComplexColumnVector& u, octave_idx_type j); void delete_sym (octave_idx_type j); void shift_sym (octave_idx_type i, octave_idx_type j); +#endif + friend OCTAVE_API std::ostream& operator << (std::ostream& os, const FloatComplexCHOL& a); private:
--- a/liboctave/fCmplxQR.cc +++ b/liboctave/fCmplxQR.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -32,6 +31,7 @@ #include "lo-error.h" #include "Range.h" #include "idx-vector.h" +#include "oct-locbuf.h" extern "C" { @@ -45,33 +45,40 @@ FloatComplex*, const octave_idx_type&, FloatComplex*, FloatComplex*, const octave_idx_type&, octave_idx_type&); - // these come from qrupdate +#ifdef HAVE_QRUPDATE F77_RET_T F77_FUNC (cqr1up, CQR1UP) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - FloatComplex*, FloatComplex*, const FloatComplex*, const FloatComplex*); + FloatComplex*, const octave_idx_type&, FloatComplex*, const octave_idx_type&, + FloatComplex*, FloatComplex*, FloatComplex*, float*); F77_RET_T F77_FUNC (cqrinc, CQRINC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - FloatComplex*, const FloatComplex*, FloatComplex*, const octave_idx_type&, const FloatComplex*); + FloatComplex*, const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, const FloatComplex*, float*); F77_RET_T F77_FUNC (cqrdec, CQRDEC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - FloatComplex*, const FloatComplex*, FloatComplex*, const octave_idx_type&); + FloatComplex*, const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, float*); F77_RET_T F77_FUNC (cqrinr, CQRINR) (const octave_idx_type&, const octave_idx_type&, - const FloatComplex*, FloatComplex*, const FloatComplex*, FloatComplex*, - const octave_idx_type&, const FloatComplex*); + FloatComplex*, const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, const FloatComplex*, float*); F77_RET_T F77_FUNC (cqrder, CQRDER) (const octave_idx_type&, const octave_idx_type&, - const FloatComplex*, FloatComplex*, const FloatComplex*, FloatComplex *, - const octave_idx_type&); + FloatComplex*, const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, FloatComplex*, float*); F77_RET_T F77_FUNC (cqrshc, CQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - FloatComplex*, FloatComplex*, const octave_idx_type&, const octave_idx_type&); + FloatComplex*, const octave_idx_type&, FloatComplex*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + FloatComplex*, float*); + +#endif } FloatComplexQR::FloatComplexQR (const FloatComplexMatrix& a, QR::type qr_type) @@ -171,6 +178,27 @@ this->r = r_arg; } +#ifdef HAVE_QRUPDATE + +void +FloatComplexQR::update (const FloatComplexColumnVector& u, const FloatComplexColumnVector& v) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + if (u.length () == m && v.length () == n) + { + FloatComplexColumnVector utmp = u, vtmp = v; + OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqr1up, CQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w, rw)); + } + else + (*current_liboctave_error_handler) ("QR update dimensions mismatch"); +} + void FloatComplexQR::update (const FloatComplexMatrix& u, const FloatComplexMatrix& v) { @@ -178,32 +206,93 @@ octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); - if (u.length () == m && v.length () == n) - F77_XFCN (cqr1up, CQR1UP, (m, n, k, q.fortran_vec (), r.fortran_vec (), - u.data (), v.data ())); + if (u.rows () == m && v.rows () == n && u.cols () == v.cols ()) + { + OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); + OCTAVE_LOCAL_BUFFER (float, rw, k); + for (octave_idx_type i = 0; i < u.cols (); i++) + { + FloatComplexColumnVector utmp = u.column (i), vtmp = v.column (i); + F77_XFCN (cqr1up, CQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w, rw)); + } + } else - (*current_liboctave_error_handler) ("QR update dimensions mismatch"); + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); } void -FloatComplexQR::insert_col (const FloatComplexMatrix& u, octave_idx_type j) +FloatComplexQR::insert_col (const FloatComplexColumnVector& u, octave_idx_type j) { octave_idx_type m = q.rows (); octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); if (u.length () != m) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - FloatComplexMatrix r1 (m,n+1); + if (k < m) + { + q.resize (m, k+1); + r.resize (k+1, n+1); + } + else + { + r.resize (k, n+1); + } + + FloatComplexColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrinc, CQRINC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + utmp.data (), rw)); + } +} + +void +FloatComplexQR::insert_col (const FloatComplexMatrix& u, const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); - F77_XFCN (cqrinc, CQRINC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1, u.data ())); + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, ASCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); - r = r1; + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (u.length () != m || u.columns () != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + else if (nj > 0 && (js(0) < 0 || js(nj-1) > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + octave_idx_type kmax = std::min (k + nj, m); + if (k < m) + { + q.resize (m, kmax); + r.resize (kmax, n + nj); + } + else + { + r.resize (k, n + nj); + } + + OCTAVE_LOCAL_BUFFER (float, rw, kmax); + for (octave_idx_type i = 0; i < js.length (); i++) + { + F77_XFCN (cqrinc, CQRINC, (m, n + i, std::min (kmax, k + i), + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, + u.column (jsi(i)).data (), rw)); + } } } @@ -214,41 +303,87 @@ octave_idx_type k = r.rows (); octave_idx_type n = r.columns (); - if (k < m && k < n) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); - else if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - FloatComplexMatrix r1 (k, n-1); + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrdec, CQRDEC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, rw)); - F77_XFCN (cqrdec, CQRDEC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1)); - - r = r1; + if (k < m) + { + q.resize (m, k-1); + r.resize (k-1, n-1); + } + else + { + r.resize (k, n-1); + } } } void -FloatComplexQR::insert_row (const FloatComplexMatrix& u, octave_idx_type j) +FloatComplexQR::delete_col (const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, DESCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + OCTAVE_LOCAL_BUFFER (float, rw, k); + for (octave_idx_type i = 0; i < js.length (); i++) + { + F77_XFCN (cqrdec, CQRDEC, (m, n - i, k == m ? k : k - i, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, rw)); + } + if (k < m) + { + q.resize (m, k - nj); + r.resize (k - nj, n - nj); + } + else + { + r.resize (k, n - nj); + } + + } +} + +void +FloatComplexQR::insert_row (const FloatComplexRowVector& u, octave_idx_type j) { octave_idx_type m = r.rows (); octave_idx_type n = r.columns (); + octave_idx_type k = std::min (m, n); if (! q.is_square () || u.length () != n) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > m) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - FloatComplexMatrix q1 (m+1, m+1); - FloatComplexMatrix r1 (m+1, n); + q.resize (m + 1, m + 1); + r.resize (m + 1, n); + FloatComplexRowVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrinr, CQRINR, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + j + 1, utmp.fortran_vec (), rw)); - F77_XFCN (cqrinr, CQRINR, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1, u.data ())); - - q = q1; - r = r1; } } @@ -259,19 +394,19 @@ octave_idx_type n = r.columns (); if (! q.is_square ()) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); else if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - FloatComplexMatrix q1 (m-1, m-1); - FloatComplexMatrix r1 (m-1, n); + OCTAVE_LOCAL_BUFFER (FloatComplex, w, m); + OCTAVE_LOCAL_BUFFER (float, rw, m); + F77_XFCN (cqrder, CQRDER, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + w, rw)); - F77_XFCN (cqrder, CQRDER, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1 )); - - q = q1; - r = r1; + q.resize (m - 1, m - 1); + r.resize (m - 1, n); } } @@ -283,22 +418,19 @@ octave_idx_type n = r.columns (); if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR shift index out of range"); + (*current_liboctave_error_handler) ("qrshift: index out of range"); else - F77_XFCN (cqrshc, CQRSHC, (m, n, k, q.fortran_vec (), r.fortran_vec (), i+1, j+1)); + { + OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrshc, CQRSHC, (m, n, k, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + i + 1, j + 1, w, rw)); + } } -void -FloatComplexQR::economize (void) -{ - octave_idx_type r_nc = r.columns (); - - if (r.rows () > r_nc) - { - q.resize (q.rows (), r_nc); - r.resize (r_nc, r_nc); - } -} +#endif /* ;;; Local Variables: ***
--- a/liboctave/fCmplxQR.h +++ b/liboctave/fCmplxQR.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -65,19 +66,27 @@ FloatComplexMatrix R (void) const { return r; } +#ifdef HAVE_QRUPDATE + + void update (const FloatComplexColumnVector& u, const FloatComplexColumnVector& v); + void update (const FloatComplexMatrix& u, const FloatComplexMatrix& v); - void insert_col (const FloatComplexMatrix& u, octave_idx_type j); + void insert_col (const FloatComplexColumnVector& u, octave_idx_type j); + + void insert_col (const FloatComplexMatrix& u, const Array<octave_idx_type>& j); void delete_col (octave_idx_type j); - void insert_row (const FloatComplexMatrix& u, octave_idx_type j); + void delete_col (const Array<octave_idx_type>& j); + + void insert_row (const FloatComplexRowVector& u, octave_idx_type j); void delete_row (octave_idx_type j); void shift_cols (octave_idx_type i, octave_idx_type j); - void economize(); +#endif friend std::ostream& operator << (std::ostream&, const FloatComplexQR&);
--- a/liboctave/floatCHOL.cc +++ b/liboctave/floatCHOL.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -52,23 +51,30 @@ float*, const octave_idx_type&, const float&, float&, float*, octave_idx_type*, octave_idx_type& F77_CHAR_ARG_LEN_DECL); +#ifdef HAVE_QRUPDATE + F77_RET_T - F77_FUNC (sch1up, SCH1UP) (const octave_idx_type&, float*, float*, float*); + F77_FUNC (sch1up, SCH1UP) (const octave_idx_type&, float*, const octave_idx_type&, + float*, float*); F77_RET_T - F77_FUNC (sch1dn, SCH1DN) (const octave_idx_type&, float*, float*, float*, + F77_FUNC (sch1dn, SCH1DN) (const octave_idx_type&, float*, const octave_idx_type&, + float*, float*, octave_idx_type&); + + F77_RET_T + F77_FUNC (schinx, SCHINX) (const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, float*, float*, octave_idx_type&); F77_RET_T - F77_FUNC (sqrshc, SQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - float*, float*, const octave_idx_type&, const octave_idx_type&); + F77_FUNC (schdex, SCHDEX) (const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, float*); F77_RET_T - F77_FUNC (schinx, SCHINX) (const octave_idx_type&, const float*, float*, const octave_idx_type&, - const float*, octave_idx_type&); - - F77_RET_T - F77_FUNC (schdex, SCHDEX) (const octave_idx_type&, const float*, float*, const octave_idx_type&); + F77_FUNC (schshx, SCHSHX) (const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + float*); +#endif } octave_idx_type @@ -186,26 +192,28 @@ (*current_liboctave_error_handler) ("FloatCHOL requires square matrix"); } +#ifdef HAVE_QRUPDATE + void -FloatCHOL::update (const FloatMatrix& u) +FloatCHOL::update (const FloatColumnVector& u) { octave_idx_type n = chol_mat.rows (); if (u.length () == n) { - FloatMatrix tmp = u; + FloatColumnVector utmp = u; OCTAVE_LOCAL_BUFFER (float, w, n); - F77_XFCN (sch1up, SCH1UP, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w)); + F77_XFCN (sch1up, SCH1UP, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), w)); } else - (*current_liboctave_error_handler) ("FloatCHOL update dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); } octave_idx_type -FloatCHOL::downdate (const FloatMatrix& u) +FloatCHOL::downdate (const FloatColumnVector& u) { octave_idx_type info = -1; @@ -213,38 +221,40 @@ if (u.length () == n) { - FloatMatrix tmp = u; + FloatColumnVector utmp = u; OCTAVE_LOCAL_BUFFER (float, w, n); - F77_XFCN (sch1dn, SCH1DN, (n, chol_mat.fortran_vec (), - tmp.fortran_vec (), w, info)); + F77_XFCN (sch1dn, SCH1DN, (n, chol_mat.fortran_vec (), chol_mat.rows (), + utmp.fortran_vec (), w, info)); } else - (*current_liboctave_error_handler) ("FloatCHOL downdate dimension mismatch"); + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); return info; } octave_idx_type -FloatCHOL::insert_sym (const FloatMatrix& u, octave_idx_type j) +FloatCHOL::insert_sym (const FloatColumnVector& u, octave_idx_type j) { octave_idx_type info = -1; octave_idx_type n = chol_mat.rows (); - if (u.length () != n+1) - (*current_liboctave_error_handler) ("FloatCHOL insert dimension mismatch"); + if (u.length () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("FloatCHOL insert index out of range"); + (*current_liboctave_error_handler) ("cholinsert: index out of range"); else { - FloatMatrix chol_mat1 (n+1, n+1); + FloatColumnVector utmp = u; + + OCTAVE_LOCAL_BUFFER (float, w, n); - F77_XFCN (schinx, SCHINX, (n, chol_mat.data (), chol_mat1.fortran_vec (), - j+1, u.data (), info)); + chol_mat.resize (n+1, n+1); - chol_mat = chol_mat1; + F77_XFCN (schinx, SCHINX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, utmp.fortran_vec (), w, info)); } return info; @@ -256,14 +266,15 @@ octave_idx_type n = chol_mat.rows (); if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("FloatCHOL delete index out of range"); + (*current_liboctave_error_handler) ("choldelete: index out of range"); else { - FloatMatrix chol_mat1 (n-1, n-1); + OCTAVE_LOCAL_BUFFER (float, w, n); - F77_XFCN (schdex, SCHDEX, (n, chol_mat.data (), chol_mat1.fortran_vec (), j+1)); + F77_XFCN (schdex, SCHDEX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + j + 1, w)); - chol_mat = chol_mat1; + chol_mat.resize (n-1, n-1); } } @@ -271,14 +282,20 @@ FloatCHOL::shift_sym (octave_idx_type i, octave_idx_type j) { octave_idx_type n = chol_mat.rows (); - float dummy; if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("FloatCHOL shift index out of range"); + (*current_liboctave_error_handler) ("cholshift: index out of range"); else - F77_XFCN (sqrshc, SQRSHC, (0, n, n, &dummy, chol_mat.fortran_vec (), i+1, j+1)); + { + OCTAVE_LOCAL_BUFFER (float, w, 2*n); + + F77_XFCN (schshx, SCHSHX, (n, chol_mat.fortran_vec (), chol_mat.rows (), + i + 1, j + 1, w)); + } } +#endif + FloatMatrix chol2inv (const FloatMatrix& r) {
--- a/liboctave/floatCHOL.h +++ b/liboctave/floatCHOL.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,14 +22,13 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #if !defined (octave_FloatCHOL_h) #define octave_FloatCHOL_h 1 #include <iostream> #include "fMatrix.h" +#include "fColVector.h" class OCTAVE_API @@ -64,16 +64,20 @@ void set (const FloatMatrix& R); - void update (const FloatMatrix& u); +#ifdef HAVE_QRUPDATE + + void update (const FloatColumnVector& u); - octave_idx_type downdate (const FloatMatrix& u); + octave_idx_type downdate (const FloatColumnVector& u); - octave_idx_type insert_sym (const FloatMatrix& u, octave_idx_type j); + octave_idx_type insert_sym (const FloatColumnVector& u, octave_idx_type j); void delete_sym (octave_idx_type j); void shift_sym (octave_idx_type i, octave_idx_type j); +#endif + friend OCTAVE_API std::ostream& operator << (std::ostream& os, const FloatCHOL& a); private:
--- a/liboctave/floatQR.cc +++ b/liboctave/floatQR.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -30,6 +31,7 @@ #include "lo-error.h" #include "Range.h" #include "idx-vector.h" +#include "oct-locbuf.h" extern "C" { @@ -41,33 +43,40 @@ F77_FUNC (sorgqr, SORGQR) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, float*, const octave_idx_type&, float*, float*, const octave_idx_type&, octave_idx_type&); - // these come from qrupdate +#ifdef HAVE_QRUPDATE F77_RET_T F77_FUNC (sqr1up, SQR1UP) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - float*, float*, const float*, const float*); + float*, const octave_idx_type&, float*, const octave_idx_type&, + float*, float*, float*); F77_RET_T F77_FUNC (sqrinc, SQRINC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - float*, const float*, float*, const octave_idx_type&, const float*); + float*, const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, const float*, float*); F77_RET_T F77_FUNC (sqrdec, SQRDEC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - float*, const float*, float*, const octave_idx_type&); + float*, const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, float*); F77_RET_T F77_FUNC (sqrinr, SQRINR) (const octave_idx_type&, const octave_idx_type&, - const float*, float*, const float*, float*, - const octave_idx_type&, const float*); + float*, const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, const float*, float*); F77_RET_T F77_FUNC (sqrder, SQRDER) (const octave_idx_type&, const octave_idx_type&, - const float*, float*, const float*, float *, - const octave_idx_type&); + float*, const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, float*); F77_RET_T F77_FUNC (sqrshc, SQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, - float*, float*, const octave_idx_type&, const octave_idx_type&); + float*, const octave_idx_type&, float*, const octave_idx_type&, + const octave_idx_type&, const octave_idx_type&, + float*); + +#endif } FloatQR::FloatQR (const FloatMatrix& a, QR::type qr_type) @@ -160,6 +169,26 @@ this->r = r_arg; } +#ifdef HAVE_QRUPDATE + +void +FloatQR::update (const FloatColumnVector& u, const FloatColumnVector& v) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + if (u.length () == m && v.length () == n) + { + FloatColumnVector utmp = u, vtmp = v; + OCTAVE_LOCAL_BUFFER (float, w, 2*k); + F77_XFCN (sqr1up, SQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w)); + } + else + (*current_liboctave_error_handler) ("QR update dimensions mismatch"); +} + void FloatQR::update (const FloatMatrix& u, const FloatMatrix& v) { @@ -167,32 +196,93 @@ octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); - if (u.length () == m && v.length () == n) - F77_XFCN (sqr1up, SQR1UP, (m, n, k, q.fortran_vec (), r.fortran_vec (), - u.data (), v.data ())); + if (u.rows () == m && v.rows () == n && u.cols () == v.cols ()) + { + OCTAVE_LOCAL_BUFFER (float, w, 2*k); + for (octave_idx_type i = 0; i < u.cols (); i++) + { + FloatColumnVector utmp = u.column (i), vtmp = v.column (i); + F77_XFCN (sqr1up, SQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec (), w)); + } + } else - (*current_liboctave_error_handler) ("QR update dimensions mismatch"); + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); } void -FloatQR::insert_col (const FloatMatrix& u, octave_idx_type j) +FloatQR::insert_col (const FloatColumnVector& u, octave_idx_type j) { octave_idx_type m = q.rows (); octave_idx_type n = r.columns (); octave_idx_type k = q.columns (); if (u.length () != m) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > n) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - FloatMatrix r1 (m, n+1); + if (k < m) + { + q.resize (m, k+1); + r.resize (k+1, n+1); + } + else + { + r.resize (k, n+1); + } + + FloatColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, w, k); + F77_XFCN (sqrinc, SQRINC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + utmp.data (), w)); + } +} + +void +FloatQR::insert_col (const FloatMatrix& u, const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); - F77_XFCN (sqrinc, SQRINC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1, u.data ())); + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, ASCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); - r = r1; + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (u.length () != m || u.columns () != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + else if (nj > 0 && (js(0) < 0 || js(nj-1) > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + octave_idx_type kmax = std::min (k + nj, m); + if (k < m) + { + q.resize (m, kmax); + r.resize (kmax, n + nj); + } + else + { + r.resize (k, n + nj); + } + + OCTAVE_LOCAL_BUFFER (float, w, kmax); + for (octave_idx_type i = 0; i < js.length (); i++) + { + FloatColumnVector utmp = u.column (jsi(i)); + F77_XFCN (sqrinc, SQRINC, (m, n + i, std::min (kmax, k + i), + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, + utmp.data (), w)); + } } } @@ -203,41 +293,87 @@ octave_idx_type k = r.rows (); octave_idx_type n = r.columns (); - if (k < m && k < n) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); - else if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - FloatMatrix r1 (k, n-1); + OCTAVE_LOCAL_BUFFER (float, w, k); + F77_XFCN (sqrdec, SQRDEC, (m, n, k, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, w)); - F77_XFCN (sqrdec, SQRDEC, (m, n, k, q.fortran_vec (), r.data (), - r1.fortran_vec (), j+1)); - - r = r1; + if (k < m) + { + q.resize (m, k-1); + r.resize (k-1, n-1); + } + else + { + r.resize (k, n-1); + } } } void -FloatQR::insert_row (const FloatMatrix& u, octave_idx_type j) +FloatQR::delete_col (const Array<octave_idx_type>& j) +{ + octave_idx_type m = q.rows (); + octave_idx_type n = r.columns (); + octave_idx_type k = q.columns (); + + Array<octave_idx_type> jsi; + Array<octave_idx_type> js = j.sort (jsi, DESCENDING); + octave_idx_type nj = js.length (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + else if (nj > 0) + { + OCTAVE_LOCAL_BUFFER (float, w, k); + for (octave_idx_type i = 0; i < js.length (); i++) + { + F77_XFCN (sqrdec, SQRDEC, (m, n - i, k == m ? k : k - i, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), js(i) + 1, w)); + } + if (k < m) + { + q.resize (m, k - nj); + r.resize (k - nj, n - nj); + } + else + { + r.resize (k, n - nj); + } + + } +} + +void +FloatQR::insert_row (const FloatRowVector& u, octave_idx_type j) { octave_idx_type m = r.rows (); octave_idx_type n = r.columns (); + octave_idx_type k = std::min (m, n); if (! q.is_square () || u.length () != n) - (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); else if (j < 0 || j > m) - (*current_liboctave_error_handler) ("QR insert index out of range"); + (*current_liboctave_error_handler) ("qrinsert: index out of range"); else { - FloatMatrix q1 (m+1, m+1); - FloatMatrix r1 (m+1, n); + q.resize (m + 1, m + 1); + r.resize (m + 1, n); + FloatRowVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, w, k); + F77_XFCN (sqrinr, SQRINR, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + j + 1, utmp.fortran_vec (), w)); - F77_XFCN (sqrinr, SQRINR, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1, u.data ())); - - q = q1; - r = r1; } } @@ -248,19 +384,18 @@ octave_idx_type n = r.columns (); if (! q.is_square ()) - (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); else if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("QR delete index out of range"); + (*current_liboctave_error_handler) ("qrdelete: index out of range"); else { - FloatMatrix q1 (m-1, m-1); - FloatMatrix r1 (m-1, n); + OCTAVE_LOCAL_BUFFER (float, w, 2*m); + F77_XFCN (sqrder, SQRDER, (m, n, q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), j + 1, + w)); - F77_XFCN (sqrder, SQRDER, (m, n, q.data (), q1.fortran_vec (), - r.data (), r1.fortran_vec (), j+1 )); - - q = q1; - r = r1; + q.resize (m - 1, m - 1); + r.resize (m - 1, n); } } @@ -272,22 +407,18 @@ octave_idx_type n = r.columns (); if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("QR shift index out of range"); + (*current_liboctave_error_handler) ("qrshift: index out of range"); else - F77_XFCN (sqrshc, SQRSHC, (m, n, k, q.fortran_vec (), r.fortran_vec (), i+1, j+1)); + { + OCTAVE_LOCAL_BUFFER (float, w, 2*k); + F77_XFCN (sqrshc, SQRSHC, (m, n, k, + q.fortran_vec (), q.rows (), + r.fortran_vec (), r.rows (), + i + 1, j + 1, w)); + } } -void -FloatQR::economize (void) -{ - octave_idx_type r_nc = r.columns (); - - if (r.rows () > r_nc) - { - q.resize (q.rows (), r_nc); - r.resize (r_nc, r_nc); - } -} +#endif /*
--- a/liboctave/floatQR.h +++ b/liboctave/floatQR.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek This file is part of Octave. @@ -21,8 +22,6 @@ */ -// updating/downdating by Jaroslav Hajek 2008 - #if !defined (octave_FloatQR_h) #define octave_FloatQR_h 1 @@ -65,19 +64,27 @@ FloatMatrix R (void) const { return r; } +#ifdef HAVE_QRUPDATE + + void update (const FloatColumnVector& u, const FloatColumnVector& v); + void update (const FloatMatrix& u, const FloatMatrix& v); - void insert_col (const FloatMatrix& u, octave_idx_type j); + void insert_col (const FloatColumnVector& u, octave_idx_type j); + + void insert_col (const FloatMatrix& u, const Array<octave_idx_type>& j); void delete_col (octave_idx_type j); - void insert_row (const FloatMatrix& u, octave_idx_type j); + void delete_col (const Array<octave_idx_type>& j); + + void insert_row (const FloatRowVector& u, octave_idx_type j); void delete_row (octave_idx_type j); void shift_cols (octave_idx_type i, octave_idx_type j); - void economize (void); +#endif friend std::ostream& operator << (std::ostream&, const FloatQR&);
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2009-01-17 Jaroslav Hajek <highegg@gmail.com> + + * DLD-FUNCTIONS/qr.cc (Fqrupdate, Fqrinsert, Fqrdelete, Fqrshift): + Reflect changes in liboctave. + * DLD-FUNCTIONS/chol.cc (Fcholupdate, Fcholinsert): + Reflect changes in liboctave. + 2009-01-19 Jaroslav Hajek <highegg@gmail.com> * ov.h (octave_value::make_unique (int)): New method.
--- a/src/DLD-FUNCTIONS/chol.cc +++ b/src/DLD-FUNCTIONS/chol.cc @@ -2,6 +2,8 @@ Copyright (C) 1996, 1997, 1999, 2000, 2002, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek +Copyright (C) 2008, 2009 VZLU Prague This file is part of Octave. @@ -21,9 +23,6 @@ */ -// The cholupdate, cholinsert, choldelete and cholshift functions were -// written by Jaroslav Hajek <highegg@gmail.com>, Copyright (C) 2008 -// VZLU Prague, a.s., Czech Republic. #ifdef HAVE_CONFIG_H #include <config.h> @@ -577,6 +576,8 @@ return retval; } +#ifdef HAVE_QRUPDATE + DEFUN_DLD (cholupdate, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {[@var{R1}, @var{info}] =} cholupdate (@var{R}, @var{u}, @var{op})\n\ @@ -628,100 +629,84 @@ if (down || op == "+") if (argr.columns () == n && argu.rows () == n && argu.columns () == 1) { + int err = 0; if (argr.is_single_type () || argu.is_single_type ()) { - if (argr.is_real_matrix () && argu.is_real_matrix ()) + if (argr.is_real_type () && argu.is_real_type ()) { // real case FloatMatrix R = argr.float_matrix_value (); - FloatMatrix u = argu.float_matrix_value (); + FloatColumnVector u = argu.float_column_vector_value (); FloatCHOL fact; fact.set (R); - int err = 0; if (down) err = fact.downdate (u); else fact.update (u); - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholupdate: downdate violates positiveness"); - retval(0) = fact.chol_matrix (); } else { // complex case FloatComplexMatrix R = argr.float_complex_matrix_value (); - FloatComplexMatrix u = argu.float_complex_matrix_value (); + FloatComplexColumnVector u = argu.float_complex_column_vector_value (); FloatComplexCHOL fact; fact.set (R); - int err = 0; if (down) err = fact.downdate (u); else fact.update (u); - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholupdate: downdate violates positiveness"); - retval(0) = fact.chol_matrix (); } } else { - if (argr.is_real_matrix () && argu.is_real_matrix ()) + if (argr.is_real_type () && argu.is_real_type ()) { // real case Matrix R = argr.matrix_value (); - Matrix u = argu.matrix_value (); + ColumnVector u = argu.column_vector_value (); CHOL fact; fact.set (R); - int err = 0; if (down) err = fact.downdate (u); else fact.update (u); - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholupdate: downdate violates positiveness"); - retval(0) = fact.chol_matrix (); } else { // complex case ComplexMatrix R = argr.complex_matrix_value (); - ComplexMatrix u = argu.complex_matrix_value (); + ComplexColumnVector u = argu.complex_column_vector_value (); ComplexCHOL fact; fact.set (R); - int err = 0; if (down) err = fact.downdate (u); else fact.update (u); - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholupdate: downdate violates positiveness"); - retval(0) = fact.chol_matrix (); } } + + if (nargout > 1) + retval(1) = err; + else if (err == 1) + error ("cholupdate: downdate violates positiveness"); + else if (err == 2) + error ("cholupdate: singular matrix"); } else error ("cholupdate: dimension mismatch"); @@ -853,22 +838,18 @@ { if (j > 0 && j <= n+1) { + int err = 0; if (argr.is_single_type () || argu.is_single_type ()) { - if (argr.is_real_matrix () && argu.is_real_matrix ()) + if (argr.is_real_type () && argu.is_real_type ()) { // real case FloatMatrix R = argr.float_matrix_value (); - FloatMatrix u = argu.float_matrix_value (); + FloatColumnVector u = argu.float_column_vector_value (); FloatCHOL fact; fact.set (R); - int err = fact.insert_sym (u, j-1); - - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholinsert: insertion violates positiveness"); + err = fact.insert_sym (u, j-1); retval(0) = fact.chol_matrix (); } @@ -876,36 +857,26 @@ { // complex case FloatComplexMatrix R = argr.float_complex_matrix_value (); - FloatComplexMatrix u = argu.float_complex_matrix_value (); + FloatComplexColumnVector u = argu.float_complex_column_vector_value (); FloatComplexCHOL fact; fact.set (R); - int err = fact.insert_sym (u, j-1); - - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholinsert: insertion violates positiveness"); + err = fact.insert_sym (u, j-1); retval(0) = fact.chol_matrix (); } } else { - if (argr.is_real_matrix () && argu.is_real_matrix ()) + if (argr.is_real_type () && argu.is_real_type ()) { // real case Matrix R = argr.matrix_value (); - Matrix u = argu.matrix_value (); + ColumnVector u = argu.column_vector_value (); CHOL fact; fact.set (R); - int err = fact.insert_sym (u, j-1); - - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholinsert: insertion violates positiveness"); + err = fact.insert_sym (u, j-1); retval(0) = fact.chol_matrix (); } @@ -913,20 +884,24 @@ { // complex case ComplexMatrix R = argr.complex_matrix_value (); - ComplexMatrix u = argu.complex_matrix_value (); + ComplexColumnVector u = argu.complex_column_vector_value (); ComplexCHOL fact; fact.set (R); - int err = fact.insert_sym (u, j-1); - - if (nargout > 1) - retval(1) = err; - else if (err) - error ("cholinsert: insertion violates positiveness"); + err = fact.insert_sym (u, j-1); retval(0) = fact.chol_matrix (); } } + + if (nargout > 1) + retval(1) = err; + else if (err == 1) + error ("cholinsert: insertion violates positiveness"); + else if (err == 2) + error ("cholinsert: singular matrix"); + else if (err == 3) + error ("cholinsert: diagonal element must be real"); } else error ("cholinsert: index out of range"); @@ -1037,7 +1012,7 @@ { if (argr.is_single_type ()) { - if (argr.is_real_matrix ()) + if (argr.is_real_type ()) { // real case FloatMatrix R = argr.float_matrix_value (); @@ -1062,7 +1037,7 @@ } else { - if (argr.is_real_matrix ()) + if (argr.is_real_type ()) { // real case Matrix R = argr.matrix_value (); @@ -1178,7 +1153,7 @@ if (argr.is_single_type () && argi.is_single_type () && argj.is_single_type ()) { - if (argr.is_real_matrix ()) + if (argr.is_real_type ()) { // real case FloatMatrix R = argr.float_matrix_value (); @@ -1203,7 +1178,7 @@ } else { - if (argr.is_real_matrix ()) + if (argr.is_real_type ()) { // real case Matrix R = argr.matrix_value (); @@ -1301,6 +1276,8 @@ %! assert(norm(R1'*R1 - single(Ac(p,p)),Inf) < 1e1*eps('single')) */ +#endif + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/DLD-FUNCTIONS/qr.cc +++ b/src/DLD-FUNCTIONS/qr.cc @@ -1,6 +1,8 @@ /* Copyright (C) 1996, 1997, 1999, 2000, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008, 2009 Jaroslav Hajek +Copyright (C) 2008, 2009 VZLU Prague This file is part of Octave. @@ -20,10 +22,6 @@ */ -// The qrupdate, qrinsert, qrdelete and qrshift functions were written by -// Jaroslav Hajek <highegg@gmail.com>, Copyright (C) 2008 VZLU -// Prague, a.s., Czech Republic. - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -741,6 +739,24 @@ */ +#ifdef HAVE_QRUPDATE + +static +bool check_qr_dims (const octave_value& q, const octave_value& r, + bool allow_ecf = false) +{ + octave_idx_type m = q.rows (), k = r.rows (), n = r.columns (); + return ((q.ndims () == 2 || r.ndims () == 2 && k == q.columns ()) + && (m == k || (allow_ecf && k == n && k < m))); +} + +static +bool check_index (const octave_value& i, bool vector_allowed = false) +{ + return ((i.is_real_type () || i.is_integer_type ()) + && (i.is_scalar_type () || vector_allowed)); +} + DEFUN_DLD (qrupdate, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {[@var{Q1}, @var{R1}] =} qrupdate (@var{Q}, @var{R}, @var{u}, @var{v})\n\ @@ -748,10 +764,14 @@ @w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and\n\ @var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization\n\ of @w{@var{A} + @var{u}*@var{v}'}, where @var{u} and @var{v} are\n\ -column vectors (rank-1 update).\n\ +column vectors (rank-1 update) or matrices with equal number of columns\n\ +(rank-k update). Notice that the latter case is done as a sequence of rank-1 updates;\n\ +thus, for k large enough, it will be both faster and more accurate to recompute\n\ +the factorization from scratch.\n\ \n\ -If the matrix @var{Q} is not square, the matrix @var{A} is updated by\n\ -Q*Q'*u*v' instead of u*v'.\n\ +The QR factorization supplied may be either full\n\ +(Q is square) or economized (R is square).\n\ +\n\ @seealso{qr, qrinsert, qrdelete}\n\ @end deftypefn") { @@ -772,18 +792,12 @@ if (argq.is_numeric_type () && argr.is_numeric_type () && argu.is_numeric_type () && argv.is_numeric_type ()) { - octave_idx_type m = argq.rows (); - octave_idx_type n = argr.columns (); - octave_idx_type k = argq.columns (); - - if (argr.rows () == k - && argu.rows () == m && argu.columns () == 1 - && argv.rows () == n && argv.columns () == 1) + if (check_qr_dims (argq, argr, true)) { - if (argq.is_real_matrix () - && argr.is_real_matrix () - && argu.is_real_matrix () - && argv.is_real_matrix ()) + if (argq.is_real_type () + && argr.is_real_type () + && argu.is_real_type () + && argv.is_real_type ()) { // all real case if (argq.is_single_type () @@ -935,12 +949,19 @@ @code{\"row\"}).\n\ \n\ The default value of @var{orient} is @code{\"col\"}.\n\ +If @var{orient} is @code{\"col\"},\n\ +@var{u} may be a matrix and @var{j} an index vector\n\ +resulting in the QR@tie{}factorization of a matrix @var{B} such that\n\ +@w{B(:,@var{j})} gives @var{u} and @w{B(:,@var{j}) = []} gives @var{A}.\n\ +Notice that the latter case is done as a sequence of k insertions;\n\ +thus, for k large enough, it will be both faster and more accurate to recompute\n\ +the factorization from scratch.\n\ \n\ -If @var{orient} is @code{\"col\"} and the matrix @var{Q} is not square,\n\ -then what gets inserted is the projection of @var{u} onto the space\n\ -spanned by columns of @var{Q}, i.e. Q*Q'*u.\n\ +If @var{orient} is @code{\"col\"},\n\ +the QR factorization supplied may be either full\n\ +(Q is square) or economized (R is square).\n\ \n\ -If @var{orient} is @code{\"row\"}, @var{Q} must be square.\n\ +If @var{orient} is @code{\"row\"}, full factorization is needed.\n\ @seealso{qr, qrupdate, qrdelete}\n\ @end deftypefn") { @@ -959,30 +980,24 @@ octave_value argx = args(3); if (argq.is_numeric_type () && argr.is_numeric_type () - && argj.is_scalar_type () && argx.is_numeric_type () + && argx.is_numeric_type () && (nargin < 5 || args(4).is_string ())) { - octave_idx_type m = argq.rows (); - octave_idx_type n = argr.columns (); - octave_idx_type k = argq.columns (); - std::string orient = (nargin < 5) ? "col" : args(4).string_value (); - bool row = orient == "row"; + bool col = orient == "col"; - if (row || orient == "col") - if (argr.rows () == k - && (! row || m == k) - && argx.rows () == (row ? 1 : m) - && argx.columns () == (row ? n : 1)) + if (col || orient == "row") + if (check_qr_dims (argq, argr, col) + && (col || argx.rows () == 1)) { - octave_idx_type j = argj.idx_type_value (); - - if (j >= 1 && j <= (row ? n : m)+1) + if (check_index (argj, col)) { - if (argq.is_real_matrix () - && argr.is_real_matrix () - && argx.is_real_matrix ()) + MArray<octave_idx_type> j = argj.int_vector_value (); + + if (argq.is_real_type () + && argr.is_real_type () + && argx.is_real_type ()) { // real case if (argq.is_single_type () @@ -995,10 +1010,10 @@ FloatQR fact (Q, R); - if (row) - fact.insert_row (x, j-1); + if (col) + fact.insert_col (x, j-1); else - fact.insert_col (x, j-1); + fact.insert_row (x.row (0), j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1012,10 +1027,10 @@ QR fact (Q, R); - if (row) - fact.insert_row (x, j-1); + if (col) + fact.insert_col (x, j-1); else - fact.insert_col (x, j-1); + fact.insert_row (x.row (0), j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1035,10 +1050,10 @@ FloatComplexQR fact (Q, R); - if (row) - fact.insert_row (x, j-1); + if (col) + fact.insert_col (x, j-1); else - fact.insert_col (x, j-1); + fact.insert_row (x.row (0), j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1051,10 +1066,10 @@ ComplexQR fact (Q, R); - if (row) - fact.insert_row (x, j-1); + if (col) + fact.insert_col (x, j-1); else - fact.insert_col (x, j-1); + fact.insert_row (x.row (0), j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1063,7 +1078,7 @@ } else - error ("qrinsert: index j out of range"); + error ("qrinsert: invalid index"); } else error ("qrinsert: dimension mismatch"); @@ -1150,18 +1165,19 @@ \n\ The default value of @var{orient} is \"col\".\n\ \n\ -If @var{orient} is \"col\", the matrix @var{Q} is not required to\n\ -be square.\n\ +If @var{orient} is @code{\"col\"},\n\ +@var{j} may be an index vector\n\ +resulting in the QR@tie{}factorization of a matrix @var{B} such that\n\ +@w{A(:,@var{j}) = []} gives @var{B}.\n\ +Notice that the latter case is done as a sequence of k deletions;\n\ +thus, for k large enough, it will be both faster and more accurate to recompute\n\ +the factorization from scratch.\n\ \n\ -For @sc{Matlab} compatibility, if @var{Q} is nonsquare on input, the\n\ -updated factorization is always stripped to the economical form, i.e.\n\ -@code{columns (Q) == rows (R) <= columns (R)}.\n\ +If @var{orient} is @code{\"col\"},\n\ +the QR factorization supplied may be either full\n\ +(Q is square) or economized (R is square).\n\ \n\ -To get the less intelligent but more natural behaviour when @var{Q}\n\ -retains it shape and @var{R} loses one column, set @var{orient} to\n\ -\"col+\" instead.\n\ -\n\ -If @var{orient} is \"row\", @var{Q} must be square.\n\ +If @var{orient} is @code{\"row\"}, full factorization is needed.\n\ @seealso{qr, qrinsert, qrupdate}\n\ @end deftypefn") { @@ -1179,27 +1195,21 @@ octave_value argj = args(2); if (argq.is_numeric_type () && argr.is_numeric_type () - && argj.is_scalar_type () && (nargin < 4 || args(3).is_string ())) { - octave_idx_type m = argq.rows (); - octave_idx_type k = argq.columns (); - octave_idx_type n = argr.columns (); - std::string orient = (nargin < 4) ? "col" : args(3).string_value (); - bool row = orient == "row"; - bool colp = orient == "col+"; + bool col = orient == "col"; - if (row || colp || orient == "col") - if (argr.rows () == k - && (! row || m == k)) + if (col || orient == "row") + if (check_qr_dims (argq, argr, col)) { - octave_idx_type j = argj.scalar_value (); - if (j >= 1 && j <= (row ? n : m)) + if (check_index (argj, col)) { - if (argq.is_real_matrix () - && argr.is_real_matrix ()) + MArray<octave_idx_type> j = argj.int_vector_value (); + + if (argq.is_real_type () + && argr.is_real_type ()) { // real case if (argq.is_single_type () @@ -1210,15 +1220,10 @@ FloatQR fact (Q, R); - if (row) - fact.delete_row (j-1); + if (col) + fact.delete_col (j-1); else - { - fact.delete_col (j-1); - - if (! colp && k < m) - fact.economize (); - } + fact.delete_row (j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1230,15 +1235,10 @@ QR fact (Q, R); - if (row) - fact.delete_row (j-1); + if (col) + fact.delete_col (j-1); else - { - fact.delete_col (j-1); - - if (! colp && k < m) - fact.economize (); - } + fact.delete_row (j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1255,15 +1255,10 @@ FloatComplexQR fact (Q, R); - if (row) - fact.delete_row (j-1); + if (col) + fact.delete_col (j-1); else - { - fact.delete_col (j-1); - - if (! colp && k < m) - fact.economize (); - } + fact.delete_row (j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1275,15 +1270,10 @@ ComplexQR fact (Q, R); - if (row) - fact.delete_row (j-1); + if (col) + fact.delete_col (j-1); else - { - fact.delete_col (j-1); - - if (! colp && k < m) - fact.economize (); - } + fact.delete_row (j(0)-1); retval(1) = fact.R (); retval(0) = fact.Q (); @@ -1291,7 +1281,7 @@ } } else - error ("qrdelete: index j out of range"); + error ("qrdelete: invalid index"); } else error ("qrdelete: dimension mismatch"); @@ -1439,20 +1429,17 @@ octave_value argi = args(2); octave_value argj = args(3); - if (argq.is_numeric_type () && argr.is_numeric_type () - && argi.is_real_scalar () && argj.is_real_scalar ()) + if (argq.is_numeric_type () && argr.is_numeric_type ()) { - octave_idx_type n = argr.columns (); - octave_idx_type k = argq.columns (); + if (check_qr_dims (argq, argr, true)) + { + if (check_index (argi) && check_index (argj)) + { + octave_idx_type i = argi.int_value (); + octave_idx_type j = argj.int_value (); - if (argr.rows () == k) - { - octave_idx_type i = argi.scalar_value (); - octave_idx_type j = argj.scalar_value (); - if (i > 1 && i <= n && j > 1 && j <= n) - { - if (argq.is_real_matrix () - && argr.is_real_matrix ()) + if (argq.is_real_type () + && argr.is_real_type ()) { // all real case if (argq.is_single_type () @@ -1508,7 +1495,7 @@ } } else - error ("qrshift: index out of range"); + error ("qrshift: invalid index"); } else error ("qrshift: dimensions mismatch"); @@ -1593,6 +1580,8 @@ %! assert(norm(vec(Q*R - AA(:,p)),Inf) < norm(AA)*1e1*eps('single')) */ +#endif + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/Makefile.in +++ b/src/Makefile.in @@ -301,7 +301,7 @@ -L../libcruft $(LIBCRUFT) -L../liboctave $(LIBOCTAVE) \ -L. $(LIBOCTINTERP) $(CHOLMOD_LIBS) $(UMFPACK_LIBS) $(AMD_LIBS) \ $(CAMD_LIBS) $(COLAMD_LIBS) $(CCOLAMD_LIBS) $(CXSPARSE_LIBS) $(BLAS_LIBS) \ - $(FFTW_LIBS) $(ARPACK_LIBS) $(LIBS) $(FLIBS) + $(FFTW_LIBS) $(QRUPDATE_LIBS) $(ARPACK_LIBS) $(LIBS) $(FLIBS) BUILT_DISTFILES = DOCSTRINGS oct-gperf.h parse.cc lex.cc y.tab.h \ $(OPT_HANDLERS) $(BUILT_EXTRAS) @@ -372,7 +372,8 @@ $(OCTAVE_LIBS) \ $(LEXLIB) $(UMFPACK_LIBS) $(AMD_LIBS) $(CAMD_LIBS) $(COLAMD_LIBS) \ $(CHOLMOD_LIBS) $(CCOLAMD_LIBS) $(CXSPARSE_LIBS) $(BLAS_LIBS) \ - $(FFTW_LIBS) $(ARPACK_LIBS) $(OPENGL_LIBS) $(LIBS) $(FLIBS) + $(FFTW_LIBS) $(QRUPDATE_LIBS) $(ARPACK_LIBS) $(OPENGL_LIBS) \ + $(LIBS) $(FLIBS) stmp-pic: pic @if [ -f stmp-pic ]; then \ @@ -652,6 +653,8 @@ __delaunayn__.oct: OCT_LINK_DEPS += $(QHULL_LIBS) __voronoi__.oct: OCT_LINK_DEPS += $(QHULL_LIBS) eigs.oct: OCT_LINK_DEPS += $(ARPACK_LIBS) +qr.oct: OCT_LINK_DEPS += $(QRUPDATE_LIBS) +chol.oct: OCT_LINK_DEPS += $(QRUPDATE_LIBS) regexp.oct: OCT_LINK_DEPS += $(REGEX_LIBS) urlwrite.oct: OCT_LINK_DEPS += $(CURL_LIBS) __glpk__.oct: OCT_LINK_DEPS += $(GLPK_LIBS)