ScaLAPACK  2.0.2
ScaLAPACK: Scalable Linear Algebra PACKage
PB_Cchkvec.c
Go to the documentation of this file.
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 }