/*  support.c  */

#include "../../InpMtx.h"

/*--------------------------------------------------------------------*/
/*
   --------------------------------------------------------------------
   purpose -- 
      this method is used to determine the support of this matrix
      for a matrix-vector multiply y[] = A * x[] when A is a
      nonsymmetric matrix.

      rowsupIV -- filled with row indices of y[] which will be updated.
      colsupIV -- filled with row indices of x[] which will be used.

   created -- 98aug01, cca
   --------------------------------------------------------------------
*/
void
InpMtx_supportNonsym (
   InpMtx   *A,
   IV       *rowsupIV,
   IV       *colsupIV
) {
char   *colmark, *rowmark ;
int    chev, col, colcount, ii, loc, maxcol, maxrow, nent, off, row,
       rowcount ;
int    *colsup, *ivec1, *ivec2, *rowsup ;
/*
   ---------------
   check the input
   ---------------
*/
if ( A == NULL || rowsupIV == NULL || colsupIV == NULL ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportNonsym(%p,%p,%p)"
           "\n bad input\n", A, rowsupIV, colsupIV) ;
   exit(-1) ;
}
if (  !INPMTX_IS_BY_ROWS(A) 
   && !INPMTX_IS_BY_COLUMNS(A) 
   && !INPMTX_IS_BY_CHEVRONS(A) ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportNonsym(%p,%p,%p)"
           "\n coordinate type\n", A, rowsupIV, colsupIV) ;
   exit(-1) ;
}
ivec1 = InpMtx_ivec1(A) ;
ivec2 = InpMtx_ivec2(A) ;
nent  = A->nent ;
/*
   -----------------------------------------------------------------
   (1) determine the maximum row and column numbers in these entries
   (2) allocate marking vectors for rows and columns
   (3) fill marking vectors for rows and columns
   (4) fill support vectors 
   -----------------------------------------------------------------
*/
if ( INPMTX_IS_BY_ROWS(A) ) {
   maxrow   = IVmax(nent, ivec1, &loc) ;
   maxcol   = IVmax(nent, ivec2, &loc) ;
   rowmark  = CVinit(1+maxrow, 'O') ;
   colmark  = CVinit(1+maxcol, 'O') ;
   rowcount = colcount = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      row = ivec1[ii] ; col = ivec2[ii] ;
      if ( rowmark[row] == 'O' ) {
         rowcount++ ;
      }
      rowmark[row] = 'X' ;
      if ( colmark[col] == 'O' ) {
         colcount++ ;
      }
      colmark[col] = 'X' ;
   }
} else if ( INPMTX_IS_BY_COLUMNS(A) ) {
   maxrow   = IVmax(nent, ivec2, &loc) ;
   maxcol   = IVmax(nent, ivec1, &loc) ;
   rowmark  = CVinit(1+maxrow, 'O') ;
   colmark  = CVinit(1+maxcol, 'O') ;
   rowcount = colcount = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      row = ivec2[ii] ; col = ivec1[ii] ;
      if ( rowmark[row] == 'O' ) {
         rowcount++ ;
      }
      rowmark[row] = 'X' ;
      if ( colmark[col] == 'O' ) {
         colcount++ ;
      }
      colmark[col] = 'X' ;
   }
} else if ( INPMTX_IS_BY_CHEVRONS(A) ) {
   maxrow = maxcol = -1 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      chev = ivec1[ii] ; off = ivec2[ii] ;
      if ( off >= 0 ) {
         row = chev ; col = chev + off ;
      } else {
         col = chev ; row = chev - off ;
      }
      if ( maxrow < row ) {
         maxrow = row ;
      }
      if ( maxcol < col ) {
         maxcol = col ;
      }
   }
   rowmark  = CVinit(1+maxrow, 'O') ;
   colmark  = CVinit(1+maxcol, 'O') ;
   rowcount = colcount = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      chev = ivec1[ii] ; off = ivec2[ii] ;
      if ( off >= 0 ) {
         row = chev ; col = chev + off ;
      } else {
         col = chev ; row = chev - off ;
      }
      if ( rowmark[row] == 'O' ) {
         rowcount++ ;
      }
      rowmark[row] = 'X' ;
      if ( colmark[col] == 'O' ) {
         colcount++ ;
      }
      colmark[col] = 'X' ;
   }
}
IV_setSize(rowsupIV, rowcount) ;
rowsup = IV_entries(rowsupIV) ;
for ( row = rowcount = 0 ; row <= maxrow ; row++ ) {
   if ( rowmark[row] == 'X' ) {
      rowsup[rowcount++] = row ;
   }
}
IV_setSize(colsupIV, colcount) ;
colsup = IV_entries(colsupIV) ;
for ( col = colcount = 0 ; col <= maxcol ; col++ ) {
   if ( colmark[col] == 'X' ) {
      colsup[colcount++] = col ;
   }
}
CVfree(colmark) ;
CVfree(rowmark) ;

