Actual source code: ctable.c
petsc-3.7.5 2017-01-01
2: /* Contributed by - Mark Adams */
4: #include <petscsys.h>
5: #include <petscctable.h>
9: static PetscErrorCode PetscTableCreateHashSize(PetscInt sz, PetscInt *hsz)
10: {
12: if (sz < 100) *hsz = 139;
13: else if (sz < 200) *hsz = 283;
14: else if (sz < 400) *hsz = 577;
15: else if (sz < 800) *hsz = 1103;
16: else if (sz < 1600) *hsz = 2239;
17: else if (sz < 3200) *hsz = 4787;
18: else if (sz < 6400) *hsz = 9337;
19: else if (sz < 12800) *hsz = 17863;
20: else if (sz < 25600) *hsz = 37649;
21: else if (sz < 51200) *hsz = 72307;
22: else if (sz < 102400) *hsz = 142979;
23: else if (sz < 204800) *hsz = 299983;
24: else if (sz < 409600) *hsz = 599869;
25: else if (sz < 819200) *hsz = 1193557;
26: else if (sz < 1638400) *hsz = 2297059;
27: else if (sz < 3276800) *hsz = 4902383;
28: else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"A really huge hash is being requested.. cannot process: %D",sz);
29: return(0);
30: }
34: /*
35: PetscTableCreate Creates a PETSc look up table
37: Input Parameters:
38: + n - expected number of keys
39: - maxkey- largest possible key
41: Notes: keys are between 1 and maxkey inclusive
43: */
44: PetscErrorCode PetscTableCreate(const PetscInt n,PetscInt maxkey,PetscTable *rta)
45: {
46: PetscTable ta;
50: if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"n < 0");
51: PetscNew(&ta);
52: PetscTableCreateHashSize(n,&ta->tablesize);
53: PetscCalloc1(ta->tablesize,&ta->keytable);
54: PetscMalloc1(ta->tablesize,&ta->table);
55: ta->head = 0;
56: ta->count = 0;
57: ta->maxkey = maxkey;
58: *rta = ta;
59: return(0);
60: }
64: /* PetscTableCreate() ********************************************
65: *
66: * hash table for non-zero data and keys
67: *
68: */
69: PetscErrorCode PetscTableCreateCopy(const PetscTable intable,PetscTable *rta)
70: {
72: PetscInt i;
73: PetscTable ta;
76: PetscNew(&ta);
77: ta->tablesize = intable->tablesize;
78: PetscMalloc1(ta->tablesize,&ta->keytable);
79: PetscMalloc1(ta->tablesize,&ta->table);
80: for (i = 0; i < ta->tablesize; i++) {
81: ta->keytable[i] = intable->keytable[i];
82: ta->table[i] = intable->table[i];
83: #if defined(PETSC_USE_DEBUG)
84: if (ta->keytable[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"ta->keytable[i] < 0");
85: #endif
86: }
87: ta->head = 0;
88: ta->count = intable->count;
89: ta->maxkey = intable->maxkey;
90: *rta = ta;
91: return(0);
92: }
96: /* PetscTableDestroy() ********************************************
97: *
98: *
99: */
100: PetscErrorCode PetscTableDestroy(PetscTable *ta)
101: {
105: if (!*ta) return(0);
106: PetscFree((*ta)->keytable);
107: PetscFree((*ta)->table);
108: PetscFree(*ta);
109: return(0);
110: }
114: /* PetscTableGetCount() ********************************************
115: */
116: PetscErrorCode PetscTableGetCount(const PetscTable ta,PetscInt *count)
117: {
119: *count = ta->count;
120: return(0);
121: }
125: /* PetscTableIsEmpty() ********************************************
126: */
127: PetscErrorCode PetscTableIsEmpty(const PetscTable ta,PetscInt *flag)
128: {
130: *flag = !(ta->count);
131: return(0);
132: }
136: /*
137: PetscTableAddExpand - called by PetscTableAdd() if more space is needed
139: */
140: PetscErrorCode PetscTableAddExpand(PetscTable ta,PetscInt key,PetscInt data,InsertMode imode)
141: {
143: PetscInt ii = 0;
144: const PetscInt tsize = ta->tablesize,tcount = ta->count;
145: PetscInt *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;
148: PetscTableCreateHashSize(ta->tablesize,&ta->tablesize);
149: PetscMalloc1(ta->tablesize,&ta->table);
150: PetscCalloc1(ta->tablesize,&ta->keytable);
152: ta->count = 0;
153: ta->head = 0;
155: PetscTableAdd(ta,key,data,INSERT_VALUES);
156: /* rehash */
157: for (ii = 0; ii < tsize; ii++) {
158: newk = oldkt[ii];
159: if (newk) {
160: ndata = oldtab[ii];
161: PetscTableAdd(ta,newk,ndata,imode);
162: }
163: }
164: if (ta->count != tcount + 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"corrupted ta->count");
166: PetscFree(oldtab);
167: PetscFree(oldkt);
168: return(0);
169: }
174: /* PetscTableRemoveAll() ********************************************
175: *
176: *
177: */
178: PetscErrorCode PetscTableRemoveAll(PetscTable ta)
179: {
183: ta->head = 0;
184: if (ta->count) {
185: ta->count = 0;
187: PetscMemzero(ta->keytable,ta->tablesize*sizeof(PetscInt));
188: }
189: return(0);
190: }
196: /* PetscTableGetHeadPosition() ********************************************
197: *
198: */
199: PetscErrorCode PetscTableGetHeadPosition(PetscTable ta,PetscTablePosition *ppos)
200: {
201: PetscInt i = 0;
204: *ppos = NULL;
205: if (!ta->count) return(0);
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(PETSC_COMM_SELF,PETSC_ERR_COR,"No head");
215: return(0);
216: }
220: /* PetscTableGetNext() ********************************************
221: *
222: * - iteration - PetscTablePosition is always valid (points to a data)
223: *
224: */
225: PetscErrorCode PetscTableGetNext(PetscTable ta,PetscTablePosition *rPosition,PetscInt *pkey,PetscInt *data)
226: {
227: PetscInt idex;
228: PetscTablePosition pos;
231: pos = *rPosition;
232: if (!pos) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null position");
233: *data = *pos;
234: if (!*data) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null data");
235: idex = pos - ta->table;
236: *pkey = ta->keytable[idex];
237: if (!*pkey) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Null key");
239: /* get next */
240: do {
241: pos++; idex++;
242: if (idex >= ta->tablesize) {
243: pos = 0; /* end of list */
244: break;
245: } else if (ta->keytable[idex]) {
246: pos = ta->table + idex;
247: break;
248: }
249: } while (idex < ta->tablesize);
250: *rPosition = pos;
251: return(0);
252: }
257: PetscErrorCode PetscTableAddCountExpand(PetscTable ta,PetscInt key)
258: {
260: PetscInt ii = 0,hash = PetscHash(ta,key);
261: const PetscInt tsize = ta->tablesize,tcount = ta->count;
262: PetscInt *oldtab = ta->table,*oldkt = ta->keytable,newk,ndata;
265: /* before making the table larger check if key is already in table */
266: while (ii++ < tsize) {
267: if (ta->keytable[hash] == key) return(0);
268: hash = (hash == (ta->tablesize-1)) ? 0 : hash+1;
269: }
271: ta->tablesize = PetscIntMultTruncate(2,ta->tablesize);
272: if (tsize == ta->tablesize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Table is as large as possible; ./configure with the option --with-64-bit-integers to run this large case");
273: PetscMalloc1(ta->tablesize,&ta->table);
274: PetscCalloc1(ta->tablesize,&ta->keytable);
276: ta->count = 0;
277: ta->head = 0;
279: /* Build a new copy of the data */
280: for (ii = 0; ii < tsize; ii++) {
281: newk = oldkt[ii];
282: if (newk) {
283: ndata = oldtab[ii];
284: PetscTableAdd(ta,newk,ndata,INSERT_VALUES);
285: }
286: }
287: PetscTableAddCount(ta,key);
288: if (ta->count != tcount + 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"corrupted ta->count");
290: PetscFree(oldtab);
291: PetscFree(oldkt);
292: return(0);
293: }