Grid::Grid(Grid *Orig){ int i; domainname = strdup(Orig->domainname); domainfile = Orig->domainfile; totverts = Orig->totverts; xcoords = dvector(0, totverts-1); ycoords = dvector(0, totverts-1); zcoords = dvector(0, totverts-1); dcopy(totverts, Orig->xcoords, 1, xcoords, 1); dcopy(totverts, Orig->ycoords, 1, ycoords, 1); dcopy(totverts, Orig->zcoords, 1, zcoords, 1); nel = Orig->nel; nverts = ivector(0, nel-1); icopy(nel, Orig->nverts, 1, nverts, 1); vertids = imatrix(0, nel-1, 0, Max_Nverts-1); icopy(nel*Max_Nverts, Orig->vertids[0], 1, vertids[0], 1); elmtids = ivector(0, nel-1); icopy(nel, Orig->elmtids, 1, elmtids, 1); vertexmap = imatrix(0, nel-1, 0, Max_Nverts-1); icopy(nel*Max_Nverts, Orig->vertexmap[0], 1, vertexmap[0], 1); }
void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, j, k, nvtxs, bestcut=0, mincut, inbfs; idx_t *xadj, *where, *bndind, *bestwhere; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; /* Allocate refinement memory. Allocate sufficient memory for both edge and node */ graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts"); graph->where = imalloc(nvtxs, "GrowBisectionNode: where"); graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr"); graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind"); graph->id = imalloc(nvtxs, "GrowBisectionNode: id"); graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed"); graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo"); bestwhere = iwspacemalloc(ctrl, nvtxs); where = graph->where; bndind = graph->bndind; for (inbfs=0; inbfs<niparts; inbfs++) { iset(nvtxs, 1, where); if (inbfs > 0) where[irandInRange(nvtxs)] = 0; Compute2WayPartitionParams(ctrl, graph); General2WayBalance(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); /* Construct and refine the vertex separator */ for (i=0; i<graph->nbnd; i++) { j = bndind[i]; if (xadj[j+1]-xadj[j] > 0) /* ignore islands */ where[j] = 2; } Compute2WayNodePartitionParams(ctrl, graph); FM_2WayNodeRefine2Sided(ctrl, graph, 4); /* printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n", inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut); */ if (inbfs == 0 || bestcut > graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; }
idx_t ComputeRealCutFromMoved(idx_t *vtxdist, idx_t *mvtxdist, idx_t *part, idx_t *mpart, char *filename, MPI_Comm comm) { idx_t i, j, nvtxs, mype, npes, cut; idx_t *xadj, *adjncy, *gpart, *gmpart, *perm, *sizes; MPI_Status status; gkMPI_Comm_size(comm, &npes); gkMPI_Comm_rank(comm, &mype); if (mype != 0) { gkMPI_Send((void *)part, vtxdist[mype+1]-vtxdist[mype], IDX_T, 0, 1, comm); gkMPI_Send((void *)mpart, mvtxdist[mype+1]-mvtxdist[mype], IDX_T, 0, 1, comm); } else { /* Processor 0 does all the rest */ gpart = imalloc(vtxdist[npes], "ComputeRealCut: gpart"); icopy(vtxdist[1], part, gpart); gmpart = imalloc(mvtxdist[npes], "ComputeRealCut: gmpart"); icopy(mvtxdist[1], mpart, gmpart); for (i=1; i<npes; i++) { gkMPI_Recv((void *)(gpart+vtxdist[i]), vtxdist[i+1]-vtxdist[i], IDX_T, i, 1, comm, &status); gkMPI_Recv((void *)(gmpart+mvtxdist[i]), mvtxdist[i+1]-mvtxdist[i], IDX_T, i, 1, comm, &status); } /* OK, now go and reconstruct the permutation to go from the graph to mgraph */ perm = imalloc(vtxdist[npes], "ComputeRealCut: perm"); sizes = ismalloc(npes+1, 0, "ComputeRealCut: sizes"); for (i=0; i<vtxdist[npes]; i++) sizes[gpart[i]]++; MAKECSR(i, npes, sizes); for (i=0; i<vtxdist[npes]; i++) perm[i] = sizes[gpart[i]]++; /* Ok, now read the graph from the file */ ReadMetisGraph(filename, &nvtxs, &xadj, &adjncy); /* OK, now compute the cut */ for (cut=0, i=0; i<nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) { if (gmpart[perm[i]] != gmpart[perm[adjncy[j]]]) cut++; } } cut = cut/2; gk_free((void **)&gpart, &gmpart, &perm, &sizes, &xadj, &adjncy, LTERM); return cut; } return 0; }
void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, ii, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs, qnum; idx_t *bestwhere, *where, *perm, *counts; idx_t *vwgt; WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; vwgt = graph->vwgt; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); counts = iwspacemalloc(ctrl, ncon); for (inbfs=0; inbfs<2*niparts; inbfs++) { irandArrayPermute(nvtxs, perm, nvtxs/2, 1); iset(ncon, 0, counts); /* partition by spliting the queues randomly */ for (ii=0; ii<nvtxs; ii++) { i = perm[ii]; qnum = iargmax(ncon, vwgt+i*ncon); where[i] = (counts[qnum]++)%2; } Compute2WayPartitionParams(ctrl, graph); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); if (inbfs == 0 || bestcut >= graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; }
void Grid::RemovePrisms(){ int i=0,j; int vertextoremove; int vertextouse; int vertexa, vertexb; do{ if(nverts[i] == 6){ #if 0 vertexa = vertids[i][0]; vertexb = vertids[i][3]; vertextoremove = min(vertexa, vertexb); vertextouse = max(vertexa, vertexb); for(j=0;j<Max_Nverts*nel;++j) vertids[0][j] = (vertids[0][j] == vertextoremove) ? vertextouse: vertids[0][j]; vertexa = vertids[i][1]; vertexb = vertids[i][2]; vertextoremove = min(vertexa, vertexb); vertextouse = max(vertexa, vertexb); for(j=0;j<Max_Nverts*nel;++j) vertids[0][j] = (vertids[0][j] == vertextoremove) ? vertextouse: vertids[0][j]; vertexa = vertids[i][4]; vertexb = vertids[i][5]; vertextoremove = min(vertexa, vertexb); vertextouse = max(vertexa, vertexb); for(j=0;j<Max_Nverts*nel;++j) vertids[0][j] = (vertids[0][j] == vertextoremove) ? vertextouse: vertids[0][j]; #endif icopy(nel-i-1, elmtids+i+1, 1, elmtids+i, 1); icopy(nel-i-1, nverts+i+1, 1, nverts+i, 1); icopy((nel-i-1)*Max_Nverts, vertids[i]+Max_Nverts, 1, vertids[i], 1); icopy((nel-i-1)*Max_Nverts, vertexmap[i]+Max_Nverts, 1, vertexmap[i], 1); --nel; } else ++i; } while(i<nel); }
void Grid::RemoveHexes(){ int i=0; do{ if(nverts[i] == 8){ icopy(nel-i-1, elmtids+i+1, 1, elmtids+i, 1); icopy(nel-i-1, nverts+i+1, 1, nverts+i, 1); icopy((nel-i-1)*Max_Nverts, vertids[i]+Max_Nverts, 1, vertids[i], 1); --nel; } else ++i; } while(i<nel); }
// shadow under stones void ImageHandler::paintShadowStone (QImage &si, int d) { //const double pixel=0.8,shadow=0.99; // these are the images int i, j, k; double di, dj, d2=(double)d/2.0-5e-1, r=d2-2e-1; double hh; k=0; bool smallerstones = false; if (smallerstones) r-=1; for (i=0; i<d; i++) for (j=0; j<d; j++) { di=i-d2; dj=j-d2; hh=r-sqrt(di*di+dj*dj); if (hh>=0) { hh=2*hh/r ; if (hh> 1) hh=1; painting_buffer[k]=((int)(255*hh)<<24)|(1<<16)|(1<<8)|(1); } else painting_buffer[k]=0; k++; } // now copy the result in QImages icopy(painting_buffer, si, d, d); }
INLINE GEN icopy_sign(GEN x, long sx) { GEN y=icopy(x); setsigne(y,sx); return y; }
void Grid::ImportTetOrientation(Grid *fromgrid){ int i,j; int lid; for(i=0;i<fromgrid->nel;++i){ lid = fromgrid->elmtids[i]; icopy(4, fromgrid->vertexmap[i], 1, vertexmap[lid], 1); } }
static Field *sortHeaders(Field *fld, int nfld){ register int i; Field *fout; int cnt,*size,*emap,*nfacet; fout = (Field *)calloc(1,sizeof(Field)); memcpy(fout,fld,sizeof(Field)); cnt = 0; for(i = 0; i < nfld; ++i) if((fld+i != ((Field* ) NULL))) // if(fld[i]) cnt += fld[i].nel; fout->nel = cnt; emap = fout->emap = ivector(0,fout->nel-1); nfacet = fout->nfacet = ivector(0,fout->nel-1); for(i = 0,cnt = 0; i < nfld; ++i){ if((fld+i != ((Field* ) NULL))){ icopy(fld[i].nel,fld[i].nfacet,1,nfacet,1); icopy(fld[i].nel,fld[i].emap, 1,emap,1); emap += fld[i].nel; nfacet += fld[i].nel; cnt += isum(fld[i].nel,fld[i].nfacet,1); } } size = fout->size = ivector(0,cnt-1); for(i = 0,cnt = 0; i < nfld; ++i){ if((fld+i != ((Field* ) NULL))){ cnt = isum(fld[i].nel,fld[i].nfacet,1); icopy(cnt,fld[i].size,1,size,1); size += cnt; } } for(i = 0,cnt = 0; i < nfld; ++i){ if((fld+i != ((Field* ) NULL))) cnt += fld[i].nel; } return fout; }
void MlevelNodeBisectionL2(ctrl_t *ctrl, graph_t *graph, idx_t niparts) { idx_t i, mincut, nruns=5; graph_t *cgraph; idx_t *bestwhere; /* if the graph is small, just find a single vertex separator */ if (graph->nvtxs < 5000) { MlevelNodeBisectionL1(ctrl, graph, niparts); return; } WCOREPUSH; ctrl->CoarsenTo = gk_max(100, graph->nvtxs/30); cgraph = CoarsenGraphNlevels(ctrl, graph, 4); bestwhere = iwspacemalloc(ctrl, cgraph->nvtxs); mincut = graph->tvwgt[0]; for (i=0; i<nruns; i++) { MlevelNodeBisectionL1(ctrl, cgraph, 0.7*niparts); if (i == 0 || cgraph->mincut < mincut) { mincut = cgraph->mincut; if (i < nruns-1) icopy(cgraph->nvtxs, cgraph->where, bestwhere); } if (mincut == 0) break; if (i < nruns-1) FreeRData(cgraph); } if (mincut != cgraph->mincut) icopy(cgraph->nvtxs, bestwhere, cgraph->where); WCOREPOP; Refine2WayNode(ctrl, graph, cgraph); }
void Grid::ImportPrismOrientation(Grid *fromgrid){ int i,j; int lid; for(i=0;i<fromgrid->nel;++i){ if(fromgrid->nverts[i] == 6){ lid = fromgrid->elmtids[i]; icopy(6, fromgrid->vertexmap[i], 1, vertexmap[lid], 1); } } }
void gimax (int *x, int n, int *work) { register int i; MPI_Allreduce (x, work, n, MPI_INT, MPI_MAX, MPI_COMM_WORLD); /* *x = *work; */ icopy(n,work,1,x,1); return; }
void Grid::FixPrismOrientation(){ int i, j, k, tmp; int *lid = ivector(0, 6-1); int *gid = ivector(0, 6-1); for(i=0;i<nel;++i){ if(nverts[i] == 6){ icopy(6, vertids[i], 1, gid, 1); for(j=0;j<6;++j) lid[j] = j; // order the local ids (maximum global id first) for(k=1;k<6;++k){ if(gid[0]<gid[k]){ tmp = gid[k]; gid[k] = gid[0]; gid[0] = tmp; tmp = lid[k]; lid[k] = lid[0]; lid[0] = tmp; } } // we now know that the local id of the maximum global id is in lid[0] if(lid[0] == 4 || lid[0] == 5){ // nothing to do } else if(lid[0] == 1 || lid[0] == 2){ // must rotate around clockwise vertexmap[i][0] = 4; vertexmap[i][1] = 0; vertexmap[i][2] = 3; vertexmap[i][3] = 5; vertexmap[i][4] = 1; vertexmap[i][5] = 2; } else if(lid[0] == 0 || lid[0] == 3){ // must rotate around clockwise vertexmap[i][0] = 1; vertexmap[i][1] = 4; vertexmap[i][2] = 5; vertexmap[i][3] = 2; vertexmap[i][4] = 0; vertexmap[i][5] = 3; } } } free(lid); free(gid); }
void InitKWayPartitioningGrow(ctrl_t *ctrl, graph_t *graph) { idx_t ntrials, curobj=0, bestobj=0; idx_t *bestwhere=NULL; WCOREPUSH; bestwhere = iwspacemalloc(ctrl, graph->nvtxs); for (ntrials=0; ntrials<ctrl->nIparts; ntrials++) { GrowKWayPartitioning(ctrl, graph); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: curobj = graph->mincut; break; case METIS_OBJTYPE_VOL: curobj = graph->minvol; break; default: gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); } printf(" Ipart.%"PRIDX" curobj: %"PRIDX"\n", ntrials, curobj); if (ntrials == 0 || bestobj > curobj) { icopy(graph->nvtxs, graph->where, bestwhere); bestobj = curobj; } } if (bestobj != curobj) icopy(graph->nvtxs, bestwhere, graph->where); printf(" Ipart Select bestobj: %"PRIDX"\n", bestobj); WCOREPOP; }
void Grid::FixTetOrientation(){ int i,j,k, tmp; // max vertex becomes top int *lid = ivector(0, 4-1); int *gid = ivector(0, 4-1); for(i=0;i<nel;++i){ icopy(4, vertids[i], 1, gid, 1); for(j=0;j<4;++j) lid[j] = j; // order the local ids (minimum global id first) for(j=0;j<4;++j) for(k=j+1;k<4;++k){ if(gid[j]>gid[k]){ tmp = gid[k]; gid[k] = gid[j]; gid[j] = tmp; tmp = lid[k]; lid[k] = lid[j]; lid[j] = tmp; } } if(checktetvolume(gid, xcoords, ycoords, zcoords) < 0){ tmp = lid[0]; lid[0] = lid[1]; lid[1] = tmp; } icopy(4, lid, 1, vertexmap[i], 1); } free(lid); free(gid); }
void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs; idx_t *bestwhere, *where; WCOREPUSH; nvtxs = graph->nvtxs; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); for (inbfs=0; inbfs<2*niparts; inbfs++) { iset(nvtxs, 1, where); where[irandInRange(nvtxs)] = 0; Compute2WayPartitionParams(ctrl, graph); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); if (inbfs == 0 || bestcut >= graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; }
void MlevelNodeBisectionMultiple(ctrl_t *ctrl, graph_t *graph) { idx_t i, mincut; idx_t *bestwhere; /* if the graph is small, just find a single vertex separator */ if (ctrl->nseps == 1 || graph->nvtxs < (ctrl->compress ? 1000 : 2000)) { MlevelNodeBisectionL2(ctrl, graph, LARGENIPARTS); return; } WCOREPUSH; bestwhere = iwspacemalloc(ctrl, graph->nvtxs); mincut = graph->tvwgt[0]; for (i=0; i<ctrl->nseps; i++) { MlevelNodeBisectionL2(ctrl, graph, LARGENIPARTS); if (i == 0 || graph->mincut < mincut) { mincut = graph->mincut; if (i < ctrl->nseps-1) icopy(graph->nvtxs, graph->where, bestwhere); } if (mincut == 0) break; if (i < ctrl->nseps-1) FreeRData(graph); } if (mincut != graph->mincut) { icopy(graph->nvtxs, bestwhere, graph->where); Compute2WayNodePartitionParams(ctrl, graph); } WCOREPOP; }
idx_t ComputeRealCut(idx_t *vtxdist, idx_t *part, char *filename, MPI_Comm comm) { idx_t i, j, nvtxs, mype, npes, cut; idx_t *xadj, *adjncy, *gpart; MPI_Status status; gkMPI_Comm_size(comm, &npes); gkMPI_Comm_rank(comm, &mype); if (mype != 0) { gkMPI_Send((void *)part, vtxdist[mype+1]-vtxdist[mype], IDX_T, 0, 1, comm); } else { /* Processor 0 does all the rest */ gpart = imalloc(vtxdist[npes], "ComputeRealCut: gpart"); icopy(vtxdist[1], part, gpart); for (i=1; i<npes; i++) gkMPI_Recv((void *)(gpart+vtxdist[i]), vtxdist[i+1]-vtxdist[i], IDX_T, i, 1, comm, &status); ReadMetisGraph(filename, &nvtxs, &xadj, &adjncy); /* OK, now compute the cut */ for (cut=0, i=0; i<nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) { if (gpart[i] != gpart[adjncy[j]]) cut++; } } cut = cut/2; gk_free((void **)&gpart, &xadj, &adjncy, LTERM); return cut; } return 0; }
void InitKWayPartitioningRB(ctrl_t *ctrl, graph_t *graph) { idx_t i, options[METIS_NOPTIONS], curobj=0; idx_t *bestwhere=NULL; real_t *ubvec=NULL; int status; METIS_SetDefaultOptions(options); options[METIS_OPTION_NITER] = 10; options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; options[METIS_OPTION_NO2HOP] = ctrl->no2hop; options[METIS_OPTION_ONDISK] = ctrl->ondisk; ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec"); for (i=0; i<graph->ncon; i++) ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts)); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: case METIS_OBJTYPE_VOL: options[METIS_OPTION_NCUTS] = ctrl->nIparts; status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); break; #ifdef XXX /* This does not seem to help */ case METIS_OBJTYPE_VOL: bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere"); options[METIS_OPTION_NCUTS] = 2; ntrials = (ctrl->nIparts+1)/2; for (i=0; i<ntrials; i++) { status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); curobj = ComputeVolume(graph, graph->where); if (i == 0 || bestobj > curobj) { bestobj = curobj; if (i < ntrials-1) icopy(graph->nvtxs, graph->where, bestwhere); } if (bestobj == 0) break; } if (bestobj != curobj) icopy(graph->nvtxs, bestwhere, graph->where); break; #endif default: gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); } gk_free((void **)&ubvec, &bestwhere, LTERM); }
idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part) { idx_t i, objval=0, curobj=0, bestobj=0; real_t curbal=0.0, bestbal=0.0; graph_t *cgraph; for (i=0; i<ctrl->ncuts; i++) { cgraph = CoarsenGraph(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startwctimer(ctrl->InitPartTmr)); AllocateKWayPartitionMemory(ctrl, cgraph); /* Compute the initial partitioning */ switch (ctrl->iptype) { case METIS_IPTYPE_METISRB: FreeWorkSpace(ctrl); /* Release the work space, for the recursive metis call */ InitKWayPartitioningRB(ctrl, cgraph); AllocateWorkSpace(ctrl, graph); /* Re-allocate the work space */ break; case METIS_IPTYPE_GROW: AllocateRefinementWorkSpace(ctrl, 2*cgraph->nedges); InitKWayPartitioningGrow(ctrl, cgraph); break; default: gk_errexit(SIGERR, "Unknown iptype: %d\n", ctrl->iptype); } IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopwctimer(ctrl->InitPartTmr)); IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial %"PRIDX \ "-way partitioning cut: %"PRIDX"\n", ctrl->nparts, objval)); RefineKWay(ctrl, graph, cgraph); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: curobj = graph->mincut; break; case METIS_OBJTYPE_VOL: curobj = graph->minvol; break; default: gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); } curbal = ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors); if (i == 0 || (curbal <= 0.0005 && bestobj > curobj) || (bestbal > 0.0005 && curbal < bestbal)) { icopy(graph->nvtxs, graph->where, part); bestobj = curobj; bestbal = curbal; } FreeRData(graph); if (bestobj == 0) break; } FreeGraph(&graph); return bestobj; }
int METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *perm, idx_t *iperm) { int sigrval=0, renumber=0; idx_t i, ii, j, l, nnvtxs=0; graph_t *graph=NULL; ctrl_t *ctrl; idx_t *cptr, *cind, *piperm; int numflag = 0; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* set up the run time parameters */ ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL); if (!ctrl) { gk_siguntrap(); return METIS_ERROR_INPUT; } /* if required, change the numbering to 0 */ if (ctrl->numflag == 1) { Change2CNumbering(*nvtxs, xadj, adjncy); renumber = 1; } IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); /* prune the dense columns */ if (ctrl->pfactor > 0.0) { piperm = imalloc(*nvtxs, "OMETIS: piperm"); graph = PruneGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, piperm, ctrl->pfactor); if (graph == NULL) { /* if there was no prunning, cleanup the pfactor */ gk_free((void **)&piperm, LTERM); ctrl->pfactor = 0.0; } else { nnvtxs = graph->nvtxs; ctrl->compress = 0; /* disable compression if prunning took place */ } } /* compress the graph; note that compression only happens if not prunning has taken place. */ if (ctrl->compress) { cptr = imalloc(*nvtxs+1, "OMETIS: cptr"); cind = imalloc(*nvtxs, "OMETIS: cind"); graph = CompressGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, cptr, cind); if (graph == NULL) { /* if there was no compression, cleanup the compress flag */ gk_free((void **)&cptr, &cind, LTERM); ctrl->compress = 0; } else { nnvtxs = graph->nvtxs; ctrl->cfactor = 1.0*(*nvtxs)/nnvtxs; if (ctrl->cfactor > 1.5 && ctrl->nseps == 1) ctrl->nseps = 2; //ctrl->nseps = (idx_t)(ctrl->cfactor*ctrl->nseps); } } /* if no prunning and no compression, setup the graph in the normal way. */ if (ctrl->pfactor == 0.0 && ctrl->compress == 0) graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); ASSERT(CheckGraph(graph, ctrl->numflag, 1)); /* allocate workspace memory */ AllocateWorkSpace(ctrl, graph); /* do the nested dissection ordering */ if (ctrl->ccorder) MlevelNestedDissectionCC(ctrl, graph, iperm, graph->nvtxs); else MlevelNestedDissection(ctrl, graph, iperm, graph->nvtxs); if (ctrl->pfactor > 0.0) { /* Order any prunned vertices */ icopy(nnvtxs, iperm, perm); /* Use perm as an auxiliary array */ for (i=0; i<nnvtxs; i++) iperm[piperm[i]] = perm[i]; for (i=nnvtxs; i<*nvtxs; i++) iperm[piperm[i]] = i; gk_free((void **)&piperm, LTERM); } else if (ctrl->compress) { /* Uncompress the ordering */ /* construct perm from iperm */ for (i=0; i<nnvtxs; i++) perm[iperm[i]] = i; for (l=ii=0; ii<nnvtxs; ii++) { i = perm[ii]; for (j=cptr[i]; j<cptr[i+1]; j++) iperm[cind[j]] = l++; } gk_free((void **)&cptr, &cind, LTERM); } for (i=0; i<*nvtxs; i++) perm[iperm[i]] = i; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); /* clean up */ FreeCtrl(&ctrl); SIGTHROW: /* if required, change the numbering back to 1 */ if (renumber) Change2FNumberingOrder(*nvtxs, xadj, adjncy, perm, iperm); gk_siguntrap(); gk_malloc_cleanup(0); return metis_rcode(sigrval); }
GEN bezout(GEN a, GEN b, GEN *pu, GEN *pv) { GEN t,u,u1,v,v1,d,d1,q,r; GEN *pt; pari_sp av, av1; long s, sa, sb; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ s = abscmpii(a,b); if (s < 0) { t=b; b=a; a=t; pt=pu; pu=pv; pv=pt; } /* now |a| >= |b| */ sa = signe(a); sb = signe(b); if (!sb) { if (pv) *pv = gen_0; switch(sa) { case 0: if (pu) *pu = gen_0; return gen_0; case 1: if (pu) *pu = gen_1; return icopy(a); case -1: if (pu) *pu = gen_m1; return(negi(a)); } } if (s == 0) /* |a| == |b| != 0 */ { if (pu) *pu = gen_0; if (sb > 0) { if (pv) *pv = gen_1; return icopy(b); } else { if (pv) *pv = gen_m1; return(negi(b)); } } /* now |a| > |b| > 0 */ if (lgefint(a) == 3) /* single-word affair */ { g = xxgcduu(uel(a,2), uel(b,2), 0, &xu, &xu1, &xv, &xv1, &s); sa = s > 0 ? sa : -sa; sb = s > 0 ? -sb : sb; if (pu) { if (xu == 0) *pu = gen_0; /* can happen when b divides a */ else if (xu == 1) *pu = sa < 0 ? gen_m1 : gen_1; else if (xu == 2) *pu = sa < 0 ? gen_m2 : gen_2; else { *pu = cgeti(3); (*pu)[1] = evalsigne(sa)|evallgefint(3); (*pu)[2] = xu; } } if (pv) { if (xv == 1) *pv = sb < 0 ? gen_m1 : gen_1; else if (xv == 2) *pv = sb < 0 ? gen_m2 : gen_2; else { *pv = cgeti(3); (*pv)[1] = evalsigne(sb)|evallgefint(3); (*pv)[2] = xv; } } if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } /* general case */ av = avma; (void)new_chunk(lgefint(b) + (lgefint(a)<<1)); /* room for u,v,gcd */ /* if a is significantly larger than b, calling lgcdii() is not the best * way to start -- reduce a mod b first */ if (lgefint(a) > lgefint(b)) { d = absi(b), q = dvmdii(absi(a), d, &d1); if (!signe(d1)) /* a == qb */ { avma = av; if (pu) *pu = gen_0; if (pv) *pv = sb < 0 ? gen_m1 : gen_1; return (icopy(d)); } else { u = gen_0; u1 = v = gen_1; v1 = negi(q); } /* if this results in lgefint(d) == 3, will fall past main loop */ } else { d = absi(a); d1 = absi(b); u = v1 = gen_1; u1 = v = gen_0; } av1 = avma; /* main loop is almost identical to that of invmod() */ while (lgefint(d) > 3 && signe(d1)) { lhmres = lgcdii((ulong *)d, (ulong *)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX); if (lhmres != 0) /* check progress */ { /* apply matrix */ if ((lhmres == 1) || (lhmres == -1)) { if (xv1 == 1) { r = subii(d,d1); d=d1; d1=r; a = subii(u,u1); u=u1; u1=a; a = subii(v,v1); v=v1; v1=a; } else { r = subii(d, mului(xv1,d1)); d=d1; d1=r; a = subii(u, mului(xv1,u1)); u=u1; u1=a; a = subii(v, mului(xv1,v1)); v=v1; v1=a; } } else { r = subii(muliu(d,xu), muliu(d1,xv)); d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r; a = subii(muliu(u,xu), muliu(u1,xv)); u1 = subii(muliu(u,xu1), muliu(u1,xv1)); u = a; a = subii(muliu(v,xu), muliu(v1,xv)); v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a; if (lhmres&1) { togglesign(d); togglesign(u); togglesign(v); } else { togglesign(d1); togglesign(u1); togglesign(v1); } } } if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); a = subii(u,mulii(q,u1)); u=u1; u1=a; a = subii(v,mulii(q,v1)); v=v1; v1=a; d=d1; d1=r; } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"bezout"); gerepileall(av1,6, &d,&d1,&u,&u1,&v,&v1); } } /* end while */ /* Postprocessing - final sprint */ if (signe(d1)) { /* Assertions: lgefint(d)==lgefint(d1)==3, and * gcd(d,d1) is nonzero and fits into one word */ g = xxgcduu(uel(d,2), uel(d1,2), 0, &xu, &xu1, &xv, &xv1, &s); u = subii(muliu(u,xu), muliu(u1, xv)); v = subii(muliu(v,xu), muliu(v1, xv)); if (s < 0) { sa = -sa; sb = -sb; } avma = av; if (pu) *pu = sa < 0 ? negi(u) : icopy(u); if (pv) *pv = sb < 0 ? negi(v) : icopy(v); if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } /* get here when the final sprint was skipped (d1 was zero already). * Now the matrix is final, and d contains the gcd. */ avma = av; if (pu) *pu = sa < 0 ? negi(u) : icopy(u); if (pv) *pv = sb < 0 ? negi(v) : icopy(v); return icopy(d); }
void EliminateComponents(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, jj, k, me, nparts, nvtxs, ncon, ncmps, other, ncand, target; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts; idx_t *cptr, *cind, *cpvec, *pcptr, *pcind, *cwhere; idx_t cid, bestcid, *cwgt, *bestcwgt; idx_t ntodo, oldntodo, *todo; rkv_t *cand; real_t *tpwgts; idx_t *vmarker = NULL, *pmarker = NULL, *modind = NULL; /* volume specific work arrays */ WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt); where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; tpwgts = ctrl->tpwgts; cptr = iwspacemalloc(ctrl, nvtxs + 1); cind = iwspacemalloc(ctrl, nvtxs); ncmps = FindPartitionInducedComponents(graph, where, cptr, cind); IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("I found %"PRIDX" components, for this %"PRIDX"-way partition\n", ncmps, nparts)); /* There are more components than partitions */ if (ncmps > nparts) { cwgt = iwspacemalloc(ctrl, ncon); bestcwgt = iwspacemalloc(ctrl, ncon); cpvec = iwspacemalloc(ctrl, nparts); pcptr = iset(nparts + 1, 0, iwspacemalloc(ctrl, nparts + 1)); pcind = iwspacemalloc(ctrl, ncmps); cwhere = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); todo = iwspacemalloc(ctrl, ncmps); cand = (rkv_t *) wspacemalloc(ctrl, nparts * sizeof(rkv_t)); if (ctrl->objtype == METIS_OBJTYPE_VOL) { /* Vol-refinement specific working arrays */ modind = iwspacemalloc(ctrl, nvtxs); vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); } /* Get a CSR representation of the components-2-partitions mapping */ for (i = 0; i < ncmps; i++) { pcptr[where[cind[cptr[i]]]]++; } MAKECSR(i, nparts, pcptr); for (i = 0; i < ncmps; i++) { pcind[pcptr[where[cind[cptr[i]]]]++] = i; } SHIFTCSR(i, nparts, pcptr); /* Assign the heaviest component of each partition to its original partition */ for (ntodo = 0, i = 0; i < nparts; i++) { if (pcptr[i + 1] - pcptr[i] == 1) { bestcid = pcind[pcptr[i]]; } else { for (bestcid = -1, j = pcptr[i]; j < pcptr[i + 1]; j++) { cid = pcind[j]; iset(ncon, 0, cwgt); for (ii = cptr[cid]; ii < cptr[cid + 1]; ii++) { iaxpy(ncon, 1, vwgt + cind[ii] * ncon, 1, cwgt, 1); } if (bestcid == -1 || isum(ncon, bestcwgt, 1) < isum(ncon, cwgt, 1)) { bestcid = cid; icopy(ncon, cwgt, bestcwgt); } } /* Keep track of those that need to be dealt with */ for (j = pcptr[i]; j < pcptr[i + 1]; j++) { if (pcind[j] != bestcid) { todo[ntodo++] = pcind[j]; } } } for (j = cptr[bestcid]; j < cptr[bestcid + 1]; j++) { ASSERT(where[cind[j]] == i); cwhere[cind[j]] = i; } } while (ntodo > 0) { oldntodo = ntodo; for (i = 0; i < ntodo; i++) { cid = todo[i]; me = where[cind[cptr[cid]]]; /* Get the domain of this component */ /* Determine the weight of the block to be moved */ iset(ncon, 0, cwgt); for (j = cptr[cid]; j < cptr[cid + 1]; j++) { iaxpy(ncon, 1, vwgt + cind[j] * ncon, 1, cwgt, 1); } IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("Trying to move %"PRIDX" [%"PRIDX"] from %"PRIDX"\n", cid, isum(ncon, cwgt, 1), me)); /* Determine the connectivity */ iset(nparts, 0, cpvec); for (j = cptr[cid]; j < cptr[cid + 1]; j++) { ii = cind[j]; for (jj = xadj[ii]; jj < xadj[ii + 1]; jj++) { if (cwhere[adjncy[jj]] != -1) { cpvec[cwhere[adjncy[jj]]] += (adjwgt ? adjwgt[jj] : 1); } } } /* Put the neighbors into a cand[] array for sorting */ for (ncand = 0, j = 0; j < nparts; j++) { if (cpvec[j] > 0) { cand[ncand].key = cpvec[j]; cand[ncand++].val = j; } } if (ncand == 0) { continue; } rkvsortd(ncand, cand); /* Limit the moves to only the top candidates, which are defined as those with connectivity at least 50% of the best. This applies only when ncon=1, as for multi-constraint, balancing will be hard. */ if (ncon == 1) { for (j = 1; j < ncand; j++) { if (cand[j].key < .5 * cand[0].key) { break; } } ncand = j; } /* Now among those, select the one with the best balance */ target = cand[0].val; for (j = 1; j < ncand; j++) { if (BetterBalanceKWay(ncon, cwgt, ctrl->ubfactors, 1, pwgts + target * ncon, ctrl->pijbm + target * ncon, 1, pwgts + cand[j].val * ncon, ctrl->pijbm + cand[j].val * ncon)) { target = cand[j].val; } } IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("\tMoving it to %"PRIDX" [%"PRIDX"] [%"PRIDX"]\n", target, cpvec[target], ncand)); /* Note that as a result of a previous movement, a connected component may now will like to stay to its original partition */ if (target != me) { switch (ctrl->objtype) { case METIS_OBJTYPE_CUT:MoveGroupContigForCut(ctrl, graph, target, cid, cptr, cind); break; case METIS_OBJTYPE_VOL: MoveGroupContigForVol(ctrl, graph, target, cid, cptr, cind, vmarker, pmarker, modind); break; default:gk_errexit(SIGERR, "Unknown objtype %d\n", ctrl->objtype); } } /* Update the cwhere vector */ for (j = cptr[cid]; j < cptr[cid + 1]; j++) { cwhere[cind[j]] = target; } todo[i] = todo[--ntodo]; } if (oldntodo == ntodo) { IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("Stopped at ntodo: %"PRIDX"\n", ntodo)); break; } } for (i = 0; i < nvtxs; i++) { ASSERT(where[i] == cwhere[i]); } } WCOREPOP; }
/*********************************************************************************** * 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. ************************************************************************************/ int ParMETIS_V3_RefineKway(idx_t *vtxdist, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *adjwgt, idx_t *wgtflag, idx_t *numflag, idx_t *ncon, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part, MPI_Comm *comm) { idx_t npes, mype, status; ctrl_t *ctrl=NULL; graph_t *graph=NULL; size_t curmem; /* Check the input parameters and return if an error */ status = CheckInputsPartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ncon, nparts, tpwgts, ubvec, options, edgecut, part, comm); if (GlobalSEMinComm(*comm, status) == 0) return METIS_ERROR; status = METIS_OK; gk_malloc_init(); curmem = gk_GetCurMemoryUsed(); /* Setup ctrl */ ctrl = SetupCtrl(PARMETIS_OP_RMETIS, options, *ncon, *nparts, tpwgts, ubvec, *comm); npes = ctrl->npes; mype = ctrl->mype; /* Take care the nparts == 1 case */ if (*nparts == 1) { iset(vtxdist[mype+1]-vtxdist[mype], (*numflag == 0 ? 0 : 1), part); *edgecut = 0; goto DONE; } /* setup the graph */ if (*numflag > 0) ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 1); graph = SetupGraph(ctrl, *ncon, vtxdist, xadj, vwgt, NULL, adjncy, adjwgt, *wgtflag); if (ctrl->ps_relation == PARMETIS_PSR_COUPLED) iset(graph->nvtxs, mype, graph->home); else icopy(graph->nvtxs, part, graph->home); /* Allocate workspace */ AllocateWSpace(ctrl, 10*graph->nvtxs); /* Partition and Remap */ STARTTIMER(ctrl, ctrl->TotalTmr); ctrl->CoarsenTo = gk_min(vtxdist[npes]+1, 50*(*ncon)*gk_max(npes, *nparts)); Adaptive_Partition(ctrl, graph); ParallelReMapGraph(ctrl, graph); icopy(graph->nvtxs, graph->where, part); *edgecut = graph->mincut; STOPTIMER(ctrl, ctrl->TotalTmr); /* Take care of output */ IFSET(ctrl->dbglvl, DBG_TIME, PrintTimingInfo(ctrl)); IFSET(ctrl->dbglvl, DBG_TIME, gkMPI_Barrier(ctrl->gcomm)); IFSET(ctrl->dbglvl, DBG_INFO, PrintPostPartInfo(ctrl, graph, 1)); FreeInitialGraphAndRemap(graph); if (*numflag > 0) ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 0); DONE: FreeCtrl(&ctrl); if (gk_GetCurMemoryUsed() - curmem > 0) { printf("ParMETIS appears to have a memory leak of %zdbytes. Report this.\n", (ssize_t)(gk_GetCurMemoryUsed() - curmem)); } gk_malloc_cleanup(0); return (int)status; }
void ImageHandler::paintBlackStone (QImage &bi, int d, int stone_render) { const double pixel=0.8;//,shadow=0.99; bool Alias=true; // these are the images int i, j, g,g1,g2, k; double di, dj, d2=(double)d/2.0-5e-1, r=d2-2e-1, f=sqrt(3.0); double x, y, z, xr,xr1, xr2, xg1,xg2,hh; k=0; bool smallerstones = false; if (smallerstones) r-=1; for (i=0; i<d; i++) for (j=0; j<d; j++) { di=i-d2; dj=j-d2; hh=r-sqrt(di*di+dj*dj); if (hh>=0) { if (stone_render !=1) { z=r*r-di*di-dj*dj; if (z>0) z=sqrt(z)*f; else z=0; x=di; y=dj; xr=sqrt(6*(x*x+y*y+z*z)); xr1=(2*z-x+y)/xr; //xr2=(1.6*z+x+1.75*y)/xr; xr2=(2*z+x-y)/xr; if (xr1>0.9) xg1=(xr1-0.9)*10; else xg1=0; //if (xr2>1) xg2=(xr2-1)*10; if (xr2>0.96) xg2=(xr2-0.96)*10; else xg2=0; //random = drand48(); g1=(int)(5+10*drand48() + 10*xr1 + xg1*140); g2=(int)(10+10* xr2+xg2*160); g=(g1 > g2 ? g1 : g2); //g=(int)1/ (1/g1 + 1/g2); if (hh>pixel || !Alias) { painting_buffer[k]=(255<<24)|(g<<16)|(g<<8)|g; } else { painting_buffer[k]=((int)(hh/pixel*255)<<24)|(g<<16)|(g<<8)|g; } } else //code for flat stones { g=0; painting_buffer[k]=((int)(255)<<24)|(g<<16)|(g<<8)|g; } } else painting_buffer[k]=0; k++; } // now copy the result in QImages icopy(painting_buffer, bi, d, d); }
/************************************************************************* * This function is the entry point of the initial partition algorithm * that does recursive bissection. * This algorithm assembles the graph to all the processors and preceeds * by parallelizing the recursive bisection step. **************************************************************************/ void InitPartition(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, ncon, mype, npes, gnvtxs, ngroups; idx_t *xadj, *adjncy, *adjwgt, *vwgt; idx_t *part, *gwhere0, *gwhere1; idx_t *tmpwhere, *tmpvwgt, *tmpxadj, *tmpadjncy, *tmpadjwgt; graph_t *agraph; idx_t lnparts, fpart, fpe, lnpes; idx_t twoparts=2, moptions[METIS_NOPTIONS], edgecut, max_cut; real_t *tpwgts, *tpwgts2, *lbvec, lbsum, min_lbsum, wsum; MPI_Comm ipcomm; struct { double sum; int rank; } lpesum, gpesum; WCOREPUSH; ncon = graph->ncon; ngroups = gk_max(gk_min(RIP_SPLIT_FACTOR, ctrl->npes), 1); IFSET(ctrl->dbglvl, DBG_TIME, gkMPI_Barrier(ctrl->comm)); IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->InitPartTmr)); lbvec = rwspacemalloc(ctrl, ncon); /* assemble the graph to all the processors */ agraph = AssembleAdaptiveGraph(ctrl, graph); gnvtxs = agraph->nvtxs; /* make a copy of the graph's structure for later */ xadj = icopy(gnvtxs+1, agraph->xadj, iwspacemalloc(ctrl, gnvtxs+1)); vwgt = icopy(gnvtxs*ncon, agraph->vwgt, iwspacemalloc(ctrl, gnvtxs*ncon)); adjncy = icopy(agraph->nedges, agraph->adjncy, iwspacemalloc(ctrl, agraph->nedges)); adjwgt = icopy(agraph->nedges, agraph->adjwgt, iwspacemalloc(ctrl, agraph->nedges)); part = iwspacemalloc(ctrl, gnvtxs); /* create different processor groups */ gkMPI_Comm_split(ctrl->gcomm, ctrl->mype % ngroups, 0, &ipcomm); gkMPI_Comm_rank(ipcomm, &mype); gkMPI_Comm_size(ipcomm, &npes); /* Go into the recursive bisection */ METIS_SetDefaultOptions(moptions); moptions[METIS_OPTION_SEED] = ctrl->sync + (ctrl->mype % ngroups) + 1; tpwgts = ctrl->tpwgts; tpwgts2 = rwspacemalloc(ctrl, 2*ncon); lnparts = ctrl->nparts; fpart = fpe = 0; lnpes = npes; while (lnpes > 1 && lnparts > 1) { /* determine the weights of the two partitions as a function of the weight of the target partition weights */ for (j=(lnparts>>1), i=0; i<ncon; i++) { tpwgts2[i] = rsum(j, tpwgts+fpart*ncon+i, ncon); tpwgts2[ncon+i] = rsum(lnparts-j, tpwgts+(fpart+j)*ncon+i, ncon); wsum = 1.0/(tpwgts2[i] + tpwgts2[ncon+i]); tpwgts2[i] *= wsum; tpwgts2[ncon+i] *= wsum; } METIS_PartGraphRecursive(&agraph->nvtxs, &ncon, agraph->xadj, agraph->adjncy, agraph->vwgt, NULL, agraph->adjwgt, &twoparts, tpwgts2, NULL, moptions, &edgecut, part); /* pick one of the branches */ if (mype < fpe+lnpes/2) { KeepPart(ctrl, agraph, part, 0); lnpes = lnpes/2; lnparts = lnparts/2; } else { KeepPart(ctrl, agraph, part, 1); fpart = fpart + lnparts/2; fpe = fpe + lnpes/2; lnpes = lnpes - lnpes/2; lnparts = lnparts - lnparts/2; } } gwhere0 = iset(gnvtxs, 0, iwspacemalloc(ctrl, gnvtxs)); gwhere1 = iwspacemalloc(ctrl, gnvtxs); if (lnparts == 1) { /* Case npes is greater than or equal to nparts */ /* Only the first process will assign labels (for the reduction to work) */ if (mype == fpe) { for (i=0; i<agraph->nvtxs; i++) gwhere0[agraph->label[i]] = fpart; } } else { /* Case in which npes is smaller than nparts */ /* create the normalized tpwgts for the lnparts from ctrl->tpwgts */ tpwgts = rwspacemalloc(ctrl, lnparts*ncon); for (j=0; j<ncon; j++) { for (wsum=0.0, i=0; i<lnparts; i++) { tpwgts[i*ncon+j] = ctrl->tpwgts[(fpart+i)*ncon+j]; wsum += tpwgts[i*ncon+j]; } for (wsum=1.0/wsum, i=0; i<lnparts; i++) tpwgts[i*ncon+j] *= wsum; } METIS_PartGraphKway(&agraph->nvtxs, &ncon, agraph->xadj, agraph->adjncy, agraph->vwgt, NULL, agraph->adjwgt, &lnparts, tpwgts, NULL, moptions, &edgecut, part); for (i=0; i<agraph->nvtxs; i++) gwhere0[agraph->label[i]] = fpart + part[i]; } gkMPI_Allreduce((void *)gwhere0, (void *)gwhere1, gnvtxs, IDX_T, MPI_SUM, ipcomm); if (ngroups > 1) { tmpxadj = agraph->xadj; tmpadjncy = agraph->adjncy; tmpadjwgt = agraph->adjwgt; tmpvwgt = agraph->vwgt; tmpwhere = agraph->where; agraph->xadj = xadj; agraph->adjncy = adjncy; agraph->adjwgt = adjwgt; agraph->vwgt = vwgt; agraph->where = gwhere1; agraph->vwgt = vwgt; agraph->nvtxs = gnvtxs; edgecut = ComputeSerialEdgeCut(agraph); ComputeSerialBalance(ctrl, agraph, gwhere1, lbvec); lbsum = rsum(ncon, lbvec, 1); gkMPI_Allreduce((void *)&edgecut, (void *)&max_cut, 1, IDX_T, MPI_MAX, ctrl->gcomm); gkMPI_Allreduce((void *)&lbsum, (void *)&min_lbsum, 1, REAL_T, MPI_MIN, ctrl->gcomm); lpesum.sum = lbsum; if (min_lbsum < UNBALANCE_FRACTION*ncon) { if (lbsum < UNBALANCE_FRACTION*ncon) lpesum.sum = edgecut; else lpesum.sum = max_cut; } lpesum.rank = ctrl->mype; gkMPI_Allreduce((void *)&lpesum, (void *)&gpesum, 1, MPI_DOUBLE_INT, MPI_MINLOC, ctrl->gcomm); gkMPI_Bcast((void *)gwhere1, gnvtxs, IDX_T, gpesum.rank, ctrl->gcomm); agraph->xadj = tmpxadj; agraph->adjncy = tmpadjncy; agraph->adjwgt = tmpadjwgt; agraph->vwgt = tmpvwgt; agraph->where = tmpwhere; } icopy(graph->nvtxs, gwhere1+graph->vtxdist[ctrl->mype], graph->where); FreeGraph(agraph); gkMPI_Comm_free(&ipcomm); IFSET(ctrl->dbglvl, DBG_TIME, gkMPI_Barrier(ctrl->comm)); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->InitPartTmr)); WCOREPOP; }
void TestParMetis_GPart(char *filename, char *xyzfile, MPI_Comm comm) { idx_t ncon, nparts, npes, mype, opt2, realcut; graph_t graph, mgraph; idx_t *part, *mpart, *savepart, *order, *sizes; idx_t numflag=0, wgtflag=0, options[10], edgecut, ndims; real_t ipc2redist, *xyz=NULL, *tpwgts = NULL, ubvec[MAXNCON]; gkMPI_Comm_size(comm, &npes); gkMPI_Comm_rank(comm, &mype); ParallelReadGraph(&graph, filename, comm); if (xyzfile) xyz = ReadTestCoordinates(&graph, xyzfile, &ndims, comm); gkMPI_Barrier(comm); part = imalloc(graph.nvtxs, "TestParMetis_V3: part"); tpwgts = rmalloc(MAXNCON*npes*2, "TestParMetis_V3: tpwgts"); rset(MAXNCON, 1.05, ubvec); graph.vwgt = ismalloc(graph.nvtxs*5, 1, "TestParMetis_GPart: vwgt"); /*====================================================================== / ParMETIS_V3_PartKway /=======================================================================*/ options[0] = 1; options[1] = 3; options[2] = 1; wgtflag = 2; numflag = 0; edgecut = 0; for (nparts=2*npes; nparts>=npes/2 && nparts > 0; nparts = nparts/2) { for (ncon=1; ncon<=NCON; ncon++) { if (ncon > 1 && nparts > 1) Mc_AdaptGraph(&graph, part, ncon, nparts, comm); else iset(graph.nvtxs, 1, graph.vwgt); if (mype == 0) printf("\nTesting ParMETIS_V3_PartKway with ncon: %"PRIDX", nparts: %"PRIDX"\n", ncon, nparts); rset(nparts*ncon, 1.0/(real_t)nparts, tpwgts); ParMETIS_V3_PartKway(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); realcut = ComputeRealCut(graph.vtxdist, part, filename, comm); if (mype == 0) { printf("ParMETIS_V3_PartKway reported a cut of %"PRIDX" [%s:%"PRIDX"]\n", edgecut, (edgecut == realcut ? "OK" : "ERROR"), realcut); } if (mype == 0) printf("\nTesting ParMETIS_V3_RefineKway with ncon: %"PRIDX", nparts: %"PRIDX"\n", ncon, nparts); options[3] = PARMETIS_PSR_UNCOUPLED; ParMETIS_V3_RefineKway(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); realcut = ComputeRealCut(graph.vtxdist, part, filename, comm); if (mype == 0) { printf("ParMETIS_V3_RefineKway reported a cut of %"PRIDX" [%s:%"PRIDX"]\n", edgecut, (edgecut == realcut ? "OK" : "ERROR"), realcut); } } } /*====================================================================== / ParMETIS_V3_PartGeomKway /=======================================================================*/ if (xyzfile != NULL) { options[0] = 1; options[1] = 3; options[2] = 1; wgtflag = 2; numflag = 0; for (nparts=2*npes; nparts>=npes/2 && nparts > 0; nparts = nparts/2) { for (ncon=1; ncon<=NCON; ncon++) { if (ncon > 1) Mc_AdaptGraph(&graph, part, ncon, nparts, comm); else iset(graph.nvtxs, 1, graph.vwgt); if (mype == 0) printf("\nTesting ParMETIS_V3_PartGeomKway with ncon: %"PRIDX", nparts: %"PRIDX"\n", ncon, nparts); rset(nparts*ncon, 1.0/(real_t)nparts, tpwgts); ParMETIS_V3_PartGeomKway(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, NULL, &wgtflag, &numflag, &ndims, xyz, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); realcut = ComputeRealCut(graph.vtxdist, part, filename, comm); if (mype == 0) printf("ParMETIS_V3_PartGeomKway reported a cut of %"PRIDX" [%s:%"PRIDX"]\n", edgecut, (edgecut == realcut ? "OK" : "ERROR"), realcut); } } } /*====================================================================== / ParMETIS_V3_PartGeom /=======================================================================*/ if (xyz != NULL) { wgtflag = 0; numflag = 0; if (mype == 0) printf("\nTesting ParMETIS_V3_PartGeom\n"); ParMETIS_V3_PartGeom(graph.vtxdist, &ndims, xyz, part, &comm); realcut = ComputeRealCut(graph.vtxdist, part, filename, comm); if (mype == 0) printf("ParMETIS_V3_PartGeom reported a cut of %"PRIDX"\n", realcut); } /*====================================================================== / Coupled ParMETIS_V3_RefineKway /=======================================================================*/ options[0] = 1; options[1] = 3; options[2] = 1; options[3] = PARMETIS_PSR_COUPLED; nparts = npes; wgtflag = 0; numflag = 0; ncon = 1; rset(nparts*ncon, 1.0/(real_t)nparts, tpwgts); if (mype == 0) printf("\nTesting coupled ParMETIS_V3_RefineKway with default options (before move)\n"); ParMETIS_V3_RefineKway(graph.vtxdist, graph.xadj, graph.adjncy, NULL, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); /* Compute a good partition and move the graph. Do so quietly! */ options[0] = 0; nparts = npes; wgtflag = 0; numflag = 0; ncon = 1; rset(nparts*ncon, 1.0/(real_t)nparts, tpwgts); ParMETIS_V3_PartKway(graph.vtxdist, graph.xadj, graph.adjncy, NULL, NULL, &wgtflag, &numflag, &ncon, &npes, tpwgts, ubvec, options, &edgecut, part, &comm); TestMoveGraph(&graph, &mgraph, part, comm); gk_free((void **)&(graph.vwgt), LTERM); mpart = ismalloc(mgraph.nvtxs, mype, "TestParMetis_V3: mpart"); savepart = imalloc(mgraph.nvtxs, "TestParMetis_V3: savepart"); /*====================================================================== / Coupled ParMETIS_V3_RefineKway /=======================================================================*/ options[0] = 1; options[1] = 3; options[2] = 1; options[3] = PARMETIS_PSR_COUPLED; nparts = npes; wgtflag = 0; numflag = 0; for (ncon=1; ncon<=NCON; ncon++) { if (mype == 0) printf("\nTesting coupled ParMETIS_V3_RefineKway with ncon: %"PRIDX", nparts: %"PRIDX"\n", ncon, nparts); rset(nparts*ncon, 1.0/(real_t)nparts, tpwgts); ParMETIS_V3_RefineKway(mgraph.vtxdist, mgraph.xadj, mgraph.adjncy, NULL, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, mpart, &comm); realcut = ComputeRealCutFromMoved(graph.vtxdist, mgraph.vtxdist, part, mpart, filename, comm); if (mype == 0) printf("ParMETIS_V3_RefineKway reported a cut of %"PRIDX" [%s:%"PRIDX"]\n", edgecut, (edgecut == realcut ? "OK" : "ERROR"), realcut); } /*ADAPTIVE:*/ /*====================================================================== / ParMETIS_V3_AdaptiveRepart /=======================================================================*/ mgraph.vwgt = ismalloc(mgraph.nvtxs*NCON, 1, "TestParMetis_V3: mgraph.vwgt"); mgraph.vsize = ismalloc(mgraph.nvtxs, 1, "TestParMetis_V3: mgraph.vsize"); AdaptGraph(&mgraph, 4, comm); options[0] = 1; options[1] = 7; options[2] = 1; options[3] = PARMETIS_PSR_COUPLED; wgtflag = 2; numflag = 0; for (nparts=2*npes; nparts>=npes/2; nparts = nparts/2) { options[0] = 0; ncon = 1; wgtflag = 0; rset(nparts*ncon, 1.0/(real_t)nparts, tpwgts); ParMETIS_V3_PartKway(mgraph.vtxdist, mgraph.xadj, mgraph.adjncy, NULL, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, savepart, &comm); options[0] = 1; wgtflag = 2; for (ncon=1; ncon<=NCON; ncon++) { rset(nparts*ncon, 1.0/(real_t)nparts, tpwgts); if (ncon > 1) Mc_AdaptGraph(&mgraph, savepart, ncon, nparts, comm); else AdaptGraph(&mgraph, 4, comm); for (ipc2redist=1000.0; ipc2redist>=0.001; ipc2redist/=1000.0) { icopy(mgraph.nvtxs, savepart, mpart); if (mype == 0) printf("\nTesting ParMETIS_V3_AdaptiveRepart with ipc2redist: %.3"PRREAL", ncon: %"PRIDX", nparts: %"PRIDX"\n", ipc2redist, ncon, nparts); ParMETIS_V3_AdaptiveRepart(mgraph.vtxdist, mgraph.xadj, mgraph.adjncy, mgraph.vwgt, mgraph.vsize, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, &ipc2redist, options, &edgecut, mpart, &comm); realcut = ComputeRealCutFromMoved(graph.vtxdist, mgraph.vtxdist, part, mpart, filename, comm); if (mype == 0) printf("ParMETIS_V3_AdaptiveRepart reported a cut of %"PRIDX" [%s:%"PRIDX"]\n", edgecut, (edgecut == realcut ? "OK" : "ERROR"), realcut); } } } gk_free((void **)&tpwgts, &part, &mpart, &savepart, &xyz, &mgraph.vwgt, &mgraph.vsize, LTERM); }
void ProjectKWayPartition(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, k, nvtxs, nbnd, nparts, me, other, istart, iend, tid, ted; idx_t *xadj, *adjncy, *adjwgt; idx_t *cmap, *where, *bndptr, *bndind, *cwhere, *htable; graph_t *cgraph; WCOREPUSH; nparts = ctrl->nparts; cgraph = graph->coarser; cwhere = cgraph->where; nvtxs = graph->nvtxs; cmap = graph->cmap; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; AllocateKWayPartitionMemory(ctrl, graph); where = graph->where; bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); htable = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); /* Compute the required info for refinement */ switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: ASSERT(CheckBnd2(cgraph)); { ckrinfo_t *myrinfo; cnbr_t *mynbrs; /* go through and project partition and compute id/ed for the nodes */ for (i=0; i<nvtxs; i++) { k = cmap[i]; where[i] = cwhere[k]; cmap[i] = cgraph->ckrinfo[k].ed; /* For optimization */ } memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs); cnbrpoolReset(ctrl); for (nbnd=0, i=0; i<nvtxs; i++) { istart = xadj[i]; iend = xadj[i+1]; myrinfo = graph->ckrinfo+i; if (cmap[i] == 0) { /* Interior node. Note that cmap[i] = crinfo[cmap[i]].ed */ for (tid=0, j=istart; j<iend; j++) tid += adjwgt[j]; myrinfo->id = tid; myrinfo->inbr = -1; } else { /* Potentially an interface node */ myrinfo->inbr = cnbrpoolGetNext(ctrl, iend-istart+1); mynbrs = ctrl->cnbrpool + myrinfo->inbr; me = where[i]; for (tid=0, ted=0, j=istart; j<iend; j++) { other = where[adjncy[j]]; if (me == other) { tid += adjwgt[j]; } else { ted += adjwgt[j]; if ((k = htable[other]) == -1) { htable[other] = myrinfo->nnbrs; mynbrs[myrinfo->nnbrs].pid = other; mynbrs[myrinfo->nnbrs++].ed = adjwgt[j]; } else { mynbrs[k].ed += adjwgt[j]; } } } myrinfo->id = tid; myrinfo->ed = ted; /* Remove space for edegrees if it was interior */ if (ted == 0) { ctrl->nbrpoolcpos -= iend-istart+1; myrinfo->inbr = -1; } else { if (ted-tid >= 0) BNDInsert(nbnd, bndind, bndptr, i); for (j=0; j<myrinfo->nnbrs; j++) htable[mynbrs[j].pid] = -1; } } } graph->nbnd = nbnd; } ASSERT(CheckBnd2(graph)); break; case METIS_OBJTYPE_VOL: { vkrinfo_t *myrinfo; vnbr_t *mynbrs; ASSERT(cgraph->minvol == ComputeVolume(cgraph, cgraph->where)); /* go through and project partition and compute id/ed for the nodes */ for (i=0; i<nvtxs; i++) { k = cmap[i]; where[i] = cwhere[k]; cmap[i] = cgraph->vkrinfo[k].ned; /* For optimization */ } memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs); vnbrpoolReset(ctrl); for (i=0; i<nvtxs; i++) { istart = xadj[i]; iend = xadj[i+1]; myrinfo = graph->vkrinfo+i; if (cmap[i] == 0) { /* Note that cmap[i] = crinfo[cmap[i]].ed */ myrinfo->nid = iend-istart; myrinfo->inbr = -1; } else { /* Potentially an interface node */ myrinfo->inbr = vnbrpoolGetNext(ctrl, iend-istart+1); mynbrs = ctrl->vnbrpool + myrinfo->inbr; me = where[i]; for (tid=0, ted=0, j=istart; j<iend; j++) { other = where[adjncy[j]]; if (me == other) { tid++; } else { ted++; if ((k = htable[other]) == -1) { htable[other] = myrinfo->nnbrs; mynbrs[myrinfo->nnbrs].gv = 0; mynbrs[myrinfo->nnbrs].pid = other; mynbrs[myrinfo->nnbrs++].ned = 1; } else { mynbrs[k].ned++; } } } myrinfo->nid = tid; myrinfo->ned = ted; /* Remove space for edegrees if it was interior */ if (ted == 0) { ctrl->nbrpoolcpos -= iend-istart+1; myrinfo->inbr = -1; } else { for (j=0; j<myrinfo->nnbrs; j++) htable[mynbrs[j].pid] = -1; } } } ComputeKWayVolGains(ctrl, graph); ASSERT(graph->minvol == ComputeVolume(graph, graph->where)); } break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } graph->mincut = cgraph->mincut; icopy(nparts*graph->ncon, cgraph->pwgts, graph->pwgts); FreeGraph(&graph->coarser); graph->coarser = NULL; WCOREPOP; }
// shaded white stones void ImageHandler::paintWhiteStone (QImage &wi, int d, int stone_render)//bool stripes ) { { WhiteDesc desc; decideAppearance(&desc, d); // the angle from which the dim starts (measured to the light direction = pi/4) // alpha should be in (0, pi) const double ALPHA = M_PI/4; // how big the dim is (should be < d/2) const double STRIPE = d/5.0; double theta; const double pixel=0.8;//, shadow=0.99; bool Alias=true; // these are the images int i, j, g, g1,g2,k; double di, dj, d2=(double)d/2.0-5e-1, r=d2-2e-1, f=sqrt(3.0); double x, y, z, xr, xr1, xr2, xg1,xg2, hh; k=0; bool smallerstones = false; if (smallerstones) r-=1; for (i=0; i<d; i++) for (j=0; j<d; j++) { di=i-d2; dj=j-d2; hh=r-sqrt(di*di+dj*dj); if (hh>=0) { if (stone_render != 1) { z=r*r-di*di-dj*dj; if (z>0) z=sqrt(z)*f; else z=0; x=di; y=dj; xr=sqrt(6*(x*x+y*y+z*z)); xr1=(2*z-x+y)/xr; xr2=(2*z+x-y)/xr; //#define WHITE_SHINE_START 0.9 //#define WHITE_SHINE_END 0.92 #define WHITE_SHINE_START 0.9795 #define WHITE_SHINE_END 0.98 if (xr1>WHITE_SHINE_START) xg1=(xr1-WHITE_SHINE_START)*10; else xg1=0; if (xr2>WHITE_SHINE_END) xg2=(xr2-WHITE_SHINE_END)*10; else xg2=0; //#define WHITENESS 200 #define WHITENESS 235 //#define WHITENESS_SHINE 10 #define WHITENESS_SHINE 5 g2=(int)(WHITENESS+WHITENESS_SHINE* xr2+xg2*45); //g=(g1 > g2 ? g1 : g2); theta = atan2(double(j-d/2), double(i-d/2)) + M_PI - M_PI/4 + M_PI/2; bool stripeband = theta > ALPHA && theta < 2*M_PI-ALPHA; if (theta > M_PI) theta = (2*M_PI-theta); double stripe = STRIPE*sin((M_PI/2)*(theta-ALPHA)/(M_PI-ALPHA)); if (stripe < 1) stripe = 1; double g1min=(int)(0+WHITENESS_SHINE*xr1+xg1*45), g2min=(int)(0+WHITENESS_SHINE*xr2+xg2*45); double g1max=(int)(WHITENESS+WHITENESS_SHINE*xr1+xg1*45), g2max=(int)(WHITENESS+WHITENESS_SHINE* xr2+xg2*45);; g1min = g1max - (g1max-g1min)*(1-exp(-1*(theta-ALPHA)/(M_PI-ALPHA))); g2min = g2max - (g2max-g2min)*(1-exp(-1*(theta-ALPHA)/(M_PI-ALPHA))); if ((hh < STRIPE) && hh > pixel && stripeband) { if (hh > stripe) g1 = (int)g1max; else g1 = int(g1min + (g1max-g1min)*sqrt(hh/stripe)); if (hh > stripe) g2 = (int)g2max; else g2 = int(g2min + (g2max-g2min)*sqrt(hh/stripe)); g=(g1 > g2 ? g1 : g2); if (stone_render == 0) //stripes) g = (int)getStripe(desc, g, xr1/7.0, i, j); painting_buffer[k]=(255<<24)|(g<<16)|((g)<<8)|(g); } else if (( hh > pixel ) || (!Alias) ) { //g1=(int)(190+10*drand48()+10*xr1+xg1*45); g=(int)(g1max > g2max ? g1max : g2max); if (stone_render == 0)//stripes) g = (int)getStripe(desc, g, xr1/7.0, i, j); painting_buffer[k]=(255<<24)|(g<<16)|((g)<<8)|(g); } else { g1=(int)(stripeband ? g1min : g1max); g2=(int)(stripeband ? g2min : g2max); g=(g1 > g2 ? g1 : g2); if (stone_render == 0)//stripes) g = (int)getStripe(desc, g, xr1/7.0, i, j); painting_buffer[k]=((int)(hh/pixel*255)<<24)|(g<<16)|(g<<8)|g; } } else // Code for flat stones { // draws a black circle for 2D stones if ((hh>=-1)&&(hh<=1)) { g=0; painting_buffer[k]=((int)(255)<<24)|(g<<16)|(g<<8)|g; } else if (hh>0) { g=255; painting_buffer[k]=((int)(255)<<24)|(g<<16)|(g<<8)|g; } } } else painting_buffer[k]=0; k++; } // now copy the result in QImages icopy(painting_buffer, wi, d, d); }