35#ifndef _BLAZE_MATH_LAPACK_GESDD_H_
36#define _BLAZE_MATH_LAPACK_GESDD_H_
74template<
typename MT,
bool SO,
typename VT,
bool TF >
75void gesdd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s );
77template<
typename MT1,
bool SO,
typename MT2,
typename VT,
bool TF >
78void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
char jobz );
80template<
typename MT1,
bool SO,
typename MT2,
typename VT,
bool TF >
81void gesdd( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V,
char jobz );
83template<
typename MT1,
bool SO,
typename MT2,
typename VT,
bool TF,
typename MT3 >
84void gesdd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
85 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V,
char jobz );
111inline auto gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
112 -> DisableIf_t< IsComplex_v< ElementType_t<MT> > >
116 using ET = ElementType_t<MT>;
118 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
119 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
120 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
126 blas_int_t lwork( 3*minimum +
max( maximum, 7*minimum ) + 2 );
127 const std::unique_ptr<ET[]> work(
new ET[lwork] );
128 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
130 gesdd(
'N', m, n, (*A).data(), lda, (*s).data(),
131 nullptr, 1,
nullptr, 1, work.get(), lwork, iwork.get(), &info );
164inline auto gesdd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s )
165 -> EnableIf_t< IsComplex_v< ElementType_t<MT> > >
169 using CT = ElementType_t<MT>;
170 using BT = UnderlyingElement_t<CT>;
172 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
173 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
174 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
181 const std::unique_ptr<CT[]> work(
new CT[lwork] );
182 const std::unique_ptr<BT[]> rwork(
new BT[7*minimum] );
183 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
185 gesdd(
'N', m, n, (*A).data(), lda, (*s).data(),
186 nullptr, 1,
nullptr, 1, work.get(), lwork, rwork.get(), iwork.get(), &info );
277 const size_t M( (*A).rows() );
278 const size_t N( (*A).columns() );
279 const size_t mindim(
min( M, N ) );
281 resize( *s, mindim,
false );
283 if( M == 0UL || N == 0 ) {
287 gesdd_backend( A, s );
311template<
typename MT1
316inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
317 DenseVector<VT,TF>& s,
char jobz )
318 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
322 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*U).rows() == (*A).rows(),
"Invalid matrix dimensions detected" );
325 using ET = ElementType_t<MT1>;
327 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
328 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
329 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
330 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
337 ?( 3*minimum +
max( maximum, 5*minimum*minimum + 4*maximum ) + 2 )
338 :( 3*minimum +
max( maximum, 7*minimum ) + 2 ) );
339 const std::unique_ptr<ET[]> work(
new ET[lwork] );
340 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
342 gesdd( jobz, m, n, (*A).data(), lda, (*s).data(),
343 ( SO ? (*U).data() :
nullptr ), ( SO ? ldu : 1 ),
344 ( SO ?
nullptr : (*U).data() ), ( SO ? 1 : ldu ),
345 work.get(), lwork, iwork.get(), &info );
376template<
typename MT1
381inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
382 DenseVector<VT,TF>& s,
char jobz )
383 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
387 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*U).rows() == (*A).rows(),
"Invalid matrix dimensions detected" );
390 using CT = ElementType_t<MT1>;
391 using BT = UnderlyingElement_t<CT>;
393 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
394 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
395 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
396 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
403 ?( 2*minimum*minimum + 2*minimum + maximum + 2 )
404 :( 2*minimum + maximum + 2 ) );
406 ?(
max( 5*minimum*minimum + 5*minimum,
407 2*maximum*minimum + 2*minimum*minimum + minimum ) )
409 const std::unique_ptr<CT[]> work(
new CT[lwork] );
410 const std::unique_ptr<BT[]> rwork(
new BT[lrwork] );
411 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
413 gesdd( jobz, m, n, (*A).data(), lda, (*s).data(),
414 ( SO ? (*U).data() :
nullptr ), ( SO ? ldu : 1 ),
415 ( SO ?
nullptr : (*U).data() ), ( SO ? 1 : ldu ),
416 work.get(), lwork, rwork.get(), iwork.get(), &info );
517template<
typename MT1
542 const size_t M( (*A).rows() );
543 const size_t N( (*A).columns() );
544 const size_t mindim(
min( M, N ) );
546 if( jobz !=
'O' && jobz !=
'N' ) {
550 if( jobz ==
'O' && M >= N ) {
554 resize( *s, mindim,
false );
557 resize( *U, M, M,
false );
560 if( (*A).rows() == 0UL || (*A).columns() == 0UL ) {
564 gesdd_backend( *A, *U, *s, jobz );
588template<
typename MT1
593inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
594 DenseMatrix<MT2,SO>& V,
char jobz )
595 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
599 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*V).rows() == (*A).columns(),
"Invalid matrix dimensions detected" );
602 using ET = ElementType_t<MT1>;
604 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
605 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
606 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
607 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
614 ?( 3*minimum +
max( maximum, 5*minimum*minimum + 4*maximum + 2 ) )
615 :( 3*minimum +
max( maximum, 7*minimum ) + 2 ) );
616 const std::unique_ptr<ET[]> work(
new ET[lwork] );
617 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
619 gesdd( jobz, m, n, (*A).data(), lda, (*s).data(),
620 ( SO ?
nullptr : (*V).data() ), ( SO ? 1 : ldv ),
621 ( SO ? (*V).data() :
nullptr ), ( SO ? ldv : 1 ),
622 work.get(), lwork, iwork.get(), &info );
653template<
typename MT1
658inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
659 DenseMatrix<MT2,SO>& V,
char jobz )
660 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
664 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*V).rows() == (*A).columns(),
"Invalid matrix dimensions detected" );
667 using CT = ElementType_t<MT1>;
668 using BT = UnderlyingElement_t<CT>;
670 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
671 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
672 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
673 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
680 ?( 2*minimum*minimum + 2*minimum + maximum + 2 )
681 :( 2*minimum + maximum + 2 ) );
683 ?(
max( 5*minimum*minimum + 5*minimum,
684 2*maximum*minimum + 2*minimum*minimum + minimum ) )
686 const std::unique_ptr<CT[]> work(
new CT[lwork] );
687 const std::unique_ptr<BT[]> rwork(
new BT[lrwork] );
688 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
690 gesdd( jobz, m, n, (*A).data(), lda, (*s).data(),
691 ( SO ?
nullptr : (*V).data() ), ( SO ? 1 : ldv ),
692 ( SO ? (*V).data() :
nullptr ), ( SO ? ldv : 1 ),
693 work.get(), lwork, rwork.get(), iwork.get(), &info );
785template<
typename MT1
810 const size_t M( (*A).rows() );
811 const size_t N( (*A).columns() );
812 const size_t mindim(
min( M, N ) );
814 if( jobz !=
'O' && jobz !=
'N' ) {
818 if( jobz ==
'O' && M < N ) {
822 resize( *s, mindim,
false );
825 resize( *V, N, N,
false );
828 if( (*A).rows() == 0UL || (*A).columns() == 0UL ) {
832 gesdd_backend( *A, *s, *V, jobz );
857template<
typename MT1
863inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
864 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V,
char jobz )
865 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
868 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*U).rows() == (*A).rows(),
"Invalid matrix dimension detected" );
870 BLAZE_INTERNAL_ASSERT( jobz !=
'S' || (*U).columns() ==
min( (*A).rows(), (*A).columns() ),
"Invalid matrix dimension detected" );
871 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*V).columns() == (*A).columns(),
"Invalid matrix dimension detected" );
873 BLAZE_INTERNAL_ASSERT( jobz !=
'S' || (*V).rows() ==
min( (*A).rows(), (*A).columns() ),
"Invalid matrix dimension detected" );
876 using ET = ElementType_t<MT1>;
878 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
879 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
880 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
881 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
882 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
888 blas_int_t lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
889 const std::unique_ptr<ET[]> work(
new ET[lwork] );
890 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
892 gesdd( jobz, m, n, (*A).data(), lda, (*s).data(),
893 ( SO ? (*U).data() : (*V).data() ), ( SO ? ldu : ldv ),
894 ( SO ? (*V).data() : (*U).data() ), ( SO ? ldv : ldu ),
895 work.get(), lwork, iwork.get(), &info );
927template<
typename MT1
933inline auto gesdd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
934 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V,
char jobz )
935 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
938 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*U).rows() == (*A).rows(),
"Invalid matrix dimension detected" );
940 BLAZE_INTERNAL_ASSERT( jobz !=
'S' || (*U).columns() ==
min( (*A).rows(), (*A).columns() ),
"Invalid matrix dimension detected" );
941 BLAZE_INTERNAL_ASSERT( jobz ==
'N' || (*V).columns() == (*A).columns(),
"Invalid matrix dimension detected" );
943 BLAZE_INTERNAL_ASSERT( jobz !=
'S' || (*V).rows() ==
min( (*A).rows(), (*A).columns() ),
"Invalid matrix dimension detected" );
946 using CT = ElementType_t<MT1>;
947 using BT = UnderlyingElement_t<CT>;
949 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
950 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
951 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
952 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
953 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
959 blas_int_t lwork( 4*minimum*minimum + 6*minimum + maximum + 2 );
961 2*maximum*minimum + 2*minimum*minimum + minimum ) );
962 const std::unique_ptr<CT[]> work(
new CT[lwork] );
963 const std::unique_ptr<BT[]> rwork(
new BT[lrwork] );
964 const std::unique_ptr<blas_int_t[]> iwork(
new blas_int_t[8*minimum] );
966 gesdd( jobz, m, n, (*A).data(), lda, (*s).data(),
967 ( SO ? (*U).data() : (*V).data() ), ( SO ? ldu : ldv ),
968 ( SO ? (*V).data() : (*U).data() ), ( SO ? ldv : ldu ),
969 work.get(), lwork, rwork.get(), iwork.get(), &info );
1083template<
typename MT1
1115 const size_t M( (*A).rows() );
1116 const size_t N( (*A).columns() );
1117 const size_t mindim(
min( M, N ) );
1119 if( jobz !=
'A' && jobz !=
'S' && jobz !=
'N' ) {
1123 resize( *s, mindim,
false );
1126 resize( *U, M, ( jobz ==
'A' ? M : mindim ),
false );
1127 resize( *V, ( jobz ==
'A' ? N : mindim ), N,
false );
1130 if( (*A).rows() == 0UL || (*A).columns() == 0UL ) {
1134 gesdd_backend( *A, *U, *s, *V, jobz );
Constraint on the data type.
Header file for auxiliary alias declarations.
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.
Definition: Aliases.h:190
Header file for run time assertion macros.
Constraint on the data type.
Constraint on the data type.
Header file for the EnableIf class template.
Header file for the IsComplex type trait.
Constraint on the data type.
Cast operators for numeric types.
Header file for the UnderlyingElement type trait.
Header file for the CLAPACK gesdd wrapper functions.
Base class for dense matrices.
Definition: DenseMatrix.h:82
Base class for N-dimensional dense vectors.
Definition: DenseVector.h:77
Constraint on the data type.
Header file for the DenseMatrix base class.
Header file for the DenseVector base class.
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:1339
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:1375
void gesdd(DenseMatrix< MT1, SO > &A, DenseMatrix< MT2, SO > &U, DenseVector< VT, TF > &s, DenseMatrix< MT3, SO > &V, char jobz)
LAPACK kernel for the singular value decomposition (SVD) of the given dense general matrix.
Definition: gesdd.h:1089
#define BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE(T)
Constraint on the data type.
Definition: BLASCompatible.h:61
#define BLAZE_CONSTRAINT_MUST_BE_CONTIGUOUS_TYPE(T)
Constraint on the data type.
Definition: Contiguous.h:61
#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE(T)
Constraint on the data type.
Definition: Computation.h:81
#define BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE(T)
Constraint on the data type.
Definition: Adaptor.h:81
#define BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS(T)
Constraint on the data type.
Definition: MutableDataAccess.h:61
int32_t blas_int_t
Signed integer type used in the BLAS/LAPACK wrapper functions.
Definition: Types.h:64
#define BLAZE_THROW_LAPACK_ERROR(MESSAGE)
Macro for the emission of an exception on detection of a LAPACK error.
Definition: Exception.h:146
void resize(Matrix< MT, SO > &matrix, size_t rows, size_t columns, bool preserve=true)
Changing the size of the matrix.
Definition: Matrix.h:1108
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:1383
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.
Definition: Assert.h:101
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.
Definition: Exception.h:235
Header file for the exception macros of the math module.
Header file for the generic max algorithm.
Header file for the generic min algorithm.