#include <matrix.hpp>
#include <iostream>
#include <limits>
#include <random>
void require(bool condition) {if(!condition) throw std::runtime_error("test failure");}
template<class F> void rejects(F f) {
bool rejected=false;
try {f();} catch(const std::exception&) {rejected=true;}
require(rejected);
}
int main() {
std::mt19937 rng(7);
std::uniform_real_distribution<double> sample(-2,2);
int cases=0;
for(std::size_t m:{1U,3U,7U}) for(std::size_t k:{1U,4U,9U})
for(std::size_t n:{1U,5U,8U}) for(std::size_t t:{1U,2U,7U,16U}) {
std::vector<double> a(m*k),b(k*n);
for(auto& x:a) x=sample(rng);
for(auto& x:b) x=sample(rng);
const auto expected=graduate::naive(a,b,m,k,n);
const auto actual=graduate::blocked(a,b,m,k,n,t);
for(std::size_t i=0;i<actual.size();++i) require(std::abs(actual[i]-expected[i])<1e-10);
++cases;
}
const std::vector<double> a{1,2,3,4},identity{1,0,0,1};
require(graduate::blocked(a,identity,2,2,2)==a);
rejects([&]{(void)graduate::blocked(a,identity,2,2,2,0);});
rejects([&]{(void)graduate::blocked(a,identity,0,2,2);});
rejects([&]{(void)graduate::blocked(a,identity,3,2,2);});
rejects([&]{(void)graduate::blocked({std::numeric_limits<double>::infinity()},{1},1,1,1);});
std::cout<<cases<<" dimension/tile comparisons, identity, and rejection checks passed\n";
}