.. _program_listing_file_src_utils_MiscUtils.hpp: Program Listing for File MiscUtils.hpp ====================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/utils/MiscUtils.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef MISCUTILS_HPP #define MISCUTILS_HPP #include #include #include #include #include #include #include #include namespace utils { inline auto approxEqual(double a, double b, double tol = 1e-6) -> bool { return std::fabs(a - b) < tol; } inline auto splitSearchPath(const std::string& searchPath) -> std::vector { #ifdef _WIN32 constexpr char sep = ';'; #else constexpr char sep = ':'; #endif std::vector dirs; std::size_t start = 0; while (start <= searchPath.size()) { const auto end = std::min(searchPath.find(sep, start), searchPath.size()); if (end > start) { dirs.push_back(searchPath.substr(start, end - start)); } start = end + 1; } return dirs; } inline auto getFilePath(const std::string& fileName, const std::string& prefix = "") { std::filesystem::path filePath(fileName); if (std::filesystem::exists(filePath)) { return filePath; } if (filePath.is_absolute()) { return std::filesystem::path(); } auto *slugDir = std::getenv("SLUG_DIR"); // NOLINT(concurrency-mt-unsafe) -- no thread-safe standard alternative; only ever called during single-threaded setup if (slugDir != nullptr) { auto slugDirPath = std::filesystem::path(slugDir) / std::filesystem::path(prefix) / filePath; if (std::filesystem::exists(slugDirPath)) { return slugDirPath; } } auto *slugDataPath = std::getenv("SLUG_DATA_PATH"); // NOLINT(concurrency-mt-unsafe) -- see SLUG_DIR above if (slugDataPath != nullptr) { for (const auto& dir : splitSearchPath(slugDataPath)) { auto dataDirPath = std::filesystem::path(dir) / std::filesystem::path(prefix) / filePath; if (std::filesystem::exists(dataDirPath)) { return dataDirPath; } } } const std::string repoDir = REPO_DIR; if (!repoDir.empty()) { auto repoDirPath = std::filesystem::path(repoDir) / std::filesystem::path(prefix) / filePath; if (std::filesystem::exists(repoDirPath)) { return repoDirPath; } } return std::filesystem::path(); } inline auto romanToInt(const std::string& s) -> int { if (s.empty()) { return 0; } const auto romanVal = [](char c) -> int { switch (c) { case 'I': return 1; case 'V': return 5; case 'X': return 10; case 'L': return 50; case 'C': return 100; case 'D': return 500; case 'M': return 1000; default: return 0; } }; int result = 0; int prev = 0; for (auto it = s.rbegin(); it != s.rend(); ++it) { // NOLINT(modernize-loop-convert) -- range-based reverse iteration requires C++20 views::reverse const int val = romanVal(*it); if (val == 0) { return 0; } result += (val < prev) ? -val : val; prev = val; } return result; } inline auto logspace(const double xMin, const double xMax, const std::size_t n) -> std::vector { std::vector result(n); result[0] = xMin; // NOLINT(cppcoreguidelines-pro-bounds-avoid-unchecked-container-access) -- n >= 2 by this function's own (unchecked) precondition, so result is non-empty result[n - 1] = xMax; // NOLINT(cppcoreguidelines-pro-bounds-avoid-unchecked-container-access) -- n >= 2 by this function's own (unchecked) precondition, so n - 1 < result.size() const double logXMin = std::log(xMin); const double logXMax = std::log(xMax); const double dLogX = (logXMax - logXMin) / static_cast(n - 1); for (std::size_t i = 1; i < n - 1; ++i) { result[i] = std::exp(logXMin + (static_cast(i) * dLogX)); // NOLINT(cppcoreguidelines-pro-bounds-avoid-unchecked-container-access) -- i < n - 1 < n == result.size() by the loop bound } return result; } inline auto minNonZeroMagnitude(const std::vector& v, const double fallback = 1.0) -> double { double m = std::numeric_limits::infinity(); for (const double x : v) { if (x != 0.0) { m = std::min(m, std::abs(x)); } } return std::isfinite(m) ? m : fallback; } template auto integrandScale(const F& f, const std::vector& points) -> double { constexpr double maxScaled = 1e300; double scale = std::numeric_limits::infinity(); double maxAbs = 0.0; for (const double x : points) { const auto v = f(x); scale = std::min(scale, minNonZeroMagnitude(v, scale)); for (const double e : v) { maxAbs = std::max(maxAbs, std::abs(e)); } } if (!std::isfinite(scale)) { return 1.0; } return std::max(scale, maxAbs / maxScaled); } } // namespace utils #endif // MISCUTILS_HPP