Blaze  3.6
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>
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 (GESDD)
69 //
70 //=================================================================================================
71 
72 //*************************************************************************************************
75 template< typename MT, bool SO, typename VT, bool TF >
76 void gesdd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s );
77 
78 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
79 void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s, char jobz );
80 
81 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
82 void gesdd( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V, char jobz );
83 
84 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
85 void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
86  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz );
88 //*************************************************************************************************
89 
90 
91 //*************************************************************************************************
108 template< typename MT // Type of the matrix A
109  , bool SO // Storage order of the matrix A
110  , typename VT // Type of the vector s
111  , bool TF > // Transpose flag of the vector s
112 inline auto gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
113  -> DisableIf_t< IsComplex_v< ElementType_t<MT> > >
114 {
115  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
116 
117  using ET = ElementType_t<MT>;
118 
119  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
120  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
121  int lda ( numeric_cast<int>( (~A).spacing() ) );
122  int info( 0 );
123 
124  const int minimum( min( m, n ) );
125  const int maximum( max( m, n ) );
126 
127  int lwork( 3*minimum + max( maximum, 7*minimum ) + 2 );
128  const std::unique_ptr<ET[]> work( new ET[lwork] );
129  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
130 
131  gesdd( 'N', m, n, (~A).data(), lda, (~s).data(),
132  nullptr, 1, nullptr, 1, work.get(), lwork, iwork.get(), &info );
133 
134  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
135 
136  if( info > 0 ) {
137  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
138  }
139 }
141 //*************************************************************************************************
142 
143 
144 //*************************************************************************************************
161 template< typename MT // Type of the matrix A
162  , bool SO // Storage order of the matrix A
163  , typename VT // Type of the vector s
164  , bool TF > // Transpose flag of the vector s
165 inline auto gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
166  -> EnableIf_t< IsComplex_v< ElementType_t<MT> > >
167 {
168  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
169 
170  using CT = ElementType_t<MT>;
171  using BT = UnderlyingElement_t<CT>;
172 
173  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
174  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
175  int lda ( numeric_cast<int>( (~A).spacing() ) );
176  int info( 0 );
177 
178  const int minimum( min( m, n ) );
179  const int maximum( max( m, n ) );
180 
181  int lwork( 2*minimum + maximum + 2 );
182  const std::unique_ptr<CT[]> work( new CT[lwork] );
183  const std::unique_ptr<BT[]> rwork( new BT[7*minimum] );
184  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
185 
186  gesdd( 'N', m, n, (~A).data(), lda, (~s).data(),
187  nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), iwork.get(), &info );
188 
189  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
190 
191  if( info > 0 ) {
192  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
193  }
194 }
196 //*************************************************************************************************
197 
198 
199 //*************************************************************************************************
261 template< typename MT // Type of the matrix A
262  , bool SO // Storage order of the matrix A
263  , typename VT // Type of the vector s
264  , bool TF > // Transpose flag of the vector s
266 {
272 
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
317 inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
318  DenseVector<VT,TF>& s, char jobz )
319  -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
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_t<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
382 inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
383  DenseVector<VT,TF>& s, char jobz )
384  -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
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_t<MT1>;
392  using BT = UnderlyingElement_t<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 {
531 
537 
542 
543  const size_t M( (~A).rows() );
544  const size_t N( (~A).columns() );
545  const size_t mindim( min( M, N ) );
546 
547  if( jobz != 'O' && jobz != 'N' ) {
548  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
549  }
550 
551  if( jobz == 'O' && M >= N ) {
552  BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix provided" );
553  }
554 
555  resize( ~s, mindim, false );
556 
557  if( jobz == 'O' ) {
558  resize( ~U, M, M, false );
559  }
560 
561  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
562  return;
563  }
564 
565  gesdd_backend( ~A, ~U, ~s, jobz );
566 }
567 //*************************************************************************************************
568 
569 
570 //*************************************************************************************************
589 template< typename MT1 // Type of the matrix A
590  , bool SO // Storage order of all matrices
591  , typename VT // Type of the vector s
592  , bool TF // Transpose flag of the vector s
593  , typename MT2 > // Type of the matrix V
594 inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
595  DenseMatrix<MT2,SO>& V, char jobz )
596  -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
597 {
598  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
599  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~V ), "Invalid matrix dimensions detected" );
600  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).rows() == (~A).columns(), "Invalid matrix dimensions detected" );
601  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
602 
603  using ET = ElementType_t<MT1>;
604 
605  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
606  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
607  int lda ( numeric_cast<int>( (~A).spacing() ) );
608  int ldv ( numeric_cast<int>( (~V).spacing() ) );
609  int info( 0 );
610 
611  const int minimum( min( m, n ) );
612  const int maximum( max( m, n ) );
613 
614  int lwork( ( jobz == 'O' )
615  ?( 3*minimum + max( maximum, 5*minimum*minimum + 4*maximum + 2 ) )
616  :( 3*minimum + max( maximum, 7*minimum ) + 2 ) );
617  const std::unique_ptr<ET[]> work( new ET[lwork] );
618  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
619 
620  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
621  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
622  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
623  work.get(), lwork, iwork.get(), &info );
624 
625  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
626 
627  if( info > 0 ) {
628  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
629  }
630 }
632 //*************************************************************************************************
633 
634 
635 //*************************************************************************************************
654 template< typename MT1 // Type of the matrix A
655  , bool SO // Storage order of all matrices
656  , typename VT // Type of the vector s
657  , bool TF // Transpose flag of the vector s
658  , typename MT2 > // Type of the matrix V
659 inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
660  DenseMatrix<MT2,SO>& V, char jobz )
661  -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
662 {
663  BLAZE_INTERNAL_ASSERT( jobz == 'O' || jobz == 'N', "Invalid jobz flag detected" );
664  BLAZE_INTERNAL_ASSERT( jobz == 'N' || isSquare( ~V ), "Invalid matrix dimensions detected" );
665  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).rows() == (~A).columns(), "Invalid matrix dimensions detected" );
666  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
667 
668  using CT = ElementType_t<MT1>;
669  using BT = UnderlyingElement_t<CT>;
670 
671  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
672  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
673  int lda ( numeric_cast<int>( (~A).spacing() ) );
674  int ldv ( numeric_cast<int>( (~V).spacing() ) );
675  int info( 0 );
676 
677  const int minimum( min( m, n ) );
678  const int maximum( max( m, n ) );
679 
680  int lwork( ( jobz == 'O' )
681  ?( 2*minimum*minimum + 2*minimum + maximum + 2 )
682  :( 2*minimum + maximum + 2 ) );
683  const int lrwork( ( jobz == 'O' )
684  ?( max( 5*minimum*minimum + 5*minimum,
685  2*maximum*minimum + 2*minimum*minimum + minimum ) )
686  :( 7*minimum ) );
687  const std::unique_ptr<CT[]> work( new CT[lwork] );
688  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
689  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
690 
691  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
692  ( SO ? nullptr : (~V).data() ), ( SO ? 1 : ldv ),
693  ( SO ? (~V).data() : nullptr ), ( SO ? ldv : 1 ),
694  work.get(), lwork, rwork.get(), iwork.get(), &info );
695 
696  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
697 
698  if( info > 0 ) {
699  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
700  }
701 }
703 //*************************************************************************************************
704 
705 
706 //*************************************************************************************************
786 template< typename MT1 // Type of the matrix A
787  , bool SO // Storage order of all matrices
788  , typename MT2 // Type of the matrix U
789  , typename VT // Type of the vector s
790  , bool TF > // Transpose flag of the vector s
792  DenseMatrix<MT2,SO>& V, char jobz )
793 {
799 
805 
810 
811  const size_t M( (~A).rows() );
812  const size_t N( (~A).columns() );
813  const size_t mindim( min( M, N ) );
814 
815  if( jobz != 'O' && jobz != 'N' ) {
816  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
817  }
818 
819  if( jobz == 'O' && M < N ) {
820  BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix provided" );
821  }
822 
823  resize( ~s, mindim, false );
824 
825  if( jobz == 'O' ) {
826  resize( ~V, N, N, false );
827  }
828 
829  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
830  return;
831  }
832 
833  gesdd_backend( ~A, ~s, ~V, jobz );
834 }
835 //*************************************************************************************************
836 
837 
838 //*************************************************************************************************
858 template< typename MT1 // Type of the matrix A
859  , bool SO // Storage order of all matrices
860  , typename MT2 // Type of the matrix U
861  , typename VT // Type of the vector s
862  , bool TF // Transpose flag of the vector s
863  , typename MT3 > // Type of the matrix V
864 inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
865  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
866  -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
867 {
868  BLAZE_INTERNAL_ASSERT( jobz == 'A' || jobz == 'S' || jobz == 'N', "Invalid jobz flag detected" );
869  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
870  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
871  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
872  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
873  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
874  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
875  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
876 
877  using ET = ElementType_t<MT1>;
878 
879  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
880  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
881  int lda ( numeric_cast<int>( (~A).spacing() ) );
882  int ldu ( numeric_cast<int>( (~U).spacing() ) );
883  int ldv ( numeric_cast<int>( (~V).spacing() ) );
884  int info( 0 );
885 
886  const int minimum( min( m, n ) );
887  const int maximum( max( m, n ) );
888 
889  int lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
890  const std::unique_ptr<ET[]> work( new ET[lwork] );
891  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
892 
893  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
894  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
895  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
896  work.get(), lwork, iwork.get(), &info );
897 
898  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
899 
900  if( info > 0 ) {
901  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
902  }
903 }
905 //*************************************************************************************************
906 
907 
908 //*************************************************************************************************
928 template< typename MT1 // Type of the matrix A
929  , bool SO // Storage order of all matrices
930  , typename MT2 // Type of the matrix U
931  , typename VT // Type of the vector s
932  , bool TF // Transpose flag of the vector s
933  , typename MT3 > // Type of the matrix V
934 inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
935  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
936  -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
937 {
938  BLAZE_INTERNAL_ASSERT( jobz == 'A' || jobz == 'S' || jobz == 'N', "Invalid jobz flag detected" );
939  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~U).rows() == (~A).rows(), "Invalid matrix dimension detected" );
940  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~U ), "Invalid non-square matrix detected" );
941  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~U).columns() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
942  BLAZE_INTERNAL_ASSERT( jobz == 'N' || (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
943  BLAZE_INTERNAL_ASSERT( jobz != 'A' || isSquare( ~V ), "Invalid non-square matrix detected" );
944  BLAZE_INTERNAL_ASSERT( jobz != 'S' || (~V).rows() == min( (~A).rows(), (~A).columns() ), "Invalid matrix dimension detected" );
945  BLAZE_INTERNAL_ASSERT( (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
946 
947  using CT = ElementType_t<MT1>;
948  using BT = UnderlyingElement_t<CT>;
949 
950  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
951  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
952  int lda ( numeric_cast<int>( (~A).spacing() ) );
953  int ldu ( numeric_cast<int>( (~U).spacing() ) );
954  int ldv ( numeric_cast<int>( (~V).spacing() ) );
955  int info( 0 );
956 
957  const int minimum( min( m, n ) );
958  const int maximum( max( m, n ) );
959 
960  int lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
961  const int lrwork( max( 5*minimum*minimum + 5*minimum,
962  2*maximum*minimum + 2*minimum*minimum + minimum ) );
963  const std::unique_ptr<CT[]> work( new CT[lwork] );
964  const std::unique_ptr<BT[]> rwork( new BT[lrwork] );
965  const std::unique_ptr<int[]> iwork( new int[8*minimum] );
966 
967  gesdd( jobz, m, n, (~A).data(), lda, (~s).data(),
968  ( SO ? (~U).data() : (~V).data() ), ( SO ? ldu : ldv ),
969  ( SO ? (~V).data() : (~U).data() ), ( SO ? ldv : ldu ),
970  work.get(), lwork, rwork.get(), iwork.get(), &info );
971 
972  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
973 
974  if( info > 0 ) {
975  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
976  }
977 }
979 //*************************************************************************************************
980 
981 
982 //*************************************************************************************************
1084 template< typename MT1 // Type of the matrix A
1085  , bool SO // Storage order of all matrices
1086  , typename MT2 // Type of the matrix U
1087  , typename VT // Type of the vector s
1088  , bool TF // Transpose flag of the vector s
1089  , typename MT3 > // Type of the matrix V
1091  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobz )
1092 {
1098 
1104 
1109 
1115 
1116  const size_t M( (~A).rows() );
1117  const size_t N( (~A).columns() );
1118  const size_t mindim( min( M, N ) );
1119 
1120  if( jobz != 'A' && jobz != 'S' && jobz != 'N' ) {
1121  BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobz argument provided" );
1122  }
1123 
1124  resize( ~s, mindim, false );
1125 
1126  if( jobz != 'N' ) {
1127  resize( ~U, M, ( jobz == 'A' ? M : mindim ), false );
1128  resize( ~V, ( jobz == 'A' ? N : mindim ), N, false );
1129  }
1130 
1131  if( (~A).rows() == 0UL || (~A).columns() == 0UL ) {
1132  return;
1133  }
1134 
1135  gesdd_backend( ~A, ~U, ~s, ~V, jobz );
1136 }
1137 //*************************************************************************************************
1138 
1139 } // namespace blaze
1140 
1141 #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
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 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
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:174
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.
Header file for the CLAPACK gesdd wrapper functions.
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