21 explicit SVD(
const NdArray& inMatrix)
23 , n_(inMatrix[0].size())
25 , eps_(
std::numeric_limits<double>::epsilon())
28 for (
uint04 i = 0; i < n_; i++)
33 tsh_ = 0.5 * std::sqrt(m_ + n_ + 1.) * s_[0] * eps_;
42 const NdArray&
u() noexcept
53 const NdArray&
v() noexcept
82 if (inInput.size() != m_)
88 returnArray.setSize(n_);
93 tsh_ = (inThresh >= 0. ? inThresh : 0.5 * std::sqrt(m_ + n_ + 1.) * s_[0] * eps_);
95 for (
uint04 j = 0; j < n_; j++)
100 for (
uint04 i = 0; i < m_; i++)
101 ss += u_[i][j] * inInput[i];
107 for (
uint04 j = 0; j < n_; j++)
110 for (
uint04 jj = 0; jj < n_; jj++)
112 ss += v_[j][jj] * tmp[jj];
131 static double SIGN(
double inA,
double inB)
noexcept
133 return inB >= 0 ? (inA >= 0 ? inA : -inA) : (inA >= 0 ? -inA : inA);
141 static bool essentiallyEqual(
double a,
double b)
143 if (
abs(a - b) < std::numeric_limits<double>::epsilon())
172 for (i = 0; i < n_; ++i)
180 for (k = i; k < m_; ++k)
182 scale += std::abs(u_[k][i]);
185 if (!essentiallyEqual(scale, 0.))
187 for (k = i; k < m_; ++k)
190 ss += u_[k][i] * u_[k][i];
194 g = -SIGN(std::sqrt(ss), f);
198 for (j = l - 1; j < n_; ++j)
200 for (ss = 0., k = i; k < m_; ++k)
202 ss += u_[k][i] * u_[k][j];
207 for (k = i; k < m_; ++k)
209 u_[k][j] += f * u_[k][i];
213 for (k = i; k < m_; ++k)
223 if (i + 1 <= m_ && i + 1 != n_)
225 for (k = l - 1; k < n_; ++k)
227 scale += std::abs(u_[i][k]);
230 if (!essentiallyEqual(scale, 0.))
232 for (k = l - 1; k < n_; ++k)
235 ss += u_[i][k] * u_[i][k];
239 g = -SIGN(std::sqrt(ss), f);
241 u_[i][l - 1] = f - g;
243 for (k = l - 1; k < n_; ++k)
245 rv1[k] = u_[i][k] / h;
248 for (j = l - 1; j < m_; ++j)
250 for (ss = 0., k = l - 1; k < n_; ++k)
252 ss += u_[j][k] * u_[i][k];
255 for (k = l - 1; k < n_; ++k)
257 u_[j][k] += ss * rv1[k];
261 for (k = l - 1; k < n_; ++k)
268 anorm = std::max(anorm, (std::abs(s_[i]) + std::abs(rv1[i])));
271 for (i = n_ - 1; i !=
static_cast<uint04>(-1); --i)
275 if (!essentiallyEqual(g, 0.))
277 for (j = l; j < n_; ++j)
279 v_[j][i] = (u_[i][j] / u_[i][l]) / g;
282 for (j = l; j < n_; ++j)
284 for (ss = 0., k = l; k < n_; ++k)
286 ss += u_[i][k] * v_[k][j];
289 for (k = l; k < n_; ++k)
291 v_[k][j] += ss * v_[k][i];
296 for (j = l; j < n_; ++j)
298 v_[i][j] = v_[j][i] = 0.;
307 for (i = std::min(m_, n_) - 1; i !=
static_cast<uint04>(-1); --i)
312 for (j = l; j < n_; ++j)
317 if (!essentiallyEqual(g, 0.))
321 for (j = l; j < n_; ++j)
323 for (ss = 0., k = l; k < m_; ++k)
325 ss += u_[k][i] * u_[k][j];
328 f = (ss / u_[i][i]) * g;
330 for (k = i; k < m_; ++k)
332 u_[k][j] += f * u_[k][i];
336 for (j = i; j < m_; ++j)
343 for (j = i; j < m_; ++j)
352 for (k = n_ - 1; k !=
static_cast<uint04>(-1); --k)
354 for (its = 0; its < 30; ++its)
357 for (l = k; l !=
static_cast<uint04>(-1); --l)
360 if (l == 0 || std::abs(rv1[l]) <= eps_ * anorm)
366 if (std::abs(s_[nm]) <= eps_ * anorm)
376 for (i = l; i < k + 1; ++i)
381 if (std::abs(f) <= eps_ * anorm)
393 for (j = 0; j < m_; ++j)
397 u_[j][nm] = y * c + z * ss;
398 u_[j][i] = z * c - y * ss;
409 for (j = 0; j < n_; ++j)
411 v_[j][k] = -v_[j][k];
419 throw Exception(_t(
"no convergence in 30 svdcmp iterations"));
427 f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2. * h * y);
429 f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
432 for (j = l; j <= nm; j++)
448 for (jj = 0; jj < n_; ++jj)
452 v_[jj][j] = x * c + z * ss;
453 v_[jj][i] = z * c - x * ss;
459 if (!essentiallyEqual(z, 0.))
469 for (jj = 0; jj < m_; ++jj)
473 u_[jj][j] = y * c + z * ss;
474 u_[jj][i] = z * c - y * ss;
511 for (i = inc; i < n_; ++i)
514 for (k = 0; k < m_; ++k)
519 for (k = 0; k < n_; ++k)
525 while (s_[j - inc] < sw)
529 for (k = 0; k < m_; ++k)
531 u_[k][j] = u_[k][j - inc];
534 for (k = 0; k < n_; ++k)
536 v_[k][j] = v_[k][j - inc];
549 for (k = 0; k < m_; ++k)
554 for (k = 0; k < n_; ++k)
561 for (k = 0; k < n_; ++k)
565 for (i = 0; i < m_; i++)
573 for (j = 0; j < n_; ++j)
581 if (ss > (m_ + n_) / 2)
583 for (i = 0; i < m_; ++i)
585 u_[i][k] = -u_[i][k];
588 for (j = 0; j < n_; ++j)
590 v_[j][k] = -v_[j][k];
605 static double pythag(
double inA,
double inB)
noexcept
607 const double absa = std::abs(inA);
608 const double absb = std::abs(inB);
610 ? absa * std::sqrt(1. + (absb / absa) * (absb / absa))
611 : (essentiallyEqual(absb, 0.) ? 0. : absb * std::sqrt(1. + (absb / absa) * (absb / absa))));
613 static Buffer<double> lstsq(
const NdArray& inA,
const Buffer<double>& inB,
double inTolerance = 1e-12)
616 const double threshold = inTolerance * svdSolver.s()[0];
618 return svdSolver.solve(inB, threshold);