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