// Numerical checks for cute_layout_tuple_complement_walkthrough_zh.md.
// Runs on the host; no GPU instructions or product/divide operations are used.
#include <cute/tensor.hpp>
#include <cstdio>
#include <cstdlib>
#include <type_traits>
using namespace cute;
namespace {
int checks = 0;
void expect(bool ok, char const* label) {
if (!ok) {
std::fprintf(stderr,"FAILED: %s\n",label);
std::exit(1);
}
++checks;
template<class T> void show(char const* label, T const& x) {
std::printf("%-25s",label); cute::print(x); std::printf("\n");
template<class L>
void json_values(FILE* f,char const* key,L const& l,bool comma=true) {
std::fprintf(f," \"%s\": [",key);
for(int i=0;i<int(size(l));++i) std::fprintf(f,"%s%d",i?",":"",int(l(i)));
std::fprintf(f,"]%s\n",comma?",":"");
void json_matrix(FILE* f,char const* key,L const& l) {
for(int m=0;m<int(size<0>(l));++m) {
std::fprintf(f,"%s[",m?",":"");
for(int n=0;n<int(size<1>(l));++n)
std::fprintf(f,"%s%d",n?",":"",int(l(m,n)));
std::fprintf(f,"]");
std::fprintf(f,"],\n");
int main(int argc,char** argv) {
auto tree=make_tuple(_2{},make_tuple(_3{},_4{}));
expect(int(rank(tree))==2,"tuple rank");
expect(int(depth(tree))==2,"tuple depth");
expect(int(size(tree))==24,"tuple product of leaves");
expect(int(get<1,0>(tree))==3,"nested tuple access");
expect(int(rank(_6{}))==1 && int(depth(_6{}))==0,"scalar IntTuple");
expect(int(depth(make_tuple(_6{})))==1,"one-element tuple depth");
static_assert(std::is_same_v<decltype(make_shape(_2{},_3{})),
decltype(make_stride(_2{},_3{}))>);
decltype(make_coord(_2{},_3{}))>);
auto row=make_layout(Shape<_2,_3>{},Stride<_3,_1>{});
auto col=make_layout(Shape<_2,_3>{},Stride<_1,_2>{});
auto padded=make_layout(Shape<_2,_3>{},Stride<_5,_1>{});
auto broadcast=make_layout(Shape<_2,_3>{},Stride<_0,_1>{});
for(int m=0;m<2;++m) for(int n=0;n<3;++n) {
expect(int(row(m,n))==3*m+n,"row-major formula");
expect(int(col(m,n))==m+2*n,"column-major formula");
expect(int(padded(m,n))==5*m+n,"padded formula");
expect(int(broadcast(m,n))==n,"broadcast formula");
int i=m+2*n;
expect(int(row(i))==int(row(m,n)),"integer coordinate is shape order");
expect(int(size(padded))==6 && int(cosize(padded))==8,"padded size and cosize");
expect(int(size(broadcast))==6 && int(cosize(broadcast))==3,"broadcast size and cosize");
auto nested_shape=Shape<_2,Shape<_2,_3>>{};
auto nested_stride=Stride<_3,Stride<_6,_1>>{};
auto h=make_layout(nested_shape,nested_stride);
expect(bool(congruent(nested_shape,nested_stride)),"shape/stride tree agreement");
expect(!bool(congruent(nested_shape,make_stride(_3{},_6{},_1{}))),"flat stride has wrong tree");
expect(int(rank(h))==2 && int(depth(h))==2,"nested layout rank and depth");
expect(int(size(h))==12 && int(size<1>(h))==6,"nested layout sizes");
expect(int(get<1,1>(shape(h)))==3,"shape leaf access");
for(int m=0;m<2;++m) for(int a=0;a<2;++a) for(int b=0;b<3;++b) {
int j=a+2*b;
int i=m+2*j;
int expected=3*m+6*a+b;
expect(int(h(make_coord(m,make_coord(a,b))))==expected,"fully nested coordinate");
expect(int(h(m,j))==expected,"partially flattened coordinate");
expect(int(h(i))==expected,"integer nested coordinate");
expect(int(flatten(h)(i))==expected,"flatten preserves 1D input mapping");
auto left=make_layout(nested_shape);
auto right=make_layout(nested_shape,LayoutRight{});
expect(bool(left==make_layout(nested_shape,Stride<_1,Stride<_2,_4>>{})),"LayoutLeft leaf strides");
expect(bool(right==make_layout(nested_shape,Stride<_6,Stride<_3,_1>>{})),"LayoutRight leaf strides");
auto compact=make_layout(Shape<_2,_3>{},Stride<_1,_2>{});
auto compact_c=coalesce(compact);
expect(int(rank(compact_c))==1,"coalesce rank");
for(int i=0;i<6;++i) expect(int(compact_c(i))==int(compact(i)),"coalesce input mapping");
int n=3;
auto mixed=make_layout(make_shape(_2{},n),make_stride(n,_1{}));
static_assert(is_static_v<decltype(row)>);
static_assert(!is_static_v<decltype(mixed)>);
for(int i=0;i<6;++i) expect(int(mixed(i))==int(row(i)),"mixed static/dynamic mapping");
show("tuple",tree);
show("row",row); show("column",col); show("padded",padded); show("broadcast",broadcast);
show("nested",h); show("nested mode 1",layout<1>(h));
show("default nested strides",left); show("LayoutRight nested",right);
show("flatten(nested)",flatten(h)); show("coalesced compact",compact_c); show("mixed",mixed);
if(argc>1) {
FILE* f=std::fopen(argv[1],"w");
if(!f) return 2;
std::fprintf(f,"{\n");
json_matrix(f,"row",row);json_matrix(f,"column",col);
json_matrix(f,"padded",padded);json_matrix(f,"broadcast",broadcast);json_matrix(f,"nested",h);
json_values(f,"row_integer",row);
std::fprintf(f," \"checks\": %d\n}\n",checks);
std::fclose(f);
std::printf("Verified %d tuple and layout mapping checks.\n",checks);