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