4
5
6
7
8
9
10
11 CHARACTER DIAG, SYMM
12 INTEGER IA, IASEED, IBSEED, IX, JA, JX, N, NRHS
13 DOUBLE PRECISION ANORM, RESID
14
15
16 INTEGER DESCA( * ), DESCX( * )
17 COMPLEX*16 WORK( * ), X( * )
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
150 $ LLD_, MB_, M_, NB_, N_, RSRC_
151 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
152 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
153 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
154 COMPLEX*16 ZERO, ONE
155 parameter( one = ( 1.0d+0, 0.0d+0 ),
156 $ zero = ( 0.0d+0, 0.0d+0 ) )
157
158
159 INTEGER IACOL, IAROW, IB, ICOFF, ICTXT, ICURCOL, IDUMM,
160 $ II, IIA, IIX, IOFFX, IPA, IPB, IPW, IPX, IROFF,
161 $ IXCOL, IXROW, J, JBRHS, JJ, JJA, JJX, LDX,
162 $ MYCOL, MYROW, NP, NPCOL, NPROW, NQ
163 DOUBLE PRECISION DIVISOR, EPS, RESID1
164 COMPLEX*16 BETA
165
166
167 EXTERNAL blacs_gridinfo, dgebr2d, dgebs2d,
169 $
pzmatgen, zgamx2d, zgemm, zgsum2d,
170 $ zlaset
171
172
173 INTEGER IZAMAX, NUMROC
174 DOUBLE PRECISION PDLAMCH
176
177
178 INTRINSIC abs, dble,
max,
min, mod
179
180
181
182
183
184 ictxt = desca( ctxt_ )
185 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
186
188 resid = 0.0d+0
189 divisor = anorm * eps * dble( n )
190
191 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
192 $ iarow, iacol )
193 CALL infog2l( ix, jx, descx, nprow, npcol, myrow, mycol, iix, jjx,
194 $ ixrow, ixcol )
195 iroff = mod( ia-1, desca( mb_ ) )
196 icoff = mod( ja-1, desca( nb_ ) )
197 np =
numroc( n+iroff, desca( mb_ ), myrow, iarow, nprow )
198 nq =
numroc( n+icoff, desca( nb_ ), mycol, iacol, npcol )
199
201 ipb = 1
202 ipx = ipb + np * descx( nb_ )
203 ipa = ipx + nq * descx( nb_ )
204
205 IF( myrow.EQ.iarow )
206 $ np = np - iroff
207 IF( mycol.EQ.iacol )
208 $ nq = nq - icoff
209
210 icurcol = ixcol
211
212
213
214 DO 40 j = 1, nrhs, descx( nb_ )
215 jbrhs =
min( descx( nb_ ), nrhs-j+1 )
216
217
218
219 ioffx = iix + ( jjx - 1 ) * descx( lld_ )
220 CALL pbztran( ictxt,
'Column',
'Transpose', n, jbrhs,
221 $ descx( mb_ ), x( ioffx ), descx( lld_ ), zero,
222 $ work( ipx ), jbrhs, ixrow, icurcol, -1, iacol,
223 $ work( ipa ) )
224
225
226
227 IF( mycol.EQ.icurcol ) THEN
228 CALL pzmatgen( ictxt,
'N',
'N', descx( m_ ), descx( n_ ),
229 $ descx( mb_ ), descx( nb_ ), work( ipb ), ldx,
230 $ ixrow, ixcol, ibseed, iix-1, np, jjx-1,
231 $ jbrhs, myrow, mycol, nprow, npcol )
232 beta = one
233 ELSE
234 beta = zero
235 END IF
236
237 IF( nq.GT.0 ) THEN
238 DO 10 ii = iia, iia+np-1, desca( mb_ )
239 ib =
min( desca( mb_ ), iia+np-ii )
240
241
242
243 CALL pzmatgen( ictxt, symm, diag, desca( m_ ),
244 $ desca( n_ ), desca( mb_ ), desca( nb_ ),
245 $ work( ipa ), ib, desca( rsrc_ ),
246 $ desca( csrc_ ), iaseed, ii-1, ib,
247 $ jja-1, nq, myrow, mycol, nprow, npcol )
248
249
250
251 CALL zgemm( 'No transpose', 'Transpose', ib, jbrhs, nq,
252 $ -one, work( ipa ), ib, work( ipx ), jbrhs,
253 $ beta, work( ipb+ii-iia ), ldx )
254
255 10 CONTINUE
256
257 ELSE IF( mycol.NE.icurcol ) THEN
258
259 CALL zlaset( 'All', np, jbrhs, zero, zero, work( ipb ),
260 $ ldx )
261
262 END IF
263
264
265
266 CALL zgsum2d( ictxt, 'Row', ' ', np, jbrhs, work( ipb ), ldx,
267 $ myrow, icurcol )
268
269 IF( mycol.EQ.icurcol ) THEN
270
271
272
273 ipw = ipa + jbrhs
274 DO 20 jj = 0, jbrhs - 1
275 IF( np.GT.0 ) THEN
276 ii = izamax( np, work( ipb+jj*ldx ), 1 )
277 work( ipa+jj ) = abs( work( ipb+ii-1+jj*ldx ) )
278 work( ipw+jj ) = abs( x( ioffx + izamax( np,
279 $ x( ioffx + jj*descx( lld_ ) ), 1 )-1+jj*
280 $ descx( lld_ ) ) )
281 ELSE
282 work( ipa+jj ) = zero
283 work( ipw+jj ) = zero
284 END IF
285 20 CONTINUE
286
287
288
289
290
291 CALL zgamx2d( ictxt, 'Column', ' ', 1, 2*jbrhs,
292 $ work( ipa ), 1, idumm, idumm, -1, 0, icurcol )
293
294
295
296 IF( myrow.EQ.0 ) THEN
297 DO 30 jj = 0, jbrhs - 1
298 resid1 = dble( work( ipa+jj ) ) /
299 $ ( dble( work( ipw+jj ) )*divisor )
300 IF( resid.LT.resid1 )
301 $ resid = resid1
302 30 CONTINUE
303 IF( mycol.NE.0 )
304 $ CALL dgesd2d( ictxt, 1, 1, resid, 1, 0, 0 )
305 END IF
306
307 ELSE IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
308
309 CALL dgerv2d( ictxt, 1, 1, resid1, 1, 0, icurcol )
310 IF( resid.LT.resid1 )
311 $ resid = resid1
312
313 END IF
314
315 IF( mycol.EQ.icurcol )
316 $ jjx = jjx + jbrhs
317 icurcol = mod( icurcol+1, npcol )
318
319 40 CONTINUE
320
321 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
322 CALL dgebs2d( ictxt, 'All', ' ', 1, 1, resid, 1 )
323 ELSE
324 CALL dgebr2d( ictxt, 'All', ' ', 1, 1, resid, 1, 0, 0 )
325 END IF
326
327 RETURN
328
329
330
subroutine pzmatgen(ictxt, aform, diag, m, n, mb, nb, a, lda, iarow, iacol, iseed, iroff, irnum, icoff, icnum, myrow, mycol, nprow, npcol)
subroutine infog2l(grindx, gcindx, desc, nprow, npcol, myrow, mycol, lrindx, lcindx, rsrc, csrc)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine pbztran(icontxt, adist, trans, m, n, nb, a, lda, beta, c, ldc, iarow, iacol, icrow, iccol, work)
double precision function pdlamch(ictxt, cmach)