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 <boost/cast.hpp>
45 #include <blaze/math/Aliases.h>
50 #include <blaze/math/Exception.h>
53 #include <blaze/math/Functions.h>
59 #include <blaze/util/Assert.h>
61 #include <blaze/util/DisableIf.h>
62 #include <blaze/util/EnableIf.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  using boost::numeric_cast;
142 
143  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
144  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
145  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
146  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
147  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
148  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
149 
150  using ET = ElementType_<MT>;
151 
152  const size_t M( (~A).rows() );
153  const size_t N( (~A).columns() );
154  const size_t mindim( min( M, N ) );
155 
156  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
157  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
158  int lda ( numeric_cast<int>( (~A).spacing() ) );
159  int ns ( 0 );
160  int info( 0 );
161 
162  ET* sptr( (~s).data() );
163  std::unique_ptr<ET[]> stmp;
164 
165  const bool tmpRequired( (~s).size() < mindim );
166 
167  if( tmpRequired ) {
168  stmp.reset( new ET[2UL*mindim] );
169  sptr = stmp.get();
170  }
171 
172  const int minimum( min( m, n ) );
173 
174  int lwork( minimum*( minimum*3 + 20 ) + 2 );
175  const std::unique_ptr<ET[]> work ( new ET[lwork] );
176  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
177 
178  gesvdx( 'N', 'N', range, m, n, (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
179  nullptr, 1, nullptr, 1, work.get(), lwork, iwork.get(), &info );
180 
181  const size_t num( numeric_cast<size_t>( ns ) );
182 
183  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
184  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
185 
186  if( info > 0 ) {
187  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
188  }
189 
190  if( tmpRequired ) {
191  for( size_t i=0UL; i<(~s).size(); ++i ) {
192  (~s)[i] = stmp[i];
193  }
194  }
195 
196  return num;
197 }
199 //*************************************************************************************************
200 
201 
202 //*************************************************************************************************
224 template< typename MT // Type of the matrix A
225  , bool SO // Storage order of the matrix A
226  , typename VT // Type of the vector s
227  , bool TF // Transpose flag of the vector s
228  , typename ST > // Type of the scalar boundary values
229 inline EnableIf_< IsComplex< ElementType_<MT> >, size_t >
230  gesvdx_backend( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s,
231  char range, ST vl, ST vu, int il, int iu )
232 {
233  using boost::numeric_cast;
234 
235  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
236  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
237  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
238  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
239  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
240  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
241 
242  using CT = ElementType_<MT>;
243  using BT = UnderlyingElement_<CT>;
244 
245  const size_t M( (~A).rows() );
246  const size_t N( (~A).columns() );
247  const size_t mindim( min( M, N ) );
248 
249  int m ( numeric_cast<int>( SO ? (~A).rows() : (~A).columns() ) );
250  int n ( numeric_cast<int>( SO ? (~A).columns() : (~A).rows() ) );
251  int lda ( numeric_cast<int>( (~A).spacing() ) );
252  int ns ( 0 );
253  int info( 0 );
254 
255  BT* sptr( (~s).data() );
256  std::unique_ptr<BT[]> stmp;
257 
258  const bool tmpRequired( (~s).size() < mindim );
259 
260  if( tmpRequired ) {
261  stmp.reset( new BT[2UL*mindim] );
262  sptr = stmp.get();
263  }
264 
265  const int minimum( min( m, n ) );
266 
267  int lwork( minimum*( minimum*3 + 20 ) + 2 );
268  const std::unique_ptr<CT[]> work ( new CT[lwork] );
269  const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
270  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
271 
272  gesvdx( 'N', 'N', range, m, n, (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
273  nullptr, 1, nullptr, 1, work.get(), lwork, rwork.get(), iwork.get(), &info );
274 
275  const size_t num( numeric_cast<size_t>( ns ) );
276 
277  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
278  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
279 
280  if( info > 0 ) {
281  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
282  }
283 
284  if( tmpRequired ) {
285  for( size_t i=0UL; i<(~s).size(); ++i ) {
286  (~s)[i] = stmp[i];
287  }
288  }
289 
290  return num;
291 }
293 //*************************************************************************************************
294 
295 
296 //*************************************************************************************************
348 template< typename MT // Type of the matrix A
349  , bool SO // Storage order of the matrix A
350  , typename VT // Type of the vector s
351  , bool TF > // Transpose flag of the vector s
353 {
358 
362 
363  using ET = ElementType_<MT>;
364  using UT = UnderlyingElement_<ET>;
365 
366  const size_t M( (~A).rows() );
367  const size_t N( (~A).columns() );
368  const size_t mindim( min( M, N ) );
369 
370  resize( ~s, mindim, false );
371 
372  if( M == 0UL || N == 0UL ) {
373  return 0;
374  }
375 
376  return gesvdx_backend( ~A, ~s, 'A', UT(), UT(), 0, 0 );
377 }
378 //*************************************************************************************************
379 
380 
381 //*************************************************************************************************
462 template< typename MT // Type of the matrix A
463  , bool SO // Storage order of the matrix A
464  , typename VT // Type of the vector s
465  , bool TF // Transpose flag of the vector s
466  , typename ST > // Type of the scalar boundary values
467 inline size_t gesvdx( DenseMatrix<MT,SO>& A, DenseVector<VT,TF>& s, ST low, ST upp )
468 {
469  using boost::numeric_cast;
470 
475 
479 
481 
482  if( IsFloatingPoint<ST>::value && low >= upp ) {
483  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
484  }
485 
486  if( !IsFloatingPoint<ST>::value && low > upp ) {
487  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
488  }
489 
490  const size_t M( (~A).rows() );
491  const size_t N( (~A).columns() );
492  const size_t mindim( min( M, N ) );
493  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
494 
495  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
496  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
497  }
498 
499  resize( ~s, expected, false );
500 
501  if( M == 0UL || N == 0UL ) {
502  return 0;
503  }
504 
505  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
506  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
507  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
508  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
509  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
510 
511  const size_t actual( gesvdx_backend( ~A, ~s, range, vl, vu, il, iu ) );
512 
513  if( IsResizable<VT>::value ) {
514  resize( ~s, actual, true );
515  }
516 
517  return actual;
518 }
519 //*************************************************************************************************
520 
521 
522 //*************************************************************************************************
545 template< typename MT1 // Type of the matrix A
546  , bool SO // Storage order of all matrices
547  , typename MT2 // Type of the matrix U
548  , typename VT // Type of the vector s
549  , bool TF // Transpose flag of the vector s
550  , typename ST > // Type of the scalar boundary values
553  char range, ST vl, ST vu, int il, int iu )
554 {
555  using boost::numeric_cast;
556 
557  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
558  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
559  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
560  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
561  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
562  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size(), "Invalid matrix dimension detected" );
563  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
564  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
565 
566  using ET = ElementType_<MT1>;
567 
568  const size_t M( (~A).rows() );
569  const size_t N( (~A).columns() );
570  const size_t mindim( min( M, N ) );
571 
572  int m ( numeric_cast<int>( SO ? M : N ) );
573  int n ( numeric_cast<int>( SO ? N : M ) );
574  int lda ( numeric_cast<int>( (~A).spacing() ) );
575  int ldu ( numeric_cast<int>( (~U).spacing() ) );
576  int ns ( 0 );
577  int info( 0 );
578 
579  ET* sptr( (~s).data() );
580  ET* uptr( (~U).data() );
581  std::unique_ptr<ET[]> stmp;
582  std::unique_ptr<ET[]> utmp;
583 
584  const bool tmpRequired( (~s).size() < mindim );
585 
586  if( tmpRequired ) {
587  stmp.reset( new ET[2UL*mindim] );
588  utmp.reset( new ET[M*mindim] );
589  sptr = stmp.get();
590  uptr = utmp.get();
591  }
592 
593  const int minimum( min( m, n ) );
594 
595  int lwork( minimum*( minimum*3 + 20 ) + 2 );
596  const std::unique_ptr<ET[]> work ( new ET[lwork] );
597  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
598 
599  gesvdx( ( SO ? 'V' : 'N' ), ( SO ? 'N' : 'V' ), range, m, n,
600  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
601  ( SO ? uptr : nullptr ), ( tmpRequired ? m : ( SO ? ldu : 1 ) ),
602  ( SO ? nullptr : uptr ), ( tmpRequired ? mindim : ( SO ? 1 : ldu ) ),
603  work.get(), lwork, iwork.get(), &info );
604 
605  const size_t num( numeric_cast<size_t>( ns ) );
606 
607  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
608  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
609 
610  if( info > 0 ) {
611  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
612  }
613 
614  if( tmpRequired )
615  {
616  for( size_t i=0UL; i<(~s).size(); ++i ) {
617  (~s)[i] = stmp[i];
618  }
619 
620  if( SO )
621  {
622  for( size_t j=0UL; j<(~U).columns(); ++j ) {
623  for( size_t i=0UL; i<(~U).rows(); ++i ) {
624  (~U)(i,j) = utmp[i+j*M];
625  }
626  }
627  }
628  else
629  {
630  for( size_t i=0UL; i<(~U).rows(); ++i ) {
631  for( size_t j=0UL; j<(~U).columns(); ++j ) {
632  (~U)(i,j) = utmp[i*mindim+j];
633  }
634  }
635  }
636  }
637 
638  return num;
639 }
641 //*************************************************************************************************
642 
643 
644 //*************************************************************************************************
667 template< typename MT1 // Type of the matrix A
668  , bool SO // Storage order of all matrices
669  , typename MT2 // Type of the matrix U
670  , typename VT // Type of the vector s
671  , bool TF // Transpose flag of the vector s
672  , typename ST > // Type of the scalar boundary values
675  char range, ST vl, ST vu, int il, int iu )
676 {
677  using boost::numeric_cast;
678 
679  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
680  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
681  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
682  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
683  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
684  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size(), "Invalid matrix dimension detected" );
685  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
686  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
687 
688  using CT = ElementType_<MT1>;
689  using BT = UnderlyingElement_<CT>;
690 
691  const size_t M( (~A).rows() );
692  const size_t N( (~A).columns() );
693  const size_t mindim( min( M, N ) );
694 
695  int m ( numeric_cast<int>( SO ? M : N ) );
696  int n ( numeric_cast<int>( SO ? N : M ) );
697  int lda ( numeric_cast<int>( (~A).spacing() ) );
698  int ldu ( numeric_cast<int>( (~U).spacing() ) );
699  int ns ( 0 );
700  int info( 0 );
701 
702  BT* sptr( (~s).data() );
703  CT* uptr( (~U).data() );
704  std::unique_ptr<BT[]> stmp;
705  std::unique_ptr<CT[]> utmp;
706 
707  const bool tmpRequired( (~s).size() < mindim );
708 
709  if( tmpRequired ) {
710  stmp.reset( new BT[2UL*mindim] );
711  utmp.reset( new CT[M*mindim] );
712  sptr = stmp.get();
713  uptr = utmp.get();
714  }
715 
716  const int minimum( min( m, n ) );
717 
718  int lwork( minimum*( minimum*3 + 20 ) + 2 );
719  const std::unique_ptr<CT[]> work ( new CT[lwork] );
720  const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
721  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
722 
723  gesvdx( ( SO ? 'V' : 'N' ), ( SO ? 'N' : 'V' ), range, m, n,
724  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
725  ( SO ? uptr : nullptr ), ( tmpRequired ? m : ( SO ? ldu : 1 ) ),
726  ( SO ? nullptr : uptr ), ( tmpRequired ? mindim : ( SO ? 1 : ldu ) ),
727  work.get(), lwork, rwork.get(), iwork.get(), &info );
728 
729  const size_t num( numeric_cast<size_t>( ns ) );
730 
731  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
732  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
733 
734  if( info > 0 ) {
735  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
736  }
737 
738  if( tmpRequired )
739  {
740  for( size_t i=0UL; i<(~s).size(); ++i ) {
741  (~s)[i] = stmp[i];
742  }
743 
744  if( SO )
745  {
746  for( size_t j=0UL; j<(~U).columns(); ++j ) {
747  for( size_t i=0UL; i<(~U).rows(); ++i ) {
748  (~U)(i,j) = utmp[i+j*M];
749  }
750  }
751  }
752  else
753  {
754  for( size_t i=0UL; i<(~U).rows(); ++i ) {
755  for( size_t j=0UL; j<(~U).columns(); ++j ) {
756  (~U)(i,j) = utmp[i*mindim+j];
757  }
758  }
759  }
760  }
761 
762  return num;
763 }
765 //*************************************************************************************************
766 
767 
768 //*************************************************************************************************
825 template< typename MT1 // Type of the matrix A
826  , bool SO // Storage order of all matrices
827  , typename MT2 // Type of the matrix U
828  , typename VT // Type of the vector s
829  , bool TF > // Transpose flag of the vector s
831 {
836 
841 
845 
846  using ET = ElementType_<MT1>;
847  using UT = UnderlyingElement_<ET>;
848 
849  const size_t M( (~A).rows() );
850  const size_t N( (~A).columns() );
851  const size_t mindim( min( M, N ) );
852 
853  resize( ~s, mindim, false );
854  resize( ~U, M, mindim, false );
855 
856  if( M == 0UL || N == 0UL ) {
857  return 0;
858  }
859 
860  return gesvdx_backend( ~A, ~U, ~s, 'A', UT(), UT(), 0, 0 );
861 }
862 //*************************************************************************************************
863 
864 
865 //*************************************************************************************************
955 template< typename MT1 // Type of the matrix A
956  , bool SO // Storage order of all matrices
957  , typename MT2 // Type of the matrix U
958  , typename VT // Type of the vector s
959  , bool TF // Transpose flag of the vector s
960  , typename ST > // Type of the scalar boundary values
962  DenseVector<VT,TF>& s, ST low, ST upp )
963 {
964  using boost::numeric_cast;
965 
970 
975 
979 
981 
982  if( IsFloatingPoint<ST>::value && low >= upp ) {
983  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
984  }
985 
986  if( !IsFloatingPoint<ST>::value && low > upp ) {
987  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
988  }
989 
990  const size_t M( (~A).rows() );
991  const size_t N( (~A).columns() );
992  const size_t mindim( min( M, N ) );
993  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
994 
995  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
996  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
997  }
998 
999  resize( ~s, expected, false );
1000  resize( ~U, M, expected, false );
1001 
1002  if( M == 0UL || N == 0UL ) {
1003  return 0;
1004  }
1005 
1006  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
1007  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
1008  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
1009  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
1010  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
1011 
1012  const size_t actual( gesvdx_backend( ~A, ~U, ~s, range, vl, vu, il, iu ) );
1013 
1014  if( IsResizable<VT>::value ) {
1015  resize( ~s, actual, true );
1016  }
1017 
1018  if( IsResizable<MT2>::value ) {
1019  resize( ~U, M, actual, true );
1020  }
1021 
1022  return actual;
1023 }
1024 //*************************************************************************************************
1025 
1026 
1027 //*************************************************************************************************
1050 template< typename MT1 // Type of the matrix A
1051  , bool SO // Storage order of all matrices
1052  , typename VT // Type of the vector s
1053  , bool TF // Transpose flag of the vector s
1054  , typename MT2 // Type of the matrix V
1055  , typename ST > // Type of the scalar boundary values
1056 inline DisableIf_< IsComplex< ElementType_<MT1> >, size_t >
1057  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V,
1058  char range, ST vl, ST vu, int il, int iu )
1059 {
1060  using boost::numeric_cast;
1061 
1062  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1063  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1064  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1065  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1066  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1067  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1068  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1069  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1070 
1071  using ET = ElementType_<MT1>;
1072 
1073  const size_t M( (~A).rows() );
1074  const size_t N( (~A).columns() );
1075  const size_t mindim( min( M, N ) );
1076 
1077  int m ( numeric_cast<int>( SO ? M : N ) );
1078  int n ( numeric_cast<int>( SO ? N : M ) );
1079  int lda ( numeric_cast<int>( (~A).spacing() ) );
1080  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1081  int ns ( 0 );
1082  int info( 0 );
1083 
1084  ET* sptr( (~s).data() );
1085  ET* vptr( (~V).data() );
1086  std::unique_ptr<ET[]> stmp;
1087  std::unique_ptr<ET[]> vtmp;
1088 
1089  const bool tmpRequired( (~s).size() < mindim );
1090 
1091  if( tmpRequired ) {
1092  stmp.reset( new ET[2UL*mindim] );
1093  vtmp.reset( new ET[mindim*N] );
1094  sptr = stmp.get();
1095  vptr = vtmp.get();
1096  }
1097 
1098  const int minimum( min( m, n ) );
1099 
1100  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1101  const std::unique_ptr<ET[]> work ( new ET[lwork] );
1102  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1103 
1104  gesvdx( ( SO ? 'N' : 'V' ), ( SO ? 'V' : 'N' ), range, m, n,
1105  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1106  ( SO ? nullptr : vptr ), ( tmpRequired ? m : ( SO ? 1 : ldv ) ),
1107  ( SO ? vptr : nullptr ), ( tmpRequired ? mindim : ( SO ? ldv : 1 ) ),
1108  work.get(), lwork, iwork.get(), &info );
1109 
1110  const size_t num( numeric_cast<size_t>( ns ) );
1111 
1112  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1113  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1114 
1115  if( info > 0 ) {
1116  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1117  }
1118 
1119  if( tmpRequired )
1120  {
1121  for( size_t i=0UL; i<(~s).size(); ++i ) {
1122  (~s)[i] = stmp[i];
1123  }
1124 
1125  if( SO )
1126  {
1127  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1128  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1129  (~V)(i,j) = vtmp[i+j*mindim];
1130  }
1131  }
1132  }
1133  else
1134  {
1135  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1136  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1137  (~V)(i,j) = vtmp[i*N+j];
1138  }
1139  }
1140  }
1141  }
1142 
1143  return num;
1144 }
1146 //*************************************************************************************************
1147 
1148 
1149 //*************************************************************************************************
1172 template< typename MT1 // Type of the matrix A
1173  , bool SO // Storage order of all matrices
1174  , typename VT // Type of the vector s
1175  , bool TF // Transpose flag of the vector s
1176  , typename MT2 // Type of the matrix V
1177  , typename ST > // Type of the scalar boundary values
1178 inline EnableIf_< IsComplex< ElementType_<MT1> >, size_t >
1179  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseVector<VT,TF>& s, DenseMatrix<MT2,SO>& V,
1180  char range, ST vl, ST vu, int il, int iu )
1181 {
1182  using boost::numeric_cast;
1183 
1184  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1185  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1186  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1187  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1188  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1189  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1190  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1191  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1192 
1193  using CT = ElementType_<MT1>;
1194  using BT = UnderlyingElement_<CT>;
1195 
1196  const size_t M( (~A).rows() );
1197  const size_t N( (~A).columns() );
1198  const size_t mindim( min( M, N ) );
1199 
1200  int m ( numeric_cast<int>( SO ? M : N ) );
1201  int n ( numeric_cast<int>( SO ? N : M ) );
1202  int lda ( numeric_cast<int>( (~A).spacing() ) );
1203  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1204  int ns ( 0 );
1205  int info( 0 );
1206 
1207  BT* sptr( (~s).data() );
1208  CT* vptr( (~V).data() );
1209  std::unique_ptr<BT[]> stmp;
1210  std::unique_ptr<CT[]> vtmp;
1211 
1212  const bool tmpRequired( (~s).size() < mindim );
1213 
1214  if( tmpRequired ) {
1215  stmp.reset( new BT[2UL*mindim] );
1216  vtmp.reset( new CT[mindim*N] );
1217  sptr = stmp.get();
1218  vptr = vtmp.get();
1219  }
1220 
1221  const int minimum( min( m, n ) );
1222 
1223  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1224  const std::unique_ptr<CT[]> work ( new CT[lwork] );
1225  const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
1226  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1227 
1228  gesvdx( ( SO ? 'N' : 'V' ), ( SO ? 'V' : 'N' ), range, m, n,
1229  (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1230  ( SO ? nullptr : vptr ), ( tmpRequired ? m : ( SO ? 1 : ldv ) ),
1231  ( SO ? vptr : nullptr ), ( tmpRequired ? mindim : ( SO ? ldv : 1 ) ),
1232  work.get(), lwork, rwork.get(), iwork.get(), &info );
1233 
1234  const size_t num( numeric_cast<size_t>( ns ) );
1235 
1236  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1237  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1238 
1239  if( info > 0 ) {
1240  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1241  }
1242 
1243  if( tmpRequired )
1244  {
1245  for( size_t i=0UL; i<(~s).size(); ++i ) {
1246  (~s)[i] = stmp[i];
1247  }
1248 
1249  if( SO )
1250  {
1251  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1252  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1253  (~V)(i,j) = vtmp[i+j*mindim];
1254  }
1255  }
1256  }
1257  else
1258  {
1259  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1260  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1261  (~V)(i,j) = vtmp[i*N+j];
1262  }
1263  }
1264  }
1265  }
1266 
1267  return num;
1268 }
1270 //*************************************************************************************************
1271 
1272 
1273 //*************************************************************************************************
1330 template< typename MT1 // Type of the matrix A
1331  , bool SO // Storage order of all matrices
1332  , typename VT // Type of the vector s
1333  , bool TF // Transpose flag of the vector s
1334  , typename MT2 > // Type of the matrix V
1336 {
1341 
1345 
1350 
1351  using ET = ElementType_<MT1>;
1352  using UT = UnderlyingElement_<ET>;
1353 
1354  const size_t M( (~A).rows() );
1355  const size_t N( (~A).columns() );
1356  const size_t mindim( min( M, N ) );
1357 
1358  resize( ~s, mindim, false );
1359  resize( ~V, mindim, N, false );
1360 
1361  if( M == 0UL || N == 0UL ) {
1362  return 0;
1363  }
1364 
1365  return gesvdx_backend( ~A, ~s, ~V, 'A', UT(), UT(), 0, 0 );
1366 }
1367 //*************************************************************************************************
1368 
1369 
1370 //*************************************************************************************************
1460 template< typename MT1 // Type of the matrix A
1461  , bool SO // Storage order of all matrices
1462  , typename VT // Type of the vector s
1463  , bool TF // Transpose flag of the vector s
1464  , typename MT2 // Type of the matrix V
1465  , typename ST > // Type of the scalar boundary values
1467  DenseMatrix<MT2,SO>& V, ST low, ST upp )
1468 {
1469  using boost::numeric_cast;
1470 
1475 
1479 
1484 
1486 
1487  if( IsFloatingPoint<ST>::value && low >= upp ) {
1488  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
1489  }
1490 
1491  if( !IsFloatingPoint<ST>::value && low > upp ) {
1492  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
1493  }
1494 
1495  const size_t M( (~A).rows() );
1496  const size_t N( (~A).columns() );
1497  const size_t mindim( min( M, N ) );
1498  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
1499 
1500  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
1501  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
1502  }
1503 
1504  resize( ~s, expected, false );
1505  resize( ~V, expected, N, false );
1506 
1507  if( M == 0UL || N == 0UL ) {
1508  return 0;
1509  }
1510 
1511  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
1512  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
1513  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
1514  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
1515  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
1516 
1517  const size_t actual( gesvdx_backend( ~A, ~s, ~V, range, vl, vu, il, iu ) );
1518 
1519  if( IsResizable<VT>::value ) {
1520  resize( ~s, actual, true );
1521  }
1522 
1523  if( IsResizable<MT2>::value ) {
1524  resize( ~V, actual, N, true );
1525  }
1526 
1527  return actual;
1528 }
1529 //*************************************************************************************************
1530 
1531 
1532 //*************************************************************************************************
1556 template< typename MT1 // Type of the matrix A
1557  , bool SO // Storage order of all matrices
1558  , typename MT2 // Type of the matrix U
1559  , typename VT // Type of the vector s
1560  , bool TF // Transpose flag of the vector s
1561  , typename MT3 // Type of the matrix V
1562  , typename ST > // Type of the scalar boundary values
1563 inline DisableIf_< IsComplex< ElementType_<MT1> >, size_t >
1564  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
1565  DenseMatrix<MT3,SO>& V, char range, ST vl, ST vu, int il, int iu )
1566 {
1567  using boost::numeric_cast;
1568 
1569  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1570  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1571  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1572  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1573  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
1574  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size() , "Invalid matrix dimension detected" );
1575  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1576  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1577  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1578  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1579 
1580  using ET = ElementType_<MT1>;
1581 
1582  const size_t M( (~A).rows() );
1583  const size_t N( (~A).columns() );
1584  const size_t mindim( min( M, N ) );
1585 
1586  int m ( numeric_cast<int>( SO ? M : N ) );
1587  int n ( numeric_cast<int>( SO ? N : M ) );
1588  int lda ( numeric_cast<int>( (~A).spacing() ) );
1589  int ldu ( numeric_cast<int>( (~U).spacing() ) );
1590  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1591  int ns ( 0 );
1592  int info( 0 );
1593 
1594  ET* sptr( (~s).data() );
1595  ET* uptr( (~U).data() );
1596  ET* vptr( (~V).data() );
1597  std::unique_ptr<ET[]> stmp;
1598  std::unique_ptr<ET[]> utmp;
1599  std::unique_ptr<ET[]> vtmp;
1600 
1601  const bool tmpRequired( (~s).size() < mindim );
1602 
1603  if( tmpRequired ) {
1604  stmp.reset( new ET[2UL*mindim] );
1605  utmp.reset( new ET[M*mindim] );
1606  vtmp.reset( new ET[mindim*N] );
1607  sptr = stmp.get();
1608  uptr = utmp.get();
1609  vptr = vtmp.get();
1610  }
1611 
1612  const int minimum( min( m, n ) );
1613 
1614  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1615  const std::unique_ptr<ET[]> work ( new ET[lwork] );
1616  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1617 
1618  gesvdx( 'V', 'V', range, m, n, (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1619  ( SO ? uptr : vptr ), ( tmpRequired ? m : ( SO ? ldu : ldv ) ),
1620  ( SO ? vptr : uptr ), ( tmpRequired ? mindim : ( SO ? ldv : ldu ) ),
1621  work.get(), lwork, iwork.get(), &info );
1622 
1623  const size_t num( numeric_cast<size_t>( ns ) );
1624 
1625  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1626  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1627 
1628  if( info > 0 ) {
1629  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1630  }
1631 
1632  if( tmpRequired )
1633  {
1634  for( size_t i=0UL; i<(~s).size(); ++i ) {
1635  (~s)[i] = stmp[i];
1636  }
1637 
1638  if( SO )
1639  {
1640  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1641  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1642  (~U)(i,j) = utmp[i+j*M];
1643  }
1644  }
1645 
1646  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1647  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1648  (~V)(i,j) = vtmp[i+j*mindim];
1649  }
1650  }
1651  }
1652  else
1653  {
1654  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1655  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1656  (~U)(i,j) = utmp[i*mindim+j];
1657  }
1658  }
1659 
1660  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1661  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1662  (~V)(i,j) = vtmp[i*N+j];
1663  }
1664  }
1665  }
1666  }
1667 
1668  return num;
1669 }
1671 //*************************************************************************************************
1672 
1673 
1674 //*************************************************************************************************
1698 template< typename MT1 // Type of the matrix A
1699  , bool SO // Storage order of all matrices
1700  , typename MT2 // Type of the matrix U
1701  , typename VT // Type of the vector s
1702  , bool TF // Transpose flag of the vector s
1703  , typename MT3 // Type of the matrix V
1704  , typename ST > // Type of the scalar boundary values
1705 inline EnableIf_< IsComplex< ElementType_<MT1> >, size_t >
1706  gesvdx_backend( DenseMatrix<MT1,SO>& A, DenseMatrix<MT2,SO>& U, DenseVector<VT,TF>& s,
1707  DenseMatrix<MT3,SO>& V, char range, ST vl, ST vu, int il, int iu )
1708 {
1709  using boost::numeric_cast;
1710 
1711  BLAZE_INTERNAL_ASSERT( range == 'A' || range == 'V' || range == 'I', "Invalid range flag detected" );
1712  BLAZE_INTERNAL_ASSERT( range != 'A' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1713  BLAZE_INTERNAL_ASSERT( range != 'V' || (~s).size() == min( (~A).rows(), (~A).columns() ), "Invalid vector dimension detected" );
1714  BLAZE_INTERNAL_ASSERT( range != 'I' || (~s).size() == size_t( iu-il+1 ), "Invalid vector dimension detected" );
1715  BLAZE_INTERNAL_ASSERT( (~U).rows() == (~A).rows() , "Invalid matrix dimension detected" );
1716  BLAZE_INTERNAL_ASSERT( (~U).columns() == (~s).size() , "Invalid matrix dimension detected" );
1717  BLAZE_INTERNAL_ASSERT( (~V).rows() == (~s).size() , "Invalid matrix dimension detected" );
1718  BLAZE_INTERNAL_ASSERT( (~V).columns() == (~A).columns(), "Invalid matrix dimension detected" );
1719  BLAZE_INTERNAL_ASSERT( vl <= vu, "Invalid floating point range detected" );
1720  BLAZE_INTERNAL_ASSERT( il <= iu, "Invalid integral range detected" );
1721 
1722  using CT = ElementType_<MT1>;
1723  using BT = UnderlyingElement_<CT>;
1724 
1725  const size_t M( (~A).rows() );
1726  const size_t N( (~A).columns() );
1727  const size_t mindim( min( M, N ) );
1728 
1729  int m ( numeric_cast<int>( SO ? M : N ) );
1730  int n ( numeric_cast<int>( SO ? N : M ) );
1731  int lda ( numeric_cast<int>( (~A).spacing() ) );
1732  int ldu ( numeric_cast<int>( (~U).spacing() ) );
1733  int ldv ( numeric_cast<int>( (~V).spacing() ) );
1734  int ns ( 0 );
1735  int info( 0 );
1736 
1737  BT* sptr( (~s).data() );
1738  CT* uptr( (~U).data() );
1739  CT* vptr( (~V).data() );
1740  std::unique_ptr<BT[]> stmp;
1741  std::unique_ptr<CT[]> utmp;
1742  std::unique_ptr<CT[]> vtmp;
1743 
1744  const bool tmpRequired( (~s).size() < mindim );
1745 
1746  if( tmpRequired ) {
1747  stmp.reset( new BT[2UL*mindim] );
1748  utmp.reset( new CT[M*mindim] );
1749  vtmp.reset( new CT[mindim*N] );
1750  sptr = stmp.get();
1751  uptr = utmp.get();
1752  vptr = vtmp.get();
1753  }
1754 
1755  const int minimum( min( m, n ) );
1756 
1757  int lwork( minimum*( minimum*3 + 20 ) + 2 );
1758  const std::unique_ptr<CT[]> work ( new CT[lwork] );
1759  const std::unique_ptr<BT[]> rwork( new BT[17*minimum*minimum] );
1760  const std::unique_ptr<int[]> iwork( new int[12*minimum] );
1761 
1762  gesvdx( 'V', 'V', range, m, n, (~A).data(), lda, vl, vu, il, iu, &ns, sptr,
1763  ( SO ? uptr : vptr ), ( tmpRequired ? m : ( SO ? ldu : ldv ) ),
1764  ( SO ? vptr : uptr ), ( tmpRequired ? mindim : ( SO ? ldv : ldu ) ),
1765  work.get(), lwork, rwork.get(), iwork.get(), &info );
1766 
1767  const size_t num( numeric_cast<size_t>( ns ) );
1768 
1769  BLAZE_INTERNAL_ASSERT( info >= 0, "Invalid argument for singular value decomposition" );
1770  BLAZE_INTERNAL_ASSERT( num <= (~s).size(), "Invalid number of singular values detected" );
1771 
1772  if( info > 0 ) {
1773  BLAZE_THROW_LAPACK_ERROR( "Singular value decomposition failed" );
1774  }
1775 
1776  if( tmpRequired )
1777  {
1778  for( size_t i=0UL; i<(~s).size(); ++i ) {
1779  (~s)[i] = stmp[i];
1780  }
1781 
1782  if( SO )
1783  {
1784  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1785  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1786  (~U)(i,j) = utmp[i+j*M];
1787  }
1788  }
1789 
1790  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1791  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1792  (~V)(i,j) = vtmp[i+j*mindim];
1793  }
1794  }
1795  }
1796  else
1797  {
1798  for( size_t i=0UL; i<(~U).rows(); ++i ) {
1799  for( size_t j=0UL; j<(~U).columns(); ++j ) {
1800  (~U)(i,j) = utmp[i*mindim+j];
1801  }
1802  }
1803 
1804  for( size_t i=0UL; i<(~V).rows(); ++i ) {
1805  for( size_t j=0UL; j<(~V).columns(); ++j ) {
1806  (~V)(i,j) = vtmp[i*N+j];
1807  }
1808  }
1809  }
1810  }
1811 
1812  return num;
1813 }
1815 //*************************************************************************************************
1816 
1817 
1818 //*************************************************************************************************
1879 template< typename MT1 // Type of the matrix A
1880  , bool SO // Storage order of all matrices
1881  , typename MT2 // Type of the matrix U
1882  , typename VT // Type of the vector s
1883  , bool TF // Transpose flag of the vector s
1884  , typename MT3 > // Type of the matrix V
1887 {
1892 
1897 
1901 
1906 
1907  using ET = ElementType_<MT1>;
1908  using UT = UnderlyingElement_<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 //*************************************************************************************************
2024 template< 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 {
2034  using boost::numeric_cast;
2035 
2040 
2045 
2049 
2054 
2056 
2057  if( IsFloatingPoint<ST>::value && low >= upp ) {
2058  BLAZE_THROW_INVALID_ARGUMENT( "Invalid value range provided" );
2059  }
2060 
2061  if( !IsFloatingPoint<ST>::value && low > upp ) {
2062  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
2063  }
2064 
2065  const size_t M( (~A).rows() );
2066  const size_t N( (~A).columns() );
2067  const size_t mindim( min( M, N ) );
2068  const size_t expected( IsFloatingPoint<ST>::value ? mindim : size_t( upp - low ) + 1UL );
2069 
2070  if( !IsFloatingPoint<ST>::value && expected > mindim ) {
2071  BLAZE_THROW_INVALID_ARGUMENT( "Invalid index range provided" );
2072  }
2073 
2074  resize( ~s, expected, false );
2075  resize( ~U, M, expected, false );
2076  resize( ~V, expected, N, false );
2077 
2078  if( M == 0UL || N == 0UL ) {
2079  return 0;
2080  }
2081 
2082  const char range( IsFloatingPoint<ST>::value ? 'V' : 'I' );
2083  const ST vl ( IsFloatingPoint<ST>::value ? low : ST() );
2084  const ST vu ( IsFloatingPoint<ST>::value ? upp : ST() );
2085  const int il ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( low ) );
2086  const int iu ( IsFloatingPoint<ST>::value ? 0 : numeric_cast<int>( upp ) );
2087 
2088  const size_t actual( gesvdx_backend( ~A, ~U, ~s, ~V, range, vl, vu, il, iu ) );
2089 
2090  if( IsResizable<VT>::value ) {
2091  resize( ~s, actual, true );
2092  }
2093 
2094  if( IsResizable<MT2>::value ) {
2095  resize( ~U, M, actual, true );
2096  }
2097 
2098  if( IsResizable<MT3>::value ) {
2099  resize( ~V, actual, N, true );
2100  }
2101 
2102  return actual;
2103 }
2104 //*************************************************************************************************
2105 
2106 } // namespace blaze
2107 
2108 #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.
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:102
Header file for auxiliary alias declarations.
Header file for mathematical functions.
#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:261
#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:223
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1755
Header file for the DenseVector base class.
Header file for the UnderlyingElement type trait.
Constraint on the data type.
#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:71
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:133
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:336
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:544
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:177
#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:223
#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:320
#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.