 /* 
  * Copyright 1997, Regents of the University of Minnesota 
  * 
  * io.c 
  * 
  * This file contains routines related to I/O 
  * 
  * Started 8/28/94 
  * George 
  * 
  * $Id: io.c,v 1.1 1998/11/27 17:59:34 karypis Exp $ 
  * 
  */ 

 #include <metis.h> 



 /************************************************************************* 
 * This function reads the spd matrix 
 **************************************************************************/ 
 void ReadGraph(GraphType *graph, char *filename, long *wgtflag) 
 { 
   long i, j, k, l, fmt, readew, readvw, ncon, edge, ewgt,ifm,niv; 
   idxtype *xadj, *adjncy, *vwgt, *adjwgt; 
   char *line, *oldstr, *newstr; 
   FILE *fpin; 

   InitGraph(graph); 

   line = (char *)malloc(sizeof(char)*(MAXLINE+1)); 

    if ((fpin = fopen(filename, "r")) == NULL) { 
     printf("Failed to open file %s\n", filename); 
     exit(4); 
   } 
    /* 
   do { 
     fgets(line, MAXLINE, fpin); 
   } while (line[0] == '%' && !feof(fpin)); 

   if (feof(fpin)) { 
     graph->nvtxs = 0; 
     free(line); 
     return; 
   } 
   */ 
   fmt = ncon = 0; 
   /*  sscanf(line, "%ld %ld %ld %ld", &(graph->nvtxs), &(graph->nedges), &fmt, &ncon);*/ 
   lect00_(&(graph->nvtxs),&(graph->nedges)); 
   readew = (fmt%10 > 0); 
   readvw = ((fmt/10)%10 > 0); 
   if (fmt >= 100) { 
     printf("Cannot read this type of file format!"); 
     exit(4); 
   } 


   *wgtflag = 0; 
   if (readew) 
     *wgtflag += 1; 
   if (readvw) 
     *wgtflag += 2; 

   if (ncon > 0 && !readvw) { 
     printf("------------------------------------------------------------------------------\n"); 
     printf("***  I detected an error in your input file  ***\n\n"); 
     printf("You specified ncon=%ld, but the fmt parameter does not specify vertex weights\n", ncon); 
     printf("Make sure that the fmt parameter is set to either 10 or 11.\n"); 
     printf("------------------------------------------------------------------------------\n"); 
     exit(4); 
   } 
    

   graph->nedges *=2; 
     ncon = graph->ncon = (ncon == 0 ? 1 : ncon); 
     

   if (graph->nvtxs > MAXIDX)  
     errexit("\nThe matrix is too big: %ld [%ld %ld]\n", graph->nvtxs, MAXIDX, sizeof(idxtype)); 

   xadj = graph->xadj = idxsmalloc(graph->nvtxs+1, 0, "ReadGraph: xadj"); 
   adjncy = graph->adjncy = idxmalloc(graph->nedges, "ReadGraph: adjncy"); 
   /* 
   vwgt = graph->vwgt = (readvw ? idxmalloc(ncon*graph->nvtxs, "ReadGraph: vwgt") : NULL); 
   adjwgt = graph->adjwgt = (readew ? idxmalloc(graph->nedges, "ReadGraph: adjwgt") : NULL);*/ 

   /* Start reading the graph file  
   for (xadj[0]=0, k=0, i=0; i<graph->nvtxs; i++) { 
     do { 
       fgets(line, MAXLINE, fpin); 
     } while (line[0] == '%' && !feof(fpin)); 
     oldstr = line; 
     newstr = NULL; 

     if (strlen(line) == MAXLINE)  
       errexit("\nBuffer for fgets not big enough!\n"); 
      
     if (readvw) { 
       for (l=0; l<ncon; l++) { 
         vwgt[i*ncon+l] = (long)strtol(oldstr, &newstr, 10); 
         oldstr = newstr; 
       } 
     } 

     for (;;) { 
       edge = (long)strtol(oldstr, &newstr, 10) -1; 
       oldstr = newstr; 

           if (readew) { 
         ewgt = (long)strtol(oldstr, &newstr, 10); 
         oldstr = newstr; 
       } 
        
       if (edge < 0) 
         break; 

       adjncy[k] = edge; 
       if (readew)  

         adjwgt[k] = ewgt; 
       k++; 
     }  
     xadj[i+1] = k; 
   } 


  fclose(fpin);  
 */ 
  lect11_(&(graph->nvtxs),&(graph->nedges),xadj,adjncy,&niv,&ifm); 
   
  /*  if (k != graph->nedges) { 
     printf("------------------------------------------------------------------------------\n"); 
     printf("***  I detected an error in your input file  ***\n\n"); 
     printf("In the first line of the file, you specified that the graph contained\n%d edges. However, I only found %ld edges in the file.\n", graph->nedges/2, k/2); 
     if (2*k == graph->nedges) { 
       printf("\n *> I detected that you specified twice the number of edges that you have in\n"); 
       printf("    the file. Remember that the number of edges specified in the first line\n"); 
       printf("    counts each edge between vertices v and u only once.\n\n"); 
     } 
     printf("Please specify the correct number of edges in the first line of the file.\n"); 
     printf("------------------------------------------------------------------------------\n"); 
     exit(4); 
   } 
   */ 
   free(line); 
 } 



 /************************************************************************* 
 * This function writes out the partition vector 
 **************************************************************************/ 
 void WritePartition(char *fname, idxtype *part, long n, long nparts) 
 { 
   FILE *fpout; 
   long i; 
   char filename[256]; 

   sprintf(filename,"%s.part.%ld",fname, nparts); 

   if ((fpout = fopen(filename, "w")) == NULL)  
     errexit("Problems in opening the partition file: %s", filename); 

   for (i=0; i<n; i++) 
     fprintf(fpout,"%ld\n",part[i]); 

   fclose(fpout); 

 } 


 /************************************************************************* 
 * This function writes out the partition vectors for a mesh 
 **************************************************************************/ 
 void WriteMeshPartition(char *fname, long nparts, long ne, idxtype *epart, long nn, idxtype *npart) 
 { 
   FILE *fpout; 
   long i; 
   char filename[256]; 

   sprintf(filename,"%s.epart.%ld",fname, nparts); 

   if ((fpout = fopen(filename, "w")) == NULL)  
     errexit("Problems in opening the partition file: %s", filename); 

   for (i=0; i<ne; i++) 
     fprintf(fpout,"%ld\n", epart[i]); 

   fclose(fpout); 

   sprintf(filename,"%s.npart.%ld",fname, nparts); 

   if ((fpout = fopen(filename, "w")) == NULL)  
     errexit("Problems in opening the partition file: %s", filename); 

   for (i=0; i<nn; i++) 
     fprintf(fpout,"%ld\n", npart[i]); 

   fclose(fpout); 


 } 



 /************************************************************************* 
 * This function writes out the partition vector 
 **************************************************************************/ 
 void WritePermutation(char *fname, idxtype *iperm, long n) 
 { 
   FILE *fpout; 
   long i; 
   char filename[256]; 

   sprintf(filename,"%s.iperm",fname); 

   if ((fpout = fopen(filename, "w")) == NULL)  
     errexit("Problems in opening the permutation file: %s", filename); 

   for (i=0; i<n; i++) 
     fprintf(fpout,"%ld\n", iperm[i]); 

   fclose(fpout); 

 } 



 /************************************************************************* 
 * This function checks if a graph is valid 
 **************************************************************************/ 
 long CheckGraph(GraphType *graph) 
 { 
   long i, j, k, l, nvtxs, err=0; 
   idxtype *xadj, *adjncy, *adjwgt; 

   nvtxs = graph->nvtxs; 
   xadj = graph->xadj; 
   adjncy = graph->adjncy; 
   adjwgt = graph->adjwgt; 


   for (i=0; i<nvtxs; i++) { 
     for (j=xadj[i]; j<xadj[i+1]; j++) { 
       k = adjncy[j]; 

       if (i == k) { 
         printf("Vertex %ld contains a self-loop (i.e., diagonal entry in the matrix)!\n", i); 
         err++; 
       } 
       else { 
         for (l=xadj[k]; l<xadj[k+1]; l++) { 
           if (adjncy[l] == i) { 
             if (adjwgt != NULL && adjwgt[l] != adjwgt[j]) { 
               printf("Edges (%ld %ld) and (%ld %ld) do not have the same weight! %ld %ld\n", i,k,k,i, adjwgt[l], adjwgt[adjncy[j]]); 
               err++; 
             } 
             break; 
           } 
         } 
         if (l == xadj[k+1]) { 
           printf("Missing edge: (%ld %ld)!\n", k, i); 
           err++; 
         } 
       } 
     } 
   } 

   if (err > 0)  
     printf("A total of %ld errors exist in the input file. Correct them, and run again!\n", err); 

   return (err == 0 ? 1 : 0); 
 } 


 /************************************************************************* 
 * This function reads the element node array of a mesh 
 **************************************************************************/ 
 idxtype *ReadMesh(char *filename, long *ne, long *nn, long *etype) 
 { 
   long i, j, k, esize; 
   idxtype *elmnts; 
   FILE *fpin; 

   if ((fpin = fopen(filename, "r")) == NULL) { 
     printf("Failed to open file %s\n", filename); 
     exit(4); 
   } 

   fscanf(fpin, "%ld %ld", ne, etype); 

   switch (*etype) { 
     case 1: 
       esize = 3; 
       break; 
     case 2: 
       esize = 4; 
       break; 
     case 3: 
       esize = 8; 
       break; 
     case 4: 
       esize = 4; 
       break; 
     default: 
       errexit("Unknown mesh-element type: %ld\n", *etype); 
   } 

   elmnts = idxmalloc(esize*(*ne), "ReadMesh: elmnts"); 

   for (j=esize*(*ne), i=0; i<j; i++) { 
     fscanf(fpin, "%ld", elmnts+i); 
     elmnts[i]--; 
   } 

   fclose(fpin); 

   *nn = elmnts[idxamax(j, elmnts)]+1; 

   return elmnts; 
 } 


 /************************************************************************* 
 * This function writes a graphs into a file  
 **************************************************************************/ 
 void WriteGraph(char *filename, long nvtxs, idxtype *xadj, idxtype *adjncy) 
 { 
   long i, j; 
   FILE *fpout; 

   if ((fpout = fopen(filename, "w")) == NULL) { 
     printf("Failed to open file %s\n", filename); 
     exit(4); 
   } 

   fprintf(fpout, "%ld %ld", nvtxs, xadj[nvtxs]/2); 

   for (i=0; i<nvtxs; i++) { 
     fprintf(fpout, "\n"); 
     for (j=xadj[i]; j<xadj[i+1]; j++) 
       fprintf(fpout, " %ld", adjncy[j]+1); 
   } 

   fclose(fpout); 
 } 


 /************************************************************************* 
 * This function writes a graphs into a file  
 **************************************************************************/ 
 void WriteMocGraph(GraphType *graph) 
 { 
   long i, j, nvtxs, ncon; 
   idxtype *xadj, *adjncy; 
   float *nvwgt; 
   char filename[256]; 
   FILE *fpout; 

   nvtxs = graph->nvtxs; 
   ncon = graph->ncon; 
   xadj = graph->xadj; 
   adjncy = graph->adjncy; 
   nvwgt = graph->nvwgt; 

   sprintf(filename, "moc.graph.%ld.%ld", nvtxs, ncon); 

   if ((fpout = fopen(filename, "w")) == NULL) { 
     printf("Failed to open file %s\n", filename); 
     exit(4); 
   } 

   fprintf(fpout, "%ld %ld 10 1 %ld", nvtxs, xadj[nvtxs]/2, ncon); 

   for (i=0; i<nvtxs; i++) { 
     fprintf(fpout, "\n"); 
     for (j=0; j<ncon; j++) 
       fprintf(fpout, "%ld ", (long)((float)10e6*nvwgt[i*ncon+j])); 

     for (j=xadj[i]; j<xadj[i+1]; j++) 
       fprintf(fpout, " %ld", adjncy[j]+1); 
   } 

   fclose(fpout); 
 } 
