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