1 #pragma once
2 #include <petscviewertypes.h>
3 #include <petscsys.h>
4 /*
5 Function pointer table that maps from function pointers to their string representation
6
7 Does not use the PetscFunctionBegin/Return() or PetscCall() because these routines are called within those macros
8 */
9 #define PetscCallQ(A) \
10 do { \
11 PetscErrorCode ierr = A; \
12 if (ierr) return ierr; \
13 } while (0);
14
15 typedef struct _n_PetscFPT *PetscFPT;
16 struct _n_PetscFPT {
17 void **functionpointer;
18 char **functionname;
19 PetscInt count;
20 unsigned long tablesize;
21 };
22 PETSC_INTERN PetscFPT PetscFPTData;
23
PetscFPTView(PetscViewer viewer)24 static inline PetscErrorCode PetscFPTView(PetscViewer viewer)
25 {
26 if (PetscFPTData) {
27 for (unsigned long i = 0; i < PetscFPTData->tablesize; ++i) {
28 if (PetscFPTData->functionpointer[i]) printf("%s()\n", PetscFPTData->functionname[i]);
29 }
30 }
31 return PETSC_SUCCESS;
32 }
33
PetscFPTDestroy(void)34 static inline PetscErrorCode PetscFPTDestroy(void)
35 {
36 PetscFPT data = PetscFPTData;
37
38 PetscFPTData = NULL;
39 if (!data) return PETSC_SUCCESS;
40 PetscCallQ(PetscFree(data->functionpointer));
41 PetscCallQ(PetscFree(data->functionname));
42 PetscCallQ(PetscFree(data));
43 return PETSC_SUCCESS;
44 }
45
46 /*
47 PetscFPTCreate Creates a PETSc look up table from function pointers to strings
48
49 Input Parameter:
50 . n - expected number of keys
51
52 */
PetscFPTCreate(PetscInt n)53 static inline PetscErrorCode PetscFPTCreate(PetscInt n)
54 {
55 PetscFPT _PetscFPTData;
56
57 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n < 0");
58 /* Cannot use PetscNew() here because it is not yet defined in the include file chain */
59 PetscCallQ(PetscMalloc(sizeof(struct _n_PetscFPT), &_PetscFPTData));
60 _PetscFPTData->tablesize = (3 * n) / 2 + 17;
61 if (_PetscFPTData->tablesize < (unsigned long)n) _PetscFPTData->tablesize = PETSC_INT_MAX / 4; /* overflow */
62 PetscCallQ(PetscCalloc(sizeof(void *) * _PetscFPTData->tablesize, &_PetscFPTData->functionpointer));
63 PetscCallQ(PetscMalloc(sizeof(char **) * _PetscFPTData->tablesize, &_PetscFPTData->functionname));
64 _PetscFPTData->count = 0;
65 PetscFPTData = _PetscFPTData;
66 return PETSC_SUCCESS;
67 }
68
PetscFPTHashPointer(void * ptr)69 static inline unsigned long PetscFPTHashPointer(void *ptr)
70 {
71 #define PETSC_FPT_HASH_FACT 79943
72 return (PETSC_FPT_HASH_FACT * ((size_t)ptr)) % PetscFPTData->tablesize;
73 }
74
PetscFPTAdd(void * key,const char * data)75 static inline PetscErrorCode PetscFPTAdd(void *key, const char *data)
76 {
77 PetscCheck(data, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Null function name");
78 if (!PetscFPTData) return PETSC_SUCCESS;
79 for (unsigned long i = 0, hash = PetscFPTHashPointer(key); i < PetscFPTData->tablesize; ++i) {
80 if (PetscFPTData->functionpointer[hash] == key) {
81 PetscFPTData->functionname[hash] = (char *)data;
82 return PETSC_SUCCESS;
83 } else if (!PetscFPTData->functionpointer[hash]) {
84 PetscFPTData->count++;
85 PetscFPTData->functionpointer[hash] = key;
86 PetscFPTData->functionname[hash] = (char *)data;
87 return PETSC_SUCCESS;
88 }
89 hash = (hash == (PetscFPTData->tablesize - 1)) ? 0 : hash + 1;
90 }
91 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Function pointer table is full");
92 }
93
94 /*
95 PetscFPTFind - checks if a function pointer is in the table
96
97 If data==0, then no entry exists
98
99 */
PetscFPTFind(void * key,char const ** data)100 static inline PetscErrorCode PetscFPTFind(void *key, char const **data)
101 {
102 unsigned long hash, ii = 0;
103
104 *data = NULL;
105 if (!PetscFPTData) return PETSC_SUCCESS;
106 hash = PetscFPTHashPointer(key);
107 while (ii++ < PetscFPTData->tablesize) {
108 if (!PetscFPTData->functionpointer[hash]) break;
109 else if (PetscFPTData->functionpointer[hash] == key) {
110 *data = PetscFPTData->functionname[hash];
111 break;
112 }
113 hash = (hash == (PetscFPTData->tablesize - 1)) ? 0 : hash + 1;
114 }
115 return PETSC_SUCCESS;
116 }
117