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:   #elif __STDC_VERSION__ < 202311L
 35:     #define PETSC_C_VERSION 22 // C2x drafts before C23 ratification
 36:   #else
 37:     #define PETSC_C_VERSION 23
 38:   #endif
 39: #endif // __STDC_VERSION__

 41: #if !defined(PETSC_C_VERSION)
 42:   #define PETSC_C_VERSION 0
 43: #endif

 45: /* ========================================================================== */
 46: /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
 47: #if defined(__cplusplus)
 48:   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
 49: #else
 50:   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
 51: #endif

 53: /* ========================================================================== */
 54: /* Since PETSc manages its own extern "C" handling users should never include PETSc include
 55:  * files within extern "C". This will generate a compiler error if a user does put the include
 56:  * file within an extern "C".
 57:  */
 58: #if defined(__cplusplus)
 59: void assert_never_put_petsc_headers_inside_an_extern_c(int);
 60: void assert_never_put_petsc_headers_inside_an_extern_c(double);
 61: #endif

 63: #if defined(__cplusplus)
 64:   #define PETSC_RESTRICT PETSC_CXX_RESTRICT
 65: #else
 66:   #define PETSC_RESTRICT restrict
 67: #endif

 69: #define PETSC_INLINE        PETSC_DEPRECATED_MACRO(3, 17, 0, "inline", ) inline
 70: #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "static inline", ) static inline

 72: #if defined(PETSC_DLL_EXPORTS) /* For Win32 shared libraries */
 73:   #define  __declspec(dllexport)
 74:   #define PETSC_DLLIMPORT __declspec(dllimport)
 75:   #define PETSC_VISIBILITY_INTERNAL
 76: #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
 77:   #define            __attribute__((visibility("default")))
 78:   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
 79:   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
 80: #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
 81:   #define            __attribute__((visibility("default")))
 82:   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
 83:   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
 84: #else
 85:   #define 
 86:   #define PETSC_DLLIMPORT
 87:   #define PETSC_VISIBILITY_INTERNAL
 88: #endif

 90: #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
 91:   #define PETSC_VISIBILITY_PUBLIC 
 92: #else /* Win32 users need this to import symbols from petsc.dll */
 93:   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
 94: #endif

 96: /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
 97:  * compiled with C++ so they may be used from C and are always visible in the shared libraries
 98:  */
 99: #if defined(__cplusplus)
100:   #define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
101:   #define PETSC_EXTERN_TYPEDEF extern "C"
102:   #define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
103: #else
104:   #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
105:   #define PETSC_EXTERN_TYPEDEF
106:   #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
107: #endif

109: /*MC
110:   PETSC_TLS - Marks a variable as thread-local when PETSc is configured with thread safety

112:   Synopsis:
113: #include <petscmacros.h>
114:   PETSC_TLS type variable;

116:   Level: developer

118:   Notes:
119:   When configured with `--with-threadsafety=1`, each thread has its own instance of the variable, whose lifetime is the lifetime of that thread.
120:   With `--with-threadsafety=0`, `PETSC_TLS` expands to nothing.

122:   In C, this macro uses C11 `_Thread_local`. In C++, it uses C++11 `thread_local`, except with Clang, where it uses `_Thread_local`
123:   to allow C++ code to access thread-local variables defined in C without requiring C++ initialization wrappers.

125:   Use `PETSC_EXTERN PETSC_TLS` for an exported declaration or `PETSC_INTERN PETSC_TLS` for an internal declaration.

127:   Example Usage:
128: .vb
129:   // In a header
130:   PETSC_EXTERN PETSC_TLS int counter;

132:   // In the source file that defines the variable
133:   PETSC_TLS int counter = 0;
134: .ve

136: .seealso: `PetscStack`, `PetscStackView()`
137: M*/
138: #if defined(PETSC_HAVE_THREADSAFETY)
139:   /* Clang's C++ thread_local can require initialization wrappers absent from C definitions. */
140:   #if defined(__cplusplus) && !defined(__clang__)
141:     #define PETSC_TLS thread_local
142:   #else
143:     #define PETSC_TLS _Thread_local
144:   #endif
145: #else
146:   #define PETSC_TLS
147: #endif

