From bfef96779dce951054513fce5405c54afe395192 Mon Sep 17 00:00:00 2001 From: Emanuel Gull Date: Thu, 24 Sep 2026 10:31:04 +0200 Subject: [PATCH 1/7] Plan: regroup step 2.3 (A-D) and move physics items to 2.6 --- ALPS3_MIGRATION_PLAN.md | 85 ++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 23 deletions(-) diff --git a/ALPS3_MIGRATION_PLAN.md b/ALPS3_MIGRATION_PLAN.md index 5e9e573..865250c 100644 --- a/ALPS3_MIGRATION_PLAN.md +++ b/ALPS3_MIGRATION_PLAN.md @@ -361,29 +361,57 @@ and Boost.Math in `legendre_convert`. ### 2.3 Code fixes -* Fix B1 through B20 (§1.6), including B7b. B21 (logging convention and verbosity) can go here or into a later step; it changes the CLI regression references on purpose. -* Moved here from 2.2 (they change the CLI references on purpose): replace - `boost::diagnostic_information` by `e.what()` (with B1), add a `SEED` - parameter for the bootstrap (B10), and delete the commented-out ublas and - LAPACK-bindings code. -* `legendre_convert` (decided 2026-09-24), in this order: - 1. Add regression cases for `legendre_convert` first (it has no tests), with - references from the current Boost build, like the `kk` cases in 2.2. - 2. Replace Boost.Random by ``. The `mt19937` engine gives identical - numbers; the normal variates differ (different algorithm), which is - harmless because the error estimate is seeded from the clock. - 3. Replace `boost::math::factorial` by a product (only small arguments - occur). - 4. Replace `boost::math::legendre_p` by the standard three-term recurrence. - `std::legendre` is not an option: libc++ (AppleClang) does not implement - the C++17 special math functions. - Keep `boost::math::sph_bessel` (also missing in libc++; our own version - would need careful checking at large l and argument) and `program_options` - (no standard equivalent). B5, B6 and B7 change reachable behavior, so each gets its own commit with a before/after test. -* Remove all `using namespace boost::numeric;` lines, `#include `, dead commented-out ublas and lapack-bindings code, and the unused `alps::cast`. -* Make `eigen_hdf5.hpp`/`eigen_lapack.hpp` functions `inline`, or move them into `.cpp` files (B8). -* Use `Eigen::Index` for loop indices (B14). Consider `BDCSVD` in place of `JacobiSVD` (B11); that one is a numerics change and needs checking against the references. -* Keep the `MaxEntSimulation` public getters stable, because the tests use them. +Grouped by what each item does to the regression references (agreed +2026-09-24). One PR per group, in this order, each with a Copilot review. +Already done elsewhere: B2, B3 (2.1), B7 (`xi_bose_bugfix`), B20 (Pade removed). + +**2.3A: no change to results** (references must stay bit-identical) + +* Fix all compiler warnings (44 at the start of 2.3): B14 (`std::size_t` vs + `Eigen::Index` loops), B12 (member initialization order), unused variables, + misleading indentation, B13 (deprecated `params::get_origin_name()`; the + default `BASENAME` must not change). Then turn on `MAXENT_WERROR` in the `dev` + preset. +* B8: make the functions in `eigen_hdf5.hpp`/`eigen_lapack.hpp` `inline`. +* B4: the size check in `Backcont::max_error` (inverted `NDEBUG` guard). +* B5, B6: remove the unreachable kernel branches. +* B9: the data-file reading loop (`while (datstream)` reads past EOF); same + results for valid files, plus a test with trailing blank lines. +* Remove the commented-out ublas and LAPACK-bindings code, `` + includes and the unused `alps::cast`. + +**2.3B: `legendre_convert`** (decided 2026-09-24), in this order: + +1. Add regression cases for `legendre_convert` first (it has no tests), with + references from the current Boost build, like the `kk` cases in 2.2. +2. Replace Boost.Random by ``. The `mt19937` engine gives identical + numbers; the normal variates differ (different algorithm), which is + harmless because the error estimate is seeded from the clock. +3. Replace `boost::math::factorial` by a product (only small arguments occur). +4. Replace `boost::math::legendre_p` by the standard three-term recurrence. + `std::legendre` is not an option: libc++ (AppleClang) does not implement the + C++17 special math functions. + +Keep `boost::math::sph_bessel` (also missing in libc++; our own version would +need careful checking at large l and argument) and `program_options` (no +standard equivalent). + +**2.3C: command-line behavior** (updates the CLI references on purpose) + +* B1: non-zero exit code on errors, together with `boost::diagnostic_information` + → `e.what()` (moved here from 2.2). +* B16: accept `half-lorentzian` as well as `half lorentzian`, and show the real + `CUT` default in `--help.grids`. +* B10: a `SEED` parameter for the bootstrap errors (moved here from 2.2). + +**2.3D: numerical changes** (each its own commit and `REFERENCE_CHANGES.md` entry) + +* B7b: time-bosonic kernel: use the ω→0 limit only at ω = 0. +* B15: remove the `float` casts in the log grid. +* B11 (optional): `BDCSVD` instead of `JacobiSVD`; measure against the + references before deciding. + +Keep the `MaxEntSimulation` public getters stable, because the tests use them. ### 2.4 Hygiene and CI @@ -406,6 +434,17 @@ This is the last task of step 2, still on ALPSCore: 2. **HDF5 seam:** move all archive access into `maxent_io_hdf5.{hpp,cpp}`, with functions such as `write_vector(path, Eigen::VectorXd)`, `read_vector(path)` and `write_params(...)`. Nothing else includes ``. 3. Tests use `std::filesystem::temp_directory_path()` in place of `alps::temporary_filename`. +### 2.6 Physics and algorithms (after 2.3–2.5) + +Moved out of 2.3 (2026-09-24) because they are physics or algorithm changes +rather than cleanup; each needs its own decision: + +* B17: Legendre bosonic kernel (currently the fermionic formula). +* B18: default grid when `OMEGA_MIN=0` (change the default, or warn). +* B19: minimizer divergence (step-size control or a trust region). +* B21: logging convention and verbosity (issue #46). +* B22: performance of the core at large NFREQ. + **Step 2 acceptance:** * Configures with CMake 3.22 through 4.x. From c5a3db6be4910d6af95f75186032c8b7aefc3b73 Mon Sep 17 00:00:00 2001 From: Emanuel Gull Date: Thu, 24 Sep 2026 10:44:23 +0200 Subject: [PATCH 2/7] Complete warning-free step 2.3A cleanup --- ALPS3_MIGRATION_PLAN.md | 5 +++ CMakePresets.json | 5 ++- legendre_convert/legendre_convert.cpp | 2 +- src/eigen_hdf5.hpp | 6 +-- src/eigen_lapack.hpp | 4 +- src/maxent.cpp | 5 +-- src/maxent_backcont.cpp | 4 +- src/maxent_backcont.hpp | 1 - src/maxent_helper.cpp | 52 ++++++++++------------ src/maxent_kernel.cpp | 21 +-------- src/maxent_matrix_def.hpp | 1 - src/maxent_params.cpp | 41 ++++++----------- src/maxent_simulation.cpp | 63 +++++++++++++-------------- test/backcontTest.cpp | 3 ++ test/paramsTest.cpp | 25 ++++++++++- 15 files changed, 113 insertions(+), 125 deletions(-) diff --git a/ALPS3_MIGRATION_PLAN.md b/ALPS3_MIGRATION_PLAN.md index 865250c..9945c58 100644 --- a/ALPS3_MIGRATION_PLAN.md +++ b/ALPS3_MIGRATION_PLAN.md @@ -367,6 +367,10 @@ Already done elsewhere: B2, B3 (2.1), B7 (`xi_bose_bugfix`), B20 (Pade removed). **2.3A: no change to results** (references must stay bit-identical) +**Done 2026-09-24.** All Maxent-owned code and utilities build with +`-Wall -Wextra -Wpedantic -Werror`; the fast and full regression suites remain +unchanged. A text-input regression covers trailing blank lines. + * Fix all compiler warnings (44 at the start of 2.3): B14 (`std::size_t` vs `Eigen::Index` loops), B12 (member initialization order), unused variables, misleading indentation, B13 (deprecated `params::get_origin_name()`; the @@ -679,3 +683,4 @@ make -j8 && ctest # 6/6 executables, 35 cases pass, ~9 s | 2026-09-23 | 2.x | Pade removed (D7), on branch `modernize/remove-pade`: `pade/` (13 files: 6 built, 5 unbuilt alternatives, header, CMake), `MAXENT_BUILD_PADE`, and the README section. It required GMP (`mpf_class`, 256-bit default precision) and did not compile (B20). | | 2026-09-24 | 2.2 | Step 2.2 done on `modernize/step2.2`: kk regression cases, kk spline, closed-form Legendre kernel (GSL removed), Boost utilities → std. No reference changed; 41/41 tests. ALPSCore#668 merged (GoogleTest 1.18, not installed, CMake 3.16). Found B22 (performance). | | 2026-09-24 | sync | Synced with ALPSCore `master` `560ae112` (#669: C++14 required and default, ALPSCore compiled with exactly `ALPS_CXX_STD`, Boost.Math dependency removed; #670: Doxygen removed). Maxent `d529a14` against it (installed as C++14, Boost 1.88): configures without `Boost_DIR`, compiles as C++17, 41/41 tests, regression unchanged (only the known Legendre rounding-level differences from 2.2). Note: build ALPSCore in a fresh build directory; an old one keeps a stale compiler identification that Maxent's configure then rejects. | +| 2026-09-24 | 2.3A | Warning cleanup and no-output-change fixes complete: Eigen index types, initializer order, unused/deprecated code, inline HDF5/LAPACK helpers, debug size check, unreachable kernel branches, robust text-file extraction, and dead bindings/config code removed. The dev preset enables `MAXENT_WERROR`; 42/42 Release tests pass including full regression, and the LAPACK build is warning-free. | diff --git a/CMakePresets.json b/CMakePresets.json index 890f970..8b4d5b7 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -20,7 +20,10 @@ "name": "dev", "displayName": "Debug", "inherits": "base", - "cacheVariables": {"CMAKE_BUILD_TYPE": "Debug"} + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "MAXENT_WERROR": "ON" + } }, { "name": "asan", diff --git a/legendre_convert/legendre_convert.cpp b/legendre_convert/legendre_convert.cpp index c4f9396..cedbf56 100644 --- a/legendre_convert/legendre_convert.cpp +++ b/legendre_convert/legendre_convert.cpp @@ -324,7 +324,7 @@ double GtBoot(vector_type gl_in, void *arg){ //************************ int main(int argc, char**argv){ namespace po = boost::program_options; - double beta,c1,c2,c3; + double beta,c1,c2; int lmax,numConvergence,maxit,maxn; bool backcontinue = false,enforceTailOff = false,enforceErrCheck=true,continueMatsubara=false; std::string input_gtau_filename,gl_filename; diff --git a/src/eigen_hdf5.hpp b/src/eigen_hdf5.hpp index ad440c1..cdc0073 100644 --- a/src/eigen_hdf5.hpp +++ b/src/eigen_hdf5.hpp @@ -11,7 +11,6 @@ #pragma once #include -#include #include #include @@ -32,7 +31,7 @@ namespace alps { if (value.size()) { std::vector first(get_extent(value[0])); if (true) - for(std::size_t i=1;i size(get_extent(value[i])); if ( first.size() != size.size() @@ -46,7 +45,7 @@ namespace alps { } }; } - void save( + inline void save( archive &ar , std::string const & path , Eigen::VectorXd &value @@ -54,7 +53,6 @@ namespace alps { , std::vector chunk =std::vector() , std::vector offset = std::vector() ) { - using alps::cast; if (ar.is_group(path)) ar.delete_group(path); if (is_continuous::value && value.size() == 0) diff --git a/src/eigen_lapack.hpp b/src/eigen_lapack.hpp index 9d55c64..2755c34 100644 --- a/src/eigen_lapack.hpp +++ b/src/eigen_lapack.hpp @@ -21,9 +21,7 @@ extern "C" void dgesvd_( const char* jobu, const char* jobvt, ///performs a SVD on input matrix K /// returns K = U (S) V^T where S is a vector of the diagonal values of /// matrix Sigma -void lapack_svd(matrix_type &K, vector_type &S, matrix_type &Vt, matrix_type &U){ - - /*boost::numeric::bindings::lapack::gesvd('S', 'S', Kt, S, U_, Vt_);*/ +inline void lapack_svd(matrix_type &K, vector_type &S, matrix_type &Vt, matrix_type &U){ //use 'S' for thin U,Vt matrices char jobu = 'S'; char jobvt = 'S'; diff --git a/src/maxent.cpp b/src/maxent.cpp index 3ce77f9..8d4639a 100644 --- a/src/maxent.cpp +++ b/src/maxent.cpp @@ -89,7 +89,7 @@ int main(int argc,const char** argv) std::string basename; if(parms.defaulted("BASENAME")){ - basename = alps::fs::remove_extensions(parms.get_origin_name()) + ".out"; + basename = alps::fs::remove_extensions(alps::origin_name(parms)) + ".out"; parms["BASENAME"] = basename; } else @@ -151,7 +151,7 @@ int main(int argc,const char** argv) ofstream_ spec_file; spec_file.open((basename+".varspec.dat").c_str()); spec_file << "#omega mean_maxspec stdev_maxspec mean_avspec stdev_avspec" <max_err){ max_err = delta; diff --git a/src/maxent_backcont.hpp b/src/maxent_backcont.hpp index 8acaafc..d3f5edf 100644 --- a/src/maxent_backcont.hpp +++ b/src/maxent_backcont.hpp @@ -11,7 +11,6 @@ #pragma once #include "maxent.hpp" -#include // needed to set up correct bindings ///This class contains necessities to analytically continue a //real function to the imaginary axis diff --git a/src/maxent_helper.cpp b/src/maxent_helper.cpp index 4d7ca75..4898a5f 100644 --- a/src/maxent_helper.cpp +++ b/src/maxent_helper.cpp @@ -10,7 +10,6 @@ *****************************************************************************/ #include "maxent.hpp" -#include // needed to set up correct bindings #include #include #include @@ -49,7 +48,7 @@ void MaxEntHelper::checkDefaultModel(const vector_type &D) const{ vector_type MaxEntHelper::transform_into_singular_space(vector_type A) const { double D; - for (unsigned int i=0; i lltofL(L); L=lltofL.matrixL(); double log_det = 0.; - for (unsigned int i=0; i es(L); lambda = es.eigenvalues(); double Ng = 0.; - for (unsigned int i=0; i=0) Ng += lambda[i]/(lambda[i]+alpha); } @@ -191,7 +186,7 @@ double MaxEntHelper::chi2(const vector_type& A) const }*/ double c = 0; - for (unsigned int i=0; igetKernelType(); - double beta = 1/(pp->T()); bool ph_sym = true; if(k_type == frequency_fermionic_kernel || k_type == frequency_bosonic_kernel || @@ -275,7 +269,7 @@ void MaxEntHelper::backcontinue(ofstream_ &os, const vector_type &A_in,const dou //A is missing delta_omega value, add back in for chi2 vector_type A_chi = A; - for (unsigned int i=0; i &in,vector_type &mean, vector_ty for(int i=0;i // needed to set up correct bindings #include "maxent_config.hpp" #include diff --git a/src/maxent_params.cpp b/src/maxent_params.cpp index bdfb493..c58c5eb 100644 --- a/src/maxent_params.cpp +++ b/src/maxent_params.cpp @@ -11,7 +11,6 @@ #include "maxent.hpp" #include "eigen_lapack.hpp" -#include // needed to set up correct bindings #include #include #include @@ -51,9 +50,8 @@ void ContiParameters::read_data_from_text_file(const alps::params& p) { std::string dataspace = p["DATASPACE"].as(); to_lower(dataspace); if(dataspace == "time" || dataspace == "legendre" || p["PARTICLE_HOLE_SYMMETRY"]==true){ - while (datstream) { - double index, X_i, dX_i; - datstream >> index >> X_i >> dX_i; + double index, X_i, dX_i; + while (datstream >> index >> X_i >> dX_i) { if (datIn < ndat()) { inputGrid_(datIn) = index; y_(datIn) = X_i / static_cast(p["NORM"]); @@ -62,7 +60,6 @@ void ContiParameters::read_data_from_text_file(const alps::params& p) { } expectedDatIn++; } - expectedDatIn-=1; } else{ if(ndat()%2 != 0){ @@ -71,9 +68,8 @@ void ContiParameters::read_data_from_text_file(const alps::params& p) { << std::endl; throw std::runtime_error("Your NDAT is odd!");\ } - while (datstream) { - double index, X_i_re, dX_i_re, X_i_im, dX_i_im; - datstream >> index >> X_i_re >> dX_i_re >> X_i_im >> dX_i_im; + double index, X_i_re, dX_i_re, X_i_im, dX_i_im; + while (datstream >> index >> X_i_re >> dX_i_re >> X_i_im >> dX_i_im) { if (datIn < ndat()) { inputGrid_(datIn) = index; inputGrid_(datIn+1) = index; @@ -83,11 +79,8 @@ void ContiParameters::read_data_from_text_file(const alps::params& p) { sigma_(datIn+1) = dX_i_im / static_cast(p["NORM"]); datIn+=2; } - expectedDatIn++; + expectedDatIn+=2; } - //fix for matsubara length - expectedDatIn*=2; - expectedDatIn-=1; } if(p["COVARIANCE_MATRIX"]!="") { std::string fname = p["COVARIANCE_MATRIX"]; @@ -117,13 +110,13 @@ void ContiParameters::read_data_from_hdf5_file(const alps::params& p) { std::stringstream path; path << "/Data"; ar >> alps::make_pvp(path.str(), tmp); - for (std::size_t i = 0; i < ndat(); i++) + for (int i = 0; i < ndat(); i++) y_(i) = tmp[i] / static_cast(p["NORM"]); path.str(""); if (p["COVARIANCE_MATRIX"]=="") { path << "/Error"; ar >> alps::make_pvp(path.str(), tmp); - for (std::size_t i = 0; i < ndat(); i++) + for (int i = 0; i < ndat(); i++) sigma_(i) = tmp[i] / static_cast(p["NORM"]); } else { path << "/Covariance"; @@ -131,8 +124,8 @@ void ContiParameters::read_data_from_hdf5_file(const alps::params& p) { tmp.clear(); tmp.resize(ndat() * ndat()); ar >> alps::make_pvp(path.str(), tmp); - for (std::size_t i = 0; i < ndat(); i++) - for (std::size_t j = 0; j < ndat(); j++) + for (int i = 0; i < ndat(); i++) + for (int j = 0; j < ndat(); j++) cov_(i, j) = tmp[i * ndat() + j]; } } @@ -225,7 +218,6 @@ void ContiParameters::read_covariance_matrix_from_text_file( void ContiParameters::decompose_covariance_matrix(const alps::params& p){ vector_type var(ndat()); - //bindings::lapack::syev('V', bindings::upper(cov_) , var, bindings::lapack::optimal_workspace()); //TODO: check if this truly implements lapack's expected overwrite of cov_ Eigen::SelfAdjointEigenSolver es(cov_); var=es.eigenvalues(); @@ -292,17 +284,12 @@ void MaxEntParameters::truncate_to_singular_space(const vector_type& S) { void MaxEntParameters::singular_value_decompose_kernel(bool verbose, vector_type& S) { - /*boost::numeric::bindings::lapack::gesvd('S', 'S', Kt, S, U_, Vt_); - */ - #ifdef HAVE_LAPACK matrix_type Kt = K_; // gesvd destroys K! lapack_svd(Kt,S, Vt_,U_); #else - const double threshold = std::sqrt(std::numeric_limits::epsilon()) - * nfreq(); Eigen::JacobiSVD svd(K_,Eigen::ComputeThinU | Eigen::ComputeThinV); //svd.setThreshold(threshold); S=svd.singularValues(); @@ -318,7 +305,7 @@ void MaxEntParameters::singular_value_decompose_kernel(bool verbose, std::cout << "# eps = " << sqrt(std::numeric_limits::epsilon()) << std::endl << "# prec = " << prec << std::endl; - for (unsigned int s = 0; s < S.size(); ++s) { + for (Eigen::Index s = 0; s < S.size(); ++s) { if (verbose) std::cout << "# " << s << "\t" << S[s] << "\n"; @@ -387,10 +374,11 @@ MaxEntParameters::MaxEntParameters(alps::params& p) : k_type = ker.getKernelType(); //scale lhs and rhs according to errors, etc. - if (p["COVARIANCE_MATRIX"]!="") + if (p["COVARIANCE_MATRIX"]!="") { decompose_covariance_matrix(p); - - check_high_frequency_limit(y(),k_type); + } + + check_high_frequency_limit(y(),k_type); //Look around Eq. D.5 in Sebastian's thesis. We have sigma_ = sqrt(eigenvalues of covariance matrix) or, //in case of a diagonal covariance matrix, we have sigma_=SIGMA_X. @@ -413,4 +401,3 @@ MaxEntParameters::MaxEntParameters(alps::params& p) : - diff --git a/src/maxent_simulation.cpp b/src/maxent_simulation.cpp index fe4ead8..f2a11f9 100644 --- a/src/maxent_simulation.cpp +++ b/src/maxent_simulation.cpp @@ -10,7 +10,6 @@ *****************************************************************************/ #include "maxent.hpp" -#include // needed to set up correct bindings #include #include #include @@ -27,8 +26,8 @@ MaxEntSimulation::MaxEntSimulation(alps::params &parms) , self(parms["SELF"]) , make_back(parms["BACKCONTINUE"]) , gen_err(parms["GENERATE_ERR"]) -, qvec((int)parms["N_ALPHA"]) , nfreq(parms["NFREQ"].as()) +, qvec((int)parms["N_ALPHA"]) { std::string bn=parms["BASENAME"]; name=bn+'.'; @@ -36,7 +35,7 @@ MaxEntSimulation::MaxEntSimulation(alps::params &parms) const double alpha_min = parms["ALPHA_MIN"]; //Smallest value of \alpha that is tried const double alpha_max = parms["ALPHA_MAX"]; //Largest value of \alpha that is tried alpha[0] = alpha_max; - for (std::size_t a=1; a::const_iterator max_lprob = std::max_element(lprob.begin(), lprob.end()); //const int max_a = max_lprob-lprob.begin(); int max_a,nothing; double max_lprob; max_lprob=lprob.maxCoeff(&max_a,¬hing); @@ -191,14 +189,14 @@ void MaxEntSimulation::evaluate(){ ar << alps::make_pvp("/alpha/values",alpha); vector_type om(spectra[0].size()); - for (int i=0;i=0.) spec[i] = avspec[i]*omega_coord(i)*M_PI; avspec_anom_str << omega_coord(i) << " " << spec[i]<=0.) spec[i] = spectra[max_a][i]*norm*omega_coord(i)*M_PI; maxspec_anom_str << omega_coord(i) << " " << spec[i] << std::endl; @@ -280,24 +278,24 @@ void MaxEntSimulation::evaluate(){ } if(Kernel_type=="bosonic"){ //for the anomalous function: use A(Omega_)=Im chi(Omega_)/(pi Omega_) (as for anomalous) vector_type spec(avspec.size()); - for (std::size_t i=0; i=0.) avspec_anom_str << omega_coord(i) << " " << spec[i]<=0.) spec[i] = spectra[max_a][i]*norm*omega_coord(i); } if (text_output) { ofstream_ maxspec_anom_str;maxspec_anom_str.open((name+"avspec_bose.dat").c_str()); - for (std::size_t i=0; i Date: Thu, 24 Sep 2026 11:13:53 +0200 Subject: [PATCH 3/7] Strengthen EOF parsing regression --- ALPS3_MIGRATION_PLAN.md | 2 +- test/paramsTest.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ALPS3_MIGRATION_PLAN.md b/ALPS3_MIGRATION_PLAN.md index 9945c58..bdcc5e4 100644 --- a/ALPS3_MIGRATION_PLAN.md +++ b/ALPS3_MIGRATION_PLAN.md @@ -683,4 +683,4 @@ make -j8 && ctest # 6/6 executables, 35 cases pass, ~9 s | 2026-09-23 | 2.x | Pade removed (D7), on branch `modernize/remove-pade`: `pade/` (13 files: 6 built, 5 unbuilt alternatives, header, CMake), `MAXENT_BUILD_PADE`, and the README section. It required GMP (`mpf_class`, 256-bit default precision) and did not compile (B20). | | 2026-09-24 | 2.2 | Step 2.2 done on `modernize/step2.2`: kk regression cases, kk spline, closed-form Legendre kernel (GSL removed), Boost utilities → std. No reference changed; 41/41 tests. ALPSCore#668 merged (GoogleTest 1.18, not installed, CMake 3.16). Found B22 (performance). | | 2026-09-24 | sync | Synced with ALPSCore `master` `560ae112` (#669: C++14 required and default, ALPSCore compiled with exactly `ALPS_CXX_STD`, Boost.Math dependency removed; #670: Doxygen removed). Maxent `d529a14` against it (installed as C++14, Boost 1.88): configures without `Boost_DIR`, compiles as C++17, 41/41 tests, regression unchanged (only the known Legendre rounding-level differences from 2.2). Note: build ALPSCore in a fresh build directory; an old one keeps a stale compiler identification that Maxent's configure then rejects. | -| 2026-09-24 | 2.3A | Warning cleanup and no-output-change fixes complete: Eigen index types, initializer order, unused/deprecated code, inline HDF5/LAPACK helpers, debug size check, unreachable kernel branches, robust text-file extraction, and dead bindings/config code removed. The dev preset enables `MAXENT_WERROR`; 42/42 Release tests pass including full regression, and the LAPACK build is warning-free. | +| 2026-09-24 | 2.3A | Warning cleanup and no-output-change fixes complete: Eigen index types, initializer order, unused/deprecated code, inline HDF5/LAPACK helpers, debug size check, unreachable kernel branches, robust text-file extraction, and dead bindings/config code removed. The dev preset enables `MAXENT_WERROR`; 43/43 Release tests pass including full regression, and the LAPACK build is warning-free. | diff --git a/test/paramsTest.cpp b/test/paramsTest.cpp index 4fa585e..c053535 100644 --- a/test/paramsTest.cpp +++ b/test/paramsTest.cpp @@ -125,6 +125,24 @@ TEST(Parameters,DataInFileWithTrailingBlankLines){ std::remove(pf.c_str()); } +TEST(Parameters,RejectsIncompleteFinalDataRecord){ + std::string pf=alps::temporary_filename("in_file.dat"); + write_minimal_input_file(pf); + { + std::ofstream tempfile(pf.c_str(), std::ios::app); + tempfile << "5 0.6\n"; // Missing the error-bar column. + } + + alps::params p; + MaxEntSimulation::define_parameters(p); + p["BETA"]=2; + p["DATA"]=pf; + p["NDAT"] = 6; + + EXPECT_THROW(ContiParameters c(p), std::runtime_error); + std::remove(pf.c_str()); +} + TEST(Parameters,MaxentParams){ //set up parameters alps::params p; From 6a2c13e3de482b82936732b971b9c65d5d22a2f8 Mon Sep 17 00:00:00 2001 From: Emanuel Gull Date: Thu, 24 Sep 2026 11:21:54 +0200 Subject: [PATCH 4/7] Test unconditional high-frequency diagnostic --- src/maxent_params.cpp | 2 +- test/paramsTest.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/maxent_params.cpp b/src/maxent_params.cpp index c58c5eb..23a1be8 100644 --- a/src/maxent_params.cpp +++ b/src/maxent_params.cpp @@ -378,6 +378,7 @@ MaxEntParameters::MaxEntParameters(alps::params& p) : decompose_covariance_matrix(p); } + // This diagnostic applies to both diagonal errors and covariance input. check_high_frequency_limit(y(),k_type); //Look around Eq. D.5 in Sebastian's thesis. We have sigma_ = sqrt(eigenvalues of covariance matrix) or, @@ -400,4 +401,3 @@ MaxEntParameters::MaxEntParameters(alps::params& p) : } - diff --git a/test/paramsTest.cpp b/test/paramsTest.cpp index c053535..831f480 100644 --- a/test/paramsTest.cpp +++ b/test/paramsTest.cpp @@ -223,6 +223,7 @@ TEST(Parameters,HighFrequencyCheck){ p["SHIFT"]=2.0; std::complex G; + testing::internal::CaptureStderr(); for(int i=0;i Date: Thu, 24 Sep 2026 11:36:24 +0200 Subject: [PATCH 5/7] Complete Eigen index and covariance coverage --- src/maxent_helper.cpp | 14 +++++++------- src/maxent_simulation.cpp | 5 ----- test/paramsTest.cpp | 5 +++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/maxent_helper.cpp b/src/maxent_helper.cpp index 4898a5f..78f2624 100644 --- a/src/maxent_helper.cpp +++ b/src/maxent_helper.cpp @@ -35,7 +35,7 @@ MaxEntParameters(p) , def_(nfreq()), text_output(p["TEXT_OUTPUT"]) /// this is needed for transform_into_singular_space /// to work safely void MaxEntHelper::checkDefaultModel(const vector_type &D) const{ - for(int i=0;iinputGrid(n) << " " << G(n)*norm << std::endl; } } else{ - for(int n=0;ninputGrid(n/2) << " " << G(n)*norm << " " << G(n+1)*norm << std::endl; } } } //scale y by error then determine 'error' of integral vector_type y_scaled = y(); - for(int i=0;i &in,vector_type &mean, vector_ty } mean /= in.size(); //compute stddev - for(int i=0;i Date: Thu, 24 Sep 2026 11:44:06 +0200 Subject: [PATCH 6/7] Cover complex input and validate sizes always --- ALPS3_MIGRATION_PLAN.md | 5 +++-- src/maxent_backcont.cpp | 2 -- test/backcontTest.cpp | 2 -- test/paramsTest.cpp | 21 +++++++++++++++++++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/ALPS3_MIGRATION_PLAN.md b/ALPS3_MIGRATION_PLAN.md index bdcc5e4..2af9773 100644 --- a/ALPS3_MIGRATION_PLAN.md +++ b/ALPS3_MIGRATION_PLAN.md @@ -377,7 +377,8 @@ unchanged. A text-input regression covers trailing blank lines. default `BASENAME` must not change). Then turn on `MAXENT_WERROR` in the `dev` preset. * B8: make the functions in `eigen_hdf5.hpp`/`eigen_lapack.hpp` `inline`. -* B4: the size check in `Backcont::max_error` (inverted `NDEBUG` guard). +* B4: make the size check in `Backcont::max_error` unconditional, avoiding an + out-of-bounds access in every build type. * B5, B6: remove the unreachable kernel branches. * B9: the data-file reading loop (`while (datstream)` reads past EOF); same results for valid files, plus a test with trailing blank lines. @@ -683,4 +684,4 @@ make -j8 && ctest # 6/6 executables, 35 cases pass, ~9 s | 2026-09-23 | 2.x | Pade removed (D7), on branch `modernize/remove-pade`: `pade/` (13 files: 6 built, 5 unbuilt alternatives, header, CMake), `MAXENT_BUILD_PADE`, and the README section. It required GMP (`mpf_class`, 256-bit default precision) and did not compile (B20). | | 2026-09-24 | 2.2 | Step 2.2 done on `modernize/step2.2`: kk regression cases, kk spline, closed-form Legendre kernel (GSL removed), Boost utilities → std. No reference changed; 41/41 tests. ALPSCore#668 merged (GoogleTest 1.18, not installed, CMake 3.16). Found B22 (performance). | | 2026-09-24 | sync | Synced with ALPSCore `master` `560ae112` (#669: C++14 required and default, ALPSCore compiled with exactly `ALPS_CXX_STD`, Boost.Math dependency removed; #670: Doxygen removed). Maxent `d529a14` against it (installed as C++14, Boost 1.88): configures without `Boost_DIR`, compiles as C++17, 41/41 tests, regression unchanged (only the known Legendre rounding-level differences from 2.2). Note: build ALPSCore in a fresh build directory; an old one keeps a stale compiler identification that Maxent's configure then rejects. | -| 2026-09-24 | 2.3A | Warning cleanup and no-output-change fixes complete: Eigen index types, initializer order, unused/deprecated code, inline HDF5/LAPACK helpers, debug size check, unreachable kernel branches, robust text-file extraction, and dead bindings/config code removed. The dev preset enables `MAXENT_WERROR`; 43/43 Release tests pass including full regression, and the LAPACK build is warning-free. | +| 2026-09-24 | 2.3A | Warning cleanup and no-output-change fixes complete: Eigen index types, initializer order, unused/deprecated code, inline HDF5/LAPACK helpers, unconditional size validation, unreachable kernel branches, robust three- and five-column text-file extraction, and dead bindings/config code removed. The dev preset enables `MAXENT_WERROR`; 44/44 Release tests pass including full regression, and the LAPACK build is warning-free. | diff --git a/src/maxent_backcont.cpp b/src/maxent_backcont.cpp index 4a76564..5b7ab21 100644 --- a/src/maxent_backcont.cpp +++ b/src/maxent_backcont.cpp @@ -39,11 +39,9 @@ vector_type Backcont::backcontinue(const vector_type &A){ } double Backcont::max_error(const vector_type &y1, const vector_type &y2){ double max_err = 0.0; -#ifndef NDEBUG if(y1.size() != y2.size()){ throw std::runtime_error("backcont vector size mismatch!"); } -#endif for(Eigen::Index i=0;imax_err){ diff --git a/test/backcontTest.cpp b/test/backcontTest.cpp index ad50a17..cc35149 100644 --- a/test/backcontTest.cpp +++ b/test/backcontTest.cpp @@ -210,9 +210,7 @@ alps::params p; //sensibility check EXPECT_EQ(G.size(),ndat); -#ifndef NDEBUG EXPECT_THROW(bc.max_error(G, vector_type::Zero(ndat + 1)), std::runtime_error); -#endif //check that backcont is right to first order const double threshold = 0.1; diff --git a/test/paramsTest.cpp b/test/paramsTest.cpp index 6e4e38d..00d3ac6 100644 --- a/test/paramsTest.cpp +++ b/test/paramsTest.cpp @@ -143,6 +143,27 @@ TEST(Parameters,RejectsIncompleteFinalDataRecord){ std::remove(pf.c_str()); } +TEST(Parameters,RejectsIncompleteFinalComplexDataRecord){ + std::string pf=alps::temporary_filename("in_file.dat"); + { + std::ofstream tempfile(pf.c_str()); + tempfile << "0 0.1 0.01 -0.2 0.02\n" + << "1 0.3 0.03 -0.4 0.04\n" + << "2 0.5 0.05 -0.6\n"; // Missing the imaginary error bar. + } + + alps::params p; + MaxEntSimulation::define_parameters(p); + p["BETA"]=2; + p["DATA"]=pf; + p["DATASPACE"]="frequency"; + p["PARTICLE_HOLE_SYMMETRY"]=false; + p["NDAT"] = 6; + + EXPECT_THROW(ContiParameters c(p), std::runtime_error); + std::remove(pf.c_str()); +} + TEST(Parameters,MaxentParams){ //set up parameters alps::params p; From 5ad3e52eb389862aee2febad7ce4932718aa7a84 Mon Sep 17 00:00:00 2001 From: Emanuel Gull Date: Thu, 24 Sep 2026 11:50:57 +0200 Subject: [PATCH 7/7] Reject malformed trailing data records --- src/maxent_params.cpp | 13 ++++++++++--- test/paramsTest.cpp | 8 ++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/maxent_params.cpp b/src/maxent_params.cpp index 23a1be8..5f61e88 100644 --- a/src/maxent_params.cpp +++ b/src/maxent_params.cpp @@ -51,7 +51,11 @@ void ContiParameters::read_data_from_text_file(const alps::params& p) { to_lower(dataspace); if(dataspace == "time" || dataspace == "legendre" || p["PARTICLE_HOLE_SYMMETRY"]==true){ double index, X_i, dX_i; - while (datstream >> index >> X_i >> dX_i) { + while (true) { + datstream >> std::ws; + if (datstream.eof()) break; + if (!(datstream >> index >> X_i >> dX_i)) + throw std::runtime_error("malformed data record in: " + fname); if (datIn < ndat()) { inputGrid_(datIn) = index; y_(datIn) = X_i / static_cast(p["NORM"]); @@ -69,7 +73,11 @@ void ContiParameters::read_data_from_text_file(const alps::params& p) { throw std::runtime_error("Your NDAT is odd!");\ } double index, X_i_re, dX_i_re, X_i_im, dX_i_im; - while (datstream >> index >> X_i_re >> dX_i_re >> X_i_im >> dX_i_im) { + while (true) { + datstream >> std::ws; + if (datstream.eof()) break; + if (!(datstream >> index >> X_i_re >> dX_i_re >> X_i_im >> dX_i_im)) + throw std::runtime_error("malformed complex data record in: " + fname); if (datIn < ndat()) { inputGrid_(datIn) = index; inputGrid_(datIn+1) = index; @@ -400,4 +408,3 @@ MaxEntParameters::MaxEntParameters(alps::params& p) : compute_minimal_chi2(); } - diff --git a/test/paramsTest.cpp b/test/paramsTest.cpp index 00d3ac6..a7ec85a 100644 --- a/test/paramsTest.cpp +++ b/test/paramsTest.cpp @@ -137,7 +137,9 @@ TEST(Parameters,RejectsIncompleteFinalDataRecord){ MaxEntSimulation::define_parameters(p); p["BETA"]=2; p["DATA"]=pf; - p["NDAT"] = 6; + // The five complete records already satisfy NDAT. The malformed tail must + // still be rejected rather than mistaken for clean EOF. + p["NDAT"] = 5; EXPECT_THROW(ContiParameters c(p), std::runtime_error); std::remove(pf.c_str()); @@ -158,7 +160,9 @@ TEST(Parameters,RejectsIncompleteFinalComplexDataRecord){ p["DATA"]=pf; p["DATASPACE"]="frequency"; p["PARTICLE_HOLE_SYMMETRY"]=false; - p["NDAT"] = 6; + // The two complete complex records already satisfy NDAT. The malformed tail + // must still be rejected rather than mistaken for clean EOF. + p["NDAT"] = 4; EXPECT_THROW(ContiParameters c(p), std::runtime_error); std::remove(pf.c_str());