From 65f80bd14f9fe4d6542cfbcf288993ac3e70ea6c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 2 Nov 2025 16:49:35 +0800 Subject: [PATCH 1/3] checks if idx != 0 for dense UniTensors when get_block(_) or put_block(_) is called --- include/UniTensor.hpp | 32 +++++++++++++++++++++++++++++--- tests/DenseUniTensor_test.cpp | 8 -------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/include/UniTensor.hpp b/include/UniTensor.hpp index 0ece48653..6ad7981ef 100644 --- a/include/UniTensor.hpp +++ b/include/UniTensor.hpp @@ -606,7 +606,13 @@ namespace cytnx { void print_diagram(const bool &bond_info = false) const; void print_blocks(const bool &full_info = true) const; void print_block(const cytnx_int64 &idx, const bool &full_info = true) const; - Tensor get_block(const cytnx_uint64 &idx = 0) const { return this->_block.clone(); } + Tensor get_block(const cytnx_uint64 &idx = 0) const { + cytnx_error_msg(idx != 0, + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "invalid. Use get_block(0).\n", + idx); + return this->_block.clone(); + } Tensor get_block(const std::vector &qnum, const bool &force) const { cytnx_error_msg( @@ -631,9 +637,21 @@ namespace cytnx { } // return a share view of block, this only work for non-symm tensor. - Tensor &get_block_(const cytnx_uint64 &idx = 0) { return this->_block; } + Tensor &get_block_(const cytnx_uint64 &idx = 0) { + cytnx_error_msg(idx != 0, + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "invalid. Use get_block_(0).\n", + idx); + return this->_block; + } // return a share view of block, this only work for non-symm tensor. - const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { return this->_block; } + const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { + cytnx_error_msg(idx != 0, + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "invalid. Use get_block_(0).\n", + idx); + return this->_block; + } cytnx_uint64 Nblocks() const { return 1; }; std::vector get_blocks() const { @@ -659,6 +677,10 @@ namespace cytnx { // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change // DenseUniTensor's dtype + cytnx_error_msg(idx != 0, + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "invalid. Use put_block(0).\n", + idx); // cytnx_error_msg(in.dtype() != this->dtype(), // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not // match.%s", @@ -685,6 +707,10 @@ namespace cytnx { void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change // DenseUniTensor's dtype + cytnx_error_msg(idx != 0, + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "invalid. Use get_block_(0).\n", + idx); // cytnx_error_msg(in.dtype() != this->dtype(), // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not diff --git a/tests/DenseUniTensor_test.cpp b/tests/DenseUniTensor_test.cpp index f9d7d9774..18b5bfe32 100644 --- a/tests/DenseUniTensor_test.cpp +++ b/tests/DenseUniTensor_test.cpp @@ -1266,11 +1266,9 @@ TEST_F(DenseUniTensorTest, get_block) { /*=====test info===== describe:test get_block out of range ====================*/ -#if FAIL_CASE_OPEN TEST_F(DenseUniTensorTest, get_block_out_of_range) { EXPECT_THROW(utzero345.get_block(3), std::logic_error); } -#endif /*=====test info===== describe:test get_block, diagonal @@ -1386,11 +1384,9 @@ TEST_F(DenseUniTensorTest, get_block__uninit) { /*=====test info===== describe:test get_block out of range ====================*/ -#if FAIL_CASE_OPEN TEST_F(DenseUniTensorTest, get_block__out_of_range) { EXPECT_THROW(utzero345.get_block_(3), std::logic_error); } -#endif TEST_F(DenseUniTensorTest, get_blocks) { EXPECT_THROW(utzero345.get_blocks(), std::logic_error); } @@ -1496,7 +1492,6 @@ TEST_F(DenseUniTensorTest, put_block_rank_mismatch) { /*=====test info===== describe:test put_block_, out of index ====================*/ -#if FAIL_CASE_OPEN TEST_F(DenseUniTensorTest, put_block_out_of_idx) { constexpr cytnx_uint64 dim1 = 2, dim2 = 3; auto tens = zeros({dim1, dim2}); @@ -1507,7 +1502,6 @@ TEST_F(DenseUniTensorTest, put_block_out_of_idx) { auto ut = UniTensor({Bond(dim1), Bond(dim2)}); EXPECT_THROW(ut.put_block(tens, 1), std::logic_error); } -#endif /*=====test info===== describe:test put_block_ @@ -1592,7 +1586,6 @@ TEST_F(DenseUniTensorTest, put_block__rank_mismatch) { /*=====test info===== describe:test put_block_, out of index ====================*/ -#if FAIL_CASE_OPEN TEST_F(DenseUniTensorTest, put_block__out_of_idx) { constexpr cytnx_uint64 dim1 = 2, dim2 = 3; auto tens = zeros({dim1, dim2}); @@ -1603,7 +1596,6 @@ TEST_F(DenseUniTensorTest, put_block__out_of_idx) { auto ut = UniTensor({Bond(dim1), Bond(dim2)}); EXPECT_THROW(ut.put_block_(tens, 1), std::logic_error); } -#endif /*=====test info===== describe:test put_blocks, input uninitialized UniTensor From ebd890c81395fd646527a7c1ccb5ed25c3202a5b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Sun, 2 Nov 2025 17:05:00 +0800 Subject: [PATCH 2/3] dense get_block(_): replaced standard argument by a method not taking any argument to avoid overhead of argument check; did not do this for put_block(_) for code readability --- include/UniTensor.hpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/include/UniTensor.hpp b/include/UniTensor.hpp index 6ad7981ef..b6eebb9d1 100644 --- a/include/UniTensor.hpp +++ b/include/UniTensor.hpp @@ -606,7 +606,8 @@ namespace cytnx { void print_diagram(const bool &bond_info = false) const; void print_blocks(const bool &full_info = true) const; void print_block(const cytnx_int64 &idx, const bool &full_info = true) const; - Tensor get_block(const cytnx_uint64 &idx = 0) const { + Tensor get_block() const { return this->_block.clone(); } + Tensor get_block(const cytnx_uint64 &idx) const { cytnx_error_msg(idx != 0, "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " "invalid. Use get_block(0).\n", @@ -637,7 +638,8 @@ namespace cytnx { } // return a share view of block, this only work for non-symm tensor. - Tensor &get_block_(const cytnx_uint64 &idx = 0) { + Tensor &get_block_() { return this->_block; } + Tensor &get_block_(const cytnx_uint64 &idx) { cytnx_error_msg(idx != 0, "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " "invalid. Use get_block_(0).\n", @@ -645,7 +647,8 @@ namespace cytnx { return this->_block; } // return a share view of block, this only work for non-symm tensor. - const Tensor &get_block_(const cytnx_uint64 &idx = 0) const { + const Tensor &get_block_() const { return this->_block; } + const Tensor &get_block_(const cytnx_uint64 &idx) const { cytnx_error_msg(idx != 0, "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " "invalid. Use get_block_(0).\n", @@ -674,7 +677,7 @@ namespace cytnx { } void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) { - // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change + // We don't check the dtype for DenseUniTensor, since it'll be more convenient to change // DenseUniTensor's dtype cytnx_error_msg(idx != 0, @@ -705,7 +708,7 @@ namespace cytnx { } // share view of the block void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { - // We don't check the dtype for DenseUniTensor, since it'll be more convinent to change + // We don't check the dtype for DenseUniTensor, since it'll be more convenient to change // DenseUniTensor's dtype cytnx_error_msg(idx != 0, "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " From 1c9a03fb095da7dc01b40f58ef8d39e5755df360 Mon Sep 17 00:00:00 2001 From: pcchen Date: Fri, 20 Mar 2026 09:09:17 +0800 Subject: [PATCH 3/3] fix DenseUniTensor put_block/put_block_ error message and format specifier - Fix copy-paste bug: put_block_ error message incorrectly said "Use get_block_(0)" instead of "Use put_block_(0)" - Replace %d with %llu (and cast to unsigned long long) for cytnx_uint64 in all four new error messages (get_block, get_block_ x2, put_block, put_block_) to avoid undefined behavior - Apply the same two-overload pattern used by get_block/get_block_ to put_block/put_block_: no-arg fast path + idx-with-check overload that delegates to it, making the API consistent Co-Authored-By: Claude Sonnet 4.6 --- include/UniTensor.hpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/include/UniTensor.hpp b/include/UniTensor.hpp index b6eebb9d1..fcee9f48f 100644 --- a/include/UniTensor.hpp +++ b/include/UniTensor.hpp @@ -609,9 +609,9 @@ namespace cytnx { Tensor get_block() const { return this->_block.clone(); } Tensor get_block(const cytnx_uint64 &idx) const { cytnx_error_msg(idx != 0, - "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu " "invalid. Use get_block(0).\n", - idx); + (unsigned long long)idx); return this->_block.clone(); } @@ -641,18 +641,18 @@ namespace cytnx { Tensor &get_block_() { return this->_block; } Tensor &get_block_(const cytnx_uint64 &idx) { cytnx_error_msg(idx != 0, - "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu " "invalid. Use get_block_(0).\n", - idx); + (unsigned long long)idx); return this->_block; } // return a share view of block, this only work for non-symm tensor. const Tensor &get_block_() const { return this->_block; } const Tensor &get_block_(const cytnx_uint64 &idx) const { cytnx_error_msg(idx != 0, - "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu " "invalid. Use get_block_(0).\n", - idx); + (unsigned long long)idx); return this->_block; } @@ -676,14 +676,10 @@ namespace cytnx { return this->_interface_block; // this will not share memory!! } - void put_block(const Tensor &in, const cytnx_uint64 &idx = 0) { + void put_block(const Tensor &in) { // We don't check the dtype for DenseUniTensor, since it'll be more convenient to change // DenseUniTensor's dtype - cytnx_error_msg(idx != 0, - "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " - "invalid. Use put_block(0).\n", - idx); // cytnx_error_msg(in.dtype() != this->dtype(), // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not // match.%s", @@ -706,14 +702,17 @@ namespace cytnx { this->_block = in.clone(); } } + void put_block(const Tensor &in, const cytnx_uint64 &idx) { + cytnx_error_msg(idx != 0, + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu " + "invalid. Use put_block(0).\n", + (unsigned long long)idx); + put_block(in); + } // share view of the block - void put_block_(Tensor &in, const cytnx_uint64 &idx = 0) { + void put_block_(Tensor &in) { // We don't check the dtype for DenseUniTensor, since it'll be more convenient to change // DenseUniTensor's dtype - cytnx_error_msg(idx != 0, - "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %d " - "invalid. Use get_block_(0).\n", - idx); // cytnx_error_msg(in.dtype() != this->dtype(), // "[ERROR][DenseUniTensor][put_block] The input tensor dtype does not @@ -737,6 +736,13 @@ namespace cytnx { this->_block = in; } } + void put_block_(Tensor &in, const cytnx_uint64 &idx) { + cytnx_error_msg(idx != 0, + "[ERROR][DenseUniTensor] Dense tensor has only one block, block number %llu " + "invalid. Use put_block_(0).\n", + (unsigned long long)idx); + put_block_(in); + } void put_block(const Tensor &in, const std::vector &qnum, const bool &force) { cytnx_error_msg(