From d716f68382e963b2ab22433e01b52ed3ceca32e7 Mon Sep 17 00:00:00 2001 From: Gary Wolfman Date: Sun, 3 May 2026 23:54:26 -0400 Subject: [PATCH 1/2] refactor(tier3): split common/common.h; clean includes and warnings Extract linalg type aliases into linalg/linalg_types.h and XML serialization templates into common/serialization.h. Lean common/common.h retains only the STL includes, Observation/StateIndex typedefs, and the math/constants.h include. Update all consumers (hmm.h, calculator.h, trainer.h, segmental_kmeans_trainer.h, numerical_stability.h, IO headers, src/common/common.cpp, tests/test_common.cpp) to include the appropriate new headers directly. Remove redundant common/common.h includes from test_pareto_distribution.cpp and test_rayleigh_distribution.cpp; both already get Observation transitively through their distribution header. Resolve all clean-build warnings: - benchmarks/src/simple_benchmark.cpp: cast nodiscard getProbability to void - benchmarks/src/libhmm_vs_hmmlib_benchmark.cpp: discard unused HMMLib viterbi return value - benchmarks/src/classic_problems_benchmark.cpp: remove unused local and private field ClassicHMMProblems problems - benchmarks/src/threeway_benchmark.cpp: discard unused HMMLib viterbi return value - tools/fb_contour_sweep.cpp, tools/hotspot_breakdown.cpp: mark FB_MAX_REDUCE_FORCE_PAIRWISE_MAX_STATES [[maybe_unused]] (only active under experimental preprocessor flags) Co-Authored-By: Oz --- benchmarks/src/classic_problems_benchmark.cpp | 4 - benchmarks/src/libhmm_vs_hmmlib_benchmark.cpp | 2 +- benchmarks/src/simple_benchmark.cpp | 2 +- benchmarks/src/threeway_benchmark.cpp | 2 +- include/libhmm/calculators/calculator.h | 2 +- include/libhmm/common/common.h | 253 +----------------- include/libhmm/common/serialization.h | 169 ++++++++++++ include/libhmm/hmm.h | 2 +- include/libhmm/io/xml_file_reader.h | 1 - include/libhmm/io/xml_file_writer.h | 1 - include/libhmm/libhmm.h | 6 +- include/libhmm/linalg/linalg_types.h | 40 +++ include/libhmm/math/constants.h | 5 + include/libhmm/math/numerical_stability.h | 2 +- .../training/segmental_kmeans_trainer.h | 2 +- include/libhmm/training/trainer.h | 2 +- src/common/common.cpp | 2 +- tests/common/test_common.cpp | 2 +- .../test_pareto_distribution.cpp | 1 - .../test_rayleigh_distribution.cpp | 1 - tools/fb_contour_sweep.cpp | 2 +- tools/hotspot_breakdown.cpp | 2 +- 22 files changed, 241 insertions(+), 264 deletions(-) create mode 100644 include/libhmm/common/serialization.h create mode 100644 include/libhmm/linalg/linalg_types.h diff --git a/benchmarks/src/classic_problems_benchmark.cpp b/benchmarks/src/classic_problems_benchmark.cpp index c134d37..27c6206 100644 --- a/benchmarks/src/classic_problems_benchmark.cpp +++ b/benchmarks/src/classic_problems_benchmark.cpp @@ -157,9 +157,6 @@ class ClassicHMMProblems { }; class ComparativeBenchmark { -private: - ClassicHMMProblems problems; - public: template BenchmarkResults runProblemComparison(ProblemType &problem, int sequence_length) { @@ -427,7 +424,6 @@ int main() { cout << "Fixed random seed (42) for reproducibility" << endl; ComparativeBenchmark benchmark; - ClassicHMMProblems problems; vector results; // Test different sequence lengths for each problem diff --git a/benchmarks/src/libhmm_vs_hmmlib_benchmark.cpp b/benchmarks/src/libhmm_vs_hmmlib_benchmark.cpp index 1c97293..6d3af4a 100644 --- a/benchmarks/src/libhmm_vs_hmmlib_benchmark.cpp +++ b/benchmarks/src/libhmm_vs_hmmlib_benchmark.cpp @@ -262,7 +262,7 @@ class HMMLibBenchmark { // Benchmark Viterbi vector hidden_sequence(obs_sequence.size()); start = high_resolution_clock::now(); - double viterbi_likelihood = hmm.viterbi(obs_sequence, hidden_sequence); + (void)hmm.viterbi(obs_sequence, hidden_sequence); end = high_resolution_clock::now(); results.viterbi_time = duration_cast(end - start).count() / 1000.0; diff --git a/benchmarks/src/simple_benchmark.cpp b/benchmarks/src/simple_benchmark.cpp index acaf2c3..cb422a5 100644 --- a/benchmarks/src/simple_benchmark.cpp +++ b/benchmarks/src/simple_benchmark.cpp @@ -174,7 +174,7 @@ void benchmarkDistributions() { if (x > 20) x = 20; // Limit for discrete distributions } - distributions[i]->getProbability(x); + static_cast(distributions[i]->getProbability(x)); } double time_ms = timer.stop(); diff --git a/benchmarks/src/threeway_benchmark.cpp b/benchmarks/src/threeway_benchmark.cpp index 75c8e3b..2752b79 100644 --- a/benchmarks/src/threeway_benchmark.cpp +++ b/benchmarks/src/threeway_benchmark.cpp @@ -241,7 +241,7 @@ class HMMLibBenchmark { // Benchmark Viterbi vector hidden_sequence(obs_sequence.size()); start = high_resolution_clock::now(); - double viterbi_likelihood = hmm.viterbi(obs_sequence, hidden_sequence); + (void)hmm.viterbi(obs_sequence, hidden_sequence); end = high_resolution_clock::now(); results.viterbi_time = duration_cast(end - start).count() / 1000.0; diff --git a/include/libhmm/calculators/calculator.h b/include/libhmm/calculators/calculator.h index 5149bf6..e166d4c 100755 --- a/include/libhmm/calculators/calculator.h +++ b/include/libhmm/calculators/calculator.h @@ -1,6 +1,6 @@ #pragma once -#include "libhmm/common/common.h" +#include "libhmm/linalg/linalg_types.h" #include "libhmm/hmm.h" #include #include diff --git a/include/libhmm/common/common.h b/include/libhmm/common/common.h index 7235f27..a221514 100755 --- a/include/libhmm/common/common.h +++ b/include/libhmm/common/common.h @@ -1,11 +1,12 @@ #pragma once -/* - * Standard Library includes - C++17 only, no external dependencies - * Consolidated to reduce duplicate includes across the project - */ +// Core C++ standard library headers used throughout the library. +// Lean version: linalg types (Matrix, Vector, ObservationSet, etc.) and XML +// serialization helpers now live in separate headers: +// libhmm/linalg/linalg_types.h — type aliases and clear_* helpers +// libhmm/common/serialization.h — MatrixSerializer / VectorSerializer +// Include those headers from files that need them. -// Core C++ standard library headers #include #include #include @@ -17,255 +18,23 @@ #include #include #include - -// Mathematical and numerical headers #include -// MSVC does not define M_PI by default; guard here once for all consumers. -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif #include #include #include #include #include -// Platform/SIMD headers are in libhmm/platform/ (moved from performance/ in Phase 1 refactor) -// Include libhmm/platform/simd_platform.h if you need SIMD intrinsics +// Constants (includes M_PI guard) +#include "libhmm/math/constants.h" namespace libhmm { -/* - * If we make all observations as double, we can truncate as needed and still - * retain tons of precision for most of the operations. - */ +/// Scalar observation type. Using double gives sufficient precision for all +/// currently supported distributions while keeping the linalg types concrete. typedef double Observation; -/* - * We know that a state is an integral value, so... - */ +/// State index type. typedef int StateIndex; } // namespace libhmm - -// linalg types live in libhmm/linalg/ (Phase 1 refactor). -// Must be included after basic typedefs to avoid naming conflicts. -#include "libhmm/linalg/basic_matrix.h" -#include "libhmm/linalg/basic_vector.h" -#include "libhmm/linalg/basic_matrix3d.h" - -// Constants extracted to their own header in Phase 1 refactor -#include "libhmm/math/constants.h" - -namespace libhmm { - -// Type aliases -using Matrix = BasicMatrix; -using Vector = BasicVector; -using ObservationSet = BasicVector; -using StateSequence = BasicVector; -using ObservationMatrix3D = BasicMatrix3D; - -template -using Matrix3DTemplate = BasicMatrix3D; - -typedef std::vector ObservationLists; - -void clear_matrix(Matrix &m); -void clear_vector(Vector &v); -void clear_vector(StateSequence &v); - -} // namespace libhmm - -/* - * Custom C++17 serialization functions for matrices and vectors. - * These replace the Boost serialization functionality with lightweight, - * standards-compliant serialization using simple XML format. - * - * Design Goals: - * - Zero external dependencies (pure C++17) - * - Backward compatibility with existing XML format where possible - * - Simple, human-readable XML output - * - Efficient parsing for HMM-specific use cases - */ -namespace libhmm { -namespace serialization { - -/** - * Simple XML serialization for BasicMatrix objects - * Replaces boost::serialization with lightweight implementation - */ -template -class MatrixSerializer { -public: - // Save matrix to XML format - static void save(std::ostream &os, const BasicMatrix &matrix, - const std::string &name = "matrix") { - os << "<" << name << ">\n"; - os << " " << matrix.size1() << "\n"; - os << " " << matrix.size2() << "\n"; - os << " \n"; - - for (std::size_t i = 0; i < matrix.size1(); ++i) { - os << " "; - for (std::size_t j = 0; j < matrix.size2(); ++j) { - os << matrix(i, j); - if (j < matrix.size2() - 1) - os << " "; - } - os << "\n"; - } - - os << " \n"; - os << "\n"; - } - - // Load matrix from XML format - static void load(std::istream &is, BasicMatrix &matrix, const std::string &name = "matrix") { - std::string line; - std::size_t rows = 0, cols = 0; - - // Simple XML parsing - find opening tag - while (std::getline(is, line)) { - if (line.find("<" + name + ">") != std::string::npos) { - break; - } - } - - // Read dimensions - if (std::getline(is, line)) { - std::size_t start = line.find("") + 6; - std::size_t end = line.find(""); - if (start != std::string::npos && end != std::string::npos) { - rows = std::stoull(line.substr(start, end - start)); - } - } - - if (std::getline(is, line)) { - std::size_t start = line.find("") + 6; - std::size_t end = line.find(""); - if (start != std::string::npos && end != std::string::npos) { - cols = std::stoull(line.substr(start, end - start)); - } - } - - // Resize matrix - matrix.resize(rows, cols); - - // Skip tag - std::getline(is, line); - - // Read matrix data - for (std::size_t i = 0; i < rows; ++i) { - if (std::getline(is, line)) { - std::size_t start = line.find("") + 5; - std::size_t end = line.find(""); - if (start != std::string::npos && end != std::string::npos) { - std::string data_str = line.substr(start, end - start); - std::istringstream row_stream(data_str); - - for (std::size_t j = 0; j < cols; ++j) { - T value; - row_stream >> value; - matrix(i, j) = value; - } - } - } - } - } -}; - -/** - * Simple XML serialization for BasicVector objects - * Replaces boost::serialization with lightweight implementation - */ -template -class VectorSerializer { -public: - // Save vector to XML format - static void save(std::ostream &os, const BasicVector &vector, - const std::string &name = "vector") { - os << "<" << name << ">\n"; - os << " " << vector.size() << "\n"; - os << " "; - - for (std::size_t i = 0; i < vector.size(); ++i) { - os << vector[i]; - if (i < vector.size() - 1) - os << " "; - } - - os << "\n"; - os << "\n"; - } - - // Load vector from XML format - static void load(std::istream &is, BasicVector &vector, const std::string &name = "vector") { - std::string line; - std::size_t size = 0; - - // Simple XML parsing - find opening tag - while (std::getline(is, line)) { - if (line.find("<" + name + ">") != std::string::npos) { - break; - } - } - - // Read size - if (std::getline(is, line)) { - std::size_t start = line.find("") + 6; - std::size_t end = line.find(""); - if (start != std::string::npos && end != std::string::npos) { - size = std::stoull(line.substr(start, end - start)); - } - } - - // Resize vector - vector.resize(size); - - // Read data - if (std::getline(is, line)) { - std::size_t start = line.find("") + 6; - std::size_t end = line.find(""); - if (start != std::string::npos && end != std::string::npos) { - std::string data_str = line.substr(start, end - start); - std::istringstream data_stream(data_str); - - for (std::size_t i = 0; i < size; ++i) { - T value; - data_stream >> value; - vector[i] = value; - } - } - } - } -}; - -/** - * Convenience functions to match the old boost::serialization style - */ - -// Matrix serialization convenience functions -template -void save(Archive &ar, const BasicMatrix &matrix, const std::string &name = "matrix") { - MatrixSerializer::save(ar, matrix, name); -} - -template -void load(Archive &ar, BasicMatrix &matrix, const std::string &name = "matrix") { - MatrixSerializer::load(ar, matrix, name); -} - -// Vector serialization convenience functions -template -void save(Archive &ar, const BasicVector &vector, const std::string &name = "vector") { - VectorSerializer::save(ar, vector, name); -} - -template -void load(Archive &ar, BasicVector &vector, const std::string &name = "vector") { - VectorSerializer::load(ar, vector, name); -} - -} // namespace serialization -} // namespace libhmm diff --git a/include/libhmm/common/serialization.h b/include/libhmm/common/serialization.h new file mode 100644 index 0000000..6261fd1 --- /dev/null +++ b/include/libhmm/common/serialization.h @@ -0,0 +1,169 @@ +#pragma once + +// XML serialization helpers for libhmm linalg types. +// +// Provides MatrixSerializer and VectorSerializer used by the HMM XML +// I/O layer (src/hmm.cpp, src/io/). Extracted from common/common.h to keep +// that header lean and avoid pulling serialization templates into every +// translation unit that only needs basic types. + +#include +#include + +#include "libhmm/linalg/linalg_types.h" + +namespace libhmm { +namespace serialization { + +/** + * Simple XML serialization for BasicMatrix objects. + * Replaces boost::serialization with a lightweight C++17 implementation. + */ +template +class MatrixSerializer { +public: + /// Save matrix to XML format + static void save(std::ostream &os, const BasicMatrix &matrix, + const std::string &name = "matrix") { + os << "<" << name << ">\n"; + os << " " << matrix.size1() << "\n"; + os << " " << matrix.size2() << "\n"; + os << " \n"; + + for (std::size_t i = 0; i < matrix.size1(); ++i) { + os << " "; + for (std::size_t j = 0; j < matrix.size2(); ++j) { + os << matrix(i, j); + if (j < matrix.size2() - 1) + os << " "; + } + os << "\n"; + } + + os << " \n"; + os << "\n"; + } + + /// Load matrix from XML format + static void load(std::istream &is, BasicMatrix &matrix, const std::string &name = "matrix") { + std::string line; + std::size_t rows = 0, cols = 0; + + while (std::getline(is, line)) { + if (line.find("<" + name + ">") != std::string::npos) + break; + } + + if (std::getline(is, line)) { + std::size_t start = line.find("") + 6; + std::size_t end = line.find(""); + if (start != std::string::npos && end != std::string::npos) + rows = std::stoull(line.substr(start, end - start)); + } + + if (std::getline(is, line)) { + std::size_t start = line.find("") + 6; + std::size_t end = line.find(""); + if (start != std::string::npos && end != std::string::npos) + cols = std::stoull(line.substr(start, end - start)); + } + + matrix.resize(rows, cols); + std::getline(is, line); // skip + + for (std::size_t i = 0; i < rows; ++i) { + if (std::getline(is, line)) { + std::size_t start = line.find("") + 5; + std::size_t end = line.find(""); + if (start != std::string::npos && end != std::string::npos) { + std::istringstream row_stream(line.substr(start, end - start)); + for (std::size_t j = 0; j < cols; ++j) { + T value; + row_stream >> value; + matrix(i, j) = value; + } + } + } + } + } +}; + +/** + * Simple XML serialization for BasicVector objects. + * Replaces boost::serialization with a lightweight C++17 implementation. + */ +template +class VectorSerializer { +public: + /// Save vector to XML format + static void save(std::ostream &os, const BasicVector &vector, + const std::string &name = "vector") { + os << "<" << name << ">\n"; + os << " " << vector.size() << "\n"; + os << " "; + for (std::size_t i = 0; i < vector.size(); ++i) { + os << vector[i]; + if (i < vector.size() - 1) + os << " "; + } + os << "\n"; + os << "\n"; + } + + /// Load vector from XML format + static void load(std::istream &is, BasicVector &vector, const std::string &name = "vector") { + std::string line; + std::size_t size = 0; + + while (std::getline(is, line)) { + if (line.find("<" + name + ">") != std::string::npos) + break; + } + + if (std::getline(is, line)) { + std::size_t start = line.find("") + 6; + std::size_t end = line.find(""); + if (start != std::string::npos && end != std::string::npos) + size = std::stoull(line.substr(start, end - start)); + } + + vector.resize(size); + + if (std::getline(is, line)) { + std::size_t start = line.find("") + 6; + std::size_t end = line.find(""); + if (start != std::string::npos && end != std::string::npos) { + std::istringstream data_stream(line.substr(start, end - start)); + for (std::size_t i = 0; i < size; ++i) { + T value; + data_stream >> value; + vector[i] = value; + } + } + } + } +}; + +// Convenience wrappers matching the old boost::serialization style +template +void save(Archive &ar, const BasicMatrix &matrix, const std::string &name = "matrix") { + MatrixSerializer::save(ar, matrix, name); +} + +template +void load(Archive &ar, BasicMatrix &matrix, const std::string &name = "matrix") { + MatrixSerializer::load(ar, matrix, name); +} + +template +void save(Archive &ar, const BasicVector &vector, const std::string &name = "vector") { + VectorSerializer::save(ar, vector, name); +} + +template +void load(Archive &ar, BasicVector &vector, const std::string &name = "vector") { + VectorSerializer::load(ar, vector, name); +} + +} // namespace serialization +} // namespace libhmm diff --git a/include/libhmm/hmm.h b/include/libhmm/hmm.h index 3ed55b1..99e6cb5 100755 --- a/include/libhmm/hmm.h +++ b/include/libhmm/hmm.h @@ -5,7 +5,7 @@ #include #include #include -#include "libhmm/common/common.h" +#include "libhmm/linalg/linalg_types.h" #include "libhmm/distributions/distributions.h" #include "libhmm/common/string_tokenizer.h" diff --git a/include/libhmm/io/xml_file_reader.h b/include/libhmm/io/xml_file_reader.h index 10a490f..19fb5bc 100644 --- a/include/libhmm/io/xml_file_reader.h +++ b/include/libhmm/io/xml_file_reader.h @@ -8,7 +8,6 @@ #include // Removed boost include - using custom C++17 XML serialization -#include "libhmm/common/common.h" #include "libhmm/hmm.h" namespace libhmm { diff --git a/include/libhmm/io/xml_file_writer.h b/include/libhmm/io/xml_file_writer.h index 3efb058..305ed47 100755 --- a/include/libhmm/io/xml_file_writer.h +++ b/include/libhmm/io/xml_file_writer.h @@ -8,7 +8,6 @@ #include // Removed boost include - using custom C++17 XML serialization -#include "libhmm/common/common.h" #include "libhmm/hmm.h" namespace libhmm { diff --git a/include/libhmm/libhmm.h b/include/libhmm/libhmm.h index e1dff7d..8127e26 100755 --- a/include/libhmm/libhmm.h +++ b/include/libhmm/libhmm.h @@ -28,7 +28,7 @@ * For large projects or when compilation time is critical, consider including * only the specific headers you need instead of this master header. * - * @version 2.8.0 + * @version 3.3.0 * @author libhmm development team */ @@ -36,7 +36,9 @@ // CORE FOUNDATION //============================================================================== -/// Core types, constants, and mathematical utilities +/// Core types, constants, and mathematical utilities. +/// linalg types (Matrix, Vector, ObservationSet, etc.) are provided +/// transitively through hmm.h → linalg/linalg_types.h. #include "libhmm/common/common.h" /// Main HMM class and state machine implementation diff --git a/include/libhmm/linalg/linalg_types.h b/include/libhmm/linalg/linalg_types.h new file mode 100644 index 0000000..f677909 --- /dev/null +++ b/include/libhmm/linalg/linalg_types.h @@ -0,0 +1,40 @@ +#pragma once + +// Linalg types for libhmm. +// +// Provides the concrete matrix/vector types and the type aliases that the HMM +// engine, calculators, trainers, and IO layer depend on. Distribution headers +// do NOT need to include this file — they work with std::span and do +// not expose or store linalg types in their public signatures. +// +// Include this header from any file that uses Matrix, Vector, ObservationSet, +// ObservationLists, StateSequence, or the clear_* helpers. + +#include + +#include "libhmm/common/common.h" // Observation, StateIndex, STL headers +#include "libhmm/linalg/basic_matrix.h" +#include "libhmm/linalg/basic_matrix3d.h" +#include "libhmm/linalg/basic_vector.h" + +namespace libhmm { + +// Core linalg type aliases +using Matrix = BasicMatrix; +using Vector = BasicVector; +using ObservationSet = BasicVector; +using StateSequence = BasicVector; +using ObservationMatrix3D = BasicMatrix3D; + +template +using Matrix3DTemplate = BasicMatrix3D; + +/// Sequence of observation vectors, one per training sequence. +typedef std::vector ObservationLists; + +// Utility helpers — implementations in src/common/common.cpp +void clear_matrix(Matrix &m); +void clear_vector(Vector &v); +void clear_vector(StateSequence &v); + +} // namespace libhmm diff --git a/include/libhmm/math/constants.h b/include/libhmm/math/constants.h index 23ec4ea..dafe4ee 100644 --- a/include/libhmm/math/constants.h +++ b/include/libhmm/math/constants.h @@ -95,6 +95,11 @@ inline constexpr std::size_t SIMD_ALIGNMENT = 32; /// Mathematical constants namespace math { +// Provide M_PI for code that tests for it (non-standard but widely expected). +// Defined before PI so both are available in the same translation unit. +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif inline constexpr double PI = 3.141592653589793238462643383279502884; inline constexpr double LN2 = 0.6931471805599453094172321214581766; inline constexpr double LN_10 = 2.302585092994046; diff --git a/include/libhmm/math/numerical_stability.h b/include/libhmm/math/numerical_stability.h index 0f30a2c..4d46cf1 100644 --- a/include/libhmm/math/numerical_stability.h +++ b/include/libhmm/math/numerical_stability.h @@ -5,7 +5,7 @@ #include #include #include -#include "libhmm/common/common.h" +#include "libhmm/linalg/linalg_types.h" namespace libhmm { namespace numerical { diff --git a/include/libhmm/training/segmental_kmeans_trainer.h b/include/libhmm/training/segmental_kmeans_trainer.h index 5a396b0..759c2ca 100644 --- a/include/libhmm/training/segmental_kmeans_trainer.h +++ b/include/libhmm/training/segmental_kmeans_trainer.h @@ -4,7 +4,7 @@ #include #include #include -#include "libhmm/common/common.h" +#include "libhmm/linalg/linalg_types.h" #include "libhmm/training/trainer.h" namespace libhmm { diff --git a/include/libhmm/training/trainer.h b/include/libhmm/training/trainer.h index 633b7cc..5b0fed1 100644 --- a/include/libhmm/training/trainer.h +++ b/include/libhmm/training/trainer.h @@ -1,6 +1,6 @@ #pragma once -#include "libhmm/common/common.h" +#include "libhmm/linalg/linalg_types.h" #include "libhmm/hmm.h" #include #include diff --git a/src/common/common.cpp b/src/common/common.cpp index c2ae410..54e7e54 100755 --- a/src/common/common.cpp +++ b/src/common/common.cpp @@ -1,4 +1,4 @@ -#include "libhmm/common/common.h" +#include "libhmm/linalg/linalg_types.h" namespace libhmm { diff --git a/tests/common/test_common.cpp b/tests/common/test_common.cpp index 50b525a..9c16b65 100644 --- a/tests/common/test_common.cpp +++ b/tests/common/test_common.cpp @@ -1,5 +1,5 @@ #include -#include "libhmm/common/common.h" +#include "libhmm/linalg/linalg_types.h" #include "libhmm/common/string_tokenizer.h" #include #include diff --git a/tests/distributions/test_pareto_distribution.cpp b/tests/distributions/test_pareto_distribution.cpp index 0cba0d1..60982d9 100644 --- a/tests/distributions/test_pareto_distribution.cpp +++ b/tests/distributions/test_pareto_distribution.cpp @@ -14,7 +14,6 @@ #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #endif -#include "libhmm/common/common.h" using libhmm::Observation; using libhmm::ParetoDistribution; diff --git a/tests/distributions/test_rayleigh_distribution.cpp b/tests/distributions/test_rayleigh_distribution.cpp index 3c62320..941a7f5 100644 --- a/tests/distributions/test_rayleigh_distribution.cpp +++ b/tests/distributions/test_rayleigh_distribution.cpp @@ -14,7 +14,6 @@ #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #endif -#include "libhmm/common/common.h" using libhmm::Observation; using libhmm::RayleighDistribution; diff --git a/tools/fb_contour_sweep.cpp b/tools/fb_contour_sweep.cpp index b875fde..52e3cc1 100644 --- a/tools/fb_contour_sweep.cpp +++ b/tools/fb_contour_sweep.cpp @@ -23,7 +23,7 @@ namespace fs = std::filesystem; namespace { constexpr double LOG_ZERO = -std::numeric_limits::infinity(); -constexpr std::size_t FB_MAX_REDUCE_FORCE_PAIRWISE_MAX_STATES = 2; +[[maybe_unused]] constexpr std::size_t FB_MAX_REDUCE_FORCE_PAIRWISE_MAX_STATES = 2; volatile double g_sink_double = 0.0; struct Config { diff --git a/tools/hotspot_breakdown.cpp b/tools/hotspot_breakdown.cpp index 24827bc..748ca63 100644 --- a/tools/hotspot_breakdown.cpp +++ b/tools/hotspot_breakdown.cpp @@ -21,7 +21,7 @@ using Millis = std::chrono::duration; namespace { constexpr double LOG_ZERO = -std::numeric_limits::infinity(); -constexpr std::size_t FB_MAX_REDUCE_FORCE_PAIRWISE_MAX_STATES = 2; +[[maybe_unused]] constexpr std::size_t FB_MAX_REDUCE_FORCE_PAIRWISE_MAX_STATES = 2; volatile double g_sink_double = 0.0; volatile int g_sink_int = 0; From 558204456d4b0eb0e62ad0d3663fe1d165451f95 Mon Sep 17 00:00:00 2001 From: GD Wolfman Date: Mon, 4 May 2026 08:51:39 -0400 Subject: [PATCH 2/2] fix: add explicit include to common.h for MSVC portability std::setprecision, std::fixed, and std::put_time are used throughout the library (all 15 distribution toString() methods, file_io_manager.cpp, numerical_stability.cpp). Apple Clang includes transitively through so the M1 build did not surface the missing include. MSVC and libstdc++ do not, causing C2039/C3861 build failures on Windows. Added with an explanatory comment to prevent future regressions during header-cleanup passes. Co-Authored-By: Oz --- include/libhmm/common/common.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/libhmm/common/common.h b/include/libhmm/common/common.h index a221514..db0d1ca 100755 --- a/include/libhmm/common/common.h +++ b/include/libhmm/common/common.h @@ -12,6 +12,9 @@ #include #include #include +#include // std::setprecision, std::fixed, std::put_time — used in toString() + // and file I/O throughout the library. Must be explicit: MSVC and + // libstdc++ do not include transitively through . #include #include #include