12eac72dbSBarry Smith /* 2f8256253SLois Curfman McInnes An index set is a generalization of a subset of integers. Index sets 3f8256253SLois Curfman McInnes are used for defining scatters and gathers. 42eac72dbSBarry Smith */ 50a835dfdSSatish Balay #if !defined(__PETSCIS_H) 60a835dfdSSatish Balay #define __PETSCIS_H 7d382aafbSBarry Smith #include "petscsys.h" 8a4d96a55SJed Brown #include "petscsf.h" 9e9fa29b7SSatish Balay PETSC_EXTERN_CXX_BEGIN 102eac72dbSBarry Smith 1197b48c8fSBarry Smith #define IS_FILE_CLASSID 1211218 127087cfbeSBarry Smith extern PetscClassId IS_CLASSID; 13f0479e8cSBarry Smith 147087cfbeSBarry Smith extern PetscErrorCode ISInitializePackage(const char[]); 152b6de112SBarry Smith 165c20da3cSBarry Smith /*S 17f22f69f0SBarry Smith IS - Abstract PETSc object that allows indexing. 185c20da3cSBarry Smith 195c20da3cSBarry Smith Level: beginner 205c20da3cSBarry Smith 215c20da3cSBarry Smith Concepts: indexing, stride 225c20da3cSBarry Smith 235c20da3cSBarry Smith .seealso: ISCreateGeneral(), ISCreateBlock(), ISCreateStride(), ISGetIndices(), ISDestroy() 245c20da3cSBarry Smith S*/ 25f09e8eb9SSatish Balay typedef struct _p_IS* IS; 262eac72dbSBarry Smith 2776bdecfbSBarry Smith /*J 2827bdab1eSBarry Smith ISType - String with the name of a PETSc vector or the creation function 2927bdab1eSBarry Smith with an optional dynamic library name, for example 3027bdab1eSBarry Smith http://www.mcs.anl.gov/petsc/lib.a:myveccreate() 3127bdab1eSBarry Smith 3227bdab1eSBarry Smith Level: beginner 3327bdab1eSBarry Smith 3427bdab1eSBarry Smith .seealso: ISSetType(), IS 3576bdecfbSBarry Smith J*/ 3627bdab1eSBarry Smith #define ISType char* 3727bdab1eSBarry Smith #define ISGENERAL "general" 3827bdab1eSBarry Smith #define ISSTRIDE "stride" 3927bdab1eSBarry Smith #define ISBLOCK "block" 4027bdab1eSBarry Smith 4127bdab1eSBarry Smith /* Dynamic creation and loading functions */ 4227bdab1eSBarry Smith extern PetscFList ISList; 4327bdab1eSBarry Smith extern PetscBool ISRegisterAllCalled; 447087cfbeSBarry Smith extern PetscErrorCode ISSetType(IS, const ISType); 457087cfbeSBarry Smith extern PetscErrorCode ISGetType(IS, const ISType *); 467087cfbeSBarry Smith extern PetscErrorCode ISRegister(const char[],const char[],const char[],PetscErrorCode (*)(IS)); 477087cfbeSBarry Smith extern PetscErrorCode ISRegisterAll(const char []); 487087cfbeSBarry Smith extern PetscErrorCode ISRegisterDestroy(void); 497087cfbeSBarry Smith extern PetscErrorCode ISCreate(MPI_Comm,IS*); 5027bdab1eSBarry Smith 5127bdab1eSBarry Smith /*MC 5227bdab1eSBarry Smith ISRegisterDynamic - Adds a new vector component implementation 5327bdab1eSBarry Smith 5427bdab1eSBarry Smith Synopsis: 5527bdab1eSBarry Smith PetscErrorCode ISRegisterDynamic(const char *name, const char *path, const char *func_name, PetscErrorCode (*create_func)(IS)) 5627bdab1eSBarry Smith 5727bdab1eSBarry Smith Not Collective 5827bdab1eSBarry Smith 5927bdab1eSBarry Smith Input Parameters: 6027bdab1eSBarry Smith + name - The name of a new user-defined creation routine 6127bdab1eSBarry Smith . path - The path (either absolute or relative) of the library containing this routine 6227bdab1eSBarry Smith . func_name - The name of routine to create method context 6327bdab1eSBarry Smith - create_func - The creation routine itself 6427bdab1eSBarry Smith 6527bdab1eSBarry Smith Notes: 6627bdab1eSBarry Smith ISRegisterDynamic() may be called multiple times to add several user-defined vectors 6727bdab1eSBarry Smith 6827bdab1eSBarry Smith If dynamic libraries are used, then the fourth input argument (routine_create) is ignored. 6927bdab1eSBarry Smith 7027bdab1eSBarry Smith Sample usage: 7127bdab1eSBarry Smith .vb 72bb7a0047SJed Brown ISRegisterDynamic("my_is_name","/home/username/my_lib/lib/libO/solaris/libmy.a", "MyISCreate", MyISCreate); 7327bdab1eSBarry Smith .ve 7427bdab1eSBarry Smith 7527bdab1eSBarry Smith Then, your vector type can be chosen with the procedural interface via 7627bdab1eSBarry Smith .vb 7727bdab1eSBarry Smith ISCreate(MPI_Comm, IS *); 78bb7a0047SJed Brown ISSetType(IS,"my_is_name"); 7927bdab1eSBarry Smith .ve 8027bdab1eSBarry Smith or at runtime via the option 8127bdab1eSBarry Smith .vb 82bb7a0047SJed Brown -is_type my_is_name 8327bdab1eSBarry Smith .ve 8427bdab1eSBarry Smith 8527bdab1eSBarry Smith Notes: $PETSC_ARCH occuring in pathname will be replaced with appropriate values. 8627bdab1eSBarry Smith If your function is not being put into a shared library then use ISRegister() instead 8727bdab1eSBarry Smith 88bb7a0047SJed Brown This is no ISSetFromOptions() and the current implementations do not have a way to dynamically determine type, so 89bb7a0047SJed Brown dynamic registration of custom IS types will be of limited use to users. 90bb7a0047SJed Brown 91bb7a0047SJed Brown Level: developer 9227bdab1eSBarry Smith 9327bdab1eSBarry Smith .keywords: IS, register 9427bdab1eSBarry Smith .seealso: ISRegisterAll(), ISRegisterDestroy(), ISRegister() 9527bdab1eSBarry Smith M*/ 9627bdab1eSBarry Smith #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 9727bdab1eSBarry Smith #define ISRegisterDynamic(a,b,c,d) ISRegister(a,b,c,0) 9827bdab1eSBarry Smith #else 9927bdab1eSBarry Smith #define ISRegisterDynamic(a,b,c,d) ISRegister(a,b,c,d) 10027bdab1eSBarry Smith #endif 10127bdab1eSBarry Smith 102639f9d9dSBarry Smith /* 103639f9d9dSBarry Smith Default index set data structures that PETSc provides. 104639f9d9dSBarry Smith */ 1057087cfbeSBarry Smith extern PetscErrorCode ISCreateGeneral(MPI_Comm,PetscInt,const PetscInt[],PetscCopyMode,IS *); 1067087cfbeSBarry Smith extern PetscErrorCode ISGeneralSetIndices(IS,PetscInt,const PetscInt[],PetscCopyMode); 1077087cfbeSBarry Smith extern PetscErrorCode ISCreateBlock(MPI_Comm,PetscInt,PetscInt,const PetscInt[],PetscCopyMode,IS *); 1087087cfbeSBarry Smith extern PetscErrorCode ISBlockSetIndices(IS,PetscInt,PetscInt,const PetscInt[],PetscCopyMode); 1097087cfbeSBarry Smith extern PetscErrorCode ISCreateStride(MPI_Comm,PetscInt,PetscInt,PetscInt,IS *); 1107087cfbeSBarry Smith extern PetscErrorCode ISStrideSetStride(IS,PetscInt,PetscInt,PetscInt); 1114b0e389bSBarry Smith 112fcfd50ebSBarry Smith extern PetscErrorCode ISDestroy(IS*); 1137087cfbeSBarry Smith extern PetscErrorCode ISSetPermutation(IS); 1147087cfbeSBarry Smith extern PetscErrorCode ISPermutation(IS,PetscBool *); 1157087cfbeSBarry Smith extern PetscErrorCode ISSetIdentity(IS); 1167087cfbeSBarry Smith extern PetscErrorCode ISIdentity(IS,PetscBool *); 1177087cfbeSBarry Smith extern PetscErrorCode ISContiguousLocal(IS,PetscInt,PetscInt,PetscInt*,PetscBool*); 11808480c60SBarry Smith 1197087cfbeSBarry Smith extern PetscErrorCode ISGetIndices(IS,const PetscInt *[]); 1207087cfbeSBarry Smith extern PetscErrorCode ISRestoreIndices(IS,const PetscInt *[]); 1217087cfbeSBarry Smith extern PetscErrorCode ISGetTotalIndices(IS,const PetscInt *[]); 1227087cfbeSBarry Smith extern PetscErrorCode ISRestoreTotalIndices(IS,const PetscInt *[]); 1237087cfbeSBarry Smith extern PetscErrorCode ISGetNonlocalIndices(IS,const PetscInt *[]); 1247087cfbeSBarry Smith extern PetscErrorCode ISRestoreNonlocalIndices(IS,const PetscInt *[]); 1257087cfbeSBarry Smith extern PetscErrorCode ISGetNonlocalIS(IS, IS *is); 1267087cfbeSBarry Smith extern PetscErrorCode ISRestoreNonlocalIS(IS, IS *is); 1277087cfbeSBarry Smith extern PetscErrorCode ISGetSize(IS,PetscInt *); 1287087cfbeSBarry Smith extern PetscErrorCode ISGetLocalSize(IS,PetscInt *); 1297087cfbeSBarry Smith extern PetscErrorCode ISInvertPermutation(IS,PetscInt,IS*); 1307087cfbeSBarry Smith extern PetscErrorCode ISView(IS,PetscViewer); 1317087cfbeSBarry Smith extern PetscErrorCode ISEqual(IS,IS,PetscBool *); 1327087cfbeSBarry Smith extern PetscErrorCode ISSort(IS); 1337087cfbeSBarry Smith extern PetscErrorCode ISSorted(IS,PetscBool *); 1347087cfbeSBarry Smith extern PetscErrorCode ISDifference(IS,IS,IS*); 1357087cfbeSBarry Smith extern PetscErrorCode ISSum(IS,IS,IS*); 1367087cfbeSBarry Smith extern PetscErrorCode ISExpand(IS,IS,IS*); 137612dd529SBarry Smith 1387087cfbeSBarry Smith extern PetscErrorCode ISBlockGetIndices(IS,const PetscInt *[]); 1397087cfbeSBarry Smith extern PetscErrorCode ISBlockRestoreIndices(IS,const PetscInt *[]); 1407087cfbeSBarry Smith extern PetscErrorCode ISBlockGetLocalSize(IS,PetscInt *); 1417087cfbeSBarry Smith extern PetscErrorCode ISBlockGetSize(IS,PetscInt *); 1427087cfbeSBarry Smith extern PetscErrorCode ISGetBlockSize(IS,PetscInt*); 1437087cfbeSBarry Smith extern PetscErrorCode ISSetBlockSize(IS,PetscInt); 144c16cb8f2SBarry Smith 1457087cfbeSBarry Smith extern PetscErrorCode ISStrideGetInfo(IS,PetscInt *,PetscInt*); 146c16cb8f2SBarry Smith 1477087cfbeSBarry Smith extern PetscErrorCode ISToGeneral(IS); 14838f40f24SLois Curfman McInnes 1497087cfbeSBarry Smith extern PetscErrorCode ISDuplicate(IS,IS*); 1507087cfbeSBarry Smith extern PetscErrorCode ISCopy(IS,IS); 1517087cfbeSBarry Smith extern PetscErrorCode ISAllGather(IS,IS*); 1527087cfbeSBarry Smith extern PetscErrorCode ISComplement(IS,PetscInt,PetscInt,IS*); 153bd6ba146SDmitry Karpeev extern PetscErrorCode ISConcatenate(MPI_Comm,PetscInt,const IS[],IS*); 154bd6ba146SDmitry Karpeev extern PetscErrorCode ISListToColoring(MPI_Comm,PetscInt, IS[],IS*,IS*); 155bd6ba146SDmitry Karpeev extern PetscErrorCode ISColoringToList(IS, IS, PetscInt*, IS *[]); 1567087cfbeSBarry Smith extern PetscErrorCode ISOnComm(IS,MPI_Comm,PetscCopyMode,IS*); 157d64ed03dSBarry Smith 15856cd22aeSBarry Smith /* --------------------------------------------------------------------------*/ 1597087cfbeSBarry Smith extern PetscClassId IS_LTOGM_CLASSID; 16056cd22aeSBarry Smith 1615c20da3cSBarry Smith /*S 162d9ffb7b8SBarry Smith ISLocalToGlobalMapping - mappings from an arbitrary 16390f02eecSBarry Smith local ordering from 0 to n-1 to a global PETSc ordering 164d4bb536fSBarry Smith used by a vector or matrix. 165d4bb536fSBarry Smith 1665c20da3cSBarry Smith Level: intermediate 1675c20da3cSBarry Smith 168d4bb536fSBarry Smith Note: mapping from Local to Global is scalable; but Global 169eec0b4cfSBarry Smith to Local may not be if the range of global values represented locally 170d4bb536fSBarry Smith is very large. 17174637425SBarry Smith 17274637425SBarry Smith Note: the ISLocalToGlobalMapping is actually a private object; it is included 173992144d0SBarry Smith here for the inline function ISLocalToGlobalMappingApply() to allow it to be inlined since 17474637425SBarry Smith it is used so often. 17574637425SBarry Smith 1765c20da3cSBarry Smith .seealso: ISLocalToGlobalMappingCreate() 1775c20da3cSBarry Smith S*/ 17874637425SBarry Smith struct _p_ISLocalToGlobalMapping{ 179011f5a45SSatish Balay PETSCHEADER(int); 18032dcc486SBarry Smith PetscInt n; /* number of local indices */ 18132dcc486SBarry Smith PetscInt *indices; /* global index of each local index */ 18232dcc486SBarry Smith PetscInt globalstart; /* first global referenced in indices */ 18332dcc486SBarry Smith PetscInt globalend; /* last + 1 global referenced in indices */ 18432dcc486SBarry Smith PetscInt *globals; /* local index for each global index between start and end */ 18574637425SBarry Smith }; 186f09e8eb9SSatish Balay typedef struct _p_ISLocalToGlobalMapping* ISLocalToGlobalMapping; 1875c20da3cSBarry Smith 1885c20da3cSBarry Smith /*E 1895c20da3cSBarry Smith ISGlobalToLocalMappingType - Indicates if missing global indices are 1905c20da3cSBarry Smith 1915c20da3cSBarry Smith IS_GTOLM_MASK - missing global indices are replaced with -1 1925c20da3cSBarry Smith IS_GTOLM_DROP - missing global indices are dropped 1935c20da3cSBarry Smith 1945c20da3cSBarry Smith Level: beginner 1955c20da3cSBarry Smith 1965c20da3cSBarry Smith .seealso: ISGlobalToLocalMappingApply() 1975c20da3cSBarry Smith 1985c20da3cSBarry Smith E*/ 199987e4450SSatish Balay typedef enum {IS_GTOLM_MASK,IS_GTOLM_DROP} ISGlobalToLocalMappingType; 20090f02eecSBarry Smith 2017087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm,PetscInt,const PetscInt[],PetscCopyMode,ISLocalToGlobalMapping*); 2027087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingCreateIS(IS,ISLocalToGlobalMapping *); 203a4d96a55SJed Brown extern PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF,PetscInt,ISLocalToGlobalMapping*); 2047087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping,PetscViewer); 205fcfd50ebSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping*); 2067087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping,IS,IS*); 2077087cfbeSBarry Smith extern PetscErrorCode ISGlobalToLocalMappingApply(ISLocalToGlobalMapping,ISGlobalToLocalMappingType,PetscInt,const PetscInt[],PetscInt*,PetscInt[]); 2087087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping,PetscInt*); 2097087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt*,PetscInt*[],PetscInt*[],PetscInt**[]); 2107087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping,PetscInt*,PetscInt*[],PetscInt*[],PetscInt**[]); 2117087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping,const PetscInt**); 2127087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping,const PetscInt**); 2137087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingBlock(ISLocalToGlobalMapping,PetscInt,ISLocalToGlobalMapping*); 2147087cfbeSBarry Smith extern PetscErrorCode ISLocalToGlobalMappingUnBlock(ISLocalToGlobalMapping,PetscInt,ISLocalToGlobalMapping*); 215f7efa3c7SJed Brown extern PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm,PetscInt,const ISLocalToGlobalMapping[],ISLocalToGlobalMapping*); 21674637425SBarry Smith 217fcfd50ebSBarry Smith #undef __FUNCT__ 218fcfd50ebSBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApply" 219d0f46423SBarry Smith PETSC_STATIC_INLINE PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[]) 220d0f46423SBarry Smith { 22153ef36baSBarry Smith PetscInt i,Nmax = mapping->n; 22253ef36baSBarry Smith const PetscInt *idx = mapping->indices; 223b7827b44SJed Brown PetscFunctionBegin; 2241620fd73SBarry Smith for (i=0; i<N; i++) { 2251620fd73SBarry Smith if (in[i] < 0) {out[i] = in[i]; continue;} 226e32f2f54SBarry Smith if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax,i); 2271620fd73SBarry Smith out[i] = idx[in[i]]; 2281620fd73SBarry Smith } 2291620fd73SBarry Smith PetscFunctionReturn(0); 23074637425SBarry Smith } 23190f02eecSBarry Smith 23256cd22aeSBarry Smith /* --------------------------------------------------------------------------*/ 233b9617806SBarry Smith /*E 234b9617806SBarry Smith ISColoringType - determines if the coloring is for the entire parallel grid/graph/matrix 235b9617806SBarry Smith or for just the local ghosted portion 236b9617806SBarry Smith 237b9617806SBarry Smith Level: beginner 238b9617806SBarry Smith 2398ee2e534SBarry Smith $ IS_COLORING_GLOBAL - does not include the colors for ghost points, this is used when the function 2408ee2e534SBarry Smith $ is called synchronously in parallel. This requires generating a "parallel coloring". 2418ee2e534SBarry Smith $ IS_COLORING_GHOSTED - includes colors for ghost points, this is used when the function can be called 2428ee2e534SBarry Smith $ seperately on individual processes with the ghost points already filled in. Does not 2438ee2e534SBarry Smith $ require a "parallel coloring", rather each process colors its local + ghost part. 2448ee2e534SBarry Smith $ Using this can result in much less parallel communication. In the paradigm of 2459a42bb27SBarry Smith $ DMGetLocalVector() and DMGetGlobalVector() this could be called IS_COLORING_LOCAL 24673d7d85fSBarry Smith 247e727c939SJed Brown .seealso: DMCreateColoring() 248b9617806SBarry Smith E*/ 2498ee2e534SBarry Smith typedef enum {IS_COLORING_GLOBAL,IS_COLORING_GHOSTED} ISColoringType; 250a34d58ebSBarry Smith extern const char *ISColoringTypes[]; 2516c09f170SSatish Balay typedef unsigned PETSC_IS_COLOR_VALUE_TYPE ISColoringValue; 2527087cfbeSBarry Smith extern PetscErrorCode ISAllGatherColors(MPI_Comm,PetscInt,ISColoringValue*,PetscInt*,ISColoringValue*[]); 253dde82324SBarry Smith 2545c20da3cSBarry Smith /*S 255dde82324SBarry Smith ISColoring - sets of IS's that define a coloring 256639f9d9dSBarry Smith of the underlying indices 2575c20da3cSBarry Smith 2585c20da3cSBarry Smith Level: intermediate 2595c20da3cSBarry Smith 2605c20da3cSBarry Smith Notes: 261b9617806SBarry Smith One should not access the *is records below directly because they may not yet 2625c20da3cSBarry Smith have been created. One should use ISColoringGetIS() to make sure they are 2635c20da3cSBarry Smith created when needed. 2645c20da3cSBarry Smith 265*a5057860SBarry Smith Developer Note: this is not a PetscObject 266*a5057860SBarry Smith 2675c20da3cSBarry Smith .seealso: ISColoringCreate(), ISColoringGetIS(), ISColoringView(), ISColoringGetIS() 2685c20da3cSBarry Smith S*/ 26995fbd943SSatish Balay struct _n_ISColoring { 270a7cc72afSBarry Smith PetscInt refct; 271a7cc72afSBarry Smith PetscInt n; /* number of colors */ 2725c20da3cSBarry Smith IS *is; /* for each color indicates columns */ 273639f9d9dSBarry Smith MPI_Comm comm; 27408b6dcc0SBarry Smith ISColoringValue *colors; /* for each column indicates color */ 27532dcc486SBarry Smith PetscInt N; /* number of columns */ 276b9617806SBarry Smith ISColoringType ctype; 277639f9d9dSBarry Smith }; 27895fbd943SSatish Balay typedef struct _n_ISColoring* ISColoring; 279639f9d9dSBarry Smith 2807087cfbeSBarry Smith extern PetscErrorCode ISColoringCreate(MPI_Comm,PetscInt,PetscInt,const ISColoringValue[],ISColoring*); 281fcfd50ebSBarry Smith extern PetscErrorCode ISColoringDestroy(ISColoring*); 2827087cfbeSBarry Smith extern PetscErrorCode ISColoringView(ISColoring,PetscViewer); 2837087cfbeSBarry Smith extern PetscErrorCode ISColoringGetIS(ISColoring,PetscInt*,IS*[]); 2847087cfbeSBarry Smith extern PetscErrorCode ISColoringRestoreIS(ISColoring,IS*[]); 2853a7fca6bSBarry Smith #define ISColoringReference(coloring) ((coloring)->refct++,0) 2863a7fca6bSBarry Smith #define ISColoringSetType(coloring,type) ((coloring)->ctype = type,0) 2873a7fca6bSBarry Smith 288dbef8a1cSBarry Smith /* --------------------------------------------------------------------------*/ 289dbef8a1cSBarry Smith 2907087cfbeSBarry Smith extern PetscErrorCode ISPartitioningToNumbering(IS,IS*); 2917087cfbeSBarry Smith extern PetscErrorCode ISPartitioningCount(IS,PetscInt,PetscInt[]); 292dbef8a1cSBarry Smith 29305d8c843SHong Zhang extern PetscErrorCode ISCompressIndicesGeneral(PetscInt,PetscInt,PetscInt,PetscInt,const IS[],IS[]); 2947087cfbeSBarry Smith extern PetscErrorCode ISCompressIndicesSorted(PetscInt,PetscInt,PetscInt,const IS[],IS[]); 29505d8c843SHong Zhang extern PetscErrorCode ISExpandIndicesGeneral(PetscInt,PetscInt,PetscInt,PetscInt,const IS[],IS[]); 296d9489beaSHong Zhang 297e9fa29b7SSatish Balay PETSC_EXTERN_CXX_END 2989e03d832SJed Brown 2999e03d832SJed Brown /* Reset __FUNCT__ in case the user does not define it themselves */ 3009e03d832SJed Brown #undef __FUNCT__ 3019e03d832SJed Brown #define __FUNCT__ "User provided function" 3029e03d832SJed Brown 303a2ce50c7SBarry Smith #endif 304