gesdd.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_LAPACK_GESDD_H_
36 #define _BLAZE_MATH_LAPACK_GESDD_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <memory>
44 #include <boost/cast.hpp>
45 #include <blaze/math/Aliases.h>
50 #include <blaze/math/Exception.h>
53 #include <blaze/math/Functions.h>
57 #include <blaze/util/Assert.h>
58 #include <blaze/util/DisableIf.h>
59 #include <blaze/util/EnableIf.h>
61 
62 
63 namespace blaze {
64 
65 //=================================================================================================
66 //
67 // LAPACK SVD FUNCTIONS (GESDD)
68 //
69 //=================================================================================================
70 
71 //*************************************************************************************************
74 template< typename MT, bool SO, typename VT, bool TF >
75 inline void gesdd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s );
76 
77 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
78 inline void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
79  DenseVector<VT,TF>& s, char jobz );
80 
81 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
82 inline void gesdd( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
83  DenseMatrix<MT2,SO>& V, char jobz );
84 
85 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
86 inline void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
87  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz );
89 //*************************************************************************************************
90 
91 
92 //*************************************************************************************************
109 template< typename MT // Type of the matrix A
110  , bool SO // Storage order of the matrix A
111  , typename VT // Type of the vector s
112  , bool TF > // Transpose flag of the vector s
113 inline DisableIf_< IsComplex< ElementType_<MT> > >
114  gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
115 {
116  using boost::numeric_cast;
117 
118  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
119 
120  using ET = ElementType_<MT>;
121 
122  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
123  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
124  int lda ( numeric_cast<int>( (~A).spacing() ) );
125  int info( 0 );
126 
127  const int minimum( min( m, n ) );
128  const int maximum( max( m, n ) );
129 
130  int lwork( 3*minimum + max( maximum, 7*minimum ) + 2 );
131  const std::unique_ptr<ET[]> work( new ET[lwork] );
132  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
133 
134  gesdd( 'N', m, n, (~A).data(), lda, (~s).data(),
135  nullptr, 1, nullptr, 1, work.get(), lwork, iwork.get(), &info );
136 
137  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
138 
139  if( info > 0 ) {
140  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
141  }
142 }
144 //*************************************************************************************************
145 
146 
147 //*************************************************************************************************
164 template< typename MT // Type of the matrix A
165  , bool SO // Storage order of the matrix A
166  , typename VT // Type of the vector s
167  , bool TF > // Transpose flag of the vector s
168 inline EnableIf_< IsComplex< ElementType_<MT> > >
169  gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
170 {
171  using boost::numeric_cast;
172 
173  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
174 
175  using CT = ElementType_<MT>;
176  using BT = UnderlyingElement_<CT>;
177 
178  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
179  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
180  int lda ( numeric_cast<int>( (~A).spacing() ) );
181  int info( 0 );
182 
183  const int minimum( min( m, n ) );
184  const int maximum( max( m, n ) );
185 
186  int lwork( 2*minimum + maximum + 2 );
187  const std::unique_ptr<CT[]> work( new CT[lwork] );
188  const std::unique_ptr<BT[]> rwork( new BT[7*minimum] );
189  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
190 
191  gesdd( 'N', m, n, (~A).data(), lda, (~s).data(),
192  nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), iwork.get(), &info );
193 
194  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
195 
196  if( info > 0 ) {
197  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
198  }
199 }
201 //*************************************************************************************************
202 
203 
204 //*************************************************************************************************
266 template< typename MT // Type of the matrix A
267  , bool SO // Storage order of the matrix A
268  , typename VT // Type of the vector s
269  , bool TF > // Transpose flag of the vector s
271 {
276 
280 
281  const size_t M( (~A).rows() );
282  const size_t N( (~A).columns() );
283  const size_t mindim( min( M, N ) );
284 
285  resize( ~s, mindim, false );
286 
287  if( M == 0UL || N == 0 ) {
288  return;
289  }
290 
291  gesdd_backend( A, s );
292 }
293 //*************************************************************************************************
294 
295 
296 //*************************************************************************************************
315 template< typename MT1 // Type of the matrix A
316  , bool SO // Storage order of all matrices
317  , typename MT2 // Type of the matrix U
318  , typename VT // Type of the vector s
319  , bool TF > // Transpose flag of the vector s
321  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
322  DenseVector<VT,TF>& s, char jobz )
323 {
324  using boost::numeric_cast;
325 
326  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
327  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~U ), "Invalid matrix dimensions detected" );
328  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimensions detected" );
329  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
330 
331  using ET = ElementType_<MT1>;
332 
333  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
334  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
335  int lda ( numeric_cast<int>( (~A).spacing() ) );
336  int ldu ( numeric_cast<int>( (~U).spacing() ) );
337  int info( 0 );
338 
339  const int minimum( min( m, n ) );
340  const int maximum( max( m, n ) );
341 
342  int lwork( ( jobz == 'O' )
343  ?( 3*minimum + max( maximum, 5*minimum*minimum + 4*maximum ) + 2 )
344  :( 3*minimum + max( maximum, 7*minimum ) + 2 ) );
345  const std::unique_ptr<ET[]> work( new ET[lwork] );
346  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
347 
348  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
349  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
350  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
351  work.get(), lwork, iwork.get(), &info );
352 
353  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
354 
355  if( info > 0 ) {
356  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
357  }
358 }
360 //*************************************************************************************************
361 
362 
363 //*************************************************************************************************
382 template< typename MT1 // Type of the matrix A
383  , bool SO // Storage order of all matrices
384  , typename MT2 // Type of the matrix U
385  , typename VT // Type of the vector s
386  , bool TF > // Transpose flag of the vector s
388  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
389  DenseVector<VT,TF>& s, char jobz )
390 {
391  using boost::numeric_cast;
392 
393  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
394  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~U ), "Invalid matrix dimensions detected" );
395  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimensions detected" );
396  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
397 
398  using CT = ElementType_<MT1>;
399  using BT = UnderlyingElement_<CT>;
400 
401  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
402  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
403  int lda ( numeric_cast<int>( (~A).spacing() ) );
404  int ldu ( numeric_cast<int>( (~U).spacing() ) );
405  int info( 0 );
406 
407  const int minimum( min( m, n ) );
408  const int maximum( max( m, n ) );
409 
410  int lwork( ( jobz == 'O' )
411  ?( 2*minimum*minimum + 2*minimum + maximum + 2 )
412  :( 2*minimum + maximum + 2 ) );
413  const int lrwork( ( jobz == 'O' )
414  ?( max( 5*minimum*minimum + 5*minimum,
415  2*maximum*minimum + 2*minimum*minimum + minimum ) )
416  :( 7*minimum ) );
417  const std::unique_ptr<CT[]> work( new CT[lwork] );
418  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
419  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
420 
421  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
422  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
423  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
424  work.get(), lwork, rwork.get(), iwork.get(), &info );
425 
426  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
427 
428  if( info > 0 ) {
429  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
430  }
431 }
433 //*************************************************************************************************
434 
435 
436 //*************************************************************************************************
525 template< typename MT1 // Type of the matrix A
526  , bool SO // Storage order of all matrices
527  , typename MT2 // Type of the matrix U
528  , typename VT // Type of the vector s
529  , bool TF > // Transpose flag of the vector s
531  DenseVector<VT,TF>& s, char jobz )
532 {
537 
542 
546 
547  const size_t M( (~A).rows() );
548  const size_t N( (~A).columns() );
549  const size_t mindim( min( M, N ) );
550 
551  if( jobz != 'O' && jobz != 'N' ) {
552  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
553  }
554 
555  if( jobz == 'O' && M >= N ) {
556  BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix provided" );
557  }
558 
559  resize( ~s, mindim, false );
560 
561  if( jobz == 'O' ) {
562  resize( ~U, M, M, false );
563  }
564 
565  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
566  return;
567  }
568 
569  gesdd_backend( ~A, ~U, ~s, jobz );
570 }
571 //*************************************************************************************************
572 
573 
574 //*************************************************************************************************
593 template< typename MT1 // Type of the matrix A
594  , bool SO // Storage order of all matrices
595  , typename VT // Type of the vector s
596  , bool TF // Transpose flag of the vector s
597  , typename MT2 > // Type of the matrix V
599  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
600  DenseMatrix<MT2,SO>& V, char jobz )
601 {
602  using boost::numeric_cast;
603 
604  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
605  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~V ), "Invalid matrix dimensions detected" );
606  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).rows() == (~A).columns(), "Invalid matrix dimensions detected" );
607  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
608 
609  using ET = ElementType_<MT1>;
610 
611  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
612  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
613  int lda ( numeric_cast<int>( (~A).spacing() ) );
614  int ldv ( numeric_cast<int>( (~V).spacing() ) );
615  int info( 0 );
616 
617  const int minimum( min( m, n ) );
618  const int maximum( max( m, n ) );
619 
620  int lwork( ( jobz == 'O' )
621  ?( 3*minimum + max( maximum, 5*minimum*minimum + 4*maximum + 2 ) )
622  :( 3*minimum + max( maximum, 7*minimum ) + 2 ) );
623  const std::unique_ptr<ET[]> work( new ET[lwork] );
624  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
625 
626  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
627  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
628  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
629  work.get(), lwork, iwork.get(), &info );
630 
631  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
632 
633  if( info > 0 ) {
634  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
635  }
636 }
638 //*************************************************************************************************
639 
640 
641 //*************************************************************************************************
660 template< typename MT1 // Type of the matrix A
661  , bool SO // Storage order of all matrices
662  , typename VT // Type of the vector s
663  , bool TF // Transpose flag of the vector s
664  , typename MT2 > // Type of the matrix V
666  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
667  DenseMatrix<MT2,SO>& V, char jobz )
668 {
669  using boost::numeric_cast;
670 
671  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
672  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~V ), "Invalid matrix dimensions detected" );
673  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).rows() == (~A).columns(), "Invalid matrix dimensions detected" );
674  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
675 
676  using CT = ElementType_<MT1>;
677  using BT = UnderlyingElement_<CT>;
678 
679  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
680  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
681  int lda ( numeric_cast<int>( (~A).spacing() ) );
682  int ldv ( numeric_cast<int>( (~V).spacing() ) );
683  int info( 0 );
684 
685  const int minimum( min( m, n ) );
686  const int maximum( max( m, n ) );
687 
688  int lwork( ( jobz == 'O' )
689  ?( 2*minimum*minimum + 2*minimum + maximum + 2 )
690  :( 2*minimum + maximum + 2 ) );
691  const int lrwork( ( jobz == 'O' )
692  ?( max( 5*minimum*minimum + 5*minimum,
693  2*maximum*minimum + 2*minimum*minimum + minimum ) )
694  :( 7*minimum ) );
695  const std::unique_ptr<CT[]> work( new CT[lwork] );
696  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
697  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
698 
699  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
700  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
701  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
702  work.get(), lwork, rwork.get(), iwork.get(), &info );
703 
704  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
705 
706  if( info > 0 ) {
707  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
708  }
709 }
711 //*************************************************************************************************
712 
713 
714 //*************************************************************************************************
794 template< typename MT1 // Type of the matrix A
795  , bool SO // Storage order of all matrices
796  , typename MT2 // Type of the matrix U
797  , typename VT // Type of the vector s
798  , bool TF > // Transpose flag of the vector s
800  DenseMatrix<MT2,SO>& V, char jobz )
801 {
806 
811 
815 
816  const size_t M( (~A).rows() );
817  const size_t N( (~A).columns() );
818  const size_t mindim( min( M, N ) );
819 
820  if( jobz != 'O' && jobz != 'N' ) {
821  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
822  }
823 
824  if( jobz == 'O' && M < N ) {
825  BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix provided" );
826  }
827 
828  resize( ~s, mindim, false );
829 
830  if( jobz == 'O' ) {
831  resize( ~V, N, N, false );
832  }
833 
834  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
835  return;
836  }
837 
838  gesdd_backend( ~A, ~s, ~V, jobz );
839 }
840 //*************************************************************************************************
841 
842 
843 //*************************************************************************************************
863 template< typename MT1 // Type of the matrix A
864  , bool SO // Storage order of all matrices
865  , typename MT2 // Type of the matrix U
866  , typename VT // Type of the vector s
867  , bool TF // Transpose flag of the vector s
868  , typename MT3 > // Type of the matrix V
870  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
871  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
872 {
873  using boost::numeric_cast;
874 
875  BLAZE_INTERNAL_ASSERT( jobz == 'A' || jobz == 'S' || jobz == 'N', "Invalid jobz flag detected" );
876  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
877  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
878  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
879  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
880  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
881  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
882  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
883 
884  using ET = ElementType_<MT1>;
885 
886  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
887  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
888  int lda ( numeric_cast<int>( (~A).spacing() ) );
889  int ldu ( numeric_cast<int>( (~U).spacing() ) );
890  int ldv ( numeric_cast<int>( (~V).spacing() ) );
891  int info( 0 );
892 
893  const int minimum( min( m, n ) );
894  const int maximum( max( m, n ) );
895 
896  int lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
897  const std::unique_ptr<ET[]> work( new ET[lwork] );
898  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
899 
900  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
901  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
902  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
903  work.get(), lwork, iwork.get(), &info );
904 
905  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
906 
907  if( info > 0 ) {
908  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
909  }
910 }
912 //*************************************************************************************************
913 
914 
915 //*************************************************************************************************
935 template< typename MT1 // Type of the matrix A
936  , bool SO // Storage order of all matrices
937  , typename MT2 // Type of the matrix U
938  , typename VT // Type of the vector s
939  , bool TF // Transpose flag of the vector s
940  , typename MT3 > // Type of the matrix V
942  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
943  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
944 {
945  using boost::numeric_cast;
946 
947  BLAZE_INTERNAL_ASSERT( jobz == 'A' || jobz == 'S' || jobz == 'N', "Invalid jobz flag detected" );
948  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
949  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
950  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
951  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
952  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
953  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
954  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
955 
956  using CT = ElementType_<MT1>;
957  using BT = UnderlyingElement_<CT>;
958 
959  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
960  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
961  int lda ( numeric_cast<int>( (~A).spacing() ) );
962  int ldu ( numeric_cast<int>( (~U).spacing() ) );
963  int ldv ( numeric_cast<int>( (~V).spacing() ) );
964  int info( 0 );
965 
966  const int minimum( min( m, n ) );
967  const int maximum( max( m, n ) );
968 
969  int lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
970  const int lrwork( max( 5*minimum*minimum + 5*minimum,
971  2*maximum*minimum + 2*minimum*minimum + minimum ) );
972  const std::unique_ptr<CT[]> work( new CT[lwork] );
973  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
974  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
975 
976  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
977  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
978  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
979  work.get(), lwork, rwork.get(), iwork.get(), &info );
980 
981  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
982 
983  if( info > 0 ) {
984  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
985  }
986 }
988 //*************************************************************************************************
989 
990 
991 //*************************************************************************************************
1093 template< typename MT1 // Type of the matrix A
1094  , bool SO // Storage order of all matrices
1095  , typename MT2 // Type of the matrix U
1096  , typename VT // Type of the vector s
1097  , bool TF // Transpose flag of the vector s
1098  , typename MT3 > // Type of the matrix V
1100  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
1101 {
1106 
1111 
1115 
1120 
1121  const size_t M( (~A).rows() );
1122  const size_t N( (~A).columns() );
1123  const size_t mindim( min( M, N ) );
1124 
1125  if( jobz != 'A' && jobz != 'S' && jobz != 'N' ) {
1126  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
1127  }
1128 
1129  resize( ~s, mindim, false );
1130 
1131  if( jobz != 'N' ) {
1132  resize( ~U, M, ( jobz == 'A' ? M : mindim ), false );
1133  resize( ~V, ( jobz == 'A' ? N : mindim ), N, false );
1134  }
1135 
1136  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
1137  return;
1138  }
1139 
1140  gesdd_backend( ~A, ~U, ~s, ~V, jobz );
1141 }
1142 //*************************************************************************************************
1143 
1144 } // namespace blaze
1145 
1146 #endif
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Constraint on the data type.
BLAZE_ALWAYS_INLINE size_t spacing(const DenseMatrix< MT, SO > &dm) noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DenseMatrix.h:102
Header file for auxiliary alias declarations.
Header file for mathematical functions.
#define BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS(T)
Constraint on the data type.In case the given data type T does not provide low-level data access to m...
Definition: MutableDataAccess.h:61
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:261
#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE(T)
Constraint on the data type.In case the given data type T is a computational expression (i...
Definition: Computation.h:81
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:223
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1755
Header file for the DenseVector base class.
Header file for the UnderlyingElement type trait.
Constraint on the data type.
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1802
#define BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE(T)
Constraint on the data type.In case the given data type T is an adaptor type (as for instance LowerMa...
Definition: Adaptor.h:81
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:71
Constraint on the data type.
Header file for the DisableIf class template.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
Header file for the DenseMatrix base class.
typename UnderlyingElement< T >::Type UnderlyingElement_
Auxiliary alias declaration for the UnderlyingElement type trait.The UnderlyingElement_ alias declara...
Definition: UnderlyingElement.h:133
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:70
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:336
void gesdd(char jobz, int m, int n, float *A, int lda, float *s, float *U, int ldu, float *V, int ldv, float *work, int lwork, int *iwork, int *info)
LAPACK kernel for the singular value decomposition (SVD) of the given dense general single precision ...
Definition: gesdd.h:163
Header file for the exception macros of the math module.
BLAZE_ALWAYS_INLINE void resize(Matrix< MT, SO > &matrix, size_t rows, size_t columns, bool preserve=true)
Changing the size of the matrix.
Definition: Matrix.h:544
Constraint on the data type.
Header file for the EnableIf class template.
Header file for run time assertion macros.
#define BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE(T)
Constraint on the data type.In case the given data type T is not a BLAS compatible data type (i...
Definition: BLASCompatible.h:61
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:223
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:320
#define BLAZE_THROW_LAPACK_ERROR(MESSAGE)
Macro for the emission of an exception on detection of a LAPACK error.This macro encapsulates the def...
Definition: Exception.h:146
Header file for the IsComplex type trait.
Header file for the CLAPACK gesdd wrapper functions.
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:677
Header file for the IsResizable type trait.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101