return ; }
   
/*--------------------------------------------------------------------*/
/*
   --------------------------------------------------------------------
   purpose -- 
      this method is used to determine the support of this matrix
      for a matrix-vector multiply y[] = A * x[] when A is a
      nonsymmetric matrix.

      rowsupIV -- filled with row indices of y[] which will be updated.
      colsupIV -- filled with row indices of x[] which will be used.

   created -- 98aug01, cca
   --------------------------------------------------------------------
*/
void
InpMtx_supportNonsymT (
   InpMtx   *A,
   IV       *rowsupIV,
   IV       *colsupIV
) {
char   *colmark, *rowmark ;
int    chev, col, colcount, ii, loc, maxcol, maxrow, nent, off, row,
       rowcount ;
int    *colsup, *ivec1, *ivec2, *rowsup ;
/*
   ---------------
   check the input
   ---------------
*/
if ( A == NULL || rowsupIV == NULL || colsupIV == NULL ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportNonsymT(%p,%p,%p)"
           "\n bad input\n", A, rowsupIV, colsupIV) ;
   exit(-1) ;
}
if (  !INPMTX_IS_BY_ROWS(A) 
   && !INPMTX_IS_BY_COLUMNS(A) 
   && !INPMTX_IS_BY_CHEVRONS(A) ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportNonsymT(%p,%p,%p)"
           "\n coordinate type\n", A, rowsupIV, colsupIV) ;
   exit(-1) ;
}
ivec1 = InpMtx_ivec1(A) ;
ivec2 = InpMtx_ivec2(A) ;
nent  = A->nent ;
/*
   -----------------------------------------------------------------
   (1) determine the maximum row and column numbers in these entries
   (2) allocate marking vectors for rows and columns
   (3) fill marking vectors for rows and columns
   (4) fill support vectors 
   -----------------------------------------------------------------
*/
if ( INPMTX_IS_BY_ROWS(A) ) {
   maxrow   = IVmax(nent, ivec1, &loc) ;
   maxcol   = IVmax(nent, ivec2, &loc) ;
   rowmark  = CVinit(1+maxcol, 'O') ;
   colmark  = CVinit(1+maxrow, 'O') ;
   rowcount = colcount = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      row = ivec1[ii] ; col = ivec2[ii] ;
      if ( colmark[row] == 'O' ) {
         colcount++ ;
      }
      colmark[row] = 'X' ;
      if ( rowmark[col] == 'O' ) {
         rowcount++ ;
      }
      rowmark[col] = 'X' ;
   }
} else if ( INPMTX_IS_BY_COLUMNS(A) ) {
   maxrow   = IVmax(nent, ivec2, &loc) ;
   maxcol   = IVmax(nent, ivec1, &loc) ;
   rowmark  = CVinit(1+maxcol, 'O') ;
   colmark  = CVinit(1+maxrow, 'O') ;
   rowcount = colcount = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      row = ivec2[ii] ; col = ivec1[ii] ;
      if ( colmark[row] == 'O' ) {
         colcount++ ;
      }
      colmark[row] = 'X' ;
      if ( rowmark[col] == 'O' ) {
         rowcount++ ;
      }
      rowmark[col] = 'X' ;
   }
} else if ( INPMTX_IS_BY_CHEVRONS(A) ) {
   maxrow = maxcol = -1 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      chev = ivec1[ii] ; off = ivec2[ii] ;
      if ( off >= 0 ) {
         row = chev ; col = chev + off ;
      } else {
         col = chev ; row = chev - off ;
      }
      if ( maxrow < row ) {
         maxrow = row ;
      }
      if ( maxcol < col ) {
         maxcol = col ;
      }
   }
   rowmark  = CVinit(1+maxcol, 'O') ;
   colmark  = CVinit(1+maxrow, 'O') ;
   rowcount = colcount = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      chev = ivec1[ii] ; off = ivec2[ii] ;
      if ( off >= 0 ) {
         row = chev ; col = chev + off ;
      } else {
         col = chev ; row = chev - off ;
      }
      if ( colmark[row] == 'O' ) {
         colcount++ ;
      }
      colmark[row] = 'X' ;
      if ( rowmark[col] == 'O' ) {
         rowcount++ ;
      }
      rowmark[col] = 'X' ;
   }
}
IV_setSize(rowsupIV, rowcount) ;
rowsup = IV_entries(rowsupIV) ;
for ( col = rowcount = 0 ; col <= maxcol ; col++ ) {
   if ( rowmark[col] == 'X' ) {
      rowsup[rowcount++] = col ;
   }
}
IV_setSize(colsupIV, colcount) ;
colsup = IV_entries(colsupIV) ;
for ( row = colcount = 0 ; row <= maxrow ; row++ ) {
   if ( colmark[row] == 'X' ) {
      colsup[colcount++] = row ;
   }
}
CVfree(colmark) ;
CVfree(rowmark) ;

