67#ifndef TPL_CA_UPDATE_SCHEME_H
68#define TPL_CA_UPDATE_SCHEME_H
88namespace ca_scheme_detail {
96template <std::
size_t W, std::
size_t H>
105template <
typename Coord,
typename Cb>
117template <
typename Coord,
typename Cb>
131template <
typename Coord,
typename Cb>
145template <std::
size_t W, std::
size_t H,
typename Coord,
typename Cb>
165template <
typename Coord,
typename Cb>
181template <
typename Order,
typename Lattice,
typename Cb>
193 std::forward<Cb>(
cb));
194 else if constexpr (std::is_same_v<Order, ColumnMajor>)
205 static_assert(
Lattice::rank <= 3,
"Update schemes currently support rank <= 3");
210template <
typename Lattice>
220template <std::
size_t Rank>
224 for (std::size_t d = 0; d <
Rank; ++d)
229 h =
splitmix64(
h ^ (
static_cast<std::uint64_t
>(d) + 1));
249template <
typename Order = RowMajor>
267 template <
typename Engine,
typename Rule>
270 using Lattice =
typename Engine::lattice_type;
273 using Neighborhood =
typename Engine::neighborhood_type;
274 constexpr std::size_t K = Neighborhood::size_v;
276 auto &
cur = e.current_buffer();
277 auto &
nxt = e.next_buffer();
278 const auto &
nh = e.neighborhood();
279 const std::size_t step = e.step_count();
281 std::array<State, K == 0 ? 1 : K>
nbuf{};
282 const std::size_t
neigh_sz = (std::min) (
nh.size(),
static_cast<std::size_t
>(
nbuf.size()));
284 ca_scheme_detail::for_each_coord<Order>(
cur, [&](
const Coord &c)
309template <
typename Order = RowMajor>
326 template <
typename Engine,
typename Rule>
329 using Lattice =
typename Engine::lattice_type;
332 using Neighborhood =
typename Engine::neighborhood_type;
333 constexpr std::size_t K = Neighborhood::size_v;
335 auto &
cur = e.current_buffer();
336 const auto &
nh = e.neighborhood();
337 const std::size_t step = e.step_count();
339 std::array<State, K == 0 ? 1 : K>
nbuf{};
340 const std::size_t
neigh_sz = (std::min) (
nh.size(),
static_cast<std::size_t
>(
nbuf.size()));
342 ca_scheme_detail::for_each_coord<Order>(
cur, [&](
const Coord &c)
371template <
typename Engine_Type = std::mt19937_64>
405 template <
typename Engine,
typename Rule>
408 using Lattice =
typename Engine::lattice_type;
411 using Neighborhood =
typename Engine::neighborhood_type;
412 constexpr std::size_t K = Neighborhood::size_v;
414 auto &
cur = e.current_buffer();
415 const auto &
nh = e.neighborhood();
416 const std::size_t step = e.step_count();
419 const std::size_t
subs
422 std::array<State, K == 0 ? 1 : K>
nbuf{};
423 const std::size_t
neigh_sz = (std::min) (
nh.size(),
static_cast<std::size_t
>(
nbuf.size()));
425 for (std::size_t sub = 0; sub <
subs; ++sub)
431 Coord c = ca_scheme_detail::coord_from_hash<Lattice::rank>(
pick_seed,
cur.extents());
458template <std::
size_t BlockSize = 4,
typename Order = RowMajor>
461 static_assert(
BlockSize >= 1,
"Block_Synchronous_Update requires BlockSize >= 1");
478 template <
typename Engine,
typename Rule>
481 using Lattice =
typename Engine::lattice_type;
484 using Neighborhood =
typename Engine::neighborhood_type;
485 constexpr std::size_t K = Neighborhood::size_v;
487 auto &
cur = e.current_buffer();
488 auto &
nxt = e.next_buffer();
489 const auto &
nh = e.neighborhood();
490 const std::size_t step = e.step_count();
507 std::array<ca_size_t, Lattice::rank>
tile_coord{};
509 std::size_t
rem = active;
520 ca_scheme_detail::for_each_coord<Order>(
cur, [&](
const Coord &c)
525 std::array<State, K == 0 ? 1 : K>
nbuf{};
526 const std::size_t
neigh_sz = (std::min) (
nh.size(),
static_cast<std::size_t
>(
nbuf.size()));
619 return (
k % 2 == 0) ? 0 : 1;
631 template <
typename Engine,
typename Block_Rule>
634 using Lattice =
typename Engine::lattice_type;
637 static_assert(
Lattice::rank == 2,
"Margolus_Update requires a 2D lattice");
639 auto &
lat = e.current_buffer();
642 if (n0 < 2
or n1 < 2)
649 const Coord nw{i, j};
650 const Coord ne{i, j + 1};
651 const Coord sw{i + 1, j};
652 const Coord se{i + 1, j + 1};
654 std::array<State, 4>
in{
lat.at(nw),
lat.at(ne),
lat.at(sw),
lat.at(se)};
655 const std::array<State, 4>
out =
r(
in);
670 template <
typename Engine,
typename Block_Rule>
Exception handling system with formatted messages for Aleph-w.
size_t size_t int32_t * out
Reproducible random-number support for stochastic CA rules (Phase 8).
Common typedefs and tag types for the Cellular Automata module.
Lattice that adds boundary-aware access on top of a storage.
typename Storage::state_type state_type
typename Storage::coord_type coord_type
static constexpr std::size_t rank
A coordinate type with N integral components.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_j0_function > > j0(const __gmp_expr< T, U > &expr)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Coord_Vec< Rank > coord_from_hash(std::uint64_t h, const std::array< ca_size_t, Rank > &ext) noexcept
Decode a 64-bit hash into a coordinate uniformly drawn over extents.
ca_size_t cell_count(const Lattice &lat) noexcept
Total cell count of a lattice (product of extents).
void for_each_coord_1d(const ca_size_t n0, Cb &&cb)
Iterate every coordinate of a rank-1 lattice in row order.
void for_each_coord_3d_row(const ca_size_t n0, const ca_size_t n1, const ca_size_t n2, Cb &&cb)
Iterate every coordinate of a rank-3 lattice in row-major order.
void for_each_coord(const Lattice &lat, Cb &&cb)
Visit every coordinate of lat honouring the chosen Order.
void for_each_coord_2d_row(const ca_size_t n0, const ca_size_t n1, Cb &&cb)
Iterate every coordinate of a rank-2 lattice in row-major order.
void for_each_coord_2d_tile(const ca_size_t n0, const ca_size_t n1, Cb &&cb)
Iterate a rank-2 lattice in H × W tiles (cache-friendly).
void for_each_coord_2d_col(const ca_size_t n0, const ca_size_t n1, Cb &&cb)
Iterate every coordinate of a rank-2 lattice in column-major order.
constexpr std::uint64_t mix_seed(const std::uint64_t a, const std::uint64_t b) noexcept
Combine two 64-bit values into a single deterministic hash.
std::span< const T > Neighbor_View
Read-only view over a contiguous range of neighbour values.
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
std::array< ca_index_t, N > Coord_Vec
Default coordinate vector.
void gather_neighbors(const Nbh &nh, const L &lat, const typename L::coord_type ¢er, std::span< T > out)
Populate out[0..nh.size()) with neighbour values of center.
constexpr std::uint64_t splitmix64(std::uint64_t x) noexcept
64-bit SplitMix hash.
std::size_t ca_size_t
Unsigned size component used for extents and counts.
State apply_rule(const Rule &r, const State &s, Neighbor_View< State > v, const Cell_Context< Rank > &ctx)
Invoke a rule, optionally forwarding the per-cell context.
Main namespace for Aleph-w library functions.
void next()
Advance all underlying iterators (bounds-checked).
Synchronous update over rotating sub-blocks.
static constexpr std::size_t block_size
void apply(Engine &e, Rule &r) const
Execute one block-synchronous step.
static constexpr bool requires_double_buffer
static constexpr bool requires_block_rule
Per-cell context handed to rules that need to know "where" and "when" they are firing.
Margolus 2×2 partition update for reversible CAs.
static constexpr bool requires_block_rule
Operates on Block_Rule, not on cell rules.
void apply_with_origin(Engine &e, Block_Rule &r, const ca_index_t origin) const
Apply the block rule to every 2×2 block of the active partition.
static constexpr bool requires_double_buffer
Margolus uses a single buffer; reads and writes the same lattice block by block.
static constexpr ca_index_t origin_for_step(const std::size_t k) noexcept
Origin offset used at step k: even → (0,0), odd → (1,1).
void apply(Engine &e, Block_Rule &r) const
Apply the block rule using the parity of the engine step.
Pick one cell at random per sub-step, update it in place.
std::size_t sub_steps_per_step
Number of single-cell sub-steps per step().
static constexpr bool requires_double_buffer
In-place updates → no second buffer.
static constexpr bool requires_block_rule
Operates on cell rules.
std::uint64_t master_seed
constexpr Random_Asynchronous_Update(const std::uint64_t seed=0, const std::size_t sub_steps=0) noexcept
Build a random asynchronous update strategy.
void apply(Engine &e, Rule &r) const
Execute one randomised step.
In-place sequential update (no double buffer).
static constexpr bool requires_block_rule
Operates on cell rules.
void apply(Engine &e, Rule &r) const
Execute one sequential in-place step.
static constexpr bool requires_double_buffer
Operates in place, no second buffer needed.
Classical double-buffer synchronous update.
static constexpr bool requires_block_rule
Operates on cell rules — not on block rules.
static constexpr bool requires_double_buffer
Engines must allocate a second buffer for this scheme.
void apply(Engine &e, Rule &r) const
Execute one synchronous step.
Iterate a 2D lattice in W x H tiles.
Detect whether O is a Tile<W, H> instantiation.
C++20 concepts for the Cellular Automata module.
Neighborhoods catalogue for Aleph::CA.