3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download SBDSVDX + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sbdsvdx.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sbdsvdx.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sbdsvdx.f">
21 * SUBROUTINE SBDSVDX( UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
22 * $ NS, S, Z, LDZ, WORK, IWORK, INFO )
24 * .. Scalar Arguments ..
25 * CHARACTER JOBZ, RANGE, UPLO
26 * INTEGER IL, INFO, IU, LDZ, N, NS
29 * .. Array Arguments ..
31 * REAL D( * ), E( * ), S( * ), WORK( * ),
40 *> SBDSVDX computes the singular value decomposition (SVD) of a real
41 *> N-by-N (upper or lower) bidiagonal matrix B, B = U * S * VT,
42 *> where S is a diagonal matrix with non-negative diagonal elements
43 *> (the singular values of B), and U and VT are orthogonal matrices
44 *> of left and right singular vectors, respectively.
46 *> Given an upper bidiagonal B with diagonal D = [ d_1 d_2 ... d_N ]
47 *> and superdiagonal E = [ e_1 e_2 ... e_N-1 ], SBDSVDX computes the
48 *> singular value decompositon of B through the eigenvalues and
49 *> eigenvectors of the N*2-by-N*2 tridiagonal matrix
53 *> TGK = | e_1 0 d_2 |
57 *> If (s,u,v) is a singular triplet of B with ||u|| = ||v|| = 1, then
58 *> (+/-s,q), ||q|| = 1, are eigenpairs of TGK, with q = P * ( u' +/-v' ) /
59 *> sqrt(2) = ( v_1 u_1 v_2 u_2 ... v_n u_n ) / sqrt(2), and
60 *> P = [ e_{n+1} e_{1} e_{n+2} e_{2} ... ].
62 *> Given a TGK matrix, one can either a) compute -s,-v and change signs
63 *> so that the singular values (and corresponding vectors) are already in
64 *> descending order (as in SGESVD/SGESDD) or b) compute s,v and reorder
65 *> the values (and corresponding vectors). SBDSVDX implements a) by
66 *> calling SSTEVX (bisection plus inverse iteration, to be replaced
67 *> with a version of the Multiple Relative Robust Representation
68 *> algorithm. (See P. Willems and B. Lang, A framework for the MR^3
69 *> algorithm: theory and implementation, SIAM J. Sci. Comput.,
78 *> UPLO is CHARACTER*1
79 *> = 'U': B is upper bidiagonal;
80 *> = 'L': B is lower bidiagonal.
85 *> JOBZ is CHARACTER*1
86 *> = 'N': Compute singular values only;
87 *> = 'V': Compute singular values and singular vectors.
92 *> RANGE is CHARACTER*1
93 *> = 'A': all singular values will be found.
94 *> = 'V': all singular values in the half-open interval [VL,VU)
96 *> = 'I': the IL-th through IU-th singular values will be found.
102 *> The order of the bidiagonal matrix. N >= 0.
107 *> D is REAL array, dimension (N)
108 *> The n diagonal elements of the bidiagonal matrix B.
113 *> E is REAL array, dimension (max(1,N-1))
114 *> The (n-1) superdiagonal elements of the bidiagonal matrix
115 *> B in elements 1 to N-1.
121 *> If RANGE='V', the lower bound of the interval to
122 *> be searched for singular values. VU > VL.
123 *> Not referenced if RANGE = 'A' or 'I'.
129 *> If RANGE='V', the upper bound of the interval to
130 *> be searched for singular values. VU > VL.
131 *> Not referenced if RANGE = 'A' or 'I'.
137 *> If RANGE='I', the index of the
138 *> smallest singular value to be returned.
139 *> 1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
140 *> Not referenced if RANGE = 'A' or 'V'.
146 *> If RANGE='I', the index of the
147 *> largest singular value to be returned.
148 *> 1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
149 *> Not referenced if RANGE = 'A' or 'V'.
155 *> The total number of singular values found. 0 <= NS <= N.
156 *> If RANGE = 'A', NS = N, and if RANGE = 'I', NS = IU-IL+1.
161 *> S is REAL array, dimension (N)
162 *> The first NS elements contain the selected singular values in
168 *> Z is REAL array, dimension (2*N,K) )
169 *> If JOBZ = 'V', then if INFO = 0 the first NS columns of Z
170 *> contain the singular vectors of the matrix B corresponding to
171 *> the selected singular values, with U in rows 1 to N and V
172 *> in rows N+1 to N*2, i.e.
175 *> If JOBZ = 'N', then Z is not referenced.
176 *> Note: The user must ensure that at least K = NS+1 columns are
177 *> supplied in the array Z; if RANGE = 'V', the exact value of
178 *> NS is not known in advance and an upper bound must be used.
184 *> The leading dimension of the array Z. LDZ >= 1, and if
185 *> JOBZ = 'V', LDZ >= max(2,N*2).
190 *> WORK is REAL array, dimension (14*N)
195 *> IWORK is INTEGER array, dimension (12*N)
196 *> If JOBZ = 'V', then if INFO = 0, the first NS elements of
197 *> IWORK are zero. If INFO > 0, then IWORK contains the indices
198 *> of the eigenvectors that failed to converge in DSTEVX.
204 *> = 0: successful exit
205 *> < 0: if INFO = -i, the i-th argument had an illegal value
206 *> > 0: if INFO = i, then i eigenvectors failed to converge
207 *> in SSTEVX. The indices of the eigenvectors
208 *> (as returned by SSTEVX) are stored in the
210 *> if INFO = N*2 + 1, an internal error occurred.
216 *> \author Univ. of Tennessee
217 *> \author Univ. of California Berkeley
218 *> \author Univ. of Colorado Denver
223 *> \ingroup realOTHEReigen
225 * =====================================================================
226 SUBROUTINE SBDSVDX( UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
227 $ NS, S, Z, LDZ, WORK, IWORK, INFO)
229 * -- LAPACK driver routine (version 3.6.1) --
230 * -- LAPACK is a software package provided by Univ. of Tennessee, --
231 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
234 * .. Scalar Arguments ..
235 CHARACTER JOBZ, RANGE, UPLO
236 INTEGER IL, INFO, IU, LDZ, N, NS
239 * .. Array Arguments ..
241 REAL D( * ), E( * ), S( * ), WORK( * ),
245 * =====================================================================
248 REAL ZERO, ONE, TEN, HNDRD, MEIGTH
249 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0, TEN = 10.0E0,
250 $ HNDRD = 100.0E0, MEIGTH = -0.1250E0 )
252 PARAMETER ( FUDGE = 2.0E0 )
254 * .. Local Scalars ..
256 LOGICAL ALLSV, INDSV, LOWER, SPLIT, SVEQ0, VALSV, WANTZ
257 INTEGER I, ICOLZ, IDBEG, IDEND, IDTGK, IDPTR, IEPTR,
258 $ IETGK, IIFAIL, IIWORK, ILTGK, IROWU, IROWV,
259 $ IROWZ, ISBEG, ISPLT, ITEMP, IUTGK, J, K,
260 $ NTGK, NRU, NRV, NSL
261 REAL ABSTOL, EPS, EMIN, MU, NRMU, NRMV, ORTOL, SMAX,
262 $ SMIN, SQRT2, THRESH, TOL, ULP,
263 $ VLTGK, VUTGK, ZJTJI
265 * .. External Functions ..
268 REAL SDOT, SLAMCH, SNRM2
269 EXTERNAL ISAMAX, LSAME, SAXPY, SDOT, SLAMCH, SNRM2
271 * .. External Subroutines ..
272 EXTERNAL SCOPY, SLASET, SSCAL, SSWAP
274 * .. Intrinsic Functions ..
275 INTRINSIC ABS, REAL, SIGN, SQRT
277 * .. Executable Statements ..
279 * Test the input parameters.
281 ALLSV = LSAME( RANGE, 'A' )
282 VALSV = LSAME( RANGE, 'V' )
283 INDSV = LSAME( RANGE, 'I' )
284 WANTZ = LSAME( JOBZ, 'V' )
285 LOWER = LSAME( UPLO, 'L' )
288 IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LOWER ) THEN
290 ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
292 ELSE IF( .NOT.( ALLSV .OR. VALSV .OR. INDSV ) ) THEN
294 ELSE IF( N.LT.0 ) THEN
296 ELSE IF( N.GT.0 ) THEN
298 IF( VL.LT.ZERO ) THEN
300 ELSE IF( VU.LE.VL ) THEN
303 ELSE IF( INDSV ) THEN
304 IF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THEN
306 ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THEN
312 IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N*2 ) ) INFO = -14
316 CALL XERBLA( 'SBDSVDX', -INFO )
320 * Quick return if possible (N.LE.1)
326 IF( ALLSV .OR. INDSV ) THEN
328 S( 1 ) = ABS( D( 1 ) )
330 IF( VL.LT.ABS( D( 1 ) ) .AND. VU.GE.ABS( D( 1 ) ) ) THEN
332 S( 1 ) = ABS( D( 1 ) )
336 Z( 1, 1 ) = SIGN( ONE, D( 1 ) )
342 ABSTOL = 2*SLAMCH( 'Safe Minimum' )
343 ULP = SLAMCH( 'Precision' )
344 EPS = SLAMCH( 'Epsilon' )
345 SQRT2 = SQRT( 2.0E0 )
348 * Criterion for splitting is taken from SBDSQR when singular
349 * values are computed to relative accuracy TOL. (See J. Demmel and
350 * W. Kahan, Accurate singular values of bidiagonal matrices, SIAM
351 * J. Sci. and Stat. Comput., 11:873–912, 1990.)
353 TOL = MAX( TEN, MIN( HNDRD, EPS**MEIGTH ) )*EPS
355 * Compute approximate maximum, minimum singular values.
357 I = ISAMAX( N, D, 1 )
359 I = ISAMAX( N-1, E, 1 )
360 SMAX = MAX( SMAX, ABS( E( I ) ) )
362 * Compute threshold for neglecting D's and E's.
365 IF( SMIN.NE.ZERO ) THEN
368 MU = ABS( D( I ) )*( MU / ( MU+ABS( E( I-1 ) ) ) )
369 SMIN = MIN( SMIN, MU )
370 IF( SMIN.EQ.ZERO ) EXIT
373 SMIN = SMIN / SQRT( REAL( N ) )
376 * Check for zeros in D and E (splits), i.e. submatrices.
379 IF( ABS( D( I ) ).LE.THRESH ) D( I ) = ZERO
380 IF( ABS( E( I ) ).LE.THRESH ) E( I ) = ZERO
382 IF( ABS( D( N ) ).LE.THRESH ) D( N ) = ZERO
384 * Pointers for arrays used by SSTEVX.
390 IIWORK = IIFAIL + N*2
392 * Set RNGVX, which corresponds to RANGE for SSTEVX in TGK mode.
393 * VL,VU or IL,IU are redefined to conform to implementation a)
394 * described in the leading comments.
403 * All singular values will be found. We aim at -s (see
404 * leading comments) with RNGVX = 'I'. IL and IU are set
405 * later (as ILTGK and IUTGK) according to the dimension
406 * of the active submatrix.
409 IF( WANTZ ) CALL SLASET( 'F', N*2, N+1, ZERO, ZERO, Z, LDZ )
410 ELSE IF( VALSV ) THEN
412 * Find singular values in a half-open interval. We aim
413 * at -s (see leading comments) and we swap VL and VU
414 * (as VUTGK and VLTGK), changing their signs.
419 WORK( IDTGK:IDTGK+2*N-1 ) = ZERO
420 CALL SCOPY( N, D, 1, WORK( IETGK ), 2 )
421 CALL SCOPY( N-1, E, 1, WORK( IETGK+1 ), 2 )
422 CALL SSTEVX( 'N', 'V', N*2, WORK( IDTGK ), WORK( IETGK ),
423 $ VLTGK, VUTGK, ILTGK, ILTGK, ABSTOL, NS, S,
424 $ Z, LDZ, WORK( ITEMP ), IWORK( IIWORK ),
425 $ IWORK( IIFAIL ), INFO )
429 IF( WANTZ ) CALL SLASET( 'F', N*2, NS, ZERO, ZERO, Z, LDZ )
431 ELSE IF( INDSV ) THEN
433 * Find the IL-th through the IU-th singular values. We aim
434 * at -s (see leading comments) and indices are mapped into
435 * values, therefore mimicking SSTEBZ, where
437 * GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN
438 * GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN
443 WORK( IDTGK:IDTGK+2*N-1 ) = ZERO
444 CALL SCOPY( N, D, 1, WORK( IETGK ), 2 )
445 CALL SCOPY( N-1, E, 1, WORK( IETGK+1 ), 2 )
446 CALL SSTEVX( 'N', 'I', N*2, WORK( IDTGK ), WORK( IETGK ),
447 $ VLTGK, VLTGK, ILTGK, ILTGK, ABSTOL, NS, S,
448 $ Z, LDZ, WORK( ITEMP ), IWORK( IIWORK ),
449 $ IWORK( IIFAIL ), INFO )
450 VLTGK = S( 1 ) - FUDGE*SMAX*ULP*N
451 WORK( IDTGK:IDTGK+2*N-1 ) = ZERO
452 CALL SCOPY( N, D, 1, WORK( IETGK ), 2 )
453 CALL SCOPY( N-1, E, 1, WORK( IETGK+1 ), 2 )
454 CALL SSTEVX( 'N', 'I', N*2, WORK( IDTGK ), WORK( IETGK ),
455 $ VUTGK, VUTGK, IUTGK, IUTGK, ABSTOL, NS, S,
456 $ Z, LDZ, WORK( ITEMP ), IWORK( IIWORK ),
457 $ IWORK( IIFAIL ), INFO )
458 VUTGK = S( 1 ) + FUDGE*SMAX*ULP*N
459 VUTGK = MIN( VUTGK, ZERO )
461 * If VLTGK=VUTGK, SSTEVX returns an error message,
462 * so if needed we change VUTGK slightly.
464 IF( VLTGK.EQ.VUTGK ) VLTGK = VLTGK - TOL
466 IF( WANTZ ) CALL SLASET( 'F', N*2, IU-IL+1, ZERO, ZERO, Z, LDZ)
469 * Initialize variables and pointers for S, Z, and WORK.
471 * NRU, NRV: number of rows in U and V for the active submatrix
472 * IDBEG, ISBEG: offsets for the entries of D and S
473 * IROWZ, ICOLZ: offsets for the rows and columns of Z
474 * IROWU, IROWV: offsets for the rows of U and V
488 * Form the tridiagonal TGK matrix.
491 WORK( IETGK+2*N-1 ) = ZERO
492 WORK( IDTGK:IDTGK+2*N-1 ) = ZERO
493 CALL SCOPY( N, D, 1, WORK( IETGK ), 2 )
494 CALL SCOPY( N-1, E, 1, WORK( IETGK+1 ), 2 )
497 * Check for splits in two levels, outer level
498 * in E and inner level in D.
501 IF( WORK( IETGK+IEPTR-1 ).EQ.ZERO ) THEN
503 * Split in E (this piece of B is square) or bottom
504 * of the (input bidiagonal) matrix.
508 DO IDPTR = IDBEG, IDEND, 2
509 IF( WORK( IETGK+IDPTR-1 ).EQ.ZERO ) THEN
511 * Split in D (rectangular submatrix). Set the number
512 * of rows in U and V (NRU and NRV) accordingly.
514 IF( IDPTR.EQ.IDBEG ) THEN
519 IF( IDBEG.EQ.IDEND) THEN
523 ELSE IF( IDPTR.EQ.IDEND ) THEN
528 NRU = (IDEND-ISPLT)/2 + 1
530 IF( ISPLT.NE.IDBEG ) THEN
534 IF( ISPLT.EQ.IDBEG ) THEN
536 * Split: top rectangular submatrix.
538 NRU = (IDPTR-IDBEG)/2
542 * Split: middle square submatrix.
544 NRU = (IDPTR-ISPLT)/2 + 1
548 ELSE IF( IDPTR.EQ.IDEND ) THEN
550 * Last entry of D in the active submatrix.
552 IF( ISPLT.EQ.IDBEG ) THEN
554 * No split (trivial case).
556 NRU = (IDEND-IDBEG)/2 + 1
560 * Split: bottom rectangular submatrix.
562 NRV = (IDEND-ISPLT)/2 + 1
571 * Compute eigenvalues/vectors of the active
572 * submatrix according to RANGE:
573 * if RANGE='A' (ALLSV) then RNGVX = 'I'
574 * if RANGE='V' (VALSV) then RNGVX = 'V'
575 * if RANGE='I' (INDSV) then RNGVX = 'V'
579 IF( ALLSV .OR. VUTGK.EQ.ZERO ) THEN
582 $ MOD(NTGK,2).GT.0 ) THEN
583 * Special case: eigenvalue equal to zero or very
584 * small, additional eigenvector is needed.
589 * Workspace needed by SSTEVX:
590 * WORK( ITEMP: ): 2*5*NTGK
591 * IWORK( 1: ): 2*6*NTGK
593 CALL SSTEVX( JOBZ, RNGVX, NTGK, WORK( IDTGK+ISPLT-1 ),
594 $ WORK( IETGK+ISPLT-1 ), VLTGK, VUTGK,
595 $ ILTGK, IUTGK, ABSTOL, NSL, S( ISBEG ),
596 $ Z( IROWZ,ICOLZ ), LDZ, WORK( ITEMP ),
597 $ IWORK( IIWORK ), IWORK( IIFAIL ),
600 * Exit with the error code from SSTEVX.
603 EMIN = ABS( MAXVAL( S( ISBEG:ISBEG+NSL-1 ) ) )
605 IF( NSL.GT.0 .AND. WANTZ ) THEN
607 * Normalize u=Z([2,4,...],:) and v=Z([1,3,...],:),
608 * changing the sign of v as discussed in the leading
609 * comments. The norms of u and v may be (slightly)
610 * different from 1/sqrt(2) if the corresponding
611 * eigenvalues are very small or too close. We check
612 * those norms and, if needed, reorthogonalize the
616 $ VUTGK.EQ.ZERO .AND.
617 $ MOD(NTGK,2).EQ.0 .AND.
618 $ EMIN.EQ.0 .AND. .NOT.SPLIT ) THEN
620 * D=0 at the top or bottom of the active submatrix:
621 * one eigenvalue is equal to zero; concatenate the
622 * eigenvectors corresponding to the two smallest
625 Z( IROWZ:IROWZ+NTGK-1,ICOLZ+NSL-2 ) =
626 $ Z( IROWZ:IROWZ+NTGK-1,ICOLZ+NSL-2 ) +
627 $ Z( IROWZ:IROWZ+NTGK-1,ICOLZ+NSL-1 )
628 Z( IROWZ:IROWZ+NTGK-1,ICOLZ+NSL-1 ) =
630 * IF( IUTGK*2.GT.NTGK ) THEN
631 * Eigenvalue equal to zero or very small.
636 DO I = 0, MIN( NSL-1, NRU-1 )
637 NRMU = SNRM2( NRU, Z( IROWU, ICOLZ+I ), 2 )
638 IF( NRMU.EQ.ZERO ) THEN
642 CALL SSCAL( NRU, ONE/NRMU,
643 $ Z( IROWU,ICOLZ+I ), 2 )
644 IF( NRMU.NE.ONE .AND.
645 $ ABS( NRMU-ORTOL )*SQRT2.GT.ONE )
648 ZJTJI = -SDOT( NRU, Z( IROWU, ICOLZ+J ),
649 $ 2, Z( IROWU, ICOLZ+I ), 2 )
650 CALL SAXPY( NRU, ZJTJI,
651 $ Z( IROWU, ICOLZ+J ), 2,
652 $ Z( IROWU, ICOLZ+I ), 2 )
654 NRMU = SNRM2( NRU, Z( IROWU, ICOLZ+I ), 2 )
655 CALL SSCAL( NRU, ONE/NRMU,
656 $ Z( IROWU,ICOLZ+I ), 2 )
659 DO I = 0, MIN( NSL-1, NRV-1 )
660 NRMV = SNRM2( NRV, Z( IROWV, ICOLZ+I ), 2 )
661 IF( NRMV.EQ.ZERO ) THEN
665 CALL SSCAL( NRV, -ONE/NRMV,
666 $ Z( IROWV,ICOLZ+I ), 2 )
667 IF( NRMV.NE.ONE .AND.
668 $ ABS( NRMV-ORTOL )*SQRT2.GT.ONE )
671 ZJTJI = -SDOT( NRV, Z( IROWV, ICOLZ+J ),
672 $ 2, Z( IROWV, ICOLZ+I ), 2 )
673 CALL SAXPY( NRU, ZJTJI,
674 $ Z( IROWV, ICOLZ+J ), 2,
675 $ Z( IROWV, ICOLZ+I ), 2 )
677 NRMV = SNRM2( NRV, Z( IROWV, ICOLZ+I ), 2 )
678 CALL SSCAL( NRV, ONE/NRMV,
679 $ Z( IROWV,ICOLZ+I ), 2 )
682 IF( VUTGK.EQ.ZERO .AND.
683 $ IDPTR.LT.IDEND .AND.
684 $ MOD(NTGK,2).GT.0 ) THEN
686 * D=0 in the middle of the active submatrix (one
687 * eigenvalue is equal to zero): save the corresponding
688 * eigenvector for later use (when bottom of the
689 * active submatrix is reached).
692 Z( IROWZ:IROWZ+NTGK-1,N+1 ) =
693 $ Z( IROWZ:IROWZ+NTGK-1,NS+NSL )
694 Z( IROWZ:IROWZ+NTGK-1,NS+NSL ) =
699 NSL = MIN( NSL, NRU )
702 * Absolute values of the eigenvalues of TGK.
705 S( ISBEG+I ) = ABS( S( ISBEG+I ) )
708 * Update pointers for TGK, S and Z.
719 END IF !** NTGK.GT.0 **!
720 IF( IROWZ.LT.N*2 .AND. WANTZ ) THEN
721 Z( 1:IROWZ-1, ICOLZ ) = ZERO
723 END DO !** IDPTR loop **!
724 IF( SPLIT .AND. WANTZ ) THEN
726 * Bring back eigenvector corresponding
727 * to eigenvalue equal to zero.
729 Z( IDBEG:IDEND-NTGK+1,ISBEG-1 ) =
730 $ Z( IDBEG:IDEND-NTGK+1,ISBEG-1 ) +
731 $ Z( IDBEG:IDEND-NTGK+1,N+1 )
732 Z( IDBEG:IDEND-NTGK+1,N+1 ) = 0
739 END IF !** Check for split in E **!
740 END DO !** IEPTR loop **!
742 * Sort the singular values into decreasing order (insertion sort on
743 * singular values, but only one transposition per singular vector)
749 IF( S( J ).LE.SMIN ) THEN
754 IF( K.NE.NS+1-I ) THEN
757 IF( WANTZ ) CALL SSWAP( N*2, Z( 1,K ), 1, Z( 1,NS+1-I ), 1 )
761 * If RANGE=I, check for singular values/vectors to be discarded.
767 IF( WANTZ ) Z( 1:N*2,K+1:NS ) = ZERO
772 * Reorder Z: U = Z( 1:N,1:NS ), V = Z( N+1:N*2,1:NS ).
773 * If B is a lower diagonal, swap U and V.
777 CALL SCOPY( N*2, Z( 1,I ), 1, WORK, 1 )
779 CALL SCOPY( N, WORK( 2 ), 2, Z( N+1,I ), 1 )
780 CALL SCOPY( N, WORK( 1 ), 2, Z( 1 ,I ), 1 )
782 CALL SCOPY( N, WORK( 2 ), 2, Z( 1 ,I ), 1 )
783 CALL SCOPY( N, WORK( 1 ), 2, Z( N+1,I ), 1 )