Working on breaking up the steps into manageable chunks
This commit is contained in:
@@ -62,7 +62,7 @@ TEST_CASE("SVD Integration: 2x2 [[1,2],[3,4]]", "[Matrix][SVD][Integration]") {
|
||||
err += diff * diff;
|
||||
}
|
||||
err = sqrtf(err);
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinRel(0.0f, 1e-3f));
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinAbs(0.0f, 1e-3f));
|
||||
|
||||
std::cout << "SVD 2x2 [[1,2],[3,4]]:\n";
|
||||
std::cout << "Sigma: [" << sigma.Get(0, 0) << ", " << sigma.Get(1, 0)
|
||||
@@ -86,8 +86,8 @@ TEST_CASE("SVD Integration: 3x3 diagonal [10,5,2]",
|
||||
// U and Vt should be identity (or close) for diagonal matrix
|
||||
float uErr = frobeniusNorm(U - Matrix<3, 3>{1, 0, 0, 0, 1, 0, 0, 0, 1});
|
||||
float vtErr = frobeniusNorm(Vt - Matrix<3, 3>{1, 0, 0, 0, 1, 0, 0, 0, 1});
|
||||
REQUIRE_THAT(uErr, Catch::Matchers::WithinRel(0.0f, 1e-2f));
|
||||
REQUIRE_THAT(vtErr, Catch::Matchers::WithinRel(0.0f, 1e-2f));
|
||||
REQUIRE_THAT(uErr, Catch::Matchers::WithinAbs(0.0f, 1e-2f));
|
||||
REQUIRE_THAT(vtErr, Catch::Matchers::WithinAbs(0.0f, 1e-2f));
|
||||
}
|
||||
|
||||
TEST_CASE("SVD Integration: 3x3 rank-deficient [[1,2,3],[4,5,6],[7,8,9]]",
|
||||
@@ -120,7 +120,7 @@ TEST_CASE("SVD Integration: 3x3 rank-deficient [[1,2,3],[4,5,6],[7,8,9]]",
|
||||
err += diff * diff;
|
||||
}
|
||||
err = sqrtf(err);
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinRel(0.0f, 1e-2f));
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinAbs(0.0f, 1e-2f));
|
||||
|
||||
std::cout << "SVD 3x3 rank-deficient:\n";
|
||||
std::cout << "Sigma: [" << sigma.Get(0, 0) << ", " << sigma.Get(1, 0) << ", "
|
||||
@@ -155,7 +155,7 @@ TEST_CASE("SVD Integration: tall 4x3 matrix", "[Matrix][SVD][Integration]") {
|
||||
err += diff * diff;
|
||||
}
|
||||
err = sqrtf(err);
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinRel(0.0f, 1e-2f));
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinAbs(0.0f, 1e-2f));
|
||||
|
||||
std::cout << "SVD tall 4x3:\n";
|
||||
std::cout << "Sigma: [" << sigma.Get(0, 0) << ", " << sigma.Get(1, 0) << ", "
|
||||
@@ -175,42 +175,25 @@ TEST_CASE("SVD Integration: wide 3x5 matrix", "[Matrix][SVD][Integration]") {
|
||||
REQUIRE_THAT(sigma.Get(1, 0), Catch::Matchers::WithinRel(2.46540f, 1e-2f));
|
||||
REQUIRE_THAT(sigma.Get(2, 0), Catch::Matchers::WithinAbs(0.0f, 1e-2f));
|
||||
|
||||
// Check reconstruction: U (3x5) * diag(sigma) (5x3) = 3x3, then * Vt (3x5) =
|
||||
// 3x5
|
||||
Matrix<3, 5> recon{0};
|
||||
Matrix<3, 5> Usig{0};
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 5; j++)
|
||||
Usig[i][j] = U.Get(i, j) * sigma.Get(j, 0);
|
||||
|
||||
// For wide matrix: A = U * Sigma * Vt where U is 3x5, Sigma is 5x5
|
||||
// (diagonal), Vt is 5x5 But our implementation returns sigma as 3x1 and Vt as
|
||||
// 3x5 So we need: recon = Usig (3x5) * Vt (3x5)^T ... no that doesn't work
|
||||
// either The SVD for wide matrices is: A = U * Sigma * Vt where:
|
||||
// U is m×m (3×3), Sigma is m×n (3×5), Vt is n×n (5×5)
|
||||
// But our API returns U as m×n (3×5), sigma as n×1 (3×1), Vt as n×n (3×5)
|
||||
// So: recon = U (3x5) * diag(sigma) (5x5) * Vt (5x5)^T ...
|
||||
// Actually, looking at the implementation, for wide matrices we swap roles.
|
||||
// Let me just check reconstruction using the actual dimensions returned.
|
||||
|
||||
// For wide matrix: A (3x5) = U (3x5) * diag(sigma) (5x5 padded) * Vt (5x5)
|
||||
// But our API returns Vt as 3x5, not 5x5
|
||||
// The implementation stores: U = QR[:,0:p]^T (3x5), sigma (3x1), Vt =
|
||||
// QL[:,0:p]^T (3x5) Reconstruction: A[i][j] = sum_k U[i][k]*sigma[k]*Vt[j][k]
|
||||
// Check reconstruction: A (3x5) = U * Sigma * Vt, where U (3x5) has
|
||||
// its meaningful part in the first 3 columns, sigma (5x1) in the
|
||||
// first 3 entries, and Vt (5x5) in its first 3 rows (right
|
||||
// singular vectors as rows). So:
|
||||
// A[i][j] = sum_k U[i][k] * sigma[k] * Vt[k][j]
|
||||
|
||||
float err2 = 0.0f;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
float recon_val = 0.0f;
|
||||
for (int k = 0; k < 3; k++) {
|
||||
recon_val += U.Get(i, k) * sigma.Get(k, 0) * Vt.Get(j, k);
|
||||
recon_val += U.Get(i, k) * sigma.Get(k, 0) * Vt.Get(k, j);
|
||||
}
|
||||
float diff = recon_val - A.Get(i, j);
|
||||
err2 += diff * diff;
|
||||
}
|
||||
}
|
||||
err2 = sqrtf(err2);
|
||||
REQUIRE_THAT(err2, Catch::Matchers::WithinRel(0.0f, 1e-2f));
|
||||
REQUIRE_THAT(err2, Catch::Matchers::WithinAbs(0.0f, 1e-2f));
|
||||
|
||||
std::cout << "SVD wide 3x5:\n";
|
||||
std::cout << "Sigma: [" << sigma.Get(0, 0) << ", " << sigma.Get(1, 0) << ", "
|
||||
@@ -230,7 +213,7 @@ TEST_CASE("SVD Integration: identity 3x3", "[Matrix][SVD][Integration]") {
|
||||
REQUIRE_THAT(sigma.Get(2, 0), Catch::Matchers::WithinRel(1.0f, 1e-3f));
|
||||
|
||||
float err = frobeniusNorm(U - Matrix<3, 3>{1, 0, 0, 0, 1, 0, 0, 0, 1});
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinRel(0.0f, 1e-2f));
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinAbs(0.0f, 1e-2f));
|
||||
}
|
||||
|
||||
TEST_CASE("SVD Integration: symmetric positive definite 2x2 [[5,3],[3,5]]",
|
||||
@@ -261,7 +244,7 @@ TEST_CASE("SVD Integration: symmetric positive definite 2x2 [[5,3],[3,5]]",
|
||||
err += diff * diff;
|
||||
}
|
||||
err = sqrtf(err);
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinRel(0.0f, 1e-3f));
|
||||
REQUIRE_THAT(err, Catch::Matchers::WithinAbs(0.0f, 1e-3f));
|
||||
|
||||
std::cout << "SVD SPD 2x2 [[5,3],[3,5]]:\n";
|
||||
std::cout << "Sigma: [" << sigma.Get(0, 0) << ", " << sigma.Get(1, 0)
|
||||
|
||||
Reference in New Issue
Block a user