Blaze 3.9
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>
57#include <blaze/util/Assert.h>
58#include <blaze/util/EnableIf.h>
61
62
63namespace blaze {
64
65//=================================================================================================
66//
67// LAPACK SVD FUNCTIONS (GESVD)
68//
69//=================================================================================================
70
71//*************************************************************************************************
74template< typename MT, bool SO, typename VT, bool TF >
75void gesvd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv );
76
77template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
78void gesvd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
79 DenseVector<VT,TF>& s, char jobu, char jobv );
80
81template< typename MT1, bool SO, typename VT, bool TF, typename MT2 >
82void gesvd( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
83 DenseMatrix<MT2,SO>& V, char jobu, char jobv );
84
85template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
86void gesvd( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
87 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv );
89//*************************************************************************************************
90
91
92//*************************************************************************************************
111template< typename MT // Type of the matrix A
112 , bool SO // Storage order of the matrix A
113 , typename VT // Type of the vector s
114 , bool TF > // Transpose flag of the vector s
115inline auto gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
116 -> DisableIf_t< IsComplex_v< ElementType_t<MT> > >
117{
118 BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
119 BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
120 BLAZE_INTERNAL_ASSERT( jobu != 'O' || jobv != 'O', "Invalid combination of jobu and jobv detected" );
121 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
122
123 using ET = ElementType_t<MT>;
124
125 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
126 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
127 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
128 blas_int_t info( 0 );
129
130 const blas_int_t minimum( min( m, n ) );
131 const blas_int_t maximum( max( m, n ) );
132
133 blas_int_t lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
134 const std::unique_ptr<ET[]> work( new ET[lwork] );
135
136 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ), m, n, (*A).data(), lda,
137 (*s).data(), nullptr, 1, nullptr, 1, work.get(), lwork, &info );
138
139 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
140
141 if( info > 0 ) {
142 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
143 }
144}
146//*************************************************************************************************
147
148
149//*************************************************************************************************
168template< typename MT // Type of the matrix A
169 , bool SO // Storage order of the matrix A
170 , typename VT // Type of the vector s
171 , bool TF > // Transpose flag of the vector s
172inline auto gesvd_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
173 -> EnableIf_t< IsComplex_v< ElementType_t<MT> > >
174{
175 BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
176 BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
177 BLAZE_INTERNAL_ASSERT( jobu != 'O' || jobv != 'O', "Invalid combination of jobu and jobv detected" );
178 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
179
180 using CT = ElementType_t<MT>;
181 using BT = UnderlyingElement_t<CT>;
182
183 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
184 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
185 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
186 blas_int_t info( 0 );
187
188 const blas_int_t minimum( min( m, n ) );
189 const blas_int_t maximum( max( m, n ) );
190
191 blas_int_t lwork( 2*minimum + maximum + 2 );
192 const std::unique_ptr<CT[]> work ( new CT[lwork] );
193 const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
194
195 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ), m, n, (*A).data(), lda,
196 (*s).data(), nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), &info );
197
198 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
199
200 if( info > 0 ) {
201 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
202 }
203}
205//*************************************************************************************************
206
207
208//*************************************************************************************************
292template< typename MT // Type of the matrix A
293 , bool SO // Storage order of the matrix A
294 , typename VT // Type of the vector s
295 , bool TF > // Transpose flag of the vector s
296inline void gesvd( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, char jobu, char jobv )
297{
303
308
309 const size_t M( (*A).rows() );
310 const size_t N( (*A).columns() );
311 const size_t mindim( min( M, N ) );
312
313 if( jobu != 'O' && jobu != 'N' ) {
314 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
315 }
316
317 if( jobv != 'O' && jobv != 'N' ) {
318 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
319 }
320
321 if( jobu == 'O' && jobv == 'O' ) {
322 BLAZE_THROW_INVALID_ARGUMENT( "Invalid combination of jobu and jobv provided" );
323 }
324
325 resize( *s, mindim, false );
326
327 if( M == 0UL || N == 0UL ) {
328 return;
329 }
330
331 gesvd_backend( *A, *s, jobu, jobv );
332}
333//*************************************************************************************************
334
335
336//*************************************************************************************************
356template< typename MT1 // Type of the matrix A
357 , bool SO // Storage order of all matrices
358 , typename MT2 // Type of the matrix U
359 , typename VT // Type of the vector s
360 , bool TF > // Transpose flag of the vector s
361inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
362 DenseVector<VT,TF>& s, char jobu, char jobv )
363 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
364{
365 BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
366 BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
367 BLAZE_INTERNAL_ASSERT( jobu == 'N' || (*U).rows() == (*A).rows(), "Invalid matrix dimension detected" );
368 BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( *U ), "Invalid non-square matrix detected" );
369 BLAZE_INTERNAL_ASSERT( jobu != 'S' || (*U).columns() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
370 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
371
372 using ET = ElementType_t<MT1>;
373
374 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
375 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
376 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
377 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
378 blas_int_t info( 0 );
379
380 const blas_int_t minimum( min( m, n ) );
381 const blas_int_t maximum( max( m, n ) );
382
383 blas_int_t lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
384 const std::unique_ptr<ET[]> work( new ET[lwork] );
385
386 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
387 m, n, (*A).data(), lda, (*s).data(),
388 ( SO ? (*U).data() : nullptr ), ( SO ? ldu : 1 ),
389 ( SO ? nullptr : (*U).data() ), ( SO ? 1 : ldu ),
390 work.get(), lwork, &info );
391
392 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
393
394 if( info > 0 ) {
395 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
396 }
397}
399//*************************************************************************************************
400
401
402//*************************************************************************************************
422template< typename MT1 // Type of the matrix A
423 , bool SO // Storage order of all matrices
424 , typename MT2 // Type of the matrix U
425 , typename VT // Type of the vector s
426 , bool TF > // Transpose flag of the vector s
427inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
428 DenseVector<VT,TF>& s, char jobu, char jobv )
429 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
430{
431 BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
432 BLAZE_INTERNAL_ASSERT( jobv == 'O' || jobv == 'N', "Invalid jobv flag detected" );
433 BLAZE_INTERNAL_ASSERT( jobu == 'N' || (*U).rows() == (*A).rows(), "Invalid matrix dimension detected" );
434 BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( *U ), "Invalid non-square matrix detected" );
435 BLAZE_INTERNAL_ASSERT( jobu != 'S' || (*U).columns() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
436 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
437
438 using CT = ElementType_t<MT1>;
439 using BT = UnderlyingElement_t<CT>;
440
441 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
442 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
443 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
444 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
445 blas_int_t info( 0 );
446
447 const blas_int_t minimum( min( m, n ) );
448 const blas_int_t maximum( max( m, n ) );
449
450 blas_int_t lwork( 2*minimum + maximum + 2 );
451 const std::unique_ptr<CT[]> work ( new CT[lwork] );
452 const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
453
454 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
455 m, n, (*A).data(), lda, (*s).data(),
456 ( SO ? (*U).data() : nullptr ), ( SO ? ldu : 1 ),
457 ( SO ? nullptr : (*U).data() ), ( SO ? 1 : ldu ),
458 work.get(), lwork, rwork.get(), &info );
459
460 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
461
462 if( info > 0 ) {
463 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
464 }
465}
467//*************************************************************************************************
468
469
470//*************************************************************************************************
571template< typename MT1 // Type of the matrix A
572 , bool SO // Storage order of all matrices
573 , typename MT2 // Type of the matrix U
574 , typename VT // Type of the vector s
575 , bool TF > // Transpose flag of the vector s
577 DenseVector<VT,TF>& s, char jobu, char jobv )
578{
584
590
595
596 const size_t M( (*A).rows() );
597 const size_t N( (*A).columns() );
598 const size_t mindim( min( M, N ) );
599
600 if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
601 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
602 }
603
604 if( jobv != 'O' && jobv != 'N' ) {
605 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
606 }
607
608 resize( *s, mindim, false );
609
610 if( jobu != 'N' ) {
611 resize( *U, M, ( jobu == 'A' ? M : mindim ), false );
612 }
613
614 if( M == 0UL || N == 0UL ) {
615 return;
616 }
617
618 gesvd_backend( *A, *U, *s, jobu, jobv );
619}
620//*************************************************************************************************
621
622
623//*************************************************************************************************
643template< typename MT1 // Type of the matrix A
644 , bool SO // Storage order of all matrices
645 , typename VT // Type of the vector s
646 , bool TF // Transpose flag of the vector s
647 , typename MT2 > // Type of the matrix V
648inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
649 DenseMatrix<MT2,SO>& V, char jobu, char jobv )
650 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
651{
652 BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
653 BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
654 BLAZE_INTERNAL_ASSERT( jobv == 'N' || (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
655 BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( *V ), "Invalid non-square matrix detected" );
656 BLAZE_INTERNAL_ASSERT( jobv != 'S' || (*V).rows() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
657 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
658
659 using ET = ElementType_t<MT1>;
660
661 blas_int_t m ( numeric_cast< blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
662 blas_int_t n ( numeric_cast< blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
663 blas_int_t lda ( numeric_cast< blas_int_t>( (*A).spacing() ) );
664 blas_int_t ldv ( numeric_cast< blas_int_t>( (*V).spacing() ) );
665 blas_int_t info( 0 );
666
667 const blas_int_t minimum( min( m, n ) );
668 const blas_int_t maximum( max( m, n ) );
669
670 blas_int_t lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
671 const std::unique_ptr<ET[]> work( new ET[lwork] );
672
673 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
674 m, n, (*A).data(), lda, (*s).data(),
675 ( SO ? nullptr : (*V).data() ), ( SO ? 1 : ldv ),
676 ( SO ? (*V).data() : nullptr ), ( SO ? ldv : 1 ),
677 work.get(), lwork, &info );
678
679 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
680
681 if( info > 0 ) {
682 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
683 }
684}
686//*************************************************************************************************
687
688
689//*************************************************************************************************
709template< typename MT1 // Type of the matrix A
710 , bool SO // Storage order of all matrices
711 , typename VT // Type of the vector s
712 , bool TF // Transpose flag of the vector s
713 , typename MT2 > // Type of the matrix V
714inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
715 DenseMatrix<MT2,SO>& V, char jobu, char jobv )
716 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
717{
718 BLAZE_INTERNAL_ASSERT( jobu == 'O' || jobu == 'N', "Invalid jobu flag detected" );
719 BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
720 BLAZE_INTERNAL_ASSERT( jobv == 'N' || (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
721 BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( *V ), "Invalid non-square matrix detected" );
722 BLAZE_INTERNAL_ASSERT( jobv != 'S' || (*V).rows() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
723 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
724
725 using CT = ElementType_t<MT1>;
726 using BT = UnderlyingElement_t<CT>;
727
728 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
729 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
730 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
731 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
732 blas_int_t info( 0 );
733
734 const blas_int_t minimum( min( m, n ) );
735 const blas_int_t maximum( max( m, n ) );
736
737 blas_int_t lwork( 2*minimum + maximum + 2 );
738 const std::unique_ptr<CT[]> work ( new CT[lwork] );
739 const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
740
741 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
742 m, n, (*A).data(), lda, (*s).data(),
743 ( SO ? nullptr : (*V).data() ), ( SO ? 1 : ldv ),
744 ( SO ? (*V).data() : nullptr ), ( SO ? ldv : 1 ),
745 work.get(), lwork, rwork.get(), &info );
746
747 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
748
749 if( info > 0 ) {
750 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
751 }
752}
754//*************************************************************************************************
755
756
757//*************************************************************************************************
858template< typename MT1 // Type of the matrix A
859 , bool SO // Storage order of all matrices
860 , typename VT // Type of the vector s
861 , bool TF // Transpose flag of the vector s
862 , typename MT2 > // Type of the matrix V
864 DenseMatrix<MT2,SO>& V, char jobu, char jobv )
865{
871
876
882
883 const size_t M( (*A).rows() );
884 const size_t N( (*A).columns() );
885 const size_t mindim( min( M, N ) );
886
887 if( jobu != 'O' && jobu != 'N' ) {
888 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
889 }
890
891 if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
892 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
893 }
894
895 resize( *s, mindim, false );
896
897 if( jobv != 'N' ) {
898 resize( *V, ( jobv == 'A' ? N : mindim ), N, false );
899 }
900
901 if( M == 0UL || N == 0UL ) {
902 return;
903 }
904
905 gesvd_backend( *A, *s, *V, jobu, jobv );
906}
907//*************************************************************************************************
908
909
910//*************************************************************************************************
931template< typename MT1 // Type of the matrix A
932 , bool SO // Storage order of all matrices
933 , typename MT2 // Type of the matrix U
934 , typename VT // Type of the vector s
935 , bool TF // Transpose flag of the vector s
936 , typename MT3 > // Type of the matrix V
937inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
938 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
939 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> > >
940{
941 BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
942 BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
943 BLAZE_INTERNAL_ASSERT( jobu == 'N' || (*U).rows() == (*A).rows(), "Invalid matrix dimension detected" );
944 BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( *U ), "Invalid non-square matrix detected" );
945 BLAZE_INTERNAL_ASSERT( jobu != 'S' || (*U).columns() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
946 BLAZE_INTERNAL_ASSERT( jobv == 'N' || (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
947 BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( *V ), "Invalid non-square matrix detected" );
948 BLAZE_INTERNAL_ASSERT( jobv != 'S' || (*V).rows() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
949 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
950
951 using ET = ElementType_t<MT1>;
952
953 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
954 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
955 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
956 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
957 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
958 blas_int_t info( 0 );
959
960 const blas_int_t minimum( min( m, n ) );
961 const blas_int_t maximum( max( m, n ) );
962
963 blas_int_t lwork( max( 3*minimum + maximum, 5*minimum ) + 2 );
964 const std::unique_ptr<ET[]> work( new ET[lwork] );
965
966 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
967 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, &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//*************************************************************************************************
1003template< typename MT1 // Type of the matrix A
1004 , bool SO // Storage order of all matrices
1005 , typename MT2 // Type of the matrix U
1006 , typename VT // Type of the vector s
1007 , bool TF // Transpose flag of the vector s
1008 , typename MT3 > // Type of the matrix V
1009inline auto gesvd_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
1010 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1011 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> > >
1012{
1013 BLAZE_INTERNAL_ASSERT( jobu == 'A' || jobu == 'S' || jobu == 'N', "Invalid jobu flag detected" );
1014 BLAZE_INTERNAL_ASSERT( jobv == 'A' || jobv == 'S' || jobv == 'N', "Invalid jobv flag detected" );
1015 BLAZE_INTERNAL_ASSERT( jobu == 'N' || (*U).rows() == (*A).rows(), "Invalid matrix dimension detected" );
1016 BLAZE_INTERNAL_ASSERT( jobu != 'A' || isSquare( *U ), "Invalid non-square matrix detected" );
1017 BLAZE_INTERNAL_ASSERT( jobu != 'S' || (*U).columns() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
1018 BLAZE_INTERNAL_ASSERT( jobv == 'N' || (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
1019 BLAZE_INTERNAL_ASSERT( jobv != 'A' || isSquare( *V ), "Invalid non-square matrix detected" );
1020 BLAZE_INTERNAL_ASSERT( jobv != 'S' || (*V).rows() == min( (*A).rows(), (*A).columns() ), "Invalid matrix dimension detected" );
1021 BLAZE_INTERNAL_ASSERT( (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1022
1023 using CT = ElementType_t<MT1>;
1024 using BT = UnderlyingElement_t<CT>;
1025
1026 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
1027 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
1028 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
1029 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
1030 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
1031 blas_int_t info( 0 );
1032
1033 const blas_int_t minimum( min( m, n ) );
1034 const blas_int_t maximum( max( m, n ) );
1035
1036 blas_int_t lwork( 2*minimum + maximum + 2 );
1037 const std::unique_ptr<CT[]> work ( new CT[lwork] );
1038 const std::unique_ptr<BT[]> rwork( new BT[5*minimum] );
1039
1040 gesvd( ( SO ? jobu : jobv ), ( SO ? jobv : jobu ),
1041 m, n, (*A).data(), lda, (*s).data(),
1042 ( SO ? (*U).data() : (*V).data() ), ( SO ? ldu : ldv ),
1043 ( SO ? (*V).data() : (*U).data() ), ( SO ? ldv : ldu ),
1044 work.get(), lwork, rwork.get(), &info );
1045
1046 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1047
1048 if( info > 0 ) {
1049 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1050 }
1051}
1053//*************************************************************************************************
1054
1055
1056//*************************************************************************************************
1164template< typename MT1 // Type of the matrix A
1165 , bool SO // Storage order of all matrices
1166 , typename MT2 // Type of the matrix U
1167 , typename VT // Type of the vector s
1168 , bool TF // Transpose flag of the vector s
1169 , typename MT3 > // Type of the matrix V
1171 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, char jobu, char jobv )
1172{
1178
1184
1189
1195
1196 const size_t M( (*A).rows() );
1197 const size_t N( (*A).columns() );
1198 const size_t mindim( min( M, N ) );
1199
1200 if( jobu != 'A' && jobu != 'S' && jobu != 'N' ) {
1201 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobu argument provided" );
1202 }
1203
1204 if( jobv != 'A' && jobv != 'S' && jobv != 'N' ) {
1205 BLAZE_THROW_INVALID_ARGUMENT( "Invalid jobv argument provided" );
1206 }
1207
1208 resize( *s, mindim, false );
1209
1210 if( jobu != 'N' ) {
1211 resize( *U, M, ( jobu == 'A' ? M : mindim ), false );
1212 resize( *V, ( jobv == 'A' ? N : mindim ), N, false );
1213 }
1214
1215 if( M == 0UL || N == 0UL ) {
1216 return;
1217 }
1218
1219 gesvd_backend( *A, *U, *s, *V, jobu, jobv );
1220}
1221//*************************************************************************************************
1222
1223} // namespace blaze
1224
1225#endif
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 gesvd 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 gesvd(DenseMatrix< MT1, SO > &A, DenseMatrix< MT2, SO > &U, DenseVector< VT, TF > &s, DenseMatrix< MT3, SO > &V, char jobu, char jobv)
LAPACK kernel for the singular value decomposition (SVD) of the given dense general matrix.
Definition: gesvd.h:1170
#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.