xref: /petsc/include/petscmacros.h (revision c748140286bc7db2f79d09b77ad2f995cbbeb47c)
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 
276797ed33SJacob Faibussowitsch #if defined(__STDC_VERSION__)
286797ed33SJacob Faibussowitsch   #if __STDC_VERSION__ <= 199901L
296797ed33SJacob Faibussowitsch     // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
306797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 9
316797ed33SJacob Faibussowitsch   #elif __STDC_VERSION__ <= 201112L
326797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 11
336797ed33SJacob Faibussowitsch   #elif __STDC_VERSION__ <= 201710L
346797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 17
356797ed33SJacob Faibussowitsch   #else
366797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
376797ed33SJacob Faibussowitsch   #endif
386797ed33SJacob Faibussowitsch #endif // __STDC_VERSION__
396797ed33SJacob Faibussowitsch 
406797ed33SJacob Faibussowitsch #ifndef PETSC_C_VERSION
416797ed33SJacob Faibussowitsch   #define PETSC_C_VERSION 0
426797ed33SJacob Faibussowitsch #endif
436797ed33SJacob Faibussowitsch 
44bde483f2SJacob Faibussowitsch /* ========================================================================== */
45bde483f2SJacob Faibussowitsch /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
46bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
47bde483f2SJacob Faibussowitsch   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
48bde483f2SJacob Faibussowitsch #else
49bde483f2SJacob Faibussowitsch   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
50bde483f2SJacob Faibussowitsch #endif
51bde483f2SJacob Faibussowitsch 
52bde483f2SJacob Faibussowitsch /* ========================================================================== */
53bde483f2SJacob Faibussowitsch /* Since PETSc manages its own extern "C" handling users should never include PETSc include
54bde483f2SJacob Faibussowitsch  * files within extern "C". This will generate a compiler error if a user does put the include
55bde483f2SJacob Faibussowitsch  * file within an extern "C".
56bde483f2SJacob Faibussowitsch  */
57bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
589371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(int);
599371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(double);
60bde483f2SJacob Faibussowitsch #endif
61bde483f2SJacob Faibussowitsch 
62bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
63bde483f2SJacob Faibussowitsch   #define PETSC_RESTRICT PETSC_CXX_RESTRICT
64bde483f2SJacob Faibussowitsch #else
656ee8c794SJacob Faibussowitsch   #define PETSC_RESTRICT restrict
66bde483f2SJacob Faibussowitsch #endif
67bde483f2SJacob Faibussowitsch 
686ee8c794SJacob Faibussowitsch #define PETSC_INLINE        PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_INLINE is deprecated (since version 3.17)\"") inline
699fbee547SJacob Faibussowitsch #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_STATIC_INLINE is deprecated (since version 3.17)\"") static inline
70bde483f2SJacob Faibussowitsch 
71bde483f2SJacob Faibussowitsch #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
72bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT __declspec(dllexport)
73bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT __declspec(dllimport)
74bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL
75bde483f2SJacob Faibussowitsch #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
76bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
77bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
78bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
79bde483f2SJacob Faibussowitsch #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
80bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
81bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
82bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
83bde483f2SJacob Faibussowitsch #else
84bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT
85bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT
86bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL
87bde483f2SJacob Faibussowitsch #endif
88bde483f2SJacob Faibussowitsch 
89bde483f2SJacob Faibussowitsch #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
90bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT
91bde483f2SJacob Faibussowitsch #else /* Win32 users need this to import symbols from petsc.dll */
92bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
93bde483f2SJacob Faibussowitsch #endif
94bde483f2SJacob Faibussowitsch 
95bde483f2SJacob Faibussowitsch /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
96bde483f2SJacob Faibussowitsch  * compiled with C++ so they may be used from C and are always visible in the shared libraries
97bde483f2SJacob Faibussowitsch  */
98bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
99bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
100bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN_TYPEDEF extern "C"
101bde483f2SJacob Faibussowitsch   #define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
102bde483f2SJacob Faibussowitsch #else
103bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
104bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN_TYPEDEF
105bde483f2SJacob Faibussowitsch   #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
106bde483f2SJacob Faibussowitsch #endif
107bde483f2SJacob Faibussowitsch 
108bde483f2SJacob Faibussowitsch #if defined(PETSC_USE_SINGLE_LIBRARY)
109bde483f2SJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
110bde483f2SJacob Faibussowitsch #else
111bde483f2SJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
112bde483f2SJacob Faibussowitsch #endif
113bde483f2SJacob Faibussowitsch 
114bde483f2SJacob Faibussowitsch /*MC
115bde483f2SJacob Faibussowitsch   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
116bde483f2SJacob Faibussowitsch 
117bde483f2SJacob Faibussowitsch   Synopsis:
118bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
119*c7481402SJacob Faibussowitsch   int PetscHasAttribute(name)
120bde483f2SJacob Faibussowitsch 
121bde483f2SJacob Faibussowitsch   Input Parameter:
122bde483f2SJacob Faibussowitsch . name - The name of the attribute to test
123bde483f2SJacob Faibussowitsch 
124bde483f2SJacob Faibussowitsch   Notes:
125bde483f2SJacob Faibussowitsch   name should be identical to what you might pass to the __attribute__ declaration itself --
126bde483f2SJacob Faibussowitsch   plain, unbroken text.
127bde483f2SJacob Faibussowitsch 
128*c7481402SJacob Faibussowitsch   As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
129*c7481402SJacob Faibussowitsch   exact type and value returned is implementation defined. In practice however, it usually
130*c7481402SJacob Faibussowitsch   returns `1` if the attribute is supported and `0` if the attribute is not supported.
131bde483f2SJacob Faibussowitsch 
132bde483f2SJacob Faibussowitsch   Example Usage:
133bde483f2SJacob Faibussowitsch   Typical usage is using the preprocessor
134bde483f2SJacob Faibussowitsch 
135bde483f2SJacob Faibussowitsch .vb
136bde483f2SJacob Faibussowitsch   #if PetscHasAttribute(always_inline)
137bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
138bde483f2SJacob Faibussowitsch   #else
139bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE
140bde483f2SJacob Faibussowitsch   #endif
141bde483f2SJacob Faibussowitsch 
142bde483f2SJacob Faibussowitsch   void foo(void) MY_ALWAYS_INLINE;
143bde483f2SJacob Faibussowitsch .ve
144bde483f2SJacob Faibussowitsch 
145bde483f2SJacob Faibussowitsch   but it can also be used in regular code
146bde483f2SJacob Faibussowitsch 
147bde483f2SJacob Faibussowitsch .vb
148bde483f2SJacob Faibussowitsch   if (PetscHasAttribute(some_attribute)) {
149bde483f2SJacob Faibussowitsch     foo();
150bde483f2SJacob Faibussowitsch   } else {
151bde483f2SJacob Faibussowitsch     bar();
152bde483f2SJacob Faibussowitsch   }
153bde483f2SJacob Faibussowitsch .ve
154bde483f2SJacob Faibussowitsch 
155bde483f2SJacob Faibussowitsch   Level: intermediate
156bde483f2SJacob Faibussowitsch 
157*c7481402SJacob Faibussowitsch .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
158*c7481402SJacob Faibussowitsch `PETSC_ATTRIBUTE_FORMAT`
159bde483f2SJacob Faibussowitsch M*/
160bde483f2SJacob Faibussowitsch #if !defined(__has_attribute)
161bde483f2SJacob Faibussowitsch   #define __has_attribute(x) 0
162bde483f2SJacob Faibussowitsch #endif
163bde483f2SJacob Faibussowitsch #define PetscHasAttribute(name) __has_attribute(name)
164bde483f2SJacob Faibussowitsch 
165*c7481402SJacob Faibussowitsch /*MC
166*c7481402SJacob Faibussowitsch   PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
167*c7481402SJacob Faibussowitsch 
168*c7481402SJacob Faibussowitsch   Synopsis:
169*c7481402SJacob Faibussowitsch   #include <petscmacros.h>
170*c7481402SJacob Faibussowitsch   int PetscHasBuiltin(name)
171*c7481402SJacob Faibussowitsch 
172*c7481402SJacob Faibussowitsch   Input Parameter:
173*c7481402SJacob Faibussowitsch . name - the name of the builtin routine
174*c7481402SJacob Faibussowitsch 
175*c7481402SJacob Faibussowitsch   Notes:
176*c7481402SJacob Faibussowitsch   Evalutates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
177*c7481402SJacob Faibussowitsch   (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
178*c7481402SJacob Faibussowitsch   detector is itself is a compiler extension with implementation-defined return type and
179*c7481402SJacob Faibussowitsch   semantics. Some compilers implement it as a macro, others as a compiler function. In practice
180*c7481402SJacob Faibussowitsch   however, all supporting compilers return an integer boolean as described.
181*c7481402SJacob Faibussowitsch 
182*c7481402SJacob Faibussowitsch   Example Usage:
183*c7481402SJacob Faibussowitsch   Typical usage is in preprocessor directives
184*c7481402SJacob Faibussowitsch 
185*c7481402SJacob Faibussowitsch .vb
186*c7481402SJacob Faibussowitsch   #if PetscHasBuiltin(__builtin_trap)
187*c7481402SJacob Faibussowitsch   __builtin_trap();
188*c7481402SJacob Faibussowitsch   #else
189*c7481402SJacob Faibussowitsch   abort();
190*c7481402SJacob Faibussowitsch   #endif
191*c7481402SJacob Faibussowitsch .ve
192*c7481402SJacob Faibussowitsch 
193*c7481402SJacob Faibussowitsch   But it may also be used in regular code
194*c7481402SJacob Faibussowitsch 
195*c7481402SJacob Faibussowitsch .vb
196*c7481402SJacob Faibussowitsch   if (PetscHasBuiltin(__builtin_alloca)) {
197*c7481402SJacob Faibussowitsch     foo();
198*c7481402SJacob Faibussowitsch   } else {
199*c7481402SJacob Faibussowitsch     bar();
200*c7481402SJacob Faibussowitsch   }
201*c7481402SJacob Faibussowitsch .ve
202*c7481402SJacob Faibussowitsch 
203*c7481402SJacob Faibussowitsch   Level: intermediate
204*c7481402SJacob Faibussowitsch 
205*c7481402SJacob Faibussowitsch .seealso: `PetscHasAttribute()`, `PetscAssume()`
206*c7481402SJacob Faibussowitsch M*/
207*c7481402SJacob Faibussowitsch #if !defined(__has_builtin)
208*c7481402SJacob Faibussowitsch   #define __has_builtin(x) 0
209*c7481402SJacob Faibussowitsch #endif
210*c7481402SJacob Faibussowitsch // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
211*c7481402SJacob Faibussowitsch // __builtin_types_compatible_p which take types or other non-functiony things as
212*c7481402SJacob Faibussowitsch // arguments. The correct way to detect these then is to use __is_identifier (also a clang
213*c7481402SJacob Faibussowitsch // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
214*c7481402SJacob Faibussowitsch #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
215*c7481402SJacob Faibussowitsch   #define PetscHasBuiltin(name) __is_identifier(name)
216*c7481402SJacob Faibussowitsch #else
217*c7481402SJacob Faibussowitsch   #define PetscHasBuiltin(name) __has_builtin(name)
218*c7481402SJacob Faibussowitsch #endif
219*c7481402SJacob Faibussowitsch 
22093d501b3SJacob Faibussowitsch #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
22193d501b3SJacob Faibussowitsch   /*
22293d501b3SJacob Faibussowitsch    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
22393d501b3SJacob Faibussowitsch    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
22493d501b3SJacob Faibussowitsch    does not match the actual type of the argument being passed in
22593d501b3SJacob Faibussowitsch */
22693d501b3SJacob Faibussowitsch   #if PetscHasAttribute(pointer_with_type_tag)
22793d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
22893d501b3SJacob Faibussowitsch   #endif
22993d501b3SJacob Faibussowitsch 
23093d501b3SJacob Faibussowitsch   #if PetscHasAttribute(type_tag_for_datatype)
23193d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
23293d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
23393d501b3SJacob Faibussowitsch   #endif
23493d501b3SJacob Faibussowitsch #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
23593d501b3SJacob Faibussowitsch 
23693d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
23793d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
23893d501b3SJacob Faibussowitsch #endif
23993d501b3SJacob Faibussowitsch 
24093d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
24193d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
24293d501b3SJacob Faibussowitsch #endif
24393d501b3SJacob Faibussowitsch 
24493d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
24593d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
24693d501b3SJacob Faibussowitsch #endif
24793d501b3SJacob Faibussowitsch 
248bde483f2SJacob Faibussowitsch /*MC
24963a3b9bcSJacob Faibussowitsch   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
25063a3b9bcSJacob Faibussowitsch   as format specifiers and checked for validity
25163a3b9bcSJacob Faibussowitsch 
25263a3b9bcSJacob Faibussowitsch   Synopsis:
25363a3b9bcSJacob Faibussowitsch   #include <petscmacros.h>
25463a3b9bcSJacob Faibussowitsch   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
25563a3b9bcSJacob Faibussowitsch 
25663a3b9bcSJacob Faibussowitsch   Input Parameters:
25763a3b9bcSJacob Faibussowitsch + strIdx   - The (1-indexed) location of the format string in the argument list
25863a3b9bcSJacob Faibussowitsch - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
25963a3b9bcSJacob Faibussowitsch 
26063a3b9bcSJacob Faibussowitsch   Notes:
26163a3b9bcSJacob Faibussowitsch   This function attribute causes the compiler to issue warnings when the format specifier does
26263a3b9bcSJacob Faibussowitsch   not match the type of the variable that will be formatted, or when there exists a mismatch
26363a3b9bcSJacob Faibussowitsch   between the number of format specifiers and variables to be formatted. It is safe to use this
26463a3b9bcSJacob Faibussowitsch   macro if your compiler does not support format specifier checking (though this is
26563a3b9bcSJacob Faibussowitsch   exceeedingly rare).
26663a3b9bcSJacob Faibussowitsch 
26763a3b9bcSJacob Faibussowitsch   Both strIdx and vaArgIdx must be compile-time constant integer literals and cannot have the
26863a3b9bcSJacob Faibussowitsch   same value.
26963a3b9bcSJacob Faibussowitsch 
27063a3b9bcSJacob Faibussowitsch   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
27163a3b9bcSJacob Faibussowitsch   the argument list, that is, there is no way to indicate gaps which should not be checked.
27263a3b9bcSJacob Faibussowitsch 
27387497f52SBarry Smith   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
27463a3b9bcSJacob Faibussowitsch   header files. In this case the macro will expand empty.
27563a3b9bcSJacob Faibussowitsch 
27663a3b9bcSJacob Faibussowitsch   Example Usage:
27763a3b9bcSJacob Faibussowitsch .vb
27863a3b9bcSJacob Faibussowitsch   // format string is 2nd argument, variable argument list containing args is 3rd argument
27963a3b9bcSJacob Faibussowitsch   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
28063a3b9bcSJacob Faibussowitsch 
28163a3b9bcSJacob Faibussowitsch   int    x = 1;
28263a3b9bcSJacob Faibussowitsch   double y = 50.0;
28363a3b9bcSJacob Faibussowitsch 
28463a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
28563a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
28663a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d %g",x,y); // OK
28763a3b9bcSJacob Faibussowitsch .ve
28863a3b9bcSJacob Faibussowitsch 
28963a3b9bcSJacob Faibussowitsch   Level: developer
29063a3b9bcSJacob Faibussowitsch 
291db781477SPatrick Sanan .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
29263a3b9bcSJacob Faibussowitsch M*/
29363a3b9bcSJacob Faibussowitsch #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
29463a3b9bcSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
29563a3b9bcSJacob Faibussowitsch #else
29663a3b9bcSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
29763a3b9bcSJacob Faibussowitsch #endif
29863a3b9bcSJacob Faibussowitsch 
29963a3b9bcSJacob Faibussowitsch /*MC
300d8e4614bSJacob Faibussowitsch   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
301d8e4614bSJacob Faibussowitsch   executed
302d8e4614bSJacob Faibussowitsch 
303d8e4614bSJacob Faibussowitsch   Notes:
304d8e4614bSJacob Faibussowitsch   The marked function is often optimized for size rather than speed and may be grouped alongside
305d8e4614bSJacob Faibussowitsch   other equally frigid routines improving code locality of lukewarm or hotter parts of program.
306d8e4614bSJacob Faibussowitsch 
307d8e4614bSJacob Faibussowitsch   The paths leading to cold functions are usually automatically marked as unlikely by the
308d8e4614bSJacob Faibussowitsch   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
309d8e4614bSJacob Faibussowitsch   as error handlers -- as cold to improve optimization of the surrounding temperate functions.
310d8e4614bSJacob Faibussowitsch 
311d8e4614bSJacob Faibussowitsch   Example Usage:
312d8e4614bSJacob Faibussowitsch .vb
313d8e4614bSJacob Faibussowitsch   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
314d8e4614bSJacob Faibussowitsch 
315d8e4614bSJacob Faibussowitsch   if (temperature < 0) {
316d8e4614bSJacob Faibussowitsch     return my_error_handler(...); // chilly!
317d8e4614bSJacob Faibussowitsch   }
318d8e4614bSJacob Faibussowitsch .ve
319d8e4614bSJacob Faibussowitsch 
320d8e4614bSJacob Faibussowitsch   Level: intermediate
321d8e4614bSJacob Faibussowitsch 
322db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
323db781477SPatrick Sanan           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
324d8e4614bSJacob Faibussowitsch M*/
325d8e4614bSJacob Faibussowitsch #if PetscHasAttribute(__cold__)
326d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
327d8e4614bSJacob Faibussowitsch #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
328d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
329d8e4614bSJacob Faibussowitsch #else
330d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD
331d8e4614bSJacob Faibussowitsch #endif
332d8e4614bSJacob Faibussowitsch 
333d8e4614bSJacob Faibussowitsch /*MC
334bde483f2SJacob Faibussowitsch   PETSC_NULLPTR - Standard way of indicating a null value or pointer
335bde483f2SJacob Faibussowitsch 
336bde483f2SJacob Faibussowitsch   Notes:
337bde483f2SJacob Faibussowitsch   Equivalent to NULL in C source, and nullptr in C++ source. Note that for the purposes of
33887497f52SBarry Smith   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
339bde483f2SJacob Faibussowitsch   equivalent to setting the same pointer to NULL in C. That is to say that the following
340bde483f2SJacob Faibussowitsch   expressions are equivalent\:
341bde483f2SJacob Faibussowitsch 
342bde483f2SJacob Faibussowitsch .vb
343bde483f2SJacob Faibussowitsch   ptr == PETSC_NULLPTR
344bde483f2SJacob Faibussowitsch   ptr == NULL
345bde483f2SJacob Faibussowitsch   ptr == 0
346bde483f2SJacob Faibussowitsch   !ptr
347bde483f2SJacob Faibussowitsch 
348bde483f2SJacob Faibussowitsch   ptr = PETSC_NULLPTR
349bde483f2SJacob Faibussowitsch   ptr = NULL
350bde483f2SJacob Faibussowitsch   ptr = 0
351bde483f2SJacob Faibussowitsch .ve
352bde483f2SJacob Faibussowitsch 
353bde483f2SJacob Faibussowitsch   and for completeness' sake\:
354bde483f2SJacob Faibussowitsch 
355bde483f2SJacob Faibussowitsch .vb
356bde483f2SJacob Faibussowitsch   PETSC_NULLPTR == NULL
357bde483f2SJacob Faibussowitsch .ve
358bde483f2SJacob Faibussowitsch 
359bde483f2SJacob Faibussowitsch   Fortran Notes:
360bde483f2SJacob Faibussowitsch   Not available in Fortran
361bde483f2SJacob Faibussowitsch 
362bde483f2SJacob Faibussowitsch   Example Usage:
363bde483f2SJacob Faibussowitsch .vb
364bde483f2SJacob Faibussowitsch   // may be used in place of '\0' or other such teminators in the definition of char arrays
365bde483f2SJacob Faibussowitsch   const char *const MyEnumTypes[] = {
366bde483f2SJacob Faibussowitsch     "foo",
367bde483f2SJacob Faibussowitsch     "bar",
368bde483f2SJacob Faibussowitsch     PETSC_NULLPTR
369bde483f2SJacob Faibussowitsch   };
370bde483f2SJacob Faibussowitsch 
371bde483f2SJacob Faibussowitsch   // may be used to nullify objects
372bde483f2SJacob Faibussowitsch   PetscObject obj = PETSC_NULLPTR;
373bde483f2SJacob Faibussowitsch 
374bde483f2SJacob Faibussowitsch   // may be used in any function expecting NULL
375bde483f2SJacob Faibussowitsch   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
376bde483f2SJacob Faibussowitsch .ve
377bde483f2SJacob Faibussowitsch 
378bde483f2SJacob Faibussowitsch   Developer Notes:
37987497f52SBarry Smith   `PETSC_NULLPTR` must be used in place of NULL in all C++ source files. Using NULL in source
380bde483f2SJacob Faibussowitsch   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
381bde483f2SJacob Faibussowitsch   resolution and/or compiler warnings.
382bde483f2SJacob Faibussowitsch 
383bde483f2SJacob Faibussowitsch   Level: beginner
384bde483f2SJacob Faibussowitsch 
385db781477SPatrick Sanan .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
386817da375SSatish Balay M*/
387bde483f2SJacob Faibussowitsch 
388bde483f2SJacob Faibussowitsch /*MC
389bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 - C++14 constexpr
390bde483f2SJacob Faibussowitsch 
391bde483f2SJacob Faibussowitsch   Notes:
392bde483f2SJacob Faibussowitsch   Equivalent to constexpr when using a C++ compiler that supports C++14. Expands to nothing
393bde483f2SJacob Faibussowitsch   if the C++ compiler does not suppport C++14 or when not compiling with a C++ compiler. Note
394bde483f2SJacob Faibussowitsch   that this cannot be used in cases where an empty expansion would result in invalid code. It
395bde483f2SJacob Faibussowitsch   is safe to use this in C source files.
396bde483f2SJacob Faibussowitsch 
397bde483f2SJacob Faibussowitsch   Fortran Notes:
398bde483f2SJacob Faibussowitsch   Not available in Fortran
399bde483f2SJacob Faibussowitsch 
400bde483f2SJacob Faibussowitsch   Example Usage:
401bde483f2SJacob Faibussowitsch .vb
402bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 int factorial(int n)
403bde483f2SJacob Faibussowitsch   {
404bde483f2SJacob Faibussowitsch     int r = 1;
405bde483f2SJacob Faibussowitsch 
406bde483f2SJacob Faibussowitsch     do {
407bde483f2SJacob Faibussowitsch       r *= n;
408bde483f2SJacob Faibussowitsch     } while (--n);
409bde483f2SJacob Faibussowitsch     return r;
410bde483f2SJacob Faibussowitsch   }
411bde483f2SJacob Faibussowitsch .ve
412bde483f2SJacob Faibussowitsch 
413bde483f2SJacob Faibussowitsch   Level: beginner
414bde483f2SJacob Faibussowitsch 
415db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
416817da375SSatish Balay M*/
417bde483f2SJacob Faibussowitsch 
418bde483f2SJacob Faibussowitsch /*MC
419bde483f2SJacob Faibussowitsch   PETSC_NODISCARD - Mark the return value of a function as non-discardable
420bde483f2SJacob Faibussowitsch 
421bde483f2SJacob Faibussowitsch   Notes:
422bde483f2SJacob Faibussowitsch   Hints to the compiler that the return value of a function must be captured. A diagnostic may
423bde483f2SJacob Faibussowitsch   (but is not required) be emitted if the value is discarded. It is safe to use this in C
424bde483f2SJacob Faibussowitsch   and C++ source files.
425bde483f2SJacob Faibussowitsch 
426bde483f2SJacob Faibussowitsch   Fortran Notes:
427bde483f2SJacob Faibussowitsch   Not available in Fortran
428bde483f2SJacob Faibussowitsch 
429bde483f2SJacob Faibussowitsch   Example Usage:
430bde483f2SJacob Faibussowitsch .vb
431bde483f2SJacob Faibussowitsch   class Foo
432bde483f2SJacob Faibussowitsch   {
433bde483f2SJacob Faibussowitsch     int x;
434bde483f2SJacob Faibussowitsch 
435bde483f2SJacob Faibussowitsch   public:
436bde483f2SJacob Faibussowitsch     PETSC_NODISCARD Foo(int y) : x(y) { }
437bde483f2SJacob Faibussowitsch   };
438bde483f2SJacob Faibussowitsch 
439bde483f2SJacob Faibussowitsch   PETSC_NODISCARD int factorial(int n)
440bde483f2SJacob Faibussowitsch   {
441bde483f2SJacob Faibussowitsch     return n <= 1 ? 1 : (n * factorial(n - 1));
442bde483f2SJacob Faibussowitsch   }
443bde483f2SJacob Faibussowitsch 
444bde483f2SJacob Faibussowitsch   auto x = factorial(10); // OK, capturing return value
445bde483f2SJacob Faibussowitsch   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
446bde483f2SJacob Faibussowitsch 
447bde483f2SJacob Faibussowitsch   auto f = Foo(x); // OK, capturing constructed object
448bde483f2SJacob Faibussowitsch   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
449bde483f2SJacob Faibussowitsch .ve
450bde483f2SJacob Faibussowitsch 
451bde483f2SJacob Faibussowitsch   Developer Notes:
452bde483f2SJacob Faibussowitsch   It is highly recommended if not downright required that any PETSc routines written in C++
45387497f52SBarry Smith   returning a PetscErrorCode be marked `PETSC_NODISCARD`. Ignoring the return value of PETSc
454bde483f2SJacob Faibussowitsch   routines is not supported; unhandled errors may leave PETSc in an unrecoverable state.
455bde483f2SJacob Faibussowitsch 
456bde483f2SJacob Faibussowitsch   Level: beginner
457bde483f2SJacob Faibussowitsch 
458db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
459817da375SSatish Balay M*/
460bde483f2SJacob Faibussowitsch 
461bde483f2SJacob Faibussowitsch /* C++11 features */
4626ee8c794SJacob Faibussowitsch #if defined(__cplusplus)
463bde483f2SJacob Faibussowitsch   #define PETSC_NULLPTR nullptr
464bde483f2SJacob Faibussowitsch #else
465bde483f2SJacob Faibussowitsch   #define PETSC_NULLPTR NULL
466bde483f2SJacob Faibussowitsch #endif
467bde483f2SJacob Faibussowitsch 
468bde483f2SJacob Faibussowitsch /* C++14 features */
4690e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 14
4706ee8c794SJacob Faibussowitsch   #define PETSC_CONSTEXPR_14 constexpr
471bde483f2SJacob Faibussowitsch #else
472bde483f2SJacob Faibussowitsch   #define PETSC_CONSTEXPR_14
473bde483f2SJacob Faibussowitsch #endif
474bde483f2SJacob Faibussowitsch 
475bde483f2SJacob Faibussowitsch /* C++17 features */
4760e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 17
477bde483f2SJacob Faibussowitsch   #define PETSC_NODISCARD    [[nodiscard]]
4780e6b6b59SJacob Faibussowitsch   #define PETSC_CONSTEXPR_17 constexpr
479bde483f2SJacob Faibussowitsch #else
480bde483f2SJacob Faibussowitsch   #if PetscHasAttribute(warn_unused_result)
481bde483f2SJacob Faibussowitsch     #define PETSC_NODISCARD __attribute__((warn_unused_result))
482bde483f2SJacob Faibussowitsch   #endif
4830e6b6b59SJacob Faibussowitsch   #define PETSC_CONSTEXPR_17
4840e6b6b59SJacob Faibussowitsch #endif
4850e6b6b59SJacob Faibussowitsch 
4860e6b6b59SJacob Faibussowitsch #ifndef PETSC_NODISCARD
4870e6b6b59SJacob Faibussowitsch   #define PETSC_NODISCARD
488bde483f2SJacob Faibussowitsch #endif
489bde483f2SJacob Faibussowitsch 
490bde483f2SJacob Faibussowitsch #include <petscversion.h>
491bde483f2SJacob Faibussowitsch #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
492bde483f2SJacob Faibussowitsch 
493267267bdSJacob Faibussowitsch /* designated initializers since C99 and C++20, MSVC never supports them though */
4940e6b6b59SJacob Faibussowitsch #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
495267267bdSJacob Faibussowitsch   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
496267267bdSJacob Faibussowitsch #else
497267267bdSJacob Faibussowitsch   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
498267267bdSJacob Faibussowitsch #endif
499267267bdSJacob Faibussowitsch 
500bde483f2SJacob Faibussowitsch /*MC
50187497f52SBarry Smith   PetscUnlikely - Hints the compiler that the given condition is usually false
502bde483f2SJacob Faibussowitsch 
503bde483f2SJacob Faibussowitsch   Synopsis:
504bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
505bde483f2SJacob Faibussowitsch   bool PetscUnlikely(bool cond)
506bde483f2SJacob Faibussowitsch 
507bde483f2SJacob Faibussowitsch   Not Collective
508bde483f2SJacob Faibussowitsch 
509bde483f2SJacob Faibussowitsch   Input Parameter:
510bde483f2SJacob Faibussowitsch . cond - Boolean expression
511bde483f2SJacob Faibussowitsch 
512bde483f2SJacob Faibussowitsch   Notes:
513bde483f2SJacob Faibussowitsch   Not available from fortran.
514bde483f2SJacob Faibussowitsch 
515bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
516bde483f2SJacob Faibussowitsch   unlikely to be true.
517bde483f2SJacob Faibussowitsch 
518bde483f2SJacob Faibussowitsch   Example usage:
519bde483f2SJacob Faibussowitsch .vb
520bde483f2SJacob Faibussowitsch   if (PetscUnlikely(cond)) {
521bde483f2SJacob Faibussowitsch     foo(); // cold path
522bde483f2SJacob Faibussowitsch   } else {
523bde483f2SJacob Faibussowitsch     bar(); // hot path
524bde483f2SJacob Faibussowitsch   }
525bde483f2SJacob Faibussowitsch .ve
526bde483f2SJacob Faibussowitsch 
527bde483f2SJacob Faibussowitsch   Level: advanced
528bde483f2SJacob Faibussowitsch 
529db781477SPatrick Sanan .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
530db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
531bde483f2SJacob Faibussowitsch M*/
532bde483f2SJacob Faibussowitsch 
533bde483f2SJacob Faibussowitsch /*MC
53487497f52SBarry Smith   PetscLikely - Hints the compiler that the given condition is usually true
535bde483f2SJacob Faibussowitsch 
536bde483f2SJacob Faibussowitsch   Synopsis:
537bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
538bde483f2SJacob Faibussowitsch   bool PetscLikely(bool cond)
539bde483f2SJacob Faibussowitsch 
540bde483f2SJacob Faibussowitsch   Not Collective
541bde483f2SJacob Faibussowitsch 
542bde483f2SJacob Faibussowitsch   Input Parameter:
543bde483f2SJacob Faibussowitsch . cond - Boolean expression
544bde483f2SJacob Faibussowitsch 
545bde483f2SJacob Faibussowitsch   Notes:
546bde483f2SJacob Faibussowitsch   Not available from fortran.
547bde483f2SJacob Faibussowitsch 
548bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
549bde483f2SJacob Faibussowitsch   likely to be true.
550bde483f2SJacob Faibussowitsch 
551bde483f2SJacob Faibussowitsch   Example usage:
552bde483f2SJacob Faibussowitsch .vb
553bde483f2SJacob Faibussowitsch   if (PetscLikely(cond)) {
554bde483f2SJacob Faibussowitsch     foo(); // hot path
555bde483f2SJacob Faibussowitsch   } else {
556bde483f2SJacob Faibussowitsch     bar(); // cold path
557bde483f2SJacob Faibussowitsch   }
558bde483f2SJacob Faibussowitsch .ve
559bde483f2SJacob Faibussowitsch 
560bde483f2SJacob Faibussowitsch   Level: advanced
561bde483f2SJacob Faibussowitsch 
562db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
563db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
564bde483f2SJacob Faibussowitsch M*/
565bde483f2SJacob Faibussowitsch #if defined(PETSC_HAVE_BUILTIN_EXPECT)
566bde483f2SJacob Faibussowitsch   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
567bde483f2SJacob Faibussowitsch   #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
568bde483f2SJacob Faibussowitsch #else
569bde483f2SJacob Faibussowitsch   #define PetscUnlikely(cond) (cond)
570bde483f2SJacob Faibussowitsch   #define PetscLikely(cond)   (cond)
571bde483f2SJacob Faibussowitsch #endif
572bde483f2SJacob Faibussowitsch 
573bde483f2SJacob Faibussowitsch /*MC
574817da375SSatish Balay   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
575bde483f2SJacob Faibussowitsch 
576bde483f2SJacob Faibussowitsch   Synopsis:
577bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
578bde483f2SJacob Faibussowitsch   void PetscUnreachable(void)
579bde483f2SJacob Faibussowitsch 
580bde483f2SJacob Faibussowitsch   Notes:
581bde483f2SJacob Faibussowitsch   Indicates to the compiler (usually via some built-in) that a particular code path is always
582bde483f2SJacob Faibussowitsch   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
583bde483f2SJacob Faibussowitsch   unceremonious crash.
584bde483f2SJacob Faibussowitsch 
585bde483f2SJacob Faibussowitsch   Example usage:
586bde483f2SJacob Faibussowitsch   Useful in situations such as switches over enums where not all enumeration values are
587bde483f2SJacob Faibussowitsch   explicitly covered by the switch
588bde483f2SJacob Faibussowitsch 
589bde483f2SJacob Faibussowitsch .vb
590bde483f2SJacob Faibussowitsch   typedef enum {RED, GREEN, BLUE} Color;
591bde483f2SJacob Faibussowitsch 
592bde483f2SJacob Faibussowitsch   int foo(Color c)
593bde483f2SJacob Faibussowitsch   {
594bde483f2SJacob Faibussowitsch     // it is known to programmer (or checked previously) that c is either RED or GREEN
595bde483f2SJacob Faibussowitsch     // but compiler may not be able to deduce this and/or emit spurious warnings
596bde483f2SJacob Faibussowitsch     switch (c) {
597bde483f2SJacob Faibussowitsch       case RED:
598bde483f2SJacob Faibussowitsch         return bar();
599bde483f2SJacob Faibussowitsch       case GREEN:
600bde483f2SJacob Faibussowitsch         return baz();
601bde483f2SJacob Faibussowitsch       default:
602bde483f2SJacob Faibussowitsch         PetscUnreachable(); // program is ill-formed if executed
603bde483f2SJacob Faibussowitsch     }
604bde483f2SJacob Faibussowitsch   }
605bde483f2SJacob Faibussowitsch .ve
606bde483f2SJacob Faibussowitsch 
607bde483f2SJacob Faibussowitsch   Level: advanced
608bde483f2SJacob Faibussowitsch 
609*c7481402SJacob Faibussowitsch .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
610817da375SSatish Balay M*/
611e58a63e1SJacob Faibussowitsch #if defined(__GNUC__)
612e58a63e1SJacob Faibussowitsch   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
613e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() __builtin_unreachable()
614e58a63e1SJacob Faibussowitsch #elif defined(_MSC_VER) /* MSVC */
615e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() __assume(0)
616e58a63e1SJacob Faibussowitsch #else /* ??? */
617e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
618e58a63e1SJacob Faibussowitsch #endif
619bde483f2SJacob Faibussowitsch 
620bde483f2SJacob Faibussowitsch /*MC
621*c7481402SJacob Faibussowitsch   PetscAssume - Indicate to the compiler a condition that is defined to be true
622*c7481402SJacob Faibussowitsch 
623*c7481402SJacob Faibussowitsch   Synopsis:
624*c7481402SJacob Faibussowitsch   #include <petscmacros.h>
625*c7481402SJacob Faibussowitsch   void PetscAssume(bool cond)
626*c7481402SJacob Faibussowitsch 
627*c7481402SJacob Faibussowitsch   Input Parameter:
628*c7481402SJacob Faibussowitsch . cond - Boolean expression
629*c7481402SJacob Faibussowitsch 
630*c7481402SJacob Faibussowitsch   Notes:
631*c7481402SJacob Faibussowitsch   If supported by the compiler, `cond` is used to inform the optimizer of an invariant
632*c7481402SJacob Faibussowitsch   truth. The argument itself is never evaluated, so any side effects of the expression will be
633*c7481402SJacob Faibussowitsch   discarded. This macro is used in `PetscAssert()` to retain information gained from debug
634*c7481402SJacob Faibussowitsch   checks that would be lost in optimized builds. For example\:
635*c7481402SJacob Faibussowitsch 
636*c7481402SJacob Faibussowitsch .vb
637*c7481402SJacob Faibussowitsch   PetscErrorCode foo(PetscInt x) {
638*c7481402SJacob Faibussowitsch 
639*c7481402SJacob Faibussowitsch     PetscAssert(x >= 0, ...);
640*c7481402SJacob Faibussowitsch   }
641*c7481402SJacob Faibussowitsch .ve
642*c7481402SJacob Faibussowitsch 
643*c7481402SJacob Faibussowitsch   The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
644*c7481402SJacob Faibussowitsch   if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
645*c7481402SJacob Faibussowitsch   when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
646*c7481402SJacob Faibussowitsch   optimizer cannot deduce any information from them.
647*c7481402SJacob Faibussowitsch 
648*c7481402SJacob Faibussowitsch   Due to compiler limitations `PetscAssume()` works best when `cond` involves
649*c7481402SJacob Faibussowitsch   constants. Certain compilers do not yet propogate symbolic inequalities i.e.\:
650*c7481402SJacob Faibussowitsch 
651*c7481402SJacob Faibussowitsch .vb
652*c7481402SJacob Faibussowitsch   int a, b, var_five;
653*c7481402SJacob Faibussowitsch 
654*c7481402SJacob Faibussowitsch   // BEST, all supporting compilers will understand a cannot be >= 5
655*c7481402SJacob Faibussowitsch   PetscAssume(a < 5);
656*c7481402SJacob Faibussowitsch 
657*c7481402SJacob Faibussowitsch    // OK, some compilers may understand that a cannot be >= 5
658*c7481402SJacob Faibussowitsch   PetscAssume(a <= b && b < 5);
659*c7481402SJacob Faibussowitsch 
660*c7481402SJacob Faibussowitsch    // WORST, most compilers will not get the memo
661*c7481402SJacob Faibussowitsch   PetscAssume(a <= b && b < var_five);
662*c7481402SJacob Faibussowitsch .ve
663*c7481402SJacob Faibussowitsch 
664*c7481402SJacob Faibussowitsch   If the condition is violated at runtime then behavior is wholly undefined. If the
665*c7481402SJacob Faibussowitsch   condition is violated at compile-time, the condition "supersedes" the compile-time violation
666*c7481402SJacob Faibussowitsch   and the program is ill-formed, no diagnostic required. For example consider the following\:
667*c7481402SJacob Faibussowitsch 
668*c7481402SJacob Faibussowitsch .vb
669*c7481402SJacob Faibussowitsch   PetscInt x = 0;
670*c7481402SJacob Faibussowitsch 
671*c7481402SJacob Faibussowitsch   PetscAssume(x != 0);
672*c7481402SJacob Faibussowitsch   if (x == 0) {
673*c7481402SJacob Faibussowitsch     x += 10;
674*c7481402SJacob Faibussowitsch   } else {
675*c7481402SJacob Faibussowitsch     popen("rm -rf /", "w");
676*c7481402SJacob Faibussowitsch   }
677*c7481402SJacob Faibussowitsch .ve
678*c7481402SJacob Faibussowitsch 
679*c7481402SJacob Faibussowitsch   Even though `x` is demonstrably `0` the compiler may opt to\:
680*c7481402SJacob Faibussowitsch 
681*c7481402SJacob Faibussowitsch   - emit an unconditional `popen("rm -rf /", "w")`
682*c7481402SJacob Faibussowitsch   - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
683*c7481402SJacob Faibussowitsch   - reformat the primary disk partition
684*c7481402SJacob Faibussowitsch 
685*c7481402SJacob Faibussowitsch   Level: advanced
686*c7481402SJacob Faibussowitsch 
687*c7481402SJacob Faibussowitsch .seealso: `PetscAssert()`
688*c7481402SJacob Faibussowitsch M*/
689*c7481402SJacob Faibussowitsch #if defined(_MSC_VER) // msvc
690*c7481402SJacob Faibussowitsch   #define PetscAssume(...) __assume(__VA_ARGS__)
691*c7481402SJacob Faibussowitsch #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
692*c7481402SJacob Faibussowitsch   #define PetscAssume(...) \
693*c7481402SJacob Faibussowitsch     do { \
694*c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic push"); \
695*c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic ignored \"-Wassume\""); \
696*c7481402SJacob Faibussowitsch       __builtin_assume(__VA_ARGS__); \
697*c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic pop"); \
698*c7481402SJacob Faibussowitsch     } while (0)
699*c7481402SJacob Faibussowitsch #else // gcc (and really old clang)
700*c7481402SJacob Faibussowitsch   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
701*c7481402SJacob Faibussowitsch   //
702*c7481402SJacob Faibussowitsch   // if (PetscUnlikely(!cond)) PetscUnreachable();
703*c7481402SJacob Faibussowitsch   //
704*c7481402SJacob Faibussowitsch   // but this it unsavory because the side effects of cond are not guaranteed to be
705*c7481402SJacob Faibussowitsch   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
706*c7481402SJacob Faibussowitsch   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
707*c7481402SJacob Faibussowitsch   // always do so. This is especially the case for opaque or non-inline function calls:
708*c7481402SJacob Faibussowitsch   //
709*c7481402SJacob Faibussowitsch   // extern int bar(int);
710*c7481402SJacob Faibussowitsch   //
711*c7481402SJacob Faibussowitsch   // int foo(int x) {
712*c7481402SJacob Faibussowitsch   //   PetscAssume(bar(x) == 2);
713*c7481402SJacob Faibussowitsch   //   if (bar(x) == 2) {
714*c7481402SJacob Faibussowitsch   //     return 1;
715*c7481402SJacob Faibussowitsch   //   } else {
716*c7481402SJacob Faibussowitsch   //     return 0;
717*c7481402SJacob Faibussowitsch   //   }
718*c7481402SJacob Faibussowitsch   // }
719*c7481402SJacob Faibussowitsch   //
720*c7481402SJacob Faibussowitsch   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
721*c7481402SJacob Faibussowitsch   // cond "tested" in the condition, but this is done to silence set-but-unused variable warnings
722*c7481402SJacob Faibussowitsch   #define PetscAssume(...) \
723*c7481402SJacob Faibussowitsch     do { \
724*c7481402SJacob Faibussowitsch       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
725*c7481402SJacob Faibussowitsch     } while (0)
726*c7481402SJacob Faibussowitsch #endif
727*c7481402SJacob Faibussowitsch 
728*c7481402SJacob Faibussowitsch /*MC
729bde483f2SJacob Faibussowitsch   PetscExpand - Expand macro argument
730bde483f2SJacob Faibussowitsch 
731bde483f2SJacob Faibussowitsch   Synopsis:
732bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
733bde483f2SJacob Faibussowitsch   <macro-expansion> PetscExpand(x)
734bde483f2SJacob Faibussowitsch 
7356aad120cSJose E. Roman   Input Parameter:
736bde483f2SJacob Faibussowitsch . x - The preprocessor token to expand
737bde483f2SJacob Faibussowitsch 
73849762cbcSSatish Balay   Level: beginner
73949762cbcSSatish Balay 
740db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscConcat()`
741817da375SSatish Balay M*/
742e58a63e1SJacob Faibussowitsch #define PetscExpand_(...) __VA_ARGS__
743e58a63e1SJacob Faibussowitsch #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
744bde483f2SJacob Faibussowitsch 
745bde483f2SJacob Faibussowitsch /*MC
746bde483f2SJacob Faibussowitsch   PetscStringize - Stringize a token
747bde483f2SJacob Faibussowitsch 
748bde483f2SJacob Faibussowitsch   Synopsis:
749bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
750bde483f2SJacob Faibussowitsch   const char* PetscStringize(x)
751bde483f2SJacob Faibussowitsch 
752bde483f2SJacob Faibussowitsch   Input Parameter:
753bde483f2SJacob Faibussowitsch . x - The token you would like to stringize
754bde483f2SJacob Faibussowitsch 
755bde483f2SJacob Faibussowitsch   Output Parameter:
756bde483f2SJacob Faibussowitsch . <return-value> - The string representation of x
757bde483f2SJacob Faibussowitsch 
758bde483f2SJacob Faibussowitsch   Notes:
759bde483f2SJacob Faibussowitsch   Not available from Fortran.
760bde483f2SJacob Faibussowitsch 
761bde483f2SJacob Faibussowitsch   PetscStringize() expands x before stringizing it, if you do not wish to do so, use
762bde483f2SJacob Faibussowitsch   PetscStringize_() instead.
763bde483f2SJacob Faibussowitsch 
764bde483f2SJacob Faibussowitsch   Example Usage:
765bde483f2SJacob Faibussowitsch .vb
766bde483f2SJacob Faibussowitsch   #define MY_OTHER_VAR hello there
767bde483f2SJacob Faibussowitsch   #define MY_VAR       MY_OTHER_VAR
768bde483f2SJacob Faibussowitsch 
769bde483f2SJacob Faibussowitsch   PetscStringize(MY_VAR)  -> "hello there"
770bde483f2SJacob Faibussowitsch   PetscStringize_(MY_VAR) -> "MY_VAR"
771bde483f2SJacob Faibussowitsch 
772bde483f2SJacob Faibussowitsch   int foo;
773bde483f2SJacob Faibussowitsch   PetscStringize(foo)  -> "foo"
774bde483f2SJacob Faibussowitsch   PetscStringize_(foo) -> "foo"
775bde483f2SJacob Faibussowitsch .ve
776bde483f2SJacob Faibussowitsch 
777bde483f2SJacob Faibussowitsch   Level: beginner
778bde483f2SJacob Faibussowitsch 
779db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
780817da375SSatish Balay M*/
7810e6b6b59SJacob Faibussowitsch #define PetscStringize_(...) #__VA_ARGS__
7820e6b6b59SJacob Faibussowitsch #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
783bde483f2SJacob Faibussowitsch 
784bde483f2SJacob Faibussowitsch /*MC
785bde483f2SJacob Faibussowitsch   PetscConcat - Concatenate two tokens
786bde483f2SJacob Faibussowitsch 
787bde483f2SJacob Faibussowitsch   Synopsis:
788bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
789bde483f2SJacob Faibussowitsch   <macro-expansion> PetscConcat(x, y)
790bde483f2SJacob Faibussowitsch 
791bde483f2SJacob Faibussowitsch   Input Parameters:
792bde483f2SJacob Faibussowitsch + x - First token
793bde483f2SJacob Faibussowitsch - y - Second token
794bde483f2SJacob Faibussowitsch 
795bde483f2SJacob Faibussowitsch   Notes:
796bde483f2SJacob Faibussowitsch   Not available from Fortran.
797bde483f2SJacob Faibussowitsch 
798bde483f2SJacob Faibussowitsch   PetscConcat() will expand both arguments before pasting them together, use PetscConcat_()
799bde483f2SJacob Faibussowitsch   if you don't want to expand them.
800bde483f2SJacob Faibussowitsch 
801bde483f2SJacob Faibussowitsch   Example usage:
802bde483f2SJacob Faibussowitsch .vb
803bde483f2SJacob Faibussowitsch   PetscConcat(hello,there) -> hellothere
804bde483f2SJacob Faibussowitsch 
805bde483f2SJacob Faibussowitsch   #define HELLO hello
806bde483f2SJacob Faibussowitsch   PetscConcat(HELLO,there)  -> hellothere
807bde483f2SJacob Faibussowitsch   PetscConcat_(HELLO,there) -> HELLOthere
808bde483f2SJacob Faibussowitsch .ve
809bde483f2SJacob Faibussowitsch 
810bde483f2SJacob Faibussowitsch   Level: beginner
811bde483f2SJacob Faibussowitsch 
812db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscExpand()`
813817da375SSatish Balay M*/
814bde483f2SJacob Faibussowitsch #define PetscConcat_(x, y) x##y
815bde483f2SJacob Faibussowitsch #define PetscConcat(x, y)  PetscConcat_(x, y)
816bde483f2SJacob Faibussowitsch 
817bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_0 1
818bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_1 0
819bde483f2SJacob Faibussowitsch 
820bde483f2SJacob Faibussowitsch /*MC
821bde483f2SJacob Faibussowitsch   PetscCompl - Expands to the integer complement of its argument
822bde483f2SJacob Faibussowitsch 
823bde483f2SJacob Faibussowitsch   Synopsis:
824bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
825bde483f2SJacob Faibussowitsch   int PetscCompl(b)
826bde483f2SJacob Faibussowitsch 
827bde483f2SJacob Faibussowitsch   Input Parameter:
828bde483f2SJacob Faibussowitsch . b - Preprocessor variable, must expand to either integer literal 0 or 1
829bde483f2SJacob Faibussowitsch 
8306aad120cSJose E. Roman   Output Parameter:
831bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
832bde483f2SJacob Faibussowitsch 
833bde483f2SJacob Faibussowitsch   Notes:
834bde483f2SJacob Faibussowitsch   Not available from Fortran.
835bde483f2SJacob Faibussowitsch 
836bde483f2SJacob Faibussowitsch   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
837bde483f2SJacob Faibussowitsch   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
838bde483f2SJacob Faibussowitsch   argument before returning the complement.
839bde483f2SJacob Faibussowitsch 
840bde483f2SJacob Faibussowitsch   This macro can be useful for negating PetscDefined() inside macros e.g.
841bde483f2SJacob Faibussowitsch 
842bde483f2SJacob Faibussowitsch $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
843bde483f2SJacob Faibussowitsch 
844bde483f2SJacob Faibussowitsch   Example usage:
845bde483f2SJacob Faibussowitsch .vb
846bde483f2SJacob Faibussowitsch   #define MY_VAR 1
847bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 0
848bde483f2SJacob Faibussowitsch 
849bde483f2SJacob Faibussowitsch   #undef  MY_VAR
850bde483f2SJacob Faibussowitsch   #define MY_VAR 0
851bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 1
852bde483f2SJacob Faibussowitsch .ve
853bde483f2SJacob Faibussowitsch 
854bde483f2SJacob Faibussowitsch   Level: beginner
855bde483f2SJacob Faibussowitsch 
856db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`
857817da375SSatish Balay M*/
858bde483f2SJacob Faibussowitsch #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
859bde483f2SJacob Faibussowitsch 
860bde483f2SJacob Faibussowitsch #if !defined(PETSC_SKIP_VARIADIC_MACROS)
861bde483f2SJacob Faibussowitsch   /*MC
862bde483f2SJacob Faibussowitsch   PetscDefined - Determine whether a boolean macro is defined
863bde483f2SJacob Faibussowitsch 
864bde483f2SJacob Faibussowitsch   Synopsis:
865bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
866bde483f2SJacob Faibussowitsch   int PetscDefined(def)
867bde483f2SJacob Faibussowitsch 
868bde483f2SJacob Faibussowitsch   Input Parameter:
869bde483f2SJacob Faibussowitsch . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
870bde483f2SJacob Faibussowitsch 
871bde483f2SJacob Faibussowitsch   Outut Parameter:
872bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
873bde483f2SJacob Faibussowitsch 
874bde483f2SJacob Faibussowitsch   Notes:
875bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
87687497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
877bde483f2SJacob Faibussowitsch 
87887497f52SBarry Smith   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
87987497f52SBarry Smith   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
880bde483f2SJacob Faibussowitsch   this macro should not be used if its argument may be defined to a non-empty value other than
881bde483f2SJacob Faibussowitsch   1.
882bde483f2SJacob Faibussowitsch 
883bde483f2SJacob Faibussowitsch   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
88487497f52SBarry Smith   add custom checks in user code, one should use `PetscDefined_()`.
885bde483f2SJacob Faibussowitsch 
886bde483f2SJacob Faibussowitsch $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_,d))
887bde483f2SJacob Faibussowitsch 
888bde483f2SJacob Faibussowitsch   Developer Notes:
889bde483f2SJacob Faibussowitsch   Getting something that works in C and CPP for an arg that may or may not be defined is
890bde483f2SJacob Faibussowitsch   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
891bde483f2SJacob Faibussowitsch   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
892bde483f2SJacob Faibussowitsch   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
893bde483f2SJacob Faibussowitsch   and when the last step cherry picks the 2nd arg, we get a zero.
894bde483f2SJacob Faibussowitsch 
895bde483f2SJacob Faibussowitsch   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
896bde483f2SJacob Faibussowitsch   nonconforming implementation of variadic macros.
897bde483f2SJacob Faibussowitsch 
898bde483f2SJacob Faibussowitsch   Example Usage:
899bde483f2SJacob Faibussowitsch   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
900bde483f2SJacob Faibussowitsch   is defined then
901bde483f2SJacob Faibussowitsch 
902bde483f2SJacob Faibussowitsch .vb
903bde483f2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
904bde483f2SJacob Faibussowitsch     foo();
905bde483f2SJacob Faibussowitsch   #else
906bde483f2SJacob Faibussowitsch     bar();
907bde483f2SJacob Faibussowitsch   #endif
908bde483f2SJacob Faibussowitsch 
909bde483f2SJacob Faibussowitsch   // or alternatively within normal code
910bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
911bde483f2SJacob Faibussowitsch     foo();
912bde483f2SJacob Faibussowitsch   } else {
913bde483f2SJacob Faibussowitsch     bar();
914bde483f2SJacob Faibussowitsch   }
915bde483f2SJacob Faibussowitsch .ve
916bde483f2SJacob Faibussowitsch 
917bde483f2SJacob Faibussowitsch   is equivalent to
918bde483f2SJacob Faibussowitsch 
919bde483f2SJacob Faibussowitsch .vb
920bde483f2SJacob Faibussowitsch   #if defined(PETSC_USE_DEBUG)
921bde483f2SJacob Faibussowitsch   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
922bde483f2SJacob Faibussowitsch        foo();
923bde483f2SJacob Faibussowitsch   #   elif PETSC_USE_DEBUG == 1
924bde483f2SJacob Faibussowitsch        foo();
925bde483f2SJacob Faibussowitsch   #   else
926bde483f2SJacob Faibussowitsch        bar();
927bde483f2SJacob Faibussowitsch   #  endif
928bde483f2SJacob Faibussowitsch   #else
929bde483f2SJacob Faibussowitsch   bar();
930bde483f2SJacob Faibussowitsch   #endif
931bde483f2SJacob Faibussowitsch .ve
932bde483f2SJacob Faibussowitsch 
933bde483f2SJacob Faibussowitsch   Level: intermediate
934bde483f2SJacob Faibussowitsch 
935db781477SPatrick Sanan .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
936db781477SPatrick Sanan           `PetscExpandToNothing()`, `PetscCompl()`
937817da375SSatish Balay M*/
938bde483f2SJacob Faibussowitsch   #define PetscDefined_arg_1                                    shift,
939bde483f2SJacob Faibussowitsch   #define PetscDefined_arg_                                     shift,
940bde483f2SJacob Faibussowitsch   #define PetscDefined__take_second_expanded(ignored, val, ...) val
941bde483f2SJacob Faibussowitsch   #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
942bde483f2SJacob Faibussowitsch   #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
943bde483f2SJacob Faibussowitsch   #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
944bde483f2SJacob Faibussowitsch   #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
945bde483f2SJacob Faibussowitsch   #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
946bde483f2SJacob Faibussowitsch 
947bde483f2SJacob Faibussowitsch   /*MC
94887497f52SBarry Smith   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
949bde483f2SJacob Faibussowitsch   the check in optimized mode
950bde483f2SJacob Faibussowitsch 
951bde483f2SJacob Faibussowitsch   Synopsis:
952bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
953bde483f2SJacob Faibussowitsch   bool PetscUnlikelyDebug(bool cond)
954bde483f2SJacob Faibussowitsch 
955bde483f2SJacob Faibussowitsch   Not Collective
956bde483f2SJacob Faibussowitsch 
957bde483f2SJacob Faibussowitsch   Input Parameters:
958bde483f2SJacob Faibussowitsch . cond - Boolean expression
959bde483f2SJacob Faibussowitsch 
960bde483f2SJacob Faibussowitsch   Notes:
961bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
96287497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
963bde483f2SJacob Faibussowitsch 
964bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
965bde483f2SJacob Faibussowitsch   likely to be false. When PETSc is compiled in optimized mode this will always return
966bde483f2SJacob Faibussowitsch   false. Additionally, cond is guaranteed to not be evaluated when PETSc is compiled in
967bde483f2SJacob Faibussowitsch   optimized mode.
968bde483f2SJacob Faibussowitsch 
969bde483f2SJacob Faibussowitsch   Example usage:
970bde483f2SJacob Faibussowitsch   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
971bde483f2SJacob Faibussowitsch   is true. So
972bde483f2SJacob Faibussowitsch 
973bde483f2SJacob Faibussowitsch .vb
974bde483f2SJacob Faibussowitsch   if (PetscUnlikelyDebug(cond)) {
975bde483f2SJacob Faibussowitsch     foo();
976bde483f2SJacob Faibussowitsch   } else {
977bde483f2SJacob Faibussowitsch     bar();
978bde483f2SJacob Faibussowitsch   }
979bde483f2SJacob Faibussowitsch .ve
980bde483f2SJacob Faibussowitsch 
981bde483f2SJacob Faibussowitsch   is equivalent to
982bde483f2SJacob Faibussowitsch 
983bde483f2SJacob Faibussowitsch .vb
984bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
985bde483f2SJacob Faibussowitsch     if (PetscUnlikely(cond)) {
986bde483f2SJacob Faibussowitsch       foo();
987bde483f2SJacob Faibussowitsch     } else {
988bde483f2SJacob Faibussowitsch       bar();
989bde483f2SJacob Faibussowitsch     }
990bde483f2SJacob Faibussowitsch   } else {
991bde483f2SJacob Faibussowitsch     bar();
992bde483f2SJacob Faibussowitsch   }
993bde483f2SJacob Faibussowitsch .ve
994bde483f2SJacob Faibussowitsch 
995bde483f2SJacob Faibussowitsch   Level: advanced
996bde483f2SJacob Faibussowitsch 
997db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
998bde483f2SJacob Faibussowitsch M*/
999bde483f2SJacob Faibussowitsch   #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1000bde483f2SJacob Faibussowitsch 
1001f7e3c444SJacob Faibussowitsch   #if defined(PETSC_CLANG_STATIC_ANALYZER)
1002f7e3c444SJacob Faibussowitsch     // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1003f7e3c444SJacob Faibussowitsch     // not what ISO C allows
10049371c9d4SSatish Balay     #define PetscMacroReturns_(retexpr, ...) \
10059371c9d4SSatish Balay       __extension__({ \
10069371c9d4SSatish Balay         __VA_ARGS__; \
10079371c9d4SSatish Balay         retexpr; \
10089371c9d4SSatish Balay       })
1009f7e3c444SJacob Faibussowitsch   #else
10109371c9d4SSatish Balay     #define PetscMacroReturns_(retexpr, ...) \
10119371c9d4SSatish Balay       retexpr; \
1012d71ae5a4SJacob Faibussowitsch       do { \
1013d71ae5a4SJacob Faibussowitsch         __VA_ARGS__; \
1014d71ae5a4SJacob Faibussowitsch       } while (0)
1015f7e3c444SJacob Faibussowitsch   #endif
1016f7e3c444SJacob Faibussowitsch 
1017bde483f2SJacob Faibussowitsch   /*MC
1018bde483f2SJacob Faibussowitsch   PetscExpandToNothing - Expands to absolutely nothing at all
1019bde483f2SJacob Faibussowitsch 
1020bde483f2SJacob Faibussowitsch   Synopsis:
1021bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
1022bde483f2SJacob Faibussowitsch   void PetscExpandToNothing(...)
1023bde483f2SJacob Faibussowitsch 
1024bde483f2SJacob Faibussowitsch   Input Parameter:
1025bde483f2SJacob Faibussowitsch . __VA_ARGS__ - Anything at all
1026bde483f2SJacob Faibussowitsch 
1027bde483f2SJacob Faibussowitsch   Notes:
1028bde483f2SJacob Faibussowitsch   Not available from Fortran, requires variadic macro support, definition is disabled by
102987497f52SBarry Smith   defining `PETSC_SKIP_VARIADIC_MACROS`.
1030bde483f2SJacob Faibussowitsch 
1031bde483f2SJacob Faibussowitsch   Must have at least 1 parameter.
1032bde483f2SJacob Faibussowitsch 
1033bde483f2SJacob Faibussowitsch   Example usage:
1034bde483f2SJacob Faibussowitsch .vb
1035bde483f2SJacob Faibussowitsch   PetscExpandToNothing(a,b,c) -> *nothing*
1036bde483f2SJacob Faibussowitsch .ve
1037bde483f2SJacob Faibussowitsch 
1038bde483f2SJacob Faibussowitsch   Level: beginner
1039bde483f2SJacob Faibussowitsch 
1040db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1041817da375SSatish Balay M*/
1042bde483f2SJacob Faibussowitsch   #define PetscExpandToNothing(...)
1043f7e3c444SJacob Faibussowitsch 
1044f7e3c444SJacob Faibussowitsch   /*MC
1045f7e3c444SJacob Faibussowitsch   PetscMacroReturns - Define a macro body that returns a value
1046f7e3c444SJacob Faibussowitsch 
1047f7e3c444SJacob Faibussowitsch   Synopsis:
1048f7e3c444SJacob Faibussowitsch   #include <petscmacros.h>
1049f7e3c444SJacob Faibussowitsch   return_type PetscMacroReturns(return_type retexpr, ...)
1050f7e3c444SJacob Faibussowitsch 
1051f7e3c444SJacob Faibussowitsch   Input Parameters:
1052f7e3c444SJacob Faibussowitsch + retexpr     - The value or expression that the macro should return
1053f7e3c444SJacob Faibussowitsch - __VA_ARGS__ - The body of the macro
1054f7e3c444SJacob Faibussowitsch 
1055f7e3c444SJacob Faibussowitsch   Notes:
1056f7e3c444SJacob Faibussowitsch   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1057f7e3c444SJacob Faibussowitsch   body of the macro and should not depend on values produced as a result of the expression. The
1058f7e3c444SJacob Faibussowitsch   user should not assume that the result of this macro is equivalent to a single logical source
1059f7e3c444SJacob Faibussowitsch   line. It is not portable to use macros defined using this one in conditional or loop bodies
1060f7e3c444SJacob Faibussowitsch   without enclosing them in curly braces\:
1061f7e3c444SJacob Faibussowitsch 
1062f7e3c444SJacob Faibussowitsch .vb
1063f7e3c444SJacob Faibussowitsch   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1064f7e3c444SJacob Faibussowitsch 
1065f7e3c444SJacob Faibussowitsch   int err,x = 10;
1066f7e3c444SJacob Faibussowitsch 
1067f7e3c444SJacob Faibussowitsch   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
1068f7e3c444SJacob Faibussowitsch   if (...) { err = FOO(x); }  // OK
1069f7e3c444SJacob Faibussowitsch 
1070f7e3c444SJacob Faibussowitsch   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1071f7e3c444SJacob Faibussowitsch   for (...) { err = FOO(x); } // OK
1072f7e3c444SJacob Faibussowitsch .ve
1073f7e3c444SJacob Faibussowitsch 
1074f7e3c444SJacob Faibussowitsch   It is also not portable to use this macro directly inside function call, conditional, loop,
1075f7e3c444SJacob Faibussowitsch   or switch statements\:
1076f7e3c444SJacob Faibussowitsch 
1077f7e3c444SJacob Faibussowitsch .vb
1078f7e3c444SJacob Faibussowitsch   extern void bar(int);
1079f7e3c444SJacob Faibussowitsch 
1080f7e3c444SJacob Faibussowitsch   int ret = FOO(x);
1081f7e3c444SJacob Faibussowitsch 
1082f7e3c444SJacob Faibussowitsch   bar(FOO(x)); // ERROR, may not compile
1083f7e3c444SJacob Faibussowitsch   bar(ret);    // OK
1084f7e3c444SJacob Faibussowitsch 
1085f7e3c444SJacob Faibussowitsch   if (FOO(x))  // ERROR, may not compile
1086f7e3c444SJacob Faibussowitsch   if (ret)     // OK
1087f7e3c444SJacob Faibussowitsch .ve
1088f7e3c444SJacob Faibussowitsch 
1089f7e3c444SJacob Faibussowitsch   Example usage:
1090f7e3c444SJacob Faibussowitsch .vb
1091f7e3c444SJacob Faibussowitsch   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1092f7e3c444SJacob Faibussowitsch 
1093f7e3c444SJacob Faibussowitsch   int x = 10;
1094f7e3c444SJacob Faibussowitsch   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1095f7e3c444SJacob Faibussowitsch 
1096f7e3c444SJacob Faibussowitsch   // multiline macros allowed, but must declare with line continuation as usual
1097f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1098f7e3c444SJacob Faibussowitsch     if (arg1 > 10) {                                            \
1099f7e3c444SJacob Faibussowitsch       puts("big int!");                                         \
1100f7e3c444SJacob Faibussowitsch     } else {                                                    \
1101f7e3c444SJacob Faibussowitsch       return 7355608;                                           \
1102f7e3c444SJacob Faibussowitsch     }                                                           \
1103f7e3c444SJacob Faibussowitsch   )
1104f7e3c444SJacob Faibussowitsch 
1105f7e3c444SJacob Faibussowitsch   // if retexpr contains commas, must enclose it with braces
1106f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1107f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1108f7e3c444SJacob Faibussowitsch 
1109f7e3c444SJacob Faibussowitsch   int x = 10;
1110f7e3c444SJacob Faibussowitsch   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1111f7e3c444SJacob Faibussowitsch   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1112f7e3c444SJacob Faibussowitsch .ve
1113f7e3c444SJacob Faibussowitsch 
1114f7e3c444SJacob Faibussowitsch   Level: intermediate
1115f7e3c444SJacob Faibussowitsch 
1116db781477SPatrick Sanan .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1117f7e3c444SJacob Faibussowitsch M*/
1118f7e3c444SJacob Faibussowitsch   #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1119f7e3c444SJacob Faibussowitsch 
1120f7e3c444SJacob Faibussowitsch   #define PetscMacroReturnStandard(...) PetscMacroReturns(0, __VA_ARGS__)
1121f7e3c444SJacob Faibussowitsch 
1122bde483f2SJacob Faibussowitsch #endif /* !PETSC_SKIP_VARIADIC_MACROS */
1123bde483f2SJacob Faibussowitsch 
1124dd39110bSPierre Jolivet /*MC
1125dd39110bSPierre Jolivet   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1126dd39110bSPierre Jolivet 
1127dd39110bSPierre Jolivet   Level: intermediate
1128dd39110bSPierre Jolivet M*/
1129dd39110bSPierre Jolivet #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
1130dd39110bSPierre Jolivet 
1131296d8154SBarry Smith /*
1132296d8154SBarry Smith   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1133296d8154SBarry Smith 
1134296d8154SBarry Smith   Example usage:
1135296d8154SBarry Smith 
1136296d8154SBarry Smith   #define mymacro(obj,...) {
1137296d8154SBarry Smith     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1138296d8154SBarry Smith     f(22 PETSC_REST_ARG(__VA_ARGS__));
1139296d8154SBarry Smith   }
1140296d8154SBarry Smith 
1141296d8154SBarry 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
1142296d8154SBarry Smith 
1143296d8154SBarry Smith   Reference:
1144296d8154SBarry Smith   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1145296d8154SBarry Smith */
1146296d8154SBarry Smith #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1147296d8154SBarry Smith #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1148296d8154SBarry Smith #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1149296d8154SBarry 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)
1150296d8154SBarry Smith #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
1151296d8154SBarry Smith #define PETSC_REST_HELPER_ONE(first)
1152296d8154SBarry Smith #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1153296d8154SBarry Smith #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1154296d8154SBarry Smith #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1155296d8154SBarry Smith 
1156bde483f2SJacob Faibussowitsch #endif /* PETSC_PREPROCESSOR_MACROS_H */
1157