ScaLAPACK 2.1  2.1
ScaLAPACK: Scalable Linear Algebra PACKage
pzamax_.c
Go to the documentation of this file.
1 /* ---------------------------------------------------------------------
2 *
3 * -- PBLAS routine (version 2.0) --
4 * University of Tennessee, Knoxville, Oak Ridge National Laboratory,
5 * and University of California, Berkeley.
6 * April 1, 1998
7 *
8 * ---------------------------------------------------------------------
9 */
10 /*
11 * Include files
12 */
13 #include "pblas.h"
14 #include "PBpblas.h"
15 #include "PBtools.h"
16 #include "PBblacs.h"
17 #include "PBblas.h"
18 
19 #ifdef __STDC__
20 void pzamax_( int * N, double * AMAX, int * INDX,
21  double * X, int * IX, int * JX, int * DESCX, int * INCX )
22 #else
23 void pzamax_( N, AMAX, INDX, X, IX, JX, DESCX, INCX )
24 /*
25 * .. Scalar Arguments ..
26 */
27  int * INCX, * INDX, * IX, * JX, * N;
28  double * AMAX;
29 /*
30 * .. Array Arguments ..
31 */
32  int * DESCX;
33  double * X;
34 #endif
35 {
36 /*
37 * Purpose
38 * =======
39 *
40 * PZAMAX computes the global index of the maximum element in absolute
41 * value of a subvector sub( X ). The global index is returned in INDX
42 * and the value of that element is returned in AMAX,
43 *
44 * where
45 *
46 * sub( X ) denotes X(IX,JX:JX+N-1) if INCX = M_X,
47 * X(IX:IX+N-1,JX) if INCX = 1 and INCX <> M_X.
48 *
49 * Notes
50 * =====
51 *
52 * A description vector is associated with each 2D block-cyclicly dis-
53 * tributed matrix. This vector stores the information required to
54 * establish the mapping between a matrix entry and its corresponding
55 * process and memory location.
56 *
57 * In the following comments, the character _ should be read as
58 * "of the distributed matrix". Let A be a generic term for any 2D
59 * block cyclicly distributed matrix. Its description vector is DESC_A:
60 *
61 * NOTATION STORED IN EXPLANATION
62 * ---------------- --------------- ------------------------------------
63 * DTYPE_A (global) DESCA[ DTYPE_ ] The descriptor type.
64 * CTXT_A (global) DESCA[ CTXT_ ] The BLACS context handle, indicating
65 * the NPROW x NPCOL BLACS process grid
66 * A is distributed over. The context
67 * itself is global, but the handle
68 * (the integer value) may vary.
69 * M_A (global) DESCA[ M_ ] The number of rows in the distribu-
70 * ted matrix A, M_A >= 0.
71 * N_A (global) DESCA[ N_ ] The number of columns in the distri-
72 * buted matrix A, N_A >= 0.
73 * IMB_A (global) DESCA[ IMB_ ] The number of rows of the upper left
74 * block of the matrix A, IMB_A > 0.
75 * INB_A (global) DESCA[ INB_ ] The number of columns of the upper
76 * left block of the matrix A,
77 * INB_A > 0.
78 * MB_A (global) DESCA[ MB_ ] The blocking factor used to distri-
79 * bute the last M_A-IMB_A rows of A,
80 * MB_A > 0.
81 * NB_A (global) DESCA[ NB_ ] The blocking factor used to distri-
82 * bute the last N_A-INB_A columns of
83 * A, NB_A > 0.
84 * RSRC_A (global) DESCA[ RSRC_ ] The process row over which the first
85 * row of the matrix A is distributed,
86 * NPROW > RSRC_A >= 0.
87 * CSRC_A (global) DESCA[ CSRC_ ] The process column over which the
88 * first column of A is distributed.
89 * NPCOL > CSRC_A >= 0.
90 * LLD_A (local) DESCA[ LLD_ ] The leading dimension of the local
91 * array storing the local blocks of
92 * the distributed matrix A,
93 * IF( Lc( 1, N_A ) > 0 )
94 * LLD_A >= MAX( 1, Lr( 1, M_A ) )
95 * ELSE
96 * LLD_A >= 1.
97 *
98 * Let K be the number of rows of a matrix A starting at the global in-
99 * dex IA,i.e, A( IA:IA+K-1, : ). Lr( IA, K ) denotes the number of rows
100 * that the process of row coordinate MYROW ( 0 <= MYROW < NPROW ) would
101 * receive if these K rows were distributed over NPROW processes. If K
102 * is the number of columns of a matrix A starting at the global index
103 * JA, i.e, A( :, JA:JA+K-1, : ), Lc( JA, K ) denotes the number of co-
104 * lumns that the process MYCOL ( 0 <= MYCOL < NPCOL ) would receive if
105 * these K columns were distributed over NPCOL processes.
106 *
107 * The values of Lr() and Lc() may be determined via a call to the func-
108 * tion PB_Cnumroc:
109 * Lr( IA, K ) = PB_Cnumroc( K, IA, IMB_A, MB_A, MYROW, RSRC_A, NPROW )
110 * Lc( JA, K ) = PB_Cnumroc( K, JA, INB_A, NB_A, MYCOL, CSRC_A, NPCOL )
111 *
112 * Arguments
113 * =========
114 *
115 * N (global input) INTEGER
116 * On entry, N specifies the length of the subvector sub( X ).
117 * N must be at least zero.
118 *
119 * AMAX (global output) COMPLEX*16 array
120 * On exit, AMAX specifies the largest entry in absolute value
121 * of the subvector sub( X ) only in its scope (See below for
122 * further details).
123 *
124 * INDX (global output) INTEGER
125 * On exit, INDX specifies the global index of the maximum ele-
126 * ment in absolute value of the subvector sub( X ) only in its
127 * scope (See below for further details).
128 *
129 * X (local input) COMPLEX*16 array
130 * On entry, X is an array of dimension (LLD_X, Kx), where LLD_X
131 * is at least MAX( 1, Lr( 1, IX ) ) when INCX = M_X and
132 * MAX( 1, Lr( 1, IX+N-1 ) ) otherwise, and, Kx is at least
133 * Lc( 1, JX+N-1 ) when INCX = M_X and Lc( 1, JX ) otherwise.
134 * Before entry, this array contains the local entries of the
135 * matrix X.
136 *
137 * IX (global input) INTEGER
138 * On entry, IX specifies X's global row index, which points to
139 * the beginning of the submatrix sub( X ).
140 *
141 * JX (global input) INTEGER
142 * On entry, JX specifies X's global column index, which points
143 * to the beginning of the submatrix sub( X ).
144 *
145 * DESCX (global and local input) INTEGER array
146 * On entry, DESCX is an integer array of dimension DLEN_. This
147 * is the array descriptor for the matrix X.
148 *
149 * INCX (global input) INTEGER
150 * On entry, INCX specifies the global increment for the
151 * elements of X. Only two values of INCX are supported in
152 * this version, namely 1 and M_X. INCX must not be zero.
153 *
154 * Further Details
155 * ===============
156 *
157 * When the result of a vector-oriented PBLAS call is a scalar, this
158 * scalar is set only within the process scope which owns the vector(s)
159 * being operated on. Let sub( X ) be a generic term for the input vec-
160 * tor(s). Then, the processes owning the correct the answer is determi-
161 * ned as follows: if an operation involves more than one vector, the
162 * processes receiving the result will be the union of the following set
163 * of processes for each vector:
164 *
165 * If N = 1, M_X = 1 and INCX = 1, then one cannot determine if a pro-
166 * cess row or process column owns the vector operand, therefore only
167 * the process owning sub( X ) receives the correct result;
168 *
169 * If INCX = M_X, then sub( X ) is a vector distributed over a process
170 * row. Each process in this row receives the result;
171 *
172 * If INCX = 1, then sub( X ) is a vector distributed over a process
173 * column. Each process in this column receives the result;
174 *
175 * -- Written on April 1, 1998 by
176 * Antoine Petitet, University of Tennessee, Knoxville 37996, USA.
177 *
178 * ---------------------------------------------------------------------
179 */
180 /*
181 * .. Local Scalars ..
182 */
183  char cbtop, cctop, rbtop, rctop;
184  int Xcol, Xgindx, Xi, Xii, Ximb, Xinb, Xj, Xjj, Xlindx, Xld, Xmb,
185  Xnb, Xnp, Xnq, Xrow, Xsrc, ctxt, dist, dst, idumm, info, k,
186  maxpos, mycol, mydist, myrow, npcol, nprow, src, size;
187  PBTYP_T * type;
188 /*
189 * .. Local Arrays ..
190 */
191  char * Xptr;
192  int Xd[DLEN_];
193  cmplx16 work[4];
194 /* ..
195 * .. Executable Statements ..
196 *
197 */
198  PB_CargFtoC( *IX, *JX, DESCX, &Xi, &Xj, Xd );
199 #ifndef NO_ARGCHK
200 /*
201 * Test the input parameters
202 */
203  Cblacs_gridinfo( ( ctxt = Xd[CTXT_] ), &nprow, &npcol, &myrow, &mycol );
204  if( !( info = ( ( nprow == -1 ) ? -( 701 + CTXT_ ) : 0 ) ) )
205  PB_Cchkvec( ctxt, "PZAMAX", "X", *N, 1, Xi, Xj, Xd, *INCX, 7, &info );
206  if( info ) { PB_Cabort( ctxt, "PZAMAX", info ); return; }
207 #endif
208 /*
209 * Initialize INDX and AMAX
210 */
211  *INDX = 0; AMAX[REAL_PART] = ZERO; AMAX[IMAG_PART] = ZERO;
212 /*
213 * Quick return if possible
214 */
215  if( *N == 0 ) return;
216 /*
217 * Retrieve process grid information
218 */
219 #ifdef NO_ARGCHK
220  Cblacs_gridinfo( ( ctxt = Xd[CTXT_] ), &nprow, &npcol, &myrow, &mycol );
221 #endif
222 /*
223 * Retrieve sub( X )'s local information: Xii, Xjj, Xrow, Xcol
224 */
225  PB_Cinfog2l( Xi, Xj, Xd, nprow, npcol, myrow, mycol, &Xii, &Xjj,
226  &Xrow, &Xcol );
227 /*
228 * Handle degenerate case separately, sub( X )'s scope is just one process
229 */
230  if( ( *INCX == 1 ) && ( Xd[M_] == 1 ) && ( *N == 1 ) )
231  {
232 /*
233 * Make sure I own some data and compute INDX and AMAX
234 */
235  if( ( ( myrow == Xrow ) || ( Xrow < 0 ) ) &&
236  ( ( mycol == Xcol ) || ( Xcol < 0 ) ) )
237  {
238  *INDX = *JX;
239  type = PB_Cztypeset();
240  Xptr = Mptr( ((char *) X), Xii, Xjj, Xd[LLD_], type->size );
241  AMAX[REAL_PART] = ((double*)(Xptr))[REAL_PART];
242  AMAX[IMAG_PART] = ((double*)(Xptr))[IMAG_PART];
243  }
244  return;
245  }
246  else if( *INCX == Xd[M_] )
247  {
248 /*
249 * sub( X ) resides in (a) process row(s)
250 */
251  if( ( myrow == Xrow ) || ( Xrow < 0 ) )
252  {
253  rctop = *PB_Ctop( &ctxt, COMBINE, ROW, TOP_GET );
254 
255  if( ( rctop == CTOP_DEFAULT ) || ( rctop == CTOP_TREE1 ) )
256  {
257 /*
258 * Inline the 1-tree combine for communication savings
259 */
260  Xinb = Xd[INB_ ]; Xnb = Xd[NB_ ]; Xsrc = Xd[CSRC_];
261  Xnq = PB_Cnumroc( *N, Xj, Xinb, Xnb, mycol, Xsrc, npcol );
262 /*
263 * Make sure I own some data and compute local INDX and AMAX
264 */
265  if( Xnq > 0 )
266  {
267  Xld = Xd[LLD_];
268  type = PB_Cztypeset(); size = type->size;
269  Xlindx = Xjj - 1 +
270  izamax_( &Xnq, Mptr( ((char *) X), Xii, Xjj, Xld,
271  size ), &Xld );
272  Mindxl2g( Xgindx, Xlindx, Xinb, Xnb, mycol, Xsrc, npcol );
273  Xptr = Mptr( ((char *) X), Xii, Xlindx, Xld, size );
274  work[0][REAL_PART] = ((double*)(Xptr))[REAL_PART];
275  work[0][IMAG_PART] = ((double*)(Xptr))[IMAG_PART];
276  work[1][REAL_PART] = ((double)( Xgindx+1 ));
277  work[1][IMAG_PART] = ZERO;
278  }
279  else
280  {
281  work[0][REAL_PART] = ZERO;
282  work[0][IMAG_PART] = ZERO;
283  work[1][REAL_PART] = ZERO;
284  work[1][IMAG_PART] = ZERO;
285  }
286 /*
287 * Combine the local results using a 1-tree topology within process column 0
288 * if npcol > 1 or Xcol >= 0, i.e sub( X ) is distributed.
289 */
290  if( ( npcol >= 2 ) && ( Xcol >= 0 ) )
291  {
292  mydist = mycol;
293  k = 1;
294 l_10:
295  if( mydist & 1 )
296  {
297  dist = k * ( mydist - 1 );
298  dst = MPosMod( dist, npcol );
299  Czgesd2d( ctxt, 2, 1, ((char*)work), 2, myrow, dst );
300  goto l_20;
301  }
302  else
303  {
304  dist = mycol + k;
305  src = MPosMod( dist, npcol );
306 
307  if( mycol < src )
308  {
309  Czgerv2d( ctxt, 2, 1, ((char*) work[2]), 2, myrow,
310  src );
311  if( ( ABS( work[0][REAL_PART] ) +
312  ABS( work[0][IMAG_PART] ) ) <
313  ( ABS( work[2][REAL_PART] ) +
314  ABS( work[2][IMAG_PART] ) ) )
315  {
316  work[0][REAL_PART] = work[2][REAL_PART];
317  work[0][IMAG_PART] = work[2][IMAG_PART];
318  work[1][REAL_PART] = work[3][REAL_PART];
319  }
320  }
321  mydist >>= 1;
322  }
323  k <<= 1;
324 
325  if( k < npcol ) goto l_10;
326 l_20:
327 /*
328 * Process column 0 broadcasts the combined values of INDX and AMAX within
329 * their process row.
330 */
331  rbtop = *PB_Ctop( &ctxt, BCAST, ROW, TOP_GET );
332  if( mycol == 0 )
333  {
334  Czgebs2d( ctxt, ROW, &rbtop, 2, 1, ((char*)work), 2 );
335  }
336  else
337  {
338  Czgebr2d( ctxt, ROW, &rbtop, 2, 1, ((char*)work), 2,
339  myrow, 0 );
340  }
341  }
342 /*
343 * Set INDX and AMAX to the replicated answers contained in work. If AMAX is
344 * zero, then select a coherent INDX.
345 */
346  AMAX[REAL_PART] = work[0][REAL_PART];
347  AMAX[IMAG_PART] = work[0][IMAG_PART];
348  *INDX = ( ( ( AMAX[REAL_PART] == ZERO ) &&
349  ( AMAX[IMAG_PART] == ZERO ) ) ?
350  ( *JX ) : ( (int)(work[1][REAL_PART]) ) );
351  }
352  else
353  {
354 /*
355 * Otherwise use the current topology settings to combine the results
356 */
357  Xinb = Xd[INB_ ]; Xnb = Xd[NB_ ]; Xsrc = Xd[CSRC_];
358  Xnq = PB_Cnumroc( *N, Xj, Xinb, Xnb, mycol, Xsrc, npcol );
359 /*
360 * Make sure I own some data and compute local INDX and AMAX
361 */
362  if( Xnq > 0 )
363  {
364 /*
365 * Compute the local maximum and its corresponding local index
366 */
367  Xld = Xd[LLD_];
368  type = PB_Cztypeset(); size = type->size;
369  Xlindx = Xjj - 1 +
370  izamax_( &Xnq, Mptr( ((char *) X), Xii, Xjj, Xld,
371  size ), &Xld );
372  Xptr = Mptr( ((char *) X), Xii, Xlindx, Xld, size );
373  AMAX[REAL_PART] = ((double*)(Xptr))[REAL_PART];
374  AMAX[IMAG_PART] = ((double*)(Xptr))[IMAG_PART];
375  }
376  else
377  {
378  AMAX[REAL_PART] = ZERO;
379  AMAX[IMAG_PART] = ZERO;
380  }
381 
382  if( Xcol >= 0 )
383  {
384 /*
385 * Combine leave on all the local maximum if Xcol >= 0, i.e sub( X ) is
386 * distributed
387 */
388  Czgamx2d( ctxt, ROW, &rctop, 1, 1, ((char*)AMAX), 1,
389  &idumm, &maxpos, 1, -1, mycol );
390 /*
391 * Broadcast the corresponding global index
392 */
393  if( ( AMAX[REAL_PART] != ZERO ) || ( AMAX[IMAG_PART] != ZERO ) )
394  {
395  rbtop = *PB_Ctop( &ctxt, BCAST, ROW, TOP_GET );
396  if( mycol == maxpos )
397  {
398  Mindxl2g( Xgindx, Xlindx, Xinb, Xnb, mycol, Xsrc, npcol );
399  *INDX = Xgindx + 1;
400  Cigebs2d( ctxt, ROW, &rbtop, 1, 1, ((char*)INDX), 1 );
401  }
402  else
403  {
404  Cigebr2d( ctxt, ROW, &rbtop, 1, 1, ((char*)INDX), 1,
405  myrow, maxpos );
406  }
407  }
408  else
409  {
410 /*
411 * If AMAX is zero, then select a coherent INDX.
412 */
413  *INDX = *JX;
414  }
415  }
416  else
417  {
418 /*
419 * sub( X ) is not distributed. If AMAX is zero, then select a coherent INDX.
420 */
421  *INDX = ( ( ( AMAX[REAL_PART] == ZERO ) &&
422  ( AMAX[IMAG_PART] == ZERO ) ) ?
423  ( *JX ) : Xlindx + 1 );
424  }
425  }
426  }
427  return;
428  }
429  else
430  {
431 /*
432 * sub( X ) resides in (a) process column(s)
433 */
434  if( ( mycol == Xcol ) || ( Xcol < 0 ) )
435  {
436  cctop = *PB_Ctop( &ctxt, COMBINE, COLUMN, TOP_GET );
437 
438  if( ( cctop == CTOP_DEFAULT ) || ( cctop == CTOP_TREE1 ) )
439  {
440 /*
441 * Inline the 1-tree combine for communication savings
442 */
443  Ximb = Xd[IMB_ ]; Xmb = Xd[MB_ ]; Xsrc = Xd[RSRC_];
444  Xnp = PB_Cnumroc( *N, Xi, Ximb, Xmb, myrow, Xsrc, nprow );
445 /*
446 * Make sure I own some data and compute local INDX and AMAX
447 */
448  if( Xnp > 0 )
449  {
450  Xld = Xd[LLD_];
451  type = PB_Cztypeset(); size = type->size;
452  Xlindx = Xii - 1 +
453  izamax_( &Xnp, Mptr( ((char *)X), Xii, Xjj, Xld,
454  size ), INCX );
455  Mindxl2g( Xgindx, Xlindx, Ximb, Xmb, myrow, Xsrc, nprow );
456  Xptr = Mptr( ((char *) X), Xlindx, Xjj, Xld, size );
457  work[0][REAL_PART] = ((double*)(Xptr))[REAL_PART];
458  work[0][IMAG_PART] = ((double*)(Xptr))[IMAG_PART];
459  work[1][REAL_PART] = ((double)( Xgindx+1 ));
460  work[1][IMAG_PART] = ZERO;
461  }
462  else
463  {
464  work[0][REAL_PART] = ZERO;
465  work[0][IMAG_PART] = ZERO;
466  work[1][REAL_PART] = ZERO;
467  work[1][IMAG_PART] = ZERO;
468  }
469 /*
470 * Combine the local results using a 1-tree topology within process row 0
471 * if nprow > 1 or Xrow >= 0, i.e sub( X ) is distributed.
472 */
473  if( ( nprow >= 2 ) && ( Xrow >= 0 ) )
474  {
475  mydist = myrow;
476  k = 1;
477 l_30:
478  if( mydist & 1 )
479  {
480  dist = k * ( mydist - 1 );
481  dst = MPosMod( dist, nprow );
482  Czgesd2d( ctxt, 2, 1, ((char*)work), 2, dst, mycol );
483  goto l_40;
484  }
485  else
486  {
487  dist = myrow + k;
488  src = MPosMod( dist, nprow );
489 
490  if( myrow < src )
491  {
492  Czgerv2d( ctxt, 2, 1, ((char*) work[2]), 2,
493  src, mycol );
494  if( ( ABS( work[0][REAL_PART] ) +
495  ABS( work[0][IMAG_PART] ) ) <
496  ( ABS( work[2][REAL_PART] ) +
497  ABS( work[2][IMAG_PART] ) ) )
498  {
499  work[0][REAL_PART] = work[2][REAL_PART];
500  work[0][IMAG_PART] = work[2][IMAG_PART];
501  work[1][REAL_PART] = work[3][REAL_PART];
502  }
503  }
504  mydist >>= 1;
505  }
506  k <<= 1;
507 
508  if( k < nprow ) goto l_30;
509 l_40:
510 /*
511 * Process row 0 broadcasts the combined values of INDX and AMAX within their
512 * process column.
513 */
514  cbtop = *PB_Ctop( &ctxt, BCAST, COLUMN, TOP_GET );
515  if( myrow == 0 )
516  {
517  Czgebs2d( ctxt, COLUMN, &cbtop, 2, 1, ((char*)work), 2 );
518  }
519  else
520  {
521  Czgebr2d( ctxt, COLUMN, &cbtop, 2, 1, ((char*)work), 2,
522  0, mycol );
523  }
524  }
525 /*
526 * Set INDX and AMAX to the replicated answers contained in work. If AMAX is
527 * zero, then select a coherent INDX.
528 */
529  AMAX[REAL_PART] = work[0][REAL_PART];
530  AMAX[IMAG_PART] = work[0][IMAG_PART];
531  *INDX = ( ( ( AMAX[REAL_PART] == ZERO ) &&
532  ( AMAX[IMAG_PART] == ZERO ) ) ?
533  ( *IX ) : ( (int)(work[1][REAL_PART]) ) );
534  }
535  else
536  {
537 /*
538 * Otherwise use the current topology settings to combine the results
539 */
540  Ximb = Xd[IMB_ ]; Xmb = Xd[MB_ ]; Xsrc = Xd[RSRC_];
541  Xnp = PB_Cnumroc( *N, Xi, Ximb, Xmb, myrow, Xsrc, nprow );
542 /*
543 * Make sure I own some data and compute local INDX and AMAX
544 */
545 
546  if( Xnp > 0 )
547  {
548 /*
549 * Compute the local maximum and its corresponding local index
550 */
551  Xld = Xd[LLD_];
552  type = PB_Cztypeset(); size = type->size;
553  Xlindx = Xii - 1 +
554  izamax_( &Xnp, Mptr( ((char *) X), Xii, Xjj, Xld,
555  size ), INCX );
556  Xptr = Mptr( ((char *) X), Xlindx, Xjj, Xld, size );
557  AMAX[REAL_PART] = ((double*)(Xptr))[REAL_PART];
558  AMAX[IMAG_PART] = ((double*)(Xptr))[IMAG_PART];
559  }
560  else
561  {
562  AMAX[REAL_PART] = ZERO;
563  AMAX[IMAG_PART] = ZERO;
564  }
565 
566  if( Xrow >= 0 )
567  {
568 /*
569 * Combine leave on all the local maximum if Xrow >= 0, i.e sub( X ) is
570 * distributed.
571 */
572  Czgamx2d( ctxt, COLUMN, &cctop, 1, 1, ((char*)AMAX), 1,
573  &maxpos, &idumm, 1, -1, mycol );
574 /*
575 * Broadcast the corresponding global index
576 */
577  if( ( AMAX[REAL_PART] != ZERO ) || ( AMAX[IMAG_PART] != ZERO ) )
578  {
579  cbtop = *PB_Ctop( &ctxt, BCAST, COLUMN, TOP_GET );
580  if( myrow == maxpos )
581  {
582  Mindxl2g( Xgindx, Xlindx, Ximb, Xmb, myrow, Xsrc, nprow );
583  *INDX = Xgindx + 1;
584  Cigebs2d( ctxt, COLUMN, &cbtop, 1, 1, ((char*)INDX), 1 );
585  }
586  else
587  {
588  Cigebr2d( ctxt, COLUMN, &cbtop, 1, 1, ((char*)INDX), 1,
589  maxpos, mycol );
590  }
591  }
592  else
593  {
594 /*
595 * If AMAX is zero, then select a coherent INDX.
596 */
597  *INDX = *IX;
598  }
599  }
600  else
601  {
602 /*
603 * sub( X ) is not distributed. If AMAX is zero, then select a coherent INDX.
604 */
605  *INDX = ( ( ( AMAX[REAL_PART] == ZERO ) &&
606  ( AMAX[IMAG_PART] == ZERO ) ) ?
607  ( *IX ) : Xlindx + 1 );
608  }
609  }
610  }
611  return;
612  }
613 /*
614 * End of PZAMAX
615 */
616 }
M_
#define M_
Definition: PBtools.h:39
Mindxl2g
#define Mindxl2g(ig_, il_, inb_, nb_, proc_, srcproc_, nprocs_)
Definition: PBtools.h:170
ROW
#define ROW
Definition: PBblacs.h:46
MB_
#define MB_
Definition: PBtools.h:43
Cigebr2d
void Cigebr2d()
NB_
#define NB_
Definition: PBtools.h:44
COLUMN
#define COLUMN
Definition: PBblacs.h:45
CSRC_
#define CSRC_
Definition: PBtools.h:46
PBblacs.h
Czgebs2d
void Czgebs2d()
PBtools.h
PBblas.h
REAL_PART
#define REAL_PART
Definition: pblas.h:135
PBpblas.h
PB_Cztypeset
PBTYP_T * PB_Cztypeset()
Definition: PB_Cztypeset.c:19
DLEN_
#define DLEN_
Definition: PBtools.h:48
Czgebr2d
void Czgebr2d()
MPosMod
#define MPosMod(I, d)
Definition: PBtools.h:95
Czgesd2d
void Czgesd2d()
LLD_
#define LLD_
Definition: PBtools.h:47
Cigebs2d
void Cigebs2d()
ZERO
#define ZERO
Definition: PBtools.h:66
PB_Cchkvec
void PB_Cchkvec()
IMB_
#define IMB_
Definition: PBtools.h:41
PB_Cabort
void PB_Cabort()
Czgerv2d
void Czgerv2d()
izamax_
int izamax_()
cmplx16
double cmplx16[2]
Definition: pblas.h:133
TOP_GET
#define TOP_GET
Definition: PBblacs.h:50
PB_Ctop
char * PB_Ctop()
RSRC_
#define RSRC_
Definition: PBtools.h:45
PB_CargFtoC
void PB_CargFtoC()
BCAST
#define BCAST
Definition: PBblacs.h:48
Czgamx2d
void Czgamx2d()
COMBINE
#define COMBINE
Definition: PBblacs.h:49
PBTYP_T::size
int size
Definition: pblas.h:329
PB_Cinfog2l
void PB_Cinfog2l()
PB_Cnumroc
int PB_Cnumroc()
ABS
#define ABS(a_)
Definition: PBtools.h:75
CTOP_TREE1
#define CTOP_TREE1
Definition: PBblacs.h:34
INB_
#define INB_
Definition: PBtools.h:42
pzamax_
void pzamax_(int *N, double *AMAX, int *INDX, double *X, int *IX, int *JX, int *DESCX, int *INCX)
Definition: pzamax_.c:23
Cblacs_gridinfo
void Cblacs_gridinfo()
PBTYP_T
Definition: pblas.h:325
pblas.h
Mptr
#define Mptr(a_, i_, j_, lda_, siz_)
Definition: PBtools.h:132
CTXT_
#define CTXT_
Definition: PBtools.h:38
IMAG_PART
#define IMAG_PART
Definition: pblas.h:136
CTOP_DEFAULT
#define CTOP_DEFAULT
Definition: PBblacs.h:26