SCALAPACK 2.2.2
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
psgemm_.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__
20void psgemm_( F_CHAR_T TRANSA, F_CHAR_T TRANSB,
21 Int * M, Int * N, Int * K,
22 float * ALPHA,
23 float * A, Int * IA, Int * JA, Int * DESCA,
24 float * B, Int * IB, Int * JB, Int * DESCB,
25 float * BETA,
26 float * C, Int * IC, Int * JC, Int * DESCC )
27#else
28void psgemm_( TRANSA, TRANSB, M, N, K, ALPHA, A, IA, JA, DESCA,
29 B, IB, JB, DESCB, BETA, C, IC, JC, DESCC )
30/*
31* .. Scalar Arguments ..
32*/
33 F_CHAR_T TRANSA, TRANSB;
34 Int * IA, * IB, * IC, * JA, * JB, * JC, * K, * M, * N;
35 float * ALPHA, * BETA;
36/*
37* .. Array Arguments ..
38*/
39 Int * DESCA, * DESCB, * DESCC;
40 float * A, * B, * C;
41#endif
42{
43/*
44* Purpose
45* =======
46*
47* PSGEMM performs one of the matrix-matrix operations
48*
49* sub( C ) := alpha*op( sub( A ) )*op( sub( B ) ) + beta*sub( C ),
50*
51* where
52*
53* sub( C ) denotes C(IC:IC+M-1,JC:JC+N-1), and, op( X ) is one of
54* op( X ) = X or op( X ) = X'.
55*
56* Thus, op( sub( A ) ) denotes A(IA:IA+M-1,JA:JA+K-1) if TRANSA = 'N',
57* A(IA:IA+K-1,JA:JA+M-1)' if TRANSA = 'T',
58* A(IA:IA+K-1,JA:JA+M-1)' if TRANSA = 'C',
59*
60* and, op( sub( B ) ) denotes B(IB:IB+K-1,JB:JB+N-1) if TRANSB = 'N',
61* B(IB:IB+N-1,JB:JB+K-1)' if TRANSB = 'T',
62* B(IB:IB+N-1,JB:JB+K-1)' if TRANSB = 'C',
63*
64* Alpha and beta are scalars. A, B and C are matrices; op( sub( A ) )
65* is an m by k submatrix, op( sub( B ) ) is an k by n submatrix and
66* sub( C ) is an m by n submatrix.
67*
68* Notes
69* =====
70*
71* A description vector is associated with each 2D block-cyclicly dis-
72* tributed matrix. This vector stores the information required to
73* establish the mapping between a matrix entry and its corresponding
74* process and memory location.
75*
76* In the following comments, the character _ should be read as
77* "of the distributed matrix". Let A be a generic term for any 2D
78* block cyclicly distributed matrix. Its description vector is DESC_A:
79*
80* NOTATION STORED IN EXPLANATION
81* ---------------- --------------- ------------------------------------
82* DTYPE_A (global) DESCA[ DTYPE_ ] The descriptor type.
83* CTXT_A (global) DESCA[ CTXT_ ] The BLACS context handle, indicating
84* the NPROW x NPCOL BLACS process grid
85* A is distributed over. The context
86* itself is global, but the handle
87* (the integer value) may vary.
88* M_A (global) DESCA[ M_ ] The number of rows in the distribu-
89* ted matrix A, M_A >= 0.
90* N_A (global) DESCA[ N_ ] The number of columns in the distri-
91* buted matrix A, N_A >= 0.
92* IMB_A (global) DESCA[ IMB_ ] The number of rows of the upper left
93* block of the matrix A, IMB_A > 0.
94* INB_A (global) DESCA[ INB_ ] The number of columns of the upper
95* left block of the matrix A,
96* INB_A > 0.
97* MB_A (global) DESCA[ MB_ ] The blocking factor used to distri-
98* bute the last M_A-IMB_A rows of A,
99* MB_A > 0.
100* NB_A (global) DESCA[ NB_ ] The blocking factor used to distri-
101* bute the last N_A-INB_A columns of
102* A, NB_A > 0.
103* RSRC_A (global) DESCA[ RSRC_ ] The process row over which the first
104* row of the matrix A is distributed,
105* NPROW > RSRC_A >= 0.
106* CSRC_A (global) DESCA[ CSRC_ ] The process column over which the
107* first column of A is distributed.
108* NPCOL > CSRC_A >= 0.
109* LLD_A (local) DESCA[ LLD_ ] The leading dimension of the local
110* array storing the local blocks of
111* the distributed matrix A,
112* IF( Lc( 1, N_A ) > 0 )
113* LLD_A >= MAX( 1, Lr( 1, M_A ) )
114* ELSE
115* LLD_A >= 1.
116*
117* Let K be the number of rows of a matrix A starting at the global in-
118* dex IA,i.e, A( IA:IA+K-1, : ). Lr( IA, K ) denotes the number of rows
119* that the process of row coordinate MYROW ( 0 <= MYROW < NPROW ) would
120* receive if these K rows were distributed over NPROW processes. If K
121* is the number of columns of a matrix A starting at the global index
122* JA, i.e, A( :, JA:JA+K-1, : ), Lc( JA, K ) denotes the number of co-
123* lumns that the process MYCOL ( 0 <= MYCOL < NPCOL ) would receive if
124* these K columns were distributed over NPCOL processes.
125*
126* The values of Lr() and Lc() may be determined via a call to the func-
127* tion PB_Cnumroc:
128* Lr( IA, K ) = PB_Cnumroc( K, IA, IMB_A, MB_A, MYROW, RSRC_A, NPROW )
129* Lc( JA, K ) = PB_Cnumroc( K, JA, INB_A, NB_A, MYCOL, CSRC_A, NPCOL )
130*
131* Arguments
132* =========
133*
134* TRANSA (global input) CHARACTER*1
135* On entry, TRANSA specifies the form of op( sub( A ) ) to be
136* used in the matrix multiplication as follows:
137*
138* TRANSA = 'N' or 'n' op( sub( A ) ) = sub( A ),
139*
140* TRANSA = 'T' or 't' op( sub( A ) ) = sub( A )',
141*
142* TRANSA = 'C' or 'c' op( sub( A ) ) = sub( A )'.
143*
144* TRANSB (global input) CHARACTER*1
145* On entry, TRANSB specifies the form of op( sub( B ) ) to be
146* used in the matrix multiplication as follows:
147*
148* TRANSB = 'N' or 'n' op( sub( B ) ) = sub( B ),
149*
150* TRANSB = 'T' or 't' op( sub( B ) ) = sub( B )',
151*
152* TRANSB = 'C' or 'c' op( sub( B ) ) = sub( B )'.
153*
154* M (global input) INTEGER
155* On entry, M specifies the number of rows of the submatrix
156* op( sub( A ) ) and of the submatrix sub( C ). M must be at
157* least zero.
158*
159* N (global input) INTEGER
160* On entry, N specifies the number of columns of the submatrix
161* op( sub( B ) ) and the number of columns of the submatrix
162* sub( C ). N must be at least zero.
163*
164* K (global input) INTEGER
165* On entry, K specifies the number of columns of the submatrix
166* op( sub( A ) ) and the number of rows of the submatrix
167* op( sub( B ) ). K must be at least zero.
168*
169* ALPHA (global input) REAL
170* On entry, ALPHA specifies the scalar alpha. When ALPHA is
171* supplied as zero then the local entries of the arrays A and
172* B corresponding to the entries of the submatrices sub( A )
173* and sub( B ) respectively need not be set on input.
174*
175* A (local input) REAL array
176* On entry, A is an array of dimension (LLD_A, Ka), where Ka is
177* at least Lc( 1, JA+K-1 ) when TRANSA = 'N' or 'n', and is at
178* least Lc( 1, JA+M-1 ) otherwise. Before entry, this array
179* contains the local entries of the matrix A.
180*
181* IA (global input) INTEGER
182* On entry, IA specifies A's global row index, which points to
183* the beginning of the submatrix sub( A ).
184*
185* JA (global input) INTEGER
186* On entry, JA specifies A's global column index, which points
187* to the beginning of the submatrix sub( A ).
188*
189* DESCA (global and local input) INTEGER array
190* On entry, DESCA is an integer array of dimension DLEN_. This
191* is the array descriptor for the matrix A.
192*
193* B (local input) REAL array
194* On entry, B is an array of dimension (LLD_B, Kb), where Kb is
195* at least Lc( 1, JB+N-1 ) when TRANSB = 'N' or 'n', and is at
196* least Lc( 1, JB+K-1 ) otherwise. Before entry, this array
197* contains the local entries of the matrix B.
198*
199* IB (global input) INTEGER
200* On entry, IB specifies B's global row index, which points to
201* the beginning of the submatrix sub( B ).
202*
203* JB (global input) INTEGER
204* On entry, JB specifies B's global column index, which points
205* to the beginning of the submatrix sub( B ).
206*
207* DESCB (global and local input) INTEGER array
208* On entry, DESCB is an integer array of dimension DLEN_. This
209* is the array descriptor for the matrix B.
210*
211* BETA (global input) REAL
212* On entry, BETA specifies the scalar beta. When BETA is
213* supplied as zero then the local entries of the array C
214* corresponding to the entries of the submatrix sub( C ) need
215* not be set on input.
216*
217* C (local input/local output) REAL array
218* On entry, C is an array of dimension (LLD_C, Kc), where Kc is
219* at least Lc( 1, JC+N-1 ). Before entry, this array contains
220* the local entries of the matrix C.
221* On exit, the entries of this array corresponding to the local
222* entries of the submatrix sub( C ) are overwritten by the
223* local entries of the m by n updated submatrix.
224*
225* IC (global input) INTEGER
226* On entry, IC specifies C's global row index, which points to
227* the beginning of the submatrix sub( C ).
228*
229* JC (global input) INTEGER
230* On entry, JC specifies C's global column index, which points
231* to the beginning of the submatrix sub( C ).
232*
233* DESCC (global and local input) INTEGER array
234* On entry, DESCC is an integer array of dimension DLEN_. This
235* is the array descriptor for the matrix C.
236*
237* -- Written on April 1, 1998 by
238* Antoine Petitet, University of Tennessee, Knoxville 37996, USA.
239*
240* ---------------------------------------------------------------------
241*/
242/*
243* .. Local Scalars ..
244*/
245 char DirAB, DirBC, OpC, OpR, TrA, TrB, ctop, ctopsave, rtop,
246 rtopsave;
247 Int Ai, Aj, Bi, Bj, ChooseAB, ChooseBC, Ci, Cj, ForceTop, ctxt,
248 info, mycol, myrow, nb, nota, notb, npcol, nprow;
249 double ABest, ACest, BCest, tmp1, tmp2, tmp3, tmp4;
250 PBTYP_T * type;
251/*
252* .. Local Arrays ..
253*/
254 Int Ad[DLEN_], Bd[DLEN_], Cd[DLEN_];
255/* ..
256* .. Executable Statements ..
257*
258*/
259 nota = ( ( TrA = Mupcase( F2C_CHAR( TRANSA )[0] ) ) == CNOTRAN );
260 notb = ( ( TrB = Mupcase( F2C_CHAR( TRANSB )[0] ) ) == CNOTRAN );
261 PB_CargFtoC( *IA, *JA, DESCA, &Ai, &Aj, Ad );
262 PB_CargFtoC( *IB, *JB, DESCB, &Bi, &Bj, Bd );
263 PB_CargFtoC( *IC, *JC, DESCC, &Ci, &Cj, Cd );
264#ifndef NO_ARGCHK
265/*
266* Test the input parameters
267*/
268 Cblacs_gridinfo( ( ctxt = Ad[CTXT_] ), &nprow, &npcol, &myrow,
269 &mycol );
270 if( !( info = ( ( nprow == -1 ) ? -( 1001 + CTXT_ ) : 0 ) ) )
271 {
272 if( ( !nota ) && ( TrA != CTRAN ) && ( TrA != CCOTRAN ) )
273 {
274 PB_Cwarn( ctxt, __LINE__, "PSGEMM", "Illegal TRANSA = %c\n", TrA );
275 info = -1;
276 }
277 else if( ( !notb ) && ( TrB != CTRAN ) && ( TrB != CCOTRAN ) )
278 {
279 PB_Cwarn( ctxt, __LINE__, "PSGEMM", "Illegal TRANSB = %c\n", TrB );
280 info = -2;
281 }
282 if( nota )
283 PB_Cchkmat( ctxt, "PSGEMM", "A", *M, 3, *K, 5, Ai, Aj, Ad, 10,
284 &info );
285 else
286 PB_Cchkmat( ctxt, "PSGEMM", "A", *K, 5, *M, 3, Ai, Aj, Ad, 10,
287 &info );
288 if( notb )
289 PB_Cchkmat( ctxt, "PSGEMM", "B", *K, 5, *N, 4, Bi, Bj, Bd, 14,
290 &info );
291 else
292 PB_Cchkmat( ctxt, "PSGEMM", "B", *N, 4, *K, 5, Bi, Bj, Bd, 14,
293 &info );
294 PB_Cchkmat( ctxt, "PSGEMM", "C", *M, 3, *N, 4, Ci, Cj, Cd, 19,
295 &info );
296 }
297 if( info ) { PB_Cabort( ctxt, "PSGEMM", info ); return; }
298#endif
299/*
300* Quick return if possible
301*/
302 if( ( *M == 0 ) || ( *N == 0 ) ||
303 ( ( ALPHA[REAL_PART] == ZERO || *K == 0 ) &&
304 ( BETA [REAL_PART] == ONE ) ) )
305 return;
306/*
307* Get type structure
308*/
309 type = PB_Cstypeset();
310/*
311* If alpha or K is zero, sub( C ) := beta * sub( C ).
312*/
313 if( ( ALPHA[REAL_PART] == ZERO ) || ( *K == 0 ) )
314 {
315 if( BETA[REAL_PART] == ZERO )
316 {
317 PB_Cplapad( type, ALL, NOCONJG, *M, *N, type->zero, type->zero,
318 ((char * ) C), Ci, Cj, Cd );
319 }
320 else if( !( BETA[REAL_PART] == ONE ) )
321 {
322 PB_Cplascal( type, ALL, NOCONJG, *M, *N, ((char *) BETA),
323 ((char * ) C), Ci, Cj, Cd );
324 }
325 return;
326 }
327/*
328* Start the operations
329*/
330#ifdef NO_ARGCHK
331 Cblacs_gridinfo( ( ctxt = Ad[CTXT_] ), &nprow, &npcol, &myrow, &mycol );
332#endif
333/*
334* Algorithm selection is based on approximation of the communication volume
335* for distributed and aligned operands.
336*
337* ABest: both operands sub( A ) and sub( B ) are communicated (M, N >> K)
338* ACest: both operands sub( A ) and sub( C ) are communicated (K, N >> M)
339* BCest: both operands sub( B ) and sub( C ) are communicated (M, K >> N)
340*/
341 ABest = (double)(*K);
342 ACest = (double)(*M);
343 BCest = (double)(*N);
344
345 if( notb )
346 {
347 if( nota )
348 {
349 tmp1 = DNROC( *M, Cd[MB_], nprow ); tmp2 = DNROC( *N, Cd[NB_], npcol );
350 ABest *= ( ( ( Ad[CSRC_] == -1 ) || ( npcol == 1 ) ) ? ZERO : tmp1 ) +
351 ( ( ( Bd[RSRC_] == -1 ) || ( nprow == 1 ) ) ? ZERO : tmp2 );
352
353 tmp1 = DNROC( *K, Bd[MB_], nprow ); tmp2 = DNROC( *N, Bd[NB_], npcol );
354 tmp3 = DNROC( *K, Ad[NB_], npcol );
355 ACest *= ( npcol == 1 ? ZERO : tmp1 ) + MAX( tmp1, tmp3 ) +
356 CBRATIO * ( nprow == 1 ? ZERO : tmp2 );
357
358 tmp1 = DNROC( *M, Ad[MB_], nprow ); tmp2 = DNROC( *K, Ad[NB_], npcol );
359 tmp4 = DNROC( *K, Bd[MB_], nprow );
360 BCest *= CBRATIO * ( npcol == 1 ? ZERO : tmp1 ) +
361 ( nprow == 1 ? ZERO : tmp2 ) + MAX( tmp2, tmp4 );
362 }
363 else
364 {
365 tmp1 = DNROC( *M, Cd[MB_], nprow ); tmp2 = DNROC( *N, Cd[NB_], npcol );
366 tmp3 = DNROC( *M, Ad[NB_], npcol );
367 ABest *= ( npcol == 1 ? ZERO : tmp1 ) + MAX( tmp1, tmp3 ) +
368 ( nprow == 1 ? ZERO : tmp2 );
369
370 tmp1 = DNROC( *K, Bd[MB_], nprow ); tmp2 = DNROC( *N, Bd[NB_], npcol );
371 ACest *= ( ( ( Ad[CSRC_] == -1 ) || ( npcol == 1 ) ) ? ZERO : tmp1 ) +
372 CBRATIO *
373 ( ( ( Bd[RSRC_] == -1 ) || ( nprow == 1 ) ) ? ZERO : tmp2 );
374
375 tmp1 = DNROC( *K, Ad[MB_], nprow ); tmp2 = DNROC( *M, Bd[NB_], npcol );
376 tmp4 = DNROC( *M, Cd[MB_], nprow );
377 BCest *= ( ( ( Bd[CSRC_] == -1 ) || ( npcol == 1 ) ) ? ZERO : tmp1 ) +
378 CBRATIO * ( nprow == 1 ? ZERO : tmp2 ) + MAX( tmp2, tmp4 );
379 }
380 }
381 else
382 {
383 if( nota )
384 {
385 tmp1 = DNROC( *M, Cd[MB_], nprow ); tmp2 = DNROC( *N, Cd[NB_], npcol );
386 tmp4 = DNROC( *N, Bd[MB_], nprow );
387 ABest *= ( npcol == 1 ? ZERO : tmp1 ) +
388 ( nprow == 1 ? ZERO : tmp2 ) + MAX( tmp2, tmp4 );
389
390 tmp1 = DNROC( *N, Bd[MB_], nprow ); tmp2 = DNROC( *K, Bd[NB_], npcol );
391 tmp3 = DNROC( *N, Cd[NB_], npcol );
392 ACest *= CBRATIO * ( npcol == 1 ? ZERO : tmp1 ) + MAX( tmp1, tmp3 ) +
393 ( ( ( Ad[RSRC_] == -1 ) || ( nprow == 1 ) ) ? ZERO : tmp2 );
394
395 tmp1 = DNROC( *M, Ad[MB_], nprow ); tmp2 = DNROC( *K, Ad[NB_], npcol );
396 BCest *= CBRATIO *
397 ( ( ( Ad[CSRC_] == -1 ) || ( npcol == 1 ) ) ? ZERO : tmp1 ) +
398 ( ( ( Bd[RSRC_] == -1 ) || ( nprow == 1 ) ) ? ZERO : tmp2 );
399 }
400 else
401 {
402 tmp1 = DNROC( *M, Cd[MB_], nprow ); tmp2 = DNROC( *N, Cd[NB_], npcol );
403 tmp3 = DNROC( *M, Ad[NB_], npcol ); tmp4 = DNROC( *N, Bd[MB_], nprow );
404 ABest *= ( npcol == 1 ? ZERO : tmp1 ) + MAX( tmp1, tmp3 ) +
405 ( nprow == 1 ? ZERO : tmp2 ) + MAX( tmp2, tmp4 );
406
407 tmp1 = DNROC( *N, Bd[MB_], nprow ); tmp2 = DNROC( *K, Bd[NB_], npcol );
408 tmp3 = DNROC( *N, Cd[NB_], npcol ); tmp4 = DNROC( *K, Ad[MB_], nprow );
409 ACest *= CBRATIO * ( npcol == 1 ? ZERO : tmp1 ) + MAX( tmp1, tmp3 ) +
410 ( nprow == 1 ? ZERO : tmp2 ) + MAX( tmp2, tmp4 );
411
412 tmp1 = DNROC( *K, Ad[MB_], nprow ); tmp2 = DNROC( *M, Ad[NB_], npcol );
413 tmp3 = DNROC( *K, Bd[NB_], npcol ); tmp4 = DNROC( *M, Cd[MB_], nprow );
414 BCest *= ( npcol == 1 ? ZERO : tmp1 ) + MAX( tmp1, tmp3 ) +
415 CBRATIO * ( nprow == 1 ? ZERO : tmp2 ) + MAX( tmp2, tmp4 );
416 }
417 }
418 ChooseAB = ( ( ABest <= ( 1.3 * BCest ) ) && ( ABest <= ( 1.3 * ACest ) ) );
419 ChooseBC = ( ( BCest <= ACest ) && ( ( 1.3 * BCest ) <= ABest ) );
420/*
421* BLACS topologies are enforced iff M, N and K are strictly greater than the
422* logical block size returned by pilaenv_. Otherwise, it is assumed that the
423* routine calling this routine has already selected an adequate topology.
424*/
425 nb = pilaenv_( &ctxt, C2F_CHAR( &type->type ) );
426 ForceTop = ( ( *M > nb ) && ( *N > nb ) && ( *K > nb ) );
427
428 if( ChooseAB )
429 {
430 OpR = CBCAST;
431 OpC = CBCAST;
432 }
433 else if( ChooseBC )
434 {
435 if( nota ) { OpR = CCOMBINE; OpC = CBCAST; }
436 else { OpR = CBCAST; OpC = CCOMBINE; }
437 }
438 else
439 {
440 if( notb ) { OpR = CBCAST; OpC = CCOMBINE; }
441 else { OpR = CCOMBINE; OpC = CBCAST; }
442 }
443
444 rtop = *PB_Ctop( &ctxt, &OpR, ROW, TOP_GET );
445 ctop = *PB_Ctop( &ctxt, &OpC, COLUMN, TOP_GET );
446
447 if( ForceTop )
448 {
449 rtopsave = rtop;
450 ctopsave = ctop;
451/*
452* No clear winner for the ring topologies, so that if a ring topology is
453* already selected, keep it.
454*/
455 if( ( rtop != CTOP_DRING ) && ( rtop != CTOP_IRING ) &&
456 ( rtop != CTOP_SRING ) )
457 rtop = *PB_Ctop( &ctxt, &OpR, ROW, TOP_IRING );
458 if( ( ctop != CTOP_DRING ) && ( ctop != CTOP_IRING ) &&
459 ( ctop != CTOP_SRING ) )
460 ctop = *PB_Ctop( &ctxt, &OpC, COLUMN, TOP_IRING );
461/*
462* Remove the next 4 lines when the BLACS combine operations support ring
463* topologies
464*/
465 if( OpR == CCOMBINE )
466 rtop = *PB_Ctop( &ctxt, &OpR, ROW, TOP_DEFAULT );
467 if( OpC == CCOMBINE )
468 ctop = *PB_Ctop( &ctxt, &OpC, COLUMN, TOP_DEFAULT );
469 }
470
471 DirAB = ( rtop == CTOP_DRING ? CBACKWARD : CFORWARD );
472 DirBC = ( ctop == CTOP_DRING ? CBACKWARD : CFORWARD );
473
474 if( ChooseAB )
475 {
476 PB_CpgemmAB( type, &DirAB, &DirBC, ( nota ? NOTRAN : TRAN ), ( notb ?
477 NOTRAN : TRAN ), *M, *N, *K, ((char *)ALPHA), ((char *)A),
478 Ai, Aj, Ad, ((char *)B), Bi, Bj, Bd, ((char *)BETA),
479 ((char *)C), Ci, Cj, Cd );
480 }
481 else if( ChooseBC )
482 {
483 PB_CpgemmBC( type, &DirAB, &DirBC, ( nota ? NOTRAN : TRAN ), ( notb ?
484 NOTRAN : TRAN ), *M, *N, *K, ((char *)ALPHA), ((char *)A),
485 Ai, Aj, Ad, ((char *)B), Bi, Bj, Bd, ((char *)BETA),
486 ((char *)C), Ci, Cj, Cd );
487 }
488 else
489 {
490 PB_CpgemmAC( type, &DirAB, &DirBC, ( nota ? NOTRAN : TRAN ), ( notb ?
491 NOTRAN : TRAN ), *M, *N, *K, ((char *)ALPHA), ((char *)A),
492 Ai, Aj, Ad, ((char *)B), Bi, Bj, Bd, ((char *)BETA),
493 ((char *)C), Ci, Cj, Cd );
494 }
495/*
496* Restore the BLACS topologies when necessary.
497*/
498 if( ForceTop )
499 {
500 rtopsave = *PB_Ctop( &ctxt, &OpR, ROW, &rtopsave );
501 ctopsave = *PB_Ctop( &ctxt, &OpC, COLUMN, &ctopsave );
502 }
503/*
504* End of PSGEMM
505*/
506}
#define Int
Definition Bconfig.h:22
#define REAL_PART
Definition pblas.h:139
#define F2C_CHAR(a)
Definition pblas.h:124
#define CBRATIO
Definition pblas.h:37
#define C2F_CHAR(a)
Definition pblas.h:125
char * F_CHAR_T
Definition pblas.h:122
#define TOP_GET
Definition PBblacs.h:50
#define COLUMN
Definition PBblacs.h:45
#define TOP_IRING
Definition PBblacs.h:52
#define CTOP_SRING
Definition PBblacs.h:29
#define TOP_DEFAULT
Definition PBblacs.h:51
#define CCOMBINE
Definition PBblacs.h:24
#define ROW
Definition PBblacs.h:46
#define CBCAST
Definition PBblacs.h:23
void Cblacs_gridinfo()
#define CTOP_IRING
Definition PBblacs.h:27
#define CTOP_DRING
Definition PBblacs.h:28
#define NOTRAN
Definition PBblas.h:44
#define ALL
Definition PBblas.h:50
#define TRAN
Definition PBblas.h:46
#define CBACKWARD
Definition PBblas.h:39
#define NOCONJG
Definition PBblas.h:45
#define CNOTRAN
Definition PBblas.h:18
#define CTRAN
Definition PBblas.h:20
#define CCOTRAN
Definition PBblas.h:22
#define CFORWARD
Definition PBblas.h:38
#define pilaenv_
Definition PBpblas.h:44
#define psgemm_
Definition PBpblas.h:146
#define CTXT_
Definition PBtools.h:38
#define MAX(a_, b_)
Definition PBtools.h:77
#define MB_
Definition PBtools.h:43
void PB_Cabort()
#define ONE
Definition PBtools.h:64
void PB_Cchkmat()
void PB_Cwarn()
char * PB_Ctop()
void PB_Cplapad()
PBTYP_T * PB_Cstypeset()
void PB_Cplascal()
#define RSRC_
Definition PBtools.h:45
void PB_CargFtoC()
#define CSRC_
Definition PBtools.h:46
void PB_CpgemmAB()
#define ZERO
Definition PBtools.h:66
void PB_CpgemmAC()
void PB_CpgemmBC()
#define Mupcase(C)
Definition PBtools.h:83
#define DLEN_
Definition PBtools.h:48
#define NB_
Definition PBtools.h:44
#define DNROC(n_, nb_, p_)
Definition PBtools.h:111
char type
Definition pblas.h:331
char * zero
Definition pblas.h:335