return ; }
   
/*--------------------------------------------------------------------*/
/*
   --------------------------------------------------------------------
   purpose -- 
      this method is used to determine the support of this matrix
      for a matrix-vector multiply y[] = A * x[] when A is a
      nonsymmetric matrix.

      rowsupIV -- filled with row indices of y[] which will be updated.
      colsupIV -- filled with row indices of x[] which will be used.

   created -- 98aug01, cca
   --------------------------------------------------------------------
*/
void
InpMtx_supportNonsymH (
   InpMtx   *A,
   IV       *rowsupIV,
   IV       *colsupIV
) {
/*
   ---------------
   check the input
   ---------------
*/
if ( A == NULL || rowsupIV == NULL || colsupIV == NULL ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportNonsymH(%p,%p,%p)"
           "\n bad input\n", A, rowsupIV, colsupIV) ;
   exit(-1) ;
}
if (  !INPMTX_IS_BY_ROWS(A) 
   && !INPMTX_IS_BY_COLUMNS(A) 
   && !INPMTX_IS_BY_CHEVRONS(A) ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportNonsymH(%p,%p,%p)"
           "\n coordinate type\n", A, rowsupIV, colsupIV) ;
   exit(-1) ;
}
InpMtx_supportNonsymT(A, rowsupIV, colsupIV) ;

return ; }