149: #if defined(PETSC_USE_SINGLE_LIBRARY)
150:   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_INTERNAL
151:   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_INTERN
152: #else
153:   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_PUBLIC
154:   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_EXTERN
155: #endif

159: #endif

163: #endif

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

168:   Synopsis:
169: #include <petscmacros.h>
170:   int PetscHasAttribute(name)

172:   Input Parameter:
173: . name - The name of the attribute to test

175:   Level: intermediate

177:   Notes:
178:   name should be identical to what you might pass to the __attribute__ declaration itself --
179:   plain, unbroken text.

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

185:   Example Usage:
186:   Typical usage is using the preprocessor

188: .vb
189:   #if PetscHasAttribute(always_inline)
190:   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
191:   #else
192:   #  define MY_ALWAYS_INLINE
193:   #endif

195:   void foo(void) MY_ALWAYS_INLINE;
196: .ve

198:   but it can also be used in regular code

200: .vb
201:   if (PetscHasAttribute(some_attribute)) {
202:     foo();
203:   } else {
204:     bar();
205:   }
206: .ve

208: .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
209: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
210: M*/
211: #define PetscHasAttribute(name) __has_attribute(name)

215: #endif

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

220:   Synopsis:
221: #include <petscmacros.h>
222:   int PetscHasBuiltin(name)

224:   Input Parameter:
225: . name - the name of the builtin routine

227:   Level: intermediate

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

236:   Example Usage:
237:   Typical usage is in preprocessor directives

239: .vb
240:   #if PetscHasBuiltin(__builtin_trap)
241:   __builtin_trap();
242:   #else
243:   abort();
244:   #endif
245: .ve

247:   But it may also be used in regular code

249: .vb
250:   if (PetscHasBuiltin(__builtin_alloca)) {
251:     foo();
252:   } else {
253:     bar();
254:   }
255: .ve

257:   Developer Note:
258:   Clang's `__has_builtin()` prior to Clang 10 did not properly handle non-function builtins such as
259:   `__builtin_types_compatible_p()` which take types or other non-functiony things as
260:   arguments. The correct way to detect these then is to use `__is_identifier()` (also a Clang
261:   extension). GCC has always worked as expected. See https://stackoverflow.com/a/45043153

263: .seealso: `PetscHasAttribute()`, `PetscAssume()`
264: M*/
265: #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
266:   #define PetscHasBuiltin(name) __is_identifier(name)
267: #else
268:   #define PetscHasBuiltin(name) __has_builtin(name)
269: #endif

271: #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
272:   /*
273:    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
274:    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
275:    does not match the actual type of the argument being passed in
276: */
277:   #if PetscHasAttribute(pointer_with_type_tag)
278:     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
279:   #endif

281:   #if PetscHasAttribute(type_tag_for_datatype)
282:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
283:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
284:   #endif
285: #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG

287: #if !defined(PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE)
288:   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
289: #endif

291: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG)
292:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
293: #endif

295: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE)
296:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
297: #endif

299: /*MC
300:   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
301:   as format specifiers and checked for validity

303:   Synopsis:
304: #include <petscmacros.h>
305:   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)

307:   Input Parameters:
308: + strIdx   - The (1-indexed) location of the format string in the argument list
309: - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list

311:   Level: developer

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

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

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

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

329:   Example Usage:
330: .vb
331:   // format string is 2nd argument, variable argument list containing args is 3rd argument
332:   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)

334:   int    x = 1;
335:   double y = 50.0;

337:   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
338:   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
339:   my_printf(NULL,"%d %g",x,y); // OK
340: .ve

342: .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
343: M*/
344: #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
345:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
346: #else
347:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
348: #endif

350: /*MC
351:   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
352:   executed

354:   Level: intermediate

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

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

364:   Example Usage:
365: .vb
366:   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;

368:   if (temperature < 0) {
369:     return my_error_handler(...); // chilly!
370:   }
371: .ve

373: .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
374:           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
375: M*/
376: #if PetscHasAttribute(__cold__)
377:   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
378: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
379:   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
380: #else
381:   #define PETSC_ATTRIBUTE_COLD
382: #endif

