// R = return type; q is summation size
// variables a, b, c, r must exist and are available for use in FUNCTION.
// Writes to r(i,j,k)=sum(FUNCTION(i,j,k,l),l=0..q-1);
// #define FUNCTION(i,j,k,l)
{
    if constexpr(R::type==ten_zero){}
    else if constexpr(R::type==ten_perm)
    {
        []<int... l>(auto&& a,auto&& b,auto&& r,std::integer_sequence<int,l...>)
        {
            r.x=(...+(FUNCTION(0,1,2,l)));
        }(a,b,r,std::make_integer_sequence<int,q>{});
    }
    else if constexpr(R::type==ten_diag)
    {
        []<int... h,int... l>(auto&& a,auto&& b,auto&& r,std::integer_sequence<int,h...>,std::integer_sequence<int,l...>)
            {
                int i{};
                (...,(i=h,r.v(i)=(...+(FUNCTION(i,i,i,l)))));
            }(a,b,r,std::make_integer_sequence<int,R::m>{},std::make_integer_sequence<int,q>{});
    }
    else if constexpr(R::type>=ten_vec_id && R::type<=ten_vec_id+2)
    {
        static constexpr int di=(R::type==ten_vec_id+0);
        static constexpr int dj=(R::type==ten_vec_id+1);
        static constexpr int dk=(R::type==ten_vec_id+2);
        []<int... h,int... l>(auto&& a,auto&& b,auto&& r,std::integer_sequence<int,h...>,std::integer_sequence<int,l...>)
            {
                int i{};
                (...,(i=h,r.v(i)=(...+(FUNCTION(i*di,i*dj,i*dk,l)))));
            }(a,b,r,std::make_integer_sequence<int,R::um>{},std::make_integer_sequence<int,q>{});
    }
    else if constexpr(R::type>=ten_vec_id_sym && R::type<=ten_vec_id_sym+2)
    {
        static constexpr int di=(R::type!=ten_vec_id_sym+2);
        static constexpr int dj=(R::type!=ten_vec_id_sym+0);
        static constexpr int dk=(R::type!=ten_vec_id_sym+1);
        if constexpr(R::m==1)
        {
            []<int... l>(auto&& a,auto&& b,auto&& r,std::integer_sequence<int,l...>)
                {
                    r.v(0)=(...+(FUNCTION(0,0,0,l)))/2;
                }(a,b,r,std::make_integer_sequence<int,q>{});
        }
        else []<int... h,int... l>(auto&& a,auto&& b,auto&& r,std::integer_sequence<int,h...>,std::integer_sequence<int,l...>)
                 {
                     int i{};
                     (...,(i=h,r.v(i)=(...+(FUNCTION((i+di)%R::m,(i+dj)%R::m,(i+dk)%R::m,l)))));
                 }(a,b,r,std::make_integer_sequence<int,R::m>{},std::make_integer_sequence<int,q>{});
    }
    else if constexpr(R::type>=ten_sym && R::type<=ten_sym+2)
    {
        static constexpr int ss=R::un*(R::un+1)/2;
        []<int... h,int... l>(auto&& a,auto&& b,auto&& r,std::integer_sequence<int,h...>,std::integer_sequence<int,l...>)
            {
                int i{};
                if constexpr(R::u==0)
                    (...,(i=h,r(i/ss,sym_i(R::un,i%ss),sym_j(R::un,i%ss))=(...+(FUNCTION(i/ss,sym_i(R::un,i%ss),sym_j(R::un,i%ss),l)))));
                if constexpr(R::u==1)
                    (...,(i=h,r(sym_i(R::un,i%ss),i/ss,sym_j(R::un,i%ss))=(...+(FUNCTION(sym_i(R::un,i%ss),i/ss,sym_j(R::un,i%ss),l)))));
                if constexpr(R::u==2)
                    (...,(i=h,r(sym_i(R::un,i%ss),sym_j(R::un,i%ss),i/ss)=(...+(FUNCTION(sym_i(R::un,i%ss),sym_j(R::un,i%ss),i/ss,l)))));
            }(a,b,r,std::make_integer_sequence<int,R::um*ss>{},std::make_integer_sequence<int,q>{});
    }
    else
    {
        static_assert(R::type==ten_gen);
        []<int... h,int... l>(auto&& a,auto&& b,auto&& r,std::integer_sequence<int,h...>,std::integer_sequence<int,l...>)
            {
                int i{};
                (...,(i=h,r(i/R::n/R::p,i%R::n,i/R::n%R::p)=(...+(FUNCTION(i/R::n/R::p,i%R::n,i/R::n%R::p,l)))));
            }(a,b,r,std::make_integer_sequence<int,R::m*R::n*R::p>{},std::make_integer_sequence<int,q>{});
    }
}
#undef FUNCTION
