Skip to content
Snippets Groups Projects
Commit a0e987b3 authored by Dmitri Naumov's avatar Dmitri Naumov
Browse files

[App] TD; Do not convert tolerances to double.

Pass the value directly instead and only check if the string
convertible to a double if not empty.

This avoids possible losses due to conversion.
parent a5893803
No related branches found
No related tags found
No related merge requests found
...@@ -23,21 +23,32 @@ ...@@ -23,21 +23,32 @@
namespace namespace
{ {
/// Safe conversion of a double to a string using decimal or decimal exponent /// Test if the given string is convertible to a valid double value, not a NaN.
/// notation. See std::snprintf() for details for "%g" conversion specifier. bool isConvertibleToDouble(std::string const& s)
/// \note std::to_string uses "%f" conversion specifier which is not sufficient
/// for small numbers like 1e-15.
std::string convert_to_string(double const& value)
{ {
// TODO (naumov) Replace this with fmt library. std::size_t pos = 0;
char buffer[32]; double value;
int const chars_written = try
std::snprintf(buffer, sizeof(buffer), "%g", value);
if (chars_written < 0 || chars_written >= static_cast<int>(sizeof(buffer)))
{ {
OGS_FATAL("Could not convert a value to string."); value = std::stod(s, &pos);
} }
return std::string{buffer}; catch (...)
{
OGS_FATAL("The given string '%s' is not convertible to double.",
s.c_str());
}
if (pos != s.size())
{
OGS_FATAL(
"Only %d characters were used for double conversion of string '%s'",
pos, s.c_str());
}
if (std::isnan(value))
{
OGS_FATAL("The given string '%s' results in a NaN value.", s.c_str());
}
return true;
} }
/// Wraps a string into double ticks. /// Wraps a string into double ticks.
...@@ -172,23 +183,35 @@ TestDefinition::TestDefinition(BaseLib::ConfigTree const& config_tree, ...@@ -172,23 +183,35 @@ TestDefinition::TestDefinition(BaseLib::ConfigTree const& config_tree,
std::string const& reference_filename = std::string const& reference_filename =
BaseLib::joinPaths(reference_path, filename); BaseLib::joinPaths(reference_path, filename);
auto const& absolute_tolerance = auto const absolute_tolerance =
//! \ogs_file_param{prj__test_definition__vtkdiff__absolute_tolerance} //! \ogs_file_param{prj__test_definition__vtkdiff__absolute_tolerance}
vtkdiff_config.getConfigParameterOptional<double>( vtkdiff_config.getConfigParameter<std::string>("absolute_tolerance",
"absolute_tolerance"); "");
if (!absolute_tolerance.empty() &&
!isConvertibleToDouble(absolute_tolerance))
{
OGS_FATAL(
"The absolute tolerance value '%s' is not convertible to "
"double.",
absolute_tolerance.c_str());
}
std::string const absolute_tolerance_parameter = std::string const absolute_tolerance_parameter =
absolute_tolerance == boost::none "--abs " + absolute_tolerance;
? ""
: "--abs " + convert_to_string(*absolute_tolerance);
auto const& relative_tolerance = auto const relative_tolerance =
//! \ogs_file_param{prj__test_definition__vtkdiff__relative_tolerance} //! \ogs_file_param{prj__test_definition__vtkdiff__relative_tolerance}
vtkdiff_config.getConfigParameterOptional<double>( vtkdiff_config.getConfigParameter<std::string>("relative_tolerance",
"relative_tolerance"); "");
if (!relative_tolerance.empty() &&
!isConvertibleToDouble(relative_tolerance))
{
OGS_FATAL(
"The relative tolerance value '%s' is not convertible to "
"double.",
relative_tolerance.c_str());
}
std::string const relative_tolerance_parameter = std::string const relative_tolerance_parameter =
relative_tolerance == boost::none "--rel " + relative_tolerance;
? ""
: "--rel " + convert_to_string(*relative_tolerance);
// //
// Construct command line. // Construct command line.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment