/* --------------------------------------------------------------------- * * -- PBLAS auxiliary routine (version 2.0) -- * University of Tennessee, Knoxville, Oak Ridge National Laboratory, * and University of California, Berkeley. * April 1, 1998 * * --------------------------------------------------------------------- */ /* * Include files */ #include "../pblas.h" #include "../PBpblas.h" #include "../PBtools.h" #include "../PBblacs.h" #include "../PBblas.h" #ifdef __STDC__ void PB_CVMcontig( PB_VM_T * VM, int * NRPQ, int * NCPQ, int * IOFF, int * JOFF ) #else void PB_CVMcontig( VM, NRPQ, NCPQ, IOFF, JOFF ) /* * .. Scalar Arguments .. */ int * IOFF, * JOFF, * NCPQ, * NRPQ; PB_VM_T * VM; #endif { /* * Purpose * ======= * * PB_CVMcontig computes the maximum number of contiguous rows and * columns corresponding to the first diagonals of the local virtual * matrix VM. This routine also returns the row and column offset of the * first diagonal entry. * * Arguments * ========= * * VM (local input) pointer to a PB_VM_T structure * On entry, VM is a pointer to a structure of type PB_VM_T, * that contains the virtual matrix information (see pblas.h). * * NRPQ (local output) INTEGER * On exit, NRPQ specifies the number of contiguous rows corres- * ponding to the first diagonals of the local virtual matrix * VM. On exit, NRPQ is at least zero. * * NCPQ (local output) INTEGER * On exit, NCPQ specifies the number of contiguous columns cor- * responding to the first diagonals of the local virtual matrix * VM. On exit, NRPQ is at least zero. * * IOFF (local output) INTEGER * On exit, IOFF is the local row offset of the first row cor- * responding to a diagonal entry of the Virtual matrix VM. If * no diagonals are found, the value zero is returned. On exit, * IOFF is at least zero. * * JOFF (local output) INTEGER * On exit, JOFF is the local column offset of the first column * corresponding to a diagonal entry of the Virtual matrix VM. * If no diagonals are found, the value zero is returned. On * exit, JOFF is at least zero. * * -- Written on April 1, 1998 by * Antoine Petitet, University of Tennessee, Knoxville 37996, USA. * * --------------------------------------------------------------------- */ /* * .. Local Scalars .. */ int ColCont=1, FirstD=0, GoSouth, GoEast, RowCont=1, ilow, imbloc, inbloc, iupp, lcmt, lcmtnn=0, lcmt00, lmbloc, lnbloc, low, mb, mblks, mbloc, mcur=0, mcurd, md=0, nb, nblks, nbloc, ncur=0, ncurd, nd=0, npq=0, pmb, qnb, tmp1, tmp2, upp; /* .. * .. Executable Statements .. * */ *NRPQ = 0; *NCPQ = 0; *IOFF = 0; *JOFF = 0; mblks = VM->mblks; nblks = VM->nblks; /* * Quick return if I don't own any blocks. */ if( ( mblks == 0 ) || ( nblks == 0 ) ) return; /* * Retrieve the contents of VM structure fields */ lcmt00 = VM->lcmt00; imbloc = VM->imbloc; mb = VM->mb; lmbloc = VM->lmbloc; iupp = VM->iupp; upp = VM->upp; pmb = VM->nprow * mb; inbloc = VM->inbloc; nb = VM->nb; lnbloc = VM->lnbloc; ilow = VM->ilow; low = VM->low; qnb = VM->npcol * nb; /* * Handle separately the first row and/or column of the LCM table. Update the * LCM value of the curent block lcmt00, as well as the coordinates of the * current entry in the LCM table (mcur,ncur). */ GoSouth = ( lcmt00 > iupp ); GoEast = ( lcmt00 < ilow ); /* * Go through the table looking for blocks owning diagonal entries. */ if( !( GoSouth ) && !( GoEast ) ) { /* * The upper left block owns diagonal entries lcmt00 >= ilow && lcmt00 <= iupp * Compute the number of diagonals in this block as well as lcm value (lcntnn) * that its neighbor should have to preserve continuity. */ if( lcmt00 >= 0 ) { tmp2 = ( ( tmp1 = imbloc - lcmt00 ) > 0 ? tmp1 : 0 ); if( tmp2 < inbloc ) { npq = tmp2; lcmtnn = -npq; } else if ( tmp2 == inbloc ) { npq = inbloc; lcmtnn = 0; } else { npq = inbloc; lcmtnn = lcmt00 + npq; } *IOFF += lcmt00; } else { tmp2 = ( ( tmp1 = inbloc + lcmt00 ) > 0 ? tmp1 : 0 ); if( tmp2 < imbloc ) { npq = tmp2; lcmtnn = npq; } else if ( tmp2 == imbloc ) { npq = tmp2; lcmtnn = 0; } else { npq = imbloc; lcmtnn = lcmt00 - npq; } *JOFF -= lcmt00; } /* * Save coordinates of last block owning diagonals. Set FirstD to one, since * a block owning diagonals has been found. */ md = 0; nd = 0; FirstD = 1; /* * Those rows and columns are obviously contiguous */ *NRPQ = *NCPQ = npq; /* * Decide whether one should go south or east in the table: Go east if the * block below the current one only owns lower entries. If this block, however, * owns diagonals, then go south. */ GoSouth = !( GoEast = ( lcmt00 - iupp + upp - pmb < ilow ) ); } if( GoSouth ) { /* * Go one step south in the LCM table. Adjust the current LCM value. */ lcmt00 -= iupp - upp + pmb; mcur++; if( !FirstD ) *IOFF += imbloc; /* * While there are blocks remaining that own upper entries, keep going south. * Adjust the current LCM value accordingly. */ while( ( mcur < mblks ) && ( lcmt00 > upp ) ) { lcmt00 -= pmb; mcur++; if( !FirstD ) *IOFF += mb; } /* * Return if no more row in the LCM table. */ if( mcur >= mblks ) goto l_end; /* * lcmt00 <= upp. The current block owns either diagonals or lower entries. * Save the current position in the LCM table. After this column has been * completely taken care of, re-start from this row and the next column of * the LCM table. */ lcmt = lcmt00; mbloc = mb; mcurd = mcur; while( ( mcurd < mblks ) && ( lcmt >= ilow ) ) { if( mcurd == mblks-1 ) mbloc = lmbloc; /* * A block owning diagonals lcmt00 >= ilow && lcmt00 <= upp has been found. * If this is not the first one, update the booleans telling if the rows * and/or columns are contiguous. */ if( FirstD ) { RowCont = RowCont && ( ( ( mcurd == md+1 ) && ( lcmtnn <= 0 ) && ( lcmt <= 0 ) ) || ( ( mcurd == md ) && ( ncur == nd+1 ) && ( lcmtnn == lcmt ) ) ); ColCont = ColCont && ( ( ( ncur == nd+1 ) && ( lcmtnn >= 0 ) && ( lcmt >= 0 ) ) || ( ( ncur == nd ) && ( mcurd == md+1 ) && ( lcmtnn == lcmt ) ) ); } /* * Compute the number of diagonals in this block as well as lcm value (lcntnn) * that its neighbor should have to preserve continuity. */ if( lcmt >= 0 ) { tmp2 = ( ( tmp1 = mbloc - lcmt ) > 0 ? tmp1 : 0 ); if( tmp2 < inbloc ) { npq = tmp2; lcmtnn = -npq; } else if ( tmp2 == inbloc ) { npq = inbloc; lcmtnn = 0; } else { npq = inbloc; lcmtnn = lcmt + npq; } if( !FirstD ) *IOFF += lcmt; } else { tmp2 = ( ( tmp1 = inbloc + lcmt ) > 0 ? tmp1 : 0 ); if( tmp2 < mbloc ) { npq = tmp2; lcmtnn = npq; } else if ( tmp2 == mbloc ) { npq = tmp2; lcmtnn = 0; } else { npq = mbloc; lcmtnn = lcmt - npq; } if( !FirstD ) *JOFF -= lcmt; } /* * Save coordinates of last block owning diagonals. Set FirstD to one, since * a block owning diagonals has been found. */ md = mcurd; nd = ncur; FirstD = 1; /* * If rows (resp columns) are still contiguous, add those npq rows (resp. * columns). */ if( RowCont ) *NRPQ += npq; if( ColCont ) *NCPQ += npq; /* * Keep going south until there are no more blocks owning diagonals */ lcmt00 = lcmt; lcmt -= pmb; mcur = mcurd++; } /* * I am done with the first column of the LCM table. Go to the next column. */ lcmt00 += low - ilow + qnb; ncur++; if( !FirstD ) *JOFF += inbloc; } else if( GoEast ) { /* * Go one step east in the LCM table. Adjust the current LCM value. */ lcmt00 += low - ilow + qnb; ncur++; if( !FirstD ) *JOFF += inbloc; /* * While there are blocks remaining that own lower entries, keep going east * in the LCM table. Adjust the current LCM value. */ while( ( ncur < nblks ) && ( lcmt00 < low ) ) { lcmt00 += qnb; ncur++; if( !FirstD ) *JOFF += nb; } /* * Return if no more column in the LCM table. */ if( ncur >= nblks ) goto l_end; /* * lcmt00 >= low. The current block owns either diagonals or upper entries. Save * the current position in the LCM table. After this row has been completely * taken care of, re-start from this column and the next row of the LCM table. */ lcmt = lcmt00; nbloc = nb; ncurd = ncur; while( ( ncurd < nblks ) && ( lcmt <= iupp ) ) { if( ncurd == nblks-1 ) nbloc = lnbloc; /* * A block owning diagonals lcmt00 >= low && lcmt00 <= iupp has been found. * If this is not the first one, update the booleans telling if the rows * and/or columns are contiguous. */ if( FirstD ) { RowCont = RowCont && ( ( ( mcur == md+1 ) && ( lcmtnn <= 0 ) && ( lcmt <= 0 ) ) || ( ( mcur == md ) && ( ncurd == nd+1 ) && ( lcmtnn == lcmt ) ) ); ColCont = ColCont && ( ( ( ncurd == nd+1 ) && ( lcmtnn >= 0 ) && ( lcmt >= 0 ) ) || ( ( ncurd == nd ) && ( mcur == md+1 ) && ( lcmtnn == lcmt ) ) ); } /* * Compute the number of diagonals in this block as well as lcm value (lcntnn) * that its neighbor should have to preserve continuity. */ if( lcmt >= 0 ) { tmp2 = ( ( tmp1 = imbloc - lcmt ) > 0 ? tmp1 : 0 ); if( tmp2 < nbloc ) { npq = tmp2; lcmtnn = -npq; } else if ( tmp2 == nbloc ) { npq = nbloc; lcmtnn = 0; } else { npq = nbloc; lcmtnn = lcmt + npq; } if( !FirstD ) *IOFF += lcmt; } else { tmp2 = ( ( tmp1 = nbloc + lcmt ) > 0 ? tmp1 : 0 ); if( tmp2 < imbloc ) { npq = tmp2; lcmtnn = npq; } else if ( tmp2 == imbloc ) { npq = tmp2; lcmtnn = 0; } else { npq = imbloc; lcmtnn = lcmt - npq; } if( !FirstD ) *JOFF -= lcmt; } /* * Save coordinates of last block owning diagonals. Set FirstD to one, since * a block owning diagonals has been found. */ md = mcur; nd = ncurd; FirstD = 1; /* * If rows (resp columns) are still contiguous, add those npq rows (resp. * columns). */ if( RowCont ) *NRPQ += npq; if( ColCont ) *NCPQ += npq; /* * Keep going east until there are no more blocks owning diagonals. */ lcmt00 = lcmt; lcmt += qnb; ncur = ncurd++; } /* * I am done with the first row of the LCM table. Go to the next row. */ lcmt00 -= iupp - upp + pmb; mcur++; if( !FirstD ) *IOFF += imbloc; } /* * Loop over the remaining columns of the LCM table. */ nbloc = nb; while( ( RowCont || ColCont ) && ( ncur < nblks ) ) { if( ncur == nblks-1 ) nbloc = lnbloc; /* * While there are blocks remaining that own upper entries, keep going south. * Adjust the current LCM value accordingly. */ while( ( mcur < mblks ) && ( lcmt00 > upp ) ) { lcmt00 -= pmb; mcur++; if( !FirstD ) *IOFF += mb; } /* * Return if no more row in the LCM table. */ if( mcur >= mblks ) goto l_end; /* * lcmt00 <= upp. The current block owns either diagonals or lower entries. * Save the current position in the LCM table. After this column has been * completely taken care of, re-start from this row and the next column of * the LCM table. */ lcmt = lcmt00; mbloc = mb; mcurd = mcur; while( ( mcurd < mblks ) && ( lcmt >= low ) ) { if( mcurd == mblks-1 ) mbloc = lmbloc; /* * A block owning diagonals lcmt00 >= low && lcmt00 <= upp has been found. * If this is not the first one, update the booleans telling if the rows * and/or columns are contiguous. */ if( FirstD ) { RowCont = RowCont && ( ( ( mcurd == md+1 ) && ( lcmtnn <= 0 ) && ( lcmt <= 0 ) ) || ( ( mcurd == md ) && ( ncur == nd+1 ) && ( lcmtnn == lcmt ) ) ); ColCont = ColCont && ( ( ( ncur == nd+1 ) && ( lcmtnn >= 0 ) && ( lcmt >= 0 ) ) || ( ( ncur == nd ) && ( mcurd == md+1 ) && ( lcmtnn == lcmt ) ) ); } /* * Compute the number of diagonals in this block as well as lcm value (lcntnn) * that its neighbor should have to preserve continuity. */ if( lcmt >= 0 ) { tmp2 = ( ( tmp1 = mbloc - lcmt ) > 0 ? tmp1 : 0 ); if( tmp2 < nbloc ) { npq = tmp2; lcmtnn = -npq; } else if ( tmp2 == nbloc ) { npq = nbloc; lcmtnn = 0; } else { npq = nbloc; lcmtnn = lcmt + npq; } if( !FirstD ) *IOFF += lcmt; } else { tmp2 = ( ( tmp1 = nbloc + lcmt ) > 0 ? tmp1 : 0 ); if( tmp2 < mbloc ) { npq = tmp2; lcmtnn = npq; } else if ( tmp2 == mbloc ) { npq = tmp2; lcmtnn = 0; } else { npq = mbloc; lcmtnn = lcmt - npq; } if( !FirstD ) *JOFF -= lcmt; } /* * Save coordinates of last block owning diagonals. Set FirstD to one, since * a block owning diagonals has been found. */ md = mcurd; nd = ncur; FirstD = 1; /* * If rows (resp columns) are still contiguous, add those npq rows (resp. * columns). */ if( RowCont ) *NRPQ += npq; if( ColCont ) *NCPQ += npq; /* * Keep going south until there are no more blocks owning diagonals */ lcmt00 = lcmt; lcmt -= pmb; mcur = mcurd++; } /* * I am done with this column of the LCM table. Go to the next column until * there are no more column in the table. */ lcmt00 += qnb; ncur++; if( !FirstD ) *JOFF += nb; } l_end: /* * If no diagonals were found, reset IOFF and JOFF to zero. */ if( !FirstD ) { *IOFF = 0; *JOFF = 0; } /* * End of PB_CVMcontig */ }