MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Logic.cpp
Go to the documentation of this file.
1#include "Logic.hpp"
2
3#include <algorithm>
4
6
8
9//-------------------------------------------------------------------------
10// Constructors
11//-------------------------------------------------------------------------
12
13Logic::Logic(double threshold)
14 : m_mode(LogicMode::DIRECT)
15 , m_operator(LogicOperator::THRESHOLD)
16 , m_history_size(1)
17 , m_input_count(1)
18 , m_threshold(threshold)
19 , m_low_threshold(threshold * 0.9)
20 , m_high_threshold(threshold)
21 , m_edge_type(EdgeType::BOTH)
22 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
23 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
24{
25 m_direct_function = [this](double input) {
26 return input > m_threshold;
27 };
28}
29
30Logic::Logic(LogicOperator op, double threshold)
31 : m_mode(LogicMode::DIRECT)
32 , m_operator(op)
33 , m_history_size(1)
34 , m_input_count(1)
35 , m_threshold(threshold)
36 , m_low_threshold(threshold * 0.9)
37 , m_high_threshold(threshold)
38 , m_edge_type(EdgeType::BOTH)
39 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
40 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
41{
42 set_operator(op);
43}
44
46 : m_mode(LogicMode::DIRECT)
47 , m_operator(LogicOperator::CUSTOM)
48 , m_direct_function(std::move(function))
49 , m_history_size(1)
50 , m_input_count(1)
51 , m_threshold(0.5)
52 , m_low_threshold(0.45)
53 , m_high_threshold(0.5)
54 , m_edge_type(EdgeType::BOTH)
55 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
56 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
57{
58}
59
60Logic::Logic(MultiInputFunction function, size_t input_count)
61 : m_mode(LogicMode::MULTI_INPUT)
62 , m_operator(LogicOperator::CUSTOM)
63 , m_multi_input_function(std::move(function))
64 , m_history_size(1)
65 , m_input_count(input_count)
66 , m_threshold(0.5)
67 , m_low_threshold(0.45)
68 , m_high_threshold(0.5)
69 , m_edge_type(EdgeType::BOTH)
70 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
71 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
72{
73 m_input_buffer.resize(input_count, 0.0);
74}
75
76Logic::Logic(SequentialFunction function, size_t history_size)
77 : m_mode(LogicMode::SEQUENTIAL)
78 , m_operator(LogicOperator::CUSTOM)
79 , m_sequential_function(std::move(function))
80 , m_history_size(history_size)
81 , m_input_count(1)
82 , m_threshold(0.5)
83 , m_low_threshold(0.45)
84 , m_high_threshold(0.5)
85 , m_edge_type(EdgeType::BOTH)
86 , m_history_ring(history_size, false)
87 , m_history_linear(history_size, false)
88 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
89 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
90{
91}
92
94 : m_mode(LogicMode::TEMPORAL)
95 , m_operator(LogicOperator::CUSTOM)
96 , m_temporal_function(std::move(function))
97 , m_history_size(1)
98 , m_input_count(1)
99 , m_threshold(0.5)
100 , m_low_threshold(0.45)
101 , m_high_threshold(0.5)
102 , m_edge_type(EdgeType::BOTH)
103 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
104 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
105{
106}
107
108//-------------------------------------------------------------------------
109// Processing Methods
110//-------------------------------------------------------------------------
111
112double Logic::process_sample(double input)
113{
114 bool result = false;
115 m_edge_detected = false;
116
117 if (m_input_node) {
118 atomic_inc_modulator_count(m_input_node->m_modulator_count, 1);
119 uint32_t state = m_input_node->m_state.load();
120 if (state & Utils::NodeState::PROCESSED) {
121 input += m_input_node->get_last_output();
122 } else {
123 input = m_input_node->process_sample(input);
125 }
126 }
127
128 bool current_bool = input > m_threshold;
129 bool previous_bool = m_last_output > 0.5;
130
131 switch (m_mode) {
133 switch (m_operator) {
135 result = current_bool;
136 break;
137
139 if (input > m_high_threshold) {
140 m_hysteresis_state = true;
141 } else if (input < m_low_threshold) {
142 m_hysteresis_state = false;
143 }
144 result = m_hysteresis_state;
145 break;
146
147 case LogicOperator::EDGE: {
148 bool previous_bool_input = m_input > m_threshold;
149 if (current_bool != previous_bool_input) {
150 switch (m_edge_type) {
151 case EdgeType::RISING:
152 m_edge_detected = current_bool && !previous_bool_input;
153 break;
155 m_edge_detected = !current_bool && previous_bool_input;
156 break;
157 case EdgeType::BOTH:
158 m_edge_detected = true;
159 break;
160 }
161 }
162 result = m_edge_detected;
163 break;
164 }
165
167 result = current_bool && previous_bool;
168 break;
169
171 result = current_bool || previous_bool;
172 break;
173
175 result = current_bool != previous_bool;
176 break;
177
179 result = !current_bool;
180 break;
181
183 result = !(current_bool && previous_bool);
184 break;
185
187 result = !(current_bool || previous_bool);
188 break;
189
191 result = m_direct_function(input);
192 break;
193
194 default:
195 result = current_bool;
196 }
197 break;
198
200 bool current_bool = input > m_threshold;
201 history_push(current_bool);
202 auto view = history_linearized_view();
203 result = m_sequential_function(view);
204 break;
205 }
206
207 case LogicMode::TEMPORAL: {
209 result = m_temporal_function(input, m_temporal_time);
210 break;
211 }
212
214 add_input(input, 0);
216 break;
217 }
218 }
219
220 m_input = input;
221 auto current = result ? 1.0 : 0.0;
222
224 && !m_networked_node) {
225 notify_tick(current);
226 }
227
228 if (m_input_node) {
229 atomic_dec_modulator_count(m_input_node->m_modulator_count, 1);
231 }
232
233 m_last_output = current;
234 return m_last_output;
235}
236
237std::vector<double> Logic::process_batch(unsigned int num_samples)
238{
239 std::vector<double> output(num_samples);
240
241 for (unsigned int i = 0; i < num_samples; ++i) {
242 // For batch processing, we use 0.0 as input
243 // This is mainly useful for temporal or sequential modes
244 output[i] = process_sample(0.0);
245 }
246
247 return output;
248}
249
250double Logic::process_multi_input(const std::vector<double>& inputs)
251{
255
256 if (m_input_buffer.size() < inputs.size()) {
257 m_input_buffer.resize(inputs.size(), 0.0);
258 m_input_count = inputs.size();
259 }
260
262 m_multi_input_function = [this](const std::vector<double>& inputs) {
263 bool result = true;
264 for (const auto& input : inputs) {
265 result = result && (input > m_threshold);
266 }
267 return result;
268 };
269 }
270 }
271
272 // Copy inputs to our buffer
273 for (size_t i = 0; i < inputs.size() && i < m_input_buffer.size(); ++i) {
274 m_input_buffer[i] = inputs[i];
275 }
276
278 m_last_output = result ? 1.0 : 0.0;
279
281
282 return m_last_output;
283}
284
285void Logic::add_input(double input, size_t index)
286{
287 if (index >= m_input_buffer.size()) {
288 m_input_buffer.resize(index + 1, 0.0);
289 }
290 m_input_buffer[index] = input;
291}
292
293//-------------------------------------------------------------------------
294// Configuration Methods
295//-------------------------------------------------------------------------
296
298{
299 std::ranges::fill(m_history_ring, false);
300 m_history_head = 0;
302 m_edge_detected = false;
303 m_last_output = 0.0;
304 m_hysteresis_state = false;
305 m_temporal_time = 0.0;
306 m_input_buffer.assign(m_input_count, 0.0);
307}
308
309void Logic::set_threshold(double threshold, bool create_default_direct_function)
310{
311 m_threshold = threshold;
312 m_high_threshold = threshold;
313 m_low_threshold = threshold * 0.9; // Default hysteresis
314
315 if (m_operator == LogicOperator::THRESHOLD && m_mode == LogicMode::DIRECT && create_default_direct_function) {
316 m_direct_function = [this](double input) {
317 return input > m_threshold;
318 };
319 }
320}
321
322void Logic::set_hysteresis(double low_threshold, double high_threshold, bool create_default_direct_function)
323{
324 m_low_threshold = low_threshold;
325 m_high_threshold = high_threshold;
326 m_threshold = high_threshold; // For compatibility with other methods
327
328 if (m_operator == LogicOperator::HYSTERESIS && m_mode == LogicMode::DIRECT && create_default_direct_function) {
329 m_direct_function = [this](double input) {
330 if (input > m_high_threshold) {
331 m_hysteresis_state = true;
332 } else if (input < m_low_threshold) {
333 m_hysteresis_state = false;
334 }
335 return m_hysteresis_state;
336 };
337 }
338}
339
340void Logic::set_edge_detection(EdgeType type, double threshold)
341{
342 m_edge_type = type;
343 m_threshold = threshold;
345}
346
347void Logic::set_operator(LogicOperator op, bool create_default_direct_function)
348{
349 m_operator = op;
350
351 if (create_default_direct_function) {
352 switch (op) {
354 m_direct_function = [this](double input) {
355 bool current = input > m_threshold;
356 bool previous = m_last_output > 0.5;
357 return current && previous;
358 };
359 break;
360
362 m_direct_function = [this](double input) {
363 bool current = input > m_threshold;
364 bool previous = m_last_output > 0.5;
365 return current || previous;
366 };
367 break;
368
370 m_direct_function = [this](double input) {
371 bool current = input > m_threshold;
372 bool previous = m_last_output > 0.5;
373 return current != previous;
374 };
375 break;
376
378 m_direct_function = [this](double input) {
379 return !(input > m_threshold);
380 };
381 break;
382
384 m_direct_function = [this](double input) {
385 bool current = input > m_threshold;
386 bool previous = m_last_output > 0.5;
387 return !(current && previous);
388 };
389 break;
390
392 m_direct_function = [this](double input) {
393 bool current = input > m_threshold;
394 bool previous = m_last_output > 0.5;
395 return !(current || previous);
396 };
397 break;
398
400 m_direct_function = [this](double input) {
401 return input > m_threshold;
402 };
403 break;
404
406 m_direct_function = [this](double input) {
407 if (input > m_high_threshold) {
408 m_hysteresis_state = true;
409 } else if (input < m_low_threshold) {
410 m_hysteresis_state = false;
411 }
412 return m_hysteresis_state;
413 };
414 break;
415
417 // Edge detection is handled in process_sample
419 // Custom function should be set directly
420 break;
421 }
422 }
423}
424
431
432void Logic::set_multi_input_function(MultiInputFunction function, size_t input_count)
433{
434 m_multi_input_function = std::move(function);
437 m_input_count = input_count;
438
439 // Resize input buffer if needed
440 if (m_input_buffer.size() != input_count) {
441 m_input_buffer.resize(input_count, 0.0);
442 }
443}
444
445void Logic::set_sequential_function(SequentialFunction function, size_t history_size)
446{
447 m_sequential_function = std::move(function);
450
451 if (history_size != m_history_size) {
452 m_history_size = history_size;
453 m_history_ring.resize(history_size, false);
454 m_history_linear.resize(history_size, false);
455 m_history_head = 0;
456 m_history_count = 0;
457 }
458}
459
467
468void Logic::set_initial_conditions(const std::vector<bool>& initial_values)
469{
470 m_history_head = 0;
471 m_history_count = std::min(initial_values.size(), m_history_size);
472
473 for (size_t i = 0; i < m_history_count; ++i) {
474 m_history_ring[i] = initial_values[i];
475 }
476}
477
500
501void Logic::notify_tick(double value)
502{
503 update_context(value);
504 bool state_changed = (value != m_last_output);
505 auto& ctx = get_last_context();
506
507 for (const auto& cb : m_all_callbacks) {
508 bool should_call = false;
509
510 switch (cb.event_type) {
512 should_call = true;
513 break;
514
516 should_call = (bool)value;
517 break;
518
520 should_call = !value;
521 break;
522
524 should_call = state_changed;
525 break;
526
528 should_call = state_changed && (bool)value;
529 break;
530
532 should_call = state_changed && !value;
533 break;
534
536 should_call = cb.condition && cb.condition.value()(ctx);
537 break;
538 }
539
540 if (should_call) {
541 cb.callback(ctx);
542 }
543 }
544}
545
547{
548 if (m_gpu_compatible) {
549 return m_context_gpu;
550 }
551 return m_context;
552}
553
554std::span<bool> Logic::get_history()
555{
556 return { reinterpret_cast<bool*>(m_history_linear.data()), m_history_count };
557}
558
559void Logic::on_tick(const NodeHook& callback)
560{
562}
563
564void Logic::on_tick_if(const NodeCondition& condition, const NodeHook& callback)
565{
566 add_callback(callback, LogicEventType::CONDITIONAL, condition);
567}
568
569void Logic::while_true(const NodeHook& callback)
570{
572}
573
574void Logic::while_false(const NodeHook& callback)
575{
577}
578
579void Logic::on_change(const NodeHook& callback)
580{
582}
583
584void Logic::on_change_to(bool target_state, const NodeHook& callback)
585{
586 add_callback(callback, target_state ? LogicEventType::TRUE : LogicEventType::FALSE);
587}
588
589bool Logic::remove_hook(const NodeHook& callback)
590{
591 auto it = std::remove_if(m_all_callbacks.begin(), m_all_callbacks.end(),
592 [&callback](const LogicCallback& cb) {
593 return cb.callback.target_type() == callback.target_type();
594 });
595
596 if (it != m_all_callbacks.end()) {
597 m_all_callbacks.erase(it, m_all_callbacks.end());
598 return true;
599 }
600 return false;
601}
602
604{
605 auto it = std::remove_if(m_all_callbacks.begin(), m_all_callbacks.end(),
606 [&callback](const LogicCallback& cb) {
607 return cb.event_type == LogicEventType::CONDITIONAL && cb.condition && cb.condition->target_type() == callback.target_type();
608 });
609
610 if (it != m_all_callbacks.end()) {
611 m_all_callbacks.erase(it, m_all_callbacks.end());
612 return true;
613 }
614 return false;
615}
616
618{
619 auto it = std::remove_if(m_all_callbacks.begin(), m_all_callbacks.end(),
620 [type](const LogicCallback& cb) {
621 return cb.event_type == type;
622 });
623 m_all_callbacks.erase(it, m_all_callbacks.end());
624}
625
627{
628 if (m_history_size == 0)
629 return;
634}
635
637{
638 for (size_t i = 0; i < m_history_count; ++i) {
640 }
641 return { reinterpret_cast<bool*>(m_history_linear.data()), m_history_count };
642}
643
659
675
676}
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:570
void set_direct_function(DirectFunction function)
Sets a custom combinational logic function.
Definition Logic.cpp:425
void set_initial_conditions(const std::vector< bool > &initial_values)
Preloads the state history buffer.
Definition Logic.cpp:468
void set_sequential_function(SequentialFunction function, size_t history_size)
Sets a custom state-based evaluation function.
Definition Logic.cpp:445
TemporalFunction m_temporal_function
Function for temporal mode.
Definition Logic.hpp:571
std::vector< uint8_t > m_saved_history_ring
Definition Logic.hpp:619
DirectFunction m_direct_function
Function for direct mode.
Definition Logic.hpp:568
void update_context(double value) override
Updates the context with the latest sample value.
Definition Logic.cpp:478
void reset()
Resets internal state to initial conditions.
Definition Logic.cpp:297
std::vector< uint8_t > m_history_linear
Linear view of history for easy access.
Definition Logic.hpp:587
std::span< bool > get_history()
Gets the current state history.
Definition Logic.cpp:554
size_t m_history_size
Maximum size of the history buffer.
Definition Logic.hpp:574
EdgeType m_edge_type
Type of edge to detect.
Definition Logic.hpp:579
Logic(double threshold=0.5)
Constructs a Logic node with threshold quantization.
Definition Logic.cpp:13
double process_sample(double input=0.) override
Processes a single input sample through the logic function.
Definition Logic.cpp:112
double m_threshold
Threshold for boolean conversion.
Definition Logic.hpp:576
void remove_hooks_of_type(LogicEventType type)
Definition Logic.cpp:617
std::function< bool(double)> DirectFunction
Function type for stateless boolean evaluation.
Definition Logic.hpp:169
double m_temporal_time
Time tracking for temporal mode.
Definition Logic.hpp:582
void set_temporal_function(TemporalFunction function)
Sets a custom time-dependent evaluation function.
Definition Logic.cpp:460
NodeContext & get_last_context() override
Retrieves the last created context object.
Definition Logic.cpp:546
double m_high_threshold
High threshold for hysteresis.
Definition Logic.hpp:578
double m_input
Current input value for multi-input mode.
Definition Logic.hpp:583
std::vector< double > m_input_buffer
Definition Logic.hpp:584
void set_edge_detection(EdgeType type, double threshold=0.5)
Configures digital transition detection.
Definition Logic.cpp:340
std::shared_ptr< Node > m_input_node
Input node for processing.
Definition Logic.hpp:585
LogicOperator m_operator
Current logic operator.
Definition Logic.hpp:567
std::function< bool(const std::vector< double > &)> MultiInputFunction
Function type for parallel input evaluation.
Definition Logic.hpp:174
void on_change_to(bool target_state, const NodeHook &callback)
Registers a callback for when output changes to a specific state.
Definition Logic.cpp:584
void set_operator(LogicOperator op, bool create_default_direct_function=false)
Sets the boolean operation to perform.
Definition Logic.cpp:347
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:598
double m_low_threshold
Low threshold for hysteresis.
Definition Logic.hpp:577
MultiInputFunction m_multi_input_function
Function for recursive/feedforward mode.
Definition Logic.hpp:569
bool m_edge_detected
Whether an edge was detected in the last processing.
Definition Logic.hpp:580
std::function< bool(std::span< bool >)> SequentialFunction
Function type for state-based evaluation.
Definition Logic.hpp:179
bool remove_conditional_hook(const NodeCondition &callback) override
Removes a previously registered conditional callback.
Definition Logic.cpp:603
std::vector< LogicCallback > m_all_callbacks
Collection of all callback functions.
Definition Logic.hpp:617
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:322
void set_multi_input_function(MultiInputFunction function, size_t input_count)
Sets a custom parallel input evaluation function.
Definition Logic.cpp:432
std::vector< double > process_batch(unsigned int num_samples) override
Processes multiple samples in batch mode.
Definition Logic.cpp:237
void save_state() override
Saves the node's current state for later restoration Recursively cascades through all connected modul...
Definition Logic.cpp:644
void on_tick_if(const NodeCondition &condition, const NodeHook &callback) override
Registers a conditional callback for generated samples.
Definition Logic.cpp:564
std::vector< uint8_t > m_history_ring
Ring buffer for history storage.
Definition Logic.hpp:586
bool m_hysteresis_state
State for hysteresis operator.
Definition Logic.hpp:581
void on_tick(const NodeHook &callback) override
Registers a callback for every generated sample.
Definition Logic.cpp:559
size_t m_history_count
Number of valid entries in the history buffer.
Definition Logic.hpp:573
void on_change(const NodeHook &callback)
Registers a callback for any state change (true↔false)
Definition Logic.cpp:579
size_t m_history_head
Head index for the history ring buffer.
Definition Logic.hpp:572
double process_multi_input(const std::vector< double > &inputs)
Processes multiple parallel inputs.
Definition Logic.cpp:250
LogicMode m_mode
Current processing mode.
Definition Logic.hpp:566
std::function< bool(double, double)> TemporalFunction
Function type for time-dependent evaluation.
Definition Logic.hpp:184
std::span< bool > history_linearized_view()
Definition Logic.cpp:636
void while_false(const NodeHook &callback)
Registers a callback that executes continuously while output is false.
Definition Logic.cpp:574
void restore_state() override
Restores the node's state from the last save Recursively cascades through all connected modulator nod...
Definition Logic.cpp:660
void notify_tick(double value) override
Notifies all registered callbacks about a new sample.
Definition Logic.cpp:501
size_t m_input_count
Expected number of inputs for multi-input mode.
Definition Logic.hpp:575
bool remove_hook(const NodeHook &callback) override
Removes a previously registered callback.
Definition Logic.cpp:589
void add_input(double input, size_t index)
Definition Logic.cpp:285
void set_threshold(double threshold, bool create_default_direct_function=false)
Sets the decision boundary for binary quantization.
Definition Logic.cpp:309
void while_true(const NodeHook &callback)
Registers a callback that executes continuously while output is true.
Definition Logic.cpp:569
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:426
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:421
double m_last_output
The most recent sample value generated by this oscillator.
Definition Node.hpp:374
bool m_fire_events_during_snapshot
Internal flag controlling whether notify_tick fires during state snapshots Default: false (events don...
Definition Node.hpp:448
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:383
uint32_t get_sample_rate()
Gets the sample rate from the default engine.
Definition Config.cpp:46
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
void atomic_add_flag(std::atomic< Utils::NodeState > &state, Utils::NodeState flag)
Atomically adds a flag to a node state.
Definition NodeUtils.cpp:96
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.
@ PROCESSED
Node has been processed this cycle.
Definition Utils.hpp:34