Blaze 3.9
gesvdx.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_LAPACK_GESVDX_H_
36#define _BLAZE_MATH_LAPACK_GESVDX_H_
37
38
39//*************************************************************************************************
40// Includes
41//*************************************************************************************************
42
43#include <memory>
44#include <blaze/math/Aliases.h>
59#include <blaze/util/Assert.h>
61#include <blaze/util/EnableIf.h>
63#include <blaze/util/Types.h>
66
67
68namespace blaze {
69
70//=================================================================================================
71//
72// LAPACK SVD FUNCTIONS (GESVDX)
73//
74//=================================================================================================
75
76//*************************************************************************************************
79template< typename MT, bool SO, typename VT, bool TF >
80size_t gesvdx( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s );
81
82template< typename MT, bool SO, typename VT, bool TF, typename ST >
83size_t gesvdx( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, ST low, ST upp );
84
85template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
86size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s );
87
88template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename ST >
89size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
90 DenseVector<VT,TF>& s, ST low, ST upp );
91
92template< typename MT1, bool SO, typename VT, bool TF, typename MT2 >
93size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V );
94
95template< typename MT1, bool SO, typename VT, bool TF, typename MT2, typename ST >
96size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
97 DenseMatrix<MT2,SO>& V, ST low, ST upp );
98
99template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
100size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
101 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V );
102
103template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3, typename ST >
104size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
105 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, ST low, ST upp );
107//*************************************************************************************************
108
109
110//*************************************************************************************************
132template< typename MT // Type of the matrix A
133 , bool SO // Storage order of the matrix A
134 , typename VT // Type of the vector s
135 , bool TF // Transpose flag of the vector s
136 , typename ST > // Type of the scalar boundary values
137inline auto gesvdx_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s,
138 char range, ST vl, ST vu, blas_int_t il, blas_int_t iu )
139 -> DisableIf_t< IsComplex_v< ElementType_t<MT> >, size_t >
140{
141 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
142 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
143 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
144 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
145 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
146 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
147
148 using ET = ElementType_t<MT>;
149
150 const size_t M( (*A).rows() );
151 const size_t N( (*A).columns() );
152 const size_t mindim( min( M, N ) );
153
154 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
155 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
156 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
157 blas_int_t ns ( 0 );
158 blas_int_t info( 0 );
159
160 ET* sptr( (*s).data() );
161 std::unique_ptr<ET[]> stmp;
162
163 const bool tmpRequired( (*s).size() < mindim );
164
165 if( tmpRequired ) {
166 stmp.reset( new ET[2UL*mindim] );
167 sptr = stmp.get();
168 }
169
170 const blas_int_t minimum( min( m, n ) );
171
172 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
173 const std::unique_ptr<ET[]> work ( new ET[lwork] );
174 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
175
176 gesvdx( 'N', 'N', range, m, n, (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
177 nullptr, 1, nullptr, 1, work.get(), lwork, iwork.get(), &info );
178
179 const size_t num( numeric_cast<size_t>( ns ) );
180
181 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
182 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
183
184 if( info > 0 ) {
185 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
186 }
187
188 if( tmpRequired ) {
189 for( size_t i=0UL; i<(*s).size(); ++i ) {
190 (*s)[i] = stmp[i];
191 }
192 }
193
194 return num;
195}
197//*************************************************************************************************
198
199
200//*************************************************************************************************
222template< typename MT // Type of the matrix A
223 , bool SO // Storage order of the matrix A
224 , typename VT // Type of the vector s
225 , bool TF // Transpose flag of the vector s
226 , typename ST > // Type of the scalar boundary values
227inline auto gesvdx_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s,
228 char range, ST vl, ST vu, blas_int_t il, blas_int_t iu )
229 -> EnableIf_t< IsComplex_v< ElementType_t<MT> >, size_t >
230{
231 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
232 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
233 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
234 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
235 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
236 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
237
238 using CT = ElementType_t<MT>;
239 using BT = UnderlyingElement_t<CT>;
240
241 const size_t M( (*A).rows() );
242 const size_t N( (*A).columns() );
243 const size_t mindim( min( M, N ) );
244
245 blas_int_t m ( numeric_cast<blas_int_t>( SO ? (*A).rows() : (*A).columns() ) );
246 blas_int_t n ( numeric_cast<blas_int_t>( SO ? (*A).columns() : (*A).rows() ) );
247 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
248 blas_int_t ns ( 0 );
249 blas_int_t info( 0 );
250
251 BT* sptr( (*s).data() );
252 std::unique_ptr<BT[]> stmp;
253
254 const bool tmpRequired( (*s).size() < mindim );
255
256 if( tmpRequired ) {
257 stmp.reset( new BT[2UL*mindim] );
258 sptr = stmp.get();
259 }
260
261 const blas_int_t minimum( min( m, n ) );
262
263 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
264 const std::unique_ptr<CT[]> work ( new CT[lwork] );
265 const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
266 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
267
268 gesvdx( 'N', 'N', range, m, n, (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
269 nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), iwork.get(), &info );
270
271 const size_t num( numeric_cast<size_t>( ns ) );
272
273 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
274 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
275
276 if( info > 0 ) {
277 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
278 }
279
280 if( tmpRequired ) {
281 for( size_t i=0UL; i<(*s).size(); ++i ) {
282 (*s)[i] = stmp[i];
283 }
284 }
285
286 return num;
287}
289//*************************************************************************************************
290
291
292//*************************************************************************************************
344template< typename MT // Type of the matrix A
345 , bool SO // Storage order of the matrix A
346 , typename VT // Type of the vector s
347 , bool TF > // Transpose flag of the vector s
349{
355
360
361 using ET = ElementType_t<MT>;
362 using UT = UnderlyingElement_t<ET>;
363
364 const size_t M( (*A).rows() );
365 const size_t N( (*A).columns() );
366 const size_t mindim( min( M, N ) );
367
368 resize( *s, mindim, false );
369
370 if( M == 0UL || N == 0UL ) {
371 return 0;
372 }
373
374 return gesvdx_backend( *A, *s, 'A', UT(), UT(), 0, 0 );
375}
376//*************************************************************************************************
377
378
379//*************************************************************************************************
460template< typename MT // Type of the matrix A
461 , bool SO // Storage order of the matrix A
462 , typename VT // Type of the vector s
463 , bool TF // Transpose flag of the vector s
464 , typename ST > // Type of the scalar boundary values
465inline size_t gesvdx( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, ST low, ST upp )
466{
472
477
479
480 if( IsFloatingPoint_v<ST> && low >= upp ) {
481 BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
482 }
483
484 if( !IsFloatingPoint_v<ST> && low > upp ) {
485 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
486 }
487
488 const size_t M( (*A).rows() );
489 const size_t N( (*A).columns() );
490 const size_t mindim( min( M, N ) );
491 const size_t expected( IsFloatingPoint_v<ST> ? mindim : size_t( upp - low ) + 1UL );
492
493 if( !IsFloatingPoint_v<ST> && expected > mindim ) {
494 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
495 }
496
497 resize( *s, expected, false );
498
499 if( M == 0UL || N == 0UL ) {
500 return 0;
501 }
502
503 const char range( IsFloatingPoint_v<ST> ? 'V' : 'I' );
504 const ST vl ( IsFloatingPoint_v<ST> ? low : ST() );
505 const ST vu ( IsFloatingPoint_v<ST> ? upp : ST() );
506 const blas_int_t il ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( low ) );
507 const blas_int_t iu ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( upp ) );
508
509 const size_t actual( gesvdx_backend( *A, *s, range, vl, vu, il, iu ) );
510
511 if( IsResizable_v<VT> ) {
512 resize( *s, actual, true );
513 }
514
515 return actual;
516}
517//*************************************************************************************************
518
519
520//*************************************************************************************************
543template< typename MT1 // Type of the matrix A
544 , bool SO // Storage order of all matrices
545 , typename MT2 // Type of the matrix U
546 , typename VT // Type of the vector s
547 , bool TF // Transpose flag of the vector s
548 , typename ST > // Type of the scalar boundary values
549inline auto gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
550 char range, ST vl, ST vu, blas_int_t il, blas_int_t iu )
551 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> >, size_t >
552{
553 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
554 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
555 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
556 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
557 BLAZE_INTERNAL_ASSERT( (*U).rows() == (*A).rows() , "Invalid matrix dimension detected" );
558 BLAZE_INTERNAL_ASSERT( (*U).columns() == (*s).size(), "Invalid matrix dimension detected" );
559 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
560 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
561
562 using ET = ElementType_t<MT1>;
563
564 const size_t M( (*A).rows() );
565 const size_t N( (*A).columns() );
566 const size_t mindim( min( M, N ) );
567
568 blas_int_t m ( numeric_cast<blas_int_t>( SO ? M : N ) );
569 blas_int_t n ( numeric_cast<blas_int_t>( SO ? N : M ) );
570 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
571 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
572 blas_int_t ns ( 0 );
573 blas_int_t info( 0 );
574
575 ET* sptr( (*s).data() );
576 ET* uptr( (*U).data() );
577 std::unique_ptr<ET[]> stmp;
578 std::unique_ptr<ET[]> utmp;
579
580 const bool tmpRequired( (*s).size() < mindim );
581
582 if( tmpRequired ) {
583 stmp.reset( new ET[2UL*mindim] );
584 utmp.reset( new ET[M*mindim] );
585 sptr = stmp.get();
586 uptr = utmp.get();
587 }
588
589 const blas_int_t minimum( min( m, n ) );
590
591 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
592 const std::unique_ptr<ET[]> work ( new ET[lwork] );
593 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
594
595 gesvdx( ( SO ? 'V' : 'N' ), ( SO ? 'N' : 'V' ), range, m, n,
596 (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
597 ( SO ? uptr : nullptr ), ( tmpRequired ? m : ( SO ? ldu : 1 ) ),
598 ( SO ? nullptr : uptr ), ( tmpRequired ? mindim : ( SO ? 1 : ldu ) ),
599 work.get(), lwork, iwork.get(), &info );
600
601 const size_t num( numeric_cast<size_t>( ns ) );
602
603 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
604 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
605
606 if( info > 0 ) {
607 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
608 }
609
610 if( tmpRequired )
611 {
612 for( size_t i=0UL; i<(*s).size(); ++i ) {
613 (*s)[i] = stmp[i];
614 }
615
616 if( SO )
617 {
618 for( size_t j=0UL; j<(*U).columns(); ++j ) {
619 for( size_t i=0UL; i<(*U).rows(); ++i ) {
620 (*U)(i,j) = utmp[i+j*M];
621 }
622 }
623 }
624 else
625 {
626 for( size_t i=0UL; i<(*U).rows(); ++i ) {
627 for( size_t j=0UL; j<(*U).columns(); ++j ) {
628 (*U)(i,j) = utmp[i*mindim+j];
629 }
630 }
631 }
632 }
633
634 return num;
635}
637//*************************************************************************************************
638
639
640//*************************************************************************************************
663template< typename MT1 // Type of the matrix A
664 , bool SO // Storage order of all matrices
665 , typename MT2 // Type of the matrix U
666 , typename VT // Type of the vector s
667 , bool TF // Transpose flag of the vector s
668 , typename ST > // Type of the scalar boundary values
669inline auto gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
670 char range, ST vl, ST vu, blas_int_t il, blas_int_t iu )
671 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> >, size_t >
672{
673 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
674 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
675 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
676 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
677 BLAZE_INTERNAL_ASSERT( (*U).rows() == (*A).rows() , "Invalid matrix dimension detected" );
678 BLAZE_INTERNAL_ASSERT( (*U).columns() == (*s).size(), "Invalid matrix dimension detected" );
679 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
680 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
681
682 using CT = ElementType_t<MT1>;
683 using BT = UnderlyingElement_t<CT>;
684
685 const size_t M( (*A).rows() );
686 const size_t N( (*A).columns() );
687 const size_t mindim( min( M, N ) );
688
689 blas_int_t m ( numeric_cast<blas_int_t>( SO ? M : N ) );
690 blas_int_t n ( numeric_cast<blas_int_t>( SO ? N : M ) );
691 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
692 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
693 blas_int_t ns ( 0 );
694 blas_int_t info( 0 );
695
696 BT* sptr( (*s).data() );
697 CT* uptr( (*U).data() );
698 std::unique_ptr<BT[]> stmp;
699 std::unique_ptr<CT[]> utmp;
700
701 const bool tmpRequired( (*s).size() < mindim );
702
703 if( tmpRequired ) {
704 stmp.reset( new BT[2UL*mindim] );
705 utmp.reset( new CT[M*mindim] );
706 sptr = stmp.get();
707 uptr = utmp.get();
708 }
709
710 const blas_int_t minimum( min( m, n ) );
711
712 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
713 const std::unique_ptr<CT[]> work ( new CT[lwork] );
714 const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
715 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
716
717 gesvdx( ( SO ? 'V' : 'N' ), ( SO ? 'N' : 'V' ), range, m, n,
718 (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
719 ( SO ? uptr : nullptr ), ( tmpRequired ? m : ( SO ? ldu : 1 ) ),
720 ( SO ? nullptr : uptr ), ( tmpRequired ? mindim : ( SO ? 1 : ldu ) ),
721 work.get(), lwork, rwork.get(), iwork.get(), &info );
722
723 const size_t num( numeric_cast<size_t>( ns ) );
724
725 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
726 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
727
728 if( info > 0 ) {
729 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
730 }
731
732 if( tmpRequired )
733 {
734 for( size_t i=0UL; i<(*s).size(); ++i ) {
735 (*s)[i] = stmp[i];
736 }
737
738 if( SO )
739 {
740 for( size_t j=0UL; j<(*U).columns(); ++j ) {
741 for( size_t i=0UL; i<(*U).rows(); ++i ) {
742 (*U)(i,j) = utmp[i+j*M];
743 }
744 }
745 }
746 else
747 {
748 for( size_t i=0UL; i<(*U).rows(); ++i ) {
749 for( size_t j=0UL; j<(*U).columns(); ++j ) {
750 (*U)(i,j) = utmp[i*mindim+j];
751 }
752 }
753 }
754 }
755
756 return num;
757}
759//*************************************************************************************************
760
761
762//*************************************************************************************************
819template< typename MT1 // Type of the matrix A
820 , bool SO // Storage order of all matrices
821 , typename MT2 // Type of the matrix U
822 , typename VT // Type of the vector s
823 , bool TF > // Transpose flag of the vector s
825{
831
837
842
843 using ET = ElementType_t<MT1>;
844 using UT = UnderlyingElement_t<ET>;
845
846 const size_t M( (*A).rows() );
847 const size_t N( (*A).columns() );
848 const size_t mindim( min( M, N ) );
849
850 resize( *s, mindim, false );
851 resize( *U, M, mindim, false );
852
853 if( M == 0UL || N == 0UL ) {
854 return 0;
855 }
856
857 return gesvdx_backend( *A, *U, *s, 'A', UT(), UT(), 0, 0 );
858}
859//*************************************************************************************************
860
861
862//*************************************************************************************************
952template< typename MT1 // Type of the matrix A
953 , bool SO // Storage order of all matrices
954 , typename MT2 // Type of the matrix U
955 , typename VT // Type of the vector s
956 , bool TF // Transpose flag of the vector s
957 , typename ST > // Type of the scalar boundary values
959 DenseVector<VT,TF>& s, ST low, ST upp )
960{
966
972
977
979
980 if( IsFloatingPoint_v<ST> && low >= upp ) {
981 BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
982 }
983
984 if( !IsFloatingPoint_v<ST> && low > upp ) {
985 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
986 }
987
988 const size_t M( (*A).rows() );
989 const size_t N( (*A).columns() );
990 const size_t mindim( min( M, N ) );
991 const size_t expected( IsFloatingPoint_v<ST> ? mindim : size_t( upp - low ) + 1UL );
992
993 if( !IsFloatingPoint_v<ST> && expected > mindim ) {
994 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
995 }
996
997 resize( *s, expected, false );
998 resize( *U, M, expected, false );
999
1000 if( M == 0UL || N == 0UL ) {
1001 return 0;
1002 }
1003
1004 const char range( IsFloatingPoint_v<ST> ? 'V' : 'I' );
1005 const ST vl ( IsFloatingPoint_v<ST> ? low : ST() );
1006 const ST vu ( IsFloatingPoint_v<ST> ? upp : ST() );
1007 const blas_int_t il ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( low ) );
1008 const blas_int_t iu ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( upp ) );
1009
1010 const size_t actual( gesvdx_backend( *A, *U, *s, range, vl, vu, il, iu ) );
1011
1012 if( IsResizable_v<VT> ) {
1013 resize( *s, actual, true );
1014 }
1015
1016 if( IsResizable_v<MT2> ) {
1017 resize( *U, M, actual, true );
1018 }
1019
1020 return actual;
1021}
1022//*************************************************************************************************
1023
1024
1025//*************************************************************************************************
1048template< typename MT1 // Type of the matrix A
1049 , bool SO // Storage order of all matrices
1050 , typename VT // Type of the vector s
1051 , bool TF // Transpose flag of the vector s
1052 , typename MT2 // Type of the matrix V
1053 , typename ST > // Type of the scalar boundary values
1054inline auto gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V,
1055 char range, ST vl, ST vu, blas_int_t il, blas_int_t iu )
1056 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> >, size_t >
1057{
1058 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1059 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1060 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1061 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1062 BLAZE_INTERNAL_ASSERT( (*V).rows() == (*s).size() , "Invalid matrix dimension detected" );
1063 BLAZE_INTERNAL_ASSERT( (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
1064 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1065 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1066
1067 using ET = ElementType_t<MT1>;
1068
1069 const size_t M( (*A).rows() );
1070 const size_t N( (*A).columns() );
1071 const size_t mindim( min( M, N ) );
1072
1073 blas_int_t m ( numeric_cast<blas_int_t>( SO ? M : N ) );
1074 blas_int_t n ( numeric_cast<blas_int_t>( SO ? N : M ) );
1075 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
1076 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
1077 blas_int_t ns ( 0 );
1078 blas_int_t info( 0 );
1079
1080 ET* sptr( (*s).data() );
1081 ET* vptr( (*V).data() );
1082 std::unique_ptr<ET[]> stmp;
1083 std::unique_ptr<ET[]> vtmp;
1084
1085 const bool tmpRequired( (*s).size() < mindim );
1086
1087 if( tmpRequired ) {
1088 stmp.reset( new ET[2UL*mindim] );
1089 vtmp.reset( new ET[mindim*N] );
1090 sptr = stmp.get();
1091 vptr = vtmp.get();
1092 }
1093
1094 const blas_int_t minimum( min( m, n ) );
1095
1096 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
1097 const std::unique_ptr<ET[]> work ( new ET[lwork] );
1098 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
1099
1100 gesvdx( ( SO ? 'N' : 'V' ), ( SO ? 'V' : 'N' ), range, m, n,
1101 (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
1102 ( SO ? nullptr : vptr ), ( tmpRequired ? m : ( SO ? 1 : ldv ) ),
1103 ( SO ? vptr : nullptr ), ( tmpRequired ? mindim : ( SO ? ldv : 1 ) ),
1104 work.get(), lwork, iwork.get(), &info );
1105
1106 const size_t num( numeric_cast<size_t>( ns ) );
1107
1108 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1109 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
1110
1111 if( info > 0 ) {
1112 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1113 }
1114
1115 if( tmpRequired )
1116 {
1117 for( size_t i=0UL; i<(*s).size(); ++i ) {
1118 (*s)[i] = stmp[i];
1119 }
1120
1121 if( SO )
1122 {
1123 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1124 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1125 (*V)(i,j) = vtmp[i+j*mindim];
1126 }
1127 }
1128 }
1129 else
1130 {
1131 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1132 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1133 (*V)(i,j) = vtmp[i*N+j];
1134 }
1135 }
1136 }
1137 }
1138
1139 return num;
1140}
1142//*************************************************************************************************
1143
1144
1145//*************************************************************************************************
1168template< typename MT1 // Type of the matrix A
1169 , bool SO // Storage order of all matrices
1170 , typename VT // Type of the vector s
1171 , bool TF // Transpose flag of the vector s
1172 , typename MT2 // Type of the matrix V
1173 , typename ST > // Type of the scalar boundary values
1174inline auto gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V,
1175 char range, ST vl, ST vu, blas_int_t il, blas_int_t iu )
1176 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> >, size_t >
1177{
1178 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1179 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1180 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1181 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1182 BLAZE_INTERNAL_ASSERT( (*V).rows() == (*s).size() , "Invalid matrix dimension detected" );
1183 BLAZE_INTERNAL_ASSERT( (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
1184 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1185 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1186
1187 using CT = ElementType_t<MT1>;
1188 using BT = UnderlyingElement_t<CT>;
1189
1190 const size_t M( (*A).rows() );
1191 const size_t N( (*A).columns() );
1192 const size_t mindim( min( M, N ) );
1193
1194 blas_int_t m ( numeric_cast<blas_int_t>( SO ? M : N ) );
1195 blas_int_t n ( numeric_cast<blas_int_t>( SO ? N : M ) );
1196 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
1197 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
1198 blas_int_t ns ( 0 );
1199 blas_int_t info( 0 );
1200
1201 BT* sptr( (*s).data() );
1202 CT* vptr( (*V).data() );
1203 std::unique_ptr<BT[]> stmp;
1204 std::unique_ptr<CT[]> vtmp;
1205
1206 const bool tmpRequired( (*s).size() < mindim );
1207
1208 if( tmpRequired ) {
1209 stmp.reset( new BT[2UL*mindim] );
1210 vtmp.reset( new CT[mindim*N] );
1211 sptr = stmp.get();
1212 vptr = vtmp.get();
1213 }
1214
1215 const blas_int_t minimum( min( m, n ) );
1216
1217 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
1218 const std::unique_ptr<CT[]> work ( new CT[lwork] );
1219 const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
1220 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
1221
1222 gesvdx( ( SO ? 'N' : 'V' ), ( SO ? 'V' : 'N' ), range, m, n,
1223 (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
1224 ( SO ? nullptr : vptr ), ( tmpRequired ? m : ( SO ? 1 : ldv ) ),
1225 ( SO ? vptr : nullptr ), ( tmpRequired ? mindim : ( SO ? ldv : 1 ) ),
1226 work.get(), lwork, rwork.get(), iwork.get(), &info );
1227
1228 const size_t num( numeric_cast<size_t>( ns ) );
1229
1230 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1231 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
1232
1233 if( info > 0 ) {
1234 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1235 }
1236
1237 if( tmpRequired )
1238 {
1239 for( size_t i=0UL; i<(*s).size(); ++i ) {
1240 (*s)[i] = stmp[i];
1241 }
1242
1243 if( SO )
1244 {
1245 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1246 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1247 (*V)(i,j) = vtmp[i+j*mindim];
1248 }
1249 }
1250 }
1251 else
1252 {
1253 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1254 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1255 (*V)(i,j) = vtmp[i*N+j];
1256 }
1257 }
1258 }
1259 }
1260
1261 return num;
1262}
1264//*************************************************************************************************
1265
1266
1267//*************************************************************************************************
1324template< typename MT1 // Type of the matrix A
1325 , bool SO // Storage order of all matrices
1326 , typename VT // Type of the vector s
1327 , bool TF // Transpose flag of the vector s
1328 , typename MT2 > // Type of the matrix V
1330{
1336
1341
1347
1348 using ET = ElementType_t<MT1>;
1349 using UT = UnderlyingElement_t<ET>;
1350
1351 const size_t M( (*A).rows() );
1352 const size_t N( (*A).columns() );
1353 const size_t mindim( min( M, N ) );
1354
1355 resize( *s, mindim, false );
1356 resize( *V, mindim, N, false );
1357
1358 if( M == 0UL || N == 0UL ) {
1359 return 0;
1360 }
1361
1362 return gesvdx_backend( *A, *s, *V, 'A', UT(), UT(), 0, 0 );
1363}
1364//*************************************************************************************************
1365
1366
1367//*************************************************************************************************
1457template< typename MT1 // Type of the matrix A
1458 , bool SO // Storage order of all matrices
1459 , typename VT // Type of the vector s
1460 , bool TF // Transpose flag of the vector s
1461 , typename MT2 // Type of the matrix V
1462 , typename ST > // Type of the scalar boundary values
1464 DenseMatrix<MT2,SO>& V, ST low, ST upp )
1465{
1471
1476
1482
1484
1485 if( IsFloatingPoint_v<ST> && low >= upp ) {
1486 BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
1487 }
1488
1489 if( !IsFloatingPoint_v<ST> && low > upp ) {
1490 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
1491 }
1492
1493 const size_t M( (*A).rows() );
1494 const size_t N( (*A).columns() );
1495 const size_t mindim( min( M, N ) );
1496 const size_t expected( IsFloatingPoint_v<ST> ? mindim : size_t( upp - low ) + 1UL );
1497
1498 if( !IsFloatingPoint_v<ST> && expected > mindim ) {
1499 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
1500 }
1501
1502 resize( *s, expected, false );
1503 resize( *V, expected, N, false );
1504
1505 if( M == 0UL || N == 0UL ) {
1506 return 0;
1507 }
1508
1509 const char range( IsFloatingPoint_v<ST> ? 'V' : 'I' );
1510 const ST vl ( IsFloatingPoint_v<ST> ? low : ST() );
1511 const ST vu ( IsFloatingPoint_v<ST> ? upp : ST() );
1512 const blas_int_t il ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( low ) );
1513 const blas_int_t iu ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( upp ) );
1514
1515 const size_t actual( gesvdx_backend( *A, *s, *V, range, vl, vu, il, iu ) );
1516
1517 if( IsResizable_v<VT> ) {
1518 resize( *s, actual, true );
1519 }
1520
1521 if( IsResizable_v<MT2> ) {
1522 resize( *V, actual, N, true );
1523 }
1524
1525 return actual;
1526}
1527//*************************************************************************************************
1528
1529
1530//*************************************************************************************************
1554template< typename MT1 // Type of the matrix A
1555 , bool SO // Storage order of all matrices
1556 , typename MT2 // Type of the matrix U
1557 , typename VT // Type of the vector s
1558 , bool TF // Transpose flag of the vector s
1559 , typename MT3 // Type of the matrix V
1560 , typename ST > // Type of the scalar boundary values
1561inline auto gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
1562 DenseMatrix<MT3,SO>& V, char range, ST vl, ST vu,
1563 blas_int_t il, blas_int_t iu )
1564 -> DisableIf_t< IsComplex_v< ElementType_t<MT1> >, size_t >
1565{
1566 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1567 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1568 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1569 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1570 BLAZE_INTERNAL_ASSERT( (*U).rows() == (*A).rows() , "Invalid matrix dimension detected" );
1571 BLAZE_INTERNAL_ASSERT( (*U).columns() == (*s).size() , "Invalid matrix dimension detected" );
1572 BLAZE_INTERNAL_ASSERT( (*V).rows() == (*s).size() , "Invalid matrix dimension detected" );
1573 BLAZE_INTERNAL_ASSERT( (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
1574 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1575 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1576
1577 using ET = ElementType_t<MT1>;
1578
1579 const size_t M( (*A).rows() );
1580 const size_t N( (*A).columns() );
1581 const size_t mindim( min( M, N ) );
1582
1583 blas_int_t m ( numeric_cast<blas_int_t>( SO ? M : N ) );
1584 blas_int_t n ( numeric_cast<blas_int_t>( SO ? N : M ) );
1585 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
1586 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
1587 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
1588 blas_int_t ns ( 0 );
1589 blas_int_t info( 0 );
1590
1591 ET* sptr( (*s).data() );
1592 ET* uptr( (*U).data() );
1593 ET* vptr( (*V).data() );
1594 std::unique_ptr<ET[]> stmp;
1595 std::unique_ptr<ET[]> utmp;
1596 std::unique_ptr<ET[]> vtmp;
1597
1598 const bool tmpRequired( (*s).size() < mindim );
1599
1600 if( tmpRequired ) {
1601 stmp.reset( new ET[2UL*mindim] );
1602 utmp.reset( new ET[M*mindim] );
1603 vtmp.reset( new ET[mindim*N] );
1604 sptr = stmp.get();
1605 uptr = utmp.get();
1606 vptr = vtmp.get();
1607 }
1608
1609 const blas_int_t minimum( min( m, n ) );
1610
1611 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
1612 const std::unique_ptr<ET[]> work ( new ET[lwork] );
1613 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
1614
1615 gesvdx( 'V', 'V', range, m, n, (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
1616 ( SO ? uptr : vptr ), ( tmpRequired ? m : ( SO ? ldu : ldv ) ),
1617 ( SO ? vptr : uptr ), ( tmpRequired ? mindim : ( SO ? ldv : ldu ) ),
1618 work.get(), lwork, iwork.get(), &info );
1619
1620 const size_t num( numeric_cast<size_t>( ns ) );
1621
1622 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1623 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
1624
1625 if( info > 0 ) {
1626 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1627 }
1628
1629 if( tmpRequired )
1630 {
1631 for( size_t i=0UL; i<(*s).size(); ++i ) {
1632 (*s)[i] = stmp[i];
1633 }
1634
1635 if( SO )
1636 {
1637 for( size_t j=0UL; j<(*U).columns(); ++j ) {
1638 for( size_t i=0UL; i<(*U).rows(); ++i ) {
1639 (*U)(i,j) = utmp[i+j*M];
1640 }
1641 }
1642
1643 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1644 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1645 (*V)(i,j) = vtmp[i+j*mindim];
1646 }
1647 }
1648 }
1649 else
1650 {
1651 for( size_t i=0UL; i<(*U).rows(); ++i ) {
1652 for( size_t j=0UL; j<(*U).columns(); ++j ) {
1653 (*U)(i,j) = utmp[i*mindim+j];
1654 }
1655 }
1656
1657 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1658 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1659 (*V)(i,j) = vtmp[i*N+j];
1660 }
1661 }
1662 }
1663 }
1664
1665 return num;
1666}
1668//*************************************************************************************************
1669
1670
1671//*************************************************************************************************
1695template< typename MT1 // Type of the matrix A
1696 , bool SO // Storage order of all matrices
1697 , typename MT2 // Type of the matrix U
1698 , typename VT // Type of the vector s
1699 , bool TF // Transpose flag of the vector s
1700 , typename MT3 // Type of the matrix V
1701 , typename ST > // Type of the scalar boundary values
1702inline auto gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
1703 DenseMatrix<MT3,SO>& V, char range, ST vl, ST vu,
1704 blas_int_t il, blas_int_t iu )
1705 -> EnableIf_t< IsComplex_v< ElementType_t<MT1> >, size_t >
1706{
1707 BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1708 BLAZE_INTERNAL_ASSERT( range != 'A' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1709 BLAZE_INTERNAL_ASSERT( range != 'V' || (*s).size() == min( (*A).rows(), (*A).columns() ), "Invalid vector dimension detected" );
1710 BLAZE_INTERNAL_ASSERT( range != 'I' || (*s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1711 BLAZE_INTERNAL_ASSERT( (*U).rows() == (*A).rows() , "Invalid matrix dimension detected" );
1712 BLAZE_INTERNAL_ASSERT( (*U).columns() == (*s).size() , "Invalid matrix dimension detected" );
1713 BLAZE_INTERNAL_ASSERT( (*V).rows() == (*s).size() , "Invalid matrix dimension detected" );
1714 BLAZE_INTERNAL_ASSERT( (*V).columns() == (*A).columns(), "Invalid matrix dimension detected" );
1715 BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1716 BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1717
1718 using CT = ElementType_t<MT1>;
1719 using BT = UnderlyingElement_t<CT>;
1720
1721 const size_t M( (*A).rows() );
1722 const size_t N( (*A).columns() );
1723 const size_t mindim( min( M, N ) );
1724
1725 blas_int_t m ( numeric_cast<blas_int_t>( SO ? M : N ) );
1726 blas_int_t n ( numeric_cast<blas_int_t>( SO ? N : M ) );
1727 blas_int_t lda ( numeric_cast<blas_int_t>( (*A).spacing() ) );
1728 blas_int_t ldu ( numeric_cast<blas_int_t>( (*U).spacing() ) );
1729 blas_int_t ldv ( numeric_cast<blas_int_t>( (*V).spacing() ) );
1730 blas_int_t ns ( 0 );
1731 blas_int_t info( 0 );
1732
1733 BT* sptr( (*s).data() );
1734 CT* uptr( (*U).data() );
1735 CT* vptr( (*V).data() );
1736 std::unique_ptr<BT[]> stmp;
1737 std::unique_ptr<CT[]> utmp;
1738 std::unique_ptr<CT[]> vtmp;
1739
1740 const bool tmpRequired( (*s).size() < mindim );
1741
1742 if( tmpRequired ) {
1743 stmp.reset( new BT[2UL*mindim] );
1744 utmp.reset( new CT[M*mindim] );
1745 vtmp.reset( new CT[mindim*N] );
1746 sptr = stmp.get();
1747 uptr = utmp.get();
1748 vptr = vtmp.get();
1749 }
1750
1751 const blas_int_t minimum( min( m, n ) );
1752
1753 blas_int_t lwork( minimum*( minimum*3 + 20 ) + 2 );
1754 const std::unique_ptr<CT[]> work ( new CT[lwork] );
1755 const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
1756 const std::unique_ptr<blas_int_t[]> iwork( new blas_int_t[12*minimum] );
1757
1758 gesvdx( 'V', 'V', range, m, n, (*A).data(), lda, vl, vu, il, iu, &ns, sptr,
1759 ( SO ? uptr : vptr ), ( tmpRequired ? m : ( SO ? ldu : ldv ) ),
1760 ( SO ? vptr : uptr ), ( tmpRequired ? mindim : ( SO ? ldv : ldu ) ),
1761 work.get(), lwork, rwork.get(), iwork.get(), &info );
1762
1763 const size_t num( numeric_cast<size_t>( ns ) );
1764
1765 BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1766 BLAZE_INTERNAL_ASSERT( num <= (*s).size(), "Invalid number of singular values detected" );
1767
1768 if( info > 0 ) {
1769 BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1770 }
1771
1772 if( tmpRequired )
1773 {
1774 for( size_t i=0UL; i<(*s).size(); ++i ) {
1775 (*s)[i] = stmp[i];
1776 }
1777
1778 if( SO )
1779 {
1780 for( size_t j=0UL; j<(*U).columns(); ++j ) {
1781 for( size_t i=0UL; i<(*U).rows(); ++i ) {
1782 (*U)(i,j) = utmp[i+j*M];
1783 }
1784 }
1785
1786 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1787 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1788 (*V)(i,j) = vtmp[i+j*mindim];
1789 }
1790 }
1791 }
1792 else
1793 {
1794 for( size_t i=0UL; i<(*U).rows(); ++i ) {
1795 for( size_t j=0UL; j<(*U).columns(); ++j ) {
1796 (*U)(i,j) = utmp[i*mindim+j];
1797 }
1798 }
1799
1800 for( size_t i=0UL; i<(*V).rows(); ++i ) {
1801 for( size_t j=0UL; j<(*V).columns(); ++j ) {
1802 (*V)(i,j) = vtmp[i*N+j];
1803 }
1804 }
1805 }
1806 }
1807
1808 return num;
1809}
1811//*************************************************************************************************
1812
1813
1814//*************************************************************************************************
1875template< typename MT1 // Type of the matrix A
1876 , bool SO // Storage order of all matrices
1877 , typename MT2 // Type of the matrix U
1878 , typename VT // Type of the vector s
1879 , bool TF // Transpose flag of the vector s
1880 , typename MT3 > // Type of the matrix V
1883{
1889
1895
1900
1906
1907 using ET = ElementType_t<MT1>;
1908 using UT = UnderlyingElement_t<ET>;
1909
1910 const size_t M( (*A).rows() );
1911 const size_t N( (*A).columns() );
1912 const size_t mindim( min( M, N ) );
1913
1914 resize( *s, mindim, false );
1915 resize( *U, M, mindim, false );
1916 resize( *V, mindim, N, false );
1917
1918 if( M == 0UL || N == 0UL ) {
1919 return 0;
1920 }
1921
1922 return gesvdx_backend( *A, *U, *s, *V, 'A', UT(), UT(), 0, 0 );
1923}
1924//*************************************************************************************************
1925
1926
1927//*************************************************************************************************
2024template< typename MT1 // Type of the matrix A
2025 , bool SO // Storage order of all matrices
2026 , typename MT2 // Type of the matrix U
2027 , typename VT // Type of the vector s
2028 , bool TF // Transpose flag of the vector s
2029 , typename MT3 // Type of the matrix V
2030 , typename ST > // Type of the scalar boundary values
2032 DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, ST low, ST upp )
2033{
2039
2045
2050
2056
2058
2059 if( IsFloatingPoint_v<ST> && low >= upp ) {
2060 BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
2061 }
2062
2063 if( !IsFloatingPoint_v<ST> && low > upp ) {
2064 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
2065 }
2066
2067 const size_t M( (*A).rows() );
2068 const size_t N( (*A).columns() );
2069 const size_t mindim( min( M, N ) );
2070 const size_t expected( IsFloatingPoint_v<ST> ? mindim : size_t( upp - low ) + 1UL );
2071
2072 if( !IsFloatingPoint_v<ST> && expected > mindim ) {
2073 BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
2074 }
2075
2076 resize( *s, expected, false );
2077 resize( *U, M, expected, false );
2078 resize( *V, expected, N, false );
2079
2080 if( M == 0UL || N == 0UL ) {
2081 return 0;
2082 }
2083
2084 const char range( IsFloatingPoint_v<ST> ? 'V' : 'I' );
2085 const ST vl ( IsFloatingPoint_v<ST> ? low : ST() );
2086 const ST vu ( IsFloatingPoint_v<ST> ? upp : ST() );
2087 const blas_int_t il ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( low ) );
2088 const blas_int_t iu ( IsFloatingPoint_v<ST> ? 0 : numeric_cast<blas_int_t>( upp ) );
2089
2090 const size_t actual( gesvdx_backend( *A, *U, *s, *V, range, vl, vu, il, iu ) );
2091
2092 if( IsResizable_v<VT> ) {
2093 resize( *s, actual, true );
2094 }
2095
2096 if( IsResizable_v<MT2> ) {
2097 resize( *U, M, actual, true );
2098 }
2099
2100 if( IsResizable_v<MT3> ) {
2101 resize( *V, actual, N, true );
2102 }
2103
2104 return actual;
2105}
2106//*************************************************************************************************
2107
2108} // namespace blaze
2109
2110#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.
Constraint on the data type.
Header file for the EnableIf class template.
Header file for the IsComplex type trait.
Header file for the IsFloatingPoint type trait.
Header file for the IsResizable type trait.
Constraint on the data type.
Cast operators for numeric types.
Header file for the UnderlyingElement type trait.
Header file for the CLAPACK gesvdx 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.
#define BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE(T)
Constraint on the data type.
Definition: Builtin.h:60
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
size_t gesvdx(DenseMatrix< MT1, SO > &A, DenseMatrix< MT2, SO > &U, DenseVector< VT, TF > &s, DenseMatrix< MT3, SO > &V, ST low, ST upp)
LAPACK kernel for the singular value decomposition (SVD) of the given dense general matrix.
Definition: gesvdx.h:2031
#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
typename UnderlyingElement< T >::Type UnderlyingElement_t
Auxiliary alias declaration for the UnderlyingElement type trait.
Definition: UnderlyingElement.h:119
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
#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 Size type trait.
Header file for basic type definitions.
Header file for the generic min algorithm.
Header file for the implementation of the Subvector view.