384: /*MC
385:   PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
386:   subjected to type-based alias analysis, but is instead assumed to be able to
387:   alias any other type of objects

389:   Example Usage:
390: .vb
391:   typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;

393:   PetscReal        *pointer;
394:   PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
395: .ve

397:   Level: advanced

399: .seealso: `PetscHasAttribute()`
400: M*/
401: #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
402:   #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
403: #else
404:   #define PETSC_ATTRIBUTE_MAY_ALIAS
405: #endif

407: /*MC
408:   PETSC_NULLPTR - Standard way of indicating a null value or pointer

410:   No Fortran Support

412:   Level: beginner

414:   Notes:
415:   Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
416:   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
417:   equivalent to setting the same pointer to `NULL` in C. That is to say that the following
418:   expressions are equivalent\:

420: .vb
421:   ptr == PETSC_NULLPTR
422:   ptr == NULL
423:   ptr == 0
424:   !ptr

426:   ptr = PETSC_NULLPTR
427:   ptr = NULL
428:   ptr = 0
429: .ve

431:   and for completeness' sake\:

433: .vb
434:   PETSC_NULLPTR == NULL
435: .ve

437:   Example Usage:
438: .vb
439:   // may be used in place of '\0' or other such terminators in the definition of char arrays
440:   const char *const MyEnumTypes[] = {
441:     "foo",
442:     "bar",
443:     PETSC_NULLPTR
444:   };

446:   // may be used to nullify objects
447:   PetscObject obj = PETSC_NULLPTR;

449:   // may be used in any function expecting NULL
450:   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
451: .ve

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

458: .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
459: M*/

461: /*MC
462:   PETSC_CONSTEXPR_14 - C++14 constexpr

464:   No Fortran Support

466:   Level: beginner

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

474:   Example Usage:
475: .vb
476:   PETSC_CONSTEXPR_14 int factorial(int n)
477:   {
478:     int r = 1;

480:     do {
481:       r *= n;
482:     } while (--n);
483:     return r;
484:   }
485: .ve

487: .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
488: M*/

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

493:   Not available in Fortran

495:   Level: beginner

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

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

508:   Example Usage:
509: .vb
510:   class Foo
511:   {
512:     int x;

514:   public:
515:     PETSC_NODISCARD Foo(int y) : x(y) { }
516:   };

518:   PETSC_NODISCARD int factorial(int n)
519:   {
520:     return n <= 1 ? 1 : (n * factorial(n - 1));
521:   }

523:   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
524:   auto x = factorial(10); // OK, capturing return value
525:   (void)factorial(10);    // Maybe OK, casting to void
526:   auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
527:   (void)y;                // set-but-not-used warnings)

529:   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
530:   auto f = Foo(x); // OK, capturing constructed object
531:   (void)Foo(x);    // Maybe OK, casting to void
532:   auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
533:   (void)g;         // warnings)
534: .ve

536: .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
537: M*/

539: /* C++11 features */
540: #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
541:   #define PETSC_NULLPTR nullptr
542: #else
543:   #define PETSC_NULLPTR NULL
544: #endif

546: /* C++14 features */
547: #if PETSC_CPP_VERSION >= 14
548:   #define PETSC_CONSTEXPR_14 constexpr
549: #else
550:   #define PETSC_CONSTEXPR_14
551: #endif

553: /* C++17 features */
554: #if PETSC_CPP_VERSION >= 17
555:   #define PETSC_CONSTEXPR_17 constexpr
556: #else
557:   #define PETSC_CONSTEXPR_17
558: #endif

560: #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
561:   #define PETSC_NODISCARD [[nodiscard]]
562: #elif PetscHasAttribute(warn_unused_result)
563:   #define PETSC_NODISCARD __attribute__((warn_unused_result))
564: #else
565:   #define PETSC_NODISCARD
566: #endif

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

571: /* designated initializers since C99 and C++20, MSVC never supports them though */
572: #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
573:   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
574: #else
575:   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
576: #endif

