#include "test_common.h" #include "./utils/utils.h" using utils::Vf; using utils::Vd; using utils::Vi; using utils::Mf; using utils::Md; using utils::Mi; // ---------- Construction & element access ---------- TEST_CASE(Matrix_Construct_Access) { Md M; // default CHECK(M.rows()==0 && M.cols()==0, "default ctor dims wrong"); Mf A(2,3, 1.0f); CHECK(A.rows()==2 && A.cols()==3, "ctor dims wrong"); CHECK(A(0,0)==1.0f && A(1,2)==1.0f, "fill wrong"); A(0,1)=2.5f; A(1,0)=3.5f; CHECK(A(0,1)==2.5f && A(1,0)==3.5f, "operator() set/get failed"); } // ---------- Equality, inequality, nearly_equal ---------- TEST_CASE(Matrix_Equality) { Mi A(2,2,0), B(2,2,0), C(2,2,1); A(0,0)=1; A(1,1)=1; // A = I B(0,0)=1; B(1,1)=1; // B = I CHECK(A == B, "== failed identical"); CHECK(!(A != B), "!= failed identical"); CHECK(A != C, "!= failed different"); Md F1(2,2,0.0), F2(2,2,0.0); F1(0,0)=1.0; F1(1,1)=2.0; F2(0,0)=1.0; F2(1,1)=2.0 + 5e-10; // tiny perturbation CHECK(!(F1 == F2), "operator== is exact; should differ"); CHECK(F1.nearly_equal(F2, 1e-9), "nearly_equal should accept tiny delta"); CHECK(!F1.nearly_equal(F2, 1e-12), "nearly_equal too strict should fail"); } // ---------- Row helpers ---------- TEST_CASE(Matrix_Row_Get_Set) { Mf M(3,4, 0.0f); Vf r(4, 0.0f); for (uint64_t j=0;j<4;++j) r[j] = float(j+1); // [1,2,3,4] M.set_row(1, r); auto out = M.get_row(1); CHECK(out == r, "set_row/get_row mismatch"); // size mismatch should throw bool threw=false; try { Vf bad(3, 9.0f); M.set_row(2, bad); } catch (const std::exception&) { threw=true; } CHECK(threw, "set_row should throw on size mismatch"); // out of range threw=false; try { (void)M.get_row(3); } catch (const std::out_of_range&) { threw=true; } CHECK(threw, "get_row should throw on OOB index"); } // ---------- Column helpers ---------- TEST_CASE(Matrix_Col_Get_Set) { Md M(3,2, 0.0); Vd c(3, 0.0); c[0]=10; c[1]=20; c[2]=30; M.set_col(1, c); auto out = M.get_col(1); CHECK(out == c, "set_col/get_col mismatch"); // size mismatch should throw bool threw=false; try { Vd bad(2, 9.0); M.set_col(0, bad); } catch (const std::exception&) { threw=true; } CHECK(threw, "set_col should throw on size mismatch"); // out of range threw=false; try { (void)M.get_col(2); } catch (const std::out_of_range&) { threw=true; } CHECK(threw, "get_col should throw on OOB index"); } // ---------- swap_rows / swap_cols ---------- TEST_CASE(Matrix_Swap_Rows_Cols) { Mi M(2,3,0); // Row 0: [1,2,3], Row 1: [4,5,6] M(0,0)=1; M(0,1)=2; M(0,2)=3; M(1,0)=4; M(1,1)=5; M(1,2)=6; M.swap_rows(0,1); CHECK(M(0,0)==4 && M(0,1)==5 && M(0,2)==6, "swap_rows row0 wrong"); CHECK(M(1,0)==1 && M(1,1)==2 && M(1,2)==3, "swap_rows row1 wrong"); // swap back via cols M.swap_cols(0,2); // After swapping col0<->col2: // Row0: [6,5,4], Row1: [3,2,1] CHECK(M(0,0)==6 && M(0,1)==5 && M(0,2)==4, "swap_cols row0 wrong"); CHECK(M(1,0)==3 && M(1,1)==2 && M(1,2)==1, "swap_cols row1 wrong"); // no-op swap (a==b) should not crash or change M.swap_rows(1,1); M.swap_cols(2,2); // OOB checks bool threw=false; try { M.swap_rows(5,1); } catch (const std::out_of_range&) { threw=true; } CHECK(threw, "swap_rows should throw on OOB"); threw=false; try { M.swap_cols(0,9); } catch (const std::out_of_range&) { threw=true; } CHECK(threw, "swap_cols should throw on OOB"); } // ---------- data() layout (contiguous row-major) ---------- TEST_CASE(Matrix_Data_Layout) { Md M(2,3, 0.0); // Fill increasing sequence double val=1.0; for (uint64_t i=0;i