MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Boolean.cpp
Go to the documentation of this file.
1#include "Boolean.hpp"
2
3#include "Kernels.hpp"
4
6
7namespace {
8
9 constexpr size_t MAX_TABLE_ARITY = 20;
10 constexpr size_t MAX_STATE_ARITY = 6;
11 constexpr uint32_t DEFAULT_SEED = 2463534242U;
12 constexpr double UINT32_SPAN = 4294967296.0;
13
14 bool rises(bool high, double& latched) noexcept
15 {
16 const bool edge = high && latched <= 0.5;
17 latched = high ? 1.0 : 0.0;
18 return edge;
19 }
20
21 size_t index_of(double value) noexcept
22 {
23 return static_cast<size_t>(std::max(value, 0.0));
24 }
25
26 uint32_t word_of(double value) noexcept
27 {
28 return static_cast<uint32_t>(std::clamp(value, 0.0, UINT32_SPAN - 1.0));
29 }
30
31}
32
33std::vector<double> truth_table_state(size_t arity, uint64_t rule)
34{
35 arity = std::min(arity, MAX_STATE_ARITY);
36
37 std::vector<double> state(1 + (size_t { 1 } << arity), 0.0);
38 state.front() = static_cast<double>(arity);
39
40 for (size_t i = 1; i < state.size(); ++i)
41 state[i] = static_cast<double>((rule >> (i - 1)) & 1U);
42 return state;
43}
44
45bool truth_table(std::span<const bool> history, std::span<const double> coefs) noexcept
46{
47 if (coefs.empty())
48 return false;
49
50 const size_t arity = index_of(coefs.front());
51 if (arity > MAX_TABLE_ARITY || coefs.size() < 1 + (size_t { 1 } << arity))
52 return false;
53
54 size_t pattern = 0;
55 for (size_t i = 0; i < arity && i < history.size(); ++i) {
56 if (history[i])
57 pattern |= size_t { 1 } << i;
58 }
59 return coefs[1 + pattern] > 0.5;
60}
61
62bool count_at_least(std::span<const bool> history, std::span<const double> coefs) noexcept
63{
64 if (coefs.size() < 2)
65 return false;
66
67 const size_t n = std::min(index_of(coefs[0]), history.size());
68 const auto set = static_cast<size_t>(std::count(history.begin(), history.begin() + static_cast<std::ptrdiff_t>(n), true));
69 return set >= index_of(coefs[1]);
70}
71
72std::vector<double> hysteresis_gate_state(double low, double high)
73{
74 return { low, high, 0.0 };
75}
76
77bool hysteresis_gate(double input, std::span<double> coefs) noexcept
78{
79 if (coefs.size() < 3)
80 return false;
81
82 if (input > coefs[1])
83 coefs[2] = 1.0;
84 else if (input < coefs[0])
85 coefs[2] = 0.0;
86 return coefs[2] > 0.5;
87}
88
89std::vector<double> rising_toggle_state(double threshold)
90{
91 return { threshold, 0.0, 0.0 };
92}
93
94bool rising_toggle(double input, std::span<double> coefs) noexcept
95{
96 if (coefs.size() < 3)
97 return false;
98
99 if (rises(input > coefs[0], coefs[1]))
100 coefs[2] = coefs[2] > 0.5 ? 0.0 : 1.0;
101 return coefs[2] > 0.5;
102}
103
104std::vector<double> edge_divider_state(size_t n, size_t offset, double threshold)
105{
106 return { threshold, 0.0, 0.0, static_cast<double>(n), static_cast<double>(offset), 0.0 };
107}
108
109bool edge_divider(double input, std::span<double> coefs) noexcept
110{
111 if (coefs.size() < 6)
112 return false;
113
114 const bool high = input > coefs[0];
115 if (rises(high, coefs[1])) {
116 const size_t n = std::max<size_t>(index_of(coefs[3]), 1);
117 const size_t edge = index_of(coefs[2]);
118 coefs[5] = (edge % n) == (index_of(coefs[4]) % n) ? 1.0 : 0.0;
119 coefs[2] = static_cast<double>(edge + 1);
120 }
121 return high && coefs[5] > 0.5;
122}
123
124std::vector<double> bernoulli_gate_state(double probability, uint32_t seed, double threshold)
125{
126 return { threshold, 0.0, probability, static_cast<double>(seed == 0 ? DEFAULT_SEED : seed), 0.0 };
127}
128
129bool bernoulli_gate(double input, std::span<double> coefs) noexcept
130{
131 if (coefs.size() < 5)
132 return false;
133
134 const bool high = input > coefs[0];
135 if (rises(high, coefs[1])) {
136 uint32_t state = word_of(coefs[3]);
137 if (state == 0)
138 state = DEFAULT_SEED;
139 state = xorshift32(state);
140 coefs[3] = static_cast<double>(state);
141 coefs[4] = static_cast<double>(state) / UINT32_SPAN < coefs[2] ? 1.0 : 0.0;
142 }
143 return high && coefs[4] > 0.5;
144}
145
146std::vector<double> galois_lfsr_state(uint32_t taps, uint32_t seed, double threshold)
147{
148 return { threshold, 0.0, static_cast<double>(taps), static_cast<double>(seed == 0 ? 1U : seed) };
149}
150
151bool galois_lfsr(double input, std::span<double> coefs) noexcept
152{
153 if (coefs.size() < 4)
154 return false;
155
156 uint32_t reg = word_of(coefs[3]);
157 if (rises(input > coefs[0], coefs[1])) {
158 if (reg == 0)
159 reg = 1;
160 const bool fell_out = (reg & 1U) != 0U;
161 reg >>= 1U;
162 if (fell_out)
163 reg ^= word_of(coefs[2]);
164 coefs[3] = static_cast<double>(reg);
165 }
166 return (reg & 1U) != 0U;
167}
168
169std::vector<double> state_machine_state(std::span<const double> table, double threshold, size_t initial)
170{
171 const size_t states = table.size() / 4;
172
173 std::vector<double> state(3 + 4 * states, 0.0);
174 state[0] = threshold;
175 state[1] = static_cast<double>(states);
176 state[2] = static_cast<double>(initial);
177
178 std::copy_n(table.begin(), static_cast<std::ptrdiff_t>(4 * states), state.begin() + 3);
179 return state;
180}
181
182bool state_machine(double input, std::span<double> coefs) noexcept
183{
184 if (coefs.size() < 3)
185 return false;
186
187 const size_t states = index_of(coefs[1]);
188 if (states == 0 || coefs.size() < 3 + 4 * states)
189 return false;
190
191 size_t current = index_of(coefs[2]);
192 if (current >= states)
193 current = 0;
194
195 const size_t row = 3 + 4 * current + (input > coefs[0] ? 2 : 0);
196 const size_t next = index_of(coefs[row]);
197 coefs[2] = static_cast<double>(next < states ? next : 0);
198 return coefs[row + 1] > 0.5;
199}
200
201std::vector<double> maximally_even_sequence(size_t pulses, size_t steps, size_t rotation)
202{
203 std::vector<double> out(steps, 0.0);
204 if (steps == 0)
205 return out;
206
207 pulses = std::min(pulses, steps);
208 for (size_t i = 0; i < steps; ++i) {
209 const size_t position = (i + rotation) % steps;
210 out[i] = (position * pulses) % steps < pulses ? 1.0 : 0.0;
211 }
212 return out;
213}
214
215bool step_pattern(double input, std::span<double> coefs) noexcept
216{
217 return step_sequence(std::span<const double>(&input, 1), coefs) > 0.5;
218}
219
220std::vector<double> refractory_gate_state(double period, double threshold)
221{
222 return { std::numeric_limits<double>::lowest(), period, threshold };
223}
224
225bool refractory_gate(double input, double time, std::span<double> coefs) noexcept
226{
227 if (coefs.size() < 3)
228 return false;
229
230 if (input > coefs[2] && time - coefs[0] >= coefs[1]) {
231 coefs[0] = time;
232 return true;
233 }
234 return false;
235}
236
237std::vector<double> one_shot_state(double duration, double threshold)
238{
239 return { threshold, 0.0, 0.0, duration };
240}
241
242bool one_shot(double input, double time, std::span<double> coefs) noexcept
243{
244 if (coefs.size() < 4)
245 return false;
246
247 if (rises(input > coefs[0], coefs[1]))
248 coefs[2] = time + coefs[3];
249 return time < coefs[2];
250}
251
252std::vector<double> set_reset_latch_state(double threshold)
253{
254 return { threshold, 0.0 };
255}
256
257bool set_reset_latch(const std::vector<double>& inputs, std::span<double> coefs) noexcept
258{
259 if (inputs.size() < 2 || coefs.size() < 2)
260 return false;
261
262 if (inputs[1] > coefs[0])
263 coefs[1] = 0.0;
264 else if (inputs[0] > coefs[0])
265 coefs[1] = 1.0;
266 return coefs[1] > 0.5;
267}
268
269std::vector<double> comparator_state(double margin)
270{
271 return { margin, 0.0 };
272}
273
274bool comparator(const std::vector<double>& inputs, std::span<double> coefs) noexcept
275{
276 if (inputs.size() < 2 || coefs.size() < 2)
277 return false;
278
279 const double difference = inputs[0] - inputs[1];
280 if (difference > coefs[0])
281 coefs[1] = 1.0;
282 else if (difference < -coefs[0])
283 coefs[1] = 0.0;
284 return coefs[1] > 0.5;
285}
286
287bool window_comparator(const std::vector<double>& inputs, std::span<const double>) noexcept
288{
289 if (inputs.size() < 3)
290 return false;
291 return inputs[0] > inputs[1] && inputs[0] < inputs[2];
292}
293
294std::vector<double> signals_at_least_state(size_t k, double threshold)
295{
296 return { threshold, static_cast<double>(k) };
297}
298
299bool signals_at_least(const std::vector<double>& inputs, std::span<const double> coefs) noexcept
300{
301 if (coefs.size() < 2)
302 return false;
303
304 const double threshold = coefs[0];
305 const auto high = static_cast<size_t>(std::count_if(inputs.begin(), inputs.end(),
306 [threshold](double v) { return v > threshold; }));
307 return high >= index_of(coefs[1]);
308}
309
310std::vector<double> input_truth_table_state(size_t arity, uint64_t rule, double threshold)
311{
312 arity = std::min(arity, MAX_STATE_ARITY);
313
314 std::vector<double> state(2 + (size_t { 1 } << arity), 0.0);
315 state[0] = threshold;
316 state[1] = static_cast<double>(arity);
317
318 for (size_t i = 2; i < state.size(); ++i)
319 state[i] = static_cast<double>((rule >> (i - 2)) & 1U);
320 return state;
321}
322
323bool input_truth_table(const std::vector<double>& inputs, std::span<const double> coefs) noexcept
324{
325 if (coefs.size() < 2)
326 return false;
327
328 const size_t arity = index_of(coefs[1]);
329 if (arity > MAX_TABLE_ARITY || coefs.size() < 2 + (size_t { 1 } << arity))
330 return false;
331
332 size_t pattern = 0;
333 for (size_t i = 0; i < arity && i < inputs.size(); ++i) {
334 if (inputs[i] > coefs[0])
335 pattern |= size_t { 1 } << i;
336 }
337 return coefs[2 + pattern] > 0.5;
338}
339
340std::vector<double> clocked_register_state(size_t length, size_t tap, double threshold)
341{
342 std::vector<double> state(4 + length, 0.0);
343 state[0] = threshold;
344 state[2] = static_cast<double>(length);
345 state[3] = static_cast<double>(tap);
346 return state;
347}
348
349bool clocked_register(const std::vector<double>& inputs, std::span<double> coefs) noexcept
350{
351 if (inputs.size() < 2 || coefs.size() < 4)
352 return false;
353
354 const size_t length = index_of(coefs[2]);
355 if (length == 0 || coefs.size() < 4 + length)
356 return false;
357
358 const auto stages = coefs.subspan(4, length);
359 if (rises(inputs[0] > coefs[0], coefs[1])) {
360 for (size_t i = length - 1; i > 0; --i)
361 stages[i] = stages[i - 1];
362 stages[0] = inputs[1] > coefs[0] ? 1.0 : 0.0;
363 }
364 return stages[std::min(index_of(coefs[3]), length - 1)] > 0.5;
365}
366
367} // namespace MayaFlux::Kinesis::Discrete
Pure decision functions of bits and an array of numbers.
uint64_t length
Definition Composite.cpp:11
uint64_t offset
Definition Composite.cpp:10
Core::GlobalInputConfig input
Definition Config.cpp:42
std::optional< glm::vec3 > position
Definition Decoder.cpp:93
glm::vec2 current
Pure functions of a newest-first window and an array of numbers.
std::vector< float > * out
glm::vec3 value
float threshold
bool one_shot(double input, double time, std::span< double > coefs) noexcept
Monostable: every rise of the input opens the output for a fixed time.
Definition Boolean.cpp:242
bool bernoulli_gate(double input, std::span< double > coefs) noexcept
Probabilistic gate: each pulse passes with the given probability.
Definition Boolean.cpp:129
bool truth_table(std::span< const bool > history, std::span< const double > coefs) noexcept
Any boolean function of the last bits, as a table.
Definition Boolean.cpp:45
std::vector< double > state_machine_state(std::span< const double > table, double threshold, size_t initial)
Builds the array state_machine reads and writes.
Definition Boolean.cpp:169
std::vector< double > truth_table_state(size_t arity, uint64_t rule)
Builds the array truth_table reads.
Definition Boolean.cpp:33
uint32_t xorshift32(uint32_t state) noexcept
One step of the 32-bit xorshift generator.
Definition Boolean.hpp:35
bool comparator(const std::vector< double > &inputs, std::span< double > coefs) noexcept
Signal against signal: true once slot 0 exceeds slot 1 by the margin.
Definition Boolean.cpp:274
std::vector< double > signals_at_least_state(size_t k, double threshold)
Builds the array signals_at_least reads.
Definition Boolean.cpp:294
std::vector< double > bernoulli_gate_state(double probability, uint32_t seed, double threshold)
Builds the array bernoulli_gate reads and writes.
Definition Boolean.cpp:124
std::vector< double > edge_divider_state(size_t n, size_t offset, double threshold)
Builds the array edge_divider reads and writes.
Definition Boolean.cpp:104
bool window_comparator(const std::vector< double > &inputs, std::span< const double >) noexcept
True while slot 0 lies strictly between slot 1 and slot 2.
Definition Boolean.cpp:287
bool step_pattern(double input, std::span< double > coefs) noexcept
A table of bits advanced by the rises of the input.
Definition Boolean.cpp:215
bool count_at_least(std::span< const bool > history, std::span< const double > coefs) noexcept
True when at least k of the last n bits are set.
Definition Boolean.cpp:62
std::vector< double > hysteresis_gate_state(double low, double high)
Builds the array hysteresis_gate reads and writes.
Definition Boolean.cpp:72
std::vector< double > comparator_state(double margin)
Builds the array comparator reads and writes.
Definition Boolean.cpp:269
std::vector< double > galois_lfsr_state(uint32_t taps, uint32_t seed, double threshold)
Builds the array galois_lfsr reads and writes.
Definition Boolean.cpp:146
bool refractory_gate(double input, double time, std::span< double > coefs) noexcept
Fires while the input is high, then ignores it for a period.
Definition Boolean.cpp:225
std::vector< double > maximally_even_sequence(size_t pulses, size_t steps, size_t rotation)
The maximally even placement of pulses among steps, as a 0 or 1 table.
Definition Boolean.cpp:201
double step_sequence(std::span< const double > window, std::span< double > coefs) noexcept
Table of values advanced by a trigger.
Definition Kernels.cpp:629
bool rising_toggle(double input, std::span< double > coefs) noexcept
Flip-flop: the output inverts on every rise of the input.
Definition Boolean.cpp:94
bool clocked_register(const std::vector< double > &inputs, std::span< double > coefs) noexcept
Shift register: slot 1 is sampled into it on every rise of slot 0.
Definition Boolean.cpp:349
std::vector< double > refractory_gate_state(double period, double threshold)
Builds the array refractory_gate reads and writes.
Definition Boolean.cpp:220
bool state_machine(double input, std::span< double > coefs) noexcept
Mealy machine: the state and the input bit pick the next state and the output.
Definition Boolean.cpp:182
bool input_truth_table(const std::vector< double > &inputs, std::span< const double > coefs) noexcept
Any boolean function of the input slots, as a table.
Definition Boolean.cpp:323
bool signals_at_least(const std::vector< double > &inputs, std::span< const double > coefs) noexcept
True when at least k of the input slots are high.
Definition Boolean.cpp:299
std::vector< double > input_truth_table_state(size_t arity, uint64_t rule, double threshold)
Builds the array input_truth_table reads.
Definition Boolean.cpp:310
std::vector< double > clocked_register_state(size_t length, size_t tap, double threshold)
Builds the array clocked_register reads and writes.
Definition Boolean.cpp:340
std::vector< double > set_reset_latch_state(double threshold)
Builds the array set_reset_latch reads and writes.
Definition Boolean.cpp:252
std::vector< double > one_shot_state(double duration, double threshold)
Builds the array one_shot reads and writes.
Definition Boolean.cpp:237
bool galois_lfsr(double input, std::span< double > coefs) noexcept
Linear feedback shift register clocked by the rises of the input.
Definition Boolean.cpp:151
bool set_reset_latch(const std::vector< double > &inputs, std::span< double > coefs) noexcept
Memory cell: slot 0 sets it, slot 1 resets it, reset wins.
Definition Boolean.cpp:257
bool edge_divider(double input, std::span< double > coefs) noexcept
Gate divider: the input passes only during every n-th pulse.
Definition Boolean.cpp:109
bool hysteresis_gate(double input, std::span< double > coefs) noexcept
Schmitt trigger: engages above high, releases below low, holds between.
Definition Boolean.cpp:77
std::vector< double > rising_toggle_state(double threshold)
Builds the array rising_toggle reads and writes.
Definition Boolean.cpp:89