#pragma once#include<algorithm>#include<cmath>#include<cstddef>#include<stdexcept>#include<vector>namespacegraduate{inlinevoidvalidate(conststd::vector<double>&a,conststd::vector<double>&b,std::size_tm,std::size_tk,std::size_tn){if(m==0||k==0||n==0||m>512||k>512||n>512)throwstd::invalid_argument("dimensions must be in 1..512");if(a.size()!=m*k||b.size()!=k*n)throwstd::invalid_argument("shape mismatch");for(doublex:a)if(!std::isfinite(x))throwstd::invalid_argument("nonfinite A");for(doublex:b)if(!std::isfinite(x))throwstd::invalid_argument("nonfinite B");}inlinevoidcheck_result(conststd::vector<double>&c){for(doublex:c)if(!std::isfinite(x))throwstd::overflow_error("nonfinite result");}inlinestd::vector<double>naive(conststd::vector<double>&a,conststd::vector<double>&b,std::size_tm,std::size_tk,std::size_tn){validate(a,b,m,k,n);std::vector<double>c(m*n,0.);for(std::size_ti=0;i<m;++i)for(std::size_tj=0;j<n;++j)for(std::size_tp=0;p<k;++p)c[i*n+j]+=a[i*k+p]*b[p*n+j];check_result(c);returnc;}inlinestd::vector<double>blocked(conststd::vector<double>&a,conststd::vector<double>&b,std::size_tm,std::size_tk,std::size_tn,std::size_ttile=24){validate(a,b,m,k,n);if(tile==0||tile>1024)throwstd::invalid_argument("tile must be in 1..1024");std::vector<double>c(m*n,0.);for(std::size_tii=0;ii<m;ii+=tile)for(std::size_tpp=0;pp<k;pp+=tile)for(std::size_tjj=0;jj<n;jj+=tile)for(std::size_ti=ii;i<std::min(ii+tile,m);++i)for(std::size_tp=pp;p<std::min(pp+tile,k);++p){constdoublevalue=a[i*k+p];for(std::size_tj=jj;j<std::min(jj+tile,n);++j)c[i*n+j]+=value*b[p*n+j];}check_result(c);returnc;}}//namespacegraduate