1//! @file register_algorithm.hpp
2//! @author ryftchen
3//! @brief The declarations (register_algorithm) in the application module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2026 ryftchen. All rights reserved.
6
7#pragma once
8
9#ifndef _PRECOMPILED_HEADER
10#include <bitset>
11#include <functional>
12#else
13#include "application/pch/precompiled_header.hpp"
14#endif
15
16#include "utility/include/common.hpp"
17#include "utility/include/macro.hpp"
18#include "utility/include/reflection.hpp"
19
20//! @brief The application module.
21namespace application // NOLINT(modernize-concat-nested-namespaces)
22{
23//! @brief Algorithm-registering-related functions in the application module.
24namespace reg_algo
25{
26extern const char* version() noexcept;
27
28//! @brief Represent the maximum value of an enum.
29//! @tparam Enum - type of specific enum
30template <typename Enum>
31struct Bottom;
32
33//! @brief Enumerate specific match methods.
34enum class MatchMethod : std::uint8_t
35{
36 //! @brief Rabin-Karp.
37 rabinKarp,
38 //! @brief Knuth-Morris-Pratt.
39 knuthMorrisPratt,
40 //! @brief Boyer-Moore.
41 boyerMoore,
42 //! @brief Horspool.
43 horspool,
44 //! @brief Sunday.
45 sunday
46};
47//! @brief Store the maximum value of the MatchMethod enum.
48template <>
49struct Bottom<MatchMethod>
50{
51 //! @brief Maximum value of the MatchMethod enum.
52 static constexpr std::uint8_t value{5};
53};
54
55//! @brief Enumerate specific notation methods.
56enum class NotationMethod : std::uint8_t
57{
58 //! @brief Prefix.
59 prefix,
60 //! @brief Postfix.
61 postfix
62};
63//! @brief Store the maximum value of the NotationMethod enum.
64template <>
65struct Bottom<NotationMethod>
66{
67 //! @brief Maximum value of the NotationMethod enum.
68 static constexpr std::uint8_t value{2};
69};
70
71//! @brief Enumerate specific optimal methods.
72enum class OptimalMethod : std::uint8_t
73{
74 //! @brief Gradient.
75 gradient,
76 //! @brief Tabu.
77 tabu,
78 //! @brief Annealing.
79 annealing,
80 //! @brief Particle.
81 particle,
82 //! @brief Ant.
83 ant,
84 //! @brief Genetic.
85 genetic
86};
87//! @brief Store the maximum value of the OptimalMethod enum.
88template <>
89struct Bottom<OptimalMethod>
90{
91 //! @brief Maximum value of the OptimalMethod enum.
92 static constexpr std::uint8_t value{6};
93};
94
95//! @brief Enumerate specific search methods.
96enum class SearchMethod : std::uint8_t
97{
98 //! @brief Binary.
99 binary,
100 //! @brief Interpolation.
101 interpolation,
102 //! @brief Fibonacci.
103 fibonacci
104};
105//! @brief Store the maximum value of the SearchMethod enum.
106template <>
107struct Bottom<SearchMethod>
108{
109 //! @brief Maximum value of the SearchMethod enum.
110 static constexpr std::uint8_t value{3};
111};
112
113//! @brief Enumerate specific sort methods.
114enum class SortMethod : std::uint8_t
115{
116 //! @brief Bubble.
117 bubble,
118 //! @brief Selection.
119 selection,
120 //! @brief Insertion.
121 insertion,
122 //! @brief Shell.
123 shell,
124 //! @brief Merge.
125 merge,
126 //! @brief Quick.
127 quick,
128 //! @brief Heap.
129 heap,
130 //! @brief Counting.
131 counting,
132 //! @brief Bucket.
133 bucket,
134 //! @brief Radix.
135 radix
136};
137//! @brief Store the maximum value of the SortMethod enum.
138template <>
139struct Bottom<SortMethod>
140{
141 //! @brief Maximum value of the SortMethod enum.
142 static constexpr std::uint8_t value{10};
143};
144
145//! @brief Manage algorithm choices.
146class ApplyAlgorithm
147{
148public:
149 //! @brief Enumerate specific algorithm choices.
150 enum class Category : std::uint8_t
151 {
152 //! @brief Match.
153 match,
154 //! @brief Notation.
155 notation,
156 //! @brief Optimal.
157 optimal,
158 //! @brief Search.
159 search,
160 //! @brief Sort.
161 sort
162 };
163
164 //! @brief Bit flags for managing match methods.
165 std::bitset<Bottom<MatchMethod>::value> matchOpts;
166 //! @brief Bit flags for managing notation methods.
167 std::bitset<Bottom<NotationMethod>::value> notationOpts;
168 //! @brief Bit flags for managing optimal methods.
169 std::bitset<Bottom<OptimalMethod>::value> optimalOpts;
170 //! @brief Bit flags for managing search methods.
171 std::bitset<Bottom<SearchMethod>::value> searchOpts;
172 //! @brief Bit flags for managing sort methods.
173 std::bitset<Bottom<SortMethod>::value> sortOpts;
174};
175
176//! @brief Manage the algorithm choices.
177namespace manage
178{
179extern ApplyAlgorithm& choiceApplier();
180
181extern bool present();
182extern void clear();
183} // namespace manage
184
185//! @brief Constraint for algorithm-registering.
186//! @tparam Meth - type of method
187template <typename Meth>
188concept Registrant = std::is_same_v<Meth, MatchMethod> || std::is_same_v<Meth, NotationMethod>
189 || std::is_same_v<Meth, OptimalMethod> || std::is_same_v<Meth, SearchMethod> || std::is_same_v<Meth, SortMethod>;
190//! @brief Set the choice.
191//! @tparam Meth - type of target method
192//! @param choice - target choice
193template <typename Meth>
194requires Registrant<Meth>
195void setChoice(const std::string& choice);
196//! @brief Run the candidates.
197//! @tparam Meth - type of target method
198//! @param candidates - container for the candidate target choices
199template <typename Meth>
200requires Registrant<Meth>
201void runCandidates(const std::vector<std::string>& candidates);
202
203//! @brief Register match.
204namespace match
205{
206extern const char* version() noexcept;
207} // namespace match
208template <>
209void setChoice<MatchMethod>(const std::string& choice);
210template <>
211void runCandidates<MatchMethod>(const std::vector<std::string>& candidates);
212
213//! @brief Register notation.
214namespace notation
215{
216extern const char* version() noexcept;
217} // namespace notation
218template <>
219void setChoice<NotationMethod>(const std::string& choice);
220template <>
221void runCandidates<NotationMethod>(const std::vector<std::string>& candidates);
222
223//! @brief Register optimal.
224namespace optimal
225{
226extern const char* version() noexcept;
227} // namespace optimal
228template <>
229void setChoice<OptimalMethod>(const std::string& choice);
230template <>
231void runCandidates<OptimalMethod>(const std::vector<std::string>& candidates);
232
233//! @brief Register search.
234namespace search
235{
236extern const char* version() noexcept;
237} // namespace search
238template <>
239void setChoice<SearchMethod>(const std::string& choice);
240template <>
241void runCandidates<SearchMethod>(const std::vector<std::string>& candidates);
242
243//! @brief Register sort.
244namespace sort
245{
246extern const char* version() noexcept;
247} // namespace sort
248template <>
249void setChoice<SortMethod>(const std::string& choice);
250template <>
251void runCandidates<SortMethod>(const std::vector<std::string>& candidates);
252} // namespace reg_algo
253} // namespace application
254
255//! @brief Reflect the algorithm category name and alias name to the field in the mapping.
256#define REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(category, alias) \
257 Field \
258 { \
259 REFLECTION_STR(MACRO_STRINGIFY(category)), &Type::MACRO_CONCAT(category, Opts), AttrList \
260 { \
261 Attr \
262 { \
263 REFLECTION_STR("alias"), MACRO_STRINGIFY(alias) \
264 } \
265 } \
266 }
267//! @brief Reflect the entry under the algorithm category and choice name to the field in the mapping.
268#define REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(entry, choice) \
269 Field \
270 { \
271 REFLECTION_STR(MACRO_STRINGIFY(entry)), Type::entry, AttrList \
272 { \
273 Attr \
274 { \
275 REFLECTION_STR("choice"), MACRO_STRINGIFY(choice) \
276 } \
277 } \
278 }
279//! @brief Static reflection for ApplyAlgorithm. Used to map command line arguments.
280template <>
281struct utility::reflection::TypeInfo<application::reg_algo::ApplyAlgorithm>
282 : public TypeInfoImpl<application::reg_algo::ApplyAlgorithm>
283{
284 //! @brief Name.
285 static constexpr std::string_view name{"app-algo"};
286 // clang-format off
287 //! @brief Field list.
288 static constexpr FieldList fields
289 {
290 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(match , m),
291 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(notation, n),
292 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(optimal , o),
293 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(search , s),
294 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(sort , S),
295 };
296 // clang-format on
297 //! @brief Attribute list.
298 static constexpr AttrList attrs{Attr{REFLECTION_STR("descr"), "apply algorithm"}};
299};
300//! @brief Static reflection for MatchMethod. Used to map command line arguments.
301template <>
302struct utility::reflection::TypeInfo<application::reg_algo::MatchMethod>
303 : public TypeInfoImpl<application::reg_algo::MatchMethod>
304{
305 //! @brief Name.
306 static constexpr std::string_view name{"match"};
307 // clang-format off
308 //! @brief Field list.
309 static constexpr FieldList fields
310 {
311 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(rabinKarp , rab),
312 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(knuthMorrisPratt, knu),
313 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(boyerMoore , boy),
314 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(horspool , hor),
315 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(sunday , sun),
316 };
317 // clang-format on
318 //! @brief Attribute list.
319 static constexpr AttrList attrs{Attr{
320 REFLECTION_STR("descr"),
321 "match-related choices\n"
322 "- rab Rabin-Karp\n"
323 "- knu Knuth-Morris-Pratt\n"
324 "- boy Boyer-Moore\n"
325 "- hor Horspool\n"
326 "- sun Sunday\n"
327 "add the choices listed above"}};
328};
329//! @brief Static reflection for NotationMethod. Used to map command line arguments.
330template <>
331struct utility::reflection::TypeInfo<application::reg_algo::NotationMethod>
332 : public TypeInfoImpl<application::reg_algo::NotationMethod>
333{
334 //! @brief Name.
335 static constexpr std::string_view name{"notation"};
336 // clang-format off
337 //! @brief Field list.
338 static constexpr FieldList fields
339 {
340 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(prefix , pre),
341 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(postfix, pos),
342 };
343 // clang-format on
344 //! @brief Attribute list.
345 static constexpr AttrList attrs{Attr{
346 REFLECTION_STR("descr"),
347 "notation-related choices\n"
348 "- pre Prefix\n"
349 "- pos Postfix\n"
350 "add the choices listed above"}};
351};
352//! @brief Static reflection for OptimalMethod. Used to map command line arguments.
353template <>
354struct utility::reflection::TypeInfo<application::reg_algo::OptimalMethod>
355 : public TypeInfoImpl<application::reg_algo::OptimalMethod>
356{
357 //! @brief Name.
358 static constexpr std::string_view name{"optimal"};
359 // clang-format off
360 //! @brief Field list.
361 static constexpr FieldList fields
362 {
363 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(gradient , gra),
364 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(tabu , tab),
365 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(annealing, ann),
366 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(particle , par),
367 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(ant , ant),
368 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(genetic , gen),
369 };
370 // clang-format on
371 //! @brief Attribute list.
372 static constexpr AttrList attrs{Attr{
373 REFLECTION_STR("descr"),
374 "optimal-related choices\n"
375 "- gra Gradient Descent\n"
376 "- tab Tabu\n"
377 "- ann Simulated Annealing\n"
378 "- par Particle Swarm\n"
379 "- ant Ant Colony\n"
380 "- gen Genetic\n"
381 "add the choices listed above"}};
382};
383//! @brief Static reflection for SearchMethod. Used to map command line arguments.
384template <>
385struct utility::reflection::TypeInfo<application::reg_algo::SearchMethod>
386 : public TypeInfoImpl<application::reg_algo::SearchMethod>
387{
388 //! @brief Name.
389 static constexpr std::string_view name{"search"};
390 // clang-format off
391 //! @brief Field list.
392 static constexpr FieldList fields
393 {
394 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(binary , bin),
395 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(interpolation, int),
396 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(fibonacci , fib),
397 };
398 // clang-format on
399 //! @brief Attribute list.
400 static constexpr AttrList attrs{Attr{
401 REFLECTION_STR("descr"),
402 "search-related choices\n"
403 "- bin Binary\n"
404 "- int Interpolation\n"
405 "- fib Fibonacci\n"
406 "add the choices listed above"}};
407};
408//! @brief Static reflection for SortMethod. Used to map command line arguments.
409template <>
410struct utility::reflection::TypeInfo<application::reg_algo::SortMethod>
411 : public TypeInfoImpl<application::reg_algo::SortMethod>
412{
413 //! @brief Name.
414 static constexpr std::string_view name{"sort"};
415 // clang-format off
416 //! @brief Field list.
417 static constexpr FieldList fields
418 {
419 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(bubble , bub),
420 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(selection, sel),
421 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(insertion, ins),
422 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(shell , she),
423 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(merge , mer),
424 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(quick , qui),
425 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(heap , hea),
426 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(counting , cou),
427 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(bucket , buc),
428 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(radix , rad),
429 };
430 // clang-format on
431 //! @brief Attribute list.
432 static constexpr AttrList attrs{Attr{
433 REFLECTION_STR("descr"),
434 "sort-related choices\n"
435 "- bub Bubble\n"
436 "- sel Selection\n"
437 "- ins Insertion\n"
438 "- she Shell\n"
439 "- mer Merge\n"
440 "- qui Quick\n"
441 "- hea Heap\n"
442 "- cou Counting\n"
443 "- buc Bucket\n"
444 "- rad Radix\n"
445 "add the choices listed above"}};
446};
447#undef REG_ALGO_REFLECT_FIRST_LEVEL_FIELD
448#undef REG_ALGO_REFLECT_SECOND_LEVEL_FIELD
449
450namespace application::reg_algo
451{
452//! @brief Alias for the type information.
453//! @tparam UDT - type of user defined data
454template <typename UDT>
455using TypeInfo = utility::reflection::TypeInfo<UDT>;
456//! @brief Alias for the category.
457using Category = ApplyAlgorithm::Category;
458//! @brief Convert category enumeration to string.
459//! @param cat - target category
460//! @return category name
461consteval std::string_view toString(const Category cat)
462{
463 switch (cat)
464 {
465 case Category::match:
466 return TypeInfo<MatchMethod>::name;
467 case Category::notation:
468 return TypeInfo<NotationMethod>::name;
469 case Category::optimal:
470 return TypeInfo<OptimalMethod>::name;
471 case Category::search:
472 return TypeInfo<SearchMethod>::name;
473 case Category::sort:
474 return TypeInfo<SortMethod>::name;
475 default:
476 break;
477 }
478 return {};
479}
480//! @brief Get the bit flags of the category in algorithm choices.
481//! @tparam Cat - target category
482//! @return reference of the category bit flags
483template <Category Cat>
484constexpr auto& categoryOpts()
485{
486 return std::invoke(
487 TypeInfo<ApplyAlgorithm>::fields.find(REFLECTION_STR(toString(Cat))).value, manage::choiceApplier());
488}
489//! @brief The literal hash value of the abbreviation for the candidate method.
490//! @tparam Meth - type of candidate method
491//! @param method - candidate method
492//! @return literal hash value
493template <typename Meth>
494consteval std::size_t abbrLitHash(const Meth method)
495{
496 static_assert(Bottom<Meth>::value == TypeInfo<Meth>::fields.size);
497 constexpr auto refl = REFLECTION_STR("choice");
498 std::size_t value = 0;
499 TypeInfo<Meth>::fields.findIf(
500 [refl, method, &value](const auto field)
501 {
502 if (field.name == TypeInfo<Meth>::fields.nameOfValue(method))
503 {
504 static_assert(field.attrs.contains(refl) && (field.attrs.size == 1));
505 const auto attr = field.attrs.find(refl);
506 static_assert(attr.hasValue);
507 value = utility::common::operator""_bkdrHash(attr.value);
508 return true;
509 }
510 return false;
511 });
512 return value;
513}
514} // namespace application::reg_algo
515