578: /*MC
579:   PetscUnlikely - Hints the compiler that the given condition is usually false

581:   Synopsis:
582: #include <petscmacros.h>
583:   bool PetscUnlikely(bool cond)

585:   Not Collective; No Fortran Support

587:   Input Parameter:
588: . cond - Boolean expression

590:   Level: advanced

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

596:   Example usage:
597: .vb
598:   if (PetscUnlikely(cond)) {
599:     foo(); // cold path
600:   } else {
601:     bar(); // hot path
602:   }
603: .ve

605: .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
606:           `PETSC_ATTRIBUTE_COLD`
607: M*/
608: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
609:   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
610: #else
611:   #define PetscUnlikely(cond) (cond)
612: #endif

614: /*MC
615:   PetscLikely - Hints the compiler that the given condition is usually true

617:   Synopsis:
618: #include <petscmacros.h>
619:   bool PetscLikely(bool cond)

621:   Not Collective; No Fortran Support

623:   Input Parameter:
624: . cond - Boolean expression

626:   Level: advanced

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

632:   Example usage:
633: .vb
634:   if (PetscLikely(cond)) {
635:     foo(); // hot path
636:   } else {
637:     bar(); // cold path
638:   }
639: .ve

641: .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`, `PETSC_ATTRIBUTE_COLD`
642: M*/
643: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
644:   #define PetscLikely(cond) __builtin_expect(!!(cond), 1)
645: #else
646:   #define PetscLikely(cond) (cond)
647: #endif

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

652:   Synopsis:
653: #include <petscmacros.h>
654:   void PetscUnreachable(void)

656:   Level: advanced

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

663:   Example usage:
664:   Useful in situations such as switches over enums where not all enumeration values are
665:   explicitly covered by the switch

667: .vb

669:   int foo(Color c)
670:   {
671:     // it is known to programmer (or checked previously) that c is either RED or GREEN
672:     // but compiler may not be able to deduce this and/or emit spurious warnings
673:     switch (c) {
674:       case RED:
675:         return bar();
676:       case GREEN:
677:         return baz();
678:       default:
679:         PetscUnreachable(); // program is ill-formed if executed
680:     }
681:   }
682: .ve

684: .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
685: M*/
686: #if PETSC_CPP_VERSION >= 23
687:   #include <utility>
688:   #define PetscUnreachable() std::unreachable()
689: #elif defined(__GNUC__)
690:   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
691:   #define PetscUnreachable() __builtin_unreachable()
692: #elif defined(_MSC_VER) /* MSVC */
693:   #define PetscUnreachable() __assume(0)
694: #else /* ??? */
695:   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
696: #endif

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

701:   Synopsis:
702: #include <petscmacros.h>
703:   void PetscAssume(bool cond)

705:   Input Parameter:
706: . cond - Boolean expression

708:   Level: advanced

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

716: .vb
717:   PetscErrorCode foo(PetscInt x) {

719:     PetscAssert(x >= 0, ...);
720:   }
721: .ve

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

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

731: .vb
732:   int a, b, var_five;

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

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

740:    // WORST, most compilers will not get the memo
741:   PetscAssume(a <= b && b < var_five);
742: .ve

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

748: .vb
749:   PetscInt x = 0;

751:   PetscAssume(x != 0);
752:   if (x == 0) {
753:     x += 10;
754:   } else {
755:     popen("rm -rf /", "w");
756:   }
757: .ve

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

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

