MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Logic.cpp
Go to the documentation of this file.
1#include "Logic.hpp"
2
4
5//-------------------------------------------------------------------------
6// Constructors
7//-------------------------------------------------------------------------
8
9Logic::Logic(double threshold)
10 : m_mode(LogicMode::DIRECT)
11 , m_operator(LogicOperator::THRESHOLD)
12 , m_history_size(1)
13 , m_input_count(1)
14 , m_threshold(threshold)
15 , m_low_threshold(threshold * 0.9)
16 , m_high_threshold(threshold)
17 , m_edge_type(EdgeType::BOTH)
18 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
19 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
20{
21 m_direct_function = [this](double input) {
22 return input > m_threshold;
23 };
24}
25
26Logic::Logic(LogicOperator op, double threshold)
27 : m_mode(LogicMode::DIRECT)
28 , m_operator(op)
29 , m_history_size(1)
30 , m_input_count(1)
31 , m_threshold(threshold)
32 , m_low_threshold(threshold * 0.9)
33 , m_high_threshold(threshold)
34 , m_edge_type(EdgeType::BOTH)
35 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
36 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
37{
38 set_operator(op);
39}
40
42 : m_mode(LogicMode::DIRECT)
43 , m_operator(LogicOperator::CUSTOM)
44 , m_direct_function(std::move(function))
45 , m_history_size(1)
46 , m_input_count(1)
47 , m_threshold(0.5)
48 , m_low_threshold(0.45)
49 , m_high_threshold(0.5)
50 , m_edge_type(EdgeType::BOTH)
51 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
52 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
53{
54}
55
56Logic::Logic(MultiInputFunction function, size_t input_count)
57 : m_mode(LogicMode::MULTI_INPUT)
58 , m_operator(LogicOperator::CUSTOM)
59 , m_multi_input_function(std::move(function))
60 , m_history_size(1)
61 , m_input_count(input_count)
62 , m_threshold(0.5)
63 , m_low_threshold(0.45)
64 , m_high_threshold(0.5)
65 , m_edge_type(EdgeType::BOTH)
66 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
67 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
68{
69 m_input_buffer.resize(input_count, 0.0);
70}
71
72Logic::Logic(SequentialFunction function, size_t history_size)
73 : m_mode(LogicMode::SEQUENTIAL)
74 , m_operator(LogicOperator::CUSTOM)
75 , m_sequential_function(std::move(function))
76 , m_history_size(history_size)
77 , m_input_count(1)
78 , m_threshold(0.5)
79 , m_low_threshold(0.45)
80 , m_high_threshold(0.5)
81 , m_edge_type(EdgeType::BOTH)
82 , m_history_ring(history_size, false)
83 , m_history_linear(history_size, false)
84 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
85 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
86{
87}
88
90 : m_mode(LogicMode::TEMPORAL)
91 , m_operator(LogicOperator::CUSTOM)
92 , m_temporal_function(std::move(function))
93 , m_history_size(1)
94 , m_input_count(1)
95 , m_threshold(0.5)
96 , m_low_threshold(0.45)
97 , m_high_threshold(0.5)
98 , m_edge_type(EdgeType::BOTH)
99 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
100 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
101{
102}
103
104//-------------------------------------------------------------------------
105// Processing Methods
106//-------------------------------------------------------------------------
107
108double Logic::process_sample(double input)
109{
110 bool result = false;
111 m_edge_detected = false;
112
113 if (m_input_node) {
114 atomic_inc_modulator_count(m_input_node->m_modulator_count, 1);
115 uint32_t state = m_input_node->m_state.load();
116 if (state & NodeState::PROCESSED) {
117 input += m_input_node->get_last_output();
118 } else {
119 input = m_input_node->process_sample(input);
121 }
122 }
123
124 bool current_bool = input > m_threshold;
125 bool previous_bool = m_last_output > 0.5;
126
127 switch (m_mode) {
129 switch (m_operator) {
131 result = current_bool;
132 break;
133
135 if (input > m_high_threshold) {
136 m_hysteresis_state = true;
137 } else if (input < m_low_threshold) {
138 m_hysteresis_state = false;
139 }
140 result = m_hysteresis_state;
141 break;
142
143 case LogicOperator::EDGE: {
144 bool previous_bool_input = m_input > m_threshold;
145 if (current_bool != previous_bool_input) {
146 switch (m_edge_type) {
147 case EdgeType::RISING:
148 m_edge_detected = current_bool && !previous_bool_input;
149 break;
151 m_edge_detected = !current_bool && previous_bool_input;
152 break;
153 case EdgeType::BOTH:
154 m_edge_detected = true;
155 break;
156 }
157 }
158 result = m_edge_detected;
159 break;
160 }
161
163 result = current_bool && previous_bool;
164 break;
165
167 result = current_bool || previous_bool;
168 break;
169
171 result = current_bool != previous_bool;
172 break;
173
175 result = !current_bool;
176 break;
177
179 result = !(current_bool && previous_bool);
180 break;
181
183 result = !(current_bool || previous_bool);
184 break;
185
187 result = m_direct_function(input);
188 break;
189
190 default:
191 result = current_bool;
192 }
193 break;
194
196 bool current_bool = input > m_threshold;
197 history_push(current_bool);
198 auto view = history_linearized_view();
199 result = m_sequential_function(view);
200 break;
201 }
202
203 case LogicMode::TEMPORAL: {
205 result = m_temporal_function(input, m_temporal_time);
206 break;
207 }
208
210 add_input(input, 0);
212 break;
213 }
214 }
215
216 m_input = input;
217 auto current = result ? 1.0 : 0.0;
218
220 && !m_networked_node) {
221 notify_tick(current);
222 }
223
224 if (m_input_node) {
225 atomic_dec_modulator_count(m_input_node->m_modulator_count, 1);
227 }
228
229 m_last_output = current;
230 return m_last_output;
231}
232
233std::vector<double> Logic::process_batch(unsigned int num_samples)
234{
235 std::vector<double> output(num_samples);
236
237 for (unsigned int i = 0; i < num_samples; ++i) {
238 // For batch processing, we use 0.0 as input
239 // This is mainly useful for temporal or sequential modes
240 output[i] = process_sample(0.0);
241 }
242
243 return output;
244}
245
246double Logic::process_multi_input(const std::vector<double>& inputs)
247{
251
252 if (m_input_buffer.size() < inputs.size()) {
253 m_input_buffer.resize(inputs.size(), 0.0);
254 m_input_count = inputs.size();
255 }
256
258 m_multi_input_function = [this](const std::vector<double>& inputs) {
259 bool result = true;
260 for (const auto& input : inputs) {
261 result = result && (input > m_threshold);
262 }
263 return result;
264 };
265 }
266 }
267
268 // Copy inputs to our buffer
269 for (size_t i = 0; i < inputs.size() && i < m_input_buffer.size(); ++i) {
270 m_input_buffer[i] = inputs[i];
271 }
272
274 m_last_output = result ? 1.0 : 0.0;
275
277
278 return m_last_output;
279}
280
281void Logic::add_input(double input, size_t index)
282{
283 if (index >= m_input_buffer.size()) {
284 m_input_buffer.resize(index + 1, 0.0);
285 }
286 m_input_buffer[index] = input;
287}
288
289//-------------------------------------------------------------------------
290// Configuration Methods
291//-------------------------------------------------------------------------
292
294{
295 std::ranges::fill(m_history_ring, false);
296 m_history_head = 0;
298 m_edge_detected = false;
299 m_last_output = 0.0;
300 m_hysteresis_state = false;
301 m_temporal_time = 0.0;
302 m_input_buffer.assign(m_input_count, 0.0);
303}
304
305void Logic::set_threshold(double threshold, bool create_default_direct_function)
306{
307 m_threshold = threshold;
308 m_high_threshold = threshold;
309 m_low_threshold = threshold * 0.9; // Default hysteresis
310
311 if (m_operator == LogicOperator::THRESHOLD && m_mode == LogicMode::DIRECT && create_default_direct_function) {
312 m_direct_function = [this](double input) {
313 return input > m_threshold;
314 };
315 }
316}
317
318void Logic::set_hysteresis(double low_threshold, double high_threshold, bool create_default_direct_function)
319{
320 m_low_threshold = low_threshold;
321 m_high_threshold = high_threshold;
322 m_threshold = high_threshold; // For compatibility with other methods
323
324 if (m_operator == LogicOperator::HYSTERESIS && m_mode == LogicMode::DIRECT && create_default_direct_function) {
325 m_direct_function = [this](double input) {
326 if (input > m_high_threshold) {
327 m_hysteresis_state = true;
328 } else if (input < m_low_threshold) {
329 m_hysteresis_state = false;
330 }
331 return m_hysteresis_state;
332 };
333 }
334}
335
336void Logic::set_edge_detection(EdgeType type, double threshold)
337{
338 m_edge_type = type;
339 m_threshold = threshold;
341}
342
343void Logic::set_operator(LogicOperator op, bool create_default_direct_function)
344{
345 m_operator = op;
346
347 if (create_default_direct_function) {
348 switch (op) {
350 m_direct_function = [this](double input) {
351 bool current = input > m_threshold;
352 bool previous = m_last_output > 0.5;
353 return current && previous;
354 };
355 break;
356
358 m_direct_function = [this](double input) {
359 bool current = input > m_threshold;
360 bool previous = m_last_output > 0.5;
361 return current || previous;
362 };
363 break;
364
366 m_direct_function = [this](double input) {
367 bool current = input > m_threshold;
368 bool previous = m_last_output > 0.5;
369 return current != previous;
370 };
371 break;
372
374 m_direct_function = [this](double input) {
375 return !(input > m_threshold);
376 };
377 break;
378
380 m_direct_function = [this](double input) {
381 bool current = input > m_threshold;
382 bool previous = m_last_output > 0.5;
383 return !(current && previous);
384 };
385 break;
386
388 m_direct_function = [this](double input) {
389 bool current = input > m_threshold;
390 bool previous = m_last_output > 0.5;
391 return !(current || previous);
392 };
393 break;
394
396 m_direct_function = [this](double input) {
397 return input > m_threshold;
398 };
399 break;
400
402 m_direct_function = [this](double input) {
403 if (input > m_high_threshold) {
404 m_hysteresis_state = true;
405 } else if (input < m_low_threshold) {
406 m_hysteresis_state = false;
407 }
408 return m_hysteresis_state;
409 };
410 break;
411
413 // Edge detection is handled in process_sample
415 // Custom function should be set directly
416 break;
417 }
418 }
419}
420
427
428void Logic::set_multi_input_function(MultiInputFunction function, size_t input_count)
429{
430 m_multi_input_function = std::move(function);
433 m_input_count = input_count;
434
435 // Resize input buffer if needed
436 if (m_input_buffer.size() != input_count) {
437 m_input_buffer.resize(input_count, 0.0);
438 }
439}
440
441void Logic::set_sequential_function(SequentialFunction function, size_t history_size)
442{
443 m_sequential_function = std::move(function);
446
447 if (history_size != m_history_size) {
448 m_history_size = history_size;
449 m_history_ring.resize(history_size, false);
450 m_history_linear.resize(history_size, false);
451 m_history_head = 0;
452 m_history_count = 0;
453 }
454}
455
463
464void Logic::set_initial_conditions(const std::vector<bool>& initial_values)
465{
466 m_history_head = 0;
467 m_history_count = std::min(initial_values.size(), m_history_size);
468
469 for (size_t i = 0; i < m_history_count; ++i) {
470 m_history_ring[i] = initial_values[i];
471 }
472}
473
502
503void Logic::notify_tick(double value)
504{
505 update_context(value);
506 bool state_changed = (value != m_last_output);
507 auto& ctx = get_last_context();
508
509 for (const auto& cb : m_all_callbacks) {
510 bool should_call = false;
511
512 switch (cb.event_type) {
514 should_call = true;
515 break;
516
518 should_call = (bool)value;
519 break;
520
522 should_call = !value;
523 break;
524
526 should_call = state_changed;
527 break;
528
530 should_call = state_changed && (bool)value;
531 break;
532
534 should_call = state_changed && !value;
535 break;
536
538 should_call = cb.condition && cb.condition.value()(ctx);
539 break;
540 }
541
542 if (should_call) {
543 cb.callback(ctx);
544 }
545 }
546}
547
549{
550 if (m_gpu_compatible) {
551 return m_context_gpu;
552 }
553 return m_context;
554}
555
556std::span<bool> Logic::get_history()
557{
558 return { reinterpret_cast<bool*>(m_history_linear.data()), m_history_count };
559}
560
561void Logic::on_tick(const NodeHook& callback)
562{
564}
565
566void Logic::on_tick_if(const NodeCondition& condition, const NodeHook& callback)
567{
568 add_callback(callback, LogicEventType::CONDITIONAL, condition);
569}
570
571void Logic::while_true(const NodeHook& callback)
572{
574}
575
576void Logic::while_false(const NodeHook& callback)
577{
579}
580
581void Logic::on_change(const NodeHook& callback)
582{
584}
585
586void Logic::on_change_to(bool target_state, const NodeHook& callback)
587{
588 add_callback(callback, target_state ? LogicEventType::TRUE : LogicEventType::FALSE);
589}
590
591bool Logic::remove_hook(const NodeHook& callback)
592{
593 auto it = std::remove_if(m_all_callbacks.begin(), m_all_callbacks.end(),
594 [&callback](const LogicCallback& cb) {
595 return cb.callback.target_type() == callback.target_type();
596 });
597
598 if (it != m_all_callbacks.end()) {
599 m_all_callbacks.erase(it, m_all_callbacks.end());
600 return true;
601 }
602 return false;
603}
604
606{
607 auto it = std::remove_if(m_all_callbacks.begin(), m_all_callbacks.end(),
608 [&callback](const LogicCallback& cb) {
609 return cb.event_type == LogicEventType::CONDITIONAL && cb.condition && cb.condition->target_type() == callback.target_type();
610 });
611
612 if (it != m_all_callbacks.end()) {
613 m_all_callbacks.erase(it, m_all_callbacks.end());
614 return true;
615 }
616 return false;
617}
618
620{
621 auto it = std::remove_if(m_all_callbacks.begin(), m_all_callbacks.end(),
622 [type](const LogicCallback& cb) {
623 return cb.event_type == type;
624 });
625 m_all_callbacks.erase(it, m_all_callbacks.end());
626}
627
629{
630 if (m_history_size == 0)
631 return;
636}
637
639{
640 for (size_t i = 0; i < m_history_count; ++i) {
642 }
643 return { reinterpret_cast<bool*>(m_history_linear.data()), m_history_count };
644}
645
661
677
678}
std::span< bool > m_history
History of boolean states.
Definition Logic.hpp:109
LogicMode m_mode
Current computational model.
Definition Logic.hpp:107
LogicOperator m_operator
Current boolean operator.
Definition Logic.hpp:108
EdgeType m_edge_type
Type of transition being monitored.
Definition Logic.hpp:112
bool m_edge_detected
Whether a state transition was detected.
Definition Logic.hpp:111
double m_threshold
Decision boundary for binary quantization.
Definition Logic.hpp:110
SequentialFunction m_sequential_function
Function for sequential mode.
Definition Logic.hpp:584
void set_direct_function(DirectFunction function)
Sets a custom combinational logic function.
Definition Logic.cpp:421
void set_initial_conditions(const std::vector< bool > &initial_values)
Preloads the state history buffer.
Definition Logic.cpp:464
void set_sequential_function(SequentialFunction function, size_t history_size)
Sets a custom state-based evaluation function.
Definition Logic.cpp:441
TemporalFunction m_temporal_function
Function for temporal mode.
Definition Logic.hpp:585
std::vector< uint8_t > m_saved_history_ring
Definition Logic.hpp:633
DirectFunction m_direct_function
Function for direct mode.
Definition Logic.hpp:582
void update_context(double value) override
Updates the context with the latest sample value.
Definition Logic.cpp:474
void reset()
Resets internal state to initial conditions.
Definition Logic.cpp:293
std::vector< uint8_t > m_history_linear
Linear view of history for easy access.
Definition Logic.hpp:601
std::span< bool > get_history()
Gets the current state history.
Definition Logic.cpp:556
size_t m_history_size
Maximum size of the history buffer.
Definition Logic.hpp:588
EdgeType m_edge_type
Type of edge to detect.
Definition Logic.hpp:593
Logic(double threshold=0.5)
Constructs a Logic node with threshold quantization.
Definition Logic.cpp:9
double process_sample(double input=0.) override
Processes a single input sample through the logic function.
Definition Logic.cpp:108
double m_threshold
Threshold for boolean conversion.
Definition Logic.hpp:590
void remove_hooks_of_type(LogicEventType type)
Definition Logic.cpp:619
std::function< bool(double)> DirectFunction
Function type for stateless boolean evaluation.
Definition Logic.hpp:173
double m_temporal_time
Time tracking for temporal mode.
Definition Logic.hpp:596
void set_temporal_function(TemporalFunction function)
Sets a custom time-dependent evaluation function.
Definition Logic.cpp:456
NodeContext & get_last_context() override
Retrieves the last created context object.
Definition Logic.cpp:548
double m_high_threshold
High threshold for hysteresis.
Definition Logic.hpp:592
double m_input
Current input value for multi-input mode.
Definition Logic.hpp:597
std::vector< double > m_input_buffer
Definition Logic.hpp:598
void set_edge_detection(EdgeType type, double threshold=0.5)
Configures digital transition detection.
Definition Logic.cpp:336
std::shared_ptr< Node > m_input_node
Input node for processing.
Definition Logic.hpp:599
LogicOperator m_operator
Current logic operator.
Definition Logic.hpp:581
std::function< bool(const std::vector< double > &)> MultiInputFunction
Function type for parallel input evaluation.
Definition Logic.hpp:178
void on_change_to(bool target_state, const NodeHook &callback)
Registers a callback for when output changes to a specific state.
Definition Logic.cpp:586
void set_operator(LogicOperator op, bool create_default_direct_function=false)
Sets the boolean operation to perform.
Definition Logic.cpp:343
void add_callback(const NodeHook &callback, LogicEventType type, const std::optional< NodeCondition > &condition=std::nullopt)
Adds a callback to the list of all callbacks.
Definition Logic.hpp:612
double m_low_threshold
Low threshold for hysteresis.
Definition Logic.hpp:591
MultiInputFunction m_multi_input_function
Function for recursive/feedforward mode.
Definition Logic.hpp:583
bool m_edge_detected
Whether an edge was detected in the last processing.
Definition Logic.hpp:594
std::function< bool(std::span< bool >)> SequentialFunction
Function type for state-based evaluation.
Definition Logic.hpp:183
bool remove_conditional_hook(const NodeCondition &callback) override
Removes a previously registered conditional callback.
Definition Logic.cpp:605
std::vector< LogicCallback > m_all_callbacks
Collection of all callback functions.
Definition Logic.hpp:631
void set_hysteresis(double low_threshold, double high_threshold, bool create_default_direct_function=false)
Configures noise-resistant binary quantization with memory.
Definition Logic.cpp:318
void set_multi_input_function(MultiInputFunction function, size_t input_count)
Sets a custom parallel input evaluation function.
Definition Logic.cpp:428
std::vector< double > process_batch(unsigned int num_samples) override
Processes multiple samples in batch mode.
Definition Logic.cpp:233
void save_state() override
Saves the node's current state for later restoration Recursively cascades through all connected modul...
Definition Logic.cpp:646
void on_tick_if(const NodeCondition &condition, const NodeHook &callback) override
Registers a conditional callback for generated samples.
Definition Logic.cpp:566
std::vector< uint8_t > m_history_ring
Ring buffer for history storage.
Definition Logic.hpp:600
bool m_hysteresis_state
State for hysteresis operator.
Definition Logic.hpp:595
void on_tick(const NodeHook &callback) override
Registers a callback for every generated sample.
Definition Logic.cpp:561
size_t m_history_count
Number of valid entries in the history buffer.
Definition Logic.hpp:587
void on_change(const NodeHook &callback)
Registers a callback for any state change (true↔false)
Definition Logic.cpp:581
size_t m_history_head
Head index for the history ring buffer.
Definition Logic.hpp:586
double process_multi_input(const std::vector< double > &inputs)
Processes multiple parallel inputs.
Definition Logic.cpp:246
LogicMode m_mode
Current processing mode.
Definition Logic.hpp:580
std::function< bool(double, double)> TemporalFunction
Function type for time-dependent evaluation.
Definition Logic.hpp:188
std::span< bool > history_linearized_view()
Definition Logic.cpp:638
void while_false(const NodeHook &callback)
Registers a callback that executes continuously while output is false.
Definition Logic.cpp:576
void restore_state() override
Restores the node's state from the last save Recursively cascades through all connected modulator nod...
Definition Logic.cpp:662
void notify_tick(double value) override
Notifies all registered callbacks about a new sample.
Definition Logic.cpp:503
size_t m_input_count
Expected number of inputs for multi-input mode.
Definition Logic.hpp:589
bool remove_hook(const NodeHook &callback) override
Removes a previously registered callback.
Definition Logic.cpp:591
void add_input(double input, size_t index)
Definition Logic.cpp:281
void set_threshold(double threshold, bool create_default_direct_function=false)
Sets the decision boundary for binary quantization.
Definition Logic.cpp:305
void while_true(const NodeHook &callback)
Registers a callback that executes continuously while output is true.
Definition Logic.cpp:571
std::span< const float > m_gpu_data
double value
Current sample value.
Definition Node.hpp:40
Base context class for node callbacks.
Definition Node.hpp:30
bool m_state_saved
tracks if the node's state has been saved by a snapshot operation
Definition Node.hpp:429
bool m_networked_node
Flag indicating if the node is part of a NodeNetwork This flag is used to disable event firing when t...
Definition Node.hpp:424
uint32_t m_sample_rate
Sample rate for audio processing, used for normalization.
Definition Node.hpp:431
double m_last_output
The most recent sample value generated by this oscillator.
Definition Node.hpp:377
bool m_fire_events_during_snapshot
Internal flag controlling whether notify_tick fires during state snapshots Default: false (events don...
Definition Node.hpp:455
bool m_gpu_compatible
Flag indicating if the node supports GPU processing This flag is set by derived classes to indicate w...
Definition Node.hpp:386
EdgeType
Digital transition patterns to detect.
Definition Logic.hpp:40
@ FALLING
High-to-low transition (1→0)
@ RISING
Low-to-high transition (0→1)
LogicMode
Defines the computational model for digital signal evaluation.
Definition Logic.hpp:11
@ SEQUENTIAL
State-based evaluation using history of inputs (sequential logic)
@ DIRECT
Stateless evaluation of current input only (combinational logic)
@ TEMPORAL
Time-dependent evaluation with timing constraints.
@ MULTI_INPUT
Parallel evaluation of multiple input signals.
LogicEventType
Events that can trigger callbacks.
Definition Logic.hpp:50
LogicOperator
Digital operators for boolean computation.
Definition Logic.hpp:22
@ NOT
Logical NOT - inverts the input.
@ NOR
Logical NOR - inverted OR operation.
@ OR
Logical OR - true when any input is true.
@ NAND
Logical NAND - inverted AND operation.
@ THRESHOLD
Binary quantization - true when input exceeds threshold.
@ AND
Logical AND - true only when all inputs are true.
@ EDGE
Transition detector - identifies state changes.
@ HYSTERESIS
Threshold with memory - prevents rapid oscillation at boundary.
@ CUSTOM
User-defined boolean function.
@ XOR
Logical XOR - true when odd number of inputs are true.
std::function< void(NodeContext &)> NodeHook
Callback function type for node processing events.
Definition NodeUtils.hpp:25
@ PROCESSED
Node has been processed this cycle.
Definition NodeSpec.hpp:49
void atomic_add_flag(std::atomic< NodeState > &state, NodeState flag)
Atomically adds a flag to a node state.
Definition NodeUtils.cpp:94
void try_reset_processed_state(std::shared_ptr< Node > node)
Attempts to reset the processed state of a node.
void atomic_inc_modulator_count(std::atomic< uint32_t > &count, int amount)
Atomically increments the modulator count by a specified amount.
std::function< bool(NodeContext &)> NodeCondition
Predicate function type for conditional callbacks.
Definition NodeUtils.hpp:43
void atomic_dec_modulator_count(std::atomic< uint32_t > &count, int amount)
Atomically decrements the modulator count by a specified amount.