00001 
00010 #include <GKlib.h>
00011 
00012 #define OMPMINOPS       50000
00013 
00014 
00018 
00019 gk_graph_t *gk_graph_Create()
00020 {
00021   gk_graph_t *graph;
00022 
00023   graph = (gk_graph_t *)gk_malloc(sizeof(gk_graph_t), "gk_graph_Create: graph");
00024 
00025   gk_graph_Init(graph);
00026 
00027   return graph;
00028 }
00029 
00030 
00031 
00035 
00036 void gk_graph_Init(gk_graph_t *graph)
00037 {
00038   memset(graph, 0, sizeof(gk_graph_t));
00039   graph->nvtxs = -1;
00040 }
00041 
00042 
00043 
00047 
00048 void gk_graph_Free(gk_graph_t **graph)
00049 {
00050   if (*graph == NULL)
00051     return;
00052   gk_graph_FreeContents(*graph);
00053   gk_free((void **)graph, LTERM);
00054 }
00055 
00056 
00057 
00062 
00063 void gk_graph_FreeContents(gk_graph_t *graph)
00064 {
00065   gk_free((void *)&graph->xadj, &graph->adjncy, 
00066           &graph->iadjwgt, &graph->fadjwgt,
00067           &graph->ivwgts, &graph->fvwgts,
00068           &graph->ivsizes, &graph->fvsizes,
00069           &graph->vlabels, 
00070           LTERM);
00071 }
00072 
00073 
00074 
00084 
00085 gk_graph_t *gk_graph_Read(char *filename, int format, int isfewgts, 
00086                 int isfvwgts, int isfvsizes)
00087 {
00088   ssize_t i, k, l;
00089   size_t nfields, nvtxs=0, nedges=0, fmt, ncon, lnlen;
00090   int32_t ival;
00091   float fval;
00092   int readsizes=0, readwgts=0, readvals=0, numbering=0;
00093   char *line=NULL, *head, *tail, fmtstr[256];
00094   FILE *fpin=NULL;
00095   gk_graph_t *graph=NULL;
00096 
00097 
00098   if (!gk_fexists(filename)) 
00099     gk_errexit(SIGERR, "File %s does not exist!\n", filename);
00100 
00101   if (format == GK_GRAPH_FMT_METIS) {
00102     fpin = gk_fopen(filename, "r", "gk_graph_Read: fpin");
00103     do {
00104       if (gk_getline(&line, &lnlen, fpin) <= 0)
00105         gk_errexit(SIGERR, "Premature end of input file: file:%s\n", filename);
00106     } while (line[0] == '%');
00107 
00108     fmt = ncon = 0;
00109     nfields = sscanf(line, "%zu %zu %zu %zu", &nvtxs, &nedges, &fmt, &ncon);
00110     if (nfields < 2)
00111       gk_errexit(SIGERR, "Header line must contain at least 2 integers (#vtxs and #edges).\n");
00112 
00113     nedges *= 2;
00114 
00115     if (fmt > 111)
00116       gk_errexit(SIGERR, "Cannot read this type of file format [fmt=%zu]!\n", fmt);
00117 
00118     sprintf(fmtstr, "%03zu", fmt%1000);
00119     readsizes = (fmtstr[0] == '1');
00120     readwgts  = (fmtstr[1] == '1');
00121     readvals  = (fmtstr[2] == '1');
00122     numbering = 1;
00123     ncon      = (ncon == 0 ? 1 : ncon);
00124   }
00125   else {
00126     gk_errexit(SIGERR, "Unrecognized format: %d\n", format);
00127   }
00128 
00129   graph = gk_graph_Create();
00130 
00131   graph->nvtxs = nvtxs;
00132 
00133   graph->xadj   = gk_zmalloc(nvtxs+1, "gk_graph_Read: xadj");
00134   graph->adjncy = gk_i32malloc(nedges, "gk_graph_Read: adjncy");
00135   if (readvals) {
00136     if (isfewgts)
00137       graph->fadjwgt = gk_fmalloc(nedges, "gk_graph_Read: fadjwgt");
00138     else
00139       graph->iadjwgt = gk_i32malloc(nedges, "gk_graph_Read: iadjwgt");
00140   }
00141 
00142   if (readsizes) {
00143     if (isfvsizes)
00144       graph->fvsizes = gk_fmalloc(nvtxs, "gk_graph_Read: fvsizes");
00145     else
00146       graph->ivsizes = gk_i32malloc(nvtxs, "gk_graph_Read: ivsizes");
00147   }
00148 
00149   if (readwgts) {
00150     if (isfvwgts)
00151       graph->fvwgts = gk_fmalloc(nvtxs*ncon, "gk_graph_Read: fvwgts");
00152     else
00153       graph->ivwgts = gk_i32malloc(nvtxs*ncon, "gk_graph_Read: ivwgts");
00154   }
00155 
00156 
00157   
00158 
00159 
00160   numbering = (numbering ? - 1 : 0);
00161   for (graph->xadj[0]=0, k=0, i=0; i<nvtxs; i++) {
00162     do {
00163       if (gk_getline(&line, &lnlen, fpin) == -1)
00164         gk_errexit(SIGERR, "Pregraphure end of input file: file while reading row %d\n", i);
00165     } while (line[0] == '%');
00166 
00167     head = line;
00168     tail = NULL;
00169 
00170     
00171     if (readsizes) {
00172       if (isfvsizes) {
00173 #ifdef __MSC__
00174         graph->fvsizes[i] = (float)strtod(head, &tail);
00175 #else
00176         graph->fvsizes[i] = strtof(head, &tail);
00177 #endif
00178         if (tail == head)
00179           gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1);
00180         if (graph->fvsizes[i] < 0)
00181           gk_errexit(SIGERR, "The size for vertex %zd must be >= 0\n", i+1);
00182       }
00183       else {
00184         graph->ivsizes[i] = strtol(head, &tail, 0);
00185         if (tail == head)
00186           gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1);
00187         if (graph->ivsizes[i] < 0)
00188           gk_errexit(SIGERR, "The size for vertex %zd must be >= 0\n", i+1);
00189       }
00190       head = tail;
00191     }
00192 
00193     
00194     if (readwgts) {
00195       for (l=0; l<ncon; l++) {
00196         if (isfvwgts) {
00197 #ifdef __MSC__
00198           graph->fvwgts[i*ncon+l] = (float)strtod(head, &tail);
00199 #else
00200           graph->fvwgts[i*ncon+l] = strtof(head, &tail);
00201 #endif
00202           if (tail == head)
00203             gk_errexit(SIGERR, "The line for vertex %zd does not have enough weights "
00204                     "for the %d constraints.\n", i+1, ncon);
00205           if (graph->fvwgts[i*ncon+l] < 0)
00206             gk_errexit(SIGERR, "The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l);
00207         }
00208         else {
00209           graph->ivwgts[i*ncon+l] = strtol(head, &tail, 0);
00210           if (tail == head)
00211             gk_errexit(SIGERR, "The line for vertex %zd does not have enough weights "
00212                     "for the %d constraints.\n", i+1, ncon);
00213           if (graph->ivwgts[i*ncon+l] < 0)
00214             gk_errexit(SIGERR, "The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l);
00215         }
00216         head = tail;
00217       }
00218     }
00219 
00220    
00221     
00222     while (1) {
00223       ival = (int)strtol(head, &tail, 0);
00224       if (tail == head) 
00225         break;
00226       head = tail;
00227       
00228       if ((graph->adjncy[k] = ival + numbering) < 0)
00229         gk_errexit(SIGERR, "Error: Invalid column number %d at row %zd.\n", ival, i);
00230 
00231       if (readvals) {
00232         if (isfewgts) {
00233 #ifdef __MSC__
00234           fval = (float)strtod(head, &tail);
00235 #else
00236           fval = strtof(head, &tail);
00237 #endif
00238           if (tail == head)
00239             gk_errexit(SIGERR, "Value could not be found for edge! Vertex:%zd, NNZ:%zd\n", i, k);
00240 
00241           graph->fadjwgt[k] = fval;
00242         }
00243         else {
00244           ival = strtol(head, &tail, 0);
00245           if (tail == head)
00246             gk_errexit(SIGERR, "Value could not be found for edge! Vertex:%zd, NNZ:%zd\n", i, k);
00247 
00248           graph->iadjwgt[k] = ival;
00249         }
00250         head = tail;
00251       }
00252       k++;
00253     }
00254     graph->xadj[i+1] = k;
00255   }
00256 
00257   if (k != nedges)
00258     gk_errexit(SIGERR, "gk_graph_Read: Something wrong with the number of edges in "
00259                        "the input file. nedges=%zd, Actualnedges=%zd.\n", nedges, k);
00260 
00261   gk_fclose(fpin);
00262 
00263   gk_free((void **)&line, LTERM);
00264 
00265   return graph;
00266 }
00267 
00268 
00269 
00276 
00277 void gk_graph_Write(gk_graph_t *graph, char *filename, int format)
00278 {
00279   ssize_t i, j;
00280   int hasvwgts, hasvsizes, hasewgts;
00281   FILE *fpout;
00282 
00283   if (format != GK_GRAPH_FMT_METIS)
00284     gk_errexit(SIGERR, "Unknown file format. %d\n", format);
00285 
00286   if (filename)
00287     fpout = gk_fopen(filename, "w", "gk_graph_Write: fpout");
00288   else
00289     fpout = stdout; 
00290 
00291 
00292   hasewgts  = (graph->iadjwgt || graph->fadjwgt);
00293   hasvwgts  = (graph->ivwgts || graph->fvwgts);
00294   hasvsizes = (graph->ivsizes || graph->fvsizes);
00295 
00296   
00297   fprintf(fpout, "%d %zd", graph->nvtxs, graph->xadj[graph->nvtxs]/2);
00298   if (hasvwgts || hasvsizes || hasewgts) 
00299     fprintf(fpout, " %d%d%d", hasvsizes, hasvwgts, hasewgts);
00300   fprintf(fpout, "\n");
00301 
00302 
00303   for (i=0; i<graph->nvtxs; i++) {
00304     if (hasvsizes) {
00305       if (graph->ivsizes)
00306         fprintf(fpout, " %d", graph->ivsizes[i]);
00307       else
00308         fprintf(fpout, " %f", graph->fvsizes[i]);
00309     }
00310 
00311     if (hasvwgts) {
00312       if (graph->ivwgts)
00313         fprintf(fpout, " %d", graph->ivwgts[i]);
00314       else
00315         fprintf(fpout, " %f", graph->fvwgts[i]);
00316     }
00317 
00318     for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++) {
00319       fprintf(fpout, " %d", graph->adjncy[j]+1);
00320       if (hasewgts) {
00321         if (graph->iadjwgt)
00322           fprintf(fpout, " %d", graph->iadjwgt[j]);
00323         else 
00324           fprintf(fpout, " %f", graph->fadjwgt[j]);
00325       }
00326     }
00327     fprintf(fpout, "\n");
00328   }
00329   if (filename)
00330     gk_fclose(fpout);
00331 }
00332 
00333 
00334 
00339 
00340 gk_graph_t *gk_graph_Dup(gk_graph_t *graph)
00341 {
00342   gk_graph_t *ngraph;
00343 
00344   ngraph = gk_graph_Create();
00345 
00346   ngraph->nvtxs  = graph->nvtxs;
00347 
00348   
00349   if (graph->xadj)
00350     ngraph->xadj = gk_zcopy(graph->nvtxs+1, graph->xadj, 
00351                             gk_zmalloc(graph->nvtxs+1, "gk_graph_Dup: xadj"));
00352   if (graph->ivwgts)
00353     ngraph->ivwgts = gk_i32copy(graph->nvtxs, graph->ivwgts, 
00354                             gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivwgts"));
00355   if (graph->ivsizes)
00356     ngraph->ivsizes = gk_i32copy(graph->nvtxs, graph->ivsizes, 
00357                             gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivsizes"));
00358   if (graph->vlabels)
00359     ngraph->vlabels = gk_i32copy(graph->nvtxs, graph->vlabels, 
00360                             gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivlabels"));
00361   if (graph->fvwgts)
00362     ngraph->fvwgts = gk_fcopy(graph->nvtxs, graph->fvwgts, 
00363                             gk_fmalloc(graph->nvtxs, "gk_graph_Dup: fvwgts"));
00364   if (graph->fvsizes)
00365     ngraph->fvsizes = gk_fcopy(graph->nvtxs, graph->fvsizes, 
00366                             gk_fmalloc(graph->nvtxs, "gk_graph_Dup: fvsizes"));
00367 
00368 
00369   if (graph->adjncy)
00370     ngraph->adjncy = gk_i32copy(graph->xadj[graph->nvtxs], graph->adjncy, 
00371                             gk_i32malloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: adjncy"));
00372   if (graph->iadjwgt)
00373     ngraph->iadjwgt = gk_i32copy(graph->xadj[graph->nvtxs], graph->iadjwgt, 
00374                             gk_i32malloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: iadjwgt"));
00375   if (graph->fadjwgt)
00376     ngraph->fadjwgt = gk_fcopy(graph->xadj[graph->nvtxs], graph->fadjwgt, 
00377                             gk_fmalloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: fadjwgt"));
00378 
00379   return ngraph;
00380 }
00381 
00382 
00383 
00390 
00391 gk_graph_t *gk_graph_ExtractSubgraph(gk_graph_t *graph, int vstart, int nvtxs)
00392 {
00393   ssize_t i;
00394   gk_graph_t *ngraph;
00395 
00396   if (vstart+nvtxs > graph->nvtxs)
00397     return NULL;
00398 
00399   ngraph = gk_graph_Create();
00400 
00401   ngraph->nvtxs  = nvtxs;
00402 
00403   
00404   if (graph->xadj)
00405     ngraph->xadj = gk_zcopy(nvtxs+1, graph->xadj+vstart, 
00406                               gk_zmalloc(nvtxs+1, "gk_graph_ExtractSubgraph: xadj"));
00407   for (i=nvtxs; i>=0; i--)
00408     ngraph->xadj[i] -= ngraph->xadj[0];
00409   ASSERT(ngraph->xadj[0] == 0);
00410 
00411   if (graph->ivwgts)
00412     ngraph->ivwgts = gk_i32copy(nvtxs, graph->ivwgts+vstart, 
00413                             gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: ivwgts"));
00414   if (graph->ivsizes)
00415     ngraph->ivsizes = gk_i32copy(nvtxs, graph->ivsizes+vstart, 
00416                             gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: ivsizes"));
00417   if (graph->vlabels)
00418     ngraph->vlabels = gk_i32copy(nvtxs, graph->vlabels+vstart, 
00419                             gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: vlabels"));
00420 
00421   if (graph->fvwgts)
00422     ngraph->fvwgts = gk_fcopy(nvtxs, graph->fvwgts+vstart, 
00423                             gk_fmalloc(nvtxs, "gk_graph_ExtractSubgraph: fvwgts"));
00424   if (graph->fvsizes)
00425     ngraph->fvsizes = gk_fcopy(nvtxs, graph->fvsizes+vstart, 
00426                             gk_fmalloc(nvtxs, "gk_graph_ExtractSubgraph: fvsizes"));
00427 
00428 
00429   ASSERT(ngraph->xadj[nvtxs] == graph->xadj[vstart+nvtxs]-graph->xadj[vstart]);
00430   if (graph->adjncy)
00431     ngraph->adjncy = gk_i32copy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], 
00432                             graph->adjncy+graph->xadj[vstart], 
00433                             gk_i32malloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart],
00434                                        "gk_graph_ExtractSubgraph: adjncy"));
00435   if (graph->iadjwgt)
00436     ngraph->iadjwgt = gk_i32copy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], 
00437                             graph->iadjwgt+graph->xadj[vstart], 
00438                             gk_i32malloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart],
00439                                        "gk_graph_ExtractSubgraph: iadjwgt"));
00440   if (graph->fadjwgt)
00441     ngraph->fadjwgt = gk_fcopy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], 
00442                             graph->fadjwgt+graph->xadj[vstart], 
00443                             gk_fmalloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart],
00444                                        "gk_graph_ExtractSubgraph: fadjwgt"));
00445 
00446   return ngraph;
00447 }
00448 
00449 
00450 
00459 
00460 gk_graph_t *gk_graph_Reorder(gk_graph_t *graph, int32_t *perm, int32_t *iperm)
00461 {
00462   ssize_t j, jj, *xadj;
00463   int i, k, u, v, nvtxs;
00464   int freeperm=0, freeiperm=0;
00465   int32_t *adjncy;
00466   gk_graph_t *ngraph;
00467 
00468   if (perm == NULL && iperm == NULL)
00469     return NULL;
00470 
00471   ngraph = gk_graph_Create();
00472 
00473   ngraph->nvtxs = nvtxs = graph->nvtxs;
00474   xadj   = graph->xadj;
00475   adjncy = graph->adjncy;
00476 
00477   
00478   if (graph->xadj)
00479     ngraph->xadj = gk_zmalloc(nvtxs+1, "gk_graph_Reorder: xadj");
00480 
00481   if (graph->ivwgts)
00482     ngraph->ivwgts = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivwgts");
00483 
00484   if (graph->ivsizes)
00485     ngraph->ivsizes = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivsizes");
00486 
00487   if (graph->vlabels)
00488     ngraph->vlabels = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivlabels");
00489 
00490   if (graph->fvwgts)
00491     ngraph->fvwgts = gk_fmalloc(nvtxs, "gk_graph_Reorder: fvwgts");
00492 
00493   if (graph->fvsizes)
00494     ngraph->fvsizes = gk_fmalloc(nvtxs, "gk_graph_Reorder: fvsizes");
00495 
00496 
00497   if (graph->adjncy)
00498     ngraph->adjncy = gk_i32malloc(graph->xadj[nvtxs], "gk_graph_Reorder: adjncy");
00499 
00500   if (graph->iadjwgt)
00501     ngraph->iadjwgt = gk_i32malloc(graph->xadj[nvtxs], "gk_graph_Reorder: iadjwgt");
00502 
00503   if (graph->fadjwgt)
00504     ngraph->fadjwgt = gk_fmalloc(graph->xadj[nvtxs], "gk_graph_Reorder: fadjwgt");
00505 
00506 
00507   
00508   if (perm == NULL) {
00509     freeperm = 1;
00510     perm = gk_i32malloc(nvtxs, "gk_graph_Reorder: perm"); 
00511     for (i=0; i<nvtxs; i++)
00512       perm[iperm[i]] = i;
00513   }
00514   if (iperm == NULL) {
00515     freeiperm = 1;
00516     iperm = gk_i32malloc(nvtxs, "gk_graph_Reorder: iperm"); 
00517     for (i=0; i<nvtxs; i++)
00518       iperm[perm[i]] = i;
00519   }
00520 
00521   
00522   ngraph->xadj[0] = jj = 0;
00523   for (v=0; v<nvtxs; v++) {
00524     u = iperm[v];
00525     for (j=xadj[u]; j<xadj[u+1]; j++, jj++) {
00526       ngraph->adjncy[jj] = perm[adjncy[j]];
00527       if (graph->iadjwgt)
00528         ngraph->iadjwgt[jj] = graph->iadjwgt[j];
00529       if (graph->fadjwgt)
00530         ngraph->fadjwgt[jj] = graph->fadjwgt[j];
00531     }
00532     if (graph->ivwgts)
00533       ngraph->ivwgts[v] = graph->ivwgts[u];
00534     if (graph->fvwgts)
00535       ngraph->fvwgts[v] = graph->fvwgts[u];
00536     if (graph->ivsizes)
00537       ngraph->ivsizes[v] = graph->ivsizes[u];
00538     if (graph->fvsizes)
00539       ngraph->fvsizes[v] = graph->fvsizes[u];
00540     if (graph->vlabels)
00541       ngraph->vlabels[v] = graph->vlabels[u];
00542 
00543     ngraph->xadj[v+1] = jj;
00544   }
00545 
00546 
00547   
00548   if (freeperm)
00549     gk_free((void **)&perm, LTERM);
00550   if (freeiperm)
00551     gk_free((void **)&iperm, LTERM);
00552 
00553   return ngraph;
00554 }
00555 
00556 
00557 
00571 
00572 int gk_graph_FindComponents(gk_graph_t *graph, int32_t *cptr, int32_t *cind)
00573 {
00574   ssize_t i, ii, j, jj, k, nvtxs, first, last, ntodo, ncmps;
00575   ssize_t *xadj;
00576   int32_t *adjncy, *pos, *todo;
00577   int32_t mustfree_ccsr=0, mustfree_where=0;
00578 
00579   nvtxs  = graph->nvtxs;
00580   xadj   = graph->xadj;
00581   adjncy = graph->adjncy;
00582 
00583   
00584   if (cptr == NULL) {
00585     cptr = gk_i32malloc(nvtxs+1, "gk_graph_FindComponents: cptr");
00586     cind = gk_i32malloc(nvtxs, "gk_graph_FindComponents: cind");
00587     mustfree_ccsr = 1;
00588   }
00589 
00590   
00591 
00592   todo = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: todo"));
00593 
00594   
00595 
00596 
00597   pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: pos"));
00598 
00599 
00600   
00601   ncmps = -1;
00602   ntodo = nvtxs;     
00603   first = last = 0;  
00604 
00605 
00606   while (ntodo > 0) {
00607     if (first == last) { 
00608       cptr[++ncmps] = first;  
00609 
00610       ASSERT(pos[todo[0]] != -1);
00611       i = todo[0];
00612 
00613       cind[last++] = i;
00614       pos[i] = -1;
00615     }
00616 
00617     i = cind[first++];  
00618 
00619     
00620 
00621 
00622 
00623     k = pos[i];
00624     j = todo[k] = todo[--ntodo];
00625     pos[j] = k;
00626 
00627     for (j=xadj[i]; j<xadj[i+1]; j++) {
00628       k = adjncy[j];
00629       if (pos[k] != -1) {
00630         cind[last++] = k;
00631         pos[k] = -1;
00632       }
00633     }
00634   }
00635   cptr[++ncmps] = first;
00636 
00637   if (mustfree_ccsr)
00638     gk_free((void **)&cptr, &cind, LTERM);
00639 
00640   gk_free((void **)&pos, &todo, LTERM);
00641 
00642   return (int) ncmps;
00643 }
00644 
00645 
00646 
00664 
00665 void gk_graph_ComputeBFSOrdering(gk_graph_t *graph, int v, int32_t **r_perm,
00666           int32_t **r_iperm)
00667 {
00668   ssize_t j, *xadj;
00669   int i, k, nvtxs, first, last;
00670   int32_t *adjncy, *cot, *pos;
00671 
00672   if (graph->nvtxs <= 0)
00673     return;
00674 
00675   nvtxs  = graph->nvtxs;
00676   xadj   = graph->xadj;
00677   adjncy = graph->adjncy;
00678 
00679   
00680   pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_ComputeBFSOrdering: pos"));
00681 
00682   
00683 
00684 
00685 
00686   cot = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_ComputeBFSOrdering: cot"));
00687 
00688 
00689   
00690   pos[0] = cot[0] = v;
00691   pos[v] = cot[v] = 0;
00692 
00693   
00694   first = last = 0;
00695   while (first < nvtxs) {
00696     if (first == last) { 
00697       k = cot[last];
00698       ASSERT(pos[k] != -1);
00699       pos[k] = -1; 
00700       last++;
00701     }
00702 
00703     i = cot[first++];  
00704     for (j=xadj[i]; j<xadj[i+1]; j++) {
00705       k = adjncy[j];
00706       
00707       if (pos[k] != -1) {
00708         
00709 
00710 
00711         cot[pos[k]]    = cot[last]; 
00712 
00713         pos[cot[last]] = pos[k];    
00714 
00715         cot[last++] = k;  
00716         pos[k]      = -1; 
00717       }
00718     }
00719   }
00720 
00721   
00722   if (r_perm != NULL) {
00723     
00724     for (i=0; i<nvtxs; i++)
00725       pos[cot[i]] = i;
00726 
00727     *r_perm = pos;
00728     pos = NULL;
00729   }
00730 
00731   if (r_iperm != NULL) {
00732     *r_iperm = cot;
00733     cot = NULL;
00734   }
00735 
00736 
00737   
00738   gk_free((void **)&pos, &cot, LTERM);
00739 
00740 }
00741 
00742 
00743 
00761 
00762 void gk_graph_ComputeBestFOrdering0(gk_graph_t *graph, int v, int type, 
00763           int32_t **r_perm, int32_t **r_iperm)
00764 {
00765   ssize_t j, jj, *xadj;
00766   int i, k, u, nvtxs;
00767   int32_t *adjncy, *perm, *degrees, *minIDs, *open;
00768   gk_i32pq_t *queue;
00769 
00770   if (graph->nvtxs <= 0)
00771     return;
00772 
00773   nvtxs  = graph->nvtxs;
00774   xadj   = graph->xadj;
00775   adjncy = graph->adjncy;
00776 
00777   
00778   degrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: degrees");
00779 
00780    
00781   minIDs  = gk_i32smalloc(nvtxs, nvtxs+1, "gk_graph_ComputeBestFOrdering: minIDs");
00782 
00783    
00784   open  = gk_i32malloc(nvtxs, "gk_graph_ComputeBestFOrdering: open");
00785 
00786   
00787 
00788 
00789   perm = gk_i32smalloc(nvtxs, -1, "gk_graph_ComputeBestFOrdering: perm");
00790 
00791   
00792   queue = gk_i32pqCreate(nvtxs);
00793   for (i=0; i<nvtxs; i++)
00794     gk_i32pqInsert(queue, i, 0);
00795   gk_i32pqUpdate(queue, v, 1);
00796 
00797   open[0] = v;
00798 
00799   
00800   for (i=0; i<nvtxs; i++) {
00801     if ((v = gk_i32pqGetTop(queue)) == -1) 
00802       gk_errexit(SIGERR, "The priority queue got empty ahead of time [i=%d].\n", i);
00803     if (perm[v] != -1)
00804       gk_errexit(SIGERR, "The perm[%d] has already been set.\n", v);
00805     perm[v] = i;
00806 
00807 
00808     for (j=xadj[v]; j<xadj[v+1]; j++) {
00809       u = adjncy[j];
00810       if (perm[u] == -1) {
00811         degrees[u]++;
00812         minIDs[u] = (i < minIDs[u] ? i : minIDs[u]);
00813 
00814         switch (type) {
00815           case 1: 
00816             gk_i32pqUpdate(queue, u, 1);
00817             break;
00818           case 2: 
00819             gk_i32pqUpdate(queue, u, degrees[u]);
00820             break;
00821           case 3: 
00822             for (k=0, jj=xadj[u]; jj<xadj[u+1]; jj++) {
00823               if (perm[adjncy[jj]] != -1)
00824                 k += perm[adjncy[jj]];
00825             }
00826             gk_i32pqUpdate(queue, u, k);
00827             break;
00828           case 4: 
00829 
00830             for (k=0, jj=xadj[u]; jj<xadj[u+1]; jj++) {
00831               if (perm[adjncy[jj]] != -1)
00832                 k += (i-perm[adjncy[jj]]);
00833             }
00834             gk_i32pqUpdate(queue, u, k);
00835             break;
00836           default:
00837             ;
00838         }
00839       }
00840     }
00841   }
00842 
00843 
00844   
00845   if (r_perm != NULL) {
00846     *r_perm = perm;
00847     perm = NULL;
00848   }
00849 
00850   if (r_iperm != NULL) {
00851     
00852     for (i=0; i<nvtxs; i++)
00853       degrees[perm[i]] = i;
00854 
00855     *r_iperm = degrees;
00856     degrees = NULL;
00857   }
00858 
00859 
00860 
00861   
00862   gk_i32pqDestroy(queue);
00863   gk_free((void **)&perm, °rees, &minIDs, &open, LTERM);
00864 
00865 }
00866 
00867 
00868 
00886 
00887 void gk_graph_ComputeBestFOrdering(gk_graph_t *graph, int v, int type, 
00888           int32_t **r_perm, int32_t **r_iperm)
00889 {
00890   ssize_t j, jj, *xadj;
00891   int i, k, u, nvtxs, nopen, ntodo;
00892   int32_t *adjncy, *perm, *degrees, *wdegrees, *sod, *level, *ot, *pos;
00893   gk_i32pq_t *queue;
00894 
00895   if (graph->nvtxs <= 0)
00896     return;
00897 
00898   nvtxs  = graph->nvtxs;
00899   xadj   = graph->xadj;
00900   adjncy = graph->adjncy;
00901 
00902   
00903   degrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: degrees");
00904 
00905   
00906   wdegrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: wdegrees");
00907 
00908   
00909   sod = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: sod");
00910 
00911   
00912   level = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: level");
00913 
00914   
00915 
00916 
00917 
00918   ot = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: ot"));
00919 
00920   
00921   pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: pos"));
00922 
00923   
00924   perm = gk_i32smalloc(nvtxs, -1, "gk_graph_ComputeBestFOrdering: perm");
00925 
00926   
00927   queue = gk_i32pqCreate(nvtxs);
00928   gk_i32pqInsert(queue, v, 1);
00929 
00930   
00931   pos[0] = ot[0] = v;
00932   pos[v] = ot[v] = 0;
00933   nopen = 1;
00934   ntodo = nvtxs;
00935 
00936   
00937   for (i=0; i<nvtxs; i++) {
00938     if (nopen == 0) { 
00939       gk_i32pqInsert(queue, ot[0], 1);  
00940       nopen++;
00941     }
00942 
00943     if ((v = gk_i32pqGetTop(queue)) == -1)
00944       gk_errexit(SIGERR, "The priority queue got empty ahead of time [i=%d].\n", i);
00945 
00946     if (perm[v] != -1)
00947       gk_errexit(SIGERR, "The perm[%d] has already been set.\n", v);
00948     perm[v] = i;
00949 
00950     if (ot[pos[v]] != v)
00951       gk_errexit(SIGERR, "Something went wrong [ot[pos[%d]]!=%d.\n", v, v);
00952     if (pos[v] >= nopen)
00953       gk_errexit(SIGERR, "The position of v is not in open list. pos[%d]=%d is >=%d.\n", v, pos[v], nopen);
00954 
00955     
00956     ot[pos[v]]       = ot[nopen-1];
00957     pos[ot[nopen-1]] = pos[v];
00958     if (ntodo > nopen) {
00959       ot[nopen-1]      = ot[ntodo-1];
00960       pos[ot[ntodo-1]] = nopen-1;
00961     }
00962     nopen--;
00963     ntodo--;
00964 
00965     for (j=xadj[v]; j<xadj[v+1]; j++) {
00966       u = adjncy[j];
00967       if (perm[u] == -1) {
00968         
00969 
00970         if (degrees[u] == 0) {
00971           ot[pos[u]]     = ot[nopen];
00972           pos[ot[nopen]] = pos[u];
00973           ot[nopen]      = u;
00974           pos[u]         = nopen;
00975           nopen++;
00976 
00977           level[u] = level[v]+1;
00978           gk_i32pqInsert(queue, u, 0);  
00979         }
00980 
00981 
00982         
00983         degrees[u]++;
00984 
00985         
00986         switch (type) {
00987           case 1: 
00988             gk_i32pqUpdate(queue, u, 1000*(i+1)+degrees[u]);
00989             break;
00990 
00991           case 2: 
00992             gk_i32pqUpdate(queue, u, degrees[u]);
00993             break;
00994 
00995           case 3: 
00996             wdegrees[u] += i;
00997             gk_i32pqUpdate(queue, u, wdegrees[u]);
00998             break;
00999 
01000           case 4: 
01001             
01002             ;
01003             break;
01004 
01005           case 5: 
01006             gk_i32pqUpdate(queue, u, -(1000*level[u] - degrees[u]));
01007             break;
01008 
01009           case 6: 
01010             gk_i32pqUpdate(queue, u, (i+1)*degrees[u]);
01011             break;
01012 
01013           default:
01014             ;
01015         }
01016       }
01017     }
01018 
01019     if (type == 4) { 
01020       for (j=0; j<nopen; j++) {
01021         u = ot[j];
01022         if (perm[u] != -1)
01023           gk_errexit(SIGERR, "For i=%d, the open list contains a closed vertex: ot[%zd]=%d, perm[%d]=%d.\n", i, j, u, u, perm[u]);
01024         sod[u] += degrees[u];
01025         if (i<1000 || i%25==0)
01026           gk_i32pqUpdate(queue, u, sod[u]);
01027       }
01028     }
01029 
01030     
01031 
01032 
01033 
01034 
01035 
01036 
01037   }
01038 
01039 
01040   
01041   if (r_perm != NULL) {
01042     *r_perm = perm;
01043     perm = NULL;
01044   }
01045 
01046   if (r_iperm != NULL) {
01047     
01048     for (i=0; i<nvtxs; i++)
01049       degrees[perm[i]] = i;
01050 
01051     *r_iperm = degrees;
01052     degrees = NULL;
01053   }
01054 
01055 
01056 
01057   
01058   gk_i32pqDestroy(queue);
01059   gk_free((void **)&perm, °rees, &wdegrees, &sod, &ot, &pos, &level, LTERM);
01060 
01061 }
01062 
01063 
01064 
01083 
01084 void gk_graph_SingleSourceShortestPaths(gk_graph_t *graph, int v, void **r_sps)
01085 {
01086   ssize_t *xadj;
01087   int i, u, nvtxs;
01088   int32_t *adjncy, *inqueue;
01089 
01090   if (graph->nvtxs <= 0)
01091     return;
01092 
01093   nvtxs  = graph->nvtxs;
01094   xadj   = graph->xadj;
01095   adjncy = graph->adjncy;
01096 
01097   inqueue = gk_i32smalloc(nvtxs, 0, "gk_graph_SingleSourceShortestPaths: inqueue");
01098 
01099   
01100   if (graph->iadjwgt != NULL) {
01101     gk_i32pq_t *queue;
01102     int32_t *adjwgt;
01103     int32_t *sps;
01104 
01105     adjwgt = graph->iadjwgt;
01106 
01107     queue = gk_i32pqCreate(nvtxs);
01108     gk_i32pqInsert(queue, v, 0);
01109     inqueue[v] = 1;
01110 
01111     sps = gk_i32smalloc(nvtxs, -1, "gk_graph_SingleSourceShortestPaths: sps");
01112     sps[v] = 0;
01113 
01114     
01115     while ((v = gk_i32pqGetTop(queue)) != -1) {
01116       inqueue[v] = 2;
01117 
01118       
01119       for (i=xadj[v]; i<xadj[v+1]; i++) {
01120         u = adjncy[i];
01121         if (inqueue[u] == 2)
01122           continue;
01123 
01124         if (sps[u] < 0 || sps[v]+adjwgt[i] < sps[u]) {
01125           sps[u] = sps[v]+adjwgt[i];
01126 
01127           if (inqueue[u])
01128             gk_i32pqUpdate(queue, u, -sps[u]);
01129           else {
01130             gk_i32pqInsert(queue, u, -sps[u]);
01131             inqueue[u] = 1;
01132           }
01133         }
01134       }
01135     }
01136 
01137     *r_sps = (void *)sps;
01138 
01139     gk_i32pqDestroy(queue);
01140   }
01141   else {
01142     gk_fpq_t *queue;
01143     float *adjwgt;
01144     float *sps;
01145 
01146     adjwgt = graph->fadjwgt;
01147 
01148     queue = gk_fpqCreate(nvtxs);
01149     gk_fpqInsert(queue, v, 0);
01150     inqueue[v] = 1;
01151 
01152     sps = gk_fsmalloc(nvtxs, -1, "gk_graph_SingleSourceShortestPaths: sps");
01153     sps[v] = 0;
01154 
01155     
01156     while ((v = gk_fpqGetTop(queue)) != -1) {
01157       inqueue[v] = 2;
01158 
01159       
01160       for (i=xadj[v]; i<xadj[v+1]; i++) {
01161         u = adjncy[i];
01162         if (inqueue[u] == 2)
01163           continue;
01164 
01165         if (sps[u] < 0 || sps[v]+adjwgt[i] < sps[u]) {
01166           sps[u] = sps[v]+adjwgt[i];
01167 
01168           if (inqueue[u])
01169             gk_fpqUpdate(queue, u, -sps[u]);
01170           else {
01171             gk_fpqInsert(queue, u, -sps[u]);
01172             inqueue[u] = 1;
01173           }
01174         }
01175       }
01176     }
01177 
01178     *r_sps = (void *)sps;
01179 
01180     gk_fpqDestroy(queue);
01181   }
01182 
01183   gk_free((void **)&inqueue, LTERM);
01184 
01185 }
01186 
01187 
01188 
01189 #ifdef XXX
01190 
01191 
01195 
01196 void gk_graph_SortAdjacencies(gk_graph_t *graph)
01197 {
01198   int n, nn=0;
01199   ssize_t *ptr;
01200   int *ind;
01201   float *val;
01202 
01203   switch (what) {
01204     case GK_CSR_ROW:
01205       if (!graph->rowptr)
01206         gk_errexit(SIGERR, "Row-based view of the graphrix does not exists.\n");
01207 
01208       n   = graph->nrows;
01209       ptr = graph->rowptr;
01210       ind = graph->rowind;
01211       val = graph->rowval;
01212       break;
01213 
01214     case GK_CSR_COL:
01215       if (!graph->colptr)
01216         gk_errexit(SIGERR, "Column-based view of the graphrix does not exists.\n");
01217 
01218       n   = graph->ncols;
01219       ptr = graph->colptr;
01220       ind = graph->colind;
01221       val = graph->colval;
01222       break;
01223 
01224     default:
01225       gk_errexit(SIGERR, "Invalid index type of %d.\n", what);
01226       return;
01227   }
01228 
01229   #pragma omp parallel if (n > 100)
01230   {
01231     ssize_t i, j, k;
01232     gk_ikv_t *cand;
01233     float *tval;
01234 
01235     #pragma omp single
01236     for (i=0; i<n; i++) 
01237       nn = gk_max(nn, ptr[i+1]-ptr[i]);
01238   
01239     cand = gk_ikvmalloc(nn, "gk_graph_SortIndices: cand");
01240     tval = gk_fmalloc(nn, "gk_graph_SortIndices: tval");
01241   
01242     #pragma omp for schedule(static)
01243     for (i=0; i<n; i++) {
01244       for (k=0, j=ptr[i]; j<ptr[i+1]; j++) {
01245         if (j > ptr[i] && ind[j] < ind[j-1])
01246           k = 1; 
01247         cand[j-ptr[i]].val = j-ptr[i];
01248         cand[j-ptr[i]].key = ind[j];
01249         tval[j-ptr[i]]     = val[j];
01250       }
01251       if (k) {
01252         gk_ikvsorti(ptr[i+1]-ptr[i], cand);
01253         for (j=ptr[i]; j<ptr[i+1]; j++) {
01254           ind[j] = cand[j-ptr[i]].key;
01255           val[j] = tval[cand[j-ptr[i]].val];
01256         }
01257       }
01258     }
01259 
01260     gk_free((void **)&cand, &tval, LTERM);
01261   }
01262 
01263 }
01264 
01265 
01266 
01273 
01274 gk_graph_t *gk_graph_ExtractRows(gk_graph_t *graph, int nrows, int *rind)
01275 {
01276   ssize_t i, ii, j, nnz;
01277   gk_graph_t *ngraph;
01278 
01279   ngraph = gk_graph_Create();
01280 
01281   ngraph->nrows = nrows;
01282   ngraph->ncols = graph->ncols;
01283 
01284   for (nnz=0, i=0; i<nrows; i++)  
01285     nnz += graph->rowptr[rind[i]+1]-graph->rowptr[rind[i]];
01286 
01287   ngraph->rowptr = gk_zmalloc(ngraph->nrows+1, "gk_graph_ExtractPartition: rowptr");
01288   ngraph->rowind = gk_imalloc(nnz, "gk_graph_ExtractPartition: rowind");
01289   ngraph->rowval = gk_fmalloc(nnz, "gk_graph_ExtractPartition: rowval");
01290 
01291   ngraph->rowptr[0] = 0;
01292   for (nnz=0, j=0, ii=0; ii<nrows; ii++) {
01293     i = rind[ii];
01294     gk_icopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowind+graph->rowptr[i], ngraph->rowind+nnz);
01295     gk_fcopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowval+graph->rowptr[i], ngraph->rowval+nnz);
01296     nnz += graph->rowptr[i+1]-graph->rowptr[i];
01297     ngraph->rowptr[++j] = nnz;
01298   }
01299   ASSERT(j == ngraph->nrows);
01300 
01301   return ngraph;
01302 }
01303 
01304 
01305 
01312 
01313 gk_graph_t *gk_graph_ExtractPartition(gk_graph_t *graph, int *part, int pid)
01314 {
01315   ssize_t i, j, nnz;
01316   gk_graph_t *ngraph;
01317 
01318   ngraph = gk_graph_Create();
01319 
01320   ngraph->nrows = 0;
01321   ngraph->ncols = graph->ncols;
01322 
01323   for (nnz=0, i=0; i<graph->nrows; i++) {
01324     if (part[i] == pid) {
01325       ngraph->nrows++;
01326       nnz += graph->rowptr[i+1]-graph->rowptr[i];
01327     }
01328   }
01329 
01330   ngraph->rowptr = gk_zmalloc(ngraph->nrows+1, "gk_graph_ExtractPartition: rowptr");
01331   ngraph->rowind = gk_imalloc(nnz, "gk_graph_ExtractPartition: rowind");
01332   ngraph->rowval = gk_fmalloc(nnz, "gk_graph_ExtractPartition: rowval");
01333 
01334   ngraph->rowptr[0] = 0;
01335   for (nnz=0, j=0, i=0; i<graph->nrows; i++) {
01336     if (part[i] == pid) {
01337       gk_icopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowind+graph->rowptr[i], ngraph->rowind+nnz);
01338       gk_fcopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowval+graph->rowptr[i], ngraph->rowval+nnz);
01339       nnz += graph->rowptr[i+1]-graph->rowptr[i];
01340       ngraph->rowptr[++j] = nnz;
01341     }
01342   }
01343   ASSERT(j == ngraph->nrows);
01344 
01345   return ngraph;
01346 }
01347 
01348 
01349 
01359 
01360 gk_graph_t **gk_graph_Split(gk_graph_t *graph, int *color)
01361 {
01362   ssize_t i, j;
01363   int nrows, ncolors;
01364   ssize_t *rowptr;
01365   int *rowind;
01366   float *rowval;
01367   gk_graph_t **sgraphs;
01368 
01369   nrows  = graph->nrows;
01370   rowptr = graph->rowptr;
01371   rowind = graph->rowind;
01372   rowval = graph->rowval;
01373 
01374   ncolors = gk_imax(rowptr[nrows], color)+1;
01375 
01376   sgraphs = (gk_graph_t **)gk_malloc(sizeof(gk_graph_t *)*ncolors, "gk_graph_Split: sgraphs");
01377   for (i=0; i<ncolors; i++) {
01378     sgraphs[i] = gk_graph_Create();
01379     sgraphs[i]->nrows  = graph->nrows;
01380     sgraphs[i]->ncols  = graph->ncols;
01381     sgraphs[i]->rowptr = gk_zsmalloc(nrows+1, 0, "gk_graph_Split: sgraphs[i]->rowptr"); 
01382   }
01383 
01384   for (i=0; i<nrows; i++) {
01385     for (j=rowptr[i]; j<rowptr[i+1]; j++) 
01386       sgraphs[color[j]]->rowptr[i]++;
01387   }
01388   for (i=0; i<ncolors; i++) 
01389     MAKECSR(j, nrows, sgraphs[i]->rowptr);
01390 
01391   for (i=0; i<ncolors; i++) {
01392     sgraphs[i]->rowind = gk_imalloc(sgraphs[i]->rowptr[nrows], "gk_graph_Split: sgraphs[i]->rowind"); 
01393     sgraphs[i]->rowval = gk_fmalloc(sgraphs[i]->rowptr[nrows], "gk_graph_Split: sgraphs[i]->rowval"); 
01394   }
01395 
01396   for (i=0; i<nrows; i++) {
01397     for (j=rowptr[i]; j<rowptr[i+1]; j++) {
01398       sgraphs[color[j]]->rowind[sgraphs[color[j]]->rowptr[i]] = rowind[j];
01399       sgraphs[color[j]]->rowval[sgraphs[color[j]]->rowptr[i]] = rowval[j];
01400       sgraphs[color[j]]->rowptr[i]++;
01401     }
01402   }
01403 
01404   for (i=0; i<ncolors; i++) 
01405     SHIFTCSR(j, nrows, sgraphs[i]->rowptr);
01406 
01407   return sgraphs;
01408 }
01409 
01410 
01411 
01427 
01428 gk_graph_t *gk_graph_Prune(gk_graph_t *graph, int what, int minf, int maxf)
01429 {
01430   ssize_t i, j, nnz;
01431   int nrows, ncols;
01432   ssize_t *rowptr, *nrowptr;
01433   int *rowind, *nrowind, *collen;
01434   float *rowval, *nrowval;
01435   gk_graph_t *ngraph;
01436 
01437   ngraph = gk_graph_Create();
01438   
01439   nrows = ngraph->nrows = graph->nrows;
01440   ncols = ngraph->ncols = graph->ncols;
01441 
01442   rowptr = graph->rowptr;
01443   rowind = graph->rowind;
01444   rowval = graph->rowval;
01445 
01446   nrowptr = ngraph->rowptr = gk_zmalloc(nrows+1, "gk_graph_Prune: nrowptr");
01447   nrowind = ngraph->rowind = gk_imalloc(rowptr[nrows], "gk_graph_Prune: nrowind");
01448   nrowval = ngraph->rowval = gk_fmalloc(rowptr[nrows], "gk_graph_Prune: nrowval");
01449 
01450 
01451   switch (what) {
01452     case GK_CSR_COL:
01453       collen = gk_ismalloc(ncols, 0, "gk_graph_Prune: collen");
01454 
01455       for (i=0; i<nrows; i++) {
01456         for (j=rowptr[i]; j<rowptr[i+1]; j++) {
01457           ASSERT(rowind[j] < ncols);
01458           collen[rowind[j]]++;
01459         }
01460       }
01461       for (i=0; i<ncols; i++)
01462         collen[i] = (collen[i] >= minf && collen[i] <= maxf ? 1 : 0);
01463 
01464       nrowptr[0] = 0;
01465       for (nnz=0, i=0; i<nrows; i++) {
01466         for (j=rowptr[i]; j<rowptr[i+1]; j++) {
01467           if (collen[rowind[j]]) {
01468             nrowind[nnz] = rowind[j];
01469             nrowval[nnz] = rowval[j];
01470             nnz++;
01471           }
01472         }
01473         nrowptr[i+1] = nnz;
01474       }
01475       gk_free((void **)&collen, LTERM);
01476       break;
01477 
01478     case GK_CSR_ROW:
01479       nrowptr[0] = 0;
01480       for (nnz=0, i=0; i<nrows; i++) {
01481         if (rowptr[i+1]-rowptr[i] >= minf && rowptr[i+1]-rowptr[i] <= maxf) {
01482           for (j=rowptr[i]; j<rowptr[i+1]; j++, nnz++) {
01483             nrowind[nnz] = rowind[j];
01484             nrowval[nnz] = rowval[j];
01485           }
01486         }
01487         nrowptr[i+1] = nnz;
01488       }
01489       break;
01490 
01491     default:
01492       gk_graph_Free(&ngraph);
01493       gk_errexit(SIGERR, "Unknown prunning type of %d\n", what);
01494       return NULL;
01495   }
01496 
01497   return ngraph;
01498 }
01499 
01500 
01501 
01502 
01510 
01511 void gk_graph_Normalize(gk_graph_t *graph, int what, int norm)
01512 {
01513   ssize_t i, j;
01514   int n;
01515   ssize_t *ptr;
01516   float *val, sum;
01517 
01518   if (what&GK_CSR_ROW && graph->rowval) {
01519     n   = graph->nrows;
01520     ptr = graph->rowptr;
01521     val = graph->rowval;
01522 
01523     #pragma omp parallel if (ptr[n] > OMPMINOPS) 
01524     {
01525       #pragma omp for private(j,sum) schedule(static)
01526       for (i=0; i<n; i++) {
01527         for (sum=0.0, j=ptr[i]; j<ptr[i+1]; j++){
01528     if (norm == 2)
01529       sum += val[j]*val[j];
01530     else if (norm == 1)
01531       sum += val[j];  
01532         }
01533         if (sum > 0) {
01534     if (norm == 2)
01535       sum=1.0/sqrt(sum); 
01536     else if (norm == 1)
01537       sum=1.0/sum; 
01538           for (j=ptr[i]; j<ptr[i+1]; j++)
01539             val[j] *= sum;
01540     
01541         }
01542       }
01543     }
01544   }
01545 
01546   if (what&GK_CSR_COL && graph->colval) {
01547     n   = graph->ncols;
01548     ptr = graph->colptr;
01549     val = graph->colval;
01550 
01551     #pragma omp parallel if (ptr[n] > OMPMINOPS)
01552     {
01553     #pragma omp for private(j,sum) schedule(static)
01554       for (i=0; i<n; i++) {
01555         for (sum=0.0, j=ptr[i]; j<ptr[i+1]; j++)
01556     if (norm == 2)
01557       sum += val[j]*val[j];
01558     else if (norm == 1)
01559       sum += val[j]; 
01560         if (sum > 0) {
01561     if (norm == 2)
01562       sum=1.0/sqrt(sum); 
01563     else if (norm == 1)
01564       sum=1.0/sum; 
01565           for (j=ptr[i]; j<ptr[i+1]; j++)
01566             val[j] *= sum;
01567         }
01568       }
01569     }
01570   }
01571 }
01572 
01573 
01574 #endif