accept denormal floating point numbers in tokenizer class and utils::numeric()

This commit is contained in:
Axel Kohlmeyer
2025-06-04 21:07:18 -04:00
parent b3f160c118
commit f5b64118cc
2 changed files with 16 additions and 1 deletions

View File

@ -19,6 +19,8 @@
#include "fmt/format.h" #include "fmt/format.h"
#include "utils.h" #include "utils.h"
#include <cmath>
#include <cstdlib>
#include <utility> #include <utility>
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
@ -365,6 +367,11 @@ double ValueTokenizer::next_double()
return val; return val;
// rethrow exceptions from std::stod() // rethrow exceptions from std::stod()
} catch (std::out_of_range const &) { } catch (std::out_of_range const &) {
// could be a denormal number. try again with std::strtod().
char *end;
auto val = std::strtod(current.c_str(), &end);
// return value of denormal
if ((val != 0.0) && (val > -HUGE_VAL) && (val < HUGE_VAL)) return val;
throw InvalidFloatException(current); throw InvalidFloatException(current);
} catch (std::invalid_argument const &) { } catch (std::invalid_argument const &) {
throw InvalidFloatException(current); throw InvalidFloatException(current);

View File

@ -34,6 +34,8 @@
#include <cctype> #include <cctype>
#include <cerrno> #include <cerrno>
#include <cmath>
#include <cstdlib>
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include <stdexcept> #include <stdexcept>
@ -529,7 +531,7 @@ double utils::numeric(const char *file, int line, const std::string &str, bool d
lmp->error->all(file, line, msg); lmp->error->all(file, line, msg);
} }
double rv = 0; double rv = 0.0;
auto msg = fmt::format("Floating point number {} in input script or data file is invalid", buf); auto msg = fmt::format("Floating point number {} in input script or data file is invalid", buf);
try { try {
std::size_t endpos; std::size_t endpos;
@ -546,6 +548,12 @@ double utils::numeric(const char *file, int line, const std::string &str, bool d
else else
lmp->error->all(file, line, msg); lmp->error->all(file, line, msg);
} catch (std::out_of_range const &) { } catch (std::out_of_range const &) {
// could be a denormal number. try again with std::strtod().
char *end;
rv = std::strtod(buf.c_str(), &end);
// return value if denormal
if ((rv != 0.0) && (rv > -HUGE_VAL) && (rv < HUGE_VAL)) return rv;
msg = fmt::format("Floating point number {} in input script or data file is out of range", buf); msg = fmt::format("Floating point number {} in input script or data file is out of range", buf);
if (do_abort) if (do_abort)
lmp->error->one(file, line, msg); lmp->error->one(file, line, msg);