qrupdate-ng
1.2.0
Toggle main menu visibility
Loading...
Searching...
No Matches
dlu1up.f90
Go to the documentation of this file.
1
! Copyright (C) 2008, 2009 VZLU Prague, a.s., Czech Republic, Jaroslav Hajek <highegg@gmail.com>
2
! Copyright (C) 2026 Martin Köhler <koehlerm(AT)mpi-magdeburg.mpg.de>
3
!
4
! This file is part of qrupdate-ng.
5
!
6
! qrupdate is free software; you can redistribute it and/or modify
7
! it under the terms of the GNU General Public License as published by
8
! the Free Software Foundation; either version 3 of the License, or
9
! (at your option) any later version.
10
!
11
! This program is distributed in the hope that it will be useful,
12
! but WITHOUT ANY WARRANTY; without even the implied warranty of
13
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
! GNU General Public License for more details.
15
!
16
! You should have received a copy of the GNU General Public License
17
! along with this software; see the file COPYING. If not, see
18
! <http://www.gnu.org/licenses/>.
19
!
20
!> \brief Updates an LU factorization after a rank-1 modification.
21
!>
22
!> \par Definition:
23
! =============
24
!> \verbatim
25
!> subroutine dlu1up(m,n,L,ldl,R,ldr,u,v)
26
!>
27
!> .. Scalar Arguments ..
28
!> integer m, n, ldl, ldr
29
!> ..
30
!> .. Array Arguments ..
31
!> double precision L(ldl,*), R(ldr,*), u(*), v(*)
32
!> ..
33
!> \endverbatim
34
!>
35
!> \par Purpose:
36
! =============
37
!> \verbatim
38
!>
39
!> DLU1UP updates an LU factorization after rank-1 modification.
40
!> Given an m-by-k lower-triangular matrix L with unit diagonal and
41
!> a k-by-n upper-trapezoidal matrix R, where k = min(m,n), this
42
!> DLU1UP updates L -> L1 and R -> R1 so that L1 is again
43
!> lower unit triangular, R1 upper trapezoidal, and
44
!> L1*R1 = L*R + u*v.', where v.' denotes the transpose of v.
45
!>
46
!> The update is performed using the Bennett algorithm with
47
!> column-major access, which processes the leading k-by-k block
48
!> first and then finishes the trailing part of R if needed.
49
!> \endverbatim
50
!>
51
!> \param[in] m
52
!> \verbatim
53
!> m is INTEGER
54
!> The number of rows of the matrix L. m >= 0.
55
!> \endverbatim
56
!>
57
!> \param[in] n
58
!> \verbatim
59
!> n is INTEGER
60
!> The number of columns of the matrix R. n >= 0.
61
!> \endverbatim
62
!>
63
!> \param[in,out] L
64
!> \verbatim
65
!> L is DOUBLE PRECISION array, dimension (ldl,k)
66
!> On entry, the unit lower triangular matrix L. On exit,
67
!> the updated unit lower triangular matrix L1.
68
!> \endverbatim
69
!>
70
!> \param[in] ldl
71
!> \verbatim
72
!> ldl is INTEGER
73
!> The leading dimension of the array L. ldl >= m.
74
!> \endverbatim
75
!>
76
!> \param[in,out] R
77
!> \verbatim
78
!> R is DOUBLE PRECISION array, dimension (ldr,n)
79
!> On entry, the upper trapezoidal m-by-n matrix R.
80
!> On exit, the updated upper trapezoidal matrix R1.
81
!> \endverbatim
82
!>
83
!> \param[in] ldr
84
!> \verbatim
85
!> ldr is INTEGER
86
!> The leading dimension of the array R. ldr >= k,
87
!> where k = min(m,n).
88
!> \endverbatim
89
!>
90
!> \param[in,out] u
91
!> \verbatim
92
!> u is DOUBLE PRECISION array, dimension (m)
93
!> On entry, the left m-vector defining the rank-1
94
!> modification. On exit, if k < m, u is destroyed;
95
!> otherwise, u contains the updated vector.
96
!> \endverbatim
97
!>
98
!> \param[in,out] v
99
!> \verbatim
100
!> v is DOUBLE PRECISION array, dimension (n)
101
!> On entry, the right n-vector defining the rank-1
102
!> modification. On exit, v is destroyed.
103
!> \endverbatim
104
!>
105
!> \ingroup ludecomp
106
subroutine
dlu1up
(m,n,L,ldl,R,ldr,u,v)
107
use
iso_fortran_env
108
use
qrupdate_error
109
integer
,
intent(in)
:: m, n, ldl, ldr
110
real
(real64),
intent(inout)
:: L(ldl,*), R(ldr,*), u(*), v(*)
111
real
(real64) ui,vi
112
integer
k,info,i,j
113
! quick return if possible.
114
k = min(m,n)
115
if
(k == 0)
return
116
! check arguments.
117
info = 0
118
if
(m < 0)
then
119
info = 1
120
else
if
(n < 0)
then
121
info = 2
122
else
if
(ldl < m)
then
123
info = 4
124
else
if
(ldr < k)
then
125
info = 6
126
endif
127
if
(info /= 0)
then
128
call
qrupdate_xerror
(
'DLU1UP'
,info)
129
return
130
end if
131
! The Bennett algorithm, modified for column-major access.
132
! The leading part.
133
do
i = 1,k
134
! prefetch
135
ui = u(i)
136
vi = v(i)
137
! delayed R update
138
do
j = 1,i-1
139
r(j,i) = r(j,i) + u(j)*vi
140
vi = vi - v(j)*r(j,i)
141
end do
142
! diagonal update
143
r(i,i) = r(i,i) + ui*vi
144
vi = vi/r(i,i)
145
! L update
146
do
j = i+1,m
147
u(j) = u(j) - ui*l(j,i)
148
l(j,i) = l(j,i) + u(j)*vi
149
end do
150
u(i) = ui
151
v(i) = vi
152
end do
153
! Finish the trailing part of R if needed.
154
do
i = k+1,n
155
vi = v(i)
156
do
j = 1,k
157
r(j,i) = r(j,i) + u(j)*vi
158
vi = vi - v(j)*r(j,i)
159
end do
160
v(i) = vi
161
end do
162
end subroutine
qrupdate_error::qrupdate_xerror
subroutine qrupdate_xerror(srname, info)
Dispatches error reporting to the handler.
Definition
qrupdate_error.f90:89
dlu1up
subroutine dlu1up(m, n, l, ldl, r, ldr, u, v)
Updates an LU factorization after a rank-1 modification.
Definition
dlu1up.f90:107
qrupdate_error
Module for custom error handling.
Definition
qrupdate_error.f90:24
src
dlu1up.f90
Generated by
1.17.0