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 <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 (GESDD)
69 //
70 //=================================================================================================
71 
72 //*************************************************************************************************
75 template< typename MT, bool SO, typename VT, bool TF >
76 inline void gesdd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s );
77 
78 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
79 inline void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
80  DenseVector<VT,TF>& s, char jobz );
81 
82 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
83 inline void gesdd( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
84  DenseMatrix<MT2,SO>& V, char jobz );
85 
86 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
87 inline void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
88  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz );
90 //*************************************************************************************************
91 
92 
93 //*************************************************************************************************
110 template< typename MT // Type of the matrix A
111  , bool SO // Storage order of the matrix A
112  , typename VT // Type of the vector s
113  , bool TF > // Transpose flag of the vector s
114 inline DisableIf_< IsComplex< ElementType_<MT> > >
115  gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
116 {
117  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
118 
119  using ET = ElementType_<MT>;
120 
121  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
122  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
123  int lda ( numeric_cast<int>( (~A).spacing() ) );
124  int info( 0 );
125 
126  const int minimum( min( m, n ) );
127  const int maximum( max( m, n ) );
128 
129  int lwork( 3*minimum + max( maximum, 7*minimum ) + 2 );
130  const std::unique_ptr<ET[]> work( new ET[lwork] );
131  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
132 
133  gesdd( 'N', m, n, (~A).data(), lda, (~s).data(),
134  nullptr, 1, nullptr, 1, work.get(), lwork, iwork.get(), &info );
135 
136  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
137 
138  if( info > 0 ) {
139  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
140  }
141 }
143 //*************************************************************************************************
144 
145 
146 //*************************************************************************************************
163 template< typename MT // Type of the matrix A
164  , bool SO // Storage order of the matrix A
165  , typename VT // Type of the vector s
166  , bool TF > // Transpose flag of the vector s
167 inline EnableIf_< IsComplex< ElementType_<MT> > >
168  gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
169 {
170  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
171 
172  using CT = ElementType_<MT>;
173  using BT = UnderlyingElement_<CT>;
174 
175  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
176  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
177  int lda ( numeric_cast<int>( (~A).spacing() ) );
178  int info( 0 );
179 
180  const int minimum( min( m, n ) );
181  const int maximum( max( m, n ) );
182 
183  int lwork( 2*minimum + maximum + 2 );
184  const std::unique_ptr<CT[]> work( new CT[lwork] );
185  const std::unique_ptr<BT[]> rwork( new BT[7*minimum] );
186  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
187 
188  gesdd( 'N', m, n, (~A).data(), lda, (~s).data(),
189  nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), iwork.get(), &info );
190 
191  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
192 
193  if( info > 0 ) {
194  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
195  }
196 }
198 //*************************************************************************************************
199 
200 
201 //*************************************************************************************************
263 template< typename MT // Type of the matrix A
264  , bool SO // Storage order of the matrix A
265  , typename VT // Type of the vector s
266  , bool TF > // Transpose flag of the vector s
268 {
273 
277 
278  const size_t M( (~A).rows() );
279  const size_t N( (~A).columns() );
280  const size_t mindim( min( M, N ) );
281 
282  resize( ~s, mindim, false );
283 
284  if( M == 0UL || N == 0 ) {
285  return;
286  }
287 
288  gesdd_backend( A, s );
289 }
290 //*************************************************************************************************
291 
292 
293 //*************************************************************************************************
312 template< typename MT1 // Type of the matrix A
313  , bool SO // Storage order of all matrices
314  , typename MT2 // Type of the matrix U
315  , typename VT // Type of the vector s
316  , bool TF > // Transpose flag of the vector s
318  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
319  DenseVector<VT,TF>& s, char jobz )
320 {
321  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
322  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~U ), "Invalid matrix dimensions detected" );
323  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimensions detected" );
324  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
325 
326  using ET = ElementType_<MT1>;
327 
328  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
329  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
330  int lda ( numeric_cast<int>( (~A).spacing() ) );
331  int ldu ( numeric_cast<int>( (~U).spacing() ) );
332  int info( 0 );
333 
334  const int minimum( min( m, n ) );
335  const int maximum( max( m, n ) );
336 
337  int lwork( ( jobz == 'O' )
338  ?( 3*minimum + max( maximum, 5*minimum*minimum + 4*maximum ) + 2 )
339  :( 3*minimum + max( maximum, 7*minimum ) + 2 ) );
340  const std::unique_ptr<ET[]> work( new ET[lwork] );
341  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
342 
343  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
344  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
345  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
346  work.get(), lwork, iwork.get(), &info );
347 
348  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
349 
350  if( info > 0 ) {
351  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
352  }
353 }
355 //*************************************************************************************************
356 
357 
358 //*************************************************************************************************
377 template< typename MT1 // Type of the matrix A
378  , bool SO // Storage order of all matrices
379  , typename MT2 // Type of the matrix U
380  , typename VT // Type of the vector s
381  , bool TF > // Transpose flag of the vector s
383  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
384  DenseVector<VT,TF>& s, char jobz )
385 {
386  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
387  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~U ), "Invalid matrix dimensions detected" );
388  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimensions detected" );
389  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
390 
391  using CT = ElementType_<MT1>;
392  using BT = UnderlyingElement_<CT>;
393 
394  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
395  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
396  int lda ( numeric_cast<int>( (~A).spacing() ) );
397  int ldu ( numeric_cast<int>( (~U).spacing() ) );
398  int info( 0 );
399 
400  const int minimum( min( m, n ) );
401  const int maximum( max( m, n ) );
402 
403  int lwork( ( jobz == 'O' )
404  ?( 2*minimum*minimum + 2*minimum + maximum + 2 )
405  :( 2*minimum + maximum + 2 ) );
406  const int lrwork( ( jobz == 'O' )
407  ?( max( 5*minimum*minimum + 5*minimum,
408  2*maximum*minimum + 2*minimum*minimum + minimum ) )
409  :( 7*minimum ) );
410  const std::unique_ptr<CT[]> work( new CT[lwork] );
411  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
412  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
413 
414  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
415  ( SO ? (~U).data() : nullptr ), ( SO ? ldu : 1 ),
416  ( SO ? nullptr : (~U).data() ), ( SO ? 1 : ldu ),
417  work.get(), lwork, rwork.get(), iwork.get(), &info );
418 
419  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
420 
421  if( info > 0 ) {
422  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
423  }
424 }
426 //*************************************************************************************************
427 
428 
429 //*************************************************************************************************
518 template< typename MT1 // Type of the matrix A
519  , bool SO // Storage order of all matrices
520  , typename MT2 // Type of the matrix U
521  , typename VT // Type of the vector s
522  , bool TF > // Transpose flag of the vector s
524  DenseVector<VT,TF>& s, char jobz )
525 {
530 
535 
539 
540  const size_t M( (~A).rows() );
541  const size_t N( (~A).columns() );
542  const size_t mindim( min( M, N ) );
543 
544  if( jobz != 'O' && jobz != 'N' ) {
545  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
546  }
547 
548  if( jobz == 'O' && M >= N ) {
549  BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix provided" );
550  }
551 
552  resize( ~s, mindim, false );
553 
554  if( jobz == 'O' ) {
555  resize( ~U, M, M, false );
556  }
557 
558  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
559  return;
560  }
561 
562  gesdd_backend( ~A, ~U, ~s, jobz );
563 }
564 //*************************************************************************************************
565 
566 
567 //*************************************************************************************************
586 template< typename MT1 // Type of the matrix A
587  , bool SO // Storage order of all matrices
588  , typename VT // Type of the vector s
589  , bool TF // Transpose flag of the vector s
590  , typename MT2 > // Type of the matrix V
592  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
593  DenseMatrix<MT2,SO>& V, char jobz )
594 {
595  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
596  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~V ), "Invalid matrix dimensions detected" );
597  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).rows() == (~A).columns(), "Invalid matrix dimensions detected" );
598  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
599 
600  using ET = ElementType_<MT1>;
601 
602  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
603  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
604  int lda ( numeric_cast<int>( (~A).spacing() ) );
605  int ldv ( numeric_cast<int>( (~V).spacing() ) );
606  int info( 0 );
607 
608  const int minimum( min( m, n ) );
609  const int maximum( max( m, n ) );
610 
611  int lwork( ( jobz == 'O' )
612  ?( 3*minimum + max( maximum, 5*minimum*minimum + 4*maximum + 2 ) )
613  :( 3*minimum + max( maximum, 7*minimum ) + 2 ) );
614  const std::unique_ptr<ET[]> work( new ET[lwork] );
615  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
616 
617  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
618  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
619  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
620  work.get(), lwork, iwork.get(), &info );
621 
622  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
623 
624  if( info > 0 ) {
625  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
626  }
627 }
629 //*************************************************************************************************
630 
631 
632 //*************************************************************************************************
651 template< typename MT1 // Type of the matrix A
652  , bool SO // Storage order of all matrices
653  , typename VT // Type of the vector s
654  , bool TF // Transpose flag of the vector s
655  , typename MT2 > // Type of the matrix V
657  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
658  DenseMatrix<MT2,SO>& V, char jobz )
659 {
660  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
661  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~V ), "Invalid matrix dimensions detected" );
662  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).rows() == (~A).columns(), "Invalid matrix dimensions detected" );
663  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
664 
665  using CT = ElementType_<MT1>;
666  using BT = UnderlyingElement_<CT>;
667 
668  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
669  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
670  int lda ( numeric_cast<int>( (~A).spacing() ) );
671  int ldv ( numeric_cast<int>( (~V).spacing() ) );
672  int info( 0 );
673 
674  const int minimum( min( m, n ) );
675  const int maximum( max( m, n ) );
676 
677  int lwork( ( jobz == 'O' )
678  ?( 2*minimum*minimum + 2*minimum + maximum + 2 )
679  :( 2*minimum + maximum + 2 ) );
680  const int lrwork( ( jobz == 'O' )
681  ?( max( 5*minimum*minimum + 5*minimum,
682  2*maximum*minimum + 2*minimum*minimum + minimum ) )
683  :( 7*minimum ) );
684  const std::unique_ptr<CT[]> work( new CT[lwork] );
685  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
686  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
687 
688  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
689  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
690  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
691  work.get(), lwork, rwork.get(), iwork.get(), &info );
692 
693  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
694 
695  if( info > 0 ) {
696  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
697  }
698 }
700 //*************************************************************************************************
701 
702 
703 //*************************************************************************************************
783 template< typename MT1 // Type of the matrix A
784  , bool SO // Storage order of all matrices
785  , typename MT2 // Type of the matrix U
786  , typename VT // Type of the vector s
787  , bool TF > // Transpose flag of the vector s
789  DenseMatrix<MT2,SO>& V, char jobz )
790 {
795 
800 
804 
805  const size_t M( (~A).rows() );
806  const size_t N( (~A).columns() );
807  const size_t mindim( min( M, N ) );
808 
809  if( jobz != 'O' && jobz != 'N' ) {
810  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
811  }
812 
813  if( jobz == 'O' && M < N ) {
814  BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix provided" );
815  }
816 
817  resize( ~s, mindim, false );
818 
819  if( jobz == 'O' ) {
820  resize( ~V, N, N, false );
821  }
822 
823  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
824  return;
825  }
826 
827  gesdd_backend( ~A, ~s, ~V, jobz );
828 }
829 //*************************************************************************************************
830 
831 
832 //*************************************************************************************************
852 template< typename MT1 // Type of the matrix A
853  , bool SO // Storage order of all matrices
854  , typename MT2 // Type of the matrix U
855  , typename VT // Type of the vector s
856  , bool TF // Transpose flag of the vector s
857  , typename MT3 > // Type of the matrix V
859  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
860  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
861 {
862  BLAZE_INTERNAL_ASSERT( jobz == 'A' || jobz == 'S' || jobz == 'N', "Invalid jobz flag detected" );
863  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
864  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
865  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
866  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
867  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
868  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
869  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
870 
871  using ET = ElementType_<MT1>;
872 
873  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
874  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
875  int lda ( numeric_cast<int>( (~A).spacing() ) );
876  int ldu ( numeric_cast<int>( (~U).spacing() ) );
877  int ldv ( numeric_cast<int>( (~V).spacing() ) );
878  int info( 0 );
879 
880  const int minimum( min( m, n ) );
881  const int maximum( max( m, n ) );
882 
883  int lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
884  const std::unique_ptr<ET[]> work( new ET[lwork] );
885  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
886 
887  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
888  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
889  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
890  work.get(), lwork, iwork.get(), &info );
891 
892  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
893 
894  if( info > 0 ) {
895  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
896  }
897 }
899 //*************************************************************************************************
900 
901 
902 //*************************************************************************************************
922 template< typename MT1 // Type of the matrix A
923  , bool SO // Storage order of all matrices
924  , typename MT2 // Type of the matrix U
925  , typename VT // Type of the vector s
926  , bool TF // Transpose flag of the vector s
927  , typename MT3 > // Type of the matrix V
929  gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
930  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
931 {
932  BLAZE_INTERNAL_ASSERT( jobz == 'A' || jobz == 'S' || jobz == 'N', "Invalid jobz flag detected" );
933  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
934  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
935  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
936  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
937  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
938  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
939  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
940 
941  using CT = ElementType_<MT1>;
942  using BT = UnderlyingElement_<CT>;
943 
944  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
945  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
946  int lda ( numeric_cast<int>( (~A).spacing() ) );
947  int ldu ( numeric_cast<int>( (~U).spacing() ) );
948  int ldv ( numeric_cast<int>( (~V).spacing() ) );
949  int info( 0 );
950 
951  const int minimum( min( m, n ) );
952  const int maximum( max( m, n ) );
953 
954  int lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
955  const int lrwork( max( 5*minimum*minimum + 5*minimum,
956  2*maximum*minimum + 2*minimum*minimum + minimum ) );
957  const std::unique_ptr<CT[]> work( new CT[lwork] );
958  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
959  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
960 
961  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
962  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
963  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
964  work.get(), lwork, rwork.get(), iwork.get(), &info );
965 
966  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
967 
968  if( info > 0 ) {
969  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
970  }
971 }
973 //*************************************************************************************************
974 
975 
976 //*************************************************************************************************
1078 template< typename MT1 // Type of the matrix A
1079  , bool SO // Storage order of all matrices
1080  , typename MT2 // Type of the matrix U
1081  , typename VT // Type of the vector s
1082  , bool TF // Transpose flag of the vector s
1083  , typename MT3 > // Type of the matrix V
1085  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
1086 {
1091 
1096 
1100 
1105 
1106  const size_t M( (~A).rows() );
1107  const size_t N( (~A).columns() );
1108  const size_t mindim( min( M, N ) );
1109 
1110  if( jobz != 'A' && jobz != 'S' && jobz != 'N' ) {
1111  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
1112  }
1113 
1114  resize( ~s, mindim, false );
1115 
1116  if( jobz != 'N' ) {
1117  resize( ~U, M, ( jobz == 'A' ? M : mindim ), false );
1118  resize( ~V, ( jobz == 'A' ? N : mindim ), N, false );
1119  }
1120 
1121  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
1122  return;
1123  }
1124 
1125  gesdd_backend( ~A, ~U, ~s, ~V, jobz );
1126 }
1127 //*************************************************************************************************
1128 
1129 } // namespace blaze
1130 
1131 #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.
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
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:1903
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:1950
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:80
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:252
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
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:76
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:506
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:165
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:714
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:490
BLAZE_ALWAYS_INLINE MT::ElementType * data(DenseMatrix< MT, SO > &dm) noexcept
Low-level data access to the dense matrix elements.
Definition: DenseMatrix.h:169
#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:908
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