ScaLAPACK 2.1  2.1
ScaLAPACK: Scalable Linear Algebra PACKage
PB_Cpdot11.c
Go to the documentation of this file.
1 /* ---------------------------------------------------------------------
2 *
3 * -- PBLAS auxiliary 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 PB_Cpdot11( PBTYP_T * TYPE, int N, char * DOT,
21  char * X, int IX, int JX, int * DESCX, int INCX,
22  char * Y, int IY, int JY, int * DESCY, int INCY,
23  VVDOT_T FDOT )
24 #else
25 void PB_Cpdot11( TYPE, N, DOT, X, IX, JX, DESCX, INCX, Y, IY, JY, DESCY,
26  INCY, FDOT )
27 /*
28 * .. Scalar Arguments ..
29 */
30  int INCX, INCY, IX, IY, JX, JY, N;
31  char * DOT;
32  PBTYP_T * TYPE;
33  VVDOT_T FDOT;
34 /*
35 * .. Array Arguments ..
36 */
37  int * DESCX, * DESCY;
38  char * X, * Y;
39 #endif
40 {
41 /*
42 * Purpose
43 * =======
44 *
45 * PB_Cpdot11 forms the dot product of two subvectors,
46 *
47 * DOT := sub( X )**T * sub( Y ) or DOT := sub( X )**H * sub( Y ),
48 *
49 * where
50 *
51 * sub( X ) denotes X(IX,JX:JX+N-1) if INCX = M_X,
52 * X(IX:IX+N-1,JX) if INCX = 1 and INCX <> M_X, and,
53 *
54 * sub( Y ) denotes Y(IY,JY:JY+N-1) if INCY = M_Y,
55 * Y(IY:IY+N-1,JY) if INCY = 1 and INCY <> M_Y.
56 *
57 * One subvector at least is assumed to be degenerated.
58 *
59 * Notes
60 * =====
61 *
62 * A description vector is associated with each 2D block-cyclicly dis-
63 * tributed matrix. This vector stores the information required to
64 * establish the mapping between a matrix entry and its corresponding
65 * process and memory location.
66 *
67 * In the following comments, the character _ should be read as
68 * "of the distributed matrix". Let A be a generic term for any 2D
69 * block cyclicly distributed matrix. Its description vector is DESC_A:
70 *
71 * NOTATION STORED IN EXPLANATION
72 * ---------------- --------------- ------------------------------------
73 * DTYPE_A (global) DESCA[ DTYPE_ ] The descriptor type.
74 * CTXT_A (global) DESCA[ CTXT_ ] The BLACS context handle, indicating
75 * the NPROW x NPCOL BLACS process grid
76 * A is distributed over. The context
77 * itself is global, but the handle
78 * (the integer value) may vary.
79 * M_A (global) DESCA[ M_ ] The number of rows in the distribu-
80 * ted matrix A, M_A >= 0.
81 * N_A (global) DESCA[ N_ ] The number of columns in the distri-
82 * buted matrix A, N_A >= 0.
83 * IMB_A (global) DESCA[ IMB_ ] The number of rows of the upper left
84 * block of the matrix A, IMB_A > 0.
85 * INB_A (global) DESCA[ INB_ ] The number of columns of the upper
86 * left block of the matrix A,
87 * INB_A > 0.
88 * MB_A (global) DESCA[ MB_ ] The blocking factor used to distri-
89 * bute the last M_A-IMB_A rows of A,
90 * MB_A > 0.
91 * NB_A (global) DESCA[ NB_ ] The blocking factor used to distri-
92 * bute the last N_A-INB_A columns of
93 * A, NB_A > 0.
94 * RSRC_A (global) DESCA[ RSRC_ ] The process row over which the first
95 * row of the matrix A is distributed,
96 * NPROW > RSRC_A >= 0.
97 * CSRC_A (global) DESCA[ CSRC_ ] The process column over which the
98 * first column of A is distributed.
99 * NPCOL > CSRC_A >= 0.
100 * LLD_A (local) DESCA[ LLD_ ] The leading dimension of the local
101 * array storing the local blocks of
102 * the distributed matrix A,
103 * IF( Lc( 1, N_A ) > 0 )
104 * LLD_A >= MAX( 1, Lr( 1, M_A ) )
105 * ELSE
106 * LLD_A >= 1.
107 *
108 * Let K be the number of rows of a matrix A starting at the global in-
109 * dex IA,i.e, A( IA:IA+K-1, : ). Lr( IA, K ) denotes the number of rows
110 * that the process of row coordinate MYROW ( 0 <= MYROW < NPROW ) would
111 * receive if these K rows were distributed over NPROW processes. If K
112 * is the number of columns of a matrix A starting at the global index
113 * JA, i.e, A( :, JA:JA+K-1, : ), Lc( JA, K ) denotes the number of co-
114 * lumns that the process MYCOL ( 0 <= MYCOL < NPCOL ) would receive if
115 * these K columns were distributed over NPCOL processes.
116 *
117 * The values of Lr() and Lc() may be determined via a call to the func-
118 * tion PB_Cnumroc:
119 * Lr( IA, K ) = PB_Cnumroc( K, IA, IMB_A, MB_A, MYROW, RSRC_A, NPROW )
120 * Lc( JA, K ) = PB_Cnumroc( K, JA, INB_A, NB_A, MYCOL, CSRC_A, NPCOL )
121 *
122 * Arguments
123 * =========
124 *
125 * TYPE (local input) pointer to a PBTYP_T structure
126 * On entry, TYPE is a pointer to a structure of type PBTYP_T,
127 * that contains type information (See pblas.h).
128 *
129 * N (global input) INTEGER
130 * On entry, N specifies the length of the subvectors to be
131 * multiplied. N must be at least zero.
132 *
133 * DOT (local output) pointer to CHAR
134 * On exit, DOT specifies the dot product of the two subvectors
135 * sub( X ) and sub( Y ) only in their scope (See below for fur-
136 * ther details).
137 *
138 * X (local input) pointer to CHAR
139 * On entry, X is an array of dimension (LLD_X, Kx), where LLD_X
140 * is at least MAX( 1, Lr( 1, IX ) ) when INCX = M_X and
141 * MAX( 1, Lr( 1, IX+N-1 ) ) otherwise, and, Kx is at least
142 * Lc( 1, JX+N-1 ) when INCX = M_X and Lc( 1, JX ) otherwise.
143 * Before entry, this array contains the local entries of the
144 * matrix X.
145 *
146 * IX (global input) INTEGER
147 * On entry, IX specifies X's global row index, which points to
148 * the beginning of the submatrix sub( X ).
149 *
150 * JX (global input) INTEGER
151 * On entry, JX specifies X's global column index, which points
152 * to the beginning of the submatrix sub( X ).
153 *
154 * DESCX (global and local input) INTEGER array
155 * On entry, DESCX is an integer array of dimension DLEN_. This
156 * is the array descriptor for the matrix X.
157 *
158 * INCX (global input) INTEGER
159 * On entry, INCX specifies the global increment for the
160 * elements of X. Only two values of INCX are supported in
161 * this version, namely 1 and M_X. INCX must not be zero.
162 *
163 * Y (local input) pointer to CHAR
164 * On entry, Y is an array of dimension (LLD_Y, Ky), where LLD_Y
165 * is at least MAX( 1, Lr( 1, IY ) ) when INCY = M_Y and
166 * MAX( 1, Lr( 1, IY+N-1 ) ) otherwise, and, Ky is at least
167 * Lc( 1, JY+N-1 ) when INCY = M_Y and Lc( 1, JY ) otherwise.
168 * Before entry, this array contains the local entries of the
169 * matrix Y.
170 *
171 * IY (global input) INTEGER
172 * On entry, IY specifies Y's global row index, which points to
173 * the beginning of the submatrix sub( Y ).
174 *
175 * JY (global input) INTEGER
176 * On entry, JY specifies Y's global column index, which points
177 * to the beginning of the submatrix sub( Y ).
178 *
179 * DESCY (global and local input) INTEGER array
180 * On entry, DESCY is an integer array of dimension DLEN_. This
181 * is the array descriptor for the matrix Y.
182 *
183 * INCY (global input) INTEGER
184 * On entry, INCY specifies the global increment for the
185 * elements of Y. Only two values of INCY are supported in
186 * this version, namely 1 and M_Y. INCY must not be zero.
187 *
188 * FDOT (local input) pointer to a function of type VVDOT
189 * On entry, FDOT points to a subroutine that computes the local
190 * dot product of two vectors.
191 *
192 * Further Details
193 * ===============
194 *
195 * When the result of a vector-oriented PBLAS call is a scalar, this
196 * scalar is set only within the process scope which owns the vector(s)
197 * being operated on. Let sub( X ) be a generic term for the input vec-
198 * tor(s). Then, the processes owning the correct the answer is determi-
199 * ned as follows: if an operation involves more than one vector, the
200 * processes receiving the result will be the union of the following set
201 * of processes for each vector:
202 *
203 * If N = 1, M_X = 1 and INCX = 1, then one cannot determine if a pro-
204 * cess row or process column owns the vector operand, therefore only
205 * the process owning sub( X ) receives the correct result;
206 *
207 * If INCX = M_X, then sub( X ) is a vector distributed over a process
208 * row. Each process in this row receives the result;
209 *
210 * If INCX = 1, then sub( X ) is a vector distributed over a process
211 * column. Each process in this column receives the result;
212 *
213 * -- Written on April 1, 1998 by
214 * Antoine Petitet, University of Tennessee, Knoxville 37996, USA.
215 *
216 * ---------------------------------------------------------------------
217 */
218 /*
219 * .. Local Scalars ..
220 */
221  char Xscope, Yscope, * top;
222  int RRorCC, Xcol, Xii, XisD, XisOne, XisR, XisRow, Xjj, Xld,
223  Xlinc, XmyprocD, XmyprocR, XprocD, XprocR, Xrow, Ycol, Yii,
224  YisD, YisOne, YisR, YisRow, Yjj, YmyprocD, YmyprocR, YprocD,
225  YprocR, Yrow, cdst, ctxt, ione=1, mycol, myrow, npcol, nprow,
226  rdst;
227 /*
228 * .. Local Arrays ..
229 */
230  int dbuf[DLEN_];
231  char * buf = NULL;
232 /* ..
233 * .. Executable Statements ..
234 *
235 */
236 /*
237 * Retrieve process grid information
238 */
239  Cblacs_gridinfo( ( ctxt = DESCX[ CTXT_ ] ), &nprow, &npcol, &myrow, &mycol );
240 /*
241 * Retrieve sub( X )'s local information: Xii, Xjj, Xrow, Xcol ...
242 */
243  PB_Cinfog2l( IX, JX, DESCX, nprow, npcol, myrow, mycol, &Xii, &Xjj,
244  &Xrow, &Xcol );
245  if( ( XisRow = ( INCX == DESCX[ M_ ] ) ) != 0 )
246  {
247  Xld = DESCX[ LLD_ ]; Xlinc = Xld;
248  XprocD = Xcol; XmyprocD = mycol; XprocR = Xrow; XmyprocR = myrow;
249  XisR = ( ( Xrow == -1 ) || ( nprow == 1 ) );
250  XisD = ( ( Xcol >= 0 ) && ( npcol > 1 ) );
251  }
252  else
253  {
254  Xld = DESCX[ LLD_ ]; Xlinc = 1;
255  XprocD = Xrow; XmyprocD = myrow; XprocR = Xcol; XmyprocR = mycol;
256  XisR = ( ( Xcol == -1 ) || ( npcol == 1 ) );
257  XisD = ( ( Xrow >= 0 ) && ( nprow > 1 ) );
258  }
259  XisOne = ( ( N == 1 ) && ( DESCX[ M_ ] == 1 ) );
260 /*
261 * Retrieve sub( Y )'s local information: Yii, Yjj, Yrow, Ycol ...
262 */
263  PB_Cinfog2l( IY, JY, DESCY, nprow, npcol, myrow, mycol, &Yii, &Yjj,
264  &Yrow, &Ycol );
265  if( ( YisRow = ( INCY == DESCY[ M_ ] ) ) != 0 )
266  {
267  YprocD = Ycol; YmyprocD = mycol; YprocR = Yrow; YmyprocR = myrow;
268  YisR = ( ( Yrow == -1 ) || ( nprow == 1 ) );
269  YisD = ( ( Ycol >= 0 ) && ( npcol > 1 ) );
270  }
271  else
272  {
273  YprocD = Yrow; YmyprocD = myrow; YprocR = Ycol; YmyprocR = mycol;
274  YisR = ( ( Ycol == -1 ) || ( npcol == 1 ) );
275  YisD = ( ( Yrow >= 0 ) && ( nprow > 1 ) );
276  }
277  YisOne = ( ( N == 1 ) && ( DESCY[ M_ ] == 1 ) );
278 /*
279 * Are sub( X ) and sub( Y ) both row or column vectors ?
280 */
281  RRorCC = ( ( XisRow && YisRow ) || ( !( XisRow ) && !( YisRow ) ) );
282 /*
283 * Copy sub( Y ) in sub( X )'s scope
284 */
285  PB_Cdescset( dbuf, 1, 1, 1, 1, 1, 1, Xrow, Xcol, ctxt, 1 );
286  buf = PB_Cmalloc( TYPE->size );
287  PB_Cpaxpby( TYPE, NOCONJG, 1, 1, TYPE->one, Y, IY, JY, DESCY, ( YisRow ?
288  ROW : COLUMN ), TYPE->zero, buf, 0, 0, dbuf, ( XisRow ? ROW :
289  COLUMN ) );
290 /*
291 * Compute the dot product in sub( X )'s scope
292 */
293  if( XisR || ( XmyprocR == XprocR ) )
294  {
295  if( ( XisD && ( XmyprocD == XprocD ) ) || ( !XisD ) )
296  FDOT( &ione, DOT, Mptr( X, Xii, Xjj, Xld, TYPE->size ), &Xlinc, buf,
297  &ione );
298  if( XisD && !XisOne )
299  {
300  Xscope = ( XisRow ? CROW : CCOLUMN );
301  top = PB_Ctop( &ctxt, COMBINE, &Xscope, TOP_GET );
302  TYPE->Cgsum2d( ctxt, &Xscope, top, 1, 1, DOT, 1, -1, 0 );
303  }
304  }
305  if( buf ) free( buf );
306 /*
307 * sub( X ) or sub( Y ) is a degenerated vector
308 */
309  if( XisD && XisOne )
310  {
311 /*
312 * Since XisOne, sub( X ) must be a row vector
313 */
314  if( XisR )
315  {
316 /*
317 * sub( X ) resides in one process column ( *, XprocD )
318 */
319  if( RRorCC )
320  {
321 /*
322 * sub( Y ) is a row vector as well
323 */
324  if( YisR || YmyprocR == YprocR )
325  {
326 /*
327 * I am a process row owning sub( Y )
328 */
329  if( YisD && YisOne )
330  {
331 /*
332 * sub( Y ) resides in a process column ( *, YprocD )
333 */
334  if( XprocD != YprocD )
335  {
336  if( XmyprocD == XprocD )
337  TYPE->Cgesd2d( ctxt, 1, 1, DOT, 1, XmyprocR, YprocD );
338  else if( YmyprocD == YprocD )
339  TYPE->Cgerv2d( ctxt, 1, 1, DOT, 1, XmyprocR, XprocD );
340  }
341  }
342  else
343  {
344 /*
345 * Every process in those rows needs the answer
346 */
347  top = PB_Ctop( &ctxt, BCAST, ROW, TOP_GET );
348  if( XmyprocD == XprocD )
349  TYPE->Cgebs2d( ctxt, ROW, top, 1, 1, DOT, 1 );
350  else
351  TYPE->Cgebr2d( ctxt, ROW, top, 1, 1, DOT, 1, XmyprocR,
352  XprocD );
353  }
354  }
355  }
356  else
357  {
358 /*
359 * sub( Y ) is a column vector
360 */
361  if( YisR )
362  {
363 /*
364 * sub( Y ) resides in every process column
365 */
366  top = PB_Ctop( &ctxt, BCAST, ROW, TOP_GET );
367  if( XmyprocD == XprocD )
368  TYPE->Cgebs2d( ctxt, ROW, top, 1, 1, DOT, 1 );
369  else
370  TYPE->Cgebr2d( ctxt, ROW, top, 1, 1, DOT, 1, XmyprocR,
371  XprocD );
372  }
373  else if( XprocD != YprocR )
374  {
375 /*
376 * sub( Y ) resides in process column YprocR
377 */
378  if( XmyprocD == XprocD )
379  TYPE->Cgesd2d( ctxt, 1, 1, DOT, 1, XmyprocR, YprocR );
380  if( YmyprocR == YprocR )
381  TYPE->Cgerv2d( ctxt, 1, 1, DOT, 1, XmyprocR, XprocD );
382  }
383  }
384  }
385  else
386  {
387 /*
388 * sub( X ) resides in one process ( XprocR, XprocD )
389 */
390  if( YisD && YisOne )
391  {
392 /*
393 * sub( Y ) resides in one process ( YprocR, YprocD ) if it is not replicated,
394 * and in one process column ( *, YprocD ) otherwise
395 */
396  if( ( XprocD != YprocD ) || ( !YisR && ( XprocR != YprocR ) ) )
397  {
398 /*
399 * ( XprocR, XprocD ) sends DOT to ( YprocR, YprocD ) if sub( Y ) is not repli-
400 * cated, and to ( XprocR, YprocD ) otherwise
401 */
402  rdst = ( YisR ? XprocR : YprocR );
403  if( ( XmyprocR == XprocR ) && ( XmyprocD == XprocD ) )
404  TYPE->Cgesd2d( ctxt, 1, 1, DOT, 1, rdst, YprocD );
405  if( ( YmyprocR == rdst ) && ( YmyprocD == YprocD ) )
406  TYPE->Cgerv2d( ctxt, 1, 1, DOT, 1, XprocR, XprocD );
407  }
408 
409  if( YisR && ( YmyprocD == YprocD ) )
410  {
411 /*
412 * Broadcast DOT within process column owning sub( Y )
413 */
414  top = PB_Ctop( &ctxt, BCAST, COLUMN, TOP_GET );
415  if( XmyprocR == XprocR )
416  TYPE->Cgebs2d( ctxt, COLUMN, top, 1, 1, DOT, 1 );
417  else
418  TYPE->Cgebr2d( ctxt, COLUMN, top, 1, 1, DOT, 1, XprocR,
419  YprocD );
420  }
421  }
422  else if( !YisR )
423  {
424 /*
425 * sub( Y ) resides in one process row or column
426 */
427  if( YisRow ) { Yscope = CROW; rdst = YprocR; cdst = XprocD; }
428  else { Yscope = CCOLUMN; rdst = XprocR; cdst = YprocR; }
429 /*
430 * ( XprocR, XprocD ) sends DOT to ( YprocR, XprocD ) if sub( Y ) is a row
431 * vector and to ( XprocR, YprocR ) otherwise. If RRorCC, then YisRow and the
432 * send occurs iff XprocR != YprocR; Otherwise !YisRow, and the send occurs
433 * iff XprocD is not YprocR.
434 */
435  if( ( RRorCC && ( XprocR != YprocR ) ) ||
436  ( !( RRorCC ) && ( XprocD != YprocR ) ) )
437  {
438  if( ( XmyprocR == XprocR ) && ( XmyprocD == XprocD ) )
439  TYPE->Cgesd2d( ctxt, 1, 1, DOT, 1, rdst, cdst );
440  if( ( myrow == rdst ) && ( mycol == cdst ) )
441  TYPE->Cgerv2d( ctxt, 1, 1, DOT, 1, XprocR, XprocD );
442  }
443 /*
444 * Broadcast the result in sub( Y )'s scope
445 */
446  if( ( myrow == rdst ) && ( mycol == cdst ) )
447  {
448  top = PB_Ctop( &ctxt, BCAST, &Yscope, TOP_GET );
449  TYPE->Cgebs2d( ctxt, &Yscope, top, 1, 1, DOT, 1 );
450  }
451  else if( ( YisRow && ( myrow == rdst ) ) ||
452  ( !( YisRow ) && ( mycol == cdst ) ) )
453  {
454  top = PB_Ctop( &ctxt, BCAST, &Yscope, TOP_GET );
455  TYPE->Cgebr2d( ctxt, &Yscope, top, 1, 1, DOT, 1, rdst, cdst );
456  }
457  }
458  else
459  {
460 /*
461 * Every process in the grid needs the answer
462 */
463  top = PB_Ctop( &ctxt, BCAST, ALL, TOP_GET );
464  if( ( XmyprocR == XprocR ) && ( XmyprocD == XprocD ) )
465  {
466  TYPE->Cgebs2d( ctxt, ALL, top, 1, 1, DOT, 1 );
467  }
468  else
469  {
470  TYPE->Cgebr2d( ctxt, ALL, top, 1, 1, DOT, 1, XprocR, XprocD );
471  }
472  }
473  }
474  }
475  else
476  {
477 /*
478 * If XisR, then the result has already been sent in every process of the grid
479 */
480  if( XisR ) return;
481 
482  if( RRorCC )
483  {
484 /*
485 * If YisD && YisOne => YisRow => XisRow, communication orthogonal to sub( X )'s
486 * direction: only process column YprocD is involved.
487 */
488  if( YisD && YisOne && ( YmyprocD != YprocD ) ) return;
489 
490  if( YisR )
491  {
492 /*
493 * YisR and sub( Y ) is // to sub( X ) => bcast orthogonal to sub( X ) direction
494 */
495  if( XisRow )
496  {
497  top = PB_Ctop( &ctxt, BCAST, COLUMN, TOP_GET );
498  if( XmyprocR == XprocR )
499  TYPE->Cgebs2d( ctxt, COLUMN, top, 1, 1, DOT, 1 );
500  else
501  TYPE->Cgebr2d( ctxt, COLUMN, top, 1, 1, DOT, 1, XprocR,
502  XmyprocD );
503  }
504  else
505  {
506  top = PB_Ctop( &ctxt, BCAST, ROW, TOP_GET );
507  if( XmyprocR == XprocR )
508  TYPE->Cgebs2d( ctxt, ROW, top, 1, 1, DOT, 1 );
509  else
510  TYPE->Cgebr2d( ctxt, ROW, top, 1, 1, DOT, 1, XmyprocD,
511  XprocR );
512  }
513  }
514  else if( XprocR != YprocR )
515  {
516 /*
517 * Send from one column/row to another if they differ
518 */
519  if( XisRow )
520  {
521  if( XmyprocR == XprocR )
522  TYPE->Cgesd2d( ctxt, 1, 1, DOT, 1, YprocR, YmyprocD );
523  if( YmyprocR == YprocR )
524  TYPE->Cgerv2d( ctxt, 1, 1, DOT, 1, XprocR, XmyprocD );
525  }
526  else
527  {
528  if( XmyprocR == XprocR )
529  TYPE->Cgesd2d( ctxt, 1, 1, DOT, 1, YmyprocD, YprocR );
530  if( YmyprocR == YprocR )
531  TYPE->Cgerv2d( ctxt, 1, 1, DOT, 1, XmyprocD, XprocR );
532  }
533  }
534  }
535  else
536  {
537 /*
538 * If XisRow then !YisRow and thus bcast result in all rows if YisR or in
539 * process row YprocR otherwise. If !YisD || ( YisD && !YisOne ), then result
540 * should be sent in the same processes because they span a row or a column of
541 * the grid.
542 */
543  if( XisRow || !( YisD ) || ( YisD && !( YisOne ) ) )
544  {
545  if( YisR || YmyprocR == YprocR )
546  {
547  if( XisRow )
548  {
549  top = PB_Ctop( &ctxt, BCAST, COLUMN, TOP_GET );
550  if( XmyprocR == XprocR )
551  TYPE->Cgebs2d( ctxt, COLUMN, top, 1, 1, DOT, 1 );
552  else
553  TYPE->Cgebr2d( ctxt, COLUMN, top, 1, 1, DOT, 1, XprocR,
554  XmyprocD );
555  }
556  else
557  {
558  top = PB_Ctop( &ctxt, BCAST, ROW, TOP_GET );
559  if( XmyprocR == XprocR )
560  TYPE->Cgebs2d( ctxt, ROW, top, 1, 1, DOT, 1 );
561  else
562  TYPE->Cgebr2d( ctxt, ROW, top, 1, 1, DOT, 1, XmyprocD,
563  XprocR );
564  }
565  }
566  }
567  else if( XprocR != YprocD )
568  {
569 /*
570 * YisD && YisOne => YisRow => !XisRow, so the column of processes owning
571 * sub( X ) send the result to the column YprocD. The process rows involved
572 * in the operation depend on YisR.
573 */
574  if( YisR || YmyprocR == YprocR )
575  {
576  if( XmyprocR == XprocR )
577  {
578  TYPE->Cgesd2d( ctxt, 1, 1, DOT, 1, YmyprocR, YprocD );
579  }
580  if( YmyprocD == YprocD )
581  {
582  TYPE->Cgerv2d( ctxt, 1, 1, DOT, 1, YmyprocR, XprocR );
583  }
584  }
585  }
586  }
587  }
588 /*
589 * End of PB_Cpdot11
590 */
591 }
M_
#define M_
Definition: PBtools.h:39
TYPE
#define TYPE
Definition: clamov.c:7
ROW
#define ROW
Definition: PBblacs.h:46
PB_Cpaxpby
void PB_Cpaxpby()
COLUMN
#define COLUMN
Definition: PBblacs.h:45
NOCONJG
#define NOCONJG
Definition: PBblas.h:45
DLEN_
#define DLEN_
Definition: PBtools.h:48
LLD_
#define LLD_
Definition: PBtools.h:47
CROW
#define CROW
Definition: PBblacs.h:21
PB_Cdescset
void PB_Cdescset()
TOP_GET
#define TOP_GET
Definition: PBblacs.h:50
PB_Ctop
char * PB_Ctop()
BCAST
#define BCAST
Definition: PBblacs.h:48
VVDOT_T
F_VOID_FCT(* VVDOT_T)()
Definition: pblas.h:286
COMBINE
#define COMBINE
Definition: PBblacs.h:49
PB_Cinfog2l
void PB_Cinfog2l()
PB_Cmalloc
char * PB_Cmalloc()
ALL
#define ALL
Definition: PBblas.h:50
CCOLUMN
#define CCOLUMN
Definition: PBblacs.h:20
Cblacs_gridinfo
void Cblacs_gridinfo()
PBTYP_T
Definition: pblas.h:325
Mptr
#define Mptr(a_, i_, j_, lda_, siz_)
Definition: PBtools.h:132
PB_Cpdot11
void PB_Cpdot11(PBTYP_T *TYPE, int N, char *DOT, char *X, int IX, int JX, int *DESCX, int INCX, char *Y, int IY, int JY, int *DESCY, int INCY, VVDOT_T FDOT)
Definition: PB_Cpdot11.c:25
CTXT_
#define CTXT_
Definition: PBtools.h:38