15#include "delpi/symbolic/Variable.h"
16#include "delpi/util/concepts.h"
17#include "delpi/util/exception.h"
36 static_assert(std::is_copy_constructible_v<T>,
"T must be copy constructible");
39 using Id = Variable::Id;
41 using mapped_type = T;
42 using value_type = std::pair<const Variable, T>;
45 VariableMap() :
min_id_{std::numeric_limits<Id>::max()} {}
51 template <TypedIterable<value_type> Items>
57 [[nodiscard]] Id min_id()
const {
return min_id_; }
59 [[nodiscard]] Id max_id()
const {
return vars_.size() +
min_id_; }
61 [[nodiscard]] std::size_t size()
const {
62 return std::ranges::count_if(
vars_, [](
const std::optional<mapped_type>& item) {
return item.has_value(); });
65 [[nodiscard]] std::size_t capacity()
const {
return vars_.size(); }
67 [[nodiscard]]
bool empty()
const {
return vars_.empty(); }
69 [[nodiscard]] std::vector<mapped_type> items()
const {
70 std::vector<mapped_type> items;
71 items.reserve(
vars_.size());
72 for (
const std::optional<mapped_type>& item :
vars_) {
73 if (item.has_value()) items.emplace_back(item.value());
110 template <TypedIterable<value_type> I>
112 const auto Comparator = [](
const std::pair<Variable, T>& a,
const std::pair<Variable, T>& b) {
113 return a.first.less(b.first);
116 if (
min_id_ == std::numeric_limits<Id>::max()) {
117 min_id_ = std::ranges::min_element(items, Comparator)->first.id();
118 vars_.resize(std::ranges::max_element(items, Comparator)->first.id() -
min_id_ + 1,
false);
119 for (
const value_type& item : items)
vars_.at(item.first.id() -
min_id_) = item.second;
125 const Id new_min = std::min(std::ranges::min_element(items, Comparator)->first.id(),
min_id_);
126 const Id new_max = std::max(std::ranges::max_element(items, Comparator)->first.id(),
vars_.size() +
min_id_ - 1);
127 const std::size_t max_diff = new_max - (
vars_.size() +
min_id_ - 1);
128 const std::size_t old_size =
vars_.size();
129 vars_.resize(new_max - new_min + 1);
132 std::rotate(
vars_.begin(),
vars_.begin() +
static_cast<std::int64_t
>(old_size),
133 vars_.end() -
static_cast<std::int64_t
>(max_diff));
136 for (
const value_type& item : items)
vars_.at(item.first.id() -
min_id_) = item.second;
151 template <TypedIterable<Variable> V>
158 min_id_ = std::numeric_limits<Id>::max();
178 bool Insert(
const Id
id,
const T& value) {
179 if (
min_id_ == std::numeric_limits<Id>::max()) {
181 vars_.emplace_back(value);
188 vars_.front() = value;
193 vars_.back() = value;
207 const bool was_present =
vars_.at(
id -
min_id_).has_value();
213 std::vector<std::optional<T>>
vars_;
217std::ostream& operator<<(std::ostream& os,
const VariableMap<T>& var_map);
223#ifdef DELPI_INCLUDE_FMT
225#include "delpi/util/logging.h"
Exception for out of range errors.
Map from variables to an arbitrary type T optimised for fast access at the cost of memory.
mapped_type At(const Variable var) const
Use the var to get the value it is mapped to, if it exists.
bool Insert(const Id id, const T &value)
Insert a variable with the given id to the map and set it to the value.
VariableMap(const Items &items)
Construct a new variable map from a range of items.
bool Contains(const Id id) const
Check if the variable with the given id is in the map.
bool Contains(const Variable &var) const
Check if the var is in the map.
void Insert(const I &items)
Insert a range of key-value pairs to the map.
bool Remove(const Id id)
Remove a variable with the given id from the map.
bool empty() const
@checked{empty, variable map}
std::vector< std::optional< T > > vars_
Vector tracking the value each variable is mapped to.
bool Remove(const Variable &var)
Remove a var from the map.
void Clear()
Clear the map of all variables.
bool Insert(const Variable &var, const mapped_type &value)
Insert a var to the map and set it to the value.
Id min_id_
Minimum id of the variables in the map.
void Remove(const V &vars)
Remove a range of vars from the map.
Global namespace for the delpi library.