Skip to content

Conversation

@jhenin
Copy link
Member

@jhenin jhenin commented Oct 23, 2025

Implements weighted Poisson integration of free energy gradients.
Also fixes a small error in Neumann boundary conditions for the existing unweighted case.

TODO:

  • revert formatting changes (braces and indents)
  • user flag to enable/disable
  • Documentation
  • Fix failing tests due to boundary condition fixes in unweighted Poisson
  • Add test for new feature, weighted Poisson

@levo-str levo-str force-pushed the weighted_poisson_merged_ended branch 2 times, most recently from 69c9e20 to 3c67197 Compare October 28, 2025 17:42
@jhenin jhenin changed the title Weighted poisson integration (for real this time) Weighted poisson integration Nov 14, 2025
@levo-str levo-str force-pushed the weighted_poisson_merged_ended branch 2 times, most recently from 3c67197 to d63167b Compare November 19, 2025 12:21
@levo-str levo-str force-pushed the weighted_poisson_merged_ended branch from 8273c3f to 817a80e Compare November 28, 2025 14:50
@levo-str levo-str force-pushed the weighted_poisson_merged_ended branch 3 times, most recently from 165ec32 to 252a3d0 Compare December 10, 2025 15:05
@jhenin jhenin marked this pull request as ready for review December 11, 2025 17:00
@jhenin jhenin requested review from HanatoK and giacomofiorin and removed request for HanatoK and giacomofiorin December 17, 2025 15:21
-2.00000000000000e-01 1.40000000000000e+00 7.70437678236428e-02
-2.00000000000000e-01 1.45000000000000e+00 7.69776442679124e-02
-2.00000000000000e-01 1.50000000000000e+00 7.69557395004421e-02
-2.00000000000000e-01 -5.00000000000000e-01 5.66747557569237e-02
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are the test data changed here? I know this PR fixes the boundary condition in the integrator but 018_pathCV does not use any periodic CVs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix applies to Neumann (non-periodic) boundary conditions.

width 0.2
lowerBoundary 1.0
upperBoundary 5.0
upperBoundary 6.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the upper boundary changed in the test here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ensures that the custom grid has a different number of points than the default one based on the colvar's parameters. Because there was an accidental match in the previous test, some errors went unnoticed.

