Skip to content

Commit ef1ecb0

Browse files
committed
tests: conj() on BTAS nested cells, the third supported inner-tile family
conj(A*B) on Tensor<btas::Tensor<complex<double>, Range>> fails to compile on master -- the per-cell op static_casts the ComplexConjugate factor, tripping the "gemm without custom element op is only applicable to plain tensors" assertion in kernels.h. It works on this branch: the factor reaches the cells as 1 and the finalization conjugates the finished tile, through btas's own value-returning conj / conj_to CPOs (external/btas.h). Nothing in the branch was aimed at BTAS, so pin the behavior with a test. Covers conj(a*b), 2*conj(a*b), -conj(a*b), unary conj(a) and conj(a)*b against explicit references. The fixture's btas rows are real (int/float/double), so this is the first complex BTAS ToT case in the suite; make_tot_1_data fills through data() because btas::Tensor has no at_ordinal(). Raised by a review comment that read the opposite way -- that the branch left BTAS ill-formed.
1 parent be546dd commit ef1ecb0

1 file changed

Lines changed: 83 additions & 1 deletion

File tree

‎tests/tot_expressions.cpp‎

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4809,7 +4809,9 @@ ArenaArr make_arena_tot_2(World& world, std::size_t ni, std::size_t nj,
48094809
const long NA = static_cast<long>(na), NB = static_cast<long>(nb);
48104810
arr.init_tiles([=](const TiledArray::Range& r) {
48114811
ArenaOuter t = TiledArray::detail::arena_outer_init<ArenaOuter>(
4812-
r, 1, [=](std::size_t) { return TiledArray::Range{NA, NB}; });
4812+
r, 1, [=](std::size_t) {
4813+
return TiledArray::Range{NA, NB};
4814+
});
48134815
for (std::size_t o = 0; o < t.range().volume(); ++o) {
48144816
ArenaInner& c = t.data()[o];
48154817
if (!c) continue;
@@ -5312,4 +5314,84 @@ BOOST_AUTO_TEST_CASE(arena_tot_times_real_plain) {
53125314
}
53135315
}
53145316

5317+
// ---- BTAS inner cells, the third supported nested-tile family. conj(A*B)
5318+
// on Tensor<btas::Tensor<complex>> does not compile on master (the per-cell
5319+
// op static_casts the ComplexConjugate factor); it works here because the
5320+
// factor reaches the cells as 1 and the finalization conjugates the finished
5321+
// tile through btas's own conj/conj_to CPOs (external/btas.h).
5322+
5323+
using btas_inner_z = btas::Tensor<Z, TiledArray::Range>;
5324+
using btas_tot_z = DistArray<Tensor<btas_inner_z>, DensePolicy>;
5325+
5326+
// btas::Tensor has no at_ordinal(); fill through data() so the same generator
5327+
// serves the owning, arena and btas rows.
5328+
template <typename Array, typename Gen>
5329+
Array make_tot_1_data(World& world, std::size_t ni, std::size_t nj,
5330+
std::size_t na, Gen gen) {
5331+
using inner_t = typename Array::value_type::value_type;
5332+
TiledRange tr{TiledRange1{0, static_cast<long>(ni)},
5333+
TiledRange1{0, static_cast<long>(nj)}};
5334+
Array arr(world, tr);
5335+
arr.init_elements([=](const auto& idx) {
5336+
inner_t t(Range{static_cast<long>(na)});
5337+
for (std::size_t a = 0; a < na; ++a) t.data()[a] = gen(idx[0], idx[1], a);
5338+
return t;
5339+
});
5340+
world.gop.fence();
5341+
return arr;
5342+
}
5343+
5344+
// c(i,k;a,b) = conj / 2 conj / -conj( sum_j a(i,j;a) b(j,k;b) ) on btas cells
5345+
BOOST_AUTO_TEST_CASE(btas_conj_of_product) {
5346+
const std::size_t ni = 2, nj = 3, nk = 2, na = 2, nb = 3;
5347+
btas_tot_z a = make_tot_1_data<btas_tot_z>(m_world, ni, nj, na, gaz1);
5348+
btas_tot_z b = make_tot_1_data<btas_tot_z>(m_world, nj, nk, nb, gbz1);
5349+
auto ref = [=](auto i, auto k, auto x, auto y) {
5350+
Z r{};
5351+
for (std::size_t j = 0; j < nj; ++j) r += gaz1(i, j, x) * gbz1(j, k, y);
5352+
return r;
5353+
};
5354+
auto check = [&](const btas_tot_z& c, Z scale, const char* what) {
5355+
auto tile = single_tile(c);
5356+
for (std::size_t i = 0; i < ni; ++i)
5357+
for (std::size_t k = 0; k < nk; ++k)
5358+
for (std::size_t x = 0; x < na; ++x)
5359+
for (std::size_t y = 0; y < nb; ++y) {
5360+
BOOST_TEST_CONTEXT(what << " i=" << i << " k=" << k << " x=" << x
5361+
<< " y=" << y)
5362+
check_close(tile(i, k).data()[x * nb + y],
5363+
scale * std::conj(ref(i, k, x, y)));
5364+
}
5365+
};
5366+
btas_tot_z c;
5367+
c("i,k;a,b") = conj(a("i,j;a") * b("j,k;b"));
5368+
check(c, Z(1.0), "btas conj(a*b)");
5369+
c("i,k;a,b") = 2.0 * conj(a("i,j;a") * b("j,k;b"));
5370+
check(c, Z(2.0), "btas 2.0*conj(a*b)");
5371+
c("i,k;a,b") = -conj(a("i,j;a") * b("j,k;b"));
5372+
check(c, Z(-1.0), "btas -conj(a*b)");
5373+
5374+
// unary conj, and conj on one operand of the product
5375+
btas_tot_z u;
5376+
u("i,j;a") = conj(a("i,j;a"));
5377+
auto utile = single_tile(u);
5378+
for (std::size_t i = 0; i < ni; ++i)
5379+
for (std::size_t j = 0; j < nj; ++j)
5380+
for (std::size_t x = 0; x < na; ++x)
5381+
check_close(utile(i, j).data()[x], std::conj(gaz1(i, j, x)));
5382+
5383+
btas_tot_z l;
5384+
l("i,k;a,b") = conj(a("i,j;a")) * b("j,k;b");
5385+
auto ltile = single_tile(l);
5386+
for (std::size_t i = 0; i < ni; ++i)
5387+
for (std::size_t k = 0; k < nk; ++k)
5388+
for (std::size_t x = 0; x < na; ++x)
5389+
for (std::size_t y = 0; y < nb; ++y) {
5390+
Z r{};
5391+
for (std::size_t j = 0; j < nj; ++j)
5392+
r += std::conj(gaz1(i, j, x)) * gbz1(j, k, y);
5393+
check_close(ltile(i, k).data()[x * nb + y], r);
5394+
}
5395+
}
5396+
53155397
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)