33#include < format>
44#include < print>
55#include < sstream>
6+ #include < utility>
7+
8+ template <typename T>
9+ struct bounds {
10+ T lower;
11+ T upper;
12+ bool contains (T x) const {
13+ return (x >= lower && x <= upper);
14+ }
15+ };
16+
17+ namespace std {
18+
19+ template <typename T, typename Char>
20+ requires std::formattable<T, Char>
21+ struct formatter <bounds<T>, Char> {
22+ std::formatter<T, Char> underlying_;
23+
24+ constexpr auto parse (std::basic_format_parse_context<Char> &ctx) {
25+ return underlying_.parse (ctx);
26+ }
27+
28+ template <typename FormatContext>
29+ auto format (const bounds<T> &b, FormatContext &ctx) const {
30+ auto out = ctx.out ();
31+ out = underlying_.format (b.lower , ctx);
32+ for (const char &c : std::string (" .. " )) {
33+ *out++ = Char (c);
34+ }
35+ out = underlying_.format (b.upper , ctx);
36+ return out;
37+ }
38+ };
39+
40+ } // namespace std
641
742namespace partdiff {
843
@@ -11,19 +46,15 @@ namespace partdiff {
1146 return static_cast <U>(v);
1247 }
1348
14- static constexpr uint64_t min_interlines = 0 ;
15- static constexpr uint64_t max_interlines = 10240 ;
16- static constexpr uint64_t min_iteration = 1 ;
17- static constexpr uint64_t max_iteration = 200000 ;
18- static constexpr uint64_t min_threads = 1 ;
19- static constexpr uint64_t max_threads = 1024 ;
20- static constexpr double min_accuracy = 1e-4 ;
21- static constexpr double max_accuracy = 1e-20 ;
22-
2349 using calculation_method = calculation_options::calculation_method;
2450 using perturbation_function = calculation_options::perturbation_function;
2551 using termination_condition = calculation_options::termination_condition;
2652
53+ static constexpr bounds<uint64_t > interlines_bounds{0 , 10240 };
54+ static constexpr bounds<uint64_t > iteration_bounds{1 , 200000 };
55+ static constexpr bounds<uint64_t > thread_bounds{1 , 1024 };
56+ static constexpr bounds<double > accuracy_bounds{1e-20 , 1e-4 };
57+
2758 argument_parser::argument_parser (const int argc, char const *argv[])
2859 : app_name(argv[0 ]),
2960 args (argv + 1 , argv + argc) {
@@ -69,7 +100,7 @@ namespace partdiff {
69100 }
70101 if (this ->options .termination == termination_condition::accuracy) {
71102 parse_param (argument_index::term_accuracy, args[5 ]);
72- this ->options .term_iteration = max_iteration ;
103+ this ->options .term_iteration = iteration_bounds. upper ;
73104 } else {
74105 parse_param (argument_index::term_iteration, args[5 ]);
75106 this ->options .term_accuracy = 0.0 ;
@@ -89,22 +120,12 @@ namespace partdiff {
89120
90121 void argument_parser::fill_argument_descriptions () {
91122
92- auto scientific_double = [](double val) {
93- auto temp = std::format (" {:.0e}" , val);
94- int epos = temp.find (" e" );
95- std::string mantissa_str = temp.substr (0 , epos);
96- std::string exponent_str = temp.substr (epos + 1 , temp.length () - epos - 1 );
97- int exponent = stoi (exponent_str);
98- return mantissa_str + " e" + std::to_string (exponent);
99- };
100-
101123 constexpr int indent_width = 17 ;
102124 const std::string indent = std::format (" {:{}s}" , " " , indent_width);
103125
104126 auto number = &(this ->options .number );
105- this ->add_argument_description (" num" , number,
106- std::format (" number of threads ({:d} .. {:d})" , min_threads, max_threads),
107- [number] { return (*number >= min_threads && *number <= max_threads); });
127+ this ->add_argument_description (" num" , number, std::format (" number of threads ({:d})" , thread_bounds),
128+ [number] { return (thread_bounds.contains (*number)); });
108129
109130 auto method = &(this ->options .method );
110131 this ->add_argument_description (
@@ -116,12 +137,11 @@ namespace partdiff {
116137 [method] { return (*method == calculation_method::gauss_seidel || *method == calculation_method::jacobi); });
117138
118139 auto interlines = &(this ->options .interlines );
119- this ->add_argument_description (
120- " lines" , interlines,
121- std::format (" number of interlines ({1:d} .. {2:d})\n "
122- " {0}matrixsize = (interlines * 8) + 9" ,
123- indent, min_interlines, max_interlines),
124- [interlines] { return (*interlines >= min_interlines && *interlines <= max_interlines); });
140+ this ->add_argument_description (" lines" , interlines,
141+ std::format (" number of interlines ({1:d})\n "
142+ " {0}matrixsize = (interlines * 8) + 9" ,
143+ indent, interlines_bounds),
144+ [interlines] { return (interlines_bounds.contains (*interlines)); });
125145
126146 auto pert_func = &(this ->options .pert_func );
127147 this ->add_argument_description (
@@ -146,22 +166,18 @@ namespace partdiff {
146166 *termination == termination_condition::iterations);
147167 });
148168
149- this ->add_argument_description (" acc/iter" ,
150- std::format (" depending on term:\n "
151- " {0}accuracy: {1:s} .. {2:s}\n "
152- " {0}iterations: {3:d} .. {4:d}\n " ,
153- indent, scientific_double (min_accuracy), scientific_double (max_accuracy),
154- min_iteration, max_iteration));
169+ this ->add_argument_description (" acc/iter" , std::format (" depending on term:\n "
170+ " {0}accuracy: {1:.0e}\n "
171+ " {0}iterations: {2:d}\n " ,
172+ indent, accuracy_bounds, iteration_bounds));
155173
156174 auto term_accuracy = &(this ->options .term_accuracy );
157- this ->add_argument_description (" acc" , term_accuracy, std::nullopt , [term_accuracy] {
158- return (*term_accuracy >= max_accuracy && *term_accuracy <= min_accuracy);
159- });
175+ this ->add_argument_description (" acc" , term_accuracy, std::nullopt ,
176+ [term_accuracy] { return (accuracy_bounds.contains (*term_accuracy)); });
160177
161178 auto term_iteration = &(this ->options .term_iteration );
162- this ->add_argument_description (" iter" , term_iteration, std::nullopt , [term_iteration] {
163- return (*term_iteration >= min_iteration && *term_iteration <= max_iteration);
164- });
179+ this ->add_argument_description (" iter" , term_iteration, std::nullopt ,
180+ [term_iteration] { return (iteration_bounds.contains (*term_iteration)); });
165181 }
166182
167183 void argument_parser::add_argument_description (std::string name, std::optional<std::string> description_for_usage) {
0 commit comments