]> granicus.if.org Git - graphviz/commitdiff
add lib/sparse convemience library: libsparse_C.la
authorellson <devnull@localhost>
Wed, 30 Jul 2008 20:17:50 +0000 (20:17 +0000)
committerellson <devnull@localhost>
Wed, 30 Jul 2008 20:17:50 +0000 (20:17 +0000)
add cmd/tools/mm2gv - using libsparse

cmd/tools/Makefile.am
cmd/tools/Makefile.old
cmd/tools/matrix_market.c [new file with mode: 0644]
cmd/tools/matrix_market.h [new file with mode: 0644]
cmd/tools/mm2gv [new file with mode: 0755]
cmd/tools/mm2gv.c [new file with mode: 0644]
cmd/tools/mmio.c [new file with mode: 0644]
cmd/tools/mmio.h [new file with mode: 0644]
configure.ac
lib/Makefile.am

index 73d480e4b72acb17c8fa92b8beea005f96e9f80b..0ab1bae74f9138819526922e8cc5d1a26b88f0d1 100644 (file)
@@ -18,6 +18,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/lib/pathplan \
        -I$(top_srcdir)/lib/pack \
        -I$(top_srcdir)/lib/neatogen \
+       -I$(top_srcdir)/lib/sparse \
        -I$(top_srcdir)/lib/gvc \
        -I$(top_srcdir)/lib/common \
        -I$(top_srcdir)/lib/ingraphs @EXPAT_INCLUDES@
@@ -26,7 +27,7 @@ pdfdir = $(pkgdatadir)/doc/pdf
 
 noinst_HEADERS = colortbl.h convert.h
 bin_PROGRAMS = gc gvcolor gxl2dot acyclic nop ccomps sccmap tred \
-       unflatten gvpack dijkstra bcomps
+       unflatten gvpack dijkstra bcomps mm2gv
 man_MANS = gc.1 gvcolor.1 gxl2dot.1 acyclic.1 nop.1 ccomps.1 sccmap.1 \
        tred.1 unflatten.1 gvpack.1 dijkstra.1 bcomps.1
 pdf_DATA = gc.pdf gvcolor.pdf gxl2dot.pdf acyclic.pdf nop.pdf ccomps.pdf \
@@ -112,6 +113,14 @@ gvpack_LDADD = \
        $(top_builddir)/lib/ingraphs/libingraphs_C.la \
        $(top_builddir)/plugin/neato_layout/libgvplugin_neato_layout.la
 
+mm2gv_SOURCES = mm2gv.c matrix_market.c mmio.c
+
+mm2gv_LDADD = \
+       $(top_builddir)/lib/gvc/libgvc.la \
+       $(top_builddir)/lib/ingraphs/libingraphs_C.la \
+       $(top_builddir)/lib/sparse/libsparse_C.la \
+       $(top_builddir)/plugin/neato_layout/libgvplugin_neato_layout.la
+
 dijkstra_SOURCES = dijkstra.c
 
 dijkstra_LDADD = \
index 5de428cd39305bededa43d25eb06e8e1d91c4614..4a008dcd075bf26644be5693c98ff815ee7473c0 100644 (file)
@@ -65,10 +65,24 @@ CCOBJS = ccomps.o
 SCCOBJS = sccmap.o
 GXLOBJS = cvtgxl.o   dot2gxl.o  gxl2dot.o
 GVPOBJS = gvpack.o gvpack_builtins.o
+MMGVOBJS = mm2gv.o matrix_market.o mmio.o
+
 BCCOBJS = bcomps.o
 MANS = acyclic.1 gvcolor.1 nop.1 tred.1 ccomps.1 gc.1 sccmap.1 \
        unflatten.1 gxl2dot.1 dot2gxl.1 gvpack.1 bcomps.1
 
+mm2gv : $(GVPOBJS)
+       $(CPP) $(LDFLAGS) $(MMGVOBJS) $(INGLIB) $(PDNLIBS) -o $@
+
+mm2gv.o : mm2gv.c
+       $(CC) -c $(CCFLAGS) $(DEFINES) $(DNINCS) $(PINCS) mm2gv.c
+
+matrix_market.o : matrix_market.c
+       $(CC) -c $(CCFLAGS) $(DEFINES) $(DNINCS) $(PINCS) matrix_market.c
+
+mmio.o : mmio.c
+       $(CC) -c $(CCFLAGS) $(DEFINES) $(DNINCS) $(PINCS) mmio.c
+
 gvpack : $(GVPOBJS)
        $(CPP) $(LDFLAGS) $(GVPOBJS) $(INGLIB) $(PDNLIBS) -o $@
 
