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

119: /*MC
120:   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler

122:   Synopsis:
123: #include <petscmacros.h>
124:   int PetscHasAttribute(name)

126:   Input Parameter:
127: . name - The name of the attribute to test

129:   Level: intermediate

131:   Notes:
132:   name should be identical to what you might pass to the __attribute__ declaration itself --
133:   plain, unbroken text.

135:   As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
136:   exact type and value returned is implementation defined. In practice however, it usually
137:   returns `1` if the attribute is supported and `0` if the attribute is not supported.

139:   Example Usage:
140:   Typical usage is using the preprocessor

142: .vb
143:   #if PetscHasAttribute(always_inline)
144:   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
145:   #else
146:   #  define MY_ALWAYS_INLINE
147:   #endif

149:   void foo(void) MY_ALWAYS_INLINE;
150: .ve

152:   but it can also be used in regular code

154: .vb
155:   if (PetscHasAttribute(some_attribute)) {
156:     foo();
157:   } else {
158:     bar();
159:   }
160: .ve

162: .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
163: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
164: M*/
167: #endif
168: #define PetscHasAttribute(name) __has_attribute(name)

170: /*MC
171:   PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler

173:   Synopsis:
174: #include <petscmacros.h>
175:   int PetscHasBuiltin(name)

177:   Input Parameter:
178: . name - the name of the builtin routine

180:   Level: intermediate

182:   Notes:
183:   Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
184:   (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
185:   detector is itself is a compiler extension with implementation-defined return type and
186:   semantics. Some compilers implement it as a macro, others as a compiler function. In practice
187:   however, all supporting compilers return an integer boolean as described.

189:   Example Usage:
190:   Typical usage is in preprocessor directives

192: .vb
193:   #if PetscHasBuiltin(__builtin_trap)
194:   __builtin_trap();
195:   #else
196:   abort();
197:   #endif
198: .ve

200:   But it may also be used in regular code

202: .vb
203:   if (PetscHasBuiltin(__builtin_alloca)) {
204:     foo();
205:   } else {
206:     bar();
207:   }
208: .ve

210: .seealso: `PetscHasAttribute()`, `PetscAssume()`
211: M*/
214: #endif
215: // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
216: // __builtin_types_compatible_p which take types or other non-functiony things as
217: // arguments. The correct way to detect these then is to use __is_identifier (also a clang
218: // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
219: #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
220:   #define PetscHasBuiltin(name) __is_identifier(name)
221: #else
222:   #define PetscHasBuiltin(name) __has_builtin(name)
223: #endif

225: #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
226:   /*
227:    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
228:    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
229:    does not match the actual type of the argument being passed in
230: */
231:   #if PetscHasAttribute(pointer_with_type_tag)
232:     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
233:   #endif

235:   #if PetscHasAttribute(type_tag_for_datatype)
236:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
237:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
238:   #endif
239: #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG

241: #if !defined(PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE)
242:   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
243: #endif

245: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG)
246:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
247: #endif

249: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE)
250:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
251: #endif

253: /*MC
254:   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
255:   as format specifiers and checked for validity

257:   Synopsis:
258: #include <petscmacros.h>
259:   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)

261:   Input Parameters:
262: + strIdx   - The (1-indexed) location of the format string in the argument list
263: - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list

265:   Level: developer

267:   Notes:
268:   This function attribute causes the compiler to issue warnings when the format specifier does
269:   not match the type of the variable that will be formatted, or when there exists a mismatch
270:   between the number of format specifiers and variables to be formatted. It is safe to use this
271:   macro if your compiler does not support format specifier checking (though this is
272:   exceeedingly rare).

274:   Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
275:   same value.

277:   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
278:   the argument list, that is, there is no way to indicate gaps which should not be checked.

280:   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
281:   header files. In this case the macro will expand empty.

283:   Example Usage:
284: .vb
285:   // format string is 2nd argument, variable argument list containing args is 3rd argument
286:   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)

288:   int    x = 1;
289:   double y = 50.0;

291:   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
292:   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
293:   my_printf(NULL,"%d %g",x,y); // OK
294: .ve

296: .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
297: M*/
298: #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
299:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
300: #else
301:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
302: #endif

