Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/numsim_cas/tensor/simplifier/tensor_simplifier_sub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,17 @@ sub_base::expr_holder_t sub_base::dispatch(tensor const &) {
return _rhs.accept(visitor);
}

// 0 - expr
// 0 - expr --> -expr
sub_base::expr_holder_t sub_base::dispatch(tensor_zero const &) {
if (is_same<tensor_zero>(m_rhs))
return make_expression<tensor_zero>(m_rhs.get().dim(), m_rhs.get().rank());
return make_expression<tensor_negative>(std::move(m_rhs));
return -std::move(m_rhs);
}

// - expr_lhs - expr_rhs --> -(expr_lhs+expr_rhs)
// operator-, not a raw node: the sum may already be zero or negative
sub_base::expr_holder_t sub_base::dispatch(tensor_negative const &lhs) {
auto expr{lhs.expr() + std::move(m_rhs)};
if (expr.is_valid()) {
return make_expression<tensor_negative>(expr);
return -std::move(expr);
}
return make_expression<tensor_zero>(lhs.dim(), lhs.rank());
}
Expand Down
36 changes: 36 additions & 0 deletions tests/CoreBugFixTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,42 @@ TEST(RoundSevenReview, AddCancelsAgainstNegativeChild) {
EXPECT_TRUE(*f == *(trace(A) + w(c4))) << to_string(f);
}

TEST(RoundSevenReview, TensorSubNormalizesLikeScalarAndT2s) {
auto [A, B] =
make_tensor_variable(std::tuple{"A", std::size_t{3}, std::size_t{2}},
std::tuple{"B", std::size_t{3}, std::size_t{2}});
auto zero = make_expression<tensor_zero>(3, 2);
// operator- short-circuits these before sub_base
auto e1 = zero - (-A);
EXPECT_TRUE(*e1 == *A) << to_string(e1);
auto e0 = zero - make_expression<tensor_zero>(3, 2);
EXPECT_TRUE(is_same<tensor_zero>(e0)) << to_string(e0);
auto e2 = (-A) - (-A);
EXPECT_TRUE(is_same<tensor_zero>(e2)) << to_string(e2);
auto e3 = (-A) - B;
EXPECT_TRUE(*e3 == *(-(A + B))) << to_string(e3);

auto e4 = (-A) - (make_expression<scalar_constant>(-1) * A);
EXPECT_TRUE(is_same<tensor_zero>(e4)) << to_string(e4);

// call sub_base directly to reach its zero/negative dispatches
auto direct = [](expression_holder<tensor_expression> const &lhs,
expression_holder<tensor_expression> const &rhs) {
tensor_detail::simplifier::sub_base visitor(lhs, rhs);
return lhs.get<tensor_visitable_t>().accept(visitor);
};
auto d1 = direct(zero, -A);
EXPECT_TRUE(*d1 == *A) << to_string(d1);
auto d2 = direct(zero, make_expression<tensor_zero>(3, 2));
EXPECT_TRUE(is_same<tensor_zero>(d2)) << to_string(d2);
auto d3 = direct(zero, B);
EXPECT_TRUE(*d3 == *(-B)) << to_string(d3);
auto d4 = direct(-A, -A);
EXPECT_TRUE(is_same<tensor_zero>(d4)) << to_string(d4);
auto d5 = direct(make_expression<tensor_negative>(zero), -B);
EXPECT_TRUE(*d5 == *B) << to_string(d5);
}

// Round-8 review: regressions from the round-7 negation probe.

// R8-1: merge_add consumed the same rhs child twice when the lhs held an
Expand Down
Loading