static int MATRIXFUNC(FILE *out, double threshold, int absval, int prec,
                      unsigned int len, const char **labels,
                      const MYTYPE *mat, int valbits, MYTYPE denom,
                      MYTYPE flag) {
   int idx, numvals, cnt = 1;
   unsigned int i, j;
   MYUTYPE mask, imask = 0, nmask = 0;
   MYTYPE tmp;
   double val;
   const MYTYPE *pos = mat;

   if(out == NULL || mat == NULL || denom == 0 || valbits == 0) return -1;
   if(valbits > sizeof(MYTYPE)*CHAR_BIT) return -2;
   numvals = (sizeof(MYTYPE)*CHAR_BIT)/valbits;
   if(numvals*valbits != sizeof(MYTYPE)*CHAR_BIT) return -2;

   for(idx = 0; idx < valbits; idx++) {
      imask|= 1<<(idx+sizeof(MYUTYPE)*CHAR_BIT-valbits);
   }
   for(idx = valbits-1; idx < sizeof(MYUTYPE)*CHAR_BIT; idx++) {
      nmask|= 1<<idx;
   }
   mask = imask;


   fprintf(out, "%d\n", len);

   if(labels != NULL && absval != 0 && prec != 0) {
#define PRINTLABEL(x) fprintf(out, "%s", labels[x])
#define DOABS(x) fabs(x)
#define PRINTVAL(x) fprintf(out, "\t%.*lf", prec, x)
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   } else if(labels != NULL && absval != 0 && prec == 0) {
#define PRINTLABEL(x) fprintf(out, "%s", labels[x])
#define DOABS(x) fabs(x)
#define PRINTVAL(x) fprintf(out, "\t%d", (x == 0)?(0):((x>0)?(1):(-1)))
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   } else if(labels != NULL && absval == 0 && prec != 0) {
#define PRINTLABEL(x) fprintf(out, "%s", labels[x])
#define DOABS(x) x
#define PRINTVAL(x) fprintf(out, "\t%.*lf", prec, x)
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   } else if(labels != NULL && absval == 0 && prec == 0) {
#define PRINTLABEL(x) fprintf(out, "%s", labels[x])
#define DOABS(x) x
#define PRINTVAL(x) fprintf(out, "\t%d", (x == 0)?(0):((x>0)?(1):(-1)))
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   } else if(labels == NULL && absval != 0 && prec != 0) {
#define PRINTLABEL(x) fprintf(out, "%d", x)
#define DOABS(x) fabs(x)
#define PRINTVAL(x) fprintf(out, "\t%.*lf", prec, x)
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   } else if(labels == NULL && absval != 0 && prec == 0) {
#define PRINTLABEL(x) fprintf(out, "%d", x)
#define DOABS(x) fabs(x)
#define PRINTVAL(x) fprintf(out, "\t%d", (x == 0)?(0):((x>0)?(1):(-1)))
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   } else if(labels == NULL && absval == 0 && prec != 0) {
#define PRINTLABEL(x) fprintf(out, "%d", x)
#define DOABS(x) x
#define PRINTVAL(x) fprintf(out, "\t%.*lf", prec, x)
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   } else /* if(labels == NULL && absval == 0 && prec == 0) */ {
#define PRINTLABEL(x) fprintf(out, "%d", x)
#define DOABS(x) x
#define PRINTVAL(x) fprintf(out, "\t%d", (x == 0)?(0):((x>0)?(1):(-1)))
#include "graphioPrintMatrixLT.c"
#undef PRINTLABEL
#undef DOABS
#undef PRINTVAL
   }

   return 0;
}

