Release Notes¶
Upcoming release (main)¶
New Features¶
The
bitstrings_to_ci_strings_symmetrize_spinfunction has been added, which allows one to obtain a collection of CI strings (with alpha and beta determinants symmetrized) from a collection of bitstrings.
recover_configurationsnow performs its per-bitstring correction in parallel when the consumer compiles with OpenMP enabled. The library remains header-only and depends only on the C++ standard library; the parallel path is guarded by_OPENMPand the serial behavior is used otherwise.
recover_configurationsvalidates all of its inputs before it corrects any bitstring. An unsatisfiable request – one whose target Hamming weight cannot be reached because too few eligible bits carry a nonzero weight – is now reported before any work begins rather than part way through it.
recover_configurationsdraws randomness from independent per-work-item streams rather than sequentially from the supplied generator, in serial and OpenMP builds alike. A counter-based engine – one whoseset_counteraccepts its counter type, such as the C++26 std::philox_engine – is keyed by bitstring index, so its result is identical for any number of threads and identical between a serial build and an OpenMP one. Any other engine must be seedable and is copied per thread; its results are valid, agree with a serial build when OpenMP runs on one thread, and depend on the thread count beyond that. A generator that is neither counter-based nor seedable is rejected at compile time under OpenMP but remains usable in a serial build.The counter-based tier is not specific to
std::philox_engine. An engine qualifies by naming a counter type – either a staticword_countfrom which the standardstd::array<result_type, word_count>shape is derived, or a nestedcounter_type– and accepting it inset_counter. See Random number generation for the reproducibility guarantees of each tier.
Upgrade Notes¶
The weighted sampling-without-replacement used by
recover_configurationsnow draws from a Fenwick tree rather than from astd::discrete_distributionwith rejection of already-drawn indices. Each draw isO(log n)with no rejection and no rebuilding, and consumes exactly one variate from the supplied generator. The sampling scheme is unchanged – it remains the sequential scheme, drawing indexiwith probability proportional to its weight among those not yet drawn – but the specific bitstrings returned for a given seed differ from previous releases.
The numerical output of
recover_configurationsfor a given seeded generator has changed. The returned unique bitstrings are now emitted in first-seen (input) order rather than in an unspecified order, and randomness is now drawn from per-work-item streams, so the specific bitstrings selected for a given seed differ. The returned distribution remains a valid refinement; only the selection and its ordering change.
A caller that catches the exception from an invalid request sees it raised earlier than before: the generator is no longer partially advanced, and a malformed bitstring is reported even when it follows bitstrings that would have corrected successfully.
recover_configurationsleavesrngin a substantially different state than before, in a way that depends on which tier the generator falls into. Either way it first draws two values to form a base seed. A seedable engine is then re-seeded from that base seed. A counter-based engine is instead re-keyed and its counter repositioned for each bitstring, so on return it is left keyed to the base seed and positioned at the last bitstring’s substream rather than anywhere related to where it started – its original key is gone. In both cases the number of values consumed is unspecified. Callers who continue to draw from the same generator afterwards should not rely on its resulting state; pass a copy if the original state matters.
Bug Fixes¶
Fixed sampling without replacement returning an out-of-range index when the weight vector spanned a wide enough range of magnitudes that accumulating it lost the smaller weights entirely (for instance
{1e-12, 1e12}). The index was used to subscript a parallel array, so the result was an out-of-bounds read and the flip of an arbitrary bit. Such a weight vector can now also exhaust its whole pool, where previously drawing from it could repeat an index or fail outright.
Other Notes¶
When the compiler asserts finite-math-only semantics (i.e., when
__FINITE_MATH_ONLY__is defined to a nonzero value, as it is under-ffinite-math-onlyand-ffast-math), the library now omits its now-redundant checks for NaN and infinite weight values.
The library will emit a compiler warning if
__FAST_MATH__is defined, as the use of-ffast-mathbreaks the IEEE 754 semantics that the library relies upon and is not supported. See Compilation flags for details.