304: /*MC
305:   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
306:   executed

308:   Level: intermediate

310:   Notes:
311:   The marked function is often optimized for size rather than speed and may be grouped alongside
312:   other equally frigid routines improving code locality of lukewarm or hotter parts of program.

314:   The paths leading to cold functions are usually automatically marked as unlikely by the
315:   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
316:   as error handlers -- as cold to improve optimization of the surrounding temperate functions.

318:   Example Usage:
319: .vb
320:   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;

322:   if (temperature < 0) {
323:     return my_error_handler(...); // chilly!
324:   }
325: .ve

327: .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
328:           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
329: M*/
330: #if PetscHasAttribute(__cold__)
331:   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
332: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
333:   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
334: #else
335:   #define PETSC_ATTRIBUTE_COLD
336: #endif

338: /*MC
339:   PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
340:   subjected to type-based alias analysis, but is instead assumed to be able to
341:   alias any other type of objects

343:   Example Usage:
344: .vb
345:   typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;

347:   PetscReal        *pointer;
348:   PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
349: .ve

351:   Level: advanced

353: .seealso: `PetscHasAttribute()`
354: M*/
355: #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
356:   #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
357: #else
358:   #define PETSC_ATTRIBUTE_MAY_ALIAS
359: #endif

361: /*MC
362:   PETSC_NULLPTR - Standard way of indicating a null value or pointer

364:   No Fortran Support

366:   Level: beginner

368:   Notes:
369:   Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
370:   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
371:   equivalent to setting the same pointer to `NULL` in C. That is to say that the following
372:   expressions are equivalent\:

374: .vb
375:   ptr == PETSC_NULLPTR
376:   ptr == NULL
377:   ptr == 0
378:   !ptr

380:   ptr = PETSC_NULLPTR
381:   ptr = NULL
382:   ptr = 0
383: .ve

385:   and for completeness' sake\:

387: .vb
388:   PETSC_NULLPTR == NULL
389: .ve

391:   Example Usage:
392: .vb
393:   // may be used in place of '\0' or other such terminators in the definition of char arrays
394:   const char *const MyEnumTypes[] = {
395:     "foo",
396:     "bar",
397:     PETSC_NULLPTR
398:   };

400:   // may be used to nullify objects
401:   PetscObject obj = PETSC_NULLPTR;

403:   // may be used in any function expecting NULL
404:   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
405: .ve

407:   Developer Notes:
408:   `PETSC_NULLPTR` must be used in place of `NULL` in all C++ source files. Using `NULL` in source
409:   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
410:   resolution and/or compiler warnings.

412: .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
413: M*/

415: /*MC
416:   PETSC_CONSTEXPR_14 - C++14 constexpr

418:   No Fortran Support

420:   Level: beginner

422:   Notes:
423:   Equivalent to `constexpr` when using a C++ compiler that supports C++14. Expands to nothing
424:   if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
425:   that this cannot be used in cases where an empty expansion would result in invalid code. It
426:   is safe to use this in C source files.

428:   Example Usage:
429: .vb
430:   PETSC_CONSTEXPR_14 int factorial(int n)
431:   {
432:     int r = 1;

434:     do {
435:       r *= n;
436:     } while (--n);
437:     return r;
438:   }
439: .ve

441: .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
442: M*/