static int ELISTFUNC(FILE *out, double threshold, int absval, int prec,
                     unsigned int len, const char **labels, const MYTYPE *mat,
                     int valbits, MYTYPE denom, MYTYPE flag) {
   int idx, numvals, cnt = 1;
   unsigned int i, j, mylen = len;
   unsigned long edgecnt;
   MYTYPE tmp;
   MYUTYPE mask, imask = 0, nmask = 0;
   double val;
   const MYTYPE *pos = mat;

   if(out == NULL || mat == NULL || denom == 0 || valbits == 0) return -1;
   if(valbits > sizeof(MYTYPE)*CHAR_BIT) return -2;
   numvals = sizeof(MYTYPE)*CHAR_BIT/valbits;
   if(numvals*valbits != sizeof(MYTYPE)*CHAR_BIT) return -2;

   for(idx = 0; idx < valbits; idx++) {
      imask|= 1<<(idx+sizeof(MYTYPE)*CHAR_BIT-valbits);
   }
   for(idx = valbits-1; idx < sizeof(MYUTYPE)*CHAR_BIT; idx++) {
      nmask|= 1<<idx;
   }
   mask = imask;

   edgecnt = ECNTFUNC(threshold, absval, mat, valbits, denom, flag, &mylen);

   fprintf(out, "%d\t%ld\n", mylen, edgecnt);

   if(labels != NULL && absval != 0 && prec != 0) {
#define DOABS(x) fabs(x)
#define PRINTEDGE(a, b, x) fprintf(out, "%s\t%s\t%.*lf\n", \
                                   labels[a], labels[b], prec, x)
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   } else if(labels != NULL && absval != 0 && prec == 0) {
#define DOABS(x) fabs(x)
#define PRINTEDGE(a, b, x) fprintf(out, "%s\t%s\n", \
                                   labels[a], labels[b])
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   } else if(labels != NULL && absval == 0 && prec != 0) {
#define DOABS(x) x
#define PRINTEDGE(a, b, x) fprintf(out, "%s\t%s\t%.*lf\n", \
                                   labels[a], labels[b], prec, x)
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   } else if(labels != NULL && absval == 0 && prec == 0) {
#define DOABS(x) x
#define PRINTEDGE(a, b, x) fprintf(out, "%s\t%s\n", \
                                   labels[a], labels[b])
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   } else if(labels == NULL && absval != 0 && prec != 0) {
#define DOABS(x) fabs(x)
#define PRINTEDGE(a, b, x) fprintf(out, "%d\t%d\t%.*lf\n", a, b, prec, x)
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   } else if(labels == NULL && absval != 0 && prec == 0) {
#define DOABS(x) fabs(x)
#define PRINTEDGE(a, b, x) fprintf(out, "%d\t%d\n", a, b)
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   } else if(labels == NULL && absval == 0 && prec != 0) {
#define DOABS(x) x
#define PRINTEDGE(a, b, x) fprintf(out, "%d\t%d\t%.*lf\n", a, b, prec, x)
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   } else /* if(labels == NULL && absval == 0 && prec == 0) */ {
#define DOABS(x) x
#define PRINTEDGE(a, b, x) fprintf(out, "%d\t%d\n", a, b)
#include "graphioPrintEdgelist.c"
#undef DOABS
#undef PRINTEDGE
   }

   return 0;
}

static unsigned long ECNTFUNC(double threshold, int absval, const MYTYPE *mat,
                              int valbits, MYTYPE denom, MYTYPE flag,
                              unsigned int* len) {
   int idx, numvals, cnt = 1;
   unsigned int i, j, mylen = 0;
   unsigned long edgecnt = 0;
   MYUTYPE mask, imask = 0, nmask = 0;
   MYTYPE tmp;
   double val;
   const MYTYPE *pos = mat;
   char *labels;

   if(mat == NULL || denom == 0 || valbits == 0) return 0;
   if(valbits > sizeof(MYTYPE)*CHAR_BIT) return 0;
   numvals = sizeof(MYTYPE)*CHAR_BIT/valbits;
   if(numvals*valbits != sizeof(MYTYPE)*CHAR_BIT) return 0;

   labels = (char *)malloc((*len)*sizeof(char));
   if(labels == NULL) return 0;
   memset(labels, 0, (*len)*sizeof(char));

   for(idx = 0; idx < valbits; idx++) {
      imask|= 1<<(idx+sizeof(MYUTYPE)*CHAR_BIT-valbits);
   }
   for(idx = valbits-1; idx < sizeof(MYUTYPE)*CHAR_BIT; idx++) {
      nmask|= 1<<idx;
   }
   mask = imask;

   if(absval != 0) {
#define DOABS(x) fabs(x)
#include "graphioEdgeCnt.c"
#undef DOABS
   } else /* if(absval == 0) */ {
#define DOABS(x) x
#include "graphioEdgeCnt.c"
#undef DOABS
   }

   *len = mylen;
   return edgecnt;
}

