Actual source code: ctable.c

  1: /*$Id: ctable.c,v 1.18 2001/03/23 23:20:45 balay Exp $*/
  2: /* Contributed by - Mark Adams */

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

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

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

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

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

 72: /* PetscTableDelete() ********************************************
 73:  * 
 74:  *
 75:  */
 76: int PetscTableDelete(PetscTable ta)
 77: {

 81:   PetscFree(ta->keytable);
 82:   PetscFree(ta->table);
 83:   PetscFree(ta);
 84:   return(0);
 85: }
 88: /* PetscTableGetCount() ********************************************
 89:  */
 90: int PetscTableGetCount(const PetscTable ta,int *count)
 91: {
 93:   *count = ta->count;
 94:   return(0);
 95: }

 99: /* PetscTableIsEmpty() ********************************************
100:  */
101: int PetscTableIsEmpty(const PetscTable ta,int *flag)
102: {
104:   *flag = !(ta->count);
105:   return(0);
106: }

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

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

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

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

169: /* PetscTableRemoveAll() ********************************************
170:  *
171:  *
172:  */
173: int PetscTableRemoveAll(PetscTable ta)
174: {

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

184:   return(0);
185: }

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

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

215: /* PetscTableGetHeadPosition() ********************************************
216:  *
217:  */
218: int PetscTableGetHeadPosition(PetscTable ta,PetscTablePosition *ppos)
219: {
220:   int i = 0;

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

235:   return(0);
236: }

240: /* PetscTableGetNext() ********************************************
241:  *
242:  *  - iteration - PetscTablePosition is always valid (points to a data)
243:  *  
244:  */
245: int PetscTableGetNext(PetscTable ta,PetscTablePosition *rPosition,int *pkey,int *data)
246: {
247:   int                idex;
248:   PetscTablePosition pos;

251:   pos = *rPosition;
252:   if (!pos) SETERRQ(1,"PetscTable error: PetscTable null position");
253:   *data = *pos;
254:   if (!*data) SETERRQ(1,"PetscTable error");
255:   idex = pos - ta->table;
256:   *pkey = ta->keytable[idex];
257:   if (!*pkey) SETERRQ(1,"PetscTable error");

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

271:   *rPosition = pos;

273:   return(0);
274: }