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 <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 (GESVD)
68 //
69 //=================================================================================================
70 
71 //*************************************************************************************************
74 template< typename MT, bool SO, typename VT, bool TF >
75 inline void gesvd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv );
76 
77 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
78 inline void gesvd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
79  DenseVector<VT,TF>& s, char jobu, char jobv );
80 
81 template< typename MT1, bool SO, typename VT, bool TF, typename MT2 >
82 inline void gesvd( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
83  DenseMatrix<MT2,SO>& V, char jobu, char jobv );
84 
85 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
86 inline void gesvd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
87  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv );
89 //*************************************************************************************************
90 
91 
92 //*************************************************************************************************
111 template< typename MT // Type of the matrix A
112  , bool SO // Storage order of the matrix A
113  , typename VT // Type of the vector s
114  , bool TF > // Transpose flag of the vector s
115 inline DisableIf_< IsComplex< ElementType_<MT> > >
116  gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
117 {
118  using boost::numeric_cast;
119 
120  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
121  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
122  BLAZE_INTERNAL_ASSERT( jobu != 'O' || jobv != 'O', "Invalid combination of jobu and jobv detected" );
123  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
124 
125  using ET = ElementType_<MT>;
126 
127  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
128  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
129  int lda ( numeric_cast<int>( (~A).spacing() ) );
130  int info( 0 );
131 
132  const int minimum( min( m, n ) );
133  const int maximum( max( m, n ) );
134 
135  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
136  const std::unique_ptr<ET[]> work( new ET[lwork] );
137 
138  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ), m, n, (~A).data(), lda,
139  (~s).data(), nullptr, 1, nullptr, 1, work.get(), lwork, &info );
140 
141  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
142 
143  if( info > 0 ) {
144  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
145  }
146 }
148 //*************************************************************************************************
149 
150 
151 //*************************************************************************************************
170 template< typename MT // Type of the matrix A
171  , bool SO // Storage order of the matrix A
172  , typename VT // Type of the vector s
173  , bool TF > // Transpose flag of the vector s
174 inline EnableIf_< IsComplex< ElementType_<MT> > >
175  gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
176 {
177  using boost::numeric_cast;
178 
179  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
180  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
181  BLAZE_INTERNAL_ASSERT( jobu != 'O' || jobv != 'O', "Invalid combination of jobu and jobv detected" );
182  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
183 
184  using CT = ElementType_<MT>;
185  using BT = UnderlyingElement_<CT>;
186 
187  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
188  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
189  int lda ( numeric_cast<int>( (~A).spacing() ) );
190  int info( 0 );
191 
192  const int minimum( min( m, n ) );
193  const int maximum( max( m, n ) );
194 
195  int lwork( 2*minimum + maximum + 2 );
196  const std::unique_ptr<CT[]> work ( new CT[lwork] );
197  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
198 
199  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ), m, n, (~A).data(), lda,
200  (~s).data(), nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), &info );
201 
202  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
203 
204  if( info > 0 ) {
205  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
206  }
207 }
209 //*************************************************************************************************
210 
211 
212 //*************************************************************************************************
296 template< typename MT // Type of the matrix A
297  , bool SO // Storage order of the matrix A
298  , typename VT // Type of the vector s
299  , bool TF > // Transpose flag of the vector s
300 inline void gesvd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
301 {
306 
310 
311  const size_t M( (~A).rows() );
312  const size_t N( (~A).columns() );
313  const size_t mindim( min( M, N ) );
314 
315  if( jobu != 'O' && jobu != 'N' ) {
316  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
317  }
318 
319  if( jobv != 'O' && jobv != 'N' ) {
320  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
321  }
322 
323  if( jobu == 'O' && jobv == 'O' ) {
324  BLAZE_THROW_INVALID_ARGUMENT( "Invalid combination of jobu and jobv provided" );
325  }
326 
327  resize( ~s, mindim, false );
328 
329  if( M == 0UL || N == 0UL ) {
330  return;
331  }
332 
333  gesvd_backend( ~A, ~s, jobu, jobv );
334 }
335 //*************************************************************************************************
336 
337 
338 //*************************************************************************************************
358 template< typename MT1 // Type of the matrix A
359  , bool SO // Storage order of all matrices
360  , typename MT2 // Type of the matrix U
361  , typename VT // Type of the vector s
362  , bool TF > // Transpose flag of the vector s
364  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
365  DenseVector<VT,TF>& s, char jobu, char jobv )
366 {
367  using boost::numeric_cast;
368 
369  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
370  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
371  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
372  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
373  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
374  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
375 
376  using ET = ElementType_<MT1>;
377 
378  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
379  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
380  int lda ( numeric_cast<int>( (~A).spacing() ) );
381  int ldu ( numeric_cast<int>( (~U).spacing() ) );
382  int info( 0 );
383 
384  const int minimum( min( m, n ) );
385  const int maximum( max( m, n ) );
386 
387  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
388  const std::unique_ptr<ET[]> work( new ET[lwork] );
389 
390  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
391  m, n, (~A).data(), lda, (~s).data(),
392  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
393  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
394  work.get(), lwork, &info );
395 
396  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
397 
398  if( info > 0 ) {
399  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
400  }
401 }
403 //*************************************************************************************************
404 
405 
406 //*************************************************************************************************
426 template< typename MT1 // Type of the matrix A
427  , bool SO // Storage order of all matrices
428  , typename MT2 // Type of the matrix U
429  , typename VT // Type of the vector s
430  , bool TF > // Transpose flag of the vector s
432  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
433  DenseVector<VT,TF>& s, char jobu, char jobv )
434 {
435  using boost::numeric_cast;
436 
437  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
438  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
439  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
440  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
441  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
442  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
443 
444  using CT = ElementType_<MT1>;
445  using BT = UnderlyingElement_<CT>;
446 
447  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
448  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
449  int lda ( numeric_cast<int>( (~A).spacing() ) );
450  int ldu ( numeric_cast<int>( (~U).spacing() ) );
451  int info( 0 );
452 
453  const int minimum( min( m, n ) );
454  const int maximum( max( m, n ) );
455 
456  int lwork( 2*minimum + maximum + 2 );
457  const std::unique_ptr<CT[]> work ( new CT[lwork] );
458  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
459 
460  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
461  m, n, (~A).data(), lda, (~s).data(),
462  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
463  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
464  work.get(), lwork, rwork.get(), &info );
465 
466  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
467 
468  if( info > 0 ) {
469  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
470  }
471 }
473 //*************************************************************************************************
474 
475 
476 //*************************************************************************************************
577 template< typename MT1 // Type of the matrix A
578  , bool SO // Storage order of all matrices
579  , typename MT2 // Type of the matrix U
580  , typename VT // Type of the vector s
581  , bool TF > // Transpose flag of the vector s
583  DenseVector<VT,TF>& s, char jobu, char jobv )
584 {
589 
594 
598 
599  const size_t M( (~A).rows() );
600  const size_t N( (~A).columns() );
601  const size_t mindim( min( M, N ) );
602 
603  if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
604  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
605  }
606 
607  if( jobv != 'O' && jobv != 'N' ) {
608  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
609  }
610 
611  resize( ~s, mindim, false );
612 
613  if( jobu != 'N' ) {
614  resize( ~U, M, ( jobu == 'A' ? M : mindim ), false );
615  }
616 
617  if( M == 0UL || N == 0UL ) {
618  return;
619  }
620 
621  gesvd_backend( ~A, ~U, ~s, jobu, jobv );
622 }
623 //*************************************************************************************************
624 
625 
626 //*************************************************************************************************
646 template< typename MT1 // Type of the matrix A
647  , bool SO // Storage order of all matrices
648  , typename VT // Type of the vector s
649  , bool TF // Transpose flag of the vector s
650  , typename MT2 > // Type of the matrix V
652  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
653  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
654 {
655  using boost::numeric_cast;
656 
657  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
658  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
659  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
660  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
661  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
662  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
663 
664  using ET = ElementType_<MT1>;
665 
666  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
667  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
668  int lda ( numeric_cast<int>( (~A).spacing() ) );
669  int ldv ( numeric_cast<int>( (~V).spacing() ) );
670  int info( 0 );
671 
672  const int minimum( min( m, n ) );
673  const int maximum( max( m, n ) );
674 
675  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
676  const std::unique_ptr<ET[]> work( new ET[lwork] );
677 
678  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
679  m, n, (~A).data(), lda, (~s).data(),
680  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
681  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
682  work.get(), lwork, &info );
683 
684  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
685 
686  if( info > 0 ) {
687  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
688  }
689 }
691 //*************************************************************************************************
692 
693 
694 //*************************************************************************************************
714 template< typename MT1 // Type of the matrix A
715  , bool SO // Storage order of all matrices
716  , typename VT // Type of the vector s
717  , bool TF // Transpose flag of the vector s
718  , typename MT2 > // Type of the matrix V
720  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
721  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
722 {
723  using boost::numeric_cast;
724 
725  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
726  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
727  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
728  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
729  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
730  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
731 
732  using CT = ElementType_<MT1>;
733  using BT = UnderlyingElement_<CT>;
734 
735  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
736  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
737  int lda ( numeric_cast<int>( (~A).spacing() ) );
738  int ldv ( numeric_cast<int>( (~V).spacing() ) );
739  int info( 0 );
740 
741  const int minimum( min( m, n ) );
742  const int maximum( max( m, n ) );
743 
744  int lwork( 2*minimum + maximum + 2 );
745  const std::unique_ptr<CT[]> work ( new CT[lwork] );
746  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
747 
748  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
749  m, n, (~A).data(), lda, (~s).data(),
750  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
751  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
752  work.get(), lwork, rwork.get(), &info );
753 
754  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
755 
756  if( info > 0 ) {
757  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
758  }
759 }
761 //*************************************************************************************************
762 
763 
764 //*************************************************************************************************
865 template< typename MT1 // Type of the matrix A
866  , bool SO // Storage order of all matrices
867  , typename VT // Type of the vector s
868  , bool TF // Transpose flag of the vector s
869  , typename MT2 > // Type of the matrix V
871  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
872 {
877 
881 
886 
887  const size_t M( (~A).rows() );
888  const size_t N( (~A).columns() );
889  const size_t mindim( min( M, N ) );
890 
891  if( jobu != 'O' && jobu != 'N' ) {
892  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
893  }
894 
895  if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
896  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
897  }
898 
899  resize( ~s, mindim, false );
900 
901  if( jobv != 'N' ) {
902  resize( ~V, ( jobv == 'A' ? N : mindim ), N, false );
903  }
904 
905  if( M == 0UL || N == 0UL ) {
906  return;
907  }
908 
909  gesvd_backend( ~A, ~s, ~V, jobu, jobv );
910 }
911 //*************************************************************************************************
912 
913 
914 //*************************************************************************************************
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  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
943  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
944 {
945  using boost::numeric_cast;
946 
947  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
948  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
949  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
950  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
951  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
952  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
953  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
954  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
955  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
956 
957  using ET = ElementType_<MT1>;
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( max( 3*minimum + maximum, 5*minimum ) + 2 );
970  const std::unique_ptr<ET[]> work( new ET[lwork] );
971 
972  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
973  m, n, (~A).data(), lda, (~s).data(),
974  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
975  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
976  work.get(), lwork, &info );
977 
978  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
979 
980  if( info > 0 ) {
981  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
982  }
983 }
985 //*************************************************************************************************
986 
987 
988 //*************************************************************************************************
1009 template< typename MT1 // Type of the matrix A
1010  , bool SO // Storage order of all matrices
1011  , typename MT2 // Type of the matrix U
1012  , typename VT // Type of the vector s
1013  , bool TF // Transpose flag of the vector s
1014  , typename MT3 > // Type of the matrix V
1016  gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
1017  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1018 {
1019  using boost::numeric_cast;
1020 
1021  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
1022  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
1023  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
1024  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
1025  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
1026  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1027  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
1028  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
1029  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1030 
1031  using CT = ElementType_<MT1>;
1032  using BT = UnderlyingElement_<CT>;
1033 
1034  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
1035  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
1036  int lda ( numeric_cast<int>( (~A).spacing() ) );
1037  int ldu ( numeric_cast<int>( (~U).spacing() ) );
1038  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1039  int info( 0 );
1040 
1041  const int minimum( min( m, n ) );
1042  const int maximum( max( m, n ) );
1043 
1044  int lwork( 2*minimum + maximum + 2 );
1045  const std::unique_ptr<CT[]> work ( new CT[lwork] );
1046  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
1047 
1048  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
1049  m, n, (~A).data(), lda, (~s).data(),
1050  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
1051  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
1052  work.get(), lwork, rwork.get(), &info );
1053 
1054  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1055 
1056  if( info > 0 ) {
1057  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1058  }
1059 }
1061 //*************************************************************************************************
1062 
1063 
1064 //*************************************************************************************************
1172 template< typename MT1 // Type of the matrix A
1173  , bool SO // Storage order of all matrices
1174  , typename MT2 // Type of the matrix U
1175  , typename VT // Type of the vector s
1176  , bool TF // Transpose flag of the vector s
1177  , typename MT3 > // Type of the matrix V
1179  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1180 {
1185 
1190 
1194 
1199 
1200  const size_t M( (~A).rows() );
1201  const size_t N( (~A).columns() );
1202  const size_t mindim( min( M, N ) );
1203 
1204  if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
1205  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
1206  }
1207 
1208  if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
1209  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
1210  }
1211 
1212  resize( ~s, mindim, false );
1213 
1214  if( jobu != 'N' ) {
1215  resize( ~U, M, ( jobu == 'A' ? M : mindim ), false );
1216  resize( ~V, ( jobv == 'A' ? N : mindim ), N, false );
1217  }
1218 
1219  if( M == 0UL || N == 0UL ) {
1220  return;
1221  }
1222 
1223  gesvd_backend( ~A, ~U, ~s, ~V, jobu, jobv );
1224 }
1225 //*************************************************************************************************
1226 
1227 } // namespace blaze
1228 
1229 #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.
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:161
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
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: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
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.
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