static int MATRIXREAD(FILE *in, double threshold, int absval,
                      int valbits, MYTYPE denom, MYTYPE flag,
                      LabelList **labels, MYTYPE **mat, int *errLine,
                      const char **errStr) {
   TabDelimFile *tdf;
   LabelList *tlabels;
   MYTYPE *pos, *tmat;
   MYUTYPE mask;
   unsigned int i, j, numvals, mlen, len, shift;
   int err;

#ifdef DEBUG
#  define ERRLINE(line, str) { \
if(errLine != NULL) *errLine = (__LINE__); \
if(errStr != NULL) *errStr = (__FILE__); \
}
#else
#  define ERRLINE(line, str) { \
if(errLine != NULL) *errLine = (line); \
if(errStr != NULL) *errStr = (str); \
}
#endif

   if(in == NULL || mat == NULL || denom == 0 || valbits == 0) {
      ERRLINE(-1, "");
      return -1;
   }
   if(valbits > sizeof(MYTYPE)*CHAR_BIT) {
      ERRLINE(-1, "");
      return -2;
   }
   numvals = sizeof(MYTYPE)*CHAR_BIT/valbits;
   if(numvals*valbits != sizeof(MYTYPE)*CHAR_BIT) {
      ERRLINE(-1, "");
      return -2;
   }
   if((tdf = initTabDelimFile(in)) == NULL) {
      ERRLINE(-1, "");
      return -3;
   }
   tdf_setCommentDelim(tdf, COMMENT);
   tdf_skipBlankLines(tdf);

   *mat = NULL;
   if(labels != NULL) {
      *labels = NULL;
   }

   mask = 0;
   for(i = 0; i < (unsigned int)valbits; i++) {
      mask|= 1<<i;
   }
   flag&= mask;

   if(tdf_getLine(tdf) < 0 || tdf_getNumFields(tdf) != 1) {
      ERRLINE(1, "first line format is invalid");
      freeTabDelimFile(tdf);
      return -4;
   }

   if((len = tdf_getFieldAsInt(tdf, 0, &err)) == 0) {
      ERRLINE(1, "number of vertices not a valid number");
      freeTabDelimFile(tdf);
      return err;
   }

   mlen = len*(len-1)>>1;
   mlen = (mlen%numvals != 0)?((mlen/numvals) + 1):(mlen/numvals);
   tmat = (MYTYPE *)malloc(sizeof(MYTYPE)*mlen);
   tlabels = initLabelList(len);
   memset(tmat, 0, sizeof(MYTYPE)*mlen);
   if(tmat == NULL || tlabels == NULL) {
      ERRLINE(-1, "");
      freeTabDelimFile(tdf);
      freeLabelList(tlabels);
      free(tmat);
      return -3;
   }
   tdf_setCommentDelim(tdf, COMMENT);
   tdf_skipBlankLines(tdf);

   pos = tmat;
   shift = numvals*valbits;
   if(absval != 0) {
#define DOABS(x) fabs(x)
#include "graphioReadMatrixLT.c"
#undef DOABS
   } else {
#define DOABS(x) (x)
#include "graphioReadMatrixLT.c"
#undef DOABS
   }

   *mat = tmat;
   if(labels != NULL) {
      *labels = tlabels;
   } else {
      freeLabelList(tlabels);
   }
   freeTabDelimFile(tdf);

   return len;
#undef ERRLINE
}

