MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
SortingHelper.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <numeric>
4
6
7#include "UniversalSorter.hpp"
8
10
11/**
12 * @file SortingHelpers.hpp
13 * @brief Digital-first sorting utilities and algorithm implementations
14 *
15 * Provides concept-based sorting utilities that integrate with the modern UniversalSorter
16 * architecture. Unlike traditional sorting helpers, this focuses on digital paradigms:
17 * algorithmic sorting, multi-dimensional operations, and cross-modal capabilities.
18 *
19 * Following the same pattern as OperationHelper - standalone functions with templated
20 * implementations in header and non-templated ones in .cpp file.
21 */
22
23namespace MayaFlux::Yantra {
24
25/**
26 * @enum SortingAlgorithm
27 * @brief Available sorting algorithms for different use cases
28 */
29enum class SortingAlgorithm : uint8_t {
30 STANDARD, ///< std::sort with comparator
31 STABLE, ///< std::stable_sort for equal element preservation
32 PARTIAL, ///< std::partial_sort for top-K selection
33 NTH_ELEMENT, ///< std::nth_element for median/percentile
34 HEAP, ///< Heap sort for memory-constrained scenarios
35 PARALLEL, ///< Parallel sorting (std::execution::par_unseq)
36 RADIX, ///< Radix sort for integer types
37 COUNTING, ///< Counting sort for limited range integers
38 BUCKET, ///< Bucket sort for floating point
39 MERGE_EXTERNAL, ///< External merge sort for large datasets
40 QUICK_OPTIMIZED, ///< Optimized quicksort with hybrid pivot selection
41 // Future algorithms for coroutine integration
42 LAZY_STREAMING, ///< Lazy evaluation with coroutines (Vruta/Kriya)
43 PREDICTIVE_ML, ///< Machine learning based predictive sorting
44 EIGEN_OPTIMIZED, ///< Eigen-specific mathematical sorting
45 GPU_ACCELERATED ///< GPU-based sorting (future Vulkan integration)
46};
47
48/**
49 * @brief Sort a single span of doubles in-place
50 * @param data Span of data to sort
51 * @param direction Sort direction
52 * @param algorithm Sort algorithm
53 */
54void sort_span_inplace(std::span<double> data,
55 SortingDirection direction,
56 SortingAlgorithm algorithm);
57
58/**
59 * @brief Sort a single span and return copy in output vector
60 * @param data Input span to sort
61 * @param output_storage Output vector to store sorted data
62 * @param direction Sort direction
63 * @param algorithm Sort algorithm
64 * @return Span view of sorted data in output_storage
65 */
66std::span<double> sort_span_extract(std::span<const double> data,
67 std::vector<double>& output_storage,
68 SortingDirection direction,
69 SortingAlgorithm algorithm);
70
71/**
72 * @brief Sort multiple channels (spans) in-place
73 * @param channels Vector of spans, each representing a channel
74 * @param direction Sort direction
75 * @param algorithm Sort algorithm
76 */
77void sort_channels_inplace(std::vector<std::span<double>>& channels,
78 SortingDirection direction,
79 SortingAlgorithm algorithm);
80
81/**
82 * @brief Sort multiple channels and return copies
83 * @param channels Vector of input spans
84 * @param output_storage Vector of vectors to store sorted data per channel
85 * @param direction Sort direction
86 * @param algorithm Sort algorithm
87 * @return Vector of spans pointing to sorted data in output_storage
88 */
89std::vector<std::span<double>> sort_channels_extract(
90 const std::vector<std::span<const double>>& channels,
91 std::vector<std::vector<double>>& output_storage,
92 SortingDirection direction,
93 SortingAlgorithm algorithm);
94
95/**
96 * @brief Generate sort indices for a single span
97 * @param data Input span
98 * @param direction Sort direction
99 * @return Vector of sorted indices
100 */
101std::vector<size_t> generate_span_sort_indices(std::span<double> data,
102 SortingDirection direction);
103
104/**
105 * @brief Generate sort indices for multiple channels
106 * @param channels Vector of input spans
107 * @param direction Sort direction
108 * @return Vector of index vectors (one per channel)
109 */
110std::vector<std::vector<size_t>> generate_channels_sort_indices(
111 const std::vector<std::span<double>>& channels,
112 SortingDirection direction);
113
114// ============================================================================
115// ALGORITHM EXECUTION
116// ============================================================================
117
118/**
119 * @brief Execute sorting algorithm on iterator range
120 * @tparam Iterator Random access iterator type
121 * @tparam Comparator Comparison function type
122 * @param begin Start iterator
123 * @param end End iterator
124 * @param comp Comparator function
125 * @param algorithm Algorithm to use
126 */
127template <std::random_access_iterator Iterator, typename Comparator>
128void execute_sorting_algorithm(Iterator begin, Iterator end,
129 Comparator comp, SortingAlgorithm algorithm)
130{
131 switch (algorithm) {
133 std::ranges::sort(begin, end, comp);
134 break;
135
137 std::ranges::stable_sort(begin, end, comp);
138 break;
139
141 if (std::distance(begin, end) > 1) {
142 auto middle = begin + std::distance(begin, end) / 2;
143 std::partial_sort(begin, middle, end, comp);
144 }
145 break;
146 }
147
149 if (std::distance(begin, end) > 1) {
150 auto middle = begin + std::distance(begin, end) / 2;
151 std::nth_element(begin, middle, end, comp);
152 }
153 break;
154 }
155
157 std::make_heap(begin, end, comp);
158 std::sort_heap(begin, end, comp);
159 break;
160 }
161
163 MayaFlux::Parallel::sort(MayaFlux::Parallel::par_unseq, begin, end, comp);
164 break;
165
174 // TODO: Implement specialized algorithms
175 default:
176 std::ranges::sort(begin, end, comp);
177 break;
178 }
179}
180
181// ============================================================================
182// COMPARATOR CREATION
183// ============================================================================
184
185/**
186 * @brief Create standard direction-based comparator for doubles
187 * @param direction Sort direction (ASCENDING/DESCENDING)
188 * @return Lambda comparator function
189 */
191{
192 return [direction](double a, double b) -> bool {
193 return direction == SortingDirection::ASCENDING ? a < b : a > b;
194 };
195}
196
197/**
198 * @brief Create magnitude-based comparator for complex numbers
199 * @tparam T Complex number type (std::complex<float/double>)
200 * @param direction Sort direction
201 * @return Lambda comparator based on magnitude
202 */
203template <ComplexData T>
205{
206 return [direction](const T& a, const T& b) -> bool {
207 auto mag_a = std::abs(a);
208 auto mag_b = std::abs(b);
209 return direction == SortingDirection::ASCENDING ? mag_a < mag_b : mag_a > mag_b;
210 };
211}
212
213/**
214 * @brief Generate sort indices for any container with custom comparator
215 * @tparam Container Container type
216 * @tparam Comparator Comparison function type
217 * @param container Container to generate indices for
218 * @param comp Comparator function
219 * @return Vector of sorted indices
220 */
221template <typename Container, typename Comparator>
222std::vector<size_t> generate_sort_indices(const Container& container, Comparator comp)
223{
224 std::vector<size_t> indices(container.size());
225 std::iota(indices.begin(), indices.end(), 0);
226
227 std::ranges::sort(indices, [&](size_t a, size_t b) {
228 return comp(container[a], container[b]);
229 });
230
231 return indices;
232}
233
234// ============================================================================
235// UNIVERSAL COMPUTE DATA FUNCTIONS
236// ============================================================================
237
238/**
239 * @brief Universal sort function - handles extraction/conversion internally
240 * @tparam T ComputeData type
241 * @param data Data to sort (modified in-place)
242 * @param direction Sort direction
243 * @param algorithm Sort algorithm
244 */
245template <ComputeData T>
247 SortingDirection direction,
248 SortingAlgorithm algorithm)
249{
250 if constexpr (RequiresContainer<T>) {
251 if (!data.has_container()) {
252 throw std::runtime_error("Region-like types require container use UniversalSorter instead");
253 }
254 auto channels = OperationHelper::extract_numeric_data(data.data, data.container.value());
255 sort_channels_inplace(channels, direction, algorithm);
256 return;
257 }
258
259 auto channels = OperationHelper::extract_numeric_data(data.data, data.needs_processig());
260 sort_channels_inplace(channels, direction, algorithm);
261}
262
263/**
264 * @brief Universal sort function - returns sorted copy
265 * @tparam T ComputeData type
266 * @param data Data to sort (not modified)
267 * @param direction Sort direction
268 * @param algorithm Sort algorithm
269 * @return Sorted copy of the data
270 */
271template <ComputeData T>
273 SortingDirection direction,
274 SortingAlgorithm algorithm)
275{
276 if constexpr (RequiresContainer<T>) {
277 static_assert(std::is_same_v<T, void>,
278 "Region-like types require container parameter - use UniversalSorter instead");
279 return T {};
280 }
281
282 std::vector<std::vector<double>> working_buffer;
283 auto [working_spans, structure_info] = OperationHelper::setup_operation_buffer(
284 const_cast<T&>(data), working_buffer);
285
286 sort_channels_inplace(working_spans, direction, algorithm);
287
288 return OperationHelper::reconstruct_from_double<T>(working_buffer, structure_info);
289}
290
291/**
292 * @brief Universal sort function - returns sorted copy
293 * @tparam T ComputeData type
294 * @param data Data to sort (not modified)
295 * @param direction Sort direction
296 * @param algorithm Sort algorithm
297 * @return Sorted copy of the data
298 */
299template <typename T>
301 SortingDirection direction,
302 SortingAlgorithm algorithm)
303{
304 std::vector<std::vector<double>> working_buffer;
305 auto [working_spans, structure_info] = OperationHelper::setup_operation_buffer(
306 const_cast<IO<T>&>(data), working_buffer);
307
308 sort_channels_inplace(working_spans, direction, algorithm);
309
310 return OperationHelper::reconstruct_from_double<T>(working_buffer, structure_info);
311}
312
313/**
314 * @brief Convenience function with default algorithm
315 * @tparam T ComputeData type
316 * @param data Data to sort
317 * @param direction Sort direction
318 * @return Sorted copy of the data
319 */
320template <ComputeData T>
325
326/**
327 * @brief Generate sort indices for any ComputeData type
328 * @tparam T ComputeData type
329 * @param data Data to generate indices for
330 * @param direction Sort direction
331 * @return Vector of index vectors (one per channel)
332 */
333template <ComputeData T>
334std::vector<std::vector<size_t>> generate_compute_data_indices(const IO<T>& data,
335 SortingDirection direction)
336{
337 if constexpr (RequiresContainer<T>) {
338 auto channels = OperationHelper::extract_numeric_data(data.data, data.container.value());
339 return generate_channels_sort_indices(channels, direction);
340 }
341
342 if constexpr (SingleVariant<T>) {
343 auto channel = OperationHelper::extract_numeric_data(data.data);
344 return { generate_span_sort_indices({ channel }, direction) };
345 } else {
346 auto channels = OperationHelper::extract_numeric_data(data.data, data.needs_processig());
347 return generate_channels_sort_indices(channels, direction);
348 }
349}
350
351/**
352 * @brief Creates a multi-key comparator for complex sorting
353 * @tparam T Data type being sorted
354 * @param keys Vector of sort keys with extractors and weights
355 * @return Lambda comparator that applies all keys in order
356 */
357template <typename T>
358auto create_multi_key_comparator(const std::vector<SortKey>& keys)
359{
360 return [keys](const T& a, const T& b) -> bool {
361 for (const auto& key : keys) {
362 try {
363 double val_a = key.extractor(std::any(a));
364 double val_b = key.extractor(std::any(b));
365
366 if (key.normalize) {
367 val_a = std::tanh(val_a);
368 val_b = std::tanh(val_b);
369 }
370
371 double weighted_diff = key.weight * (val_a - val_b);
372 if (std::abs(weighted_diff) > 1e-9) {
373 return key.direction == SortingDirection::ASCENDING ? weighted_diff < 0 : weighted_diff > 0;
374 }
375 } catch (...) {
376 continue;
377 }
378 }
379 return false;
380 };
381}
382
383/**
384 * @brief Helper function to get temporal position from various types
385 * Used by TemporalSortable concept
386 */
387template <typename T>
388double get_temporal_position(const T& item)
389{
390 if constexpr (requires { item.start_coordinates; }) {
391 return !item.start_coordinates.empty() ? static_cast<double>(item.start_coordinates[0]) : 0.0;
392 } else if constexpr (requires { item.timestamp; }) {
393 return static_cast<double>(item.timestamp);
394 } else if constexpr (requires { item.time; }) {
395 return static_cast<double>(item.time);
396 } else {
397 static_assert(std::is_same_v<T, void>, "Type does not have temporal information");
398 return 0.0;
399 }
400}
401
402/**
403 * @brief Create universal sort key extractor for common data types
404 * @tparam T Data type to extract sort key from
405 * @param name Sort key name
406 * @param direction Sort direction (for the key metadata)
407 * @return SortKey with appropriate extractor
408 */
409template <typename T>
410SortKey create_universal_sort_key(const std::string& name,
412{
413 SortKey key(name, [](const std::any& data) -> double {
414 auto cast_result = safe_any_cast<T>(data);
415 if (!cast_result) {
416 return 0.0;
417 }
418
419 const T& value = *cast_result.value;
420
421 if constexpr (ArithmeticData<T>) {
422 return static_cast<double>(value);
423 } else if constexpr (ComplexData<T>) {
424 return std::abs(value);
425 } else if constexpr (requires { get_temporal_position(value); }) {
426 return get_temporal_position(value);
427 } else {
428 return 0.0;
429 }
430 });
431
432 key.direction = direction;
433 return key;
434}
435
436} // namespace MayaFlux::Yantra
Modern, digital-first universal sorting framework for Maya Flux.
static auto setup_operation_buffer(T &input, std::vector< std::vector< double > > &working_buffer)
Setup operation buffer from IO or ComputeData type.
static std::span< double > extract_numeric_data(const T &compute_data)
extract numeric data from single-variant types
A SingleVariant is either a single DataVariant, an Eigen vector type, or any type constructible from ...
Definition DataSpec.hpp:98
void execute_sorting_algorithm(Iterator begin, Iterator end, Comparator comp, SortingAlgorithm algorithm)
Execute sorting algorithm on iterator range.
std::vector< size_t > generate_span_sort_indices(std::span< double > data, SortingDirection direction)
Generate sort indices for a single span.
void sort_channels_inplace(std::vector< std::span< double > > &channels, SortingDirection direction, SortingAlgorithm algorithm)
Sort multiple channels (spans) in-place.
std::vector< std::vector< size_t > > generate_channels_sort_indices(const std::vector< std::span< double > > &channels, SortingDirection direction)
Generate sort indices for multiple channels.
T sort_compute_data(const T &data, SortingDirection direction=SortingDirection::ASCENDING)
Convenience function with default algorithm.
std::vector< std::vector< size_t > > generate_compute_data_indices(const IO< T > &data, SortingDirection direction)
Generate sort indices for any ComputeData type.
std::vector< size_t > generate_sort_indices(const Container &container, Comparator comp)
Generate sort indices for any container with custom comparator.
void sort_span_inplace(std::span< double > data, SortingDirection direction, SortingAlgorithm algorithm)
Sort a single span of doubles in-place.
double get_temporal_position(const T &item)
Helper function to get temporal position from various types Used by TemporalSortable concept.
auto create_double_comparator(SortingDirection direction)
Create standard direction-based comparator for doubles.
SortKey create_universal_sort_key(const std::string &name, SortingDirection direction=SortingDirection::ASCENDING)
Create universal sort key extractor for common data types.
auto create_complex_magnitude_comparator(SortingDirection direction)
Create magnitude-based comparator for complex numbers.
SortingDirection
Basic sort direction for simple comparisons.
@ ASCENDING
Smallest to largest.
SortingAlgorithm
Available sorting algorithms for different use cases.
@ QUICK_OPTIMIZED
Optimized quicksort with hybrid pivot selection.
@ STABLE
std::stable_sort for equal element preservation
@ GPU_ACCELERATED
GPU-based sorting (future Vulkan integration)
@ EIGEN_OPTIMIZED
Eigen-specific mathematical sorting.
@ RADIX
Radix sort for integer types.
@ STANDARD
std::sort with comparator
@ COUNTING
Counting sort for limited range integers.
@ LAZY_STREAMING
Lazy evaluation with coroutines (Vruta/Kriya)
@ HEAP
Heap sort for memory-constrained scenarios.
@ MERGE_EXTERNAL
External merge sort for large datasets.
@ NTH_ELEMENT
std::nth_element for median/percentile
@ PREDICTIVE_ML
Machine learning based predictive sorting.
@ PARALLEL
Parallel sorting (std::execution::par_unseq)
@ BUCKET
Bucket sort for floating point.
@ PARTIAL
std::partial_sort for top-K selection
@ PARALLEL
Parallel with other operations.
std::vector< std::span< double > > sort_channels_extract(const std::vector< std::span< const double > > &channels, std::vector< std::vector< double > > &output_storage, SortingDirection direction, SortingAlgorithm algorithm)
Sort multiple channels and return copies.
std::span< double > sort_span_extract(std::span< const double > data, std::vector< double > &output_storage, SortingDirection direction, SortingAlgorithm algorithm)
Sort a single span and return copy in output vector.
T sort_compute_data_extract(const T &data, SortingDirection direction, SortingAlgorithm algorithm)
Universal sort function - returns sorted copy.
auto create_multi_key_comparator(const std::vector< SortKey > &keys)
Creates a multi-key comparator for complex sorting.
void sort_compute_data_inplace(IO< T > &data, SortingDirection direction, SortingAlgorithm algorithm)
Universal sort function - handles extraction/conversion internally.
bool has_container() const
Check if a container reference is associated.
Definition DataIO.hpp:155
bool needs_processig() const
Check if processing is needed (for container types)
Definition DataIO.hpp:164
T data
The actual computation data.
Definition DataIO.hpp:25
std::optional< std::shared_ptr< Kakshya::SignalSourceContainer > > container
Optional reference to container, required for regions.
Definition DataIO.hpp:31
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:24
Multi-dimensional sort key specification for complex sorting.