cisst-saw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Classes
nmrSVDEconomy.h File Reference

Declaration of nmrSVDEconomy. More...

#include <cisstCommon/cmnThrow.h>
#include <cisstVector/vctFixedSizeMatrix.h>
#include <cisstVector/vctDynamicMatrix.h>
#include <cisstNumerical/nmrNetlib.h>
#include <cisstNumerical/nmrExport.h>

Go to the source code of this file.

Classes

class  nmrSVDEconomyDynamicData
 Data for SVD problem (Dynamic). More...
 
class  nmrSVDEconomyDynamicData::Friend
 

Functions

Algorithm SVD: Singular Value Decomposition

The nmrSVDEconomy functions compute the singular value decomposition (SVD) of a real $ M \times N $ matrix A, optionally computing the left and/or right singular vectors. The SVD problem is written:

$ A = U * \Sigma * V^{T} $

where $ \Sigma $ is a $ M \times N $ matrix which is zero except for its min(m,n) diagonal elements, U is a $ M \times M $ orthogonal matrix, and V is a $ N \times N $ orthogonal matrix. The diagonal elements of $ \Sigma $ are the singular values of A; they are real and non-negative, and are returned in descending order. The first $ \mbox{min}(m,n) $ columns of U and V are the left and right singular vectors of A.

These functions are wrappers around the LAPACK routine dgesvd, therefore they share some features with the LAPACK routine:

  1. They return $ V^{T} $, not $ V $.
  2. On exit, the content of A is altered.
  3. The vectors and matrices must be compact, i.e. use a contiguous block of memory.

The nmrSVDEconomy functions add the following features:

  1. A simplified interface to the cisstVector matrices, either vctDynamicMatrix
  2. The possibility to use any storage order, i.e. VCT_ROW_MAJOR or VCT_COL_MAJOR. In the specific case of SVD, the storage order can be treated as a transpose and the properties of the decomposition are preserved (nmrSVDEconomy will swap U and Vt pointers). This is performed at no extra cost, i.e. no copy back and forth of the elements nor extra memory allocation.
  3. Input validation checks are performed, i.e. an std::runtime_error exception will be thrown if the sizes or storage order don't match or if the containers are not compact.
  4. Helper classes to allocate memory for the output and workspace: nmrSVDEconomyDynamicData.

There are different ways to call this function to compute the SVD of the matrix A. These correspond to different overloaded nmrSVDEconomy functions:

  1. Using a preallocated data object.

    The user creates the input matrix A:

    vctRandom(A, -10.0, 10.0);

    The user allocates a data object which could be of type nmrSVDEconomyDynamicData. corresponding to fixed size or dynamic matrix A:

    Call the nmrSVDEconomy function:

    nmrSVDEconomy(A, data);

    The content of input matrix A is modified by this routine. The matrices U, Vt and vector S are available through the following methods

    std::cout << "U: " << data.U() << std::endl
    << "S: " << data.S() << std::endl
    << "V: " << data.Vt().Transpose() << std::endl;

  2. The user provides the matrices U, Vt, and vector S.

    The User allocates memory for these matrices and vector:

    Call the SVD routine:

    nmrSVDEconomy(A, U, S, Vt);

    The SVD function verifies that the size of the data objects matches the input, and allocates workspace memory, which is deallocated when the function ends.

  3. The user provides the matrices U, Vt, and vector S along with workspace required by SVD routine of LAPACK.

    Create matrices and vector:

    One also needs to allocate memory the for workspace. This approach is particularly useful when the user is using more than one numerical method from the library and is willing or need to share the workspace between them. In such as case, the user can allocate a block of memory greater than the minimum required by different methods. To help the user determine the minimum workspace required the library provides the helper function nmrSVDEconomyDynamicData::WorkspaceSize().

    Call the SVD function:

    nmrSVDEconomy(A, U, S, Vt, workspace);

Note
The SVD functions make use of LAPACK routines. To activate this code, set the CISST_HAS_CISSTNETLIB flag to ON during the configuration of cisst with CMake.
The general rule for numerical functions which depend on LAPACK is that column major matrices should be used everywhere, and that all matrices should be compact. In this case, both row major and column major are allowed but they must not be mixed in a data object.
template<class _matrixOwnerType >
CISSTNETLIB_INTEGER nmrSVDEconomy (vctDynamicMatrixBase< _matrixOwnerType, CISSTNETLIB_DOUBLE > &A, nmrSVDEconomyDynamicData &data) throw (std::runtime_error)
 
