1//! @file apply_algorithm.hpp
2//! @author ryftchen
3//! @brief The declarations (apply_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 <gsl/gsl_sf.h>
11#include <mpfr.h>
12#include <cstring>
13#include <iostream>
14#include <memory>
15#include <span>
16#else
17#include "application/pch/precompiled_header.hpp"
18#endif // _PRECOMPILED_HEADER
19
20#include "algorithm/include/match.hpp"
21#include "algorithm/include/notation.hpp"
22#include "algorithm/include/optimal.hpp"
23#include "algorithm/include/search.hpp"
24#include "algorithm/include/sort.hpp"
25
26//! @brief The application module.
27namespace application // NOLINT(modernize-concat-nested-namespaces)
28{
29//! @brief Algorithm-applying-related functions in the application module.
30namespace app_algo
31{
32//! @brief Apply match.
33namespace match
34{
35//! @brief The version used to apply.
36const char* const version = algorithm::match::version();
37
38//! @brief Set input parameters.
39namespace input
40{
41//! @brief Single pattern for match methods.
42constexpr std::string_view patternString = "12345";
43} // namespace input
44
45//! @brief Maximum number per line of printing.
46constexpr std::uint32_t maxNumPerLineOfPrint = 50;
47
48//! @brief Builder for the input.
49class InputBuilder
50{
51public:
52 //! @brief Construct a new InputBuilder object.
53 //! @param pattern - single pattern
54 explicit InputBuilder(const std::string_view pattern) :
55 marchingText{std::make_unique<unsigned char[]>(num: maxDigit + 1)},
56 textLen{maxDigit},
57 singlePattern{std::make_unique<unsigned char[]>(num: pattern.length() + 1)},
58 patternLen{static_cast<std::uint32_t>(pattern.length())}
59 {
60 marchingText[0] = '\0';
61 singlePattern[0] = '\0';
62 createMatchingText(text: marchingText.get(), textLen: maxDigit);
63 std::memcpy(dest: singlePattern.get(), src: pattern.data(), n: pattern.length() * sizeof(unsigned char));
64 }
65 //! @brief Destroy the InputBuilder object.
66 virtual ~InputBuilder() { ::mpfr_free_cache(); }
67 //! @brief Construct a new InputBuilder object.
68 InputBuilder(const InputBuilder&) = delete;
69 //! @brief Construct a new InputBuilder object.
70 InputBuilder(InputBuilder&&) = delete;
71 //! @brief The operator (=) overloading of InputBuilder class.
72 //! @return reference of the InputBuilder object
73 InputBuilder& operator=(const InputBuilder&) = delete;
74 //! @brief The operator (=) overloading of InputBuilder class.
75 //! @return reference of the InputBuilder object
76 InputBuilder& operator=(InputBuilder&&) = delete;
77
78 //! @brief Maximum digit for the target text.
79 static constexpr std::uint32_t maxDigit{100'000};
80 //! @brief Get the matching text.
81 //! @return matching text
82 [[nodiscard]] const std::unique_ptr<unsigned char[]>& getMatchingText() const noexcept { return marchingText; }
83 //! @brief Get the length of the matching text.
84 //! @return length of the matching text
85 [[nodiscard]] std::uint32_t getTextLength() const noexcept { return textLen; }
86 //! @brief Get the single pattern.
87 //! @return single pattern
88 [[nodiscard]] const std::unique_ptr<unsigned char[]>& getSinglePattern() const noexcept { return singlePattern; }
89 //! @brief Get the length of the single pattern.
90 //! @return length of the single pattern
91 [[nodiscard]] std::uint32_t getPatternLength() const noexcept { return patternLen; }
92
93private:
94 //! @brief Matching text.
95 const std::unique_ptr<unsigned char[]> marchingText;
96 //! @brief Length of the matching text.
97 const std::uint32_t textLen{0};
98 //! @brief Single pattern.
99 const std::unique_ptr<unsigned char[]> singlePattern;
100 //! @brief Length of the single pattern.
101 const std::uint32_t patternLen{0};
102
103 //! @brief Base number for converting the digit to precision.
104 static constexpr int mpfrBase{10};
105 //! @brief Create the matching text.
106 //! @param text - target matching text
107 //! @param textLen - length of matching text
108 static void createMatchingText(unsigned char* const text, const std::uint32_t textLen)
109 {
110 if (!text || (textLen == 0))
111 {
112 return;
113 }
114
115 ::mpfr_t operand{};
116 ::mpfr_init2(operand, calculatePrecision(digit: textLen));
117 ::mpfr_const_pi(operand, ::MPFR_RNDN);
118 ::mpfr_exp_t decimalLocation = 0;
119 char* const piText = ::mpfr_get_str(nullptr, &decimalLocation, mpfrBase, 0, operand, ::MPFR_RNDN);
120
121 if (std::strlen(s: piText) != 0)
122 {
123 piText[textLen] = '\0';
124 std::memcpy(dest: text, src: piText, n: textLen * sizeof(unsigned char));
125#ifdef _RUNTIME_PRINTING
126 std::string brief(text, text + textLen);
127 if (textLen > 1)
128 {
129 brief = std::string{brief.at(n: 0)} + '.' + brief.substr(pos: 1, n: brief.length());
130 }
131 std::cout << "\nπ " << textLen << " digits:\n"
132 << brief.substr(pos: 0, n: std::min(a: textLen, b: maxNumPerLineOfPrint)) << std::endl;
133 if (textLen > maxNumPerLineOfPrint)
134 {
135 std::cout << "...\n"
136 << ((textLen > (maxNumPerLineOfPrint * 2))
137 ? brief.substr(pos: brief.length() - maxNumPerLineOfPrint, n: brief.length())
138 : brief.substr(pos: maxNumPerLineOfPrint + 1, n: brief.length()))
139 << std::endl;
140 }
141#endif // _RUNTIME_PRINTING
142 }
143 ::mpfr_clear(operand);
144 ::mpfr_free_str(piText);
145 }
146 //! @brief Calculate precision by digit.
147 //! @param digit - digit for the target text
148 //! @return precision converted from digit
149 static int calculatePrecision(const std::uint32_t digit)
150 {
151 return 1 + static_cast<int>(std::ceil(x: static_cast<double>(digit) * std::log2(x: mpfrBase)));
152 }
153};
154} // namespace match
155extern void applyingMatch(const std::vector<std::string>& candidates);
156
157//! @brief Apply notation.
158namespace notation
159{
160//! @brief The version used to apply.
161const char* const version = algorithm::notation::version();
162
163//! @brief Set input parameters.
164namespace input
165{
166//! @brief Infix string for notation methods.
167constexpr std::string_view infixString = "a+b*(c^d-e)^(f+g*h)-i";
168} // namespace input
169
170//! @brief Builder for the input.
171class InputBuilder
172{
173public:
174 //! @brief Construct a new InputBuilder object.
175 //! @param infixNotation - infix notation
176 explicit InputBuilder(const std::string_view infixNotation) : infixNotation{infixNotation}
177 {
178#ifdef _RUNTIME_PRINTING
179 std::cout << "\nInfix notation:\n" << infixNotation << std::endl;
180#endif // _RUNTIME_PRINTING
181 }
182
183 //! @brief Get the infix notation.
184 //! @return infix notation
185 [[nodiscard]] std::string getInfixNotation() const noexcept { return infixNotation; }
186
187private:
188 //! @brief Infix notation.
189 const std::string infixNotation;
190};
191} // namespace notation
192extern void applyingNotation(const std::vector<std::string>& candidates);
193
194//! @brief Apply optimal.
195namespace optimal
196{
197//! @brief The version used to apply.
198const char* const version = algorithm::optimal::version();
199
200//! @brief Alias for the target function.
201using Function = std::function<double(const double)>;
202//! @brief Wrapper for the target function.
203class FuncIntf
204{
205public:
206 //! @brief Construct a new FuncIntf object.
207 FuncIntf() = default;
208 //! @brief Destroy the FuncIntf object.
209 virtual ~FuncIntf() = default;
210 //! @brief Construct a new FuncIntf object.
211 FuncIntf(const FuncIntf&) = default;
212 //! @brief Construct a new FuncIntf object.
213 FuncIntf(FuncIntf&&) noexcept = default;
214 //! @brief The operator (=) overloading of FuncIntf class.
215 //! @return reference of the FuncIntf object
216 FuncIntf& operator=(const FuncIntf&) = default;
217 //! @brief The operator (=) overloading of FuncIntf class.
218 //! @return reference of the FuncIntf object
219 FuncIntf& operator=(FuncIntf&&) noexcept = default;
220
221 //! @brief The operator (()) overloading of FuncIntf class.
222 //! @param x - independent variable
223 //! @return dependent variable
224 virtual double operator()(const double x) const = 0;
225 //! @brief The operator (Function) overloading of FuncIntf class.
226 //! @return Function object
227 virtual explicit operator Function() const
228 {
229 return [this](const double x) { return operator()(x); };
230 }
231};
232
233//! @brief Set input parameters.
234namespace input
235{
236//! @brief Spherical Bessel.
237class SphericalBessel : public FuncIntf
238{
239public:
240 //! @brief The operator (()) overloading of SphericalBessel class.
241 //! @param x - independent variable
242 //! @return dependent variable
243 double operator()(const double x) const override { return ::gsl_sf_bessel_j0(x); }
244
245 //! @brief Left endpoint.
246 static constexpr double range1{0.0};
247 //! @brief Right endpoint.
248 static constexpr double range2{20.0};
249 //! @brief Spherical Bessel function of the first kind.
250 static constexpr std::string_view funcDescr{"f(x)=j₀(x),x∈[0,20] (Spherical Bessel function of the first kind)"};
251};
252} // namespace input
253
254//! @brief Builder for the input.
255class InputBuilder
256{
257public:
258 //! @brief Construct a new Input Builder object.
259 //! @param function - target function
260 //! @param range1 - left endpoint
261 //! @param range2 - right endpoint
262 //! @param funcDescr - function description
263 InputBuilder(
264 Function function,
265 const double range1,
266 const double range2,
267 [[maybe_unused]] const std::string_view funcDescr) :
268 function{std::move(function)}, range1{range1}, range2{range2}
269 {
270#ifdef _RUNTIME_PRINTING
271 std::cout << "\nOptimal function:\n" << funcDescr << std::endl;
272#endif // _RUNTIME_PRINTING
273 }
274
275 //! @brief Get the target function.
276 //! @return target function
277 [[nodiscard]] Function getFunction() const noexcept { return function; }
278 //! @brief Get the pair of ranges.
279 //! @return pair of ranges
280 [[nodiscard]] std::pair<double, double> getRanges() const noexcept { return std::make_pair(x: range1, y: range2); }
281
282private:
283 //! @brief Target function.
284 const Function function;
285 //! @brief Left endpoint.
286 const double range1{0.0};
287 //! @brief Right endpoint.
288 const double range2{0.0};
289};
290} // namespace optimal
291extern void applyingOptimal(const std::vector<std::string>& candidates);
292
293//! @brief Apply search.
294namespace search
295{
296//! @brief The version used to apply.
297const char* const version = algorithm::search::version();
298
299//! @brief Set input parameters.
300namespace input
301{
302//! @brief Minimum of the array for search methods.
303constexpr float arrayRangeMin = -50.0;
304//! @brief Maximum of the array for search methods.
305constexpr float arrayRangeMax = 150.0;
306//! @brief Length of the array for search methods.
307constexpr std::uint32_t arrayLength = 53;
308} // namespace input
309
310//! @brief Maximum alignment length per element of printing.
311constexpr std::uint8_t maxAlignOfPrint = 16;
312//! @brief Maximum columns per row of printing.
313constexpr std::uint8_t maxColumnOfPrint = 5;
314
315//! @brief Builder for the input.
316//! @tparam Elem - type of builder for the target
317template <typename Elem>
318class InputBuilder
319{
320public:
321 //! @brief Construct a new InputBuilder object.
322 //! @param length - length of array
323 //! @param left - left boundary of the array
324 //! @param right - right boundary of the array
325 InputBuilder(const std::uint32_t length, const Elem left, const Elem right) :
326 orderedArray{std::make_unique<Elem[]>(length + 1)}, length{length}
327 {
328 orderedArray[0] = '\0';
329 setOrderedArray(orderedArray.get(), length, left, right);
330 }
331 //! @brief Destroy the InputBuilder object.
332 virtual ~InputBuilder() = default;
333 //! @brief Construct a new InputBuilder object.
334 //! @param rhs - right-hand side
335 InputBuilder(const InputBuilder& rhs) : orderedArray{std::make_unique<Elem[]>(rhs.length + 1)}, length{rhs.length}
336 {
337 orderedArray[0] = '\0';
338 clone(rhs);
339 }
340 //! @brief Construct a new InputBuilder object.
341 InputBuilder(InputBuilder&&) noexcept = default;
342 //! @brief The operator (!=) overloading of InputBuilder class.
343 //! @param rhs - right-hand side
344 //! @return reference of the InputBuilder object
345 InputBuilder<Elem>& operator=(const InputBuilder& rhs)
346 {
347 if (&rhs != this)
348 {
349 clone(rhs);
350 }
351 return *this;
352 }
353 //! @brief The operator (=) overloading of InputBuilder class.
354 //! @return reference of the InputBuilder object
355 InputBuilder& operator=(InputBuilder&&) noexcept = default;
356
357 //! @brief Get the ordered array.
358 //! @return ordered array
359 const std::unique_ptr<Elem[]>& getOrderedArray() const noexcept { return orderedArray; }
360 //! @brief Get the length.
361 //! @return length
362 [[nodiscard]] std::uint32_t getLength() const noexcept { return length; }
363 //! @brief Get the search key.
364 //! @return search key
365 Elem getSearchKey() const noexcept { return orderedArray[length / 2]; }
366 //! @brief Splice from array for printing.
367 //! @param array - target array
368 //! @param length - length of array
369 //! @param fmtBuffer - buffer for printing
370 //! @param bufferSize - size of the buffer
371 //! @return buffer after splicing
372 static char* spliceAll(
373 const Elem* const array, const std::uint32_t length, char* const fmtBuffer, const std::uint32_t bufferSize)
374 {
375 if (!array || (length == 0) || !fmtBuffer || (bufferSize == 0))
376 {
377 return fmtBuffer;
378 }
379
380 std::uint32_t align = 0;
381 for (std::uint32_t i = 0; i < length; ++i)
382 {
383 align = std::max(a: static_cast<std::uint32_t>(std::to_string(*(array + i)).length()), b: align);
384 }
385
386 std::array<char, 16> spliceFmt{};
387 if constexpr (std::is_integral_v<Elem>)
388 {
389 std::snprintf(s: spliceFmt.data(), maxlen: spliceFmt.size(), format: "%%%dd%%c", align + 1);
390 }
391 else if constexpr (std::is_floating_point_v<Elem>)
392 {
393 std::snprintf(s: spliceFmt.data(), maxlen: spliceFmt.size(), format: "%%%d.5f%%c", align + 1);
394 }
395 else
396 {
397 return fmtBuffer;
398 }
399
400 for (std::uint32_t i = 0, offset = 0; i < length; ++i)
401 {
402 const char sep = (((i + 1) % maxColumnOfPrint == 0) && ((i + 1) != length)) ? '\n' : ' ';
403 const int written =
404 std::snprintf(s: fmtBuffer + offset, maxlen: bufferSize - offset, format: spliceFmt.data(), *(array + i), sep);
405 if ((written < 0) || (written >= static_cast<int>(bufferSize - offset)))
406 {
407 break;
408 }
409 offset += written;
410 }
411 return fmtBuffer;
412 }
413
414private:
415 //! @brief Ordered array.
416 const std::unique_ptr<Elem[]> orderedArray{};
417 //! @brief Length of the ordered array.
418 const std::uint32_t length{0};
419
420 //! @brief Deep copy for copy constructor.
421 //! @param rhs - right-hand side
422 void clone(const InputBuilder& rhs) const
423 {
424 if (rhs.orderedArray && orderedArray)
425 {
426 std::memcpy(dest: orderedArray.get(), src: rhs.orderedArray.get(), n: length * sizeof(Elem));
427 }
428 }
429 //! @brief Set the ordered array.
430 //! @param array - ordered array
431 //! @param length - length of the ordered array
432 //! @param left - left boundary of the ordered array
433 //! @param right - left right of the ordered array
434 static void setOrderedArray(Elem* const array, const std::uint32_t length, const Elem left, const Elem right)
435 requires std::is_integral_v<Elem>
436 {
437 if (!array || (length == 0) || (left > right))
438 {
439 return;
440 }
441
442 const std::span<Elem> sequence{array, length};
443 std::for_each(
444 sequence.begin(),
445 sequence.end(),
446 [engine = std::ranlux48(std::random_device{}()),
447 dist = std::uniform_int_distribution<Elem>(left, right)](auto& elem) mutable { elem = dist(engine); });
448 std::sort(sequence.begin(), sequence.end());
449#ifdef _RUNTIME_PRINTING
450 const std::uint32_t bufferSize = sequence.size() * maxAlignOfPrint;
451 std::vector<char> fmtBuffer(bufferSize + 1);
452 std::cout << "\nGenerate " << sequence.size() << " ordered integral numbers from " << left << " to " << right
453 << ":\n"
454 << spliceAll(array: sequence.data(), length: sequence.size(), fmtBuffer: fmtBuffer.data(), bufferSize: bufferSize + 1) << std::endl;
455#endif // _RUNTIME_PRINTING
456 }
457 //! @brief Set the ordered array.
458 //! @param array - ordered array
459 //! @param length - length of the ordered array
460 //! @param left - left boundary of the ordered array
461 //! @param right - left right of the ordered array
462 static void setOrderedArray(Elem* const array, const std::uint32_t length, const Elem left, const Elem right)
463 requires std::is_floating_point_v<Elem>
464 {
465 if (!array || (length == 0) || (left > right))
466 {
467 return;
468 }
469
470 const std::span<Elem> sequence{array, length};
471 std::for_each(
472 sequence.begin(),
473 sequence.end(),
474 [engine = std::ranlux48(std::random_device{}()),
475 dist = std::uniform_real_distribution<Elem>(left, right)](auto& elem) mutable { elem = dist(engine); });
476 std::sort(sequence.begin(), sequence.end());
477#ifdef _RUNTIME_PRINTING
478 const std::uint32_t bufferSize = sequence.size() * maxAlignOfPrint;
479 std::vector<char> fmtBuffer(bufferSize + 1);
480 std::cout << "\nGenerate " << sequence.size() << " ordered floating point numbers from " << left << " to "
481 << right << ":\n"
482 << spliceAll(array: sequence.data(), length: sequence.size(), fmtBuffer: fmtBuffer.data(), bufferSize: bufferSize + 1) << std::endl;
483#endif // _RUNTIME_PRINTING
484 }
485};
486} // namespace search
487extern void applyingSearch(const std::vector<std::string>& candidates);
488
489//! @brief Apply sort.
490namespace sort
491{
492//! @brief The version used to apply.
493const char* const version = algorithm::sort::version();
494
495//! @brief Set input parameters.
496namespace input
497{
498//! @brief Minimum of the array for sort methods.
499constexpr std::int32_t arrayRangeMin = -50;
500//! @brief Maximum of the array for sort methods.
501constexpr std::int32_t arrayRangeMax = 150;
502//! @brief Length of the array for sort methods.
503constexpr std::uint32_t arrayLength = 53;
504} // namespace input
505
506//! @brief Maximum alignment length per element of printing.
507constexpr std::uint8_t maxAlignOfPrint = 16;
508//! @brief Maximum columns per row of printing.
509constexpr std::uint8_t maxColumnOfPrint = 10;
510
511//! @brief Builder for the input.
512//! @tparam Elem - type of builder for the target
513template <typename Elem>
514class InputBuilder
515{
516public:
517 //! @brief Construct a new InputBuilder object.
518 //! @param length - length of array
519 //! @param left - left boundary of the array
520 //! @param right - right boundary of the array
521 InputBuilder(const std::uint32_t length, const Elem left, const Elem right) :
522 randomArray{std::make_unique<Elem[]>(length + 1)}, length{length}
523 {
524 randomArray[0] = '\0';
525 setRandomArray(randomArray.get(), length, left, right);
526 }
527 //! @brief Destroy the InputBuilder object.
528 virtual ~InputBuilder() = default;
529 //! @brief Construct a new InputBuilder object.
530 //! @param rhs - right-hand side
531 InputBuilder(const InputBuilder& rhs) : randomArray{std::make_unique<Elem[]>(rhs.length + 1)}, length{rhs.length}
532 {
533 randomArray[0] = '\0';
534 clone(rhs);
535 }
536 //! @brief Construct a new InputBuilder object.
537 InputBuilder(InputBuilder&&) noexcept = default;
538 //! @brief The operator (!=) overloading of InputBuilder class.
539 //! @param rhs - right-hand side
540 //! @return reference of the InputBuilder object
541 InputBuilder<Elem>& operator=(const InputBuilder& rhs)
542 {
543 if (&rhs != this)
544 {
545 clone(rhs);
546 }
547 return *this;
548 }
549 //! @brief The operator (=) overloading of InputBuilder class.
550 //! @return reference of the InputBuilder object
551 InputBuilder& operator=(InputBuilder&&) noexcept = default;
552
553 //! @brief Get the random array.
554 //! @return random array
555 const std::unique_ptr<Elem[]>& getRandomArray() const noexcept { return randomArray; }
556 //! @brief Get the length.
557 //! @return length
558 [[nodiscard]] std::uint32_t getLength() const noexcept { return length; }
559 //! @brief Splice from array for printing.
560 //! @param array - target array
561 //! @param length - length of array
562 //! @param fmtBuffer - buffer for printing
563 //! @param bufferSize - size of the buffer
564 //! @return buffer after splicing
565 static char* spliceAll(
566 const Elem* const array, const std::uint32_t length, char* const fmtBuffer, const std::uint32_t bufferSize)
567 {
568 if (!array || (length == 0) || !fmtBuffer || (bufferSize == 0))
569 {
570 return fmtBuffer;
571 }
572
573 std::uint32_t align = 0;
574 for (std::uint32_t i = 0; i < length; ++i)
575 {
576 align = std::max(a: static_cast<std::uint32_t>(std::to_string(*(array + i)).length()), b: align);
577 }
578
579 std::array<char, 16> spliceFmt{};
580 if constexpr (std::is_integral_v<Elem>)
581 {
582 std::snprintf(s: spliceFmt.data(), maxlen: spliceFmt.size(), format: "%%%dd%%c", align + 1);
583 }
584 else if constexpr (std::is_floating_point_v<Elem>)
585 {
586 std::snprintf(s: spliceFmt.data(), maxlen: spliceFmt.size(), format: "%%%d.5f%%c", align + 1);
587 }
588 else
589 {
590 return fmtBuffer;
591 }
592
593 for (std::uint32_t i = 0, offset = 0; i < length; ++i)
594 {
595 const char sep = (((i + 1) % maxColumnOfPrint == 0) && ((i + 1) != length)) ? '\n' : ' ';
596 const int written =
597 std::snprintf(s: fmtBuffer + offset, maxlen: bufferSize - offset, format: spliceFmt.data(), *(array + i), sep);
598 if ((written < 0) || (written >= static_cast<int>(bufferSize - offset)))
599 {
600 break;
601 }
602 offset += written;
603 }
604 return fmtBuffer;
605 }
606
607private:
608 //! @brief Random array.
609 const std::unique_ptr<Elem[]> randomArray{};
610 //! @brief Length of the random array.
611 const std::uint32_t length{0};
612
613 //! @brief Deep copy for copy constructor.
614 //! @param rhs - right-hand side
615 void clone(const InputBuilder& rhs) const
616 {
617 if (rhs.randomArray && randomArray)
618 {
619 std::memcpy(dest: randomArray.get(), src: rhs.randomArray.get(), n: length * sizeof(Elem));
620 }
621 }
622 //! @brief Set the random array.
623 //! @param array - random array
624 //! @param length - length of the random array
625 //! @param left - left boundary of the random array
626 //! @param right - left right of the random array
627 static void setRandomArray(Elem* const array, const std::uint32_t length, const Elem left, const Elem right)
628 requires std::is_integral_v<Elem>
629 {
630 if (!array || (length == 0) || (left > right))
631 {
632 return;
633 }
634
635 const std::span<Elem> sequence{array, length};
636 std::for_each(
637 sequence.begin(),
638 sequence.end(),
639 [engine = std::ranlux48(std::random_device{}()),
640 dist = std::uniform_int_distribution<Elem>(left, right)](auto& elem) mutable { elem = dist(engine); });
641#ifdef _RUNTIME_PRINTING
642 const std::uint32_t bufferSize = sequence.size() * maxAlignOfPrint;
643 std::vector<char> fmtBuffer(bufferSize + 1);
644 std::cout << "\nGenerate " << sequence.size() << " random integral numbers from " << left << " to " << right
645 << ":\n"
646 << spliceAll(array: sequence.data(), length: sequence.size(), fmtBuffer: fmtBuffer.data(), bufferSize: bufferSize + 1) << std::endl;
647#endif // _RUNTIME_PRINTING
648 }
649 //! @brief Set the random array.
650 //! @param array - random array
651 //! @param length - length of the random array
652 //! @param left - left boundary of the random array
653 //! @param right - left right of the random array
654 static void setRandomArray(Elem* const array, const std::uint32_t length, const Elem left, const Elem right)
655 requires std::is_floating_point_v<Elem>
656 {
657 if (!array || (length == 0) || (left > right))
658 {
659 return;
660 }
661
662 const std::span<Elem> sequence{array, length};
663 std::for_each(
664 sequence.begin(),
665 sequence.end(),
666 [engine = std::ranlux48(std::random_device{}()),
667 dist = std::uniform_real_distribution<Elem>(left, right)](auto& elem) mutable { elem = dist(engine); });
668#ifdef _RUNTIME_PRINTING
669 const std::uint32_t bufferSize = sequence.size() * maxAlignOfPrint;
670 std::vector<char> fmtBuffer(bufferSize + 1);
671 std::cout << "\nGenerate " << sequence.size() << " random floating point numbers from " << left << " to "
672 << right << ":\n"
673 << spliceAll(array: sequence.data(), length: sequence.size(), fmtBuffer: fmtBuffer.data(), bufferSize: bufferSize + 1) << std::endl;
674#endif // _RUNTIME_PRINTING
675 }
676};
677} // namespace sort
678extern void applyingSort(const std::vector<std::string>& candidates);
679} // namespace app_algo
680} // namespace application
681