765: .seealso: `PetscAssert()`
766: M*/
767: #if PETSC_CPP_VERSION >= 23
768:   #define PetscAssume(...) [[assume(__VA_ARGS__)]]
769: #elif defined(_MSC_VER) // msvc
770:   #define PetscAssume(...) __assume(__VA_ARGS__)
771: #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
772:   #define PetscAssume(...) \
773:     do { \
774:       _Pragma("clang diagnostic push"); \
775:       _Pragma("clang diagnostic ignored \"-Wassume\""); \
776:       __builtin_assume(__VA_ARGS__); \
777:       _Pragma("clang diagnostic pop"); \
778:     } while (0)
779: #else // gcc (and really old clang)
780:   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
781:   //
782:   // if (PetscUnlikely(!cond)) PetscUnreachable();
783:   //
784:   // but this it unsavory because the side effects of cond are not guaranteed to be
785:   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
786:   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
787:   // always do so. This is especially the case for opaque or non-inline function calls:
788:   //
789:   // extern int bar(int);
790:   //
791:   // int foo(int x) {
792:   //   PetscAssume(bar(x) == 2);
793:   //   if (bar(x) == 2) {
794:   //     return 1;
795:   //   } else {
796:   //     return 0;
797:   //   }
798:   // }
799:   //
800:   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
801:   // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
802:   #define PetscAssume(...) \
803:     do { \
804:       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
805:     } while (0)
806: #endif

808: /*MC
809:   PetscExpand - Expand macro argument

811:   Synopsis:
812: #include <petscmacros.h>
813:   <macro-expansion> PetscExpand(x)

815:   Input Parameter:
816: . x - The preprocessor token to expand

818:   Level: beginner

820: .seealso: `PetscStringize()`, `PetscConcat()`
821: M*/
822: #define PetscExpand_(...) __VA_ARGS__
823: #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)

825: /*MC
826:   PetscStringize - Stringize a token

828:   Synopsis:
829: #include <petscmacros.h>
830:   const char* PetscStringize(x)

832:   No Fortran Support

834:   Input Parameter:
835: . x - The token you would like to stringize

837:   Output Parameter:
838: . <return_value> - The string representation of `x`

840:   Level: beginner

842:   Note:
843:   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
844:   `PetscStringize_()` instead.

846:   Example Usage:
847: .vb
848:   #define MY_OTHER_VAR hello there
849:   #define MY_VAR       MY_OTHER_VAR

851:   PetscStringize(MY_VAR)  -> "hello there"
852:   PetscStringize_(MY_VAR) -> "MY_VAR"

854:   int foo;
855:   PetscStringize(foo)  -> "foo"
856:   PetscStringize_(foo) -> "foo"
857: .ve

859: .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
860: M*/
861: #define PetscStringize_(...) #__VA_ARGS__
862: #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)

864: /*MC
865:   PetscConcat - Concatenate two tokens

867:   Synopsis:
868: #include <petscmacros.h>
869:   <macro-expansion> PetscConcat(x, y)

871:   No Fortran Support

873:   Input Parameters:
874: + x - First token
875: - y - Second token

877:   Level: beginner

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

883:   Example usage:
884: .vb
885:   PetscConcat(hello,there) -> hellothere

887:   #define HELLO hello
888:   PetscConcat(HELLO,there)  -> hellothere
889:   PetscConcat_(HELLO,there) -> HELLOthere
890: .ve

892: .seealso: `PetscStringize()`, `PetscExpand()`
893: M*/
894: #define PetscConcat_(x, y) x##y
895: #define PetscConcat(x, y)  PetscConcat_(x, y)

897: #define PETSC_INTERNAL_COMPL_0 1
898: #define PETSC_INTERNAL_COMPL_1 0

900: /*MC
901:   PetscCompl - Expands to the integer complement of its argument

903:   Synopsis:
904: #include <petscmacros.h>
905:   int PetscCompl(b)

907:   No Fortran Support

909:   Input Parameter:
910: . b - Preprocessor variable, must expand to either integer literal `0` or `1`

912:   Output Parameter:
913: . <return_value> - Either integer literal `0` or `1`

915:   Level: beginner

917:   Notes:
918:   Expands to integer literal `0` if `b` expands to 1, or integer literal `1` if `b` expands to
919:   `0`. Behavior is undefined if `b` expands to anything else. `PetscCompl()` will expand its
920:   argument before returning the complement.

922:   This macro can be useful for negating `PetscDefined()` inside macros, e.g.,
923: .vb
924:   #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
925: .ve

927:   Example usage:
928: .vb
929:   #define MY_VAR 1
930:   PetscCompl(MY_VAR) -> 0

932:   #undef  MY_VAR
933:   #define MY_VAR 0
934:   PetscCompl(MY_VAR) -> 1
935: .ve

937: .seealso: `PetscConcat()`, `PetscDefined()`
938: M*/
939: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))

