diff --git a/CMakeLists.txt b/CMakeLists.txt
index b5b2a5c9..bce8e828 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -160,12 +160,9 @@ if(${mp++_VERSION} VERSION_LESS ${_OBAKE_MIN_MPPP_VERSION})
message(FATAL_ERROR "The minimum mp++ version required by obake is ${_OBAKE_MIN_MPPP_VERSION}, but version ${mp++_VERSION} was found instead.")
endif()
-# abseil.
-find_package(absl REQUIRED)
-
# Boost setup.
-# NOTE: stacktrace available since 1.65.0.
-set(_OBAKE_MIN_BOOST_VERSION "1.69")
+# NOTE: need 1.81 for unordered_flat_set.
+set(_OBAKE_MIN_BOOST_VERSION "1.81")
# NOTE: we look for Boost in CONFIG mode first, as that has become the official supported way
# of locating Boost in recent Boost/CMake versions. If we fail, we try again in
# MODULE mode as last resort.
@@ -307,7 +304,6 @@ if(YACMA_COMPILER_IS_MSVC)
"${CMAKE_CURRENT_LIST_DIR}/include/obake/key/key_tex_stream_insert.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/obake/key/key_trim.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/obake/key/key_trim_identify.hpp"
- "${CMAKE_CURRENT_LIST_DIR}/include/obake/detail/abseil.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/obake/detail/atomic_flag_array.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/obake/detail/atomic_lock_guard.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/obake/detail/fcast.hpp"
@@ -360,13 +356,6 @@ target_compile_options(obake PRIVATE
target_compile_features(obake PUBLIC cxx_std_20)
# Ensure vanilla C++ is being used.
set_property(TARGET obake PROPERTY CXX_EXTENSIONS NO)
-if(YACMA_COMPILER_IS_MSVC)
- # NOTE: older abseil versions have a problem on MSVC
- # when using C++20:
- # https://github.com/abseil/abseil-cpp/issues/649
- # Hopefully we can eventually remove this.
- target_compile_definitions(obake PUBLIC -D_HAS_DEPRECATED_RESULT_OF=1)
-endif()
if(YACMA_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10")
# GCC < 10 still needs the -fconcepts flag, even if C++20 is in use.
message(STATUS "Activating the '-fconcepts' flag for GCC < 10.")
@@ -383,8 +372,6 @@ target_include_directories(obake PUBLIC
target_link_libraries(obake PUBLIC
Threads::Threads
mp++::mp++
- absl::flat_hash_map
- absl::flat_hash_set
Boost::boost
Boost::serialization
Boost::disable_autolinking
diff --git a/doc/install.rst b/doc/install.rst
index 5fb3ad90..33c14a61 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -11,8 +11,7 @@ Requirements
Currently, obake has the following mandatory dependencies:
* the `mp++ `_ multiprecision library (at least version 0.27),
-* the `Boost `_ C++ libraries (at least version 1.65),
-* the `Abseil `_ C++ libraries,
+* the `Boost `_ C++ libraries (at least version 1.81),
* the `Intel TBB `__ library,
* the `{fmt} `__ library.
diff --git a/include/obake/detail/abseil.hpp b/include/obake/detail/abseil.hpp
deleted file mode 100644
index 09d3fa55..00000000
--- a/include/obake/detail/abseil.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2019-2020 Francesco Biscani (bluescarni@gmail.com)
-//
-// This file is part of the obake library.
-//
-// This Source Code Form is subject to the terms of the Mozilla
-// Public License v. 2.0. If a copy of the MPL was not distributed
-// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef OBAKE_DETAIL_ABSEIL_HPP
-#define OBAKE_DETAIL_ABSEIL_HPP
-
-// NOTE: on MSVC, some abseil headers give
-// warnings in debug mode, which make
-// obake's debug builds fail. Suppress
-// those warnings.
-#if defined(_MSC_VER) && !defined(__clang__)
-
-#pragma warning(push)
-#pragma warning(disable : 4245)
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4996)
-#pragma warning(disable : 4324)
-
-#endif
-
-#include
-#include
-#include
-#include
-
-#if defined(_MSC_VER) && !defined(__clang__)
-
-#pragma warning(pop)
-
-#endif
-
-#endif
diff --git a/include/obake/polynomials/polynomial.hpp b/include/obake/polynomials/polynomial.hpp
index 992cc7cc..1a007f39 100644
--- a/include/obake/polynomials/polynomial.hpp
+++ b/include/obake/polynomials/polynomial.hpp
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include
#include
@@ -41,7 +42,6 @@
#include
#include
-#include
#include
#include
#include
@@ -120,111 +120,111 @@ concept Polynomial = is_polynomial_v;
namespace detail
{
- // Enabler for make_polynomials():
- // - need at least 1 Arg,
- // - T must be a polynomial,
- // - std::string can be constructed from each input Args,
- // - poly key can be constructed from a const int * range,
- // - poly cf can be constructed from an integral literal.
- template
- using make_polynomials_supported
- = ::std::conjunction<::std::integral_constant 0u)>, is_polynomial,
- ::std::is_constructible<::std::string, const Args &>...,
- ::std::is_constructible, const int *, const int *>,
- ::std::is_constructible, int>>;
-
- template
- using make_polynomials_enabler = ::std::enable_if_t::value, int>;
-
- // Overload with a symbol set.
- template = 0>
- inline auto make_polynomials_impl(const symbol_set &ss, const Args &...names)
- {
- // Create a temp vector of ints which we will use to
- // init the keys.
- ::std::vector tmp(::obake::safe_cast<::std::vector::size_type>(ss.size()));
-
- // Create the fw version of the symbol set.
- const detail::ss_fw ss_fw(ss);
-
- auto make_poly = [&ss_fw, &ss, &tmp](const auto &n) {
- using str_t = remove_cvref_t;
-
- // Fetch a const reference to either the original
- // std::string object n, or to a string temporary
- // created from it.
- const auto &s = [&n]() -> decltype(auto) {
- if constexpr (::std::is_same_v) {
- return n;
- } else {
- return ::std::string(n);
- }
- }();
+// Enabler for make_polynomials():
+// - need at least 1 Arg,
+// - T must be a polynomial,
+// - std::string can be constructed from each input Args,
+// - poly key can be constructed from a const int * range,
+// - poly cf can be constructed from an integral literal.
+template
+using make_polynomials_supported
+ = ::std::conjunction<::std::integral_constant 0u)>, is_polynomial,
+ ::std::is_constructible<::std::string, const Args &>...,
+ ::std::is_constructible, const int *, const int *>,
+ ::std::is_constructible, int>>;
+
+template
+using make_polynomials_enabler = ::std::enable_if_t::value, int>;
+
+// Overload with a symbol set.
+template = 0>
+inline auto make_polynomials_impl(const symbol_set &ss, const Args &...names)
+{
+ // Create a temp vector of ints which we will use to
+ // init the keys.
+ ::std::vector tmp(::obake::safe_cast<::std::vector::size_type>(ss.size()));
- // Init the retval, assign the symbol set.
- T retval;
- retval.set_symbol_set_fw(ss_fw);
+ // Create the fw version of the symbol set.
+ const detail::ss_fw ss_fw(ss);
- // Try to locate s within the symbol set.
- const auto it = ss.find(s);
- if (obake_unlikely(it == ss.end() || *it != s)) {
- obake_throw(::std::invalid_argument, "Cannot create a polynomial with symbol set "
- + detail::to_string(ss) + " from the generator '" + s
- + "': the generator is not in the symbol set");
+ auto make_poly = [&ss_fw, &ss, &tmp](const auto &n) {
+ using str_t = remove_cvref_t;
+
+ // Fetch a const reference to either the original
+ // std::string object n, or to a string temporary
+ // created from it.
+ const auto &s = [&n]() -> decltype(auto) {
+ if constexpr (::std::is_same_v) {
+ return n;
+ } else {
+ return ::std::string(n);
}
+ }();
- // Set to 1 the exponent of the corresponding generator.
- tmp[static_cast<::std::vector::size_type>(ss.index_of(it))] = 1;
+ // Init the retval, assign the symbol set.
+ T retval;
+ retval.set_symbol_set_fw(ss_fw);
- // Create and add a new term.
- // NOTE: at least for some monomial types (e.g., packed monomial),
- // we will be computing the iterator difference when constructing from
- // a range. Make sure we can safely represent the size of tmp via
- // iterator difference.
- ::obake::detail::it_diff_check(tmp.size());
- retval.add_term(series_key_t(::std::as_const(tmp).data(), ::std::as_const(tmp).data() + tmp.size()), 1);
+ // Try to locate s within the symbol set.
+ const auto it = ss.find(s);
+ if (obake_unlikely(it == ss.end() || *it != s)) {
+ obake_throw(::std::invalid_argument, "Cannot create a polynomial with symbol set " + detail::to_string(ss)
+ + " from the generator '" + s
+ + "': the generator is not in the symbol set");
+ }
- // Set back to zero the exponent that was previously set to 1.
- tmp[static_cast<::std::vector::size_type>(ss.index_of(it))] = 0;
+ // Set to 1 the exponent of the corresponding generator.
+ tmp[static_cast<::std::vector::size_type>(ss.index_of(it))] = 1;
- return retval;
- };
+ // Create and add a new term.
+ // NOTE: at least for some monomial types (e.g., packed monomial),
+ // we will be computing the iterator difference when constructing from
+ // a range. Make sure we can safely represent the size of tmp via
+ // iterator difference.
+ ::obake::detail::it_diff_check(tmp.size());
+ retval.add_term(series_key_t(::std::as_const(tmp).data(), ::std::as_const(tmp).data() + tmp.size()), 1);
- return detail::make_array(make_poly(names)...);
- }
+ // Set back to zero the exponent that was previously set to 1.
+ tmp[static_cast<::std::vector::size_type>(ss.index_of(it))] = 0;
- // Overload without a symbol set.
- template = 0>
- inline auto make_polynomials_impl(const Args &...names)
- {
- auto make_poly = [](const auto &n) {
- using str_t = remove_cvref_t;
+ return retval;
+ };
- // Init the retval, assign a symbol set containing only n.
- T retval;
- if constexpr (::std::is_same_v) {
- retval.set_symbol_set(symbol_set{n});
- } else {
- retval.set_symbol_set(symbol_set{::std::string(n)});
- }
+ return detail::make_array(make_poly(names)...);
+}
+
+// Overload without a symbol set.
+template = 0>
+inline auto make_polynomials_impl(const Args &...names)
+{
+ auto make_poly = [](const auto &n) {
+ using str_t = remove_cvref_t;
+
+ // Init the retval, assign a symbol set containing only n.
+ T retval;
+ if constexpr (::std::is_same_v) {
+ retval.set_symbol_set(symbol_set{n});
+ } else {
+ retval.set_symbol_set(symbol_set{::std::string(n)});
+ }
- static constexpr int arr[] = {1};
+ static constexpr int arr[] = {1};
- // Create and add a new term.
- retval.add_term(series_key_t(&arr[0], &arr[0] + 1), 1);
+ // Create and add a new term.
+ retval.add_term(series_key_t(&arr[0], &arr[0] + 1), 1);
- return retval;
- };
+ return retval;
+ };
- return detail::make_array(make_poly(names)...);
- }
+ return detail::make_array(make_poly(names)...);
+}
} // namespace detail
// Polynomial creation functor.
template
-inline constexpr auto make_polynomials
- = [](const auto &...args) OBAKE_SS_FORWARD_LAMBDA(detail::make_polynomials_impl(args...));
+inline constexpr auto make_polynomials =
+ [](const auto &...args) OBAKE_SS_FORWARD_LAMBDA(detail::make_polynomials_impl(args...));
namespace polynomials
{
@@ -666,8 +666,8 @@ inline auto poly_mul_estimate_product_size(const ::std::vector &x, const ::s
// Init the hash set we will be using for the trials.
// NOTE: use exactly the same hasher/comparer as in series.hpp, so that
// we are sure we are being consistent wrt type requirements, etc.
- using local_set = ::absl::flat_hash_set;
+ using local_set = ::boost::unordered_flat_set;
local_set ls;
ls.reserve(::obake::safe_cast(vidx1.size()));
@@ -1361,15 +1361,8 @@ inline void poly_mul_impl_mt_hm(Ret &retval, const T &x, const U &y, const Args
// coefficient. This is wasteful, it would be better to directly
// construct the coefficient product only if the insertion actually
// takes place (using a lazy multiplication approach).
- // Unfortunately, abseil's hash map is not exception safe,
- // and if the lazy multiplication throws, the table will be left
- // in an inconsistent state. See:
- // https://github.com/abseil/abseil-cpp/issues/388
- // See the commit
- // 3e334f560d5844f5f2d8face05aa58be21649ff8
+ // See the commit 3e334f560d5844f5f2d8face05aa58be21649ff8
// for an implementation of the lazy multiplication approach.
- // If they fix the exception safety issue, we can re-enable the
- // lazy approach.
// NOTE: the coefficient concept demands default constructibility,
// thus we can always emplace without arguments for the coefficient.
const auto res = table.try_emplace(tmp_key);
@@ -1401,11 +1394,10 @@ inline void poly_mul_impl_mt_hm(Ret &retval, const T &x, const U &y, const Args
// in the current table.
const auto it_f = table.end();
for (auto it = table.begin(); it != it_f;) {
- // NOTE: abseil's flat_hash_map returns void on erase(),
- // thus we need to increase 'it' before possibly erasing.
- // erase() does not cause rehash and thus will not invalidate
- // any other iterator apart from the one being erased.
if (obake_unlikely(::obake::is_zero(::std::as_const(it->second)))) {
+ // NOTE: increase 'it' before erasing.
+ // erase() does not cause rehash and thus will not invalidate
+ // any other iterator apart from the one being erased.
table.erase(it++);
} else {
++it;
@@ -1504,15 +1496,8 @@ inline void poly_mul_impl_mt_hm(Ret &retval, const T &x, const U &y, const Args
// coefficient. This is wasteful, it would be better to directly
// construct the coefficient product only if the insertion actually
// takes place (using a lazy multiplication approach).
- // Unfortunately, abseil's hash map is not exception safe,
- // and if the lazy multiplication throws, the table will be left
- // in an inconsistent state. See:
- // https://github.com/abseil/abseil-cpp/issues/388
- // See the commit
- // 3e334f560d5844f5f2d8face05aa58be21649ff8
+ // See the commit 3e334f560d5844f5f2d8face05aa58be21649ff8
// for an implementation of the lazy multiplication approach.
- // If they fix the exception safety issue, we can re-enable the
- // lazy approach.
// NOTE: the coefficient concept demands default constructibility,
// thus we can always emplace without arguments for the coefficient.
const auto res = table.try_emplace(tmp_key);
@@ -1544,11 +1529,10 @@ inline void poly_mul_impl_mt_hm(Ret &retval, const T &x, const U &y, const Args
// in the current table.
const auto it_f = table.end();
for (auto it = table.begin(); it != it_f;) {
- // NOTE: abseil's flat_hash_map returns void on erase(),
- // thus we need to increase 'it' before possibly erasing.
- // erase() does not cause rehash and thus will not invalidate
- // any other iterator apart from the one being erased.
if (obake_unlikely(::obake::is_zero(::std::as_const(it->second)))) {
+ // NOTE: increase 'it' before erasing.
+ // erase() does not cause rehash and thus will not invalidate
+ // any other iterator apart from the one being erased.
table.erase(it++);
} else {
++it;
@@ -1867,11 +1851,10 @@ inline void poly_mul_impl_simple(Ret &retval, const T &x, const U &y, const Args
// in the return value.
const auto it_f = tab.end();
for (auto it = tab.begin(); it != it_f;) {
- // NOTE: abseil's flat_hash_map returns void on erase(),
- // thus we need to increase 'it' before possibly erasing.
- // erase() does not cause rehash and thus will not invalidate
- // any other iterator apart from the one being erased.
if (obake_unlikely(::obake::is_zero(::std::as_const(it->second)))) {
+ // NOTE: increase 'it' before erasing.
+ // erase() does not cause rehash and thus will not invalidate
+ // any other iterator apart from the one being erased.
tab.erase(it++);
} else {
++it;
@@ -2041,8 +2024,9 @@ inline auto poly_mul_impl_switch(const T &x, const U &y, const Args &...args)
} // namespace detail
template
-requires(detail::poly_mul_algo, polynomial> != 0) inline detail::poly_mul_ret_t<
- polynomial, polynomial> series_mul(const polynomial &x, const polynomial &y)
+ requires(detail::poly_mul_algo, polynomial> != 0)
+inline detail::poly_mul_ret_t, polynomial> series_mul(const polynomial &x,
+ const polynomial &y)
{
return detail::poly_mul_impl_switch(x, y);
}
@@ -2127,18 +2111,17 @@ inline constexpr auto poly_mul_truncated_p_degree_algo
// NOTE: do we need the type traits/concepts as well?
// NOTE: should these be function objects?
template
-requires(detail::poly_mul_truncated_degree_algo, polynomial, V> != 0) inline detail::
- poly_mul_ret_t, polynomial> truncated_mul(const polynomial &x,
- const polynomial &y, const V &max_degree)
+ requires(detail::poly_mul_truncated_degree_algo, polynomial, V> != 0)
+inline detail::poly_mul_ret_t, polynomial>
+truncated_mul(const polynomial &x, const polynomial &y, const V &max_degree)
{
return detail::poly_mul_impl_switch(x, y, max_degree);
}
template
-requires(detail::poly_mul_truncated_p_degree_algo, polynomial, V> != 0) inline detail::
- poly_mul_ret_t, polynomial> truncated_mul(const polynomial &x,
- const polynomial &y, const V &max_degree,
- const symbol_set &s)
+ requires(detail::poly_mul_truncated_p_degree_algo, polynomial, V> != 0)
+inline detail::poly_mul_ret_t, polynomial>
+truncated_mul(const polynomial &x, const polynomial &y, const V &max_degree, const symbol_set &s)
{
return detail::poly_mul_impl_switch(x, y, max_degree, s);
}
@@ -2193,9 +2176,8 @@ inline auto pow_poly_impl(T &&x, U &&y)
// Exponentiation.
template
-requires Polynomial> &&(
- customisation::internal::series_default_pow_algo<
- T &&, U &&> != 0) inline customisation::internal::series_default_pow_ret_t pow(T &&x, U &&y)
+ requires Polynomial> && (customisation::internal::series_default_pow_algo != 0)
+inline customisation::internal::series_default_pow_ret_t pow(T &&x, U &&y)
{
return detail::pow_poly_impl(::std::forward(x), ::std::forward(y));
}
@@ -2327,8 +2309,8 @@ inline auto poly_subs_impl(T &&x_, const symbol_map &sm)
// Polynomial subs.
template
-requires Polynomial> &&(
- detail::poly_subs_algo != 0) inline detail::poly_subs_ret_t subs(T &&x, const symbol_map &sm)
+ requires Polynomial> && (detail::poly_subs_algo != 0)
+inline detail::poly_subs_ret_t subs(T &&x, const symbol_map &sm)
{
return detail::poly_subs_impl(::std::forward(x), sm);
}
@@ -2662,8 +2644,8 @@ inline auto poly_diff_impl(T &&x_, const ::std::string &s)
} // namespace detail
template
-requires Polynomial> &&(detail::poly_diff_algo != 0) inline detail::poly_diff_ret_t diff(
- T &&x, const ::std::string &s)
+ requires Polynomial> && (detail::poly_diff_algo != 0)
+inline detail::poly_diff_ret_t diff(T &&x, const ::std::string &s)
{
return detail::poly_diff_impl(::std::forward(x), s);
}
@@ -2876,9 +2858,8 @@ inline auto poly_integrate_impl(T &&x_, const ::std::string &s)
} // namespace detail
template
-requires Polynomial> &&(
- detail::poly_integrate_algo != 0) inline detail::poly_integrate_ret_t integrate(T &&x,
- const ::std::string &s)
+ requires Polynomial> && (detail::poly_integrate_algo != 0)
+inline detail::poly_integrate_ret_t integrate(T &&x, const ::std::string &s)
{
return detail::poly_integrate_impl(::std::forward(x), s);
}
diff --git a/include/obake/series.hpp b/include/obake/series.hpp
index f03737c9..6c3a890d 100644
--- a/include/obake/series.hpp
+++ b/include/obake/series.hpp
@@ -37,6 +37,7 @@
#include
#include
#include
+#include
#include
@@ -50,7 +51,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -483,39 +483,12 @@ concept SeriesConvertible = is_series_convertible_v;
namespace detail
{
-// A small hashing wrapper for keys. It accomplishes two tasks:
-// - force the evaluation of a key through const reference,
-// so that, in the Key requirements, we can request hashability
-// through const lvalue ref;
-// - provide additional mixing.
+// Wrapper to force key hashing via const lvalue refs.
struct series_key_hasher {
- // NOTE: here we are duplicating a bit of internal
- // abseil code for integral hash mixing, with the intent
- // of avoiding the per-process seeding that abseil does.
- // See here for the original code:
- // https://github.com/abseil/abseil-cpp/blob/37dd2562ec830d547a1524bb306be313ac3f2556/absl/hash/internal/hash.h#L754
- // If/when abseil starts supporting DLL builds, we can
- // remove this code and switch back to using abseil's
- // own hash machinery for mixing.
- static constexpr ::std::uint64_t kMul
- = sizeof(::std::size_t) == 4u ? ::std::uint64_t{0xcc9e2d51ull} : ::std::uint64_t{0x9ddfea08eb382d69ull};
- ABSL_ATTRIBUTE_ALWAYS_INLINE static ::std::uint64_t Mix(::std::uint64_t state, ::std::uint64_t v)
- {
- using MultType = ::std::conditional_t;
- // We do the addition in 64-bit space to make sure the 128-bit
- // multiplication is fast. If we were to do it as MultType the compiler has
- // to assume that the high word is non-zero and needs to perform 2
- // multiplications instead of one.
- MultType m = state + v;
- m *= kMul;
- return static_cast<::std::uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2)));
- }
template
::std::size_t operator()(const K &k) const noexcept(noexcept(::obake::hash(k)))
{
- // NOTE: mix with a compile-time seed.
- return static_cast<::std::size_t>(
- series_key_hasher::Mix(15124392053943080205ull, static_cast<::std::uint64_t>(::obake::hash(k))));
+ return ::obake::hash(k);
}
};
@@ -661,7 +634,8 @@ class series
public:
// Define the table type, and the type holding the set of tables (i.e., the segmented table).
- using table_type = ::absl::flat_hash_map;
+ using table_type
+ = ::boost::unordered::unordered_flat_map;
using s_table_type = ::boost::container::small_vector;
// Shortcut for the segmented table size type.
@@ -1518,11 +1492,6 @@ class series
// - the original table had no incompatible keys,
// - the original table did not overflow the max size,
// - the original table had only unique keys.
- // Note that deserialisation of a series that was saved
- // in a previous program execution will result in a term
- // order different from the original one due to abseil's salting,
- // but the number of terms in a specific table will be the same
- // because the first level hash is not salted.
// NOTE: this is essentially identical to a straight emplace_back()
// on the table, just with some added assertions.
detail::series_add_term_table) - (sizeof(k) + sizeof(c)));
}
- // Add the space occupied by the unused slots.
- assert(tab.capacity() >= tab.size());
- ret += (tab.capacity() - tab.size()) * sizeof(series_term_t);
-
+ // NOTE: here we are not accounting for the empty slots in the table.
+ // Hopefully we do not end up very far from the true memory utilisation.
return ret;
}
template
@@ -3346,8 +3313,7 @@ inline series_default_div_ret_t series_default_div_impl(T &&x, U &&y
c /= ::std::as_const(y);
if (obake_unlikely(::obake::is_zero(::std::as_const(c)))) {
- // NOTE: abseil's flat_hash_map returns void on erase(),
- // thus we need to increase 'it' before possibly erasing.
+ // NOTE: increase 'it' before erasing.
// erase() does not cause rehash and thus will not invalidate
// any other iterator apart from the one being erased.
t.erase(it++);
@@ -4288,13 +4254,12 @@ inline void filter_impl(series &s, const F &f)
const auto it_f = table.end();
for (auto it = table.begin(); it != it_f;) {
- // NOTE: abseil's flat_hash_map returns void on erase(),
- // thus we need to increase 'it' before possibly erasing.
- // erase() does not cause rehash and thus will not invalidate
- // any other iterator apart from the one being erased.
if (f(::std::as_const(*it))) {
++it;
} else {
+ // NOTE: increase 'it' before erasing.
+ // erase() does not cause rehash and thus will not invalidate
+ // any other iterator apart from the one being erased.
table.erase(it++);
}
}
diff --git a/obake-config.cmake.in b/obake-config.cmake.in
index e0917c0d..9e65db1b 100644
--- a/obake-config.cmake.in
+++ b/obake-config.cmake.in
@@ -8,7 +8,6 @@ find_package(mp++ REQUIRED)
if(${mp++_VERSION} VERSION_LESS @_OBAKE_MIN_MPPP_VERSION@)
message(FATAL_ERROR "The minimum mp++ version required by obake is @_OBAKE_MIN_MPPP_VERSION@, but version ${mp++_VERSION} was found instead.")
endif()
-find_package(absl REQUIRED)
# TBB. Try to find it first in config mode (supported
# since version 2021 after the oneTBB rename), and, if this
# fails, fall back to our own FindTBB.cmake. This is of course
diff --git a/tools/conda_asan.sh b/tools/conda_asan.sh
index 33ecbd1e..d3381b51 100644
--- a/tools/conda_asan.sh
+++ b/tools/conda_asan.sh
@@ -11,7 +11,7 @@ export deps_dir=$HOME/local
export PATH="$HOME/miniconda/bin:$PATH"
bash miniconda.sh -b -p $HOME/miniconda
conda create -y -p $deps_dir cmake c-compiler cxx-compiler fmt backtrace mppp \
- libboost-devel libabseil tbb-devel ninja
+ libboost-devel tbb-devel ninja
source activate $deps_dir
# Create the build dir and cd into it.
diff --git a/tools/conda_coverage.sh b/tools/conda_coverage.sh
index b26a45bd..2b78759f 100644
--- a/tools/conda_coverage.sh
+++ b/tools/conda_coverage.sh
@@ -15,7 +15,7 @@ bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --add channels conda-forge
conda config --set channel_priority strict
-conda_pkgs="cmake mppp boost-cpp tbb tbb-devel abseil-cpp backtrace fmt"
+conda_pkgs="cmake mppp boost-cpp tbb tbb-devel backtrace fmt"
conda create -q -p $deps_dir -y $conda_pkgs
source activate $deps_dir
diff --git a/tools/conda_docs.sh b/tools/conda_docs.sh
index a77b8e2d..67e624d1 100644
--- a/tools/conda_docs.sh
+++ b/tools/conda_docs.sh
@@ -15,7 +15,7 @@ bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --add channels conda-forge
conda config --set channel_priority strict
-conda_pkgs="cmake mppp boost-cpp tbb tbb-devel abseil-cpp fmt backtrace sphinx pip"
+conda_pkgs="cmake mppp boost-cpp tbb tbb-devel fmt backtrace sphinx pip"
conda create -q -p $deps_dir -y $conda_pkgs
source activate $deps_dir
diff --git a/tools/conda_ubsan.sh b/tools/conda_ubsan.sh
index 417957dd..329b56a1 100644
--- a/tools/conda_ubsan.sh
+++ b/tools/conda_ubsan.sh
@@ -15,7 +15,7 @@ bash miniconda.sh -b -p $HOME/miniconda
export PATH="$HOME/miniconda/bin:$PATH"
conda config --add channels conda-forge
conda config --set channel_priority strict
-conda_pkgs="cmake mppp boost-cpp tbb tbb-devel abseil-cpp fmt backtrace"
+conda_pkgs="cmake mppp boost-cpp tbb tbb-devel fmt backtrace"
conda create -q -p $deps_dir -y $conda_pkgs
source activate $deps_dir