Actual source code: ctable.c
1: /* Contributed by - Mark Adams */
3: #include petsc.h
4: #include src/sys/ctable.h
5: #if defined (PETSC_HAVE_LIMITS_H)
6: #include <limits.h>
7: #endif
8: #define HASH_FACT 79943
9: #define HASHT(ta,x) ((unsigned long)((HASH_FACT*(unsigned long)x)%ta->tablesize))
13: /* PetscTableCreate() ********************************************
14: *
15: * hash table for non-zero data and keys
16: *
17: */
18: PetscErrorCode PetscTableCreate(const PetscInt n,PetscTable *rta)
19: {
20: PetscTable ta;
24: if (n < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"n < 0");
25: PetscNew(struct _p_PetscTable,&ta);
26: ta->tablesize = (3*n)/2 + 17;
27: if (ta->tablesize < n) ta->tablesize = INT_MAX/4; /* overflow */
28: PetscMalloc(sizeof(PetscInt)*ta->tablesize,&ta->keytable);
29: PetscMemzero(ta->keytable,sizeof(PetscInt)*ta->tablesize);
30: PetscMalloc(sizeof(PetscInt)*ta->tablesize,&ta->table);
31: ta->head = 0;
32: ta->count = 0;
33: *rta = ta;
34: return(0);
35: }
39: /* PetscTableCreate() ********************************************
40: *
41: * hash table for non-zero data and keys
42: *
43: */
44: PetscErrorCode PetscTableCreateCopy(const PetscTable intable,PetscTable *rta)
45: {
47: PetscInt i;
48: PetscTable ta;
51: PetscNew(struct _p_PetscTable,&ta);
52: ta->tablesize = intable->tablesize;
53: PetscMalloc(sizeof(PetscInt)*ta->tablesize,&ta->keytable);
54: PetscMalloc(sizeof(PetscInt)*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(PETSC_ERR_COR,"ta->keytable[i] < 0");
60: #endif
61: }
62: ta->head = 0;
63: ta->count = intable->count;
64: *rta = ta;
65: return(0);
66: }
70: /* PetscTableDelete() ********************************************
71: *
72: *
73: */
74: PetscErrorCode PetscTableDelete(PetscTable ta)
75: {
79: PetscFree(ta->keytable);
80: PetscFree(ta->table);
81: PetscFree(ta);
82: return(0);
83: }
86: /* PetscTableGetCount() ********************************************
87: */
88: PetscErrorCode PetscTableGetCount(const PetscTable ta,PetscInt *count)
89: {
91: *count = ta->count;
92: return(0);
93: }
97: /* PetscTableIsEmpty() ********************************************
98: */
99: PetscErrorCode PetscTableIsEmpty(const PetscTable ta,PetscInt *flag)
100: {
102: *flag = !(ta->count);
103: return(0);
104: }
108: /* PetscTableAdd() ********************************************
109: *
110: */
111: PetscErrorCode PetscTableAdd(PetscTable ta,const PetscInt key,const PetscInt data)
112: {
114: PetscInt ii = 0,hash = HASHT(ta,key);
115: const PetscInt tsize = ta->tablesize,tcount = ta->count;
116:
118: if (key <= 0) SETERRQ(PETSC_ERR_COR,"key <= 0");
119: if (!data) SETERRQ(PETSC_ERR_COR,"Null 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(PETSC_ERR_COR,"Full table");
134: } else {
135: PetscInt *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;
137: /* alloc new (bigger) table */
138: if (ta->tablesize == INT_MAX/4) SETERRQ(PETSC_ERR_COR,"ta->tablesize < 0");
139: ta->tablesize = 2*tsize;
140: if (ta->tablesize <= tsize) ta->tablesize = INT_MAX/4;
142: PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->table);
143: PetscMalloc(ta->tablesize*sizeof(PetscInt),&ta->keytable);
144: PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));
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: PetscTableAdd(ta,newk,ndata);
156: }
157: }
158: if (ta->count != tcount + 1) SETERRQ(PETSC_ERR_COR,"corrupted ta->count");
159:
160: PetscFree(oldtab);
161: PetscFree(oldkt);
162: }
163: return(0);
164: }
168: /* PetscTableRemoveAll() ********************************************
169: *
170: *
171: */
172: PetscErrorCode PetscTableRemoveAll(PetscTable ta)
173: {
177: ta->head = 0;
178: if (ta->count) {
179: ta->count = 0;
180: PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));
181: }
182: return(0);
183: }
187: /* PetscTableFind() ********************************************
188: *
189: * returns data. If data==0, then no table entry exists.
190: *
191: */
192: PetscErrorCode PetscTableFind(PetscTable ta,const PetscInt key,PetscInt *data)
193: {
194: PetscInt hash,ii = 0;
197: if (!key) SETERRQ(PETSC_ERR_COR,"Null key");
198: hash = HASHT(ta,key);
199: *data = 0;
200: while (ii++ < ta->tablesize) {
201: if (!ta->keytable[hash]) break;
202: else if (ta->keytable[hash] == key) {
203: *data = ta->table[hash];
204: break;
205: }
206: hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
207: }
208: return(0);
209: }
213: /* PetscTableGetHeadPosition() ********************************************
214: *
215: */
216: PetscErrorCode PetscTableGetHeadPosition(PetscTable ta,PetscTablePosition *ppos)
217: {
218: PetscInt i = 0;
221: *ppos = NULL;
222: if (!ta->count) return(0);
223:
224: /* find first valid place */
225: do {
226: if (ta->keytable[i]) {
227: *ppos = (PetscTablePosition)&ta->table[i];
228: break;
229: }
230: } while (i++ < ta->tablesize);
231: if (!*ppos) SETERRQ(PETSC_ERR_COR,"No head");
232: return(0);
233: }
237: /* PetscTableGetNext() ********************************************
238: *
239: * - iteration - PetscTablePosition is always valid (points to a data)
240: *
241: */
242: PetscErrorCode PetscTableGetNext(PetscTable ta,PetscTablePosition *rPosition,PetscInt *pkey,PetscInt *data)
243: {
244: PetscInt idex;
245: PetscTablePosition pos;
248: pos = *rPosition;
249: if (!pos) SETERRQ(PETSC_ERR_COR,"Null position");
250: *data = *pos;
251: if (!*data) SETERRQ(PETSC_ERR_COR,"Null data");
252: idex = pos - ta->table;
253: *pkey = ta->keytable[idex];
254: if (!*pkey) SETERRQ(PETSC_ERR_COR,"Null key");
256: /* get next */
257: do {
258: pos++; idex++;
259: if (idex >= ta->tablesize) {
260: pos = 0; /* end of list */
261: break;
262: } else if (ta->keytable[idex]) {
263: pos = ta->table + idex;
264: break;
265: }
266: } while (idex < ta->tablesize);
267: *rPosition = pos;
268: return(0);
269: }