MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
OperationHelper.cpp
Go to the documentation of this file.
1#include "OperationHelper.hpp"
2
4
6
7namespace MayaFlux::Yantra {
8
9namespace detail {
10
12 Kakshya::DataModality modality,
13 std::type_index original_type)
14 {
15 switch (modality) {
21
24
27
30
33
34 default:
35 break;
36 }
37
38 if (original_type == std::type_index(typeid(std::vector<glm::vec2>))) {
40 }
41 if (original_type == std::type_index(typeid(std::vector<glm::vec3>))) {
43 }
44 if (original_type == std::type_index(typeid(std::vector<glm::vec4>))) {
46 }
47 if (original_type == std::type_index(typeid(std::vector<glm::mat4>))) {
49 }
50 if (original_type == std::type_index(typeid(std::vector<std::complex<double>>))
51 || original_type == std::type_index(typeid(std::vector<std::complex<float>>))) {
53 }
54
56 }
57
59 {
60 switch (interp) {
62 return 1;
65 return 2;
67 return 3;
69 return 4;
71 return 16;
73 return 1;
74 }
75 return 1;
76 }
77
78} // namespace detail
79
81 const std::vector<std::vector<double>>& columns,
82 const DataStructureInfo& structure_info)
83{
84 if (columns.empty()) {
85 return {};
86 }
87
88 if (structure_info.dimensions.size() >= 2) {
89 int expected_rows = static_cast<int>(structure_info.dimensions[0].size);
90 int expected_cols = static_cast<int>(structure_info.dimensions[1].size);
91
92 if (columns.size() != expected_cols) {
93 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
94 "Column count doesn't match dimension info. Expected {}, got {}", expected_cols, columns.size());
95 }
96 if (!columns.empty() && columns[0].size() != expected_rows) {
97 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
98 "Row count doesn't match dimension info. Expected {}, got {}", expected_rows, columns[0].size());
99 }
100
101 return create_eigen_matrix(columns);
102 }
103
104 return create_eigen_matrix(columns);
105}
106
108 const std::vector<std::span<const double>>& spans,
109 const DataStructureInfo& structure_info)
110{
111 if (spans.empty()) {
112 return {};
113 }
114
115 if (structure_info.dimensions.size() >= 2) {
116 int expected_rows = static_cast<int>(structure_info.dimensions[0].size);
117 int expected_cols = static_cast<int>(structure_info.dimensions[1].size);
118
119 if (spans.size() != expected_cols) {
120 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
121 "Column count doesn't match dimension info. Expected {}, got {}", expected_cols, spans.size());
122 }
123 if (!spans.empty() && spans[0].size() != expected_rows) {
124 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::Runtime, std::source_location::current(),
125 "Row count doesn't match dimension info. Expected {}, got {}", expected_rows, spans[0].size());
126 }
127 }
128
129 return create_eigen_matrix(spans);
130}
131
133 const DataStructureInfo& structure_info)
134{
135 if (double_data.empty()) {
136 return Kakshya::DataVariant { std::vector<double> {} };
137 }
138
140 structure_info.modality, structure_info.original_type);
141
143 if (structure_info.original_type == std::type_index(typeid(std::vector<float>))) {
144 std::vector<float> float_data;
145 float_data.reserve(double_data.size());
146 std::ranges::transform(double_data, std::back_inserter(float_data),
147 [](double v) { return static_cast<float>(v); });
148 return Kakshya::DataVariant { std::move(float_data) };
149 }
150
151 if (structure_info.original_type == std::type_index(typeid(std::vector<uint8_t>))) {
152 std::vector<uint8_t> u8_data;
153 u8_data.reserve(double_data.size());
154 std::ranges::transform(double_data, std::back_inserter(u8_data),
155 [](double v) { return static_cast<uint8_t>(std::clamp(v, 0.0, 255.0)); });
156 return Kakshya::DataVariant { std::move(u8_data) };
157 }
158
159 if (structure_info.original_type == std::type_index(typeid(std::vector<uint16_t>))) {
160 std::vector<uint16_t> u16_data;
161 u16_data.reserve(double_data.size());
162 std::ranges::transform(double_data, std::back_inserter(u16_data),
163 [](double v) { return static_cast<uint16_t>(std::clamp(v, 0.0, 65535.0)); });
164 return Kakshya::DataVariant { std::move(u16_data) };
165 }
166
167 if (structure_info.original_type == std::type_index(typeid(std::vector<uint32_t>))) {
168 std::vector<uint32_t> u32_data;
169 u32_data.reserve(double_data.size());
170 std::ranges::transform(double_data, std::back_inserter(u32_data),
171 [](double v) { return static_cast<uint32_t>(std::max(v, 0.0)); });
172 return Kakshya::DataVariant { std::move(u32_data) };
173 }
174
175 return Kakshya::DataVariant { double_data };
176 }
177
178 size_t rows = detail::interpretation_row_count(interp);
179
180 if (double_data.size() % rows != 0) {
181 return Kakshya::DataVariant { double_data };
182 }
183
184 /**
185 * interleave_channels (called before this function) produces
186 * sample-major layout: [x0,y0,z0, x1,y1,z1, ...].
187 * Eigen default storage is column-major. With rows=components
188 * and cols=elements, Eigen::Map reads column 0 as [x0,y0,z0],
189 * column 1 as [x1,y1,z1], which matches the interleaved order.
190 */
191 auto r = static_cast<Eigen::Index>(rows);
192 auto c = static_cast<Eigen::Index>(double_data.size() / rows);
193
194 Eigen::Map<const Eigen::MatrixXd> mapped(double_data.data(), r, c);
195
196 return Kakshya::from_eigen_matrix(mapped, interp);
197}
198
199} // namespace MayaFlux::Yantra
static Kakshya::DataVariant reconstruct_data_variant_from_double(const std::vector< double > &double_data, const DataStructureInfo &structure_info)
Reconstruct DataVariant from double data and structure info.
static Eigen::MatrixXd create_eigen_matrix(const std::vector< std::vector< T > > &columns)
Infer data structure from ComputeData type.
static Eigen::MatrixXd recreate_eigen_matrix(const std::vector< std::vector< double > > &columns, const DataStructureInfo &structure_info)
Infer data structure from ComputeData type.
@ Runtime
General runtime operations (default fallback)
@ Yantra
DSP algorithms, computational units, matrix operations, Grammar.
Kakshya::DataVariant from_eigen_matrix(const Eigen::MatrixXd &matrix, MatrixInterpretation interpretation=MatrixInterpretation::AUTO)
Convenience function for direct conversion.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:76
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:81
@ SPECTRAL_2D
2D spectral data (time + frequency)
MatrixInterpretation
How to interpret Eigen matrix rows/columns.
@ MAT4
16 rows → glm::mat4 (flattened)
@ SCALAR
Single row → scalar values.
@ COMPLEX
2 rows → complex (row 0 = real, row 1 = imag)
size_t interpretation_row_count(Kakshya::MatrixInterpretation interp)
Kakshya::MatrixInterpretation modality_to_interpretation(Kakshya::DataModality modality, std::type_index original_type)
std::vector< Kakshya::DataDimension > dimensions
Metadata about data structure for reconstruction.