diff --git a/cmd/tools/matrix_market.c b/cmd/tools/matrix_market.c
new file mode 100644 (file)
index 0000000..36052af
--- /dev/null
@@ -0,0 +1,307 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "SparseMatrix.h"
+#include "mmio.h"
+#include "matrix_market.h"
+#include "render.h"
+#define MALLOC gmalloc
+#define REALLOC grealloc
+#define FREE free
+#define MEMCPY memcpy
+
+int mm_get_type(MM_typecode typecode){
+  if (mm_is_complex(typecode)){
+    return MATRIX_TYPE_COMPLEX;
+  } else if (mm_is_real(typecode)) {
+    return MATRIX_TYPE_REAL;
+  } else if (mm_is_integer(typecode)) {
+    return MATRIX_TYPE_INTEGER;
+  } else if (mm_is_pattern(typecode)){
+    return MATRIX_TYPE_PATTERN;
+  }
+  return MATRIX_TYPE_UNKNOWN;
+}
+
+static void set_mm_typecode(int type, MM_typecode *typecode){
+  switch (type){
+  case MATRIX_TYPE_COMPLEX:
+    mm_set_complex(typecode);
+    break;
+  case MATRIX_TYPE_REAL:
+    mm_set_real(typecode);
+    break;
+  case MATRIX_TYPE_INTEGER:
+    mm_set_integer(typecode);
+    break;
+  case MATRIX_TYPE_PATTERN:
+    mm_set_pattern(typecode);
+    break;
+  default:
+    break;
+  }
+}
+
+
+
+
+SparseMatrix SparseMatrix_import_matrix_market(FILE *f, int format){
+  int ret_code, type;
+  MM_typecode matcode;
+  real *val = NULL, *v;
+  int *vali = NULL, i, m, n, *I = NULL, *J = NULL, nz;
+  void *vp = NULL;
+  SparseMatrix A = NULL;
+  int nzold;
+  int c;
+
+  if ((c=fgetc(f)) != '%'){
+    ungetc(c, f);
+    return NULL;
+  }
+  ungetc(c, f);
+  if (mm_read_banner(f, &matcode) != 0) {
+#ifdef DEBUG
+    printf("Could not process Matrix Market banner.\n");
+#endif
+    return NULL;
+  }
+  
+  
+  /*  This is how one can screen matrix types if their application */
+  /*  only supports a subset of the Matrix Market data types.      */
+  
+  if (!mm_is_matrix(matcode) || 
+      !mm_is_sparse(matcode) ){
+    assert(0);
+    /*
+       printf("Sorry, this application does not support dense matrix");
+       printf("Market Market type: [%s]\n", mm_typecode_to_str(matcode));
+    */
+    return NULL;
+  }
+  
+  /* find out size of sparse matrix .... */
+  if ((ret_code = mm_read_mtx_crd_size(f, &m, &n, &nz)) !=0){
+    assert(0);
+    return NULL;
+  }
+  /* reseve memory for matrices */
+  
+  I = MALLOC(nz * sizeof(int));
+  J = MALLOC(nz * sizeof(int));
+  
+  
+
+  switch (format){
+  case FORMAT_CSC:
+    assert(0);/* not supported yet */
+    break;
+  case FORMAT_CSR:
+  case FORMAT_COORD:
+
+    /* NOTE: when reading in doubles, ANSI C requires the use of the "l"  */
+    /*   specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
+    /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */
+    type = mm_get_type(matcode);
+    switch (type) {
+    case MATRIX_TYPE_REAL:
+      val = (real *) malloc(nz * sizeof(real));
+      for (i=0; i<nz; i++) {
+       fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
+       I[i]--;  /* adjust from 1-based to 0-based */
+       J[i]--;
+      }
+      if (mm_is_symmetric(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       val = REALLOC(val, 2*sizeof(real)*nz);
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         if (I[i] != J[i]) {
+           I[nz] = J[i];
+           J[nz] = I[i];
+           val[nz++] = val[i];
+         }
+       }
+      } else if (mm_is_skew(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       val = REALLOC(val, 2*sizeof(real)*nz);
+       vp = (void*) val;
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         assert(I[i] != J[i]);/* skew symm has no diag */
+         I[nz] = J[i];
+         J[nz] = I[i];
+         val[nz++] = -val[i];
+       }
+      } else {
+       assert(!mm_is_hermitian(matcode));
+      }
+      vp = (void*) val;
+      break;
+    case MATRIX_TYPE_INTEGER:
+      vali = (int *) malloc(nz * sizeof(int));
+      for (i=0; i<nz; i++) {
+       fscanf(f, "%d %d %d\n", &I[i], &J[i], &vali[i]);
+       I[i]--;  /* adjust from 1-based to 0-based */
+       J[i]--;
+      }
+      if (mm_is_symmetric(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       vali = REALLOC(vali, 2*sizeof(int)*nz);
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         if (I[i] != J[i]) {
+           I[nz] = J[i];
+           J[nz] = I[i];
+           vali[nz++] = vali[i];
+         }
+       }
+      } else if (mm_is_skew(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       vali = REALLOC(vali, 2*sizeof(int)*nz);
+       vp = (void*) val;
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         assert(I[i] != J[i]);/* skew symm has no diag */
+         I[nz] = J[i];
+         J[nz] = I[i];
+         vali[nz++] = -vali[i];
+       }
+      } else {
+       assert(!mm_is_hermitian(matcode));
+      }
+      vp = (void*) vali;
+      break;
+    case MATRIX_TYPE_PATTERN:
+      for (i=0; i<nz; i++) {
+       fscanf(f, "%d %d\n", &I[i], &J[i]);
+       I[i]--;  /* adjust from 1-based to 0-based */
+       J[i]--;
+      }
+      if (mm_is_symmetric(matcode) || mm_is_skew(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         if (I[i] != J[i]) {
+           I[nz] = J[i];
+           J[nz++] = I[i];
+         }
+       }
+      } else {
+       assert(!mm_is_hermitian(matcode));
+      }
+      break;
+    case MATRIX_TYPE_COMPLEX:
+      val = (real *) malloc(2* nz * sizeof(real));
+      v = val;
+      for (i=0; i<nz; i++) {
+       fscanf(f, "%d %d %lg %lg\n", &I[i], &J[i], &v[0], &v[1]);
+       v +=2;
+       I[i]--;  /* adjust from 1-based to 0-based */
+       J[i]--;
+      }
+      if (mm_is_symmetric(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       val = REALLOC(val, 4*sizeof(real)*nz);
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         if (I[i] != J[i]) {
+           I[nz] = J[i];
+           J[nz] = I[i];
+           val[2*nz] = val[2*i];
+           val[2*nz+1] = val[2*i+1];
+           nz++;
+         }
+       }
+      } else if (mm_is_skew(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       val = REALLOC(val, 4*sizeof(real)*nz);
+       vp = (void*) val;
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         assert(I[i] != J[i]);/* skew symm has no diag */
+         I[nz] = J[i];
+         J[nz] = I[i];
+         val[2*nz] = -val[2*i];
+         val[2*nz+1] = -val[2*i+1];
+         nz++;
+
+       }
+      } else if (mm_is_hermitian(matcode)){
+       I = REALLOC(I, 2*sizeof(int)*nz);
+       J = REALLOC(J, 2*sizeof(int)*nz);
+       val = REALLOC(val, 4*sizeof(real)*nz);
+       vp = (void*) val;
+       nzold = nz;
+       for (i = 0; i < nzold; i++){
+         if (I[i] != J[i]){
+           I[nz] = J[i];
+           J[nz] = I[i];
+           val[2*nz] = val[2*i];
+           val[2*nz+1] = -val[2*i+1];
+           nz++;
+         }
+       }
+      }
+      vp = (void*) val;
+      break;
+    default:
+      return 0;
+    }
+
+    if (format == FORMAT_CSR) {
+      A = SparseMatrix_from_coordinate_arrays(nz, m, n, I, J, vp, type);
+    } else {
+      A = SparseMatrix_new(m, n, 1, type, FORMAT_COORD);
+      A = SparseMatrix_coordinate_form_add_entries(A, nz, I, J, vp);
+    }
+    break;
+  default:
+    A = NULL;
+  }
+  FREE(I);
+  FREE(J);
+  FREE(val);
+
+  if (mm_is_symmetric(matcode)){
+    SparseMatrix_set_symmetric(A);
+    SparseMatrix_set_pattern_symmetric(A);
+  } else if (mm_is_skew(matcode)){
+    SparseMatrix_set_skew(A);
+  } else if (mm_is_hermitian(matcode)){
+    SparseMatrix_set_hemitian(A);
+  }
+
+
+  return A;
+}
+
+
+static void mm_write_comment(FILE *file, char *comment){
+  char percent[2]="%";
+  fprintf(file, "%s %s\n",percent,comment);
+}
+
+void SparseMatrix_export_matrix_market(FILE *file, SparseMatrix A, char *comment){
+  MM_typecode matcode;     
+
+  mm_initialize_typecode(&matcode);
+  mm_set_matrix(&matcode);
+  mm_set_sparse(&matcode);
+  mm_set_general(&matcode);
+  set_mm_typecode(A->type, &matcode);
+
+  mm_write_banner(file, matcode); 
+  mm_write_comment(file, comment);
+
+  SparseMatrix_export(file, A);
+
+}  
diff --git a/cmd/tools/matrix_market.h b/cmd/tools/matrix_market.h
new file mode 100644 (file)
index 0000000..50b9f82
--- /dev/null
@@ -0,0 +1,5 @@
+#include "mmio.h"
+#include "SparseMatrix.h"
+int mm_get_type(MM_typecode typecode);
+void SparseMatrix_export_matrix_market(FILE *file, SparseMatrix A, char *comment);
+SparseMatrix SparseMatrix_import_matrix_market(FILE *f, int format);
diff --git a/cmd/tools/mm2gv b/cmd/tools/mm2gv
new file mode 100755 (executable)
index 0000000..cd6f439
--- /dev/null
@@ -0,0 +1,131 @@
+#! /bin/sh
+
+# mm2gv - temporary wrapper script for .libs/mm2gv
+# Generated by ltmain.sh - GNU libtool 1.5.24 (1.1220.2.456 2007/06/24 02:25:32)
+#
+# The mm2gv program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='/bin/sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/ellson/FIX/Linux.x86_64/build/graphviz2/cmd/tools; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=\"/home/ellson/bin:/home/ellson/FIX/Linux.x86_64/bin:/usr/lib64/qt-3.3/bin:/usr/kerberos/bin:/usr/lib64/ccache:/usr/local/bin:/usr/bin:/bin:/bin\"; export PATH; /usr/bin/gcc -g -O2 -Wno-unknown-pragmas -Wstrict-prototypes -Wpointer-arith -Wall -ffast-math -o \$progdir/\$file mm2gv.o matrix_market.o mmio.o  -L/home/ellson/FIX/Linux.x86_64/lib ../../lib/gvc/.libs/libgvc.so ../../lib/ingraphs/.libs/libingraphs_C.a ../../lib/sparse/.libs/libsparse_C.a ../../plugin/neato_layout/.libs/libgvplugin_neato_layout.so /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/gvc/.libs/libgvc.so -lexpat /usr/lib64/libltdl.so -ldl -lz /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/graph/.libs/libgraph.so /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/cdt/.libs/libcdt.so /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/pathplan/.libs/libpathplan.so -lgts -lglib-2.0 -lm  -Wl,--rpath -Wl,/home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/gvc/.libs -Wl,--rpath -Wl,/home/ellson/FIX/Linux.x86_64/build/graphviz2/plugin/neato_layout/.libs -Wl,--rpath -Wl,/home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/graph/.libs -Wl,--rpath -Wl,/home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/cdt/.libs -Wl,--rpath -Wl,/home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/pathplan/.libs -Wl,--rpath -Wl,/home/ellson/FIX/Linux.x86_64/lib -Wl,--rpath -Wl,/home/ellson/FIX/Linux.x86_64/lib/graphviz ) "
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+  # install mode needs the following variable:
+  notinst_deplibs=' ../../lib/gvc/libgvc.la ../../plugin/neato_layout/libgvplugin_neato_layout.la /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/gvc/libgvc.la /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/graph/libgraph.la /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/cdt/libcdt.la /home/ellson/FIX/Linux.x86_64/build/graphviz2/lib/pathplan/libpathplan.la'
+else
+  # When we are sourced in execute mode, $file and $echo are already set.
+  if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+    echo="echo"
+    file="$0"
+    # Make sure echo works.
+    if test "X$1" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+      # Yippee, $echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe $echo will work.
+      exec /bin/sh "$0" --no-reexec ${1+"$@"}
+    fi
+  fi
+
+  # Find the directory that this script lives in.
+  thisdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+  test "x$thisdir" = "x$file" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+  while test -n "$file"; do
+    destdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+
+    # If there was a directory component, then change thisdir.
+    if test "x$destdir" != "x$file"; then
+      case "$destdir" in
+      [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+      *) thisdir="$thisdir/$destdir" ;;
+      esac
+    fi
+
+    file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+    file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=`cd "$thisdir" && pwd`
+  test -n "$absdir" && thisdir="$absdir"
+
+  program=lt-'mm2gv'
+  progdir="$thisdir/.libs"
+
+  if test ! -f "$progdir/$program" || \
+     { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+       test "X$file" != "X$progdir/$program"; }; then
+
+    file="$$-$program"
+
+    if test ! -d "$progdir"; then
+      mkdir "$progdir"
+    else
+      rm -f "$progdir/$file"
+    fi
+
+    # relink executable if necessary
+    if test -n "$relink_command"; then
+      if relink_command_output=`eval $relink_command 2>&1`; then :
+      else
+       echo "$relink_command_output" >&2
+       rm -f "$progdir/$file"
+       exit 1
+      fi
+    fi
+
+    mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+    { rm -f "$progdir/$program";
+      mv -f "$progdir/$file" "$progdir/$program"; }
+    rm -f "$progdir/$file"
+  fi
+
+  if test -f "$progdir/$program"; then
+    if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+      # Run the actual program with our arguments.
+
+      exec "$progdir/$program" ${1+"$@"}
+
+      $echo "$0: cannot exec $program $*"
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    $echo "$0: error: \`$progdir/$program' does not exist" 1>&2
+    $echo "This script is just a wrapper for $program." 1>&2
+    echo "See the libtool documentation for more information." 1>&2
+    exit 1
+  fi
+fi
diff --git a/cmd/tools/mm2gv.c b/cmd/tools/mm2gv.c
new file mode 100644 (file)
index 0000000..e64971e
--- /dev/null
@@ -0,0 +1,417 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+#include "mmio.h"
+#include "SparseMatrix.h"
+#include "matrix_market.h"
+#define MALLOC malloc
+#define FREE free
+#define test_flag(a, flag) ((a)&(flag))
+
+#include "render.h"
+
+#define real double
+
+#define ND_id(n) (n)->u.id
+
+real distance(real *x, int dim, int i, int j){
+  int k;
+  real dist = 0.;
+  for (k = 0; k < dim; k++) dist += (x[i*dim+k] - x[j*dim + k])*(x[i*dim+k] - x[j*dim + k]);
+  dist = sqrt(dist);
+  return dist;
+}
+
+real Hue2RGB(real v1, real v2, real H) {
+  if(H < 0.0) H += 1.0;
+  if(H > 1.0) H -= 1.0;
+  if((6.0*H) < 1.0) return (v1 + (v2 - v1) * 6.0 * H);
+  if((2.0*H) < 1.0) return v2;
+  if((3.0*H) < 2.0) return (v1 + (v2 - v1) * ((2.0/3.0) - H) * 6.0);
+  return v1;
+}
+
+char *hex[16]={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
+
+char * hue2rgb(real hue, char *color){
+  real v1, v2, lightness = .5, saturation = 1;
+  int red, blue, green;
+
+  if(lightness < 0.5) 
+    v2 = lightness * (1.0 + saturation);
+  else
+    v2 = (lightness + saturation) - (saturation * lightness);
+
+  v1 = 2.0 * lightness - v2;
+
+  red =   (int)(255.0 * Hue2RGB(v1, v2, hue + (1.0/3.0)) + 0.5);
+  green = (int)(255.0 * Hue2RGB(v1, v2, hue) + 0.5);
+  blue =  (int)(255.0 * Hue2RGB(v1, v2, hue - (1.0/3.0)) + 0.5);
+  color[0] = '#';
+  sprintf(color+1,"%s",hex[red/16]);
+  sprintf(color+2,"%s",hex[red%16]);
+  sprintf(color+3,"%s",hex[green/16]);
+  sprintf(color+4,"%s",hex[green%16]);
+  sprintf(color+5,"%s",hex[blue/16]);
+  sprintf(color+6,"%s",hex[blue%16]);
+  color[7] = '\0';
+  return color;
+}
+
+static void
+posStr (char* buf, int dim, real* x, double sc)
+{
+  if (dim== 3){
+    sprintf (buf, "%f,%f,%f", sc*x[0], sc*x[1], sc*x[2]);
+  } else {
+    sprintf (buf, "%f,%f", sc*x[0], sc*x[1]);
+  }
+}
+
+void 
+attach_embedding (Agraph_t* g, int dim, double sc, real *x)
+{
+  Agsym_t* sym = agfindattr(g->proto->n, "pos"); 
+  Agnode_t* n;
+  char buf[1024];
+  int i = 0;
+
+  if (!sym)
+    sym = agnodeattr (g, "pos", "");
+
+  for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
+    assert (i == ND_id(n));
+    posStr (buf, dim, x + i*dim, sc);
+    agxset (n, sym->index, buf);
+    i++;
+  }
+  
+}
+
+/* SparseMatrix_import_dot:
+ * Assumes g is connected and simple, i.e., we can have a->b and b->a
+ * but not a->b and a->b
+ */
+SparseMatrix 
+SparseMatrix_import_dot (Agraph_t* g, int dim, real **label_sizes, real **x, int format)
+{
+  SparseMatrix A = 0;
+  Agnode_t* n;
+  Agedge_t* e;
+  Agsym_t* sym;
+  int nnodes;
+  int nedges;
+  int i, row;
+  int* I;
+  int* J;
+  real* val;
+  real v;
+  int type = MATRIX_TYPE_REAL;
+  real padding = 10;
+
+  if (!g) return NULL;
+  nnodes = agnnodes (g);
+  nedges = agnedges (g);
+  if (format != FORMAT_CSR) {
+    fprintf (stderr, "Format %d not supported\n", format);
+    exit (1);
+  }
+
+  /* Assign node ids */
+  i = 0;
+  for (n = agfstnode (g); n; n = agnxtnode (g, n))
+    ND_id(n) = i++;
+
+  I = N_NEW(nedges, int);
+  J = N_NEW(nedges, int);
+  val = N_NEW(nedges, real);
+
+  sym = agfindattr(g->proto->e, "wt"); 
+  i = 0;
+  for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
+    row = ND_id(n);
+    for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
+      I[i] = row;
+      J[i] = ND_id(e->head);
+      if (sym) {
+        if (sscanf (agxget (e, sym->index), "%lf", &v) != 1)
+          v = 1;
+      }
+      else
+        v = 1;
+      val[i] = v;
+      i++;
+    }
+  }
+  
+  *label_sizes = MALLOC(sizeof(real)*2*nnodes);
+  for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
+    real sz;
+    i = ND_id(n);
+    if (agget(n, "width") && agget(n, "height")){
+      sscanf(agget(n, "width"), "%lf", &sz);
+      /*      (*label_sizes)[i*2] = POINTS(sz)*.6;*/
+      (*label_sizes)[i*2] = POINTS(sz)*.5 + padding*0.5;
+      sscanf(agget(n, "height"), "%lf", &sz);
+      /*(*label_sizes)[i*2+1] = POINTS(sz)*.6;*/
+      (*label_sizes)[i*2+1] = POINTS(sz)*.5  + padding*0.5;
+    } else {
+      (*label_sizes)[i*2] = 4*POINTS(0.75)*.5;
+      (*label_sizes)[i*2+1] = 4*POINTS(0.5)*.5;
+    }
+ }
+
+  if (x){
+    *x = MALLOC(sizeof(real)*dim*nnodes);
+    for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
+      real xx,yy;
+      i = ND_id(n);
+      if (agget(n, "pos")){
+       sscanf(agget(n, "pos"), "%lf,%lf", &xx, &yy);
+       (*x)[i*dim] = xx;
+       (*x)[i*dim+1] = yy;
+      } else {
+       (*x)[i*dim] = 0;
+       (*x)[i*dim+1] = 0;
+      }
+    }
+  }
+
+  A = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, val, type);
+
+  FREE(I);
+  FREE(J);
+  FREE(val);
+
+  return A;
+}
+
+char *strip_dir(char *s){
+  int i, first = TRUE;
+  for (i = strlen(s); i >= 0; i--) {
+    if (first && s[i] == '.') {/* get rid of .mtx */
+      s[i] = '\0';
+      first = FALSE;
+    }
+    if (s[i] == '/') return (char*) &(s[i+1]);
+  }
+  return s;
+}
+
+Agraph_t* 
+makeDotGraph (SparseMatrix A, char *name, int dim, real *x, int with_color, int with_label)
+{
+  Agraph_t* g;
+  Agnode_t* n;
+  Agnode_t* h;
+  Agedge_t* e;
+  int i, j;
+  char buf[1024], buf2[1024];
+  Agsym_t *sym, *sym2 = NULL, *sym3 = NULL;
+  int* ia=A->ia;
+  int* ja=A->ja;
+  real* val = (real*)(A->a);
+  Agnode_t** arr = N_NEW (A->m, Agnode_t*);
+  real *color = NULL;
+  char cstring[8];
+  char *label_string;
+
+  if (!name){
+    name = "stdin";
+  } else {
+    name = strip_dir(name);
+  }
+  label_string = MALLOC(sizeof(char)*1000);
+  aginit ();
+  if (SparseMatrix_known_undirected(A)){
+    g = agopen ("G", AGRAPH);
+  } else {
+    g = agopen ("G", AGDIGRAPH);
+  }
+  sprintf (buf, "%f", 1.0);
+
+  label_string = strcpy(label_string, name);
+  label_string = strcat(label_string, ". ");
+  sprintf (buf, "%d", A->m);
+  label_string = strcat(label_string, buf);
+  label_string = strcat(label_string, " nodes, ");
+  sprintf (buf, "%d", A->nz);
+  label_string = strcat(label_string, buf);
+  label_string = strcat(label_string, " edges.");
+
+
+  if (with_label) sym = agraphattr(g, "label", label_string); 
+  if (with_color) sym = agraphattr(g, "bgcolor", "black"); 
+
+
+  if (with_color) {
+    sym2 = agedgeattr(g, "color", ""); 
+    sym3 = agedgeattr(g, "wt", ""); 
+  }
+  for (i = 0; i < A->m; i++) {
+    sprintf (buf, "%d", i);
+    n = agnode (g, buf);
+    ND_id(n) = i;
+    arr[i] = n;
+  }
+
+  if (with_color){
+    real maxdist = 0.;
+    real mindist = 0.;
+    int first = TRUE;
+    color = malloc(sizeof(real)*A->nz);
+    for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
+      i = ND_id(n);
+      if (A->type != MATRIX_TYPE_REAL){
+       for (j = ia[i]; j < ia[i+1]; j++) {
+         color[j] = distance(x, dim, i, ja[j]);
+         if (i != ja[j]){
+           if (first){
+             mindist = color[j];
+             first = FALSE;
+           } else {
+             mindist = MIN(mindist, color[j]);
+           }
+         }
+         maxdist = MAX(color[j], maxdist);
+       }
+      } else {
+       for (j = ia[i]; j < ia[i+1]; j++) {
+         color[j] = ABS(val[j]);
+         if (i != ja[j]){
+           if (first){
+             mindist = color[j];
+             first = FALSE;
+           } else {
+             mindist = MIN(mindist, color[j]);
+           }
+         }
+         maxdist = MAX(color[j], maxdist);
+       }
+      }
+    }
+    for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
+      i = ND_id(n);
+      for (j = ia[i]; j < ia[i+1]; j++) {
+       color[j] = ((color[j] - mindist)/MAX(maxdist-mindist, 0.000001));
+      }
+    }
+  }
+
+  i = 0;
+  for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
+    i = ND_id(n);
+    for (j = ia[i]; j < ia[i+1]; j++) {
+      h = arr [ja[j]];
+      if (val){
+       sprintf (buf, "%f", val[j]);
+       if (with_color) sprintf (buf2, hue2rgb(.65*color[j], cstring));
+      } else {
+       sprintf (buf, "%f", 1.);
+       if (with_color) sprintf (buf2, hue2rgb(.65*color[j], cstring));
+     }
+      e = agedge (g, n, h);
+      if (with_color) {
+       agxset (e, sym2->index, buf2);
+       sprintf (buf2, "%f", color[j]);
+       agxset (e, sym3->index, buf2);
+      }
+    }
+  }
+  
+  FREE(color);
+  FREE (arr);
+  FREE(label_string);
+  return g;
+}
+
+
+
+static void usage (char* cmd, int eval)
+{
+    fprintf(stderr, "Usage: %s <option> matrix_market_filename.\n", cmd);
+    exit(eval);
+}
+
+static FILE* openF (char* fname, char* mode)
+{
+    FILE* f = fopen (fname, mode);
+    if (!f) {
+        fprintf (stderr, "Could not open %s for %s\n", fname,
+            ((*mode == 'r') ? "reading" : "writing"));
+        exit (1);
+    }
+    return f;
+}
+static int get_opt_sta_sto(int argc, char **argv, char *optchar, int *sta, int *sto){
+  int i, j;
+  *sta = 1; *sto = 0;
+  for (i = 1; i < argc; i++){
+    if (strcmp(argv[i], optchar) == 0){
+      *sta = i+1;
+      *sto = argc - 1;
+      for (j = *sta; j < argc; j++){
+       if (argv[j][0] == '-') {
+         *sto = j - 1;
+         return 1;
+       }
+      }
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int main(int argc, char *argv[])
+{
+  Agraph_t* g = 0;
+
+  char *infile = NULL;
+  FILE *f;
+  SparseMatrix A = NULL;
+  int dim;
+  int undirected = 0, sta, sto = 1;
+
+  /* ======================= read graph ==================== */
+  if (get_opt_sta_sto(argc, argv, "-u", &sta, &sto)){
+    undirected = 1;
+    infile = argv[sto];
+  } else {
+    infile = argv[1];
+  }
+
+
+  if (infile) {
+    f = openF (infile, "r");
+  } else {
+    f = stdin;
+  }
+
+  A = SparseMatrix_import_matrix_market(f, FORMAT_CSR);
+  if (!A) {
+    usage("sfdp",1);
+  }
+
+  A = SparseMatrix_to_square_matrix(A);
+
+  if (!A){
+    fprintf(stderr,"can not import from file %s\n",infile);
+    exit(1);
+  }
+
+  if (undirected) {
+    SparseMatrix B;
+    B = SparseMatrix_make_undirected(A);
+    SparseMatrix_delete(A);
+    A = B;
+  } 
+  g = makeDotGraph (A, infile, dim, NULL, FALSE, TRUE);
+    
+  f = stdout;
+  
+  agwrite (g, f);
+
+  return 0;
+}
diff --git a/cmd/tools/mmio.c b/cmd/tools/mmio.c
new file mode 100644 (file)
index 0000000..2e4cb87
--- /dev/null
@@ -0,0 +1,514 @@
+/* 
+*   Matrix Market I/O library for ANSI C
+*
+*   See http://math.nist.gov/MatrixMarket for details.
+*
+*
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+/*#include <malloc.h>*/
+#include <ctype.h>
+
+#include "mmio.h"
+
+int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
+                double **val_, int **I_, int **J_)
+{
+    FILE *f;
+    MM_typecode matcode;
+    int M, N, nz;
+    int i;
+    double *val;
+    int *I, *J;
+    if ((f = fopen(fname, "r")) == NULL)
+            return -1;
+    if (mm_read_banner(f, &matcode) != 0)
+    {
+        fprintf(stderr, "mm_read_unsymetric: Could not process Matrix Market banner ");
+        fprintf(stderr, " in file [%s]\n", fname);
+        return -1;
+    }
+    if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) &&
+            mm_is_sparse(matcode)))
+    {
+        fprintf(stderr, "Sorry, this application does not support ");
+        fprintf(stderr, "Market Market type: [%s]\n",
+                mm_typecode_to_str(matcode));
+        return -1;
+    }
+    /* find out size of sparse matrix: M, N, nz .... */
+    if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0)
+    {
+        fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n");
+        return -1;
+    }
+    *M_ = M;
+    *N_ = N;
+    *nz_ = nz;
+    /* reseve memory for matrices */
+    I = (int *) malloc(nz * sizeof(int));
+    J = (int *) malloc(nz * sizeof(int));
+    val = (double *) malloc(nz * sizeof(double));
+    *val_ = val;
+    *I_ = I;
+    *J_ = J;
+    /* NOTE: when reading in doubles, ANSI C requires the use of the "l"  */
+    /*   specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
+    /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */
+    for (i=0; i<nz; i++)
+    {
+        fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
+        I[i]--;  /* adjust from 1-based to 0-based */
+        J[i]--;
+    }
+    fclose(f);
+    return 0;
+}
+
+int mm_is_valid(MM_typecode matcode)
+{
+    if (!mm_is_matrix(matcode)) return 0;
+    if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;
+    if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;
+    if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) || 
+                mm_is_skew(matcode))) return 0;
+    return 1;
+}
+
+int mm_read_banner(FILE *f, MM_typecode *matcode)
+{
+    char line[MM_MAX_LINE_LENGTH];
+    char banner[MM_MAX_TOKEN_LENGTH];
+    char mtx[MM_MAX_TOKEN_LENGTH]; 
+    char crd[MM_MAX_TOKEN_LENGTH];
+    char data_type[MM_MAX_TOKEN_LENGTH];
+    char storage_scheme[MM_MAX_TOKEN_LENGTH];
+    char *p;
+
+
+    mm_clear_typecode(matcode);  
+
+    if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) 
+        return MM_PREMATURE_EOF;
+
+    if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type, 
+        storage_scheme) != 5)
+        return MM_PREMATURE_EOF;
+
+    for (p=mtx; *p!='\0'; *p=tolower(*p),p++);  /* convert to lower case */
+    for (p=crd; *p!='\0'; *p=tolower(*p),p++);  
+    for (p=data_type; *p!='\0'; *p=tolower(*p),p++);
+    for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++);
+
+    /* check for banner */
+    if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)
+        return MM_NO_HEADER;
+
+    /* first field should be "mtx" */
+    if (strcmp(mtx, MM_MTX_STR) != 0)
+        return  MM_UNSUPPORTED_TYPE;
+    mm_set_matrix(matcode);
+
+
+    /* second field describes whether this is a sparse matrix (in coordinate
+            storgae) or a dense array */
+
+
+    if (strcmp(crd, MM_SPARSE_STR) == 0)
+        mm_set_sparse(matcode);
+    else
+    if (strcmp(crd, MM_DENSE_STR) == 0)
+            mm_set_dense(matcode);
+    else
+        return MM_UNSUPPORTED_TYPE;
+    
+
+    /* third field */
+
+    if (strcmp(data_type, MM_REAL_STR) == 0)
+        mm_set_real(matcode);
+    else
+    if (strcmp(data_type, MM_COMPLEX_STR) == 0)
+        mm_set_complex(matcode);
+    else
+    if (strcmp(data_type, MM_PATTERN_STR) == 0)
+        mm_set_pattern(matcode);
+    else
+    if (strcmp(data_type, MM_INT_STR) == 0)
+        mm_set_integer(matcode);
+    else
+        return MM_UNSUPPORTED_TYPE;
+    
+
+    /* fourth field */
+
+    if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)
+        mm_set_general(matcode);
+    else
+    if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
+        mm_set_symmetric(matcode);
+    else
+    if (strcmp(storage_scheme, MM_HERM_STR) == 0)
+        mm_set_hermitian(matcode);
+    else
+    if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
+        mm_set_skew(matcode);
+    else
+        return MM_UNSUPPORTED_TYPE;
+        
+
+    return 0;
+}
+
+int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)
+{
+    if (fprintf(f, "%d %d %d\n", M, N, nz) != 3)
+        return MM_COULD_NOT_WRITE_FILE;
+    else 
+        return 0;
+}
+
+int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz )
+{
+    char line[MM_MAX_LINE_LENGTH];
+    int num_items_read;
+
+    /* set return null parameter values, in case we exit with errors */
+    *M = *N = *nz = 0;
+
+    /* now continue scanning until you reach the end-of-comments */
+    do 
+    {
+        if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL) 
+            return MM_PREMATURE_EOF;
+    }while (line[0] == '%');
+
+    /* line[] is either blank or has M,N, nz */
+    if (sscanf(line, "%d %d %d", M, N, nz) == 3)
+        return 0;
+        
+    else
+    do
+    { 
+        num_items_read = fscanf(f, "%d %d %d", M, N, nz); 
+        if (num_items_read == EOF) return MM_PREMATURE_EOF;
+    }
+    while (num_items_read != 3);
+
+    return 0;
+}
+
+
+int mm_read_mtx_array_size(FILE *f, int *M, int *N)
+{
+    char line[MM_MAX_LINE_LENGTH];
+    int num_items_read;
+    /* set return null parameter values, in case we exit with errors */
+    *M = *N = 0;
+       
+    /* now continue scanning until you reach the end-of-comments */
+    do 
+    {
+        if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL) 
+            return MM_PREMATURE_EOF;
+    }while (line[0] == '%');
+
+    /* line[] is either blank or has M,N, nz */
+    if (sscanf(line, "%d %d", M, N) == 2)
+        return 0;
+        
+    else /* we have a blank line */
+    do
+    { 
+        num_items_read = fscanf(f, "%d %d", M, N); 
+        if (num_items_read == EOF) return MM_PREMATURE_EOF;
+    }
+    while (num_items_read != 2);
+
+    return 0;
+}
+
+int mm_write_mtx_array_size(FILE *f, int M, int N)
+{
+    if (fprintf(f, "%d %d\n", M, N) != 2)
+        return MM_COULD_NOT_WRITE_FILE;
+    else 
+        return 0;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+
+/******************************************************************/
+/* use when I[], J[], and val[]J, and val[] are already allocated */
+/******************************************************************/
+
+int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
+        double val[], MM_typecode matcode)
+{
+    int i;
+    if (mm_is_complex(matcode))
+    {
+        for (i=0; i<nz; i++)
+            if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2*i], &val[2*i+1])
+                != 4) return MM_PREMATURE_EOF;
+    }
+    else if (mm_is_real(matcode))
+    {
+        for (i=0; i<nz; i++)
+        {
+            if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
+                != 3) return MM_PREMATURE_EOF;
+
+        }
+    }
+
+    else if (mm_is_pattern(matcode))
+    {
+        for (i=0; i<nz; i++)
+            if (fscanf(f, "%d %d", &I[i], &J[i])
+                != 2) return MM_PREMATURE_EOF;
+    }
+    else
+        return MM_UNSUPPORTED_TYPE;
+
+    return 0;
+        
+}
+
+int mm_read_mtx_crd_entry(FILE *f, int *I, int *J,
+        double *real, double *imag, MM_typecode matcode)
+{
+    if (mm_is_complex(matcode))
+    {
+            if (fscanf(f, "%d %d %lg %lg", I, J, real, imag)
+                != 4) return MM_PREMATURE_EOF;
+    }
+    else if (mm_is_real(matcode))
+    {
+            if (fscanf(f, "%d %d %lg\n", I, J, real)
+                != 3) return MM_PREMATURE_EOF;
+
+    }
+
+    else if (mm_is_pattern(matcode))
+    {
+            if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF;
+    }
+    else
+        return MM_UNSUPPORTED_TYPE;
+
+    return 0;
+        
+}
+
+
+/************************************************************************
+    mm_read_mtx_crd()  fills M, N, nz, array of values, and return
+                        type code, e.g. 'MCRS'
+
+                        if matrix is complex, values[] is of size 2*nz,
+                            (nz pairs of real/imaginary values)
+************************************************************************/
+
+int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J, 
+        double **val, MM_typecode *matcode)
+{
+    int ret_code;
+    FILE *f;
+
+    if (strcmp(fname, "stdin") == 0) f=stdin;
+    else
+    if ((f = fopen(fname, "r")) == NULL)
+        return MM_COULD_NOT_READ_FILE;
+
+
+    if ((ret_code = mm_read_banner(f, matcode)) != 0)
+        return ret_code;
+
+    if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) && 
+            mm_is_matrix(*matcode)))
+        return MM_UNSUPPORTED_TYPE;
+
+    if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)
+        return ret_code;
+
+
+    *I = (int *)  malloc(*nz * sizeof(int));
+    *J = (int *)  malloc(*nz * sizeof(int));
+    *val = NULL;
+
+    if (mm_is_complex(*matcode))
+    {
+        *val = (double *) malloc(*nz * 2 * sizeof(double));
+        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, 
+                *matcode);
+        if (ret_code != 0) return ret_code;
+    }
+    else if (mm_is_real(*matcode))
+    {
+        *val = (double *) malloc(*nz * sizeof(double));
+        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, 
+                *matcode);
+        if (ret_code != 0) return ret_code;
+    }
+
+    else if (mm_is_pattern(*matcode))
+    {
+        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val, 
+                *matcode);
+        if (ret_code != 0) return ret_code;
+    }
+
+    if (f != stdin) fclose(f);
+    return 0;
+}
+
+int mm_write_banner(FILE *f, MM_typecode matcode)
+{
+    char *str = mm_typecode_to_str(matcode);
+    int ret_code;
+
+    ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
+    free(str);
+    if (ret_code !=2 )
+        return MM_COULD_NOT_WRITE_FILE;
+    else
+        return 0;
+}
+
+int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
+        double val[], MM_typecode matcode)
+{
+    FILE *f;
+    int i;
+
+    if (strcmp(fname, "stdout") == 0) 
+        f = stdout;
+    else
+    if ((f = fopen(fname, "w")) == NULL)
+        return MM_COULD_NOT_WRITE_FILE;
+    
+    /* print banner followed by typecode */
+    fprintf(f, "%s ", MatrixMarketBanner);
+    fprintf(f, "%s\n", mm_typecode_to_str(matcode));
+
+    /* print matrix sizes and nonzeros */
+    fprintf(f, "%d %d %d\n", M, N, nz);
+
+    /* print values */
+    if (mm_is_pattern(matcode))
+        for (i=0; i<nz; i++)
+            fprintf(f, "%d %d\n", I[i], J[i]);
+    else
+    if (mm_is_real(matcode))
+        for (i=0; i<nz; i++)
+            fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
+    else
+    if (mm_is_complex(matcode))
+        for (i=0; i<nz; i++)
+            fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i], 
+                        val[2*i+1]);
+    else
+    {
+        if (f != stdout) fclose(f);
+        return MM_UNSUPPORTED_TYPE;
+    }
+
+    if (f !=stdout) fclose(f);
+
+    return 0;
+}
+  
+
+/**
+*  Create a new copy of a string s.  strdup() is a common routine, but
+*  not part of ANSI C, so it is included here.  Used by mm_typecode_to_str().
+*
+*/
+/* part of gcc
+char *strdup(const char *s)
+{
+       int len = strlen(s);
+       char *s2 = (char *) malloc((len+1)*sizeof(char));
+       return strcpy(s2, s);
+}
+*/
+
+char  *mm_typecode_to_str(MM_typecode matcode)
+{
+    char buffer[MM_MAX_LINE_LENGTH];
+    char *types[4];
+    /* char *strdup(const char *);*/
+    int error =0;
+
+    /* check for MTX type */
+    if (mm_is_matrix(matcode)) 
+        types[0] = MM_MTX_STR;
+    else
+        error=1;
+
+    /* check for CRD or ARR matrix */
+    if (mm_is_sparse(matcode))
+        types[1] = MM_SPARSE_STR;
+    else
+    if (mm_is_dense(matcode))
+        types[1] = MM_DENSE_STR;
+    else
+        return NULL;
+
+    /* check for element data type */
+    if (mm_is_real(matcode))
+        types[2] = MM_REAL_STR;
+    else
+    if (mm_is_complex(matcode))
+        types[2] = MM_COMPLEX_STR;
+    else
+    if (mm_is_pattern(matcode))
+        types[2] = MM_PATTERN_STR;
+    else
+    if (mm_is_integer(matcode))
+        types[2] = MM_INT_STR;
+    else
+        return NULL;
+
+
+    /* check for symmetry type */
+    if (mm_is_general(matcode))
+        types[3] = MM_GENERAL_STR;
+    else
+    if (mm_is_symmetric(matcode))
+        types[3] = MM_SYMM_STR;
+    else 
+    if (mm_is_hermitian(matcode))
+        types[3] = MM_HERM_STR;
+    else 
+    if (mm_is_skew(matcode))
+        types[3] = MM_SKEW_STR;
+    else
+        return NULL;
+
+    sprintf(buffer,"%s %s %s %s", types[0], types[1], types[2], types[3]);
+    return strdup(buffer);
+
+}
diff --git a/cmd/tools/mmio.h b/cmd/tools/mmio.h
new file mode 100644 (file)
index 0000000..d35d761
--- /dev/null
@@ -0,0 +1,133 @@
+/* 
+*   Matrix Market I/O library for ANSI C
+*
+*   See http://math.nist.gov/MatrixMarket for details.
+*
+*
+*/
+
+#ifndef MM_IO_H
+#define MM_IO_H
+
+#define MM_MAX_LINE_LENGTH 100025
+#define MatrixMarketBanner "%%MatrixMarket"
+#define MM_MAX_TOKEN_LENGTH 64
+
+typedef char MM_typecode[4];
+
+char *mm_typecode_to_str(MM_typecode matcode);
+
+int mm_read_banner(FILE *f, MM_typecode *matcode);
+int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz);
+int mm_read_mtx_array_size(FILE *f, int *M, int *N);
+
+int mm_write_banner(FILE *f, MM_typecode matcode);
+int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz);
+int mm_write_mtx_array_size(FILE *f, int M, int N);
+
+
+/********************* MM_typecode query fucntions ***************************/
+
+#define mm_is_matrix(typecode) ((typecode)[0]=='M')
+
+#define mm_is_sparse(typecode) ((typecode)[1]=='C')
+#define mm_is_coordinate(typecode)((typecode)[1]=='C')
+#define mm_is_dense(typecode)  ((typecode)[1]=='A')
+#define mm_is_array(typecode)  ((typecode)[1]=='A')
+
+#define mm_is_complex(typecode)        ((typecode)[2]=='C')
+#define mm_is_real(typecode)           ((typecode)[2]=='R')
+#define mm_is_pattern(typecode)        ((typecode)[2]=='P')
+#define mm_is_integer(typecode) ((typecode)[2]=='I')
+
+#define mm_is_symmetric(typecode)((typecode)[3]=='S')
+#define mm_is_general(typecode)        ((typecode)[3]=='G')
+#define mm_is_skew(typecode)   ((typecode)[3]=='K')
+#define mm_is_hermitian(typecode)((typecode)[3]=='H')
+
+int mm_is_valid(MM_typecode matcode);          /* too complex for a macro */
+
+
+/********************* MM_typecode modify fucntions ***************************/
+
+#define mm_set_matrix(typecode)        ((*typecode)[0]='M')
+#define mm_set_coordinate(typecode)    ((*typecode)[1]='C')
+#define mm_set_array(typecode) ((*typecode)[1]='A')
+#define mm_set_dense(typecode) mm_set_array(typecode)
+#define mm_set_sparse(typecode)        mm_set_coordinate(typecode)
+
+#define mm_set_complex(typecode)((*typecode)[2]='C')
+#define mm_set_real(typecode)  ((*typecode)[2]='R')
+#define mm_set_pattern(typecode)((*typecode)[2]='P')
+#define mm_set_integer(typecode)((*typecode)[2]='I')
+
+
+#define mm_set_symmetric(typecode)((*typecode)[3]='S')
+#define mm_set_general(typecode)((*typecode)[3]='G')
+#define mm_set_skew(typecode)  ((*typecode)[3]='K')
+#define mm_set_hermitian(typecode)((*typecode)[3]='H')
+
+#define mm_clear_typecode(typecode) ((*typecode)[0]=(*typecode)[1]= \
+                                                                       (*typecode)[2]=' ',(*typecode)[3]='G')
+
+#define mm_initialize_typecode(typecode) mm_clear_typecode(typecode)
+
+
+/********************* Matrix Market error codes ***************************/
+
+
+#define MM_COULD_NOT_READ_FILE 11
+#define MM_PREMATURE_EOF               12
+#define MM_NOT_MTX                             13
+#define MM_NO_HEADER                   14
+#define MM_UNSUPPORTED_TYPE            15
+#define MM_LINE_TOO_LONG               16
+#define MM_COULD_NOT_WRITE_FILE        17
+
+
+/******************** Matrix Market internal definitions ********************
+
+   MM_matrix_typecode: 4-character sequence
+
+                                   ojbect              sparse/         data        storage 
+                                                               dense           type        scheme
+
+   string position:     [0]        [1]                 [2]         [3]
+
+   Matrix typecode:  M(atrix)  C(oord)         R(eal)          G(eneral)
+                                                       A(array)        C(omplex)   H(ermitian)
+                                                                                       P(attern)   S(ymmetric)
+                                                                               I(nteger)       K(kew)
+
+ ***********************************************************************/
+
+#define MM_MTX_STR             "matrix"
+#define MM_ARRAY_STR   "array"
+#define MM_DENSE_STR   "array"
+#define MM_COORDINATE_STR "coordinate" 
+#define MM_SPARSE_STR  "coordinate"
+#define MM_COMPLEX_STR "complex"
+#define MM_REAL_STR            "real"
+#define MM_INT_STR             "integer"
+#define MM_GENERAL_STR  "general"
+#define MM_SYMM_STR            "symmetric"
+#define MM_HERM_STR            "hermitian"
+#define MM_SKEW_STR            "skew-symmetric"
+#define MM_PATTERN_STR  "pattern"
+
+
+/*  high level routines */
+
+int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
+                double val[], MM_typecode matcode);
+int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
+               double val[], MM_typecode matcode);
+int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *realpart, double *img,
+                       MM_typecode matcode);
+
+int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
+                double **val_, int **I_, int **J_);
+
+
+
+#endif
index b28764be9ec560d28e2b2f171dbcd02749b081a8..b9172e8e1608a1b3934cbbcc7ee986177066445a 100644 (file)
@@ -2836,6 +2836,7 @@ AC_CONFIG_FILES(Makefile
        lib/dotgen/Makefile
        lib/neatogen/Makefile
        lib/fdpgen/Makefile
+       lib/sparse/Makefile
        lib/sfdpgen/Makefile
        lib/circogen/Makefile
        lib/twopigen/Makefile
index 3b278c2b6f21673bb57f7b203d3085650bf23412..6aaf34e53eaa56454e5e4d7aa4210e94cadd3afe 100644 (file)
@@ -2,7 +2,7 @@
 ## Process this file with automake to produce Makefile.in
 
 SUBDIRS = cdt graph agraph gd pathplan agutil sfio vmalloc ast vpsc \
-       circogen dotgen fdpgen neatogen twopigen sfdpgen patchwork common  \
-       pack gvc ingraphs expr cgraph xdot topfish glcomp
+       circogen dotgen fdpgen neatogen twopigen sparse sfdpgen \
+       patchwork common pack gvc ingraphs expr cgraph xdot topfish glcomp
 
 EXTRA_DIST = Makefile.old