cisst-saw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
nmrSVDEconomy.h
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */
3 
4 /*
5  Author(s): Ankur Kapoor, Anton Deguet
6  Created on: 2005-10-18
7 
8  (C) Copyright 2005-2014 Johns Hopkins University (JHU), All Rights
9  Reserved.
10 
11 --- begin cisst license - do not edit ---
12 
13 This software is provided "as is" under an open source license, with
14 no warranty. The complete license can be found in license.txt and
15 http://www.cisst.org/cisst/license.txt.
16 
17 --- end cisst license ---
18 */
19 
20 
27 #ifndef _nmrSVDEconomy_h
28 #define _nmrSVDEconomy_h
29 
30 #include <cisstCommon/cmnThrow.h>
34 
35 // Always include last
37 
38 
106 
107 public:
113  typedef unsigned int size_type;
114 
118 
119 protected:
122 
129 
139 
148 
153  inline void SetDimension(size_type m, size_type n, bool storageOrder)
154  {
155  StorageOrderMember = storageOrder;
156  MMember = m;
157  NMember = n;
158  }
159 
179  inline void AllocateOutputWorkspace(bool allocateOutput, bool allocateWorkspace)
180  {
181  // allocate output
182  if (allocateOutput) {
183  const size_type minmn = (MMember < NMember) ? MMember : NMember;
184  const size_type outputLength = MMember * minmn + NMember * NMember + minmn;
185  this->OutputMemory.SetSize(outputLength);
186  this->UReference.SetRef(MMember, minmn,
187  (StorageOrderMember) ? minmn : 1,
188  (StorageOrderMember) ? 1 : MMember,
189  this->OutputMemory.Pointer(0));
191  (StorageOrderMember) ? NMember : 1,
192  (StorageOrderMember) ? 1 : NMember,
193  this->OutputMemory.Pointer(MMember * minmn));
194  this->SReference.SetRef(minmn,
195  this->OutputMemory.Pointer(MMember * minmn + NMember * NMember), 1);
196  } else {
197  this->OutputMemory.SetSize(0);
198  }
199  // allocate workspace
200  if (allocateWorkspace) {
203  } else {
204  this->WorkspaceMemory.SetSize(0);
205  }
206  }
207 
208 
216  template <typename _matrixOwnerTypeU,
217  typename _vectorOwnerTypeS,
218  typename _matrixOwnerTypeVt>
222  throw(std::runtime_error)
223  {
224  // check sizes and storage order
225  const size_type minmn = (MMember < NMember) ? MMember : NMember;
226  if ((inU.rows() != MMember ) || (inU.cols() != minmn)) {
227  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Size of matrix U is incorrect."));
228  }
229  if (inU.StorageOrder() != StorageOrderMember) {
230  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Storage order of U is incorrect."));
231  }
232  if (!inU.IsCompact()) {
233  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Matrix U must be compact."));
234  }
235  if (! inVt.IsSquare(NMember)) {
236  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Size of matrix Vt is incorrect."));
237  }
238  if (inVt.StorageOrder() != StorageOrderMember) {
239  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Storage order of Vt is incorrect."));
240  }
241  if (!inVt.IsCompact()) {
242  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Matrix Vt must be compact."));
243  }
244  if (minmn != inS.size()) {
245  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Size of vector S is incorrect."));
246  }
247  if (!inS.IsCompact()) {
248  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Vector S must be compact."));
249  }
250  }
251 
252 
260  template <typename _vectorOwnerTypeWorkspace>
261  inline void
263  throw(std::runtime_error)
264  {
266  if (lwork > inWorkspace.size()) {
267  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Workspace is too small."));
268  }
269  if (!inWorkspace.IsCompact()) {
270  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Workspace must be compact."));
271  }
272  }
273 
274 
275 public:
276 
283  {
284  const size_type minmn = (m < n) ? m : n;
285  const size_type maxmn = (m > n) ? m : n;
286  const size_type lwork_1 = 3 * minmn + maxmn;
287  const size_type lwork_2 = 5 * minmn;
288  return (lwork_1 > lwork_2) ? lwork_1 : lwork_2;
289  }
290 
296  template <class _matrixOwnerTypeA>
298  {
300  }
301 
302 
310  template <class _matrixOwnerTypeA>
311  static inline
313  {
314  nsize_type matrixSize(A.rows(), (A.rows() < A.cols()) ? A.row() : A.cols());
315  return matrixSize;
316  }
317 
318 
327  template <class _matrixOwnerTypeA, class _matrixOwnerTypeS, class _vectorOwnerTypeS>
328  static inline
333  throw(std::runtime_error)
334  {
335  const size_type minmn = (A.rows() < A.cols()) ? A.rows() : A.cols();
336  if ((minmn != matrixS.rows()) || (minmn != matrixS.cols())) {
337  cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData::UpdateMatrixS: Size of matrix S is incorrect."));
338  }
339  matrixS.SetAll(0.0);
340  matrixS.Diagonal().Assign(vectorS);
341  return matrixS;
342  }
343 
344 #ifndef SWIG
345 #ifndef DOXYGEN
346 
352  class Friend {
353  private:
355  public:
356  Friend(nmrSVDEconomyDynamicData &inData): Data(inData) {
357  }
359  return Data.SReference;
360  }
362  return Data.UReference;
363  }
365  return Data.VtReference;
366  }
368  return Data.WorkspaceReference;
369  }
370  inline size_type M(void) {
371  return Data.MMember;
372  }
373  inline size_type N(void) {
374  return Data.NMember;
375  }
376  inline bool StorageOrder(void) {
377  return Data.StorageOrderMember;
378  }
379  };
380  friend class Friend;
381 #endif // DOXYGEN
382 #endif // SWIG
383 
394  MMember(static_cast<size_type>(0)),
395  NMember(static_cast<size_type>(0)),
397  {
398  AllocateOutputWorkspace(false, false);
399  }
400 
414  {
415  this->Allocate(m, n, storageOrder);
416  }
417 
430  template <class _matrixOwnerTypeA>
432  {
433  this->Allocate(A);
434  }
435 
450  template <class _matrixOwnerTypeA, class _vectorOwnerTypeWorkspace>
453  {
454  this->SetRefWorkspace(A, inWorkspace);
455  }
456 
471  template <typename _matrixOwnerTypeU,
472  typename _vectorOwnerTypeS,
473  typename _matrixOwnerTypeVt,
474  typename _vectorOwnerTypeWorkspace>
479  {
480  this->SetRef(inU, inS, inVt, inWorkspace);
481  }
482 
493  template <typename _matrixOwnerTypeU,
494  typename _vectorOwnerTypeS,
495  typename _matrixOwnerTypeVt>
499  {
500  this->SetRefOutput(inU, inS, inVt);
501  }
502 
503 
514  template <class _matrixOwnerTypeA>
516  {
517  this->Allocate(A.rows(), A.cols(), A.StorageOrder());
518  }
519 
531  template <class _matrixOwnerTypeA, class _vectorOwnerTypeWorkspace>
534  {
535  this->SetDimension(A.rows(), A.cols(), A.StorageOrder());
536 
537  // allocate output and set references
538  this->AllocateOutputWorkspace(true, false);
539 
540  // set reference on user provided workspace
541  this->ThrowUnlessWorkspaceSizeIsCorrect(inWorkspace);
542  this->WorkspaceReference.SetRef(inWorkspace);
543  }
544 
555  void Allocate(size_type m, size_type n, bool storageOrder)
556  {
557  this->SetDimension(m, n, storageOrder);
558  this->AllocateOutputWorkspace(true, true);
559  }
560 
573  template <typename _matrixOwnerTypeU,
574  typename _vectorOwnerTypeS,
575  typename _matrixOwnerTypeVt,
576  typename _vectorOwnerTypeWorkspace>
581  throw(std::runtime_error)
582  {
583  this->SetDimension(inU.rows(), inVt.rows(), inU.StorageOrder());
584  this->AllocateOutputWorkspace(false, false);
585  this->ThrowUnlessOutputSizeIsCorrect(inU, inS, inVt);
586  this->ThrowUnlessWorkspaceSizeIsCorrect(inWorkspace);
587 
588  this->SReference.SetRef(inS);
589  this->UReference.SetRef(inU);
590  this->VtReference.SetRef(inVt);
591  this->WorkspaceReference.SetRef(inWorkspace);
592  }
593 
594 
603  template <typename _matrixOwnerTypeU,
604  typename _vectorOwnerTypeS, typename _matrixOwnerTypeVt>
608  throw(std::runtime_error)
609  {
610  this->SetDimension(inU.rows(), inVt.rows(), inU.StorageOrder());
611  this->ThrowUnlessOutputSizeIsCorrect(inU, inS, inVt);
612 
613  this->SReference.SetRef(inS);
614  this->UReference.SetRef(inU);
615  this->VtReference.SetRef(inVt);
616 
617  AllocateOutputWorkspace(false, true);
618  }
619 
623  inline const vctDynamicVectorRef<CISSTNETLIB_DOUBLE> & S(void) const {
624  return SReference;
625  }
626 
630  inline const vctDynamicMatrixRef<CISSTNETLIB_DOUBLE> & U(void) const {
631  return UReference;
632  }
636  inline const vctDynamicMatrixRef<CISSTNETLIB_DOUBLE> & Vt(void) const {
637  return VtReference;
638  }
639 };
640 
641 
642 
643 
644 
645 
646 
647 
778 
779 
800 template <class _matrixOwnerType>
803  throw (std::runtime_error)
804 {
805  typename nmrSVDEconomyDynamicData::Friend dataFriend(data);
806  CISSTNETLIB_INTEGER Info;
807  char m_Jobu = 'S';
808  char m_Jobvt = 'A';
809  CISSTNETLIB_INTEGER m_Lwork = static_cast<CISSTNETLIB_INTEGER>(nmrSVDEconomyDynamicData::WorkspaceSize(dataFriend.M(),
810  dataFriend.N()));
811  /* check that storage order matches with Allocate() */
812  if (A.StorageOrder() != dataFriend.StorageOrder()) {
813  cmnThrow(std::runtime_error("nmrSVDEconomy: Storage order used for Allocate was different"));
814  }
815  /* check sizes */
816  if ((dataFriend.M() != A.rows()) || (dataFriend.N() != A.cols())) {
817  cmnThrow(std::runtime_error("nmrSVDEconomy: Size used for Allocate was different"));
818  }
819  /* check that the matrices are compact */
820  if (! A.IsCompact()) {
821  cmnThrow(std::runtime_error("nmrSVDEconomy: Requires a compact matrix"));
822  }
823 
824  /* Based on storage order, permute U and Vt as well as dimension */
825  CISSTNETLIB_DOUBLE *UPtr, *VtPtr;
826  CISSTNETLIB_INTEGER m_Lda, m_Ldu, m_Ldvt;
827 
828  if (A.IsColMajor()) {
829  m_Lda = (1 > dataFriend.M()) ? 1 : dataFriend.M();
830  m_Ldu = dataFriend.M();
831  m_Ldvt = dataFriend.N();
832  UPtr = dataFriend.U().Pointer();
833  VtPtr = dataFriend.Vt().Pointer();
834  } else {
835  m_Lda = (1 > dataFriend.N()) ? 1 : dataFriend.N();
836  m_Ldu = dataFriend.N();
837  m_Ldvt = dataFriend.M();
838  UPtr = dataFriend.Vt().Pointer();
839  VtPtr = dataFriend.U().Pointer();
840  }
841 
842  // for versions based on gfortran/lapack, CISSTNETLIB_VERSION is
843  // defined
844 #if defined(CISSTNETLIB_VERSION)
845 #if defined(CISSTNETLIB_VERSION_MAJOR)
846 #if (CISSTNETLIB_VERSION_MAJOR >= 3)
847  cisstNetlib_dgesvd_(&m_Jobu, &m_Jobvt, &m_Ldu, &m_Ldvt,
848  A.Pointer(), &m_Lda, dataFriend.S().Pointer(),
849  UPtr, &m_Ldu,
850  VtPtr, &m_Ldvt,
851  dataFriend.Workspace().Pointer(), &m_Lwork, &Info);
852 #endif
853 #else // no major version
854  dgesvd_(&m_Jobu, &m_Jobvt, &m_Ldu, &m_Ldvt,
855  A.Pointer(), &m_Lda, dataFriend.S().Pointer(),
856  UPtr, &m_Ldu,
857  VtPtr, &m_Ldvt,
858  dataFriend.Workspace().Pointer(), &m_Lwork, &Info);
859 #endif // CISSTNETLIB_VERSION
860 #else
861  ftnlen jobu_len = (ftnlen)1, jobvt_len = (ftnlen)1;
862  la_dzlapack_MP_sgesvd_nat(&m_Jobu, &m_Jobvt, &m_Ldu, &m_Ldvt,
863  A.Pointer(), &m_Lda, dataFriend.S().Pointer(),
864  UPtr, &m_Ldu,
865  VtPtr, &m_Ldvt,
866  dataFriend.Workspace().Pointer(), &m_Lwork, &Info,
867  jobu_len, jobvt_len);
868 #endif
869  return Info;
870 }
871 
888 template <class _matrixOwnerTypeA, class _matrixOwnerTypeU,
889  class _vectorOwnerTypeS, class _matrixOwnerTypeVt,
890  class _vectorOwnerTypeWorkspace>
896 {
897  nmrSVDEconomyDynamicData svdData(U, S, Vt, Workspace);
898  CISSTNETLIB_INTEGER ret_value = nmrSVDEconomy(A, svdData);
899  return ret_value;
900 }
901 
922 template <class _matrixOwnerTypeA, class _matrixOwnerTypeU,
923  class _vectorOwnerTypeS, class _matrixOwnerTypeVt>
928 {
929  nmrSVDEconomyDynamicData svdData(U, S, Vt);
930  CISSTNETLIB_INTEGER ret_value = nmrSVDEconomy(A, svdData);
931  return ret_value;
932 }
933 
934 
936 
937 
938 #endif
939 
vctDynamicVector< CISSTNETLIB_DOUBLE > WorkspaceMemory
Definition: nmrSVDEconomy.h:121
const vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & U(void) const
Definition: nmrSVDEconomy.h:630
void ThrowUnlessOutputSizeIsCorrect(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt) const
Definition: nmrSVDEconomy.h:219
Declaration of vctDynamicMatrix.
Definition: vctDynamicMatrixBase.h:42
const vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & Vt(void) const
Definition: nmrSVDEconomy.h:636
unsigned int size_type
Definition: nmrSVDEconomy.h:113
size_type MMember
Definition: nmrSVDEconomy.h:144
Data for SVD problem (Dynamic).
Definition: nmrSVDEconomy.h:105
Declaration of vctFixedSizeMatrix.
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A)
Definition: nmrSVDEconomy.h:431
vctFixedSizeVector< size_type, 2 > nsize_type
Definition: nmrSVDEconomy.h:117
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > SReference
Definition: nmrSVDEconomy.h:136
bool StorageOrder(void)
Definition: nmrSVDEconomy.h:376
bool StorageOrder(void) const
Definition: vctDynamicConstMatrixBase.h:656
void SetRef(size_type size, pointer data, stride_type stride=1)
Definition: vctDynamicVectorRef.h:156
void SetRefOutput(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt)
Definition: nmrSVDEconomy.h:605
nmrSVDEconomyDynamicData()
Definition: nmrSVDEconomy.h:393
void ThrowUnlessWorkspaceSizeIsCorrect(vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace) const
Definition: nmrSVDEconomy.h:262
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & Vt(void)
Definition: nmrSVDEconomy.h:364
nmrSVDEconomyDynamicData(size_type m, size_type n, bool storageOrder)
Definition: nmrSVDEconomy.h:413
const vctDynamicVectorRef< CISSTNETLIB_DOUBLE > & S(void) const
Definition: nmrSVDEconomy.h:623
static size_type WorkspaceSize(size_type m, size_type n)
Definition: nmrSVDEconomy.h:282
void SetSize(size_type size)
Definition: vctDynamicVector.h:315
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt)
Definition: nmrSVDEconomy.h:496
Definition: vctDynamicConstMatrixBase.h:77
Implementation of a fixed-size vector using template metaprogramming.
Definition: vctFixedSizeVector.h:52
void SetDimension(size_type m, size_type n, bool storageOrder)
Definition: nmrSVDEconomy.h:153
void SetRef(size_type rows, size_type cols, stride_type rowStride, stride_type colStride, pointer dataPointer)
Definition: vctDynamicMatrixRef.h:217
static vctDynamicMatrixBase< _matrixOwnerTypeS, CISSTNETLIB_DOUBLE > & UpdateMatrixS(const vctDynamicConstMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, const vctDynamicConstVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &vectorS, vctDynamicMatrixBase< _matrixOwnerTypeS, CISSTNETLIB_DOUBLE > &matrixS)
Definition: nmrSVDEconomy.h:330
void SetRef(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace)
Definition: nmrSVDEconomy.h:577
bool StorageOrderMember
Definition: nmrSVDEconomy.h:146
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace)
Definition: nmrSVDEconomy.h:475
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > VtReference
Definition: nmrSVDEconomy.h:135
pointer Pointer(size_type rowIndex, size_type colIndex)
Definition: vctDynamicMatrixBase.h:143
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & U(void)
Definition: nmrSVDEconomy.h:361
size_type rows() const
Definition: vctDynamicConstMatrixBase.h:238
size_type cols() const
Definition: vctDynamicConstMatrixBase.h:243
void Allocate(size_type m, size_type n, bool storageOrder)
Definition: nmrSVDEconomy.h:555
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > WorkspaceReference
Definition: nmrSVDEconomy.h:137
#define cmnThrow(a)
Definition: MinimalCmn.h:4
vctDynamicVector< CISSTNETLIB_DOUBLE > OutputMemory
Definition: nmrSVDEconomy.h:128
pointer Pointer(index_type index=0)
Definition: vctDynamicVectorBase.h:155
Definition: nmrSVDEconomy.h:352
void SetRefWorkspace(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace)
Definition: nmrSVDEconomy.h:532
size_type M(void)
Definition: nmrSVDEconomy.h:370
CISSTNETLIB_INTEGER nmrSVDEconomy(vctDynamicMatrixBase< _matrixOwnerType, CISSTNETLIB_DOUBLE > &A, nmrSVDEconomyDynamicData &data)
Definition: nmrSVDEconomy.h:801
size_type N(void)
Definition: nmrSVDEconomy.h:373
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > & S(void)
Definition: nmrSVDEconomy.h:358
Definition: vctDynamicConstVectorBase.h:77
void Allocate(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A)
Definition: nmrSVDEconomy.h:515
Friend(nmrSVDEconomyDynamicData &inData)
Definition: nmrSVDEconomy.h:356
Declaration of the template function cmnThrow.
const bool VCT_COL_MAJOR
Definition: vctForwardDeclarations.h:46
size_type NMember
Definition: nmrSVDEconomy.h:145
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > & Workspace(void)
Definition: nmrSVDEconomy.h:367
void AllocateOutputWorkspace(bool allocateOutput, bool allocateWorkspace)
Definition: nmrSVDEconomy.h:179
Rules of exporting.
static nsize_type MatrixSSize(const vctDynamicConstMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A)
Definition: nmrSVDEconomy.h:312
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > UReference
Definition: nmrSVDEconomy.h:134
static size_type WorkspaceSize(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &inA)
Definition: nmrSVDEconomy.h:297
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace)
Definition: nmrSVDEconomy.h:451
Definition: vctDynamicVectorBase.h:61