MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataUtils.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
7#include <glm/gtc/type_ptr.hpp>
8#include <typeindex>
9
10namespace MayaFlux::Kakshya {
11
12/**
13 * @enum ComplexConversionStrategy
14 * @brief Strategy for converting complex numbers to real values
15 */
16enum class ComplexConversionStrategy : uint8_t {
17 MAGNITUDE, ///< |z| = sqrt(real² + imag²)
18 REAL_PART, ///< z.real()
19 IMAG_PART, ///< z.imag()
20 SQUARED_MAGNITUDE ///< |z|² = real² + imag²
21};
22
23template <typename From, typename To, typename Enable = void>
25 static std::span<To> convert(std::span<From> /*source*/,
26 std::vector<To>& /*storage*/,
28 {
29 static_assert(always_false_v<From>, "No conversion available for these types");
30 return {};
31 }
32};
33
34// === Specialization: Identity Conversion ===
35
36template <typename T>
37struct DataConverter<T, T> {
38 static std::span<T> convert(std::span<T> source,
39 std::vector<T>&,
41 {
42 return source;
43 }
44};
45
46// === Specialization: Arithmetic to Arithmetic (excluding GLM) ===
47
48template <typename From, typename To>
50 From, To,
51 std::enable_if_t<
52 ArithmeticData<From> && ArithmeticData<To> && !std::is_same_v<From, To> && !GlmType<From> && !GlmType<To>>> {
53 static std::span<To> convert(
54 std::span<From> source,
55 std::vector<To>& storage,
57 {
58 storage.resize(source.size());
59 std::transform(
60 source.begin(), source.end(), storage.begin(),
61 [](From val) { return static_cast<To>(val); });
62
63 return std::span<To>(storage.data(), storage.size());
64 }
65};
66
67// === Specialization: Complex to Arithmetic ===
68
69template <typename From, typename To>
71 From, To,
72 std::enable_if_t<
73 ComplexData<From> && ArithmeticData<To> && !GlmType<From> && !GlmType<To>>> {
74 static std::span<To> convert(
75 std::span<From> source,
76 std::vector<To>& storage,
78 {
79 storage.resize(source.size());
80
81 for (size_t i = 0; i < source.size(); ++i) {
82 switch (strategy) {
84 storage[i] = static_cast<To>(std::abs(source[i]));
85 break;
87 storage[i] = static_cast<To>(source[i].real());
88 break;
90 storage[i] = static_cast<To>(source[i].imag());
91 break;
93 storage[i] = static_cast<To>(std::norm(source[i]));
94 break;
95 }
96 }
97
98 return std::span<To>(storage.data(), storage.size());
99 }
100};
101
102// === Specialization: Arithmetic to Complex ===
103
104template <typename From, typename To>
106 From, To,
107 std::enable_if_t<
108 ArithmeticData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To>>> {
109 static std::span<To> convert(
110 std::span<From> source,
111 std::vector<To>& storage,
113 {
114 using ComplexValueType = typename To::value_type;
115 storage.resize(source.size());
116
117 for (size_t i = 0; i < source.size(); ++i) {
118 storage[i] = To(static_cast<ComplexValueType>(source[i]), ComplexValueType { 0 });
119 }
120
121 return std::span<To>(storage.data(), storage.size());
122 }
123};
124
125// === Specialization: GLM to Arithmetic (Flattening) ===
126
127template <typename From, typename To>
129 From, To,
130 std::enable_if_t<
131 GlmType<From> && ArithmeticData<To> && !GlmType<To>>> {
132 static std::span<To> convert(
133 std::span<From> source,
134 std::vector<To>& storage,
136 {
137 constexpr size_t components = glm_component_count<From>();
138 using ComponentType = glm_component_type<From>;
139
140 storage.resize(source.size() * components);
141
142 size_t out_idx = 0;
143 for (const auto& elem : source) {
144 const ComponentType* ptr = glm::value_ptr(elem);
145 for (size_t c = 0; c < components; ++c) {
146 storage[out_idx++] = static_cast<To>(ptr[c]);
147 }
148 }
149
150 return std::span<To>(storage.data(), storage.size());
151 }
152};
153
154// === Specialization: Arithmetic to GLM (Structuring) ===
155
156template <typename From, typename To>
158 From, To,
159 std::enable_if_t<
160 ArithmeticData<From> && GlmType<To> && !GlmType<From>>> {
161 static std::span<To> convert(
162 std::span<From> source,
163 std::vector<To>& storage,
165 {
166 constexpr size_t components = glm_component_count<To>();
167 using ComponentType = glm_component_type<To>;
168
169 if (source.size() % components != 0) {
170 error<std::invalid_argument>(
173 std::source_location::current(),
174 "Source size ({}) must be multiple of GLM component count ({})",
175 source.size(),
176 components);
177 }
178
179 size_t element_count = source.size() / components;
180 storage.resize(element_count);
181
182 for (size_t i = 0; i < element_count; ++i) {
183 ComponentType temp[components];
184 for (size_t c = 0; c < components; ++c) {
185 temp[c] = static_cast<ComponentType>(source[i * components + c]);
186 }
187
188 if constexpr (GlmVec2Type<To>) {
189 storage[i] = To(temp[0], temp[1]);
190 } else if constexpr (GlmVec3Type<To>) {
191 storage[i] = To(temp[0], temp[1], temp[2]);
192 } else if constexpr (GlmVec4Type<To>) {
193 storage[i] = To(temp[0], temp[1], temp[2], temp[3]);
194 } else if constexpr (GlmMatrixType<To>) {
195 storage[i] = glm::make_mat4(temp);
196 }
197 }
198
199 return std::span<To>(storage.data(), storage.size());
200 }
201};
202
203// === Specialization: GLM to GLM (same component count) ===
204
205template <typename From, typename To>
207 From, To,
208 std::enable_if_t<
209 GlmType<From> && GlmType<To> && !std::is_same_v<From, To> && (glm_component_count<From>() == glm_component_count<To>())>> {
210 static std::span<To> convert(
211 std::span<From> source,
212 std::vector<To>& storage,
214 {
215 using FromComponent = glm_component_type<From>;
216 using ToComponent = glm_component_type<To>;
217 constexpr size_t components = glm_component_count<From>();
218
219 storage.resize(source.size());
220
221 for (size_t i = 0; i < source.size(); ++i) {
222 const FromComponent* src_ptr = glm::value_ptr(source[i]);
223 ToComponent temp[components];
224
225 for (size_t c = 0; c < components; ++c) {
226 temp[c] = static_cast<ToComponent>(src_ptr[c]);
227 }
228
229 if constexpr (GlmVec2Type<To>) {
230 storage[i] = To(temp[0], temp[1]);
231 } else if constexpr (GlmVec3Type<To>) {
232 storage[i] = To(temp[0], temp[1], temp[2]);
233 } else if constexpr (GlmVec4Type<To>) {
234 storage[i] = To(temp[0], temp[1], temp[2], temp[3]);
235 } else if constexpr (GlmMatrixType<To>) {
236 storage[i] = glm::make_mat4(temp);
237 }
238 }
239
240 return std::span<To>(storage.data(), storage.size());
241 }
242};
243
244// === Specialization: Complex -> Complex ===
245template <typename From, typename To>
247 From, To,
248 std::enable_if_t<
249 ComplexData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To> && !std::is_same_v<From, To>>> {
250 static std::span<To> convert(
251 std::span<From> source,
252 std::vector<To>& storage,
254 {
255 using FromValue = typename From::value_type;
256 using ToValue = typename To::value_type;
257
258 storage.resize(source.size());
259 for (size_t i = 0; i < source.size(); ++i) {
260 const auto r = static_cast<FromValue>(source[i].real());
261 const auto im = static_cast<FromValue>(source[i].imag());
262 storage[i] = To(static_cast<ToValue>(r), static_cast<ToValue>(im));
263 }
264
265 return std::span<To>(storage.data(), storage.size());
266 }
267};
268
269/**
270 * @brief Calculate the total number of elements in an N-dimensional container.
271 * @param dimensions Dimension descriptors.
272 * @return Product of all dimension sizes.
273 */
274uint64_t calculate_total_elements(const std::vector<DataDimension>& dimensions);
275
276/**
277 * @brief Calculate the frame size (number of elements per frame) for a set of dimensions.
278 * @param dimensions Dimension descriptors.
279 * @return Frame size (product of all but the first dimension).
280 */
281uint64_t calculate_frame_size(const std::vector<DataDimension>& dimensions);
282
283/**
284 * @brief Get type index from DataVariant
285 */
286std::type_index get_variant_type_index(const DataVariant& data);
287
288/**
289 * @brief Extract a single frame of data from a span.
290 * @tparam T Data type.
291 * @param data Source data span.
292 * @param frame_index Index of the frame to extract.
293 * @param frame_size Number of elements per frame.
294 * @return Span containing the frame data.
295 */
296template <ProcessableData T>
297constexpr std::span<T> extract_frame(std::span<T> data, uint64_t frame_index, uint64_t frame_size) noexcept
298{
299 uint64_t start = frame_index * frame_size;
300 uint64_t end = std::min(static_cast<uint64_t>(start + frame_size),
301 static_cast<uint64_t>(data.size()));
302
303 if (start >= data.size()) {
304 return {};
305 }
306
307 return data.subspan(start, end - start);
308}
309
310/**
311 * @brief Extract a single frame from planar data (returns interleaved).
312 * @tparam T Data type.
313 * @param channel_spans Vector of spans, one per channel.
314 * @param frame_index Index of the frame to extract.
315 * @param output_buffer Buffer to store interleaved frame data.
316 * @return Span containing the interleaved frame data.
317 */
318template <ProcessableData T>
319std::span<T> extract_frame(
320 const std::vector<std::span<T>>& channel_spans,
321 uint64_t frame_index,
322 std::vector<T>& output_buffer) noexcept
323{
324 output_buffer.clear();
325 output_buffer.reserve(channel_spans.size());
326
327 for (const auto& channel_span : channel_spans) {
328 if (frame_index < channel_span.size()) {
329 output_buffer.push_back(channel_span[frame_index]);
330 } else {
331 output_buffer.push_back(T { 0 });
332 }
333 }
334
335 return std::span<T>(output_buffer.data(), output_buffer.size());
336}
337
338/**
339 * @brief Convert a span of one data type to another (with type conversion).
340 * @tparam From Source type.
341 * @tparam To Destination type.
342 * @param source Source data span.
343 * @param dest Destination data span.
344 * @return Span of converted data.
345 */
346template <typename From, typename To>
347std::span<To> convert_data(std::span<From> source,
348 std::vector<To>& storage,
350{
351 return DataConverter<From, To>::convert(source, storage, strategy);
352}
353
354/**
355 * @brief Legacy interface - redirects to convert_data
356 */
357template <typename From, typename To>
358 requires(ComplexData<From> && ArithmeticData<To>)
359void convert_complex(std::span<From> source,
360 std::span<To> destination,
362{
363 std::vector<To> temp_storage;
364 auto result = convert_data(source, temp_storage, strategy);
365 std::copy_n(result.begin(), std::min(result.size(), destination.size()), destination.begin());
366}
367
368/**
369 * @brief Get const span from DataVariant without conversion (zero-copy for matching types)
370 * @tparam T Data type (must match DataVariant contents)
371 * @param variant DataVariant to extract from
372 * @return Const span of type T
373 * @throws std::runtime_error if type doesn't match
374 */
375template <ProcessableData T>
376std::span<T> convert_variant(DataVariant& variant,
378{
379 if (std::holds_alternative<std::vector<T>>(variant)) {
380 auto& vec = std::get<std::vector<T>>(variant);
381 return std::span<T>(vec.data(), vec.size());
382 }
383
384 return std::visit([&variant, strategy](auto& data) -> std::span<T> {
385 using ValueType = typename std::decay_t<decltype(data)>::value_type;
386
387 if constexpr (is_convertible_data_v<ValueType, T>) {
388 std::vector<T> new_storage;
389 auto source_span = std::span<ValueType>(data.data(), data.size());
390 auto result = convert_data(source_span, new_storage, strategy);
391
392 variant = std::move(new_storage);
393 auto& new_vec = std::get<std::vector<T>>(variant);
394 return std::span<T>(new_vec.data(), new_vec.size());
395 } else {
396 error<std::invalid_argument>(
399 std::source_location::current(),
400 "No conversion available from {} to {}",
401 typeid(ValueType).name(),
402 typeid(T).name());
403 }
404 },
405 variant);
406}
407
408template <ProcessableData T>
409std::span<T> convert_variant(const DataVariant& variant,
411{
412 return convert_variant<T>(const_cast<DataVariant&>(variant), strategy);
413}
414
415template <ProcessableData T>
416std::vector<std::span<T>> convert_variants(
417 const std::vector<DataVariant>& variants,
419{
420 std::vector<std::span<T>> result;
421 result.reserve(variants.size());
422
423 for (const auto& i : variants) {
424 result.push_back(convert_variant<T>(const_cast<DataVariant&>(i), strategy));
425 }
426 return result;
427}
428
429/**
430 * @brief Concept-based data extraction with type conversion
431 * @tparam T Target type (must satisfy ProcessableData)
432 * @param variant Source DataVariant (may be modified for conversion)
433 * @return Span of converted data
434 *
435 * Performance advantage: Eliminates runtime type dispatch for supported types
436 * Uses constexpr branching for compile-time optimization
437 */
438template <ProcessableData From, ProcessableData To>
439std::span<To> extract_data(std::span<const From> source,
440 std::vector<To>& destination,
442{
443 const size_t total_bytes = source.size() * sizeof(From);
444 const size_t required_elements = (total_bytes + sizeof(To) - 1) / sizeof(To);
445 destination.resize(required_elements);
446
447 if constexpr (std::is_same_v<From, To>) {
448 destination.resize(source.size());
449 std::memcpy(destination.data(), source.data(), total_bytes);
450 return std::span<To>(destination.data(), source.size());
451 } else if constexpr (std::is_trivially_copyable_v<From> && std::is_trivially_copyable_v<To> && (sizeof(From) == sizeof(To))) {
452 // Bitwise reinterpretation allowed (e.g. int32_t <-> float)
453 std::memcpy(destination.data(), source.data(), total_bytes);
454 return std::span<To>(destination.data(), source.size());
455 } else {
456 // General case — use proper conversion
457 std::vector<From> temp(source.begin(), source.end());
458 auto converted = convert_data<From, To>(std::span<const From>(temp), strategy);
459 destination.assign(converted.begin(), converted.end());
460 return std::span<To>(destination.data(), destination.size());
461 }
462}
463
464/**
465 * @brief Get typed span from DataVariant using concepts
466 * @tparam T Data type (must satisfy ProcessableData)
467 * @param variant DataVariant to extract from
468 * @return Span of type T, or empty span if type doesn't match
469 */
470template <ProcessableData T>
471std::span<T> extract_from_variant(const DataVariant& variant,
472 std::vector<T>& storage,
474{
475 return std::visit([&storage, strategy](const auto& data) -> std::span<T> {
476 using ValueType = typename std::decay_t<decltype(data)>::value_type;
477
478 if constexpr (std::is_same_v<ValueType, T>) {
479 storage = data;
480 return std::span<T>(storage.data(), storage.size());
481 } else if constexpr (is_convertible_data_v<ValueType, T>) {
482 auto source_span = std::span<const ValueType>(data.data(), data.size());
483 std::vector<ValueType> temp_source(source_span.begin(), source_span.end());
484 auto temp_span = std::span<ValueType>(temp_source.data(), temp_source.size());
485 return convert_data(temp_span, storage, strategy);
486 } else {
487 // throw std::runtime_error("Cannot convert from " + std::string(typeid(ValueType).name()) + " to " + std::string(typeid(T).name()));
488 error<std::invalid_argument>(
491 std::source_location::current(),
492 "No conversion available from {} to {}",
493 typeid(ValueType).name(),
494 typeid(T).name());
495 }
496 },
497 variant);
498}
499
500/**
501 * @brief Extract a value of type T from a DataVariant at a specific position.
502 * @tparam T Desired type.
503 * @param variant DataVariant to extract from.
504 * @param pos Position in the data.
505 * @return Optional value of type T.
506 */
507template <typename T>
508std::optional<T> extract_from_variant_at(const DataVariant& variant, uint64_t pos)
509{
510 return std::visit([pos](const auto& data) -> std::optional<T> {
511 using DataType = std::decay_t<decltype(data)>;
512 using ValueType = typename DataType::value_type;
513
514 if (pos >= data.size()) {
515 return std::nullopt;
516 }
517
518 if constexpr (std::is_same_v<ValueType, T>) {
519 return data[pos];
520 } else if constexpr (std::is_arithmetic_v<ValueType> && std::is_arithmetic_v<T>) {
521 return static_cast<T>(data[pos]);
522 } else if constexpr (std::is_same_v<ValueType, std::complex<float>> || std::is_same_v<ValueType, std::complex<double>>) {
523 if constexpr (std::is_arithmetic_v<T>) {
524 return static_cast<T>(std::abs(data[pos]));
525 } else {
526 return std::nullopt;
527 }
528 } else {
529 return std::nullopt;
530 }
531 },
532 variant);
533}
534
535/**
536 * @brief Safely copy data from a DataVariant to another DataVariant, handling type conversion.
537 * @param input Source DataVariant.
538 * @param output Destination DataVariant.
539 */
540void safe_copy_data_variant(const DataVariant& input, DataVariant& output);
541
542/**
543 * @brief Safely copy data from a DataVariant to a span of doubles.
544 * @param input Source DataVariant.
545 * @param output Destination span of doubles.
546 * @throws std::runtime_error if complex types are involved.
547 */
548inline std::span<const double> safe_copy_data_variant_to_span(const DataVariant& input, std::vector<double>& output)
549{
550 return extract_from_variant(input, output);
551}
552
553/**
554 * @brief Safely copy data from a DataVariant to another DataVariant of a specific type.
555 * @tparam T Data type.
556 * @param input Source DataVariant.
557 * @param output Destination DataVariant.
558 */
559template <typename T>
561{
562 std::vector<T> temp_storage;
563 auto input_span = extract_from_variant<T>(input, temp_storage);
564 auto output_span = get_typed_data<T>(output);
565 std::copy_n(input_span.begin(), std::min(input_span.size(), output_span.size()),
566 output_span.begin());
567}
568
569/**
570 * @brief Convert variant to double span
571 * @param data Source DataVariant (may be modified for conversion)
572 * @param strategy Conversion strategy for complex numbers
573 * @return Span of double data
574 */
575inline std::span<double> convert_variant_to_double(DataVariant& data,
577{
578 return convert_variant<double>(data, strategy);
579}
580
581/**
582 * @brief Set a value in a metadata map (key-value).
583 * @param metadata Metadata map.
584 * @param key Key to set.
585 * @param value Value to set.
586 */
587void set_metadata_value(std::unordered_map<std::string, std::any>& metadata, const std::string& key, std::any value);
588
589/**
590 * @brief Get a value from a metadata map by key.
591 * @tparam T Expected type.
592 * @param metadata Metadata map.
593 * @param key Key to retrieve.
594 * @return Optional value if present and convertible.
595 */
596template <typename T>
597std::optional<T> get_metadata_value(const std::unordered_map<std::string, std::any>& metadata, const std::string& key)
598{
599 auto it = metadata.find(key);
600 if (it != metadata.end()) {
601 try {
602 return safe_any_cast<T>(it->second);
603 } catch (const std::bad_any_cast&) {
604 return std::nullopt;
605 }
606 }
607 return std::nullopt;
608}
609
610/**
611 * @brief Find the index of a dimension by its semantic role.
612 * @param dimensions Dimension descriptors.
613 * @param role Semantic role to search for.
614 * @return Index of the dimension, or -1 if not found.
615 */
616int find_dimension_by_role(const std::vector<DataDimension>& dimensions, DataDimension::Role role);
617
618/**
619 * @brief Detects data modality from dimension information
620 * @param dimensions Vector of data dimensions with role information
621 * @return Detected DataModality type
622 *
623 * Consolidates modality detection logic that was duplicated across analyzers.
624 * Uses dimension roles and count to determine appropriate processing approach.
625 */
626DataModality detect_data_modality(const std::vector<DataDimension>& dimensions);
627
628/**
629 * @brief Detect data dimensions from a DataVariant
630 * @param data DataVariant to analyze
631 * @return Vector of DataDimension descriptors
632 *
633 * This function analyzes the structure of the provided DataVariant and extracts
634 * dimension information, including size, stride, and semantic roles.
635 */
636std::vector<Kakshya::DataDimension> detect_data_dimensions(const DataVariant& data);
637
638/**
639 * @brief Detect data dimensions from a vector of DataVariants
640 * @param variants Vector of DataVariants to analyze
641 * @return Vector of DataDimension descriptors
642 *
643 * This function analyzes the structure of the provided vector of DataVariants and extracts
644 * dimension information, including size, stride, and semantic roles.
645 *
646 * WARNING: This method makes naive assumptions about the data structure and may lead to incorrect interpretations.
647 * It is recommended to use more specific methods when dealing with known containers, regions, or segments.
648 * Use this function only when absolutely necessary and be aware of potential computational errors.
649 */
650std::vector<Kakshya::DataDimension> detect_data_dimensions(const std::vector<Kakshya::DataVariant>& variants);
651}
Eigen::MatrixXd storage
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
std::optional< T > extract_from_variant_at(const DataVariant &variant, uint64_t pos)
Extract a value of type T from a DataVariant at a specific position.
std::vector< DataDimension > detect_data_dimensions(const DataVariant &data)
Detect data dimensions from a DataVariant.
std::span< T > extract_from_variant(const DataVariant &variant, std::vector< T > &storage, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Get typed span from DataVariant using concepts.
uint64_t calculate_frame_size(const std::vector< DataDimension > &dimensions)
Calculate the frame size (number of elements per frame) for a set of dimensions.
Definition DataUtils.cpp:15
constexpr std::span< T > extract_frame(std::span< T > data, uint64_t frame_index, uint64_t frame_size) noexcept
Extract a single frame of data from a span.
std::span< To > extract_data(std::span< const From > source, std::vector< To > &destination, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Concept-based data extraction with type 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:73
std::span< double > convert_variant_to_double(DataVariant &data, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Convert variant to double span.
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:78
std::type_index get_variant_type_index(const DataVariant &data)
Get type index from DataVariant.
Definition DataUtils.cpp:26
int find_dimension_by_role(const std::vector< DataDimension > &dimensions, DataDimension::Role role)
Find the index of a dimension by its semantic role.
Definition DataUtils.cpp:64
std::span< const double > safe_copy_data_variant_to_span(const DataVariant &input, std::vector< double > &output)
Safely copy data from a DataVariant to a span of doubles.
void set_metadata_value(std::unordered_map< std::string, std::any > &metadata, const std::string &key, std::any value)
Set a value in a metadata map (key-value).
Definition DataUtils.cpp:59
void convert_complex(std::span< From > source, std::span< To > destination, ComplexConversionStrategy strategy)
Legacy interface - redirects to convert_data.
DataModality detect_data_modality(const std::vector< DataDimension > &dimensions)
Detects data modality from dimension information.
Definition DataUtils.cpp:72
void safe_copy_typed_variant(const DataVariant &input, DataVariant &output)
Safely copy data from a DataVariant to another DataVariant of a specific type.
void safe_copy_data_variant(const DataVariant &input, DataVariant &output)
Safely copy data from a DataVariant to another DataVariant, handling type conversion.
Definition DataUtils.cpp:34
std::span< To > convert_data(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Convert a span of one data type to another (with type conversion).
ComplexConversionStrategy
Strategy for converting complex numbers to real values.
Definition DataUtils.hpp:16
@ SQUARED_MAGNITUDE
|z|² = real² + imag²
@ MAGNITUDE
|z| = sqrt(real² + imag²)
std::span< T > convert_variant(DataVariant &variant, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
Get const span from DataVariant without conversion (zero-copy for matching types)
uint64_t calculate_total_elements(const std::vector< DataDimension > &dimensions)
Calculate the total number of elements in an N-dimensional container.
Definition DataUtils.cpp:5
std::optional< T > get_metadata_value(const std::unordered_map< std::string, std::any > &metadata, const std::string &key)
Get a value from a metadata map by key.
std::vector< std::span< T > > convert_variants(const std::vector< DataVariant > &variants, ComplexConversionStrategy strategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
Definition DataUtils.hpp:53
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy strategy)
Definition DataUtils.hpp:74
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
static std::span< T > convert(std::span< T > source, std::vector< T > &, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
Definition DataUtils.hpp:38
static std::span< To > convert(std::span< From >, std::vector< To > &, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
Definition DataUtils.hpp:25
Role
Semantic role of the dimension.
Definition NDData.hpp:146