@@ -152,7 +152,7 @@ bool is_exact_integer(float_type x) {
152152 return static_cast <float_type>(i) == x;
153153}
154154
155- // Nouvelle version template de describe
155+ // New template version of describe
156156template <typename T>
157157void describe (const std::variant<std::vector<TestCase<float >>, std::vector<TestCase<double >>> &numbers,
158158 const std::vector<BenchArgs<T>> &args,
@@ -166,6 +166,8 @@ void describe(const std::variant<std::vector<TestCase<float>>, std::vector<TestC
166166 }
167167 std::vector<size_t > sizes (lines.size (), std::numeric_limits<size_t >::max ());
168168 std::vector<std::string> shortest (lines.size ());
169+ std::vector<size_t > min_digits (lines.size (), std::numeric_limits<size_t >::max ());
170+ std::vector<std::string> min_digits_str (lines.size ());
169171 std::vector<std::tuple<std::string, size_t , double , bool >> results;
170172 size_t min_size = std::numeric_limits<size_t >::max ();
171173 for (const auto &algo : args) {
@@ -182,6 +184,12 @@ void describe(const std::variant<std::vector<TestCase<float>>, std::vector<TestC
182184 sizes[i] = len;
183185 shortest[i].assign (bufspan.data (), len);
184186 }
187+ // Check for minimal number of significant digits
188+ size_t digits = count_significant_digits (std::string_view (bufspan.data (), len));
189+ if (min_digits[i] > digits) {
190+ min_digits[i] = digits;
191+ min_digits_str[i].assign (bufspan.data (), len);
192+ }
185193 total_size += len;
186194 std::string_view sv (buffer.data (), len);
187195 auto parsed = parse_float<T>(sv);
@@ -194,22 +202,25 @@ void describe(const std::variant<std::vector<TestCase<float>>, std::vector<TestC
194202 results.emplace_back (algo.name , total_size, avg, precise);
195203 if (precise && total_size < min_size) min_size = total_size;
196204 }
197- constexpr size_t warning_max = 1 ;
205+ std::map<std::string, std::tuple< bool , bool >> algo_results ;
198206 for (const auto &algo : args) {
199207 if (!algo.used ) continue ;
200208 if (algo_filtered_out (algo.name , algo_filter)) continue ;
201209 size_t howmany = 0 ;
210+ size_t howmany_digits = 0 ;
202211 std::vector<char > buffer (100 );
203212 std::span<char > bufspan (buffer);
204213 size_t worse_than_shortest = 0 ;
214+ size_t digits_worse_than_min = 0 ;
205215 for (size_t i = 0 ; i < lines.size (); ++i) {
206216 const auto &d = lines[i];
207217 int len = algo.func (d.value , bufspan);
218+ // Case where the string is longer than the shortest
208219 if (sizes[i] < len) {
209220 howmany++;
210221 bool new_record = (len > worse_than_shortest + sizes[i]);
211222 worse_than_shortest = (std::max)(worse_than_shortest, len - sizes[i]);
212- if (new_record || howmany <= warning_max ) {
223+ if (new_record) {
213224 fmt::print (stderr, " Warning: algorithm {} produced a longer string ({}) than the shortest ({}) for value {}\n " ,
214225 algo.name , len, sizes[i], d.value );
215226 fmt::print (stderr, " Shortest: '{}'\n " , shortest[i]);
@@ -223,18 +234,44 @@ void describe(const std::variant<std::vector<TestCase<float>>, std::vector<TestC
223234 fmt::print (stderr, " BUG! Parsed values differ: {} vs {}\n " ,
224235 parsed_ref.value (), parsed_this.value ());
225236 }
237+ }
238+ }
239+ // Case where the string has more significant digits than the minimum
240+ size_t digits = count_significant_digits (std::string_view (bufspan.data (), len));
241+ if (min_digits[i] < digits) {
226242
243+ bool new_record = (len > digits_worse_than_min + sizes[i]);
244+ digits_worse_than_min = (std::max)(digits_worse_than_min, digits - min_digits[i]);
245+ if (new_record) {
246+ fmt::print (stderr, " Warning: algorithm {} produced a string with more significant digits ({}) than the minimum ({}) for value {}\n " ,
247+ algo.name , digits, min_digits[i], d.value );
248+ fmt::print (stderr, " Min digits: '{}'\n " , min_digits_str[i]);
249+ std::string_view this_answer (bufspan.data (), len);
250+ fmt::print (stderr, " Produced: '{}'\n " , this_answer);
227251 }
228252 }
229253 }
230- if (howmany > warning_max ) {
254+ if (howmany > 0 ) {
231255 fmt::print (stderr, " Warning: algorithm {} produced longer strings than the shortest for {} values, worst gap is {} characters\n " ,
232256 algo.name , howmany, worse_than_shortest);
233257 }
258+ if (howmany_digits > 0 ) {
259+ fmt::print (stderr, " Warning: algorithm {} produced more significant digits than the minimum for {} values, worst gap is {} digits\n " ,
260+ algo.name , howmany_digits, digits_worse_than_min);
261+ }
262+ if (howmany > 0 || howmany_digits > 0 ) {
263+ fmt::println (" ---" );
264+ }
265+ algo_results[algo.name ] = std::make_tuple (howmany == 0 , howmany_digits == 0 );
266+
234267 }
235268 for (const auto &[name, total_size, avg, precise] : results) {
236- bool is_min = (precise && total_size == min_size);
237- fmt::print (" {:<18} {:>12} ({:>5.3f} chars/f){}{}\n " , name, total_size, avg, is_min ? " [minimal]" : " " , precise ? " [precise]" : " [imprecise]" );
269+ auto [is_shortest, is_min_digits_algo] = algo_results[name];
270+ fmt::print (" {:<18} {:>12} ({:>5.3f} chars/f) {:<18} {:<12} {:<15}\n " ,
271+ name, total_size, avg,
272+ is_shortest ? " [minimal string]" : " [non minimal]" ,
273+ precise ? " [precise]" : " [imprecise]" ,
274+ is_min_digits_algo ? " [min digits]" : " [non min digits]" );
238275 }
239276 fmt::println (" count: {}, 32-bit ints: {}, 64-bit ints: {}" , lines.size (), integers32, integers64);
240277 }, numbers);
0 commit comments