444: /*MC
445:   PETSC_NODISCARD - Mark the return value of a function as non-discardable

447:   Not available in Fortran

449:   Level: beginner

451:   Notes:
452:   Hints to the compiler that the return value of a function must be captured. A diagnostic may
453:   (but is not required to) be emitted if the value is discarded. It is safe to use this in both
454:   C and C++ source files.

456:   In this context "captured" means assigning the return value of a function to a named
457:   variable or casting it to `void`. Between the two, assigning to a named variable is the most
458:   portable way of silencing any warnings, since `PETSC_NODISCARD` may expand to GCC's
459:   `__attribute__((warn_unused_result))` which will still emit warnings when casting results to
460:   `void`.

462:   Example Usage:
463: .vb
464:   class Foo
465:   {
466:     int x;

468:   public:
469:     PETSC_NODISCARD Foo(int y) : x(y) { }
470:   };

472:   PETSC_NODISCARD int factorial(int n)
473:   {
474:     return n <= 1 ? 1 : (n * factorial(n - 1));
475:   }

477:   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
478:   auto x = factorial(10); // OK, capturing return value
479:   (void)factorial(10);    // Maybe OK, casting to void
480:   auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
481:   (void)y;                // set-but-not-used warnings)

483:   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
484:   auto f = Foo(x); // OK, capturing constructed object
485:   (void)Foo(x);    // Maybe OK, casting to void
486:   auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
487:   (void)g;         // warnings)
488: .ve

490: .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
491: M*/

493: /* C++11 features */
494: #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
495:   #define PETSC_NULLPTR nullptr
496: #else
497:   #define PETSC_NULLPTR NULL
498: #endif

500: /* C++14 features */
501: #if PETSC_CPP_VERSION >= 14
502:   #define PETSC_CONSTEXPR_14 constexpr
503: #else
504:   #define PETSC_CONSTEXPR_14
505: #endif

507: /* C++17 features */
508: #if PETSC_CPP_VERSION >= 17
509:   #define PETSC_CONSTEXPR_17 constexpr
510: #else
511:   #define PETSC_CONSTEXPR_17
512: #endif

514: #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
515:   #define PETSC_NODISCARD [[nodiscard]]
516: #elif PetscHasAttribute(warn_unused_result)
517:   #define PETSC_NODISCARD __attribute__((warn_unused_result))
518: #else
519:   #define PETSC_NODISCARD
520: #endif

522: #include <petscversion.h>
523: #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"

525: /* designated initializers since C99 and C++20, MSVC never supports them though */
526: #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
527:   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
528: #else
529:   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
530: #endif

532: /*MC
533:   PetscUnlikely - Hints the compiler that the given condition is usually false

535:   Synopsis:
536: #include <petscmacros.h>
537:   bool PetscUnlikely(bool cond)

539:   Not Collective; No Fortran Support

541:   Input Parameter:
542: . cond - Boolean expression

544:   Level: advanced

546:   Note:
547:   This returns the same truth value, it is only a hint to compilers that the result of cond is
548:   unlikely to be true.

550:   Example usage:
551: .vb
552:   if (PetscUnlikely(cond)) {
553:     foo(); // cold path
554:   } else {
555:     bar(); // hot path
556:   }
557: .ve

559: .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
560:           `PETSC_ATTRIBUTE_COLD`
561: M*/
562: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
563:   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
564: #else
565:   #define PetscUnlikely(cond) (cond)
566: #endif

568: /*MC
569:   PetscLikely - Hints the compiler that the given condition is usually true

571:   Synopsis:
572: #include <petscmacros.h>
573:   bool PetscLikely(bool cond)

575:   Not Collective; No Fortran Support

577:   Input Parameter:
578: . cond - Boolean expression

580:   Level: advanced

582:   Note:
583:   This returns the same truth value, it is only a hint to compilers that the result of cond is
584:   likely to be true.

586:   Example usage:
587: .vb
588:   if (PetscLikely(cond)) {
589:     foo(); // hot path
590:   } else {
591:     bar(); // cold path
592:   }
593: .ve

595: .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`, `PETSC_ATTRIBUTE_COLD`
596: M*/
597: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
598:   #define PetscLikely(cond) __builtin_expect(!!(cond), 1)
599: #else
600:   #define PetscLikely(cond) (cond)
601: #endif

