2015-05-07 21:54:07 +08:00
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
2016-09-16 17:46:46 +08:00
template < typename T >
2016-09-21 23:08:51 +08:00
Array < T , 4 , 1 > four_denorms ( ) ;
2016-09-16 17:46:46 +08:00
template < >
Array4f four_denorms ( ) { return Array4f ( 5.60844e-39 f , - 5.60844e-39 f , 4.94e-44 f , - 4.94e-44 f ) ; }
template < >
Array4d four_denorms ( ) { return Array4d ( 5.60844e-313 , - 5.60844e-313 , 4.94e-324 , - 4.94e-324 ) ; }
2016-09-21 23:08:51 +08:00
template < typename T >
Array < T , 4 , 1 > four_denorms ( ) { return four_denorms < double > ( ) . cast < T > ( ) ; }
2016-09-16 17:46:46 +08:00
2015-05-07 21:54:07 +08:00
template < typename MatrixType >
void svd_fill_random ( MatrixType & m , int Option = 0 )
{
2016-07-20 21:19:17 +08:00
using std : : pow ;
2015-05-07 21:54:07 +08:00
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : RealScalar RealScalar ;
typedef typename MatrixType : : Index Index ;
Index diagSize = ( std : : min ) ( m . rows ( ) , m . cols ( ) ) ;
RealScalar s = std : : numeric_limits < RealScalar > : : max_exponent10 / 4 ;
s = internal : : random < RealScalar > ( 1 , s ) ;
Matrix < RealScalar , Dynamic , 1 > d = Matrix < RealScalar , Dynamic , 1 > : : Random ( diagSize ) ;
for ( Index k = 0 ; k < diagSize ; + + k )
2016-07-20 21:19:17 +08:00
d ( k ) = d ( k ) * pow ( RealScalar ( 10 ) , internal : : random < RealScalar > ( - s , s ) ) ;
2015-05-07 21:54:07 +08:00
bool dup = internal : : random < int > ( 0 , 10 ) < 3 ;
bool unit_uv = internal : : random < int > ( 0 , 10 ) < ( dup ? 7 : 3 ) ; // if we duplicate some diagonal entries, then increase the chance to preserve them using unitary U and V factors
// duplicate some singular values
if ( dup )
{
Index n = internal : : random < Index > ( 0 , d . size ( ) - 1 ) ;
for ( Index i = 0 ; i < n ; + + i )
d ( internal : : random < Index > ( 0 , d . size ( ) - 1 ) ) = d ( internal : : random < Index > ( 0 , d . size ( ) - 1 ) ) ;
}
Matrix < Scalar , Dynamic , Dynamic > U ( m . rows ( ) , diagSize ) ;
Matrix < Scalar , Dynamic , Dynamic > VT ( diagSize , m . cols ( ) ) ;
if ( unit_uv )
{
// in very rare cases let's try with a pure diagonal matrix
if ( internal : : random < int > ( 0 , 10 ) < 1 )
{
U . setIdentity ( ) ;
VT . setIdentity ( ) ;
}
else
{
createRandomPIMatrixOfRank ( diagSize , U . rows ( ) , U . cols ( ) , U ) ;
createRandomPIMatrixOfRank ( diagSize , VT . rows ( ) , VT . cols ( ) , VT ) ;
}
}
else
{
U . setRandom ( ) ;
VT . setRandom ( ) ;
}
2016-07-26 20:45:44 +08:00
Matrix < Scalar , Dynamic , 1 > samples ( 9 ) ;
2016-09-16 17:46:46 +08:00
samples < < 0 , four_denorms < RealScalar > ( ) ,
- RealScalar ( 1 ) / NumTraits < RealScalar > : : highest ( ) , RealScalar ( 1 ) / NumTraits < RealScalar > : : highest ( ) , ( std : : numeric_limits < RealScalar > : : min ) ( ) , pow ( ( std : : numeric_limits < RealScalar > : : min ) ( ) , 0.8 ) ;
2015-05-13 00:44:46 +08:00
2015-05-07 21:54:07 +08:00
if ( Option = = Symmetric )
{
m = U * d . asDiagonal ( ) * U . transpose ( ) ;
// randomly nullify some rows/columns
{
2015-05-13 00:44:46 +08:00
Index count = internal : : random < Index > ( - diagSize , diagSize ) ;
2015-05-07 21:54:07 +08:00
for ( Index k = 0 ; k < count ; + + k )
{
Index i = internal : : random < Index > ( 0 , diagSize - 1 ) ;
m . row ( i ) . setZero ( ) ;
m . col ( i ) . setZero ( ) ;
}
2015-05-13 00:44:46 +08:00
if ( count < 0 )
// (partly) cancel some coeffs
if ( ! ( dup & & unit_uv ) )
{
Index n = internal : : random < Index > ( 0 , m . size ( ) - 1 ) ;
for ( Index k = 0 ; k < n ; + + k )
{
Index i = internal : : random < Index > ( 0 , m . rows ( ) - 1 ) ;
Index j = internal : : random < Index > ( 0 , m . cols ( ) - 1 ) ;
m ( j , i ) = m ( i , j ) = samples ( internal : : random < Index > ( 0 , samples . size ( ) - 1 ) ) ;
2016-04-15 04:47:30 +08:00
if ( NumTraits < Scalar > : : IsComplex )
* ( & numext : : real_ref ( m ( j , i ) ) + 1 ) = * ( & numext : : real_ref ( m ( i , j ) ) + 1 ) = samples . real ( ) ( internal : : random < Index > ( 0 , samples . size ( ) - 1 ) ) ;
2015-05-13 00:44:46 +08:00
}
}
2015-05-07 21:54:07 +08:00
}
}
else
{
m = U * d . asDiagonal ( ) * VT ;
// (partly) cancel some coeffs
if ( ! ( dup & & unit_uv ) )
{
Index n = internal : : random < Index > ( 0 , m . size ( ) - 1 ) ;
2016-04-15 04:47:30 +08:00
for ( Index k = 0 ; k < n ; + + k )
{
Index i = internal : : random < Index > ( 0 , m . rows ( ) - 1 ) ;
Index j = internal : : random < Index > ( 0 , m . cols ( ) - 1 ) ;
m ( i , j ) = samples ( internal : : random < Index > ( 0 , samples . size ( ) - 1 ) ) ;
if ( NumTraits < Scalar > : : IsComplex )
* ( & numext : : real_ref ( m ( i , j ) ) + 1 ) = samples . real ( ) ( internal : : random < Index > ( 0 , samples . size ( ) - 1 ) ) ;
}
2015-05-07 21:54:07 +08:00
}
}
}