| 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. |
| 21 | namespace application // NOLINT(modernize-concat-nested-namespaces) |
| 22 | { |
| 23 | //! @brief Algorithm-registering-related functions in the application module. |
| 24 | namespace reg_algo |
| 25 | { |
| 26 | extern const char* version() noexcept; |
| 27 | |
| 28 | //! @brief Represent the maximum value of an enum. |
| 29 | //! @tparam Enum - type of specific enum |
| 30 | template <typename Enum> |
| 31 | struct Bottom; |
| 32 | |
| 33 | //! @brief Enumerate specific match methods. |
| 34 | enum 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. |
| 48 | template <> |
| 49 | struct 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. |
| 56 | enum 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. |
| 64 | template <> |
| 65 | struct 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. |
| 72 | enum 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. |
| 88 | template <> |
| 89 | struct 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. |
| 96 | enum 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. |
| 106 | template <> |
| 107 | struct 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. |
| 114 | enum 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. |
| 138 | template <> |
| 139 | struct 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. |
| 146 | class ApplyAlgorithm |
| 147 | { |
| 148 | public: |
| 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. |
| 177 | namespace manage |
| 178 | { |
| 179 | extern ApplyAlgorithm& choiceApplier(); |
| 180 | |
| 181 | extern bool present(); |
| 182 | extern void clear(); |
| 183 | } // namespace manage |
| 184 | |
| 185 | //! @brief Set choice. |
| 186 | //! @tparam Meth - type of target method |
| 187 | //! @param choice - target choice |
| 188 | template <typename Meth> |
| 189 | void 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 |
| 193 | template <typename Meth> |
| 194 | void runCandidates(const std::vector<std::string>& candidates); |
| 195 | |
| 196 | //! @brief Register match. |
| 197 | namespace match |
| 198 | { |
| 199 | extern const char* version() noexcept; |
| 200 | } // namespace match |
| 201 | template <> |
| 202 | void setChoice<MatchMethod>(const std::string& choice); |
| 203 | template <> |
| 204 | void runCandidates<MatchMethod>(const std::vector<std::string>& candidates); |
| 205 | |
| 206 | //! @brief Register notation. |
| 207 | namespace notation |
| 208 | { |
| 209 | extern const char* version() noexcept; |
| 210 | } // namespace notation |
| 211 | template <> |
| 212 | void setChoice<NotationMethod>(const std::string& choice); |
| 213 | template <> |
| 214 | void runCandidates<NotationMethod>(const std::vector<std::string>& candidates); |
| 215 | |
| 216 | //! @brief Register optimal. |
| 217 | namespace optimal |
| 218 | { |
| 219 | extern const char* version() noexcept; |
| 220 | } // namespace optimal |
| 221 | template <> |
| 222 | void setChoice<OptimalMethod>(const std::string& choice); |
| 223 | template <> |
| 224 | void runCandidates<OptimalMethod>(const std::vector<std::string>& candidates); |
| 225 | |
| 226 | //! @brief Register search. |
| 227 | namespace search |
| 228 | { |
| 229 | extern const char* version() noexcept; |
| 230 | } // namespace search |
| 231 | template <> |
| 232 | void setChoice<SearchMethod>(const std::string& choice); |
| 233 | template <> |
| 234 | void runCandidates<SearchMethod>(const std::vector<std::string>& candidates); |
| 235 | |
| 236 | //! @brief Register sort. |
| 237 | namespace sort |
| 238 | { |
| 239 | extern const char* version() noexcept; |
| 240 | } // namespace sort |
| 241 | template <> |
| 242 | void setChoice<SortMethod>(const std::string& choice); |
| 243 | template <> |
| 244 | void 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. |
| 273 | template <> |
| 274 | struct 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. |
| 294 | template <> |
| 295 | struct 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. |
| 323 | template <> |
| 324 | struct 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. |
| 346 | template <> |
| 347 | struct 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. |
| 377 | template <> |
| 378 | struct 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. |
| 402 | template <> |
| 403 | struct 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 | |
| 443 | namespace application::reg_algo |
| 444 | { |
| 445 | //! @brief Alias for the type information. |
| 446 | //! @tparam UDT - type of user defined data |
| 447 | template <typename UDT> |
| 448 | using TypeInfo = utility::reflection::TypeInfo<UDT>; |
| 449 | //! @brief Alias for the category. |
| 450 | using Category = ApplyAlgorithm::Category; |
| 451 | //! @brief Convert category enumeration to string. |
| 452 | //! @param cat - target category |
| 453 | //! @return category name |
| 454 | consteval 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 |
| 476 | template <Category Cat> |
| 477 | constexpr 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 |
| 486 | template <typename Meth> |
| 487 | consteval 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 | |