1*> \brief \b DLA_SYAMV computes a matrix-vector product using a symmetric indefinite matrix to calculate error bounds.
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download DLA_SYAMV + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dla_syamv.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dla_syamv.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dla_syamv.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE DLA_SYAMV( UPLO, N, ALPHA, A, LDA, X, INCX, BETA, Y,
22*                             INCY )
23*
24*       .. Scalar Arguments ..
25*       DOUBLE PRECISION   ALPHA, BETA
26*       INTEGER            INCX, INCY, LDA, N, UPLO
27*       ..
28*       .. Array Arguments ..
29*       DOUBLE PRECISION   A( LDA, * ), X( * ), Y( * )
30*       ..
31*
32*
33*> \par Purpose:
34*  =============
35*>
36*> \verbatim
37*>
38*> DLA_SYAMV  performs the matrix-vector operation
39*>
40*>         y := alpha*abs(A)*abs(x) + beta*abs(y),
41*>
42*> where alpha and beta are scalars, x and y are vectors and A is an
43*> n by n symmetric matrix.
44*>
45*> This function is primarily used in calculating error bounds.
46*> To protect against underflow during evaluation, components in
47*> the resulting vector are perturbed away from zero by (N+1)
48*> times the underflow threshold.  To prevent unnecessarily large
49*> errors for block-structure embedded in general matrices,
50*> "symbolically" zero components are not perturbed.  A zero
51*> entry is considered "symbolic" if all multiplications involved
52*> in computing that entry have at least one zero multiplicand.
53*> \endverbatim
54*
55*  Arguments:
56*  ==========
57*
58*> \param[in] UPLO
59*> \verbatim
60*>          UPLO is INTEGER
61*>           On entry, UPLO specifies whether the upper or lower
62*>           triangular part of the array A is to be referenced as
63*>           follows:
64*>
65*>              UPLO = BLAS_UPPER   Only the upper triangular part of A
66*>                                  is to be referenced.
67*>
68*>              UPLO = BLAS_LOWER   Only the lower triangular part of A
69*>                                  is to be referenced.
70*>
71*>           Unchanged on exit.
72*> \endverbatim
73*>
74*> \param[in] N
75*> \verbatim
76*>          N is INTEGER
77*>           On entry, N specifies the number of columns of the matrix A.
78*>           N must be at least zero.
79*>           Unchanged on exit.
80*> \endverbatim
81*>
82*> \param[in] ALPHA
83*> \verbatim
84*>          ALPHA is DOUBLE PRECISION .
85*>           On entry, ALPHA specifies the scalar alpha.
86*>           Unchanged on exit.
87*> \endverbatim
88*>
89*> \param[in] A
90*> \verbatim
91*>          A is DOUBLE PRECISION array, dimension ( LDA, n ).
92*>           Before entry, the leading m by n part of the array A must
93*>           contain the matrix of coefficients.
94*>           Unchanged on exit.
95*> \endverbatim
96*>
97*> \param[in] LDA
98*> \verbatim
99*>          LDA is INTEGER
100*>           On entry, LDA specifies the first dimension of A as declared
101*>           in the calling (sub) program. LDA must be at least
102*>           max( 1, n ).
103*>           Unchanged on exit.
104*> \endverbatim
105*>
106*> \param[in] X
107*> \verbatim
108*>          X is DOUBLE PRECISION array, dimension
109*>           ( 1 + ( n - 1 )*abs( INCX ) )
110*>           Before entry, the incremented array X must contain the
111*>           vector x.
112*>           Unchanged on exit.
113*> \endverbatim
114*>
115*> \param[in] INCX
116*> \verbatim
117*>          INCX is INTEGER
118*>           On entry, INCX specifies the increment for the elements of
119*>           X. INCX must not be zero.
120*>           Unchanged on exit.
121*> \endverbatim
122*>
123*> \param[in] BETA
124*> \verbatim
125*>          BETA is DOUBLE PRECISION .
126*>           On entry, BETA specifies the scalar beta. When BETA is
127*>           supplied as zero then Y need not be set on input.
128*>           Unchanged on exit.
129*> \endverbatim
130*>
131*> \param[in,out] Y
132*> \verbatim
133*>          Y is DOUBLE PRECISION array, dimension
134*>           ( 1 + ( n - 1 )*abs( INCY ) )
135*>           Before entry with BETA non-zero, the incremented array Y
136*>           must contain the vector y. On exit, Y is overwritten by the
137*>           updated vector y.
138*> \endverbatim
139*>
140*> \param[in] INCY
141*> \verbatim
142*>          INCY is INTEGER
143*>           On entry, INCY specifies the increment for the elements of
144*>           Y. INCY must not be zero.
145*>           Unchanged on exit.
146*> \endverbatim
147*
148*  Authors:
149*  ========
150*
151*> \author Univ. of Tennessee
152*> \author Univ. of California Berkeley
153*> \author Univ. of Colorado Denver
154*> \author NAG Ltd.
155*
156*> \date June 2017
157*
158*> \ingroup doubleSYcomputational
159*
160*> \par Further Details:
161*  =====================
162*>
163*> \verbatim
164*>
165*>  Level 2 Blas routine.
166*>
167*>  -- Written on 22-October-1986.
168*>     Jack Dongarra, Argonne National Lab.
169*>     Jeremy Du Croz, Nag Central Office.
170*>     Sven Hammarling, Nag Central Office.
171*>     Richard Hanson, Sandia National Labs.
172*>  -- Modified for the absolute-value product, April 2006
173*>     Jason Riedy, UC Berkeley
174*> \endverbatim
175*>
176*  =====================================================================
177      SUBROUTINE DLA_SYAMV( UPLO, N, ALPHA, A, LDA, X, INCX, BETA, Y,
178     $                      INCY )
179*
180*  -- LAPACK computational routine (version 3.7.1) --
181*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
182*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
183*     June 2017
184*
185*     .. Scalar Arguments ..
186      DOUBLE PRECISION   ALPHA, BETA
187      INTEGER            INCX, INCY, LDA, N, UPLO
188*     ..
189*     .. Array Arguments ..
190      DOUBLE PRECISION   A( LDA, * ), X( * ), Y( * )
191*     ..
192*
193*  =====================================================================
194*
195*     .. Parameters ..
196      DOUBLE PRECISION   ONE, ZERO
197      PARAMETER          ( ONE = 1.0D+0, ZERO = 0.0D+0 )
198*     ..
199*     .. Local Scalars ..
200      LOGICAL            SYMB_ZERO
201      DOUBLE PRECISION   TEMP, SAFE1
202      INTEGER            I, INFO, IY, J, JX, KX, KY
203*     ..
204*     .. External Subroutines ..
205      EXTERNAL           XERBLA, DLAMCH
206      DOUBLE PRECISION   DLAMCH
207*     ..
208*     .. External Functions ..
209      EXTERNAL           ILAUPLO
210      INTEGER            ILAUPLO
211*     ..
212*     .. Intrinsic Functions ..
213      INTRINSIC          MAX, ABS, SIGN
214*     ..
215*     .. Executable Statements ..
216*
217*     Test the input parameters.
218*
219      INFO = 0
220      IF     ( UPLO.NE.ILAUPLO( 'U' ) .AND.
221     $         UPLO.NE.ILAUPLO( 'L' ) ) THEN
222         INFO = 1
223      ELSE IF( N.LT.0 )THEN
224         INFO = 2
225      ELSE IF( LDA.LT.MAX( 1, N ) )THEN
226         INFO = 5
227      ELSE IF( INCX.EQ.0 )THEN
228         INFO = 7
229      ELSE IF( INCY.EQ.0 )THEN
230         INFO = 10
231      END IF
232      IF( INFO.NE.0 )THEN
233         CALL XERBLA( 'DLA_SYAMV', INFO )
234         RETURN
235      END IF
236*
237*     Quick return if possible.
238*
239      IF( ( N.EQ.0 ).OR.( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) )
240     $   RETURN
241*
242*     Set up the start points in  X  and  Y.
243*
244      IF( INCX.GT.0 )THEN
245         KX = 1
246      ELSE
247         KX = 1 - ( N - 1 )*INCX
248      END IF
249      IF( INCY.GT.0 )THEN
250         KY = 1
251      ELSE
252         KY = 1 - ( N - 1 )*INCY
253      END IF
254*
255*     Set SAFE1 essentially to be the underflow threshold times the
256*     number of additions in each row.
257*
258      SAFE1 = DLAMCH( 'Safe minimum' )
259      SAFE1 = (N+1)*SAFE1
260*
261*     Form  y := alpha*abs(A)*abs(x) + beta*abs(y).
262*
263*     The O(N^2) SYMB_ZERO tests could be replaced by O(N) queries to
264*     the inexact flag.  Still doesn't help change the iteration order
265*     to per-column.
266*
267      IY = KY
268      IF ( INCX.EQ.1 ) THEN
269         IF ( UPLO .EQ. ILAUPLO( 'U' ) ) THEN
270            DO I = 1, N
271               IF ( BETA .EQ. ZERO ) THEN
272                  SYMB_ZERO = .TRUE.
273                  Y( IY ) = 0.0D+0
274               ELSE IF ( Y( IY ) .EQ. ZERO ) THEN
275                  SYMB_ZERO = .TRUE.
276               ELSE
277                  SYMB_ZERO = .FALSE.
278                  Y( IY ) = BETA * ABS( Y( IY ) )
279               END IF
280               IF ( ALPHA .NE. ZERO ) THEN
281                  DO J = 1, I
282                     TEMP = ABS( A( J, I ) )
283                     SYMB_ZERO = SYMB_ZERO .AND.
284     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
285
286                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( J ) )*TEMP
287                  END DO
288                  DO J = I+1, N
289                     TEMP = ABS( A( I, J ) )
290                     SYMB_ZERO = SYMB_ZERO .AND.
291     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
292
293                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( J ) )*TEMP
294                  END DO
295               END IF
296
297               IF ( .NOT.SYMB_ZERO )
298     $              Y( IY ) = Y( IY ) + SIGN( SAFE1, Y( IY ) )
299
300               IY = IY + INCY
301            END DO
302         ELSE
303            DO I = 1, N
304               IF ( BETA .EQ. ZERO ) THEN
305                  SYMB_ZERO = .TRUE.
306                  Y( IY ) = 0.0D+0
307               ELSE IF ( Y( IY ) .EQ. ZERO ) THEN
308                  SYMB_ZERO = .TRUE.
309               ELSE
310                  SYMB_ZERO = .FALSE.
311                  Y( IY ) = BETA * ABS( Y( IY ) )
312               END IF
313               IF ( ALPHA .NE. ZERO ) THEN
314                  DO J = 1, I
315                     TEMP = ABS( A( I, J ) )
316                     SYMB_ZERO = SYMB_ZERO .AND.
317     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
318
319                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( J ) )*TEMP
320                  END DO
321                  DO J = I+1, N
322                     TEMP = ABS( A( J, I ) )
323                     SYMB_ZERO = SYMB_ZERO .AND.
324     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
325
326                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( J ) )*TEMP
327                  END DO
328               END IF
329
330               IF ( .NOT.SYMB_ZERO )
331     $              Y( IY ) = Y( IY ) + SIGN( SAFE1, Y( IY ) )
332
333               IY = IY + INCY
334            END DO
335         END IF
336      ELSE
337         IF ( UPLO .EQ. ILAUPLO( 'U' ) ) THEN
338            DO I = 1, N
339               IF ( BETA .EQ. ZERO ) THEN
340                  SYMB_ZERO = .TRUE.
341                  Y( IY ) = 0.0D+0
342               ELSE IF ( Y( IY ) .EQ. ZERO ) THEN
343                  SYMB_ZERO = .TRUE.
344               ELSE
345                  SYMB_ZERO = .FALSE.
346                  Y( IY ) = BETA * ABS( Y( IY ) )
347               END IF
348               JX = KX
349               IF ( ALPHA .NE. ZERO ) THEN
350                  DO J = 1, I
351                     TEMP = ABS( A( J, I ) )
352                     SYMB_ZERO = SYMB_ZERO .AND.
353     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
354
355                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( JX ) )*TEMP
356                     JX = JX + INCX
357                  END DO
358                  DO J = I+1, N
359                     TEMP = ABS( A( I, J ) )
360                     SYMB_ZERO = SYMB_ZERO .AND.
361     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
362
363                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( JX ) )*TEMP
364                     JX = JX + INCX
365                  END DO
366               END IF
367
368               IF ( .NOT.SYMB_ZERO )
369     $              Y( IY ) = Y( IY ) + SIGN( SAFE1, Y( IY ) )
370
371               IY = IY + INCY
372            END DO
373         ELSE
374            DO I = 1, N
375               IF ( BETA .EQ. ZERO ) THEN
376                  SYMB_ZERO = .TRUE.
377                  Y( IY ) = 0.0D+0
378               ELSE IF ( Y( IY ) .EQ. ZERO ) THEN
379                  SYMB_ZERO = .TRUE.
380               ELSE
381                  SYMB_ZERO = .FALSE.
382                  Y( IY ) = BETA * ABS( Y( IY ) )
383               END IF
384               JX = KX
385               IF ( ALPHA .NE. ZERO ) THEN
386                  DO J = 1, I
387                     TEMP = ABS( A( I, J ) )
388                     SYMB_ZERO = SYMB_ZERO .AND.
389     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
390
391                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( JX ) )*TEMP
392                     JX = JX + INCX
393                  END DO
394                  DO J = I+1, N
395                     TEMP = ABS( A( J, I ) )
396                     SYMB_ZERO = SYMB_ZERO .AND.
397     $                    ( X( J ) .EQ. ZERO .OR. TEMP .EQ. ZERO )
398
399                     Y( IY ) = Y( IY ) + ALPHA*ABS( X( JX ) )*TEMP
400                     JX = JX + INCX
401                  END DO
402               END IF
403
404               IF ( .NOT.SYMB_ZERO )
405     $              Y( IY ) = Y( IY ) + SIGN( SAFE1, Y( IY ) )
406
407               IY = IY + INCY
408            END DO
409         END IF
410
411      END IF
412*
413      RETURN
414*
415*     End of DLA_SYAMV
416*
417      END
418