TEST_CASE("TCI Matrix exponential - complex64 dtype preservation") in test/source/test_linear_algebra.cpp fails in about half of full-suite runs and passes in the rest, from one binary with no rebuild in between. The assertion that fails is the unitarity check, not the dtype check.
Both observations below are on f59751a, with external/Cytnx and external/tcict — the conformance-test suite, both public per .gitmodules — at their pinned revisions. All commands run from the repository root. Environment: macOS arm64, Apple clang version 21.0.0 (clang-2100.1.1.101), Command Line Tools 26.6.0, Homebrew OpenBLAS 0.3.34.
Reproduction
cmake -Stest -Bbuild-a -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/macos-homebrew.cmake
cmake --build build-a -j8 --target TCITests
This is the configure shape .github/workflows/macos.yml and .github/workflows/ubuntu.yml use, plus the toolchain file needed to find keg-only OpenBLAS. The source root is test/, so the binary lands at build-a/TCITests.
Running it eight times: four runs reported the failure, four did not. Every failure reported the same value, and it is far outside the tolerance rather than marginally over it:
===============================================================================
test/source/test_linear_algebra.cpp:36:
TEST CASE: TCI Matrix exponential - complex64 dtype preservation
test/source/test_linear_algebra.cpp:56: ERROR: CHECK( std::abs(col0_norm_sq - 1.0f) < 1e-2f ) is NOT correct!
values: CHECK( 0.492126 < 0.01 )
Six runs of the same binary restricted to --test-case="TCI Matrix exponential*" all passed. The suite is doctest and add_test passes no ordering flags, so cases run in declaration order with no randomization — yet the same binary in the same order gives different answers across runs.
The sanitizer build does not reproduce it
brew-debug is in the tracked CMakePresets.json and roots at the repository, so its binary is one level deeper:
cmake --preset brew-debug -Bbuild-b
cmake --build build-b -j8 --target TCITests
ASAN_OPTIONS=detect_odr_violation=1:detect_container_overflow=0:abort_on_error=0:halt_on_error=0 \
build-b/test/TCITests
Eight runs, none reported the failure. Both arms were driven the same way — the test binary executed directly, no ctest wrapper — so the harness is not the variable.
Two caveats on this arm, both of which weaken it as evidence:
- The preset sets
ENABLE_ASAN_ODR=ON, declared in the root CMakeLists.txt, which adds -fsanitize=address -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls. That is a change of optimization level as well as a sanitizer, so this arm does not isolate the sanitizer. A third build at -O1 without it would separate them; I have not run one.
- The
ASAN_OPTIONS string is the one the root CMakeLists.txt attaches to the TCITests ctest entry. Its detect_container_overflow=0 is load-bearing — without it the binary aborts early on a libc++ container check — but that detector is also how ASan would report an out-of-bounds write, which is one of the shapes that could explain a run-to-run-varying element. So this arm's silence may be partly self-inflicted.
Why a precision explanation does not fit
The case builds a 2x2 tensor, zero-initialized, then sets two entries:
tci::CytnxTensor<cytnx::cytnx_complex64> anti_herm_f;
tci::zeros(ctx, {2, 2}, anti_herm_f);
tci::set_elem(ctx, anti_herm_f, {0, 1}, cytnx::cytnx_complex64(1.0f, 0.0f));
tci::set_elem(ctx, anti_herm_f, {1, 0}, cytnx::cytnx_complex64(-1.0f, 0.0f));
The exponential of that matrix is a plane rotation, so its first column has unit norm exactly, and 0.492126 is wrong by roughly half rather than by a rounding step.
I have not identified the mechanism. The fact to explain is that the result varies run to run for a fixed binary and a fixed case order.
Note
The case creates its context as tci::context_handle_t<tci::CytnxTensor<cytnx::cytnx_complex128>> and then passes it to cytnx::cytnx_complex64 tensors and operations. CytnxContextHandle wraps only an int device id, so the mismatch looks cosmetic rather than causal — recorded in case it is not.
TEST_CASE("TCI Matrix exponential - complex64 dtype preservation")intest/source/test_linear_algebra.cppfails in about half of full-suite runs and passes in the rest, from one binary with no rebuild in between. The assertion that fails is the unitarity check, not the dtype check.Both observations below are on
f59751a, withexternal/Cytnxandexternal/tcict— the conformance-test suite, both public per.gitmodules— at their pinned revisions. All commands run from the repository root. Environment: macOS arm64,Apple clang version 21.0.0 (clang-2100.1.1.101), Command Line Tools 26.6.0, Homebrew OpenBLAS 0.3.34.Reproduction
This is the configure shape
.github/workflows/macos.ymland.github/workflows/ubuntu.ymluse, plus the toolchain file needed to find keg-only OpenBLAS. The source root istest/, so the binary lands atbuild-a/TCITests.Running it eight times: four runs reported the failure, four did not. Every failure reported the same value, and it is far outside the tolerance rather than marginally over it:
Six runs of the same binary restricted to
--test-case="TCI Matrix exponential*"all passed. The suite is doctest andadd_testpasses no ordering flags, so cases run in declaration order with no randomization — yet the same binary in the same order gives different answers across runs.The sanitizer build does not reproduce it
brew-debugis in the trackedCMakePresets.jsonand roots at the repository, so its binary is one level deeper:Eight runs, none reported the failure. Both arms were driven the same way — the test binary executed directly, no ctest wrapper — so the harness is not the variable.
Two caveats on this arm, both of which weaken it as evidence:
ENABLE_ASAN_ODR=ON, declared in the rootCMakeLists.txt, which adds-fsanitize=address -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls. That is a change of optimization level as well as a sanitizer, so this arm does not isolate the sanitizer. A third build at-O1without it would separate them; I have not run one.ASAN_OPTIONSstring is the one the rootCMakeLists.txtattaches to theTCITestsctest entry. Itsdetect_container_overflow=0is load-bearing — without it the binary aborts early on a libc++ container check — but that detector is also how ASan would report an out-of-bounds write, which is one of the shapes that could explain a run-to-run-varying element. So this arm's silence may be partly self-inflicted.Why a precision explanation does not fit
The case builds a 2x2 tensor, zero-initialized, then sets two entries:
The exponential of that matrix is a plane rotation, so its first column has unit norm exactly, and
0.492126is wrong by roughly half rather than by a rounding step.I have not identified the mechanism. The fact to explain is that the result varies run to run for a fixed binary and a fixed case order.
Note
The case creates its context as
tci::context_handle_t<tci::CytnxTensor<cytnx::cytnx_complex128>>and then passes it tocytnx::cytnx_complex64tensors and operations.CytnxContextHandlewraps only anintdevice id, so the mismatch looks cosmetic rather than causal — recorded in case it is not.