xref: /petsc/include/petscmacros.h (revision 8d031ccafb4c5bb757e07d394bfebfdd11b369fc)
1a4963045SJacob Faibussowitsch #pragma once
2bde483f2SJacob Faibussowitsch 
3bde483f2SJacob Faibussowitsch #include <petscconf.h>
4bde483f2SJacob Faibussowitsch #include <petscconf_poison.h> /* for PetscDefined() error checking */
5bde483f2SJacob Faibussowitsch 
6ac09b921SBarry Smith /* SUBMANSEC = Sys */
7ac09b921SBarry Smith 
80e6b6b59SJacob Faibussowitsch #if defined(__cplusplus)
90e6b6b59SJacob Faibussowitsch   #if __cplusplus <= 201103L
100e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 11
110e6b6b59SJacob Faibussowitsch   #elif __cplusplus <= 201402L
120e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 14
130e6b6b59SJacob Faibussowitsch   #elif __cplusplus <= 201703L
140e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 17
150e6b6b59SJacob Faibussowitsch   #elif __cplusplus <= 202002L
160e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 20
170e6b6b59SJacob Faibussowitsch   #else
180e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
190e6b6b59SJacob Faibussowitsch   #endif
200e6b6b59SJacob Faibussowitsch #endif // __cplusplus
210e6b6b59SJacob Faibussowitsch 
220e6b6b59SJacob Faibussowitsch #ifndef PETSC_CPP_VERSION
230e6b6b59SJacob Faibussowitsch   #define PETSC_CPP_VERSION 0
240e6b6b59SJacob Faibussowitsch #endif
250e6b6b59SJacob Faibussowitsch 
266797ed33SJacob Faibussowitsch #if defined(__STDC_VERSION__)
276797ed33SJacob Faibussowitsch   #if __STDC_VERSION__ <= 199901L
286797ed33SJacob Faibussowitsch     // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
296797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 9
306797ed33SJacob Faibussowitsch   #elif __STDC_VERSION__ <= 201112L
316797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 11
326797ed33SJacob Faibussowitsch   #elif __STDC_VERSION__ <= 201710L
336797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 17
346797ed33SJacob Faibussowitsch   #else
356797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
366797ed33SJacob Faibussowitsch   #endif
376797ed33SJacob Faibussowitsch #endif // __STDC_VERSION__
386797ed33SJacob Faibussowitsch 
396797ed33SJacob Faibussowitsch #ifndef PETSC_C_VERSION
406797ed33SJacob Faibussowitsch   #define PETSC_C_VERSION 0
416797ed33SJacob Faibussowitsch #endif
426797ed33SJacob Faibussowitsch 
43bde483f2SJacob Faibussowitsch /* ========================================================================== */
44bde483f2SJacob Faibussowitsch /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
45bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
46bde483f2SJacob Faibussowitsch   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
47bde483f2SJacob Faibussowitsch #else
48bde483f2SJacob Faibussowitsch   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
49bde483f2SJacob Faibussowitsch #endif
50bde483f2SJacob Faibussowitsch 
51bde483f2SJacob Faibussowitsch /* ========================================================================== */
52bde483f2SJacob Faibussowitsch /* Since PETSc manages its own extern "C" handling users should never include PETSc include
53bde483f2SJacob Faibussowitsch  * files within extern "C". This will generate a compiler error if a user does put the include
54bde483f2SJacob Faibussowitsch  * file within an extern "C".
55bde483f2SJacob Faibussowitsch  */
56bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
579371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(int);
589371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(double);
59bde483f2SJacob Faibussowitsch #endif
60bde483f2SJacob Faibussowitsch 
61bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
62bde483f2SJacob Faibussowitsch   #define PETSC_RESTRICT PETSC_CXX_RESTRICT
63bde483f2SJacob Faibussowitsch #else
646ee8c794SJacob Faibussowitsch   #define PETSC_RESTRICT restrict
65bde483f2SJacob Faibussowitsch #endif
66bde483f2SJacob Faibussowitsch 
67edd03b47SJacob Faibussowitsch #define PETSC_INLINE        PETSC_DEPRECATED_MACRO(3, 17, 0, "inline", ) inline
68edd03b47SJacob Faibussowitsch #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "static inline", ) static inline
69bde483f2SJacob Faibussowitsch 
70bde483f2SJacob Faibussowitsch #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
71bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT __declspec(dllexport)
72bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT __declspec(dllimport)
73bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL
74bde483f2SJacob Faibussowitsch #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
75bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
76bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
77bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
78bde483f2SJacob Faibussowitsch #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
79bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
80bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
81bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
82bde483f2SJacob Faibussowitsch #else
83bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT
84bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT
85bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL
86bde483f2SJacob Faibussowitsch #endif
87bde483f2SJacob Faibussowitsch 
88bde483f2SJacob Faibussowitsch #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
89bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT
90bde483f2SJacob Faibussowitsch #else /* Win32 users need this to import symbols from petsc.dll */
91bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
92bde483f2SJacob Faibussowitsch #endif
93bde483f2SJacob Faibussowitsch 
94bde483f2SJacob Faibussowitsch /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
95bde483f2SJacob Faibussowitsch  * compiled with C++ so they may be used from C and are always visible in the shared libraries
96bde483f2SJacob Faibussowitsch  */
97bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
98bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
99bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN_TYPEDEF extern "C"
100bde483f2SJacob Faibussowitsch   #define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
101bde483f2SJacob Faibussowitsch #else
102bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
103bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN_TYPEDEF
104bde483f2SJacob Faibussowitsch   #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
105bde483f2SJacob Faibussowitsch #endif
106bde483f2SJacob Faibussowitsch 
107bde483f2SJacob Faibussowitsch #if defined(PETSC_USE_SINGLE_LIBRARY)
10847f8145dSJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_INTERNAL
109bde483f2SJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_INTERN
110bde483f2SJacob Faibussowitsch #else
11147f8145dSJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_PUBLIC
112bde483f2SJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_EXTERN
113bde483f2SJacob Faibussowitsch #endif
114bde483f2SJacob Faibussowitsch 
1151cf396e4SJacob Faibussowitsch #if !defined(__has_feature)
1161cf396e4SJacob Faibussowitsch   #define __has_feature(x) 0
1171cf396e4SJacob Faibussowitsch #endif
1181cf396e4SJacob Faibussowitsch 
119bde483f2SJacob Faibussowitsch /*MC
120bde483f2SJacob Faibussowitsch   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
121bde483f2SJacob Faibussowitsch 
122bde483f2SJacob Faibussowitsch   Synopsis:
123bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
124c7481402SJacob Faibussowitsch   int PetscHasAttribute(name)
125bde483f2SJacob Faibussowitsch 
126bde483f2SJacob Faibussowitsch   Input Parameter:
127bde483f2SJacob Faibussowitsch . name - The name of the attribute to test
128bde483f2SJacob Faibussowitsch 
12995bd0b28SBarry Smith   Level: intermediate
13095bd0b28SBarry Smith 
131bde483f2SJacob Faibussowitsch   Notes:
132bde483f2SJacob Faibussowitsch   name should be identical to what you might pass to the __attribute__ declaration itself --
133bde483f2SJacob Faibussowitsch   plain, unbroken text.
134bde483f2SJacob Faibussowitsch 
135c7481402SJacob Faibussowitsch   As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
136c7481402SJacob Faibussowitsch   exact type and value returned is implementation defined. In practice however, it usually
137c7481402SJacob Faibussowitsch   returns `1` if the attribute is supported and `0` if the attribute is not supported.
138bde483f2SJacob Faibussowitsch 
139bde483f2SJacob Faibussowitsch   Example Usage:
140bde483f2SJacob Faibussowitsch   Typical usage is using the preprocessor
141bde483f2SJacob Faibussowitsch 
142bde483f2SJacob Faibussowitsch .vb
143bde483f2SJacob Faibussowitsch   #if PetscHasAttribute(always_inline)
144bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
145bde483f2SJacob Faibussowitsch   #else
146bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE
147bde483f2SJacob Faibussowitsch   #endif
148bde483f2SJacob Faibussowitsch 
149bde483f2SJacob Faibussowitsch   void foo(void) MY_ALWAYS_INLINE;
150bde483f2SJacob Faibussowitsch .ve
151bde483f2SJacob Faibussowitsch 
152bde483f2SJacob Faibussowitsch   but it can also be used in regular code
153bde483f2SJacob Faibussowitsch 
154bde483f2SJacob Faibussowitsch .vb
155bde483f2SJacob Faibussowitsch   if (PetscHasAttribute(some_attribute)) {
156bde483f2SJacob Faibussowitsch     foo();
157bde483f2SJacob Faibussowitsch   } else {
158bde483f2SJacob Faibussowitsch     bar();
159bde483f2SJacob Faibussowitsch   }
160bde483f2SJacob Faibussowitsch .ve
161bde483f2SJacob Faibussowitsch 
162c7481402SJacob Faibussowitsch .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
163f7b5d04fSPierre Jolivet `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
164bde483f2SJacob Faibussowitsch M*/
165bde483f2SJacob Faibussowitsch #if !defined(__has_attribute)
166bde483f2SJacob Faibussowitsch   #define __has_attribute(x) 0
167bde483f2SJacob Faibussowitsch #endif
168bde483f2SJacob Faibussowitsch #define PetscHasAttribute(name) __has_attribute(name)
169bde483f2SJacob Faibussowitsch 
170c7481402SJacob Faibussowitsch /*MC
171c7481402SJacob Faibussowitsch   PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
172c7481402SJacob Faibussowitsch 
173c7481402SJacob Faibussowitsch   Synopsis:
174c7481402SJacob Faibussowitsch   #include <petscmacros.h>
175c7481402SJacob Faibussowitsch   int PetscHasBuiltin(name)
176c7481402SJacob Faibussowitsch 
177c7481402SJacob Faibussowitsch   Input Parameter:
178c7481402SJacob Faibussowitsch . name - the name of the builtin routine
179c7481402SJacob Faibussowitsch 
18095bd0b28SBarry Smith   Level: intermediate
18195bd0b28SBarry Smith 
182c7481402SJacob Faibussowitsch   Notes:
183d5b43468SJose E. Roman   Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
184c7481402SJacob Faibussowitsch   (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
185c7481402SJacob Faibussowitsch   detector is itself is a compiler extension with implementation-defined return type and
186c7481402SJacob Faibussowitsch   semantics. Some compilers implement it as a macro, others as a compiler function. In practice
187c7481402SJacob Faibussowitsch   however, all supporting compilers return an integer boolean as described.
188c7481402SJacob Faibussowitsch 
189c7481402SJacob Faibussowitsch   Example Usage:
190c7481402SJacob Faibussowitsch   Typical usage is in preprocessor directives
191c7481402SJacob Faibussowitsch 
192c7481402SJacob Faibussowitsch .vb
193c7481402SJacob Faibussowitsch   #if PetscHasBuiltin(__builtin_trap)
194c7481402SJacob Faibussowitsch   __builtin_trap();
195c7481402SJacob Faibussowitsch   #else
196c7481402SJacob Faibussowitsch   abort();
197c7481402SJacob Faibussowitsch   #endif
198c7481402SJacob Faibussowitsch .ve
199c7481402SJacob Faibussowitsch 
200c7481402SJacob Faibussowitsch   But it may also be used in regular code
201c7481402SJacob Faibussowitsch 
202c7481402SJacob Faibussowitsch .vb
203c7481402SJacob Faibussowitsch   if (PetscHasBuiltin(__builtin_alloca)) {
204c7481402SJacob Faibussowitsch     foo();
205c7481402SJacob Faibussowitsch   } else {
206c7481402SJacob Faibussowitsch     bar();
207c7481402SJacob Faibussowitsch   }
208c7481402SJacob Faibussowitsch .ve
209c7481402SJacob Faibussowitsch 
210c7481402SJacob Faibussowitsch .seealso: `PetscHasAttribute()`, `PetscAssume()`
211c7481402SJacob Faibussowitsch M*/
212c7481402SJacob Faibussowitsch #if !defined(__has_builtin)
213c7481402SJacob Faibussowitsch   #define __has_builtin(x) 0
214c7481402SJacob Faibussowitsch #endif
215c7481402SJacob Faibussowitsch // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
216c7481402SJacob Faibussowitsch // __builtin_types_compatible_p which take types or other non-functiony things as
217c7481402SJacob Faibussowitsch // arguments. The correct way to detect these then is to use __is_identifier (also a clang
218c7481402SJacob Faibussowitsch // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
219c7481402SJacob Faibussowitsch #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
220c7481402SJacob Faibussowitsch   #define PetscHasBuiltin(name) __is_identifier(name)
221c7481402SJacob Faibussowitsch #else
222c7481402SJacob Faibussowitsch   #define PetscHasBuiltin(name) __has_builtin(name)
223c7481402SJacob Faibussowitsch #endif
224c7481402SJacob Faibussowitsch 
22593d501b3SJacob Faibussowitsch #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
22693d501b3SJacob Faibussowitsch   /*
22793d501b3SJacob Faibussowitsch    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
22893d501b3SJacob Faibussowitsch    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
22993d501b3SJacob Faibussowitsch    does not match the actual type of the argument being passed in
23093d501b3SJacob Faibussowitsch */
23193d501b3SJacob Faibussowitsch   #if PetscHasAttribute(pointer_with_type_tag)
23293d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
23393d501b3SJacob Faibussowitsch   #endif
23493d501b3SJacob Faibussowitsch 
23593d501b3SJacob Faibussowitsch   #if PetscHasAttribute(type_tag_for_datatype)
23693d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
23793d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
23893d501b3SJacob Faibussowitsch   #endif
23993d501b3SJacob Faibussowitsch #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
24093d501b3SJacob Faibussowitsch 
24193d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
24293d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
24393d501b3SJacob Faibussowitsch #endif
24493d501b3SJacob Faibussowitsch 
24593d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
24693d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
24793d501b3SJacob Faibussowitsch #endif
24893d501b3SJacob Faibussowitsch 
24993d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
25093d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
25193d501b3SJacob Faibussowitsch #endif
25293d501b3SJacob Faibussowitsch 
253bde483f2SJacob Faibussowitsch /*MC
25463a3b9bcSJacob Faibussowitsch   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
25563a3b9bcSJacob Faibussowitsch   as format specifiers and checked for validity
25663a3b9bcSJacob Faibussowitsch 
25763a3b9bcSJacob Faibussowitsch   Synopsis:
25863a3b9bcSJacob Faibussowitsch   #include <petscmacros.h>
25963a3b9bcSJacob Faibussowitsch   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
26063a3b9bcSJacob Faibussowitsch 
26163a3b9bcSJacob Faibussowitsch   Input Parameters:
26263a3b9bcSJacob Faibussowitsch + strIdx   - The (1-indexed) location of the format string in the argument list
26363a3b9bcSJacob Faibussowitsch - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
26463a3b9bcSJacob Faibussowitsch 
26516a05f60SBarry Smith   Level: developer
26616a05f60SBarry Smith 
26763a3b9bcSJacob Faibussowitsch   Notes:
26863a3b9bcSJacob Faibussowitsch   This function attribute causes the compiler to issue warnings when the format specifier does
26963a3b9bcSJacob Faibussowitsch   not match the type of the variable that will be formatted, or when there exists a mismatch
27063a3b9bcSJacob Faibussowitsch   between the number of format specifiers and variables to be formatted. It is safe to use this
27163a3b9bcSJacob Faibussowitsch   macro if your compiler does not support format specifier checking (though this is
27263a3b9bcSJacob Faibussowitsch   exceeedingly rare).
27363a3b9bcSJacob Faibussowitsch 
27416a05f60SBarry Smith   Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
27563a3b9bcSJacob Faibussowitsch   same value.
27663a3b9bcSJacob Faibussowitsch 
27763a3b9bcSJacob Faibussowitsch   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
27863a3b9bcSJacob Faibussowitsch   the argument list, that is, there is no way to indicate gaps which should not be checked.
27963a3b9bcSJacob Faibussowitsch 
28087497f52SBarry Smith   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
28163a3b9bcSJacob Faibussowitsch   header files. In this case the macro will expand empty.
28263a3b9bcSJacob Faibussowitsch 
28363a3b9bcSJacob Faibussowitsch   Example Usage:
28463a3b9bcSJacob Faibussowitsch .vb
28563a3b9bcSJacob Faibussowitsch   // format string is 2nd argument, variable argument list containing args is 3rd argument
28663a3b9bcSJacob Faibussowitsch   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
28763a3b9bcSJacob Faibussowitsch 
28863a3b9bcSJacob Faibussowitsch   int    x = 1;
28963a3b9bcSJacob Faibussowitsch   double y = 50.0;
29063a3b9bcSJacob Faibussowitsch 
29163a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
29263a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
29363a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d %g",x,y); // OK
29463a3b9bcSJacob Faibussowitsch .ve
29563a3b9bcSJacob Faibussowitsch 
296db781477SPatrick Sanan .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
29763a3b9bcSJacob Faibussowitsch M*/
29863a3b9bcSJacob Faibussowitsch #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
29963a3b9bcSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
30063a3b9bcSJacob Faibussowitsch #else
30163a3b9bcSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
30263a3b9bcSJacob Faibussowitsch #endif
30363a3b9bcSJacob Faibussowitsch 
30463a3b9bcSJacob Faibussowitsch /*MC
305d8e4614bSJacob Faibussowitsch   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
306d8e4614bSJacob Faibussowitsch   executed
307d8e4614bSJacob Faibussowitsch 
30816a05f60SBarry Smith   Level: intermediate
30916a05f60SBarry Smith 
310d8e4614bSJacob Faibussowitsch   Notes:
311d8e4614bSJacob Faibussowitsch   The marked function is often optimized for size rather than speed and may be grouped alongside
312d8e4614bSJacob Faibussowitsch   other equally frigid routines improving code locality of lukewarm or hotter parts of program.
313d8e4614bSJacob Faibussowitsch 
314d8e4614bSJacob Faibussowitsch   The paths leading to cold functions are usually automatically marked as unlikely by the
315d8e4614bSJacob Faibussowitsch   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
316d8e4614bSJacob Faibussowitsch   as error handlers -- as cold to improve optimization of the surrounding temperate functions.
317d8e4614bSJacob Faibussowitsch 
318d8e4614bSJacob Faibussowitsch   Example Usage:
319d8e4614bSJacob Faibussowitsch .vb
320d8e4614bSJacob Faibussowitsch   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
321d8e4614bSJacob Faibussowitsch 
322d8e4614bSJacob Faibussowitsch   if (temperature < 0) {
323d8e4614bSJacob Faibussowitsch     return my_error_handler(...); // chilly!
324d8e4614bSJacob Faibussowitsch   }
325d8e4614bSJacob Faibussowitsch .ve
326d8e4614bSJacob Faibussowitsch 
327db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
328db781477SPatrick Sanan           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
329d8e4614bSJacob Faibussowitsch M*/
330d8e4614bSJacob Faibussowitsch #if PetscHasAttribute(__cold__)
331d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
332d8e4614bSJacob Faibussowitsch #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
333d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
334d8e4614bSJacob Faibussowitsch #else
335d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD
336d8e4614bSJacob Faibussowitsch #endif
337d8e4614bSJacob Faibussowitsch 
338d8e4614bSJacob Faibussowitsch /*MC
339f7b5d04fSPierre Jolivet   PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
340f7b5d04fSPierre Jolivet   subjected to type-based alias analysis, but is instead assumed to be able to
341f7b5d04fSPierre Jolivet   alias any other type of objects
342f7b5d04fSPierre Jolivet 
343752b9880SPierre Jolivet   Example Usage:
344752b9880SPierre Jolivet .vb
345752b9880SPierre Jolivet   typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;
346752b9880SPierre Jolivet 
347752b9880SPierre Jolivet   PetscReal        *pointer;
348752b9880SPierre Jolivet   PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
349752b9880SPierre Jolivet .ve
350752b9880SPierre Jolivet 
351f7b5d04fSPierre Jolivet   Level: advanced
352f7b5d04fSPierre Jolivet 
353f7b5d04fSPierre Jolivet .seealso: `PetscHasAttribute()`
354f7b5d04fSPierre Jolivet M*/
355f7b5d04fSPierre Jolivet #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
356f7b5d04fSPierre Jolivet   #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
357f7b5d04fSPierre Jolivet #else
358f7b5d04fSPierre Jolivet   #define PETSC_ATTRIBUTE_MAY_ALIAS
359f7b5d04fSPierre Jolivet #endif
360f7b5d04fSPierre Jolivet 
361f7b5d04fSPierre Jolivet /*MC
362bde483f2SJacob Faibussowitsch   PETSC_NULLPTR - Standard way of indicating a null value or pointer
363bde483f2SJacob Faibussowitsch 
36420f4b53cSBarry Smith   No Fortran Support
36520f4b53cSBarry Smith 
36620f4b53cSBarry Smith   Level: beginner
36720f4b53cSBarry Smith 
368bde483f2SJacob Faibussowitsch   Notes:
36916a05f60SBarry Smith   Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
37016a05f60SBarry Smith   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
37120f4b53cSBarry Smith   equivalent to setting the same pointer to `NULL` in C. That is to say that the following
372bde483f2SJacob Faibussowitsch   expressions are equivalent\:
373bde483f2SJacob Faibussowitsch 
374bde483f2SJacob Faibussowitsch .vb
375bde483f2SJacob Faibussowitsch   ptr == PETSC_NULLPTR
376bde483f2SJacob Faibussowitsch   ptr == NULL
377bde483f2SJacob Faibussowitsch   ptr == 0
378bde483f2SJacob Faibussowitsch   !ptr
379bde483f2SJacob Faibussowitsch 
380bde483f2SJacob Faibussowitsch   ptr = PETSC_NULLPTR
381bde483f2SJacob Faibussowitsch   ptr = NULL
382bde483f2SJacob Faibussowitsch   ptr = 0
383bde483f2SJacob Faibussowitsch .ve
384bde483f2SJacob Faibussowitsch 
385bde483f2SJacob Faibussowitsch   and for completeness' sake\:
386bde483f2SJacob Faibussowitsch 
387bde483f2SJacob Faibussowitsch .vb
388bde483f2SJacob Faibussowitsch   PETSC_NULLPTR == NULL
389bde483f2SJacob Faibussowitsch .ve
390bde483f2SJacob Faibussowitsch 
391bde483f2SJacob Faibussowitsch   Example Usage:
392bde483f2SJacob Faibussowitsch .vb
393baca6076SPierre Jolivet   // may be used in place of '\0' or other such terminators in the definition of char arrays
394bde483f2SJacob Faibussowitsch   const char *const MyEnumTypes[] = {
395bde483f2SJacob Faibussowitsch     "foo",
396bde483f2SJacob Faibussowitsch     "bar",
397bde483f2SJacob Faibussowitsch     PETSC_NULLPTR
398bde483f2SJacob Faibussowitsch   };
399bde483f2SJacob Faibussowitsch 
400bde483f2SJacob Faibussowitsch   // may be used to nullify objects
401bde483f2SJacob Faibussowitsch   PetscObject obj = PETSC_NULLPTR;
402bde483f2SJacob Faibussowitsch 
403bde483f2SJacob Faibussowitsch   // may be used in any function expecting NULL
404bde483f2SJacob Faibussowitsch   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
405bde483f2SJacob Faibussowitsch .ve
406bde483f2SJacob Faibussowitsch 
407bde483f2SJacob Faibussowitsch   Developer Notes:
40816a05f60SBarry Smith   `PETSC_NULLPTR` must be used in place of `NULL` in all C++ source files. Using `NULL` in source
409bde483f2SJacob Faibussowitsch   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
410bde483f2SJacob Faibussowitsch   resolution and/or compiler warnings.
411bde483f2SJacob Faibussowitsch 
412db781477SPatrick Sanan .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
413817da375SSatish Balay M*/
414bde483f2SJacob Faibussowitsch 
415bde483f2SJacob Faibussowitsch /*MC
416bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 - C++14 constexpr
417bde483f2SJacob Faibussowitsch 
41820f4b53cSBarry Smith   No Fortran Support
41920f4b53cSBarry Smith 
42020f4b53cSBarry Smith   Level: beginner
42120f4b53cSBarry Smith 
422bde483f2SJacob Faibussowitsch   Notes:
42316a05f60SBarry Smith   Equivalent to `constexpr` when using a C++ compiler that supports C++14. Expands to nothing
424d5b43468SJose E. Roman   if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
425bde483f2SJacob Faibussowitsch   that this cannot be used in cases where an empty expansion would result in invalid code. It
426bde483f2SJacob Faibussowitsch   is safe to use this in C source files.
427bde483f2SJacob Faibussowitsch 
428bde483f2SJacob Faibussowitsch   Example Usage:
429bde483f2SJacob Faibussowitsch .vb
430bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 int factorial(int n)
431bde483f2SJacob Faibussowitsch   {
432bde483f2SJacob Faibussowitsch     int r = 1;
433bde483f2SJacob Faibussowitsch 
434bde483f2SJacob Faibussowitsch     do {
435bde483f2SJacob Faibussowitsch       r *= n;
436bde483f2SJacob Faibussowitsch     } while (--n);
437bde483f2SJacob Faibussowitsch     return r;
438bde483f2SJacob Faibussowitsch   }
439bde483f2SJacob Faibussowitsch .ve
440bde483f2SJacob Faibussowitsch 
441db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
442817da375SSatish Balay M*/
443bde483f2SJacob Faibussowitsch 
444bde483f2SJacob Faibussowitsch /*MC
445bde483f2SJacob Faibussowitsch   PETSC_NODISCARD - Mark the return value of a function as non-discardable
446bde483f2SJacob Faibussowitsch 
447089fb57cSJacob Faibussowitsch   Not available in Fortran
448089fb57cSJacob Faibussowitsch 
449089fb57cSJacob Faibussowitsch   Level: beginner
450089fb57cSJacob Faibussowitsch 
451bde483f2SJacob Faibussowitsch   Notes:
452bde483f2SJacob Faibussowitsch   Hints to the compiler that the return value of a function must be captured. A diagnostic may
453089fb57cSJacob Faibussowitsch   (but is not required to) be emitted if the value is discarded. It is safe to use this in both
454089fb57cSJacob Faibussowitsch   C and C++ source files.
455bde483f2SJacob Faibussowitsch 
456d571e81cSJacob Faibussowitsch   In this context "captured" means assigning the return value of a function to a named
457d571e81cSJacob Faibussowitsch   variable or casting it to `void`. Between the two, assigning to a named variable is the most
458d571e81cSJacob Faibussowitsch   portable way of silencing any warnings, since `PETSC_NODISCARD` may expand to GCC's
459d571e81cSJacob Faibussowitsch   `__attribute__((warn_unused_result))` which will still emit warnings when casting results to
460d571e81cSJacob Faibussowitsch   `void`.
461d571e81cSJacob Faibussowitsch 
462bde483f2SJacob Faibussowitsch   Example Usage:
463bde483f2SJacob Faibussowitsch .vb
464bde483f2SJacob Faibussowitsch   class Foo
465bde483f2SJacob Faibussowitsch   {
466bde483f2SJacob Faibussowitsch     int x;
467bde483f2SJacob Faibussowitsch 
468bde483f2SJacob Faibussowitsch   public:
469bde483f2SJacob Faibussowitsch     PETSC_NODISCARD Foo(int y) : x(y) { }
470bde483f2SJacob Faibussowitsch   };
471bde483f2SJacob Faibussowitsch 
472bde483f2SJacob Faibussowitsch   PETSC_NODISCARD int factorial(int n)
473bde483f2SJacob Faibussowitsch   {
474bde483f2SJacob Faibussowitsch     return n <= 1 ? 1 : (n * factorial(n - 1));
475bde483f2SJacob Faibussowitsch   }
476bde483f2SJacob Faibussowitsch 
477bde483f2SJacob Faibussowitsch   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
478d571e81cSJacob Faibussowitsch   auto x = factorial(10); // OK, capturing return value
479d571e81cSJacob Faibussowitsch   (void)factorial(10);    // Maybe OK, casting to void
480d571e81cSJacob Faibussowitsch   auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
481d571e81cSJacob Faibussowitsch   (void)y;                // set-but-not-used warnings)
482bde483f2SJacob Faibussowitsch 
483bde483f2SJacob Faibussowitsch   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
484d571e81cSJacob Faibussowitsch   auto f = Foo(x); // OK, capturing constructed object
485d571e81cSJacob Faibussowitsch   (void)Foo(x);    // Maybe OK, casting to void
486d571e81cSJacob Faibussowitsch   auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
487d571e81cSJacob Faibussowitsch   (void)g;         // warnings)
488bde483f2SJacob Faibussowitsch .ve
489bde483f2SJacob Faibussowitsch 
490db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
491817da375SSatish Balay M*/
492bde483f2SJacob Faibussowitsch 
493bde483f2SJacob Faibussowitsch /* C++11 features */
494089fb57cSJacob Faibussowitsch #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
495bde483f2SJacob Faibussowitsch   #define PETSC_NULLPTR nullptr
496bde483f2SJacob Faibussowitsch #else
497bde483f2SJacob Faibussowitsch   #define PETSC_NULLPTR NULL
498bde483f2SJacob Faibussowitsch #endif
499bde483f2SJacob Faibussowitsch 
500bde483f2SJacob Faibussowitsch /* C++14 features */
5010e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 14
5026ee8c794SJacob Faibussowitsch   #define PETSC_CONSTEXPR_14 constexpr
503bde483f2SJacob Faibussowitsch #else
504bde483f2SJacob Faibussowitsch   #define PETSC_CONSTEXPR_14
505bde483f2SJacob Faibussowitsch #endif
506bde483f2SJacob Faibussowitsch 
507bde483f2SJacob Faibussowitsch /* C++17 features */
5080e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 17
5090e6b6b59SJacob Faibussowitsch   #define PETSC_CONSTEXPR_17 constexpr
510bde483f2SJacob Faibussowitsch #else
5110e6b6b59SJacob Faibussowitsch   #define PETSC_CONSTEXPR_17
5120e6b6b59SJacob Faibussowitsch #endif
5130e6b6b59SJacob Faibussowitsch 
514089fb57cSJacob Faibussowitsch #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
515089fb57cSJacob Faibussowitsch   #define PETSC_NODISCARD [[nodiscard]]
516089fb57cSJacob Faibussowitsch #elif PetscHasAttribute(warn_unused_result)
517089fb57cSJacob Faibussowitsch   #define PETSC_NODISCARD __attribute__((warn_unused_result))
518089fb57cSJacob Faibussowitsch #else
5190e6b6b59SJacob Faibussowitsch   #define PETSC_NODISCARD
520bde483f2SJacob Faibussowitsch #endif
521bde483f2SJacob Faibussowitsch 
522bde483f2SJacob Faibussowitsch #include <petscversion.h>
523bde483f2SJacob Faibussowitsch #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
524bde483f2SJacob Faibussowitsch 
525267267bdSJacob Faibussowitsch /* designated initializers since C99 and C++20, MSVC never supports them though */
5260e6b6b59SJacob Faibussowitsch #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
527267267bdSJacob Faibussowitsch   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
528267267bdSJacob Faibussowitsch #else
529267267bdSJacob Faibussowitsch   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
530267267bdSJacob Faibussowitsch #endif
531267267bdSJacob Faibussowitsch 
532bde483f2SJacob Faibussowitsch /*MC
53387497f52SBarry Smith   PetscUnlikely - Hints the compiler that the given condition is usually false
534bde483f2SJacob Faibussowitsch 
535bde483f2SJacob Faibussowitsch   Synopsis:
536bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
537bde483f2SJacob Faibussowitsch   bool PetscUnlikely(bool cond)
538bde483f2SJacob Faibussowitsch 
53916a05f60SBarry Smith   Not Collective; No Fortran Support
540bde483f2SJacob Faibussowitsch 
541bde483f2SJacob Faibussowitsch   Input Parameter:
542bde483f2SJacob Faibussowitsch . cond - Boolean expression
543bde483f2SJacob Faibussowitsch 
54416a05f60SBarry Smith   Level: advanced
545bde483f2SJacob Faibussowitsch 
546af27ebaaSBarry Smith   Note:
547bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
548bde483f2SJacob Faibussowitsch   unlikely to be true.
549bde483f2SJacob Faibussowitsch 
550bde483f2SJacob Faibussowitsch   Example usage:
551bde483f2SJacob Faibussowitsch .vb
552bde483f2SJacob Faibussowitsch   if (PetscUnlikely(cond)) {
553bde483f2SJacob Faibussowitsch     foo(); // cold path
554bde483f2SJacob Faibussowitsch   } else {
555bde483f2SJacob Faibussowitsch     bar(); // hot path
556bde483f2SJacob Faibussowitsch   }
557bde483f2SJacob Faibussowitsch .ve
558bde483f2SJacob Faibussowitsch 
559db781477SPatrick Sanan .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
560db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
561bde483f2SJacob Faibussowitsch M*/
562bde483f2SJacob Faibussowitsch 
563bde483f2SJacob Faibussowitsch /*MC
56487497f52SBarry Smith   PetscLikely - Hints the compiler that the given condition is usually true
565bde483f2SJacob Faibussowitsch 
566bde483f2SJacob Faibussowitsch   Synopsis:
567bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
568bde483f2SJacob Faibussowitsch   bool PetscLikely(bool cond)
569bde483f2SJacob Faibussowitsch 
57016a05f60SBarry Smith   Not Collective; No Fortran Support
571bde483f2SJacob Faibussowitsch 
572bde483f2SJacob Faibussowitsch   Input Parameter:
573bde483f2SJacob Faibussowitsch . cond - Boolean expression
574bde483f2SJacob Faibussowitsch 
57516a05f60SBarry Smith   Level: advanced
576bde483f2SJacob Faibussowitsch 
577af27ebaaSBarry Smith   Note:
578bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
579bde483f2SJacob Faibussowitsch   likely to be true.
580bde483f2SJacob Faibussowitsch 
581bde483f2SJacob Faibussowitsch   Example usage:
582bde483f2SJacob Faibussowitsch .vb
583bde483f2SJacob Faibussowitsch   if (PetscLikely(cond)) {
584bde483f2SJacob Faibussowitsch     foo(); // hot path
585bde483f2SJacob Faibussowitsch   } else {
586bde483f2SJacob Faibussowitsch     bar(); // cold path
587bde483f2SJacob Faibussowitsch   }
588bde483f2SJacob Faibussowitsch .ve
589bde483f2SJacob Faibussowitsch 
590db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
591db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
592bde483f2SJacob Faibussowitsch M*/
593bde483f2SJacob Faibussowitsch #if defined(PETSC_HAVE_BUILTIN_EXPECT)
594bde483f2SJacob Faibussowitsch   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
595bde483f2SJacob Faibussowitsch   #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
596bde483f2SJacob Faibussowitsch #else
597bde483f2SJacob Faibussowitsch   #define PetscUnlikely(cond) (cond)
598bde483f2SJacob Faibussowitsch   #define PetscLikely(cond)   (cond)
599bde483f2SJacob Faibussowitsch #endif
600bde483f2SJacob Faibussowitsch 
601bde483f2SJacob Faibussowitsch /*MC
602817da375SSatish Balay   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
603bde483f2SJacob Faibussowitsch 
604bde483f2SJacob Faibussowitsch   Synopsis:
605bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
606bde483f2SJacob Faibussowitsch   void PetscUnreachable(void)
607bde483f2SJacob Faibussowitsch 
60816a05f60SBarry Smith   Level: advanced
60916a05f60SBarry Smith 
610af27ebaaSBarry Smith   Note:
611bde483f2SJacob Faibussowitsch   Indicates to the compiler (usually via some built-in) that a particular code path is always
612bde483f2SJacob Faibussowitsch   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
613bde483f2SJacob Faibussowitsch   unceremonious crash.
614bde483f2SJacob Faibussowitsch 
615bde483f2SJacob Faibussowitsch   Example usage:
616bde483f2SJacob Faibussowitsch   Useful in situations such as switches over enums where not all enumeration values are
617bde483f2SJacob Faibussowitsch   explicitly covered by the switch
618bde483f2SJacob Faibussowitsch 
619bde483f2SJacob Faibussowitsch .vb
620bde483f2SJacob Faibussowitsch   typedef enum {RED, GREEN, BLUE} Color;
621bde483f2SJacob Faibussowitsch 
622bde483f2SJacob Faibussowitsch   int foo(Color c)
623bde483f2SJacob Faibussowitsch   {
624bde483f2SJacob Faibussowitsch     // it is known to programmer (or checked previously) that c is either RED or GREEN
625bde483f2SJacob Faibussowitsch     // but compiler may not be able to deduce this and/or emit spurious warnings
626bde483f2SJacob Faibussowitsch     switch (c) {
627bde483f2SJacob Faibussowitsch       case RED:
628bde483f2SJacob Faibussowitsch         return bar();
629bde483f2SJacob Faibussowitsch       case GREEN:
630bde483f2SJacob Faibussowitsch         return baz();
631bde483f2SJacob Faibussowitsch       default:
632bde483f2SJacob Faibussowitsch         PetscUnreachable(); // program is ill-formed if executed
633bde483f2SJacob Faibussowitsch     }
634bde483f2SJacob Faibussowitsch   }
635bde483f2SJacob Faibussowitsch .ve
636bde483f2SJacob Faibussowitsch 
637c7481402SJacob Faibussowitsch .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
638817da375SSatish Balay M*/
639563b2f50SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 23
640563b2f50SJacob Faibussowitsch   #include <utility>
641563b2f50SJacob Faibussowitsch   #define PetscUnreachable() std::unreachable()
642563b2f50SJacob Faibussowitsch #elif defined(__GNUC__)
643e58a63e1SJacob Faibussowitsch   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
644e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() __builtin_unreachable()
645e58a63e1SJacob Faibussowitsch #elif defined(_MSC_VER) /* MSVC */
646e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() __assume(0)
647e58a63e1SJacob Faibussowitsch #else /* ??? */
648e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
649e58a63e1SJacob Faibussowitsch #endif
650bde483f2SJacob Faibussowitsch 
651bde483f2SJacob Faibussowitsch /*MC
652c7481402SJacob Faibussowitsch   PetscAssume - Indicate to the compiler a condition that is defined to be true
653c7481402SJacob Faibussowitsch 
654c7481402SJacob Faibussowitsch   Synopsis:
655c7481402SJacob Faibussowitsch   #include <petscmacros.h>
656c7481402SJacob Faibussowitsch   void PetscAssume(bool cond)
657c7481402SJacob Faibussowitsch 
658c7481402SJacob Faibussowitsch   Input Parameter:
659c7481402SJacob Faibussowitsch . cond - Boolean expression
660c7481402SJacob Faibussowitsch 
66116a05f60SBarry Smith   Level: advanced
66216a05f60SBarry Smith 
663c7481402SJacob Faibussowitsch   Notes:
664c7481402SJacob Faibussowitsch   If supported by the compiler, `cond` is used to inform the optimizer of an invariant
665c7481402SJacob Faibussowitsch   truth. The argument itself is never evaluated, so any side effects of the expression will be
666c7481402SJacob Faibussowitsch   discarded. This macro is used in `PetscAssert()` to retain information gained from debug
667c7481402SJacob Faibussowitsch   checks that would be lost in optimized builds. For example\:
668c7481402SJacob Faibussowitsch 
669c7481402SJacob Faibussowitsch .vb
670c7481402SJacob Faibussowitsch   PetscErrorCode foo(PetscInt x) {
671c7481402SJacob Faibussowitsch 
672c7481402SJacob Faibussowitsch     PetscAssert(x >= 0, ...);
673c7481402SJacob Faibussowitsch   }
674c7481402SJacob Faibussowitsch .ve
675c7481402SJacob Faibussowitsch 
676c7481402SJacob Faibussowitsch   The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
677c7481402SJacob Faibussowitsch   if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
678c7481402SJacob Faibussowitsch   when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
679c7481402SJacob Faibussowitsch   optimizer cannot deduce any information from them.
680c7481402SJacob Faibussowitsch 
681c7481402SJacob Faibussowitsch   Due to compiler limitations `PetscAssume()` works best when `cond` involves
682d5b43468SJose E. Roman   constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
683c7481402SJacob Faibussowitsch 
684c7481402SJacob Faibussowitsch .vb
685c7481402SJacob Faibussowitsch   int a, b, var_five;
686c7481402SJacob Faibussowitsch 
687c7481402SJacob Faibussowitsch   // BEST, all supporting compilers will understand a cannot be >= 5
688c7481402SJacob Faibussowitsch   PetscAssume(a < 5);
689c7481402SJacob Faibussowitsch 
690c7481402SJacob Faibussowitsch    // OK, some compilers may understand that a cannot be >= 5
691c7481402SJacob Faibussowitsch   PetscAssume(a <= b && b < 5);
692c7481402SJacob Faibussowitsch 
693c7481402SJacob Faibussowitsch    // WORST, most compilers will not get the memo
694c7481402SJacob Faibussowitsch   PetscAssume(a <= b && b < var_five);
695c7481402SJacob Faibussowitsch .ve
696c7481402SJacob Faibussowitsch 
697c7481402SJacob Faibussowitsch   If the condition is violated at runtime then behavior is wholly undefined. If the
698c7481402SJacob Faibussowitsch   condition is violated at compile-time, the condition "supersedes" the compile-time violation
699c7481402SJacob Faibussowitsch   and the program is ill-formed, no diagnostic required. For example consider the following\:
700c7481402SJacob Faibussowitsch 
701c7481402SJacob Faibussowitsch .vb
702c7481402SJacob Faibussowitsch   PetscInt x = 0;
703c7481402SJacob Faibussowitsch 
704c7481402SJacob Faibussowitsch   PetscAssume(x != 0);
705c7481402SJacob Faibussowitsch   if (x == 0) {
706c7481402SJacob Faibussowitsch     x += 10;
707c7481402SJacob Faibussowitsch   } else {
708c7481402SJacob Faibussowitsch     popen("rm -rf /", "w");
709c7481402SJacob Faibussowitsch   }
710c7481402SJacob Faibussowitsch .ve
711c7481402SJacob Faibussowitsch 
712c7481402SJacob Faibussowitsch   Even though `x` is demonstrably `0` the compiler may opt to\:
713c7481402SJacob Faibussowitsch 
714c7481402SJacob Faibussowitsch   - emit an unconditional `popen("rm -rf /", "w")`
715c7481402SJacob Faibussowitsch   - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
716c7481402SJacob Faibussowitsch   - reformat the primary disk partition
717c7481402SJacob Faibussowitsch 
718c7481402SJacob Faibussowitsch .seealso: `PetscAssert()`
719c7481402SJacob Faibussowitsch M*/
720563b2f50SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 23
721563b2f50SJacob Faibussowitsch   #define PetscAssume(...) [[assume(__VA_ARGS__)]]
722563b2f50SJacob Faibussowitsch #elif defined(_MSC_VER) // msvc
723c7481402SJacob Faibussowitsch   #define PetscAssume(...) __assume(__VA_ARGS__)
724c7481402SJacob Faibussowitsch #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
725c7481402SJacob Faibussowitsch   #define PetscAssume(...) \
726c7481402SJacob Faibussowitsch     do { \
727c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic push"); \
728c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic ignored \"-Wassume\""); \
729c7481402SJacob Faibussowitsch       __builtin_assume(__VA_ARGS__); \
730c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic pop"); \
731c7481402SJacob Faibussowitsch     } while (0)
732c7481402SJacob Faibussowitsch #else // gcc (and really old clang)
733c7481402SJacob Faibussowitsch   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
734c7481402SJacob Faibussowitsch   //
735c7481402SJacob Faibussowitsch   // if (PetscUnlikely(!cond)) PetscUnreachable();
736c7481402SJacob Faibussowitsch   //
737c7481402SJacob Faibussowitsch   // but this it unsavory because the side effects of cond are not guaranteed to be
738c7481402SJacob Faibussowitsch   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
739c7481402SJacob Faibussowitsch   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
740c7481402SJacob Faibussowitsch   // always do so. This is especially the case for opaque or non-inline function calls:
741c7481402SJacob Faibussowitsch   //
742c7481402SJacob Faibussowitsch   // extern int bar(int);
743c7481402SJacob Faibussowitsch   //
744c7481402SJacob Faibussowitsch   // int foo(int x) {
745c7481402SJacob Faibussowitsch   //   PetscAssume(bar(x) == 2);
746c7481402SJacob Faibussowitsch   //   if (bar(x) == 2) {
747c7481402SJacob Faibussowitsch   //     return 1;
748c7481402SJacob Faibussowitsch   //   } else {
749c7481402SJacob Faibussowitsch   //     return 0;
750c7481402SJacob Faibussowitsch   //   }
751c7481402SJacob Faibussowitsch   // }
752c7481402SJacob Faibussowitsch   //
753c7481402SJacob Faibussowitsch   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
7542f181314SPierre Jolivet   // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
755c7481402SJacob Faibussowitsch   #define PetscAssume(...) \
756c7481402SJacob Faibussowitsch     do { \
757c7481402SJacob Faibussowitsch       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
758c7481402SJacob Faibussowitsch     } while (0)
759c7481402SJacob Faibussowitsch #endif
760c7481402SJacob Faibussowitsch 
761c7481402SJacob Faibussowitsch /*MC
762bde483f2SJacob Faibussowitsch   PetscExpand - Expand macro argument
763bde483f2SJacob Faibussowitsch 
764bde483f2SJacob Faibussowitsch   Synopsis:
765bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
766bde483f2SJacob Faibussowitsch   <macro-expansion> PetscExpand(x)
767bde483f2SJacob Faibussowitsch 
7686aad120cSJose E. Roman   Input Parameter:
769bde483f2SJacob Faibussowitsch . x - The preprocessor token to expand
770bde483f2SJacob Faibussowitsch 
77149762cbcSSatish Balay   Level: beginner
77249762cbcSSatish Balay 
773db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscConcat()`
774817da375SSatish Balay M*/
775e58a63e1SJacob Faibussowitsch #define PetscExpand_(...) __VA_ARGS__
776e58a63e1SJacob Faibussowitsch #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
777bde483f2SJacob Faibussowitsch 
778bde483f2SJacob Faibussowitsch /*MC
779bde483f2SJacob Faibussowitsch   PetscStringize - Stringize a token
780bde483f2SJacob Faibussowitsch 
781bde483f2SJacob Faibussowitsch   Synopsis:
782bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
783bde483f2SJacob Faibussowitsch   const char* PetscStringize(x)
784bde483f2SJacob Faibussowitsch 
78516a05f60SBarry Smith   No Fortran Support
78616a05f60SBarry Smith 
787bde483f2SJacob Faibussowitsch   Input Parameter:
788bde483f2SJacob Faibussowitsch . x - The token you would like to stringize
789bde483f2SJacob Faibussowitsch 
790bde483f2SJacob Faibussowitsch   Output Parameter:
79116a05f60SBarry Smith . <return-value> - The string representation of `x`
792bde483f2SJacob Faibussowitsch 
79316a05f60SBarry Smith   Level: beginner
794bde483f2SJacob Faibussowitsch 
79516a05f60SBarry Smith   Note:
79616a05f60SBarry Smith   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
79716a05f60SBarry Smith   `PetscStringize_()` instead.
798bde483f2SJacob Faibussowitsch 
799bde483f2SJacob Faibussowitsch   Example Usage:
800bde483f2SJacob Faibussowitsch .vb
801bde483f2SJacob Faibussowitsch   #define MY_OTHER_VAR hello there
802bde483f2SJacob Faibussowitsch   #define MY_VAR       MY_OTHER_VAR
803bde483f2SJacob Faibussowitsch 
804bde483f2SJacob Faibussowitsch   PetscStringize(MY_VAR)  -> "hello there"
805bde483f2SJacob Faibussowitsch   PetscStringize_(MY_VAR) -> "MY_VAR"
806bde483f2SJacob Faibussowitsch 
807bde483f2SJacob Faibussowitsch   int foo;
808bde483f2SJacob Faibussowitsch   PetscStringize(foo)  -> "foo"
809bde483f2SJacob Faibussowitsch   PetscStringize_(foo) -> "foo"
810bde483f2SJacob Faibussowitsch .ve
811bde483f2SJacob Faibussowitsch 
812db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
813817da375SSatish Balay M*/
8140e6b6b59SJacob Faibussowitsch #define PetscStringize_(...) #__VA_ARGS__
8150e6b6b59SJacob Faibussowitsch #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
816bde483f2SJacob Faibussowitsch 
817bde483f2SJacob Faibussowitsch /*MC
818bde483f2SJacob Faibussowitsch   PetscConcat - Concatenate two tokens
819bde483f2SJacob Faibussowitsch 
820bde483f2SJacob Faibussowitsch   Synopsis:
821bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
822bde483f2SJacob Faibussowitsch   <macro-expansion> PetscConcat(x, y)
823bde483f2SJacob Faibussowitsch 
82416a05f60SBarry Smith   No Fortran Support
82516a05f60SBarry Smith 
826bde483f2SJacob Faibussowitsch   Input Parameters:
827bde483f2SJacob Faibussowitsch + x - First token
828bde483f2SJacob Faibussowitsch - y - Second token
829bde483f2SJacob Faibussowitsch 
83016a05f60SBarry Smith   Level: beginner
831bde483f2SJacob Faibussowitsch 
83216a05f60SBarry Smith   Note:
83316a05f60SBarry Smith   `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
834bde483f2SJacob Faibussowitsch   if you don't want to expand them.
835bde483f2SJacob Faibussowitsch 
836bde483f2SJacob Faibussowitsch   Example usage:
837bde483f2SJacob Faibussowitsch .vb
838bde483f2SJacob Faibussowitsch   PetscConcat(hello,there) -> hellothere
839bde483f2SJacob Faibussowitsch 
840bde483f2SJacob Faibussowitsch   #define HELLO hello
841bde483f2SJacob Faibussowitsch   PetscConcat(HELLO,there)  -> hellothere
842bde483f2SJacob Faibussowitsch   PetscConcat_(HELLO,there) -> HELLOthere
843bde483f2SJacob Faibussowitsch .ve
844bde483f2SJacob Faibussowitsch 
845db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscExpand()`
846817da375SSatish Balay M*/
847bde483f2SJacob Faibussowitsch #define PetscConcat_(x, y) x##y
848bde483f2SJacob Faibussowitsch #define PetscConcat(x, y)  PetscConcat_(x, y)
849bde483f2SJacob Faibussowitsch 
850bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_0 1
851bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_1 0
852bde483f2SJacob Faibussowitsch 
853bde483f2SJacob Faibussowitsch /*MC
854bde483f2SJacob Faibussowitsch   PetscCompl - Expands to the integer complement of its argument
855bde483f2SJacob Faibussowitsch 
856bde483f2SJacob Faibussowitsch   Synopsis:
857bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
858bde483f2SJacob Faibussowitsch   int PetscCompl(b)
859bde483f2SJacob Faibussowitsch 
86016a05f60SBarry Smith   No Fortran Support
86116a05f60SBarry Smith 
862bde483f2SJacob Faibussowitsch   Input Parameter:
863bde483f2SJacob Faibussowitsch . b - Preprocessor variable, must expand to either integer literal 0 or 1
864bde483f2SJacob Faibussowitsch 
8656aad120cSJose E. Roman   Output Parameter:
866bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
867bde483f2SJacob Faibussowitsch 
86816a05f60SBarry Smith   Level: beginner
869bde483f2SJacob Faibussowitsch 
87016a05f60SBarry Smith   Notes:
871bde483f2SJacob Faibussowitsch   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
872bde483f2SJacob Faibussowitsch   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
873bde483f2SJacob Faibussowitsch   argument before returning the complement.
874bde483f2SJacob Faibussowitsch 
87516a05f60SBarry Smith   This macro can be useful for negating `PetscDefined()` inside macros e.g.
876af27ebaaSBarry Smith .vb
877af27ebaaSBarry Smith   #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
878af27ebaaSBarry Smith .ve
879bde483f2SJacob Faibussowitsch 
880bde483f2SJacob Faibussowitsch   Example usage:
881bde483f2SJacob Faibussowitsch .vb
882bde483f2SJacob Faibussowitsch   #define MY_VAR 1
883bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 0
884bde483f2SJacob Faibussowitsch 
885bde483f2SJacob Faibussowitsch   #undef  MY_VAR
886bde483f2SJacob Faibussowitsch   #define MY_VAR 0
887bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 1
888bde483f2SJacob Faibussowitsch .ve
889bde483f2SJacob Faibussowitsch 
890db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`
891817da375SSatish Balay M*/
892bde483f2SJacob Faibussowitsch #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
893bde483f2SJacob Faibussowitsch 
894bde483f2SJacob Faibussowitsch /*MC
895bde483f2SJacob Faibussowitsch   PetscDefined - Determine whether a boolean macro is defined
896bde483f2SJacob Faibussowitsch 
897bde483f2SJacob Faibussowitsch   Synopsis:
898bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
899bde483f2SJacob Faibussowitsch   int PetscDefined(def)
900bde483f2SJacob Faibussowitsch 
9017cdbe19fSJose E. Roman   No Fortran Support
9027cdbe19fSJose E. Roman 
903bde483f2SJacob Faibussowitsch   Input Parameter:
904bde483f2SJacob Faibussowitsch . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
905bde483f2SJacob Faibussowitsch 
906d5b43468SJose E. Roman   Output Parameter:
907bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
908bde483f2SJacob Faibussowitsch 
90916a05f60SBarry Smith   Level: intermediate
91016a05f60SBarry Smith 
911bde483f2SJacob Faibussowitsch   Notes:
91287497f52SBarry Smith   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
91387497f52SBarry Smith   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
914bde483f2SJacob Faibussowitsch   this macro should not be used if its argument may be defined to a non-empty value other than
915bde483f2SJacob Faibussowitsch   1.
916bde483f2SJacob Faibussowitsch 
917bde483f2SJacob Faibussowitsch   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
91887497f52SBarry Smith   add custom checks in user code, one should use `PetscDefined_()`.
919af27ebaaSBarry Smith .vb
920af27ebaaSBarry Smith   #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
921af27ebaaSBarry Smith .ve
922bde483f2SJacob Faibussowitsch 
923bde483f2SJacob Faibussowitsch   Developer Notes:
924bde483f2SJacob Faibussowitsch   Getting something that works in C and CPP for an arg that may or may not be defined is
925bde483f2SJacob Faibussowitsch   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
926bde483f2SJacob Faibussowitsch   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
927bde483f2SJacob Faibussowitsch   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
928bde483f2SJacob Faibussowitsch   and when the last step cherry picks the 2nd arg, we get a zero.
929bde483f2SJacob Faibussowitsch 
930bde483f2SJacob Faibussowitsch   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
931bde483f2SJacob Faibussowitsch   nonconforming implementation of variadic macros.
932bde483f2SJacob Faibussowitsch 
933bde483f2SJacob Faibussowitsch   Example Usage:
934bde483f2SJacob Faibussowitsch   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
935bde483f2SJacob Faibussowitsch   is defined then
936bde483f2SJacob Faibussowitsch 
937bde483f2SJacob Faibussowitsch .vb
938bde483f2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
939bde483f2SJacob Faibussowitsch     foo();
940bde483f2SJacob Faibussowitsch   #else
941bde483f2SJacob Faibussowitsch     bar();
942bde483f2SJacob Faibussowitsch   #endif
943bde483f2SJacob Faibussowitsch 
944bde483f2SJacob Faibussowitsch   // or alternatively within normal code
945bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
946bde483f2SJacob Faibussowitsch     foo();
947bde483f2SJacob Faibussowitsch   } else {
948bde483f2SJacob Faibussowitsch     bar();
949bde483f2SJacob Faibussowitsch   }
950bde483f2SJacob Faibussowitsch .ve
951bde483f2SJacob Faibussowitsch 
952bde483f2SJacob Faibussowitsch   is equivalent to
953bde483f2SJacob Faibussowitsch 
954bde483f2SJacob Faibussowitsch .vb
955bde483f2SJacob Faibussowitsch   #if defined(PETSC_USE_DEBUG)
956bde483f2SJacob Faibussowitsch   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
957bde483f2SJacob Faibussowitsch        foo();
958bde483f2SJacob Faibussowitsch   #   elif PETSC_USE_DEBUG == 1
959bde483f2SJacob Faibussowitsch        foo();
960bde483f2SJacob Faibussowitsch   #   else
961bde483f2SJacob Faibussowitsch        bar();
962bde483f2SJacob Faibussowitsch   #  endif
963bde483f2SJacob Faibussowitsch   #else
964bde483f2SJacob Faibussowitsch   bar();
965bde483f2SJacob Faibussowitsch   #endif
966bde483f2SJacob Faibussowitsch .ve
967bde483f2SJacob Faibussowitsch 
968db781477SPatrick Sanan .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
969db781477SPatrick Sanan           `PetscExpandToNothing()`, `PetscCompl()`
970817da375SSatish Balay M*/
971bde483f2SJacob Faibussowitsch #define PetscDefined_arg_1                                    shift,
972bde483f2SJacob Faibussowitsch #define PetscDefined_arg_                                     shift,
973bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expanded(ignored, val, ...) val
974bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
975bde483f2SJacob Faibussowitsch #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
976bde483f2SJacob Faibussowitsch #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
977bde483f2SJacob Faibussowitsch #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
978bde483f2SJacob Faibussowitsch #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
979bde483f2SJacob Faibussowitsch 
980bde483f2SJacob Faibussowitsch /*MC
98187497f52SBarry Smith   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
982bde483f2SJacob Faibussowitsch   the check in optimized mode
983bde483f2SJacob Faibussowitsch 
984bde483f2SJacob Faibussowitsch   Synopsis:
985bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
986bde483f2SJacob Faibussowitsch   bool PetscUnlikelyDebug(bool cond)
987bde483f2SJacob Faibussowitsch 
988af27ebaaSBarry Smith   Not Collective; No Fortran Support
989bde483f2SJacob Faibussowitsch 
9902fe279fdSBarry Smith   Input Parameter:
991bde483f2SJacob Faibussowitsch . cond - Boolean expression
992bde483f2SJacob Faibussowitsch 
99316a05f60SBarry Smith   Level: advanced
99416a05f60SBarry Smith 
99516a05f60SBarry Smith   Note:
99616a05f60SBarry Smith   This returns the same truth value, it is only a hint to compilers that the result of `cond` is
997bde483f2SJacob Faibussowitsch   likely to be false. When PETSc is compiled in optimized mode this will always return
99816a05f60SBarry Smith   false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
999bde483f2SJacob Faibussowitsch   optimized mode.
1000bde483f2SJacob Faibussowitsch 
1001bde483f2SJacob Faibussowitsch   Example usage:
1002bde483f2SJacob Faibussowitsch   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
1003bde483f2SJacob Faibussowitsch   is true. So
1004bde483f2SJacob Faibussowitsch 
1005bde483f2SJacob Faibussowitsch .vb
1006bde483f2SJacob Faibussowitsch   if (PetscUnlikelyDebug(cond)) {
1007bde483f2SJacob Faibussowitsch     foo();
1008bde483f2SJacob Faibussowitsch   } else {
1009bde483f2SJacob Faibussowitsch     bar();
1010bde483f2SJacob Faibussowitsch   }
1011bde483f2SJacob Faibussowitsch .ve
1012bde483f2SJacob Faibussowitsch 
1013bde483f2SJacob Faibussowitsch   is equivalent to
1014bde483f2SJacob Faibussowitsch 
1015bde483f2SJacob Faibussowitsch .vb
1016bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
1017bde483f2SJacob Faibussowitsch     if (PetscUnlikely(cond)) {
1018bde483f2SJacob Faibussowitsch       foo();
1019bde483f2SJacob Faibussowitsch     } else {
1020bde483f2SJacob Faibussowitsch       bar();
1021bde483f2SJacob Faibussowitsch     }
1022bde483f2SJacob Faibussowitsch   } else {
1023bde483f2SJacob Faibussowitsch     bar();
1024bde483f2SJacob Faibussowitsch   }
1025bde483f2SJacob Faibussowitsch .ve
1026bde483f2SJacob Faibussowitsch 
1027db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1028bde483f2SJacob Faibussowitsch M*/
1029bde483f2SJacob Faibussowitsch #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1030bde483f2SJacob Faibussowitsch 
1031f7e3c444SJacob Faibussowitsch #if defined(PETSC_CLANG_STATIC_ANALYZER)
1032f7e3c444SJacob Faibussowitsch   // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1033f7e3c444SJacob Faibussowitsch   // not what ISO C allows
10349371c9d4SSatish Balay   #define PetscMacroReturns_(retexpr, ...) \
10359371c9d4SSatish Balay     __extension__({ \
10369371c9d4SSatish Balay       __VA_ARGS__; \
10379371c9d4SSatish Balay       retexpr; \
10389371c9d4SSatish Balay     })
1039f7e3c444SJacob Faibussowitsch #else
10409371c9d4SSatish Balay   #define PetscMacroReturns_(retexpr, ...) \
10419371c9d4SSatish Balay     retexpr; \
1042d71ae5a4SJacob Faibussowitsch     do { \
1043d71ae5a4SJacob Faibussowitsch       __VA_ARGS__; \
1044d71ae5a4SJacob Faibussowitsch     } while (0)
1045f7e3c444SJacob Faibussowitsch #endif
1046f7e3c444SJacob Faibussowitsch 
1047bde483f2SJacob Faibussowitsch /*MC
104816a05f60SBarry Smith   PetscExpandToNothing - Expands to absolutely nothing
1049bde483f2SJacob Faibussowitsch 
1050bde483f2SJacob Faibussowitsch   Synopsis:
1051bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
1052bde483f2SJacob Faibussowitsch   void PetscExpandToNothing(...)
1053bde483f2SJacob Faibussowitsch 
10547cdbe19fSJose E. Roman   No Fortran Support
10557cdbe19fSJose E. Roman 
1056bde483f2SJacob Faibussowitsch   Input Parameter:
1057bde483f2SJacob Faibussowitsch . __VA_ARGS__ - Anything at all
1058bde483f2SJacob Faibussowitsch 
105916a05f60SBarry Smith   Level: beginner
106016a05f60SBarry Smith 
106116a05f60SBarry Smith   Note:
1062bde483f2SJacob Faibussowitsch   Must have at least 1 parameter.
1063bde483f2SJacob Faibussowitsch 
1064bde483f2SJacob Faibussowitsch   Example usage:
1065bde483f2SJacob Faibussowitsch .vb
1066bde483f2SJacob Faibussowitsch   PetscExpandToNothing(a,b,c) -> *nothing*
1067bde483f2SJacob Faibussowitsch .ve
1068bde483f2SJacob Faibussowitsch 
1069db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1070817da375SSatish Balay M*/
1071bde483f2SJacob Faibussowitsch #define PetscExpandToNothing(...)
1072f7e3c444SJacob Faibussowitsch 
1073f7e3c444SJacob Faibussowitsch /*MC
1074f7e3c444SJacob Faibussowitsch   PetscMacroReturns - Define a macro body that returns a value
1075f7e3c444SJacob Faibussowitsch 
1076f7e3c444SJacob Faibussowitsch   Synopsis:
1077f7e3c444SJacob Faibussowitsch   #include <petscmacros.h>
1078f7e3c444SJacob Faibussowitsch   return_type PetscMacroReturns(return_type retexpr, ...)
1079f7e3c444SJacob Faibussowitsch 
1080f7e3c444SJacob Faibussowitsch   Input Parameters:
1081f7e3c444SJacob Faibussowitsch + retexpr     - The value or expression that the macro should return
1082f7e3c444SJacob Faibussowitsch - __VA_ARGS__ - The body of the macro
1083f7e3c444SJacob Faibussowitsch 
108416a05f60SBarry Smith   Level: intermediate
108516a05f60SBarry Smith 
1086f7e3c444SJacob Faibussowitsch   Notes:
1087f7e3c444SJacob Faibussowitsch   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1088f7e3c444SJacob Faibussowitsch   body of the macro and should not depend on values produced as a result of the expression. The
1089f7e3c444SJacob Faibussowitsch   user should not assume that the result of this macro is equivalent to a single logical source
1090f7e3c444SJacob Faibussowitsch   line. It is not portable to use macros defined using this one in conditional or loop bodies
1091f7e3c444SJacob Faibussowitsch   without enclosing them in curly braces\:
1092f7e3c444SJacob Faibussowitsch 
1093f7e3c444SJacob Faibussowitsch .vb
1094f7e3c444SJacob Faibussowitsch   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1095f7e3c444SJacob Faibussowitsch 
1096f7e3c444SJacob Faibussowitsch   int err,x = 10;
1097f7e3c444SJacob Faibussowitsch 
1098f7e3c444SJacob Faibussowitsch   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
1099f7e3c444SJacob Faibussowitsch   if (...) { err = FOO(x); }  // OK
1100f7e3c444SJacob Faibussowitsch 
1101f7e3c444SJacob Faibussowitsch   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1102f7e3c444SJacob Faibussowitsch   for (...) { err = FOO(x); } // OK
1103f7e3c444SJacob Faibussowitsch .ve
1104f7e3c444SJacob Faibussowitsch 
1105f7e3c444SJacob Faibussowitsch   It is also not portable to use this macro directly inside function call, conditional, loop,
1106f7e3c444SJacob Faibussowitsch   or switch statements\:
1107f7e3c444SJacob Faibussowitsch 
1108f7e3c444SJacob Faibussowitsch .vb
1109f7e3c444SJacob Faibussowitsch   extern void bar(int);
1110f7e3c444SJacob Faibussowitsch 
1111f7e3c444SJacob Faibussowitsch   int ret = FOO(x);
1112f7e3c444SJacob Faibussowitsch 
1113f7e3c444SJacob Faibussowitsch   bar(FOO(x)); // ERROR, may not compile
1114f7e3c444SJacob Faibussowitsch   bar(ret);    // OK
1115f7e3c444SJacob Faibussowitsch 
1116f7e3c444SJacob Faibussowitsch   if (FOO(x))  // ERROR, may not compile
1117f7e3c444SJacob Faibussowitsch   if (ret)     // OK
1118f7e3c444SJacob Faibussowitsch .ve
1119f7e3c444SJacob Faibussowitsch 
1120f7e3c444SJacob Faibussowitsch   Example usage:
1121f7e3c444SJacob Faibussowitsch .vb
1122f7e3c444SJacob Faibussowitsch   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1123f7e3c444SJacob Faibussowitsch 
1124f7e3c444SJacob Faibussowitsch   int x = 10;
1125f7e3c444SJacob Faibussowitsch   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1126f7e3c444SJacob Faibussowitsch 
1127f7e3c444SJacob Faibussowitsch   // multiline macros allowed, but must declare with line continuation as usual
1128f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1129f7e3c444SJacob Faibussowitsch     if (arg1 > 10) {                                            \
1130f7e3c444SJacob Faibussowitsch       puts("big int!");                                         \
1131f7e3c444SJacob Faibussowitsch     } else {                                                    \
1132f7e3c444SJacob Faibussowitsch       return 7355608;                                           \
1133f7e3c444SJacob Faibussowitsch     }                                                           \
1134f7e3c444SJacob Faibussowitsch   )
1135f7e3c444SJacob Faibussowitsch 
1136f7e3c444SJacob Faibussowitsch   // if retexpr contains commas, must enclose it with braces
1137f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1138f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1139f7e3c444SJacob Faibussowitsch 
1140f7e3c444SJacob Faibussowitsch   int x = 10;
1141f7e3c444SJacob Faibussowitsch   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1142f7e3c444SJacob Faibussowitsch   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1143f7e3c444SJacob Faibussowitsch .ve
1144f7e3c444SJacob Faibussowitsch 
1145db781477SPatrick Sanan .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1146f7e3c444SJacob Faibussowitsch M*/
1147f7e3c444SJacob Faibussowitsch #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1148f7e3c444SJacob Faibussowitsch 
11493ba16761SJacob Faibussowitsch #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)
1150f7e3c444SJacob Faibussowitsch 
1151dd39110bSPierre Jolivet /*MC
1152dd39110bSPierre Jolivet   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1153dd39110bSPierre Jolivet 
115416a05f60SBarry Smith   Synopsis:
115516a05f60SBarry Smith   #include <petscmacros.h>
115616a05f60SBarry Smith   size_t PETSC_STATIC_ARRAY_LENGTH(a)
115716a05f60SBarry Smith 
115816a05f60SBarry Smith   Input Parameter:
115916a05f60SBarry Smith . a - a static array of any type
116016a05f60SBarry Smith 
116116a05f60SBarry Smith   Output Parameter:
116216a05f60SBarry Smith . <return-value> -  the length of the array
116316a05f60SBarry Smith 
116416a05f60SBarry Smith   Example:
116516a05f60SBarry Smith .vb
116616a05f60SBarry Smith   PetscInt a[22];
116716a05f60SBarry Smith   size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
116816a05f60SBarry Smith .ve
116916a05f60SBarry Smith   `sa` will have a value of 22
117016a05f60SBarry Smith 
1171dd39110bSPierre Jolivet   Level: intermediate
1172dd39110bSPierre Jolivet M*/
117391c5ff90SBarry Smith #if PETSC_CPP_VERSION >= 14
117491c5ff90SBarry Smith   #include <cstddef>
117591c5ff90SBarry Smith   #include <type_traits>
117691c5ff90SBarry Smith 
117791c5ff90SBarry Smith template <typename T>
117891c5ff90SBarry Smith static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
117991c5ff90SBarry Smith {
118091c5ff90SBarry Smith   static_assert(std::is_array<T>::value, "");
118191c5ff90SBarry Smith   return std::extent<T, std::rank<T>::value - 1>::value;
118291c5ff90SBarry Smith }
118391c5ff90SBarry Smith #else
118491c5ff90SBarry Smith   #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
118591c5ff90SBarry Smith #endif
1186dd39110bSPierre Jolivet 
1187296d8154SBarry Smith /*
1188296d8154SBarry Smith   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1189296d8154SBarry Smith 
1190296d8154SBarry Smith   Example usage:
1191296d8154SBarry Smith 
1192296d8154SBarry Smith   #define mymacro(obj,...) {
1193296d8154SBarry Smith     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1194296d8154SBarry Smith     f(22 PETSC_REST_ARG(__VA_ARGS__));
1195296d8154SBarry Smith   }
1196296d8154SBarry Smith 
1197296d8154SBarry 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
1198296d8154SBarry Smith 
1199296d8154SBarry Smith   Reference:
1200296d8154SBarry Smith   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1201296d8154SBarry Smith */
1202296d8154SBarry Smith #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1203296d8154SBarry Smith #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1204296d8154SBarry Smith #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1205296d8154SBarry 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)
1206296d8154SBarry Smith #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
1207296d8154SBarry Smith #define PETSC_REST_HELPER_ONE(first)
1208296d8154SBarry Smith #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1209296d8154SBarry Smith #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1210296d8154SBarry Smith #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1211296d8154SBarry Smith 
12121c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
12131c7e414eSJacob Faibussowitsch   _Pragma(PetscStringize(name diagnostic push)) \
12141c7e414eSJacob Faibussowitsch   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))
12151c7e414eSJacob Faibussowitsch 
12161c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))
12171c7e414eSJacob Faibussowitsch 
12181c7e414eSJacob Faibussowitsch #if defined(__clang__)
12191c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
12201c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
12211c7e414eSJacob Faibussowitsch #elif defined(__GNUC__) || defined(__GNUG__)
12229bab7813SJacob Faibussowitsch   // gcc >= 4.6.0
12239bab7813SJacob Faibussowitsch   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
12241c7e414eSJacob Faibussowitsch     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
12251c7e414eSJacob Faibussowitsch     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
12261c7e414eSJacob Faibussowitsch   #endif
12279bab7813SJacob Faibussowitsch #endif
12281c7e414eSJacob Faibussowitsch 
12291c7e414eSJacob Faibussowitsch #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
12301c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
12311c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
12321c7e414eSJacob Faibussowitsch   // only undefine these if they are not used
12331c7e414eSJacob Faibussowitsch   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
12341c7e414eSJacob Faibussowitsch   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
12351c7e414eSJacob Faibussowitsch #endif
12361c7e414eSJacob Faibussowitsch 
1237*8d031ccaSJunchao Zhang /*MC
1238*8d031ccaSJunchao Zhang   PetscPragmaOMP - Sets an OpenMP pragma to affect the next block of code
1239*8d031ccaSJunchao Zhang 
1240*8d031ccaSJunchao Zhang   Synopsis:
1241*8d031ccaSJunchao Zhang   #include <petscmacros.h>
1242*8d031ccaSJunchao Zhang   int PetscPragmaOMP(name)
1243*8d031ccaSJunchao Zhang 
1244*8d031ccaSJunchao Zhang   No Fortran Support
1245*8d031ccaSJunchao Zhang 
1246*8d031ccaSJunchao Zhang   Input Parameter:
1247*8d031ccaSJunchao Zhang . name - the OpenMP pragma, for example, `critical` or `parallel for`
1248*8d031ccaSJunchao Zhang 
1249*8d031ccaSJunchao Zhang   Level: intermediate
1250*8d031ccaSJunchao Zhang 
1251*8d031ccaSJunchao Zhang   Note:
1252*8d031ccaSJunchao Zhang   The pragma takes effect when PETSc was configured with `--with-openmp`. See `PetscPragmaUseOMPKernels()`
1253*8d031ccaSJunchao Zhang   for when PETSc was configured to use OpenMP in some of its numerical kernals.
1254*8d031ccaSJunchao Zhang 
1255*8d031ccaSJunchao Zhang .seealso: `PetscPragmaUseOMPKernels()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1256*8d031ccaSJunchao Zhang `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1257*8d031ccaSJunchao Zhang M*/
12582e327cfbSJacob Faibussowitsch #if defined(_OPENMP)
12592e327cfbSJacob Faibussowitsch   #if defined(_MSC_VER)
12602e327cfbSJacob Faibussowitsch     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
12612e327cfbSJacob Faibussowitsch   #else
12622e327cfbSJacob Faibussowitsch     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
12632e327cfbSJacob Faibussowitsch   #endif
1264*8d031ccaSJunchao Zhang #else
1265*8d031ccaSJunchao Zhang   #define PetscPragmaOMP(...)
12662e327cfbSJacob Faibussowitsch #endif
12672e327cfbSJacob Faibussowitsch 
1268*8d031ccaSJunchao Zhang /*MC
1269*8d031ccaSJunchao Zhang   PetscPragmaUseOMPKernels - Sets an OpenMP pragma to affect the next block of code
1270*8d031ccaSJunchao Zhang 
1271*8d031ccaSJunchao Zhang   Synopsis:
1272*8d031ccaSJunchao Zhang   #include <petscmacros.h>
1273*8d031ccaSJunchao Zhang   int PetscPragmaUseOMPKernels(name)
1274*8d031ccaSJunchao Zhang 
1275*8d031ccaSJunchao Zhang   No Fortran Support
1276*8d031ccaSJunchao Zhang 
1277*8d031ccaSJunchao Zhang   Input Parameter:
1278*8d031ccaSJunchao Zhang . name - the OpenMP pragma, for example, `critical` or `parallel for`
1279*8d031ccaSJunchao Zhang 
1280*8d031ccaSJunchao Zhang   Level: intermediate
1281*8d031ccaSJunchao Zhang 
1282*8d031ccaSJunchao Zhang   Note:
1283*8d031ccaSJunchao Zhang   The pragma takes effect when PETSc was configured with `--with-openmp-kernels`. See `PetscPragmaOMP()`
1284*8d031ccaSJunchao Zhang   for when PETSc was configured with OpenMP but not to use it in its numerical kernels
1285*8d031ccaSJunchao Zhang 
1286*8d031ccaSJunchao Zhang .seealso: `PetscPragmaOMP()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1287*8d031ccaSJunchao Zhang `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1288*8d031ccaSJunchao Zhang M*/
1289*8d031ccaSJunchao Zhang #if defined(PETSC_USE_OPENMP_KERNELS)
1290*8d031ccaSJunchao Zhang   #if defined(_MSC_VER)
1291*8d031ccaSJunchao Zhang     #define PetscPragmaUseOMPKernels(...) __pragma(__VA_ARGS__)
1292*8d031ccaSJunchao Zhang   #else
1293*8d031ccaSJunchao Zhang     #define PetscPragmaUseOMPKernels(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1294*8d031ccaSJunchao Zhang   #endif
1295*8d031ccaSJunchao Zhang #else
1296*8d031ccaSJunchao Zhang   #define PetscPragmaUseOMPKernels(...)
12972e327cfbSJacob Faibussowitsch #endif
12982e327cfbSJacob Faibussowitsch 
12992e327cfbSJacob Faibussowitsch /* PetscPragmaSIMD - from CeedPragmaSIMD */
13002e327cfbSJacob Faibussowitsch #if defined(__NEC__)
13012e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
13022e327cfbSJacob Faibussowitsch #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
13032e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD _Pragma("vector")
13042e327cfbSJacob Faibussowitsch #elif defined(__GNUC__)
13052e327cfbSJacob Faibussowitsch   #if __GNUC__ >= 5 && !defined(__PGI)
13062e327cfbSJacob Faibussowitsch     #define PetscPragmaSIMD _Pragma("GCC ivdep")
13072e327cfbSJacob Faibussowitsch   #endif
13082e327cfbSJacob Faibussowitsch #elif defined(_OPENMP) && _OPENMP >= 201307
13092e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD PetscPragmaOMP(simd)
13102e327cfbSJacob Faibussowitsch #elif defined(PETSC_HAVE_CRAY_VECTOR)
13112e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
13122e327cfbSJacob Faibussowitsch #endif
13132e327cfbSJacob Faibussowitsch 
13142e327cfbSJacob Faibussowitsch #ifndef PetscPragmaSIMD
13152e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD
13162e327cfbSJacob Faibussowitsch #endif
13172e327cfbSJacob Faibussowitsch 
13185029be03SJacob Faibussowitsch #include <petsc/private/petscadvancedmacros.h>
13195029be03SJacob Faibussowitsch 
13205029be03SJacob Faibussowitsch #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
13215029be03SJacob Faibussowitsch #define PetscConcat6(a, b, c, d, e, f)  PetscConcat6_(a, b, c, d, e, f)
13225029be03SJacob Faibussowitsch 
13235029be03SJacob Faibussowitsch #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
13245029be03SJacob Faibussowitsch   PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
132558cbeaadSJacob Faibussowitsch                       __PETSC_DEPRECATION_MACRO__)(PetscStringize(Use replacement (since version major.minor.subminor) instead. Silence this warning (as well as all others for this version) by defining PetscConcat_(PETSC_, __SILENCE_MACRO__). __VA_ARGS__))
13265029be03SJacob Faibussowitsch 
13275029be03SJacob Faibussowitsch #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
13285029be03SJacob Faibussowitsch   PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)
13295029be03SJacob Faibussowitsch 
1330a14d4ff0SToby Isaac #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...)   PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1331edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1332edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1333edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1334edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1335