603: /*MC
604:   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable

606:   Synopsis:
607: #include <petscmacros.h>
608:   void PetscUnreachable(void)

610:   Level: advanced

612:   Note:
613:   Indicates to the compiler (usually via some built-in) that a particular code path is always
614:   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
615:   unceremonious crash.

617:   Example usage:
618:   Useful in situations such as switches over enums where not all enumeration values are
619:   explicitly covered by the switch

621: .vb

623:   int foo(Color c)
624:   {
625:     // it is known to programmer (or checked previously) that c is either RED or GREEN
626:     // but compiler may not be able to deduce this and/or emit spurious warnings
627:     switch (c) {
628:       case RED:
629:         return bar();
630:       case GREEN:
631:         return baz();
632:       default:
633:         PetscUnreachable(); // program is ill-formed if executed
634:     }
635:   }
636: .ve

638: .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
639: M*/
640: #if PETSC_CPP_VERSION >= 23
641:   #include <utility>
642:   #define PetscUnreachable() std::unreachable()
643: #elif defined(__GNUC__)
644:   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
645:   #define PetscUnreachable() __builtin_unreachable()
646: #elif defined(_MSC_VER) /* MSVC */
647:   #define PetscUnreachable() __assume(0)
648: #else /* ??? */
649:   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
650: #endif

652: /*MC
653:   PetscAssume - Indicate to the compiler a condition that is defined to be true

655:   Synopsis:
656: #include <petscmacros.h>
657:   void PetscAssume(bool cond)

659:   Input Parameter:
660: . cond - Boolean expression

662:   Level: advanced

664:   Notes:
665:   If supported by the compiler, `cond` is used to inform the optimizer of an invariant
666:   truth. The argument itself is never evaluated, so any side effects of the expression will be
667:   discarded. This macro is used in `PetscAssert()` to retain information gained from debug
668:   checks that would be lost in optimized builds. For example\:

670: .vb
671:   PetscErrorCode foo(PetscInt x) {

673:     PetscAssert(x >= 0, ...);
674:   }
675: .ve

677:   The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
678:   if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
679:   when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
680:   optimizer cannot deduce any information from them.

682:   Due to compiler limitations `PetscAssume()` works best when `cond` involves
683:   constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:

685: .vb
686:   int a, b, var_five;

688:   // BEST, all supporting compilers will understand a cannot be >= 5
689:   PetscAssume(a < 5);

691:    // OK, some compilers may understand that a cannot be >= 5
692:   PetscAssume(a <= b && b < 5);

694:    // WORST, most compilers will not get the memo
695:   PetscAssume(a <= b && b < var_five);
696: .ve

698:   If the condition is violated at runtime then behavior is wholly undefined. If the
699:   condition is violated at compile-time, the condition "supersedes" the compile-time violation
700:   and the program is ill-formed, no diagnostic required. For example consider the following\:

702: .vb
703:   PetscInt x = 0;

705:   PetscAssume(x != 0);
706:   if (x == 0) {
707:     x += 10;
708:   } else {
709:     popen("rm -rf /", "w");
710:   }
711: .ve

713:   Even though `x` is demonstrably `0` the compiler may opt to\:

715:   - emit an unconditional `popen("rm -rf /", "w")`
716:   - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
717:   - reformat the primary disk partition

719: .seealso: `PetscAssert()`
720: M*/
721: #if PETSC_CPP_VERSION >= 23
722:   #define PetscAssume(...) [[assume(__VA_ARGS__)]]
723: #elif defined(_MSC_VER) // msvc
724:   #define PetscAssume(...) __assume(__VA_ARGS__)
725: #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
726:   #define PetscAssume(...) \
727:     do { \
728:       _Pragma("clang diagnostic push"); \
729:       _Pragma("clang diagnostic ignored \"-Wassume\""); \
730:       __builtin_assume(__VA_ARGS__); \
731:       _Pragma("clang diagnostic pop"); \
732:     } while (0)
733: #else // gcc (and really old clang)
734:   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
735:   //
736:   // if (PetscUnlikely(!cond)) PetscUnreachable();
737:   //
738:   // but this it unsavory because the side effects of cond are not guaranteed to be
739:   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
740:   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
741:   // always do so. This is especially the case for opaque or non-inline function calls:
742:   //
743:   // extern int bar(int);
744:   //
745:   // int foo(int x) {
746:   //   PetscAssume(bar(x) == 2);
747:   //   if (bar(x) == 2) {
748:   //     return 1;
749:   //   } else {
750:   //     return 0;
751:   //   }
752:   // }
753:   //
754:   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
755:   // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
756:   #define PetscAssume(...) \
757:     do { \
758:       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
759:     } while (0)
760: #endif

