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