Actual source code: petscmacros.h
1: #pragma once
3: #include <petscconf.h>
4: #include <petscconf_poison.h> /* for PetscDefined() error checking */
6: /* SUBMANSEC = Sys */
8: #if defined(__cplusplus)
9: #if __cplusplus <= 201103L
10: #define PETSC_CPP_VERSION 11
11: #elif __cplusplus <= 201402L
12: #define PETSC_CPP_VERSION 14
13: #elif __cplusplus <= 201703L
14: #define PETSC_CPP_VERSION 17
15: #elif __cplusplus <= 202002L
16: #define PETSC_CPP_VERSION 20
17: #else
18: #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
19: #endif
20: #endif // __cplusplus
22: #if !defined(PETSC_CPP_VERSION)
23: #define PETSC_CPP_VERSION 0
24: #endif
26: #if defined(__STDC_VERSION__)
27: #if __STDC_VERSION__ <= 199901L
28: // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
29: #define PETSC_C_VERSION 9
30: #elif __STDC_VERSION__ <= 201112L
31: #define PETSC_C_VERSION 11
32: #elif __STDC_VERSION__ <= 201710L
33: #define PETSC_C_VERSION 17
34: #else
35: #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
36: #endif
37: #endif // __STDC_VERSION__
39: #if !defined(PETSC_C_VERSION)
40: #define PETSC_C_VERSION 0
41: #endif
43: /* ========================================================================== */
44: /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
45: #if defined(__cplusplus)
46: #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
47: #else
48: #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
49: #endif
51: /* ========================================================================== */
52: /* Since PETSc manages its own extern "C" handling users should never include PETSc include
53: * files within extern "C". This will generate a compiler error if a user does put the include
54: * file within an extern "C".
55: */
56: #if defined(__cplusplus)
57: void assert_never_put_petsc_headers_inside_an_extern_c(int);
58: void assert_never_put_petsc_headers_inside_an_extern_c(double);
59: #endif
61: #if defined(__cplusplus)
62: #define PETSC_RESTRICT PETSC_CXX_RESTRICT
63: #else
64: #define PETSC_RESTRICT restrict
65: #endif
67: #define PETSC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "inline", ) inline
68: #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "static inline", ) static inline
70: #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
71: #define __declspec(dllexport)
72: #define PETSC_DLLIMPORT __declspec(dllimport)
73: #define PETSC_VISIBILITY_INTERNAL
74: #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
75: #define __attribute__((visibility("default")))
76: #define PETSC_DLLIMPORT __attribute__((visibility("default")))
77: #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
78: #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
79: #define __attribute__((visibility("default")))
80: #define PETSC_DLLIMPORT __attribute__((visibility("default")))
81: #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
82: #else
83: #define
84: #define PETSC_DLLIMPORT
85: #define PETSC_VISIBILITY_INTERNAL
86: #endif
88: #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
89: #define PETSC_VISIBILITY_PUBLIC
90: #else /* Win32 users need this to import symbols from petsc.dll */
91: #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
92: #endif
94: /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
95: * compiled with C++ so they may be used from C and are always visible in the shared libraries
96: */
97: #if defined(__cplusplus)
98: #define PETSC_EXTERN extern "C" PETSC_VISIBILITY_PUBLIC
99: #define PETSC_EXTERN_TYPEDEF extern "C"
100: #define PETSC_INTERN extern "C" PETSC_VISIBILITY_INTERNAL
101: #else
102: #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
103: #define PETSC_EXTERN_TYPEDEF
104: #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
105: #endif
107: #if defined(PETSC_USE_SINGLE_LIBRARY)
108: #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_INTERNAL
109: #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
110: #else
111: #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_PUBLIC
112: #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
113: #endif
117: #endif
121: #endif
123: /*MC
124: PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
126: Synopsis:
127: #include <petscmacros.h>
128: int PetscHasAttribute(name)
130: Input Parameter:
131: . name - The name of the attribute to test
133: Level: intermediate
135: Notes:
136: name should be identical to what you might pass to the __attribute__ declaration itself --
137: plain, unbroken text.
139: As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
140: exact type and value returned is implementation defined. In practice however, it usually
141: returns `1` if the attribute is supported and `0` if the attribute is not supported.
143: Example Usage:
144: Typical usage is using the preprocessor
146: .vb
147: #if PetscHasAttribute(always_inline)
148: # define MY_ALWAYS_INLINE __attribute__((always_inline))
149: #else
150: # define MY_ALWAYS_INLINE
151: #endif
153: void foo(void) MY_ALWAYS_INLINE;
154: .ve
156: but it can also be used in regular code
158: .vb
159: if (PetscHasAttribute(some_attribute)) {
160: foo();
161: } else {
162: bar();
163: }
164: .ve
166: .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
167: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
168: M*/
169: #define PetscHasAttribute(name) __has_attribute(name)
173: #endif
175: /*MC
176: PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
178: Synopsis:
179: #include <petscmacros.h>
180: int PetscHasBuiltin(name)
182: Input Parameter:
183: . name - the name of the builtin routine
185: Level: intermediate
187: Notes:
188: Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
189: (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
190: detector is itself is a compiler extension with implementation-defined return type and
191: semantics. Some compilers implement it as a macro, others as a compiler function. In practice
192: however, all supporting compilers return an integer boolean as described.
194: Example Usage:
195: Typical usage is in preprocessor directives
197: .vb
198: #if PetscHasBuiltin(__builtin_trap)
199: __builtin_trap();
200: #else
201: abort();
202: #endif
203: .ve
205: But it may also be used in regular code
207: .vb
208: if (PetscHasBuiltin(__builtin_alloca)) {
209: foo();
210: } else {
211: bar();
212: }
213: .ve
215: Developer Note:
216: Clang's `__has_builtin()` prior to Clang 10 did not properly handle non-function builtins such as
217: `__builtin_types_compatible_p()` which take types or other non-functiony things as
218: arguments. The correct way to detect these then is to use `__is_identifier()` (also a Clang
219: extension). GCC has always worked as expected. See https://stackoverflow.com/a/45043153
221: .seealso: `PetscHasAttribute()`, `PetscAssume()`
222: M*/
223: #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
224: #define PetscHasBuiltin(name) __is_identifier(name)
225: #else
226: #define PetscHasBuiltin(name) __has_builtin(name)
227: #endif
229: #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
230: /*
231: Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
232: This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
233: does not match the actual type of the argument being passed in
234: */
235: #if PetscHasAttribute(pointer_with_type_tag)
236: #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
237: #endif
239: #if PetscHasAttribute(type_tag_for_datatype)
240: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type) __attribute__((type_tag_for_datatype(MPI, type)))
241: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
242: #endif
243: #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
245: #if !defined(PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE)
246: #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
247: #endif
249: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG)
250: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
251: #endif
253: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE)
254: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
255: #endif
257: /*MC
258: PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
259: as format specifiers and checked for validity
261: Synopsis:
262: #include <petscmacros.h>
263: <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
265: Input Parameters:
266: + strIdx - The (1-indexed) location of the format string in the argument list
267: - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
269: Level: developer
271: Notes:
272: This function attribute causes the compiler to issue warnings when the format specifier does
273: not match the type of the variable that will be formatted, or when there exists a mismatch
274: between the number of format specifiers and variables to be formatted. It is safe to use this
275: macro if your compiler does not support format specifier checking (though this is
276: exceeedingly rare).
278: Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
279: same value.
281: The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
282: the argument list, that is, there is no way to indicate gaps which should not be checked.
284: Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
285: header files. In this case the macro will expand empty.
287: Example Usage:
288: .vb
289: // format string is 2nd argument, variable argument list containing args is 3rd argument
290: void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
292: int x = 1;
293: double y = 50.0;
295: my_printf(NULL,"%g",x); // WARNING, format specifier does not match for 'int'!
296: my_printf(NULL,"%d",x,y); // WARNING, more arguments than format specifiers!
297: my_printf(NULL,"%d %g",x,y); // OK
298: .ve
300: .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
301: M*/
302: #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
303: #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
304: #else
305: #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
306: #endif
308: /*MC
309: PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
310: executed
312: Level: intermediate
314: Notes:
315: The marked function is often optimized for size rather than speed and may be grouped alongside
316: other equally frigid routines improving code locality of lukewarm or hotter parts of program.
318: The paths leading to cold functions are usually automatically marked as unlikely by the
319: compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
320: as error handlers -- as cold to improve optimization of the surrounding temperate functions.
322: Example Usage:
323: .vb
324: void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
326: if (temperature < 0) {
327: return my_error_handler(...); // chilly!
328: }
329: .ve
331: .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
332: `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
333: M*/
334: #if PetscHasAttribute(__cold__)
335: #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
336: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
337: #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
338: #else
339: #define PETSC_ATTRIBUTE_COLD
340: #endif
342: /*MC
343: PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
344: subjected to type-based alias analysis, but is instead assumed to be able to
345: alias any other type of objects
347: Example Usage:
348: .vb
349: typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;
351: PetscReal *pointer;
352: PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
353: .ve
355: Level: advanced
357: .seealso: `PetscHasAttribute()`
358: M*/
359: #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
360: #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
361: #else
362: #define PETSC_ATTRIBUTE_MAY_ALIAS
363: #endif
365: /*MC
366: PETSC_NULLPTR - Standard way of indicating a null value or pointer
368: No Fortran Support
370: Level: beginner
372: Notes:
373: Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
374: interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
375: equivalent to setting the same pointer to `NULL` in C. That is to say that the following
376: expressions are equivalent\:
378: .vb
379: ptr == PETSC_NULLPTR
380: ptr == NULL
381: ptr == 0
382: !ptr
384: ptr = PETSC_NULLPTR
385: ptr = NULL
386: ptr = 0
387: .ve
389: and for completeness' sake\:
391: .vb
392: PETSC_NULLPTR == NULL
393: .ve
395: Example Usage:
396: .vb
397: // may be used in place of '\0' or other such terminators in the definition of char arrays
398: const char *const MyEnumTypes[] = {
399: "foo",
400: "bar",
401: PETSC_NULLPTR
402: };
404: // may be used to nullify objects
405: PetscObject obj = PETSC_NULLPTR;
407: // may be used in any function expecting NULL
408: PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
409: .ve
411: Developer Notes:
412: `PETSC_NULLPTR` must be used in place of `NULL` in all C++ source files. Using `NULL` in source
413: files compiled with a C++ compiler may lead to unexpected side-effects in function overload
414: resolution and/or compiler warnings.
416: .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
417: M*/
419: /*MC
420: PETSC_CONSTEXPR_14 - C++14 constexpr
422: No Fortran Support
424: Level: beginner
426: Notes:
427: Equivalent to `constexpr` when using a C++ compiler that supports C++14. Expands to nothing
428: if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
429: that this cannot be used in cases where an empty expansion would result in invalid code. It
430: is safe to use this in C source files.
432: Example Usage:
433: .vb
434: PETSC_CONSTEXPR_14 int factorial(int n)
435: {
436: int r = 1;
438: do {
439: r *= n;
440: } while (--n);
441: return r;
442: }
443: .ve
445: .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
446: M*/
448: /*MC
449: PETSC_NODISCARD - Mark the return value of a function as non-discardable
451: Not available in Fortran
453: Level: beginner
455: Notes:
456: Hints to the compiler that the return value of a function must be captured. A diagnostic may
457: (but is not required to) be emitted if the value is discarded. It is safe to use this in both
458: C and C++ source files.
460: In this context "captured" means assigning the return value of a function to a named
461: variable or casting it to `void`. Between the two, assigning to a named variable is the most
462: portable way of silencing any warnings, since `PETSC_NODISCARD` may expand to GCC's
463: `__attribute__((warn_unused_result))` which will still emit warnings when casting results to
464: `void`.
466: Example Usage:
467: .vb
468: class Foo
469: {
470: int x;
472: public:
473: PETSC_NODISCARD Foo(int y) : x(y) { }
474: };
476: PETSC_NODISCARD int factorial(int n)
477: {
478: return n <= 1 ? 1 : (n * factorial(n - 1));
479: }
481: factorial(10); // Warning: ignoring return value of function declared 'nodiscard'
482: auto x = factorial(10); // OK, capturing return value
483: (void)factorial(10); // Maybe OK, casting to void
484: auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
485: (void)y; // set-but-not-used warnings)
487: Foo(x); // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
488: auto f = Foo(x); // OK, capturing constructed object
489: (void)Foo(x); // Maybe OK, casting to void
490: auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
491: (void)g; // warnings)
492: .ve
494: .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
495: M*/
497: /* C++11 features */
498: #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
499: #define PETSC_NULLPTR nullptr
500: #else
501: #define PETSC_NULLPTR NULL
502: #endif
504: /* C++14 features */
505: #if PETSC_CPP_VERSION >= 14
506: #define PETSC_CONSTEXPR_14 constexpr
507: #else
508: #define PETSC_CONSTEXPR_14
509: #endif
511: /* C++17 features */
512: #if PETSC_CPP_VERSION >= 17
513: #define PETSC_CONSTEXPR_17 constexpr
514: #else
515: #define PETSC_CONSTEXPR_17
516: #endif
518: #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
519: #define PETSC_NODISCARD [[nodiscard]]
520: #elif PetscHasAttribute(warn_unused_result)
521: #define PETSC_NODISCARD __attribute__((warn_unused_result))
522: #else
523: #define PETSC_NODISCARD
524: #endif
526: #include <petscversion.h>
527: #define PETSC_AUTHOR_INFO " The PETSc Team\n petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
529: /* designated initializers since C99 and C++20, MSVC never supports them though */
530: #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
531: #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
532: #else
533: #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
534: #endif
536: /*MC
537: PetscUnlikely - Hints the compiler that the given condition is usually false
539: Synopsis:
540: #include <petscmacros.h>
541: bool PetscUnlikely(bool cond)
543: Not Collective; No Fortran Support
545: Input Parameter:
546: . cond - Boolean expression
548: Level: advanced
550: Note:
551: This returns the same truth value, it is only a hint to compilers that the result of cond is
552: unlikely to be true.
554: Example usage:
555: .vb
556: if (PetscUnlikely(cond)) {
557: foo(); // cold path
558: } else {
559: bar(); // hot path
560: }
561: .ve
563: .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
564: `PETSC_ATTRIBUTE_COLD`
565: M*/
566: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
567: #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
568: #else
569: #define PetscUnlikely(cond) (cond)
570: #endif
572: /*MC
573: PetscLikely - Hints the compiler that the given condition is usually true
575: Synopsis:
576: #include <petscmacros.h>
577: bool PetscLikely(bool cond)
579: Not Collective; No Fortran Support
581: Input Parameter:
582: . cond - Boolean expression
584: Level: advanced
586: Note:
587: This returns the same truth value, it is only a hint to compilers that the result of cond is
588: likely to be true.
590: Example usage:
591: .vb
592: if (PetscLikely(cond)) {
593: foo(); // hot path
594: } else {
595: bar(); // cold path
596: }
597: .ve
599: .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`, `PETSC_ATTRIBUTE_COLD`
600: M*/
601: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
602: #define PetscLikely(cond) __builtin_expect(!!(cond), 1)
603: #else
604: #define PetscLikely(cond) (cond)
605: #endif
607: /*MC
608: PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
610: Synopsis:
611: #include <petscmacros.h>
612: void PetscUnreachable(void)
614: Level: advanced
616: Note:
617: Indicates to the compiler (usually via some built-in) that a particular code path is always
618: unreachable. Behavior is undefined if this function is ever executed, the user can expect an
619: unceremonious crash.
621: Example usage:
622: Useful in situations such as switches over enums where not all enumeration values are
623: explicitly covered by the switch
625: .vb
627: int foo(Color c)
628: {
629: // it is known to programmer (or checked previously) that c is either RED or GREEN
630: // but compiler may not be able to deduce this and/or emit spurious warnings
631: switch (c) {
632: case RED:
633: return bar();
634: case GREEN:
635: return baz();
636: default:
637: PetscUnreachable(); // program is ill-formed if executed
638: }
639: }
640: .ve
642: .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
643: M*/
644: #if PETSC_CPP_VERSION >= 23
645: #include <utility>
646: #define PetscUnreachable() std::unreachable()
647: #elif defined(__GNUC__)
648: /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
649: #define PetscUnreachable() __builtin_unreachable()
650: #elif defined(_MSC_VER) /* MSVC */
651: #define PetscUnreachable() __assume(0)
652: #else /* ??? */
653: #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
654: #endif
656: /*MC
657: PetscAssume - Indicate to the compiler a condition that is defined to be true
659: Synopsis:
660: #include <petscmacros.h>
661: void PetscAssume(bool cond)
663: Input Parameter:
664: . cond - Boolean expression
666: Level: advanced
668: Notes:
669: If supported by the compiler, `cond` is used to inform the optimizer of an invariant
670: truth. The argument itself is never evaluated, so any side effects of the expression will be
671: discarded. This macro is used in `PetscAssert()` to retain information gained from debug
672: checks that would be lost in optimized builds. For example\:
674: .vb
675: PetscErrorCode foo(PetscInt x) {
677: PetscAssert(x >= 0, ...);
678: }
679: .ve
681: The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
682: if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
683: when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
684: optimizer cannot deduce any information from them.
686: Due to compiler limitations `PetscAssume()` works best when `cond` involves
687: constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
689: .vb
690: int a, b, var_five;
692: // BEST, all supporting compilers will understand a cannot be >= 5
693: PetscAssume(a < 5);
695: // OK, some compilers may understand that a cannot be >= 5
696: PetscAssume(a <= b && b < 5);
698: // WORST, most compilers will not get the memo
699: PetscAssume(a <= b && b < var_five);
700: .ve
702: If the condition is violated at runtime then behavior is wholly undefined. If the
703: condition is violated at compile-time, the condition "supersedes" the compile-time violation
704: and the program is ill-formed, no diagnostic required. For example consider the following\:
706: .vb
707: PetscInt x = 0;
709: PetscAssume(x != 0);
710: if (x == 0) {
711: x += 10;
712: } else {
713: popen("rm -rf /", "w");
714: }
715: .ve
717: Even though `x` is demonstrably `0` the compiler may opt to\:
719: - emit an unconditional `popen("rm -rf /", "w")`
720: - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
721: - reformat the primary disk partition
723: .seealso: `PetscAssert()`
724: M*/
725: #if PETSC_CPP_VERSION >= 23
726: #define PetscAssume(...) [[assume(__VA_ARGS__)]]
727: #elif defined(_MSC_VER) // msvc
728: #define PetscAssume(...) __assume(__VA_ARGS__)
729: #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
730: #define PetscAssume(...) \
731: do { \
732: _Pragma("clang diagnostic push"); \
733: _Pragma("clang diagnostic ignored \"-Wassume\""); \
734: __builtin_assume(__VA_ARGS__); \
735: _Pragma("clang diagnostic pop"); \
736: } while (0)
737: #else // gcc (and really old clang)
738: // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
739: //
740: // if (PetscUnlikely(!cond)) PetscUnreachable();
741: //
742: // but this it unsavory because the side effects of cond are not guaranteed to be
743: // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
744: // for which cond is false would be undefined results in undefined behavior anyway) it cannot
745: // always do so. This is especially the case for opaque or non-inline function calls:
746: //
747: // extern int bar(int);
748: //
749: // int foo(int x) {
750: // PetscAssume(bar(x) == 2);
751: // if (bar(x) == 2) {
752: // return 1;
753: // } else {
754: // return 0;
755: // }
756: // }
757: //
758: // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
759: // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
760: #define PetscAssume(...) \
761: do { \
762: if (0 && (__VA_ARGS__)) PetscUnreachable(); \
763: } while (0)
764: #endif
766: /*MC
767: PetscExpand - Expand macro argument
769: Synopsis:
770: #include <petscmacros.h>
771: <macro-expansion> PetscExpand(x)
773: Input Parameter:
774: . x - The preprocessor token to expand
776: Level: beginner
778: .seealso: `PetscStringize()`, `PetscConcat()`
779: M*/
780: #define PetscExpand_(...) __VA_ARGS__
781: #define PetscExpand(...) PetscExpand_(__VA_ARGS__)
783: /*MC
784: PetscStringize - Stringize a token
786: Synopsis:
787: #include <petscmacros.h>
788: const char* PetscStringize(x)
790: No Fortran Support
792: Input Parameter:
793: . x - The token you would like to stringize
795: Output Parameter:
796: . <return-value> - The string representation of `x`
798: Level: beginner
800: Note:
801: `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
802: `PetscStringize_()` instead.
804: Example Usage:
805: .vb
806: #define MY_OTHER_VAR hello there
807: #define MY_VAR MY_OTHER_VAR
809: PetscStringize(MY_VAR) -> "hello there"
810: PetscStringize_(MY_VAR) -> "MY_VAR"
812: int foo;
813: PetscStringize(foo) -> "foo"
814: PetscStringize_(foo) -> "foo"
815: .ve
817: .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
818: M*/
819: #define PetscStringize_(...) #__VA_ARGS__
820: #define PetscStringize(...) PetscStringize_(__VA_ARGS__)
822: /*MC
823: PetscConcat - Concatenate two tokens
825: Synopsis:
826: #include <petscmacros.h>
827: <macro-expansion> PetscConcat(x, y)
829: No Fortran Support
831: Input Parameters:
832: + x - First token
833: - y - Second token
835: Level: beginner
837: Note:
838: `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
839: if you don't want to expand them.
841: Example usage:
842: .vb
843: PetscConcat(hello,there) -> hellothere
845: #define HELLO hello
846: PetscConcat(HELLO,there) -> hellothere
847: PetscConcat_(HELLO,there) -> HELLOthere
848: .ve
850: .seealso: `PetscStringize()`, `PetscExpand()`
851: M*/
852: #define PetscConcat_(x, y) x##y
853: #define PetscConcat(x, y) PetscConcat_(x, y)
855: #define PETSC_INTERNAL_COMPL_0 1
856: #define PETSC_INTERNAL_COMPL_1 0
858: /*MC
859: PetscCompl - Expands to the integer complement of its argument
861: Synopsis:
862: #include <petscmacros.h>
863: int PetscCompl(b)
865: No Fortran Support
867: Input Parameter:
868: . b - Preprocessor variable, must expand to either integer literal 0 or 1
870: Output Parameter:
871: . <return-value> - Either integer literal 0 or 1
873: Level: beginner
875: Notes:
876: Expands to integer literal 0 if `b` expands to 1, or integer literal 1 if `b` expands to
877: 0. Behavior is undefined if `b` expands to anything else. `PetscCompl()` will expand its
878: argument before returning the complement.
880: This macro can be useful for negating `PetscDefined()` inside macros e.g.
881: .vb
882: #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
883: .ve
885: Example usage:
886: .vb
887: #define MY_VAR 1
888: PetscCompl(MY_VAR) -> 0
890: #undef MY_VAR
891: #define MY_VAR 0
892: PetscCompl(MY_VAR) -> 1
893: .ve
895: .seealso: `PetscConcat()`, `PetscDefined()`
896: M*/
897: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
899: #define PetscDefined_arg_1 shift,
900: #define PetscDefined_arg_ shift,
901: #define PetscDefined__take_second_expanded(ignored, val, ...) val
902: #define PetscDefined__take_second_expand(args) PetscDefined__take_second_expanded args
903: #define PetscDefined__take_second(...) PetscDefined__take_second_expand((__VA_ARGS__))
904: #define PetscDefined__(arg1_or_junk) PetscDefined__take_second(arg1_or_junk 1, 0, at_)
905: #define PetscDefined_(value) PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
907: /*MC
908: PetscDefined - Determine whether a boolean macro is defined
910: Synopsis:
911: #include <petscmacros.h>
912: int PetscDefined(def)
914: No Fortran Support
916: Input Parameter:
917: . def - PETSc-style preprocessor variable (without `PETSC_` prepended!)
919: Output Parameter:
920: . <return-value> - Either integer literal 0 or 1
922: Level: intermediate
924: Notes:
925: `PetscDefined()` returns 1 if and only if `PETSC_ ## def` is defined (but empty) or defined to
926: integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
927: this macro should not be used if its argument may be defined to a non-empty value other than
928: 1.
930: The prefix `PETSC_` is automatically prepended to `def`, which is treated as a literal suffix
931: and is not macro-expanded. To avoid prepending `PETSC_`, say to add custom checks in user code,
932: one should use `PetscDefined_()`.
933: .vb
934: #define FooDefined(d) PetscDefined_(FOO_##d)
935: .ve
937: Developer Notes:
938: Getting something that works in C and CPP for an arg that may or may not be defined is
939: tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
940: insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
941: the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
942: and when the last step cherry picks the 2nd arg, we get a zero.
944: Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
945: nonconforming implementation of variadic macros. The `PETSC_` prefix must be pasted in
946: `PetscDefined()` itself so that an unprefixed macro matching `def` cannot expand before the
947: prefix is added.
949: Example Usage:
950: Suppose you would like to call either `foo()` or `bar()` depending on whether `PETSC_USE_DEBUG`
951: is defined then
953: .vb
954: #if PetscDefined(USE_DEBUG)
955: foo();
956: #else
957: bar();
958: #endif
960: // or alternatively within normal code
961: if (PetscDefined(USE_DEBUG)) {
962: foo();
963: } else {
964: bar();
965: }
966: .ve
968: is equivalent to
970: .vb
971: #if defined(PETSC_USE_DEBUG)
972: # if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
973: foo();
974: # elif PETSC_USE_DEBUG == 1
975: foo();
976: # else
977: bar();
978: # endif
979: #else
980: bar();
981: #endif
982: .ve
984: .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
985: `PetscExpandToNothing()`, `PetscCompl()`
986: M*/
987: #define PetscDefined(def) PetscDefined_(PETSC_##def)
989: /*MC
990: PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
991: the check in optimized mode
993: Synopsis:
994: #include <petscmacros.h>
995: bool PetscUnlikelyDebug(bool cond)
997: Not Collective; No Fortran Support
999: Input Parameter:
1000: . cond - Boolean expression
1002: Level: advanced
1004: Note:
1005: This returns the same truth value, it is only a hint to compilers that the result of `cond` is
1006: likely to be false. When PETSc is compiled in optimized mode this will always return
1007: false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
1008: optimized mode.
1010: Example usage:
1011: This routine is shorthand for checking both the condition and whether `PetscDefined(USE_DEBUG)`
1012: is true. So
1014: .vb
1015: if (PetscUnlikelyDebug(cond)) {
1016: foo();
1017: } else {
1018: bar();
1019: }
1020: .ve
1022: is equivalent to
1024: .vb
1025: if (PetscDefined(USE_DEBUG)) {
1026: if (PetscUnlikely(cond)) {
1027: foo();
1028: } else {
1029: bar();
1030: }
1031: } else {
1032: bar();
1033: }
1034: .ve
1036: .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1037: M*/
1038: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1040: #if defined(PETSC_CLANG_STATIC_ANALYZER)
1041: // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1042: // not what ISO C allows
1043: #define PetscMacroReturns_(retexpr, ...) \
1044: __extension__({ \
1045: __VA_ARGS__; \
1046: retexpr; \
1047: })
1048: #else
1049: #define PetscMacroReturns_(retexpr, ...) \
1050: retexpr; \
1051: do { \
1052: __VA_ARGS__; \
1053: } while (0)
1054: #endif
1056: /*MC
1057: PetscExpandToNothing - Expands to absolutely nothing
1059: Synopsis:
1060: #include <petscmacros.h>
1061: void PetscExpandToNothing(...)
1063: No Fortran Support
1065: Input Parameter:
1066: . __VA_ARGS__ - Anything at all
1068: Level: beginner
1070: Note:
1071: Must have at least 1 parameter.
1073: Example usage:
1074: .vb
1075: PetscExpandToNothing(a,b,c) -> *nothing*
1076: .ve
1078: .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1079: M*/
1080: #define PetscExpandToNothing(...)
1082: /*MC
1083: PetscMacroReturns - Define a macro body that returns a value
1085: Synopsis:
1086: #include <petscmacros.h>
1087: return_type PetscMacroReturns(return_type retexpr, ...)
1089: Input Parameters:
1090: + retexpr - The value or expression that the macro should return
1091: - __VA_ARGS__ - The body of the macro
1093: Level: intermediate
1095: Notes:
1096: Due to limitations of the C-preprocessor `retexpr` cannot depend on symbols declared in the
1097: body of the macro and should not depend on values produced as a result of the expression. The
1098: user should not assume that the result of this macro is equivalent to a single logical source
1099: line. It is not portable to use macros defined using this one in conditional or loop bodies
1100: without enclosing them in curly braces\:
1102: .vb
1103: #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1105: int err,x = 10;
1107: if (...) err = FOO(x); // ERROR, body of FOO() executed outside the if statement
1108: if (...) { err = FOO(x); } // OK
1110: for (...) err = FOO(x); // ERROR, body of FOO() executed outside the loop
1111: for (...) { err = FOO(x); } // OK
1112: .ve
1114: It is also not portable to use this macro directly inside function call, conditional, loop,
1115: or switch statements\:
1117: .vb
1118: extern void bar(int);
1120: int ret = FOO(x);
1122: bar(FOO(x)); // ERROR, may not compile
1123: bar(ret); // OK
1125: if (FOO(x)) // ERROR, may not compile
1126: if (ret) // OK
1127: .ve
1129: Example usage:
1130: .vb
1131: #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1133: int x = 10;
1134: int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1136: // multiline macros allowed, but must declare with line continuation as usual
1137: #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1138: if (arg1 > 10) { \
1139: puts("big int!"); \
1140: } else { \
1141: return 7355608; \
1142: } \
1143: )
1145: // if retexpr contains commas, must enclose it with braces
1146: #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1147: #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1149: int x = 10;
1150: int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1151: int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1152: .ve
1154: .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1155: M*/
1156: #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1158: #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)
1160: /*MC
1161: PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1163: Synopsis:
1164: #include <petscmacros.h>
1165: size_t PETSC_STATIC_ARRAY_LENGTH(a)
1167: Input Parameter:
1168: . a - a static array of any type
1170: Output Parameter:
1171: . <return-value> - the length of the array
1173: Example:
1174: .vb
1175: PetscInt a[22];
1176: size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
1177: .ve
1178: `sa` will have a value of 22
1180: Level: intermediate
1181: M*/
1182: #if PETSC_CPP_VERSION >= 14
1183: #include <cstddef>
1184: #include <type_traits>
1186: template <typename T>
1187: static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
1188: {
1189: static_assert(std::is_array<T>::value, "");
1190: return std::extent<T, std::rank<T>::value - 1>::value;
1191: }
1192: #else
1193: #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
1194: #endif
1196: /*
1197: These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1199: Example usage:
1201: #define mymacro(obj,...) {
1202: PETSC_FIRST_ARG((__VA_ARGS__,unused));
1203: f(22 PETSC_REST_ARG(__VA_ARGS__));
1204: }
1206: 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
1208: Reference:
1209: https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1210: */
1211: #define PETSC_FIRST_ARG_(N, ...) N
1212: #define PETSC_FIRST_ARG(args) PETSC_FIRST_ARG_ args
1213: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1214: #define PETSC_NUM(...) PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1215: #define PETSC_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
1216: #define PETSC_REST_HELPER_ONE(first)
1217: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1218: #define PETSC_REST_HELPER(qty, ...) PETSC_REST_HELPER2(qty, __VA_ARGS__)
1219: #define PETSC_REST_ARG(...) PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1221: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1222: _Pragma(PetscStringize(name diagnostic push)) \
1223: _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))
1225: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))
1227: #if defined(__clang__)
1228: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1229: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1230: #elif defined(__GNUC__) || defined(__GNUG__)
1231: // gcc >= 4.6.0
1232: #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1233: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1234: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1235: #endif
1236: #endif
1238: #if !defined(PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN)
1239: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1240: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1241: // only undefine these if they are not used
1242: #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1243: #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1244: #endif
1246: /*MC
1247: PetscPragmaOMP - Sets an OpenMP pragma to affect the next block of code
1249: Synopsis:
1250: #include <petscmacros.h>
1251: int PetscPragmaOMP(name)
1253: No Fortran Support
1255: Input Parameter:
1256: . name - the OpenMP pragma, for example, `critical` or `parallel for`
1258: Level: intermediate
1260: Note:
1261: The pragma takes effect when PETSc was configured with `--with-openmp`. See `PetscPragmaUseOMPKernels()`
1262: for when PETSc was configured to use OpenMP in some of its numerical kernels.
1264: .seealso: `PetscPragmaUseOMPKernels()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1265: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1266: M*/
1267: #if defined(_OPENMP)
1268: #if defined(_MSC_VER)
1269: #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1270: #else
1271: #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1272: #endif
1273: #else
1274: #define PetscPragmaOMP(...)
1275: #endif
1277: /*MC
1278: PetscPragmaUseOMPKernels - Sets an OpenMP pragma to affect the next block of code
1280: Synopsis:
1281: #include <petscmacros.h>
1282: int PetscPragmaUseOMPKernels(name)
1284: No Fortran Support
1286: Input Parameter:
1287: . name - the OpenMP pragma, for example, `critical` or `parallel for`
1289: Level: intermediate
1291: Note:
1292: The pragma takes effect when PETSc was configured with `--with-openmp-kernels`. See `PetscPragmaOMP()`
1293: for when PETSc was configured with OpenMP but not to use it in its numerical kernels
1295: .seealso: `PetscPragmaOMP()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1296: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1297: M*/
1298: #if defined(PETSC_USE_OPENMP_KERNELS)
1299: #if defined(_MSC_VER)
1300: #define PetscPragmaUseOMPKernels(...) __pragma(__VA_ARGS__)
1301: #else
1302: #define PetscPragmaUseOMPKernels(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1303: #endif
1304: #else
1305: #define PetscPragmaUseOMPKernels(...)
1306: #endif
1308: /* PetscPragmaSIMD - from CeedPragmaSIMD */
1309: #if defined(__NEC__)
1310: #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1311: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1312: #define PetscPragmaSIMD _Pragma("vector")
1313: #elif defined(__GNUC__)
1314: #if __GNUC__ >= 5 && !defined(__PGI)
1315: #define PetscPragmaSIMD _Pragma("GCC ivdep")
1316: #endif
1317: #elif defined(_OPENMP) && _OPENMP >= 201307
1318: #define PetscPragmaSIMD PetscPragmaOMP(simd)
1319: #elif defined(PETSC_HAVE_CRAY_VECTOR)
1320: #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1321: #endif
1323: #if !defined(PetscPragmaSIMD)
1324: #define PetscPragmaSIMD
1325: #endif
1327: #include <petsc/private/petscadvancedmacros.h>
1329: #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
1331: /*MC
1332: PetscConcat6 - Concatenate six preprocessor tokens after expansion
1334: Synopsis:
1335: #include <petscmacros.h>
1336: <macro-expansion> PetscConcat6(a, b, c, d, e, f)
1338: No Fortran Support
1340: Input Parameters:
1341: + a - first token
1342: . b - second token
1343: . c - third token
1344: . d - fourth token
1345: . e - fifth token
1346: - f - sixth token
1348: Level: developer
1350: Note:
1351: Like `PetscConcat()` but for six arguments. Used internally to build identifier names that mix several macro arguments, for example version-stamped silence macros for deprecation warnings.
1353: .seealso: `PetscConcat()`, `PetscStringize()`, `PetscExpand()`
1354: M*/
1355: #define PetscConcat6(a, b, c, d, e, f) PetscConcat6_(a, b, c, d, e, f)
1357: #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
1358: PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
1359: __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__))
1361: #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
1362: PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)
1364: #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1365: #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1366: #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1367: #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1368: #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)