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-2025 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 // _PRECOMPILED_HEADER
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 Set choice.
186//! @tparam Meth - type of target method
187//! @param choice - target choice
188template <typename Meth>
189void setChoice(const std::string& choice);
190//! @brief Run candidates.
191//! @tparam Meth - type of target method
192//! @param candidates - container for the candidate target choices
193template <typename Meth>
194void runCandidates(const std::vector<std::string>& candidates);
195
196//! @brief Register match.
197namespace match
198{
199extern const char* version() noexcept;
200} // namespace match
201template <>
202void setChoice<MatchMethod>(const std::string& choice);
203template <>
204void runCandidates<MatchMethod>(const std::vector<std::string>& candidates);
205
206//! @brief Register notation.
207namespace notation
208{
209extern const char* version() noexcept;
210} // namespace notation
211template <>
212void setChoice<NotationMethod>(const std::string& choice);
213template <>
214void runCandidates<NotationMethod>(const std::vector<std::string>& candidates);
215
216//! @brief Register optimal.
217namespace optimal
218{
219extern const char* version() noexcept;
220} // namespace optimal
221template <>
222void setChoice<OptimalMethod>(const std::string& choice);
223template <>
224void runCandidates<OptimalMethod>(const std::vector<std::string>& candidates);
225
226//! @brief Register search.
227namespace search
228{
229extern const char* version() noexcept;
230} // namespace search
231template <>
232void setChoice<SearchMethod>(const std::string& choice);
233template <>
234void runCandidates<SearchMethod>(const std::vector<std::string>& candidates);
235
236//! @brief Register sort.
237namespace sort
238{
239extern const char* version() noexcept;
240} // namespace sort
241template <>
242void setChoice<SortMethod>(const std::string& choice);
243template <>
244void runCandidates<SortMethod>(const std::vector<std::string>& candidates);
245} // namespace reg_algo
246} // namespace application
247
248//! @brief Reflect the algorithm category name and alias name to the field in the mapping.
249#define REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(category, alias) \
250 Field \
251 { \
252 REFLECTION_STR(MACRO_STRINGIFY(category)), &Type::MACRO_CONCAT(category, Opts), AttrList \
253 { \
254 Attr \
255 { \
256 REFLECTION_STR("alias"), MACRO_STRINGIFY(alias) \
257 } \
258 } \
259 }
260//! @brief Reflect the entry under the algorithm category and choice name to the field in the mapping.
261#define REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(entry, choice) \
262 Field \
263 { \
264 REFLECTION_STR(MACRO_STRINGIFY(entry)), Type::entry, AttrList \
265 { \
266 Attr \
267 { \
268 REFLECTION_STR("choice"), MACRO_STRINGIFY(choice) \
269 } \
270 } \
271 }
272//! @brief Static reflection for ApplyAlgorithm. Used to map command line arguments.
273template <>
274struct utility::reflection::TypeInfo<application::reg_algo::ApplyAlgorithm>
275 : public TypeInfoImpl<application::reg_algo::ApplyAlgorithm>
276{
277 //! @brief Name.
278 static constexpr std::string_view name{"app-algo"};
279 // clang-format off
280 //! @brief Field list.
281 static constexpr FieldList fields
282 {
283 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(match , m),
284 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(notation, n),
285 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(optimal , o),
286 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(search , s),
287 REG_ALGO_REFLECT_FIRST_LEVEL_FIELD(sort , S),
288 };
289 // clang-format on
290 //! @brief Attribute list.
291 static constexpr AttrList attrs{Attr{REFLECTION_STR("descr"), "apply algorithm"}};
292};
293//! @brief Static reflection for MatchMethod. Used to map command line arguments.
294template <>
295struct utility::reflection::TypeInfo<application::reg_algo::MatchMethod>
296 : public TypeInfoImpl<application::reg_algo::MatchMethod>
297{
298 //! @brief Name.
299 static constexpr std::string_view name{"match"};
300 // clang-format off
301 //! @brief Field list.
302 static constexpr FieldList fields
303 {
304 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(rabinKarp , rab),
305 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(knuthMorrisPratt, knu),
306 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(boyerMoore , boy),
307 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(horspool , hor),
308 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(sunday , sun),
309 };
310 // clang-format on
311 //! @brief Attribute list.
312 static constexpr AttrList attrs{Attr{
313 REFLECTION_STR("descr"),
314 "match-related choices\n"
315 "- rab Rabin-Karp\n"
316 "- knu Knuth-Morris-Pratt\n"
317 "- boy Boyer-Moore\n"
318 "- hor Horspool\n"
319 "- sun Sunday\n"
320 "add the choices listed above"}};
321};
322//! @brief Static reflection for NotationMethod. Used to map command line arguments.
323template <>
324struct utility::reflection::TypeInfo<application::reg_algo::NotationMethod>
325 : public TypeInfoImpl<application::reg_algo::NotationMethod>
326{
327 //! @brief Name.
328 static constexpr std::string_view name{"notation"};
329 // clang-format off
330 //! @brief Field list.
331 static constexpr FieldList fields
332 {
333 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(prefix , pre),
334 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(postfix, pos),
335 };
336 // clang-format on
337 //! @brief Attribute list.
338 static constexpr AttrList attrs{Attr{
339 REFLECTION_STR("descr"),
340 "notation-related choices\n"
341 "- pre Prefix\n"
342 "- pos Postfix\n"
343 "add the choices listed above"}};
344};
345//! @brief Static reflection for OptimalMethod. Used to map command line arguments.
346template <>
347struct utility::reflection::TypeInfo<application::reg_algo::OptimalMethod>
348 : public TypeInfoImpl<application::reg_algo::OptimalMethod>
349{
350 //! @brief Name.
351 static constexpr std::string_view name{"optimal"};
352 // clang-format off
353 //! @brief Field list.
354 static constexpr FieldList fields
355 {
356 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(gradient , gra),
357 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(tabu , tab),
358 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(annealing, ann),
359 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(particle , par),
360 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(ant , ant),
361 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(genetic , gen),
362 };
363 // clang-format on
364 //! @brief Attribute list.
365 static constexpr AttrList attrs{Attr{
366 REFLECTION_STR("descr"),
367 "optimal-related choices\n"
368 "- gra Gradient Descent\n"
369 "- tab Tabu\n"
370 "- ann Simulated Annealing\n"
371 "- par Particle Swarm\n"
372 "- ant Ant Colony\n"
373 "- gen Genetic\n"
374 "add the choices listed above"}};
375};
376//! @brief Static reflection for SearchMethod. Used to map command line arguments.
377template <>
378struct utility::reflection::TypeInfo<application::reg_algo::SearchMethod>
379 : public TypeInfoImpl<application::reg_algo::SearchMethod>
380{
381 //! @brief Name.
382 static constexpr std::string_view name{"search"};
383 // clang-format off
384 //! @brief Field list.
385 static constexpr FieldList fields
386 {
387 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(binary , bin),
388 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(interpolation, int),
389 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(fibonacci , fib),
390 };
391 // clang-format on
392 //! @brief Attribute list.
393 static constexpr AttrList attrs{Attr{
394 REFLECTION_STR("descr"),
395 "search-related choices\n"
396 "- bin Binary\n"
397 "- int Interpolation\n"
398 "- fib Fibonacci\n"
399 "add the choices listed above"}};
400};
401//! @brief Static reflection for SortMethod. Used to map command line arguments.
402template <>
403struct utility::reflection::TypeInfo<application::reg_algo::SortMethod>
404 : public TypeInfoImpl<application::reg_algo::SortMethod>
405{
406 //! @brief Name.
407 static constexpr std::string_view name{"sort"};
408 // clang-format off
409 //! @brief Field list.
410 static constexpr FieldList fields
411 {
412 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(bubble , bub),
413 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(selection, sel),
414 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(insertion, ins),
415 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(shell , she),
416 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(merge , mer),
417 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(quick , qui),
418 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(heap , hea),
419 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(counting , cou),
420 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(bucket , buc),
421 REG_ALGO_REFLECT_SECOND_LEVEL_FIELD(radix , rad),
422 };
423 // clang-format on
424 //! @brief Attribute list.
425 static constexpr AttrList attrs{Attr{
426 REFLECTION_STR("descr"),
427 "sort-related choices\n"
428 "- bub Bubble\n"
429 "- sel Selection\n"
430 "- ins Insertion\n"
431 "- she Shell\n"
432 "- mer Merge\n"
433 "- qui Quick\n"
434 "- hea Heap\n"
435 "- cou Counting\n"
436 "- buc Bucket\n"
437 "- rad Radix\n"
438 "add the choices listed above"}};
439};
440#undef REG_ALGO_REFLECT_FIRST_LEVEL_FIELD
441#undef REG_ALGO_REFLECT_SECOND_LEVEL_FIELD
442
443namespace application::reg_algo
444{
445//! @brief Alias for the type information.
446//! @tparam UDT - type of user defined data
447template <typename UDT>
448using TypeInfo = utility::reflection::TypeInfo<UDT>;
449//! @brief Alias for the category.
450using Category = ApplyAlgorithm::Category;
451//! @brief Convert category enumeration to string.
452//! @param cat - target category
453//! @return category name
454consteval std::string_view toString(const Category cat)
455{
456 switch (cat)
457 {
458 case Category::match:
459 return TypeInfo<MatchMethod>::name;
460 case Category::notation:
461 return TypeInfo<NotationMethod>::name;
462 case Category::optimal:
463 return TypeInfo<OptimalMethod>::name;
464 case Category::search:
465 return TypeInfo<SearchMethod>::name;
466 case Category::sort:
467 return TypeInfo<SortMethod>::name;
468 default:
469 break;
470 }
471 return {};
472}
473//! @brief Get the bit flags of the category in algorithm choices.
474//! @tparam Cat - target category
475//! @return reference of the category bit flags
476template <Category Cat>
477constexpr auto& categoryOpts()
478{
479 return std::invoke(
480 TypeInfo<ApplyAlgorithm>::fields.find(REFLECTION_STR(toString(Cat))).value, manage::choiceApplier());
481}
482//! @brief The literal hash value of the abbreviation for the candidate method.
483//! @tparam Meth - type of candidate method
484//! @param method - candidate method
485//! @return literal hash value
486template <typename Meth>
487consteval std::size_t abbrLitHash(const Meth method)
488{
489 static_assert(Bottom<Meth>::value == TypeInfo<Meth>::fields.size);
490 constexpr auto refl = REFLECTION_STR("choice");
491 std::size_t value = 0;
492 TypeInfo<Meth>::fields.findIf(
493 [refl, method, &value](const auto field)
494 {
495 if (field.name == TypeInfo<Meth>::fields.nameOfValue(method))
496 {
497 static_assert(field.attrs.contains(refl) && (field.attrs.size == 1));
498 const auto attr = field.attrs.find(refl);
499 static_assert(attr.hasValue);
500 value = utility::common::operator""_bkdrHash(attr.value);
501 return true;
502 }
503 return false;
504 });
505 return value;
506}
507} // namespace application::reg_algo
508