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