From cf1063a399822b6b2d19ff779fb9282a7a84ed24 Mon Sep 17 00:00:00 2001 From: i80287 Date: Wed, 30 Oct 2024 04:38:19 +0300 Subject: [PATCH 1/6] update attributes in the config_macros.hpp and cleanup integer casts --- bstrees/RBTree.cppm | 2 +- bstrees/config_macros.hpp | 239 +++++++++++-------- graphs/HungarianAlgorithm/config_macros.hpp | 239 +++++++++++-------- graphs/HungarianAlgorithm/hungarian_algo.hpp | 6 +- number_theory/bitmatrix.hpp | 48 ++-- number_theory/config_macros.hpp | 239 +++++++++++-------- number_theory/fft.hpp | 10 +- number_theory/gosper_algorithm.hpp | 6 +- number_theory/integers_128_bit.hpp | 6 +- number_theory/is_prime.hpp | 156 ++++++------ number_theory/kronecker_symbol.hpp | 34 +-- number_theory/longint.hpp | 145 +++++------ number_theory/math_functions.hpp | 140 ++++++----- number_theory/test_is_prime_bpsw.cpp | 4 +- number_theory/test_kronecker_symbol.cpp | 11 +- tests/.clang-tidy | 3 +- tests/CMakeLists.txt | 12 +- vec_instructs/config_macros.hpp | 239 +++++++++++-------- vec_instructs/memcount.h | 21 +- vec_instructs/memset_int.h | 14 +- 20 files changed, 835 insertions(+), 739 deletions(-) diff --git a/bstrees/RBTree.cppm b/bstrees/RBTree.cppm index e2f6440..982d295 100644 --- a/bstrees/RBTree.cppm +++ b/bstrees/RBTree.cppm @@ -1161,7 +1161,7 @@ protected: [[nodiscard]] ATTRIBUTE_PURE constexpr size_type size() const noexcept { const size_type value = Base::Size(); RBTREE_ASSERT_INVARIANT(value <= max_size()); - ATTRIBUTE_ASSUME(value <= max_size()); + CONFIG_ASSUME_STATEMENT(value <= max_size()); return value; } diff --git a/bstrees/config_macros.hpp b/bstrees/config_macros.hpp index 8b1a6ff..0672803 100644 --- a/bstrees/config_macros.hpp +++ b/bstrees/config_macros.hpp @@ -22,12 +22,6 @@ #define CONFIG_HAS_GCC_ATTRIBUTE(attr) 0 #endif -#if defined(__cplusplus) && defined(__has_cpp_attribute) -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) -#else -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 -#endif - #if defined(__has_builtin) #define CONFIG_HAS_BUILTIN(name) __has_builtin(name) #else @@ -79,6 +73,12 @@ #define CONFIG_HAS_AT_LEAST_CXX_23 0 #endif +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define CONFIG_HAS_AT_LEAST_C_99 1 +#else +#define CONFIG_HAS_AT_LEAST_C_99 0 +#endif + #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define CONFIG_HAS_AT_LEAST_C_11 1 #else @@ -97,6 +97,18 @@ #define CONFIG_HAS_AT_LEAST_C_23 0 #endif +#if CONFIG_HAS_AT_LEAST_C_99 && defined(__has_c_attribute) +#define CONFIG_HAS_C_ATTRIBUTE(attr) __has_c_attribute(attr) +#else +#define CONFIG_HAS_C_ATTRIBUTE(attr) 0 +#endif + +#if CONFIG_HAS_AT_LEAST_CXX_11 && defined(__has_cpp_attribute) +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) +#else +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 +#endif + // https://en.cppreference.com/w/cpp/feature_test #if defined(__cpp_concepts) && __cpp_concepts >= 201907L #define CONFIG_HAS_CONCEPTS 1 @@ -104,9 +116,9 @@ #define CONFIG_HAS_CONCEPTS 0 #endif -/** - * Restrict qualifier for the C++ (C has `restrict` keyword since C99) - */ +#if CONFIG_HAS_AT_LEAST_C_99 +#define RESTRICT_QUALIFIER restrict +#else #if defined(__GNUC__) || defined(__clang__) #define RESTRICT_QUALIFIER __restrict__ #elif defined(_MSC_VER) @@ -114,6 +126,7 @@ #else #define RESTRICT_QUALIFIER #endif +#endif #if defined(__GNUC__) || defined(__clang__) #define FUNCTION_MACRO __PRETTY_FUNCTION__ @@ -127,67 +140,61 @@ #include #endif -#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L -#define CONFIG_UNREACHABLE() std::unreachable() -#elif CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define CONFIG_UNREACHABLE() [[assume(false)]] -#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) -#define CONFIG_UNREACHABLE() __builtin_unreachable() -#elif CONFIG_HAS_BUILTIN(__builtin_assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __builtin_assume(false) -#else -#define CONFIG_UNREACHABLE() __builtin_assume(0) -#endif +#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) +#define CONFIG_ASSUME_STATEMENT(expr) [[assume(expr)]] +#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) +#define CONFIG_ASSUME_STATEMENT(expr) __builtin_assume(expr) #elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __attribute__((assume(false))) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(false))); \ + } \ + } while (false) #else -#define CONFIG_UNREACHABLE() __attribute__((assume(0))) +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(0))); \ + } \ + } while (0) #endif #elif defined(_MSC_VER) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __assume(false) +#define CONFIG_ASSUME_STATEMENT(expr) __assume(expr) #else -#define CONFIG_UNREACHABLE() __assume(0) -#endif -#else -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() \ - do { \ +#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + std::unreachable(); \ + } \ + } while (false) +#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (false) #else -#define CONFIG_UNREACHABLE() \ - do { \ +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (0) #endif +#else +#define CONFIG_ASSUME_STATEMENT(expr) +#endif #endif -#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) [[assume(expr)]] -#elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) __attribute__((assume(expr))) -#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) -// Side effect of expr is discarded -#define ATTRIBUTE_ASSUME(expr) __builtin_assume(expr) -#elif defined(_MSC_VER) -#define ATTRIBUTE_ASSUME(expr) __assume(expr) -#else #if defined(__cplusplus) -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (false) +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(false) #else -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (0) -#endif +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(0) #endif /* __builtin_expect is in gcc 3.0 */ @@ -208,23 +215,22 @@ #define unlikely(x) __builtin_expect((x), 0) #endif -#else +#elif !defined(likely) || !defined(likely) -#if !defined(likely) -#if defined(__cplusplus) -#define likely(x) static_cast(x) -#else -#define likely(x) !!(x) +#if defined(likely) +#undef likely #endif +#if defined(unlikely) +#undef unlikely #endif -#if !defined(unlikely) #if defined(__cplusplus) +#define likely(x) static_cast(x) #define unlikely(x) static_cast(x) #else +#define likely(x) !!(x) #define unlikely(x) !!(x) #endif -#endif #endif @@ -233,69 +239,68 @@ #define __attribute__(...) #endif -#if CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) -#define ATTRIBUTE_CONST __attribute__((__const__)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) #define ATTRIBUTE_CONST [[gnu::__const__]] +#elif CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) +#define ATTRIBUTE_CONST __attribute__((__const__)) #else #define ATTRIBUTE_CONST #endif -#if CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) -#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(maybe_unused) #define ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]] +#elif CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) +#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) #else #define ATTRIBUTE_MAYBE_UNUSED #endif -#if CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) -#define ATTRIBUTE_PURE __attribute__((pure)) -#elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) #define ATTRIBUTE_PURE [[gnu::pure]] +#elif CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) +#define ATTRIBUTE_PURE __attribute__((pure)) #else #define ATTRIBUTE_PURE #endif -#if CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) -#define ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) #define ATTRIBUTE_NOINLINE [[clang::noinline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::noinline) #define ATTRIBUTE_NOINLINE [[gnu::noinline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::noinline) #define ATTRIBUTE_NOINLINE [[msvc::noinline]] -#elif defined(_MSC_VER) && \ - (_MSC_VER >= 1920 || defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017) +#elif defined(_MSC_VER) && _MSC_VER >= 1920 && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017 #define ATTRIBUTE_NOINLINE __declspec(noinline) +#elif CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) +#define ATTRIBUTE_NOINLINE __attribute__((noinline)) #else #define ATTRIBUTE_NOINLINE #endif -#if CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) -#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[clang::always_inline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[gnu::always_inline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::forceinline) #define ATTRIBUTE_ALWAYS_INLINE [[msvc::forceinline]] +#elif CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) +#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) #else #define ATTRIBUTE_ALWAYS_INLINE #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) -#define ATTRIBUTE_COLD __attribute__((cold)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) #define ATTRIBUTE_COLD [[gnu::cold]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) +#define ATTRIBUTE_COLD __attribute__((cold)) #else #define ATTRIBUTE_COLD #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) -#define ATTRIBUTE_HOT __attribute__((hot)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) #define ATTRIBUTE_HOT [[gnu::hot]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) +#define ATTRIBUTE_HOT __attribute__((hot)) #else #define ATTRIBUTE_HOT #endif @@ -306,10 +311,10 @@ * indicate the size of the allocation. * Clang docs: https://clang.llvm.org/docs/AttributeReference.html#alloc-size */ -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) -#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) #define ATTRIBUTE_ALLOC_SIZE(...) [[gnu::alloc_size(__VA_ARGS__)]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) +#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) #else #define ATTRIBUTE_ALLOC_SIZE(...) #endif @@ -323,7 +328,17 @@ * * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html for more info */ -#if CONFIG_GNUC_AT_LEAST(10, 0) +#if CONFIG_GNUC_AT_LEAST(10, 0) || CONFIG_HAS_GCC_ATTRIBUTE(access) +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(gnu::access) +#define ATTRIBUTE_ACCESS(mode, memory_argument_pos) [[gnu::access(mode, memory_argument_pos)]] +#define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ + [[gnu::access(mode, memory_argument_pos, range_size_argument_pos)]] +#if CONFIG_GNUC_AT_LEAST(11, 0) +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) ATTRIBUTE_ACCESS(none, memory_argument_pos) +#else +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) +#endif +#else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) \ __attribute__((access(mode, memory_argument_pos))) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ @@ -333,6 +348,7 @@ #else #define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) #endif +#endif #else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) @@ -343,25 +359,33 @@ * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html * and https://clang.llvm.org/docs/AttributeReference.html#id664 for more info */ -#if CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) -#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) -#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 && (defined(__GNUG__) || defined(__clang__)) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nonnull) #define ATTRIBUTE_NONNULL(...) [[gnu::nonnull(__VA_ARGS__)]] #define ATTRIBUTE_NONNULL_ALL_ARGS [[gnu::nonnull]] +#elif CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) +#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) #else #define ATTRIBUTE_NONNULL(...) #define ATTRIBUTE_NONNULL_ALL_ARGS #endif -#if CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) -#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) #define ATTRIBUTE_RETURNS_NONNULL [[gnu::returns_nonnull]] +#elif CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) +#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) #else #define ATTRIBUTE_RETURNS_NONNULL #endif +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::target) +#define ATTRIBUTE_TARGET(config_string) [[gnu::target(config_string)]] +#elif CONFIG_GNUC_AT_LEAST(4, 4) || CONFIG_HAS_GCC_ATTRIBUTE(target) +#define ATTRIBUTE_TARGET(config_string) __attribute__((target(config_string))) +#else +#define ATTRIBUTE_TARGET(config_string) +#endif + #if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::lifetimebound) #define ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] #else @@ -374,13 +398,16 @@ #define ATTRIBUTE_REINITIALIZES #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(nodiscard) #define ATTRIBUTE_NODISCARD [[nodiscard]] #if CONFIG_HAS_AT_LEAST_CXX_20 #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #else #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard]] #endif +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(nodiscard) +#define ATTRIBUTE_NODISCARD [[nodiscard]] +#define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(warn_unused_result) #define ATTRIBUTE_NODISCARD __attribute__((warn_unused_result)) #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) __attribute__((warn_unused_result)) @@ -389,9 +416,9 @@ #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) #endif -#if CONFIG_HAS_AT_LEAST_CXX_11 +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] #elif CONFIG_HAS_AT_LEAST_C_11 #define ATTRIBUTE_NORETURN _Noreturn @@ -411,15 +438,17 @@ #define CONFIG_NOEXCEPT_FUNCTION #endif -#if CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nothrow) +#define ATTRIBUTE_NOTHROW [[gnu::nothrow]] +#elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) #define ATTRIBUTE_NOTHROW __attribute__((nothrow)) #else #define ATTRIBUTE_NOTHROW #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] #elif CONFIG_GNUC_AT_LEAST(7, 1) || CONFIG_HAS_GCC_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH __attribute__((fallthrough)) diff --git a/graphs/HungarianAlgorithm/config_macros.hpp b/graphs/HungarianAlgorithm/config_macros.hpp index 8b1a6ff..0672803 100644 --- a/graphs/HungarianAlgorithm/config_macros.hpp +++ b/graphs/HungarianAlgorithm/config_macros.hpp @@ -22,12 +22,6 @@ #define CONFIG_HAS_GCC_ATTRIBUTE(attr) 0 #endif -#if defined(__cplusplus) && defined(__has_cpp_attribute) -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) -#else -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 -#endif - #if defined(__has_builtin) #define CONFIG_HAS_BUILTIN(name) __has_builtin(name) #else @@ -79,6 +73,12 @@ #define CONFIG_HAS_AT_LEAST_CXX_23 0 #endif +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define CONFIG_HAS_AT_LEAST_C_99 1 +#else +#define CONFIG_HAS_AT_LEAST_C_99 0 +#endif + #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define CONFIG_HAS_AT_LEAST_C_11 1 #else @@ -97,6 +97,18 @@ #define CONFIG_HAS_AT_LEAST_C_23 0 #endif +#if CONFIG_HAS_AT_LEAST_C_99 && defined(__has_c_attribute) +#define CONFIG_HAS_C_ATTRIBUTE(attr) __has_c_attribute(attr) +#else +#define CONFIG_HAS_C_ATTRIBUTE(attr) 0 +#endif + +#if CONFIG_HAS_AT_LEAST_CXX_11 && defined(__has_cpp_attribute) +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) +#else +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 +#endif + // https://en.cppreference.com/w/cpp/feature_test #if defined(__cpp_concepts) && __cpp_concepts >= 201907L #define CONFIG_HAS_CONCEPTS 1 @@ -104,9 +116,9 @@ #define CONFIG_HAS_CONCEPTS 0 #endif -/** - * Restrict qualifier for the C++ (C has `restrict` keyword since C99) - */ +#if CONFIG_HAS_AT_LEAST_C_99 +#define RESTRICT_QUALIFIER restrict +#else #if defined(__GNUC__) || defined(__clang__) #define RESTRICT_QUALIFIER __restrict__ #elif defined(_MSC_VER) @@ -114,6 +126,7 @@ #else #define RESTRICT_QUALIFIER #endif +#endif #if defined(__GNUC__) || defined(__clang__) #define FUNCTION_MACRO __PRETTY_FUNCTION__ @@ -127,67 +140,61 @@ #include #endif -#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L -#define CONFIG_UNREACHABLE() std::unreachable() -#elif CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define CONFIG_UNREACHABLE() [[assume(false)]] -#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) -#define CONFIG_UNREACHABLE() __builtin_unreachable() -#elif CONFIG_HAS_BUILTIN(__builtin_assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __builtin_assume(false) -#else -#define CONFIG_UNREACHABLE() __builtin_assume(0) -#endif +#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) +#define CONFIG_ASSUME_STATEMENT(expr) [[assume(expr)]] +#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) +#define CONFIG_ASSUME_STATEMENT(expr) __builtin_assume(expr) #elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __attribute__((assume(false))) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(false))); \ + } \ + } while (false) #else -#define CONFIG_UNREACHABLE() __attribute__((assume(0))) +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(0))); \ + } \ + } while (0) #endif #elif defined(_MSC_VER) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __assume(false) +#define CONFIG_ASSUME_STATEMENT(expr) __assume(expr) #else -#define CONFIG_UNREACHABLE() __assume(0) -#endif -#else -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() \ - do { \ +#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + std::unreachable(); \ + } \ + } while (false) +#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (false) #else -#define CONFIG_UNREACHABLE() \ - do { \ +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (0) #endif +#else +#define CONFIG_ASSUME_STATEMENT(expr) +#endif #endif -#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) [[assume(expr)]] -#elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) __attribute__((assume(expr))) -#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) -// Side effect of expr is discarded -#define ATTRIBUTE_ASSUME(expr) __builtin_assume(expr) -#elif defined(_MSC_VER) -#define ATTRIBUTE_ASSUME(expr) __assume(expr) -#else #if defined(__cplusplus) -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (false) +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(false) #else -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (0) -#endif +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(0) #endif /* __builtin_expect is in gcc 3.0 */ @@ -208,23 +215,22 @@ #define unlikely(x) __builtin_expect((x), 0) #endif -#else +#elif !defined(likely) || !defined(likely) -#if !defined(likely) -#if defined(__cplusplus) -#define likely(x) static_cast(x) -#else -#define likely(x) !!(x) +#if defined(likely) +#undef likely #endif +#if defined(unlikely) +#undef unlikely #endif -#if !defined(unlikely) #if defined(__cplusplus) +#define likely(x) static_cast(x) #define unlikely(x) static_cast(x) #else +#define likely(x) !!(x) #define unlikely(x) !!(x) #endif -#endif #endif @@ -233,69 +239,68 @@ #define __attribute__(...) #endif -#if CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) -#define ATTRIBUTE_CONST __attribute__((__const__)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) #define ATTRIBUTE_CONST [[gnu::__const__]] +#elif CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) +#define ATTRIBUTE_CONST __attribute__((__const__)) #else #define ATTRIBUTE_CONST #endif -#if CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) -#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(maybe_unused) #define ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]] +#elif CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) +#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) #else #define ATTRIBUTE_MAYBE_UNUSED #endif -#if CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) -#define ATTRIBUTE_PURE __attribute__((pure)) -#elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) #define ATTRIBUTE_PURE [[gnu::pure]] +#elif CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) +#define ATTRIBUTE_PURE __attribute__((pure)) #else #define ATTRIBUTE_PURE #endif -#if CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) -#define ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) #define ATTRIBUTE_NOINLINE [[clang::noinline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::noinline) #define ATTRIBUTE_NOINLINE [[gnu::noinline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::noinline) #define ATTRIBUTE_NOINLINE [[msvc::noinline]] -#elif defined(_MSC_VER) && \ - (_MSC_VER >= 1920 || defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017) +#elif defined(_MSC_VER) && _MSC_VER >= 1920 && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017 #define ATTRIBUTE_NOINLINE __declspec(noinline) +#elif CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) +#define ATTRIBUTE_NOINLINE __attribute__((noinline)) #else #define ATTRIBUTE_NOINLINE #endif -#if CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) -#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[clang::always_inline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[gnu::always_inline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::forceinline) #define ATTRIBUTE_ALWAYS_INLINE [[msvc::forceinline]] +#elif CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) +#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) #else #define ATTRIBUTE_ALWAYS_INLINE #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) -#define ATTRIBUTE_COLD __attribute__((cold)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) #define ATTRIBUTE_COLD [[gnu::cold]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) +#define ATTRIBUTE_COLD __attribute__((cold)) #else #define ATTRIBUTE_COLD #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) -#define ATTRIBUTE_HOT __attribute__((hot)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) #define ATTRIBUTE_HOT [[gnu::hot]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) +#define ATTRIBUTE_HOT __attribute__((hot)) #else #define ATTRIBUTE_HOT #endif @@ -306,10 +311,10 @@ * indicate the size of the allocation. * Clang docs: https://clang.llvm.org/docs/AttributeReference.html#alloc-size */ -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) -#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) #define ATTRIBUTE_ALLOC_SIZE(...) [[gnu::alloc_size(__VA_ARGS__)]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) +#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) #else #define ATTRIBUTE_ALLOC_SIZE(...) #endif @@ -323,7 +328,17 @@ * * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html for more info */ -#if CONFIG_GNUC_AT_LEAST(10, 0) +#if CONFIG_GNUC_AT_LEAST(10, 0) || CONFIG_HAS_GCC_ATTRIBUTE(access) +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(gnu::access) +#define ATTRIBUTE_ACCESS(mode, memory_argument_pos) [[gnu::access(mode, memory_argument_pos)]] +#define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ + [[gnu::access(mode, memory_argument_pos, range_size_argument_pos)]] +#if CONFIG_GNUC_AT_LEAST(11, 0) +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) ATTRIBUTE_ACCESS(none, memory_argument_pos) +#else +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) +#endif +#else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) \ __attribute__((access(mode, memory_argument_pos))) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ @@ -333,6 +348,7 @@ #else #define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) #endif +#endif #else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) @@ -343,25 +359,33 @@ * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html * and https://clang.llvm.org/docs/AttributeReference.html#id664 for more info */ -#if CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) -#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) -#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 && (defined(__GNUG__) || defined(__clang__)) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nonnull) #define ATTRIBUTE_NONNULL(...) [[gnu::nonnull(__VA_ARGS__)]] #define ATTRIBUTE_NONNULL_ALL_ARGS [[gnu::nonnull]] +#elif CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) +#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) #else #define ATTRIBUTE_NONNULL(...) #define ATTRIBUTE_NONNULL_ALL_ARGS #endif -#if CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) -#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) #define ATTRIBUTE_RETURNS_NONNULL [[gnu::returns_nonnull]] +#elif CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) +#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) #else #define ATTRIBUTE_RETURNS_NONNULL #endif +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::target) +#define ATTRIBUTE_TARGET(config_string) [[gnu::target(config_string)]] +#elif CONFIG_GNUC_AT_LEAST(4, 4) || CONFIG_HAS_GCC_ATTRIBUTE(target) +#define ATTRIBUTE_TARGET(config_string) __attribute__((target(config_string))) +#else +#define ATTRIBUTE_TARGET(config_string) +#endif + #if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::lifetimebound) #define ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] #else @@ -374,13 +398,16 @@ #define ATTRIBUTE_REINITIALIZES #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(nodiscard) #define ATTRIBUTE_NODISCARD [[nodiscard]] #if CONFIG_HAS_AT_LEAST_CXX_20 #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #else #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard]] #endif +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(nodiscard) +#define ATTRIBUTE_NODISCARD [[nodiscard]] +#define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(warn_unused_result) #define ATTRIBUTE_NODISCARD __attribute__((warn_unused_result)) #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) __attribute__((warn_unused_result)) @@ -389,9 +416,9 @@ #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) #endif -#if CONFIG_HAS_AT_LEAST_CXX_11 +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] #elif CONFIG_HAS_AT_LEAST_C_11 #define ATTRIBUTE_NORETURN _Noreturn @@ -411,15 +438,17 @@ #define CONFIG_NOEXCEPT_FUNCTION #endif -#if CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nothrow) +#define ATTRIBUTE_NOTHROW [[gnu::nothrow]] +#elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) #define ATTRIBUTE_NOTHROW __attribute__((nothrow)) #else #define ATTRIBUTE_NOTHROW #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] #elif CONFIG_GNUC_AT_LEAST(7, 1) || CONFIG_HAS_GCC_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH __attribute__((fallthrough)) diff --git a/graphs/HungarianAlgorithm/hungarian_algo.hpp b/graphs/HungarianAlgorithm/hungarian_algo.hpp index 0e3da68..0c27a09 100644 --- a/graphs/HungarianAlgorithm/hungarian_algo.hpp +++ b/graphs/HungarianAlgorithm/hungarian_algo.hpp @@ -179,10 +179,8 @@ class MinAssignmentGraph final { size_(size) {} [[nodiscard]] - ATTRIBUTE_CONST - static constexpr std::size_t align_size(std::size_t n) noexcept { - n = (n + 32) & ~std::size_t(31); - ATTRIBUTE_ASSUME(n % 32 == 0); + ATTRIBUTE_CONST static constexpr std::size_t align_size(std::size_t n) noexcept { + n = (n + 32) & ~std::size_t{31}; return n; } diff --git a/number_theory/bitmatrix.hpp b/number_theory/bitmatrix.hpp index c48b54c..d669d11 100644 --- a/number_theory/bitmatrix.hpp +++ b/number_theory/bitmatrix.hpp @@ -115,37 +115,37 @@ constexpr void transpose8(const uint8_t (&src)[8], uint8_t (&dst)[8]) noexcept { ((x >> 28) & 0x00000000F0F0F0F0ULL); if constexpr (!AgainstMinorDiagonal) { - dst[0] = uint8_t(x); + dst[0] = static_cast(x); x >>= 8; - dst[1] = uint8_t(x); + dst[1] = static_cast(x); x >>= 8; - dst[2] = uint8_t(x); + dst[2] = static_cast(x); x >>= 8; - dst[3] = uint8_t(x); + dst[3] = static_cast(x); x >>= 8; - dst[4] = uint8_t(x); + dst[4] = static_cast(x); x >>= 8; - dst[5] = uint8_t(x); + dst[5] = static_cast(x); x >>= 8; - dst[6] = uint8_t(x); + dst[6] = static_cast(x); x >>= 8; - dst[7] = uint8_t(x); + dst[7] = static_cast(x); } else { - dst[7] = uint8_t(x); + dst[7] = static_cast(x); x >>= 8; - dst[6] = uint8_t(x); + dst[6] = static_cast(x); x >>= 8; - dst[5] = uint8_t(x); + dst[5] = static_cast(x); x >>= 8; - dst[4] = uint8_t(x); + dst[4] = static_cast(x); x >>= 8; - dst[3] = uint8_t(x); + dst[3] = static_cast(x); x >>= 8; - dst[2] = uint8_t(x); + dst[2] = static_cast(x); x >>= 8; - dst[1] = uint8_t(x); + dst[1] = static_cast(x); x >>= 8; - dst[0] = uint8_t(x); + dst[0] = static_cast(x); } } @@ -453,50 +453,50 @@ struct alignas(std::uint64_t) alignas(word_type) square_bitmatrix { // clang-format off [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr iterator begin() noexcept ATTRIBUTE_LIFETIME_BOUND { return data_.begin(); } [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr iterator end() noexcept ATTRIBUTE_LIFETIME_BOUND { return begin() + N; } [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr const_iterator begin() const noexcept ATTRIBUTE_LIFETIME_BOUND { return data_.begin(); } [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr const_iterator end() const noexcept ATTRIBUTE_LIFETIME_BOUND { return begin() + N; } [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr const_iterator cbegin() const noexcept ATTRIBUTE_LIFETIME_BOUND { return data_.cbegin(); } [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr const_iterator cend() const noexcept ATTRIBUTE_LIFETIME_BOUND { return cbegin() + N; } [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr pointer data() noexcept ATTRIBUTE_LIFETIME_BOUND { return data_.data(); } [[nodiscard]] - ATTRIBUTE_ALWAYS_INLINE ATTRIBUTE_PURE + ATTRIBUTE_ALWAYS_INLINE constexpr const_pointer data() const noexcept ATTRIBUTE_LIFETIME_BOUND { return data_.data(); } diff --git a/number_theory/config_macros.hpp b/number_theory/config_macros.hpp index 8b1a6ff..0672803 100644 --- a/number_theory/config_macros.hpp +++ b/number_theory/config_macros.hpp @@ -22,12 +22,6 @@ #define CONFIG_HAS_GCC_ATTRIBUTE(attr) 0 #endif -#if defined(__cplusplus) && defined(__has_cpp_attribute) -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) -#else -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 -#endif - #if defined(__has_builtin) #define CONFIG_HAS_BUILTIN(name) __has_builtin(name) #else @@ -79,6 +73,12 @@ #define CONFIG_HAS_AT_LEAST_CXX_23 0 #endif +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define CONFIG_HAS_AT_LEAST_C_99 1 +#else +#define CONFIG_HAS_AT_LEAST_C_99 0 +#endif + #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define CONFIG_HAS_AT_LEAST_C_11 1 #else @@ -97,6 +97,18 @@ #define CONFIG_HAS_AT_LEAST_C_23 0 #endif +#if CONFIG_HAS_AT_LEAST_C_99 && defined(__has_c_attribute) +#define CONFIG_HAS_C_ATTRIBUTE(attr) __has_c_attribute(attr) +#else +#define CONFIG_HAS_C_ATTRIBUTE(attr) 0 +#endif + +#if CONFIG_HAS_AT_LEAST_CXX_11 && defined(__has_cpp_attribute) +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) +#else +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 +#endif + // https://en.cppreference.com/w/cpp/feature_test #if defined(__cpp_concepts) && __cpp_concepts >= 201907L #define CONFIG_HAS_CONCEPTS 1 @@ -104,9 +116,9 @@ #define CONFIG_HAS_CONCEPTS 0 #endif -/** - * Restrict qualifier for the C++ (C has `restrict` keyword since C99) - */ +#if CONFIG_HAS_AT_LEAST_C_99 +#define RESTRICT_QUALIFIER restrict +#else #if defined(__GNUC__) || defined(__clang__) #define RESTRICT_QUALIFIER __restrict__ #elif defined(_MSC_VER) @@ -114,6 +126,7 @@ #else #define RESTRICT_QUALIFIER #endif +#endif #if defined(__GNUC__) || defined(__clang__) #define FUNCTION_MACRO __PRETTY_FUNCTION__ @@ -127,67 +140,61 @@ #include #endif -#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L -#define CONFIG_UNREACHABLE() std::unreachable() -#elif CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define CONFIG_UNREACHABLE() [[assume(false)]] -#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) -#define CONFIG_UNREACHABLE() __builtin_unreachable() -#elif CONFIG_HAS_BUILTIN(__builtin_assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __builtin_assume(false) -#else -#define CONFIG_UNREACHABLE() __builtin_assume(0) -#endif +#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) +#define CONFIG_ASSUME_STATEMENT(expr) [[assume(expr)]] +#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) +#define CONFIG_ASSUME_STATEMENT(expr) __builtin_assume(expr) #elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __attribute__((assume(false))) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(false))); \ + } \ + } while (false) #else -#define CONFIG_UNREACHABLE() __attribute__((assume(0))) +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(0))); \ + } \ + } while (0) #endif #elif defined(_MSC_VER) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __assume(false) +#define CONFIG_ASSUME_STATEMENT(expr) __assume(expr) #else -#define CONFIG_UNREACHABLE() __assume(0) -#endif -#else -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() \ - do { \ +#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + std::unreachable(); \ + } \ + } while (false) +#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (false) #else -#define CONFIG_UNREACHABLE() \ - do { \ +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (0) #endif +#else +#define CONFIG_ASSUME_STATEMENT(expr) +#endif #endif -#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) [[assume(expr)]] -#elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) __attribute__((assume(expr))) -#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) -// Side effect of expr is discarded -#define ATTRIBUTE_ASSUME(expr) __builtin_assume(expr) -#elif defined(_MSC_VER) -#define ATTRIBUTE_ASSUME(expr) __assume(expr) -#else #if defined(__cplusplus) -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (false) +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(false) #else -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (0) -#endif +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(0) #endif /* __builtin_expect is in gcc 3.0 */ @@ -208,23 +215,22 @@ #define unlikely(x) __builtin_expect((x), 0) #endif -#else +#elif !defined(likely) || !defined(likely) -#if !defined(likely) -#if defined(__cplusplus) -#define likely(x) static_cast(x) -#else -#define likely(x) !!(x) +#if defined(likely) +#undef likely #endif +#if defined(unlikely) +#undef unlikely #endif -#if !defined(unlikely) #if defined(__cplusplus) +#define likely(x) static_cast(x) #define unlikely(x) static_cast(x) #else +#define likely(x) !!(x) #define unlikely(x) !!(x) #endif -#endif #endif @@ -233,69 +239,68 @@ #define __attribute__(...) #endif -#if CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) -#define ATTRIBUTE_CONST __attribute__((__const__)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) #define ATTRIBUTE_CONST [[gnu::__const__]] +#elif CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) +#define ATTRIBUTE_CONST __attribute__((__const__)) #else #define ATTRIBUTE_CONST #endif -#if CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) -#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(maybe_unused) #define ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]] +#elif CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) +#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) #else #define ATTRIBUTE_MAYBE_UNUSED #endif -#if CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) -#define ATTRIBUTE_PURE __attribute__((pure)) -#elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) #define ATTRIBUTE_PURE [[gnu::pure]] +#elif CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) +#define ATTRIBUTE_PURE __attribute__((pure)) #else #define ATTRIBUTE_PURE #endif -#if CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) -#define ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) #define ATTRIBUTE_NOINLINE [[clang::noinline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::noinline) #define ATTRIBUTE_NOINLINE [[gnu::noinline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::noinline) #define ATTRIBUTE_NOINLINE [[msvc::noinline]] -#elif defined(_MSC_VER) && \ - (_MSC_VER >= 1920 || defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017) +#elif defined(_MSC_VER) && _MSC_VER >= 1920 && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017 #define ATTRIBUTE_NOINLINE __declspec(noinline) +#elif CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) +#define ATTRIBUTE_NOINLINE __attribute__((noinline)) #else #define ATTRIBUTE_NOINLINE #endif -#if CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) -#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[clang::always_inline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[gnu::always_inline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::forceinline) #define ATTRIBUTE_ALWAYS_INLINE [[msvc::forceinline]] +#elif CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) +#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) #else #define ATTRIBUTE_ALWAYS_INLINE #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) -#define ATTRIBUTE_COLD __attribute__((cold)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) #define ATTRIBUTE_COLD [[gnu::cold]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) +#define ATTRIBUTE_COLD __attribute__((cold)) #else #define ATTRIBUTE_COLD #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) -#define ATTRIBUTE_HOT __attribute__((hot)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) #define ATTRIBUTE_HOT [[gnu::hot]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) +#define ATTRIBUTE_HOT __attribute__((hot)) #else #define ATTRIBUTE_HOT #endif @@ -306,10 +311,10 @@ * indicate the size of the allocation. * Clang docs: https://clang.llvm.org/docs/AttributeReference.html#alloc-size */ -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) -#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) #define ATTRIBUTE_ALLOC_SIZE(...) [[gnu::alloc_size(__VA_ARGS__)]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) +#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) #else #define ATTRIBUTE_ALLOC_SIZE(...) #endif @@ -323,7 +328,17 @@ * * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html for more info */ -#if CONFIG_GNUC_AT_LEAST(10, 0) +#if CONFIG_GNUC_AT_LEAST(10, 0) || CONFIG_HAS_GCC_ATTRIBUTE(access) +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(gnu::access) +#define ATTRIBUTE_ACCESS(mode, memory_argument_pos) [[gnu::access(mode, memory_argument_pos)]] +#define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ + [[gnu::access(mode, memory_argument_pos, range_size_argument_pos)]] +#if CONFIG_GNUC_AT_LEAST(11, 0) +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) ATTRIBUTE_ACCESS(none, memory_argument_pos) +#else +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) +#endif +#else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) \ __attribute__((access(mode, memory_argument_pos))) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ @@ -333,6 +348,7 @@ #else #define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) #endif +#endif #else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) @@ -343,25 +359,33 @@ * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html * and https://clang.llvm.org/docs/AttributeReference.html#id664 for more info */ -#if CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) -#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) -#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 && (defined(__GNUG__) || defined(__clang__)) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nonnull) #define ATTRIBUTE_NONNULL(...) [[gnu::nonnull(__VA_ARGS__)]] #define ATTRIBUTE_NONNULL_ALL_ARGS [[gnu::nonnull]] +#elif CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) +#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) #else #define ATTRIBUTE_NONNULL(...) #define ATTRIBUTE_NONNULL_ALL_ARGS #endif -#if CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) -#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) #define ATTRIBUTE_RETURNS_NONNULL [[gnu::returns_nonnull]] +#elif CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) +#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) #else #define ATTRIBUTE_RETURNS_NONNULL #endif +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::target) +#define ATTRIBUTE_TARGET(config_string) [[gnu::target(config_string)]] +#elif CONFIG_GNUC_AT_LEAST(4, 4) || CONFIG_HAS_GCC_ATTRIBUTE(target) +#define ATTRIBUTE_TARGET(config_string) __attribute__((target(config_string))) +#else +#define ATTRIBUTE_TARGET(config_string) +#endif + #if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::lifetimebound) #define ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] #else @@ -374,13 +398,16 @@ #define ATTRIBUTE_REINITIALIZES #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(nodiscard) #define ATTRIBUTE_NODISCARD [[nodiscard]] #if CONFIG_HAS_AT_LEAST_CXX_20 #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #else #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard]] #endif +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(nodiscard) +#define ATTRIBUTE_NODISCARD [[nodiscard]] +#define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(warn_unused_result) #define ATTRIBUTE_NODISCARD __attribute__((warn_unused_result)) #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) __attribute__((warn_unused_result)) @@ -389,9 +416,9 @@ #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) #endif -#if CONFIG_HAS_AT_LEAST_CXX_11 +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] #elif CONFIG_HAS_AT_LEAST_C_11 #define ATTRIBUTE_NORETURN _Noreturn @@ -411,15 +438,17 @@ #define CONFIG_NOEXCEPT_FUNCTION #endif -#if CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nothrow) +#define ATTRIBUTE_NOTHROW [[gnu::nothrow]] +#elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) #define ATTRIBUTE_NOTHROW __attribute__((nothrow)) #else #define ATTRIBUTE_NOTHROW #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] #elif CONFIG_GNUC_AT_LEAST(7, 1) || CONFIG_HAS_GCC_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH __attribute__((fallthrough)) diff --git a/number_theory/fft.hpp b/number_theory/fft.hpp index 40e5353..c0246ee 100644 --- a/number_theory/fft.hpp +++ b/number_theory/fft.hpp @@ -46,7 +46,7 @@ struct private_impl final { ATTRIBUTE_SIZED_ACCESS(read_write, 1, 2) ATTRIBUTE_NONNULL(1) static void forward_or_backward_fft(complex* const p, const std::size_t k) noexcept { - ATTRIBUTE_ASSUME(k > 0 && (k & (k - 1)) == 0); + CONFIG_ASSUME_STATEMENT(k > 0 && (k & (k - 1)) == 0); for (std::size_t i = 1, k_reversed_i = 0; i < k; i++) { // 'Increase' k_reversed_i by one @@ -100,17 +100,17 @@ struct private_impl final { } static void ensure_roots_capacity(const std::size_t n) { - ATTRIBUTE_ASSUME(n > 0 && (n & (n - 1)) == 0); + CONFIG_ASSUME_STATEMENT(n > 0 && (n & (n - 1)) == 0); std::size_t current_len = fft_roots.size(); assert(current_len >= 2 && (current_len & (current_len - 1)) == 0); - ATTRIBUTE_ASSUME(current_len >= 2 && (current_len & (current_len - 1)) == 0); + CONFIG_ASSUME_STATEMENT(current_len >= 2 && (current_len & (current_len - 1)) == 0); if (current_len >= n) { return; } assert(n >= 4); - ATTRIBUTE_ASSUME(n >= 4); + CONFIG_ASSUME_STATEMENT(n >= 4); fft_roots.reserve(n); auto add_point = [fft_roots_data = fft_roots.data(), ¤t_len](std::size_t i) noexcept { @@ -142,7 +142,7 @@ struct private_impl final { inline void forward_backward_fft(complex* p1, complex* p2, const std::size_t n) { assert(n > 0 && (n & (n - 1)) == 0); - ATTRIBUTE_ASSUME(n > 0 && (n & (n - 1)) == 0); + CONFIG_ASSUME_STATEMENT(n > 0 && (n & (n - 1)) == 0); fft::detail::private_impl::ensure_roots_capacity(n); fft::detail::private_impl::forward_or_backward_fft(p1, n); diff --git a/number_theory/gosper_algorithm.hpp b/number_theory/gosper_algorithm.hpp index d04bd6e..55b6890 100644 --- a/number_theory/gosper_algorithm.hpp +++ b/number_theory/gosper_algorithm.hpp @@ -52,13 +52,13 @@ constexpr LoopDetectResult loop_detection_Gosper(Function f, std::int32_t x0) no * m = j - 1 */ const std::uint32_t m = ((((n >> k) - 1) | 1) << k) - 1; - ATTRIBUTE_ASSUME(m < n); + CONFIG_ASSUME_STATEMENT(m < n); const std::uint32_t lambda = n - m; - ATTRIBUTE_ASSUME(lambda >= 1); + CONFIG_ASSUME_STATEMENT(lambda >= 1); const auto mu_upper = m; const auto gap = std::max(1u, lambda - 1) - 1; const auto mu_lower = mu_upper >= gap ? mu_upper - gap : 0; - ATTRIBUTE_ASSUME(mu_lower <= mu_upper); + CONFIG_ASSUME_STATEMENT(mu_lower <= mu_upper); return {mu_lower, mu_upper, lambda}; } } diff --git a/number_theory/integers_128_bit.hpp b/number_theory/integers_128_bit.hpp index 0a1dcca..827f740 100644 --- a/number_theory/integers_128_bit.hpp +++ b/number_theory/integers_128_bit.hpp @@ -287,7 +287,7 @@ inline std::ostream& operator<<(std::ostream& out, int128_t number) { } char* ptr = ::format_impl_uint128_t::uint128_t_format_fill_chars_buffer( - uint128_t(number), &digits[buffer_size - 1]); + static_cast(number), &digits[buffer_size - 1]); if (negative) { *--ptr = '-'; } @@ -352,8 +352,8 @@ inline int print_u128_newline(uint128_t number) noexcept { char digits[buffer_size]; digits[buffer_size - 1] = '\0'; - uint128_t t = uint128_t(number >> 127); - uint128_t number_abs = (uint128_t(number) ^ t) - t; + const uint128_t t = static_cast(number >> 127); + const uint128_t number_abs = (static_cast(number) ^ t) - t; char* ptr = ::format_impl_uint128_t::uint128_t_format_fill_chars_buffer( number_abs, &digits[buffer_size - 1]); diff --git a/number_theory/is_prime.hpp b/number_theory/is_prime.hpp index 4223916..974a4a7 100644 --- a/number_theory/is_prime.hpp +++ b/number_theory/is_prime.hpp @@ -45,24 +45,24 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_prp(uint64_t n, uint64_t a) noexce } } - ATTRIBUTE_ASSUME(a >= 2); - ATTRIBUTE_ASSUME(n % 2 == 1); - ATTRIBUTE_ASSUME(n >= 3); + CONFIG_ASSUME_STATEMENT(a >= 2); + CONFIG_ASSUME_STATEMENT(n % 2 == 1); + CONFIG_ASSUME_STATEMENT(n >= 3); const uint64_t n_minus_1 = n - 1; /* Find q and r satisfying: n - 1 = q * (2^r), q odd */ auto [q, r] = ::math_functions::extract_pow2(n_minus_1); // n - 1 >= 2 => r >= 1 - ATTRIBUTE_ASSUME(r >= 1); - ATTRIBUTE_ASSUME(q % 2 == 1); + CONFIG_ASSUME_STATEMENT(r >= 1); + CONFIG_ASSUME_STATEMENT(q % 2 == 1); // Redundant but still - ATTRIBUTE_ASSUME(q >= 1); + CONFIG_ASSUME_STATEMENT(q >= 1); /* Check a^((2^t)*q) mod n for 0 <= t < r */ // Init test = ((a^q) mod n) uint64_t test = ::math_functions::bin_pow_mod(a, q, n); - ATTRIBUTE_ASSUME(test < n); + CONFIG_ASSUME_STATEMENT(test < n); if (test == 1 || test == n_minus_1) { return true; } @@ -70,9 +70,9 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_prp(uint64_t n, uint64_t a) noexce // Since n is odd and n - 1 is even >= 2, initially r > 0. while (--r) { /* test = (test ^ 2) % n */ - ATTRIBUTE_ASSUME(test < n); + CONFIG_ASSUME_STATEMENT(test < n); test = uint64_t((uint128_t(test) * test) % n); - ATTRIBUTE_ASSUME(test < n); + CONFIG_ASSUME_STATEMENT(test < n); if (test == n_minus_1) { return true; } @@ -113,20 +113,20 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_lucas_prp(uint64_t n, uint32_t p, } } - ATTRIBUTE_ASSUME(d != 0); - ATTRIBUTE_ASSUME(n % 2 == 1); - ATTRIBUTE_ASSUME(n >= 3); + CONFIG_ASSUME_STATEMENT(d != 0); + CONFIG_ASSUME_STATEMENT(n % 2 == 1); + CONFIG_ASSUME_STATEMENT(n >= 3); /* nmj = n - (D/n), where (D/n) is the Jacobi symbol */ uint64_t nmj = n - uint64_t(int64_t(::math_functions::kronecker_symbol(d, n))); - ATTRIBUTE_ASSUME(nmj >= 2); + CONFIG_ASSUME_STATEMENT(nmj >= 2); /* Find s and r satisfying: nmj = s * (2 ^ r), s odd */ const auto [s, r] = ::math_functions::extract_pow2(nmj); - ATTRIBUTE_ASSUME(r >= 1); - ATTRIBUTE_ASSUME(s % 2 == 1); + CONFIG_ASSUME_STATEMENT(r >= 1); + CONFIG_ASSUME_STATEMENT(s % 2 == 1); // Redundant but still - ATTRIBUTE_ASSUME(s >= 1); + CONFIG_ASSUME_STATEMENT(s >= 1); /** * make sure U_s == 0 mod n or V_((2^t)*s) == 0 mod n, @@ -139,119 +139,119 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_lucas_prp(uint64_t n, uint32_t p, uint64_t qh = 1; // q mod n const uint64_t widen_q = (q >= 0 ? uint32_t(q) : (n - (uint64_t(-uint32_t(q)) % n))) % n; - ATTRIBUTE_ASSUME(widen_q < n); + CONFIG_ASSUME_STATEMENT(widen_q < n); // n >= 3 => n - 1 >= 2 => n - 1 >= 1 => s >= 1 for (uint32_t j = ::math_functions::log2_floor(s); j != 0; j--) { - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); /* ql = ql*qh (mod n) */ ql = uint64_t((uint128_t(ql) * qh) % n); - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); if (s & (uint64_t(1) << j)) { - ATTRIBUTE_ASSUME(qh < n); + CONFIG_ASSUME_STATEMENT(qh < n); /* qh = ql*q */ qh = uint64_t((uint128_t(ql) * widen_q) % n); - ATTRIBUTE_ASSUME(qh < n); + CONFIG_ASSUME_STATEMENT(qh < n); - ATTRIBUTE_ASSUME(uh < n); + CONFIG_ASSUME_STATEMENT(uh < n); /* uh = uh*vh (mod n) */ uh = uint64_t((uint128_t(uh) * vh) % n); - ATTRIBUTE_ASSUME(uh < n); + CONFIG_ASSUME_STATEMENT(uh < n); - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(vl < n); /* vl = vh*vl - p*ql (mod n) */ uint64_t vh_vl = uint64_t((uint128_t(vh) * vl) % n); uint64_t p_ql = uint64_t((p * uint128_t(ql)) % n); - ATTRIBUTE_ASSUME(vh_vl < n); - ATTRIBUTE_ASSUME(p_ql < n); + CONFIG_ASSUME_STATEMENT(vh_vl < n); + CONFIG_ASSUME_STATEMENT(p_ql < n); uint64_t tmp_vl = vh_vl - p_ql; vl = vh_vl >= p_ql ? tmp_vl : tmp_vl + n; - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(vl < n); - ATTRIBUTE_ASSUME(vh < n); + CONFIG_ASSUME_STATEMENT(vh < n); /* vh = vh*vh - 2*qh (mod n) */ uint64_t vh_vh = uint64_t((uint128_t(vh) * vh) % n); - ATTRIBUTE_ASSUME(vh_vh < n); + CONFIG_ASSUME_STATEMENT(vh_vh < n); uint128_t tmp_qh_2 = 2 * uint128_t(qh); - ATTRIBUTE_ASSUME(tmp_qh_2 <= 2 * uint128_t(n - 1)); + CONFIG_ASSUME_STATEMENT(tmp_qh_2 <= 2 * uint128_t(n - 1)); uint64_t qh_2 = tmp_qh_2 < n ? uint64_t(tmp_qh_2) : uint64_t(tmp_qh_2 - n); - ATTRIBUTE_ASSUME(qh_2 < n); - ATTRIBUTE_ASSUME(qh_2 == (uint128_t(qh) * 2) % n); + CONFIG_ASSUME_STATEMENT(qh_2 < n); + CONFIG_ASSUME_STATEMENT(qh_2 == (uint128_t(qh) * 2) % n); uint64_t tmp_vh = vh_vh - qh_2; vh = vh_vh >= qh_2 ? tmp_vh : tmp_vh + n; - ATTRIBUTE_ASSUME(vh < n); + CONFIG_ASSUME_STATEMENT(vh < n); } else { /* qh = ql */ qh = ql; - ATTRIBUTE_ASSUME(uh < n); - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(uh < n); + CONFIG_ASSUME_STATEMENT(vl < n); /* uh = uh*vl - ql (mod n) */ uint64_t uh_vl = uint64_t((uint128_t(uh) * vl) % n); - ATTRIBUTE_ASSUME(uh_vl < n); - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(uh_vl < n); + CONFIG_ASSUME_STATEMENT(ql < n); uint64_t tmp_uh = uh_vl - ql; uh = uh_vl >= ql ? tmp_uh : tmp_uh + n; - ATTRIBUTE_ASSUME(uh < n); + CONFIG_ASSUME_STATEMENT(uh < n); - ATTRIBUTE_ASSUME(vh < n); - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(vh < n); + CONFIG_ASSUME_STATEMENT(vl < n); /* vh = vh*vl - p*ql (mod n) */ uint64_t vh_vl = uint64_t((uint128_t(vh) * vl) % n); uint64_t p_ql = uint64_t((p * uint128_t(ql)) % n); - ATTRIBUTE_ASSUME(vh_vl < n); - ATTRIBUTE_ASSUME(p_ql < n); + CONFIG_ASSUME_STATEMENT(vh_vl < n); + CONFIG_ASSUME_STATEMENT(p_ql < n); uint64_t tmp_vh = vh_vl - p_ql; vh = vh_vl >= p_ql ? tmp_vh : tmp_vh + n; - ATTRIBUTE_ASSUME(vh < n); + CONFIG_ASSUME_STATEMENT(vh < n); - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(vl < n); /* vl = vl*vl - 2*ql (mod n) */ uint64_t vl_vl = uint64_t((uint128_t(vl) * vl) % n); - ATTRIBUTE_ASSUME(vl_vl < n); + CONFIG_ASSUME_STATEMENT(vl_vl < n); uint128_t tmp_ql_2 = 2 * uint128_t(ql); - ATTRIBUTE_ASSUME(tmp_ql_2 <= 2 * uint128_t(n - 1)); + CONFIG_ASSUME_STATEMENT(tmp_ql_2 <= 2 * uint128_t(n - 1)); uint64_t ql_2 = tmp_ql_2 < n ? uint64_t(tmp_ql_2) : uint64_t(tmp_ql_2 - n); - ATTRIBUTE_ASSUME(ql_2 < n); - ATTRIBUTE_ASSUME(ql_2 == (uint128_t(ql) * 2) % n); + CONFIG_ASSUME_STATEMENT(ql_2 < n); + CONFIG_ASSUME_STATEMENT(ql_2 == (uint128_t(ql) * 2) % n); uint64_t tmp_vl = vl_vl - ql_2; vl = vl_vl >= ql_2 ? tmp_vl : tmp_vl + n; - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(vl < n); } } - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); /* ql = ql*qh */ ql = uint64_t((uint128_t(ql) * qh) % n); - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); - ATTRIBUTE_ASSUME(qh < n); + CONFIG_ASSUME_STATEMENT(qh < n); /* qh = ql*q */ qh = uint64_t((uint128_t(ql) * widen_q) % n); - ATTRIBUTE_ASSUME(qh < n); + CONFIG_ASSUME_STATEMENT(qh < n); - ATTRIBUTE_ASSUME(uh < n); + CONFIG_ASSUME_STATEMENT(uh < n); /* uh = uh*vl - ql (mod n) */ uint64_t uh_vl = uint64_t((uint128_t(uh) * vl) % n); - ATTRIBUTE_ASSUME(uh_vl < n); - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(uh_vl < n); + CONFIG_ASSUME_STATEMENT(ql < n); uint64_t tmp_uh = uh_vl - ql; uh = uh_vl >= ql ? tmp_uh : tmp_uh + n; - ATTRIBUTE_ASSUME(uh < n); - ATTRIBUTE_ASSUME(uh == (uint128_t(n) + uh_vl - ql) % n); + CONFIG_ASSUME_STATEMENT(uh < n); + CONFIG_ASSUME_STATEMENT(uh == (uint128_t(n) + uh_vl - ql) % n); /* uh contains LucasU_s */ if (uh == 0) { return true; } - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(vl < n); /* vl = vh*vl - p*ql (mod n) */ uint64_t vh_vl = uint64_t((uint128_t(vh) * vl) % n); uint64_t p_ql = uint64_t((p * uint128_t(ql)) % n); uint64_t tmp_vl = vh_vl - p_ql; vl = vh_vl >= p_ql ? tmp_vl : tmp_vl + n; - ATTRIBUTE_ASSUME(vl < n); - ATTRIBUTE_ASSUME(vl == (uint128_t(n) + vh_vl - p_ql) % n); + CONFIG_ASSUME_STATEMENT(vl < n); + CONFIG_ASSUME_STATEMENT(vl == (uint128_t(n) + vh_vl - p_ql) % n); /* uh contains LucasU_s and vl contains LucasV_s */ if (vl == 0) { @@ -259,34 +259,34 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_lucas_prp(uint64_t n, uint32_t p, return true; } - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); /* ql = ql*qh */ ql = uint64_t((uint128_t(ql) * qh) % n); - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); /* r - 1 for mpz_extrastronglucas_prp */ for (uint32_t j = 1; j < r; j++) { - ATTRIBUTE_ASSUME(vl < n); + CONFIG_ASSUME_STATEMENT(vl < n); /* vl = vl*vl - 2*ql (mod n) */ uint64_t vl_vl = uint64_t((uint128_t(vl) * vl) % n); - ATTRIBUTE_ASSUME(vl_vl < n); + CONFIG_ASSUME_STATEMENT(vl_vl < n); uint128_t tmp_ql_2 = 2 * uint128_t(ql); - ATTRIBUTE_ASSUME(tmp_ql_2 <= 2 * uint128_t(n - 1)); + CONFIG_ASSUME_STATEMENT(tmp_ql_2 <= 2 * uint128_t(n - 1)); uint64_t ql_2 = tmp_ql_2 < n ? uint64_t(tmp_ql_2) : uint64_t(tmp_ql_2 - n); - ATTRIBUTE_ASSUME(ql_2 < n); - ATTRIBUTE_ASSUME(ql_2 == (uint128_t(ql) * 2) % n); + CONFIG_ASSUME_STATEMENT(ql_2 < n); + CONFIG_ASSUME_STATEMENT(ql_2 == (uint128_t(ql) * 2) % n); tmp_vl = vl_vl - ql_2; vl = vl_vl >= ql_2 ? tmp_vl : tmp_vl + n; - ATTRIBUTE_ASSUME(vl < n); - ATTRIBUTE_ASSUME(vl == (uint128_t(n) + vl_vl - ql_2) % n); + CONFIG_ASSUME_STATEMENT(vl < n); + CONFIG_ASSUME_STATEMENT(vl == (uint128_t(n) + vl_vl - ql_2) % n); if (vl == 0) { return true; } - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); /* ql = ql*ql (mod n) */ ql = uint64_t((uint128_t(ql) * ql) % n); - ATTRIBUTE_ASSUME(ql < n); + CONFIG_ASSUME_STATEMENT(ql < n); } return false; @@ -312,9 +312,9 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_selfridge_prp(uint64_t n) noexcept } } - ATTRIBUTE_ASSUME(n % 2 == 1); + CONFIG_ASSUME_STATEMENT(n % 2 == 1); // Redundant but still - ATTRIBUTE_ASSUME(n >= 1); + CONFIG_ASSUME_STATEMENT(n >= 1); constexpr std::int32_t kStep = 2; for (int32_t d = 5;; d += (d > 0) ? kStep : -kStep, d = -d) { constexpr std::int32_t kMaxD = 999'997; @@ -341,10 +341,10 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_selfridge_prp(uint64_t n) noexcept } break; case -1: { - ATTRIBUTE_ASSUME(d <= kMaxD + kStep * 2); - ATTRIBUTE_ASSUME((1 - d) % 4 == 0); + CONFIG_ASSUME_STATEMENT(d <= kMaxD + kStep * 2); + CONFIG_ASSUME_STATEMENT((1 - d) % 4 == 0); const std::int32_t q = (1 - d) / 4; - ATTRIBUTE_ASSUME(1 - 4 * q == d); + CONFIG_ASSUME_STATEMENT(1 - 4 * q == d); return ::math_functions::detail::is_strong_lucas_prp(n, 1, q); } default: @@ -571,7 +571,7 @@ ATTRIBUTE_CONST I128_CONSTEXPR bool is_strong_selfridge_prp(uint64_t n) noexcept return false; } const auto [q, p] = ::math_functions::extract_pow2(np1); - ATTRIBUTE_ASSUME(q == 1); + CONFIG_ASSUME_STATEMENT(q == 1); switch (p) { case 2: diff --git a/number_theory/kronecker_symbol.hpp b/number_theory/kronecker_symbol.hpp index d0ff081..550fcfc 100644 --- a/number_theory/kronecker_symbol.hpp +++ b/number_theory/kronecker_symbol.hpp @@ -27,7 +27,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_ui(Uint a, Uint n) noexc } auto [q, p] = ::math_functions::extract_pow2(n); - ATTRIBUTE_ASSUME(q % 2 == 1); + CONFIG_ASSUME_STATEMENT(q % 2 == 1); n = q; switch (a % 8) { @@ -43,7 +43,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_ui(Uint a, Uint n) noexc // a === +-3 (mod 8) // t = (-1) ^ p t -= static_cast((p % 2) * 2); - ATTRIBUTE_ASSUME(t == -1 || t == 1); + CONFIG_ASSUME_STATEMENT(t == -1 || t == 1); break; case 1: case 7: @@ -57,9 +57,9 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_ui(Uint a, Uint n) noexc } } - ATTRIBUTE_ASSUME(n % 2 == 1); + CONFIG_ASSUME_STATEMENT(n % 2 == 1); // Redundant but still - ATTRIBUTE_ASSUME(n != 0); + CONFIG_ASSUME_STATEMENT(n != 0); // step 1 a %= n; Uint r = 0; @@ -70,7 +70,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_ui(Uint a, Uint n) noexc auto [a_odd_part, a_exp] = ::math_functions::extract_pow2(a); a = a_odd_part; r = n % 8; - ATTRIBUTE_ASSUME(r <= 7); + CONFIG_ASSUME_STATEMENT(r <= 7); switch (r) { case 3: case 5: @@ -91,7 +91,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_ui(Uint a, Uint n) noexc a %= n; } - ATTRIBUTE_ASSUME(t == -1 || t == 1); + CONFIG_ASSUME_STATEMENT(t == -1 || t == 1); return (n == 1) ? t : 0; } @@ -113,7 +113,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_si(Sint a, Sint n) noexc } auto [q, p] = ::math_functions::extract_pow2(n_u); - ATTRIBUTE_ASSUME(q % 2 == 1); + CONFIG_ASSUME_STATEMENT(q % 2 == 1); n_u = q; switch (static_cast((a % 8) + 8) % 8) { @@ -129,7 +129,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_si(Sint a, Sint n) noexc // a === +-3 (mod 8) // t = (-1) ^ p t -= static_cast((p % 2) * 2); - ATTRIBUTE_ASSUME(t == -1 || t == 1); + CONFIG_ASSUME_STATEMENT(t == -1 || t == 1); break; case 1: case 7: @@ -143,9 +143,9 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_si(Sint a, Sint n) noexc } } - ATTRIBUTE_ASSUME(n_u % 2 == 1); + CONFIG_ASSUME_STATEMENT(n_u % 2 == 1); // Redundant but still - ATTRIBUTE_ASSUME(n_u > 0); + CONFIG_ASSUME_STATEMENT(n_u > 0); // step 1 Uint a_u = (static_cast(a % static_cast(n_u)) + n_u) % n_u; Uint r = 0; @@ -156,7 +156,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_si(Sint a, Sint n) noexc auto [a_u_odd_part, a_u_exp] = ::math_functions::extract_pow2(a_u); a_u = a_u_odd_part; r = n_u % 8; - ATTRIBUTE_ASSUME(r <= 7); + CONFIG_ASSUME_STATEMENT(r <= 7); switch (r) { case 3: case 5: @@ -177,7 +177,7 @@ ATTRIBUTE_CONST constexpr std::int32_t kronecker_symbol_si(Sint a, Sint n) noexc a_u %= n_u; } - ATTRIBUTE_ASSUME(t == -1 || t == 1); + CONFIG_ASSUME_STATEMENT(t == -1 || t == 1); return (n_u == 1) ? (!carry ? t : -t) : 0; } @@ -196,7 +196,7 @@ ATTRIBUTE_CONST constexpr int32_t kronecker_symbol_si_ui(Sint a, Uint n) noexcep } auto [q, p] = ::math_functions::extract_pow2(n); - ATTRIBUTE_ASSUME(q % 2 == 1); + CONFIG_ASSUME_STATEMENT(q % 2 == 1); n = q; switch (static_cast((a % 8) + 8) % 8) { @@ -212,7 +212,7 @@ ATTRIBUTE_CONST constexpr int32_t kronecker_symbol_si_ui(Sint a, Uint n) noexcep // a === +-3 (mod 8) // t = (-1) ^ p t -= static_cast((p % 2) * 2); - ATTRIBUTE_ASSUME(t == -1 || t == 1); + CONFIG_ASSUME_STATEMENT(t == -1 || t == 1); break; case 1: case 7: @@ -226,9 +226,9 @@ ATTRIBUTE_CONST constexpr int32_t kronecker_symbol_si_ui(Sint a, Uint n) noexcep } } - ATTRIBUTE_ASSUME(n % 2 == 1); + CONFIG_ASSUME_STATEMENT(n % 2 == 1); // Redundant but still - ATTRIBUTE_ASSUME(n != 0); + CONFIG_ASSUME_STATEMENT(n != 0); // step 1 // a_u = a mod n Uint a_u = (a >= 0 ? static_cast(a) : (n - (-static_cast(a)) % n)) % n; @@ -260,7 +260,7 @@ ATTRIBUTE_CONST constexpr int32_t kronecker_symbol_si_ui(Sint a, Uint n) noexcep a_u %= n; } - ATTRIBUTE_ASSUME(t == -1 || t == 1); + CONFIG_ASSUME_STATEMENT(t == -1 || t == 1); return (n == 1) ? t : 0; } diff --git a/number_theory/longint.hpp b/number_theory/longint.hpp index aaa091f..0789ba1 100644 --- a/number_theory/longint.hpp +++ b/number_theory/longint.hpp @@ -219,13 +219,13 @@ inline void Deallocate(void* memory) noexcept { #if CONFIG_GNUC_AT_LEAST(2, 96) #if IS_INLINE_LONGINT_ALLOCATE || defined(__clang__) || defined(__MINGW32__) || \ !CONFIG_GNUC_AT_LEAST(10, 0) -__attribute__((malloc)) +[[gnu::malloc]] #else -__attribute__((malloc, malloc(::longint_allocator::Deallocate, 1))) +[[gnu::malloc, gnu::malloc(::longint_allocator::Deallocate, 1)]] #endif #endif -ATTRIBUTE_RETURNS_NONNULL -ATTRIBUTE_ALLOC_SIZE(1) INLINE_LONGINT_ALLOCATE void* Allocate(std::size_t size) { +ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_ALLOC_SIZE(1) INLINE_LONGINT_ALLOCATE + void* Allocate(std::size_t size) { if (size <= inner_impl::SmallPage::kCapacity && inner_impl::free_small_pages_head != nullptr) { inner_impl::SmallPage* p = inner_impl::free_small_pages_head; #ifdef DEBUG_LI_ALLOC_PRINTING @@ -678,10 +678,10 @@ struct longint { static_assert(max_size() + 1 > max_size()); const size_type usize1 = set_size_at_least(std::max(usize(), usize2) + (find_sum ? 1 : 0)); LONGINT_DEBUG_ASSERT(usize1 >= usize2); - ATTRIBUTE_ASSUME(usize1 >= usize2); + CONFIG_ASSUME_STATEMENT(usize1 >= usize2); if (find_sum) { LONGINT_DEBUG_ASSERT(usize1 > usize2); - ATTRIBUTE_ASSUME(usize1 > usize2); + CONFIG_ASSUME_STATEMENT(usize1 > usize2); longint_add_with_free_space(nums_, usize1, other.nums_, usize2); } else { if (longint_subtract_with_free_space(nums_, usize1, other.nums_, usize2)) { @@ -874,13 +874,14 @@ struct longint { return size_ < other.size_; } - const size_type usize_value = usize(); - const uint32_t* r_end = nums_ - 1; - const uint32_t* r_nums = r_end + usize_value; - const uint32_t* r_other_nums = other.nums_ - 1 + usize_value; + const size_type usize_value = usize(); + const digit_t* r_end = nums_ - 1; + const digit_t* r_nums = r_end + usize_value; + const digit_t* r_other_nums = other.nums_ - 1 + usize_value; for (; r_nums != r_end; r_nums--, r_other_nums--) { if (*r_nums != *r_other_nums) { - return int64_t(*r_nums) * sign() < int64_t(*r_other_nums) * other.sign(); + static_assert(sizeof(int64_t) == sizeof(double_digit_t), ""); + return int64_t{*r_nums} * sign() < int64_t{*r_other_nums} * other.sign(); } } @@ -1438,7 +1439,7 @@ struct longint { return *this; } LONGINT_DEBUG_ASSERT(1 <= m && m <= k); - ATTRIBUTE_ASSUME(1 <= m && m <= k); + CONFIG_ASSUME_STATEMENT(1 <= m && m <= k); const dec_size_type new_size = m + k; if (m <= 16 || m * k <= 1024) { DecNaive::multiply_and_store_to(m_ptr, m, k_ptr, k, *this); @@ -1563,7 +1564,7 @@ struct longint { const dec_digit_t k_digits[], const dec_size_type k_size, Decimal& product_result) { LONGINT_DEBUG_ASSERT(m_size <= k_size); - ATTRIBUTE_ASSUME(m_size <= k_size); + CONFIG_ASSUME_STATEMENT(m_size <= k_size); const dec_size_type new_size = m_size + k_size; dec_digit_t* const ans = allocate(new_size); std::fill_n(ans, new_size, dec_digit_t{0}); @@ -1679,7 +1680,7 @@ struct longint { ATTRIBUTE_ALWAYS_INLINE static constexpr dec_size_type polys_size(const dec_size_type size_value) noexcept { LONGINT_DEBUG_ASSERT(size_value <= kMaxDecFFTSize); - ATTRIBUTE_ASSUME(size_value <= kMaxDecFFTSize); + CONFIG_ASSUME_STATEMENT(size_value <= kMaxDecFFTSize); static_assert(3 * kMaxDecFFTSize > kMaxDecFFTSize); static_assert( 3 * kMaxDecFFTSize < @@ -1837,7 +1838,7 @@ struct longint { constexpr dec_size_type poly_size() const noexcept { const auto value = poly_size_; LONGINT_DEBUG_ASSERT(math_functions::is_power_of_two(value)); - ATTRIBUTE_ASSUME(math_functions::is_power_of_two(value)); + CONFIG_ASSUME_STATEMENT(math_functions::is_power_of_two(value)); return value; } @@ -1882,7 +1883,7 @@ struct longint { const digit_t k_ptr[], const size_type k, digit_t* const ans) noexcept { LONGINT_DEBUG_ASSERT(m <= k); - ATTRIBUTE_ASSUME(m <= k); + CONFIG_ASSUME_STATEMENT(m <= k); digit_t* ans_store_ptr = ans; for (size_type j = 0; j < m; ans_store_ptr++, j++) { const double_digit_t b_j = m_ptr[j]; @@ -1916,7 +1917,7 @@ struct longint { n *= 2; } LONGINT_DEBUG_ASSERT(math_functions::is_power_of_two(n)); - ATTRIBUTE_ASSUME(math_functions::is_power_of_two(n)); + CONFIG_ASSUME_STATEMENT(math_functions::is_power_of_two(n)); return {n, need_high_precision}; } @@ -1969,23 +1970,23 @@ struct longint { fft::complex* p, const poly_size_type n, bool need_high_precision) noexcept { LONGINT_DEBUG_ASSERT(0 < m); - ATTRIBUTE_ASSUME(0 < m); + CONFIG_ASSUME_STATEMENT(0 < m); LONGINT_DEBUG_ASSERT(m <= k); - ATTRIBUTE_ASSUME(m <= k); + CONFIG_ASSUME_STATEMENT(m <= k); LONGINT_DEBUG_ASSERT(m <= max_size()); - ATTRIBUTE_ASSUME(m <= max_size()); + CONFIG_ASSUME_STATEMENT(m <= max_size()); LONGINT_DEBUG_ASSERT(k <= max_size()); - ATTRIBUTE_ASSUME(k <= max_size()); + CONFIG_ASSUME_STATEMENT(k <= max_size()); LONGINT_DEBUG_ASSERT(m + k <= max_size()); - ATTRIBUTE_ASSUME(m + k <= max_size()); + CONFIG_ASSUME_STATEMENT(m + k <= max_size()); LONGINT_DEBUG_ASSERT(m + k <= n); - ATTRIBUTE_ASSUME(m + k <= n); + CONFIG_ASSUME_STATEMENT(m + k <= n); LONGINT_DEBUG_ASSERT(need_high_precision || n <= kFFTPrecisionBorder); - ATTRIBUTE_ASSUME(need_high_precision || n <= kFFTPrecisionBorder); + CONFIG_ASSUME_STATEMENT(need_high_precision || n <= kFFTPrecisionBorder); LONGINT_DEBUG_ASSERT(!need_high_precision || n > kFFTPrecisionBorder * 2); - ATTRIBUTE_ASSUME(!need_high_precision || n > kFFTPrecisionBorder * 2); + CONFIG_ASSUME_STATEMENT(!need_high_precision || n > kFFTPrecisionBorder * 2); LONGINT_DEBUG_ASSERT(math_functions::is_power_of_two(n)); - ATTRIBUTE_ASSUME(math_functions::is_power_of_two(n)); + CONFIG_ASSUME_STATEMENT(math_functions::is_power_of_two(n)); static_assert(kNumsBits == 32); if (likely(!need_high_precision)) { @@ -2065,17 +2066,17 @@ struct longint { const poly_size_type n, bool need_high_precision) noexcept { LONGINT_DEBUG_ASSERT(0 < nums_size); - ATTRIBUTE_ASSUME(0 < nums_size); + CONFIG_ASSUME_STATEMENT(0 < nums_size); LONGINT_DEBUG_ASSERT(nums_size <= max_size()); - ATTRIBUTE_ASSUME(nums_size <= max_size()); + CONFIG_ASSUME_STATEMENT(nums_size <= max_size()); LONGINT_DEBUG_ASSERT(nums_size * 2 <= n); - ATTRIBUTE_ASSUME(nums_size * 2 <= n); + CONFIG_ASSUME_STATEMENT(nums_size * 2 <= n); LONGINT_DEBUG_ASSERT(need_high_precision || n <= kFFTPrecisionBorder); - ATTRIBUTE_ASSUME(need_high_precision || n <= kFFTPrecisionBorder); + CONFIG_ASSUME_STATEMENT(need_high_precision || n <= kFFTPrecisionBorder); LONGINT_DEBUG_ASSERT(!need_high_precision || n > kFFTPrecisionBorder * 2); - ATTRIBUTE_ASSUME(!need_high_precision || n > kFFTPrecisionBorder * 2); + CONFIG_ASSUME_STATEMENT(!need_high_precision || n > kFFTPrecisionBorder * 2); LONGINT_DEBUG_ASSERT(math_functions::is_power_of_two(n)); - ATTRIBUTE_ASSUME(math_functions::is_power_of_two(n)); + CONFIG_ASSUME_STATEMENT(math_functions::is_power_of_two(n)); static_assert(kNumsBits == 32); if (likely(!need_high_precision)) { @@ -2180,13 +2181,13 @@ struct longint { const digit_t* const v = other.nums_; const digit_t last_v_num = v[n - 1]; LONGINT_DEBUG_ASSERT(last_v_num > 0); - ATTRIBUTE_ASSUME(last_v_num > 0); + CONFIG_ASSUME_STATEMENT(last_v_num > 0); static_assert(kNumsBits == 32); // 0 <= s < kNumsBits const auto s = static_cast(math_functions::countl_zero(last_v_num)); longint::divmod_normalize_vn(vn, v, n, s); LONGINT_DEBUG_ASSERT(vn[n - 1] >= digit_t{1} << (kNumsBits - 1)); - ATTRIBUTE_ASSUME(vn[n - 1] >= digit_t{1} << (kNumsBits - 1)); + CONFIG_ASSUME_STATEMENT(vn[n - 1] >= digit_t{1} << (kNumsBits - 1)); longint::divmod_normalize_un(un, u, m, m + 1, s); longint::divmod_impl_unchecked( /* un = */ un, @@ -2213,32 +2214,32 @@ struct longint { const size_type vn_size, digit_t* RESTRICT_QUALIFIER const quot) noexcept { LONGINT_DEBUG_ASSERT(vn_size >= 2); - ATTRIBUTE_ASSUME(vn_size >= 2); + CONFIG_ASSUME_STATEMENT(vn_size >= 2); LONGINT_DEBUG_ASSERT(un_size > vn_size); - ATTRIBUTE_ASSUME(un_size > vn_size); + CONFIG_ASSUME_STATEMENT(un_size > vn_size); for (size_type j = un_size - vn_size - 1; static_cast(j) >= 0; j--) { // Compute estimate qhat of q[j]. const double_digit_t cur = (double_digit_t{un[j + vn_size]} << kNumsBits) | un[j + vn_size - 1]; const digit_t last_vn = vn[vn_size - 1]; LONGINT_DEBUG_ASSERT(last_vn >= digit_t{1} << (kNumsBits - 1)); - ATTRIBUTE_ASSUME(last_vn >= digit_t{1} << (kNumsBits - 1)); + CONFIG_ASSUME_STATEMENT(last_vn >= digit_t{1} << (kNumsBits - 1)); double_digit_t qhat = cur / last_vn; double_digit_t rhat = cur % last_vn; LONGINT_DEBUG_ASSERT(qhat * last_vn + rhat == cur); - ATTRIBUTE_ASSUME(qhat * last_vn + rhat == cur); + CONFIG_ASSUME_STATEMENT(qhat * last_vn + rhat == cur); while (qhat >= kNumsBase || qhat * vn[vn_size - 2] > kNumsBase * rhat + un[j + vn_size - 2]) { qhat--; rhat += last_vn; LONGINT_DEBUG_ASSERT(qhat * last_vn + rhat == cur); - ATTRIBUTE_ASSUME(qhat * last_vn + rhat == cur); + CONFIG_ASSUME_STATEMENT(qhat * last_vn + rhat == cur); if (rhat >= kNumsBase) { break; } } LONGINT_DEBUG_ASSERT(qhat * last_vn + rhat == cur); - ATTRIBUTE_ASSUME(qhat * last_vn + rhat == cur); + CONFIG_ASSUME_STATEMENT(qhat * last_vn + rhat == cur); // Multiply and subtract double_digit_t t = divmod_mult_sub(un + j, vn, vn_size, qhat); quot[j] = static_cast(qhat); // Store quotient digit @@ -2269,7 +2270,7 @@ struct longint { const size_type vn_size, const double_digit_t qhat) noexcept { LONGINT_DEBUG_ASSERT(vn_size >= 2); - ATTRIBUTE_ASSUME(vn_size >= 2); + CONFIG_ASSUME_STATEMENT(vn_size >= 2); double_digit_t carry = 0; for (size_type i = 0; i < vn_size; i++) { double_digit_t p = qhat * vn[i]; @@ -2290,7 +2291,7 @@ struct longint { const digit_t* RESTRICT_QUALIFIER const vn, const size_type vn_size) noexcept { LONGINT_DEBUG_ASSERT(vn_size >= 2); - ATTRIBUTE_ASSUME(vn_size >= 2); + CONFIG_ASSUME_STATEMENT(vn_size >= 2); double_digit_t carry = 0; for (size_type i = 0; i < vn_size; i++) { double_digit_t t = double_digit_t{un[i]} + double_digit_t{vn[i]} + carry; @@ -2307,9 +2308,9 @@ struct longint { static constexpr void divmod_normalize_vn(digit_t vn[], const digit_t v[], size_type n, std::uint32_t s) noexcept { LONGINT_DEBUG_ASSERT(n > 1); - ATTRIBUTE_ASSUME(n > 1); + CONFIG_ASSUME_STATEMENT(n > 1); LONGINT_DEBUG_ASSERT(s < 32); - ATTRIBUTE_ASSUME(s < 32); + CONFIG_ASSUME_STATEMENT(s < 32); for (size_type i = n - 1; i > 0; i--) { vn[i] = (v[i] << s) | static_cast(double_digit_t{v[i - 1]} >> (kNumsBits - s)); } @@ -2324,11 +2325,11 @@ struct longint { ATTRIBUTE_MAYBE_UNUSED size_type m_plus_one, std::uint32_t s) noexcept { LONGINT_DEBUG_ASSERT(m > 1); - ATTRIBUTE_ASSUME(m > 1); + CONFIG_ASSUME_STATEMENT(m > 1); LONGINT_DEBUG_ASSERT(s < 32); - ATTRIBUTE_ASSUME(s < 32); + CONFIG_ASSUME_STATEMENT(s < 32); LONGINT_DEBUG_ASSERT(m + 1 == m_plus_one); - ATTRIBUTE_ASSUME(m + 1 == m_plus_one); + CONFIG_ASSUME_STATEMENT(m + 1 == m_plus_one); un[m] = static_cast(double_digit_t{u[m - 1]} >> (kNumsBits - s)); for (size_type i = m - 1; i > 0; i--) { un[i] = (u[i] << s) | static_cast(double_digit_t{u[i - 1]} >> (kNumsBits - s)); @@ -2345,11 +2346,11 @@ struct longint { ATTRIBUTE_MAYBE_UNUSED size_type n_plus_one, std::uint32_t s) noexcept { LONGINT_DEBUG_ASSERT(n > 1); - ATTRIBUTE_ASSUME(n > 1); + CONFIG_ASSUME_STATEMENT(n > 1); LONGINT_DEBUG_ASSERT(s < 32); - ATTRIBUTE_ASSUME(s < 32); + CONFIG_ASSUME_STATEMENT(s < 32); LONGINT_DEBUG_ASSERT(n + 1 == n_plus_one); - ATTRIBUTE_ASSUME(n + 1 == n_plus_one); + CONFIG_ASSUME_STATEMENT(n + 1 == n_plus_one); for (size_type i = 0; i < n; i++) { rem[i] = (un[i] >> s) | static_cast(double_digit_t{un[i + 1]} << (kNumsBits - s)); @@ -2405,7 +2406,7 @@ struct longint { const longint& conv_base_pow, digit_t mult_add_buffer[], fft::complex fft_poly_buffer[]) { LONGINT_DEBUG_ASSERT(0 < conv_base_pow.size_); - ATTRIBUTE_ASSUME(0 < conv_base_pow.size_); + CONFIG_ASSUME_STATEMENT(0 < conv_base_pow.size_); const size_type m_size = conv_base_pow.usize(); const digit_t* const m_ptr = conv_base_pow.nums_; assert(0 < m_size && m_size <= conv_len / 2); @@ -2423,13 +2424,13 @@ struct longint { fft::complex fft_poly_buffer[]) { const size_type half_conv_len = conv_len / 2; LONGINT_DEBUG_ASSERT(0 < m_size); - ATTRIBUTE_ASSUME(0 < m_size); + CONFIG_ASSUME_STATEMENT(0 < m_size); LONGINT_DEBUG_ASSERT(m_size <= half_conv_len); - ATTRIBUTE_ASSUME(m_size <= half_conv_len); + CONFIG_ASSUME_STATEMENT(m_size <= half_conv_len); LONGINT_DEBUG_ASSERT(math_functions::is_power_of_two(half_conv_len)); - ATTRIBUTE_ASSUME(math_functions::is_power_of_two(half_conv_len)); + CONFIG_ASSUME_STATEMENT(math_functions::is_power_of_two(half_conv_len)); LONGINT_DEBUG_ASSERT(conv_len <= max_size()); - ATTRIBUTE_ASSUME(conv_len <= max_size()); + CONFIG_ASSUME_STATEMENT(conv_len <= max_size()); const digit_t* num_hi = conv_digits + half_conv_len; static_assert(max_size() + max_size() > max_size()); const size_type prod_size = m_size + half_conv_len; @@ -2467,7 +2468,7 @@ struct longint { ATTRIBUTE_SIZED_ACCESS(read_only, 1, 2) static Decimal convertBinBaseImpl(const digit_t nums[], const std::size_t size) { LONGINT_DEBUG_ASSERT(math_functions::is_power_of_two(size)); - ATTRIBUTE_ASSUME(math_functions::is_power_of_two(size)); + CONFIG_ASSUME_STATEMENT(math_functions::is_power_of_two(size)); switch (size) { case 0: case 1: @@ -2513,7 +2514,7 @@ struct longint { static_assert(max_size() * 2 > max_size()); const size_type new_capacity = (current_capacity * 2) | (current_capacity == 0); LONGINT_DEBUG_ASSERT(capacity_ < new_capacity); - ATTRIBUTE_ASSUME(capacity_ < new_capacity); + CONFIG_ASSUME_STATEMENT(capacity_ < new_capacity); reserve(new_capacity); } @@ -2611,7 +2612,7 @@ struct longint { const digit_t rhs[], const size_type rhs_size) noexcept { LONGINT_DEBUG_ASSERT(lhs_size > rhs_size); - ATTRIBUTE_ASSUME(lhs_size > rhs_size); + CONFIG_ASSUME_STATEMENT(lhs_size > rhs_size); double_digit_t carry = 0; const digit_t* const lhs_end = lhs + lhs_size; const digit_t* const rhs_end = rhs + rhs_size; @@ -2636,7 +2637,7 @@ struct longint { const digit_t rhs[], const size_type rhs_size) noexcept { LONGINT_DEBUG_ASSERT(lhs_size >= rhs_size); - ATTRIBUTE_ASSUME(lhs_size >= rhs_size); + CONFIG_ASSUME_STATEMENT(lhs_size >= rhs_size); bool overflowed = longint_subtract_with_carry(lhs, lhs_size, rhs, rhs_size); if (overflowed) { lhs[0] = -lhs[0]; @@ -2654,7 +2655,7 @@ struct longint { const digit_t rhs[], const size_type rhs_size) noexcept { LONGINT_DEBUG_ASSERT(lhs_size >= rhs_size); - ATTRIBUTE_ASSUME(lhs_size >= rhs_size); + CONFIG_ASSUME_STATEMENT(lhs_size >= rhs_size); const digit_t* const lhs_end = lhs + lhs_size; const digit_t* const rhs_end = rhs + rhs_size; bool carry = false; @@ -2772,7 +2773,7 @@ struct longint { if (checked_value > max_size()) { CONFIG_UNREACHABLE(); } - ATTRIBUTE_ASSUME(checked_value == value); + CONFIG_ASSUME_STATEMENT(checked_value == value); return checked_value; } [[noreturn]] @@ -2876,7 +2877,7 @@ inline void longint::set_str_impl(const unsigned char* str, const std::size_t st const size_type aligned_str_conv_digits_size = check_size( math_functions::nearest_greater_equal_power_of_two(uint64_t{str_conv_digits_size})); LONGINT_DEBUG_ASSERT(str_conv_digits_size <= aligned_str_conv_digits_size); - ATTRIBUTE_ASSUME(str_conv_digits_size <= aligned_str_conv_digits_size); + CONFIG_ASSUME_STATEMENT(str_conv_digits_size <= aligned_str_conv_digits_size); reserveUninitializedWithoutCopy(aligned_str_conv_digits_size); digit_t* str_conv_digits = nums_; @@ -2895,23 +2896,23 @@ inline void longint::set_str_impl(const unsigned char* str, const std::size_t st do { static_assert(kStrConvBaseDigits == 9, ""); - uint32_t current = uint32_t(*str_iter) - '0'; + uint32_t current = uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; - current = current * 10 + uint32_t(*str_iter) - '0'; + current = current * 10 + uint32_t{*str_iter} - '0'; str_iter++; *--str_conv_digits_iter = current; } while (str_iter != str_end); @@ -2937,7 +2938,7 @@ inline void longint::set_str_impl(const unsigned char* str, const std::size_t st for (size_type conv_len = 2; conv_len <= aligned_str_conv_digits_size; conv_len *= 2, ++conv_dec_base_pows_iter) { LONGINT_DEBUG_ASSERT(math_functions::is_power_of_two(conv_len)); - ATTRIBUTE_ASSUME(math_functions::is_power_of_two(conv_len)); + CONFIG_ASSUME_STATEMENT(math_functions::is_power_of_two(conv_len)); for (size_type pos = 0; pos < aligned_str_conv_digits_size; pos += conv_len) { convertDecBaseMultAdd(str_conv_digits + pos, conv_len, *conv_dec_base_pows_iter, mult_add_buffer, fft_poly_buffer); diff --git a/number_theory/math_functions.hpp b/number_theory/math_functions.hpp index 66e233e..c424f49 100644 --- a/number_theory/math_functions.hpp +++ b/number_theory/math_functions.hpp @@ -127,16 +127,16 @@ template std::uint64_t widen_n = n; while (true) { if (p % 2 != 0) { - ATTRIBUTE_ASSUME(widen_n < (1ull << 32)); + CONFIG_ASSUME_STATEMENT(widen_n < (1ull << 32)); res = (res * widen_n) % mod; } p /= 2; if (p == 0) { return static_cast(res); } - ATTRIBUTE_ASSUME(widen_n < (1ull << 32)); + CONFIG_ASSUME_STATEMENT(widen_n < (1ull << 32)); widen_n = (widen_n * widen_n) % mod; - ATTRIBUTE_ASSUME(widen_n < (1ull << 32)); + CONFIG_ASSUME_STATEMENT(widen_n < (1ull << 32)); } } @@ -193,7 +193,7 @@ ATTRIBUTE_CONST I128_CONSTEXPR uint64_t bin_pow_mod(uint64_t n, uint64_t p, uint } #endif - ATTRIBUTE_ASSUME(y < (1u << 16)); + CONFIG_ASSUME_STATEMENT(y < (1u << 16)); return y; } @@ -211,17 +211,17 @@ ATTRIBUTE_CONST I128_CONSTEXPR uint64_t bin_pow_mod(uint64_t n, uint64_t p, uint std::uint64_t l = 1; std::uint64_t r = std::min((n >> 5) + 8, std::uint64_t{0xFFFFFFFFull}); do { - ATTRIBUTE_ASSUME(l <= r); - ATTRIBUTE_ASSUME((r >> 32) == 0); + CONFIG_ASSUME_STATEMENT(l <= r); + CONFIG_ASSUME_STATEMENT((r >> 32) == 0); uint64_t m = (l + r) / 2; - ATTRIBUTE_ASSUME((m >> 32) == 0); + CONFIG_ASSUME_STATEMENT((m >> 32) == 0); if (n >= m * m) { l = m + 1; } else { r = m - 1; } } while (r >= l); - ATTRIBUTE_ASSUME(((l - 1) >> 32) == 0); + CONFIG_ASSUME_STATEMENT(((l - 1) >> 32) == 0); return static_cast(l - 1); #if defined(__GNUG__) || defined(__clang__) || CONFIG_HAS_AT_LEAST_CXX_20 } else { @@ -238,12 +238,12 @@ ATTRIBUTE_CONST I128_CONSTEXPR uint64_t bin_pow_mod(uint64_t n, uint64_t p, uint */ std::uint64_t l = 0; uint128_t r_approx = (n >> 6) + 16; - std::uint64_t r = - r_approx > 0xFFFFFFFFFFFFFFFFull ? uint64_t(0xFFFFFFFFFFFFFFFFull) : uint64_t(r_approx); + std::uint64_t r = r_approx > 0xFFFFFFFFFFFFFFFFull ? std::uint64_t{0xFFFFFFFFFFFFFFFFull} + : static_cast(r_approx); do { // m = (l + r + 1) / 2 std::uint64_t m = (l / 2) + (r / 2) + ((r % 2) | (l % 2)); - if (n >= uint128_t(m) * m) { + if (n >= uint128_t{m} * m) { l = m; } else { r = m - 1; @@ -291,11 +291,11 @@ ATTRIBUTE_CONST I128_CONSTEXPR uint64_t bin_pow_mod(uint64_t n, uint64_t p, uint } } // 1625^3 = 4291015625 < 2^32 - 1 = 4294967295 < 4298942376 = 1626^3 - ATTRIBUTE_ASSUME(y <= 1625u); + CONFIG_ASSUME_STATEMENT(y <= 1625u); #if defined(__GNUG__) && !defined(__clang__) && CONFIG_HAS_AT_LEAST_CXX_17 // Clang ignores this assumption because it contains potential side effects (fpu register // flags), while GCC has made almost all math functions constexpr long before the C++26 - ATTRIBUTE_ASSUME( + CONFIG_ASSUME_STATEMENT( y == (static_cast(std::cbrt(static_cast(n_original_value))))); #endif return y; @@ -317,16 +317,16 @@ ATTRIBUTE_CONST I128_CONSTEXPR uint64_t bin_pow_mod(uint64_t n, uint64_t p, uint } } for (int32_t s = 57; s >= 0; s -= 3) { - ATTRIBUTE_ASSUME(y <= 1321122u); + CONFIG_ASSUME_STATEMENT(y <= 1321122u); y *= 2; - ATTRIBUTE_ASSUME(y <= 2642244u); + CONFIG_ASSUME_STATEMENT(y <= 2642244u); uint64_t bs = (3 * y * (y + 1) | 1) << s; if (n >= bs) { n -= bs; y++; } } - ATTRIBUTE_ASSUME(y <= 2642245u); + CONFIG_ASSUME_STATEMENT(y <= 2642245u); return static_cast(y); } @@ -539,7 +539,7 @@ int32_t sign(bool x) = delete; int32_t sign(char x) = delete; [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(signed char x) noexcept { - return std::int32_t(x > 0) - std::int32_t(x < 0); + return static_cast(x > 0) - static_cast(x < 0); } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(unsigned char x) noexcept { @@ -547,7 +547,7 @@ int32_t sign(char x) = delete; } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(short x) noexcept { - return std::int32_t(x > 0) - std::int32_t(x < 0); + return static_cast(x > 0) - static_cast(x < 0); } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(unsigned short x) noexcept { @@ -555,7 +555,7 @@ int32_t sign(char x) = delete; } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(int x) noexcept { - return std::int32_t(x > 0) - std::int32_t(x < 0); + return static_cast(x > 0) - static_cast(x < 0); } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(unsigned x) noexcept { @@ -563,7 +563,7 @@ int32_t sign(char x) = delete; } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(long x) noexcept { - return std::int32_t(x > 0) - std::int32_t(x < 0); + return static_cast(x > 0) - static_cast(x < 0); } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(unsigned long x) noexcept { @@ -571,7 +571,7 @@ int32_t sign(char x) = delete; } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(long long x) noexcept { - return std::int32_t(x > 0) - std::int32_t(x < 0); + return static_cast(x > 0) - static_cast(x < 0); } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(unsigned long long x) noexcept { @@ -581,8 +581,8 @@ int32_t sign(char x) = delete; #if defined(INTEGERS_128_BIT_HPP) [[nodiscard]] ATTRIBUTE_CONST I128_CONSTEXPR int32_t sign(int128_t x) noexcept { - const auto sign_bit = static_cast(static_cast(x) >> 127); - return int32_t(x != 0) - int32_t(2 * sign_bit); + const std::uint32_t sign_bit = static_cast(static_cast(x) >> 127); + return static_cast(x != 0) - static_cast(2 * sign_bit); } [[nodiscard]] ATTRIBUTE_CONST constexpr int32_t sign(uint128_t x) noexcept { @@ -841,7 +841,7 @@ concept unsigned_integral = ::math_functions::detail::helper_ns::unsigned_integr n <<= 2; } m -= n >> 31; - ATTRIBUTE_ASSUME(m <= 31); + CONFIG_ASSUME_STATEMENT(m <= 31); return m; } @@ -874,7 +874,7 @@ concept unsigned_integral = ::math_functions::detail::helper_ns::unsigned_integr n <<= 2; } m -= static_cast(n >> 63); - ATTRIBUTE_ASSUME(m <= 63); + CONFIG_ASSUME_STATEMENT(m <= 63); return m; } @@ -903,7 +903,7 @@ concept unsigned_integral = ::math_functions::detail::helper_ns::unsigned_integr n >>= 2; } m -= (n & 1); - ATTRIBUTE_ASSUME(m <= 31); + CONFIG_ASSUME_STATEMENT(m <= 31); return m; } @@ -912,7 +912,7 @@ concept unsigned_integral = ::math_functions::detail::helper_ns::unsigned_integr for (n = ~n & (n - 1); n != 0; n >>= 1) { m++; } - ATTRIBUTE_ASSUME(m <= 64); + CONFIG_ASSUME_STATEMENT(m <= 64); return m; } @@ -925,7 +925,7 @@ concept unsigned_integral = ::math_functions::detail::helper_ns::unsigned_integr n = (n & 0x0F0F0F0F) + ((n >> 4) & 0x0F0F0F0F); n = (n & 0x00FF00FF) + ((n >> 8) & 0x00FF00FF); n = (n & 0x0000FFFF) + ((n >> 16) & 0x0000FFFF); - ATTRIBUTE_ASSUME(n <= 32); + CONFIG_ASSUME_STATEMENT(n <= 32); return n; } @@ -939,7 +939,7 @@ concept unsigned_integral = ::math_functions::detail::helper_ns::unsigned_integr n = (n & 0x00FF00FF00FF00FFull) + ((n >> 8) & 0x00FF00FF00FF00FFull); n = (n & 0x0000FFFF0000FFFFull) + ((n >> 16) & 0x0000FFFF0000FFFFull); n = (n & 0x00000000FFFFFFFFull) + ((n >> 32) & 0x00000000FFFFFFFFull); - ATTRIBUTE_ASSUME(n <= 64); + CONFIG_ASSUME_STATEMENT(n <= 64); return n; } @@ -1005,7 +1005,7 @@ template } const std::uint64_t high = static_cast(n >> 64); - ATTRIBUTE_ASSUME(high != 0); + CONFIG_ASSUME_STATEMENT(high != 0); #if CONFIG_HAS_AT_LEAST_CXX_20 int32_t high_trailing_zeros_count = std::countr_zero(high); #elif defined(__GNUG__) @@ -1076,7 +1076,7 @@ template } const std::uint64_t low = static_cast(n); - ATTRIBUTE_ASSUME(low != 0); + CONFIG_ASSUME_STATEMENT(low != 0); // Avoid recursive call to countl_zero #if CONFIG_HAS_AT_LEAST_CXX_20 return 64 + std::countl_zero(low); @@ -1495,8 +1495,9 @@ ATTRIBUTE_CONST constexpr uint32_t log10_floor_compile_time_impl(uint64_t n, 999999999999999999ull, 9999999999999999999ull, }; - const auto adjustment = int32_t((table2[uint32_t(approx_log10 + 1)] - n) >> 63); - return uint32_t(approx_log10 + adjustment); + const int32_t adjustment = + static_cast((table2[static_cast(approx_log10 + 1)] - n) >> 63); + return static_cast(approx_log10 + adjustment); } ATTRIBUTE_CONST static inline uint32_t log10_floor_runtime_impl(uint64_t n, @@ -1528,8 +1529,9 @@ ATTRIBUTE_CONST static inline uint32_t log10_floor_runtime_impl(uint64_t n, 999999999999999999ull, 9999999999999999999ull, }; - const auto adjustment = int32_t((table2[uint32_t(approx_log10 + 1)] - n) >> 63); - return uint32_t(approx_log10 + adjustment); + const int32_t adjustment = + static_cast((table2[static_cast(approx_log10 + 1)] - n) >> 63); + return static_cast(approx_log10 + adjustment); } } // namespace detail @@ -1543,9 +1545,9 @@ ATTRIBUTE_CONST static inline uint32_t log10_floor_runtime_impl(uint64_t n, * See Hackers Delight 11-4 */ - static_assert(::math_functions::countl_zero(uint64_t(0)) == 64, "countl_zero detail error"); - const int32_t approx_log10 = (19 * (63 - int32_t(::math_functions::countl_zero(n)))) >> 6; - ATTRIBUTE_ASSUME((-19 >> 6) <= approx_log10 && approx_log10 <= ((19 * 63) >> 6)); + static_assert(::math_functions::countl_zero(uint64_t{0}) == 64, "countl_zero detail error"); + const int32_t approx_log10 = (19 * (63 - ::math_functions::countl_zero(n))) >> 6; + CONFIG_ASSUME_STATEMENT((-19 >> 6) <= approx_log10 && approx_log10 <= ((19 * 63) >> 6)); #if CONFIG_HAS_AT_LEAST_CXX_20 || \ (CONFIG_HAS_AT_LEAST_CXX_17 && (defined(__clang__) || CONFIG_GNUC_AT_LEAST(10, 0))) @@ -1586,7 +1588,7 @@ template #endif [[nodiscard]] ATTRIBUTE_CONST constexpr ExtractPow2Result extract_pow2(T n) noexcept { auto r = static_cast(::math_functions::countr_zero(n)); - ATTRIBUTE_ASSUME(r <= sizeof(n) * CHAR_BIT); + CONFIG_ASSUME_STATEMENT(r <= sizeof(n) * CHAR_BIT); return {n != 0 ? (n >> r) : 0, r}; } @@ -1831,16 +1833,16 @@ visit_prime_factors(NumericType n, Function visitor) noexcept( auto [s, pow_of_2] = ::math_functions::extract_pow2(n_abs); n_abs = s; if constexpr (check_early_exit) { - if (!visitor(PrimeFactorType(UnsignedNumericType(2), pow_of_2))) { + if (!visitor(PrimeFactorType{UnsignedNumericType{2}, pow_of_2})) { return; } } else { - visitor(PrimeFactorType(UnsignedNumericType(2), pow_of_2)); + visitor(PrimeFactorType{UnsignedNumericType{2}, pow_of_2}); } } for (UnsignedNumericType d = 3; d * d <= n_abs; d += 2) { - ATTRIBUTE_ASSUME(d >= 3); + CONFIG_ASSUME_STATEMENT(d >= 3); if (n_abs % d == 0) { std::uint32_t pow_of_d = 0; do { @@ -1859,13 +1861,7 @@ visit_prime_factors(NumericType n, Function visitor) noexcept( } if (n_abs > 1) { - if constexpr (check_early_exit) { - if (!visitor(PrimeFactorType(n_abs, std::uint32_t(1)))) { - return; - } - } else { - visitor(PrimeFactorType(n_abs, std::uint32_t(1))); - } + visitor(PrimeFactorType(n_abs, std::uint32_t{1})); } } @@ -1965,7 +1961,7 @@ class [[nodiscard]] Factorizer final { pfs.back().factor_power++; } // assert(n % lpf == 0); - ATTRIBUTE_ASSUME(n % lpf == 0); + CONFIG_ASSUME_STATEMENT(n % lpf == 0); n /= lpf; } @@ -1996,7 +1992,7 @@ class [[nodiscard]] Factorizer final { while (n >= 3) { const std::uint32_t least_pf = least_prime_factor[n]; - ATTRIBUTE_ASSUME(least_pf >= 2); + CONFIG_ASSUME_STATEMENT(least_pf >= 2); unique_pfs_count += least_pf != last_pf; n /= least_pf; last_pf = least_pf; @@ -2172,10 +2168,10 @@ constexpr HelperRetType congruence_helper(const std::uint32_t a, const std::uint return {}; } - ATTRIBUTE_ASSUME(a == 0 || a >= d); - ATTRIBUTE_ASSUME(a % d == 0); - ATTRIBUTE_ASSUME(m >= d); - ATTRIBUTE_ASSUME(m % d == 0); + CONFIG_ASSUME_STATEMENT(a == 0 || a >= d); + CONFIG_ASSUME_STATEMENT(a % d == 0); + CONFIG_ASSUME_STATEMENT(m >= d); + CONFIG_ASSUME_STATEMENT(m % d == 0); /* * Solves a_ * x === c_ (mod m_) as gcd(a_, m_) == 1 @@ -2192,7 +2188,7 @@ constexpr HelperRetType congruence_helper(const std::uint32_t a, const std::uint // a * (u_ * c_) + m * (v_ * c_) == c // x0 = u_ * c_ const auto x0 = static_cast((unsigned_u_ * c_) % m_); - ATTRIBUTE_ASSUME(x0 != ::math_functions::kNoCongruenceSolution); + CONFIG_ASSUME_STATEMENT(x0 != ::math_functions::kNoCongruenceSolution); return {x0, d, m_}; } @@ -2439,9 +2435,9 @@ ATTRIBUTE_CONST constexpr std::uint32_t solve_binary_congruence_modulo_m( } const auto [r, s] = ::math_functions::extract_pow2(m); - ATTRIBUTE_ASSUME(r >= 1); + CONFIG_ASSUME_STATEMENT(r >= 1); const auto min_k_s = std::min(k, std::uint32_t{s}); - ATTRIBUTE_ASSUME(min_k_s < 32); + CONFIG_ASSUME_STATEMENT(min_k_s < 32); // gcd(2^k, m) const auto gcd_2k_m = std::uint32_t{1} << min_k_s; if (c % gcd_2k_m != 0) { @@ -2458,10 +2454,10 @@ ATTRIBUTE_CONST constexpr std::uint32_t solve_binary_congruence_modulo_m( return c_mod_m_; } - ATTRIBUTE_ASSUME(min_k_s == s); - ATTRIBUTE_ASSUME(k > s); - ATTRIBUTE_ASSUME(m_ == r); - ATTRIBUTE_ASSUME(m_ % 2 == 1); + CONFIG_ASSUME_STATEMENT(min_k_s == s); + CONFIG_ASSUME_STATEMENT(k > s); + CONFIG_ASSUME_STATEMENT(m_ == r); + CONFIG_ASSUME_STATEMENT(m_ % 2 == 1); /** * Solve 2^{k-s} * x ≡ c / 2^{s} (mod r), where r = m_ = m / 2^{s} */ @@ -2474,9 +2470,9 @@ ATTRIBUTE_CONST constexpr std::uint32_t solve_binary_congruence_modulo_m( ::math_functions::extended_euclid_algorithm( ::math_functions::bin_pow_mod(uint32_t{2}, lhs_bin_power, m_), m_) .u_value; - ATTRIBUTE_ASSUME(u_ < m_); + CONFIG_ASSUME_STATEMENT(u_ < m_); const auto unsigned_u_ = static_cast(u_ >= 0 ? u_ : u_ + m_); - ATTRIBUTE_ASSUME(unsigned_u_ < m_); + CONFIG_ASSUME_STATEMENT(unsigned_u_ < m_); rhs *= unsigned_u_; } else { /** @@ -2497,7 +2493,7 @@ ATTRIBUTE_CONST constexpr std::uint32_t solve_binary_congruence_modulo_m( } const auto x0 = static_cast(rhs % m_); - ATTRIBUTE_ASSUME(x0 != ::math_functions::kNoCongruenceSolution); + CONFIG_ASSUME_STATEMENT(x0 != ::math_functions::kNoCongruenceSolution); return x0; } @@ -2544,7 +2540,7 @@ ATTRIBUTE_CONST constexpr std::uint32_t solve_binary_congruence_modulo_m( std::uint32_t b_i = 0; do { - b_i += n / std::uint32_t(pow_of_p_i); + b_i += n / static_cast(pow_of_p_i); pow_of_p_i *= pf.factor; } while (pow_of_p_i <= n); @@ -2637,8 +2633,8 @@ ATTRIBUTE_CONST constexpr std::uint32_t solve_binary_congruence_modulo_m( #if defined(INTEGERS_128_BIT_HPP) [[nodiscard]] ATTRIBUTE_CONST I128_CONSTEXPR bool is_perfect_number(uint128_t n) noexcept { - return n > std::numeric_limits::max() - ? n == (((uint128_t(1) << 61) - 1) << (61 - 1)) + return n > std::numeric_limits::max() + ? n == (((uint128_t{1} << 61) - 1) << (61 - 1)) : ::math_functions::is_perfect_number(static_cast(n)); } @@ -2740,12 +2736,12 @@ ATTRIBUTE_CONST constexpr T powers_sum(const std::uint32_t n) noexcept { if (n_minus_1 % 3 == 0) { return tmp2 * (tmp3 + (n_minus_1 / 3)); } else { - ATTRIBUTE_ASSUME(tmp2 % 3 == 0); + CONFIG_ASSUME_STATEMENT(tmp2 % 3 == 0); return tmp2 * tmp3 + ((tmp2 / 3) * n_minus_1); } } case 1: { - ATTRIBUTE_ASSUME(two_n_plus_3_u64 % 5 == 0); + CONFIG_ASSUME_STATEMENT(two_n_plus_3_u64 % 5 == 0); const auto lhs = static_cast(n_square_u64) * (two_n_plus_3_u64 / 5); const std::uint32_t n_minus_1_over_5 = n_minus_1 / 5; if (n_minus_1_over_5 % 3 == 0) { @@ -2899,7 +2895,7 @@ namespace std { // gcd(a, b) = gcd(a, b0) = gcd(b0, a % b0) = gcd(a1, b1) uint128_t a1 = b0; // b1 = a % b0 - uint64_t b1 = a < b0 ? a : a % uint64_t(b0); // a < 2^64 => b1 < 2^64 + uint64_t b1 = a < b0 ? a : a % static_cast(b0); // a < 2^64 => b1 < 2^64 if (b1 == 0) { return a1; } @@ -2907,7 +2903,7 @@ namespace std { uint64_t a2 = b1; // b1 < 2^64 => a2 < 2^64 // b2 = a1 % b1 // a1 = b0, b1 = a % b0 => b1 < a1 - uint64_t b2 = uint64_t(a1 % b1); // b1 < 2^64 => b2 = a1 % b1 < 2^64 + uint64_t b2 = static_cast(a1 % b1); // b1 < 2^64 => b2 = a1 % b1 < 2^64 return std::gcd(a2, b2); } diff --git a/number_theory/test_is_prime_bpsw.cpp b/number_theory/test_is_prime_bpsw.cpp index b5f38f1..e3797c8 100644 --- a/number_theory/test_is_prime_bpsw.cpp +++ b/number_theory/test_is_prime_bpsw.cpp @@ -419,7 +419,7 @@ static void TestRandomPrimesGMP() noexcept { mp_limb_t* const n_gmp_array = mpz_limbs_write(n_gmp, 1); for (size_t test = kTotalTests; test != 0; test--) { const uint64_t n = rnd() | 1; - ATTRIBUTE_ASSUME(n % 2 == 1); + assert(n % 2 == 1); n_gmp_array[0] = n; mpz_limbs_finish(n_gmp, 1); @@ -430,7 +430,7 @@ static void TestRandomPrimesGMP() noexcept { } else if constexpr (sizeof(unsigned long) == sizeof(uint32_t)) { for (size_t test = kTotalTests; test != 0; test--) { const uint64_t n = rnd() | 1; - ATTRIBUTE_ASSUME(n % 2 == 1); + assert(n % 2 == 1); mpz_set_ui(n_gmp, static_cast(n >> 32)); mpz_mul_2exp(n_gmp, n_gmp, 32); diff --git a/number_theory/test_kronecker_symbol.cpp b/number_theory/test_kronecker_symbol.cpp index b35617d..ce6d3dd 100644 --- a/number_theory/test_kronecker_symbol.cpp +++ b/number_theory/test_kronecker_symbol.cpp @@ -274,16 +274,15 @@ static void CheckJacobiBasic() noexcept { } for (uint32_t a = 0; a <= kLen; a++) { - int32_t j_a_p = kronecker_symbol(a, p); + const int32_t j_a_p = kronecker_symbol(a, p); assert(j_a_p == -1 || j_a_p == 0 || j_a_p == 1); - ATTRIBUTE_ASSUME(j_a_p == -1 || j_a_p == 0 || j_a_p == 1); - uint32_t j_a_p_mod_p = j_a_p == -1 ? p - 1 : uint32_t(j_a_p); - uint32_t a_p12 = math_functions::bin_pow_mod(a, (p - 1) / 2, p); + const uint32_t j_a_p_mod_p = j_a_p == -1 ? p - 1 : uint32_t(j_a_p); + const uint32_t a_p12 = math_functions::bin_pow_mod(a, (p - 1) / 2, p); assert(j_a_p_mod_p == a_p12); for (uint32_t b = 0; b <= kLen; b++) { - int32_t j_b_p = kronecker_symbol(b, p); + const int32_t j_b_p = kronecker_symbol(b, p); assert(a % p != b % p || j_a_p == j_b_p); - int32_t j_ab_p = kronecker_symbol(a * b, p); + const int32_t j_ab_p = kronecker_symbol(a * b, p); assert(j_ab_p == j_a_p * j_b_p); } } diff --git a/tests/.clang-tidy b/tests/.clang-tidy index f129355..c1278af 100644 --- a/tests/.clang-tidy +++ b/tests/.clang-tidy @@ -75,7 +75,7 @@ hicpp-exception-baseclass, hicpp-multiway-paths-covered, misc-*, -misc-const-correctness, --misc-include-cleaner +-misc-include-cleaner, -misc-non-private-member-variables-in-classes, -misc-no-recursion, -misc-unused-parameters, @@ -99,6 +99,7 @@ readability-convert-member-functions-to-static, readability-delete-null-pointer, readability-deleted-default, readability-identifier-naming, +readability-implicit-bool-conversion, readability-inconsistent-declaration-parameter-name, readability-make-member-function-const, readability-misleading-indentation, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 14fe558..5444514 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -536,12 +536,12 @@ if((NOT mingw_gcc_or_clang) OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 10.0. endif() unset(mingw_gcc_or_clang) -list(APPEND TestFilenames "test_actrie.cpp") -list(APPEND TestDirectories "tf_idf_actrie") -list(APPEND TestLangVersions "20 23 26") -list(APPEND TestDependencies "") -list(APPEND TestOptionalDependencies "") -list(APPEND TestIsCProject False) +# list(APPEND TestFilenames "test_actrie.cpp") +# list(APPEND TestDirectories "tf_idf_actrie") +# list(APPEND TestLangVersions "20 23 26") +# list(APPEND TestDependencies "") +# list(APPEND TestOptionalDependencies "") +# list(APPEND TestIsCProject False) list(APPEND TestFilenames "test_tf_idf_actrie.cpp search_lib.cpp") list(APPEND TestDirectories "tf_idf_actrie") diff --git a/vec_instructs/config_macros.hpp b/vec_instructs/config_macros.hpp index 8b1a6ff..0672803 100644 --- a/vec_instructs/config_macros.hpp +++ b/vec_instructs/config_macros.hpp @@ -22,12 +22,6 @@ #define CONFIG_HAS_GCC_ATTRIBUTE(attr) 0 #endif -#if defined(__cplusplus) && defined(__has_cpp_attribute) -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) -#else -#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 -#endif - #if defined(__has_builtin) #define CONFIG_HAS_BUILTIN(name) __has_builtin(name) #else @@ -79,6 +73,12 @@ #define CONFIG_HAS_AT_LEAST_CXX_23 0 #endif +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define CONFIG_HAS_AT_LEAST_C_99 1 +#else +#define CONFIG_HAS_AT_LEAST_C_99 0 +#endif + #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define CONFIG_HAS_AT_LEAST_C_11 1 #else @@ -97,6 +97,18 @@ #define CONFIG_HAS_AT_LEAST_C_23 0 #endif +#if CONFIG_HAS_AT_LEAST_C_99 && defined(__has_c_attribute) +#define CONFIG_HAS_C_ATTRIBUTE(attr) __has_c_attribute(attr) +#else +#define CONFIG_HAS_C_ATTRIBUTE(attr) 0 +#endif + +#if CONFIG_HAS_AT_LEAST_CXX_11 && defined(__has_cpp_attribute) +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr) +#else +#define CONFIG_HAS_CPP_ATTRIBUTE(attr) 0 +#endif + // https://en.cppreference.com/w/cpp/feature_test #if defined(__cpp_concepts) && __cpp_concepts >= 201907L #define CONFIG_HAS_CONCEPTS 1 @@ -104,9 +116,9 @@ #define CONFIG_HAS_CONCEPTS 0 #endif -/** - * Restrict qualifier for the C++ (C has `restrict` keyword since C99) - */ +#if CONFIG_HAS_AT_LEAST_C_99 +#define RESTRICT_QUALIFIER restrict +#else #if defined(__GNUC__) || defined(__clang__) #define RESTRICT_QUALIFIER __restrict__ #elif defined(_MSC_VER) @@ -114,6 +126,7 @@ #else #define RESTRICT_QUALIFIER #endif +#endif #if defined(__GNUC__) || defined(__clang__) #define FUNCTION_MACRO __PRETTY_FUNCTION__ @@ -127,67 +140,61 @@ #include #endif -#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L -#define CONFIG_UNREACHABLE() std::unreachable() -#elif CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define CONFIG_UNREACHABLE() [[assume(false)]] -#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) -#define CONFIG_UNREACHABLE() __builtin_unreachable() -#elif CONFIG_HAS_BUILTIN(__builtin_assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __builtin_assume(false) -#else -#define CONFIG_UNREACHABLE() __builtin_assume(0) -#endif +#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) +#define CONFIG_ASSUME_STATEMENT(expr) [[assume(expr)]] +#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) +#define CONFIG_ASSUME_STATEMENT(expr) __builtin_assume(expr) #elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __attribute__((assume(false))) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(false))); \ + } \ + } while (false) #else -#define CONFIG_UNREACHABLE() __attribute__((assume(0))) +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __attribute__((assume(0))); \ + } \ + } while (0) #endif #elif defined(_MSC_VER) -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() __assume(false) +#define CONFIG_ASSUME_STATEMENT(expr) __assume(expr) #else -#define CONFIG_UNREACHABLE() __assume(0) -#endif -#else -#if defined(__cplusplus) -#define CONFIG_UNREACHABLE() \ - do { \ +#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + std::unreachable(); \ + } \ + } while (false) +#elif CONFIG_HAS_BUILTIN(__builtin_unreachable) +#if defined(__cplusplus) || CONFIG_HAS_AT_LEAST_C_23 +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (false) #else -#define CONFIG_UNREACHABLE() \ - do { \ +#define CONFIG_ASSUME_STATEMENT(expr) \ + do { \ + if (!(expr)) { \ + __builtin_unreachable(); \ + } \ } while (0) #endif +#else +#define CONFIG_ASSUME_STATEMENT(expr) +#endif #endif -#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) [[assume(expr)]] -#elif CONFIG_GNUC_AT_LEAST(13, 0) && CONFIG_HAS_GCC_ATTRIBUTE(assume) -#define ATTRIBUTE_ASSUME(expr) __attribute__((assume(expr))) -#elif defined(__clang__) && CONFIG_HAS_BUILTIN(__builtin_assume) -// Side effect of expr is discarded -#define ATTRIBUTE_ASSUME(expr) __builtin_assume(expr) -#elif defined(_MSC_VER) -#define ATTRIBUTE_ASSUME(expr) __assume(expr) -#else #if defined(__cplusplus) -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (false) +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(false) #else -#define ATTRIBUTE_ASSUME(expr) \ - do { \ - if (!(expr)) { \ - CONFIG_UNREACHABLE(); \ - } \ - } while (0) -#endif +#define CONFIG_UNREACHABLE() CONFIG_ASSUME_STATEMENT(0) #endif /* __builtin_expect is in gcc 3.0 */ @@ -208,23 +215,22 @@ #define unlikely(x) __builtin_expect((x), 0) #endif -#else +#elif !defined(likely) || !defined(likely) -#if !defined(likely) -#if defined(__cplusplus) -#define likely(x) static_cast(x) -#else -#define likely(x) !!(x) +#if defined(likely) +#undef likely #endif +#if defined(unlikely) +#undef unlikely #endif -#if !defined(unlikely) #if defined(__cplusplus) +#define likely(x) static_cast(x) #define unlikely(x) static_cast(x) #else +#define likely(x) !!(x) #define unlikely(x) !!(x) #endif -#endif #endif @@ -233,69 +239,68 @@ #define __attribute__(...) #endif -#if CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) -#define ATTRIBUTE_CONST __attribute__((__const__)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::__const__) #define ATTRIBUTE_CONST [[gnu::__const__]] +#elif CONFIG_GNUC_AT_LEAST(2, 6) || CONFIG_HAS_GCC_ATTRIBUTE(__const__) +#define ATTRIBUTE_CONST __attribute__((__const__)) #else #define ATTRIBUTE_CONST #endif -#if CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) -#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(maybe_unused) #define ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]] +#elif CONFIG_GNUC_AT_LEAST(2, 7) || CONFIG_HAS_GCC_ATTRIBUTE(unused) +#define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused)) #else #define ATTRIBUTE_MAYBE_UNUSED #endif -#if CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) -#define ATTRIBUTE_PURE __attribute__((pure)) -#elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::pure) #define ATTRIBUTE_PURE [[gnu::pure]] +#elif CONFIG_GNUC_AT_LEAST(2, 96) || CONFIG_HAS_GCC_ATTRIBUTE(pure) +#define ATTRIBUTE_PURE __attribute__((pure)) #else #define ATTRIBUTE_PURE #endif -#if CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) -#define ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::noinline) #define ATTRIBUTE_NOINLINE [[clang::noinline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::noinline) #define ATTRIBUTE_NOINLINE [[gnu::noinline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::noinline) #define ATTRIBUTE_NOINLINE [[msvc::noinline]] -#elif defined(_MSC_VER) && \ - (_MSC_VER >= 1920 || defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017) +#elif defined(_MSC_VER) && _MSC_VER >= 1920 && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191025017 #define ATTRIBUTE_NOINLINE __declspec(noinline) +#elif CONFIG_GNUC_AT_LEAST(3, 0) || CONFIG_HAS_GCC_ATTRIBUTE(noinline) +#define ATTRIBUTE_NOINLINE __attribute__((noinline)) #else #define ATTRIBUTE_NOINLINE #endif -#if CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) -#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) -#elif defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) +#if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[clang::always_inline]] #elif defined(__GNUG__) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::always_inline) #define ATTRIBUTE_ALWAYS_INLINE [[gnu::always_inline]] #elif defined(_MSC_VER) && CONFIG_HAS_CPP_ATTRIBUTE(msvc::forceinline) #define ATTRIBUTE_ALWAYS_INLINE [[msvc::forceinline]] +#elif CONFIG_GNUC_AT_LEAST(3, 2) || CONFIG_HAS_GCC_ATTRIBUTE(always_inline) +#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) #else #define ATTRIBUTE_ALWAYS_INLINE #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) -#define ATTRIBUTE_COLD __attribute__((cold)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::cold) #define ATTRIBUTE_COLD [[gnu::cold]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(cold) +#define ATTRIBUTE_COLD __attribute__((cold)) #else #define ATTRIBUTE_COLD #endif -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) -#define ATTRIBUTE_HOT __attribute__((hot)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::hot) #define ATTRIBUTE_HOT [[gnu::hot]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(hot) +#define ATTRIBUTE_HOT __attribute__((hot)) #else #define ATTRIBUTE_HOT #endif @@ -306,10 +311,10 @@ * indicate the size of the allocation. * Clang docs: https://clang.llvm.org/docs/AttributeReference.html#alloc-size */ -#if CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) -#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::alloc_size) #define ATTRIBUTE_ALLOC_SIZE(...) [[gnu::alloc_size(__VA_ARGS__)]] +#elif CONFIG_GNUC_AT_LEAST(4, 3) || CONFIG_HAS_GCC_ATTRIBUTE(alloc_size) +#define ATTRIBUTE_ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__))) #else #define ATTRIBUTE_ALLOC_SIZE(...) #endif @@ -323,7 +328,17 @@ * * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html for more info */ -#if CONFIG_GNUC_AT_LEAST(10, 0) +#if CONFIG_GNUC_AT_LEAST(10, 0) || CONFIG_HAS_GCC_ATTRIBUTE(access) +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(gnu::access) +#define ATTRIBUTE_ACCESS(mode, memory_argument_pos) [[gnu::access(mode, memory_argument_pos)]] +#define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ + [[gnu::access(mode, memory_argument_pos, range_size_argument_pos)]] +#if CONFIG_GNUC_AT_LEAST(11, 0) +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) ATTRIBUTE_ACCESS(none, memory_argument_pos) +#else +#define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) +#endif +#else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) \ __attribute__((access(mode, memory_argument_pos))) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) \ @@ -333,6 +348,7 @@ #else #define ATTRIBUTE_ACCESS_NONE(memory_argument_pos) #endif +#endif #else #define ATTRIBUTE_ACCESS(mode, memory_argument_pos) #define ATTRIBUTE_SIZED_ACCESS(mode, memory_argument_pos, range_size_argument_pos) @@ -343,25 +359,33 @@ * See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html * and https://clang.llvm.org/docs/AttributeReference.html#id664 for more info */ -#if CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) -#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) -#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) -#elif CONFIG_HAS_AT_LEAST_CXX_17 && (defined(__GNUG__) || defined(__clang__)) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nonnull) #define ATTRIBUTE_NONNULL(...) [[gnu::nonnull(__VA_ARGS__)]] #define ATTRIBUTE_NONNULL_ALL_ARGS [[gnu::nonnull]] +#elif CONFIG_GNUC_AT_LEAST(3, 3) || CONFIG_HAS_GCC_ATTRIBUTE(nonnull) +#define ATTRIBUTE_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#define ATTRIBUTE_NONNULL_ALL_ARGS __attribute__((nonnull)) #else #define ATTRIBUTE_NONNULL(...) #define ATTRIBUTE_NONNULL_ALL_ARGS #endif -#if CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) -#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) -#elif (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::returns_nonnull) #define ATTRIBUTE_RETURNS_NONNULL [[gnu::returns_nonnull]] +#elif CONFIG_GNUC_AT_LEAST(4, 9) || CONFIG_HAS_GCC_ATTRIBUTE(returns_nonnull) +#define ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) #else #define ATTRIBUTE_RETURNS_NONNULL #endif +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::target) +#define ATTRIBUTE_TARGET(config_string) [[gnu::target(config_string)]] +#elif CONFIG_GNUC_AT_LEAST(4, 4) || CONFIG_HAS_GCC_ATTRIBUTE(target) +#define ATTRIBUTE_TARGET(config_string) __attribute__((target(config_string))) +#else +#define ATTRIBUTE_TARGET(config_string) +#endif + #if defined(__clang__) && CONFIG_HAS_CPP_ATTRIBUTE(clang::lifetimebound) #define ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] #else @@ -374,13 +398,16 @@ #define ATTRIBUTE_REINITIALIZES #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(nodiscard) #define ATTRIBUTE_NODISCARD [[nodiscard]] #if CONFIG_HAS_AT_LEAST_CXX_20 #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #else #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard]] #endif +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(nodiscard) +#define ATTRIBUTE_NODISCARD [[nodiscard]] +#define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) [[nodiscard(message)]] #elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(warn_unused_result) #define ATTRIBUTE_NODISCARD __attribute__((warn_unused_result)) #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) __attribute__((warn_unused_result)) @@ -389,9 +416,9 @@ #define ATTRIBUTE_NODISCARD_WITH_MESSAGE(message) #endif -#if CONFIG_HAS_AT_LEAST_CXX_11 +#if CONFIG_HAS_AT_LEAST_CXX_11 && CONFIG_HAS_CPP_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(noreturn) #define ATTRIBUTE_NORETURN [[noreturn]] #elif CONFIG_HAS_AT_LEAST_C_11 #define ATTRIBUTE_NORETURN _Noreturn @@ -411,15 +438,17 @@ #define CONFIG_NOEXCEPT_FUNCTION #endif -#if CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) +#if (defined(__GNUG__) || defined(__clang__)) && CONFIG_HAS_CPP_ATTRIBUTE(gnu::nothrow) +#define ATTRIBUTE_NOTHROW [[gnu::nothrow]] +#elif CONFIG_GNUC_AT_LEAST(3, 4) || CONFIG_HAS_GCC_ATTRIBUTE(nothrow) #define ATTRIBUTE_NOTHROW __attribute__((nothrow)) #else #define ATTRIBUTE_NOTHROW #endif -#if CONFIG_HAS_AT_LEAST_CXX_17 +#if CONFIG_HAS_AT_LEAST_CXX_17 && CONFIG_HAS_CPP_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] -#elif CONFIG_HAS_AT_LEAST_C_23 +#elif CONFIG_HAS_AT_LEAST_C_23 && CONFIG_HAS_C_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH [[fallthrough]] #elif CONFIG_GNUC_AT_LEAST(7, 1) || CONFIG_HAS_GCC_ATTRIBUTE(fallthrough) #define ATTRIBUTE_FALLTHROUGH __attribute__((fallthrough)) diff --git a/vec_instructs/memcount.h b/vec_instructs/memcount.h index 49e2530..e33b12d 100644 --- a/vec_instructs/memcount.h +++ b/vec_instructs/memcount.h @@ -18,18 +18,13 @@ EXTERN_WITH_C_LINKAGE_END EXTERN_WITH_C_LINKAGE_BEGIN -#define MEMCOUNT_ATTRIBUTES \ - ATTRIBUTE_NODISCARD_WITH_MESSAGE("return value of the memcount should not be ommited") \ - ATTRIBUTE_NOTHROW ATTRIBUTE_SIZED_ACCESS(read_only, 1, 3) ATTRIBUTE_PURE - -#if defined(__GNUC__) || defined(__clang__) -#define FAST_MEMCOUNT_TARGET_ATTRIBUTE __attribute__((target("popcnt,avx,avx2"))) -#else -#define FAST_MEMCOUNT_TARGET_ATTRIBUTE -#endif +#define MEMCOUNT_ATTRIBUTES \ + ATTRIBUTE_PURE ATTRIBUTE_NOTHROW ATTRIBUTE_NODISCARD_WITH_MESSAGE( \ + "return value of the memcount should not be ommited") \ + ATTRIBUTE_SIZED_ACCESS(read_only, 1, 3) +ATTRIBUTE_TARGET("popcnt,avx,avx2") MEMCOUNT_ATTRIBUTES -FAST_MEMCOUNT_TARGET_ATTRIBUTE static inline size_t memcount_avx(const uint8_t* const src, const uint8_t chr, size_t size) CONFIG_NOEXCEPT_FUNCTION { #if defined(__cplusplus) @@ -84,8 +79,6 @@ static inline size_t memcount_avx(const uint8_t* const src, const uint8_t chr, return eq_count; } -#undef FAST_MEMCOUNT_TARGET_ATTRIBUTE - MEMCOUNT_ATTRIBUTES static inline size_t memcount_default(const uint8_t* const src, const uint8_t chr, size_t size) CONFIG_NOEXCEPT_FUNCTION { @@ -99,10 +92,10 @@ static inline size_t memcount_default(const uint8_t* const src, const uint8_t ch #if defined(__GNUC__) || defined(__clang__) +ATTRIBUTE_RETURNS_NONNULL +ATTRIBUTE_NOTHROW ATTRIBUTE_NODISCARD_WITH_MESSAGE("this function is resolver and should not be used") ATTRIBUTE_MAYBE_UNUSED -ATTRIBUTE_NOTHROW -ATTRIBUTE_RETURNS_NONNULL #if defined(__clang__) __attribute__((no_sanitize("address", "thread", "memory", "undefined"))) #elif defined(__GNUC__) diff --git a/vec_instructs/memset_int.h b/vec_instructs/memset_int.h index da92c4d..f291ef2 100644 --- a/vec_instructs/memset_int.h +++ b/vec_instructs/memset_int.h @@ -30,14 +30,8 @@ EXTERN_WITH_C_LINKAGE_BEGIN #define MEMSET_INT_FUNC_ATTRIBUTES ATTRIBUTE_NOTHROW ATTRIBUTE_SIZED_ACCESS(write_only, 1, 3) -#if defined(__GNUC__) || defined(__clang__) -#define FAST_MEMSET_INT_TARGET_ATTRIBUTE __attribute__((target("avx"))) -#else -#define FAST_MEMSET_INT_TARGET_ATTRIBUTE -#endif - MEMSET_INT_FUNC_ATTRIBUTES -FAST_MEMSET_INT_TARGET_ATTRIBUTE +ATTRIBUTE_TARGET("avx") static inline void memset_int_avx(int32_t* dst, int32_t value, size_t size) CONFIG_NOEXCEPT_FUNCTION { uint32_t* aligned_4_address = (uint32_t*)dst; @@ -86,8 +80,6 @@ static inline void memset_int_avx(int32_t* dst, int32_t value, } } -#undef FAST_MEMSET_INT_TARGET_ATTRIBUTE - MEMSET_INT_FUNC_ATTRIBUTES static inline void memset_int_default(int32_t* dst, int32_t value, size_t size) CONFIG_NOEXCEPT_FUNCTION { @@ -133,10 +125,10 @@ static inline void memset_int_default(int32_t* dst, int32_t value, #pragma clang diagnostic ignored "-Wc++17-compat-mangling" #endif -ATTRIBUTE_NODISCARD_WITH_MESSAGE("this function is resolver and should not be used") -ATTRIBUTE_MAYBE_UNUSED ATTRIBUTE_NOTHROW ATTRIBUTE_RETURNS_NONNULL +ATTRIBUTE_MAYBE_UNUSED +ATTRIBUTE_NODISCARD_WITH_MESSAGE("this function is resolver and should not be used") #if defined(__clang__) __attribute__((no_sanitize("address", "thread", "memory", "undefined"))) #elif defined(__GNUC__) From 6ab9419b1f4d102c48ad4b1a6376d335cba6dbf5 Mon Sep 17 00:00:00 2001 From: i80287 Date: Wed, 30 Oct 2024 05:12:12 +0300 Subject: [PATCH 2/6] update CMakeLists.txt --- tests/CMakeLists.txt | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5444514..0bbf8c7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,15 @@ set(USING_MINGW_GCC False) set(USING_MINGW_GCC_32 False) set(USING_MSYS2_MINGW_GCC False) -# other versions can be added below depending on the compiler version +set(LINK_THREADS_LIBRARY_MANUALLY False) +set(LINK_COMPILER_RT_BUILTINS_MANUALLY False) + +# Empty by default +set(TEST_C_COMPILE_OPTIONS) +set(TEST_CXX_COMPILE_OPTIONS) +set(TEST_COMPILE_DEFINITIONS) + +# Other versions can be added below depending on the compiler version set(COMPILER_SUPPORTED_C_VERSIONS "99") set(COMPILER_SUPPORTED_CXX_VERSIONS "11;14;17") @@ -30,9 +38,6 @@ if(USING_MINGW_GCC) endif() endif() -set(LINK_THREADS_LIBRARY_MANUALLY False) -set(LINK_COMPILER_RT_BUILTINS_MANUALLY False) - if(CMAKE_SYSTEM_NAME MATCHES "Linux") find_program(CMAKE_CXX_CPPCHECK NAMES cppcheck) @@ -89,11 +94,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") endif() endif() -# Empty by default -set(TEST_C_COMPILE_OPTIONS) -set(TEST_CXX_COMPILE_OPTIONS) -set(TEST_COMPILE_DEFINITIONS) - function(configure_gcc_or_clang_gcc_options) if(MSVC) message(FATAL_ERROR "ClangCL should not be configured with this function") @@ -347,7 +347,6 @@ function(configure_msvc_or_clang_msvc_options) PARENT_SCOPE) endfunction(configure_msvc_or_clang_msvc_options) - # https://en.cppreference.com/w/cpp/compiler_support if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") @@ -536,12 +535,12 @@ if((NOT mingw_gcc_or_clang) OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 10.0. endif() unset(mingw_gcc_or_clang) -# list(APPEND TestFilenames "test_actrie.cpp") -# list(APPEND TestDirectories "tf_idf_actrie") -# list(APPEND TestLangVersions "20 23 26") -# list(APPEND TestDependencies "") -# list(APPEND TestOptionalDependencies "") -# list(APPEND TestIsCProject False) +list(APPEND TestFilenames "test_actrie.cpp") +list(APPEND TestDirectories "tf_idf_actrie") +list(APPEND TestLangVersions "20 23 26") +list(APPEND TestDependencies "") +list(APPEND TestOptionalDependencies "") +list(APPEND TestIsCProject False) list(APPEND TestFilenames "test_tf_idf_actrie.cpp search_lib.cpp") list(APPEND TestDirectories "tf_idf_actrie") From 5de01cba9d435cf60705c441539573c54e27122a Mon Sep 17 00:00:00 2001 From: i80287 Date: Wed, 30 Oct 2024 06:34:19 +0300 Subject: [PATCH 3/6] add new warning options to the CMakeLists.txt and update code --- tests/CMakeLists.txt | 78 +++++++++++++++++++++++++++++++++++----- tests/run_codechecker.sh | 2 -- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0bbf8c7..c4390e9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -135,6 +135,8 @@ function(configure_gcc_or_clang_gcc_options) -Wtype-limits -Wshift-negative-value -Walloca + -Wdate-time + -Wdouble-promotion -Werror -pedantic-errors ) @@ -170,7 +172,6 @@ function(configure_gcc_or_clang_gcc_options) -Wshift-sign-overflow -Wshorten-64-to-32 -Wthread-safety - -Wnull-pointer-arithmetic -Wnullable-to-nonnull-conversion -Wsometimes-uninitialized -Wstatic-in-inline @@ -183,6 +184,50 @@ function(configure_gcc_or_clang_gcc_options) -Wimplicit -Wimplicit-fallthrough -Winconsistent-missing-destructor-override + -Wabstract-vbase-init + -Warc-repeated-use-of-weak + -Wassign-enum + -Watomic-properties + -Watomic-implicit-seq-cst + -Wbad-function-cast + -Wbind-to-temporary-copy + -Wcast-function-type + -Wcomma + -Wc++-compat + -Wcalled-once-parameter + -Wcompound-token-split + -Wconditional-uninitialized + -Wconsumed + -Wdeprecated-implementations + -Wdirect-ivar-access + -Wdisabled-macro-expansion + # -Wdocumentation # TODO: + -Wdtor-name + -Wduplicate-decl-specifier + -Wduplicate-enum + -Wduplicate-method-arg + -Wduplicate-method-match + -Wexpansion-to-defined # enabled by the -Wextra on gcc + -Wexplicit-ownership-type + -Wloop-analysis + -Wextra-semi + -Wextra-semi-stmt + -Wheader-hygiene + -Wimplicit-retain-self + -Wimport-preprocessor-directive-pedantic + -Winvalid-or-nonexistent-directory + -Wmain # enabled by the -Wpedantic on gcc + -Wmethod-signatures + -Wmicrosoft + -Wnarrowing # enabled by the -Wpedantic on gcc + -Wnewline-eof + -Wover-aligned + -Woverriding-method-mismatch + -Wunguarded-availability + -Wunused-member-function + -Wused-but-marked-unused + -Wvector-conversion + -Wvla -fcolor-diagnostics -fansi-escape-codes -ftemplate-backtrace-limit=0) @@ -191,11 +236,6 @@ function(configure_gcc_or_clang_gcc_options) ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} -Wframe-address) endif() - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0.0) - set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS - ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} - -Wnull-pointer-subtraction) - endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0.0) set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} @@ -226,13 +266,27 @@ function(configure_gcc_or_clang_gcc_options) set(LOCAL_FN_TEST_C_COMPILE_OPTIONS ${LOCAL_FN_TEST_C_COMPILE_OPTIONS} -Wwrite-strings - -Wbad-function-cast -Wint-conversion ) - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0.0) + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(LOCAL_FN_TEST_C_COMPILE_OPTIONS ${LOCAL_FN_TEST_C_COMPILE_OPTIONS} - -fanalyzer + -Wincompatible-pointer-types # TODO: may be turned on by -Wpedantic ? + -Wbad-function-cast # added on the C++ stage if Clang is used + ) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0.0) + set(LOCAL_FN_TEST_C_COMPILE_OPTIONS + ${LOCAL_FN_TEST_C_COMPILE_OPTIONS} + -fanalyzer + ) + endif() + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(LOCAL_FN_TEST_C_COMPILE_OPTIONS + ${LOCAL_FN_TEST_C_COMPILE_OPTIONS} + -Wc11-extensions + -Wc23-compat + -Wc23-extensions ) endif() # Flags for C++ only @@ -249,6 +303,12 @@ function(configure_gcc_or_clang_gcc_options) ) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0.0) + set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS + ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} + -Wcomma-subscript + -Wregister + -Wchanges-meaning + ) set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} -fanalyzer diff --git a/tests/run_codechecker.sh b/tests/run_codechecker.sh index d7ecb04..f829f23 100755 --- a/tests/run_codechecker.sh +++ b/tests/run_codechecker.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash -set -e - build_dir=cmake-build-codechecker cmake_build_dir=cmake-build-dir From 017e5abe9056ef81537ee06efb99c14ca70c1034 Mon Sep 17 00:00:00 2001 From: i80287 Date: Wed, 30 Oct 2024 06:39:20 +0300 Subject: [PATCH 4/6] add new warning options to the CMakeLists.txt and update code --- bstrees/config_macros.hpp | 11 +++++++++++ graphs/HungarianAlgorithm/config_macros.hpp | 11 +++++++++++ number_theory/config_macros.hpp | 11 +++++++++++ number_theory/math_functions.hpp | 16 ++++++++-------- number_theory/test_tools.hpp | 2 +- tests/CMakeLists.txt | 17 +++++++++++++---- vec_instructs/config_macros.hpp | 11 +++++++++++ vec_instructs/test_memset_int.c | 6 ++++-- 8 files changed, 70 insertions(+), 15 deletions(-) diff --git a/bstrees/config_macros.hpp b/bstrees/config_macros.hpp index 0672803..f69c39c 100644 --- a/bstrees/config_macros.hpp +++ b/bstrees/config_macros.hpp @@ -660,7 +660,18 @@ ATTRIBUTE_ALWAYS_INLINE constexpr bool is_gcc_constant_p(ATTRIBUTE_MAYBE_UNUSED static_assert(std::is_trivial::value, "Type passed to the is_gcc_constant_p() should be trivial"); #endif + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wused-but-marked-unused" +#endif + return static_cast(__builtin_constant_p(expr)); + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + #else return false; #endif diff --git a/graphs/HungarianAlgorithm/config_macros.hpp b/graphs/HungarianAlgorithm/config_macros.hpp index 0672803..f69c39c 100644 --- a/graphs/HungarianAlgorithm/config_macros.hpp +++ b/graphs/HungarianAlgorithm/config_macros.hpp @@ -660,7 +660,18 @@ ATTRIBUTE_ALWAYS_INLINE constexpr bool is_gcc_constant_p(ATTRIBUTE_MAYBE_UNUSED static_assert(std::is_trivial::value, "Type passed to the is_gcc_constant_p() should be trivial"); #endif + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wused-but-marked-unused" +#endif + return static_cast(__builtin_constant_p(expr)); + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + #else return false; #endif diff --git a/number_theory/config_macros.hpp b/number_theory/config_macros.hpp index 0672803..f69c39c 100644 --- a/number_theory/config_macros.hpp +++ b/number_theory/config_macros.hpp @@ -660,7 +660,18 @@ ATTRIBUTE_ALWAYS_INLINE constexpr bool is_gcc_constant_p(ATTRIBUTE_MAYBE_UNUSED static_assert(std::is_trivial::value, "Type passed to the is_gcc_constant_p() should be trivial"); #endif + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wused-but-marked-unused" +#endif + return static_cast(__builtin_constant_p(expr)); + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + #else return false; #endif diff --git a/number_theory/math_functions.hpp b/number_theory/math_functions.hpp index c424f49..c23c191 100644 --- a/number_theory/math_functions.hpp +++ b/number_theory/math_functions.hpp @@ -352,8 +352,8 @@ ATTRIBUTE_CONST I128_CONSTEXPR uint64_t bin_pow_mod(uint64_t n, uint64_t p, uint template struct IsPerfectSquareResult { - bool is_perfect_square; - T root; + T root{}; + bool is_perfect_square{}; [[nodiscard]] constexpr explicit operator bool() const noexcept { return is_perfect_square; @@ -384,10 +384,10 @@ ATTRIBUTE_CONST constexpr IsPerfectSquareResult is_perfect_square(uint case 9: { const std::uint32_t root = ::math_functions::isqrt(n); const bool is_perf_square = root * root == n; - return {is_perf_square, is_perf_square ? root : 0}; + return {is_perf_square ? root : 0, is_perf_square}; } default: - return {false, 0}; + return {0, false}; } } @@ -415,10 +415,10 @@ ATTRIBUTE_CONST constexpr IsPerfectSquareResult is_perfect_square(uint case 9: { const std::uint32_t root = ::math_functions::isqrt(n); const bool is_perf_square = std::uint64_t{root} * root == n; - return {is_perf_square, is_perf_square ? root : 0}; + return {is_perf_square ? root : 0, is_perf_square}; } default: - return {false, 0}; + return {0, false}; } } @@ -449,10 +449,10 @@ ATTRIBUTE_CONST I128_CONSTEXPR case 9: { const std::uint64_t root = ::math_functions::isqrt(n); const bool is_perf_square = uint128_t{root} * root == n; - return {is_perf_square, is_perf_square ? root : 0}; + return {is_perf_square ? root : 0, is_perf_square}; } default: - return {false, 0}; + return {0, false}; } } diff --git a/number_theory/test_tools.hpp b/number_theory/test_tools.hpp index 8d40e5f..89e8f9e 100644 --- a/number_theory/test_tools.hpp +++ b/number_theory/test_tools.hpp @@ -131,7 +131,7 @@ ATTRIBUTE_ALWAYS_INLINE inline void log_tests_started_impl(const char* function_ #define log_tests_started() test_tools_detail::log_tests_started_impl(FUNCTION_MACRO) -#define log_location() test_tools_detail::log_location_impl(__FILE__, __LINE__, FUNCTION_MACRO); +#define log_location() test_tools_detail::log_location_impl(__FILE__, __LINE__, FUNCTION_MACRO) #define log_message(message) \ test_tools_detail::log_message_impl(__FILE__, __LINE__, FUNCTION_MACRO, message); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c4390e9..35e3b86 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -194,15 +194,12 @@ function(configure_gcc_or_clang_gcc_options) -Wcast-function-type -Wcomma -Wc++-compat - -Wcalled-once-parameter - -Wcompound-token-split -Wconditional-uninitialized -Wconsumed -Wdeprecated-implementations -Wdirect-ivar-access -Wdisabled-macro-expansion # -Wdocumentation # TODO: - -Wdtor-name -Wduplicate-decl-specifier -Wduplicate-enum -Wduplicate-method-arg @@ -234,7 +231,19 @@ function(configure_gcc_or_clang_gcc_options) if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0.0) set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} - -Wframe-address) + -Wframe-address + -Wdtor-name) + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0.0) + set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS + ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} + -Wcalled-once-parameter + -Wcompound-token-split) + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0.0) + set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS + ${LOCAL_FN_TEST_CXX_COMPILE_OPTIONS} + -Wcast-function-type) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0.0) set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS diff --git a/vec_instructs/config_macros.hpp b/vec_instructs/config_macros.hpp index 0672803..f69c39c 100644 --- a/vec_instructs/config_macros.hpp +++ b/vec_instructs/config_macros.hpp @@ -660,7 +660,18 @@ ATTRIBUTE_ALWAYS_INLINE constexpr bool is_gcc_constant_p(ATTRIBUTE_MAYBE_UNUSED static_assert(std::is_trivial::value, "Type passed to the is_gcc_constant_p() should be trivial"); #endif + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wused-but-marked-unused" +#endif + return static_cast(__builtin_constant_p(expr)); + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + #else return false; #endif diff --git a/vec_instructs/test_memset_int.c b/vec_instructs/test_memset_int.c index 4f08edd..2eb498f 100644 --- a/vec_instructs/test_memset_int.c +++ b/vec_instructs/test_memset_int.c @@ -5,9 +5,11 @@ #include "memset_int.h" +enum { kArrLen = 512 }; + int main(void) { - const size_t arr_len = 512; - int32_t buffer[arr_len + 1]; + const size_t arr_len = kArrLen; + int32_t buffer[kArrLen + 1]; const int32_t k = atoi("-1345452112"); for (size_t offset = 0; offset <= 1; offset++) { From 80d5dc52b890b5da942abc269abdbae535e7c2b0 Mon Sep 17 00:00:00 2001 From: i80287 Date: Wed, 30 Oct 2024 06:41:03 +0300 Subject: [PATCH 5/6] update warning options in the CMakeLists.txt --- tests/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 35e3b86..281c63a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -191,7 +191,6 @@ function(configure_gcc_or_clang_gcc_options) -Watomic-implicit-seq-cst -Wbad-function-cast -Wbind-to-temporary-copy - -Wcast-function-type -Wcomma -Wc++-compat -Wconditional-uninitialized From 9987b13724a07057483d4f668b4eb0ff0f3c42c8 Mon Sep 17 00:00:00 2001 From: i80287 Date: Wed, 30 Oct 2024 06:44:45 +0300 Subject: [PATCH 6/6] update warning options in the CMakeLists.txt --- tests/CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 281c63a..fec4afe 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -293,9 +293,14 @@ function(configure_gcc_or_clang_gcc_options) set(LOCAL_FN_TEST_C_COMPILE_OPTIONS ${LOCAL_FN_TEST_C_COMPILE_OPTIONS} -Wc11-extensions - -Wc23-compat - -Wc23-extensions ) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 18.0.1) + set(LOCAL_FN_TEST_C_COMPILE_OPTIONS + ${LOCAL_FN_TEST_C_COMPILE_OPTIONS} + -Wc23-compat + -Wc23-extensions + ) + endif() endif() # Flags for C++ only set(LOCAL_FN_TEST_CXX_COMPILE_OPTIONS