MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MathematicalTransformer.hpp
Go to the documentation of this file.
1#pragma once
2
6
7namespace MayaFlux::Yantra {
8
10/**
11 * @enum MathematicalOperation
12 * @brief Specific mathematical operations supported
13 */
14enum class MathematicalOperation : uint8_t {
15 GAIN, ///< Linear gain/attenuation
16 OFFSET, ///< DC offset
17 POWER, ///< Power function
18 LOGARITHMIC, ///< Logarithmic transform
19 EXPONENTIAL, ///< Exponential transform
20 TRIGONOMETRIC, ///< Trigonometric functions
21 QUANTIZE, ///< Quantization/bit reduction
22 NORMALIZE, ///< Normalization
23 POLYNOMIAL ///< Polynomial transform
24};
25
26/**
27 * @class MathematicalTransformer
28 * @brief Concrete transformer for mathematical operations
29 *
30 * Handles pure mathematical transformations:
31 * - Arithmetic operations (gain, offset, scaling)
32 * - Trigonometric functions
33 * - Logarithmic and exponential transforms
34 * - Polynomial and power functions
35 * - Quantization and bit reduction
36 */
37template <ComputeData InputType = std::vector<Kakshya::DataVariant>, ComputeData OutputType = InputType>
38class MAYAFLUX_API MathematicalTransformer final : public UniversalTransformer<InputType, OutputType> {
39public:
42
43 /**
44 * @brief Constructs a MathematicalTransformer with specified operation
45 * @param op The mathematical operation to perform (default: GAIN)
46 */
47 explicit MathematicalTransformer(MathematicalOperation op = MathematicalOperation::GAIN)
48 : m_operation(op)
49 {
50 set_default_parameters();
51 }
52
53 /**
54 * @brief Gets the transformation type
55 * @return TransformationType::MATHEMATICAL
56 */
57 [[nodiscard]] TransformationType get_transformation_type() const override
58 {
59 return TransformationType::MATHEMATICAL;
60 }
61
62 /**
63 * @brief Gets the transformer name including the operation type
64 * @return String representation of the transformer name
65 */
66 [[nodiscard]] std::string get_transformer_name() const override
67 {
68 return std::string("MathematicalTransformer_").append(Reflect::enum_to_string(m_operation));
69 }
70
71protected:
72 /**
73 * @brief Core transformation implementation
74 * @param input Input data to transform
75 * @return Transformed output data
76 *
77 * Performs the mathematical operation specified by m_operation on the input data.
78 * Supports both in-place and out-of-place transformations based on transformer settings.
79 */
81 {
82 switch (m_operation) {
83
84 case MathematicalOperation::GAIN: {
85 const auto a = get_parameter_or<double>("gain_factor", 1.0);
86 return apply_per_channel(input, [a](std::span<double> ch) {
87 D::linear(ch, a, 0.0);
88 });
89 }
90
91 case MathematicalOperation::OFFSET: {
92 const auto b = get_parameter_or<double>("offset_value", 0.0);
93 return apply_per_channel(input, [b](std::span<double> ch) {
94 D::linear(ch, 1.0, b);
95 });
96 }
97
98 case MathematicalOperation::POWER: {
99 const auto exp = get_parameter_or<double>("exponent", 2.0);
100 return apply_per_channel(input, [exp](std::span<double> ch) {
101 D::power(ch, exp);
102 });
103 }
104
105 case MathematicalOperation::LOGARITHMIC: {
106 const auto a = get_parameter_or<double>("scale", 1.0);
107 const auto b = get_parameter_or<double>("input_scale", 1.0);
108 const auto c = get_parameter_or<double>("offset", 1.0);
109 const auto base = get_parameter_or<double>("base", std::numbers::e);
110 return apply_per_channel(input, [a, b, c, base](std::span<double> ch) {
111 D::logarithmic(ch, a, b, c, base);
112 });
113 }
114
115 case MathematicalOperation::EXPONENTIAL: {
116 const auto a = get_parameter_or<double>("scale", 1.0);
117 const auto b = get_parameter_or<double>("rate", 1.0);
118 const auto base = get_parameter_or<double>("base", std::numbers::e);
119 return apply_per_channel(input, [a, b, base](std::span<double> ch) {
120 D::exponential(ch, a, b, base);
121 });
122 }
123
124 case MathematicalOperation::TRIGONOMETRIC: {
125 const auto fn = get_parameter_or<std::string>("trig_function", "sin");
126 const auto freq = get_parameter_or<double>("frequency", 1.0);
127 const auto amp = get_parameter_or<double>("amplitude", 1.0);
128 const auto ph = get_parameter_or<double>("phase", 0.0);
129 if (fn == "cos")
130 return apply_per_channel(input, [freq, amp, ph](std::span<double> ch) {
131 D::apply_trig(ch, [](double x) { return std::cos(x); }, freq, amp, ph);
132 });
133 if (fn == "tan")
134 return apply_per_channel(input, [freq, amp, ph](std::span<double> ch) {
135 D::apply_trig(ch, [](double x) { return std::tan(x); }, freq, amp, ph);
136 });
137 return apply_per_channel(input, [freq, amp, ph](std::span<double> ch) {
138 D::apply_trig(ch, [](double x) { return std::sin(x); }, freq, amp, ph);
139 });
140 }
141
142 case MathematicalOperation::QUANTIZE: {
143 const auto bits = get_parameter_or<uint8_t>("bits", 16);
144 return apply_per_channel(input, [bits](std::span<double> ch) {
145 D::quantize(ch, bits);
146 });
147 }
148
149 case MathematicalOperation::NORMALIZE: {
150 const auto peak = get_parameter_or<double>("target_peak", 1.0);
151 return apply_per_channel(input, [peak](std::span<double> ch) {
152 D::normalize(ch, -peak, peak);
153 });
154 }
155
156 case MathematicalOperation::POLYNOMIAL: {
157 const auto coeffs = get_parameter_or<std::vector<double>>(
158 "coefficients", std::vector<double> { 0.0, 1.0 });
159 auto poly = std::make_shared<Nodes::Generator::Polynomial>(coeffs);
160 return apply_per_channel(input, [&poly](std::span<double> ch) {
161 std::ranges::transform(ch, ch.begin(),
162 [&poly](double x) { return poly->process_sample(x); });
163 });
164 }
165
166 default:
167 return create_output(input);
168 }
169 }
170
171 /**
172 * @brief Sets transformation parameters
173 * @param name Parameter name
174 * @param value Parameter value
175 *
176 * Handles setting of operation type and delegates other parameters to base class.
177 * Supports both enum and string values for the "operation" parameter.
178 */
179 void set_transformation_parameter(const std::string& name, std::any value) override
180 {
181 if (name == "operation") {
182 if (auto r = safe_any_cast<MathematicalOperation>(value)) {
183 m_operation = *r.value;
184 return;
185 }
186 if (auto r = safe_any_cast<std::string>(value)) {
187 if (auto e = Reflect::string_to_enum_case_insensitive<MathematicalOperation>(*r.value)) {
188 m_operation = *e;
189 return;
190 }
191 }
192 }
193
195 }
196
197private:
198 MathematicalOperation m_operation; ///< Current mathematical operation
199 mutable std::vector<std::vector<double>> m_working_buffer; ///< Buffer for out-of-place operations
200
201 /**
202 * @brief Extracts per-channel spans, applies an in-place func to each, and reconstructs.
203 * @tparam Func Callable matching void(std::span<double>)
204 *
205 * In-place: results are copied back into the original channel spans of @p input before
206 * reconstruction. Out-of-place: input is not mutated.
207 */
208 template <typename Func>
210 {
211 auto [channels, structure_info] = OperationHelper::extract_structured_double(input);
212 m_working_buffer.resize(channels.size());
213 for (size_t i = 0; i < channels.size(); ++i) {
214 m_working_buffer[i].assign(channels[i].begin(), channels[i].end());
215 func(std::span<double> { m_working_buffer[i] });
216 }
217 if (this->is_in_place())
218 for (size_t i = 0; i < channels.size(); ++i)
219 std::ranges::copy(m_working_buffer[i], channels[i].begin());
220 return create_output(
221 OperationHelper::reconstruct_from_double<InputType>(m_working_buffer, structure_info));
222 }
223
224 /**
225 * @brief Sets default parameter values for all mathematical operations
226 *
227 * Initializes all possible parameters with sensible defaults to ensure
228 * the transformer works correctly regardless of the selected operation.
229 */
231 {
232 this->set_parameter("gain_factor", 1.0);
233 this->set_parameter("offset_value", 0.0);
234 this->set_parameter("exponent", 2.0);
235 this->set_parameter("base", std::numbers::e);
236 this->set_parameter("scale", 1.0);
237 this->set_parameter("trig_function", std::string { "sin" });
238 this->set_parameter("frequency", 1.0);
239 this->set_parameter("amplitude", 1.0);
240 this->set_parameter("phase", 0.0);
241 this->set_parameter("bits", uint8_t { 16 });
242 this->set_parameter("target_peak", 1.0);
243 this->set_parameter("coefficients", std::vector<double> { 0.0, 1.0 });
244 this->set_parameter("input_scale", 1.0);
245 this->set_parameter("offset", 1.0);
246 this->set_parameter("rate", 1.0);
247 }
248
249 /**
250 * @brief Gets a parameter value with fallback to default
251 * @tparam T Parameter type
252 * @param name Parameter name
253 * @param default_value Default value if parameter not found or wrong type
254 * @return Parameter value or default
255 */
256 template <typename T>
257 T get_parameter_or(const std::string& name, const T& default_value) const
258 {
259 auto param = this->get_transformation_parameter(name);
260 if (!param.has_value())
261 return default_value;
262
263 auto result = safe_any_cast<T>(param);
264 return result.value_or(default_value);
265 }
266
267 /**
268 * @brief Creates output with proper type conversion
269 * @param data Input data to convert
270 * @return Output with converted data type
271 *
272 * Handles type conversion between InputType and OutputType when necessary,
273 * or direct assignment when types match.
274 */
276 {
277 if constexpr (std::is_same_v<InputType, OutputType>) {
278 return input;
279 } else {
280 auto [result_data, metadata] = OperationHelper::extract_structured_double(input);
281 return this->convert_result(result_data, metadata);
282 }
283 }
284};
285}
size_t a
size_t b
Discrete sequence transformation primitives for MayaFlux::Kinesis.
Float Processing Guidelines.
output_type create_output(const input_type &input)
Creates output with proper type conversion.
MathematicalTransformer(MathematicalOperation op=MathematicalOperation::GAIN)
Constructs a MathematicalTransformer with specified operation.
std::string get_transformer_name() const override
Gets the transformer name including the operation type.
TransformationType get_transformation_type() const override
Gets the transformation type.
void set_default_parameters()
Sets default parameter values for all mathematical operations.
void set_transformation_parameter(const std::string &name, std::any value) override
Sets transformation parameters.
T get_parameter_or(const std::string &name, const T &default_value) const
Gets a parameter value with fallback to default.
output_type transform_implementation(input_type &input) override
Core transformation implementation.
MathematicalOperation m_operation
Current mathematical operation.
std::vector< std::vector< double > > m_working_buffer
Buffer for out-of-place operations.
output_type apply_per_channel(input_type &input, Func &&func)
Extracts per-channel spans, applies an in-place func to each, and reconstructs.
Concrete transformer for mathematical operations.
Template-flexible transformer base with instance-defined I/O types.
@ POWER
Power (sum of squares)
MathematicalOperation
Specific mathematical operations supported.
@ GAIN
Linear gain/attenuation.
@ QUANTIZE
Quantization/bit reduction.
@ TRIGONOMETRIC
Trigonometric functions.
@ LOGARITHMIC
Logarithmic transform.
@ EXPONENTIAL
Exponential transform.
TransformationType
Categories of transformation operations for discovery and organization.
double peak(const std::vector< double > &data)
Find peak amplitude in single-channel data.
Definition Yantra.cpp:216
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:24