@@ -1342,3 +1342,117 @@ BOOST_AUTO_TEST_CASE(einsum_expression_route_matches_legacy) {
13421342}
13431343
13441344BOOST_AUTO_TEST_SUITE_END ()
1345+
1346+ // Distributed (np > 1) coverage of general products. Unlike
1347+ // general_product_suite (serial-labeled: classification/optimizer unit tests
1348+ // + np=1 evaluation), this suite carries NO label, so the CI harness runs it
1349+ // at BOTH np=1 and np=2 (see tests/CMakeLists.txt: np-1 excludes @distributed,
1350+ // np-2 excludes @serial). It exercises the batched Summa across ranks -- a
1351+ // path the serial suite never covered. Each case differential-tests the
1352+ // expression route against the legacy sub-World einsum oracle.
1353+ //
1354+ // N.B. these all evaluate via the shared-grid (hgroups == 1) batched Summa;
1355+ // the experimental h-grouped 3-d grid (TA_SUMMA_HGROUPS) is not yet correct
1356+ // at np > 1 and is intentionally not exercised here.
1357+ BOOST_AUTO_TEST_SUITE (general_product_distributed_suite)
1358+
1359+ // the fixtures/helpers live in general_product_suite's anonymous namespace
1360+ using general_product_suite::diff_norm;
1361+ using general_product_suite::diff_norm_sp;
1362+ using general_product_suite::ForceLegacyEinsum;
1363+ using general_product_suite::make_patterned_array;
1364+ using general_product_suite::make_patterned_sparse_array;
1365+ using general_product_suite::make_patterned_tot_array;
1366+ using general_product_suite::TArrayToT;
1367+ using general_product_suite::tot_max_abs_diff;
1368+
1369+ BOOST_AUTO_TEST_CASE (dist_dense) {
1370+ // batched general product: b fused, j contracted, i/k free
1371+ auto & world = TA::get_default_world ();
1372+ ForceLegacyEinsum legacy_oracle;
1373+ TA ::TiledRange tr_a{{0 , 2 , 4 }, {0 , 2 , 3 }, {0 , 2 , 5 }}; // b, i, j
1374+ TA ::TiledRange tr_b{{0 , 2 , 4 }, {0 , 2 , 5 }, {0 , 3 , 4 }}; // b, j, k
1375+ auto a = make_patterned_array (world, tr_a, 1.0 );
1376+ auto b = make_patterned_array (world, tr_b, 2.0 );
1377+ TA ::TArrayD c;
1378+ BOOST_REQUIRE_NO_THROW (c (" b,i,k" ) = a (" b,i,j" ) * b (" b,j,k" ));
1379+ auto c_ref = TA::einsum (a (" b,i,j" ), b (" b,j,k" ), " b,i,k" );
1380+ BOOST_CHECK_SMALL (diff_norm (c, c_ref, " b,i,k" ), 1e-10 );
1381+ }
1382+
1383+ BOOST_AUTO_TEST_CASE (dist_sparse) {
1384+ // block-sparse batched general product (SparseShape::gemm_batched +
1385+ // the sparse (h,k)-keyed Summa groups, across ranks)
1386+ auto & world = TA::get_default_world ();
1387+ ForceLegacyEinsum legacy_oracle;
1388+ TA ::TiledRange tr_a{{0 , 2 , 5 }, {0 , 3 , 4 }, {0 , 2 , 6 , 7 }}; // b, i, j
1389+ TA ::TiledRange tr_b{{0 , 2 , 5 }, {0 , 2 , 6 , 7 }, {0 , 4 , 5 }}; // b, j, k
1390+ auto a = make_patterned_sparse_array (world, tr_a, 1.0 , 3 );
1391+ auto b = make_patterned_sparse_array (world, tr_b, 2.0 , 4 );
1392+ TA ::TSpArrayD c;
1393+ BOOST_REQUIRE_NO_THROW (c (" b,i,k" ) = a (" b,i,j" ) * b (" b,j,k" ));
1394+ auto c_ref = TA::einsum (a (" b,i,j" ), b (" b,j,k" ), " b,i,k" );
1395+ BOOST_CHECK_SMALL (diff_norm_sp (c, c_ref, " b,i,k" ), 1e-10 );
1396+ }
1397+
1398+ BOOST_AUTO_TEST_CASE (dist_tot_mixed) {
1399+ // mixed T x ToT general product (inner Scale) across ranks
1400+ auto & world = TA::get_default_world ();
1401+ ForceLegacyEinsum legacy_oracle;
1402+ TA ::TiledRange tr_a{{0 , 2 , 4 }, {0 , 2 , 3 }, {0 , 2 , 5 }}; // b, i, j
1403+ TA ::TiledRange tr_b{{0 , 2 , 4 }, {0 , 2 , 5 }, {0 , 3 , 4 }}; // b, j, k
1404+ auto a = make_patterned_array (world, tr_a, 1.0 );
1405+ auto b = make_patterned_tot_array (world, tr_b, {3 }, 2.0 );
1406+ TArrayToT c;
1407+ BOOST_REQUIRE_NO_THROW (c (" b,i,k;m" ) = a (" b,i,j" ) * b (" b,j,k;m" ));
1408+ auto c_ref = TA::einsum (a (" b,i,j" ), b (" b,j,k;m" ), " b,i,k;m" );
1409+ BOOST_CHECK_SMALL (tot_max_abs_diff (c, c_ref), 1e-10 );
1410+ }
1411+
1412+ BOOST_AUTO_TEST_CASE (dist_no_externals_dense) {
1413+ // no-external general product (Hadamard reduction shape) across ranks;
1414+ // the synthetic unit left-external mode handling under distribution
1415+ auto & world = TA::get_default_world ();
1416+ ForceLegacyEinsum legacy_oracle;
1417+ TA ::TiledRange tr{{0 , 2 , 4 }, {0 , 3 , 5 }}; // i, j
1418+ auto a = make_patterned_array (world, tr, 1.0 );
1419+ auto b = make_patterned_array (world, tr, 2.0 );
1420+ TA ::TArrayD c;
1421+ BOOST_REQUIRE_NO_THROW (c (" i" ) = a (" i,j" ) * b (" i,j" ));
1422+ auto c_ref = TA::einsum (a (" i,j" ), b (" i,j" ), " i" );
1423+ BOOST_CHECK_SMALL (diff_norm (c, c_ref, " i" ), 1e-10 );
1424+ }
1425+
1426+ BOOST_AUTO_TEST_CASE (dist_no_externals_tot) {
1427+ // no-external ToT general product across ranks
1428+ auto & world = TA::get_default_world ();
1429+ ForceLegacyEinsum legacy_oracle;
1430+ TA ::TiledRange tr{{0 , 3 , 5 }, {0 , 2 , 4 }, {0 , 2 , 3 }}; // x, i, j
1431+ auto a = make_patterned_tot_array (world, tr, {2 }, 1.0 );
1432+ auto b = make_patterned_tot_array (world, tr, {3 }, 2.0 );
1433+ TArrayToT c;
1434+ BOOST_REQUIRE_NO_THROW (c (" i,j;a,b" ) = a (" x,i,j;a" ) * b (" x,i,j;b" ));
1435+ auto c_ref = TA::einsum (a (" x,i,j;a" ), b (" x,i,j;b" ), " i,j;a,b" );
1436+ BOOST_CHECK_SMALL (tot_max_abs_diff (c, c_ref), 1e-10 );
1437+ }
1438+
1439+ BOOST_AUTO_TEST_CASE (dist_inner_node_thc) {
1440+ // THC reconstruction in one expression (general products at inner nodes)
1441+ // across ranks
1442+ auto & world = TA::get_default_world ();
1443+ TA ::TiledRange tr_x{{0 , 2 , 4 }, {0 , 3 , 5 }}; // orbital x auxiliary
1444+ TA ::TiledRange tr_z{{0 , 3 , 5 }, {0 , 3 , 5 }}; // auxiliary x auxiliary
1445+ auto x = make_patterned_array (world, tr_x, 1.0 );
1446+ auto z = make_patterned_array (world, tr_z, 2.0 );
1447+ TA ::TArrayD g;
1448+ BOOST_REQUIRE_NO_THROW (g (" p,q,r,s" ) = x (" p,r1" ) * x (" q,r1" ) * z (" r1,r2" ) *
1449+ x (" r,r2" ) * x (" s,r2" ));
1450+ TA ::TArrayD i1, i2, i3, g_ref;
1451+ i1 (" r1,p,q" ) = x (" p,r1" ) * x (" q,r1" );
1452+ i2 (" p,q,r2" ) = i1 (" r1,p,q" ) * z (" r1,r2" );
1453+ i3 (" r2,p,q,r" ) = i2 (" p,q,r2" ) * x (" r,r2" );
1454+ g_ref (" p,q,r,s" ) = i3 (" r2,p,q,r" ) * x (" s,r2" );
1455+ BOOST_CHECK_SMALL (diff_norm (g, g_ref, " p,q,r,s" ), 1e-10 );
1456+ }
1457+
1458+ BOOST_AUTO_TEST_SUITE_END ()
0 commit comments