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: #undef __FUNCT__
13: /* PetscTableCreate() ********************************************
14: *
15: * hash table for non-zero data and keys
16: *
17: */
18: int PetscTableCreate(const int n,PetscTable *rta)
19: {
20: PetscTable ta;
21: int ierr;
24: if(n < 0) SETERRQ(1,"PetscTable error: n < 0");
25: ierr = PetscNew(struct _p_PetscTable,&ta);
26: ta->tablesize = (3*n)/2 + 17;
27: if(ta->tablesize < n) ta->tablesize = INT_MAX/4; /* overflow */
28: ierr = PetscMalloc(sizeof(int)*ta->tablesize,&ta->keytable);
29: ierr = PetscMemzero(ta->keytable,sizeof(int)*ta->tablesize);
30: ierr = PetscMalloc(sizeof(int)*ta->tablesize,&ta->table);
31: ta->head = 0;
32: ta->count = 0;
33:
34: *rta = ta;
35: return(0);
36: }
38: #undef __FUNCT__
40: /* PetscTableCreate() ********************************************
41: *
42: * hash table for non-zero data and keys
43: *
44: */
45: int PetscTableCreateCopy(const PetscTable intable,PetscTable *rta)
46: {
47: int i,ierr;
48: PetscTable ta;
51: ierr = PetscNew(struct _p_PetscTable,&ta);
52: ta->tablesize = intable->tablesize;
53: ierr = PetscMalloc(sizeof(int)*ta->tablesize,&ta->keytable);
54: ierr = PetscMalloc(sizeof(int)*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(1,"TABLE error: ta->keytable[i] < 0");
60: #endif
61: }
62: ta->head = 0;
63: ta->count = intable->count;
64:
65: *rta = ta;
66: return(0);
67: }
69: #undef __FUNCT__
71: /* PetscTableDelete() ********************************************
72: *
73: *
74: */
75: int PetscTableDelete(PetscTable ta)
76: {
80: PetscFree(ta->keytable);
81: PetscFree(ta->table);
82: PetscFree(ta);
83: return(0);
84: }
85: #undef __FUNCT__
87: /* PetscTableGetCount() ********************************************
88: */
89: int PetscTableGetCount(const PetscTable ta,int *count)
90: {
92: *count = ta->count;
93: return(0);
94: }
96: #undef __FUNCT__
98: /* PetscTableIsEmpty() ********************************************
99: */
100: int PetscTableIsEmpty(const PetscTable ta,int *flag)
101: {
103: *flag = !(ta->count);
104: return(0);
105: }
107: #undef __FUNCT__
109: /* PetscTableAdd() ********************************************
110: *
111: */
112: int PetscTableAdd(PetscTable ta,const int key,const int data)
113: {
114: int ii = 0,hash = HASHT(ta,key),ierr;
115: const int tsize = ta->tablesize,tcount = ta->count;
116:
118: if (key <= 0) SETERRQ(1,"PetscTable error: key <= 0");
119: if (!data) SETERRQ(1,"PetscTable error: Table zero 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(1,"PetscTable error: full table");
134: } else {
135: int *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;
137: /* alloc new (bigger) table */
138: if(ta->tablesize == INT_MAX/4) SETERRQ(1,"PetscTable error: ta->tablesize < 0");
139: ta->tablesize = 2*tsize;
140: if (ta->tablesize <= tsize) ta->tablesize = INT_MAX/4;
142: PetscMalloc(ta->tablesize*sizeof(int),&ta->table);
143: PetscMalloc(ta->tablesize*sizeof(int),&ta->keytable);
144: PetscMemzero(ta->keytable,ta->tablesize*sizeof(int));
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: ierr = PetscTableAdd(ta,newk,ndata);
156: }
157: }
158: if (ta->count != tcount + 1) SETERRQ(1,"PetscTable error");
159:
160: PetscFree(oldtab);
161: PetscFree(oldkt);
162: }
163: return(0);
164: }
166: #undef __FUNCT__
168: /* PetscTableRemoveAll() ********************************************
169: *
170: *
171: */
172: int PetscTableRemoveAll(PetscTable ta)
173: {
177: ta->head = 0;
178: if (ta->count) {
179: ta->count = 0;
180: PetscMemzero(ta->keytable,ta->tablesize*sizeof(int));
181: }
183: return(0);
184: }
186: #undef __FUNCT__
188: /* PetscTableFind() ********************************************
189: *
190: * returns data. If data==0, then no table entry exists.
191: *
192: */
193: int PetscTableFind(PetscTable ta,const int key,int *data)
194: {
195: int hash,ii = 0;
198: if(!key) SETERRQ(1,"PetscTable error: PetscTable zero key");
199: hash = HASHT(ta,key);
200: *data = 0;
201: while (ii++ < ta->tablesize) {
202: if (!ta->keytable[hash]) break;
203: else if (ta->keytable[hash] == key) {
204: *data = ta->table[hash];
205: break;
206: }
207: hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
208: }
209: return(0);
210: }
212: #undef __FUNCT__
214: /* PetscTableGetHeadPosition() ********************************************
215: *
216: */
217: int PetscTableGetHeadPosition(PetscTable ta,PetscTablePosition *ppos)
218: {
219: int i = 0;
222: *ppos = NULL;
223: if (!ta->count) return(0);
224:
225: /* find first valid place */
226: do {
227: if (ta->keytable[i]) {
228: *ppos = (PetscTablePosition)&ta->table[i];
229: break;
230: }
231: } while (i++ < ta->tablesize);
232: if (!*ppos) SETERRQ(1,"TABLE error: No head");
234: return(0);
235: }
237: #undef __FUNCT__
239: /* PetscTableGetNext() ********************************************
240: *
241: * - iteration - PetscTablePosition is always valid (points to a data)
242: *
243: */
244: int PetscTableGetNext(PetscTable ta,PetscTablePosition *rPosition,int *pkey,int *data)
245: {
246: int idex;
247: PetscTablePosition pos;
250: pos = *rPosition;
251: if (!pos) SETERRQ(1,"PetscTable error: PetscTable null position");
252: *data = *pos;
253: if (!*data) SETERRQ(1,"PetscTable error");
254: idex = pos - ta->table;
255: *pkey = ta->keytable[idex];
256: if (!*pkey) SETERRQ(1,"PetscTable error");
258: /* get next */
259: do {
260: pos++; idex++;
261: if (idex >= ta->tablesize) {
262: pos = 0; /* end of list */
263: break;
264: } else if (ta->keytable[idex]) {
265: pos = ta->table + idex;
266: break;
267: }
268: } while (idex < ta->tablesize);
270: *rPosition = pos;
272: return(0);
273: }