|
ScaLAPACK
2.0.2
ScaLAPACK: Scalable Linear Algebra PACKage
|
00001 /* --------------------------------------------------------------------- 00002 * 00003 * -- PBLAS auxiliary routine (version 2.0) -- 00004 * University of Tennessee, Knoxville, Oak Ridge National Laboratory, 00005 * and University of California, Berkeley. 00006 * April 1, 1998 00007 * 00008 * --------------------------------------------------------------------- 00009 */ 00010 /* 00011 * Include files 00012 */ 00013 #include "../pblas.h" 00014 #include "../PBpblas.h" 00015 #include "../PBtools.h" 00016 #include "../PBblacs.h" 00017 #include "../PBblas.h" 00018 00019 #ifdef __STDC__ 00020 void PB_Cchkvec( int ICTXT, char * ROUT, char * VNAME, int N, int NPOS0, 00021 int IX, int JX, int * DESCX, int INCX, int DPOS0, 00022 int * INFO ) 00023 #else 00024 void PB_Cchkvec( ICTXT, ROUT, VNAME, N, NPOS0, IX, JX, DESCX, INCX, 00025 DPOS0, INFO ) 00026 /* 00027 * .. Scalar Arguments .. 00028 */ 00029 int DPOS0, ICTXT, IX, * INFO, INCX, JX, N, NPOS0; 00030 /* 00031 * .. Array Arguments .. 00032 */ 00033 char * ROUT, * VNAME; 00034 int * DESCX; 00035 #endif 00036 { 00037 /* 00038 * Purpose 00039 * ======= 00040 * 00041 * PB_Cchkvec checks the validity of a descriptor vector DESCX, the 00042 * related global indexes IX, JX and the global increment INCX. If an 00043 * inconsistency is found among its parameters IX, JX, DESCX and INCX, 00044 * the routine returns an error code in INFO. 00045 * 00046 * Arguments 00047 * ========= 00048 * 00049 * ICTXT (local input) INTEGER 00050 * On entry, ICTXT specifies the BLACS context handle, indica- 00051 * ting the global context of the operation. The context itself 00052 * is global, but the value of ICTXT is local. 00053 * 00054 * ROUT (global input) pointer to CHAR 00055 * On entry, ROUT specifies the name of the routine calling this 00056 * input error checking routine. 00057 * 00058 * VNAME (global input) pointer to CHAR 00059 * On entry, VNAME specifies the name of the formal array argu- 00060 * ment in the calling routine. 00061 * 00062 * N (global input) INTEGER 00063 * On entry, N specifies the length of the subvector sub( X ). 00064 * 00065 * NPOS0 (global input) INTEGER 00066 * On entry, NPOS0 specifies the position in the calling rou- 00067 * tine's parameter list where the formal parameter N appears. 00068 * 00069 * IX (global input) INTEGER 00070 * On entry, IX specifies X's global row index, which points to 00071 * the beginning of the submatrix sub( X ). 00072 * 00073 * JX (global input) INTEGER 00074 * On entry, JX specifies X's global column index, which points 00075 * to the beginning of the submatrix sub( X ). 00076 * 00077 * DESCX (global and local input) INTEGER array 00078 * On entry, DESCX is an integer array of dimension DLEN_. This 00079 * is the array descriptor for the matrix X. 00080 * 00081 * INCX (global input) INTEGER 00082 * On entry, INCX specifies the global increment for the 00083 * elements of X. Only two values of INCX are supported in 00084 * this version, namely 1 and M_X. INCX must not be zero. 00085 * 00086 * DPOS0 (global input) INTEGER 00087 * On entry, DPOS0 specifies the position in the calling rou- 00088 * tine's parameter list where the formal parameter DESCX ap- 00089 * pears. Note that it is assumed that IX and JX are respecti- 00090 * vely 2 and 1 entries behind DESCX, and INCX is 1 entry after 00091 * DESCX. 00092 * 00093 * INFO (local input/local output) INTEGER 00094 * = 0: successful exit 00095 * < 0: If the i-th argument is an array and the j-entry had an 00096 * illegal value, then INFO = -(i*100+j), if the i-th 00097 * argument is a scalar and had an illegal value, then 00098 * INFO = -i. 00099 * 00100 * -- Written on April 1, 1998 by 00101 * R. Clint Whaley, University of Tennessee, Knoxville 37996, USA. 00102 * 00103 * --------------------------------------------------------------------- 00104 */ 00105 /* 00106 * .. Local Scalars .. 00107 */ 00108 int dpos, icpos, ixpos, jxpos, mycol, myrow, np, npcol, npos, 00109 nprow, nq; 00110 /* .. 00111 * .. Executable Statements .. 00112 * 00113 */ 00114 /* 00115 * Want to find errors with MIN(), so if no error, set it to a big number. If 00116 * there already is an error, multiply by the the descriptor multiplier. 00117 */ 00118 if( *INFO >= 0 ) *INFO = BIGNUM; 00119 else if( *INFO < -DESCMULT ) *INFO = -(*INFO); 00120 else *INFO = -(*INFO) * DESCMULT; 00121 /* 00122 * Figure where in parameter list each parameter was, factoring in descriptor 00123 * multiplier 00124 */ 00125 npos = NPOS0 * DESCMULT; 00126 ixpos = ( DPOS0 - 2 ) * DESCMULT; 00127 jxpos = ( DPOS0 - 1 ) * DESCMULT; 00128 icpos = ( DPOS0 + 1 ) * DESCMULT; 00129 dpos = DPOS0 * DESCMULT + 1; 00130 /* 00131 * Get process grid information 00132 */ 00133 Cblacs_gridinfo( ICTXT, &nprow, &npcol, &myrow, &mycol ); 00134 /* 00135 * Are N, IX, JX, DESCX and INCX legal inputs ? 00136 */ 00137 if( N < 0 ) 00138 { 00139 /* 00140 * N must be at least zero 00141 */ 00142 *INFO = MIN( *INFO, npos ); 00143 PB_Cwarn( ICTXT, -1, ROUT, "%s sub( %s ) = %d, it must be at least 0", 00144 "Illegal length of", VNAME, N ); 00145 } 00146 00147 if( IX < 0 ) 00148 { 00149 /* 00150 * IX must be at least zero 00151 */ 00152 *INFO = MIN( *INFO, ixpos ); 00153 PB_Cwarn( ICTXT, -1, ROUT, "Illegal I%s = %d, I%s must be at least 1", 00154 VNAME, IX+1, VNAME ); 00155 } 00156 if( JX < 0 ) 00157 { 00158 /* 00159 * JX must be at least zero 00160 */ 00161 *INFO = MIN( *INFO, jxpos ); 00162 PB_Cwarn( ICTXT, -1, ROUT, "Illegal J%s = %d, J%s must be at least 1", 00163 VNAME, JX+1, VNAME ); 00164 } 00165 00166 if( DESCX[DTYPE_] != BLOCK_CYCLIC_2D_INB ) 00167 { 00168 /* 00169 * Internally, only the descriptor type BLOCK_CYCLIC_2D_INB is supported. 00170 */ 00171 *INFO = MIN( *INFO, dpos + DTYPE_ ); 00172 PB_Cwarn( ICTXT, -1, ROUT, "%s %d for matrix %s. PBLAS accepts: %d or %d", 00173 "Illegal descriptor type", DESCX[DTYPE_], VNAME, 00174 BLOCK_CYCLIC_2D, BLOCK_CYCLIC_2D_INB ); 00175 if( *INFO % DESCMULT == 0 ) *INFO = -( (*INFO) / DESCMULT ); 00176 else *INFO = -(*INFO); 00177 /* 00178 * No need to go any further ... 00179 */ 00180 return; 00181 } 00182 00183 if( DESCX[CTXT_] != ICTXT ) 00184 { 00185 /* 00186 * Check if the context of X match the other contexts. Only intra-context 00187 * operations are supported. 00188 */ 00189 *INFO = MIN( *INFO, dpos + CTXT_ ); 00190 PB_Cwarn( ICTXT, -1, ROUT, "DESC%s[CTXT_] = %d %s= %d", VNAME, 00191 DESCX[CTXT_], "does not match other operand's context ", 00192 ICTXT ); 00193 if( *INFO % DESCMULT == 0 ) *INFO = -( (*INFO) / DESCMULT ); 00194 else *INFO = -(*INFO); 00195 /* 00196 * No need to go any further ... 00197 */ 00198 return; 00199 } 00200 00201 if( DESCX[IMB_] < 1 ) 00202 { 00203 /* 00204 * DESCX[IMB_] must be at least one 00205 */ 00206 *INFO = MIN( *INFO, dpos + IMB_ ); 00207 PB_Cwarn( ICTXT, -1, ROUT, "Illegal DESC%s[IMB_] = %d, DESC%s[IMB_] %s", 00208 VNAME, DESCX[IMB_], VNAME, "must be at least 1" ); 00209 } 00210 if( DESCX[INB_] < 1 ) 00211 { 00212 /* 00213 * DESCX[INB_] must be at least one 00214 */ 00215 *INFO = MIN( *INFO, dpos + INB_ ); 00216 PB_Cwarn( ICTXT, -1, ROUT, "Illegal DESC%s[INB_] = %d, DESC%s[INB_] %s", 00217 VNAME, DESCX[INB_], VNAME, "must be at least 1" ); 00218 } 00219 if( DESCX[MB_] < 1 ) 00220 { 00221 /* 00222 * DESCX[MB_] must be at least one 00223 */ 00224 *INFO = MIN( *INFO, dpos + MB_ ); 00225 PB_Cwarn( ICTXT, -1, ROUT, "Illegal DESC%s[MB_] = %d, DESC%s[MB_] %s", 00226 VNAME, DESCX[MB_], VNAME, "must be at least 1" ); 00227 } 00228 if( DESCX[NB_] < 1 ) 00229 { 00230 /* 00231 * DESCX[NB_] must be at least one 00232 */ 00233 *INFO = MIN( *INFO, dpos + NB_ ); 00234 PB_Cwarn( ICTXT, -1, ROUT, "Illegal DESC%s[NB_] = %d, DESC%s[NB_] %s", 00235 VNAME, DESCX[NB_], VNAME, "must be at least 1" ); 00236 } 00237 00238 if( ( DESCX[RSRC_] < -1 ) || ( DESCX[RSRC_] >= nprow ) ) 00239 { 00240 /* 00241 * DESCX[RSRC_] must be either -1 (replication) or in the interval [0 .. nprow) 00242 */ 00243 *INFO = MIN( *INFO, dpos + RSRC_ ); 00244 PB_Cwarn( ICTXT, -1, ROUT, 00245 "Illegal DESC%s[RSRC_] = %d, DESC%s[RSRC_] %s%d", VNAME, 00246 DESCX[RSRC_], VNAME, "must be either -1, or >= 0 and < ", 00247 nprow ); 00248 } 00249 if( ( DESCX[CSRC_] < -1 ) || ( DESCX[CSRC_] >= npcol ) ) 00250 { 00251 /* 00252 * DESCX[CSRC_] must be either -1 (replication) or in the interval [0 .. npcol) 00253 */ 00254 *INFO = MIN( *INFO, dpos + CSRC_ ); 00255 PB_Cwarn( ICTXT, -1, ROUT, 00256 "Illegal DESC%s[CSRC_] = %d, DESC%s[CSRC_] %s%d", VNAME, 00257 DESCX[CSRC_], VNAME, "must be either -1, or >= 0 and < ", 00258 npcol ); 00259 } 00260 00261 if( INCX != 1 && INCX != DESCX[M_] ) 00262 { 00263 /* 00264 * INCX must be either 1 or DESCX[M_] 00265 */ 00266 *INFO = MIN( *INFO, icpos ); 00267 PB_Cwarn( ICTXT, -1, ROUT, 00268 "Illegal INC%s = %d, INC%s should be either 1 or %d", VNAME, 00269 DESCX[M_], VNAME ); 00270 } 00271 00272 if( N == 0 ) 00273 { 00274 /* 00275 * NULL vector, relax some checks 00276 */ 00277 if( DESCX[M_] < 0 ) 00278 { 00279 /* 00280 * DESCX[M_] must be at least 0 00281 */ 00282 *INFO = MIN( *INFO, dpos + M_ ); 00283 PB_Cwarn( ICTXT, -1, ROUT, "DESC%s[M_] = %d, it must be at least 0", 00284 VNAME, DESCX[M_] ); 00285 00286 } 00287 if( DESCX[N_] < 0 ) 00288 { 00289 /* 00290 * DESCX[N_] must be at least 0 00291 */ 00292 *INFO = MIN( *INFO, dpos + N_ ); 00293 PB_Cwarn( ICTXT, -1, ROUT, "DESC%s[N_] = %d, it must be at least 0", 00294 VNAME, DESCX[N_] ); 00295 } 00296 00297 if( DESCX[LLD_] < 1 ) 00298 { 00299 /* 00300 * DESCX[LLD_] must be at least 1 00301 */ 00302 *INFO = MIN( *INFO, dpos + LLD_ ); 00303 PB_Cwarn( ICTXT, -1, ROUT, "DESC%s[LLD_] = %d, it must be at least 1", 00304 VNAME, DESCX[LLD_] ); 00305 } 00306 } 00307 else 00308 { 00309 /* 00310 * more rigorous checks for non-degenerate vector 00311 */ 00312 if( DESCX[M_] < 1 ) 00313 { 00314 /* 00315 * DESCX[M_] must be at least 1 00316 */ 00317 *INFO = MIN( *INFO, dpos + M_ ); 00318 PB_Cwarn( ICTXT, -1, ROUT, 00319 "Illegal DESC%s[M_] = %d, it must be at least 1", VNAME, 00320 DESCX[M_]); 00321 00322 } 00323 if( DESCX[N_] < 1 ) 00324 { 00325 /* 00326 * DESCX[N_] must be at least 1 00327 */ 00328 *INFO = MIN( *INFO, dpos + N_ ); 00329 PB_Cwarn( ICTXT, -1, ROUT, 00330 "Illegal DESC%s[N_] = %d, it must be at least 1", VNAME, 00331 DESCX[N_]); 00332 } 00333 00334 if( ( DESCX[M_] >= 1 ) && ( DESCX[N_] >= 1 ) ) 00335 { 00336 if( INCX == DESCX[M_] ) 00337 { 00338 /* 00339 * sub( X ) resides in (a) process row(s) 00340 */ 00341 if( IX >= DESCX[M_] ) 00342 { 00343 /* 00344 * IX must be in [ 0 ... DESCX[M_]-1 ] 00345 */ 00346 *INFO = MIN( *INFO, ixpos ); 00347 PB_Cwarn( ICTXT, -1, ROUT, "%s I%s = %d, DESC%s[M_] = %d", 00348 "Array subscript out of bounds:", VNAME, IX+1, VNAME, 00349 DESCX[M_]); 00350 } 00351 if( JX+N > DESCX[N_] ) 00352 { 00353 /* 00354 * JX + N must be in [ 0 ... DESCX[N_]-1 ] 00355 */ 00356 *INFO = MIN( *INFO, jxpos ); 00357 PB_Cwarn( ICTXT, -1, ROUT, 00358 "%s N = %d, J%s = %d, DESC%s[N_] = %d", 00359 "Operation out of bounds:", N, VNAME, JX+1, VNAME, 00360 DESCX[N_]); 00361 } 00362 } 00363 else 00364 { 00365 /* 00366 * sub( X ) resides in (a) process column(s) 00367 */ 00368 if( JX >= DESCX[N_] ) 00369 { 00370 /* 00371 * JX must be in [ 0 ... DESCX[N_] ] 00372 */ 00373 *INFO = MIN( *INFO, jxpos ); 00374 PB_Cwarn( ICTXT, -1, ROUT, "%s J%s = %d, DESC%s[N_] = %d", 00375 "Array subscript out of bounds:", VNAME, JX+1, VNAME, 00376 DESCX[N_]); 00377 } 00378 if( IX+N > DESCX[M_] ) 00379 { 00380 /* 00381 * IX + N must be in [ 0 ... DESCX[M_] ] 00382 */ 00383 *INFO = MIN( *INFO, ixpos ); 00384 PB_Cwarn( ICTXT, -1, ROUT, 00385 "%s N = %d, I%s = %d, DESC%s[M_] = %d", 00386 "Operation out of bounds:", N, VNAME, IX+1, VNAME, 00387 DESCX[M_]); 00388 } 00389 } 00390 } 00391 /* 00392 * *INFO == BIGNUM => No errors have been found so far 00393 */ 00394 if( *INFO == BIGNUM ) 00395 { 00396 Mnumroc( np, DESCX[M_], 0, DESCX[IMB_], DESCX[MB_], myrow, 00397 DESCX[RSRC_], nprow ); 00398 if( DESCX[LLD_] < MAX( 1, np ) ) 00399 { 00400 Mnumroc( nq, DESCX[N_], 0, DESCX[INB_], DESCX[NB_], mycol, 00401 DESCX[CSRC_], npcol ); 00402 /* 00403 * DESCX[LLD_] must be at least 1 in order to be legal and this is enough if no 00404 * columns of X reside in this process 00405 */ 00406 if( DESCX[LLD_] < 1 ) 00407 { 00408 *INFO = MIN( *INFO, dpos + LLD_ ); 00409 PB_Cwarn( ICTXT, -1, ROUT, 00410 "DESC%s[LLD_] = %d, it must be at least 1", VNAME, 00411 DESCX[LLD_] ); 00412 } 00413 else if( nq > 0 ) 00414 { 00415 /* 00416 * Some columns of X reside in this process, DESCX[LLD_] must be at least 00417 * MAX( 1, np ) 00418 */ 00419 *INFO = MIN( *INFO, dpos + LLD_ ); 00420 PB_Cwarn( ICTXT, -1, ROUT, 00421 "DESC%s[LLD_] = %d, it must be at least %d", VNAME, 00422 DESCX[LLD_], MAX( 1, np ) ); 00423 } 00424 } 00425 } 00426 } 00427 /* 00428 * Prepare output: set INFO = 0 if no error, and divide by DESCMULT if error is 00429 * not in a descriptor entry. 00430 */ 00431 if( *INFO == BIGNUM ) *INFO = 0; 00432 else if( *INFO % DESCMULT == 0 ) *INFO = -( (*INFO) / DESCMULT ); 00433 else *INFO = -(*INFO); 00434 /* 00435 * End of PB_Cchkvec 00436 */ 00437 }