13 template <
typename dtype>
29 E[
"ij"] -= U[
"ki"]*conj<dtype>(U)[
"kj"];
31 bool pass_orthogonality =
true;
33 double nrm1, nrm2, nrm3;
35 if (nrm1 > m*n*1.E-6){
36 pass_orthogonality =
false;
41 E[
"ij"] -= VT[
"ik"]*conj<dtype>(VT)[
"jk"];
44 if (nrm2 > m*n*1.E-6){
45 pass_orthogonality =
false;
48 A[
"ij"] -= U[
"ik"]*S[
"k"]*VT[
"kj"];
50 bool pass_residual =
true;
52 if (nrm3 > m*n*n*1.E-6){
53 pass_residual =
false;
58 printf(
"SVD orthogonality check returned %d, residual check %d\n", pass_orthogonality, pass_residual);
61 if (!pass_residual || ! pass_orthogonality){
63 printf(
"SVD orthogonality check returned %d (%lf, %lf), residual check %d (%lf)\n", pass_orthogonality, nrm1, nrm2, pass_residual, nrm3);
67 return pass_residual & pass_orthogonality;
76 pass = pass & svd<float>(A,m,n,k,dw);
82 pass = pass & svd<double>(B,m,n,k,dw);
86 pass = pass & svd<std::complex<float>>(cA,m,n,k,dw);
91 pass = pass & svd<std::complex<double>>(cB,m,n,k,dw);
94 printf(
"{ A = USVT and U^TU = I } passed\n");
96 printf(
"{ A = USVT and U^TU = I } failed\n");
108 char ** itr = std::find(begin, end, option);
109 if (itr != end && ++itr != end){
116 int main(
int argc,
char ** argv){
117 int rank,
np, m, n, k, pass;
118 int const in_num = argc;
119 char ** input_str = argv;
121 MPI_Init(&argc, &argv);
122 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
123 MPI_Comm_size(MPI_COMM_WORLD, &np);
126 m = atoi(
getCmdOption(input_str, input_str+in_num,
"-m"));
132 n = atoi(
getCmdOption(input_str, input_str+in_num,
"-n"));
138 k = atoi(
getCmdOption(input_str, input_str+in_num,
"-k"));
139 if (k < 0) k = std::min(m,n);
140 }
else k = std::min(m,n);
142 assert(k<=std::min(m,n));
146 World dw(argc, argv);
149 printf(
"Testing rank %d %d-by-%d SVD factorization\n", k, m, n);
Matrix class which encapsulates a 2D tensor.
bool svd(Matrix< dtype > A, int m, int n, int k, World &dw)
char * getCmdOption(char **begin, char **end, const std::string &option)
Vector class which encapsulates a 1D tensor.
an instance of the CTF library (world) on a MPI communicator
dtype norm2()
computes the frobenius norm of the tensor (needs sqrt()!)
void fill_random(dtype rmin, dtype rmax)
fills local unique tensor elements to random values in the range [min,max] works only for dtype in {f...
int rank
rank of local processor
void svd(Matrix< dtype > &U, Vector< dtype > &S, Matrix< dtype > &VT, int rank=0)
bool test_svd(int m, int n, int k, World dw)
int main(int argc, char **argv)