cisst-saw
Loading...
Searching...
No Matches
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-2018 Johns Hopkins University (JHU), All Rights Reserved.
9
10--- begin cisst license - do not edit ---
11
12This software is provided "as is" under an open source license, with
13no warranty. The complete license can be found in license.txt and
14http://www.cisst.org/cisst/license.txt.
15
16--- end cisst license ---
17*/
18
19
24
25
26#ifndef _nmrSVDEconomy_h
27#define _nmrSVDEconomy_h
28
33
34// Always include last
36
37
105
106public:
112 typedef unsigned int size_type;
113
117
118protected:
121
128
138
147
152 inline void SetDimension(size_type m, size_type n, bool storageOrder)
153 {
154 StorageOrderMember = storageOrder;
155 MMember = m;
156 NMember = n;
157 }
158
178 inline void AllocateOutputWorkspace(bool allocateOutput, bool allocateWorkspace)
179 {
180 // allocate output
181 if (allocateOutput) {
182 const size_type minmn = (MMember < NMember) ? MMember : NMember;
183 const size_type outputLength = MMember * minmn + NMember * NMember + minmn;
184 this->OutputMemory.SetSize(outputLength);
185 this->UReference.SetRef(MMember, minmn,
186 (StorageOrderMember) ? minmn : 1,
188 this->OutputMemory.Pointer(0));
189 this->VtReference.SetRef(NMember, NMember,
192 this->OutputMemory.Pointer(MMember * minmn));
193 this->SReference.SetRef(minmn,
194 this->OutputMemory.Pointer(MMember * minmn + NMember * NMember), 1);
195 } else {
196 this->OutputMemory.SetSize(0);
197 }
198 // allocate workspace
199 if (allocateWorkspace) {
200 this->WorkspaceMemory.SetSize(WorkspaceSize(MMember, NMember));
201 this->WorkspaceReference.SetRef(this->WorkspaceMemory);
202 } else {
203 this->WorkspaceMemory.SetSize(0);
204 }
205 }
206
207
215 template <typename _matrixOwnerTypeU,
216 typename _vectorOwnerTypeS,
217 typename _matrixOwnerTypeVt>
221 CISST_THROW(std::runtime_error)
222 {
223 // check sizes and storage order
224 const size_type minmn = (MMember < NMember) ? MMember : NMember;
225 if ((inU.rows() != MMember ) || (inU.cols() != minmn)) {
226 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Size of matrix U is incorrect."));
227 }
228 if (inU.StorageOrder() != StorageOrderMember) {
229 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Storage order of U is incorrect."));
230 }
231 if (!inU.IsCompact()) {
232 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Matrix U must be compact."));
233 }
234 if (! inVt.IsSquare(NMember)) {
235 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Size of matrix Vt is incorrect."));
236 }
237 if (inVt.StorageOrder() != StorageOrderMember) {
238 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Storage order of Vt is incorrect."));
239 }
240 if (!inVt.IsCompact()) {
241 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Matrix Vt must be compact."));
242 }
243 if (minmn != inS.size()) {
244 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Size of vector S is incorrect."));
245 }
246 if (!inS.IsCompact()) {
247 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Vector S must be compact."));
248 }
249 }
250
251
259 template <typename _vectorOwnerTypeWorkspace>
260 inline void
262 CISST_THROW(std::runtime_error)
263 {
265 if (lwork > inWorkspace.size()) {
266 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Workspace is too small."));
267 }
268 if (!inWorkspace.IsCompact()) {
269 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData: Workspace must be compact."));
270 }
271 }
272
273
274public:
275
282 {
283 const size_type minmn = (m < n) ? m : n;
284 const size_type maxmn = (m > n) ? m : n;
285 const size_type lwork_1 = 3 * minmn + maxmn;
286 const size_type lwork_2 = 5 * minmn;
287 return (lwork_1 > lwork_2) ? lwork_1 : lwork_2;
288 }
289
295 template <class _matrixOwnerTypeA>
300
301
309 template <class _matrixOwnerTypeA>
310 static inline
312 {
313 nsize_type matrixSize(A.rows(), (A.rows() < A.cols()) ? A.row() : A.cols());
314 return matrixSize;
315 }
316
317
326 template <class _matrixOwnerTypeA, class _matrixOwnerTypeS, class _vectorOwnerTypeS>
327 static inline
332 CISST_THROW(std::runtime_error)
333 {
334 const size_type minmn = (A.rows() < A.cols()) ? A.rows() : A.cols();
335 if ((minmn != matrixS.rows()) || (minmn != matrixS.cols())) {
336 cmnThrow(std::runtime_error("nmrSVDEconomyDynamicData::UpdateMatrixS: Size of matrix S is incorrect."));
337 }
338 matrixS.SetAll(0.0);
339 matrixS.Diagonal().Assign(vectorS);
340 return matrixS;
341 }
342
343#ifndef SWIG
344#ifndef DOXYGEN
351 class Friend {
352 private:
354 public:
355 Friend(nmrSVDEconomyDynamicData &inData): Data(inData) {
356 }
358 return Data.SReference;
359 }
361 return Data.UReference;
362 }
364 return Data.VtReference;
365 }
367 return Data.WorkspaceReference;
368 }
369 inline size_type M(void) {
370 return Data.MMember;
371 }
372 inline size_type N(void) {
373 return Data.NMember;
374 }
375 inline bool StorageOrder(void) {
376 return Data.StorageOrderMember;
377 }
378 };
379 friend class Friend;
380#endif // DOXYGEN
381#endif // SWIG
382
393 MMember(static_cast<size_type>(0)),
394 NMember(static_cast<size_type>(0)),
396 {
397 AllocateOutputWorkspace(false, false);
398 }
399
413 {
414 this->Allocate(m, n, storageOrder);
415 }
416
429 template <class _matrixOwnerTypeA>
434
449 template <class _matrixOwnerTypeA, class _vectorOwnerTypeWorkspace>
455
470 template <typename _matrixOwnerTypeU,
471 typename _vectorOwnerTypeS,
472 typename _matrixOwnerTypeVt,
473 typename _vectorOwnerTypeWorkspace>
481
492 template <typename _matrixOwnerTypeU,
493 typename _vectorOwnerTypeS,
494 typename _matrixOwnerTypeVt>
501
502
513 template <class _matrixOwnerTypeA>
515 {
516 this->Allocate(A.rows(), A.cols(), A.StorageOrder());
517 }
518
530 template <class _matrixOwnerTypeA, class _vectorOwnerTypeWorkspace>
533 {
534 this->SetDimension(A.rows(), A.cols(), A.StorageOrder());
535
536 // allocate output and set references
537 this->AllocateOutputWorkspace(true, false);
538
539 // set reference on user provided workspace
540 this->ThrowUnlessWorkspaceSizeIsCorrect(inWorkspace);
541 this->WorkspaceReference.SetRef(inWorkspace);
542 }
543
554 void Allocate(size_type m, size_type n, bool storageOrder)
555 {
556 this->SetDimension(m, n, storageOrder);
557 this->AllocateOutputWorkspace(true, true);
558 }
559
572 template <typename _matrixOwnerTypeU,
573 typename _vectorOwnerTypeS,
574 typename _matrixOwnerTypeVt,
575 typename _vectorOwnerTypeWorkspace>
580 CISST_THROW(std::runtime_error)
581 {
582 this->SetDimension(inU.rows(), inVt.rows(), inU.StorageOrder());
583 this->AllocateOutputWorkspace(false, false);
584 this->ThrowUnlessOutputSizeIsCorrect(inU, inS, inVt);
585 this->ThrowUnlessWorkspaceSizeIsCorrect(inWorkspace);
586
587 this->SReference.SetRef(inS);
588 this->UReference.SetRef(inU);
589 this->VtReference.SetRef(inVt);
590 this->WorkspaceReference.SetRef(inWorkspace);
591 }
592
593
602 template <typename _matrixOwnerTypeU,
603 typename _vectorOwnerTypeS, typename _matrixOwnerTypeVt>
607 CISST_THROW(std::runtime_error)
608 {
609 this->SetDimension(inU.rows(), inVt.rows(), inU.StorageOrder());
610 this->ThrowUnlessOutputSizeIsCorrect(inU, inS, inVt);
611
612 this->SReference.SetRef(inS);
613 this->UReference.SetRef(inU);
614 this->VtReference.SetRef(inVt);
615
616 AllocateOutputWorkspace(false, true);
617 }
618
622 inline const vctDynamicVectorRef<CISSTNETLIB_DOUBLE> & S(void) const {
623 return SReference;
624 }
625
629 inline const vctDynamicMatrixRef<CISSTNETLIB_DOUBLE> & U(void) const {
630 return UReference;
631 }
632
635 inline const vctDynamicMatrixRef<CISSTNETLIB_DOUBLE> & Vt(void) const {
636 return VtReference;
637 }
638};
639
640
641
642
643
644
645
646
777
778
799template <class _matrixOwnerType>
802 CISST_THROW(std::runtime_error)
803{
804 typename nmrSVDEconomyDynamicData::Friend dataFriend(data);
805 CISSTNETLIB_INTEGER Info;
806 char m_Jobu = 'S';
807 char m_Jobvt = 'A';
808 CISSTNETLIB_INTEGER m_Lwork = static_cast<CISSTNETLIB_INTEGER>(nmrSVDEconomyDynamicData::WorkspaceSize(dataFriend.M(),
809 dataFriend.N()));
810 /* check that storage order matches with Allocate() */
811 if (A.StorageOrder() != dataFriend.StorageOrder()) {
812 cmnThrow(std::runtime_error("nmrSVDEconomy: Storage order used for Allocate was different"));
813 }
814 /* check sizes */
815 if ((dataFriend.M() != A.rows()) || (dataFriend.N() != A.cols())) {
816 cmnThrow(std::runtime_error("nmrSVDEconomy: Size used for Allocate was different"));
817 }
818 /* check that the matrices are compact */
819 if (! A.IsCompact()) {
820 cmnThrow(std::runtime_error("nmrSVDEconomy: Requires a compact matrix"));
821 }
822
823 /* Based on storage order, permute U and Vt as well as dimension */
824 CISSTNETLIB_DOUBLE *UPtr, *VtPtr;
825 CISSTNETLIB_INTEGER m_Lda, m_Ldu, m_Ldvt;
826
827 if (A.IsColMajor()) {
828 m_Lda = (1 > dataFriend.M()) ? 1 : dataFriend.M();
829 m_Ldu = dataFriend.M();
830 m_Ldvt = dataFriend.N();
831 UPtr = dataFriend.U().Pointer();
832 VtPtr = dataFriend.Vt().Pointer();
833 } else {
834 m_Lda = (1 > dataFriend.N()) ? 1 : dataFriend.N();
835 m_Ldu = dataFriend.N();
836 m_Ldvt = dataFriend.M();
837 UPtr = dataFriend.Vt().Pointer();
838 VtPtr = dataFriend.U().Pointer();
839 }
840
841 // for versions based on gfortran/lapack, CISSTNETLIB_VERSION is
842 // defined
843#if defined(CISSTNETLIB_VERSION)
844#if defined(CISSTNETLIB_VERSION_MAJOR)
845#if (CISSTNETLIB_VERSION_MAJOR >= 3)
846 cisstNetlib_dgesvd_(&m_Jobu, &m_Jobvt, &m_Ldu, &m_Ldvt,
847 A.Pointer(), &m_Lda, dataFriend.S().Pointer(),
848 UPtr, &m_Ldu,
849 VtPtr, &m_Ldvt,
850 dataFriend.Workspace().Pointer(), &m_Lwork, &Info);
851#endif
852#else // no major version
853 dgesvd_(&m_Jobu, &m_Jobvt, &m_Ldu, &m_Ldvt,
854 A.Pointer(), &m_Lda, dataFriend.S().Pointer(),
855 UPtr, &m_Ldu,
856 VtPtr, &m_Ldvt,
857 dataFriend.Workspace().Pointer(), &m_Lwork, &Info);
858#endif // CISSTNETLIB_VERSION
859#else
860 ftnlen jobu_len = (ftnlen)1, jobvt_len = (ftnlen)1;
861 la_dzlapack_MP_sgesvd_nat(&m_Jobu, &m_Jobvt, &m_Ldu, &m_Ldvt,
862 A.Pointer(), &m_Lda, dataFriend.S().Pointer(),
863 UPtr, &m_Ldu,
864 VtPtr, &m_Ldvt,
865 dataFriend.Workspace().Pointer(), &m_Lwork, &Info,
866 jobu_len, jobvt_len);
867#endif
868 return Info;
869}
870
887template <class _matrixOwnerTypeA, class _matrixOwnerTypeU,
888 class _vectorOwnerTypeS, class _matrixOwnerTypeVt,
889 class _vectorOwnerTypeWorkspace>
900
921template <class _matrixOwnerTypeA, class _matrixOwnerTypeU,
922 class _vectorOwnerTypeS, class _matrixOwnerTypeVt>
932
933
935
936
937#endif
Definition nmrSVDEconomy.h:351
size_type M(void)
Definition nmrSVDEconomy.h:369
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > & S(void)
Definition nmrSVDEconomy.h:357
bool StorageOrder(void)
Definition nmrSVDEconomy.h:375
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > & Workspace(void)
Definition nmrSVDEconomy.h:366
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & Vt(void)
Definition nmrSVDEconomy.h:363
Friend(nmrSVDEconomyDynamicData &inData)
Definition nmrSVDEconomy.h:355
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & U(void)
Definition nmrSVDEconomy.h:360
size_type N(void)
Definition nmrSVDEconomy.h:372
Data for SVD problem (Dynamic).
Definition nmrSVDEconomy.h:104
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > WorkspaceReference
Definition nmrSVDEconomy.h:136
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt)
Definition nmrSVDEconomy.h:495
void SetRefOutput(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt) CISST_THROW(std
Definition nmrSVDEconomy.h:604
vctFixedSizeVector< size_type, 2 > nsize_type
Definition nmrSVDEconomy.h:116
void SetDimension(size_type m, size_type n, bool storageOrder)
Definition nmrSVDEconomy.h:152
static size_type WorkspaceSize(size_type m, size_type n)
Definition nmrSVDEconomy.h:281
nmrSVDEconomyDynamicData()
Definition nmrSVDEconomy.h:392
void SetRefWorkspace(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace)
Definition nmrSVDEconomy.h:531
nmrSVDEconomyDynamicData(size_type m, size_type n, bool storageOrder)
Definition nmrSVDEconomy.h:412
static size_type WorkspaceSize(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &inA)
Definition nmrSVDEconomy.h:296
static nsize_type MatrixSSize(const vctDynamicConstMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A)
Definition nmrSVDEconomy.h:311
void Allocate(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A)
Definition nmrSVDEconomy.h:514
vctDynamicVectorRef< CISSTNETLIB_DOUBLE > SReference
Definition nmrSVDEconomy.h:135
void AllocateOutputWorkspace(bool allocateOutput, bool allocateWorkspace)
Definition nmrSVDEconomy.h:178
const vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & Vt(void) const
Definition nmrSVDEconomy.h:635
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace)
Definition nmrSVDEconomy.h:474
vctDynamicVector< CISSTNETLIB_DOUBLE > WorkspaceMemory
Definition nmrSVDEconomy.h:120
size_type MMember
Definition nmrSVDEconomy.h:143
static vctDynamicMatrixBase< _matrixOwnerTypeS, CISSTNETLIB_DOUBLE > & UpdateMatrixS(const vctDynamicConstMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, const vctDynamicConstVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &vectorS, vctDynamicMatrixBase< _matrixOwnerTypeS, CISSTNETLIB_DOUBLE > &matrixS) CISST_THROW(std
Definition nmrSVDEconomy.h:329
void SetRef(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace) CISST_THROW(std
Definition nmrSVDEconomy.h:576
const vctDynamicVectorRef< CISSTNETLIB_DOUBLE > & S(void) const
Definition nmrSVDEconomy.h:622
void ThrowUnlessOutputSizeIsCorrect(vctDynamicMatrixBase< _matrixOwnerTypeU, CISSTNETLIB_DOUBLE > &inU, vctDynamicVectorBase< _vectorOwnerTypeS, CISSTNETLIB_DOUBLE > &inS, vctDynamicMatrixBase< _matrixOwnerTypeVt, CISSTNETLIB_DOUBLE > &inVt) const CISST_THROW(std
Definition nmrSVDEconomy.h:218
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > UReference
Definition nmrSVDEconomy.h:133
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A)
Definition nmrSVDEconomy.h:430
void Allocate(size_type m, size_type n, bool storageOrder)
Definition nmrSVDEconomy.h:554
void ThrowUnlessWorkspaceSizeIsCorrect(vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace) const CISST_THROW(std
Definition nmrSVDEconomy.h:261
vctDynamicVector< CISSTNETLIB_DOUBLE > OutputMemory
Definition nmrSVDEconomy.h:127
vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > VtReference
Definition nmrSVDEconomy.h:134
size_type NMember
Definition nmrSVDEconomy.h:144
const vctDynamicMatrixRef< CISSTNETLIB_DOUBLE > & U(void) const
Definition nmrSVDEconomy.h:629
unsigned int size_type
Definition nmrSVDEconomy.h:112
nmrSVDEconomyDynamicData(vctDynamicMatrixBase< _matrixOwnerTypeA, CISSTNETLIB_DOUBLE > &A, vctDynamicVectorBase< _vectorOwnerTypeWorkspace, CISSTNETLIB_DOUBLE > &inWorkspace)
Definition nmrSVDEconomy.h:450
bool StorageOrderMember
Definition nmrSVDEconomy.h:145
Definition vctForwardDeclarations.h:145
Definition vctForwardDeclarations.h:119
Definition vctDynamicMatrixBase.h:43
pointer Pointer(size_type rowIndex, size_type colIndex)
Definition vctDynamicMatrixBase.h:143
Dynamic matrix referencing existing memory.
Definition vctDynamicMatrixRef.h:75
void SetRef(size_type rows, size_type cols, stride_type rowStride, stride_type colStride, pointer dataPointer)
Definition vctDynamicMatrixRef.h:217
Definition vctDynamicVectorBase.h:62
pointer Pointer(index_type index=0)
Definition vctDynamicVectorBase.h:155
Definition vctForwardDeclarations.h:131
Dynamic vector referencing existing memory.
Definition vctDynamicVectorRef.h:78
void SetRef(size_type size, pointer data, stride_type stride=1)
Definition vctDynamicVectorRef.h:156
Implementation of a fixed-size vector using template metaprogramming.
Definition vctFixedSizeVector.h:54
#define CISST_THROW(exceptionParameter)
Somewhat portable compilation warning message. This works with very recent versions of gcc (4....
Definition cmnPortability.h:559
Declaration of the template function cmnThrow.
void cmnThrow(const _exceptionType &except, cmnLogLevel lod=CMN_LOG_LEVEL_INIT_ERROR)
Definition cmnThrow.h:76
Rules of exporting.
CISSTNETLIB_INTEGER nmrSVDEconomy(vctDynamicMatrixBase< _matrixOwnerType, CISSTNETLIB_DOUBLE > &A, nmrSVDEconomyDynamicData &data) CISST_THROW(std
Definition nmrSVDEconomy.h:800
Declaration of vctDynamicMatrix.
Declaration of vctFixedSizeMatrix.
const bool VCT_COL_MAJOR
Definition vctForwardDeclarations.h:44