7#include <glm/gtc/type_ptr.hpp>
23template <
typename From,
typename To,
typename Enable =
void>
25 static std::span<To>
convert(std::span<From> ,
29 static_assert(always_false_v<From>,
"No conversion available for these types");
38 static std::span<T>
convert(std::span<T> source,
48template <
typename From,
typename To>
52 ArithmeticData<From> && ArithmeticData<To> && !std::is_same_v<From, To> && !GlmType<From> && !GlmType<To>>> {
54 std::span<From> source,
60 source.begin(), source.end(),
storage.begin(),
61 [](From val) { return static_cast<To>(val); });
69template <
typename From,
typename To>
73 ComplexData<From> && ArithmeticData<To> && !GlmType<From> && !GlmType<To>>> {
75 std::span<From> source,
81 for (
size_t i = 0; i < source.size(); ++i) {
84 storage[i] =
static_cast<To
>(std::abs(source[i]));
87 storage[i] =
static_cast<To
>(source[i].real());
90 storage[i] =
static_cast<To
>(source[i].imag());
93 storage[i] =
static_cast<To
>(std::norm(source[i]));
104template <
typename From,
typename To>
108 ArithmeticData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To>>> {
110 std::span<From> source,
114 using ComplexValueType =
typename To::value_type;
117 for (
size_t i = 0; i < source.size(); ++i) {
118 storage[i] = To(
static_cast<ComplexValueType
>(source[i]), ComplexValueType { 0 });
127template <
typename From,
typename To>
131 GlmType<From> && ArithmeticData<To> && !GlmType<To>>> {
133 std::span<From> source,
137 constexpr size_t components = glm_component_count<From>();
138 using ComponentType = glm_component_type<From>;
140 storage.resize(source.size() * components);
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]);
156template <
typename From,
typename To>
160 ArithmeticData<From> && GlmType<To> && !GlmType<From>>> {
162 std::span<From> source,
166 constexpr size_t components = glm_component_count<To>();
167 using ComponentType = glm_component_type<To>;
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 ({})",
179 size_t element_count = source.size() / components;
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]);
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);
205template <
typename From,
typename To>
209 GlmType<From> && GlmType<To> && !std::is_same_v<From, To> && (glm_component_count<From>() == glm_component_count<To>())>> {
211 std::span<From> source,
215 using FromComponent = glm_component_type<From>;
216 using ToComponent = glm_component_type<To>;
217 constexpr size_t components = glm_component_count<From>();
221 for (
size_t i = 0; i < source.size(); ++i) {
222 const FromComponent* src_ptr = glm::value_ptr(source[i]);
223 ToComponent temp[components];
225 for (
size_t c = 0; c < components; ++c) {
226 temp[c] =
static_cast<ToComponent
>(src_ptr[c]);
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);
245template <
typename From,
typename To>
249 ComplexData<From> && ComplexData<To> && !GlmType<From> && !GlmType<To> && !std::is_same_v<From, To>>> {
251 std::span<From> source,
255 using FromValue =
typename From::value_type;
256 using ToValue =
typename To::value_type;
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));
296template <ProcessableData T>
297constexpr std::span<T>
extract_frame(std::span<T> data, uint64_t frame_index, uint64_t frame_size)
noexcept
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()));
303 if (start >= data.size()) {
307 return data.subspan(start, end - start);
318template <ProcessableData T>
320 const std::vector<std::span<T>>& channel_spans,
321 uint64_t frame_index,
322 std::vector<T>& output_buffer)
noexcept
324 output_buffer.clear();
325 output_buffer.reserve(channel_spans.size());
327 for (
const auto& channel_span : channel_spans) {
328 if (frame_index < channel_span.size()) {
329 output_buffer.push_back(channel_span[frame_index]);
331 output_buffer.push_back(T { 0 });
335 return std::span<T>(output_buffer.data(), output_buffer.size());
346template <
typename From,
typename To>
357template <
typename From,
typename To>
358 requires(ComplexData<From> && ArithmeticData<To>)
360 std::span<To> destination,
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());
375template <ProcessableData T>
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());
384 return std::visit([&variant, strategy](
auto& data) -> std::span<T> {
385 using ValueType =
typename std::decay_t<
decltype(data)>::value_type;
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);
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());
396 error<std::invalid_argument>(
399 std::source_location::current(),
400 "No conversion available from {} to {}",
401 typeid(ValueType).name(),
408template <ProcessableData T>
412 return convert_variant<T>(
const_cast<DataVariant&
>(variant), strategy);
415template <ProcessableData T>
417 const std::vector<DataVariant>& variants,
420 std::vector<std::span<T>> result;
421 result.reserve(variants.size());
423 for (
const auto& i : variants) {
424 result.push_back(convert_variant<T>(
const_cast<DataVariant&
>(i), strategy));
438template <ProcessableData From, ProcessableData To>
440 std::vector<To>& destination,
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);
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))) {
453 std::memcpy(destination.data(), source.data(), total_bytes);
454 return std::span<To>(destination.data(), source.size());
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());
470template <ProcessableData T>
475 return std::visit([&
storage, strategy](
const auto& data) -> std::span<T> {
476 using ValueType =
typename std::decay_t<
decltype(data)>::value_type;
478 if constexpr (std::is_same_v<ValueType, T>) {
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());
488 error<std::invalid_argument>(
491 std::source_location::current(),
492 "No conversion available from {} to {}",
493 typeid(ValueType).name(),
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;
514 if (pos >= data.size()) {
518 if constexpr (std::is_same_v<ValueType, T>) {
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]));
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());
578 return convert_variant<double>(data, strategy);
587void set_metadata_value(std::unordered_map<std::string, std::any>& metadata,
const std::string& key, std::any value);
597std::optional<T>
get_metadata_value(
const std::unordered_map<std::string, std::any>& metadata,
const std::string& key)
599 auto it = metadata.find(key);
600 if (it != metadata.end()) {
602 return safe_any_cast<T>(it->second);
603 }
catch (
const std::bad_any_cast&) {
@ 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.
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.
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.
std::type_index get_variant_type_index(const DataVariant &data)
Get type index from DataVariant.
int find_dimension_by_role(const std::vector< DataDimension > &dimensions, DataDimension::Role role)
Find the index of a dimension by its semantic role.
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).
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.
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.
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.
@ 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.
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)
static std::span< To > convert(std::span< From > source, std::vector< To > &storage, ComplexConversionStrategy strategy)
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)
static std::span< To > convert(std::span< From >, std::vector< To > &, ComplexConversionStrategy=ComplexConversionStrategy::MAGNITUDE)
Role
Semantic role of the dimension.