// Host-only CuTe layout examples used by cute_layout_product_walkthrough_zh.md.
// Build: nvcc -std=c++17 -I include cute_layout_product_trace.cu -o /tmp/cute_layout_product_trace
#include <cute/tensor.hpp>
#include <cstdio>
#include <cstdlib>
using namespace cute;
int checked = 0;
void expect(int actual, int expected, char const* label) {
if (actual != expected) {
std::fprintf(stderr, "%s: got %d, expected %d\n", label, actual, expected);
std::exit(1);
}
++checked;
template<class T>
void show(char const* name, T const& x) {
std::printf("%-23s", name);
cute::print(x);
std::printf("\n");
int main(int argc, char** argv) {
auto dense = logical_product(Layout<_3,_1>{}, Layout<_4,_1>{});
auto gaps = logical_product(Layout<_3,_2>{}, Layout<_4,_1>{});
auto ordered = logical_product(Layout<_3,_1>{},
Layout<Shape<_2,_2>,Stride<_2,_1>>{});
auto gather = logical_product(Layout<_4,_1>{}, Layout<_2,_2>{});
auto a = make_layout(Shape<_2,_3>{}, Stride<_3,_1>{});
auto b = make_layout(Shape<_2,_2>{}, Stride<_1,_2>{});
auto lp = logical_product(a,b);
auto zp = zipped_product(a,b);
auto tp = tiled_product(a,b);
auto fp = flat_product(a,b);
auto bp = blocked_product(a,b);
auto rp = raked_product(a,b);
auto target = tile_to_shape(a, Shape<_4,_6>{});
auto by_mode = make_tile(Layout<_2,_3>{}, Layout<_2,_4>{});
auto ml = logical_product(a, by_mode);
auto mz = zipped_product(a, by_mode);
auto mt = tiled_product(a, by_mode);
auto mf = flat_product(a, by_mode);
auto naive = logical_product(a, make_tile(_2{},_2{}));
auto threads = Layout<_4,_1>{};
auto values = Layout<_2,_1>{};
auto copy_blocked = blocked_product(threads, values);
auto copy_raked = raked_product(threads, values);
auto copy_tv = right_inverse(copy_raked).with_shape(Shape<_4,_2>{});
auto mma_threads = tiled_product(Layout<_32,_1>{},
make_layout(Shape<_2,_2,_1>{}));
for (int j=0;j<4;++j) for (int i=0;i<3;++i) {
expect(dense(i,j), i+3*j, "dense");
expect(gaps(i,j), 2*i+j%2+6*(j/2), "gaps");
expect(ordered(i,j), i+3*(2*(j%2)+j/2), "ordered");
for (int j=0;j<2;++j) for (int i=0;i<4;++i)
expect(gather(i,j),i+8*j,"retile gather");
for (int q=0;q<2;++q) for (int p=0;p<2;++p)
for (int n=0;n<3;++n) for (int m=0;m<2;++m) {
int expected = 3*m+n+6*p+12*q;
auto local = make_coord(m,n);
auto tile = make_coord(p,q);
expect(lp(local,tile),expected,"logical");
expect(zp(local,tile),expected,"zipped");
expect(tp(local,p,q),expected,"tiled");
expect(fp(m,n,p,q),expected,"flat");
expect(bp(make_coord(m,p),make_coord(n,q)),expected,"blocked nested");
expect(bp(m+2*p,n+3*q),expected,"blocked scalar");
expect(rp(make_coord(p,m),make_coord(q,n)),expected,"raked nested");
expect(rp(p+2*m,q+2*n),expected,"raked scalar");
expect(target(m+2*p,n+3*q),expected,"tile_to_shape");
expect(ml(make_coord(m,p),make_coord(n,q)),expected,"by-mode logical");
expect(mz(local,tile),expected,"by-mode zipped");
expect(mt(local,p,q),expected,"by-mode tiled");
expect(mf(m,n,p,q),expected,"by-mode flat");
expect(naive(make_coord(0,1),make_coord(0,0)),1,"naive alias 1");
expect(naive(make_coord(0,0),make_coord(1,0)),1,"naive alias 2");
for (int v=0;v<2;++v) for (int t=0;t<4;++t) {
expect(copy_blocked(t+4*v),t+4*v,"copy blocked");
expect(copy_raked(v+2*t),t+4*v,"copy raked");
expect(copy_tv(t,v),v+2*t,"copy TV inverse");
for (int q=0;q<2;++q) for (int p=0;p<2;++p) for (int lane=0;lane<32;++lane)
expect(mma_threads(lane,p,q,0),lane+32*p+64*q,"MMA thread ID");
if (argc>1) {
FILE* f=std::fopen(argv[1],"w");
if (!f) return 2;
std::fprintf(f,"{\n \"dense\": [");
for (int j=0;j<4;++j) {
std::fprintf(f,"%s[",j?",":"");
for (int i=0;i<3;++i) std::fprintf(f,"%s%d",i?",":"",int(dense(i,j)));
std::fprintf(f,"]");
std::fprintf(f,"],\n \"gaps\": [");
for (int i=0;i<3;++i) std::fprintf(f,"%s%d",i?",":"",int(gaps(i,j)));
std::fprintf(f,"],\n \"blocked\": [");
for (int m=0;m<4;++m) {
std::fprintf(f,"%s[",m?",":"");
for (int n=0;n<6;++n) std::fprintf(f,"%s%d",n?",":"",int(bp(m,n)));
std::fprintf(f,"],\n \"raked\": [");
for (int n=0;n<6;++n) std::fprintf(f,"%s%d",n?",":"",int(rp(m,n)));
std::fprintf(f,"],\n \"checked\": %d\n}\n",checked);
std::fclose(f);
show("dense",dense); show("complement(3:1)",complement(Layout<_3,_1>{}));
show("complement(3:2)",complement(Layout<_3,_2>{})); show("gaps",gaps);
show("ordered repetitions",ordered); show("retile gather",gather);
show("A",a); show("B",b); show("logical",lp); show("zipped",zp);
show("tiled",tp); show("flat",fp); show("blocked",bp); show("raked",rp);
show("tile_to_shape",target); show("by-mode logical",ml); show("by-mode zipped",mz);
show("by-mode tiled",mt); show("by-mode flat",mf); show("naive by-mode",naive);
show("copy blocked",copy_blocked); show("copy raked",copy_raked);
show("copy TV",copy_tv); show("MMA threads",mma_threads);
std::printf("Verified %d coordinate mappings. No GPU required.\n", checked);