template<class _matrixOwnerTypeA , class _matrixOwnerTypeU , class _vectorOwnerTypeS , class _matrixOwnerTypeVt , class _vectorOwnerTypeWorkspace >
CISSTNETLIB_INTEGER nmrSVDEconomy (vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &U, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &S, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &Vt, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &Workspace)
 
template<class _matrixOwnerTypeA , class _matrixOwnerTypeU , class _vectorOwnerTypeS , class _matrixOwnerTypeVt >
CISSTNETLIB_INTEGER nmrSVDEconomy (vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &U, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &S, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &Vt)
 

Detailed Description

Declaration of nmrSVDEconomy.

Function Documentation

template<class _matrixOwnerType >
CISSTNETLIB_INTEGER nmrSVDEconomy ( vctDynamicMatrixBase< _matrixOwnerType, CISSTNETLIB_DOUBLE > &  A,
nmrSVDEconomyDynamicData data 
)
throw (std::runtime_error
)
inline

This function solves the SVD problem for a dynamic matrix using an nmrSVDEconomyDynamicData.

This function checks for valid input (size, storage order and compact) and calls the LAPACK function. If the input doesn't match the data, an exception is thrown (std::runtime_error).

This function modifies the input matrix A and stores the results in the data. Each component of the result can be obtained via the const methods nmrSVDEconomyDynamicData::U(), nmrSVDEconomyDynamicData::S() and nmrSVDEconomyDynamicData::Vt().

Parameters
AA matrix of size MxN, either vctDynamicMatrix or vctDynamicMatrixRef.
dataA data object corresponding to the input matrix.
Test:
nmrSVDEconomyTest::TestDynamicColumnMajor nmrSVDEconomyTest::TestDynamicRowMajor nmrSVDEconomyTest::TestDynamicColumnMajorUserAlloc nmrSVDEconomyTest::TestDynamicRowMajorUserAlloc
template<class _matrixOwnerTypeA , class _matrixOwnerTypeU , class _vectorOwnerTypeS , class _matrixOwnerTypeVt , class _vectorOwnerTypeWorkspace >
CISSTNETLIB_INTEGER nmrSVDEconomy ( vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &  A,
vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &  U,
vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &  S,
vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &  Vt,
vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &  Workspace 
)
inline

This function solves the SVD problem for a dynamic matrix using the storage provided by the user for both the output (U, S, Vt) and the workspace.

Internally, a data is created using the storage provided by the user (see nmrSVDEconomyDynamicData::SetRef). While the data is being build, the consistency of the output and workspace is checked. Then, the nmrSVDEconomy(A, data) function can be used safely.

Parameters
Ais a reference to a dynamic matrix of size MxN
U,S,VtThe output matrices and vector for SVD
WorkspaceThe workspace for LAPACK.
Test:
nmrSVDEconomyTest::TestDynamicColumnMajorUserAlloc nmrSVDEconomyTest::TestDynamicRowMajorUserAlloc
template<class _matrixOwnerTypeA , class _matrixOwnerTypeU , class _vectorOwnerTypeS , class _matrixOwnerTypeVt >
CISSTNETLIB_INTEGER nmrSVDEconomy ( vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &  A,
vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &  U,
vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &  S,
vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &  Vt 
)
inline

This function solves the SVD problem for a dynamic matrix using the storage provided by the user for the output (U, S, Vt). A workspace will be dynamically allocated.

Internally, a data is created using the storage provided by the user (see nmrSVDEconomyDynamicData::SetRefOutput). While the data is being build, the consistency of the output is checked. Then, the nmrSVDEconomy(A, data) function can be used safely.

Parameters
Ais a reference to a dynamic matrix of size MxN
U,S,VtThe output matrices and vector for SVD
Test:
nmrSVDEconomyTest::TestDynamicColumnMajorUserAlloc nmrSVDEconomyTest::TestDynamicRowMajorUserAlloc
Warning
Again, this method will dynamically allocate a workspace at each call. This is somewhat inefficient if the method is to be called many times. For a real-time task, the dynamic allocation might even break your application.