Actual source code: ctable.c

petsc-3.7.5 2017-01-01
Report Typos and Errors
  2: /* Contributed by - Mark Adams */

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

  9: static PetscErrorCode PetscTableCreateHashSize(PetscInt sz, PetscInt *hsz)
 10: {
 12:   if (sz < 100)          *hsz = 139;
 13:   else if (sz < 200)     *hsz = 283;
 14:   else if (sz < 400)     *hsz = 577;
 15:   else if (sz < 800)     *hsz = 1103;
 16:   else if (sz < 1600)    *hsz = 2239;
 17:   else if (sz < 3200)    *hsz = 4787;
 18:   else if (sz < 6400)    *hsz = 9337;
 19:   else if (sz < 12800)   *hsz = 17863;
 20:   else if (sz < 25600)   *hsz = 37649;
 21:   else if (sz < 51200)   *hsz = 72307;
 22:   else if (sz < 102400)  *hsz = 142979;
 23:   else if (sz < 204800)  *hsz = 299983;
 24:   else if (sz < 409600)  *hsz = 599869;
 25:   else if (sz < 819200)  *hsz = 1193557;
 26:   else if (sz < 1638400) *hsz = 2297059;
 27:   else if (sz < 3276800) *hsz = 4902383;
 28:   else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"A really huge hash is being requested.. cannot process: %D",sz);
 29:   return(0);
 30: }

 34: /*
 35:    PetscTableCreate  Creates a PETSc look up table

 37:    Input Parameters:
 38: +     n - expected number of keys
 39: -     maxkey- largest possible key

 41:    Notes: keys are between 1 and maxkey inclusive

 43: */
 44: PetscErrorCode  PetscTableCreate(const PetscInt n,PetscInt maxkey,PetscTable *rta)
 45: {
 46:   PetscTable     ta;

 50:   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"n < 0");
 51:   PetscNew(&ta);
 52:   PetscTableCreateHashSize(n,&ta->tablesize);
 53:   PetscCalloc1(ta->tablesize,&ta->keytable);
 54:   PetscMalloc1(ta->tablesize,&ta->table);
 55:   ta->head   = 0;
 56:   ta->count  = 0;
 57:   ta->maxkey = maxkey;
 58:   *rta       = ta;
 59:   return(0);
 60: }

 64: /* PetscTableCreate() ********************************************
 65:  *
 66:  * hash table for non-zero data and keys
 67:  *
 68:  */
 69: PetscErrorCode  PetscTableCreateCopy(const PetscTable intable,PetscTable *rta)
 70: {
 72:   PetscInt       i;
 73:   PetscTable     ta;

 76:   PetscNew(&ta);
 77:   ta->tablesize = intable->tablesize;
 78:   PetscMalloc1(ta->tablesize,&ta->keytable);
 79:   PetscMalloc1(ta->tablesize,&ta->table);
 80:   for (i = 0; i < ta->tablesize; i++) {
 81:     ta->keytable[i] = intable->keytable[i];
 82:     ta->table[i]    = intable->table[i];
 83: #if defined(PETSC_USE_DEBUG)
 84:     if (ta->keytable[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"ta->keytable[i] < 0");
 85: #endif
 86:   }
 87:   ta->head   = 0;
 88:   ta->count  = intable->count;
 89:   ta->maxkey = intable->maxkey;
 90:   *rta       = ta;
 91:   return(0);
 92: }

 96: /* PetscTableDestroy() ********************************************
 97:  *
 98:  *
 99:  */
100: PetscErrorCode  PetscTableDestroy(PetscTable *ta)
101: {

105:   if (!*ta) return(0);
106:   PetscFree((*ta)->keytable);
107:   PetscFree((*ta)->table);
108:   PetscFree(*ta);
109:   return(0);
110: }

114: /* PetscTableGetCount() ********************************************
115:  */
116: PetscErrorCode  PetscTableGetCount(const PetscTable ta,PetscInt *count)
117: {
119:   *count = ta->count;
120:   return(0);
121: }

125: /* PetscTableIsEmpty() ********************************************
126:  */
127: PetscErrorCode  PetscTableIsEmpty(const PetscTable ta,PetscInt *flag)
128: {
130:   *flag = !(ta->count);
131:   return(0);
132: }

136: /*
137:     PetscTableAddExpand - called by PetscTableAdd() if more space is needed

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

148:   PetscTableCreateHashSize(ta->tablesize,&ta->tablesize);
149:   PetscMalloc1(ta->tablesize,&ta->table);
150:   PetscCalloc1(ta->tablesize,&ta->keytable);

152:   ta->count = 0;
153:   ta->head  = 0;

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

166:   PetscFree(oldtab);
167:   PetscFree(oldkt);
168:   return(0);
169: }


174: /* PetscTableRemoveAll() ********************************************
175:  *
176:  *
177:  */
178: PetscErrorCode  PetscTableRemoveAll(PetscTable ta)
179: {

183:   ta->head = 0;
184:   if (ta->count) {
185:     ta->count = 0;

187:     PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));
188:   }
189:   return(0);
190: }



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: }

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

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

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


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

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

271:   ta->tablesize = PetscIntMultTruncate(2,ta->tablesize);
272:   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");
273:   PetscMalloc1(ta->tablesize,&ta->table);
274:   PetscCalloc1(ta->tablesize,&ta->keytable);

276:   ta->count = 0;
277:   ta->head  = 0;

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

290:   PetscFree(oldtab);
291:   PetscFree(oldkt);
292:   return(0);
293: }