66#ifndef TPL_CA_GHOST_LATTICE_H
67#define TPL_CA_GHOST_LATTICE_H
82namespace ca_ghost_detail {
85template <std::
size_t N>
86inline std::array<ca_size_t, N>
enlarge_extents(
const std::array<ca_size_t, N> &user,
87 const std::size_t
halo)
noexcept
89 std::array<ca_size_t, N> e{};
90 for (std::size_t d = 0; d <
N; ++d)
91 e[d] = user[d] == 0 ? 0 : user[d] + 2 *
halo;
127 return u >= n ? n - 1 : u;
151template <
typename Storage,
typename Boundary = OpenBoundary, std::
size_t Halo = 1>
154 static_assert(
Halo >= 1,
"Ghost_Lattice requires Halo >= 1");
164 static constexpr std::size_t
rank = Storage::rank;
177 for (std::size_t d = 0; d <
rank; ++d)
185 if constexpr (ca_lattice_detail::is_constant_boundary_v<Boundary>)
186 return static_cast<state_type>(Boundary::value);
196 using namespace ca_ghost_detail;
197 for (std::size_t d = 0; d <
rank; ++d)
203 if constexpr (std::is_same_v<Boundary, ToroidalBoundary>)
205 c[d] =
static_cast<ca_index_t>(positive_mod(c[d], n));
207 else if constexpr (std::is_same_v<Boundary, ReflectiveBoundary>)
209 c[d] =
static_cast<ca_index_t>(reflect_index(c[d], n));
211 else if constexpr (std::is_same_v<Boundary, NeumannBoundary>)
213 c[d] =
static_cast<ca_index_t>(clamp_index(c[d], n));
236 template <
typename F>
239 for (std::size_t d = 0; d <
rank; ++d)
343 for (std::size_t d = 0; d <
rank; ++d)
355 <<
"Ghost_Lattice::size: axis " << d <<
" out of range";
374 for (std::size_t d = 0; d <
rank; ++d)
376 <<
"Ghost_Lattice::at: coord[" << d <<
"]=" << c[d] <<
" out of [0, "
393 for (std::size_t d = 0; d <
rank; ++d)
395 <<
"Ghost_Lattice::set: coord[" << d <<
"]=" << c[d] <<
" out of [0, "
422 for (std::size_t d = 0; d <
rank; ++d)
427 if (c[d] < -
h or c[d] >= n +
h)
458 if constexpr (std::is_same_v<Boundary, OpenBoundary>)
462 else if constexpr (ca_lattice_detail::is_constant_boundary_v<Boundary>)
467 else if constexpr (std::is_same_v<Boundary, NeumannBoundary>)
472 for (std::size_t d = 0; d <
rank; ++d)
478 else if constexpr (std::is_same_v<Boundary, ToroidalBoundary>)
483 for (std::size_t d = 0; d <
rank; ++d)
489 else if constexpr (std::is_same_v<Boundary, ReflectiveBoundary>)
494 for (std::size_t d = 0; d <
rank; ++d)
502 static_assert(std::is_same_v<Boundary, OpenBoundary>
503 or std::is_same_v<Boundary, ToroidalBoundary>
504 or std::is_same_v<Boundary, ReflectiveBoundary>
505 or std::is_same_v<Boundary, NeumannBoundary>
506 or ca_lattice_detail::is_constant_boundary_v<Boundary>,
507 "Ghost_Lattice: unsupported Boundary policy");
527 auto go = [&](
auto &&
self_fn, std::size_t d) ->
void
561template <
typename Storage,
typename Boundary, std::
size_t Halo>
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
size_t size_t int32_t value
Common typedefs and tag types for the Cellular Automata module.
Lattice with Halo ghost layers around the user-visible cells.
void for_each_halo_cell(F &&f) const
Invoke f(user_coord) on every halo cell of the storage.
const Storage & storage() const noexcept
Direct access to the underlying storage (read-only).
ca_size_t size() const noexcept
void refresh_halo()
Populate every ghost cell according to the boundary policy.
void set(const coord_type &c, const state_type &v)
Strict write through a user coordinate.
extents_type user_ext_
extents seen from the outside
extents_type store_ext_
extents of the backing storage (user + 2H)
Storage & storage() noexcept
Direct access to the underlying storage.
static constexpr std::size_t halo_radius() noexcept
state_type at_safe(const coord_type &c) const
Boundary-aware read exploiting the halo as a fast path.
void swap(Ghost_Lattice &other) noexcept(noexcept(store_.swap(other.store_)))
O(1) swap with another ghost lattice of the same type.
typename Storage::coord_type coord_type
state_type store_get(const coord_type &user_c) const
Read directly from the store at the given user coord.
void store_set(const coord_type &user_c, const state_type &value)
Write value directly into the store at the given user coord.
state_type at(const coord_type &c) const
Strict read through a user coordinate.
state_type out_of_range_value() const
Value returned when at_safe sees a coordinate outside the halo.
Storage store_
underlying storage (allocated once)
Ghost_Lattice()=default
Construct an empty ghost lattice (no cells allocated).
coord_type to_store(const coord_type &c) const noexcept
Convert a user coordinate into a store coordinate.
const extents_type & store_extents() const noexcept
Ghost_Lattice(const extents_type &user_extents, const state_type &init=state_type{})
Construct a ghost lattice with given user extents and init value.
static constexpr std::size_t rank
Number of axes (same as the underlying storage).
ca_size_t size(std::size_t d) const
User-visible extent along axis d.
void fill(const state_type &value)
Set every user-visible cell to value.
typename Storage::state_type state_type
static constexpr std::size_t dimension() noexcept
typename Storage::extents_type extents_type
static constexpr std::size_t halo_v
Halo thickness (ghost cells per side per axis).
const extents_type & extents() const noexcept
state_type resolve_via_policy(coord_type c) const
Resolve a user coordinate through the boundary policy (slow path).
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
std::array< ca_size_t, N > enlarge_extents(const std::array< ca_size_t, N > &user, const std::size_t halo) noexcept
Bump the storage extents by 2 * Halo on every axis.
ca_size_t positive_mod(ca_index_t v, const ca_size_t n) noexcept
Wrap a possibly-negative index into [0, n) with positive modulo.
ca_size_t clamp_index(const ca_index_t v, const ca_size_t n) noexcept
Clamp a signed coordinate into [0, n - 1] for Neumann fills.
ca_size_t reflect_index(const ca_index_t v, const ca_size_t n) noexcept
Reflect a signed coordinate into [0, n) using the no-repeat triangle wave that also powers Lattice::a...
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
void swap(Bit_Cell_Storage< N > &a, Bit_Cell_Storage< N > &b) noexcept
Free-function swap so the storage plays nicely with std::swap.
std::size_t ca_size_t
Unsigned size component used for extents and counts.
Main namespace for Aleph-w library functions.
auto enumerate(const Container &c)
Return pairs of (element, index).
static std::atomic< bool > init
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
C++20 concepts for the Cellular Automata module.
Cellular automata lattice with pluggable boundary policies.