xref: /petsc/include/petscmacros.h (revision 0e6b6b5985dd9b1172860d21fb88bd3966bf7c54)
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 
9*0e6b6b59SJacob Faibussowitsch #if defined(__cplusplus)
10*0e6b6b59SJacob Faibussowitsch #if __cplusplus <= 201103L
11*0e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 11
12*0e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 201402L
13*0e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 14
14*0e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 201703L
15*0e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 17
16*0e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 202002L
17*0e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 20
18*0e6b6b59SJacob Faibussowitsch #else
19*0e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
20*0e6b6b59SJacob Faibussowitsch #endif
21*0e6b6b59SJacob Faibussowitsch #endif // __cplusplus
22*0e6b6b59SJacob Faibussowitsch 
23*0e6b6b59SJacob Faibussowitsch #ifndef PETSC_CPP_VERSION
24*0e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 0
25*0e6b6b59SJacob Faibussowitsch #endif
26*0e6b6b59SJacob 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 
148bde483f2SJacob Faibussowitsch /*MC
14963a3b9bcSJacob Faibussowitsch   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
15063a3b9bcSJacob Faibussowitsch   as format specifiers and checked for validity
15163a3b9bcSJacob Faibussowitsch 
15263a3b9bcSJacob Faibussowitsch   Synopsis:
15363a3b9bcSJacob Faibussowitsch   #include <petscmacros.h>
15463a3b9bcSJacob Faibussowitsch   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
15563a3b9bcSJacob Faibussowitsch 
15663a3b9bcSJacob Faibussowitsch   Input Parameters:
15763a3b9bcSJacob Faibussowitsch + strIdx   - The (1-indexed) location of the format string in the argument list
15863a3b9bcSJacob Faibussowitsch - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
15963a3b9bcSJacob Faibussowitsch 
16063a3b9bcSJacob Faibussowitsch   Notes:
16163a3b9bcSJacob Faibussowitsch   This function attribute causes the compiler to issue warnings when the format specifier does
16263a3b9bcSJacob Faibussowitsch   not match the type of the variable that will be formatted, or when there exists a mismatch
16363a3b9bcSJacob Faibussowitsch   between the number of format specifiers and variables to be formatted. It is safe to use this
16463a3b9bcSJacob Faibussowitsch   macro if your compiler does not support format specifier checking (though this is
16563a3b9bcSJacob Faibussowitsch   exceeedingly rare).
16663a3b9bcSJacob Faibussowitsch 
16763a3b9bcSJacob Faibussowitsch   Both strIdx and vaArgIdx must be compile-time constant integer literals and cannot have the
16863a3b9bcSJacob Faibussowitsch   same value.
16963a3b9bcSJacob Faibussowitsch 
17063a3b9bcSJacob Faibussowitsch   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
17163a3b9bcSJacob Faibussowitsch   the argument list, that is, there is no way to indicate gaps which should not be checked.
17263a3b9bcSJacob Faibussowitsch 
17387497f52SBarry Smith   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
17463a3b9bcSJacob Faibussowitsch   header files. In this case the macro will expand empty.
17563a3b9bcSJacob Faibussowitsch 
17663a3b9bcSJacob Faibussowitsch   Example Usage:
17763a3b9bcSJacob Faibussowitsch .vb
17863a3b9bcSJacob Faibussowitsch   // format string is 2nd argument, variable argument list containing args is 3rd argument
17963a3b9bcSJacob Faibussowitsch   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
18063a3b9bcSJacob Faibussowitsch 
18163a3b9bcSJacob Faibussowitsch   int    x = 1;
18263a3b9bcSJacob Faibussowitsch   double y = 50.0;
18363a3b9bcSJacob Faibussowitsch 
18463a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
18563a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
18663a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d %g",x,y); // OK
18763a3b9bcSJacob Faibussowitsch .ve
18863a3b9bcSJacob Faibussowitsch 
18963a3b9bcSJacob Faibussowitsch   Level: developer
19063a3b9bcSJacob Faibussowitsch 
191db781477SPatrick Sanan .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
19263a3b9bcSJacob Faibussowitsch M*/
19363a3b9bcSJacob Faibussowitsch #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
19463a3b9bcSJacob Faibussowitsch #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
19563a3b9bcSJacob Faibussowitsch #else
19663a3b9bcSJacob Faibussowitsch #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
19763a3b9bcSJacob Faibussowitsch #endif
19863a3b9bcSJacob Faibussowitsch 
19963a3b9bcSJacob Faibussowitsch /*MC
200d8e4614bSJacob Faibussowitsch   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
201d8e4614bSJacob Faibussowitsch   executed
202d8e4614bSJacob Faibussowitsch 
203d8e4614bSJacob Faibussowitsch   Notes:
204d8e4614bSJacob Faibussowitsch   The marked function is often optimized for size rather than speed and may be grouped alongside
205d8e4614bSJacob Faibussowitsch   other equally frigid routines improving code locality of lukewarm or hotter parts of program.
206d8e4614bSJacob Faibussowitsch 
207d8e4614bSJacob Faibussowitsch   The paths leading to cold functions are usually automatically marked as unlikely by the
208d8e4614bSJacob Faibussowitsch   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
209d8e4614bSJacob Faibussowitsch   as error handlers -- as cold to improve optimization of the surrounding temperate functions.
210d8e4614bSJacob Faibussowitsch 
211d8e4614bSJacob Faibussowitsch   Example Usage:
212d8e4614bSJacob Faibussowitsch .vb
213d8e4614bSJacob Faibussowitsch   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
214d8e4614bSJacob Faibussowitsch 
215d8e4614bSJacob Faibussowitsch   if (temperature < 0) {
216d8e4614bSJacob Faibussowitsch     return my_error_handler(...); // chilly!
217d8e4614bSJacob Faibussowitsch   }
218d8e4614bSJacob Faibussowitsch .ve
219d8e4614bSJacob Faibussowitsch 
220d8e4614bSJacob Faibussowitsch   Level: intermediate
221d8e4614bSJacob Faibussowitsch 
222db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
223db781477SPatrick Sanan           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
224d8e4614bSJacob Faibussowitsch M*/
225d8e4614bSJacob Faibussowitsch #if PetscHasAttribute(__cold__)
226d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
227d8e4614bSJacob Faibussowitsch #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
228d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
229d8e4614bSJacob Faibussowitsch #else
230d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD
231d8e4614bSJacob Faibussowitsch #endif
232d8e4614bSJacob Faibussowitsch 
233d8e4614bSJacob Faibussowitsch /*MC
234bde483f2SJacob Faibussowitsch   PETSC_NULLPTR - Standard way of indicating a null value or pointer
235bde483f2SJacob Faibussowitsch 
236bde483f2SJacob Faibussowitsch   Notes:
237bde483f2SJacob Faibussowitsch   Equivalent to NULL in C source, and nullptr in C++ source. Note that for the purposes of
23887497f52SBarry Smith   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
239bde483f2SJacob Faibussowitsch   equivalent to setting the same pointer to NULL in C. That is to say that the following
240bde483f2SJacob Faibussowitsch   expressions are equivalent\:
241bde483f2SJacob Faibussowitsch 
242bde483f2SJacob Faibussowitsch .vb
243bde483f2SJacob Faibussowitsch   ptr == PETSC_NULLPTR
244bde483f2SJacob Faibussowitsch   ptr == NULL
245bde483f2SJacob Faibussowitsch   ptr == 0
246bde483f2SJacob Faibussowitsch   !ptr
247bde483f2SJacob Faibussowitsch 
248bde483f2SJacob Faibussowitsch   ptr = PETSC_NULLPTR
249bde483f2SJacob Faibussowitsch   ptr = NULL
250bde483f2SJacob Faibussowitsch   ptr = 0
251bde483f2SJacob Faibussowitsch .ve
252bde483f2SJacob Faibussowitsch 
253bde483f2SJacob Faibussowitsch   and for completeness' sake\:
254bde483f2SJacob Faibussowitsch 
255bde483f2SJacob Faibussowitsch .vb
256bde483f2SJacob Faibussowitsch   PETSC_NULLPTR == NULL
257bde483f2SJacob Faibussowitsch .ve
258bde483f2SJacob Faibussowitsch 
259bde483f2SJacob Faibussowitsch   Fortran Notes:
260bde483f2SJacob Faibussowitsch   Not available in Fortran
261bde483f2SJacob Faibussowitsch 
262bde483f2SJacob Faibussowitsch   Example Usage:
263bde483f2SJacob Faibussowitsch .vb
264bde483f2SJacob Faibussowitsch   // may be used in place of '\0' or other such teminators in the definition of char arrays
265bde483f2SJacob Faibussowitsch   const char *const MyEnumTypes[] = {
266bde483f2SJacob Faibussowitsch     "foo",
267bde483f2SJacob Faibussowitsch     "bar",
268bde483f2SJacob Faibussowitsch     PETSC_NULLPTR
269bde483f2SJacob Faibussowitsch   };
270bde483f2SJacob Faibussowitsch 
271bde483f2SJacob Faibussowitsch   // may be used to nullify objects
272bde483f2SJacob Faibussowitsch   PetscObject obj = PETSC_NULLPTR;
273bde483f2SJacob Faibussowitsch 
274bde483f2SJacob Faibussowitsch   // may be used in any function expecting NULL
275bde483f2SJacob Faibussowitsch   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
276bde483f2SJacob Faibussowitsch .ve
277bde483f2SJacob Faibussowitsch 
278bde483f2SJacob Faibussowitsch   Developer Notes:
27987497f52SBarry Smith   `PETSC_NULLPTR` must be used in place of NULL in all C++ source files. Using NULL in source
280bde483f2SJacob Faibussowitsch   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
281bde483f2SJacob Faibussowitsch   resolution and/or compiler warnings.
282bde483f2SJacob Faibussowitsch 
283bde483f2SJacob Faibussowitsch   Level: beginner
284bde483f2SJacob Faibussowitsch 
285db781477SPatrick Sanan .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
286817da375SSatish Balay M*/
287bde483f2SJacob Faibussowitsch 
288bde483f2SJacob Faibussowitsch /*MC
289bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 - C++14 constexpr
290bde483f2SJacob Faibussowitsch 
291bde483f2SJacob Faibussowitsch   Notes:
292bde483f2SJacob Faibussowitsch   Equivalent to constexpr when using a C++ compiler that supports C++14. Expands to nothing
293bde483f2SJacob Faibussowitsch   if the C++ compiler does not suppport C++14 or when not compiling with a C++ compiler. Note
294bde483f2SJacob Faibussowitsch   that this cannot be used in cases where an empty expansion would result in invalid code. It
295bde483f2SJacob Faibussowitsch   is safe to use this in C source files.
296bde483f2SJacob Faibussowitsch 
297bde483f2SJacob Faibussowitsch   Fortran Notes:
298bde483f2SJacob Faibussowitsch   Not available in Fortran
299bde483f2SJacob Faibussowitsch 
300bde483f2SJacob Faibussowitsch   Example Usage:
301bde483f2SJacob Faibussowitsch .vb
302bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 int factorial(int n)
303bde483f2SJacob Faibussowitsch   {
304bde483f2SJacob Faibussowitsch     int r = 1;
305bde483f2SJacob Faibussowitsch 
306bde483f2SJacob Faibussowitsch     do {
307bde483f2SJacob Faibussowitsch       r *= n;
308bde483f2SJacob Faibussowitsch     } while (--n);
309bde483f2SJacob Faibussowitsch     return r;
310bde483f2SJacob Faibussowitsch   }
311bde483f2SJacob Faibussowitsch .ve
312bde483f2SJacob Faibussowitsch 
313bde483f2SJacob Faibussowitsch   Level: beginner
314bde483f2SJacob Faibussowitsch 
315db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
316817da375SSatish Balay M*/
317bde483f2SJacob Faibussowitsch 
318bde483f2SJacob Faibussowitsch /*MC
319bde483f2SJacob Faibussowitsch   PETSC_NODISCARD - Mark the return value of a function as non-discardable
320bde483f2SJacob Faibussowitsch 
321bde483f2SJacob Faibussowitsch   Notes:
322bde483f2SJacob Faibussowitsch   Hints to the compiler that the return value of a function must be captured. A diagnostic may
323bde483f2SJacob Faibussowitsch   (but is not required) be emitted if the value is discarded. It is safe to use this in C
324bde483f2SJacob Faibussowitsch   and C++ source files.
325bde483f2SJacob Faibussowitsch 
326bde483f2SJacob Faibussowitsch   Fortran Notes:
327bde483f2SJacob Faibussowitsch   Not available in Fortran
328bde483f2SJacob Faibussowitsch 
329bde483f2SJacob Faibussowitsch   Example Usage:
330bde483f2SJacob Faibussowitsch .vb
331bde483f2SJacob Faibussowitsch   class Foo
332bde483f2SJacob Faibussowitsch   {
333bde483f2SJacob Faibussowitsch     int x;
334bde483f2SJacob Faibussowitsch 
335bde483f2SJacob Faibussowitsch   public:
336bde483f2SJacob Faibussowitsch     PETSC_NODISCARD Foo(int y) : x(y) { }
337bde483f2SJacob Faibussowitsch   };
338bde483f2SJacob Faibussowitsch 
339bde483f2SJacob Faibussowitsch   PETSC_NODISCARD int factorial(int n)
340bde483f2SJacob Faibussowitsch   {
341bde483f2SJacob Faibussowitsch     return n <= 1 ? 1 : (n * factorial(n - 1));
342bde483f2SJacob Faibussowitsch   }
343bde483f2SJacob Faibussowitsch 
344bde483f2SJacob Faibussowitsch   auto x = factorial(10); // OK, capturing return value
345bde483f2SJacob Faibussowitsch   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
346bde483f2SJacob Faibussowitsch 
347bde483f2SJacob Faibussowitsch   auto f = Foo(x); // OK, capturing constructed object
348bde483f2SJacob Faibussowitsch   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
349bde483f2SJacob Faibussowitsch .ve
350bde483f2SJacob Faibussowitsch 
351bde483f2SJacob Faibussowitsch   Developer Notes:
352bde483f2SJacob Faibussowitsch   It is highly recommended if not downright required that any PETSc routines written in C++
35387497f52SBarry Smith   returning a PetscErrorCode be marked `PETSC_NODISCARD`. Ignoring the return value of PETSc
354bde483f2SJacob Faibussowitsch   routines is not supported; unhandled errors may leave PETSc in an unrecoverable state.
355bde483f2SJacob Faibussowitsch 
356bde483f2SJacob Faibussowitsch   Level: beginner
357bde483f2SJacob Faibussowitsch 
358db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
359817da375SSatish Balay M*/
360bde483f2SJacob Faibussowitsch 
361bde483f2SJacob Faibussowitsch /* C++11 features */
3626ee8c794SJacob Faibussowitsch #if defined(__cplusplus)
363bde483f2SJacob Faibussowitsch #define PETSC_NULLPTR nullptr
364bde483f2SJacob Faibussowitsch #else
365bde483f2SJacob Faibussowitsch #define PETSC_NULLPTR NULL
366bde483f2SJacob Faibussowitsch #endif
367bde483f2SJacob Faibussowitsch 
368bde483f2SJacob Faibussowitsch /* C++14 features */
369*0e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 14
3706ee8c794SJacob Faibussowitsch #define PETSC_CONSTEXPR_14 constexpr
371bde483f2SJacob Faibussowitsch #else
372bde483f2SJacob Faibussowitsch #define PETSC_CONSTEXPR_14
373bde483f2SJacob Faibussowitsch #endif
374bde483f2SJacob Faibussowitsch 
375bde483f2SJacob Faibussowitsch /* C++17 features */
376*0e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 17
377bde483f2SJacob Faibussowitsch #define PETSC_NODISCARD    [[nodiscard]]
378*0e6b6b59SJacob Faibussowitsch #define PETSC_CONSTEXPR_17 constexpr
379bde483f2SJacob Faibussowitsch #else
380bde483f2SJacob Faibussowitsch #if PetscHasAttribute(warn_unused_result)
381bde483f2SJacob Faibussowitsch #define PETSC_NODISCARD __attribute__((warn_unused_result))
382bde483f2SJacob Faibussowitsch #endif
383*0e6b6b59SJacob Faibussowitsch #define PETSC_CONSTEXPR_17
384*0e6b6b59SJacob Faibussowitsch #endif
385*0e6b6b59SJacob Faibussowitsch 
386*0e6b6b59SJacob Faibussowitsch #ifndef PETSC_NODISCARD
387*0e6b6b59SJacob Faibussowitsch #define PETSC_NODISCARD
388bde483f2SJacob Faibussowitsch #endif
389bde483f2SJacob Faibussowitsch 
390bde483f2SJacob Faibussowitsch #include <petscversion.h>
391bde483f2SJacob Faibussowitsch #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
392bde483f2SJacob Faibussowitsch 
393267267bdSJacob Faibussowitsch /* designated initializers since C99 and C++20, MSVC never supports them though */
394*0e6b6b59SJacob Faibussowitsch #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
395267267bdSJacob Faibussowitsch #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
396267267bdSJacob Faibussowitsch #else
397267267bdSJacob Faibussowitsch #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
398267267bdSJacob Faibussowitsch #endif
399267267bdSJacob Faibussowitsch 
400bde483f2SJacob Faibussowitsch /*MC
40187497f52SBarry Smith   PetscUnlikely - Hints the compiler that the given condition is usually false
402bde483f2SJacob Faibussowitsch 
403bde483f2SJacob Faibussowitsch   Synopsis:
404bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
405bde483f2SJacob Faibussowitsch   bool PetscUnlikely(bool cond)
406bde483f2SJacob Faibussowitsch 
407bde483f2SJacob Faibussowitsch   Not Collective
408bde483f2SJacob Faibussowitsch 
409bde483f2SJacob Faibussowitsch   Input Parameter:
410bde483f2SJacob Faibussowitsch . cond - Boolean expression
411bde483f2SJacob Faibussowitsch 
412bde483f2SJacob Faibussowitsch   Notes:
413bde483f2SJacob Faibussowitsch   Not available from fortran.
414bde483f2SJacob Faibussowitsch 
415bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
416bde483f2SJacob Faibussowitsch   unlikely to be true.
417bde483f2SJacob Faibussowitsch 
418bde483f2SJacob Faibussowitsch   Example usage:
419bde483f2SJacob Faibussowitsch .vb
420bde483f2SJacob Faibussowitsch   if (PetscUnlikely(cond)) {
421bde483f2SJacob Faibussowitsch     foo(); // cold path
422bde483f2SJacob Faibussowitsch   } else {
423bde483f2SJacob Faibussowitsch     bar(); // hot path
424bde483f2SJacob Faibussowitsch   }
425bde483f2SJacob Faibussowitsch .ve
426bde483f2SJacob Faibussowitsch 
427bde483f2SJacob Faibussowitsch   Level: advanced
428bde483f2SJacob Faibussowitsch 
429db781477SPatrick Sanan .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
430db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
431bde483f2SJacob Faibussowitsch M*/
432bde483f2SJacob Faibussowitsch 
433bde483f2SJacob Faibussowitsch /*MC
43487497f52SBarry Smith   PetscLikely - Hints the compiler that the given condition is usually true
435bde483f2SJacob Faibussowitsch 
436bde483f2SJacob Faibussowitsch   Synopsis:
437bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
438bde483f2SJacob Faibussowitsch   bool PetscLikely(bool cond)
439bde483f2SJacob Faibussowitsch 
440bde483f2SJacob Faibussowitsch   Not Collective
441bde483f2SJacob Faibussowitsch 
442bde483f2SJacob Faibussowitsch   Input Parameter:
443bde483f2SJacob Faibussowitsch . cond - Boolean expression
444bde483f2SJacob Faibussowitsch 
445bde483f2SJacob Faibussowitsch   Notes:
446bde483f2SJacob Faibussowitsch   Not available from fortran.
447bde483f2SJacob Faibussowitsch 
448bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
449bde483f2SJacob Faibussowitsch   likely to be true.
450bde483f2SJacob Faibussowitsch 
451bde483f2SJacob Faibussowitsch   Example usage:
452bde483f2SJacob Faibussowitsch .vb
453bde483f2SJacob Faibussowitsch   if (PetscLikely(cond)) {
454bde483f2SJacob Faibussowitsch     foo(); // hot path
455bde483f2SJacob Faibussowitsch   } else {
456bde483f2SJacob Faibussowitsch     bar(); // cold path
457bde483f2SJacob Faibussowitsch   }
458bde483f2SJacob Faibussowitsch .ve
459bde483f2SJacob Faibussowitsch 
460bde483f2SJacob Faibussowitsch   Level: advanced
461bde483f2SJacob Faibussowitsch 
462db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
463db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
464bde483f2SJacob Faibussowitsch M*/
465bde483f2SJacob Faibussowitsch #if defined(PETSC_HAVE_BUILTIN_EXPECT)
466bde483f2SJacob Faibussowitsch #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
467bde483f2SJacob Faibussowitsch #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
468bde483f2SJacob Faibussowitsch #else
469bde483f2SJacob Faibussowitsch #define PetscUnlikely(cond) (cond)
470bde483f2SJacob Faibussowitsch #define PetscLikely(cond)   (cond)
471bde483f2SJacob Faibussowitsch #endif
472bde483f2SJacob Faibussowitsch 
473bde483f2SJacob Faibussowitsch /*MC
474817da375SSatish Balay   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
475bde483f2SJacob Faibussowitsch 
476bde483f2SJacob Faibussowitsch   Synopsis:
477bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
478bde483f2SJacob Faibussowitsch   void PetscUnreachable(void)
479bde483f2SJacob Faibussowitsch 
480bde483f2SJacob Faibussowitsch   Notes:
481bde483f2SJacob Faibussowitsch   Indicates to the compiler (usually via some built-in) that a particular code path is always
482bde483f2SJacob Faibussowitsch   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
483bde483f2SJacob Faibussowitsch   unceremonious crash.
484bde483f2SJacob Faibussowitsch 
485bde483f2SJacob Faibussowitsch   Example usage:
486bde483f2SJacob Faibussowitsch   Useful in situations such as switches over enums where not all enumeration values are
487bde483f2SJacob Faibussowitsch   explicitly covered by the switch
488bde483f2SJacob Faibussowitsch 
489bde483f2SJacob Faibussowitsch .vb
490bde483f2SJacob Faibussowitsch   typedef enum {RED, GREEN, BLUE} Color;
491bde483f2SJacob Faibussowitsch 
492bde483f2SJacob Faibussowitsch   int foo(Color c)
493bde483f2SJacob Faibussowitsch   {
494bde483f2SJacob Faibussowitsch     // it is known to programmer (or checked previously) that c is either RED or GREEN
495bde483f2SJacob Faibussowitsch     // but compiler may not be able to deduce this and/or emit spurious warnings
496bde483f2SJacob Faibussowitsch     switch (c) {
497bde483f2SJacob Faibussowitsch       case RED:
498bde483f2SJacob Faibussowitsch         return bar();
499bde483f2SJacob Faibussowitsch       case GREEN:
500bde483f2SJacob Faibussowitsch         return baz();
501bde483f2SJacob Faibussowitsch       default:
502bde483f2SJacob Faibussowitsch         PetscUnreachable(); // program is ill-formed if executed
503bde483f2SJacob Faibussowitsch     }
504bde483f2SJacob Faibussowitsch   }
505bde483f2SJacob Faibussowitsch .ve
506bde483f2SJacob Faibussowitsch 
507bde483f2SJacob Faibussowitsch   Level: advanced
508bde483f2SJacob Faibussowitsch 
509db781477SPatrick Sanan .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`
510817da375SSatish Balay M*/
511e58a63e1SJacob Faibussowitsch #if defined(__GNUC__)
512e58a63e1SJacob Faibussowitsch /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
513e58a63e1SJacob Faibussowitsch #define PetscUnreachable() __builtin_unreachable()
514e58a63e1SJacob Faibussowitsch #elif defined(_MSC_VER) /* MSVC */
515e58a63e1SJacob Faibussowitsch #define PetscUnreachable() __assume(0)
516e58a63e1SJacob Faibussowitsch #else /* ??? */
517e58a63e1SJacob Faibussowitsch #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
518e58a63e1SJacob Faibussowitsch #endif
519bde483f2SJacob Faibussowitsch 
520bde483f2SJacob Faibussowitsch /*MC
521bde483f2SJacob Faibussowitsch   PetscExpand - Expand macro argument
522bde483f2SJacob Faibussowitsch 
523bde483f2SJacob Faibussowitsch   Synopsis:
524bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
525bde483f2SJacob Faibussowitsch   <macro-expansion> PetscExpand(x)
526bde483f2SJacob Faibussowitsch 
5276aad120cSJose E. Roman   Input Parameter:
528bde483f2SJacob Faibussowitsch . x - The preprocessor token to expand
529bde483f2SJacob Faibussowitsch 
53049762cbcSSatish Balay   Level: beginner
53149762cbcSSatish Balay 
532db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscConcat()`
533817da375SSatish Balay M*/
534e58a63e1SJacob Faibussowitsch #define PetscExpand_(...) __VA_ARGS__
535e58a63e1SJacob Faibussowitsch #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
536bde483f2SJacob Faibussowitsch 
537bde483f2SJacob Faibussowitsch /*MC
538bde483f2SJacob Faibussowitsch   PetscStringize - Stringize a token
539bde483f2SJacob Faibussowitsch 
540bde483f2SJacob Faibussowitsch   Synopsis:
541bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
542bde483f2SJacob Faibussowitsch   const char* PetscStringize(x)
543bde483f2SJacob Faibussowitsch 
544bde483f2SJacob Faibussowitsch   Input Parameter:
545bde483f2SJacob Faibussowitsch . x - The token you would like to stringize
546bde483f2SJacob Faibussowitsch 
547bde483f2SJacob Faibussowitsch   Output Parameter:
548bde483f2SJacob Faibussowitsch . <return-value> - The string representation of x
549bde483f2SJacob Faibussowitsch 
550bde483f2SJacob Faibussowitsch   Notes:
551bde483f2SJacob Faibussowitsch   Not available from Fortran.
552bde483f2SJacob Faibussowitsch 
553bde483f2SJacob Faibussowitsch   PetscStringize() expands x before stringizing it, if you do not wish to do so, use
554bde483f2SJacob Faibussowitsch   PetscStringize_() instead.
555bde483f2SJacob Faibussowitsch 
556bde483f2SJacob Faibussowitsch   Example Usage:
557bde483f2SJacob Faibussowitsch .vb
558bde483f2SJacob Faibussowitsch   #define MY_OTHER_VAR hello there
559bde483f2SJacob Faibussowitsch   #define MY_VAR       MY_OTHER_VAR
560bde483f2SJacob Faibussowitsch 
561bde483f2SJacob Faibussowitsch   PetscStringize(MY_VAR)  -> "hello there"
562bde483f2SJacob Faibussowitsch   PetscStringize_(MY_VAR) -> "MY_VAR"
563bde483f2SJacob Faibussowitsch 
564bde483f2SJacob Faibussowitsch   int foo;
565bde483f2SJacob Faibussowitsch   PetscStringize(foo)  -> "foo"
566bde483f2SJacob Faibussowitsch   PetscStringize_(foo) -> "foo"
567bde483f2SJacob Faibussowitsch .ve
568bde483f2SJacob Faibussowitsch 
569bde483f2SJacob Faibussowitsch   Level: beginner
570bde483f2SJacob Faibussowitsch 
571db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
572817da375SSatish Balay M*/
573*0e6b6b59SJacob Faibussowitsch #define PetscStringize_(...) #__VA_ARGS__
574*0e6b6b59SJacob Faibussowitsch #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
575bde483f2SJacob Faibussowitsch 
576bde483f2SJacob Faibussowitsch /*MC
577bde483f2SJacob Faibussowitsch   PetscConcat - Concatenate two tokens
578bde483f2SJacob Faibussowitsch 
579bde483f2SJacob Faibussowitsch   Synopsis:
580bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
581bde483f2SJacob Faibussowitsch   <macro-expansion> PetscConcat(x, y)
582bde483f2SJacob Faibussowitsch 
583bde483f2SJacob Faibussowitsch   Input Parameters:
584bde483f2SJacob Faibussowitsch + x - First token
585bde483f2SJacob Faibussowitsch - y - Second token
586bde483f2SJacob Faibussowitsch 
587bde483f2SJacob Faibussowitsch   Notes:
588bde483f2SJacob Faibussowitsch   Not available from Fortran.
589bde483f2SJacob Faibussowitsch 
590bde483f2SJacob Faibussowitsch   PetscConcat() will expand both arguments before pasting them together, use PetscConcat_()
591bde483f2SJacob Faibussowitsch   if you don't want to expand them.
592bde483f2SJacob Faibussowitsch 
593bde483f2SJacob Faibussowitsch   Example usage:
594bde483f2SJacob Faibussowitsch .vb
595bde483f2SJacob Faibussowitsch   PetscConcat(hello,there) -> hellothere
596bde483f2SJacob Faibussowitsch 
597bde483f2SJacob Faibussowitsch   #define HELLO hello
598bde483f2SJacob Faibussowitsch   PetscConcat(HELLO,there)  -> hellothere
599bde483f2SJacob Faibussowitsch   PetscConcat_(HELLO,there) -> HELLOthere
600bde483f2SJacob Faibussowitsch .ve
601bde483f2SJacob Faibussowitsch 
602bde483f2SJacob Faibussowitsch   Level: beginner
603bde483f2SJacob Faibussowitsch 
604db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscExpand()`
605817da375SSatish Balay M*/
606bde483f2SJacob Faibussowitsch #define PetscConcat_(x, y) x##y
607bde483f2SJacob Faibussowitsch #define PetscConcat(x, y)  PetscConcat_(x, y)
608bde483f2SJacob Faibussowitsch 
609bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_0 1
610bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_1 0
611bde483f2SJacob Faibussowitsch 
612bde483f2SJacob Faibussowitsch /*MC
613bde483f2SJacob Faibussowitsch   PetscCompl - Expands to the integer complement of its argument
614bde483f2SJacob Faibussowitsch 
615bde483f2SJacob Faibussowitsch   Synopsis:
616bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
617bde483f2SJacob Faibussowitsch   int PetscCompl(b)
618bde483f2SJacob Faibussowitsch 
619bde483f2SJacob Faibussowitsch   Input Parameter:
620bde483f2SJacob Faibussowitsch . b - Preprocessor variable, must expand to either integer literal 0 or 1
621bde483f2SJacob Faibussowitsch 
6226aad120cSJose E. Roman   Output Parameter:
623bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
624bde483f2SJacob Faibussowitsch 
625bde483f2SJacob Faibussowitsch   Notes:
626bde483f2SJacob Faibussowitsch   Not available from Fortran.
627bde483f2SJacob Faibussowitsch 
628bde483f2SJacob Faibussowitsch   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
629bde483f2SJacob Faibussowitsch   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
630bde483f2SJacob Faibussowitsch   argument before returning the complement.
631bde483f2SJacob Faibussowitsch 
632bde483f2SJacob Faibussowitsch   This macro can be useful for negating PetscDefined() inside macros e.g.
633bde483f2SJacob Faibussowitsch 
634bde483f2SJacob Faibussowitsch $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
635bde483f2SJacob Faibussowitsch 
636bde483f2SJacob Faibussowitsch   Example usage:
637bde483f2SJacob Faibussowitsch .vb
638bde483f2SJacob Faibussowitsch   #define MY_VAR 1
639bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 0
640bde483f2SJacob Faibussowitsch 
641bde483f2SJacob Faibussowitsch   #undef  MY_VAR
642bde483f2SJacob Faibussowitsch   #define MY_VAR 0
643bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 1
644bde483f2SJacob Faibussowitsch .ve
645bde483f2SJacob Faibussowitsch 
646bde483f2SJacob Faibussowitsch   Level: beginner
647bde483f2SJacob Faibussowitsch 
648db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`
649817da375SSatish Balay M*/
650bde483f2SJacob Faibussowitsch #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
651bde483f2SJacob Faibussowitsch 
652bde483f2SJacob Faibussowitsch #if !defined(PETSC_SKIP_VARIADIC_MACROS)
653bde483f2SJacob Faibussowitsch /*MC
654bde483f2SJacob Faibussowitsch   PetscDefined - Determine whether a boolean macro is defined
655bde483f2SJacob Faibussowitsch 
656bde483f2SJacob Faibussowitsch   Synopsis:
657bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
658bde483f2SJacob Faibussowitsch   int PetscDefined(def)
659bde483f2SJacob Faibussowitsch 
660bde483f2SJacob Faibussowitsch   Input Parameter:
661bde483f2SJacob Faibussowitsch . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
662bde483f2SJacob Faibussowitsch 
663bde483f2SJacob Faibussowitsch   Outut Parameter:
664bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
665bde483f2SJacob Faibussowitsch 
666bde483f2SJacob Faibussowitsch   Notes:
667bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
66887497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
669bde483f2SJacob Faibussowitsch 
67087497f52SBarry Smith   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
67187497f52SBarry Smith   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
672bde483f2SJacob Faibussowitsch   this macro should not be used if its argument may be defined to a non-empty value other than
673bde483f2SJacob Faibussowitsch   1.
674bde483f2SJacob Faibussowitsch 
675bde483f2SJacob Faibussowitsch   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
67687497f52SBarry Smith   add custom checks in user code, one should use `PetscDefined_()`.
677bde483f2SJacob Faibussowitsch 
678bde483f2SJacob Faibussowitsch $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_,d))
679bde483f2SJacob Faibussowitsch 
680bde483f2SJacob Faibussowitsch   Developer Notes:
681bde483f2SJacob Faibussowitsch   Getting something that works in C and CPP for an arg that may or may not be defined is
682bde483f2SJacob Faibussowitsch   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
683bde483f2SJacob Faibussowitsch   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
684bde483f2SJacob Faibussowitsch   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
685bde483f2SJacob Faibussowitsch   and when the last step cherry picks the 2nd arg, we get a zero.
686bde483f2SJacob Faibussowitsch 
687bde483f2SJacob Faibussowitsch   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
688bde483f2SJacob Faibussowitsch   nonconforming implementation of variadic macros.
689bde483f2SJacob Faibussowitsch 
690bde483f2SJacob Faibussowitsch   Example Usage:
691bde483f2SJacob Faibussowitsch   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
692bde483f2SJacob Faibussowitsch   is defined then
693bde483f2SJacob Faibussowitsch 
694bde483f2SJacob Faibussowitsch .vb
695bde483f2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
696bde483f2SJacob Faibussowitsch     foo();
697bde483f2SJacob Faibussowitsch   #else
698bde483f2SJacob Faibussowitsch     bar();
699bde483f2SJacob Faibussowitsch   #endif
700bde483f2SJacob Faibussowitsch 
701bde483f2SJacob Faibussowitsch   // or alternatively within normal code
702bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
703bde483f2SJacob Faibussowitsch     foo();
704bde483f2SJacob Faibussowitsch   } else {
705bde483f2SJacob Faibussowitsch     bar();
706bde483f2SJacob Faibussowitsch   }
707bde483f2SJacob Faibussowitsch .ve
708bde483f2SJacob Faibussowitsch 
709bde483f2SJacob Faibussowitsch   is equivalent to
710bde483f2SJacob Faibussowitsch 
711bde483f2SJacob Faibussowitsch .vb
712bde483f2SJacob Faibussowitsch   #if defined(PETSC_USE_DEBUG)
713bde483f2SJacob Faibussowitsch   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
714bde483f2SJacob Faibussowitsch        foo();
715bde483f2SJacob Faibussowitsch   #   elif PETSC_USE_DEBUG == 1
716bde483f2SJacob Faibussowitsch        foo();
717bde483f2SJacob Faibussowitsch   #   else
718bde483f2SJacob Faibussowitsch        bar();
719bde483f2SJacob Faibussowitsch   #  endif
720bde483f2SJacob Faibussowitsch   #else
721bde483f2SJacob Faibussowitsch   bar();
722bde483f2SJacob Faibussowitsch   #endif
723bde483f2SJacob Faibussowitsch .ve
724bde483f2SJacob Faibussowitsch 
725bde483f2SJacob Faibussowitsch   Level: intermediate
726bde483f2SJacob Faibussowitsch 
727db781477SPatrick Sanan .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
728db781477SPatrick Sanan           `PetscExpandToNothing()`, `PetscCompl()`
729817da375SSatish Balay M*/
730bde483f2SJacob Faibussowitsch #define PetscDefined_arg_1                                    shift,
731bde483f2SJacob Faibussowitsch #define PetscDefined_arg_                                     shift,
732bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expanded(ignored, val, ...) val
733bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
734bde483f2SJacob Faibussowitsch #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
735bde483f2SJacob Faibussowitsch #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
736bde483f2SJacob Faibussowitsch #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
737bde483f2SJacob Faibussowitsch #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
738bde483f2SJacob Faibussowitsch 
739bde483f2SJacob Faibussowitsch /*MC
74087497f52SBarry Smith   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
741bde483f2SJacob Faibussowitsch   the check in optimized mode
742bde483f2SJacob Faibussowitsch 
743bde483f2SJacob Faibussowitsch   Synopsis:
744bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
745bde483f2SJacob Faibussowitsch   bool PetscUnlikelyDebug(bool cond)
746bde483f2SJacob Faibussowitsch 
747bde483f2SJacob Faibussowitsch   Not Collective
748bde483f2SJacob Faibussowitsch 
749bde483f2SJacob Faibussowitsch   Input Parameters:
750bde483f2SJacob Faibussowitsch . cond - Boolean expression
751bde483f2SJacob Faibussowitsch 
752bde483f2SJacob Faibussowitsch   Notes:
753bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
75487497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
755bde483f2SJacob Faibussowitsch 
756bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
757bde483f2SJacob Faibussowitsch   likely to be false. When PETSc is compiled in optimized mode this will always return
758bde483f2SJacob Faibussowitsch   false. Additionally, cond is guaranteed to not be evaluated when PETSc is compiled in
759bde483f2SJacob Faibussowitsch   optimized mode.
760bde483f2SJacob Faibussowitsch 
761bde483f2SJacob Faibussowitsch   Example usage:
762bde483f2SJacob Faibussowitsch   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
763bde483f2SJacob Faibussowitsch   is true. So
764bde483f2SJacob Faibussowitsch 
765bde483f2SJacob Faibussowitsch .vb
766bde483f2SJacob Faibussowitsch   if (PetscUnlikelyDebug(cond)) {
767bde483f2SJacob Faibussowitsch     foo();
768bde483f2SJacob Faibussowitsch   } else {
769bde483f2SJacob Faibussowitsch     bar();
770bde483f2SJacob Faibussowitsch   }
771bde483f2SJacob Faibussowitsch .ve
772bde483f2SJacob Faibussowitsch 
773bde483f2SJacob Faibussowitsch   is equivalent to
774bde483f2SJacob Faibussowitsch 
775bde483f2SJacob Faibussowitsch .vb
776bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
777bde483f2SJacob Faibussowitsch     if (PetscUnlikely(cond)) {
778bde483f2SJacob Faibussowitsch       foo();
779bde483f2SJacob Faibussowitsch     } else {
780bde483f2SJacob Faibussowitsch       bar();
781bde483f2SJacob Faibussowitsch     }
782bde483f2SJacob Faibussowitsch   } else {
783bde483f2SJacob Faibussowitsch     bar();
784bde483f2SJacob Faibussowitsch   }
785bde483f2SJacob Faibussowitsch .ve
786bde483f2SJacob Faibussowitsch 
787bde483f2SJacob Faibussowitsch   Level: advanced
788bde483f2SJacob Faibussowitsch 
789db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
790bde483f2SJacob Faibussowitsch M*/
791bde483f2SJacob Faibussowitsch #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
792bde483f2SJacob Faibussowitsch 
793f7e3c444SJacob Faibussowitsch #if defined(PETSC_CLANG_STATIC_ANALYZER)
794f7e3c444SJacob Faibussowitsch // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
795f7e3c444SJacob Faibussowitsch // not what ISO C allows
7969371c9d4SSatish Balay #define PetscMacroReturns_(retexpr, ...) \
7979371c9d4SSatish Balay   __extension__({ \
7989371c9d4SSatish Balay     __VA_ARGS__; \
7999371c9d4SSatish Balay     retexpr; \
8009371c9d4SSatish Balay   })
801f7e3c444SJacob Faibussowitsch #else
8029371c9d4SSatish Balay #define PetscMacroReturns_(retexpr, ...) \
8039371c9d4SSatish Balay   retexpr; \
8049371c9d4SSatish Balay   do { __VA_ARGS__; } while (0)
805f7e3c444SJacob Faibussowitsch #endif
806f7e3c444SJacob Faibussowitsch 
807bde483f2SJacob Faibussowitsch /*MC
808bde483f2SJacob Faibussowitsch   PetscExpandToNothing - Expands to absolutely nothing at all
809bde483f2SJacob Faibussowitsch 
810bde483f2SJacob Faibussowitsch   Synopsis:
811bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
812bde483f2SJacob Faibussowitsch   void PetscExpandToNothing(...)
813bde483f2SJacob Faibussowitsch 
814bde483f2SJacob Faibussowitsch   Input Parameter:
815bde483f2SJacob Faibussowitsch . __VA_ARGS__ - Anything at all
816bde483f2SJacob Faibussowitsch 
817bde483f2SJacob Faibussowitsch   Notes:
818bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
81987497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
820bde483f2SJacob Faibussowitsch 
821bde483f2SJacob Faibussowitsch   Must have at least 1 parameter.
822bde483f2SJacob Faibussowitsch 
823bde483f2SJacob Faibussowitsch   Example usage:
824bde483f2SJacob Faibussowitsch .vb
825bde483f2SJacob Faibussowitsch   PetscExpandToNothing(a,b,c) -> *nothing*
826bde483f2SJacob Faibussowitsch .ve
827bde483f2SJacob Faibussowitsch 
828bde483f2SJacob Faibussowitsch   Level: beginner
829bde483f2SJacob Faibussowitsch 
830db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
831817da375SSatish Balay M*/
832bde483f2SJacob Faibussowitsch #define PetscExpandToNothing(...)
833f7e3c444SJacob Faibussowitsch 
834f7e3c444SJacob Faibussowitsch /*MC
835f7e3c444SJacob Faibussowitsch   PetscMacroReturns - Define a macro body that returns a value
836f7e3c444SJacob Faibussowitsch 
837f7e3c444SJacob Faibussowitsch   Synopsis:
838f7e3c444SJacob Faibussowitsch   #include <petscmacros.h>
839f7e3c444SJacob Faibussowitsch   return_type PetscMacroReturns(return_type retexpr, ...)
840f7e3c444SJacob Faibussowitsch 
841f7e3c444SJacob Faibussowitsch   Input Parameters:
842f7e3c444SJacob Faibussowitsch + retexpr     - The value or expression that the macro should return
843f7e3c444SJacob Faibussowitsch - __VA_ARGS__ - The body of the macro
844f7e3c444SJacob Faibussowitsch 
845f7e3c444SJacob Faibussowitsch   Notes:
846f7e3c444SJacob Faibussowitsch   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
847f7e3c444SJacob Faibussowitsch   body of the macro and should not depend on values produced as a result of the expression. The
848f7e3c444SJacob Faibussowitsch   user should not assume that the result of this macro is equivalent to a single logical source
849f7e3c444SJacob Faibussowitsch   line. It is not portable to use macros defined using this one in conditional or loop bodies
850f7e3c444SJacob Faibussowitsch   without enclosing them in curly braces\:
851f7e3c444SJacob Faibussowitsch 
852f7e3c444SJacob Faibussowitsch .vb
853f7e3c444SJacob Faibussowitsch   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
854f7e3c444SJacob Faibussowitsch 
855f7e3c444SJacob Faibussowitsch   int err,x = 10;
856f7e3c444SJacob Faibussowitsch 
857f7e3c444SJacob Faibussowitsch   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
858f7e3c444SJacob Faibussowitsch   if (...) { err = FOO(x); }  // OK
859f7e3c444SJacob Faibussowitsch 
860f7e3c444SJacob Faibussowitsch   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
861f7e3c444SJacob Faibussowitsch   for (...) { err = FOO(x); } // OK
862f7e3c444SJacob Faibussowitsch .ve
863f7e3c444SJacob Faibussowitsch 
864f7e3c444SJacob Faibussowitsch   It is also not portable to use this macro directly inside function call, conditional, loop,
865f7e3c444SJacob Faibussowitsch   or switch statements\:
866f7e3c444SJacob Faibussowitsch 
867f7e3c444SJacob Faibussowitsch .vb
868f7e3c444SJacob Faibussowitsch   extern void bar(int);
869f7e3c444SJacob Faibussowitsch 
870f7e3c444SJacob Faibussowitsch   int ret = FOO(x);
871f7e3c444SJacob Faibussowitsch 
872f7e3c444SJacob Faibussowitsch   bar(FOO(x)); // ERROR, may not compile
873f7e3c444SJacob Faibussowitsch   bar(ret);    // OK
874f7e3c444SJacob Faibussowitsch 
875f7e3c444SJacob Faibussowitsch   if (FOO(x))  // ERROR, may not compile
876f7e3c444SJacob Faibussowitsch   if (ret)     // OK
877f7e3c444SJacob Faibussowitsch .ve
878f7e3c444SJacob Faibussowitsch 
879f7e3c444SJacob Faibussowitsch   Example usage:
880f7e3c444SJacob Faibussowitsch .vb
881f7e3c444SJacob Faibussowitsch   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
882f7e3c444SJacob Faibussowitsch 
883f7e3c444SJacob Faibussowitsch   int x = 10;
884f7e3c444SJacob Faibussowitsch   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
885f7e3c444SJacob Faibussowitsch 
886f7e3c444SJacob Faibussowitsch   // multiline macros allowed, but must declare with line continuation as usual
887f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
888f7e3c444SJacob Faibussowitsch     if (arg1 > 10) {                                            \
889f7e3c444SJacob Faibussowitsch       puts("big int!");                                         \
890f7e3c444SJacob Faibussowitsch     } else {                                                    \
891f7e3c444SJacob Faibussowitsch       return 7355608;                                           \
892f7e3c444SJacob Faibussowitsch     }                                                           \
893f7e3c444SJacob Faibussowitsch   )
894f7e3c444SJacob Faibussowitsch 
895f7e3c444SJacob Faibussowitsch   // if retexpr contains commas, must enclose it with braces
896f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
897f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
898f7e3c444SJacob Faibussowitsch 
899f7e3c444SJacob Faibussowitsch   int x = 10;
900f7e3c444SJacob Faibussowitsch   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
901f7e3c444SJacob Faibussowitsch   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
902f7e3c444SJacob Faibussowitsch .ve
903f7e3c444SJacob Faibussowitsch 
904f7e3c444SJacob Faibussowitsch   Level: intermediate
905f7e3c444SJacob Faibussowitsch 
906db781477SPatrick Sanan .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
907f7e3c444SJacob Faibussowitsch M*/
908f7e3c444SJacob Faibussowitsch #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
909f7e3c444SJacob Faibussowitsch 
910f7e3c444SJacob Faibussowitsch #define PetscMacroReturnStandard(...) PetscMacroReturns(0, __VA_ARGS__)
911f7e3c444SJacob Faibussowitsch 
912bde483f2SJacob Faibussowitsch #endif /* !PETSC_SKIP_VARIADIC_MACROS */
913bde483f2SJacob Faibussowitsch 
914dd39110bSPierre Jolivet /*MC
915dd39110bSPierre Jolivet   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
916dd39110bSPierre Jolivet 
917dd39110bSPierre Jolivet   Level: intermediate
918dd39110bSPierre Jolivet M*/
919dd39110bSPierre Jolivet #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
920dd39110bSPierre Jolivet 
921296d8154SBarry Smith /*
922296d8154SBarry Smith   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
923296d8154SBarry Smith 
924296d8154SBarry Smith   Example usage:
925296d8154SBarry Smith 
926296d8154SBarry Smith   #define mymacro(obj,...) {
927296d8154SBarry Smith     PETSC_FIRST_ARG((__VA_ARGS__,unused));
928296d8154SBarry Smith     f(22 PETSC_REST_ARG(__VA_ARGS__));
929296d8154SBarry Smith   }
930296d8154SBarry Smith 
931296d8154SBarry 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
932296d8154SBarry Smith 
933296d8154SBarry Smith   Reference:
934296d8154SBarry Smith   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
935296d8154SBarry Smith */
936296d8154SBarry Smith #define PETSC_FIRST_ARG_(N, ...)                                                                      N
937296d8154SBarry Smith #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
938296d8154SBarry Smith #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
939296d8154SBarry 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)
940296d8154SBarry Smith #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
941296d8154SBarry Smith #define PETSC_REST_HELPER_ONE(first)
942296d8154SBarry Smith #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
943296d8154SBarry Smith #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
944296d8154SBarry Smith #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
945296d8154SBarry Smith 
946bde483f2SJacob Faibussowitsch #endif /* PETSC_PREPROCESSOR_MACROS_H */
947