You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Surfaced in code review of PR #291 (#287 rank-4 inv-diff scalar-arg case).
The inv() factory in include/numsim_cas/tensor/tensor_functions.h:467 rejects rank ≠ 2 and rank ≠ 4 at construction with a clear invalid_expression_error. The tensor_inv wrapper constructor in include/numsim_cas/tensor/wrappers/tensor_inv.h:14-85, however, runs no rank check itself — it only branches on r == 2 / r == 4 for space propagation and silently leaves the space empty otherwise.
So make_expression<tensor_inv>(rank3_tensor) (bypassing the factory) builds a "valid-looking" rank-3 tensor_inv AST node that misbehaves anywhere downstream:
Visitors (differentiation, evaluator, printer) hit the wrong rank path.
The space-propagation block silently produces a rank-3 tensor_inv with no space tag and the wrong algebraic implications.
The belt-and-braces throw in tensor_differentiation_wrt_scalar.cpp:248-253 becomes unreachable; either:
(a) Keep it with a comment "should be caught by wrapper ctor; double-guard for direct base-class construction".
(b) Replace with assert(r == 2 || r == 4).
The corresponding test TensorDiffWrtScalarTest.InvRank3ThrowsNotImplemented becomes redundant; can either be kept as a defense-in-depth witness or replaced by a wrapper-level direct test.
Context
Surfaced in code review of PR #291 (#287 rank-4 inv-diff scalar-arg case).
The
inv()factory ininclude/numsim_cas/tensor/tensor_functions.h:467rejects rank ≠ 2 and rank ≠ 4 at construction with a clearinvalid_expression_error. Thetensor_invwrapper constructor ininclude/numsim_cas/tensor/wrappers/tensor_inv.h:14-85, however, runs no rank check itself — it only branches onr == 2/r == 4for space propagation and silently leaves the space empty otherwise.So
make_expression<tensor_inv>(rank3_tensor)(bypassing the factory) builds a "valid-looking" rank-3tensor_invAST node that misbehaves anywhere downstream:tensor_invwith no space tag and the wrong algebraic implications.Fix
Mirror the factory's rank gate in the wrapper ctor:
Throws are the codebase convention here (matches
inv()factory'sinvalid_expression_errorstyle) and — unlikeassert— fires in Release builds too.Test plan
EXPECT_THROW(make_expression<tensor_inv>(rank3_T), invalid_expression_error).tensor_differentiation_wrt_scalar.cpp:248-253becomes unreachable; either:(a) Keep it with a comment "should be caught by wrapper ctor; double-guard for direct base-class construction".
(b) Replace with
assert(r == 2 || r == 4).TensorDiffWrtScalarTest.InvRank3ThrowsNotImplementedbecomes redundant; can either be kept as a defense-in-depth witness or replaced by a wrapper-level direct test.Related
tensor_functions.h:467(inv()accepts non-rank-2 inputs even though comment says "Rank-2 only"; rank-4 path constructs a symbolic node that won't evaluate #192, Should tensor_inv support rank-4 inverses for the algorithmic-tangent use case? #248).src/numsim_cas/tensor/visitors/tensor_differentiation_wrt_scalar.cpp:248-253.