762: /*MC
763:   PetscExpand - Expand macro argument

765:   Synopsis:
766: #include <petscmacros.h>
767:   <macro-expansion> PetscExpand(x)

769:   Input Parameter:
770: . x - The preprocessor token to expand

772:   Level: beginner

774: .seealso: `PetscStringize()`, `PetscConcat()`
775: M*/
776: #define PetscExpand_(...) __VA_ARGS__
777: #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)

779: /*MC
780:   PetscStringize - Stringize a token

782:   Synopsis:
783: #include <petscmacros.h>
784:   const char* PetscStringize(x)

786:   No Fortran Support

788:   Input Parameter:
789: . x - The token you would like to stringize

791:   Output Parameter:
792: . <return-value> - The string representation of `x`

794:   Level: beginner

796:   Note:
797:   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
798:   `PetscStringize_()` instead.

800:   Example Usage:
801: .vb
802:   #define MY_OTHER_VAR hello there
803:   #define MY_VAR       MY_OTHER_VAR

805:   PetscStringize(MY_VAR)  -> "hello there"
806:   PetscStringize_(MY_VAR) -> "MY_VAR"

808:   int foo;
809:   PetscStringize(foo)  -> "foo"
810:   PetscStringize_(foo) -> "foo"
811: .ve

813: .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
814: M*/
815: #define PetscStringize_(...) #__VA_ARGS__
816: #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)

818: /*MC
819:   PetscConcat - Concatenate two tokens

821:   Synopsis:
822: #include <petscmacros.h>
823:   <macro-expansion> PetscConcat(x, y)

825:   No Fortran Support

827:   Input Parameters:
828: + x - First token
829: - y - Second token

831:   Level: beginner

833:   Note:
834:   `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
835:   if you don't want to expand them.

837:   Example usage:
838: .vb
839:   PetscConcat(hello,there) -> hellothere

841:   #define HELLO hello
842:   PetscConcat(HELLO,there)  -> hellothere
843:   PetscConcat_(HELLO,there) -> HELLOthere
844: .ve

846: .seealso: `PetscStringize()`, `PetscExpand()`
847: M*/
848: #define PetscConcat_(x, y) x##y
849: #define PetscConcat(x, y)  PetscConcat_(x, y)

851: #define PETSC_INTERNAL_COMPL_0 1
852: #define PETSC_INTERNAL_COMPL_1 0

854: /*MC
855:   PetscCompl - Expands to the integer complement of its argument

857:   Synopsis:
858: #include <petscmacros.h>
859:   int PetscCompl(b)

861:   No Fortran Support

863:   Input Parameter:
864: . b - Preprocessor variable, must expand to either integer literal 0 or 1

866:   Output Parameter:
867: . <return-value> - Either integer literal 0 or 1

869:   Level: beginner

871:   Notes:
872:   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
873:   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
874:   argument before returning the complement.

876:   This macro can be useful for negating `PetscDefined()` inside macros e.g.
877: .vb
878:   #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
879: .ve

881:   Example usage:
882: .vb
883:   #define MY_VAR 1
884:   PetscCompl(MY_VAR) -> 0

886:   #undef  MY_VAR
887:   #define MY_VAR 0
888:   PetscCompl(MY_VAR) -> 1
889: .ve

891: .seealso: `PetscConcat()`, `PetscDefined()`
892: M*/
893: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))

