diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b1c571f..82ec1ae1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [0.8.0] - Unreleased +- Reduce the maximum allowed number of bits in the binary representation of + a basis state index (``hilbert_space::max_n_bits``) to 63. This way + ``hilbert_space::dim()`` can return a valid value of type ``sv_index_type`` + even when all 63 bits are used up. - Fixed a negative index bug in ``n_fermion_sector_view``. Credits to Dr. Cezary Śliwa for providing the patch. - Whenever possible, use compiler intrinsics to speed up complex bit diff --git a/doc/images/basis_state.svg b/doc/images/basis_state.svg index 85e316fd..4754d268 100644 --- a/doc/images/basis_state.svg +++ b/doc/images/basis_state.svg @@ -1,20 +1,20 @@ + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + sodipodi:docname="basis_state.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:ns2="http://www.iki.fi/pav/software/textext/"> + id="base" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1"> + type="xygrid" + spacingy="1" + spacingx="1" + units="mm" + visible="true" /> + position="35.86875,4.2422485" + inkscape:locked="false" /> + position="32.429167,3.4484985" + inkscape:locked="false" /> + position="40.895833,1.5964085" + inkscape:locked="false" /> @@ -628,7 +638,7 @@ 63 + style="font-size:1.41111px;stroke-width:0.264583px">62 \ @@ -166,8 +170,7 @@ does not matter -- they will be reordered automatically. Construction of the elementary spaces is performed by the functor :expr:`es_constr`. Throws :struct:`hilbert_space_too_big` if all collected elementary spaces - together would overflow the 64-bit integer type of the basis state index. - + together would exceed the 63-bit limit of the basis state index. .. rubric:: Copy/move-constructors and assignments @@ -191,7 +194,7 @@ does not matter -- they will be reordered automatically. :struct:`elementary_space_exists` if an elementary space equivalent to :expr:`es` is already part of the product. Throws :struct:`hilbert_space_too_big` if adding :expr:`es` into the product - would overflow the 64-bit integer type of the basis state index. + would exceed the 63-bit limit of the basis state index. .. function:: bool has(elementary_space const& es) const @@ -233,8 +236,8 @@ does not matter -- they will be reordered automatically. The total number of used bits in the binary representation of a basis state index. - .. function:: std::size_t dim() const - friend std::size_t get_dim(hilbert_space const& hs) + .. function:: sv_index_type dim() const + friend sv_index_type get_dim(hilbert_space const& hs) The dimension of this Hilbert space computed as a product of dimensions of the elementary spaces. @@ -266,7 +269,7 @@ does not matter -- they will be reordered automatically. .. struct:: hilbert_space_too_big : public std::runtime_error - The total basis state index size exceeds 64 bits. + The total basis state index size exceeds 63 bits. .. function:: template class hilbert_space { // Size of a Hilbert space must be representable by an integer with // at most this number of bits. - static constexpr int max_n_bits = std::numeric_limits::digits; + static constexpr int max_n_bits = + std::numeric_limits::digits - 1; // Compare two elementary_space_t objects wrapped in std::unique_ptr struct less { @@ -94,7 +95,7 @@ template class hilbert_space { explicit hilbert_space_too_big(int n_bits) : std::runtime_error("Hilbert space size is not representable " "by a " + - std::to_string(max_n_bits) + + std::to_string(max_n_bits + 1) + "-bit integer (n_bits = " + std::to_string(n_bits) + ")"), n_bits(n_bits) {} @@ -227,8 +228,8 @@ template class hilbert_space { int total_n_bits() const { return bit_range_end_ + 1; } // Dimension of this Hilbert space - std::size_t dim() const { return std::size_t(1) << total_n_bits(); } - friend std::size_t get_dim(hilbert_space const& hs) { return hs.dim(); } + sv_index_type dim() const { return sv_index_type(1) << total_n_bits(); } + friend sv_index_type get_dim(hilbert_space const& hs) { return hs.dim(); } // Apply functor `f` to all basis state indices template diff --git a/test/hilbert_space.cpp b/test/hilbert_space.cpp index 770fbb35..1dd10492 100644 --- a/test/hilbert_space.cpp +++ b/test/hilbert_space.cpp @@ -348,17 +348,18 @@ TEST_CASE("Hilbert space", "[hilbert_space]") { SECTION("Very big Hilbert space") { hs_type hs1; - for(int i = 0; i < 32; ++i) + for(int i = 0; i < 31; ++i) hs1.add(make_space_spin(3.0 / 2, "s", i)); using ex_type = hs_type::hilbert_space_too_big; - CHECK_THROWS_AS(hs1.add(make_space_spin(3.0 / 2, "s", 32)), ex_type); + CHECK_THROWS_AS(hs1.add(make_space_spin(3.0 / 2, "s", 31)), ex_type); auto expr = expression(1); - for(int i = 0; i < 32; ++i) + for(int i = 0; i < 31; ++i) expr *= S_p<4>("s", i); + expr *= S_p<2>("s", 31); hs_type hs2(expr); - CHECK(hs2.total_n_bits() == 64); + CHECK(hs2.total_n_bits() == 63); expr *= S_p<4>("s", 32); CHECK_THROWS_AS(hs_type(expr), ex_type);