-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrandom_svd.cpp
62 lines (49 loc) · 2.15 KB
/
random_svd.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <Eigen/Dense>
#include <random>
using namespace Eigen;
extern "C" {
__declspec(dllexport) void randomSVD(const MatrixXd& A, MatrixXd& U, MatrixXd& S, MatrixXd& V, int k) noexcept {
try {
// Check if k is valid
if (k <= 0 || k > std::min(A.rows(), A.cols())) {
throw std::invalid_argument("k must be between 1 and min(rows, cols)");
}
// Print dimensions for debugging
std::cout << "The dimensions of input matrix: " << A.rows() << " x " << A.cols() << std::endl;
// Preallocate matrices
U = MatrixXd::Zero(A.rows(), k);
S = MatrixXd::Zero(k, k);
V = MatrixXd::Zero(A.cols(), k);
// Generate random matrix Omega
MatrixXd Omega = MatrixXd::Random(A.cols(), k);
MatrixXd Y = A * Omega;
// QR decomposition
HouseholderQR<MatrixXd> qr(Y);
MatrixXd Q = qr.householderQ();
// Compute B = Q^T * A
MatrixXd B = Q.transpose() * A;
// SVD of B
JacobiSVD<MatrixXd> svd(B, ComputeThinU | ComputeThinV);
U = Q * svd.matrixU().leftCols(k);
S = svd.singularValues().head(k).asDiagonal();
V = svd.matrixV().leftCols(k);
} catch (const std::exception& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unknown exception caught." << std::endl;
}
}
__declspec(dllexport) void random_svd(double* A, int rows, int cols, double* U, double* S, double* V, int k) {
MatrixXd matA = Map<MatrixXd>(A, rows, cols);
MatrixXd matU, matS, matV;
// Initialize U, S, and V with the correct dimensions
matU.resize(rows, k);
matS.resize(k, k);
matV.resize(cols, k);
randomSVD(matA, matU, matS, matV, k);
Map<MatrixXd>(U, rows, k) = matU; // Output U
Map<MatrixXd>(S, k, k) = matS; // Output S
Map<MatrixXd>(V, cols, k) = matV; // Output V
}
}