895: /*MC
896:   PetscDefined - Determine whether a boolean macro is defined

898:   Synopsis:
899: #include <petscmacros.h>
900:   int PetscDefined(def)

902:   No Fortran Support

904:   Input Parameter:
905: . def - PETSc-style preprocessor variable (without PETSC_ prepended!)

907:   Output Parameter:
908: . <return-value> - Either integer literal 0 or 1

910:   Level: intermediate

912:   Notes:
913:   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
914:   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
915:   this macro should not be used if its argument may be defined to a non-empty value other than
916:   1.

918:   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
919:   add custom checks in user code, one should use `PetscDefined_()`.
920: .vb
921:   #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
922: .ve

924:   Developer Notes:
925:   Getting something that works in C and CPP for an arg that may or may not be defined is
926:   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
927:   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
928:   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
929:   and when the last step cherry picks the 2nd arg, we get a zero.

931:   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
932:   nonconforming implementation of variadic macros.

934:   Example Usage:
935:   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
936:   is defined then

938: .vb
939:   #if PetscDefined(USE_DEBUG)
940:     foo();
941:   #else
942:     bar();
943:   #endif

945:   // or alternatively within normal code
946:   if (PetscDefined(USE_DEBUG)) {
947:     foo();
948:   } else {
949:     bar();
950:   }
951: .ve

953:   is equivalent to

955: .vb
956:   #if defined(PETSC_USE_DEBUG)
957:   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
958:        foo();
959:   #   elif PETSC_USE_DEBUG == 1
960:        foo();
961:   #   else
962:        bar();
963:   #  endif
964:   #else
965:   bar();
966:   #endif
967: .ve

969: .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
970:           `PetscExpandToNothing()`, `PetscCompl()`
971: M*/
972: #define PetscDefined_arg_1                                    shift,
973: #define PetscDefined_arg_                                     shift,
974: #define PetscDefined__take_second_expanded(ignored, val, ...) val
975: #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
976: #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
977: #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
978: #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
979: #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))

981: /*MC
982:   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
983:   the check in optimized mode

985:   Synopsis:
986: #include <petscmacros.h>
987:   bool PetscUnlikelyDebug(bool cond)

989:   Not Collective; No Fortran Support

991:   Input Parameter:
992: . cond - Boolean expression

994:   Level: advanced

996:   Note:
997:   This returns the same truth value, it is only a hint to compilers that the result of `cond` is
998:   likely to be false. When PETSc is compiled in optimized mode this will always return
999:   false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
1000:   optimized mode.

1002:   Example usage:
1003:   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
1004:   is true. So

1006: .vb
1007:   if (PetscUnlikelyDebug(cond)) {
1008:     foo();
1009:   } else {
1010:     bar();
1011:   }
1012: .ve

1014:   is equivalent to

1016: .vb
1017:   if (PetscDefined(USE_DEBUG)) {
1018:     if (PetscUnlikely(cond)) {
1019:       foo();
1020:     } else {
1021:       bar();
1022:     }
1023:   } else {
1024:     bar();
1025:   }
1026: .ve

1028: .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1029: M*/
1030: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))

1032: #if defined(PETSC_CLANG_STATIC_ANALYZER)
1033:   // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1034:   // not what ISO C allows
1035:   #define PetscMacroReturns_(retexpr, ...) \
1036:     __extension__({ \
1037:       __VA_ARGS__; \
1038:       retexpr; \
1039:     })
1040: #else
1041:   #define PetscMacroReturns_(retexpr, ...) \
1042:     retexpr; \
1043:     do { \
1044:       __VA_ARGS__; \
1045:     } while (0)
1046: #endif

