gesvd.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_LAPACK_GESVD_H_
36 #define _BLAZE_MATH_LAPACK_GESVD_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <memory>
44 #include <blaze/math/Aliases.h>
49 #include <blaze/math/Exception.h>
57 #include <blaze/util/Assert.h>
58 #include <blaze/util/DisableIf.h>
59 #include <blaze/util/EnableIf.h>
60 #include <blaze/util/NumericCast.h>
62 
63 
64 namespace blaze {
65 
66 //=================================================================================================
67 //
68 // LAPACK SVD FUNCTIONS (GESVD)
69 //
70 //=================================================================================================
71 
72 //*************************************************************************************************
75 template< typename MT, bool SO, typename VT, bool TF >
76 inline void gesvd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv );
77 
78 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
79 inline void gesvd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
80  DenseVector<VT,TF>& s, char jobu, char jobv );
81 
82 template< typename MT1, bool SO, typename VT, bool TF, typename MT2 >
83 inline void gesvd( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
84  DenseMatrix<MT2,SO>& V, char jobu, char jobv );
85 
86 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
87 inline void gesvd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
88  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv );
90 //*************************************************************************************************
91 
92 
93 //*************************************************************************************************
112 template< typename MT // Type of the matrix A
113  , bool SO // Storage order of the matrix A
114  , typename VT // Type of the vector s
115  , bool TF > // Transpose flag of the vector s
116 inline DisableIf_< IsComplex< ElementType_<MT> > >
117  gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
118 {
119  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
120  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
121  BLAZE_INTERNAL_ASSERT( jobu != 'O' || jobv != 'O', "Invalid combination of jobu and jobv detected" );
122  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
123 
124  using ET = ElementType_<MT>;
125 
126  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
127  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
128  int lda ( numeric_cast<int>( (~A).spacing() ) );
129  int info( 0 );
130 
131  const int minimum( min( m, n ) );
132  const int maximum( max( m, n ) );
133 
134  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
135  const std::unique_ptr<ET[]> work( new ET[lwork] );
136 
137  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ), m, n, (~A).data(), lda,
138  (~s).data(), nullptr, 1, nullptr, 1, work.get(), lwork, &info );
139 
140  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
141 
142  if( info > 0 ) {
143  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
144  }
145 }
147 //*************************************************************************************************
148 
149 
150 //*************************************************************************************************
169 template< typename MT // Type of the matrix A
170  , bool SO // Storage order of the matrix A
171  , typename VT // Type of the vector s
172  , bool TF > // Transpose flag of the vector s
173 inline EnableIf_< IsComplex< ElementType_<MT> > >
174  gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
175 {
176  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
177  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
178  BLAZE_INTERNAL_ASSERT( jobu != 'O' || jobv != 'O', "Invalid combination of jobu and jobv detected" );
179  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
180 
181  using CT = ElementType_<MT>;
182  using BT = UnderlyingElement_<CT>;
183 
184  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
185  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
186  int lda ( numeric_cast<int>( (~A).spacing() ) );
187  int info( 0 );
188 
189  const int minimum( min( m, n ) );
190  const int maximum( max( m, n ) );
191 
192  int lwork( 2*minimum + maximum + 2 );
193  const std::unique_ptr<CT[]> work ( new CT[lwork] );
194  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
195 
196  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ), m, n, (~A).data(), lda,
197  (~s).data(), nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), &info );
198 
199  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
200 
201  if( info > 0 ) {
202  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
203  }
204 }
206 //*************************************************************************************************
207 
208 
209 //*************************************************************************************************
293 template< typename MT // Type of the matrix A
294  , bool SO // Storage order of the matrix A
295  , typename VT // Type of the vector s
296  , bool TF > // Transpose flag of the vector s
297 inline void gesvd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
298 {
303 
307 
308  const size_t M( (~A).rows() );
309  const size_t N( (~A).columns() );
310  const size_t mindim( min( M, N ) );
311 
312  if( jobu != 'O' && jobu != 'N' ) {
313  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
314  }
315 
316  if( jobv != 'O' && jobv != 'N' ) {
317  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
318  }
319 
320  if( jobu == 'O' && jobv == 'O' ) {
321  BLAZE_THROW_INVALID_ARGUMENT( "Invalid combination of jobu and jobv provided" );
322  }
323 
324  resize( ~s, mindim, false );
325 
326  if( M == 0UL || N == 0UL ) {
327  return;
328  }
329 
330  gesvd_backend( ~A, ~s, jobu, jobv );
331 }
332 //*************************************************************************************************
333 
334 
335 //*************************************************************************************************
355 template< typename MT1 // Type of the matrix A
356  , bool SO // Storage order of all matrices
357  , typename MT2 // Type of the matrix U
358  , typename VT // Type of the vector s
359  , bool TF > // Transpose flag of the vector s
361  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
362  DenseVector<VT,TF>& s, char jobu, char jobv )
363 {
364  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
365  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
366  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
367  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
368  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
369  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
370 
371  using ET = ElementType_<MT1>;
372 
373  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
374  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
375  int lda ( numeric_cast<int>( (~A).spacing() ) );
376  int ldu ( numeric_cast<int>( (~U).spacing() ) );
377  int info( 0 );
378 
379  const int minimum( min( m, n ) );
380  const int maximum( max( m, n ) );
381 
382  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
383  const std::unique_ptr<ET[]> work( new ET[lwork] );
384 
385  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
386  m, n, (~A).data(), lda, (~s).data(),
387  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
388  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
389  work.get(), lwork, &info );
390 
391  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
392 
393  if( info > 0 ) {
394  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
395  }
396 }
398 //*************************************************************************************************
399 
400 
401 //*************************************************************************************************
421 template< typename MT1 // Type of the matrix A
422  , bool SO // Storage order of all matrices
423  , typename MT2 // Type of the matrix U
424  , typename VT // Type of the vector s
425  , bool TF > // Transpose flag of the vector s
427  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
428  DenseVector<VT,TF>& s, char jobu, char jobv )
429 {
430  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
431  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
432  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
433  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
434  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
435  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
436 
437  using CT = ElementType_<MT1>;
438  using BT = UnderlyingElement_<CT>;
439 
440  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
441  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
442  int lda ( numeric_cast<int>( (~A).spacing() ) );
443  int ldu ( numeric_cast<int>( (~U).spacing() ) );
444  int info( 0 );
445 
446  const int minimum( min( m, n ) );
447  const int maximum( max( m, n ) );
448 
449  int lwork( 2*minimum + maximum + 2 );
450  const std::unique_ptr<CT[]> work ( new CT[lwork] );
451  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
452 
453  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
454  m, n, (~A).data(), lda, (~s).data(),
455  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
456  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
457  work.get(), lwork, rwork.get(), &info );
458 
459  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
460 
461  if( info > 0 ) {
462  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
463  }
464 }
466 //*************************************************************************************************
467 
468 
469 //*************************************************************************************************
570 template< typename MT1 // Type of the matrix A
571  , bool SO // Storage order of all matrices
572  , typename MT2 // Type of the matrix U
573  , typename VT // Type of the vector s
574  , bool TF > // Transpose flag of the vector s
576  DenseVector<VT,TF>& s, char jobu, char jobv )
577 {
582 
587 
591 
592  const size_t M( (~A).rows() );
593  const size_t N( (~A).columns() );
594  const size_t mindim( min( M, N ) );
595 
596  if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
597  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
598  }
599 
600  if( jobv != 'O' && jobv != 'N' ) {
601  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
602  }
603 
604  resize( ~s, mindim, false );
605 
606  if( jobu != 'N' ) {
607  resize( ~U, M, ( jobu == 'A' ? M : mindim ), false );
608  }
609 
610  if( M == 0UL || N == 0UL ) {
611  return;
612  }
613 
614  gesvd_backend( ~A, ~U, ~s, jobu, jobv );
615 }
616 //*************************************************************************************************
617 
618 
619 //*************************************************************************************************
639 template< typename MT1 // Type of the matrix A
640  , bool SO // Storage order of all matrices
641  , typename VT // Type of the vector s
642  , bool TF // Transpose flag of the vector s
643  , typename MT2 > // Type of the matrix V
645  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
646  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
647 {
648  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
649  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
650  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
651  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
652  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
653  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
654 
655  using ET = ElementType_<MT1>;
656 
657  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
658  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
659  int lda ( numeric_cast<int>( (~A).spacing() ) );
660  int ldv ( numeric_cast<int>( (~V).spacing() ) );
661  int info( 0 );
662 
663  const int minimum( min( m, n ) );
664  const int maximum( max( m, n ) );
665 
666  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
667  const std::unique_ptr<ET[]> work( new ET[lwork] );
668 
669  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
670  m, n, (~A).data(), lda, (~s).data(),
671  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
672  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
673  work.get(), lwork, &info );
674 
675  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
676 
677  if( info > 0 ) {
678  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
679  }
680 }
682 //*************************************************************************************************
683 
684 
685 //*************************************************************************************************
705 template< typename MT1 // Type of the matrix A
706  , bool SO // Storage order of all matrices
707  , typename VT // Type of the vector s
708  , bool TF // Transpose flag of the vector s
709  , typename MT2 > // Type of the matrix V
711  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
712  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
713 {
714  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
715  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
716  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
717  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
718  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
719  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
720 
721  using CT = ElementType_<MT1>;
722  using BT = UnderlyingElement_<CT>;
723 
724  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
725  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
726  int lda ( numeric_cast<int>( (~A).spacing() ) );
727  int ldv ( numeric_cast<int>( (~V).spacing() ) );
728  int info( 0 );
729 
730  const int minimum( min( m, n ) );
731  const int maximum( max( m, n ) );
732 
733  int lwork( 2*minimum + maximum + 2 );
734  const std::unique_ptr<CT[]> work ( new CT[lwork] );
735  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
736 
737  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
738  m, n, (~A).data(), lda, (~s).data(),
739  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
740  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
741  work.get(), lwork, rwork.get(), &info );
742 
743  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
744 
745  if( info > 0 ) {
746  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
747  }
748 }
750 //*************************************************************************************************
751 
752 
753 //*************************************************************************************************
854 template< typename MT1 // Type of the matrix A
855  , bool SO // Storage order of all matrices
856  , typename VT // Type of the vector s
857  , bool TF // Transpose flag of the vector s
858  , typename MT2 > // Type of the matrix V
860  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
861 {
866 
870 
875 
876  const size_t M( (~A).rows() );
877  const size_t N( (~A).columns() );
878  const size_t mindim( min( M, N ) );
879 
880  if( jobu != 'O' && jobu != 'N' ) {
881  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
882  }
883 
884  if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
885  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
886  }
887 
888  resize( ~s, mindim, false );
889 
890  if( jobv != 'N' ) {
891  resize( ~V, ( jobv == 'A' ? N : mindim ), N, false );
892  }
893 
894  if( M == 0UL || N == 0UL ) {
895  return;
896  }
897 
898  gesvd_backend( ~A, ~s, ~V, jobu, jobv );
899 }
900 //*************************************************************************************************
901 
902 
903 //*************************************************************************************************
924 template< typename MT1 // Type of the matrix A
925  , bool SO // Storage order of all matrices
926  , typename MT2 // Type of the matrix U
927  , typename VT // Type of the vector s
928  , bool TF // Transpose flag of the vector s
929  , typename MT3 > // Type of the matrix V
931  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
932  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
933 {
934  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
935  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
936  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
937  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
938  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
939  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
940  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
941  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
942  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
943 
944  using ET = ElementType_<MT1>;
945 
946  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
947  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
948  int lda ( numeric_cast<int>( (~A).spacing() ) );
949  int ldu ( numeric_cast<int>( (~U).spacing() ) );
950  int ldv ( numeric_cast<int>( (~V).spacing() ) );
951  int info( 0 );
952 
953  const int minimum( min( m, n ) );
954  const int maximum( max( m, n ) );
955 
956  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
957  const std::unique_ptr<ET[]> work( new ET[lwork] );
958 
959  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
960  m, n, (~A).data(), lda, (~s).data(),
961  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
962  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
963  work.get(), lwork, &info );
964 
965  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
966 
967  if( info > 0 ) {
968  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
969  }
970 }
972 //*************************************************************************************************
973 
974 
975 //*************************************************************************************************
996 template< typename MT1 // Type of the matrix A
997  , bool SO // Storage order of all matrices
998  , typename MT2 // Type of the matrix U
999  , typename VT // Type of the vector s
1000  , bool TF // Transpose flag of the vector s
1001  , typename MT3 > // Type of the matrix V
1003  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
1004  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1005 {
1006  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
1007  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
1008  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
1009  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
1010  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
1011  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1012  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
1013  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
1014  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1015 
1016  using CT = ElementType_<MT1>;
1017  using BT = UnderlyingElement_<CT>;
1018 
1019  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
1020  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
1021  int lda ( numeric_cast<int>( (~A).spacing() ) );
1022  int ldu ( numeric_cast<int>( (~U).spacing() ) );
1023  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1024  int info( 0 );
1025 
1026  const int minimum( min( m, n ) );
1027  const int maximum( max( m, n ) );
1028 
1029  int lwork( 2*minimum + maximum + 2 );
1030  const std::unique_ptr<CT[]> work ( new CT[lwork] );
1031  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
1032 
1033  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
1034  m, n, (~A).data(), lda, (~s).data(),
1035  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
1036  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
1037  work.get(), lwork, rwork.get(), &info );
1038 
1039  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1040 
1041  if( info > 0 ) {
1042  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1043  }
1044 }
1046 //*************************************************************************************************
1047 
1048 
1049 //*************************************************************************************************
1157 template< typename MT1 // Type of the matrix A
1158  , bool SO // Storage order of all matrices
1159  , typename MT2 // Type of the matrix U
1160  , typename VT // Type of the vector s
1161  , bool TF // Transpose flag of the vector s
1162  , typename MT3 > // Type of the matrix V
1164  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1165 {
1170 
1175 
1179 
1184 
1185  const size_t M( (~A).rows() );
1186  const size_t N( (~A).columns() );
1187  const size_t mindim( min( M, N ) );
1188 
1189  if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
1190  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
1191  }
1192 
1193  if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
1194  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
1195  }
1196 
1197  resize( ~s, mindim, false );
1198 
1199  if( jobu != 'N' ) {
1200  resize( ~U, M, ( jobu == 'A' ? M : mindim ), false );
1201  resize( ~V, ( jobv == 'A' ? N : mindim ), N, false );
1202  }
1203 
1204  if( M == 0UL || N == 0UL ) {
1205  return;
1206  }
1207 
1208  gesvd_backend( ~A, ~U, ~s, ~V, jobu, jobv );
1209 }
1210 //*************************************************************************************************
1211 
1212 } // namespace blaze
1213 
1214 #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.
Header file for auxiliary alias declarations.
void gesvd(char jobu, char jobv, int m, int n, float *A, int lda, float *s, float *U, int ldu, float *V, int ldv, float *work, int lwork, int *info)
LAPACK kernel for the singular value decomposition (SVD) of the given dense general single precision ...
Definition: gesvd.h:163
Headerfile for the generic min algorithm.
#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:265
#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
Header file for the CLAPACK gesvd wrapper functions.
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:224
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1762
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:1809
Cast operators for numeric types.
#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:78
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:110
Headerfile for the generic max algorithm.
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:132
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:340
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:548
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:224
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:324
#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.
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:742
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