4141* > with respect to the columns of
4242* > Q = [ Q1 ] .
4343* > [ Q2 ]
44- * > The columns of Q must be orthonormal.
44+ * > The Euclidean norm of X must be one and the columns of Q must be
45+ * > orthonormal. The orthogonalized vector will be zero if and only if it
46+ * > lies entirely in the range of Q.
4547* >
46- * > If the projection is zero according to Kahan's "twice is enough"
47- * > criterion, then the zero vector is returned.
48+ * > The projection is computed with at most two iterations of the
49+ * > classical Gram-Schmidt algorithm, see
50+ * > * L. Giraud, J. Langou, M. Rozložník. "On the round-off error
51+ * > analysis of the Gram-Schmidt algorithm with reorthogonalization."
52+ * > 2002. CERFACS Technical Report No. TR/PA/02/33. URL:
53+ * > https://www.cerfacs.fr/algor/reports/2002/TR_PA_02_33.pdf
4854* >
4955* >\endverbatim
5056*
@@ -167,15 +173,18 @@ SUBROUTINE DORBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
167173* =====================================================================
168174*
169175* .. Parameters ..
170- DOUBLE PRECISION ALPHASQ , REALONE, REALZERO
171- PARAMETER ( ALPHASQ = 0.01D0 , REALONE = 1.0D0 ,
176+ DOUBLE PRECISION ALPHA , REALONE, REALZERO
177+ PARAMETER ( ALPHA = 0.01D0 , REALONE = 1.0D0 ,
172178 $ REALZERO = 0.0D0 )
173179 DOUBLE PRECISION NEGONE, ONE, ZERO
174180 PARAMETER ( NEGONE = - 1.0D0 , ONE = 1.0D0 , ZERO = 0.0D0 )
175181* ..
176182* .. Local Scalars ..
177- INTEGER I
178- DOUBLE PRECISION NORMSQ1, NORMSQ2, SCL1, SCL2, SSQ1, SSQ2
183+ INTEGER I, IX
184+ REAL EPS, NORM, NORM_NEW, SCL, SSQ
185+ * ..
186+ * .. External Functions ..
187+ DOUBLE PRECISION DLAMCH
179188* ..
180189* .. External Subroutines ..
181190 EXTERNAL DGEMV, DLASSQ, XERBLA
@@ -210,17 +219,17 @@ SUBROUTINE DORBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
210219 CALL XERBLA( ' DORBDB6' , - INFO )
211220 RETURN
212221 END IF
222+ *
223+ EPS = DLAMCH( ' Precision' )
213224*
214225* First, project X onto the orthogonal complement of Q's column
215226* space
216227*
217- SCL1 = REALZERO
218- SSQ1 = REALONE
219- CALL DLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
220- SCL2 = REALZERO
221- SSQ2 = REALONE
222- CALL DLASSQ( M2, X2, INCX2, SCL2, SSQ2 )
223- NORMSQ1 = SCL1** 2 * SSQ1 + SCL2** 2 * SSQ2
228+ * Christoph Conrads: In debugging mode the norm should be computed
229+ * and an assertion added comparing the norm with one. Alas, Fortran
230+ * never made it into 1989 when assert() was introduced into the C
231+ * programming language.
232+ NORM = REALONE
224233*
225234 IF ( M1 .EQ. 0 ) THEN
226235 DO I = 1 , N
@@ -238,27 +247,31 @@ SUBROUTINE DORBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
238247 CALL DGEMV( ' N' , M2, N, NEGONE, Q2, LDQ2, WORK, 1 , ONE, X2,
239248 $ INCX2 )
240249*
241- SCL1 = REALZERO
242- SSQ1 = REALONE
243- CALL DLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
244- SCL2 = REALZERO
245- SSQ2 = REALONE
246- CALL DLASSQ( M2, X2, INCX2, SCL2, SSQ2 )
247- NORMSQ2 = SCL1** 2 * SSQ1 + SCL2** 2 * SSQ2
250+ SCL = REALZERO
251+ SSQ = REALZERO
252+ CALL DLASSQ( M1, X1, INCX1, SCL, SSQ )
253+ CALL DLASSQ( M2, X2, INCX2, SCL, SSQ )
254+ NORM_NEW = SCL * SQRT (SSQ)
248255*
249256* If projection is sufficiently large in norm, then stop.
250257* If projection is zero, then stop.
251258* Otherwise, project again.
252259*
253- IF ( NORMSQ2 .GE. ALPHASQ * NORMSQ1 ) THEN
260+ IF ( NORM_NEW .GE. ALPHA * NORM ) THEN
254261 RETURN
255262 END IF
256263*
257- IF ( NORMSQ2 .EQ. ZERO ) THEN
264+ IF ( NORM_NEW .LE. N * EPS * NORM ) THEN
265+ DO IX = 1 , 1 + (M1-1 )* INCX1, INCX1
266+ X1( IX ) = ZERO
267+ END DO
268+ DO IX = 1 , 1 + (M2-1 )* INCX2, INCX2
269+ X2( IX ) = ZERO
270+ END DO
258271 RETURN
259272 END IF
260273*
261- NORMSQ1 = NORMSQ2
274+ NORM = NORM_NEW
262275*
263276 DO I = 1 , N
264277 WORK(I) = ZERO
@@ -280,24 +293,22 @@ SUBROUTINE DORBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
280293 CALL DGEMV( ' N' , M2, N, NEGONE, Q2, LDQ2, WORK, 1 , ONE, X2,
281294 $ INCX2 )
282295*
283- SCL1 = REALZERO
284- SSQ1 = REALONE
285- CALL DLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
286- SCL2 = REALZERO
287- SSQ2 = REALONE
288- CALL DLASSQ( M1, X1, INCX1, SCL1, SSQ1 )
289- NORMSQ2 = SCL1** 2 * SSQ1 + SCL2** 2 * SSQ2
296+ SCL = REALZERO
297+ SSQ = REALZERO
298+ CALL DLASSQ( M1, X1, INCX1, SCL, SSQ )
299+ CALL DLASSQ( M2, X2, INCX2, SCL, SSQ )
300+ NORM_NEW = SCL * SQRT (SSQ)
290301*
291302* If second projection is sufficiently large in norm, then do
292303* nothing more. Alternatively, if it shrunk significantly, then
293304* truncate it to zero.
294305*
295- IF ( NORMSQ2 .LT. ALPHASQ * NORMSQ1 ) THEN
296- DO I = 1 , M1
297- X1(I ) = ZERO
306+ IF ( NORM_NEW .LT. ALPHA * NORM ) THEN
307+ DO IX = 1 , 1 + (M1 -1 ) * INCX1, INCX1
308+ X1(IX ) = ZERO
298309 END DO
299- DO I = 1 , M2
300- X2(I ) = ZERO
310+ DO IX = 1 , 1 + (M2 -1 ) * INCX2, INCX2
311+ X2(IX ) = ZERO
301312 END DO
302313 END IF
303314*
@@ -306,4 +317,3 @@ SUBROUTINE DORBDB6( M1, M2, N, X1, INCX1, X2, INCX2, Q1, LDQ1, Q2,
306317* End of DORBDB6
307318*
308319 END
309-
0 commit comments