Actual source code: ctable.c

  1: /* Contributed by - Mark Adams */

 3:  #include petsc.h
 4:  #include src/sys/ctable.h
  5: #if defined (PETSC_HAVE_LIMITS_H)
  6: #include <limits.h>
  7: #endif
  8: #define HASH_FACT 79943
  9: #define HASHT(ta,x) ((unsigned long)((HASH_FACT*(unsigned long)x)%ta->tablesize))

 13: /* PetscTableCreate() ********************************************
 14:  * 
 15:  * hash table for non-zero data and keys 
 16:  *
 17:  */
 18: PetscErrorCode PetscTableCreate(const PetscInt n,PetscTable *rta)
 19: {
 20:   PetscTable     ta;

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

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

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

 70: /* PetscTableDelete() ********************************************
 71:  * 
 72:  *
 73:  */
 74: PetscErrorCode PetscTableDelete(PetscTable ta)
 75: {

 79:   PetscFree(ta->keytable);
 80:   PetscFree(ta->table);
 81:   PetscFree(ta);
 82:   return(0);
 83: }
 86: /* PetscTableGetCount() ********************************************
 87:  */
 88: PetscErrorCode PetscTableGetCount(const PetscTable ta,PetscInt *count)
 89: {
 91:   *count = ta->count;
 92:   return(0);
 93: }

 97: /* PetscTableIsEmpty() ********************************************
 98:  */
 99: PetscErrorCode PetscTableIsEmpty(const PetscTable ta,PetscInt *flag)
100: {
102:   *flag = !(ta->count);
103:   return(0);
104: }

108: /* PetscTableAdd() ********************************************
109:  *
110:  */
111: PetscErrorCode PetscTableAdd(PetscTable ta,const PetscInt key,const PetscInt data)
112: {
114:   PetscInt       ii = 0,hash = HASHT(ta,key);
115:   const PetscInt tsize = ta->tablesize,tcount = ta->count;
116: 
118:   if (key <= 0) SETERRQ(PETSC_ERR_COR,"key <= 0");
119:   if (!data) SETERRQ(PETSC_ERR_COR,"Null data");
120: 
121:   if (ta->count < 5*(ta->tablesize/6) - 1) {
122:     while (ii++ < ta->tablesize){
123:       if (ta->keytable[hash] == key) {
124:         ta->table[hash] = data; /* over write */
125:         return(0);
126:       } else if (!ta->keytable[hash]) {
127:         ta->count++; /* add */
128:         ta->keytable[hash] = key; ta->table[hash] = data;
129:         return(0);
130:       }
131:       hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
132:     }
133:     SETERRQ(PETSC_ERR_COR,"Full table");
134:   } else {
135:     PetscInt *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;

137:     /* alloc new (bigger) table */
138:     if (ta->tablesize == INT_MAX/4) SETERRQ(PETSC_ERR_COR,"ta->tablesize < 0");
139:     ta->tablesize = 2*tsize;
140:     if (ta->tablesize <= tsize) ta->tablesize = INT_MAX/4;

142:     PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->table);
143:     PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->keytable);
144:     PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));

146:     ta->count     = 0;
147:     ta->head      = 0;
148: 
149:     PetscTableAdd(ta,key,data);
150:     /* rehash */
151:     for (ii = 0; ii < tsize; ii++) {
152:       newk = oldkt[ii];
153:       if (newk) {
154:         ndata = oldtab[ii];
155:         PetscTableAdd(ta,newk,ndata);
156:       }
157:     }
158:     if (ta->count != tcount + 1) SETERRQ(PETSC_ERR_COR,"corrupted ta->count");
159: 
160:     PetscFree(oldtab);
161:     PetscFree(oldkt);
162:   }
163:   return(0);
164: }

168: /* PetscTableRemoveAll() ********************************************
169:  *
170:  *
171:  */
172: PetscErrorCode PetscTableRemoveAll(PetscTable ta)
173: {

177:   ta->head = 0;
178:   if (ta->count) {
179:     ta->count = 0;
180:     PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));
181:   }
182:   return(0);
183: }

187: /* PetscTableFind() ********************************************
188:  *
189:  * returns data. If data==0, then no table entry exists.
190:  *
191:  */
192: PetscErrorCode PetscTableFind(PetscTable ta,const PetscInt key,PetscInt *data)
193: {
194:   PetscInt hash,ii = 0;

197:   if (!key) SETERRQ(PETSC_ERR_COR,"Null key");
198:   hash  = HASHT(ta,key);
199:   *data = 0;
200:   while (ii++ < ta->tablesize) {
201:     if (!ta->keytable[hash]) break;
202:     else if (ta->keytable[hash] == key) {
203:       *data = ta->table[hash];
204:       break;
205:     }
206:     hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
207:   }
208:   return(0);
209: }

213: /* PetscTableGetHeadPosition() ********************************************
214:  *
215:  */
216: PetscErrorCode PetscTableGetHeadPosition(PetscTable ta,PetscTablePosition *ppos)
217: {
218:   PetscInt i = 0;

221:   *ppos = NULL;
222:   if (!ta->count) return(0);
223: 
224:   /* find first valid place */
225:   do {
226:     if (ta->keytable[i]) {
227:       *ppos = (PetscTablePosition)&ta->table[i];
228:       break;
229:     }
230:   } while (i++ < ta->tablesize);
231:   if (!*ppos) SETERRQ(PETSC_ERR_COR,"No head");
232:   return(0);
233: }

237: /* PetscTableGetNext() ********************************************
238:  *
239:  *  - iteration - PetscTablePosition is always valid (points to a data)
240:  *  
241:  */
242: PetscErrorCode PetscTableGetNext(PetscTable ta,PetscTablePosition *rPosition,PetscInt *pkey,PetscInt *data)
243: {
244:   PetscInt           idex;
245:   PetscTablePosition pos;

248:   pos = *rPosition;
249:   if (!pos) SETERRQ(PETSC_ERR_COR,"Null position");
250:   *data = *pos;
251:   if (!*data) SETERRQ(PETSC_ERR_COR,"Null data");
252:   idex = pos - ta->table;
253:   *pkey = ta->keytable[idex];
254:   if (!*pkey) SETERRQ(PETSC_ERR_COR,"Null key");

256:   /* get next */
257:   do {
258:     pos++;  idex++;
259:     if (idex >= ta->tablesize) {
260:       pos = 0; /* end of list */
261:       break;
262:     } else if (ta->keytable[idex]) {
263:       pos = ta->table + idex;
264:       break;
265:     }
266:   } while (idex < ta->tablesize);
267:   *rPosition = pos;
268:   return(0);
269: }