941: #define PetscDefined_arg_1                                    shift,
942: #define PetscDefined_arg_                                     shift,
943: #define PetscDefined__take_second_expanded(ignored, val, ...) val
944: #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
945: #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
946: #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
947: #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))

949: /*MC
950:   PetscDefined - Determine whether a Boolean macro is defined

952:   Synopsis:
953: #include <petscmacros.h>
954:   int PetscDefined(def)

956:   No Fortran Support

958:   Input Parameter:
959: . def - PETSc-style preprocessor variable (without `PETSC_` prepended!)

961:   Output Parameter:
962: . <return_value> - Either integer literal `0` or `1`

964:   Level: intermediate

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

971:   The prefix `PETSC_` is automatically prepended to `def`, which is treated as a literal suffix
972:   and is not macro-expanded. To avoid prepending `PETSC_`, say to add custom checks in user code,
973:   one should use `PetscDefined_()`.
974: .vb
975:   #define FooDefined(d) PetscDefined_(FOO_##d)
976: .ve

978:   Developer Notes:
979:   Getting something that works in C and CPP for an arg that may or may not be defined is
980:   tricky. Here, if we have `#define PETSC_HAVE_BOOGER 1`, we match on the placeholder define,
981:   insert the `0,` for `arg1` and generate the triplet `(0, 1, 0)`. Then, the last step cherry picks
982:   the second argument (a one). When `PETSC_HAVE_BOOGER` is not defined, we generate a `(... 1, 0)` pair,
983:   and when the last step cherry picks the second argument, we get a zero.

985:   Our extra expansion via `PetscDefined__take_second_expand()` is needed with MSVC, which has a
986:   nonconforming implementation of variadic macros. The `PETSC_` prefix must be pasted in
987:   `PetscDefined()` itself so that an unprefixed macro matching `def` cannot expand before the
988:   prefix is added.

990:   Example Usage:
991:   Suppose you would like to call either `foo()` or `bar()` depending on whether `PETSC_USE_DEBUG`
992:   is defined then

994: .vb
995:   #if PetscDefined(USE_DEBUG)
996:     foo();
997:   #else
998:     bar();
999:   #endif

1001:   // or alternatively within normal code
1002:   if (PetscDefined(USE_DEBUG)) {
1003:     foo();
1004:   } else {
1005:     bar();
1006:   }
1007: .ve

1009:   is equivalent to

1011: .vb
1012:   #if defined(PETSC_USE_DEBUG)
1013:   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
1014:        foo();
1015:   #   elif PETSC_USE_DEBUG == 1
1016:        foo();
1017:   #   else
1018:        bar();
1019:   #  endif
1020:   #else
1021:   bar();
1022:   #endif
1023: .ve

1025: .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
1026:           `PetscExpandToNothing()`, `PetscCompl()`
1027: M*/
1028: #define PetscDefined(def) PetscDefined_(PETSC_##def)

1030: /* C23 or C++11 constexpr for static constant variables when the current compile supports it; C23 rejects
1031:    constexpr floating initializers that excess precision (__FLT_EVAL_METHOD__ != 0) makes inexact */
1032: #if defined(__cplusplus) || (PetscDefined(HAVE_C_STATIC_CONSTEXPR) && PETSC_C_VERSION >= 23 && (!defined(__FLT_EVAL_METHOD__) || __FLT_EVAL_METHOD__ == 0))
1033:   #define PETSC_CONSTEXPR_ENABLED 1
1034:   #define PETSC_STATIC_CONSTEXPR  static constexpr
1035: #else
1036:   #define PETSC_STATIC_CONSTEXPR static const
1037: #endif

1039: /* Whether a static constant variable may be initialized from another const value */
1040: #if defined(__cplusplus) || PetscDefined(CONSTEXPR_ENABLED) || PetscDefined(HAVE_C_STATIC_CONST_INIT_FROM_CONST)
1041:   #define PETSC_HAVE_STATIC_CONST_INIT 1
1042: #endif

