MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
StandardSorter.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "UniversalSorter.hpp"
4
5/**
6 * @file StandardSorter.hpp
7 * @brief Example concrete implementation of UniversalSorter
8 *
9 * Demonstrates how to implement a concrete sorter that works with the modern
10 * concept-based architecture. This sorter handles standard comparison-based
11 * sorting for various data types.
12 */
13
14namespace MayaFlux::Yantra {
15
16/**
17 * @class StandardSorter
18 * @brief Concrete implementation for standard comparison-based sorting
19 *
20 * This sorter handles most common sorting scenarios using standard algorithms
21 * and comparators. It supports:
22 * - Numeric containers (vector<double>, vector<float>, etc.)
23 * - DataVariant sorting with type dispatch
24 * - Region-based sorting by coordinates/duration
25 * - Eigen matrix/vector sorting
26 * - Complex number sorting by magnitude
27 * - Multi-key sorting with configurable weights
28 */
29template <ComputeData InputType = Kakshya::DataVariant, ComputeData OutputType = InputType>
30class MAYAFLUX_API StandardSorter : public UniversalSorter<InputType, OutputType> {
31public:
35
36 /**
37 * @brief Constructor with default configuration
38 */
40 {
41 this->set_direction(SortingDirection::ASCENDING);
42 this->set_strategy(SortingStrategy::COPY_SORT);
43 this->set_granularity(SortingGranularity::RAW_DATA);
44 }
45
46 /**
47 * @brief Get sorting type category
48 */
49 [[nodiscard]] SortingType get_sorting_type() const override
50 {
51 return SortingType::STANDARD;
52 }
53
54 /**
55 * @brief Configure sorting algorithm
56 */
57 void set_algorithm(SortingAlgorithm algorithm) { m_algorithm = algorithm; }
58 [[nodiscard]] SortingAlgorithm get_algorithm() const { return m_algorithm; }
59
60protected:
61 /**
62 * @brief Get sorter name
63 */
64 [[nodiscard]] std::string get_sorter_name() const override
65 {
66 return "StandardSorter";
67 }
68
69 /**
70 * @brief Main sorting implementation with type dispatch
71 */
73 {
74 switch (this->get_strategy()) {
75 case SortingStrategy::IN_PLACE:
76 return sort_in_place(input);
77 case SortingStrategy::COPY_SORT:
78 return sort_copy(input);
79 case SortingStrategy::INDEX_ONLY:
80 return sort_indices_only(input);
81 case SortingStrategy::PARTIAL_SORT:
82 return sort_partial(input);
83 case SortingStrategy::CHUNKED_SORT:
84 return sort_chunked(input);
85 case SortingStrategy::PARALLEL_SORT:
86 return sort_parallel(input);
87 default:
88 return sort_copy(input);
89 }
90 }
91
92 /**
93 * @brief Input validation
94 */
95 bool validate_sorting_input(const input_type& input) const override
96 {
97 return validate_input_type(input.data);
98 }
99
100 /**
101 * @brief Custom parameter handling
102 */
103 void set_sorting_parameter(const std::string& name, std::any value) override
104 {
105 if (name == "algorithm") {
106 if (auto alg_result = safe_any_cast<SortingAlgorithm>(value)) {
107 m_algorithm = *alg_result.value;
108 return;
109 }
110 if (auto str_result = safe_any_cast<std::string>(value)) {
111 auto algorithm_enum = Reflect::string_to_enum_case_insensitive<SortingAlgorithm>(*str_result.value);
112 if (algorithm_enum) {
113 m_algorithm = *algorithm_enum;
114 return;
115 }
116 }
117 }
118 if (name == "chunk_size") {
119 if (auto size_result = safe_any_cast<size_t>(value)) {
120 m_chunk_size = *size_result.value;
121 return;
122 }
123 }
124 base_type::set_sorting_parameter(name, std::move(value));
125 }
126
127 [[nodiscard]] std::any get_sorting_parameter(const std::string& name) const override
128 {
129 if (name == "algorithm") {
130 return m_algorithm;
131 }
132 if (name == "chunk_size") {
133 return m_chunk_size;
134 }
135 return base_type::get_sorting_parameter(name);
136 }
137
138private:
139 SortingAlgorithm m_algorithm = SortingAlgorithm::STANDARD;
140 size_t m_chunk_size = 1024;
141
142 /**
143 * @brief Copy-based sorting (preserves input)
144 */
146 {
147 try {
148 std::vector<std::vector<double>> working_buffer;
149 auto [working_spans, structure_info] = OperationHelper::setup_operation_buffer(
150 const_cast<input_type&>(input), working_buffer);
151
152 Kinesis::Discrete::sort_channels(working_spans, this->get_direction(), m_algorithm);
153
154 output_type result = this->convert_result(working_buffer, structure_info);
155 result.metadata = input.metadata;
156 result.container = input.container;
157 result.metadata["sort_type"] = "copy";
158
159 return result;
160
161 } catch (const std::exception& e) {
162 output_type error_result;
163 error_result.metadata = input.metadata;
164 error_result.container = input.container;
165 error_result.metadata["error"] = std::string("Sorting failed: ") + e.what();
166 return error_result;
167 }
168 }
169
170 /**
171 * @brief In-place sorting (modifies input)
172 */
174 {
175 if constexpr (std::same_as<InputType, OutputType>) {
176 auto result = input;
177 sort_data_in_place(result);
178 return result;
179 } else {
180 return sort_copy(input);
181 }
182 }
183
184 /**
185 * @brief Generate sort indices only
186 */
188 {
189 if constexpr (std::same_as<OutputType, std::vector<size_t>>) {
190 auto result = output_type {};
191 result.data = generate_compute_data_indices(input, this->get_direction());
192 result.metadata = input.metadata;
193 result.metadata["sort_type"] = "indices_only";
194 return result;
195 } else {
196 // If output type is not vector<size_t>, fall back to copy sort
197 return sort_copy(input);
198 }
199 }
200
201 /**
202 * @brief Partial sorting (top-K elements)
203 */
205 {
206 auto result = input;
207 if constexpr (std::same_as<InputType, OutputType>) {
208 result.data = sort_data_partial(input);
209 return result;
210 } else {
211 return convert_and_sort(input);
212 }
213 }
214
215 /**
216 * @brief Parallel sorting
217 */
219 {
220 auto old_algorithm = m_algorithm;
221 m_algorithm = SortingAlgorithm::PARALLEL;
222 auto result = sort_copy(input);
223 m_algorithm = old_algorithm;
224 result.metadata["sort_type"] = "parallel";
225 return result;
226 }
227
228 // ===== Type-specific sorting implementations =====
229
230 /**
231 * @brief Sort data with copy semantics
232 */
233 InputType sort_data_copy(const input_type& data)
234 {
235 return sort_compute_data_extract(data, this->get_direction(), m_algorithm);
236 }
237
238 /**
239 * @brief Sort data in-place
240 */
242 {
243 sort_compute_data_inplace(data, this->get_direction(), m_algorithm);
244 }
245
246 /**
247 * @brief Partial sorting implementation
248 */
249 InputType sort_data_partial(const input_type& data)
250 {
251 auto old_algorithm = m_algorithm;
252 m_algorithm = SortingAlgorithm::PARTIAL;
253 auto result = sort_compute_data_extract(data, this->get_direction(), m_algorithm);
254 m_algorithm = old_algorithm;
255 return result;
256 }
257
258 std::vector<InputType> extract_chunked_data(std::vector<std::span<double>> channels, DataStructureInfo info)
259 {
260 std::vector<InputType> chunks;
261
262 for (size_t start = 0; start < channels[0].size(); start += m_chunk_size) {
263 std::vector<std::vector<double>> chunk_data;
264 chunk_data.resize(channels.size());
265
266 for (size_t ch = 0; ch < channels.size(); ++ch) {
267 size_t end = std::min(start + m_chunk_size, channels[ch].size());
268 auto chunk_span = channels[ch].subspan(start, end - start);
269
270 chunk_data[ch].assign(chunk_span.begin(), chunk_span.end());
271 Kinesis::Discrete::sort_span(std::span<double>(chunk_data[ch]), this->get_direction(), m_algorithm);
272 }
273
274 chunks.push_back(OperationHelper::reconstruct_from_double<InputType>(chunk_data, info));
275 }
276
277 return chunks;
278 }
279
280 /**
281 * @brief Chunked sorting implementation
282 */
284 {
285 try {
286 auto [data_span, structure_info] = OperationHelper::extract_structured_double(
287 const_cast<input_type&>(data));
288 return merge_chunks_to_result(extract_chunked_data(data_span, structure_info), data, structure_info);
289
290 } catch (...) {
291 return { sort_data_copy(data) };
292 }
293 }
294
295 /**
296 * @brief Merge chunks back to single result
297 */
298 output_type merge_chunks_to_result(const std::vector<InputType>& chunks, const input_type& original_input, DataStructureInfo info)
299 {
300 output_type result {};
301 result.metadata = original_input.metadata;
302 result.metadata["sort_type"] = "chunked_merged";
303
304 if constexpr (std::same_as<InputType, OutputType>) {
305 if (chunks.empty()) {
306 return result;
307 }
308
309 try {
310 std::vector<std::vector<double>> merged_channels;
311
312 for (const auto& chunk : chunks) {
313 auto chunk_channels = OperationHelper::extract_numeric_data(chunk);
314
315 if (merged_channels.empty()) {
316 merged_channels.resize(chunk_channels.size());
317 }
318
319 for (size_t ch = 0; ch < chunk_channels.size() && ch < merged_channels.size(); ++ch) {
320 merged_channels[ch].insert(merged_channels[ch].end(),
321 chunk_channels[ch].begin(), chunk_channels[ch].end());
322 }
323 }
324
325 result = this->convert_result(merged_channels, info);
326 result.metadata = original_input.metadata;
327 result.metadata["sort_type"] = "chunked_merged";
328
329 } catch (...) {
330 result.data = chunks[0];
331 }
332 }
333
334 return result;
335 }
336
337 /**
338 * @brief Handle type conversion scenarios
339 */
341 {
342 std::vector<std::vector<double>> working_buffer;
343 auto [working_spans, structure_info] = OperationHelper::setup_operation_buffer(
344 const_cast<input_type&>(input), working_buffer);
345
346 Kinesis::Discrete::sort_channels(working_spans, this->get_direction(), SortingAlgorithm::PARTIAL);
347 return this->convert_result(working_buffer, structure_info);
348 }
349
350 /**
351 * @brief Validate input type for sorting
352 */
353 bool validate_input_type(const input_type& data) const
354 {
355 if constexpr (RequiresContainer<InputType>) {
356 return data.has_container();
357 }
358 return true;
359 }
360};
361
362// ===== Convenience Specializations =====
363
364/// Standard sorter for DataVariant
366
367/// Standard sorter for numeric vectors (DataVariant contains these)
368template <typename T>
370
371/// Standard sorter for region groups (proper way to handle multiple regions)
373
374/// Standard sorter for region segments
376
377/// Standard sorter for Eigen matrices
379
380/// Standard sorter for Eigen vectors
382
383/// Standard sorter that generates indices
384template <ComputeData InputType = std::vector<Kakshya::DataVariant>>
386
387} // namespace MayaFlux::Yantra
Modern, digital-first universal sorting framework for Maya Flux.
void set_algorithm(SortingAlgorithm algorithm)
Configure sorting algorithm.
output_type sort_parallel(const input_type &input)
Parallel sorting.
output_type sort_indices_only(const input_type &input)
Generate sort indices only.
InputType sort_data_partial(const input_type &data)
Partial sorting implementation.
output_type sort_chunked(const input_type &data)
Chunked sorting implementation.
output_type sort_partial(const input_type &input)
Partial sorting (top-K elements)
StandardSorter()
Constructor with default configuration.
InputType sort_data_copy(const input_type &data)
Sort data with copy semantics.
output_type sort_implementation(const input_type &input) override
Main sorting implementation with type dispatch.
output_type sort_in_place(const input_type &input)
In-place sorting (modifies input)
typename base_type::input_type input_type
void set_sorting_parameter(const std::string &name, std::any value) override
Custom parameter handling.
std::any get_sorting_parameter(const std::string &name) const override
bool validate_sorting_input(const input_type &input) const override
Input validation.
output_type sort_copy(const input_type &input)
Copy-based sorting (preserves input)
SortingAlgorithm get_algorithm() const
bool validate_input_type(const input_type &data) const
Validate input type for sorting.
std::string get_sorter_name() const override
Get sorter name.
SortingType get_sorting_type() const override
Get sorting type category.
output_type merge_chunks_to_result(const std::vector< InputType > &chunks, const input_type &original_input, DataStructureInfo info)
Merge chunks back to single result.
void sort_data_in_place(input_type &data)
Sort data in-place.
output_type convert_and_sort(const input_type &input)
Handle type conversion scenarios.
std::vector< InputType > extract_chunked_data(std::vector< std::span< double > > channels, DataStructureInfo info)
typename base_type::output_type output_type
Concrete implementation for standard comparison-based sorting.
Template-flexible sorter base with instance-defined I/O types.
SortingAlgorithm
Available sorting algorithm backends.
Definition Sort.hpp:41
std::vector< std::vector< size_t > > generate_compute_data_indices(const Datum< T > &data, SortingDirection direction)
Generate sort indices for any ComputeData type.
SortingType
Categories of sorting operations for discovery and organization.
void sort_compute_data_inplace(Datum< T > &data, SortingDirection direction, SortingAlgorithm algorithm)
Universal sort function - handles extraction/conversion internally.
T sort_compute_data_extract(const T &data, SortingDirection direction, SortingAlgorithm algorithm)
Universal sort function - returns sorted copy.
Metadata about data structure for reconstruction.
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:24