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