1044: /*MC
1045:   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
1046:   the check in optimized mode

1048:   Synopsis:
1049: #include <petscmacros.h>
1050:   bool PetscUnlikelyDebug(bool cond)

1052:   Not Collective; No Fortran Support

1054:   Input Parameter:
1055: . cond - Boolean expression

1057:   Level: advanced

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

1065:   Example usage:
1066:   This routine is shorthand for checking both the condition and whether `PetscDefined(USE_DEBUG)`
1067:   is true. So

1069: .vb
1070:   if (PetscUnlikelyDebug(cond)) {
1071:     foo();
1072:   } else {
1073:     bar();
1074:   }
1075: .ve

1077:   is equivalent to

1079: .vb
1080:   if (PetscDefined(USE_DEBUG)) {
1081:     if (PetscUnlikely(cond)) {
1082:       foo();
1083:     } else {
1084:       bar();
1085:     }
1086:   } else {
1087:     bar();
1088:   }
1089: .ve

1091: .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1092: M*/
1093: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))

1095: #if defined(PETSC_CLANG_STATIC_ANALYZER)
1096:   // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1097:   // not what ISO C allows
1098:   #define PetscMacroReturns_(retexpr, ...) \
1099:     __extension__({ \
1100:       __VA_ARGS__; \
1101:       retexpr; \
1102:     })
1103: #else
1104:   #define PetscMacroReturns_(retexpr, ...) \
1105:     retexpr; \
1106:     do { \
1107:       __VA_ARGS__; \
1108:     } while (0)
1109: #endif

1111: /*MC
1112:   PetscExpandToNothing - Expands to absolutely nothing

1114:   Synopsis:
1115: #include <petscmacros.h>
1116:   void PetscExpandToNothing(...)

1118:   No Fortran Support

1120:   Input Parameter:
1121: . __VA_ARGS__ - Anything at all

1123:   Level: beginner

1125:   Note:
1126:   Must have at least 1 parameter.

1128:   Example usage:
1129: .vb
1130:   PetscExpandToNothing(a,b,c) -> *nothing*
1131: .ve

1133: .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1134: M*/
1135: #define PetscExpandToNothing(...)

1137: /*MC
1138:   PetscMacroReturns - Define a macro body that returns a value

1140:   Synopsis:
1141: #include <petscmacros.h>
1142:   return_type PetscMacroReturns(return_type retexpr, ...)

1144:   Input Parameters:
1145: + retexpr     - The value or expression that the macro should return
1146: - __VA_ARGS__ - The body of the macro

1148:   Level: intermediate

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

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

1160:   int err,x = 10;

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

1165:   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1166:   for (...) { err = FOO(x); } // OK
1167: .ve

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

1172: .vb
1173:   extern void bar(int);

1175:   int ret = FOO(x);

1177:   bar(FOO(x)); // ERROR, may not compile
1178:   bar(ret);    // OK

1180:   if (FOO(x))  // ERROR, may not compile
1181:   if (ret)     // OK
1182: .ve

1184:   Example usage:
1185: .vb
1186:   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)

1188:   int x = 10;
1189:   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20

1191:   // multiline macros allowed, but must declare with line continuation as usual
1192:   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1193:     if (arg1 > 10) {                                            \
1194:       puts("big int!");                                         \
1195:     } else {                                                    \
1196:       return 7355608;                                           \
1197:     }                                                           \
1198:   )

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

1204:   int x = 10;
1205:   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1206:   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1207: .ve

1209: .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1210: M*/
1211: #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)

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

1215: /*MC
1216:   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array

1218:   Synopsis:
1219: #include <petscmacros.h>
1220:   size_t PETSC_STATIC_ARRAY_LENGTH(a)

1222:   Input Parameter:
1223: . a - a static array of any type

1225:   Output Parameter:
1226: . <return_value> - the length of the array

1228:   Example:
1229: .vb
1230:   PetscInt a[22];
1231:   size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
1232: .ve
1233:   `sa` will have a value of 22

1235:   Level: intermediate
1236: M*/
1237: #if PETSC_CPP_VERSION >= 14
1238:   #include <cstddef>
1239:   #include <type_traits>

