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>
49 #include <blaze/math/Exception.h>
58 #include <blaze/util/Assert.h>
60 #include <blaze/util/DisableIf.h>
61 #include <blaze/util/EnableIf.h>
62 #include <blaze/util/NumericCast.h>
63 #include <blaze/util/Types.h>
66 
67 
68 namespace blaze {
69 
70 //=================================================================================================
71 //
72 // LAPACK SVD FUNCTIONS (GESVDX)
73 //
74 //=================================================================================================
75 
76 //*************************************************************************************************
79 template< typename MT, bool SO, typename VT, bool TF >
80 inline size_t gesvdx( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s );
81 
82 template< typename MT, bool SO, typename VT, bool TF, typename ST >
83 inline size_t gesvdx( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, ST low, ST upp );
84 
85 template< typename MT1, bool SO, typename MT2, typename VT, bool TF >
86 inline size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s );
87 
88 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename ST >
89 inline size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
90  DenseVector<VT,TF>& s, ST low, ST upp );
91 
92 template< typename MT1, bool SO, typename VT, bool TF, typename MT2 >
93 inline size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V );
94 
95 template< typename MT1, bool SO, typename VT, bool TF, typename MT2, typename ST >
96 inline size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s,
97  DenseMatrix<MT2,SO>& V, ST low, ST upp );
98 
99 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3 >
100 inline size_t gesvdx( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U,
101  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V );
102 
103 template< typename MT1, bool SO, typename MT2, typename VT, bool TF, typename MT3, typename ST >
104 inline size_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 //*************************************************************************************************
132 template< 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
137 inline DisableIf_< IsComplex< ElementType_<MT> >, size_t >
138  gesvdx_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s,
139  char range, ST vl, ST vu, int il, int iu )
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_<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  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
155  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
156  int lda ( numeric_cast<int>( (~A).spacing() ) );
157  int ns ( 0 );
158  int 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 int minimum( min( m, n ) );
171 
172  int lwork( minimum*( minimum*3 + 20 ) + 2 );
173  const std::unique_ptr<ET[]> work ( new ET[lwork] );
174  const std::unique_ptr<int[]> iwork( new int[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 //*************************************************************************************************
222 template< 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
227 inline EnableIf_< IsComplex< ElementType_<MT> >, size_t >
228  gesvdx_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s,
229  char range, ST vl, ST vu, int il, int iu )
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_<MT>;
239  using BT = UnderlyingElement_<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  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
246  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
247  int lda ( numeric_cast<int>( (~A).spacing() ) );
248  int ns ( 0 );
249  int 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 int minimum( min( m, n ) );
262 
263  int 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<int[]> iwork( new int[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 //*************************************************************************************************
344 template< 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 {
354 
358 
359  using ET = ElementType_<MT>;
360  using UT = UnderlyingElement_<ET>;
361 
362  const size_t M( (~A).rows() );
363  const size_t N( (~A).columns() );
364  const size_t mindim( min( M, N ) );
365 
366  resize( ~s, mindim, false );
367 
368  if( M == 0UL || N == 0UL ) {
369  return 0;
370  }
371 
372  return gesvdx_backend( ~A, ~s, 'A', UT(), UT(), 0, 0 );
373 }
374 //*************************************************************************************************
375 
376 
377 //*************************************************************************************************
458 template< typename MT // Type of the matrix A
459  , bool SO // Storage order of the matrix A
460  , typename VT // Type of the vector s
461  , bool TF // Transpose flag of the vector s
462  , typename ST > // Type of the scalar boundary values
463 inline size_t gesvdx( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, ST low, ST upp )
464 {
469 
473 
475 
476  if( IsFloatingPoint<ST>::value && low >= upp ) {
477  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
478  }
479 
480  if( !IsFloatingPoint<ST>::value && low > upp ) {
481  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
482  }
483 
484  const size_t M( (~A).rows() );
485  const size_t N( (~A).columns() );
486  const size_t mindim( min( M, N ) );
487  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
488 
489  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
490  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
491  }
492 
493  resize( ~s, expected, false );
494 
495  if( M == 0UL || N == 0UL ) {
496  return 0;
497  }
498 
499  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
500  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
501  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
502  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
503  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
504 
505  const size_t actual( gesvdx_backend( ~A, ~s, range, vl, vu, il, iu ) );
506 
507  if( IsResizable<VT>::value ) {
508  resize( ~s, actual, true );
509  }
510 
511  return actual;
512 }
513 //*************************************************************************************************
514 
515 
516 //*************************************************************************************************
539 template< typename MT1 // Type of the matrix A
540  , bool SO // Storage order of all matrices
541  , typename MT2 // Type of the matrix U
542  , typename VT // Type of the vector s
543  , bool TF // Transpose flag of the vector s
544  , typename ST > // Type of the scalar boundary values
547  char range, ST vl, ST vu, int il, int iu )
548 {
549  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
550  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
551  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
552  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
553  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
554  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size(), "Invalid matrix dimension detected" );
555  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
556  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
557 
558  using ET = ElementType_<MT1>;
559 
560  const size_t M( (~A).rows() );
561  const size_t N( (~A).columns() );
562  const size_t mindim( min( M, N ) );
563 
564  int m ( numeric_cast<int>( SO ? M : N ) );
565  int n ( numeric_cast<int>( SO ? N : M ) );
566  int lda ( numeric_cast<int>( (~A).spacing() ) );
567  int ldu ( numeric_cast<int>( (~U).spacing() ) );
568  int ns ( 0 );
569  int info( 0 );
570 
571  ET* sptr( (~s).data() );
572  ET* uptr( (~U).data() );
573  std::unique_ptr<ET[]> stmp;
574  std::unique_ptr<ET[]> utmp;
575 
576  const bool tmpRequired( (~s).size() < mindim );
577 
578  if( tmpRequired ) {
579  stmp.reset( new ET[2UL*mindim] );
580  utmp.reset( new ET[M*mindim] );
581  sptr = stmp.get();
582  uptr = utmp.get();
583  }
584 
585  const int minimum( min( m, n ) );
586 
587  int lwork( minimum*( minimum*3 + 20 ) + 2 );
588  const std::unique_ptr<ET[]> work ( new ET[lwork] );
589  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
590 
591  gesvdx( ( SO ? 'V' : 'N' ), ( SO ? 'N' : 'V' ), range, m, n,
592  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
593  ( SO ? uptr : nullptr ), ( tmpRequired ? m : ( SO ? ldu : 1 ) ),
594  ( SO ? nullptr : uptr ), ( tmpRequired ? mindim : ( SO ? 1 : ldu ) ),
595  work.get(), lwork, iwork.get(), &info );
596 
597  const size_t num( numeric_cast<size_t>( ns ) );
598 
599  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
600  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
601 
602  if( info > 0 ) {
603  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
604  }
605 
606  if( tmpRequired )
607  {
608  for( size_t i=0UL; i<(~s).size(); ++i ) {
609  (~s)[i] = stmp[i];
610  }
611 
612  if( SO )
613  {
614  for( size_t j=0UL; j<(~U).columns(); ++j ) {
615  for( size_t i=0UL; i<(~U).rows(); ++i ) {
616  (~U)(i,j) = utmp[i+j*M];
617  }
618  }
619  }
620  else
621  {
622  for( size_t i=0UL; i<(~U).rows(); ++i ) {
623  for( size_t j=0UL; j<(~U).columns(); ++j ) {
624  (~U)(i,j) = utmp[i*mindim+j];
625  }
626  }
627  }
628  }
629 
630  return num;
631 }
633 //*************************************************************************************************
634 
635 
636 //*************************************************************************************************
659 template< typename MT1 // Type of the matrix A
660  , bool SO // Storage order of all matrices
661  , typename MT2 // Type of the matrix U
662  , typename VT // Type of the vector s
663  , bool TF // Transpose flag of the vector s
664  , typename ST > // Type of the scalar boundary values
667  char range, ST vl, ST vu, int il, int iu )
668 {
669  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
670  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
671  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
672  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
673  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
674  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size(), "Invalid matrix dimension detected" );
675  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
676  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
677 
678  using CT = ElementType_<MT1>;
679  using BT = UnderlyingElement_<CT>;
680 
681  const size_t M( (~A).rows() );
682  const size_t N( (~A).columns() );
683  const size_t mindim( min( M, N ) );
684 
685  int m ( numeric_cast<int>( SO ? M : N ) );
686  int n ( numeric_cast<int>( SO ? N : M ) );
687  int lda ( numeric_cast<int>( (~A).spacing() ) );
688  int ldu ( numeric_cast<int>( (~U).spacing() ) );
689  int ns ( 0 );
690  int info( 0 );
691 
692  BT* sptr( (~s).data() );
693  CT* uptr( (~U).data() );
694  std::unique_ptr<BT[]> stmp;
695  std::unique_ptr<CT[]> utmp;
696 
697  const bool tmpRequired( (~s).size() < mindim );
698 
699  if( tmpRequired ) {
700  stmp.reset( new BT[2UL*mindim] );
701  utmp.reset( new CT[M*mindim] );
702  sptr = stmp.get();
703  uptr = utmp.get();
704  }
705 
706  const int minimum( min( m, n ) );
707 
708  int lwork( minimum*( minimum*3 + 20 ) + 2 );
709  const std::unique_ptr<CT[]> work ( new CT[lwork] );
710  const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
711  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
712 
713  gesvdx( ( SO ? 'V' : 'N' ), ( SO ? 'N' : 'V' ), range, m, n,
714  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
715  ( SO ? uptr : nullptr ), ( tmpRequired ? m : ( SO ? ldu : 1 ) ),
716  ( SO ? nullptr : uptr ), ( tmpRequired ? mindim : ( SO ? 1 : ldu ) ),
717  work.get(), lwork, rwork.get(), iwork.get(), &info );
718 
719  const size_t num( numeric_cast<size_t>( ns ) );
720 
721  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
722  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
723 
724  if( info > 0 ) {
725  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
726  }
727 
728  if( tmpRequired )
729  {
730  for( size_t i=0UL; i<(~s).size(); ++i ) {
731  (~s)[i] = stmp[i];
732  }
733 
734  if( SO )
735  {
736  for( size_t j=0UL; j<(~U).columns(); ++j ) {
737  for( size_t i=0UL; i<(~U).rows(); ++i ) {
738  (~U)(i,j) = utmp[i+j*M];
739  }
740  }
741  }
742  else
743  {
744  for( size_t i=0UL; i<(~U).rows(); ++i ) {
745  for( size_t j=0UL; j<(~U).columns(); ++j ) {
746  (~U)(i,j) = utmp[i*mindim+j];
747  }
748  }
749  }
750  }
751 
752  return num;
753 }
755 //*************************************************************************************************
756 
757 
758 //*************************************************************************************************
815 template< typename MT1 // Type of the matrix A
816  , bool SO // Storage order of all matrices
817  , typename MT2 // Type of the matrix U
818  , typename VT // Type of the vector s
819  , bool TF > // Transpose flag of the vector s
821 {
826 
831 
835 
836  using ET = ElementType_<MT1>;
837  using UT = UnderlyingElement_<ET>;
838 
839  const size_t M( (~A).rows() );
840  const size_t N( (~A).columns() );
841  const size_t mindim( min( M, N ) );
842 
843  resize( ~s, mindim, false );
844  resize( ~U, M, mindim, false );
845 
846  if( M == 0UL || N == 0UL ) {
847  return 0;
848  }
849 
850  return gesvdx_backend( ~A, ~U, ~s, 'A', UT(), UT(), 0, 0 );
851 }
852 //*************************************************************************************************
853 
854 
855 //*************************************************************************************************
945 template< typename MT1 // Type of the matrix A
946  , bool SO // Storage order of all matrices
947  , typename MT2 // Type of the matrix U
948  , typename VT // Type of the vector s
949  , bool TF // Transpose flag of the vector s
950  , typename ST > // Type of the scalar boundary values
952  DenseVector<VT,TF>& s, ST low, ST upp )
953 {
958 
963 
967 
969 
970  if( IsFloatingPoint<ST>::value && low >= upp ) {
971  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
972  }
973 
974  if( !IsFloatingPoint<ST>::value && low > upp ) {
975  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
976  }
977 
978  const size_t M( (~A).rows() );
979  const size_t N( (~A).columns() );
980  const size_t mindim( min( M, N ) );
981  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
982 
983  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
984  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
985  }
986 
987  resize( ~s, expected, false );
988  resize( ~U, M, expected, false );
989 
990  if( M == 0UL || N == 0UL ) {
991  return 0;
992  }
993 
994  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
995  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
996  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
997  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
998  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
999 
1000  const size_t actual( gesvdx_backend( ~A, ~U, ~s, range, vl, vu, il, iu ) );
1001 
1002  if( IsResizable<VT>::value ) {
1003  resize( ~s, actual, true );
1004  }
1005 
1006  if( IsResizable<MT2>::value ) {
1007  resize( ~U, M, actual, true );
1008  }
1009 
1010  return actual;
1011 }
1012 //*************************************************************************************************
1013 
1014 
1015 //*************************************************************************************************
1038 template< typename MT1 // Type of the matrix A
1039  , bool SO // Storage order of all matrices
1040  , typename VT // Type of the vector s
1041  , bool TF // Transpose flag of the vector s
1042  , typename MT2 // Type of the matrix V
1043  , typename ST > // Type of the scalar boundary values
1044 inline DisableIf_< IsComplex< ElementType_<MT1> >, size_t >
1045  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V,
1046  char range, ST vl, ST vu, int il, int iu )
1047 {
1048  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1049  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1050  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1051  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1052  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1053  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1054  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1055  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1056 
1057  using ET = ElementType_<MT1>;
1058 
1059  const size_t M( (~A).rows() );
1060  const size_t N( (~A).columns() );
1061  const size_t mindim( min( M, N ) );
1062 
1063  int m ( numeric_cast<int>( SO ? M : N ) );
1064  int n ( numeric_cast<int>( SO ? N : M ) );
1065  int lda ( numeric_cast<int>( (~A).spacing() ) );
1066  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1067  int ns ( 0 );
1068  int info( 0 );
1069 
1070  ET* sptr( (~s).data() );
1071  ET* vptr( (~V).data() );
1072  std::unique_ptr<ET[]> stmp;
1073  std::unique_ptr<ET[]> vtmp;
1074 
1075  const bool tmpRequired( (~s).size() < mindim );
1076 
1077  if( tmpRequired ) {
1078  stmp.reset( new ET[2UL*mindim] );
1079  vtmp.reset( new ET[mindim*N] );
1080  sptr = stmp.get();
1081  vptr = vtmp.get();
1082  }
1083 
1084  const int minimum( min( m, n ) );
1085 
1086  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1087  const std::unique_ptr<ET[]> work ( new ET[lwork] );
1088  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1089 
1090  gesvdx( ( SO ? 'N' : 'V' ), ( SO ? 'V' : 'N' ), range, m, n,
1091  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1092  ( SO ? nullptr : vptr ), ( tmpRequired ? m : ( SO ? 1 : ldv ) ),
1093  ( SO ? vptr : nullptr ), ( tmpRequired ? mindim : ( SO ? ldv : 1 ) ),
1094  work.get(), lwork, iwork.get(), &info );
1095 
1096  const size_t num( numeric_cast<size_t>( ns ) );
1097 
1098  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1099  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1100 
1101  if( info > 0 ) {
1102  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1103  }
1104 
1105  if( tmpRequired )
1106  {
1107  for( size_t i=0UL; i<(~s).size(); ++i ) {
1108  (~s)[i] = stmp[i];
1109  }
1110 
1111  if( SO )
1112  {
1113  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1114  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1115  (~V)(i,j) = vtmp[i+j*mindim];
1116  }
1117  }
1118  }
1119  else
1120  {
1121  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1122  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1123  (~V)(i,j) = vtmp[i*N+j];
1124  }
1125  }
1126  }
1127  }
1128 
1129  return num;
1130 }
1132 //*************************************************************************************************
1133 
1134 
1135 //*************************************************************************************************
1158 template< typename MT1 // Type of the matrix A
1159  , bool SO // Storage order of all matrices
1160  , typename VT // Type of the vector s
1161  , bool TF // Transpose flag of the vector s
1162  , typename MT2 // Type of the matrix V
1163  , typename ST > // Type of the scalar boundary values
1164 inline EnableIf_< IsComplex< ElementType_<MT1> >, size_t >
1165  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V,
1166  char range, ST vl, ST vu, int il, int iu )
1167 {
1168  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1169  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1170  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1171  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1172  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1173  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1174  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1175  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1176 
1177  using CT = ElementType_<MT1>;
1178  using BT = UnderlyingElement_<CT>;
1179 
1180  const size_t M( (~A).rows() );
1181  const size_t N( (~A).columns() );
1182  const size_t mindim( min( M, N ) );
1183 
1184  int m ( numeric_cast<int>( SO ? M : N ) );
1185  int n ( numeric_cast<int>( SO ? N : M ) );
1186  int lda ( numeric_cast<int>( (~A).spacing() ) );
1187  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1188  int ns ( 0 );
1189  int info( 0 );
1190 
1191  BT* sptr( (~s).data() );
1192  CT* vptr( (~V).data() );
1193  std::unique_ptr<BT[]> stmp;
1194  std::unique_ptr<CT[]> vtmp;
1195 
1196  const bool tmpRequired( (~s).size() < mindim );
1197 
1198  if( tmpRequired ) {
1199  stmp.reset( new BT[2UL*mindim] );
1200  vtmp.reset( new CT[mindim*N] );
1201  sptr = stmp.get();
1202  vptr = vtmp.get();
1203  }
1204 
1205  const int minimum( min( m, n ) );
1206 
1207  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1208  const std::unique_ptr<CT[]> work ( new CT[lwork] );
1209  const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
1210  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1211 
1212  gesvdx( ( SO ? 'N' : 'V' ), ( SO ? 'V' : 'N' ), range, m, n,
1213  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1214  ( SO ? nullptr : vptr ), ( tmpRequired ? m : ( SO ? 1 : ldv ) ),
1215  ( SO ? vptr : nullptr ), ( tmpRequired ? mindim : ( SO ? ldv : 1 ) ),
1216  work.get(), lwork, rwork.get(), iwork.get(), &info );
1217 
1218  const size_t num( numeric_cast<size_t>( ns ) );
1219 
1220  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1221  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1222 
1223  if( info > 0 ) {
1224  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1225  }
1226 
1227  if( tmpRequired )
1228  {
1229  for( size_t i=0UL; i<(~s).size(); ++i ) {
1230  (~s)[i] = stmp[i];
1231  }
1232 
1233  if( SO )
1234  {
1235  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1236  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1237  (~V)(i,j) = vtmp[i+j*mindim];
1238  }
1239  }
1240  }
1241  else
1242  {
1243  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1244  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1245  (~V)(i,j) = vtmp[i*N+j];
1246  }
1247  }
1248  }
1249  }
1250 
1251  return num;
1252 }
1254 //*************************************************************************************************
1255 
1256 
1257 //*************************************************************************************************
1314 template< typename MT1 // Type of the matrix A
1315  , bool SO // Storage order of all matrices
1316  , typename VT // Type of the vector s
1317  , bool TF // Transpose flag of the vector s
1318  , typename MT2 > // Type of the matrix V
1320 {
1325 
1329 
1334 
1335  using ET = ElementType_<MT1>;
1336  using UT = UnderlyingElement_<ET>;
1337 
1338  const size_t M( (~A).rows() );
1339  const size_t N( (~A).columns() );
1340  const size_t mindim( min( M, N ) );
1341 
1342  resize( ~s, mindim, false );
1343  resize( ~V, mindim, N, false );
1344 
1345  if( M == 0UL || N == 0UL ) {
1346  return 0;
1347  }
1348 
1349  return gesvdx_backend( ~A, ~s, ~V, 'A', UT(), UT(), 0, 0 );
1350 }
1351 //*************************************************************************************************
1352 
1353 
1354 //*************************************************************************************************
1444 template< typename MT1 // Type of the matrix A
1445  , bool SO // Storage order of all matrices
1446  , typename VT // Type of the vector s
1447  , bool TF // Transpose flag of the vector s
1448  , typename MT2 // Type of the matrix V
1449  , typename ST > // Type of the scalar boundary values
1451  DenseMatrix<MT2,SO>& V, ST low, ST upp )
1452 {
1457 
1461 
1466 
1468 
1469  if( IsFloatingPoint<ST>::value && low >= upp ) {
1470  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
1471  }
1472 
1473  if( !IsFloatingPoint<ST>::value && low > upp ) {
1474  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
1475  }
1476 
1477  const size_t M( (~A).rows() );
1478  const size_t N( (~A).columns() );
1479  const size_t mindim( min( M, N ) );
1480  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
1481 
1482  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
1483  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
1484  }
1485 
1486  resize( ~s, expected, false );
1487  resize( ~V, expected, N, false );
1488 
1489  if( M == 0UL || N == 0UL ) {
1490  return 0;
1491  }
1492 
1493  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
1494  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
1495  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
1496  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
1497  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
1498 
1499  const size_t actual( gesvdx_backend( ~A, ~s, ~V, range, vl, vu, il, iu ) );
1500 
1501  if( IsResizable<VT>::value ) {
1502  resize( ~s, actual, true );
1503  }
1504 
1505  if( IsResizable<MT2>::value ) {
1506  resize( ~V, actual, N, true );
1507  }
1508 
1509  return actual;
1510 }
1511 //*************************************************************************************************
1512 
1513 
1514 //*************************************************************************************************
1538 template< typename MT1 // Type of the matrix A
1539  , bool SO // Storage order of all matrices
1540  , typename MT2 // Type of the matrix U
1541  , typename VT // Type of the vector s
1542  , bool TF // Transpose flag of the vector s
1543  , typename MT3 // Type of the matrix V
1544  , typename ST > // Type of the scalar boundary values
1545 inline DisableIf_< IsComplex< ElementType_<MT1> >, size_t >
1546  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
1547  DenseMatrix<MT3,SO>& V, char range, ST vl, ST vu, int il, int iu )
1548 {
1549  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1550  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1551  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1552  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1553  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
1554  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size() , "Invalid matrix dimension detected" );
1555  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1556  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1557  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1558  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1559 
1560  using ET = ElementType_<MT1>;
1561 
1562  const size_t M( (~A).rows() );
1563  const size_t N( (~A).columns() );
1564  const size_t mindim( min( M, N ) );
1565 
1566  int m ( numeric_cast<int>( SO ? M : N ) );
1567  int n ( numeric_cast<int>( SO ? N : M ) );
1568  int lda ( numeric_cast<int>( (~A).spacing() ) );
1569  int ldu ( numeric_cast<int>( (~U).spacing() ) );
1570  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1571  int ns ( 0 );
1572  int info( 0 );
1573 
1574  ET* sptr( (~s).data() );
1575  ET* uptr( (~U).data() );
1576  ET* vptr( (~V).data() );
1577  std::unique_ptr<ET[]> stmp;
1578  std::unique_ptr<ET[]> utmp;
1579  std::unique_ptr<ET[]> vtmp;
1580 
1581  const bool tmpRequired( (~s).size() < mindim );
1582 
1583  if( tmpRequired ) {
1584  stmp.reset( new ET[2UL*mindim] );
1585  utmp.reset( new ET[M*mindim] );
1586  vtmp.reset( new ET[mindim*N] );
1587  sptr = stmp.get();
1588  uptr = utmp.get();
1589  vptr = vtmp.get();
1590  }
1591 
1592  const int minimum( min( m, n ) );
1593 
1594  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1595  const std::unique_ptr<ET[]> work ( new ET[lwork] );
1596  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1597 
1598  gesvdx( 'V', 'V', range, m, n, (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1599  ( SO ? uptr : vptr ), ( tmpRequired ? m : ( SO ? ldu : ldv ) ),
1600  ( SO ? vptr : uptr ), ( tmpRequired ? mindim : ( SO ? ldv : ldu ) ),
1601  work.get(), lwork, iwork.get(), &info );
1602 
1603  const size_t num( numeric_cast<size_t>( ns ) );
1604 
1605  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1606  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1607 
1608  if( info > 0 ) {
1609  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1610  }
1611 
1612  if( tmpRequired )
1613  {
1614  for( size_t i=0UL; i<(~s).size(); ++i ) {
1615  (~s)[i] = stmp[i];
1616  }
1617 
1618  if( SO )
1619  {
1620  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1621  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1622  (~U)(i,j) = utmp[i+j*M];
1623  }
1624  }
1625 
1626  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1627  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1628  (~V)(i,j) = vtmp[i+j*mindim];
1629  }
1630  }
1631  }
1632  else
1633  {
1634  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1635  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1636  (~U)(i,j) = utmp[i*mindim+j];
1637  }
1638  }
1639 
1640  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1641  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1642  (~V)(i,j) = vtmp[i*N+j];
1643  }
1644  }
1645  }
1646  }
1647 
1648  return num;
1649 }
1651 //*************************************************************************************************
1652 
1653 
1654 //*************************************************************************************************
1678 template< typename MT1 // Type of the matrix A
1679  , bool SO // Storage order of all matrices
1680  , typename MT2 // Type of the matrix U
1681  , typename VT // Type of the vector s
1682  , bool TF // Transpose flag of the vector s
1683  , typename MT3 // Type of the matrix V
1684  , typename ST > // Type of the scalar boundary values
1685 inline EnableIf_< IsComplex< ElementType_<MT1> >, size_t >
1686  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
1687  DenseMatrix<MT3,SO>& V, char range, ST vl, ST vu, int il, int iu )
1688 {
1689  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1690  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1691  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1692  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1693  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
1694  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size() , "Invalid matrix dimension detected" );
1695  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1696  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1697  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1698  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1699 
1700  using CT = ElementType_<MT1>;
1701  using BT = UnderlyingElement_<CT>;
1702 
1703  const size_t M( (~A).rows() );
1704  const size_t N( (~A).columns() );
1705  const size_t mindim( min( M, N ) );
1706 
1707  int m ( numeric_cast<int>( SO ? M : N ) );
1708  int n ( numeric_cast<int>( SO ? N : M ) );
1709  int lda ( numeric_cast<int>( (~A).spacing() ) );
1710  int ldu ( numeric_cast<int>( (~U).spacing() ) );
1711  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1712  int ns ( 0 );
1713  int info( 0 );
1714 
1715  BT* sptr( (~s).data() );
1716  CT* uptr( (~U).data() );
1717  CT* vptr( (~V).data() );
1718  std::unique_ptr<BT[]> stmp;
1719  std::unique_ptr<CT[]> utmp;
1720  std::unique_ptr<CT[]> vtmp;
1721 
1722  const bool tmpRequired( (~s).size() < mindim );
1723 
1724  if( tmpRequired ) {
1725  stmp.reset( new BT[2UL*mindim] );
1726  utmp.reset( new CT[M*mindim] );
1727  vtmp.reset( new CT[mindim*N] );
1728  sptr = stmp.get();
1729  uptr = utmp.get();
1730  vptr = vtmp.get();
1731  }
1732 
1733  const int minimum( min( m, n ) );
1734 
1735  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1736  const std::unique_ptr<CT[]> work ( new CT[lwork] );
1737  const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
1738  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1739 
1740  gesvdx( 'V', 'V', range, m, n, (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1741  ( SO ? uptr : vptr ), ( tmpRequired ? m : ( SO ? ldu : ldv ) ),
1742  ( SO ? vptr : uptr ), ( tmpRequired ? mindim : ( SO ? ldv : ldu ) ),
1743  work.get(), lwork, rwork.get(), iwork.get(), &info );
1744 
1745  const size_t num( numeric_cast<size_t>( ns ) );
1746 
1747  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1748  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1749 
1750  if( info > 0 ) {
1751  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1752  }
1753 
1754  if( tmpRequired )
1755  {
1756  for( size_t i=0UL; i<(~s).size(); ++i ) {
1757  (~s)[i] = stmp[i];
1758  }
1759 
1760  if( SO )
1761  {
1762  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1763  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1764  (~U)(i,j) = utmp[i+j*M];
1765  }
1766  }
1767 
1768  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1769  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1770  (~V)(i,j) = vtmp[i+j*mindim];
1771  }
1772  }
1773  }
1774  else
1775  {
1776  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1777  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1778  (~U)(i,j) = utmp[i*mindim+j];
1779  }
1780  }
1781 
1782  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1783  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1784  (~V)(i,j) = vtmp[i*N+j];
1785  }
1786  }
1787  }
1788  }
1789 
1790  return num;
1791 }
1793 //*************************************************************************************************
1794 
1795 
1796 //*************************************************************************************************
1857 template< typename MT1 // Type of the matrix A
1858  , bool SO // Storage order of all matrices
1859  , typename MT2 // Type of the matrix U
1860  , typename VT // Type of the vector s
1861  , bool TF // Transpose flag of the vector s
1862  , typename MT3 > // Type of the matrix V
1865 {
1870 
1875 
1879 
1884 
1885  using ET = ElementType_<MT1>;
1886  using UT = UnderlyingElement_<ET>;
1887 
1888  const size_t M( (~A).rows() );
1889  const size_t N( (~A).columns() );
1890  const size_t mindim( min( M, N ) );
1891 
1892  resize( ~s, mindim, false );
1893  resize( ~U, M, mindim, false );
1894  resize( ~V, mindim, N, false );
1895 
1896  if( M == 0UL || N == 0UL ) {
1897  return 0;
1898  }
1899 
1900  return gesvdx_backend( ~A, ~U, ~s, ~V, 'A', UT(), UT(), 0, 0 );
1901 }
1902 //*************************************************************************************************
1903 
1904 
1905 //*************************************************************************************************
2002 template< typename MT1 // Type of the matrix A
2003  , bool SO // Storage order of all matrices
2004  , typename MT2 // Type of the matrix U
2005  , typename VT // Type of the vector s
2006  , bool TF // Transpose flag of the vector s
2007  , typename MT3 // Type of the matrix V
2008  , typename ST > // Type of the scalar boundary values
2010  DenseVector<VT,TF>& s, DenseMatrix<MT3,SO>& V, ST low, ST upp )
2011 {
2016 
2021 
2025 
2030 
2032 
2033  if( IsFloatingPoint<ST>::value && low >= upp ) {
2034  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
2035  }
2036 
2037  if( !IsFloatingPoint<ST>::value && low > upp ) {
2038  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
2039  }
2040 
2041  const size_t M( (~A).rows() );
2042  const size_t N( (~A).columns() );
2043  const size_t mindim( min( M, N ) );
2044  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
2045 
2046  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
2047  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
2048  }
2049 
2050  resize( ~s, expected, false );
2051  resize( ~U, M, expected, false );
2052  resize( ~V, expected, N, false );
2053 
2054  if( M == 0UL || N == 0UL ) {
2055  return 0;
2056  }
2057 
2058  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
2059  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
2060  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
2061  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
2062  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
2063 
2064  const size_t actual( gesvdx_backend( ~A, ~U, ~s, ~V, range, vl, vu, il, iu ) );
2065 
2066  if( IsResizable<VT>::value ) {
2067  resize( ~s, actual, true );
2068  }
2069 
2070  if( IsResizable<MT2>::value ) {
2071  resize( ~U, M, actual, true );
2072  }
2073 
2074  if( IsResizable<MT3>::value ) {
2075  resize( ~V, actual, N, true );
2076  }
2077 
2078  return actual;
2079 }
2080 //*************************************************************************************************
2081 
2082 } // namespace blaze
2083 
2084 #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
Header file for basic type definitions.
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:265
#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE(T)
Constraint on the data type.In case the given data type T is a computational expression (i...
Definition: Computation.h:81
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:224
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1762
Header file for the DenseVector base class.
Header file for the UnderlyingElement type trait.
Constraint on the data type.
Cast operators for numeric types.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE(T)
Constraint on the data type.In case the given data type T is an adaptor type (as for instance LowerMa...
Definition: Adaptor.h:81
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:78
BLAZE_ALWAYS_INLINE size_t spacing(const DenseMatrix< MT, SO > &dm) noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DenseMatrix.h:110
Header file for the implementation of the Subvector view.
Constraint on the data type.
Header file for the DisableIf class template.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
Header file for the IsFloatingPoint type trait.
Header file for the DenseMatrix base class.
typename UnderlyingElement< T >::Type UnderlyingElement_
Auxiliary alias declaration for the UnderlyingElement type trait.The UnderlyingElement_ alias declara...
Definition: UnderlyingElement.h:132
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:70
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:340
Header file for the exception macros of the math module.
Compile time check for floating point data types.This type trait tests whether or not the given templ...
Definition: IsFloatingPoint.h:75
BLAZE_ALWAYS_INLINE void resize(Matrix< MT, SO > &matrix, size_t rows, size_t columns, bool preserve=true)
Changing the size of the matrix.
Definition: Matrix.h:548
Constraint on the data type.
Header file for the EnableIf class template.
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
Header file for the CLAPACK gesvdx wrapper functions.
Header file for run time assertion macros.
void gesvdx(char jobu, char jobv, char range, int m, int n, float *A, int lda, float vl, float vu, int il, int iu, int *ns, 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: gesvdx.h:179
#define BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE(T)
Constraint on the data type.In case the given data type T is not a BLAS compatible data type (i...
Definition: BLASCompatible.h:61
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:224
#define BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE(T)
Constraint on the data type.In case the given data type T is not a built-in data type, a compilation error is created.
Definition: Builtin.h:60
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:324
#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 IsResizable type trait.
Header file for the Size type trait.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Constraint on the data type.