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