From 896d73294cdde108eb12cdaa0e9580b31d546636 Mon Sep 17 00:00:00 2001 From: Ying-Jer Kao Date: Sat, 4 Apr 2026 00:09:08 +0800 Subject: [PATCH] fix: normalize Zn symmetry qnums --- src/Symmetry.cpp | 18 +++++++++++++----- tests/Bond_test.cpp | 13 +++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/Symmetry.cpp b/src/Symmetry.cpp index 3b65ff162..3d6ab8b5c 100644 --- a/src/Symmetry.cpp +++ b/src/Symmetry.cpp @@ -10,6 +10,14 @@ using namespace std; namespace cytnx { + namespace { + cytnx_int64 NormalizeZnQnum(cytnx_int64 qnum, const cytnx_int64 n) { + qnum %= n; + if (qnum < 0) qnum += n; + return qnum; + } + } // namespace + bool cytnx::Symmetry::operator==(const cytnx::Symmetry &rhs) const { return (this->stype() == rhs.stype()) && (this->n() == rhs.n()); } @@ -117,19 +125,19 @@ namespace cytnx { const std::vector &inR) { out.resize(inL.size() * inR.size()); for (cytnx_uint64 i = 0; i < out.size(); i++) { - out[i] = (inL[cytnx_uint64(i / inR.size())] + inR[i % inR.size()]) % (this->n); + out[i] = NormalizeZnQnum(inL[cytnx_uint64(i / inR.size())] + inR[i % inR.size()], this->n); } } void cytnx::ZnSymmetry::combine_rule_(cytnx_int64 &out, const cytnx_int64 &inL, const cytnx_int64 &inR, const bool &is_reverse) { + const cytnx_int64 combined = NormalizeZnQnum(inL + inR, this->n); if (is_reverse) - this->reverse_rule_(out, (inL + inR) % (this->n)); + this->reverse_rule_(out, combined); else - out = (inL + inR) % (this->n); + out = combined; } void cytnx::ZnSymmetry::reverse_rule_(cytnx_int64 &out, const cytnx_int64 &in) { - // out = -in<0?-in+this->n:-in; - out = -in + this->n; + out = NormalizeZnQnum(-in, this->n); } void cytnx::ZnSymmetry::print_info() const { diff --git a/tests/Bond_test.cpp b/tests/Bond_test.cpp index 13119b9b5..d7fc93acd 100644 --- a/tests/Bond_test.cpp +++ b/tests/Bond_test.cpp @@ -165,6 +165,19 @@ TEST(Bond, CombindBondSymm_v2) { EXPECT_THROW(bd_sym_a.combineBond(bd_sym_g), std::logic_error); } +TEST(Bond, ZnSymmetryNormalizesPublicRules) { + Symmetry z2 = Symmetry::Zn(2); + + EXPECT_EQ(z2.combine_rule(-1, 0), 1); + EXPECT_EQ(z2.combine_rule(0, -1), 1); + EXPECT_EQ(z2.combine_rule(-1, 0, true), 1); + EXPECT_EQ(z2.reverse_rule(0), 0); + EXPECT_EQ(z2.reverse_rule(1), 1); + EXPECT_TRUE(z2.check_qnum(z2.combine_rule(-1, 0))); + EXPECT_TRUE(z2.check_qnum(z2.combine_rule(0, -1))); + EXPECT_TRUE(z2.check_qnum(z2.reverse_rule(0))); +} + TEST(Bond, Clear_type) { Bond bd_sym = Bond(BD_KET, {{0, 2}, {3, 5}, {1, 6}, {4, 1}}, {4, 7, 2, 3});