@@ -130,15 +130,22 @@ BOOST_AUTO_TEST_CASE(optimizer_rejects_implicit_reduction) {
130130
131131namespace {
132132
133+ // / sets the einsum legacy-subworld toggle within a scope; the previous value
134+ // / is restored on scope exit (also on exceptions)
135+ struct ScopedEinsumRoute {
136+ bool prev_;
137+ explicit ScopedEinsumRoute (const bool legacy)
138+ : prev_(TA ::detail::einsum_legacy_subworld()) {
139+ TA::detail::einsum_legacy_subworld () = legacy;
140+ }
141+ ~ScopedEinsumRoute () { TA::detail::einsum_legacy_subworld () = prev_; }
142+ };
143+
133144// / forces the legacy sub-World einsum within a scope, so einsum-based
134145// / reference values remain an *independent* oracle for the expression route
135146// / (einsum itself routes general products through the expression layer now)
136- struct ForceLegacyEinsum {
137- bool prev_;
138- ForceLegacyEinsum () : prev_(TA ::detail::einsum_legacy_subworld()) {
139- TA::detail::einsum_legacy_subworld () = true ;
140- }
141- ~ForceLegacyEinsum () { TA::detail::einsum_legacy_subworld () = prev_; }
147+ struct ForceLegacyEinsum : ScopedEinsumRoute {
148+ ForceLegacyEinsum () : ScopedEinsumRoute(true ) {}
142149};
143150
144151// / makes a dense array over \p tr filled with an index-dependent pattern
@@ -578,9 +585,11 @@ BOOST_AUTO_TEST_CASE(expression_general_product_tot_batched_outer) {
578585 auto b = make_patterned_tot_array (world, tr_b, {3 , 2 }, 2.0 );
579586
580587 auto c = TA::einsum (a (" b1,b2,i2,i1;x" ), b (" b1,b2;x,y" ), " i2,i1,b1,b2;y" );
581- TiledArray::detail::einsum_legacy_subworld () = false ;
582- auto c_new = TA::einsum (a (" b1,b2,i2,i1;x" ), b (" b1,b2;x,y" ), " i2,i1,b1,b2;y" );
583- TiledArray::detail::einsum_legacy_subworld () = true ;
588+ decltype (c) c_new;
589+ {
590+ ScopedEinsumRoute expression_route (false );
591+ c_new = TA::einsum (a (" b1,b2,i2,i1;x" ), b (" b1,b2;x,y" ), " i2,i1,b1,b2;y" );
592+ }
584593 BOOST_CHECK_SMALL (tot_max_abs_diff (c_new, c), 1e-10 );
585594}
586595
@@ -597,9 +606,11 @@ BOOST_AUTO_TEST_CASE(expression_general_product_t_tot_batched_outer) {
597606 auto b = make_patterned_tot_array (world, tr_b, {3 }, 2.0 );
598607
599608 auto c = TA::einsum (a (" i3,i1" ), b (" i3,i1,i2;x" ), " i2,i3,i1;x" );
600- TiledArray::detail::einsum_legacy_subworld () = false ;
601- auto c_new = TA::einsum (a (" i3,i1" ), b (" i3,i1,i2;x" ), " i2,i3,i1;x" );
602- TiledArray::detail::einsum_legacy_subworld () = true ;
609+ decltype (c) c_new;
610+ {
611+ ScopedEinsumRoute expression_route (false );
612+ c_new = TA::einsum (a (" i3,i1" ), b (" i3,i1,i2;x" ), " i2,i3,i1;x" );
613+ }
603614 BOOST_CHECK_SMALL (tot_max_abs_diff (c_new, c), 1e-10 );
604615}
605616
@@ -616,9 +627,11 @@ BOOST_AUTO_TEST_CASE(expression_general_product_tot_t_nonleading_fused) {
616627 auto b = make_patterned_array (world, tr_b, 2.0 );
617628
618629 auto c_ref = TA::einsum (a (" i4,i1,m;x" ), b (" m,i4,K" ), " i1,i4,K;x" );
619- TiledArray::detail::einsum_legacy_subworld () = false ;
620- auto c_new = TA::einsum (a (" i4,i1,m;x" ), b (" m,i4,K" ), " i1,i4,K;x" );
621- TiledArray::detail::einsum_legacy_subworld () = true ;
630+ decltype (c_ref) c_new;
631+ {
632+ ScopedEinsumRoute expression_route (false );
633+ c_new = TA::einsum (a (" i4,i1,m;x" ), b (" m,i4,K" ), " i1,i4,K;x" );
634+ }
622635 BOOST_CHECK_SMALL (tot_max_abs_diff (c_new, c_ref), 1e-10 );
623636}
624637
@@ -916,17 +929,17 @@ BOOST_AUTO_TEST_CASE(expression_general_product_csv_like) {
916929 // mirror the CSV path exactly: through einsum (which canonicalizes the
917930 // target and permutes at the end), new route vs the legacy oracle
918931 auto c_ref = TA::einsum (a (" i2,i1,m;a" ), b (" m,i2,K" ), " i1,i2,K;a" );
919- TA::detail::einsum_legacy_subworld () = false ;
920932 ArenaSpArr c1, c2;
921- try {
922- c1 = TA::einsum (a (" i2,i1,m;a" ), b (" m,i2,K" ), " i1,i2,K;a" );
923- c2 = TA::einsum (a (" i2,i1,m;a" ), b (" m,i2,K" ), " i1,i2,K;a" );
924- } catch (std::exception& ex) {
925- std::cerr << " EXPRESSION ROUTE THREW: " << ex.what () << std::endl;
926- TA::detail::einsum_legacy_subworld () = true ;
927- throw ;
933+ {
934+ ScopedEinsumRoute expression_route (false );
935+ try {
936+ c1 = TA::einsum (a (" i2,i1,m;a" ), b (" m,i2,K" ), " i1,i2,K;a" );
937+ c2 = TA::einsum (a (" i2,i1,m;a" ), b (" m,i2,K" ), " i1,i2,K;a" );
938+ } catch (std::exception& ex) {
939+ std::cerr << " EXPRESSION ROUTE THREW: " << ex.what () << std::endl;
940+ throw ;
941+ }
928942 }
929- TA::detail::einsum_legacy_subworld () = true ;
930943
931944 // BISECT: same shape, CANONICAL target, direct expression (no einsum
932945 // wrapper, no final permutation) vs the legacy oracle
@@ -1006,15 +1019,18 @@ BOOST_AUTO_TEST_CASE(einsum_expression_route_matches_legacy) {
10061019 // interleaved (non-canonical) target reached by the final permutation
10071020 // assignment
10081021 auto & world = TA::get_default_world ();
1022+ ForceLegacyEinsum legacy_oracle; // keep the einsum reference independent
10091023 TA ::TiledRange tr_a{{0 , 2 , 5 }, {0 , 3 , 4 }, {0 , 2 , 6 , 7 }}; // b, i, j
10101024 TA ::TiledRange tr_b{{0 , 2 , 5 }, {0 , 2 , 6 , 7 }, {0 , 4 , 5 }}; // b, j, k
10111025 auto a = make_patterned_array (world, tr_a, 1.0 );
10121026 auto b = make_patterned_array (world, tr_b, 2.0 );
10131027
10141028 auto c_legacy = TA::einsum (a (" b,i,j" ), b (" b,j,k" ), " i,b,k" );
1015- TA::detail::einsum_legacy_subworld () = false ;
1016- auto c_new = TA::einsum (a (" b,i,j" ), b (" b,j,k" ), " i,b,k" );
1017- TA::detail::einsum_legacy_subworld () = true ;
1029+ decltype (c_legacy) c_new;
1030+ {
1031+ ScopedEinsumRoute expression_route (false );
1032+ c_new = TA::einsum (a (" b,i,j" ), b (" b,j,k" ), " i,b,k" );
1033+ }
10181034 BOOST_CHECK_SMALL (diff_norm (c_new, c_legacy, " i,b,k" ), 1e-10 );
10191035}
10201036
0 commit comments