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/.
template < typename MatrixType >
void svd_fill_random ( MatrixType & m , int Option = 0 )
{
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 )
d ( k ) = d ( k ) * std : : pow ( RealScalar ( 10 ) , internal : : random < RealScalar > ( - s , s ) ) ;
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 ( ) ;
}
2015-05-13 00:44:46 +08:00
Matrix < Scalar , Dynamic , 1 > samples ( 7 ) ;
samples < < 0 , 5.60844e-313 , - 5.60844e-313 , 4.94e-324 , - 4.94e-324 , - 1. / NumTraits < RealScalar > : : highest ( ) , 1. / NumTraits < RealScalar > : : highest ( ) ;
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
}
}
}