bool colvarproxy_stub::total_forces_same_step() const
{
return total_force_requested;
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this changed? Should it be also applied to the GPU test interface?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, but @giacomofiorin may have a different opinion. I didn't see a rationale for that flag changing based on total_force_requested, i.e. the fact that it's true does not indicate that total forces are enabled or requested or even available.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really have an opinion here, and certainly I wouldn't have a strong opinion on total-forces features. As a matter of fact, I even suggested to remove the code path associated with the "same step" feature.
#887 (comment)

bool weighted = false;
bool precompute = true;

colvar_grid_scalar* computation_grid;
Copy link
Member

@HanatoK HanatoK Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to use shared_ptr instead of a raw pointer, you can inherit this class from std::enable_shared_from_this. Also, if you want to keep the raw pointer, it should be initialized as nullptr.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, since this is not managing any memory, we'll keep the raw pointer for simplicity but initialize to nullptr.


// Helper function to print vector<int>
std::string vec_to_string(const std::vector<int> &vec)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helper function is defined in the global namespace, and only used when debugging. It may cause linking errors if downstream MD engines have a function with the same name, so I think either it should be commented out, or put in the colvarmodule or a separate namespace.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, this is a leftover from debugging, removing.

gradients->incr(ix)) {
size_t count = gradients->samples->value(ix);
if (count > 0) {
insert_into_sorted_list<size_t>(sorted_counts, count);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with the algorithm details, but random insertion in a vector should be quite slow. Why not just push_back and then std::sort?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, thanks!

coefficient += regularized_weights[gradients->address(weight_coordinate)];
}
coefficient *= weight_counts[i];
laplacian_coefficients[computation_grid->address(ix) * multiplicity + i] += coefficient;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to pre-calculate the computation_grid->address(ix) * multiplicity in the outer loop?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm suggesting that Kevin-Lâm tries it, but my recent experience is that current compilers already optimize the hell out of everything, so there might be nothing to gain.

std::vector<int> zero_vector(nd, 0);
gradients_to_average_relative_positions.push_back(zero_vector);
} else {
for (int i = 0; i < pow(2, directions_to_average_along.size()); i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each time when comparing i with the end of loop, it has to recalculate pow, which might be slow. Is it possible to cache the index of the end of loop? Also, you should consider using cvm::integer_power.

@HanatoK
Copy link
Member

HanatoK commented Dec 17, 2025

When restarting 000_eulerangles_ext_abf2d_euler_weighted, NAMD crashes. The GDB backtrace:

#0  0x00007ffff763dd3c in __pthread_kill_implementation () from /lib64/libc.so.6
#1  0x00007ffff75e27b6 in raise () from /lib64/libc.so.6
#2  0x00007ffff75c934b in abort () from /lib64/libc.so.6
#3  0x00007ffff7889972 in std::__glibcxx_assert_fail(char const*, int, char const*, char const*) () from /lib64/libstdc++.so.6
#4  0x00000000009b1cd7 in std::vector<double, std::allocator<double> >::operator[] (this=0x1d85b08, __n=0) at /usr/include/c++/15/bits/stl_vector.h:1263
#5  0x00000000013ba889 in colvargrid_integrate::update_weighted_div_local (this=0x1d85770, ix0=std::vector of length 2, capacity 2 = {...}) at colvars/src/colvargrid_integrate.cpp:344
#6  0x00000000013b8029 in colvargrid_integrate::set_weighted_div (this=0x1d85770) at colvars/src/colvargrid_integrate.cpp:151
#7  0x00000000012b8869 in colvargrid_integrate::set_div (this=0x1d85770) at colvars/src/colvargrid_integrate.h:50
#8  0x00000000012c48fb in colvarbias_abf::read_state_data_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:968
#9  0x00000000012b66ab in colvarbias_abf::read_state_data (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:1017
#10 0x00000000012a9a2a in colvarbias::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:641
#11 0x00000000012a43fb in colvarbias::read_state (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:665
#12 0x00000000013d2c5e in colvarmodule::read_objects_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1811
#13 0x00000000013e7d2f in colvarmodule::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1724
#14 0x00000000013d25b9 in colvarmodule::read_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1732
#15 0x00000000013d11fe in colvarmodule::setup_input (this=0x1b92970) at colvars/src/colvarmodule.cpp:1562
#16 0x00000000014274e0 in cvscript_cv_load (pobj=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript_commands.h:484
#17 0x000000000141c9c1 in colvarscript::run (this=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript.cpp:439
#18 0x000000000141e87f in tcl_run_colvarscript_command (my_interp=0x1a75410, objc=3, objv=0x1a79790) at colvars/src/colvarscript.cpp:740
#19 0x00007ffff7de3ab8 in TclNRRunCallbacks () from /lib64/libtcl8.6.so
#20 0x00007ffff7dea234 in ?? () from /lib64/libtcl8.6.so
#21 0x00007ffff7e90587 in Tcl_FSEvalFileEx () from /lib64/libtcl8.6.so
#22 0x00007ffff7e90807 in Tcl_EvalFile () from /lib64/libtcl8.6.so
#23 0x0000000001121e77 in ScriptTcl::load (this=0x1a742b0, scriptFile=0x7fffffffd459 "test.restart.namd") at src/ScriptTcl.C:2423
#24 0x00000000009c463c in after_backend_init (argc=2, argv=0x7fffffffce68) at src/mainfunc.C:181
#25 0x00000000009c3f88 in main (argc=3, argv=0x7fffffffce68) at src/mainfunc.C:52

cvm::real weight = regularized_weights[gradients->address(surrounding_point_coordinates)];

for (size_t i = 0; i < nd; i++) {
div_at_point += pow(-1, surrounding_point_relative_position[i] + 1) *
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(-1)^n could be either -1 or 1 depending on whether n is an even number or an odd number, so this can be simply calculated without calling pow.

{
const size_t linear_index = computation_grid->address(ix0);
cvm::real div_at_point = 0;
for (std::vector<int> surrounding_point_relative_position :
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to use const std::vector<int>&.

surrounding_points_relative_positions.clear();
size_t n_combinations = pow(2, nd);
for (size_t i = 0; i < n_combinations; i++) {
surrounding_points_relative_positions.push_back(convert_base_two(i, nd));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that the calls to convert_base_two is unnecessary because an integer has already all its bits itself. convert_base_two simply checks the bits of i and stores them into a vector of nd size. But maybe I am wrong, and I am not sure how to optimize this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not performance-critical, and this form is more legible than a bunch of (n >>i)&1 throughout the code.

@levo-str levo-str force-pushed the weighted_poisson_merged_ended branch from 7f3e54a to 24f4098 Compare December 19, 2025 10:10
Thanks Haochuan for the feedback.
@levo-str
Copy link

When restarting 000_eulerangles_ext_abf2d_euler_weighted, NAMD crashes. The GDB backtrace:

#0  0x00007ffff763dd3c in __pthread_kill_implementation () from /lib64/libc.so.6
#1  0x00007ffff75e27b6 in raise () from /lib64/libc.so.6
#2  0x00007ffff75c934b in abort () from /lib64/libc.so.6
#3  0x00007ffff7889972 in std::__glibcxx_assert_fail(char const*, int, char const*, char const*) () from /lib64/libstdc++.so.6
#4  0x00000000009b1cd7 in std::vector<double, std::allocator<double> >::operator[] (this=0x1d85b08, __n=0) at /usr/include/c++/15/bits/stl_vector.h:1263
#5  0x00000000013ba889 in colvargrid_integrate::update_weighted_div_local (this=0x1d85770, ix0=std::vector of length 2, capacity 2 = {...}) at colvars/src/colvargrid_integrate.cpp:344
#6  0x00000000013b8029 in colvargrid_integrate::set_weighted_div (this=0x1d85770) at colvars/src/colvargrid_integrate.cpp:151
#7  0x00000000012b8869 in colvargrid_integrate::set_div (this=0x1d85770) at colvars/src/colvargrid_integrate.h:50
#8  0x00000000012c48fb in colvarbias_abf::read_state_data_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:968
#9  0x00000000012b66ab in colvarbias_abf::read_state_data (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:1017
#10 0x00000000012a9a2a in colvarbias::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:641
#11 0x00000000012a43fb in colvarbias::read_state (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:665
#12 0x00000000013d2c5e in colvarmodule::read_objects_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1811
#13 0x00000000013e7d2f in colvarmodule::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1724
#14 0x00000000013d25b9 in colvarmodule::read_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1732
#15 0x00000000013d11fe in colvarmodule::setup_input (this=0x1b92970) at colvars/src/colvarmodule.cpp:1562
#16 0x00000000014274e0 in cvscript_cv_load (pobj=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript_commands.h:484
#17 0x000000000141c9c1 in colvarscript::run (this=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript.cpp:439
#18 0x000000000141e87f in tcl_run_colvarscript_command (my_interp=0x1a75410, objc=3, objv=0x1a79790) at colvars/src/colvarscript.cpp:740
#19 0x00007ffff7de3ab8 in TclNRRunCallbacks () from /lib64/libtcl8.6.so
#20 0x00007ffff7dea234 in ?? () from /lib64/libtcl8.6.so
#21 0x00007ffff7e90587 in Tcl_FSEvalFileEx () from /lib64/libtcl8.6.so
#22 0x00007ffff7e90807 in Tcl_EvalFile () from /lib64/libtcl8.6.so
#23 0x0000000001121e77 in ScriptTcl::load (this=0x1a742b0, scriptFile=0x7fffffffd459 "test.restart.namd") at src/ScriptTcl.C:2423
#24 0x00000000009c463c in after_backend_init (argc=2, argv=0x7fffffffce68) at src/mainfunc.C:181
#25 0x00000000009c3f88 in main (argc=3, argv=0x7fffffffce68) at src/mainfunc.C:52

Could you tell me exactly how you got this ? Is it running on local ? Because on git all the tests pass.

@HanatoK
Copy link
Member

HanatoK commented Jan 12, 2026

When restarting 000_eulerangles_ext_abf2d_euler_weighted, NAMD crashes. The GDB backtrace:

#0  0x00007ffff763dd3c in __pthread_kill_implementation () from /lib64/libc.so.6
#1  0x00007ffff75e27b6 in raise () from /lib64/libc.so.6
#2  0x00007ffff75c934b in abort () from /lib64/libc.so.6
#3  0x00007ffff7889972 in std::__glibcxx_assert_fail(char const*, int, char const*, char const*) () from /lib64/libstdc++.so.6
#4  0x00000000009b1cd7 in std::vector<double, std::allocator<double> >::operator[] (this=0x1d85b08, __n=0) at /usr/include/c++/15/bits/stl_vector.h:1263
#5  0x00000000013ba889 in colvargrid_integrate::update_weighted_div_local (this=0x1d85770, ix0=std::vector of length 2, capacity 2 = {...}) at colvars/src/colvargrid_integrate.cpp:344
#6  0x00000000013b8029 in colvargrid_integrate::set_weighted_div (this=0x1d85770) at colvars/src/colvargrid_integrate.cpp:151
#7  0x00000000012b8869 in colvargrid_integrate::set_div (this=0x1d85770) at colvars/src/colvargrid_integrate.h:50
#8  0x00000000012c48fb in colvarbias_abf::read_state_data_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:968
#9  0x00000000012b66ab in colvarbias_abf::read_state_data (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:1017
#10 0x00000000012a9a2a in colvarbias::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:641
#11 0x00000000012a43fb in colvarbias::read_state (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:665
#12 0x00000000013d2c5e in colvarmodule::read_objects_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1811
#13 0x00000000013e7d2f in colvarmodule::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1724
#14 0x00000000013d25b9 in colvarmodule::read_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1732
#15 0x00000000013d11fe in colvarmodule::setup_input (this=0x1b92970) at colvars/src/colvarmodule.cpp:1562
#16 0x00000000014274e0 in cvscript_cv_load (pobj=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript_commands.h:484
#17 0x000000000141c9c1 in colvarscript::run (this=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript.cpp:439
#18 0x000000000141e87f in tcl_run_colvarscript_command (my_interp=0x1a75410, objc=3, objv=0x1a79790) at colvars/src/colvarscript.cpp:740
#19 0x00007ffff7de3ab8 in TclNRRunCallbacks () from /lib64/libtcl8.6.so
#20 0x00007ffff7dea234 in ?? () from /lib64/libtcl8.6.so
#21 0x00007ffff7e90587 in Tcl_FSEvalFileEx () from /lib64/libtcl8.6.so
#22 0x00007ffff7e90807 in Tcl_EvalFile () from /lib64/libtcl8.6.so
#23 0x0000000001121e77 in ScriptTcl::load (this=0x1a742b0, scriptFile=0x7fffffffd459 "test.restart.namd") at src/ScriptTcl.C:2423
#24 0x00000000009c463c in after_backend_init (argc=2, argv=0x7fffffffce68) at src/mainfunc.C:181
#25 0x00000000009c3f88 in main (argc=3, argv=0x7fffffffce68) at src/mainfunc.C:52

Could you tell me exactly how you got this ? Is it running on local ? Because on git all the tests pass.

Yes, I ran the code locally. The Github CI test should fail on the crash but I don't know why it didn't. As you can see in https://github.com/Colvars/colvars/actions/runs/20366808773/job/58523739156?pr=872#step:15:109, NAMD indeed crashed.

@levo-str
Copy link

When restarting 000_eulerangles_ext_abf2d_euler_weighted, NAMD crashes. The GDB backtrace:

#0  0x00007ffff763dd3c in __pthread_kill_implementation () from /lib64/libc.so.6
#1  0x00007ffff75e27b6 in raise () from /lib64/libc.so.6
#2  0x00007ffff75c934b in abort () from /lib64/libc.so.6
#3  0x00007ffff7889972 in std::__glibcxx_assert_fail(char const*, int, char const*, char const*) () from /lib64/libstdc++.so.6
#4  0x00000000009b1cd7 in std::vector<double, std::allocator<double> >::operator[] (this=0x1d85b08, __n=0) at /usr/include/c++/15/bits/stl_vector.h:1263
#5  0x00000000013ba889 in colvargrid_integrate::update_weighted_div_local (this=0x1d85770, ix0=std::vector of length 2, capacity 2 = {...}) at colvars/src/colvargrid_integrate.cpp:344
#6  0x00000000013b8029 in colvargrid_integrate::set_weighted_div (this=0x1d85770) at colvars/src/colvargrid_integrate.cpp:151
#7  0x00000000012b8869 in colvargrid_integrate::set_div (this=0x1d85770) at colvars/src/colvargrid_integrate.h:50
#8  0x00000000012c48fb in colvarbias_abf::read_state_data_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:968
#9  0x00000000012b66ab in colvarbias_abf::read_state_data (this=0x1d5a880, is=...) at colvars/src/colvarbias_abf.cpp:1017
#10 0x00000000012a9a2a in colvarbias::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:641
#11 0x00000000012a43fb in colvarbias::read_state (this=0x1d5a880, is=...) at colvars/src/colvarbias.cpp:665
#12 0x00000000013d2c5e in colvarmodule::read_objects_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1811
#13 0x00000000013e7d2f in colvarmodule::read_state_template_<std::basic_istream<char, std::char_traits<char> > > (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1724
#14 0x00000000013d25b9 in colvarmodule::read_state (this=0x1b92970, is=...) at colvars/src/colvarmodule.cpp:1732
#15 0x00000000013d11fe in colvarmodule::setup_input (this=0x1b92970) at colvars/src/colvarmodule.cpp:1562
#16 0x00000000014274e0 in cvscript_cv_load (pobj=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript_commands.h:484
#17 0x000000000141c9c1 in colvarscript::run (this=0x1b4b140, objc=3, objv=0x7fffffffb9b0) at colvars/src/colvarscript.cpp:439
#18 0x000000000141e87f in tcl_run_colvarscript_command (my_interp=0x1a75410, objc=3, objv=0x1a79790) at colvars/src/colvarscript.cpp:740
#19 0x00007ffff7de3ab8 in TclNRRunCallbacks () from /lib64/libtcl8.6.so
#20 0x00007ffff7dea234 in ?? () from /lib64/libtcl8.6.so
#21 0x00007ffff7e90587 in Tcl_FSEvalFileEx () from /lib64/libtcl8.6.so
#22 0x00007ffff7e90807 in Tcl_EvalFile () from /lib64/libtcl8.6.so
#23 0x0000000001121e77 in ScriptTcl::load (this=0x1a742b0, scriptFile=0x7fffffffd459 "test.restart.namd") at src/ScriptTcl.C:2423
#24 0x00000000009c463c in after_backend_init (argc=2, argv=0x7fffffffce68) at src/mainfunc.C:181
#25 0x00000000009c3f88 in main (argc=3, argv=0x7fffffffce68) at src/mainfunc.C:52

Could you tell me exactly how you got this ? Is it running on local ? Because on git all the tests pass.

Yes, I ran the code locally. The Github CI test should fail on the crash but I don't know why it didn't. As you can see in https://github.com/Colvars/colvars/actions/runs/20366808773/job/58523739156?pr=872#step:15:109, NAMD indeed crashed.

Ok, thank you ! it should be fixed now. I had already spotted the bug and fixed it but in another branch (that you may review soon too)...

Fix the compilation error of comparing signed and unsigned integers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants