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 REAL 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 REAL ZERO, ONE
155 parameter( one = 1.0e+0, zero = 0.0e+0 )
156
157
158 INTEGER IACOL, IAROW, IB, ICOFF, ICTXT, ICURCOL, IDUMM,
159 $ II, IIA, IIX, IOFFX, IPA, IPB, IPW, IPX, IROFF,
160 $ IXCOL, IXROW, J, JBRHS, JJ, JJA, JJX, LDX,
161 $ MYCOL, MYROW, NP, NPCOL, NPROW, NQ
162 REAL BETA, DIVISOR, EPS, RESID1
163
164
166 $ sgamx2d, sgebr2d, sgebs2d, sgemm,
167 $ sgerv2d, sgesd2d, sgsum2d, slaset
168
169
170 INTEGER ISAMAX, NUMROC
171 REAL PSLAMCH
173
174
175 INTRINSIC abs,
max,
min, mod, real
176
177
178
179
180
181 ictxt = desca( ctxt_ )
182 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
183
185 resid = 0.0e+0
186 divisor = anorm * eps * real( n )
187
188 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
189 $ iarow, iacol )
190 CALL infog2l( ix, jx, descx, nprow, npcol, myrow, mycol, iix, jjx,
191 $ ixrow, ixcol )
192 iroff = mod( ia-1, desca( mb_ ) )
193 icoff = mod( ja-1, desca( nb_ ) )
194 np =
numroc( n+iroff, desca( mb_ ), myrow, iarow, nprow )
195 nq =
numroc( n+icoff, desca( nb_ ), mycol, iacol, npcol )
196
198 ipb = 1
199 ipx = ipb + np * descx( nb_ )
200 ipa = ipx + nq * descx( nb_ )
201
202 IF( myrow.EQ.iarow )
203 $ np = np - iroff
204 IF( mycol.EQ.iacol )
205 $ nq = nq - icoff
206
207 icurcol = ixcol
208
209
210
211 DO 40 j = 1, nrhs, descx( nb_ )
212 jbrhs =
min( descx( nb_ ), nrhs-j+1 )
213
214
215
216 ioffx = iix + ( jjx - 1 ) * descx( lld_ )
217 CALL pbstran( ictxt,
'Column',
'Transpose', n, jbrhs,
218 $ descx( mb_ ), x( ioffx ), descx( lld_ ), zero,
219 $ work( ipx ), jbrhs, ixrow, icurcol, -1, iacol,
220 $ work( ipa ) )
221
222
223
224 IF( mycol.EQ.icurcol ) THEN
225 CALL psmatgen( ictxt,
'N',
'N', descx( m_ ), descx( n_ ),
226 $ descx( mb_ ), descx( nb_ ), work( ipb ), ldx,
227 $ ixrow, ixcol, ibseed, iix-1, np, jjx-1,
228 $ jbrhs, myrow, mycol, nprow, npcol )
229 beta = one
230 ELSE
231 beta = zero
232 END IF
233
234 IF( nq.GT.0 ) THEN
235 DO 10 ii = iia, iia+np-1, desca( mb_ )
236 ib =
min( desca( mb_ ), iia+np-ii )
237
238
239
240 CALL psmatgen( ictxt, symm, diag, desca( m_ ),
241 $ desca( n_ ), desca( mb_ ), desca( nb_ ),
242 $ work( ipa ), ib, desca( rsrc_ ),
243 $ desca( csrc_ ), iaseed, ii-1, ib,
244 $ jja-1, nq, myrow, mycol, nprow, npcol )
245
246
247
248 CALL sgemm( 'No transpose', 'Transpose', ib, jbrhs, nq,
249 $ -one, work( ipa ), ib, work( ipx ), jbrhs,
250 $ beta, work( ipb+ii-iia ), ldx )
251
252 10 CONTINUE
253
254 ELSE IF( mycol.NE.icurcol ) THEN
255
256 CALL slaset( 'All', np, jbrhs, zero, zero, work( ipb ),
257 $ ldx )
258
259 END IF
260
261
262
263 CALL sgsum2d( ictxt, 'Row', ' ', np, jbrhs, work( ipb ), ldx,
264 $ myrow, icurcol )
265
266 IF( mycol.EQ.icurcol ) THEN
267
268
269
270 ipw = ipa + jbrhs
271 DO 20 jj = 0, jbrhs - 1
272 IF( np.GT.0 ) THEN
273 ii = isamax( np, work( ipb+jj*ldx ), 1 )
274 work( ipa+jj ) = abs( work( ipb+ii-1+jj*ldx ) )
275 work( ipw+jj ) = abs( x( ioffx + isamax( np,
276 $ x( ioffx + jj*descx( lld_ ) ), 1 )-1+jj*
277 $ descx( lld_ ) ) )
278 ELSE
279 work( ipa+jj ) = zero
280 work( ipw+jj ) = zero
281 END IF
282 20 CONTINUE
283
284
285
286
287
288 CALL sgamx2d( ictxt, 'Column', ' ', 1, 2*jbrhs,
289 $ work( ipa ), 1, idumm, idumm, -1, 0, icurcol )
290
291
292
293 IF( myrow.EQ.0 ) THEN
294 DO 30 jj = 0, jbrhs - 1
295 resid1 = work( ipa+jj ) / ( work( ipw+jj )*divisor )
296 IF( resid.LT.resid1 )
297 $ resid = resid1
298 30 CONTINUE
299 IF( mycol.NE.0 )
300 $ CALL sgesd2d( ictxt, 1, 1, resid, 1, 0, 0 )
301 END IF
302
303 ELSE IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
304
305 CALL sgerv2d( ictxt, 1, 1, resid1, 1, 0, icurcol )
306 IF( resid.LT.resid1 )
307 $ resid = resid1
308
309 END IF
310
311 IF( mycol.EQ.icurcol )
312 $ jjx = jjx + jbrhs
313 icurcol = mod( icurcol+1, npcol )
314
315 40 CONTINUE
316
317 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
318 CALL sgebs2d( ictxt, 'All', ' ', 1, 1, resid, 1 )
319 ELSE
320 CALL sgebr2d( ictxt, 'All', ' ', 1, 1, resid, 1, 0, 0 )
321 END IF
322
323 RETURN
324
325
326
subroutine psmatgen(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 pbstran(icontxt, adist, trans, m, n, nb, a, lda, beta, c, ldc, iarow, iacol, icrow, iccol, work)
real function pslamch(ictxt, cmach)