1 *> \brief \b CLATPS solves a triangular system of equations with the matrix held in packed storage.
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download CLATPS + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/clatps.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/clatps.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clatps.f">
21 * SUBROUTINE CLATPS( UPLO, TRANS, DIAG, NORMIN, N, AP, X, SCALE,
24 * .. Scalar Arguments ..
25 * CHARACTER DIAG, NORMIN, TRANS, UPLO
29 * .. Array Arguments ..
31 * COMPLEX AP( * ), X( * )
40 *> CLATPS solves one of the triangular systems
42 *> A * x = s*b, A**T * x = s*b, or A**H * x = s*b,
44 *> with scaling to prevent overflow, where A is an upper or lower
45 *> triangular matrix stored in packed form. Here A**T denotes the
46 *> transpose of A, A**H denotes the conjugate transpose of A, x and b
47 *> are n-element vectors, and s is a scaling factor, usually less than
48 *> or equal to 1, chosen so that the components of x will be less than
49 *> the overflow threshold. If the unscaled problem will not cause
50 *> overflow, the Level 2 BLAS routine CTPSV is called. If the matrix A
51 *> is singular (A(j,j) = 0 for some j), then s is set to 0 and a
52 *> non-trivial solution to A*x = 0 is returned.
60 *> UPLO is CHARACTER*1
61 *> Specifies whether the matrix A is upper or lower triangular.
62 *> = 'U': Upper triangular
63 *> = 'L': Lower triangular
68 *> TRANS is CHARACTER*1
69 *> Specifies the operation applied to A.
70 *> = 'N': Solve A * x = s*b (No transpose)
71 *> = 'T': Solve A**T * x = s*b (Transpose)
72 *> = 'C': Solve A**H * x = s*b (Conjugate transpose)
77 *> DIAG is CHARACTER*1
78 *> Specifies whether or not the matrix A is unit triangular.
79 *> = 'N': Non-unit triangular
80 *> = 'U': Unit triangular
85 *> NORMIN is CHARACTER*1
86 *> Specifies whether CNORM has been set or not.
87 *> = 'Y': CNORM contains the column norms on entry
88 *> = 'N': CNORM is not set on entry. On exit, the norms will
89 *> be computed and stored in CNORM.
95 *> The order of the matrix A. N >= 0.
100 *> AP is COMPLEX array, dimension (N*(N+1)/2)
101 *> The upper or lower triangular matrix A, packed columnwise in
102 *> a linear array. The j-th column of A is stored in the array
104 *> if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;
105 *> if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.
110 *> X is COMPLEX array, dimension (N)
111 *> On entry, the right hand side b of the triangular system.
112 *> On exit, X is overwritten by the solution vector x.
118 *> The scaling factor s for the triangular system
119 *> A * x = s*b, A**T * x = s*b, or A**H * x = s*b.
120 *> If SCALE = 0, the matrix A is singular or badly scaled, and
121 *> the vector x is an exact or approximate solution to A*x = 0.
124 *> \param[in,out] CNORM
126 *> CNORM is REAL array, dimension (N)
128 *> If NORMIN = 'Y', CNORM is an input argument and CNORM(j)
129 *> contains the norm of the off-diagonal part of the j-th column
130 *> of A. If TRANS = 'N', CNORM(j) must be greater than or equal
131 *> to the infinity-norm, and if TRANS = 'T' or 'C', CNORM(j)
132 *> must be greater than or equal to the 1-norm.
134 *> If NORMIN = 'N', CNORM is an output argument and CNORM(j)
135 *> returns the 1-norm of the offdiagonal part of the j-th column
142 *> = 0: successful exit
143 *> < 0: if INFO = -k, the k-th argument had an illegal value
149 *> \author Univ. of Tennessee
150 *> \author Univ. of California Berkeley
151 *> \author Univ. of Colorado Denver
154 *> \date September 2012
156 *> \ingroup complexOTHERauxiliary
158 *> \par Further Details:
159 * =====================
163 *> A rough bound on x is computed; if that is less than overflow, CTPSV
164 *> is called, otherwise, specific code is used which checks for possible
165 *> overflow or divide-by-zero at every operation.
167 *> A columnwise scheme is used for solving A*x = b. The basic algorithm
168 *> if A is lower triangular is
172 *> x(j) := x(j) / A(j,j)
173 *> x[j+1:n] := x[j+1:n] - x(j) * A[j+1:n,j]
176 *> Define bounds on the components of x after j iterations of the loop:
177 *> M(j) = bound on x[1:j]
178 *> G(j) = bound on x[j+1:n]
179 *> Initially, let M(0) = 0 and G(0) = max{x(i), i=1,...,n}.
181 *> Then for iteration j+1 we have
182 *> M(j+1) <= G(j) / | A(j+1,j+1) |
183 *> G(j+1) <= G(j) + M(j+1) * | A[j+2:n,j+1] |
184 *> <= G(j) ( 1 + CNORM(j+1) / | A(j+1,j+1) | )
186 *> where CNORM(j+1) is greater than or equal to the infinity-norm of
187 *> column j+1 of A, not counting the diagonal. Hence
189 *> G(j) <= G(0) product ( 1 + CNORM(i) / | A(i,i) | )
193 *> |x(j)| <= ( G(0) / |A(j,j)| ) product ( 1 + CNORM(i) / |A(i,i)| )
196 *> Since |x(j)| <= M(j), we use the Level 2 BLAS routine CTPSV if the
197 *> reciprocal of the largest M(j), j=1,..,n, is larger than
198 *> max(underflow, 1/overflow).
200 *> The bound on x(j) is also used to determine when a step in the
201 *> columnwise method can be performed without fear of overflow. If
202 *> the computed bound is greater than a large constant, x is scaled to
203 *> prevent overflow, but if the bound overflows, x is set to 0, x(j) to
204 *> 1, and scale to 0, and a non-trivial solution to A*x = 0 is found.
206 *> Similarly, a row-wise scheme is used to solve A**T *x = b or
207 *> A**H *x = b. The basic algorithm for A upper triangular is
210 *> x(j) := ( b(j) - A[1:j-1,j]' * x[1:j-1] ) / A(j,j)
213 *> We simultaneously compute two bounds
214 *> G(j) = bound on ( b(i) - A[1:i-1,i]' * x[1:i-1] ), 1<=i<=j
215 *> M(j) = bound on x(i), 1<=i<=j
217 *> The initial values are G(0) = 0, M(0) = max{b(i), i=1,..,n}, and we
218 *> add the constraint G(j) >= G(j-1) and M(j) >= M(j-1) for j >= 1.
219 *> Then the bound on x(j) is
221 *> M(j) <= M(j-1) * ( 1 + CNORM(j) ) / | A(j,j) |
223 *> <= M(0) * product ( ( 1 + CNORM(i) ) / |A(i,i)| )
226 *> and we can safely call CTPSV if 1/M(n) and 1/G(n) are both greater
227 *> than max(underflow, 1/overflow).
230 * =====================================================================
231 SUBROUTINE CLATPS( UPLO, TRANS, DIAG, NORMIN, N, AP, X, SCALE,
234 * -- LAPACK auxiliary routine (version 3.4.2) --
235 * -- LAPACK is a software package provided by Univ. of Tennessee, --
236 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
239 * .. Scalar Arguments ..
240 CHARACTER DIAG, NORMIN, TRANS, UPLO
244 * .. Array Arguments ..
246 COMPLEX AP( * ), X( * )
249 * =====================================================================
252 REAL ZERO, HALF, ONE, TWO
253 PARAMETER ( ZERO = 0.0E+0, HALF = 0.5E+0, ONE = 1.0E+0,
256 * .. Local Scalars ..
257 LOGICAL NOTRAN, NOUNIT, UPPER
258 INTEGER I, IMAX, IP, J, JFIRST, JINC, JLAST, JLEN
259 REAL BIGNUM, GROW, REC, SMLNUM, TJJ, TMAX, TSCAL,
261 COMPLEX CSUMJ, TJJS, USCAL, ZDUM
263 * .. External Functions ..
265 INTEGER ICAMAX, ISAMAX
267 COMPLEX CDOTC, CDOTU, CLADIV
268 EXTERNAL LSAME, ICAMAX, ISAMAX, SCASUM, SLAMCH, CDOTC,
271 * .. External Subroutines ..
272 EXTERNAL CAXPY, CSSCAL, CTPSV, SLABAD, SSCAL, XERBLA
274 * .. Intrinsic Functions ..
275 INTRINSIC ABS, AIMAG, CMPLX, CONJG, MAX, MIN, REAL
277 * .. Statement Functions ..
280 * .. Statement Function definitions ..
281 CABS1( ZDUM ) = ABS( REAL( ZDUM ) ) + ABS( AIMAG( ZDUM ) )
282 CABS2( ZDUM ) = ABS( REAL( ZDUM ) / 2. ) +
283 $ ABS( AIMAG( ZDUM ) / 2. )
285 * .. Executable Statements ..
288 UPPER = LSAME( UPLO, 'U' )
289 NOTRAN = LSAME( TRANS, 'N' )
290 NOUNIT = LSAME( DIAG, 'N' )
292 * Test the input parameters.
294 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
296 ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.
297 $ LSAME( TRANS, 'C' ) ) THEN
299 ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN
301 ELSE IF( .NOT.LSAME( NORMIN, 'Y' ) .AND. .NOT.
302 $ LSAME( NORMIN, 'N' ) ) THEN
304 ELSE IF( N.LT.0 ) THEN
308 CALL XERBLA( 'CLATPS', -INFO )
312 * Quick return if possible
317 * Determine machine dependent parameters to control overflow.
319 SMLNUM = SLAMCH( 'Safe minimum' )
320 BIGNUM = ONE / SMLNUM
321 CALL SLABAD( SMLNUM, BIGNUM )
322 SMLNUM = SMLNUM / SLAMCH( 'Precision' )
323 BIGNUM = ONE / SMLNUM
326 IF( LSAME( NORMIN, 'N' ) ) THEN
328 * Compute the 1-norm of each column, not including the diagonal.
332 * A is upper triangular.
336 CNORM( J ) = SCASUM( J-1, AP( IP ), 1 )
341 * A is lower triangular.
345 CNORM( J ) = SCASUM( N-J, AP( IP+1 ), 1 )
352 * Scale the column norms by TSCAL if the maximum element in CNORM is
353 * greater than BIGNUM/2.
355 IMAX = ISAMAX( N, CNORM, 1 )
357 IF( TMAX.LE.BIGNUM*HALF ) THEN
360 TSCAL = HALF / ( SMLNUM*TMAX )
361 CALL SSCAL( N, TSCAL, CNORM, 1 )
364 * Compute a bound on the computed solution vector to see if the
365 * Level 2 BLAS routine CTPSV can be used.
369 XMAX = MAX( XMAX, CABS2( X( J ) ) )
374 * Compute the growth in A * x = b.
386 IF( TSCAL.NE.ONE ) THEN
393 * A is non-unit triangular.
395 * Compute GROW = 1/G(j) and XBND = 1/M(j).
396 * Initially, G(0) = max{x(i), i=1,...,n}.
398 GROW = HALF / MAX( XBND, SMLNUM )
400 IP = JFIRST*( JFIRST+1 ) / 2
402 DO 40 J = JFIRST, JLAST, JINC
404 * Exit the loop if the growth factor is too small.
412 IF( TJJ.GE.SMLNUM ) THEN
414 * M(j) = G(j-1) / abs(A(j,j))
416 XBND = MIN( XBND, MIN( ONE, TJJ )*GROW )
419 * M(j) could overflow, set XBND to 0.
424 IF( TJJ+CNORM( J ).GE.SMLNUM ) THEN
426 * G(j) = G(j-1)*( 1 + CNORM(j) / abs(A(j,j)) )
428 GROW = GROW*( TJJ / ( TJJ+CNORM( J ) ) )
431 * G(j) could overflow, set GROW to 0.
441 * A is unit triangular.
443 * Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}.
445 GROW = MIN( ONE, HALF / MAX( XBND, SMLNUM ) )
446 DO 50 J = JFIRST, JLAST, JINC
448 * Exit the loop if the growth factor is too small.
453 * G(j) = G(j-1)*( 1 + CNORM(j) )
455 GROW = GROW*( ONE / ( ONE+CNORM( J ) ) )
462 * Compute the growth in A**T * x = b or A**H * x = b.
474 IF( TSCAL.NE.ONE ) THEN
481 * A is non-unit triangular.
483 * Compute GROW = 1/G(j) and XBND = 1/M(j).
484 * Initially, M(0) = max{x(i), i=1,...,n}.
486 GROW = HALF / MAX( XBND, SMLNUM )
488 IP = JFIRST*( JFIRST+1 ) / 2
490 DO 70 J = JFIRST, JLAST, JINC
492 * Exit the loop if the growth factor is too small.
497 * G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) )
499 XJ = ONE + CNORM( J )
500 GROW = MIN( GROW, XBND / XJ )
505 IF( TJJ.GE.SMLNUM ) THEN
507 * M(j) = M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j))
510 $ XBND = XBND*( TJJ / XJ )
513 * M(j) could overflow, set XBND to 0.
520 GROW = MIN( GROW, XBND )
523 * A is unit triangular.
525 * Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}.
527 GROW = MIN( ONE, HALF / MAX( XBND, SMLNUM ) )
528 DO 80 J = JFIRST, JLAST, JINC
530 * Exit the loop if the growth factor is too small.
535 * G(j) = ( 1 + CNORM(j) )*G(j-1)
537 XJ = ONE + CNORM( J )
544 IF( ( GROW*TSCAL ).GT.SMLNUM ) THEN
546 * Use the Level 2 BLAS solve if the reciprocal of the bound on
547 * elements of X is not too small.
549 CALL CTPSV( UPLO, TRANS, DIAG, N, AP, X, 1 )
552 * Use a Level 1 BLAS solve, scaling intermediate results.
554 IF( XMAX.GT.BIGNUM*HALF ) THEN
556 * Scale X so that its components are less than or equal to
557 * BIGNUM in absolute value.
559 SCALE = ( BIGNUM*HALF ) / XMAX
560 CALL CSSCAL( N, SCALE, X, 1 )
570 IP = JFIRST*( JFIRST+1 ) / 2
571 DO 110 J = JFIRST, JLAST, JINC
573 * Compute x(j) = b(j) / A(j,j), scaling x if necessary.
577 TJJS = AP( IP )*TSCAL
584 IF( TJJ.GT.SMLNUM ) THEN
586 * abs(A(j,j)) > SMLNUM:
588 IF( TJJ.LT.ONE ) THEN
589 IF( XJ.GT.TJJ*BIGNUM ) THEN
594 CALL CSSCAL( N, REC, X, 1 )
599 X( J ) = CLADIV( X( J ), TJJS )
601 ELSE IF( TJJ.GT.ZERO ) THEN
603 * 0 < abs(A(j,j)) <= SMLNUM:
605 IF( XJ.GT.TJJ*BIGNUM ) THEN
607 * Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM
608 * to avoid overflow when dividing by A(j,j).
610 REC = ( TJJ*BIGNUM ) / XJ
611 IF( CNORM( J ).GT.ONE ) THEN
613 * Scale by 1/CNORM(j) to avoid overflow when
614 * multiplying x(j) times column j.
616 REC = REC / CNORM( J )
618 CALL CSSCAL( N, REC, X, 1 )
622 X( J ) = CLADIV( X( J ), TJJS )
626 * A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and
627 * scale = 0, and compute a solution to A*x = 0.
639 * Scale x if necessary to avoid overflow when adding a
640 * multiple of column j of A.
644 IF( CNORM( J ).GT.( BIGNUM-XMAX )*REC ) THEN
646 * Scale x by 1/(2*abs(x(j))).
649 CALL CSSCAL( N, REC, X, 1 )
652 ELSE IF( XJ*CNORM( J ).GT.( BIGNUM-XMAX ) ) THEN
656 CALL CSSCAL( N, HALF, X, 1 )
664 * x(1:j-1) := x(1:j-1) - x(j) * A(1:j-1,j)
666 CALL CAXPY( J-1, -X( J )*TSCAL, AP( IP-J+1 ), 1, X,
668 I = ICAMAX( J-1, X, 1 )
669 XMAX = CABS1( X( I ) )
676 * x(j+1:n) := x(j+1:n) - x(j) * A(j+1:n,j)
678 CALL CAXPY( N-J, -X( J )*TSCAL, AP( IP+1 ), 1,
680 I = J + ICAMAX( N-J, X( J+1 ), 1 )
681 XMAX = CABS1( X( I ) )
687 ELSE IF( LSAME( TRANS, 'T' ) ) THEN
691 IP = JFIRST*( JFIRST+1 ) / 2
693 DO 150 J = JFIRST, JLAST, JINC
695 * Compute x(j) = b(j) - sum A(k,j)*x(k).
700 REC = ONE / MAX( XMAX, ONE )
701 IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN
703 * If x(j) could overflow, scale x by 1/(2*XMAX).
707 TJJS = AP( IP )*TSCAL
712 IF( TJJ.GT.ONE ) THEN
714 * Divide by A(j,j) when scaling x if A(j,j) > 1.
716 REC = MIN( ONE, REC*TJJ )
717 USCAL = CLADIV( USCAL, TJJS )
719 IF( REC.LT.ONE ) THEN
720 CALL CSSCAL( N, REC, X, 1 )
727 IF( USCAL.EQ.CMPLX( ONE ) ) THEN
729 * If the scaling needed for A in the dot product is 1,
730 * call CDOTU to perform the dot product.
733 CSUMJ = CDOTU( J-1, AP( IP-J+1 ), 1, X, 1 )
734 ELSE IF( J.LT.N ) THEN
735 CSUMJ = CDOTU( N-J, AP( IP+1 ), 1, X( J+1 ), 1 )
739 * Otherwise, use in-line code for the dot product.
743 CSUMJ = CSUMJ + ( AP( IP-J+I )*USCAL )*X( I )
745 ELSE IF( J.LT.N ) THEN
747 CSUMJ = CSUMJ + ( AP( IP+I )*USCAL )*X( J+I )
752 IF( USCAL.EQ.CMPLX( TSCAL ) ) THEN
754 * Compute x(j) := ( x(j) - CSUMJ ) / A(j,j) if 1/A(j,j)
755 * was not used to scale the dotproduct.
757 X( J ) = X( J ) - CSUMJ
761 * Compute x(j) = x(j) / A(j,j), scaling if necessary.
763 TJJS = AP( IP )*TSCAL
770 IF( TJJ.GT.SMLNUM ) THEN
772 * abs(A(j,j)) > SMLNUM:
774 IF( TJJ.LT.ONE ) THEN
775 IF( XJ.GT.TJJ*BIGNUM ) THEN
777 * Scale X by 1/abs(x(j)).
780 CALL CSSCAL( N, REC, X, 1 )
785 X( J ) = CLADIV( X( J ), TJJS )
786 ELSE IF( TJJ.GT.ZERO ) THEN
788 * 0 < abs(A(j,j)) <= SMLNUM:
790 IF( XJ.GT.TJJ*BIGNUM ) THEN
792 * Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM.
794 REC = ( TJJ*BIGNUM ) / XJ
795 CALL CSSCAL( N, REC, X, 1 )
799 X( J ) = CLADIV( X( J ), TJJS )
802 * A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and
803 * scale = 0 and compute a solution to A**T *x = 0.
815 * Compute x(j) := x(j) / A(j,j) - CSUMJ if the dot
816 * product has already been divided by 1/A(j,j).
818 X( J ) = CLADIV( X( J ), TJJS ) - CSUMJ
820 XMAX = MAX( XMAX, CABS1( X( J ) ) )
829 IP = JFIRST*( JFIRST+1 ) / 2
831 DO 190 J = JFIRST, JLAST, JINC
833 * Compute x(j) = b(j) - sum A(k,j)*x(k).
838 REC = ONE / MAX( XMAX, ONE )
839 IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN
841 * If x(j) could overflow, scale x by 1/(2*XMAX).
845 TJJS = CONJG( AP( IP ) )*TSCAL
850 IF( TJJ.GT.ONE ) THEN
852 * Divide by A(j,j) when scaling x if A(j,j) > 1.
854 REC = MIN( ONE, REC*TJJ )
855 USCAL = CLADIV( USCAL, TJJS )
857 IF( REC.LT.ONE ) THEN
858 CALL CSSCAL( N, REC, X, 1 )
865 IF( USCAL.EQ.CMPLX( ONE ) ) THEN
867 * If the scaling needed for A in the dot product is 1,
868 * call CDOTC to perform the dot product.
871 CSUMJ = CDOTC( J-1, AP( IP-J+1 ), 1, X, 1 )
872 ELSE IF( J.LT.N ) THEN
873 CSUMJ = CDOTC( N-J, AP( IP+1 ), 1, X( J+1 ), 1 )
877 * Otherwise, use in-line code for the dot product.
881 CSUMJ = CSUMJ + ( CONJG( AP( IP-J+I ) )*USCAL )*
884 ELSE IF( J.LT.N ) THEN
886 CSUMJ = CSUMJ + ( CONJG( AP( IP+I ) )*USCAL )*
892 IF( USCAL.EQ.CMPLX( TSCAL ) ) THEN
894 * Compute x(j) := ( x(j) - CSUMJ ) / A(j,j) if 1/A(j,j)
895 * was not used to scale the dotproduct.
897 X( J ) = X( J ) - CSUMJ
901 * Compute x(j) = x(j) / A(j,j), scaling if necessary.
903 TJJS = CONJG( AP( IP ) )*TSCAL
910 IF( TJJ.GT.SMLNUM ) THEN
912 * abs(A(j,j)) > SMLNUM:
914 IF( TJJ.LT.ONE ) THEN
915 IF( XJ.GT.TJJ*BIGNUM ) THEN
917 * Scale X by 1/abs(x(j)).
920 CALL CSSCAL( N, REC, X, 1 )
925 X( J ) = CLADIV( X( J ), TJJS )
926 ELSE IF( TJJ.GT.ZERO ) THEN
928 * 0 < abs(A(j,j)) <= SMLNUM:
930 IF( XJ.GT.TJJ*BIGNUM ) THEN
932 * Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM.
934 REC = ( TJJ*BIGNUM ) / XJ
935 CALL CSSCAL( N, REC, X, 1 )
939 X( J ) = CLADIV( X( J ), TJJS )
942 * A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and
943 * scale = 0 and compute a solution to A**H *x = 0.
955 * Compute x(j) := x(j) / A(j,j) - CSUMJ if the dot
956 * product has already been divided by 1/A(j,j).
958 X( J ) = CLADIV( X( J ), TJJS ) - CSUMJ
960 XMAX = MAX( XMAX, CABS1( X( J ) ) )
965 SCALE = SCALE / TSCAL
968 * Scale the column norms by 1/TSCAL for return.
970 IF( TSCAL.NE.ONE ) THEN
971 CALL SSCAL( N, ONE / TSCAL, CNORM, 1 )