Blaze  3.6
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>
50 #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 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 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 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 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 auto gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
117  -> DisableIf_t< IsComplex_v< ElementType_t<MT> > >
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_t<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 auto gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
174  -> EnableIf_t< IsComplex_v< ElementType_t<MT> > >
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_t<MT>;
182  using BT = UnderlyingElement_t<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 {
304 
309 
310  const size_t M( (~A).rows() );
311  const size_t N( (~A).columns() );
312  const size_t mindim( min( M, N ) );
313 
314  if( jobu != 'O' && jobu != 'N' ) {
315  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
316  }
317 
318  if( jobv != 'O' && jobv != 'N' ) {
319  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
320  }
321 
322  if( jobu == 'O' && jobv == 'O' ) {
323  BLAZE_THROW_INVALID_ARGUMENT( "Invalid combination of jobu and jobv provided" );
324  }
325 
326  resize( ~s, mindim, false );
327 
328  if( M == 0UL || N == 0UL ) {
329  return;
330  }
331 
332  gesvd_backend( ~A, ~s, jobu, jobv );
333 }
334 //*************************************************************************************************
335 
336 
337 //*************************************************************************************************
357 template< typename MT1 // Type of the matrix A
358  , bool SO // Storage order of all matrices
359  , typename MT2 // Type of the matrix U
360  , typename VT // Type of the vector s
361  , bool TF > // Transpose flag of the vector s
362 inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
363  DenseVector<VT,TF>& s, char jobu, char jobv )
364  -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
365 {
366  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
367  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
368  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
369  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
370  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
371  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
372 
373  using ET = ElementType_t<MT1>;
374 
375  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
376  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
377  int lda ( numeric_cast<int>( (~A).spacing() ) );
378  int ldu ( numeric_cast<int>( (~U).spacing() ) );
379  int info( 0 );
380 
381  const int minimum( min( m, n ) );
382  const int maximum( max( m, n ) );
383 
384  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
385  const std::unique_ptr<ET[]> work( new ET[lwork] );
386 
387  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
388  m, n, (~A).data(), lda, (~s).data(),
389  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
390  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
391  work.get(), lwork, &info );
392 
393  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
394 
395  if( info > 0 ) {
396  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
397  }
398 }
400 //*************************************************************************************************
401 
402 
403 //*************************************************************************************************
423 template< typename MT1 // Type of the matrix A
424  , bool SO // Storage order of all matrices
425  , typename MT2 // Type of the matrix U
426  , typename VT // Type of the vector s
427  , bool TF > // Transpose flag of the vector s
428 inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
429  DenseVector<VT,TF>& s, char jobu, char jobv )
430  -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
431 {
432  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
433  BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
434  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
435  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
436  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
437  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
438 
439  using CT = ElementType_t<MT1>;
440  using BT = UnderlyingElement_t<CT>;
441 
442  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
443  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
444  int lda ( numeric_cast<int>( (~A).spacing() ) );
445  int ldu ( numeric_cast<int>( (~U).spacing() ) );
446  int info( 0 );
447 
448  const int minimum( min( m, n ) );
449  const int maximum( max( m, n ) );
450 
451  int lwork( 2*minimum + maximum + 2 );
452  const std::unique_ptr<CT[]> work ( new CT[lwork] );
453  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
454 
455  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
456  m, n, (~A).data(), lda, (~s).data(),
457  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
458  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
459  work.get(), lwork, rwork.get(), &info );
460 
461  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
462 
463  if( info > 0 ) {
464  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
465  }
466 }
468 //*************************************************************************************************
469 
470 
471 //*************************************************************************************************
572 template< typename MT1 // Type of the matrix A
573  , bool SO // Storage order of all matrices
574  , typename MT2 // Type of the matrix U
575  , typename VT // Type of the vector s
576  , bool TF > // Transpose flag of the vector s
578  DenseVector<VT,TF>& s, char jobu, char jobv )
579 {
585 
591 
596 
597  const size_t M( (~A).rows() );
598  const size_t N( (~A).columns() );
599  const size_t mindim( min( M, N ) );
600 
601  if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
602  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
603  }
604 
605  if( jobv != 'O' && jobv != 'N' ) {
606  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
607  }
608 
609  resize( ~s, mindim, false );
610 
611  if( jobu != 'N' ) {
612  resize( ~U, M, ( jobu == 'A' ? M : mindim ), false );
613  }
614 
615  if( M == 0UL || N == 0UL ) {
616  return;
617  }
618 
619  gesvd_backend( ~A, ~U, ~s, jobu, jobv );
620 }
621 //*************************************************************************************************
622 
623 
624 //*************************************************************************************************
644 template< typename MT1 // Type of the matrix A
645  , bool SO // Storage order of all matrices
646  , typename VT // Type of the vector s
647  , bool TF // Transpose flag of the vector s
648  , typename MT2 > // Type of the matrix V
649 inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
650  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
651  -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
652 {
653  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
654  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
655  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
656  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
657  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
658  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
659 
660  using ET = ElementType_t<MT1>;
661 
662  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
663  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
664  int lda ( numeric_cast<int>( (~A).spacing() ) );
665  int ldv ( numeric_cast<int>( (~V).spacing() ) );
666  int info( 0 );
667 
668  const int minimum( min( m, n ) );
669  const int maximum( max( m, n ) );
670 
671  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
672  const std::unique_ptr<ET[]> work( new ET[lwork] );
673 
674  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
675  m, n, (~A).data(), lda, (~s).data(),
676  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
677  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
678  work.get(), lwork, &info );
679 
680  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
681 
682  if( info > 0 ) {
683  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
684  }
685 }
687 //*************************************************************************************************
688 
689 
690 //*************************************************************************************************
710 template< typename MT1 // Type of the matrix A
711  , bool SO // Storage order of all matrices
712  , typename VT // Type of the vector s
713  , bool TF // Transpose flag of the vector s
714  , typename MT2 > // Type of the matrix V
715 inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
716  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
717  -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
718 {
719  BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
720  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
721  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
722  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
723  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
724  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
725 
726  using CT = ElementType_t<MT1>;
727  using BT = UnderlyingElement_t<CT>;
728 
729  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
730  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
731  int lda ( numeric_cast<int>( (~A).spacing() ) );
732  int ldv ( numeric_cast<int>( (~V).spacing() ) );
733  int info( 0 );
734 
735  const int minimum( min( m, n ) );
736  const int maximum( max( m, n ) );
737 
738  int lwork( 2*minimum + maximum + 2 );
739  const std::unique_ptr<CT[]> work ( new CT[lwork] );
740  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
741 
742  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
743  m, n, (~A).data(), lda, (~s).data(),
744  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
745  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
746  work.get(), lwork, rwork.get(), &info );
747 
748  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
749 
750  if( info > 0 ) {
751  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
752  }
753 }
755 //*************************************************************************************************
756 
757 
758 //*************************************************************************************************
859 template< typename MT1 // Type of the matrix A
860  , bool SO // Storage order of all matrices
861  , typename VT // Type of the vector s
862  , bool TF // Transpose flag of the vector s
863  , typename MT2 > // Type of the matrix V
865  DenseMatrix<MT2,SO>& V, char jobu, char jobv )
866 {
872 
877 
883 
884  const size_t M( (~A).rows() );
885  const size_t N( (~A).columns() );
886  const size_t mindim( min( M, N ) );
887 
888  if( jobu != 'O' && jobu != 'N' ) {
889  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
890  }
891 
892  if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
893  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
894  }
895 
896  resize( ~s, mindim, false );
897 
898  if( jobv != 'N' ) {
899  resize( ~V, ( jobv == 'A' ? N : mindim ), N, false );
900  }
901 
902  if( M == 0UL || N == 0UL ) {
903  return;
904  }
905 
906  gesvd_backend( ~A, ~s, ~V, jobu, jobv );
907 }
908 //*************************************************************************************************
909 
910 
911 //*************************************************************************************************
932 template< typename MT1 // Type of the matrix A
933  , bool SO // Storage order of all matrices
934  , typename MT2 // Type of the matrix U
935  , typename VT // Type of the vector s
936  , bool TF // Transpose flag of the vector s
937  , typename MT3 > // Type of the matrix V
938 inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
939  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
940  -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
941 {
942  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
943  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
944  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
945  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
946  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
947  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
948  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
949  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
950  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
951 
952  using ET = ElementType_t<MT1>;
953 
954  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
955  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
956  int lda ( numeric_cast<int>( (~A).spacing() ) );
957  int ldu ( numeric_cast<int>( (~U).spacing() ) );
958  int ldv ( numeric_cast<int>( (~V).spacing() ) );
959  int info( 0 );
960 
961  const int minimum( min( m, n ) );
962  const int maximum( max( m, n ) );
963 
964  int lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
965  const std::unique_ptr<ET[]> work( new ET[lwork] );
966 
967  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
968  m, n, (~A).data(), lda, (~s).data(),
969  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
970  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
971  work.get(), lwork, &info );
972 
973  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
974 
975  if( info > 0 ) {
976  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
977  }
978 }
980 //*************************************************************************************************
981 
982 
983 //*************************************************************************************************
1004 template< typename MT1 // Type of the matrix A
1005  , bool SO // Storage order of all matrices
1006  , typename MT2 // Type of the matrix U
1007  , typename VT // Type of the vector s
1008  , bool TF // Transpose flag of the vector s
1009  , typename MT3 > // Type of the matrix V
1010 inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
1011  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1012  -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
1013 {
1014  BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
1015  BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
1016  BLAZE_INTERNAL_ASSERT( jobu == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
1017  BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
1018  BLAZE_INTERNAL_ASSERT( jobu != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
1019  BLAZE_INTERNAL_ASSERT( jobv == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1020  BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
1021  BLAZE_INTERNAL_ASSERT( jobv != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
1022  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1023 
1024  using CT = ElementType_t<MT1>;
1025  using BT = UnderlyingElement_t<CT>;
1026 
1027  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
1028  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
1029  int lda ( numeric_cast<int>( (~A).spacing() ) );
1030  int ldu ( numeric_cast<int>( (~U).spacing() ) );
1031  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1032  int info( 0 );
1033 
1034  const int minimum( min( m, n ) );
1035  const int maximum( max( m, n ) );
1036 
1037  int lwork( 2*minimum + maximum + 2 );
1038  const std::unique_ptr<CT[]> work ( new CT[lwork] );
1039  const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
1040 
1041  gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
1042  m, n, (~A).data(), lda, (~s).data(),
1043  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
1044  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
1045  work.get(), lwork, rwork.get(), &info );
1046 
1047  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1048 
1049  if( info > 0 ) {
1050  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1051  }
1052 }
1054 //*************************************************************************************************
1055 
1056 
1057 //*************************************************************************************************
1165 template< typename MT1 // Type of the matrix A
1166  , bool SO // Storage order of all matrices
1167  , typename MT2 // Type of the matrix U
1168  , typename VT // Type of the vector s
1169  , bool TF // Transpose flag of the vector s
1170  , typename MT3 > // Type of the matrix V
1172  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1173 {
1179 
1185 
1190 
1196 
1197  const size_t M( (~A).rows() );
1198  const size_t N( (~A).columns() );
1199  const size_t mindim( min( M, N ) );
1200 
1201  if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
1202  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
1203  }
1204 
1205  if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
1206  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
1207  }
1208 
1209  resize( ~s, mindim, false );
1210 
1211  if( jobu != 'N' ) {
1212  resize( ~U, M, ( jobu == 'A' ? M : mindim ), false );
1213  resize( ~V, ( jobv == 'A' ? N : mindim ), N, false );
1214  }
1215 
1216  if( M == 0UL || N == 0UL ) {
1217  return;
1218  }
1219 
1220  gesvd_backend( ~A, ~U, ~s, ~V, jobu, jobv );
1221 }
1222 //*************************************************************************************************
1223 
1224 } // namespace blaze
1225 
1226 #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:172
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
MT::ElementType * data(DenseMatrix< MT, SO > &dm) noexcept
Low-level data access to the dense matrix elements.
Definition: DenseMatrix.h:170
#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.
Header file for the DenseVector base class.
Header file for the UnderlyingElement type trait.
Constraint on the data type.
Constraint on the data type.
Cast operators for numeric types.
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
#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:81
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.The ElementType_t alias declaration provide...
Definition: Aliases.h:170
size_t spacing(const DenseMatrix< MT, SO > &dm) noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DenseMatrix.h:253
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:58
#define BLAZE_CONSTRAINT_MUST_BE_CONTIGUOUS_TYPE(T)
Constraint on the data type.In case the given data type T is not an array-like data type with contigu...
Definition: Contiguous.h:61
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1162
Header file for the DenseMatrix base class.
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:76
Header file for the exception macros of the math module.
decltype(auto) max(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise maximum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1198
void resize(Matrix< MT, SO > &matrix, size_t rows, size_t columns, bool preserve=true)
Changing the size of the matrix.
Definition: Matrix.h:738
Constraint on the data type.
Header file for the EnableIf class template.
Header file for run time assertion macros.
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:530
#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
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
#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.
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:951
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression,...
Definition: Assert.h:101