static int ELISTREAD(FILE *in, double threshold, int absval,
                     int valbits, MYTYPE denom, MYTYPE flag,
                     LabelList **labels, MYTYPE **mat, int *errLine,
                     const char **errStr) {
   TabDelimFile *tdf;
   LabelList *tlabels;
   MYTYPE *pos, *tmat;
   MYUTYPE mask, blockflag;
   MYTYPE val, nflag;
   unsigned int i, numvals, mlen, len, shift;
   unsigned long edge, edgecnt;
   int err, fcnt = 0;

#ifdef DEBUG
#  define ERRLINE(line, str) { \
if(errLine != NULL) *errLine = (__LINE__); \
if(errStr != NULL) *errStr = (__FILE__); \
}
#else
#  define ERRLINE(line, str) { \
if(errLine != NULL) *errLine = (line); \
if(errStr != NULL) *errStr = (str); \
}
#endif

   //printf("%d %d %d %d\n",in,mat,denom,valbits);
   if(in == NULL || mat == NULL || denom == 0 || valbits == 0) {
      ERRLINE(-1, "");
      return -1;
   }
   if(valbits > sizeof(MYTYPE)*CHAR_BIT) {
      ERRLINE(-1, "");
      return -2;
   }
   numvals = sizeof(MYTYPE)*CHAR_BIT/valbits;
   if(numvals*valbits != sizeof(MYTYPE)*CHAR_BIT) {
      ERRLINE(-1, "");
      return -2;
   }
   if((tdf = initTabDelimFile(in)) == NULL) {
      ERRLINE(-1, "");
      return -3;
   }
   tdf_setCommentDelim(tdf, COMMENT);
   tdf_skipBlankLines(tdf);

   *mat = NULL;
   if(labels != NULL) {
      *labels = NULL;
   }

   mask = 0;
   for(i = 0; i < (unsigned int)valbits; i++) {
      mask|= 1<<i;
   }
   flag&= mask;
   if(valbits == 1) {
      nflag = (MYTYPE)((flag == 1)?(0):(1));
   } else {
      nflag = (MYTYPE)((flag == 1)?(mask&(-1)):(1));
   }
   blockflag = 0;
   for(i = 0; i < numvals; i++) {
      blockflag|= flag<<(i*valbits);
   }

   if(tdf_getLine(tdf) < 0 || tdf_getNumFields(tdf) != 2) {
      ERRLINE(1, "first line format is invalid");
      freeTabDelimFile(tdf);
      return -4;
   }

   if((len = tdf_getFieldAsInt(tdf, 0, &err)) == 0) {
      ERRLINE(1, "invalid value for number of vertices");
      freeTabDelimFile(tdf);
      return err;
   }
   if((edgecnt = tdf_getFieldAsInt(tdf, 1, &err)) == 0) {
      ERRLINE(1, "invalid value for number of edges");
      freeTabDelimFile(tdf);
      return err;
   }

   mlen = len*(len-1)>>1;
   mlen = (mlen%numvals != 0)?((mlen/numvals) + 1):(mlen/numvals);
   tmat = (MYTYPE *)malloc(sizeof(MYTYPE)*mlen);
   tlabels = initLabelList(len);
   if(tmat == NULL || tlabels == NULL) {
      ERRLINE(-1, "");
      freeTabDelimFile(tdf);
      freeLabelList(tlabels);
      free(tmat);
      return -3;
   }
   tdf_setCommentDelim(tdf, COMMENT);
   tdf_skipBlankLines(tdf);

   pos = tmat;
   for(i = 0; i < mlen; i++) {
      *pos = blockflag;
      pos++;
   }

   pos = tmat;
   shift = numvals*valbits;
   if(absval != 0) {
#define DOABS(x) fabs(x)
#include "graphioReadEdgelist.c"
#undef DOABS
   } else {
#define DOABS(x) (x)
#include "graphioReadEdgelist.c"
#undef DOABS
   }

   len = ll_getLength(tlabels);
   mlen = len*(len-1)>>1;
   mlen = (mlen%numvals != 0)?((mlen/numvals) + 1):(mlen/numvals);
   if((*mat = (MYTYPE *)realloc(tmat, mlen*sizeof(MYTYPE))) == NULL) {
      *mat = tmat;
   }

   if(labels != NULL) {
      ll_compactList(tlabels);
      *labels = tlabels;
   } else {
      freeLabelList(tlabels);
   }
   freeTabDelimFile(tdf);
   
   return len;
#undef ERRLINE
}
