4
5
6
7
8
9
10
11 CHARACTER DIAG, SYMM
12 INTEGER IA, IASEED, IBSEED, IX, JA, JX, N, NRHS
13 REAL ANORM, RESID
14
15
16 INTEGER DESCA( * ), DESCX( * )
17 COMPLEX 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 ZERO, ONE
155 parameter( one = ( 1.0e+0, 0.0e+0 ),
156 $ zero = ( 0.0e+0, 0.0e+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 REAL DIVISOR, EPS, RESID1
164 COMPLEX BETA
165
166
167 EXTERNAL blacs_gridinfo, cgamx2d, cgemm, cgsum2d,
169 $ sgebs2d, sgerv2d, sgesd2d
170
171
172 INTEGER ICAMAX, NUMROC
173 REAL PSLAMCH
175
176
177 INTRINSIC abs,
max,
min, mod, real
178
179
180
181
182
183 ictxt = desca( ctxt_ )
184 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
185
187 resid = 0.0e+0
188 divisor = anorm * eps * real( n )
189
190 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
191 $ iarow, iacol )
192 CALL infog2l( ix, jx, descx, nprow, npcol, myrow, mycol, iix, jjx,
193 $ ixrow, ixcol )
194 iroff = mod( ia-1, desca( mb_ ) )
195 icoff = mod( ja-1, desca( nb_ ) )
196 np =
numroc( n+iroff, desca( mb_ ), myrow, iarow, nprow )
197 nq =
numroc( n+icoff, desca( nb_ ), mycol, iacol, npcol )
198
200 ipb = 1
201 ipx = ipb + np * descx( nb_ )
202 ipa = ipx + nq * descx( nb_ )
203
204 IF( myrow.EQ.iarow )
205 $ np = np - iroff
206 IF( mycol.EQ.iacol )
207 $ nq = nq - icoff
208
209 icurcol = ixcol
210
211
212
213 DO 40 j = 1, nrhs, descx( nb_ )
214 jbrhs =
min( descx( nb_ ), nrhs-j+1 )
215
216
217
218 ioffx = iix + ( jjx - 1 ) * descx( lld_ )
219 CALL pbctran( ictxt,
'Column',
'Transpose', n, jbrhs,
220 $ descx( mb_ ), x( ioffx ), descx( lld_ ), zero,
221 $ work( ipx ), jbrhs, ixrow, icurcol, -1, iacol,
222 $ work( ipa ) )
223
224
225
226 IF( mycol.EQ.icurcol ) THEN
227 CALL pcmatgen( ictxt,
'N',
'N', descx( m_ ), descx( n_ ),
228 $ descx( mb_ ), descx( nb_ ), work( ipb ), ldx,
229 $ ixrow, ixcol, ibseed, iix-1, np, jjx-1,
230 $ jbrhs, myrow, mycol, nprow, npcol )
231 beta = one
232 ELSE
233 beta = zero
234 END IF
235
236 IF( nq.GT.0 ) THEN
237 DO 10 ii = iia, iia+np-1, desca( mb_ )
238 ib =
min( desca( mb_ ), iia+np-ii )
239
240
241
242 CALL pcmatgen( ictxt, symm, diag, desca( m_ ),
243 $ desca( n_ ), desca( mb_ ), desca( nb_ ),
244 $ work( ipa ), ib, desca( rsrc_ ),
245 $ desca( csrc_ ), iaseed, ii-1, ib,
246 $ jja-1, nq, myrow, mycol, nprow, npcol )
247
248
249
250 CALL cgemm( 'No transpose', 'Transpose', ib, jbrhs, nq,
251 $ -one, work( ipa ), ib, work( ipx ), jbrhs,
252 $ beta, work( ipb+ii-iia ), ldx )
253
254 10 CONTINUE
255
256 ELSE IF( mycol.NE.icurcol ) THEN
257
258 CALL claset( 'All', np, jbrhs, zero, zero, work( ipb ),
259 $ ldx )
260
261 END IF
262
263
264
265 CALL cgsum2d( ictxt, 'Row', ' ', np, jbrhs, work( ipb ), ldx,
266 $ myrow, icurcol )
267
268 IF( mycol.EQ.icurcol ) THEN
269
270
271
272 ipw = ipa + jbrhs
273 DO 20 jj = 0, jbrhs - 1
274 IF( np.GT.0 ) THEN
275 ii = icamax( np, work( ipb+jj*ldx ), 1 )
276 work( ipa+jj ) = abs( work( ipb+ii-1+jj*ldx ) )
277 work( ipw+jj ) = abs( x( ioffx + icamax( np,
278 $ x( ioffx + jj*descx( lld_ ) ), 1 )-1+jj*
279 $ descx( lld_ ) ) )
280 ELSE
281 work( ipa+jj ) = zero
282 work( ipw+jj ) = zero
283 END IF
284 20 CONTINUE
285
286
287
288
289
290 CALL cgamx2d( ictxt, 'Column', ' ', 1, 2*jbrhs,
291 $ work( ipa ), 1, idumm, idumm, -1, 0, icurcol )
292
293
294
295 IF( myrow.EQ.0 ) THEN
296 DO 30 jj = 0, jbrhs - 1
297 resid1 = real( work( ipa+jj ) ) /
298 $ ( real( work( ipw+jj ) )*divisor )
299 IF( resid.LT.resid1 )
300 $ resid = resid1
301 30 CONTINUE
302 IF( mycol.NE.0 )
303 $ CALL sgesd2d( ictxt, 1, 1, resid, 1, 0, 0 )
304 END IF
305
306 ELSE IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
307
308 CALL sgerv2d( ictxt, 1, 1, resid1, 1, 0, icurcol )
309 IF( resid.LT.resid1 )
310 $ resid = resid1
311
312 END IF
313
314 IF( mycol.EQ.icurcol )
315 $ jjx = jjx + jbrhs
316 icurcol = mod( icurcol+1, npcol )
317
318 40 CONTINUE
319
320 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
321 CALL sgebs2d( ictxt, 'All', ' ', 1, 1, resid, 1 )
322 ELSE
323 CALL sgebr2d( ictxt, 'All', ' ', 1, 1, resid, 1, 0, 0 )
324 END IF
325
326 RETURN
327
328
329
subroutine pcmatgen(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 pbctran(icontxt, adist, trans, m, n, nb, a, lda, beta, c, ldc, iarow, iacol, icrow, iccol, work)
real function pslamch(ictxt, cmach)