fix(symmetry): FermionParitySymmetry::check_qnums rejected all qnums#1012
Conversation
check_qnums compared each qnum against this->n, but FermionParitySymmetry sets n = -2 (the fPar stype sentinel, not a modulus), so the plural form returned false for every non-empty input while the singular check_qnum correctly validated against [0, 2). No in-tree caller was affected (Bond validation uses the singular form), but the plural form is exposed via the Python bindings. Reimplement check_qnums as a loop over check_qnum so the two cannot diverge again, and add a gtest covering both forms. Note: the value-type Symmetry refactor branch (refactor/symmetry-value-type, #842) deliberately preserved this quirk byte-for-byte and will need to pick up this fix on rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request refactors FermionParitySymmetry::check_qnums in src/Symmetry.cpp to simplify the validation logic by delegating to check_qnum and returning early on failure. It also introduces unit tests for these checks in a new test file tests/Symmetry_test.cpp and registers it in tests/CMakeLists.txt. The reviewer suggested using a range-based for loop in check_qnums to make the code more idiomatic and avoid potential type mismatches.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| for (cytnx_uint64 i = 0; i < qnums.size(); i++) { | ||
| out = ((qnums[i] >= 0) && (qnums[i] < this->n)); | ||
| if (out == false) break; | ||
| if (!this->check_qnum(qnums[i])) return false; | ||
| } |
There was a problem hiding this comment.
Using a range-based for loop is more idiomatic in modern C++ and avoids potential type mismatch issues between cytnx_uint64 and std::vector::size_type (which is size_t).
| for (cytnx_uint64 i = 0; i < qnums.size(); i++) { | |
| out = ((qnums[i] >= 0) && (qnums[i] < this->n)); | |
| if (out == false) break; | |
| if (!this->check_qnum(qnums[i])) return false; | |
| } | |
| for (const auto &qnum : qnums) { | |
| if (!this->check_qnum(qnum)) return false; | |
| } |
There was a problem hiding this comment.
Applied in 816e73d — switched to the range-based for. Behavior is unchanged (still delegates to check_qnum and short-circuits on the first invalid qnum); this just drops the cytnx_uint64 vs size_t index-type mismatch. clang-format (v14) clean.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1012 +/- ##
==========================================
+ Coverage 31.82% 32.67% +0.84%
==========================================
Files 230 230
Lines 33124 33001 -123
Branches 13852 13746 -106
==========================================
+ Hits 10543 10784 +241
+ Misses 15539 14957 -582
- Partials 7042 7260 +218
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 55 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
Code Review — LGTMThe bug (confirmed): the plural form tested The fix (verified): reimplements the plural as a loop over Tests: both forms pinned for fPar — singular 0/1 accept, −1/2 reject; plural Coordination note (🟡)This collides with open #1010 (Symmetry → variant), which (1) also creates No findings on the change itself. LGTM. Posted by Claude Code on behalf of @pcchen |
…ck_qnums Address @gemini-code-assist review on #1012: a range-based loop is more idiomatic and sidesteps the cytnx_uint64 vs std::vector::size_type (size_t) index-type mismatch. Pure cleanup — behavior is unchanged (still delegates to check_qnum, still short-circuits on the first invalid qnum). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pcchen
left a comment
There was a problem hiding this comment.
Approving. Confirmed bug (the plural form tested qnums[i] < this->n against the n = -2 fPar sentinel — always false for non-empty input) and a structural fix: the plural now delegates per-element to the always-correct singular check_qnum ([0,2) range), so the two forms cannot diverge again. Empty-input semantics preserved; both forms pinned by tests (including the {0,1,2} not-just-first-element case); CI fully green on the current head (the follow-up commit is a cosmetic range-for conversion, semantically identical).
Coordination note stands: #1010 quirk-pinned this exact behavior and adds the same test file — its rebase should flip the pin and merge the two Symmetry_test.cpp contents.
Posted by Claude Code on behalf of @pcchen
Summary
FermionParitySymmetry::check_qnumscompared each qnum againstthis->n, butFermionParitySymmetrysetsn = -2— thefParstype sentinel fromSymmetryType, not a modulus. As a result the plural form returnedfalsefor every non-empty input, while the singularcheck_qnumcorrectly validated against[0, 2).Impact: no in-tree caller was affected — Bond validation (
src/Bond.cpp) uses the singularcheck_qnum, which is why fPar bonds have always validated fine. The plural form is, however, exposed to users via the Python bindings (Symmetry.check_qnums), where it silently rejected valid parity qnum lists.Fix
Reimplement
check_qnumsas a loop overcheck_qnumso the two forms cannot diverge again.Tests
New
tests/Symmetry_test.cpp(registered intests/CMakeLists.txt) covering both forms for fPar:check_qnums({0, 1}) == true,check_qnums({2}) == false, plus{-1}and{0, 1, 2}rejectioncheck_qnumfor 0/1 accepted, -1/2 rejectedVerified red-green: the
check_qnums({0, 1})assertion fails before the fix and passes after.Note for #842
The value-type Symmetry refactor branch (
refactor/symmetry-value-type, #842) deliberately preserved this quirk byte-for-byte; it should pick up this fix when rebasing.🤖 Generated with Claude Code