void METIS_NodeRefine(int nvtxs, idxtype *xadj, idxtype *vwgt, idxtype *adjncy, idxtype *adjwgt, idxtype *where, idxtype *hmarker, float ubfactor) { GraphType *graph; CtrlType ctrl; ctrl.dbglvl = ONMETIS_DBGLVL; ctrl.optype = OP_ONMETIS; graph = CreateGraph(); SetUpGraph(graph, OP_ONMETIS, nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3); AllocateWorkSpace(&ctrl, graph, 2); Allocate2WayNodePartitionMemory(&ctrl, graph); idxcopy(nvtxs, where, graph->where); Compute2WayNodePartitionParams(&ctrl, graph); FM_2WayNodeRefine_OneSidedP(&ctrl, graph, hmarker, ubfactor, 10); /* FM_2WayNodeRefine_TwoSidedP(&ctrl, graph, hmarker, ubfactor, 10); */ FreeWorkSpace(&ctrl, graph); idxcopy(nvtxs, graph->where, where); FreeGraph(graph); }
/************************************************************************* * This function is the entry point for PWMETIS that accepts exact weights * for the target partitions **************************************************************************/ void METIS_WPartGraphRecursive(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, floattype *tpwgts, int *options, int *edgecut, idxtype *part) { int i, j; GraphType graph; CtrlType ctrl; floattype *mytpwgts; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); SetUpGraph(&graph, OP_PMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, *wgtflag); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = PMETIS_CTYPE; ctrl.IType = PMETIS_ITYPE; ctrl.RType = PMETIS_RTYPE; ctrl.dbglvl = PMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.optype = OP_PMETIS; ctrl.CoarsenTo = 20; ctrl.maxvwgt = 1.5*(idxsum(*nvtxs, graph.vwgt)/ctrl.CoarsenTo); mytpwgts = fmalloc(*nparts, "PWMETIS: mytpwgts"); for (i=0; i<*nparts; i++) mytpwgts[i] = tpwgts[i]; InitRandom(-1); AllocateWorkSpace(&ctrl, &graph, *nparts); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); *edgecut = MlevelRecursiveBisection(&ctrl, &graph, *nparts, part, mytpwgts, 1.000, 0); IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); FreeWorkSpace(&ctrl, &graph); free(mytpwgts); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); }
/************************************************************************* * This function is the entry point for ONWMETIS. It requires weights on the * vertices. It is for the case that the matrix has been pre-compressed. **************************************************************************/ void METIS_EdgeComputeSeparator(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *options, int *sepsize, idxtype *part) { int i, j, tvwgt, tpwgts[2]; GraphType graph; CtrlType ctrl; SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3); tvwgt = idxsum(*nvtxs, graph.vwgt); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.oflags = 0; ctrl.pfactor = 0; ctrl.nseps = 5; ctrl.optype = OP_OEMETIS; ctrl.CoarsenTo = amin(100, *nvtxs-1); ctrl.maxvwgt = 1.5*tvwgt/ctrl.CoarsenTo; InitRandom(options[7]); AllocateWorkSpace(&ctrl, &graph, 2); /*============================================================ * Perform the bisection *============================================================*/ tpwgts[0] = tvwgt/2; tpwgts[1] = tvwgt-tpwgts[0]; MlevelEdgeBisection(&ctrl, &graph, tpwgts, 1.05); ConstructMinCoverSeparator(&ctrl, &graph, 1.05); *sepsize = graph.pwgts[2]; idxcopy(*nvtxs, graph.where, part); GKfree((void**)&graph.gdata, &graph.rdata, &graph.label, LTERM); FreeWorkSpace(&ctrl, &graph); }
/************************************************************************* * This function is the entry point for OEMETIS **************************************************************************/ void METIS_EdgeND(int *nvtxs, idxtype *xadj, idxtype *adjncy, int *numflag, int *options, idxtype *perm, idxtype *iperm) { int i, j; GraphType graph; CtrlType ctrl; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); SetUpGraph(&graph, OP_OEMETIS, *nvtxs, 1, xadj, adjncy, NULL, NULL, 0); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = OEMETIS_CTYPE; ctrl.IType = OEMETIS_ITYPE; ctrl.RType = OEMETIS_RTYPE; ctrl.dbglvl = OEMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.oflags = 0; ctrl.pfactor = -1; ctrl.nseps = 1; ctrl.optype = OP_OEMETIS; ctrl.CoarsenTo = 20; ctrl.maxvwgt = 1.5*(idxsum(*nvtxs, graph.vwgt)/ctrl.CoarsenTo); InitRandom(-1); AllocateWorkSpace(&ctrl, &graph, 2); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); MlevelNestedDissection(&ctrl, &graph, iperm, ORDER_UNBALANCE_FRACTION, *nvtxs); IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); for (i=0; i<*nvtxs; i++) perm[iperm[i]] = i; FreeWorkSpace(&ctrl, &graph); if (*numflag == 1) Change2FNumberingOrder(*nvtxs, xadj, adjncy, perm, iperm); }
/************************************************************************* * This function is the entry point for ONWMETIS. It requires weights on the * vertices. It is for the case that the matrix has been pre-compressed. **************************************************************************/ void METIS_NodeComputeSeparator(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *options, idxtype *sepsize, idxtype *part) { idxtype i, j, tvwgt, tpwgts[2]; GraphType graph; CtrlType ctrl; SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3); tvwgt = idxsum(*nvtxs, graph.vwgt, 1); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.oflags = 0; ctrl.pfactor = 0; ctrl.nseps = 3; ctrl.optype = OP_ONMETIS; ctrl.CoarsenTo = amin(100, *nvtxs-1); ctrl.maxvwgt = 1.5*tvwgt/ctrl.CoarsenTo; InitRandom(options[7]); AllocateWorkSpace(&ctrl, &graph, 2); /*============================================================ * Perform the bisection *============================================================*/ tpwgts[0] = tvwgt/2; tpwgts[1] = tvwgt-tpwgts[0]; MlevelNodeBisectionMultiple(&ctrl, &graph, tpwgts, 1.02); *sepsize = graph.pwgts[2]; idxcopy(*nvtxs, graph.where, part); FreeGraph(&graph, 0); FreeWorkSpace(&ctrl, &graph); }
/************************************************************************* * This function is the entry point for ONWMETIS. It requires weights on the * vertices. It is for the case that the matrix has been pre-compressed. **************************************************************************/ void METIS_NodeComputeSeparator(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, float *ubfactor, int *options, int *sepsize, idxtype *part) { int i, j, tvwgt, tpwgts[2]; GraphType graph; CtrlType ctrl; SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3); tvwgt = idxsum(*nvtxs, graph.vwgt); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.oflags = OFLAG_COMPRESS; /* For by-passing the pre-coarsening for multiple runs */ ctrl.RType = 2; /* Standard 1-sided node refinement code */ ctrl.pfactor = 0; ctrl.nseps = 5; /* This should match NUM_INIT_MSECTIONS in ParMETISLib/defs.h */ ctrl.optype = OP_ONMETIS; InitRandom(options[7]); AllocateWorkSpace(&ctrl, &graph, 2); /*============================================================ * Perform the bisection *============================================================*/ tpwgts[0] = tvwgt/2; tpwgts[1] = tvwgt-tpwgts[0]; MlevelNodeBisectionMultiple(&ctrl, &graph, tpwgts, *ubfactor*.95); *sepsize = graph.pwgts[2]; idxcopy(*nvtxs, graph.where, part); GKfree((void **)&graph.gdata, &graph.rdata, &graph.label, LTERM); FreeWorkSpace(&ctrl, &graph); }
/************************************************************************* * This function is the entry point for KWMETIS **************************************************************************/ void METIS_mCPartGraphKway(int *nvtxs, int *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, floattype *rubvec, int *options, int *edgecut, idxtype *part) { int i, j; GraphType graph; CtrlType ctrl; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); SetUpGraph(&graph, OP_KMETIS, *nvtxs, *ncon, xadj, adjncy, vwgt, adjwgt, *wgtflag); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = McKMETIS_CTYPE; ctrl.IType = McKMETIS_ITYPE; ctrl.RType = McKMETIS_RTYPE; ctrl.dbglvl = McKMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.optype = OP_KMETIS; ctrl.CoarsenTo = amax((*nvtxs)/(20*log2Int(*nparts)), 30*(*nparts)); ctrl.nmaxvwgt = 1.5/(1.0*ctrl.CoarsenTo); InitRandom(-1); AllocateWorkSpace(&ctrl, &graph, *nparts); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); ASSERT(CheckGraph(&graph)); *edgecut = MCMlevelKWayPartitioning(&ctrl, &graph, *nparts, part, rubvec); IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); FreeWorkSpace(&ctrl, &graph); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); }
/*********************************************************************************** * This function is the entry point of the parallel multilevel local diffusion * algorithm. It uses parallel undirected diffusion followed by adaptive k-way * refinement. This function utilizes local coarsening. ************************************************************************************/ void ParMETIS_RepartLDiffusion(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, realtype *adjwgt, int *wgtflag, int *numflag, int *options, int *edgecut, idxtype *part, MPI_Comm *comm) { int npes, mype; CtrlType ctrl; WorkSpaceType wspace; GraphType *graph; MPI_Comm_size(*comm, &npes); MPI_Comm_rank(*comm, &mype); if (npes == 1) { /* Take care the npes = 1 case */ idxset(vtxdist[1], 0, part); *edgecut = 0; return; } if (*numflag == 1) ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 1); SetUpCtrl(&ctrl, npes, options, *comm); ctrl.CoarsenTo = amin(vtxdist[npes]+1, 70*npes); graph = SetUpGraph(&ctrl, vtxdist, xadj, vwgt, adjncy, adjwgt, *wgtflag); graph->vsize = idxsmalloc(graph->nvtxs, 1, "Par_KMetis: vsize"); PreAllocateMemory(&ctrl, graph, &wspace); IFSET(ctrl.dbglvl, DBG_TRACK, printf("%d ParMETIS_RepartLDiffusion about to call AdaptiveUndirected_Partition\n",mype)); AdaptiveUndirected_Partition(&ctrl, graph, &wspace); IFSET(ctrl.dbglvl, DBG_TRACK, printf("%d ParMETIS_RepartLDiffusion about to call ReMapGraph\n",mype)); ReMapGraph(&ctrl, graph, 0, &wspace); idxcopy(graph->nvtxs, graph->where, part); *edgecut = graph->mincut; IMfree((void**)&graph->vsize, LTERM); FreeInitialGraphAndRemap(graph, *wgtflag); FreeWSpace(&wspace); FreeCtrl(&ctrl); if (*numflag == 1) ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 0); }
/************************************************************************* * This function is the entry point for KWMETIS with seed specification * in options[7] **************************************************************************/ void METIS_WPartGraphKway2(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, float *tpwgts, int *options, int *edgecut, idxtype *part) { int i, j; GraphType graph; CtrlType ctrl; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); SetUpGraph(&graph, OP_KMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, *wgtflag); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = KMETIS_CTYPE; ctrl.IType = KMETIS_ITYPE; ctrl.RType = KMETIS_RTYPE; ctrl.dbglvl = KMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.optype = OP_KMETIS; ctrl.CoarsenTo = 20*(*nparts); ctrl.maxvwgt = 1.5*((graph.vwgt ? idxsum(*nvtxs, graph.vwgt) : (*nvtxs))/ctrl.CoarsenTo); InitRandom(options[7]); AllocateWorkSpace(&ctrl, &graph, *nparts); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); *edgecut = MlevelKWayPartitioning(&ctrl, &graph, *nparts, part, tpwgts, 1.000); IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); FreeWorkSpace(&ctrl, &graph); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); }
/*********************************************************************************** * This function creates the fused-element-graph and returns the partition ************************************************************************************/ void ParMETIS_FusedElementGraph(idxtype *vtxdist, idxtype *xadj, realtype *vvol, realtype *vsurf, idxtype *adjncy, idxtype *vwgt, realtype *adjwgt, int *wgtflag, int *numflag, int *nparts, int *options, idxtype *part, MPI_Comm *comm) { int npes, mype, nvtxs; CtrlType ctrl; WorkSpaceType wspace; GraphType *graph; MPI_Comm_size(*comm, &npes); MPI_Comm_rank(*comm, &mype); nvtxs = vtxdist[mype+1]-vtxdist[mype]; /* IFSET(options[OPTION_DBGLVL], DBG_TRACK, printf("%d ParMETIS_FEG npes=%d\n",mype, npes)); */ SetUpCtrl(&ctrl, *nparts, options, *comm); ctrl.CoarsenTo = amin(vtxdist[npes]+1, 25*amax(npes, *nparts)); graph = SetUpGraph(&ctrl, vtxdist, xadj, vwgt, adjncy, adjwgt, *wgtflag); graph->where = part; PreAllocateMemory(&ctrl, graph, &wspace); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); CreateFusedElementGraph(&ctrl, graph, &wspace, numflag); idxcopy(nvtxs, graph->where, part); IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm)); IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); if (((*wgtflag)&2) == 0) IMfree((void**)&graph->vwgt, LTERM); IMfree((void**)&graph->lperm, &graph->peind, &graph->pexadj, &graph->peadjncy, &graph->peadjloc, &graph->recvptr, &graph->recvind, &graph->sendptr, &graph->imap, &graph->sendind, &graph, LTERM); FreeWSpace(&wspace); FreeCtrl(&ctrl); }
/****************************************************************************** * This function takes a graph and its partition vector and creates a new * graph corresponding to the one after the movement *******************************************************************************/ void TestMoveGraph(GraphType *ograph, GraphType *omgraph, idxtype *part, MPI_Comm comm) { int npes, mype; CtrlType ctrl; WorkSpaceType wspace; GraphType *graph, *mgraph; int options[5] = {0, 0, 1, 0, 0}; MPI_Comm_size(comm, &npes); MPI_Comm_rank(comm, &mype); SetUpCtrl(&ctrl, npes, 0, comm); ctrl.CoarsenTo = 1; /* Needed by SetUpGraph, otherwise we can FP errors */ graph = SetUpGraph(&ctrl, ograph->vtxdist, ograph->xadj, NULL, ograph->adjncy, NULL, 0); AllocateWSpace(&ctrl, graph, &wspace); SetUp(&ctrl, graph, &wspace); graph->where = part; graph->ncon = 1; mgraph = Mc_MoveGraph(&ctrl, graph, &wspace); omgraph->gnvtxs = mgraph->gnvtxs; omgraph->nvtxs = mgraph->nvtxs; omgraph->nedges = mgraph->nedges; omgraph->vtxdist = mgraph->vtxdist; omgraph->xadj = mgraph->xadj; omgraph->adjncy = mgraph->adjncy; mgraph->vtxdist = NULL; mgraph->xadj = NULL; mgraph->adjncy = NULL; FreeGraph(mgraph); graph->where = NULL; FreeInitialGraphAndRemap(graph, 0, 1); FreeWSpace(&wspace); }
/************************************************************************* * This function is the entry point for the node ND code for ParMETIS **************************************************************************/ void METIS_NodeNDP(int nvtxs, idxtype *xadj, idxtype *adjncy, int npes, int *options, idxtype *perm, idxtype *iperm, idxtype *sizes) { int i, ii, j, l, wflag, nflag; GraphType graph; CtrlType ctrl; idxtype *cptr, *cind; if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; ctrl.oflags = ONMETIS_OFLAGS; ctrl.pfactor = ONMETIS_PFACTOR; ctrl.nseps = ONMETIS_NSEPS; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; ctrl.oflags = options[OPTION_OFLAGS]; ctrl.pfactor = options[OPTION_PFACTOR]; ctrl.nseps = options[OPTION_NSEPS]; } if (ctrl.nseps < 1) ctrl.nseps = 1; ctrl.optype = OP_ONMETIS; ctrl.CoarsenTo = 100; IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); InitRandom(-1); if (ctrl.oflags&OFLAG_COMPRESS) { /*============================================================ * Compress the graph ==============================================================*/ cptr = idxmalloc(nvtxs+1, "ONMETIS: cptr"); cind = idxmalloc(nvtxs, "ONMETIS: cind"); CompressGraph(&ctrl, &graph, nvtxs, xadj, adjncy, cptr, cind); if (graph.nvtxs >= COMPRESSION_FRACTION*(nvtxs)) { ctrl.oflags--; /* We actually performed no compression */ GKfree((void**)&cptr, &cind, LTERM); } else if (2*graph.nvtxs < nvtxs && ctrl.nseps == 1) ctrl.nseps = 2; } else { SetUpGraph(&graph, OP_ONMETIS, nvtxs, 1, xadj, adjncy, NULL, NULL, 0); } /*============================================================= * Do the nested dissection ordering --=============================================================*/ ctrl.maxvwgt = 1.5*(idxsum(graph.nvtxs, graph.vwgt)/ctrl.CoarsenTo); AllocateWorkSpace(&ctrl, &graph, 2); idxset(2*npes-1, 0, sizes); MlevelNestedDissectionP(&ctrl, &graph, iperm, graph.nvtxs, npes, 0, sizes); FreeWorkSpace(&ctrl, &graph); if (ctrl.oflags&OFLAG_COMPRESS) { /* Uncompress the ordering */ if (graph.nvtxs < COMPRESSION_FRACTION*(nvtxs)) { /* construct perm from iperm */ for (i=0; i<graph.nvtxs; i++) perm[iperm[i]] = i; for (l=ii=0; ii<graph.nvtxs; ii++) { i = perm[ii]; for (j=cptr[i]; j<cptr[i+1]; j++) iperm[cind[j]] = l++; } } GKfree((void**)&cptr, &cind, LTERM); } for (i=0; i<nvtxs; i++) perm[iperm[i]] = i; IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); }
/************************************************************************* * This function is the entry point for KMETIS **************************************************************************/ void *METIS_PartGraphForContact(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, double *xyzcoords, idxtype *sflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part) { idxtype i, j, ii, dim, ncon, wgtflag, mcnumflag, nnodes, nlnodes, nclean, naclean, ndirty, maxdepth, rwgtflag, rnumflag; idxtype *mcvwgt, *dtpart, *marker, *leafpart; idxtype *adjwgt; float rubvec[2], lbvec[2]; GraphType graph, *cgraph; ContactInfoType *cinfo; DKeyValueType *xyzcand[3]; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); /*--------------------------------------------------------------------- * Allocate memory for the contact info type *---------------------------------------------------------------------*/ cinfo = (ContactInfoType *)gk_malloc(sizeof(ContactInfoType), "METIS_PartGraphForContact: cinfo"); cinfo->leafptr = idxsmalloc(*nvtxs+1, 0, "METIS_PartGraphForContact: leafptr"); cinfo->leafind = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: leafind"); cinfo->leafwgt = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: leafwgt"); cinfo->part = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: part"); leafpart = cinfo->leafpart = idxmalloc(*nvtxs, "METIS_PartGraphForContact: leafpart"); cinfo->dtree = (DTreeNodeType *)gk_malloc(sizeof(DTreeNodeType)*(*nvtxs), "METIS_PartGraphForContact: cinfo->dtree"); cinfo->nvtxs = *nvtxs; /*--------------------------------------------------------------------- * Compute the initial k-way partitioning *---------------------------------------------------------------------*/ mcvwgt = idxsmalloc(2*(*nvtxs), 0, "METIS_PartGraphForContact: mcvwgt"); for (i=0; i<*nvtxs; i++) { mcvwgt[2*i+0] = 1; mcvwgt[2*i+1] = (sflag[i] == 0 ? 0 : 1); } adjwgt = idxmalloc(xadj[*nvtxs], "METIS_PartGraphForContact: adjwgt"); for (i=0; i<*nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) adjwgt[j] = (sflag[i] && sflag[adjncy[j]] ? 5 : 1); } rubvec[0] = 1.03; rubvec[1] = 1.05; ncon = 2; mcnumflag = 0; wgtflag = 1; METIS_mCPartGraphKway(nvtxs, &ncon, xadj, adjncy, mcvwgt, adjwgt, &wgtflag, &mcnumflag, nparts, rubvec, options, edgecut, part); /* The following is just for stat reporting purposes */ SetUpGraph(&graph, OP_KMETIS, *nvtxs, 2, xadj, adjncy, mcvwgt, NULL, 0); graph.vwgt = mcvwgt; ComputePartitionBalance(&graph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(&graph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Induce the decission tree *---------------------------------------------------------------------*/ dtpart = idxmalloc(*nvtxs, "METIS_PartGraphForContact: dtpart"); marker = idxsmalloc(*nvtxs, 0, "METIS_PartGraphForContact: marker"); for (dim=0; dim<3; dim++) { xyzcand[dim] = (DKeyValueType *)gk_malloc(sizeof(DKeyValueType)*(*nvtxs), "METIS_PartGraphForContact: xyzcand[dim]"); for (i=0; i<*nvtxs; i++) { xyzcand[dim][i].key = xyzcoords[3*i+dim]; xyzcand[dim][i].val = i; } idkeysort(*nvtxs, xyzcand[dim]); } nnodes = nlnodes = nclean = naclean = ndirty = maxdepth = 0; InduceDecissionTree(*nvtxs, xyzcand, sflag, *nparts, part, *nvtxs/(20*(*nparts)), *nvtxs/(20*(*nparts)*(*nparts)), 0.90, &nnodes, &nlnodes, cinfo->dtree, leafpart, dtpart, &nclean, &naclean, &ndirty, &maxdepth, marker); mprintf("NNodes: %5D, NLNodes: %5D, NClean: %5D, NAClean: %5D, NDirty: %5D, MaxDepth: %3D\n", nnodes, nlnodes, nclean, naclean, ndirty, maxdepth); /*--------------------------------------------------------------------- * Create the tree-induced coarse graph and refine it *---------------------------------------------------------------------*/ cgraph = CreatePartitionGraphForContact(*nvtxs, xadj, adjncy, mcvwgt, adjwgt, nlnodes, leafpart); for (i=0; i<*nvtxs; i++) part[leafpart[i]] = dtpart[i]; ComputePartitionBalance(cgraph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(cgraph, part), lbvec[0], lbvec[1]); rwgtflag = 3; rnumflag = 0; METIS_mCRefineGraphKway(&(cgraph->nvtxs), &ncon, cgraph->xadj, cgraph->adjncy, cgraph->vwgt, cgraph->adjwgt, &rwgtflag, &rnumflag, nparts, rubvec, options, edgecut, part); ComputePartitionBalance(cgraph, *nparts, part, lbvec); mprintf(" %D-way Edge-Cut: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(cgraph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Use that to compute the partition of the original graph *---------------------------------------------------------------------*/ idxcopy(cgraph->nvtxs, part, dtpart); for (i=0; i<*nvtxs; i++) part[i] = dtpart[leafpart[i]]; ComputePartitionBalance(&graph, *nparts, part, lbvec); idxset(*nvtxs, 1, graph.vwgt); mprintf(" %D-way Edge-Cut: %7D, Volume: %7D, Balance: %5.2f %5.2f\n", *nparts, ComputeCut(&graph, part), ComputeVolume(&graph, part), lbvec[0], lbvec[1]); /*--------------------------------------------------------------------- * Induce the final decission tree *---------------------------------------------------------------------*/ nnodes = nlnodes = nclean = naclean = ndirty = maxdepth = 0; InduceDecissionTree(*nvtxs, xyzcand, sflag, *nparts, part, *nvtxs/((40)*(*nparts)), 1, 1.00, &nnodes, &nlnodes, cinfo->dtree, leafpart, dtpart, &nclean, &naclean, &ndirty, &maxdepth, marker); mprintf("NNodes: %5D, NLNodes: %5D, NClean: %5D, NAClean: %5D, NDirty: %5D, MaxDepth: %3D\n", nnodes, nlnodes, nclean, naclean, ndirty, maxdepth); /*--------------------------------------------------------------------- * Populate the remaining fields of the cinfo data structure *---------------------------------------------------------------------*/ cinfo->nnodes = nnodes; cinfo->nleafs = nlnodes; idxcopy(*nvtxs, part, cinfo->part); BuildDTLeafContents(cinfo, sflag); CheckDTree(*nvtxs, xyzcoords, part, cinfo); gk_free((void **)&mcvwgt, &dtpart, &xyzcand[0], &xyzcand[1], &xyzcand[2], &marker, &adjwgt, LTERM); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); return (void *)cinfo; }
/************************************************************************* * This function is the entry point for PWMETIS that accepts exact weights * for the target partitions **************************************************************************/ void METIS_mCPartGraphRecursive2(int *nvtxs, int *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, float *tpwgts, int *options, int *edgecut, idxtype *part) { int i, j; GraphType graph; CtrlType ctrl; float *mytpwgts; float avgwgt; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); SetUpGraph(&graph, OP_PMETIS, *nvtxs, *ncon, xadj, adjncy, vwgt, adjwgt, *wgtflag); graph.npwgts = NULL; mytpwgts = fmalloc(*nparts, "mytpwgts"); scopy(*nparts, tpwgts, mytpwgts); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = McPMETIS_CTYPE; ctrl.IType = McPMETIS_ITYPE; ctrl.RType = McPMETIS_RTYPE; ctrl.dbglvl = McPMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.optype = OP_PMETIS; ctrl.CoarsenTo = 100; ctrl.nmaxvwgt = 1.5/(1.0*ctrl.CoarsenTo); InitRandom(options[7]); AllocateWorkSpace(&ctrl, &graph, *nparts); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); ASSERT(CheckGraph(&graph)); *edgecut = MCMlevelRecursiveBisection2(&ctrl, &graph, *nparts, mytpwgts, part, 1.000, 0); /* { idxtype wgt[2048], minwgt, maxwgt, sumwgt; printf("nvtxs: %d, nparts: %d, ncon: %d\n", graph.nvtxs, *nparts, *ncon); for (i=0; i<(*nparts)*(*ncon); i++) wgt[i] = 0; for (i=0; i<graph.nvtxs; i++) for (j=0; j<*ncon; j++) wgt[part[i]*(*ncon)+j] += vwgt[i*(*ncon)+j]; for (j=0; j<*ncon; j++) { minwgt = maxwgt = sumwgt = 0; for (i=0; i<(*nparts); i++) { minwgt = (wgt[i*(*ncon)+j] < wgt[minwgt*(*ncon)+j]) ? i : minwgt; maxwgt = (wgt[i*(*ncon)+j] > wgt[maxwgt*(*ncon)+j]) ? i : maxwgt; sumwgt += wgt[i*(*ncon)+j]; } avgwgt = (float)sumwgt / (float)*nparts; printf("min: %5d, max: %5d, avg: %5.2f, balance: %6.3f\n", wgt[minwgt*(*ncon)+j], wgt[maxwgt*(*ncon)+j], avgwgt, (float)wgt[maxwgt*(*ncon)+j] / avgwgt); } printf("\n"); } */ IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); FreeWorkSpace(&ctrl, &graph); GKfree((void**)(void *)&mytpwgts, LTERM); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); }
int main (int argc, const char * argv[]) { if (argc == 1) { fprintf (stderr, "%s\n", usageStr); exit(0); } char* filePath = 0; bool shouldPlay = false; bool shouldSetBank = false; bool shouldUseMIDIEndpoint = false; bool shouldPrint = true; bool waitAtEnd = false; bool diskStream = false; OSType dataFormat = 0; Float64 srate = 0; const char* outputFilePath = 0; MusicSequenceLoadFlags loadFlags = 0; char* bankPath = 0; Float32 startTime = 0; UInt32 numFrames = 512; for (int i = 1; i < argc; ++i) { if (!strcmp ("-p", argv[i])) { shouldPlay = true; } else if (!strcmp ("-w", argv[i])) { waitAtEnd = true; } else if (!strcmp ("-d", argv[i])) { diskStream = true; } else if (!strcmp ("-b", argv[i])) { shouldSetBank = true; if (++i == argc) goto malformedInput; bankPath = const_cast<char*>(argv[i]); } else if (!strcmp ("-n", argv[i])) { shouldPrint = false; } else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~')) { filePath = const_cast<char*>(argv[i]); } else if (!strcmp ("-t", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%f", &startTime); } else if (!strcmp("-e", argv[i])) { shouldUseMIDIEndpoint = true; } else if (!strcmp("-c", argv[i])) { loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks; } else if (!strcmp ("-i", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%ld", &numFrames); } else if (!strcmp ("-f", argv[i])) { if (i + 3 >= argc) goto malformedInput; outputFilePath = argv[++i]; str2OSType (argv[++i], dataFormat); sscanf (argv[++i], "%lf", &srate); } else { malformedInput: fprintf (stderr, "%s\n", usageStr); exit (1); } } if (filePath == 0) { fprintf (stderr, "You have to specify a MIDI file to print or play\n"); fprintf (stderr, "%s\n", usageStr); exit (1); } if (shouldUseMIDIEndpoint && outputFilePath) { printf ("can't write a file when you try to play out to a MIDI Endpoint\n"); exit (1); } MusicSequence sequence; OSStatus result; require_noerr (result = LoadSMF (filePath, sequence, loadFlags), fail); if (shouldPrint) CAShow (sequence); if (shouldPlay) { AUGraph graph = 0; AudioUnit theSynth = 0; require_noerr (result = MusicSequenceGetAUGraph (sequence, &graph), fail); require_noerr (result = AUGraphOpen (graph), fail); require_noerr (result = GetSynthFromGraph (graph, theSynth), fail); require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &maxCPULoad, sizeof(maxCPULoad)), fail); if (shouldUseMIDIEndpoint) { MIDIClientRef theMidiClient; MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient); ItemCount destCount = MIDIGetNumberOfDestinations(); if (destCount == 0) { fprintf (stderr, "No MIDI Endpoints to play to.\n"); exit(1); } require_noerr (result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0)), fail); } else { if (shouldSetBank) { FSRef soundBankRef; require_noerr (result = FSPathMakeRef ((const UInt8*)bankPath, &soundBankRef, 0), fail); printf ("Setting Sound Bank:%s\n", bankPath); require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_SoundBankFSRef, kAudioUnitScope_Global, 0, &soundBankRef, sizeof(soundBankRef)), fail); } if (diskStream) { UInt32 value = diskStream; require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } if (outputFilePath) { // need to tell synth that is going to render a file. UInt32 value = 1; require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } require_noerr (result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL)), fail); if (shouldPrint) { printf ("Sample Rate: %.1f \n", srate); printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F')); } require_noerr (result = AUGraphInitialize (graph), fail); if (shouldPrint) CAShow (graph); } MusicPlayer player; require_noerr (result = NewMusicPlayer (&player), fail); require_noerr (result = MusicPlayerSetSequence (player, sequence), fail); // figure out sequence length UInt32 ntracks; require_noerr(MusicSequenceGetTrackCount (sequence, &ntracks), fail); MusicTimeStamp sequenceLength = 0; for (UInt32 i = 0; i < ntracks; ++i) { MusicTrack track; MusicTimeStamp trackLength; UInt32 propsize = sizeof(MusicTimeStamp); require_noerr (result = MusicSequenceGetIndTrack(sequence, i, &track), fail); require_noerr (result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize), fail); if (trackLength > sequenceLength) sequenceLength = trackLength; } // now I'm going to add 8 beats on the end for the reverb/long releases to tail off... sequenceLength += 8; require_noerr (result = MusicPlayerSetTime (player, startTime), fail); require_noerr (result = MusicPlayerPreroll (player), fail); if (shouldPrint) { printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); getc(stdin); } startRunningTime = AudioGetCurrentHostTime (); require_noerr (result = MusicPlayerStart (player), fail); if (outputFilePath) WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player); else PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd); require_noerr (result = MusicPlayerStop (player), fail); if (shouldPrint) printf ("finished playing\n"); // this shows you how you should dispose of everything require_noerr (result = DisposeMusicPlayer (player), fail); require_noerr (result = DisposeMusicSequence(sequence), fail); // don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....) } else { require_noerr (result = DisposeMusicSequence(sequence), fail); } while (waitAtEnd) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); return 0; fail: if (shouldPrint) printf ("Error = %ld\n", result); return result; }
int main (int argc, const char * argv[]) { if (argc == 1) { fprintf (stderr, "%s\n", usageStr); exit(0); } char* filePath = 0; bool shouldPlay = false; bool shouldSetBank = false; bool shouldUseMIDIEndpoint = false; bool shouldPrint = true; bool waitAtEnd = false; bool diskStream = false; OSType dataFormat = 0; Float64 srate = 0; const char* outputFilePath = 0; MusicSequenceLoadFlags loadFlags = 0; char* bankPath = 0; Float32 startTime = 0; UInt32 numFrames = 512; std::set<int> trackSet; for (int i = 1; i < argc; ++i) { if (!strcmp ("-p", argv[i])) { shouldPlay = true; } else if (!strcmp ("-w", argv[i])) { waitAtEnd = true; } else if (!strcmp ("-d", argv[i])) { diskStream = true; } else if (!strcmp ("-b", argv[i])) { shouldSetBank = true; if (++i == argc) goto malformedInput; bankPath = const_cast<char*>(argv[i]); } else if (!strcmp ("-n", argv[i])) { shouldPrint = false; } else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~')) { filePath = const_cast<char*>(argv[i]); } else if (!strcmp ("-s", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%f", &startTime); } else if (!strcmp ("-t", argv[i])) { int index; if (++i == argc) goto malformedInput; sscanf (argv[i], "%d", &index); trackSet.insert(--index); } else if (!strcmp("-e", argv[i])) { shouldUseMIDIEndpoint = true; } else if (!strcmp("-c", argv[i])) { loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks; } else if (!strcmp ("-i", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%lu", (unsigned long*)(&numFrames)); } else if (!strcmp ("-f", argv[i])) { if (i + 3 >= argc) goto malformedInput; outputFilePath = argv[++i]; StrToOSType (argv[++i], dataFormat); sscanf (argv[++i], "%lf", &srate); } else { malformedInput: fprintf (stderr, "%s\n", usageStr); exit (1); } } if (filePath == 0) { fprintf (stderr, "You have to specify a MIDI file to print or play\n"); fprintf (stderr, "%s\n", usageStr); exit (1); } if (shouldUseMIDIEndpoint && outputFilePath) { printf ("can't write a file when you try to play out to a MIDI Endpoint\n"); exit (1); } MusicSequence sequence; OSStatus result; FailIf ((result = LoadSMF (filePath, sequence, loadFlags)), fail, "LoadSMF"); if (shouldPrint) CAShow (sequence); if (shouldPlay) { AUGraph graph = 0; AudioUnit theSynth = 0; FailIf ((result = MusicSequenceGetAUGraph (sequence, &graph)), fail, "MusicSequenceGetAUGraph"); FailIf ((result = AUGraphOpen (graph)), fail, "AUGraphOpen"); FailIf ((result = GetSynthFromGraph (graph, theSynth)), fail, "GetSynthFromGraph"); FailIf ((result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &maxCPULoad, sizeof(maxCPULoad))), fail, "AudioUnitSetProperty: kAudioUnitProperty_CPULoad"); if (shouldUseMIDIEndpoint) { MIDIClientRef theMidiClient; MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient); ItemCount destCount = MIDIGetNumberOfDestinations(); if (destCount == 0) { fprintf (stderr, "No MIDI Endpoints to play to.\n"); exit(1); } FailIf ((result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0))), fail, "MusicSequenceSetMIDIEndpoint"); } else { if (shouldSetBank) { CFURLRef soundBankURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)bankPath, strlen(bankPath), false); printf ("Setting Sound Bank:%s\n", bankPath); result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_SoundBankURL, kAudioUnitScope_Global, 0, &soundBankURL, sizeof(soundBankURL)); if (soundBankURL) CFRelease(soundBankURL); FailIf (result, fail, "AudioUnitSetProperty: kMusicDeviceProperty_SoundBankURL"); } if (diskStream) { UInt32 value = diskStream; FailIf ((result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, sizeof(value))), fail, "AudioUnitSetProperty: kMusicDeviceProperty_StreamFromDisk"); } if (outputFilePath) { // need to tell synth that is going to render a file. UInt32 value = 1; FailIf ((result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &value, sizeof(value))), fail, "AudioUnitSetProperty: kAudioUnitProperty_OfflineRender"); } FailIf ((result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL))), fail, "SetUpGraph"); if (shouldPrint) { printf ("Sample Rate: %.1f \n", srate); printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F')); } FailIf ((result = AUGraphInitialize (graph)), fail, "AUGraphInitialize"); if (shouldPrint) CAShow (graph); } MusicPlayer player; FailIf ((result = NewMusicPlayer (&player)), fail, "NewMusicPlayer"); FailIf ((result = MusicPlayerSetSequence (player, sequence)), fail, "MusicPlayerSetSequence"); // figure out sequence length UInt32 ntracks; FailIf ((MusicSequenceGetTrackCount (sequence, &ntracks)), fail, "MusicSequenceGetTrackCount"); MusicTimeStamp sequenceLength = 0; bool shouldPrintTracks = shouldPrint && !trackSet.empty(); if (shouldPrintTracks) printf ("Only playing specified tracks:\n\t"); for (UInt32 i = 0; i < ntracks; ++i) { MusicTrack track; MusicTimeStamp trackLength; UInt32 propsize = sizeof(MusicTimeStamp); FailIf ((result = MusicSequenceGetIndTrack(sequence, i, &track)), fail, "MusicSequenceGetIndTrack"); FailIf ((result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize)), fail, "MusicTrackGetProperty: kSequenceTrackProperty_TrackLength"); if (trackLength > sequenceLength) sequenceLength = trackLength; if (!trackSet.empty() && (trackSet.find(i) == trackSet.end())) { Boolean mute = true; FailIf ((result = MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &mute, sizeof(mute))), fail, "MusicTrackSetProperty: kSequenceTrackProperty_MuteStatus"); } else if (shouldPrintTracks) { printf ("%d, ", int(i+1)); } } if (shouldPrintTracks) printf ("\n"); // now I'm going to add 8 beats on the end for the reverb/long releases to tail off... sequenceLength += 8; FailIf ((result = MusicPlayerSetTime (player, startTime)), fail, "MusicPlayerSetTime"); FailIf ((result = MusicPlayerPreroll (player)), fail, "MusicPlayerPreroll"); if (shouldPrint) { printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); getc(stdin); } startRunningTime = CAHostTimeBase::GetTheCurrentTime(); /* if (waitAtEnd && graph) AUGraphStart(graph); */ FailIf ((result = MusicPlayerStart (player)), fail, "MusicPlayerStart"); if (outputFilePath) WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player); else PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd); FailIf ((result = MusicPlayerStop (player)), fail, "MusicPlayerStop"); if (shouldPrint) printf ("finished playing\n"); /* if (waitAtEnd) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); if (graph) AUGraphStop(graph); if (shouldPrint) printf ("disposing\n"); } */ // this shows you how you should dispose of everything FailIf ((result = DisposeMusicPlayer (player)), fail, "DisposeMusicPlayer"); FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence"); // don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....) } else { FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence"); } while (waitAtEnd) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); return 0; fail: if (shouldPrint) printf ("Error = %ld\n", (long)result); return result; }
/************************************************************************* * This function is the entry point for ONCMETIS **************************************************************************/ void METIS_NodeND(int *nvtxs, idxtype *xadj, idxtype *adjncy, int *numflag, int *options, idxtype *perm, idxtype *iperm) { int i, ii, j, l, wflag, nflag; GraphType graph; CtrlType ctrl; idxtype *cptr, *cind, *piperm; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = ONMETIS_CTYPE; ctrl.IType = ONMETIS_ITYPE; ctrl.RType = ONMETIS_RTYPE; ctrl.dbglvl = ONMETIS_DBGLVL; ctrl.oflags = ONMETIS_OFLAGS; ctrl.pfactor = ONMETIS_PFACTOR; ctrl.nseps = ONMETIS_NSEPS; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; ctrl.oflags = options[OPTION_OFLAGS]; ctrl.pfactor = options[OPTION_PFACTOR]; ctrl.nseps = options[OPTION_NSEPS]; } if (ctrl.nseps < 1) ctrl.nseps = 1; ctrl.optype = OP_ONMETIS; ctrl.CoarsenTo = 100; IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr)); InitRandom(-1); if (ctrl.pfactor > 0) { /*============================================================ * Prune the dense columns ==============================================================*/ piperm = idxmalloc(*nvtxs, "ONMETIS: piperm"); PruneGraph(&ctrl, &graph, *nvtxs, xadj, adjncy, piperm, (float)(0.1*ctrl.pfactor)); } else if (ctrl.oflags&OFLAG_COMPRESS) { /*============================================================ * Compress the graph ==============================================================*/ cptr = idxmalloc(*nvtxs+1, "ONMETIS: cptr"); cind = idxmalloc(*nvtxs, "ONMETIS: cind"); CompressGraph(&ctrl, &graph, *nvtxs, xadj, adjncy, cptr, cind); if (graph.nvtxs >= COMPRESSION_FRACTION*(*nvtxs)) { ctrl.oflags--; /* We actually performed no compression */ GKfree(&cptr, &cind, LTERM); } else if (2*graph.nvtxs < *nvtxs && ctrl.nseps == 1) ctrl.nseps = 2; } else { SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, NULL, NULL, 0); } /*============================================================= * Do the nested dissection ordering --=============================================================*/ ctrl.maxvwgt = 1.5*(idxsum(graph.nvtxs, graph.vwgt)/ctrl.CoarsenTo); AllocateWorkSpace(&ctrl, &graph, 2); if (ctrl.oflags&OFLAG_CCMP) MlevelNestedDissectionCC(&ctrl, &graph, iperm, ORDER_UNBALANCE_FRACTION, graph.nvtxs); else MlevelNestedDissection(&ctrl, &graph, iperm, ORDER_UNBALANCE_FRACTION, graph.nvtxs); FreeWorkSpace(&ctrl, &graph); if (ctrl.pfactor > 0) { /* Order any prunned vertices */ if (graph.nvtxs < *nvtxs) { idxcopy(graph.nvtxs, iperm, perm); /* Use perm as an auxiliary array */ for (i=0; i<graph.nvtxs; i++) iperm[piperm[i]] = perm[i]; for (i=graph.nvtxs; i<*nvtxs; i++) iperm[piperm[i]] = i; } GKfree(&piperm, LTERM); } else if (ctrl.oflags&OFLAG_COMPRESS) { /* Uncompress the ordering */ if (graph.nvtxs < COMPRESSION_FRACTION*(*nvtxs)) { /* construct perm from iperm */ for (i=0; i<graph.nvtxs; i++) perm[iperm[i]] = i; for (l=ii=0; ii<graph.nvtxs; ii++) { i = perm[ii]; for (j=cptr[i]; j<cptr[i+1]; j++) iperm[cind[j]] = l++; } } GKfree(&cptr, &cind, LTERM); } for (i=0; i<*nvtxs; i++) perm[iperm[i]] = i; IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); if (*numflag == 1) Change2FNumberingOrder(*nvtxs, xadj, adjncy, perm, iperm); }