1241: template <typename T>
1242: static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
1243: {
1244:   static_assert(std::is_array<T>::value, "");
1245:   return std::extent<T, std::rank<T>::value - 1>::value;
1246: }
1247: #else
1248:   #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
1249: #endif

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

1254:   Example usage:

1256:   #define mymacro(obj,...) {
1257:     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1258:     f(22 PETSC_REST_ARG(__VA_ARGS__));
1259:   }

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

1263:   Reference:
1264:   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1265: */
1266: #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1267: #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1268: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1269: #define PETSC_NUM(...)                          PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1270: #define PETSC_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
1271: #define PETSC_REST_HELPER_ONE(first)
1272: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1273: #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1274: #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)

1276: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1277:   _Pragma(PetscStringize(name diagnostic push)) \
1278:   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))

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

1282: #if defined(__clang__)
1283:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1284:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1285: #elif defined(__GNUC__) || defined(__GNUG__)
1286:   // gcc >= 4.6.0
1287:   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1288:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1289:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1290:   #endif
1291: #endif

1293: #if !defined(PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN)
1294:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1295:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1296:   // only undefine these if they are not used
1297:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1298:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1299: #endif

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

1304:   Synopsis:
1305: #include <petscmacros.h>
1306:   int PetscPragmaOMP(name)

1308:   No Fortran Support

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

1313:   Level: intermediate

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

1319: .seealso: `PetscPragmaUseOMPKernels()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1320: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1321: M*/
1322: #if defined(_OPENMP)
1323:   #if defined(_MSC_VER)
1324:     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1325:   #else
1326:     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1327:   #endif
1328: #else
1329:   #define PetscPragmaOMP(...)
1330: #endif

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

1335:   Synopsis:
1336: #include <petscmacros.h>
1337:   int PetscPragmaUseOMPKernels(name)

1339:   No Fortran Support

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

1344:   Level: intermediate

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

1350: .seealso: `PetscPragmaOMP()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1351: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1352: M*/
1353: #if defined(PETSC_USE_OPENMP_KERNELS)
1354:   #if defined(_MSC_VER)
1355:     #define PetscPragmaUseOMPKernels(...) __pragma(__VA_ARGS__)
1356:   #else
1357:     #define PetscPragmaUseOMPKernels(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1358:   #endif
1359: #else
1360:   #define PetscPragmaUseOMPKernels(...)
1361: #endif

1363: /* PetscPragmaSIMD - from CeedPragmaSIMD */
1364: #if defined(__NEC__)
1365:   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1366: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1367:   #define PetscPragmaSIMD _Pragma("vector")
1368: #elif defined(__GNUC__)
1369:   #if __GNUC__ >= 5 && !defined(__PGI)
1370:     #define PetscPragmaSIMD _Pragma("GCC ivdep")
1371:   #endif
1372: #elif defined(_OPENMP) && _OPENMP >= 201307
1373:   #define PetscPragmaSIMD PetscPragmaOMP(simd)
1374: #elif defined(PETSC_HAVE_CRAY_VECTOR)
1375:   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1376: #endif

1378: #if !defined(PetscPragmaSIMD)
1379:   #define PetscPragmaSIMD
1380: #endif

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

1384: #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f

1386: /*MC
1387:   PetscConcat6 - Concatenate six preprocessor tokens after expansion

1389:   Synopsis:
1390: #include <petscmacros.h>
1391:   <macro-expansion> PetscConcat6(a, b, c, d, e, f)

1393:   No Fortran Support

1395:   Input Parameters:
1396: + a - first token
1397: . b - second token
1398: . c - third token
1399: . d - fourth token
1400: . e - fifth token
1401: - f - sixth token

1403:   Level: developer

1405:   Note:
1406:   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.

1408: .seealso: `PetscConcat()`, `PetscStringize()`, `PetscExpand()`
1409: M*/
1410: #define PetscConcat6(a, b, c, d, e, f) PetscConcat6_(a, b, c, d, e, f)

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

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

1419: #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...)   PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1420: #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1421: #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1422: #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1423: #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)