1048: /*MC
1049:   PetscExpandToNothing - Expands to absolutely nothing

1051:   Synopsis:
1052: #include <petscmacros.h>
1053:   void PetscExpandToNothing(...)

1055:   No Fortran Support

1057:   Input Parameter:
1058: . __VA_ARGS__ - Anything at all

1060:   Level: beginner

1062:   Note:
1063:   Must have at least 1 parameter.

1065:   Example usage:
1066: .vb
1067:   PetscExpandToNothing(a,b,c) -> *nothing*
1068: .ve

1070: .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1071: M*/
1072: #define PetscExpandToNothing(...)

1074: /*MC
1075:   PetscMacroReturns - Define a macro body that returns a value

1077:   Synopsis:
1078: #include <petscmacros.h>
1079:   return_type PetscMacroReturns(return_type retexpr, ...)

1081:   Input Parameters:
1082: + retexpr     - The value or expression that the macro should return
1083: - __VA_ARGS__ - The body of the macro

1085:   Level: intermediate

1087:   Notes:
1088:   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1089:   body of the macro and should not depend on values produced as a result of the expression. The
1090:   user should not assume that the result of this macro is equivalent to a single logical source
1091:   line. It is not portable to use macros defined using this one in conditional or loop bodies
1092:   without enclosing them in curly braces\:

1094: .vb
1095:   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0

1097:   int err,x = 10;

1099:   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
1100:   if (...) { err = FOO(x); }  // OK

1102:   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1103:   for (...) { err = FOO(x); } // OK
1104: .ve

1106:   It is also not portable to use this macro directly inside function call, conditional, loop,
1107:   or switch statements\:

1109: .vb
1110:   extern void bar(int);

1112:   int ret = FOO(x);

1114:   bar(FOO(x)); // ERROR, may not compile
1115:   bar(ret);    // OK

1117:   if (FOO(x))  // ERROR, may not compile
1118:   if (ret)     // OK
1119: .ve

1121:   Example usage:
1122: .vb
1123:   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)

1125:   int x = 10;
1126:   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20

1128:   // multiline macros allowed, but must declare with line continuation as usual
1129:   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1130:     if (arg1 > 10) {                                            \
1131:       puts("big int!");                                         \
1132:     } else {                                                    \
1133:       return 7355608;                                           \
1134:     }                                                           \
1135:   )

1137:   // if retexpr contains commas, must enclose it with braces
1138:   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1139:   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)

1141:   int x = 10;
1142:   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1143:   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1144: .ve

1146: .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1147: M*/
1148: #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)

1150: #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)

1152: /*MC
1153:   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array

1155:   Synopsis:
1156: #include <petscmacros.h>
1157:   size_t PETSC_STATIC_ARRAY_LENGTH(a)

1159:   Input Parameter:
1160: . a - a static array of any type

1162:   Output Parameter:
1163: . <return-value> -  the length of the array

1165:   Example:
1166: .vb
1167:   PetscInt a[22];
1168:   size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
1169: .ve
1170:   `sa` will have a value of 22

1172:   Level: intermediate
1173: M*/
1174: #if PETSC_CPP_VERSION >= 14
1175:   #include <cstddef>
1176:   #include <type_traits>

1178: template <typename T>
1179: static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
1180: {
1181:   static_assert(std::is_array<T>::value, "");
1182:   return std::extent<T, std::rank<T>::value - 1>::value;
1183: }
1184: #else
1185:   #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
1186: #endif

1188: /*
1189:   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.

1191:   Example usage:

1193:   #define mymacro(obj,...) {
1194:     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1195:     f(22 PETSC_REST_ARG(__VA_ARGS__));
1196:   }

1198:   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

1200:   Reference:
1201:   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1202: */
1203: #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1204: #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1205: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1206: #define PETSC_NUM(...)                          PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1207: #define PETSC_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
1208: #define PETSC_REST_HELPER_ONE(first)
1209: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1210: #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1211: #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)

