MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Polynomial.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
8
9/**
10 * @enum PolynomialMode
11 * @brief Defines how the polynomial function processes input values
12 */
13enum class PolynomialMode : uint8_t {
14 DIRECT, ///< Evaluates f(x) where x is the current phase/input
15 RECURSIVE, ///< Evaluates using current and previous outputs: y[n] = f(y[n-1], y[n-2], ...)
16 FEEDFORWARD ///< Evaluates using current and previous inputs: y[n] = f(x[n], x[n-1], ...)
17};
18
19class MAYAFLUX_API PolynomialContext : public NodeContext {
20public:
21 /**
22 * @brief Constructs a PolynomialContext
23 * @param value Current output value
24 * @param mode Current polynomial mode
25 * @param buffer_size Size of the input/output buffers
26 * @param input_buffer Current input buffer contents
27 * @param output_buffer Current output buffer contents
28 * @param coefficients Current polynomial coefficients
29 */
32 size_t buffer_size,
33 std::span<double> input_buffer,
34 std::span<double> output_buffer,
35 const std::vector<double>& coefficients)
37 , m_mode(mode)
38 , m_buffer_size(buffer_size)
39 , m_input_buffer(input_buffer)
40 , m_output_buffer(output_buffer)
41 , m_coefficients(coefficients)
42 {
43 }
44
45 /**
46 * @brief Gets the current polynomial mode
47 * @return Current polynomial mode
48 */
49 [[nodiscard]] PolynomialMode get_mode() const { return m_mode; }
50
51 /**
52 * @brief Gets the buffer size
53 * @return Current buffer size
54 */
55 [[nodiscard]] size_t get_buffer_size() const { return m_buffer_size; }
56
57 /**
58 * @brief Gets the input buffer
59 * @return Reference to the input buffer
60 */
61 [[nodiscard]] std::span<double> get_input_buffer() const { return m_input_buffer; }
62
63 /**
64 * @brief Gets the output buffer
65 * @return Reference to the output buffer
66 */
67 [[nodiscard]] std::span<double> get_output_buffer() const { return m_output_buffer; }
68
69 /**
70 * @brief Gets the polynomial coefficients
71 * @return Reference to the coefficient vector
72 */
73 [[nodiscard]] const std::vector<double>& get_coefficients() const { return m_coefficients; }
74
75private:
76 PolynomialMode m_mode; ///< Current processing mode
77 size_t m_buffer_size; ///< Size of the buffers
78 std::span<double> m_input_buffer; ///< Copy of input buffer
79 std::span<double> m_output_buffer; ///< Copy of output buffer
80 const std::vector<double>& m_coefficients; ///< Copy of polynomial coefficients
81
82 friend class Polynomial;
83};
84
85class MAYAFLUX_API PolynomialContextGpu
86 : public PolynomialContext,
87 public GpuVectorData {
88public:
90 double value,
92 size_t buffer_size,
93 std::span<double> input_buffer,
94 std::span<double> output_buffer,
95 const std::vector<double>& coefficients,
96 std::span<const float> gpu_data)
97 : PolynomialContext(value, mode, buffer_size, input_buffer, output_buffer, coefficients)
98 , GpuVectorData(gpu_data)
99 {
100 }
101
102 friend class Polynomial;
103
104 std::vector<float> gpu_float_buffer;
105};
106
107/**
108 * @class Polynomial
109 * @brief Generator that produces values based on polynomial functions
110 *
111 * The Polynomial generator creates a signal based on mathematical functions
112 * that can operate in different modes:
113 * - Direct mode: evaluates f(x) where x is the current phase or input
114 * - Recursive mode: evaluates using current and previous outputs
115 * - Feedforward mode: evaluates using current and previous inputs
116 *
117 * This flexible approach allows implementing various types of polynomial
118 * equations, difference equations, and recurrence relations.
119 */
120class MAYAFLUX_API Polynomial : public Generator {
121public:
122 /**
123 * @brief Function type for direct polynomial evaluation
124 *
125 * Takes a single input value and returns the computed output.
126 */
127 using DirectFunction = std::function<double(double)>;
128
129 /**
130 * @brief Function type for recursive/feedforward polynomial evaluation
131 *
132 * Takes a reference to a buffer of values and returns the computed output.
133 * For recursive mode, the buffer contains previous outputs.
134 * For feedforward mode, the buffer contains current and previous inputs.
135 */
136 using BufferFunction = std::function<double(std::span<double>)>;
137
138 /**
139 * @brief Function type for recursive/feedforward evaluation with access to the coefficient array
140 *
141 * Takes the history window, as for BufferFunction, and the node's own
142 * coefficient array, which the function may read and write.
143 */
144 using CoefBufferFunction = std::function<double(std::span<double>, std::span<double>)>;
145
146 /**
147 * @class PolynomialContext
148 * @brief Context object for polynomial node callbacks
149 *
150 * Extends the base NodeContext with polynomial-specific information
151 * such as mode, buffer contents, and coefficients.
152 */
153 ;
154
155 /**
156 * @brief Constructs a Polynomial generator in direct mode with coefficient-based definition
157 * @param coefficients Vector of polynomial coefficients (highest power first)
158 *
159 * Creates a polynomial generator that evaluates a standard polynomial function
160 * defined by the provided coefficients. The coefficients are ordered from
161 * highest power to lowest (e.g., [2, 3, 1] represents 2x² + 3x + 1).
162 */
163 explicit Polynomial(const std::vector<double>& coefficients);
164
165 /**
166 * @brief Constructs a Polynomial generator in direct mode with a custom function
167 * @param function Custom function that maps input to output value
168 *
169 * Creates a polynomial generator that evaluates a custom mathematical function
170 * provided by the user.
171 */
172 explicit Polynomial(DirectFunction function);
173
174 /**
175 * @brief Constructs a Polynomial generator in recursive or feedforward mode
176 * @param function Function that processes a buffer of values
177 * @param mode Processing mode (RECURSIVE or FEEDFORWARD)
178 * @param buffer_size Number of previous values to maintain
179 *
180 * Creates a polynomial generator that evaluates using current and previous values.
181 * In recursive mode, the buffer contains previous outputs.
182 * In feedforward mode, the buffer contains current and previous inputs.
183 */
184 Polynomial(BufferFunction function, PolynomialMode mode, size_t buffer_size);
185
186 /**
187 * @brief Constructs a Polynomial generator in recursive or feedforward mode with a coefficient array
188 * @param function Function receiving the history window and the coefficient array
189 * @param mode Processing mode (RECURSIVE or FEEDFORWARD)
190 * @param buffer_size Number of previous values to maintain
191 * @param coefficients Initial contents of the coefficient array
192 */
193 Polynomial(CoefBufferFunction function, PolynomialMode mode, size_t buffer_size, std::vector<double> coefficients = {});
194
195 ~Polynomial() override = default;
196
197 /**
198 * @brief Processes a single sample
199 * @param input Input value
200 * @return The next sample value from the polynomial function
201 *
202 * Computes the next output value based on the polynomial function and current mode.
203 */
204 double process_sample(double input = 0.) override;
205
206 /**
207 * @brief Processes multiple samples at once
208 * @param num_samples Number of samples to generate
209 * @return Vector of generated samples
210 *
211 * This method is more efficient than calling process_sample() repeatedly
212 * when generating multiple samples at once.
213 */
214 std::vector<double> process_batch(unsigned int num_samples) override;
215
216 /**
217 * @brief Resets the generator to its initial state
218 *
219 * Clears the internal buffers and resets to initial conditions.
220 */
221 void reset();
222
223 /**
224 * @brief An independent node with the same behaviour and fresh history
225 *
226 * Same mode, buffer size, function, scale and coefficient array as the
227 * array stands now, so a state-bearing kernel's clone continues from the
228 * current state. History, saved state and hooks are not copied. The input
229 * node, if any, is shared. Closure state captured by a function is shared
230 * too; the coefficient array is the state that is not.
231 *
232 * Attach one clone per channel instead of one node to several.
233 */
234 [[nodiscard]] std::shared_ptr<Polynomial> clone() const;
235
236 /**
237 * @brief Sets the polynomial coefficients (for direct mode)
238 * @param coefficients Vector of polynomial coefficients (highest power first)
239 *
240 * Updates the polynomial function to use the specified coefficients.
241 * This allows dynamically changing the polynomial during operation.
242 * A node built from a coefficient list evaluates this array directly, so the
243 * change applies on the next sample. A node built from a function keeps its
244 * function; the array then only reaches coefficient-aware buffer functions.
245 * Updates of unchanged size are written in place; changing the size should
246 * happen on the scheduler tick, not concurrently with processing.
247 */
248 void set_coefficients(const std::vector<double>& coefficients);
249
250 /**
251 * @brief Sets a custom direct function
252 * @param function Custom function that maps input to output value
253 *
254 * Updates the generator to use the specified custom function.
255 */
256 void set_direct_function(DirectFunction function);
257
258 /**
259 * @brief Sets a custom buffer function
260 * @param function Function that processes a buffer of values
261 * @param mode Processing mode (RECURSIVE or FEEDFORWARD)
262 * @param buffer_size Number of previous values to maintain
263 *
264 * Updates the generator to use the specified buffer function and mode.
265 */
266 void set_buffer_function(BufferFunction function, PolynomialMode mode, size_t buffer_size);
267
268 /**
269 * @brief Sets a buffer function that receives the coefficient array
270 * @param function Function receiving the history window and the coefficient array
271 * @param mode Processing mode (RECURSIVE or FEEDFORWARD)
272 * @param buffer_size Number of previous values to maintain
273 */
274 void set_buffer_function(CoefBufferFunction function, PolynomialMode mode, size_t buffer_size);
275
276 /**
277 * @brief Sets initial conditions for recursive mode
278 * @param initial_values Vector of initial output values
279 *
280 * Sets the initial values for the output buffer in recursive mode.
281 * The values are ordered from newest to oldest.
282 */
283 void set_initial_conditions(const std::vector<double>& initial_values);
284
285 /**
286 * @brief Creates a polynomial function from coefficients
287 * @param coefficients Vector of polynomial coefficients (highest power first)
288 * @return Function that evaluates the polynomial
289 *
290 * Generates a function that evaluates the polynomial defined by the
291 * specified coefficients.
292 * The cofficients are ordered from highest power to lowest.
293 */
294 DirectFunction create_polynomial_function(const std::vector<double>& coefficients);
295
296 /**
297 * @brief Sets the input node to generate polynomial values from
298 * @param input_node Node providing the input values
299 *
300 * Configures the node to receive input from another node
301 */
302 inline void set_input_node(const std::shared_ptr<Node>& input_node) { m_input_node = input_node; }
303
304 /**
305 * @brief Gets the current polynomial mode
306 * @return Current polynomial mode
307 */
308 [[nodiscard]] PolynomialMode get_mode() const { return m_mode; }
309
310 /**
311 * @brief Gets the buffer size
312 * @return Current buffer size
313 */
314 [[nodiscard]] size_t get_buffer_size() const { return m_buffer_size; }
315
316 /**
317 * @brief Gets the polynomial coefficients
318 * @return Reference to the coefficient vector
319 */
320 [[nodiscard]] const std::vector<double>& get_coefficients() const { return m_coefficients; }
321
322 /**
323 * @brief Gets the input buffer
324 * @return Reference to the input buffer
325 */
326 [[nodiscard]] std::span<double> get_input_buffer() { return m_history.linearized_view(); }
327
328 /**
329 * @brief Gets the output buffer
330 * @return Reference to the output buffer
331 */
332 [[nodiscard]] std::span<double> get_output_buffer() { return m_history.linearized_view(); }
333
334 /**
335 * @brief Sets the scaling factor for the output values
336 */
337 inline void set_amplitude(double amplitude) override { m_scale_factor = amplitude; }
338
339 /**
340 * @brief Gets the current amplitude scaling factor
341 * @return Current amplitude scaling factor
342 *
343 * This method retrieves the scaling factor applied to the output values,
344 * which controls the overall amplitude of the generated signal.
345 */
346 [[nodiscard]] inline double get_amplitude() const override { return m_scale_factor; }
347
348 void save_state() override;
349 void restore_state() override;
350
351 /**
352 * @brief Uses an external buffer context for processing
353 * @param buffer_view Span representing the external buffer
354 *
355 * Configures the generator to use an external buffer context
356 * for its internal processing, allowing integration with
357 * external data sources.
358 */
359 void set_buffer_context(std::span<double> buffer_view)
360 {
361 m_external_buffer_context = buffer_view;
362 m_use_external_context = true;
363 }
364
365 /**
366 * @brief Clear external buffer context, resume internal accumulation
367 */
369 {
370 m_use_external_context = false;
371 m_external_buffer_context = {};
372 }
373
374 [[nodiscard]] inline bool using_external_context() const
375 {
376 return m_use_external_context;
377 }
378
379 /**
380 * @brief Retrieves the last created context object
381 * @return Reference to the last PolynomialContext object
382 *
383 * This method provides access to the most recent PolynomialContext object
384 * created by the polynomial generator. This context contains information
385 * about the generator's state at the time of the last output generation.
386 */
387 NodeContext& get_last_context() override;
388
389 void set_gpu_compatible(bool compatible) override
390 {
391 Node::set_gpu_compatible(compatible);
392 if (compatible) {
393 m_node_capability |= NodeCapability::VECTOR;
394 } else {
395 m_node_capability &= ~NodeCapability::VECTOR;
396 }
397 }
398
399 /**
400 * @brief Retrieves the current modulators connected to this node
401 * @return Vector of pairs containing the modulator role and the corresponding node
402 */
403 [[nodiscard]] std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>> get_modulators() const override;
404
405protected:
406 /**
407 * @brief Updates the context object with the current node state
408 * @param value The current sample value
409 */
410 void update_context(double value) override;
411
412private:
413 /**
414 * @brief Converts coefficient vector to a polynomial function
415 * @param coefficients Vector of polynomial coefficients (highest power first)
416 * @return Function that evaluates the polynomial
417 *
418 * Creates a function that evaluates the polynomial defined by the
419 * specified coefficients.
420 */
421 // DirectFunction create_polynomial_function(const std::vector<double>& coefficients);
422
423 /**
424 * @brief Adapts a CoefBufferFunction to the BufferFunction slot
425 * @param function Function receiving the history window and the coefficient array
426 * @return BufferFunction that supplies m_coefficients on every call
427 */
428 BufferFunction bind_coefficients(CoefBufferFunction function);
429
430 /**
431 * @brief Evaluates the coefficient list at x, highest power first
432 * @param coefficients Coefficient vector
433 * @param x Evaluation point
434 * @return Sum of coefficient * x^k, accumulated from the last coefficient
435 *
436 * The one loop behind create_polynomial_function and the live DIRECT
437 * evaluation of a node built from coefficients.
438 */
439 static double power_sum(const std::vector<double>& coefficients, double x) noexcept;
440
441 PolynomialMode m_mode; ///< Current processing mode
442 DirectFunction m_direct_function; ///< Function for direct mode
443 BufferFunction m_buffer_function; ///< Function for recursive/feedforward mode
444 CoefBufferFunction m_coef_function; ///< The function behind m_buffer_function while a CoefBufferFunction is bound
445 std::vector<double> m_coefficients; ///< Polynomial coefficients (if using coefficient-based definition)
446 std::span<double> m_external_buffer_context; ///< View into external buffer
447
448 Memory::HistoryBuffer<double> m_history; ///< Ring buffer for input/output history
449 std::vector<double> m_linear_view; ///< Linearized view of history for easy access
450
451 std::vector<double> m_saved_history_state; ///< Saved state of the history buffer
452 std::vector<double> m_saved_coefficients; ///< Saved coefficient array, used when a CoefBufferFunction is bound
453 bool m_coef_bound {}; ///< True once a CoefBufferFunction has been bound
454 bool m_coef_direct {}; ///< True while DIRECT output is evaluated from m_coefficients
455
456 size_t m_buffer_size {}; ///< Maximum size of the buffers
457 double m_scale_factor; ///< Scaling factor for output
458 std::shared_ptr<Node> m_input_node; ///< Input node for processing
459 size_t m_current_buffer_position {}; // Where we are in the external buffer
460
461 double m_saved_last_output {};
462 bool m_use_external_context {}; // Whether to use it
463
466
467 std::span<double> external_context_view(double input);
468};
469
470} // namespace MayaFlux::Nodes::Generator
Core::GlobalInputConfig input
Definition Config.cpp:42
uint32_t mode
glm::vec3 value
History buffer for difference equations and recursive relations.
Base class for all signal and pattern generators in Maya Flux.
PolynomialContextGpu(double value, PolynomialMode mode, size_t buffer_size, std::span< double > input_buffer, std::span< double > output_buffer, const std::vector< double > &coefficients, std::span< const float > gpu_data)
std::span< double > get_output_buffer() const
Gets the output buffer.
const std::vector< double > & m_coefficients
Copy of polynomial coefficients.
const std::vector< double > & get_coefficients() const
Gets the polynomial coefficients.
std::span< double > m_output_buffer
Copy of output buffer.
PolynomialMode m_mode
Current processing mode.
PolynomialContext(double value, PolynomialMode mode, size_t buffer_size, std::span< double > input_buffer, std::span< double > output_buffer, const std::vector< double > &coefficients)
Constructs a PolynomialContext.
std::span< double > m_input_buffer
Copy of input buffer.
std::span< double > get_input_buffer() const
Gets the input buffer.
size_t get_buffer_size() const
Gets the buffer size.
PolynomialMode get_mode() const
Gets the current polynomial mode.
CoefBufferFunction m_coef_function
The function behind m_buffer_function while a CoefBufferFunction is bound.
std::function< double(std::span< double >)> BufferFunction
Function type for recursive/feedforward polynomial evaluation.
void set_gpu_compatible(bool compatible) override
Sets whether the node is compatible with GPU processing.
std::vector< double > m_saved_coefficients
Saved coefficient array, used when a CoefBufferFunction is bound.
PolynomialMode m_mode
Current processing mode.
std::function< double(std::span< double >, std::span< double >)> CoefBufferFunction
Function type for recursive/feedforward evaluation with access to the coefficient array.
std::vector< double > m_saved_history_state
Saved state of the history buffer.
void set_amplitude(double amplitude) override
Sets the scaling factor for the output values.
Memory::HistoryBuffer< double > m_history
Ring buffer for input/output history.
PolynomialMode get_mode() const
Gets the current polynomial mode.
void set_input_node(const std::shared_ptr< Node > &input_node)
Sets the input node to generate polynomial values from.
void set_buffer_context(std::span< double > buffer_view)
Uses an external buffer context for processing.
const std::vector< double > & get_coefficients() const
Gets the polynomial coefficients.
double get_amplitude() const override
Gets the current amplitude scaling factor.
double m_scale_factor
Scaling factor for output.
std::span< double > m_external_buffer_context
View into external buffer.
size_t get_buffer_size() const
Gets the buffer size.
void clear_buffer_context()
Clear external buffer context, resume internal accumulation.
std::vector< double > m_linear_view
Linearized view of history for easy access.
BufferFunction m_buffer_function
Function for recursive/feedforward mode.
std::shared_ptr< Node > m_input_node
Input node for processing.
std::span< double > get_output_buffer()
Gets the output buffer.
std::function< double(double)> DirectFunction
Function type for direct polynomial evaluation.
DirectFunction m_direct_function
Function for direct mode.
std::span< double > get_input_buffer()
Gets the input buffer.
std::vector< double > m_coefficients
Polynomial coefficients (if using coefficient-based definition)
Generator that produces values based on polynomial functions.
GPU-uploadable 1D array data interface.
Base context class for node callbacks.
Definition Node.hpp:53
@ DIRECT
Stateless evaluation of current input only (combinational logic)
PolynomialMode
Defines how the polynomial function processes input values.
@ RECURSIVE
Evaluates using current and previous outputs: y[n] = f(y[n-1], y[n-2], ...)
@ FEEDFORWARD
Evaluates using current and previous inputs: y[n] = f(x[n], x[n-1], ...)
NodeCapability
Bitmask flags declaring what data shapes a node's context can produce.
Definition NodeSpec.hpp:109