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 HASHT(ta,x) ((3*x)%ta->tablesize)

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

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

 36: /* PetscTableCreate() ********************************************
 37:  * 
 38:  * hash table for non-zero data and keys 
 39:  *
 40:  */
 41: int PetscTableCreateCopy(const PetscTable intable,PetscTable *rta)
 42: {
 43:   int        i,ierr;
 44:   PetscTable ta;

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

 65: /* PetscTableDelete() ********************************************
 66:  * 
 67:  *
 68:  */
 69: int PetscTableDelete(PetscTable ta)
 70: {

 74:   PetscFree(ta->keytable);
 75:   PetscFree(ta->table);
 76:   PetscFree(ta);
 77:   return(0);
 78: }
 79: /* PetscTableGetCount() ********************************************
 80:  */
 81: int PetscTableGetCount(const PetscTable ta,int *count)
 82: {
 84:   *count = ta->count;
 85:   return(0);
 86: }

 88: /* PetscTableIsEmpty() ********************************************
 89:  */
 90: int PetscTableIsEmpty(const PetscTable ta,int *flag)
 91: {
 93:   *flag = !(ta->count);
 94:   return(0);
 95: }

 97: /* PetscTableAdd() ********************************************
 98:  *
 99:  */
100: int PetscTableAdd(PetscTable ta,const int key,const int data)
101: {
102:   int       ii = 0,hash = HASHT(ta,key),ierr;
103:   const int tsize = ta->tablesize,tcount = ta->count;
104: 
106:   if (key <= 0) SETERRQ(1,"PetscTable error: key <= 0");
107:   if (!data) SETERRQ(1,"PetscTable error: Table zero data");
108: 
109:   if (ta->count < 5*(ta->tablesize/6) - 1) {
110:     while (ii++ < ta->tablesize){
111:       if (ta->keytable[hash] == key) {
112:         ta->table[hash] = data; /* over write */
113:         return(0);
114:       } else if (!ta->keytable[hash]) {
115:         ta->count++; /* add */
116:         ta->keytable[hash] = key; ta->table[hash] = data;
117:         return(0);
118:       }
119:       hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
120:     }
121:     SETERRQ(1,"PetscTable error: full table");
122:   } else {
123:     int *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;

125:     /* alloc new (bigger) table */
126:     if(ta->tablesize == INT_MAX/4) SETERRQ(1,"PetscTable error: ta->tablesize < 0");
127:     ta->tablesize = 2*tsize;
128:     if (ta->tablesize <= tsize) ta->tablesize = INT_MAX/4;

130:     PetscMalloc(ta->tablesize*sizeof(int),&ta->table);
131:     PetscMalloc(ta->tablesize*sizeof(int),&ta->keytable);
132:     PetscMemzero(ta->keytable,ta->tablesize*sizeof(int));

134:     ta->count     = 0;
135:     ta->head      = 0;
136: 
137:     PetscTableAdd(ta,key,data);
138:     /* rehash */
139:     for (ii = 0; ii < tsize; ii++) {
140:       newk = oldkt[ii];
141:       if (newk) {
142:         ndata = oldtab[ii];
143:         ierr  = PetscTableAdd(ta,newk,ndata);
144:       }
145:     }
146:     if (ta->count != tcount + 1) SETERRQ(1,"PetscTable error");
147: 
148:     PetscFree(oldtab);
149:     PetscFree(oldkt);
150:   }
151:   return(0);
152: }

154: /* PetscTableRemoveAll() ********************************************
155:  *
156:  *
157:  */
158: int PetscTableRemoveAll(PetscTable ta)
159: {

163:   ta->head = 0;
164:   if (ta->count) {
165:     ta->count = 0;
166:     PetscMemzero(ta->keytable,ta->tablesize*sizeof(int));
167:   }

169:   return(0);
170: }

172: /* PetscTableFind() ********************************************
173:  *
174:  * returns data. If data==0, then no table entry exists.
175:  *
176:  */
177: int PetscTableFind(PetscTable ta,const int key,int *data)
178: {
179:   int hash,ii = 0;

182:   if(!key) SETERRQ(1,"PetscTable error: PetscTable zero key");
183:   hash = HASHT(ta,key);
184:   *data = 0;
185:   while (ii++ < ta->tablesize) {
186:     if (!ta->keytable[hash]) break;
187:     else if (ta->keytable[hash] == key) {
188:       *data = ta->table[hash];
189:       break;
190:     }
191:     hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
192:   }
193:   return(0);
194: }

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

204:   *ppos = NULL;
205:   if (!ta->count) return(0);
206: 
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(1,"TABLE error: No head");

216:   return(0);
217: }

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

230:   pos = *rPosition;
231:   if (!pos) SETERRQ(1,"PetscTable error: PetscTable null position");
232:   *data = *pos;
233:   if (!*data) SETERRQ(1,"PetscTable error");
234:   index = pos - ta->table;
235:   *pkey = ta->keytable[index];
236:   if (!*pkey) SETERRQ(1,"PetscTable error");

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

250:   *rPosition = pos;

252:   return(0);
253: }