1213: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1214:   _Pragma(PetscStringize(name diagnostic push)) \
1215:   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))

1217: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))

1219: #if defined(__clang__)
1220:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1221:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1222: #elif defined(__GNUC__) || defined(__GNUG__)
1223:   // gcc >= 4.6.0
1224:   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1225:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1226:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1227:   #endif
1228: #endif

1230: #if !defined(PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN)
1231:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1232:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1233:   // only undefine these if they are not used
1234:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1235:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1236: #endif

1238: /*MC
1239:   PetscPragmaOMP - Sets an OpenMP pragma to affect the next block of code

1241:   Synopsis:
1242: #include <petscmacros.h>
1243:   int PetscPragmaOMP(name)

1245:   No Fortran Support

1247:   Input Parameter:
1248: . name - the OpenMP pragma, for example, `critical` or `parallel for`

1250:   Level: intermediate

1252:   Note:
1253:   The pragma takes effect when PETSc was configured with `--with-openmp`. See `PetscPragmaUseOMPKernels()`
1254:   for when PETSc was configured to use OpenMP in some of its numerical kernels.

1256: .seealso: `PetscPragmaUseOMPKernels()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1257: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1258: M*/
1259: #if defined(_OPENMP)
1260:   #if defined(_MSC_VER)
1261:     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1262:   #else
1263:     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1264:   #endif
1265: #else
1266:   #define PetscPragmaOMP(...)
1267: #endif

1269: /*MC
1270:   PetscPragmaUseOMPKernels - Sets an OpenMP pragma to affect the next block of code

1272:   Synopsis:
1273: #include <petscmacros.h>
1274:   int PetscPragmaUseOMPKernels(name)

1276:   No Fortran Support

1278:   Input Parameter:
1279: . name - the OpenMP pragma, for example, `critical` or `parallel for`

1281:   Level: intermediate

1283:   Note:
1284:   The pragma takes effect when PETSc was configured with `--with-openmp-kernels`. See `PetscPragmaOMP()`
1285:   for when PETSc was configured with OpenMP but not to use it in its numerical kernels

1287: .seealso: `PetscPragmaOMP()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1288: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1289: M*/
1290: #if defined(PETSC_USE_OPENMP_KERNELS)
1291:   #if defined(_MSC_VER)
1292:     #define PetscPragmaUseOMPKernels(...) __pragma(__VA_ARGS__)
1293:   #else
1294:     #define PetscPragmaUseOMPKernels(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1295:   #endif
1296: #else
1297:   #define PetscPragmaUseOMPKernels(...)
1298: #endif

1300: /* PetscPragmaSIMD - from CeedPragmaSIMD */
1301: #if defined(__NEC__)
1302:   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1303: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1304:   #define PetscPragmaSIMD _Pragma("vector")
1305: #elif defined(__GNUC__)
1306:   #if __GNUC__ >= 5 && !defined(__PGI)
1307:     #define PetscPragmaSIMD _Pragma("GCC ivdep")
1308:   #endif
1309: #elif defined(_OPENMP) && _OPENMP >= 201307
1310:   #define PetscPragmaSIMD PetscPragmaOMP(simd)
1311: #elif defined(PETSC_HAVE_CRAY_VECTOR)
1312:   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1313: #endif

1315: #if !defined(PetscPragmaSIMD)
1316:   #define PetscPragmaSIMD
1317: #endif

1319: #include <petsc/private/petscadvancedmacros.h>

1321: #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
1322: #define PetscConcat6(a, b, c, d, e, f)  PetscConcat6_(a, b, c, d, e, f)

1324: #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
1325:   PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
1326:                       __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__))

1328: #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
1329:   PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)

1331: #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...)   PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1332: #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1333: #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1334: #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1335: #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)