xref: /petsc/include/petsc/private/petscfptimpl.h (revision e7dfef6fe55161823ad808feb7b24ef448a5fa5f)
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