/******************************************************** * ██████╗ ██████╗████████╗██╗ * ██╔════╝ ██╔════╝╚══██╔══╝██║ * ██║ ███╗██║ ██║ ██║ * ██║ ██║██║ ██║ ██║ * ╚██████╔╝╚██████╗ ██║ ███████╗ * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ * Geophysical Computational Tools & Library (GCTL) * * Copyright (c) 2022 Yi Zhang (yizhang-geo@zju.edu.cn) * * GCTL is distributed under a dual licensing scheme. You can redistribute * it and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either version 2 * of the License, or (at your option) any later version. You should have * received a copy of the GNU Lesser General Public License along with this * program. If not, see . * * If the terms and conditions of the LGPL v.2. would prevent you from using * the GCTL, please consider the option to obtain a commercial license for a * fee. These licenses are offered by the GCTL's original author. As a rule, * licenses are provided "as-is", unlimited in time for a one time fee. Please * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget * to include some description of your company and the realm of its activities. * Also add information on how to contact you by electronic and paper mail. ******************************************************/ #include "svd.h" gctl::svd::svd() { reset(); } gctl::svd::svd(const matrix &src_mat) : svd() { decompose(src_mat); } void gctl::svd::reset() { maxi_iteration = 1000; K = 0; epsilon = 1e-8; U.clear(); V.clear(); S.clear(); return; } void gctl::svd::set_singular_number(int k) { if (k <= 0) { throw invalid_argument("Invalid singular number. From gctl::svd::set_singular_number(...)"); } K = k; return; } void gctl::svd::set_iteration(int t) { if (t <= 0) { throw invalid_argument("Invalid singular number. From gctl::svd::set_iteration(...)"); } maxi_iteration = t; return; } void gctl::svd::set_epsilon(double e) { if (e <= 0) { throw invalid_argument("Invalid singular number. From gctl::svd::set_epsilon(...)"); } epsilon = e; return; } void gctl::svd::decompose(const matrix &src_mat) { int M = src_mat.row_size(); int N = src_mat.col_size(); if (K == 0) K = N; S.resize(K, 0.0); U.resize(K, M, 0.0); V.resize(K, N, 0.0); srand(time(0)); array left_vector(M), next_left_vector(M); array right_vector(N), next_right_vector(N); array U_tmp(M), V_tmp(N); double diff, r, d; for(int col=0;col epsilon) break; } for(int iter=0; diff >= epsilon && iter < maxi_iteration; iter++) { next_left_vector.assign_all(0.0); next_right_vector.assign_all(0.0); for(int i=0;i=epsilon) { S[col]=r; for (int i = 0; i < M; i++) { U[col][i] = left_vector[i]; } for (int i = 0; i < N; i++) { V[col][i] = right_vector[i]; } } else break; } return; }