Date: 2013-07-02T14:39:10+00:00

Actual source code: ctable.c
petsc-3.4.2 2013-07-02

      2: /* Contributed by - Mark Adams */

      4: #include <petscsys.h>
      5: #include <petscctable.h>

      9: /*
     10:    PetscTableCreate  Creates a PETSc look up table

     12:    Input Parameters:
     13: +     n - expected number of keys
     14: -     maxkey- largest possible key

     16:    Notes: keys are between 1 and N inclusive

     18: */
     19: PetscErrorCode  PetscTableCreate(const PetscInt n,PetscInt maxkey,PetscTable *rta)
     20: {
     21:   PetscTable     ta;

     25:   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"n < 0");
     26:   PetscNew(struct _n_PetscTable,&ta);
     27:   ta->tablesize = (3*n)/2 + 17;
     28:   if (ta->tablesize < n) ta->tablesize = PETSC_MAX_INT/4; /* overflow */
     29:   PetscMalloc(sizeof(PetscInt)*ta->tablesize,&ta->keytable);
     30:   PetscMemzero(ta->keytable,sizeof(PetscInt)*ta->tablesize);
     31:   PetscMalloc(sizeof(PetscInt)*ta->tablesize,&ta->table);
     32:   ta->head   = 0;
     33:   ta->count  = 0;
     34:   ta->maxkey = maxkey;
     35:   *rta       = ta;
     36:   return(0);
     37: }

     41: /* PetscTableCreate() ********************************************
     42:  *
     43:  * hash table for non-zero data and keys
     44:  *
     45:  */
     46: PetscErrorCode  PetscTableCreateCopy(const PetscTable intable,PetscTable *rta)
     47: {
     49:   PetscInt       i;
     50:   PetscTable     ta;

     53:   PetscNew(struct _n_PetscTable,&ta);
     54:   ta->tablesize = intable->tablesize;
     55:   PetscMalloc(sizeof(PetscInt)*ta->tablesize,&ta->keytable);
     56:   PetscMalloc(sizeof(PetscInt)*ta->tablesize,&ta->table);
     57:   for (i = 0; i < ta->tablesize; i++) {
     58:     ta->keytable[i] = intable->keytable[i];
     59:     ta->table[i]    = intable->table[i];
     60: #if defined(PETSC_USE_DEBUG)
     61:     if (ta->keytable[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"ta->keytable[i] < 0");
     62: #endif
     63:   }
     64:   ta->head   = 0;
     65:   ta->count  = intable->count;
     66:   ta->maxkey = intable->maxkey;
     67:   *rta       = ta;
     68:   return(0);
     69: }

     73: /* PetscTableDestroy() ********************************************
     74:  *
     75:  *
     76:  */
     77: PetscErrorCode  PetscTableDestroy(PetscTable *ta)
     78: {

     82:   if (!*ta) return(0);
     83:   PetscFree((*ta)->keytable);
     84:   PetscFree((*ta)->table);
     85:   PetscFree(*ta);
     86:   return(0);
     87: }

     91: /* PetscTableGetCount() ********************************************
     92:  */
     93: PetscErrorCode  PetscTableGetCount(const PetscTable ta,PetscInt *count)
     94: {
     96:   *count = ta->count;
     97:   return(0);
     98: }

    102: /* PetscTableIsEmpty() ********************************************
    103:  */
    104: PetscErrorCode  PetscTableIsEmpty(const PetscTable ta,PetscInt *flag)
    105: {
    107:   *flag = !(ta->count);
    108:   return(0);
    109: }

    113: /*
    114:     PetscTableAddExpand - called PetscTableAdd() if more space needed

    116: */
    117: PetscErrorCode  PetscTableAddExpand(PetscTable ta,PetscInt key,PetscInt data,InsertMode imode)
    118: {
    120:   PetscInt       ii      = 0;
    121:   const PetscInt tsize   = ta->tablesize,tcount = ta->count;
    122:   PetscInt       *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;

    125:   if (ta->tablesize == PETSC_MAX_INT/4) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"ta->tablesize < 0");
    126:   ta->tablesize = 2*tsize;
    127:   if (ta->tablesize <= tsize) ta->tablesize = PETSC_MAX_INT/4;

    129:   PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->table);
    130:   PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->keytable);
    131:   PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));

    133:   ta->count = 0;
    134:   ta->head  = 0;

    136:   PetscTableAdd(ta,key,data,INSERT_VALUES);
    137:   /* rehash */
    138:   for (ii = 0; ii < tsize; ii++) {
    139:     newk = oldkt[ii];
    140:     if (newk) {
    141:       ndata = oldtab[ii];
    142:       PetscTableAdd(ta,newk,ndata,imode);
    143:     }
    144:   }
    145:   if (ta->count != tcount + 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"corrupted ta->count");

    147:   PetscFree(oldtab);
    148:   PetscFree(oldkt);
    149:   return(0);
    150: }

    155: /* PetscTableRemoveAll() ********************************************
    156:  *
    157:  *
    158:  */
    159: PetscErrorCode  PetscTableRemoveAll(PetscTable ta)
    160: {

    164:   ta->head = 0;
    165:   if (ta->count) {
    166:     ta->count = 0;

    168:     PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));
    169:   }
    170:   return(0);
    171: }

    177: /* PetscTableGetHeadPosition() ********************************************
    178:  *
    179:  */
    180: PetscErrorCode  PetscTableGetHeadPosition(PetscTable ta,PetscTablePosition *ppos)
    181: {
    182:   PetscInt i = 0;

    185:   *ppos = NULL;
    186:   if (!ta->count) return(0);

    188:   /* find first valid place */
    189:   do {
    190:     if (ta->keytable[i]) {
    191:       *ppos = (PetscTablePosition)&ta->table[i];
    192:       break;
    193:     }
    194:   } while (i++ < ta->tablesize);
    195:   if (!*ppos) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"No head");
    196:   return(0);
    197: }

    201: /* PetscTableGetNext() ********************************************
    202:  *
    203:  *  - iteration - PetscTablePosition is always valid (points to a data)
    204:  *
    205:  */
    206: PetscErrorCode  PetscTableGetNext(PetscTable ta,PetscTablePosition *rPosition,PetscInt *pkey,PetscInt *data)
    207: {
    208:   PetscInt           idex;
    209:   PetscTablePosition pos;

    212:   pos = *rPosition;
    213:   if (!pos) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null position");
    214:   *data = *pos;
    215:   if (!*data) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null data");
    216:   idex  = pos - ta->table;
    217:   *pkey = ta->keytable[idex];
    218:   if (!*pkey) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null key");

    220:   /* get next */
    221:   do {
    222:     pos++;  idex++;
    223:     if (idex >= ta->tablesize) {
    224:       pos = 0; /* end of list */
    225:       break;
    226:     } else if (ta->keytable[idex]) {
    227:       pos = ta->table + idex;
    228:       break;
    229:     }
    230:   } while (idex < ta->tablesize);
    231:   *rPosition = pos;
    232:   return(0);
    233: }

    238: PetscErrorCode  PetscTableAddCountExpand(PetscTable ta,PetscInt key)
    239: {
    241:   PetscInt       ii      = 0,hash = PetscHash(ta,key);
    242:   const PetscInt tsize   = ta->tablesize,tcount = ta->count;
    243:   PetscInt       *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;

    246:   /* before making the table larger check if key is already in table */
    247:   while (ii++ < ta->tablesize) {
    248:     if (ta->keytable[hash] == key) return(0);
    249:     hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
    250:   }

    252:   /* alloc new (bigger) table */
    253:   if (ta->tablesize == PETSC_MAX_INT/4) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"ta->tablesize < 0");
    254:   ta->tablesize = 2*tsize;
    255:   if (ta->tablesize <= tsize) ta->tablesize = PETSC_MAX_INT/4;

    257:   PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->table);
    258:   PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->keytable);
    259:   PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));

    261:   ta->count = 0;
    262:   ta->head  = 0;

    264:   /* Build a new copy of the data */
    265:   for (ii = 0; ii < tsize; ii++) {
    266:     newk = oldkt[ii];
    267:     if (newk) {
    268:       ndata = oldtab[ii];
    269:       PetscTableAdd(ta,newk,ndata,INSERT_VALUES);
    270:     }
    271:   }
    272:   PetscTableAddCount(ta,key);
    273:   if (ta->count != tcount + 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"corrupted ta->count");

    275:   PetscFree(oldtab);
    276:   PetscFree(oldkt);
    277:   return(0);
    278: }