113 template <
typename Real>
126 unsigned int maxIterations);
134 unsigned int Solve(Real
const*
input,
int sortType);
144 void GetU(Real* uMatrix)
const;
145 void GetV(Real* vMatrix)
const;
151 void GetVColumn(
int index, Real* vColumn)
const;
166 void GetSinCos(Real u, Real
v, Real& cs, Real& sn);
249 template <
typename Real>
251 int numCols,
unsigned int maxIterations)
257 if (numCols > 1 && numRows >= numCols && maxIterations > 0)
262 mMatrix.resize(numRows * numCols);
265 mRGivens.reserve(maxIterations*(numCols - 1));
266 mLGivens.reserve(maxIterations*(numCols - 1));
278 template <
typename Real>
285 std::copy(input, input + numElements,
mMatrix.begin());
297 Real maxAbsComp =
std::abs(input[0]);
298 for (
int i = 1; i < numElements; ++i)
301 if (absComp > maxAbsComp)
303 maxAbsComp = absComp;
308 if (maxAbsComp > (Real)0)
310 Real invMaxAbsComp = ((Real)1) / maxAbsComp;
311 for (
int i = 0; i < numElements; ++i)
313 Real ratio = input[i] * invMaxAbsComp;
314 norm += ratio * ratio;
316 norm = maxAbsComp*sqrt(norm);
319 Real
const multiplier = (Real)8;
320 Real
const epsilon = std::numeric_limits<Real>::epsilon();
321 Real
const threshold = multiplier * epsilon * norm;
327 int imin = -1, imax = -1;
328 for (
int i = mNumCols - 2; i >= 0; --i)
379 template <
typename Real>
381 Real* singularValues)
const 397 size_t numBytes =
mNumCols*
sizeof(Real);
403 template <
typename Real>
416 uMatrix[d + mNumRows*d] = (Real)1;
421 for (
int i0 =
mNumCols - 1, i1 = i0 + 1; i0 >= 0; --i0, --i1)
457 int j0 = givens.index0;
458 int j1 = givens.index1;
461 Real& q0 = uMatrix[j0];
462 Real& q1 = uMatrix[j1];
463 Real prd0 = givens.cs * q0 - givens.sn * q1;
464 Real prd1 = givens.sn * q0 + givens.cs * q1;
479 int start =
c, current =
c, next;
489 uMatrix[current + mNumRows*
r] =
490 uMatrix[next + mNumRows*
r];
504 template <
typename Real>
517 vMatrix[d + mNumCols*d] = (Real)1;
521 int i0 = mNumCols - 3;
525 for (; i0 >= 0; --i0, --i1, --i2)
561 int j0 = givens.index0;
562 int j1 = givens.index1;
565 Real& q0 = vMatrix[j0];
566 Real& q1 = vMatrix[j1];
567 Real prd0 = givens.cs * q0 - givens.sn * q1;
568 Real prd1 = givens.sn * q0 + givens.cs * q1;
592 int start =
c, current =
c, next;
602 vMatrix[current + mNumCols*
r] =
603 vMatrix[next + mNumCols*
r];
617 template <
typename Real>
628 memset(x, 0,
mNumRows *
sizeof(Real));
642 Real& xr0 = x[givens.index0];
643 Real& xr1 = x[givens.index1];
644 Real tmp0 = givens.cs * xr0 + givens.sn * xr1;
645 Real tmp1 = -givens.sn * xr0 + givens.cs * xr1;
655 for (r = 0; r <
c; ++
r)
662 for (
int j = r + 1; j <
mNumRows; ++j)
683 size_t numBytes =
mNumRows*
sizeof(Real);
684 Memcpy(uColumn, x, numBytes);
689 template <
typename Real>
700 memset(x, 0,
mNumCols *
sizeof(Real));
715 Real& xr0 = x[givens.index0];
716 Real& xr1 = x[givens.index1];
717 Real tmp0 = givens.cs * xr0 + givens.sn * xr1;
718 Real tmp1 = -givens.sn * xr0 + givens.cs * xr1;
728 for (c = 0; c <
r + 1; ++
c)
735 for (
int j = c + 1; j <
mNumCols; ++j)
737 s += x[j] *
mMatrix[j + mNumCols *
r];
756 size_t numBytes =
mNumCols*
sizeof(Real);
757 Memcpy(vColumn, x, numBytes);
762 template <
typename Real>
784 template <
typename Real>
788 for (
int i = 0, ip1 = 1; i <
mNumCols; ++i, ++ip1)
799 length = sqrt(length);
803 Real sgn = (u1 >= (Real)0 ? (Real)1 : (Real)-1);
804 Real invDenom = ((Real)1) / (u1 + sgn *
length);
815 Real invudu = (Real)1 / udu;
816 Real twoinvudu = invudu * (Real)2;
836 if (i < mNumCols - 2)
842 Real vc =
mMatrix[c + mNumCols*i];
847 length = sqrt(length);
851 Real sgn = (v1 >= (Real)0 ? (Real)1 : (Real)-1);
852 Real invDenom = ((Real)1) / (v1 + sgn *
length);
863 Real invvdv = (Real)1 / vdv;
864 Real twoinvvdv = invvdv * (Real)2;
900 int k, ksup = mNumCols - 1,
index = 0, delta = mNumCols + 1;
901 for (k = 0; k < ksup; ++k, index += delta)
909 template <
typename Real>
920 sn = ((Real)1) / sqrt(((Real)1) + tau*tau);
926 cs = ((Real)1) / sqrt(((Real)1) + tau*tau);
937 template <
typename Real>
939 int imax, Real threshold)
941 for (
int i = imin; i <= imax; ++i)
950 for (
int j = i + 1; j <= imax + 1; ++j)
969 template <
typename Real>
978 Real a00 = d1*d1 + f0*f0;
980 Real a11 = d2*d2 + f1*f1;
981 Real dif = (a00 - a11) * (Real)0.5;
982 Real sgn = (dif >= (Real)0 ? (Real)1 : (Real)-1);
983 Real a01sqr = a01 * a01;
984 Real u = a11 - a01sqr / (dif + sgn*sqrt(dif*dif + a01sqr));
988 Real a12, a21, a22, a23, cs, sn;
990 int i0 = imin - 1, i1 = imin, i2 = imin + 1;
991 for (; i1 <= imax; ++i0, ++i1, ++i2)
1001 mSuperdiagonal[i0] = cs*mSuperdiagonal[i0] - sn*a02;
1005 a12 = mSuperdiagonal[i1];
1008 mSuperdiagonal[i1] = sn*a11 + cs*a12;
1023 a12 = mSuperdiagonal[i1];
1026 mSuperdiagonal[i1] = cs*a12 - sn*a22;
1031 a23 = mSuperdiagonal[i2];
1033 mSuperdiagonal[i2] = cs*a23;
1036 x = mSuperdiagonal[i1];
1042 template <
typename Real>
1059 template <
typename Real>
1078 std::vector<SortItem> items(
mNumCols);
1088 std::sort(items.begin(), items.end(),
1089 [](SortItem
const& item0, SortItem
const& item1)
1091 return item0.singularValue < item1.singularValue;
1097 std::sort(items.begin(), items.end(),
1098 [](SortItem
const& item0, SortItem
const& item1)
1100 return item0.singularValue > item1.singularValue;
1106 for (
auto const& item : items)
1128 template <
typename Real>
1135 template <
typename Real>
1137 int inIndex1, Real inCs, Real inSn)
void GetU(Real *uMatrix) const
SingularValueDecomposition(int numRows, int numCols, unsigned int maxIterations)
ReversalObject< ReverseIterator > reverse(Iterable &&range)
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
std::vector< Real > mVVector
std::vector< Real > mWVector
bool DiagonalEntriesNonzero(int imin, int imax, Real threshold)
std::vector< int > mVisited
void GetVColumn(int index, Real *vColumn) const
void DoGolubKahanStep(int imin, int imax)
unsigned int mMaxIterations
GLenum GLenum GLsizei void GLsizei void * column
std::vector< GivensRotation > mRGivens
GLenum GLenum GLsizei void * row
std::vector< Real > mTwoInvUTU
void EnsureNonnegativeDiagonal()
std::vector< Real > mSuperdiagonal
std::vector< Real > mDiagonal
GLuint GLsizei GLsizei * length
GLdouble GLdouble GLdouble z
GLenum GLenum GLenum input
std::vector< Real > mMatrix
void Memcpy(void *target, void const *source, size_t count)
std::vector< Real > mTwoInvVTV
std::vector< Real > mFixupDiagonal
std::vector< Real > mUVector
unsigned int Solve(Real const *input, int sortType)
void GetSinCos(Real u, Real v, Real &cs, Real &sn)
std::vector< GivensRotation > mLGivens
void GetV(Real *vMatrix) const
void GetSingularValues(Real *singularValues) const
std::vector< int > mPermutation
Real GetSingularValue(int index) const
void ComputePermutation(int sortType)
void GetUColumn(int index, Real *uColumn) const