/*--------------------------------------------------------------------*/
/*
   --------------------------------------------------------------------
   purpose -- 
      this method is used to determine the support of this matrix
      for a matrix-vector multiply y[] = A * x[] when A is a 
      symmetric matrix.

      supIV -- filled with row indices of y[] which will be updated
               and row indices of x[] which will be used.

   created -- 98aug01, cca
   --------------------------------------------------------------------
*/
void
InpMtx_supportSym (
   InpMtx   *A,
   IV       *supIV
) {
char   *mark ;
int    chev, col, count, ii, loc, maxcol, maxrow, maxv, nent, off, row ;
int    *ivec1, *ivec2, *sup ;
/*
   ---------------
   check the input
   ---------------
*/
if ( A == NULL || supIV == NULL ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportSym(%p,%p)"
           "\n bad input\n", A, supIV) ;
   exit(-1) ;
}
if (  !INPMTX_IS_BY_ROWS(A) 
   && !INPMTX_IS_BY_COLUMNS(A) 
   && !INPMTX_IS_BY_CHEVRONS(A) ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportSym(%p,%p)"
           "\n coordinate type\n", A, supIV) ;
   exit(-1) ;
}
ivec1 = InpMtx_ivec1(A) ;
ivec2 = InpMtx_ivec2(A) ;
nent  = A->nent ;
/*
   -----------------------------------------------------------------
   (1) determine the maximum row and column numbers in these entries
   (2) allocate marking vectors for rows and columns
   (3) fill marking vectors for rows and columns
   (4) fill support vectors 
   -----------------------------------------------------------------
*/
if ( INPMTX_IS_BY_ROWS(A) ) {
   maxrow = IVmax(nent, ivec1, &loc) ;
   maxcol = IVmax(nent, ivec2, &loc) ;
   maxv   = (maxrow >= maxcol) ? maxrow : maxcol ;
   mark   = CVinit(1+maxv, 'O') ;
   count  = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      row = ivec1[ii] ; col = ivec2[ii] ;
      if ( mark[row] == 'O' ) {
         count++ ;
      }
      mark[row] = 'X' ;
      if ( mark[col] == 'O' ) {
         count++ ;
      }
      mark[col] = 'X' ;
   }
} else if ( INPMTX_IS_BY_COLUMNS(A) ) {
   maxrow = IVmax(nent, ivec2, &loc) ;
   maxcol = IVmax(nent, ivec1, &loc) ;
   maxv   = (maxrow >= maxcol) ? maxrow : maxcol ;
   mark   = CVinit(1+maxv, 'O') ;
   count  = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      row = ivec2[ii] ; col = ivec1[ii] ;
      if ( mark[row] == 'O' ) {
         count++ ;
      }
      mark[row] = 'X' ;
      if ( mark[col] == 'O' ) {
         count++ ;
      }
      mark[col] = 'X' ;
   }
} else if ( INPMTX_IS_BY_CHEVRONS(A) ) {
   maxv = -1 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      chev = ivec1[ii] ; off = ivec2[ii] ;
      if ( off >= 0 ) {
         row = chev ; col = chev + off ;
         if ( maxv < col ) {
            maxv = col ;
         }
      } else {
         col = chev ; row = chev - off ;
         if ( maxv < row ) {
            maxv = row ;
         }
      }
   }
   mark = CVinit(1+maxv, 'O') ;
   count = 0 ;
   for ( ii = 0 ; ii < nent ; ii++ ) {
      chev = ivec1[ii] ; off = ivec2[ii] ;
      if ( off >= 0 ) {
         row = chev ; col = chev + off ;
      } else {
         col = chev ; row = chev - off ;
      }
      if ( mark[row] == 'O' ) {
         count++ ;
      }
      mark[row] = 'X' ;
      if ( mark[col] == 'O' ) {
         count++ ;
      }
      mark[col] = 'X' ;
   }
}
IV_setSize(supIV, count) ;
sup = IV_entries(supIV) ;
for ( row = count = 0 ; row <= maxv ; row++ ) {
   if ( mark[row] == 'X' ) {
      sup[count++] = row ;
   }
}
CVfree(mark) ;

return ; }
   
/*--------------------------------------------------------------------*/
/*
   --------------------------------------------------------------------
   purpose -- 
      this method is used to determine the support of this matrix
      for a matrix-vector multiply y[] = A * x[] when A is a 
      Hermitian matrix.

      supIV -- filled with row indices of y[] which will be updated
               and row indices of x[] which will be used.

   created -- 98aug01, cca
   --------------------------------------------------------------------
*/
void
InpMtx_supportHerm (
   InpMtx   *A,
   IV       *supIV
) {
/*
   ---------------
   check the input
   ---------------
*/
if ( A == NULL || supIV == NULL ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportHerm(%p,%p)"
           "\n bad input\n", A, supIV) ;
   exit(-1) ;
}
if (  !INPMTX_IS_BY_ROWS(A) 
   && !INPMTX_IS_BY_COLUMNS(A) 
   && !INPMTX_IS_BY_CHEVRONS(A) ) {
   fprintf(stderr, "\n fatal error in InpMtx_supportHerm(%p,%p)"
           "\n coordinate type\n", A, supIV) ;
   exit(-1) ;
}
InpMtx_supportSym(A, supIV) ;

return ; }

/*--------------------------------------------------------------------*/