Summary
PR #108 added three lock-in tests for Skew annotation preservation through negation, scalar-mul, and tensor_mul-as-child. The full preservation matrix is much wider — five space tags × every tensor composition node. A property-style test that walks the matrix would lock in the contract end-to-end and catch the platform-specific loss tracked by #93 if it ever recurs.
Scope
Space tags (perm × trace combinations):
Skew × AnyTraceTag
Symmetric × AnyTraceTag
Symmetric × VolumetricTag
Symmetric × DeviatoricTag
Symmetric × HarmonicTag
- No annotation (control)
Composition nodes to walk (tensor → tensor):
tensor_negative (unary)
basis_change_imp / trans (unary)
tensor_inv (unary)
tensor_pow (binary tensor × scalar)
tensor_scalar_mul (binary scalar × tensor)
tensor_add (n-ary)
tensor_mul (n-ary)
inner_product_wrapper (binary tensor × tensor)
outer_product_wrapper (binary tensor × tensor)
tensor_to_scalar_with_tensor_mul (cross-domain)
tensor_projector ⊕ inner_product (the skew() / sym() / vol() / dev() projection paths)
For each (space, node) pair, the test should check:
- The annotation that should be preserved (e.g. Symmetric through inv → Symmetric).
- The annotation that should be downgraded (e.g. Deviatoric through inv → Symmetric, since tr(D^{-1}) ≠ 0).
- The annotation that should be dropped (e.g. Skew through
pow with odd exponent → can't determine, drop).
- The annotation that should be derived (e.g.
trans(A) − A → Skew even if A had no annotation).
Why a single matrix vs many individual tests
- Each pair could be its own gtest, but the matrix is ~60 cells. Parameterised (
TEST_P with a value-parameterised fixture) is far less repetitive.
- A property-style walker (loop in code, accumulate failures with context) is more maintainable than 60 hand-written tests.
- The matrix doubles as documentation of the annotation contract.
What this catches
Acceptance criteria
Not blocking
The current three tests in PR #108 catch the most common cases. This is the comprehensive next step that would replace those three.
References
Summary
PR #108 added three lock-in tests for Skew annotation preservation through negation, scalar-mul, and tensor_mul-as-child. The full preservation matrix is much wider — five space tags × every tensor composition node. A property-style test that walks the matrix would lock in the contract end-to-end and catch the platform-specific loss tracked by #93 if it ever recurs.
Scope
Space tags (perm × trace combinations):
Skew×AnyTraceTagSymmetric×AnyTraceTagSymmetric×VolumetricTagSymmetric×DeviatoricTagSymmetric×HarmonicTagComposition nodes to walk (tensor → tensor):
tensor_negative(unary)basis_change_imp/trans(unary)tensor_inv(unary)tensor_pow(binary tensor × scalar)tensor_scalar_mul(binary scalar × tensor)tensor_add(n-ary)tensor_mul(n-ary)inner_product_wrapper(binary tensor × tensor)outer_product_wrapper(binary tensor × tensor)tensor_to_scalar_with_tensor_mul(cross-domain)tensor_projector⊕inner_product(theskew()/sym()/vol()/dev()projection paths)For each (space, node) pair, the test should check:
powwith odd exponent → can't determine, drop).trans(A) − A→ Skew even if A had no annotation).Why a single matrix vs many individual tests
TEST_Pwith a value-parameterised fixture) is far less repetitive.What this catches
tensor_negativepreserves Symmetric butbasis_change_impdoesn't).Acceptance criteria
(space_annotation, composition_callable)pair and runs it.Not blocking
The current three tests in PR #108 catch the most common cases. This is the comprehensive next step that would replace those three.
References
include/numsim_cas/tensor/skew_classification.h— current structural fallback.include/numsim_cas/tensor/functions/tensor_inv.h— example of preservation/downgrade rules.tests/TensorSpacePropagationTest.h— existing partial coverage that this matrix would consolidate.