1//! @file apply_algorithm.cpp
2//! @author ryftchen
3//! @brief The definitions (apply_algorithm) in the application module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2025 ryftchen. All rights reserved.
6
7#include "apply_algorithm.hpp"
8#include "register_algorithm.hpp"
9
10#ifndef _PRECOMPILED_HEADER
11#include <iomanip>
12#include <ranges>
13#else
14#include "application/pch/precompiled_header.hpp"
15#endif // _PRECOMPILED_HEADER
16
17#include "application/core/include/log.hpp"
18#include "utility/include/currying.hpp"
19#include "utility/include/time.hpp"
20
21//! @brief Title of printing when algorithm tasks are beginning.
22#define APP_ALGO_PRINT_TASK_TITLE_SCOPE_BEGIN(title) \
23 std::osyncstream(std::cout) << "\nAPPLY ALGORITHM: " << std::setiosflags(std::ios_base::left) << std::setfill('.') \
24 << std::setw(50) << (title) << "BEGIN" << std::resetiosflags(std::ios_base::left) \
25 << std::setfill(' ') << std::endl; \
26 {
27//! @brief Title of printing when algorithm tasks are ending.
28#define APP_ALGO_PRINT_TASK_TITLE_SCOPE_END(title) \
29 } \
30 std::osyncstream(std::cout) << "\nAPPLY ALGORITHM: " << std::setiosflags(std::ios_base::left) << std::setfill('.') \
31 << std::setw(50) << (title) << "END" << std::resetiosflags(std::ios_base::left) \
32 << std::setfill(' ') << '\n' \
33 << std::endl;
34
35namespace application::app_algo
36{
37using namespace reg_algo; // NOLINT(google-build-using-namespace)
38
39//! @brief Make the title of a particular method in algorithm choices.
40//! @tparam Meth - type of target method
41//! @param method - target method
42//! @return initial capitalized title
43template <typename Meth>
44static std::string customTitle(const Meth method)
45{
46 std::string title(TypeInfo<Meth>::fields.nameOfValue(method));
47 title.at(n: 0) = std::toupper(c: title.at(n: 0));
48 return title;
49}
50
51//! @brief Get the curried task name.
52//! @return curried task name
53static const auto& curriedTaskName()
54{
55 static const auto curried = utility::currying::curry(func: configure::task::presetName, args: TypeInfo<ApplyAlgorithm>::name);
56 return curried;
57}
58
59//! @brief Get the alias of the category in algorithm choices.
60//! @tparam Cat - target category
61//! @return alias of the category name
62template <Category Cat>
63static consteval std::string_view categoryAlias()
64{
65 constexpr auto attr =
66 TypeInfo<ApplyAlgorithm>::fields.find(REFLECTION_STR(toString(Cat))).attrs.find(REFLECTION_STR("alias"));
67 static_assert(attr.hasValue);
68 return attr.value;
69}
70
71namespace match
72{
73//! @brief Show the contents of the match result.
74//! @param method - used match method
75//! @param result - match result
76//! @param pattern - single pattern
77//! @param interval - time interval
78static void display(
79 const MatchMethod method, const std::int64_t result, const unsigned char* const pattern, const double interval)
80{
81 if (result != -1)
82 {
83 std::printf(
84 format: "\n==> %-16s Method <==\npattern \"%s\" found starting (1st) at index %ld, run time: %8.5f ms\n",
85 customTitle(method).c_str(),
86 pattern,
87 result,
88 interval);
89 }
90 else
91 {
92 std::printf(
93 format: "\n==> %-16s Method <==\npattern \"%s\" could not be found, run time: %8.5f ms\n",
94 customTitle(method).c_str(),
95 pattern,
96 interval);
97 }
98}
99
100//! @brief Solution of match.
101//! @param method - used match method
102//! @param text - matching text
103//! @param pattern - single pattern
104//! @param textLen - length of matching text
105//! @param patternLen - length of single pattern
106static void solution(
107 const MatchMethod method,
108 const unsigned char* const text,
109 const unsigned char* const pattern,
110 const std::uint32_t textLen,
111 const std::uint32_t patternLen)
112try
113{
114 std::int64_t result = 0;
115 const utility::time::Stopwatch timing{};
116 switch (method)
117 {
118 using algorithm::match::Match;
119 case MatchMethod::rabinKarp:
120 result = Match().rk(text, pattern, textLen, patternLen);
121 break;
122 case MatchMethod::knuthMorrisPratt:
123 result = Match().kmp(text, pattern, textLen, patternLen);
124 break;
125 case MatchMethod::boyerMoore:
126 result = Match().bm(text, pattern, textLen, patternLen);
127 break;
128 case MatchMethod::horspool:
129 result = Match().horspool(text, pattern, textLen, patternLen);
130 break;
131 case MatchMethod::sunday:
132 result = Match().sunday(text, pattern, textLen, patternLen);
133 break;
134 default:
135 return;
136 }
137 display(method, result, pattern, interval: timing.elapsedTime());
138}
139catch (const std::exception& err)
140{
141 LOG_WRN_P("Exception in %s (%s): %s", __func__, customTitle(method).c_str(), err.what());
142}
143} // namespace match
144//! @brief To apply match-related methods that are mapped to choices.
145//! @param candidates - container for the candidate target choices
146void applyingMatch(const std::vector<std::string>& candidates)
147{
148 constexpr auto category = Category::match;
149 const auto& spec = categoryOpts<category>();
150 if (spec.none())
151 {
152 return;
153 }
154 MACRO_ASSERT(spec.size() == candidates.size());
155
156 const std::string_view title = algorithm::match::description();
157 APP_ALGO_PRINT_TASK_TITLE_SCOPE_BEGIN(title);
158
159 auto& pooling = configure::task::resourcePool();
160 auto* const allocatedJob = pooling.newEntry(args: spec.count());
161 using match::InputBuilder, match::input::patternString;
162 static_assert(InputBuilder::maxDigit > patternString.length());
163 const auto inputData = std::make_shared<InputBuilder>(args: patternString);
164 const auto taskNamer = utility::currying::curry(curried: curriedTaskName(), args: categoryAlias<category>());
165 const auto addTask =
166 [allocatedJob, &inputData, &taskNamer](const std::string_view subTask, const MatchMethod method)
167 {
168 allocatedJob->enqueue(
169 name: taskNamer(subTask),
170 func&: match::solution,
171 args: method,
172 args: inputData->getMatchingText().get(),
173 args: inputData->getSinglePattern().get(),
174 args: inputData->getTextLength(),
175 args: inputData->getPatternLength());
176 };
177 MACRO_DEFER(utility::common::wrapClosure([&]() { pooling.deleteEntry(allocatedJob); }));
178
179 for (const auto index :
180 std::views::iota(0U, spec.size()) | std::views::filter([&spec](const auto i) { return spec.test(position: i); }))
181 {
182 const auto& choice = candidates.at(n: index);
183 switch (utility::common::bkdrHash(str: choice.c_str()))
184 {
185 case abbrLitHash(method: MatchMethod::rabinKarp):
186 addTask(choice, MatchMethod::rabinKarp);
187 break;
188 case abbrLitHash(method: MatchMethod::knuthMorrisPratt):
189 addTask(choice, MatchMethod::knuthMorrisPratt);
190 break;
191 case abbrLitHash(method: MatchMethod::boyerMoore):
192 addTask(choice, MatchMethod::boyerMoore);
193 break;
194 case abbrLitHash(method: MatchMethod::horspool):
195 addTask(choice, MatchMethod::horspool);
196 break;
197 case abbrLitHash(method: MatchMethod::sunday):
198 addTask(choice, MatchMethod::sunday);
199 break;
200 default:
201 throw std::runtime_error{"Unknown " + std::string{toString(cat: category)} + " choice: " + choice + '.'};
202 }
203 }
204
205 APP_ALGO_PRINT_TASK_TITLE_SCOPE_END(title);
206}
207
208namespace notation
209{
210//! @brief Show the contents of the notation result.
211//! @param method - used notation method
212//! @param result - notation result
213//! @param descr - notation description
214static void display(const NotationMethod method, const std::string& result, const std::string& descr)
215{
216 std::printf(format: "\n==> %-7s Method <==\n%s: %s\n", customTitle(method).c_str(), descr.c_str(), result.c_str());
217}
218
219//! @brief Solution of notation.
220//! @param method - used notation method
221//! @param infix - infix notation
222static void solution(const NotationMethod method, const std::string_view infix)
223try
224{
225 std::string result{};
226 std::string descr{};
227 switch (method)
228 {
229 using algorithm::notation::Notation;
230 case NotationMethod::prefix:
231 result = Notation().prefix(infix);
232 descr = "polish notation";
233 break;
234 case NotationMethod::postfix:
235 result = Notation().postfix(infix);
236 descr = "reverse polish notation";
237 break;
238 default:
239 return;
240 }
241 display(method, result, descr);
242}
243catch (const std::exception& err)
244{
245 LOG_WRN_P("Exception in %s (%s): %s", __func__, customTitle(method).c_str(), err.what());
246}
247} // namespace notation
248//! @brief To apply notation-related methods that are mapped to choices.
249//! @param candidates - container for the candidate target choices
250void applyingNotation(const std::vector<std::string>& candidates)
251{
252 constexpr auto category = Category::notation;
253 const auto& spec = categoryOpts<category>();
254 if (spec.none())
255 {
256 return;
257 }
258 MACRO_ASSERT(spec.size() == candidates.size());
259
260 const std::string_view title = algorithm::notation::description();
261 APP_ALGO_PRINT_TASK_TITLE_SCOPE_BEGIN(title);
262
263 auto& pooling = configure::task::resourcePool();
264 auto* const allocatedJob = pooling.newEntry(args: spec.count());
265 using notation::InputBuilder, notation::input::infixString;
266 const auto inputData = std::make_shared<InputBuilder>(args: infixString);
267 const auto taskNamer = utility::currying::curry(curried: curriedTaskName(), args: categoryAlias<category>());
268 const auto addTask =
269 [allocatedJob, &inputData, &taskNamer](const std::string_view subTask, const NotationMethod method)
270 { allocatedJob->enqueue(name: taskNamer(subTask), func&: notation::solution, args: method, args: inputData->getInfixNotation()); };
271 MACRO_DEFER(utility::common::wrapClosure([&]() { pooling.deleteEntry(allocatedJob); }));
272
273 for (const auto index :
274 std::views::iota(0U, spec.size()) | std::views::filter([&spec](const auto i) { return spec.test(position: i); }))
275 {
276 const auto& choice = candidates.at(n: index);
277 switch (utility::common::bkdrHash(str: choice.c_str()))
278 {
279 case abbrLitHash(method: NotationMethod::prefix):
280 addTask(choice, NotationMethod::prefix);
281 break;
282 case abbrLitHash(method: NotationMethod::postfix):
283 addTask(choice, NotationMethod::postfix);
284 break;
285 default:
286 throw std::runtime_error{"Unknown " + std::string{toString(cat: category)} + " choice: " + choice + '.'};
287 }
288 }
289
290 APP_ALGO_PRINT_TASK_TITLE_SCOPE_END(title);
291}
292
293namespace optimal
294{
295//! @brief Show the contents of the optimal result.
296//! @param method - used optimal method
297//! @param result - optimal result
298//! @param interval - time interval
299static void display(
300 const OptimalMethod method, const std::optional<std::tuple<double, double>>& result, const double interval)
301{
302 if (result.has_value())
303 {
304 std::printf(
305 format: "\n==> %-9s Method <==\nF(min)=%+.5f X=%+.5f, run time: %8.5f ms\n",
306 customTitle(method).c_str(),
307 std::get<0>(t: result.value()),
308 std::get<1>(t: result.value()),
309 interval);
310 }
311 else
312 {
313 std::printf(
314 format: "\n==> %-9s Method <==\nF(min) could not be found, run time: %8.5f ms\n",
315 customTitle(method).c_str(),
316 interval);
317 }
318}
319
320//! @brief Solution of optimal.
321//! @param method - used optimal method
322//! @param func - target function
323//! @param left - left endpoint
324//! @param right - right endpoint
325static void solution(const OptimalMethod method, const Function& func, const double left, const double right)
326try
327{
328 std::optional<std::tuple<double, double>> result = std::nullopt;
329 const utility::time::Stopwatch timing{};
330 switch (method)
331 {
332 using namespace algorithm::optimal; // NOLINT(google-build-using-namespace)
333 case OptimalMethod::gradient:
334 result = Gradient(func)(left, right, epsilon);
335 break;
336 case OptimalMethod::tabu:
337 result = Tabu(func)(left, right, epsilon);
338 break;
339 case OptimalMethod::annealing:
340 result = Annealing(func)(left, right, epsilon);
341 break;
342 case OptimalMethod::particle:
343 result = Particle(func)(left, right, epsilon);
344 break;
345 case OptimalMethod::ant:
346 result = Ant(func)(left, right, epsilon);
347 break;
348 case OptimalMethod::genetic:
349 result = Genetic(func)(left, right, epsilon);
350 break;
351 default:
352 return;
353 }
354 display(method, result, interval: timing.elapsedTime());
355}
356catch (const std::exception& err)
357{
358 LOG_WRN_P("Exception in %s (%s): %s", __func__, customTitle(method).c_str(), err.what());
359}
360} // namespace optimal
361//! @brief To apply optimal-related methods that are mapped to choices.
362//! @param candidates - container for the candidate target choices
363void applyingOptimal(const std::vector<std::string>& candidates)
364{
365 constexpr auto category = Category::optimal;
366 const auto& spec = categoryOpts<category>();
367 if (spec.none())
368 {
369 return;
370 }
371 MACRO_ASSERT(spec.size() == candidates.size());
372
373 const std::string_view title = algorithm::optimal::description();
374 APP_ALGO_PRINT_TASK_TITLE_SCOPE_BEGIN(title);
375
376 auto& pooling = configure::task::resourcePool();
377 auto* const allocatedJob = pooling.newEntry(args: spec.count());
378 using optimal::InputBuilder, optimal::input::SphericalBessel, optimal::Function;
379 static_assert(algorithm::optimal::epsilon >= std::numeric_limits<double>::epsilon());
380 const auto inputData = std::make_shared<InputBuilder>(
381 args: SphericalBessel{}, args: SphericalBessel::range1, args: SphericalBessel::range2, args: SphericalBessel::funcDescr);
382 const auto taskNamer = utility::currying::curry(curried: curriedTaskName(), args: categoryAlias<category>());
383 const auto addTask =
384 [allocatedJob, &inputData, &taskNamer](const std::string_view subTask, const OptimalMethod method)
385 {
386 allocatedJob->enqueue(
387 name: taskNamer(subTask),
388 func&: optimal::solution,
389 args: method,
390 args: inputData->getFunction(),
391 args: inputData->getRanges().first,
392 args: inputData->getRanges().second);
393 };
394 MACRO_DEFER(utility::common::wrapClosure([&]() { pooling.deleteEntry(allocatedJob); }));
395
396 for (const auto index :
397 std::views::iota(0U, spec.size()) | std::views::filter([&spec](const auto i) { return spec.test(position: i); }))
398 {
399 const auto& choice = candidates.at(n: index);
400 switch (utility::common::bkdrHash(str: choice.c_str()))
401 {
402 case abbrLitHash(method: OptimalMethod::gradient):
403 addTask(choice, OptimalMethod::gradient);
404 break;
405 case abbrLitHash(method: OptimalMethod::tabu):
406 addTask(choice, OptimalMethod::tabu);
407 break;
408 case abbrLitHash(method: OptimalMethod::annealing):
409 addTask(choice, OptimalMethod::annealing);
410 break;
411 case abbrLitHash(method: OptimalMethod::particle):
412 addTask(choice, OptimalMethod::particle);
413 break;
414 case abbrLitHash(method: OptimalMethod::ant):
415 addTask(choice, OptimalMethod::ant);
416 break;
417 case abbrLitHash(method: OptimalMethod::genetic):
418 addTask(choice, OptimalMethod::genetic);
419 break;
420 default:
421 throw std::runtime_error{"Unknown " + std::string{toString(cat: category)} + " choice: " + choice + '.'};
422 }
423 }
424
425 APP_ALGO_PRINT_TASK_TITLE_SCOPE_END(title);
426}
427
428namespace search
429{
430//! @brief Show the contents of the search result.
431//! @param method - used search method
432//! @param result - search result
433//! @param key - search key
434//! @param interval - time interval
435static void display(const SearchMethod method, const std::int64_t result, const float key, const double interval)
436{
437 if (result != -1)
438 {
439 std::printf(
440 format: "\n==> %-13s Method <==\nfound the key \"%.5f\" that appears in the index %ld, run time: %8.5f ms\n",
441 customTitle(method).c_str(),
442 key,
443 result,
444 interval);
445 }
446 else
447 {
448 std::printf(
449 format: "\n==> %-13s Method <==\ncould not find the key \"%.5f\", run time: %8.5f ms\n",
450 customTitle(method).c_str(),
451 key,
452 interval);
453 }
454}
455
456//! @brief Solution of search.
457//! @param method - used search method
458//! @param array - ordered array to be searched
459//! @param length - length of array
460//! @param key - search key
461static void solution(const SearchMethod method, const float* const array, const std::uint32_t length, const float key)
462try
463{
464 std::int64_t result = 0;
465 const utility::time::Stopwatch timing{};
466 switch (method)
467 {
468 using algorithm::search::Search;
469 case SearchMethod::binary:
470 result = Search<float>().binary(array, length, key);
471 break;
472 case SearchMethod::interpolation:
473 result = Search<float>().interpolation(array, length, key);
474 break;
475 case SearchMethod::fibonacci:
476 result = Search<float>().fibonacci(array, length, key);
477 break;
478 default:
479 return;
480 }
481 display(method, result, key, interval: timing.elapsedTime());
482}
483catch (const std::exception& err)
484{
485 LOG_WRN_P("Exception in %s (%s): %s", __func__, customTitle(method).c_str(), err.what());
486}
487} // namespace search
488//! @brief To apply search-related methods that are mapped to choices.
489//! @param candidates - container for the candidate target choices
490void applyingSearch(const std::vector<std::string>& candidates)
491{
492 constexpr auto category = Category::search;
493 const auto& spec = categoryOpts<category>();
494 if (spec.none())
495 {
496 return;
497 }
498 MACRO_ASSERT(spec.size() == candidates.size());
499
500 const std::string_view title = algorithm::search::description();
501 APP_ALGO_PRINT_TASK_TITLE_SCOPE_BEGIN(title);
502
503 auto& pooling = configure::task::resourcePool();
504 auto* const allocatedJob = pooling.newEntry(args: spec.count());
505 using search::InputBuilder, search::input::arrayLength, search::input::arrayRangeMin, search::input::arrayRangeMax;
506 static_assert((arrayRangeMin < arrayRangeMax) && (arrayLength > 0));
507 const auto inputData = std::make_shared<InputBuilder<float>>(args: arrayLength, args: arrayRangeMin, args: arrayRangeMax);
508 const auto taskNamer = utility::currying::curry(curried: curriedTaskName(), args: categoryAlias<category>());
509 const auto addTask =
510 [allocatedJob, &inputData, &taskNamer](const std::string_view subTask, const SearchMethod method)
511 {
512 allocatedJob->enqueue(
513 name: taskNamer(subTask),
514 func&: search::solution,
515 args: method,
516 args: inputData->getOrderedArray().get(),
517 args: inputData->getLength(),
518 args: inputData->getSearchKey());
519 };
520 MACRO_DEFER(utility::common::wrapClosure([&]() { pooling.deleteEntry(allocatedJob); }));
521
522 for (const auto index :
523 std::views::iota(0U, spec.size()) | std::views::filter([&spec](const auto i) { return spec.test(position: i); }))
524 {
525 const auto& choice = candidates.at(n: index);
526 switch (utility::common::bkdrHash(str: choice.c_str()))
527 {
528 case abbrLitHash(method: SearchMethod::binary):
529 addTask(choice, SearchMethod::binary);
530 break;
531 case abbrLitHash(method: SearchMethod::interpolation):
532 addTask(choice, SearchMethod::interpolation);
533 break;
534 case abbrLitHash(method: SearchMethod::fibonacci):
535 addTask(choice, SearchMethod::fibonacci);
536 break;
537 default:
538 throw std::runtime_error{"Unknown " + std::string{toString(cat: category)} + " choice: " + choice + '.'};
539 }
540 }
541
542 APP_ALGO_PRINT_TASK_TITLE_SCOPE_END(title);
543}
544
545namespace sort
546{
547//! @brief Show the contents of the sort result.
548//! @param method - used sort method
549//! @param result - sort result
550//! @param interval - time interval
551static void display(const SortMethod method, const std::vector<std::int32_t>& result, const double interval)
552{
553 const std::uint32_t bufferSize = result.size() * maxAlignOfPrint;
554 std::vector<char> fmtBuffer(bufferSize + 1);
555 std::printf(
556 format: "\n==> %-9s Method <==\n%s\n(asc) run time: %8.5f ms\n",
557 customTitle(method).c_str(),
558 InputBuilder<std::int32_t>::spliceAll(array: result.data(), length: result.size(), fmtBuffer: fmtBuffer.data(), bufferSize: bufferSize + 1),
559 interval);
560}
561
562//! @brief Solution of sort.
563//! @param method - used sort method
564//! @param array - array to be sorted
565//! @param length - length of array
566static void solution(const SortMethod method, const std::int32_t* const array, const std::uint32_t length)
567try
568{
569 std::vector<std::int32_t> result{};
570 const utility::time::Stopwatch timing{};
571 switch (method)
572 {
573 using algorithm::sort::Sort;
574 case SortMethod::bubble:
575 result = Sort<std::int32_t>().bubble(array, length);
576 break;
577 case SortMethod::selection:
578 result = Sort<std::int32_t>().selection(array, length);
579 break;
580 case SortMethod::insertion:
581 result = Sort<std::int32_t>().insertion(array, length);
582 break;
583 case SortMethod::shell:
584 result = Sort<std::int32_t>().shell(array, length);
585 break;
586 case SortMethod::merge:
587 result = Sort<std::int32_t>().merge(array, length);
588 break;
589 case SortMethod::quick:
590 result = Sort<std::int32_t>().quick(array, length);
591 break;
592 case SortMethod::heap:
593 result = Sort<std::int32_t>().heap(array, length);
594 break;
595 case SortMethod::counting:
596 result = Sort<std::int32_t>().counting(array, length);
597 break;
598 case SortMethod::bucket:
599 result = Sort<std::int32_t>().bucket(array, length);
600 break;
601 case SortMethod::radix:
602 result = Sort<std::int32_t>().radix(array, length);
603 break;
604 default:
605 return;
606 }
607 display(method, result, interval: timing.elapsedTime());
608}
609catch (const std::exception& err)
610{
611 LOG_WRN_P("Exception in %s (%s): %s", __func__, customTitle(method).c_str(), err.what());
612}
613} // namespace sort
614//! @brief To apply sort-related methods that are mapped to choices.
615//! @param candidates - container for the candidate target choices
616void applyingSort(const std::vector<std::string>& candidates)
617{
618 constexpr auto category = Category::sort;
619 const auto& spec = categoryOpts<category>();
620 if (spec.none())
621 {
622 return;
623 }
624 MACRO_ASSERT(spec.size() == candidates.size());
625
626 const std::string_view title = algorithm::sort::description();
627 APP_ALGO_PRINT_TASK_TITLE_SCOPE_BEGIN(title);
628
629 auto& pooling = configure::task::resourcePool();
630 auto* const allocatedJob = pooling.newEntry(args: spec.count());
631 using sort::InputBuilder, sort::input::arrayLength, sort::input::arrayRangeMin, sort::input::arrayRangeMax;
632 static_assert((arrayRangeMin < arrayRangeMax) && (arrayLength > 0));
633 const auto inputData = std::make_shared<InputBuilder<std::int32_t>>(args: arrayLength, args: arrayRangeMin, args: arrayRangeMax);
634 const auto taskNamer = utility::currying::curry(curried: curriedTaskName(), args: categoryAlias<category>());
635 const auto addTask = [allocatedJob, &inputData, &taskNamer](const std::string_view subTask, const SortMethod method)
636 {
637 allocatedJob->enqueue(
638 name: taskNamer(subTask), func&: sort::solution, args: method, args: inputData->getRandomArray().get(), args: inputData->getLength());
639 };
640 MACRO_DEFER(utility::common::wrapClosure([&]() { pooling.deleteEntry(allocatedJob); }));
641
642 for (const auto index :
643 std::views::iota(0U, spec.size()) | std::views::filter([&spec](const auto i) { return spec.test(position: i); }))
644 {
645 const auto& choice = candidates.at(n: index);
646 switch (utility::common::bkdrHash(str: choice.c_str()))
647 {
648 case abbrLitHash(method: SortMethod::bubble):
649 addTask(choice, SortMethod::bubble);
650 break;
651 case abbrLitHash(method: SortMethod::selection):
652 addTask(choice, SortMethod::selection);
653 break;
654 case abbrLitHash(method: SortMethod::insertion):
655 addTask(choice, SortMethod::insertion);
656 break;
657 case abbrLitHash(method: SortMethod::shell):
658 addTask(choice, SortMethod::shell);
659 break;
660 case abbrLitHash(method: SortMethod::merge):
661 addTask(choice, SortMethod::merge);
662 break;
663 case abbrLitHash(method: SortMethod::quick):
664 addTask(choice, SortMethod::quick);
665 break;
666 case abbrLitHash(method: SortMethod::heap):
667 addTask(choice, SortMethod::heap);
668 break;
669 case abbrLitHash(method: SortMethod::counting):
670 addTask(choice, SortMethod::counting);
671 break;
672 case abbrLitHash(method: SortMethod::bucket):
673 addTask(choice, SortMethod::bucket);
674 break;
675 case abbrLitHash(method: SortMethod::radix):
676 addTask(choice, SortMethod::radix);
677 break;
678 default:
679 throw std::runtime_error{"Unknown " + std::string{toString(cat: category)} + " choice: " + choice + '.'};
680 }
681 }
682
683 APP_ALGO_PRINT_TASK_TITLE_SCOPE_END(title);
684}
685} // namespace application::app_algo
686
687#undef APP_ALGO_PRINT_TASK_TITLE_SCOPE_BEGIN
688#undef APP_ALGO_PRINT_TASK_TITLE_SCOPE_END
689