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