Actual source code: ctable.c
petsc-3.13.6 2020-09-29
Report Typos and Errors

      2: /* Contributed by - Mark Adams */

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

      7: static PetscErrorCode PetscTableCreateHashSize(PetscInt sz, PetscInt *hsz)
      8: {
     10:   if (sz < 100)          *hsz = 139;
     11:   else if (sz < 200)     *hsz = 283;
     12:   else if (sz < 400)     *hsz = 577;
     13:   else if (sz < 800)     *hsz = 1103;
     14:   else if (sz < 1600)    *hsz = 2239;
     15:   else if (sz < 3200)    *hsz = 4787;
     16:   else if (sz < 6400)    *hsz = 9337;
     17:   else if (sz < 12800)   *hsz = 17863;
     18:   else if (sz < 25600)   *hsz = 37649;
     19:   else if (sz < 51200)   *hsz = 72307;
     20:   else if (sz < 102400)  *hsz = 142979;
     21:   else if (sz < 204800)  *hsz = 299983;
     22:   else if (sz < 409600)  *hsz = 599869;
     23:   else if (sz < 819200)  *hsz = 1193557;
     24:   else if (sz < 1638400) *hsz = 2297059;
     25:   else if (sz < 3276800) *hsz = 4902383;
     26:   else if (sz < 6553600) *hsz = 9179113;
     27:   else if (sz < 13107200)*hsz = 18350009;
     28:   else if (sz < 26214400)*hsz = 36700021;
     29:   else if (sz < 52428800)*hsz = 73400279;
     30:   else if (sz < 104857600)*hsz = 146800471;
     31:   else if (sz < 209715200)*hsz = 293601569;
     32:   else if (sz < 419430400)*hsz = 587202269;
     33:   else if (sz < 838860800)*hsz = 1175862839;
     34:   else if (sz < 1677721600)*hsz = 2147321881;
     35: #if defined(PETSC_USE_64BIT_INDICES)
     36:   else if (sz < 3355443200l)*hsz = 4695452647l;
     37:   else if (sz < 6710886400l)*hsz = 9384888067l;
     38:   else if (sz < 13421772800l)*hsz = 18787024237l;
     39:   else if (sz < 26843545600l)*hsz = 32416190071l;
     40: #endif
     41:   else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"A really huge hash is being requested.. cannot process: %D",sz);
     42:   return(0);
     43: }

     45: /*
     46:    PetscTableCreate  Creates a PETSc look up table

     48:    Input Parameters:
     49: +     n - expected number of keys
     50: -     maxkey- largest possible key

     52:    Notes:
     53:     keys are between 1 and maxkey inclusive

     55: */
     56: PetscErrorCode  PetscTableCreate(const PetscInt n,PetscInt maxkey,PetscTable *rta)
     57: {
     58:   PetscTable     ta;

     62:   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"n < 0");
     63:   PetscNew(&ta);
     64:   PetscTableCreateHashSize(n,&ta->tablesize);
     65:   PetscCalloc1(ta->tablesize,&ta->keytable);
     66:   PetscMalloc1(ta->tablesize,&ta->table);
     67:   ta->head   = 0;
     68:   ta->count  = 0;
     69:   ta->maxkey = maxkey;
     70:   *rta       = ta;
     71:   return(0);
     72: }

     74: /* PetscTableCreate() ********************************************
     75:  *
     76:  * hash table for non-zero data and keys
     77:  *
     78:  */
     79: PetscErrorCode  PetscTableCreateCopy(const PetscTable intable,PetscTable *rta)
     80: {
     82:   PetscTable     ta;

     85:   PetscNew(&ta);
     86:   ta->tablesize = intable->tablesize;
     87:   PetscMalloc1(ta->tablesize,&ta->keytable);
     88:   PetscMalloc1(ta->tablesize,&ta->table);
     89:   PetscMemcpy(ta->keytable,intable->keytable,ta->tablesize*sizeof(PetscInt));
     90:   PetscMemcpy(ta->table,intable->table,ta->tablesize*sizeof(PetscInt));
     91: #if defined(PETSC_USE_DEBUG)
     92:   {
     93:   PetscInt i;
     94:   for (i = 0; i < ta->tablesize; i++) {
     95:     if (ta->keytable[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"ta->keytable[i] < 0");
     96:   }
     97:   }
     98: #endif
     99:   ta->head   = 0;
    100:   ta->count  = intable->count;
    101:   ta->maxkey = intable->maxkey;
    102:   *rta       = ta;
    103:   return(0);
    104: }

    106: /* PetscTableDestroy() ********************************************
    107:  *
    108:  *
    109:  */
    110: PetscErrorCode  PetscTableDestroy(PetscTable *ta)
    111: {

    115:   if (!*ta) return(0);
    116:   PetscFree((*ta)->keytable);
    117:   PetscFree((*ta)->table);
    118:   PetscFree(*ta);
    119:   return(0);
    120: }

    122: /* PetscTableGetCount() ********************************************
    123:  */
    124: PetscErrorCode  PetscTableGetCount(const PetscTable ta,PetscInt *count)
    125: {
    127:   *count = ta->count;
    128:   return(0);
    129: }

    131: /* PetscTableIsEmpty() ********************************************
    132:  */
    133: PetscErrorCode  PetscTableIsEmpty(const PetscTable ta,PetscInt *flag)
    134: {
    136:   *flag = !(ta->count);
    137:   return(0);
    138: }

    140: /*
    141:     PetscTableAddExpand - called by PetscTableAdd() if more space is needed

    143: */
    144: PetscErrorCode  PetscTableAddExpand(PetscTable ta,PetscInt key,PetscInt data,InsertMode imode)
    145: {
    147:   PetscInt       ii      = 0;
    148:   const PetscInt tsize   = ta->tablesize,tcount = ta->count;
    149:   PetscInt       *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;

    152:   PetscTableCreateHashSize(ta->tablesize,&ta->tablesize);
    153:   PetscMalloc1(ta->tablesize,&ta->table);
    154:   PetscCalloc1(ta->tablesize,&ta->keytable);

    156:   ta->count = 0;
    157:   ta->head  = 0;

    159:   PetscTableAdd(ta,key,data,INSERT_VALUES);
    160:   /* rehash */
    161:   for (ii = 0; ii < tsize; ii++) {
    162:     newk = oldkt[ii];
    163:     if (newk) {
    164:       ndata = oldtab[ii];
    165:       PetscTableAdd(ta,newk,ndata,imode);
    166:     }
    167:   }
    168:   if (ta->count != tcount + 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"corrupted ta->count");

    170:   PetscFree(oldtab);
    171:   PetscFree(oldkt);
    172:   return(0);
    173: }

    176: /* PetscTableRemoveAll() ********************************************
    177:  *
    178:  *
    179:  */
    180: PetscErrorCode  PetscTableRemoveAll(PetscTable ta)
    181: {

    185:   ta->head = 0;
    186:   if (ta->count) {
    187:     ta->count = 0;

    189:     PetscArrayzero(ta->keytable,ta->tablesize);
    190:   }
    191:   return(0);
    192: }

    196: /* PetscTableGetHeadPosition() ********************************************
    197:  *
    198:  */
    199: PetscErrorCode  PetscTableGetHeadPosition(PetscTable ta,PetscTablePosition *ppos)
    200: {
    201:   PetscInt i = 0;

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

    207:   /* find first valid place */
    208:   do {
    209:     if (ta->keytable[i]) {
    210:       *ppos = (PetscTablePosition)&ta->table[i];
    211:       break;
    212:     }
    213:   } while (i++ < ta->tablesize);
    214:   if (!*ppos) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"No head");
    215:   return(0);
    216: }

    218: /* PetscTableGetNext() ********************************************
    219:  *
    220:  *  - iteration - PetscTablePosition is always valid (points to a data)
    221:  *
    222:  */
    223: PetscErrorCode  PetscTableGetNext(PetscTable ta,PetscTablePosition *rPosition,PetscInt *pkey,PetscInt *data)
    224: {
    225:   PetscInt           idex;
    226:   PetscTablePosition pos;

    229:   pos = *rPosition;
    230:   if (!pos) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null position");
    231:   *data = *pos;
    232:   if (!*data) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null data");
    233:   idex  = pos - ta->table;
    234:   *pkey = ta->keytable[idex];
    235:   if (!*pkey) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null key");

    237:   /* get next */
    238:   do {
    239:     pos++;  idex++;
    240:     if (idex >= ta->tablesize) {
    241:       pos = NULL; /* end of list */
    242:       break;
    243:     } else if (ta->keytable[idex]) {
    244:       pos = ta->table + idex;
    245:       break;
    246:     }
    247:   } while (idex < ta->tablesize);
    248:   *rPosition = pos;
    249:   return(0);
    250: }

    253: PetscErrorCode  PetscTableAddCountExpand(PetscTable ta,PetscInt key)
    254: {
    256:   PetscInt       ii      = 0,hash = PetscHash(ta,key);
    257:   const PetscInt tsize   = ta->tablesize,tcount = ta->count;
    258:   PetscInt       *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;

    261:   /* before making the table larger check if key is already in table */
    262:   while (ii++ < tsize) {
    263:     if (ta->keytable[hash] == key) return(0);
    264:     hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
    265:   }

    267:   ta->tablesize = PetscIntMultTruncate(2,ta->tablesize);
    268:   if (tsize == ta->tablesize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Table is as large as possible; ./configure with the option --with-64-bit-integers to run this large case");
    269:   PetscMalloc1(ta->tablesize,&ta->table);
    270:   PetscCalloc1(ta->tablesize,&ta->keytable);

    272:   ta->count = 0;
    273:   ta->head  = 0;

    275:   /* Build a new copy of the data */
    276:   for (ii = 0; ii < tsize; ii++) {
    277:     newk = oldkt[ii];
    278:     if (newk) {
    279:       ndata = oldtab[ii];
    280:       PetscTableAdd(ta,newk,ndata,INSERT_VALUES);
    281:     }
    282:   }
    283:   PetscTableAddCount(ta,key);
    284:   if (ta->count != tcount + 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"corrupted ta->count");

    286:   PetscFree(oldtab);
    287:   PetscFree(oldkt);
    288:   return(0);
    289: }