3#include "ConnectedSubsetTreeLocalizer.hpp"
4#include "../utils/Common.hpp"
10#include <initializer_list>
19namespace mmcfilters::local_attributes {
22struct BinaryVisibilityStateAccess;
43 template <std::
size_t N>
59 void validate()
const {
60 if (offsets_.empty()) {
61 throw std::invalid_argument(
"ObservationWindow requires at least one offset.");
64 throw std::invalid_argument(
"ObservationWindow supports at most 32 offsets.");
67 std::size_t numZeroOffsets = 0;
68 for (std::size_t i = 0; i < offsets_.size(); ++i) {
69 if (offsets_[i] == WindowOffset{}) {
72 for (std::size_t j = 0; j < i; ++j) {
73 if (offsets_[i] == offsets_[j]) {
74 throw std::invalid_argument(
"ObservationWindow does not permit duplicate offsets.");
78 if (numZeroOffsets != 1) {
79 throw std::invalid_argument(
"ObservationWindow requires the zero offset exactly once.");
83 std::vector<WindowOffset> offsets_;
95 if (coordinateCount_ == 0) {
96 throw std::invalid_argument(
"BinaryVisibilityState requires at least one coordinate.");
99 throw std::invalid_argument(
"BinaryVisibilityState supports at most 32 coordinates.");
101 const std::uint32_t
validMask = coordinateCount_ == 32 ? std::numeric_limits<std::uint32_t>::max()
102 : (std::uint32_t{1} << coordinateCount_) - std::uint32_t{1};
104 throw std::invalid_argument(
"BinaryVisibilityState contains bits outside its coordinate domain.");
116 throw std::out_of_range(
"BinaryVisibilityState coordinate is outside the observation window.");
118 return (bits_ & (std::uint32_t{1} <<
coordinate)) != 0;
135 struct UncheckedConstructionTag {};
145 std::uint32_t bits_ = 0;
146 std::size_t coordinateCount_ = 0;
148 friend struct detail::BinaryVisibilityStateAccess;
177 std::vector<std::optional<NodeId>> entries_;
180using AnchorBranch = std::vector<NodeId>;
181using AnchoredEntrySet = std::set<NodeId>;
182using OrderedAnchoredEntries = std::vector<AnchoredEntryMask>;
213template <
class Decision>
214concept LocalDecision =
requires(
const Decision& decision, BinaryVisibilityState state) {
215 typename Decision::Value;
216 { decision.evaluateLocalDecision(state) } -> std::same_as<typename Decision::Value>;
220template <
class Algebra,
class Value>
221concept EventAlgebra =
requires(
const Algebra& algebra, Value& target,
const Value& source) {
222 { algebra.additiveIdentity() } -> std::same_as<Value>;
223 { algebra.addAssign(target, source) } -> std::same_as<void>;
224 { algebra.subtractAssign(target, source) } -> std::same_as<void>;
constexpr NodeId InvalidNode
Sentinel value used to denote an invalid node identifier.
constexpr PixelId InvalidPixel
Sentinel value used to denote an invalid pixel identifier.
Window-coordinate map whose missing entries represent out-of-domain samples.
std::span< const std::optional< NodeId > > entries() const noexcept
Returns every coordinate entry.
const std::optional< NodeId > & operator[](std::size_t coordinate) const noexcept
Returns one coordinate entry.
std::size_t size() const noexcept
Returns the coordinate count.
PixelId anchorPixel() const noexcept
Returns the anchor pixel.
AnchoredEntryMap(PixelId anchorPixel, std::vector< std::optional< NodeId > > entries)
Builds a coordinate-preserving map.
Binary sample-visibility vector encoded in observation-window order.
BinaryVisibilityState withEnteringOffsets(std::uint32_t enteringOffsetMask) const
Returns a state with additional coordinates visible.
bool isVisible(std::size_t coordinate) const
Tests one visibility coordinate.
std::uint32_t bits() const noexcept
Returns the visibility mask.
friend bool operator==(const BinaryVisibilityState &lhs, const BinaryVisibilityState &rhs)=default
Compares visibility masks and coordinate domains.
std::size_t coordinateCount() const noexcept
Returns the coordinate domain size.
BinaryVisibilityState(std::uint32_t bits, std::size_t coordinateCount)
Builds a validated binary state.
Indexed finite set of translated-sample offsets.
ObservationWindow(std::vector< WindowOffset > offsets)
Builds and validates a window.
const WindowOffset & operator[](std::size_t index) const noexcept
Returns one offset without bounds checking.
std::span< const WindowOffset > offsets() const noexcept
Returns all ordered offsets.
ObservationWindow(const std::array< WindowOffset, N > &offsets)
Builds and validates a fixed-size window.
auto end() const noexcept
Returns the past-the-end offset iterator.
ObservationWindow(std::initializer_list< WindowOffset > offsets)
Builds and validates a window.
std::size_t size() const noexcept
Returns the number of offsets.
static constexpr std::size_t maxNumOffsets
Maximum number of offsets representable by one visibility bit mask.
auto begin() const noexcept
Returns the first offset iterator.
Additive event algebra kept separate from the local decision.
Pure local decision from a binary visibility state to one value.
Owning result for one computed scalar attribute layout and buffer.
One inclusion node and the observation coordinates that enter there.
NodeId node
Anchored-entry node.
friend bool operator==(const AnchoredEntryMask &lhs, const AnchoredEntryMask &rhs)=default
Compares node and coordinate mask.
std::uint32_t enteringOffsetMask
Coordinates entering at node.
One anchor-specific signed change attached to an anchored entry.
NodeId anchoredEntry
Node where the new coordinates enter.
friend bool operator==(const EventDelta &lhs, const EventDelta &rhs)=default
Compares every event field.
PixelId anchorPixel
Anchor whose local state changed.
Value value
Signed decision difference.
Sum of anchor-specific event deltas attached directly to one node.
Value value
Non-aggregated signed increment.
NodeId node
Dense node slot.
friend bool operator==(const LocalAttributeIncrement &lhs, const LocalAttributeIncrement &rhs)=default
Compares node and increment value.
Final bottom-up aggregated attribute value for one node.
friend bool operator==(const NodeAttribute &lhs, const NodeAttribute &rhs)=default
Compares node and attribute value.
Value value
Aggregated node attribute.
NodeId node
Dense node slot.
Relative row-column offset of one translated local sample.