xref: /petsc/include/petscmacros.h (revision 6797ed33bfc5684cca29e5d9b9bbfc6c8aac93e0)
1bde483f2SJacob Faibussowitsch #ifndef PETSC_PREPROCESSOR_MACROS_H
2bde483f2SJacob Faibussowitsch #define PETSC_PREPROCESSOR_MACROS_H
3bde483f2SJacob Faibussowitsch 
4bde483f2SJacob Faibussowitsch #include <petscconf.h>
5bde483f2SJacob Faibussowitsch #include <petscconf_poison.h> /* for PetscDefined() error checking */
6bde483f2SJacob Faibussowitsch 
7ac09b921SBarry Smith /* SUBMANSEC = Sys */
8ac09b921SBarry Smith 
90e6b6b59SJacob Faibussowitsch #if defined(__cplusplus)
100e6b6b59SJacob Faibussowitsch #if __cplusplus <= 201103L
110e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 11
120e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 201402L
130e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 14
140e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 201703L
150e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 17
160e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 202002L
170e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 20
180e6b6b59SJacob Faibussowitsch #else
190e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
200e6b6b59SJacob Faibussowitsch #endif
210e6b6b59SJacob Faibussowitsch #endif // __cplusplus
220e6b6b59SJacob Faibussowitsch 
230e6b6b59SJacob Faibussowitsch #ifndef PETSC_CPP_VERSION
240e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 0
250e6b6b59SJacob Faibussowitsch #endif
260e6b6b59SJacob Faibussowitsch 
27*6797ed33SJacob Faibussowitsch #if defined(__STDC_VERSION__)
28*6797ed33SJacob Faibussowitsch #if __STDC_VERSION__ <= 199901L
29*6797ed33SJacob Faibussowitsch // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
30*6797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 9
31*6797ed33SJacob Faibussowitsch #elif __STDC_VERSION__ <= 201112L
32*6797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 11
33*6797ed33SJacob Faibussowitsch #elif __STDC_VERSION__ <= 201710L
34*6797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 17
35*6797ed33SJacob Faibussowitsch #else
36*6797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
37*6797ed33SJacob Faibussowitsch #endif
38*6797ed33SJacob Faibussowitsch #endif // __STDC_VERSION__
39*6797ed33SJacob Faibussowitsch 
40*6797ed33SJacob Faibussowitsch #ifndef PETSC_C_VERSION
41*6797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 0
42*6797ed33SJacob Faibussowitsch #endif
43*6797ed33SJacob Faibussowitsch 
44bde483f2SJacob Faibussowitsch /* ========================================================================== */
45bde483f2SJacob Faibussowitsch /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
46bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
47bde483f2SJacob Faibussowitsch #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
48bde483f2SJacob Faibussowitsch #else
49bde483f2SJacob Faibussowitsch #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
50bde483f2SJacob Faibussowitsch #endif
51bde483f2SJacob Faibussowitsch 
52bde483f2SJacob Faibussowitsch /* ========================================================================== */
53bde483f2SJacob Faibussowitsch /* Since PETSc manages its own extern "C" handling users should never include PETSc include
54bde483f2SJacob Faibussowitsch  * files within extern "C". This will generate a compiler error if a user does put the include
55bde483f2SJacob Faibussowitsch  * file within an extern "C".
56bde483f2SJacob Faibussowitsch  */
57bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
589371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(int);
599371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(double);
60bde483f2SJacob Faibussowitsch #endif
61bde483f2SJacob Faibussowitsch 
62bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
63bde483f2SJacob Faibussowitsch #define PETSC_RESTRICT PETSC_CXX_RESTRICT
64bde483f2SJacob Faibussowitsch #else
656ee8c794SJacob Faibussowitsch #define PETSC_RESTRICT restrict
66bde483f2SJacob Faibussowitsch #endif
67bde483f2SJacob Faibussowitsch 
686ee8c794SJacob Faibussowitsch #define PETSC_INLINE        PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_INLINE is deprecated (since version 3.17)\"") inline
699fbee547SJacob Faibussowitsch #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_STATIC_INLINE is deprecated (since version 3.17)\"") static inline
70bde483f2SJacob Faibussowitsch 
71bde483f2SJacob Faibussowitsch #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
72bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT __declspec(dllexport)
73bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT __declspec(dllimport)
74bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL
75bde483f2SJacob Faibussowitsch #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
76bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
77bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
78bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
79bde483f2SJacob Faibussowitsch #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
80bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
81bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
82bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
83bde483f2SJacob Faibussowitsch #else
84bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT
85bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT
86bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL
87bde483f2SJacob Faibussowitsch #endif
88bde483f2SJacob Faibussowitsch 
89bde483f2SJacob Faibussowitsch #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
90bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT
91bde483f2SJacob Faibussowitsch #else /* Win32 users need this to import symbols from petsc.dll */
92bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
93bde483f2SJacob Faibussowitsch #endif
94bde483f2SJacob Faibussowitsch 
95bde483f2SJacob Faibussowitsch /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
96bde483f2SJacob Faibussowitsch  * compiled with C++ so they may be used from C and are always visible in the shared libraries
97bde483f2SJacob Faibussowitsch  */
98bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
99bde483f2SJacob Faibussowitsch #define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
100bde483f2SJacob Faibussowitsch #define PETSC_EXTERN_TYPEDEF extern "C"
101bde483f2SJacob Faibussowitsch #define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
102bde483f2SJacob Faibussowitsch #else
103bde483f2SJacob Faibussowitsch #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
104bde483f2SJacob Faibussowitsch #define PETSC_EXTERN_TYPEDEF
105bde483f2SJacob Faibussowitsch #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
106bde483f2SJacob Faibussowitsch #endif
107bde483f2SJacob Faibussowitsch 
108bde483f2SJacob Faibussowitsch #if defined(PETSC_USE_SINGLE_LIBRARY)
109bde483f2SJacob Faibussowitsch #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
110bde483f2SJacob Faibussowitsch #else
111bde483f2SJacob Faibussowitsch #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
112bde483f2SJacob Faibussowitsch #endif
113bde483f2SJacob Faibussowitsch 
114bde483f2SJacob Faibussowitsch /*MC
115bde483f2SJacob Faibussowitsch   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
116bde483f2SJacob Faibussowitsch 
117bde483f2SJacob Faibussowitsch   Synopsis:
118bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
119bde483f2SJacob Faibussowitsch   boolean PetscHasAttribute(name)
120bde483f2SJacob Faibussowitsch 
121bde483f2SJacob Faibussowitsch   Input Parameter:
122bde483f2SJacob Faibussowitsch . name - The name of the attribute to test
123bde483f2SJacob Faibussowitsch 
124bde483f2SJacob Faibussowitsch   Notes:
125bde483f2SJacob Faibussowitsch   name should be identical to what you might pass to the __attribute__ declaration itself --
126bde483f2SJacob Faibussowitsch   plain, unbroken text.
127bde483f2SJacob Faibussowitsch 
12887497f52SBarry Smith   As `PetscHasAttribute()` is wrapper over the function-like macro __has_attribute(), the exact
129bde483f2SJacob Faibussowitsch   type and value returned is implementation defined. In practice however, it usually returns
130bde483f2SJacob Faibussowitsch   the integer literal 1 if the attribute is supported, and integer literal 0 if the attribute
131bde483f2SJacob Faibussowitsch   is not supported.
132bde483f2SJacob Faibussowitsch 
133bde483f2SJacob Faibussowitsch   Example Usage:
134bde483f2SJacob Faibussowitsch   Typical usage is using the preprocessor
135bde483f2SJacob Faibussowitsch 
136bde483f2SJacob Faibussowitsch .vb
137bde483f2SJacob Faibussowitsch   #if PetscHasAttribute(always_inline)
138bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
139bde483f2SJacob Faibussowitsch   #else
140bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE
141bde483f2SJacob Faibussowitsch   #endif
142bde483f2SJacob Faibussowitsch 
143bde483f2SJacob Faibussowitsch   void foo(void) MY_ALWAYS_INLINE;
144bde483f2SJacob Faibussowitsch .ve
145bde483f2SJacob Faibussowitsch 
146bde483f2SJacob Faibussowitsch   but it can also be used in regular code
147bde483f2SJacob Faibussowitsch 
148bde483f2SJacob Faibussowitsch .vb
149bde483f2SJacob Faibussowitsch   if (PetscHasAttribute(some_attribute)) {
150bde483f2SJacob Faibussowitsch     foo();
151bde483f2SJacob Faibussowitsch   } else {
152bde483f2SJacob Faibussowitsch     bar();
153bde483f2SJacob Faibussowitsch   }
154bde483f2SJacob Faibussowitsch .ve
155bde483f2SJacob Faibussowitsch 
156bde483f2SJacob Faibussowitsch   Level: intermediate
157bde483f2SJacob Faibussowitsch 
158db781477SPatrick Sanan .seealso: `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`, `PETSC_ATTRIBUTE_FORMAT`
159bde483f2SJacob Faibussowitsch M*/
160bde483f2SJacob Faibussowitsch #if !defined(__has_attribute)
161bde483f2SJacob Faibussowitsch #define __has_attribute(x) 0
162bde483f2SJacob Faibussowitsch #endif
163bde483f2SJacob Faibussowitsch #define PetscHasAttribute(name) __has_attribute(name)
164bde483f2SJacob Faibussowitsch 
16593d501b3SJacob Faibussowitsch #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
16693d501b3SJacob Faibussowitsch /*
16793d501b3SJacob Faibussowitsch    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
16893d501b3SJacob Faibussowitsch    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
16993d501b3SJacob Faibussowitsch    does not match the actual type of the argument being passed in
17093d501b3SJacob Faibussowitsch */
17193d501b3SJacob Faibussowitsch #if PetscHasAttribute(pointer_with_type_tag)
17293d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
17393d501b3SJacob Faibussowitsch #endif
17493d501b3SJacob Faibussowitsch 
17593d501b3SJacob Faibussowitsch #if PetscHasAttribute(type_tag_for_datatype)
17693d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
17793d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
17893d501b3SJacob Faibussowitsch #endif
17993d501b3SJacob Faibussowitsch #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
18093d501b3SJacob Faibussowitsch 
18193d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
18293d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
18393d501b3SJacob Faibussowitsch #endif
18493d501b3SJacob Faibussowitsch 
18593d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
18693d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
18793d501b3SJacob Faibussowitsch #endif
18893d501b3SJacob Faibussowitsch 
18993d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
19093d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
19193d501b3SJacob Faibussowitsch #endif
19293d501b3SJacob Faibussowitsch 
193bde483f2SJacob Faibussowitsch /*MC
19463a3b9bcSJacob Faibussowitsch   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
19563a3b9bcSJacob Faibussowitsch   as format specifiers and checked for validity
19663a3b9bcSJacob Faibussowitsch 
19763a3b9bcSJacob Faibussowitsch   Synopsis:
19863a3b9bcSJacob Faibussowitsch   #include <petscmacros.h>
19963a3b9bcSJacob Faibussowitsch   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
20063a3b9bcSJacob Faibussowitsch 
20163a3b9bcSJacob Faibussowitsch   Input Parameters:
20263a3b9bcSJacob Faibussowitsch + strIdx   - The (1-indexed) location of the format string in the argument list
20363a3b9bcSJacob Faibussowitsch - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
20463a3b9bcSJacob Faibussowitsch 
20563a3b9bcSJacob Faibussowitsch   Notes:
20663a3b9bcSJacob Faibussowitsch   This function attribute causes the compiler to issue warnings when the format specifier does
20763a3b9bcSJacob Faibussowitsch   not match the type of the variable that will be formatted, or when there exists a mismatch
20863a3b9bcSJacob Faibussowitsch   between the number of format specifiers and variables to be formatted. It is safe to use this
20963a3b9bcSJacob Faibussowitsch   macro if your compiler does not support format specifier checking (though this is
21063a3b9bcSJacob Faibussowitsch   exceeedingly rare).
21163a3b9bcSJacob Faibussowitsch 
21263a3b9bcSJacob Faibussowitsch   Both strIdx and vaArgIdx must be compile-time constant integer literals and cannot have the
21363a3b9bcSJacob Faibussowitsch   same value.
21463a3b9bcSJacob Faibussowitsch 
21563a3b9bcSJacob Faibussowitsch   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
21663a3b9bcSJacob Faibussowitsch   the argument list, that is, there is no way to indicate gaps which should not be checked.
21763a3b9bcSJacob Faibussowitsch 
21887497f52SBarry Smith   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
21963a3b9bcSJacob Faibussowitsch   header files. In this case the macro will expand empty.
22063a3b9bcSJacob Faibussowitsch 
22163a3b9bcSJacob Faibussowitsch   Example Usage:
22263a3b9bcSJacob Faibussowitsch .vb
22363a3b9bcSJacob Faibussowitsch   // format string is 2nd argument, variable argument list containing args is 3rd argument
22463a3b9bcSJacob Faibussowitsch   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
22563a3b9bcSJacob Faibussowitsch 
22663a3b9bcSJacob Faibussowitsch   int    x = 1;
22763a3b9bcSJacob Faibussowitsch   double y = 50.0;
22863a3b9bcSJacob Faibussowitsch 
22963a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
23063a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
23163a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d %g",x,y); // OK
23263a3b9bcSJacob Faibussowitsch .ve
23363a3b9bcSJacob Faibussowitsch 
23463a3b9bcSJacob Faibussowitsch   Level: developer
23563a3b9bcSJacob Faibussowitsch 
236db781477SPatrick Sanan .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
23763a3b9bcSJacob Faibussowitsch M*/
23863a3b9bcSJacob Faibussowitsch #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
23963a3b9bcSJacob Faibussowitsch #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
24063a3b9bcSJacob Faibussowitsch #else
24163a3b9bcSJacob Faibussowitsch #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
24263a3b9bcSJacob Faibussowitsch #endif
24363a3b9bcSJacob Faibussowitsch 
24463a3b9bcSJacob Faibussowitsch /*MC
245d8e4614bSJacob Faibussowitsch   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
246d8e4614bSJacob Faibussowitsch   executed
247d8e4614bSJacob Faibussowitsch 
248d8e4614bSJacob Faibussowitsch   Notes:
249d8e4614bSJacob Faibussowitsch   The marked function is often optimized for size rather than speed and may be grouped alongside
250d8e4614bSJacob Faibussowitsch   other equally frigid routines improving code locality of lukewarm or hotter parts of program.
251d8e4614bSJacob Faibussowitsch 
252d8e4614bSJacob Faibussowitsch   The paths leading to cold functions are usually automatically marked as unlikely by the
253d8e4614bSJacob Faibussowitsch   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
254d8e4614bSJacob Faibussowitsch   as error handlers -- as cold to improve optimization of the surrounding temperate functions.
255d8e4614bSJacob Faibussowitsch 
256d8e4614bSJacob Faibussowitsch   Example Usage:
257d8e4614bSJacob Faibussowitsch .vb
258d8e4614bSJacob Faibussowitsch   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
259d8e4614bSJacob Faibussowitsch 
260d8e4614bSJacob Faibussowitsch   if (temperature < 0) {
261d8e4614bSJacob Faibussowitsch     return my_error_handler(...); // chilly!
262d8e4614bSJacob Faibussowitsch   }
263d8e4614bSJacob Faibussowitsch .ve
264d8e4614bSJacob Faibussowitsch 
265d8e4614bSJacob Faibussowitsch   Level: intermediate
266d8e4614bSJacob Faibussowitsch 
267db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
268db781477SPatrick Sanan           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
269d8e4614bSJacob Faibussowitsch M*/
270d8e4614bSJacob Faibussowitsch #if PetscHasAttribute(__cold__)
271d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
272d8e4614bSJacob Faibussowitsch #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
273d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
274d8e4614bSJacob Faibussowitsch #else
275d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD
276d8e4614bSJacob Faibussowitsch #endif
277d8e4614bSJacob Faibussowitsch 
278d8e4614bSJacob Faibussowitsch /*MC
279bde483f2SJacob Faibussowitsch   PETSC_NULLPTR - Standard way of indicating a null value or pointer
280bde483f2SJacob Faibussowitsch 
281bde483f2SJacob Faibussowitsch   Notes:
282bde483f2SJacob Faibussowitsch   Equivalent to NULL in C source, and nullptr in C++ source. Note that for the purposes of
28387497f52SBarry Smith   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
284bde483f2SJacob Faibussowitsch   equivalent to setting the same pointer to NULL in C. That is to say that the following
285bde483f2SJacob Faibussowitsch   expressions are equivalent\:
286bde483f2SJacob Faibussowitsch 
287bde483f2SJacob Faibussowitsch .vb
288bde483f2SJacob Faibussowitsch   ptr == PETSC_NULLPTR
289bde483f2SJacob Faibussowitsch   ptr == NULL
290bde483f2SJacob Faibussowitsch   ptr == 0
291bde483f2SJacob Faibussowitsch   !ptr
292bde483f2SJacob Faibussowitsch 
293bde483f2SJacob Faibussowitsch   ptr = PETSC_NULLPTR
294bde483f2SJacob Faibussowitsch   ptr = NULL
295bde483f2SJacob Faibussowitsch   ptr = 0
296bde483f2SJacob Faibussowitsch .ve
297bde483f2SJacob Faibussowitsch 
298bde483f2SJacob Faibussowitsch   and for completeness' sake\:
299bde483f2SJacob Faibussowitsch 
300bde483f2SJacob Faibussowitsch .vb
301bde483f2SJacob Faibussowitsch   PETSC_NULLPTR == NULL
302bde483f2SJacob Faibussowitsch .ve
303bde483f2SJacob Faibussowitsch 
304bde483f2SJacob Faibussowitsch   Fortran Notes:
305bde483f2SJacob Faibussowitsch   Not available in Fortran
306bde483f2SJacob Faibussowitsch 
307bde483f2SJacob Faibussowitsch   Example Usage:
308bde483f2SJacob Faibussowitsch .vb
309bde483f2SJacob Faibussowitsch   // may be used in place of '\0' or other such teminators in the definition of char arrays
310bde483f2SJacob Faibussowitsch   const char *const MyEnumTypes[] = {
311bde483f2SJacob Faibussowitsch     "foo",
312bde483f2SJacob Faibussowitsch     "bar",
313bde483f2SJacob Faibussowitsch     PETSC_NULLPTR
314bde483f2SJacob Faibussowitsch   };
315bde483f2SJacob Faibussowitsch 
316bde483f2SJacob Faibussowitsch   // may be used to nullify objects
317bde483f2SJacob Faibussowitsch   PetscObject obj = PETSC_NULLPTR;
318bde483f2SJacob Faibussowitsch 
319bde483f2SJacob Faibussowitsch   // may be used in any function expecting NULL
320bde483f2SJacob Faibussowitsch   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
321bde483f2SJacob Faibussowitsch .ve
322bde483f2SJacob Faibussowitsch 
323bde483f2SJacob Faibussowitsch   Developer Notes:
32487497f52SBarry Smith   `PETSC_NULLPTR` must be used in place of NULL in all C++ source files. Using NULL in source
325bde483f2SJacob Faibussowitsch   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
326bde483f2SJacob Faibussowitsch   resolution and/or compiler warnings.
327bde483f2SJacob Faibussowitsch 
328bde483f2SJacob Faibussowitsch   Level: beginner
329bde483f2SJacob Faibussowitsch 
330db781477SPatrick Sanan .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
331817da375SSatish Balay M*/
332bde483f2SJacob Faibussowitsch 
333bde483f2SJacob Faibussowitsch /*MC
334bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 - C++14 constexpr
335bde483f2SJacob Faibussowitsch 
336bde483f2SJacob Faibussowitsch   Notes:
337bde483f2SJacob Faibussowitsch   Equivalent to constexpr when using a C++ compiler that supports C++14. Expands to nothing
338bde483f2SJacob Faibussowitsch   if the C++ compiler does not suppport C++14 or when not compiling with a C++ compiler. Note
339bde483f2SJacob Faibussowitsch   that this cannot be used in cases where an empty expansion would result in invalid code. It
340bde483f2SJacob Faibussowitsch   is safe to use this in C source files.
341bde483f2SJacob Faibussowitsch 
342bde483f2SJacob Faibussowitsch   Fortran Notes:
343bde483f2SJacob Faibussowitsch   Not available in Fortran
344bde483f2SJacob Faibussowitsch 
345bde483f2SJacob Faibussowitsch   Example Usage:
346bde483f2SJacob Faibussowitsch .vb
347bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 int factorial(int n)
348bde483f2SJacob Faibussowitsch   {
349bde483f2SJacob Faibussowitsch     int r = 1;
350bde483f2SJacob Faibussowitsch 
351bde483f2SJacob Faibussowitsch     do {
352bde483f2SJacob Faibussowitsch       r *= n;
353bde483f2SJacob Faibussowitsch     } while (--n);
354bde483f2SJacob Faibussowitsch     return r;
355bde483f2SJacob Faibussowitsch   }
356bde483f2SJacob Faibussowitsch .ve
357bde483f2SJacob Faibussowitsch 
358bde483f2SJacob Faibussowitsch   Level: beginner
359bde483f2SJacob Faibussowitsch 
360db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
361817da375SSatish Balay M*/
362bde483f2SJacob Faibussowitsch 
363bde483f2SJacob Faibussowitsch /*MC
364bde483f2SJacob Faibussowitsch   PETSC_NODISCARD - Mark the return value of a function as non-discardable
365bde483f2SJacob Faibussowitsch 
366bde483f2SJacob Faibussowitsch   Notes:
367bde483f2SJacob Faibussowitsch   Hints to the compiler that the return value of a function must be captured. A diagnostic may
368bde483f2SJacob Faibussowitsch   (but is not required) be emitted if the value is discarded. It is safe to use this in C
369bde483f2SJacob Faibussowitsch   and C++ source files.
370bde483f2SJacob Faibussowitsch 
371bde483f2SJacob Faibussowitsch   Fortran Notes:
372bde483f2SJacob Faibussowitsch   Not available in Fortran
373bde483f2SJacob Faibussowitsch 
374bde483f2SJacob Faibussowitsch   Example Usage:
375bde483f2SJacob Faibussowitsch .vb
376bde483f2SJacob Faibussowitsch   class Foo
377bde483f2SJacob Faibussowitsch   {
378bde483f2SJacob Faibussowitsch     int x;
379bde483f2SJacob Faibussowitsch 
380bde483f2SJacob Faibussowitsch   public:
381bde483f2SJacob Faibussowitsch     PETSC_NODISCARD Foo(int y) : x(y) { }
382bde483f2SJacob Faibussowitsch   };
383bde483f2SJacob Faibussowitsch 
384bde483f2SJacob Faibussowitsch   PETSC_NODISCARD int factorial(int n)
385bde483f2SJacob Faibussowitsch   {
386bde483f2SJacob Faibussowitsch     return n <= 1 ? 1 : (n * factorial(n - 1));
387bde483f2SJacob Faibussowitsch   }
388bde483f2SJacob Faibussowitsch 
389bde483f2SJacob Faibussowitsch   auto x = factorial(10); // OK, capturing return value
390bde483f2SJacob Faibussowitsch   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
391bde483f2SJacob Faibussowitsch 
392bde483f2SJacob Faibussowitsch   auto f = Foo(x); // OK, capturing constructed object
393bde483f2SJacob Faibussowitsch   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
394bde483f2SJacob Faibussowitsch .ve
395bde483f2SJacob Faibussowitsch 
396bde483f2SJacob Faibussowitsch   Developer Notes:
397bde483f2SJacob Faibussowitsch   It is highly recommended if not downright required that any PETSc routines written in C++
39887497f52SBarry Smith   returning a PetscErrorCode be marked `PETSC_NODISCARD`. Ignoring the return value of PETSc
399bde483f2SJacob Faibussowitsch   routines is not supported; unhandled errors may leave PETSc in an unrecoverable state.
400bde483f2SJacob Faibussowitsch 
401bde483f2SJacob Faibussowitsch   Level: beginner
402bde483f2SJacob Faibussowitsch 
403db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
404817da375SSatish Balay M*/
405bde483f2SJacob Faibussowitsch 
406bde483f2SJacob Faibussowitsch /* C++11 features */
4076ee8c794SJacob Faibussowitsch #if defined(__cplusplus)
408bde483f2SJacob Faibussowitsch #define PETSC_NULLPTR nullptr
409bde483f2SJacob Faibussowitsch #else
410bde483f2SJacob Faibussowitsch #define PETSC_NULLPTR NULL
411bde483f2SJacob Faibussowitsch #endif
412bde483f2SJacob Faibussowitsch 
413bde483f2SJacob Faibussowitsch /* C++14 features */
4140e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 14
4156ee8c794SJacob Faibussowitsch #define PETSC_CONSTEXPR_14 constexpr
416bde483f2SJacob Faibussowitsch #else
417bde483f2SJacob Faibussowitsch #define PETSC_CONSTEXPR_14
418bde483f2SJacob Faibussowitsch #endif
419bde483f2SJacob Faibussowitsch 
420bde483f2SJacob Faibussowitsch /* C++17 features */
4210e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 17
422bde483f2SJacob Faibussowitsch #define PETSC_NODISCARD    [[nodiscard]]
4230e6b6b59SJacob Faibussowitsch #define PETSC_CONSTEXPR_17 constexpr
424bde483f2SJacob Faibussowitsch #else
425bde483f2SJacob Faibussowitsch #if PetscHasAttribute(warn_unused_result)
426bde483f2SJacob Faibussowitsch #define PETSC_NODISCARD __attribute__((warn_unused_result))
427bde483f2SJacob Faibussowitsch #endif
4280e6b6b59SJacob Faibussowitsch #define PETSC_CONSTEXPR_17
4290e6b6b59SJacob Faibussowitsch #endif
4300e6b6b59SJacob Faibussowitsch 
4310e6b6b59SJacob Faibussowitsch #ifndef PETSC_NODISCARD
4320e6b6b59SJacob Faibussowitsch #define PETSC_NODISCARD
433bde483f2SJacob Faibussowitsch #endif
434bde483f2SJacob Faibussowitsch 
435bde483f2SJacob Faibussowitsch #include <petscversion.h>
436bde483f2SJacob Faibussowitsch #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
437bde483f2SJacob Faibussowitsch 
438267267bdSJacob Faibussowitsch /* designated initializers since C99 and C++20, MSVC never supports them though */
4390e6b6b59SJacob Faibussowitsch #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
440267267bdSJacob Faibussowitsch #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
441267267bdSJacob Faibussowitsch #else
442267267bdSJacob Faibussowitsch #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
443267267bdSJacob Faibussowitsch #endif
444267267bdSJacob Faibussowitsch 
445bde483f2SJacob Faibussowitsch /*MC
44687497f52SBarry Smith   PetscUnlikely - Hints the compiler that the given condition is usually false
447bde483f2SJacob Faibussowitsch 
448bde483f2SJacob Faibussowitsch   Synopsis:
449bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
450bde483f2SJacob Faibussowitsch   bool PetscUnlikely(bool cond)
451bde483f2SJacob Faibussowitsch 
452bde483f2SJacob Faibussowitsch   Not Collective
453bde483f2SJacob Faibussowitsch 
454bde483f2SJacob Faibussowitsch   Input Parameter:
455bde483f2SJacob Faibussowitsch . cond - Boolean expression
456bde483f2SJacob Faibussowitsch 
457bde483f2SJacob Faibussowitsch   Notes:
458bde483f2SJacob Faibussowitsch   Not available from fortran.
459bde483f2SJacob Faibussowitsch 
460bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
461bde483f2SJacob Faibussowitsch   unlikely to be true.
462bde483f2SJacob Faibussowitsch 
463bde483f2SJacob Faibussowitsch   Example usage:
464bde483f2SJacob Faibussowitsch .vb
465bde483f2SJacob Faibussowitsch   if (PetscUnlikely(cond)) {
466bde483f2SJacob Faibussowitsch     foo(); // cold path
467bde483f2SJacob Faibussowitsch   } else {
468bde483f2SJacob Faibussowitsch     bar(); // hot path
469bde483f2SJacob Faibussowitsch   }
470bde483f2SJacob Faibussowitsch .ve
471bde483f2SJacob Faibussowitsch 
472bde483f2SJacob Faibussowitsch   Level: advanced
473bde483f2SJacob Faibussowitsch 
474db781477SPatrick Sanan .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
475db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
476bde483f2SJacob Faibussowitsch M*/
477bde483f2SJacob Faibussowitsch 
478bde483f2SJacob Faibussowitsch /*MC
47987497f52SBarry Smith   PetscLikely - Hints the compiler that the given condition is usually true
480bde483f2SJacob Faibussowitsch 
481bde483f2SJacob Faibussowitsch   Synopsis:
482bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
483bde483f2SJacob Faibussowitsch   bool PetscLikely(bool cond)
484bde483f2SJacob Faibussowitsch 
485bde483f2SJacob Faibussowitsch   Not Collective
486bde483f2SJacob Faibussowitsch 
487bde483f2SJacob Faibussowitsch   Input Parameter:
488bde483f2SJacob Faibussowitsch . cond - Boolean expression
489bde483f2SJacob Faibussowitsch 
490bde483f2SJacob Faibussowitsch   Notes:
491bde483f2SJacob Faibussowitsch   Not available from fortran.
492bde483f2SJacob Faibussowitsch 
493bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
494bde483f2SJacob Faibussowitsch   likely to be true.
495bde483f2SJacob Faibussowitsch 
496bde483f2SJacob Faibussowitsch   Example usage:
497bde483f2SJacob Faibussowitsch .vb
498bde483f2SJacob Faibussowitsch   if (PetscLikely(cond)) {
499bde483f2SJacob Faibussowitsch     foo(); // hot path
500bde483f2SJacob Faibussowitsch   } else {
501bde483f2SJacob Faibussowitsch     bar(); // cold path
502bde483f2SJacob Faibussowitsch   }
503bde483f2SJacob Faibussowitsch .ve
504bde483f2SJacob Faibussowitsch 
505bde483f2SJacob Faibussowitsch   Level: advanced
506bde483f2SJacob Faibussowitsch 
507db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
508db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
509bde483f2SJacob Faibussowitsch M*/
510bde483f2SJacob Faibussowitsch #if defined(PETSC_HAVE_BUILTIN_EXPECT)
511bde483f2SJacob Faibussowitsch #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
512bde483f2SJacob Faibussowitsch #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
513bde483f2SJacob Faibussowitsch #else
514bde483f2SJacob Faibussowitsch #define PetscUnlikely(cond) (cond)
515bde483f2SJacob Faibussowitsch #define PetscLikely(cond)   (cond)
516bde483f2SJacob Faibussowitsch #endif
517bde483f2SJacob Faibussowitsch 
518bde483f2SJacob Faibussowitsch /*MC
519817da375SSatish Balay   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
520bde483f2SJacob Faibussowitsch 
521bde483f2SJacob Faibussowitsch   Synopsis:
522bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
523bde483f2SJacob Faibussowitsch   void PetscUnreachable(void)
524bde483f2SJacob Faibussowitsch 
525bde483f2SJacob Faibussowitsch   Notes:
526bde483f2SJacob Faibussowitsch   Indicates to the compiler (usually via some built-in) that a particular code path is always
527bde483f2SJacob Faibussowitsch   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
528bde483f2SJacob Faibussowitsch   unceremonious crash.
529bde483f2SJacob Faibussowitsch 
530bde483f2SJacob Faibussowitsch   Example usage:
531bde483f2SJacob Faibussowitsch   Useful in situations such as switches over enums where not all enumeration values are
532bde483f2SJacob Faibussowitsch   explicitly covered by the switch
533bde483f2SJacob Faibussowitsch 
534bde483f2SJacob Faibussowitsch .vb
535bde483f2SJacob Faibussowitsch   typedef enum {RED, GREEN, BLUE} Color;
536bde483f2SJacob Faibussowitsch 
537bde483f2SJacob Faibussowitsch   int foo(Color c)
538bde483f2SJacob Faibussowitsch   {
539bde483f2SJacob Faibussowitsch     // it is known to programmer (or checked previously) that c is either RED or GREEN
540bde483f2SJacob Faibussowitsch     // but compiler may not be able to deduce this and/or emit spurious warnings
541bde483f2SJacob Faibussowitsch     switch (c) {
542bde483f2SJacob Faibussowitsch       case RED:
543bde483f2SJacob Faibussowitsch         return bar();
544bde483f2SJacob Faibussowitsch       case GREEN:
545bde483f2SJacob Faibussowitsch         return baz();
546bde483f2SJacob Faibussowitsch       default:
547bde483f2SJacob Faibussowitsch         PetscUnreachable(); // program is ill-formed if executed
548bde483f2SJacob Faibussowitsch     }
549bde483f2SJacob Faibussowitsch   }
550bde483f2SJacob Faibussowitsch .ve
551bde483f2SJacob Faibussowitsch 
552bde483f2SJacob Faibussowitsch   Level: advanced
553bde483f2SJacob Faibussowitsch 
554db781477SPatrick Sanan .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`
555817da375SSatish Balay M*/
556e58a63e1SJacob Faibussowitsch #if defined(__GNUC__)
557e58a63e1SJacob Faibussowitsch /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
558e58a63e1SJacob Faibussowitsch #define PetscUnreachable() __builtin_unreachable()
559e58a63e1SJacob Faibussowitsch #elif defined(_MSC_VER) /* MSVC */
560e58a63e1SJacob Faibussowitsch #define PetscUnreachable() __assume(0)
561e58a63e1SJacob Faibussowitsch #else /* ??? */
562e58a63e1SJacob Faibussowitsch #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
563e58a63e1SJacob Faibussowitsch #endif
564bde483f2SJacob Faibussowitsch 
565bde483f2SJacob Faibussowitsch /*MC
566bde483f2SJacob Faibussowitsch   PetscExpand - Expand macro argument
567bde483f2SJacob Faibussowitsch 
568bde483f2SJacob Faibussowitsch   Synopsis:
569bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
570bde483f2SJacob Faibussowitsch   <macro-expansion> PetscExpand(x)
571bde483f2SJacob Faibussowitsch 
5726aad120cSJose E. Roman   Input Parameter:
573bde483f2SJacob Faibussowitsch . x - The preprocessor token to expand
574bde483f2SJacob Faibussowitsch 
57549762cbcSSatish Balay   Level: beginner
57649762cbcSSatish Balay 
577db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscConcat()`
578817da375SSatish Balay M*/
579e58a63e1SJacob Faibussowitsch #define PetscExpand_(...) __VA_ARGS__
580e58a63e1SJacob Faibussowitsch #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
581bde483f2SJacob Faibussowitsch 
582bde483f2SJacob Faibussowitsch /*MC
583bde483f2SJacob Faibussowitsch   PetscStringize - Stringize a token
584bde483f2SJacob Faibussowitsch 
585bde483f2SJacob Faibussowitsch   Synopsis:
586bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
587bde483f2SJacob Faibussowitsch   const char* PetscStringize(x)
588bde483f2SJacob Faibussowitsch 
589bde483f2SJacob Faibussowitsch   Input Parameter:
590bde483f2SJacob Faibussowitsch . x - The token you would like to stringize
591bde483f2SJacob Faibussowitsch 
592bde483f2SJacob Faibussowitsch   Output Parameter:
593bde483f2SJacob Faibussowitsch . <return-value> - The string representation of x
594bde483f2SJacob Faibussowitsch 
595bde483f2SJacob Faibussowitsch   Notes:
596bde483f2SJacob Faibussowitsch   Not available from Fortran.
597bde483f2SJacob Faibussowitsch 
598bde483f2SJacob Faibussowitsch   PetscStringize() expands x before stringizing it, if you do not wish to do so, use
599bde483f2SJacob Faibussowitsch   PetscStringize_() instead.
600bde483f2SJacob Faibussowitsch 
601bde483f2SJacob Faibussowitsch   Example Usage:
602bde483f2SJacob Faibussowitsch .vb
603bde483f2SJacob Faibussowitsch   #define MY_OTHER_VAR hello there
604bde483f2SJacob Faibussowitsch   #define MY_VAR       MY_OTHER_VAR
605bde483f2SJacob Faibussowitsch 
606bde483f2SJacob Faibussowitsch   PetscStringize(MY_VAR)  -> "hello there"
607bde483f2SJacob Faibussowitsch   PetscStringize_(MY_VAR) -> "MY_VAR"
608bde483f2SJacob Faibussowitsch 
609bde483f2SJacob Faibussowitsch   int foo;
610bde483f2SJacob Faibussowitsch   PetscStringize(foo)  -> "foo"
611bde483f2SJacob Faibussowitsch   PetscStringize_(foo) -> "foo"
612bde483f2SJacob Faibussowitsch .ve
613bde483f2SJacob Faibussowitsch 
614bde483f2SJacob Faibussowitsch   Level: beginner
615bde483f2SJacob Faibussowitsch 
616db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
617817da375SSatish Balay M*/
6180e6b6b59SJacob Faibussowitsch #define PetscStringize_(...) #__VA_ARGS__
6190e6b6b59SJacob Faibussowitsch #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
620bde483f2SJacob Faibussowitsch 
621bde483f2SJacob Faibussowitsch /*MC
622bde483f2SJacob Faibussowitsch   PetscConcat - Concatenate two tokens
623bde483f2SJacob Faibussowitsch 
624bde483f2SJacob Faibussowitsch   Synopsis:
625bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
626bde483f2SJacob Faibussowitsch   <macro-expansion> PetscConcat(x, y)
627bde483f2SJacob Faibussowitsch 
628bde483f2SJacob Faibussowitsch   Input Parameters:
629bde483f2SJacob Faibussowitsch + x - First token
630bde483f2SJacob Faibussowitsch - y - Second token
631bde483f2SJacob Faibussowitsch 
632bde483f2SJacob Faibussowitsch   Notes:
633bde483f2SJacob Faibussowitsch   Not available from Fortran.
634bde483f2SJacob Faibussowitsch 
635bde483f2SJacob Faibussowitsch   PetscConcat() will expand both arguments before pasting them together, use PetscConcat_()
636bde483f2SJacob Faibussowitsch   if you don't want to expand them.
637bde483f2SJacob Faibussowitsch 
638bde483f2SJacob Faibussowitsch   Example usage:
639bde483f2SJacob Faibussowitsch .vb
640bde483f2SJacob Faibussowitsch   PetscConcat(hello,there) -> hellothere
641bde483f2SJacob Faibussowitsch 
642bde483f2SJacob Faibussowitsch   #define HELLO hello
643bde483f2SJacob Faibussowitsch   PetscConcat(HELLO,there)  -> hellothere
644bde483f2SJacob Faibussowitsch   PetscConcat_(HELLO,there) -> HELLOthere
645bde483f2SJacob Faibussowitsch .ve
646bde483f2SJacob Faibussowitsch 
647bde483f2SJacob Faibussowitsch   Level: beginner
648bde483f2SJacob Faibussowitsch 
649db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscExpand()`
650817da375SSatish Balay M*/
651bde483f2SJacob Faibussowitsch #define PetscConcat_(x, y) x##y
652bde483f2SJacob Faibussowitsch #define PetscConcat(x, y)  PetscConcat_(x, y)
653bde483f2SJacob Faibussowitsch 
654bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_0 1
655bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_1 0
656bde483f2SJacob Faibussowitsch 
657bde483f2SJacob Faibussowitsch /*MC
658bde483f2SJacob Faibussowitsch   PetscCompl - Expands to the integer complement of its argument
659bde483f2SJacob Faibussowitsch 
660bde483f2SJacob Faibussowitsch   Synopsis:
661bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
662bde483f2SJacob Faibussowitsch   int PetscCompl(b)
663bde483f2SJacob Faibussowitsch 
664bde483f2SJacob Faibussowitsch   Input Parameter:
665bde483f2SJacob Faibussowitsch . b - Preprocessor variable, must expand to either integer literal 0 or 1
666bde483f2SJacob Faibussowitsch 
6676aad120cSJose E. Roman   Output Parameter:
668bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
669bde483f2SJacob Faibussowitsch 
670bde483f2SJacob Faibussowitsch   Notes:
671bde483f2SJacob Faibussowitsch   Not available from Fortran.
672bde483f2SJacob Faibussowitsch 
673bde483f2SJacob Faibussowitsch   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
674bde483f2SJacob Faibussowitsch   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
675bde483f2SJacob Faibussowitsch   argument before returning the complement.
676bde483f2SJacob Faibussowitsch 
677bde483f2SJacob Faibussowitsch   This macro can be useful for negating PetscDefined() inside macros e.g.
678bde483f2SJacob Faibussowitsch 
679bde483f2SJacob Faibussowitsch $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
680bde483f2SJacob Faibussowitsch 
681bde483f2SJacob Faibussowitsch   Example usage:
682bde483f2SJacob Faibussowitsch .vb
683bde483f2SJacob Faibussowitsch   #define MY_VAR 1
684bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 0
685bde483f2SJacob Faibussowitsch 
686bde483f2SJacob Faibussowitsch   #undef  MY_VAR
687bde483f2SJacob Faibussowitsch   #define MY_VAR 0
688bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 1
689bde483f2SJacob Faibussowitsch .ve
690bde483f2SJacob Faibussowitsch 
691bde483f2SJacob Faibussowitsch   Level: beginner
692bde483f2SJacob Faibussowitsch 
693db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`
694817da375SSatish Balay M*/
695bde483f2SJacob Faibussowitsch #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
696bde483f2SJacob Faibussowitsch 
697bde483f2SJacob Faibussowitsch #if !defined(PETSC_SKIP_VARIADIC_MACROS)
698bde483f2SJacob Faibussowitsch /*MC
699bde483f2SJacob Faibussowitsch   PetscDefined - Determine whether a boolean macro is defined
700bde483f2SJacob Faibussowitsch 
701bde483f2SJacob Faibussowitsch   Synopsis:
702bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
703bde483f2SJacob Faibussowitsch   int PetscDefined(def)
704bde483f2SJacob Faibussowitsch 
705bde483f2SJacob Faibussowitsch   Input Parameter:
706bde483f2SJacob Faibussowitsch . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
707bde483f2SJacob Faibussowitsch 
708bde483f2SJacob Faibussowitsch   Outut Parameter:
709bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
710bde483f2SJacob Faibussowitsch 
711bde483f2SJacob Faibussowitsch   Notes:
712bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
71387497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
714bde483f2SJacob Faibussowitsch 
71587497f52SBarry Smith   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
71687497f52SBarry Smith   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
717bde483f2SJacob Faibussowitsch   this macro should not be used if its argument may be defined to a non-empty value other than
718bde483f2SJacob Faibussowitsch   1.
719bde483f2SJacob Faibussowitsch 
720bde483f2SJacob Faibussowitsch   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
72187497f52SBarry Smith   add custom checks in user code, one should use `PetscDefined_()`.
722bde483f2SJacob Faibussowitsch 
723bde483f2SJacob Faibussowitsch $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_,d))
724bde483f2SJacob Faibussowitsch 
725bde483f2SJacob Faibussowitsch   Developer Notes:
726bde483f2SJacob Faibussowitsch   Getting something that works in C and CPP for an arg that may or may not be defined is
727bde483f2SJacob Faibussowitsch   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
728bde483f2SJacob Faibussowitsch   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
729bde483f2SJacob Faibussowitsch   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
730bde483f2SJacob Faibussowitsch   and when the last step cherry picks the 2nd arg, we get a zero.
731bde483f2SJacob Faibussowitsch 
732bde483f2SJacob Faibussowitsch   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
733bde483f2SJacob Faibussowitsch   nonconforming implementation of variadic macros.
734bde483f2SJacob Faibussowitsch 
735bde483f2SJacob Faibussowitsch   Example Usage:
736bde483f2SJacob Faibussowitsch   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
737bde483f2SJacob Faibussowitsch   is defined then
738bde483f2SJacob Faibussowitsch 
739bde483f2SJacob Faibussowitsch .vb
740bde483f2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
741bde483f2SJacob Faibussowitsch     foo();
742bde483f2SJacob Faibussowitsch   #else
743bde483f2SJacob Faibussowitsch     bar();
744bde483f2SJacob Faibussowitsch   #endif
745bde483f2SJacob Faibussowitsch 
746bde483f2SJacob Faibussowitsch   // or alternatively within normal code
747bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
748bde483f2SJacob Faibussowitsch     foo();
749bde483f2SJacob Faibussowitsch   } else {
750bde483f2SJacob Faibussowitsch     bar();
751bde483f2SJacob Faibussowitsch   }
752bde483f2SJacob Faibussowitsch .ve
753bde483f2SJacob Faibussowitsch 
754bde483f2SJacob Faibussowitsch   is equivalent to
755bde483f2SJacob Faibussowitsch 
756bde483f2SJacob Faibussowitsch .vb
757bde483f2SJacob Faibussowitsch   #if defined(PETSC_USE_DEBUG)
758bde483f2SJacob Faibussowitsch   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
759bde483f2SJacob Faibussowitsch        foo();
760bde483f2SJacob Faibussowitsch   #   elif PETSC_USE_DEBUG == 1
761bde483f2SJacob Faibussowitsch        foo();
762bde483f2SJacob Faibussowitsch   #   else
763bde483f2SJacob Faibussowitsch        bar();
764bde483f2SJacob Faibussowitsch   #  endif
765bde483f2SJacob Faibussowitsch   #else
766bde483f2SJacob Faibussowitsch   bar();
767bde483f2SJacob Faibussowitsch   #endif
768bde483f2SJacob Faibussowitsch .ve
769bde483f2SJacob Faibussowitsch 
770bde483f2SJacob Faibussowitsch   Level: intermediate
771bde483f2SJacob Faibussowitsch 
772db781477SPatrick Sanan .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
773db781477SPatrick Sanan           `PetscExpandToNothing()`, `PetscCompl()`
774817da375SSatish Balay M*/
775bde483f2SJacob Faibussowitsch #define PetscDefined_arg_1                                    shift,
776bde483f2SJacob Faibussowitsch #define PetscDefined_arg_                                     shift,
777bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expanded(ignored, val, ...) val
778bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
779bde483f2SJacob Faibussowitsch #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
780bde483f2SJacob Faibussowitsch #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
781bde483f2SJacob Faibussowitsch #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
782bde483f2SJacob Faibussowitsch #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
783bde483f2SJacob Faibussowitsch 
784bde483f2SJacob Faibussowitsch /*MC
78587497f52SBarry Smith   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
786bde483f2SJacob Faibussowitsch   the check in optimized mode
787bde483f2SJacob Faibussowitsch 
788bde483f2SJacob Faibussowitsch   Synopsis:
789bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
790bde483f2SJacob Faibussowitsch   bool PetscUnlikelyDebug(bool cond)
791bde483f2SJacob Faibussowitsch 
792bde483f2SJacob Faibussowitsch   Not Collective
793bde483f2SJacob Faibussowitsch 
794bde483f2SJacob Faibussowitsch   Input Parameters:
795bde483f2SJacob Faibussowitsch . cond - Boolean expression
796bde483f2SJacob Faibussowitsch 
797bde483f2SJacob Faibussowitsch   Notes:
798bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
79987497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
800bde483f2SJacob Faibussowitsch 
801bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
802bde483f2SJacob Faibussowitsch   likely to be false. When PETSc is compiled in optimized mode this will always return
803bde483f2SJacob Faibussowitsch   false. Additionally, cond is guaranteed to not be evaluated when PETSc is compiled in
804bde483f2SJacob Faibussowitsch   optimized mode.
805bde483f2SJacob Faibussowitsch 
806bde483f2SJacob Faibussowitsch   Example usage:
807bde483f2SJacob Faibussowitsch   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
808bde483f2SJacob Faibussowitsch   is true. So
809bde483f2SJacob Faibussowitsch 
810bde483f2SJacob Faibussowitsch .vb
811bde483f2SJacob Faibussowitsch   if (PetscUnlikelyDebug(cond)) {
812bde483f2SJacob Faibussowitsch     foo();
813bde483f2SJacob Faibussowitsch   } else {
814bde483f2SJacob Faibussowitsch     bar();
815bde483f2SJacob Faibussowitsch   }
816bde483f2SJacob Faibussowitsch .ve
817bde483f2SJacob Faibussowitsch 
818bde483f2SJacob Faibussowitsch   is equivalent to
819bde483f2SJacob Faibussowitsch 
820bde483f2SJacob Faibussowitsch .vb
821bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
822bde483f2SJacob Faibussowitsch     if (PetscUnlikely(cond)) {
823bde483f2SJacob Faibussowitsch       foo();
824bde483f2SJacob Faibussowitsch     } else {
825bde483f2SJacob Faibussowitsch       bar();
826bde483f2SJacob Faibussowitsch     }
827bde483f2SJacob Faibussowitsch   } else {
828bde483f2SJacob Faibussowitsch     bar();
829bde483f2SJacob Faibussowitsch   }
830bde483f2SJacob Faibussowitsch .ve
831bde483f2SJacob Faibussowitsch 
832bde483f2SJacob Faibussowitsch   Level: advanced
833bde483f2SJacob Faibussowitsch 
834db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
835bde483f2SJacob Faibussowitsch M*/
836bde483f2SJacob Faibussowitsch #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
837bde483f2SJacob Faibussowitsch 
838f7e3c444SJacob Faibussowitsch #if defined(PETSC_CLANG_STATIC_ANALYZER)
839f7e3c444SJacob Faibussowitsch // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
840f7e3c444SJacob Faibussowitsch // not what ISO C allows
8419371c9d4SSatish Balay #define PetscMacroReturns_(retexpr, ...) \
8429371c9d4SSatish Balay   __extension__({ \
8439371c9d4SSatish Balay     __VA_ARGS__; \
8449371c9d4SSatish Balay     retexpr; \
8459371c9d4SSatish Balay   })
846f7e3c444SJacob Faibussowitsch #else
8479371c9d4SSatish Balay #define PetscMacroReturns_(retexpr, ...) \
8489371c9d4SSatish Balay   retexpr; \
8499371c9d4SSatish Balay   do { __VA_ARGS__; } while (0)
850f7e3c444SJacob Faibussowitsch #endif
851f7e3c444SJacob Faibussowitsch 
852bde483f2SJacob Faibussowitsch /*MC
853bde483f2SJacob Faibussowitsch   PetscExpandToNothing - Expands to absolutely nothing at all
854bde483f2SJacob Faibussowitsch 
855bde483f2SJacob Faibussowitsch   Synopsis:
856bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
857bde483f2SJacob Faibussowitsch   void PetscExpandToNothing(...)
858bde483f2SJacob Faibussowitsch 
859bde483f2SJacob Faibussowitsch   Input Parameter:
860bde483f2SJacob Faibussowitsch . __VA_ARGS__ - Anything at all
861bde483f2SJacob Faibussowitsch 
862bde483f2SJacob Faibussowitsch   Notes:
863bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
86487497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
865bde483f2SJacob Faibussowitsch 
866bde483f2SJacob Faibussowitsch   Must have at least 1 parameter.
867bde483f2SJacob Faibussowitsch 
868bde483f2SJacob Faibussowitsch   Example usage:
869bde483f2SJacob Faibussowitsch .vb
870bde483f2SJacob Faibussowitsch   PetscExpandToNothing(a,b,c) -> *nothing*
871bde483f2SJacob Faibussowitsch .ve
872bde483f2SJacob Faibussowitsch 
873bde483f2SJacob Faibussowitsch   Level: beginner
874bde483f2SJacob Faibussowitsch 
875db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
876817da375SSatish Balay M*/
877bde483f2SJacob Faibussowitsch #define PetscExpandToNothing(...)
878f7e3c444SJacob Faibussowitsch 
879f7e3c444SJacob Faibussowitsch /*MC
880f7e3c444SJacob Faibussowitsch   PetscMacroReturns - Define a macro body that returns a value
881f7e3c444SJacob Faibussowitsch 
882f7e3c444SJacob Faibussowitsch   Synopsis:
883f7e3c444SJacob Faibussowitsch   #include <petscmacros.h>
884f7e3c444SJacob Faibussowitsch   return_type PetscMacroReturns(return_type retexpr, ...)
885f7e3c444SJacob Faibussowitsch 
886f7e3c444SJacob Faibussowitsch   Input Parameters:
887f7e3c444SJacob Faibussowitsch + retexpr     - The value or expression that the macro should return
888f7e3c444SJacob Faibussowitsch - __VA_ARGS__ - The body of the macro
889f7e3c444SJacob Faibussowitsch 
890f7e3c444SJacob Faibussowitsch   Notes:
891f7e3c444SJacob Faibussowitsch   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
892f7e3c444SJacob Faibussowitsch   body of the macro and should not depend on values produced as a result of the expression. The
893f7e3c444SJacob Faibussowitsch   user should not assume that the result of this macro is equivalent to a single logical source
894f7e3c444SJacob Faibussowitsch   line. It is not portable to use macros defined using this one in conditional or loop bodies
895f7e3c444SJacob Faibussowitsch   without enclosing them in curly braces\:
896f7e3c444SJacob Faibussowitsch 
897f7e3c444SJacob Faibussowitsch .vb
898f7e3c444SJacob Faibussowitsch   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
899f7e3c444SJacob Faibussowitsch 
900f7e3c444SJacob Faibussowitsch   int err,x = 10;
901f7e3c444SJacob Faibussowitsch 
902f7e3c444SJacob Faibussowitsch   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
903f7e3c444SJacob Faibussowitsch   if (...) { err = FOO(x); }  // OK
904f7e3c444SJacob Faibussowitsch 
905f7e3c444SJacob Faibussowitsch   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
906f7e3c444SJacob Faibussowitsch   for (...) { err = FOO(x); } // OK
907f7e3c444SJacob Faibussowitsch .ve
908f7e3c444SJacob Faibussowitsch 
909f7e3c444SJacob Faibussowitsch   It is also not portable to use this macro directly inside function call, conditional, loop,
910f7e3c444SJacob Faibussowitsch   or switch statements\:
911f7e3c444SJacob Faibussowitsch 
912f7e3c444SJacob Faibussowitsch .vb
913f7e3c444SJacob Faibussowitsch   extern void bar(int);
914f7e3c444SJacob Faibussowitsch 
915f7e3c444SJacob Faibussowitsch   int ret = FOO(x);
916f7e3c444SJacob Faibussowitsch 
917f7e3c444SJacob Faibussowitsch   bar(FOO(x)); // ERROR, may not compile
918f7e3c444SJacob Faibussowitsch   bar(ret);    // OK
919f7e3c444SJacob Faibussowitsch 
920f7e3c444SJacob Faibussowitsch   if (FOO(x))  // ERROR, may not compile
921f7e3c444SJacob Faibussowitsch   if (ret)     // OK
922f7e3c444SJacob Faibussowitsch .ve
923f7e3c444SJacob Faibussowitsch 
924f7e3c444SJacob Faibussowitsch   Example usage:
925f7e3c444SJacob Faibussowitsch .vb
926f7e3c444SJacob Faibussowitsch   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
927f7e3c444SJacob Faibussowitsch 
928f7e3c444SJacob Faibussowitsch   int x = 10;
929f7e3c444SJacob Faibussowitsch   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
930f7e3c444SJacob Faibussowitsch 
931f7e3c444SJacob Faibussowitsch   // multiline macros allowed, but must declare with line continuation as usual
932f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
933f7e3c444SJacob Faibussowitsch     if (arg1 > 10) {                                            \
934f7e3c444SJacob Faibussowitsch       puts("big int!");                                         \
935f7e3c444SJacob Faibussowitsch     } else {                                                    \
936f7e3c444SJacob Faibussowitsch       return 7355608;                                           \
937f7e3c444SJacob Faibussowitsch     }                                                           \
938f7e3c444SJacob Faibussowitsch   )
939f7e3c444SJacob Faibussowitsch 
940f7e3c444SJacob Faibussowitsch   // if retexpr contains commas, must enclose it with braces
941f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
942f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
943f7e3c444SJacob Faibussowitsch 
944f7e3c444SJacob Faibussowitsch   int x = 10;
945f7e3c444SJacob Faibussowitsch   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
946f7e3c444SJacob Faibussowitsch   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
947f7e3c444SJacob Faibussowitsch .ve
948f7e3c444SJacob Faibussowitsch 
949f7e3c444SJacob Faibussowitsch   Level: intermediate
950f7e3c444SJacob Faibussowitsch 
951db781477SPatrick Sanan .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
952f7e3c444SJacob Faibussowitsch M*/
953f7e3c444SJacob Faibussowitsch #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
954f7e3c444SJacob Faibussowitsch 
955f7e3c444SJacob Faibussowitsch #define PetscMacroReturnStandard(...) PetscMacroReturns(0, __VA_ARGS__)
956f7e3c444SJacob Faibussowitsch 
957bde483f2SJacob Faibussowitsch #endif /* !PETSC_SKIP_VARIADIC_MACROS */
958bde483f2SJacob Faibussowitsch 
959dd39110bSPierre Jolivet /*MC
960dd39110bSPierre Jolivet   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
961dd39110bSPierre Jolivet 
962dd39110bSPierre Jolivet   Level: intermediate
963dd39110bSPierre Jolivet M*/
964dd39110bSPierre Jolivet #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
965dd39110bSPierre Jolivet 
966296d8154SBarry Smith /*
967296d8154SBarry Smith   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
968296d8154SBarry Smith 
969296d8154SBarry Smith   Example usage:
970296d8154SBarry Smith 
971296d8154SBarry Smith   #define mymacro(obj,...) {
972296d8154SBarry Smith     PETSC_FIRST_ARG((__VA_ARGS__,unused));
973296d8154SBarry Smith     f(22 PETSC_REST_ARG(__VA_ARGS__));
974296d8154SBarry Smith   }
975296d8154SBarry Smith 
976296d8154SBarry Smith   Note you add a dummy extra argument to __VA_ARGS__ and enclose them in an extra set of () for PETSC_FIRST_ARG() and PETSC_REST_ARG(__VA_ARGS__) automatically adds a leading comma only if there are additional arguments
977296d8154SBarry Smith 
978296d8154SBarry Smith   Reference:
979296d8154SBarry Smith   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
980296d8154SBarry Smith */
981296d8154SBarry Smith #define PETSC_FIRST_ARG_(N, ...)                                                                      N
982296d8154SBarry Smith #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
983296d8154SBarry Smith #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
984296d8154SBarry Smith #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
985296d8154SBarry Smith #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
986296d8154SBarry Smith #define PETSC_REST_HELPER_ONE(first)
987296d8154SBarry Smith #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
988296d8154SBarry Smith #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
989296d8154SBarry Smith #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
990296d8154SBarry Smith 
991bde483f2SJacob Faibussowitsch #endif /* PETSC_PREPROCESSOR_MACROS_H */
992