Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/macros.h
3206 views
/*1* Copyright 1997, Regents of the University of Minnesota2*3* macros.h4*5* This file contains macros used in multilevel6*7* Started 9/25/948* George9*10* $Id: macros.h 10060 2011-06-02 18:56:30Z karypis $11*12*/1314#ifndef _LIBMETIS_MACROS_H_15#define _LIBMETIS_MACROS_H_1617/*************************************************************************18* The following macro returns a random number in the specified range19**************************************************************************/20#define AND(a, b) ((a) < 0 ? ((-(a))&(b)) : ((a)&(b)))21#define OR(a, b) ((a) < 0 ? -((-(a))|(b)) : ((a)|(b)))22#define XOR(a, b) ((a) < 0 ? -((-(a))^(b)) : ((a)^(b)))2324//#define icopy(n, a, b) (idx_t *)memcpy((void *)(b), (void *)(a), sizeof(idx_t)*(n))2526#define HASHFCT(key, size) ((key)%(size))27#define SWAP gk_SWAP2829/* gets the appropriate option value */30#define GETOPTION(options, idx, defval) \31((options) == NULL || (options)[idx] == -1 ? defval : (options)[idx])3233/* converts a user provided ufactor into a real ubfactor */34#define I2RUBFACTOR(ufactor) (1.0+0.001*(ufactor))3536/* set/reset the current workspace core */37#define WCOREPUSH wspacepush(ctrl)38#define WCOREPOP wspacepop(ctrl)39404142/*************************************************************************43* These macros insert and remove nodes from a Direct Access list44**************************************************************************/45#define ListInsert(n, lind, lptr, i) \46do { \47ASSERT(lptr[i] == -1); \48lind[n] = i; \49lptr[i] = (n)++;\50} while(0)5152#define ListDelete(n, lind, lptr, i) \53do { \54ASSERT(lptr[i] != -1); \55lind[lptr[i]] = lind[--(n)]; \56lptr[lind[n]] = lptr[i]; \57lptr[i] = -1; \58} while(0)596061/*************************************************************************62* These macros insert and remove nodes from the boundary list63**************************************************************************/64#define BNDInsert(nbnd, bndind, bndptr, vtx) \65ListInsert(nbnd, bndind, bndptr, vtx)6667#define BNDDelete(nbnd, bndind, bndptr, vtx) \68ListDelete(nbnd, bndind, bndptr, vtx)697071/*************************************************************************72* These macros deal with id/ed updating during k-way refinement73**************************************************************************/74#define UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, \75nbnd, bndptr, bndind, bndtype) \76do { \77where[i] = to; \78myrinfo->ed += myrinfo->id-mynbrs[k].ed; \79SWAP(myrinfo->id, mynbrs[k].ed, j); \80if (mynbrs[k].ed == 0) \81mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \82else \83mynbrs[k].pid = from; \84\85/* Update the boundary information. Both deletion and addition is \86allowed as this routine can be used for moving arbitrary nodes. */ \87if (bndtype == BNDTYPE_REFINE) { \88if (bndptr[i] != -1 && myrinfo->ed - myrinfo->id < 0) \89BNDDelete(nbnd, bndind, bndptr, i); \90if (bndptr[i] == -1 && myrinfo->ed - myrinfo->id >= 0) \91BNDInsert(nbnd, bndind, bndptr, i); \92} \93else { \94if (bndptr[i] != -1 && myrinfo->ed <= 0) \95BNDDelete(nbnd, bndind, bndptr, i); \96if (bndptr[i] == -1 && myrinfo->ed > 0) \97BNDInsert(nbnd, bndind, bndptr, i); \98} \99} while(0)100101102#define UpdateAdjacentVertexInfoAndBND(ctrl, vid, adjlen, me, from, to, \103myrinfo, ewgt, nbnd, bndptr, bndind, bndtype) \104do { \105idx_t k; \106cnbr_t *mynbrs; \107\108if (myrinfo->inbr == -1) { \109myrinfo->inbr = cnbrpoolGetNext(ctrl, adjlen+1); \110myrinfo->nnbrs = 0; \111} \112ASSERT(CheckRInfo(ctrl, myrinfo)); \113\114mynbrs = ctrl->cnbrpool + myrinfo->inbr; \115\116/* Update global ID/ED and boundary */ \117if (me == from) { \118INC_DEC(myrinfo->ed, myrinfo->id, (ewgt)); \119if (bndtype == BNDTYPE_REFINE) { \120if (myrinfo->ed-myrinfo->id >= 0 && bndptr[(vid)] == -1) \121BNDInsert(nbnd, bndind, bndptr, (vid)); \122} \123else { \124if (myrinfo->ed > 0 && bndptr[(vid)] == -1) \125BNDInsert(nbnd, bndind, bndptr, (vid)); \126} \127} \128else if (me == to) { \129INC_DEC(myrinfo->id, myrinfo->ed, (ewgt)); \130if (bndtype == BNDTYPE_REFINE) { \131if (myrinfo->ed-myrinfo->id < 0 && bndptr[(vid)] != -1) \132BNDDelete(nbnd, bndind, bndptr, (vid)); \133} \134else { \135if (myrinfo->ed <= 0 && bndptr[(vid)] != -1) \136BNDDelete(nbnd, bndind, bndptr, (vid)); \137} \138} \139\140/* Remove contribution from the .ed of 'from' */ \141if (me != from) { \142for (k=0; k<myrinfo->nnbrs; k++) { \143if (mynbrs[k].pid == from) { \144if (mynbrs[k].ed == (ewgt)) \145mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \146else \147mynbrs[k].ed -= (ewgt); \148break; \149} \150} \151} \152\153/* Add contribution to the .ed of 'to' */ \154if (me != to) { \155for (k=0; k<myrinfo->nnbrs; k++) { \156if (mynbrs[k].pid == to) { \157mynbrs[k].ed += (ewgt); \158break; \159} \160} \161if (k == myrinfo->nnbrs) { \162mynbrs[k].pid = to; \163mynbrs[k].ed = (ewgt); \164myrinfo->nnbrs++; \165} \166} \167\168ASSERT(CheckRInfo(ctrl, myrinfo));\169} while(0)170171172#define UpdateQueueInfo(queue, vstatus, vid, me, from, to, myrinfo, oldnnbrs, \173nupd, updptr, updind, bndtype) \174do { \175real_t rgain; \176\177if (me == to || me == from || oldnnbrs != myrinfo->nnbrs) { \178rgain = (myrinfo->nnbrs > 0 ? \1791.0*myrinfo->ed/sqrt(myrinfo->nnbrs) : 0.0) - myrinfo->id; \180\181if (bndtype == BNDTYPE_REFINE) { \182if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \183if (myrinfo->ed-myrinfo->id >= 0) \184rpqUpdate(queue, (vid), rgain); \185else { \186rpqDelete(queue, (vid)); \187vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \188ListDelete(nupd, updind, updptr, (vid)); \189} \190} \191else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed-myrinfo->id >= 0) { \192rpqInsert(queue, (vid), rgain); \193vstatus[(vid)] = VPQSTATUS_PRESENT; \194ListInsert(nupd, updind, updptr, (vid)); \195} \196} \197else { \198if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \199if (myrinfo->ed > 0) \200rpqUpdate(queue, (vid), rgain); \201else { \202rpqDelete(queue, (vid)); \203vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \204ListDelete(nupd, updind, updptr, (vid)); \205} \206} \207else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed > 0) { \208rpqInsert(queue, (vid), rgain); \209vstatus[(vid)] = VPQSTATUS_PRESENT; \210ListInsert(nupd, updind, updptr, (vid)); \211} \212} \213} \214} while(0)215216217218/*************************************************************************/219/*! This macro determines the set of subdomains that a vertex can move to220without increasins the maxndoms. */221/*************************************************************************/222#define SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, vtmp) \223do { \224idx_t j, k, l, nadd, to; \225for (j=0; j<myrinfo->nnbrs; j++) { \226safetos[to = mynbrs[j].pid] = 0; \227\228/* uncompress the connectivity info for the 'to' subdomain */ \229for (k=0; k<nads[to]; k++) \230vtmp[adids[to][k]] = 1; \231\232for (nadd=0, k=0; k<myrinfo->nnbrs; k++) { \233if (k == j) \234continue; \235\236l = mynbrs[k].pid; \237if (vtmp[l] == 0) { \238if (nads[l] > maxndoms-1) { \239nadd = maxndoms; \240break; \241} \242nadd++; \243} \244} \245if (nads[to]+nadd <= maxndoms) \246safetos[to] = 1; \247if (nadd == 0) \248safetos[to] = 2; \249\250/* cleanup the connectivity info due to the 'to' subdomain */ \251for (k=0; k<nads[to]; k++) \252vtmp[adids[to][k]] = 0; \253} \254} while (0)255256257#endif258259260