1 //=================================================================================================
2 /*!
3 //  \file blaze/math/DynamicMatrix.h
4 //  \brief Header file for the complete DynamicMatrix implementation
5 //
6 //  Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 //  This file is part of the Blaze library. You can redistribute it and/or modify it under
9 //  the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 //  forms, with or without modification, are permitted provided that the following conditions
11 //  are met:
12 //
13 //  1. Redistributions of source code must retain the above copyright notice, this list of
14 //     conditions and the following disclaimer.
15 //  2. Redistributions in binary form must reproduce the above copyright notice, this list
16 //     of conditions and the following disclaimer in the documentation and/or other materials
17 //     provided with the distribution.
18 //  3. Neither the names of the Blaze development group nor the names of its contributors
19 //     may be used to endorse or promote products derived from this software without specific
20 //     prior written permission.
21 //
22 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 //  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 //  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 //  SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 //  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 //  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 //  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 //  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 //  DAMAGE.
32 */
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_DYNAMICMATRIX_H_
36 #define _BLAZE_MATH_DYNAMICMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/constraints/Scalar.h>
44 #include <blaze/math/dense/DynamicMatrix.h>
45 #include <blaze/math/DenseMatrix.h>
46 #include <blaze/math/DynamicVector.h>
47 #include <blaze/math/Exception.h>
48 #include <blaze/math/IdentityMatrix.h>
49 #include <blaze/math/shims/Conjugate.h>
50 #include <blaze/math/shims/Real.h>
51 #include <blaze/math/typetraits/UnderlyingBuiltin.h>
52 #include <blaze/math/ZeroMatrix.h>
53 #include <blaze/util/Assert.h>
54 #include <blaze/util/Random.h>
55 
56 
57 namespace blaze {
58 
59 //=================================================================================================
60 //
61 //  RAND SPECIALIZATION
62 //
63 //=================================================================================================
64 
65 //*************************************************************************************************
66 /*! \cond BLAZE_INTERNAL */
67 /*!\brief Specialization of the Rand class template for DynamicMatrix.
68 // \ingroup random
69 //
70 // This specialization of the Rand class creates random instances of DynamicMatrix.
71 */
72 template< typename Type   // Data type of the matrix
73         , bool SO         // Storage order
74         , typename Tag >  // Type tag
75 class Rand< DynamicMatrix<Type,SO,Tag> >
76 {
77  public:
78    //**********************************************************************************************
79    /*!\brief Generation of a random DynamicMatrix.
80    //
81    // \param m The number of rows of the random matrix.
82    // \param n The number of columns of the random matrix.
83    // \return The generated random matrix.
84    */
85    inline const DynamicMatrix<Type,SO,Tag>
generate(size_t m,size_t n)86       generate( size_t m, size_t n ) const
87    {
88       DynamicMatrix<Type,SO,Tag> matrix( m, n );
89       randomize( matrix );
90       return matrix;
91    }
92    //**********************************************************************************************
93 
94    //**********************************************************************************************
95    /*!\brief Generation of a random DynamicMatrix.
96    //
97    // \param m The number of rows of the random matrix.
98    // \param n The number of columns of the random matrix.
99    // \param min The smallest possible value for a matrix element.
100    // \param max The largest possible value for a matrix element.
101    // \return The generated random matrix.
102    */
103    template< typename Arg >  // Min/max argument type
104    inline const DynamicMatrix<Type,SO,Tag>
generate(size_t m,size_t n,const Arg & min,const Arg & max)105       generate( size_t m, size_t n, const Arg& min, const Arg& max ) const
106    {
107       DynamicMatrix<Type,SO,Tag> matrix( m, n );
108       randomize( matrix, min, max );
109       return matrix;
110    }
111    //**********************************************************************************************
112 
113    //**********************************************************************************************
114    /*!\brief Randomization of a DynamicMatrix.
115    //
116    // \param matrix The matrix to be randomized.
117    // \return void
118    */
randomize(DynamicMatrix<Type,SO,Tag> & matrix)119    inline void randomize( DynamicMatrix<Type,SO,Tag>& matrix ) const
120    {
121       using blaze::randomize;
122 
123       const size_t m( matrix.rows()    );
124       const size_t n( matrix.columns() );
125 
126       for( size_t i=0UL; i<m; ++i ) {
127          for( size_t j=0UL; j<n; ++j ) {
128             randomize( matrix(i,j) );
129          }
130       }
131    }
132    //**********************************************************************************************
133 
134    //**********************************************************************************************
135    /*!\brief Randomization of a DynamicMatrix.
136    //
137    // \param matrix The matrix to be randomized.
138    // \param min The smallest possible value for a matrix element.
139    // \param max The largest possible value for a matrix element.
140    // \return void
141    */
142    template< typename Arg >  // Min/max argument type
randomize(DynamicMatrix<Type,SO,Tag> & matrix,const Arg & min,const Arg & max)143    inline void randomize( DynamicMatrix<Type,SO,Tag>& matrix,
144                           const Arg& min, const Arg& max ) const
145    {
146       using blaze::randomize;
147 
148       const size_t m( matrix.rows()    );
149       const size_t n( matrix.columns() );
150 
151       for( size_t i=0UL; i<m; ++i ) {
152          for( size_t j=0UL; j<n; ++j ) {
153             randomize( matrix(i,j), min, max );
154          }
155       }
156    }
157    //**********************************************************************************************
158 };
159 /*! \endcond */
160 //*************************************************************************************************
161 
162 
163 
164 
165 //=================================================================================================
166 //
167 //  MAKE FUNCTIONS
168 //
169 //=================================================================================================
170 
171 //*************************************************************************************************
172 /*! \cond BLAZE_INTERNAL */
173 /*!\brief Setup of a random symmetric DynamicMatrix.
174 //
175 // \param matrix The matrix to be randomized.
176 // \return void
177 // \exception std::invalid_argument Invalid non-square matrix provided.
178 */
179 template< typename Type   // Data type of the matrix
180         , bool SO         // Storage order
181         , typename Tag >  // Type tag
makeSymmetric(DynamicMatrix<Type,SO,Tag> & matrix)182 void makeSymmetric( DynamicMatrix<Type,SO,Tag>& matrix )
183 {
184    using blaze::randomize;
185 
186    if( !isSquare( *matrix ) ) {
187       BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
188    }
189 
190    const size_t n( matrix.rows() );
191 
192    for( size_t i=0UL; i<n; ++i ) {
193       for( size_t j=0UL; j<i; ++j ) {
194          randomize( matrix(i,j) );
195          matrix(j,i) = matrix(i,j);
196       }
197       randomize( matrix(i,i) );
198    }
199 
200    BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
201 }
202 /*! \endcond */
203 //*************************************************************************************************
204 
205 
206 //*************************************************************************************************
207 /*! \cond BLAZE_INTERNAL */
208 /*!\brief Setup of a random symmetric DynamicMatrix.
209 //
210 // \param matrix The matrix to be randomized.
211 // \param min The smallest possible value for a matrix element.
212 // \param max The largest possible value for a matrix element.
213 // \return void
214 // \exception std::invalid_argument Invalid non-square matrix provided.
215 */
216 template< typename Type   // Data type of the matrix
217         , bool SO         // Storage order
218         , typename Tag    // Type tag
219         , typename Arg >  // Min/max argument type
makeSymmetric(DynamicMatrix<Type,SO,Tag> & matrix,const Arg & min,const Arg & max)220 void makeSymmetric( DynamicMatrix<Type,SO,Tag>& matrix, const Arg& min, const Arg& max )
221 {
222    using blaze::randomize;
223 
224    if( !isSquare( *matrix ) ) {
225       BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
226    }
227 
228    const size_t n( matrix.rows() );
229 
230    for( size_t i=0UL; i<n; ++i ) {
231       for( size_t j=0UL; j<i; ++j ) {
232          randomize( matrix(i,j), min, max );
233          matrix(j,i) = matrix(i,j);
234       }
235       randomize( matrix(i,i), min, max );
236    }
237 
238    BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
239 }
240 /*! \endcond */
241 //*************************************************************************************************
242 
243 
244 //*************************************************************************************************
245 /*! \cond BLAZE_INTERNAL */
246 /*!\brief Setup of a random Hermitian DynamicMatrix.
247 //
248 // \param matrix The matrix to be randomized.
249 // \return void
250 // \exception std::invalid_argument Invalid non-square matrix provided.
251 */
252 template< typename Type   // Data type of the matrix
253         , bool SO         // Storage order
254         , typename Tag >  // Type tag
makeHermitian(DynamicMatrix<Type,SO,Tag> & matrix)255 void makeHermitian( DynamicMatrix<Type,SO,Tag>& matrix )
256 {
257    using blaze::randomize;
258 
259    BLAZE_CONSTRAINT_MUST_BE_SCALAR_TYPE( Type );
260 
261    using BT = UnderlyingBuiltin_t<Type>;
262 
263    if( !isSquare( *matrix ) ) {
264       BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
265    }
266 
267    const size_t n( matrix.rows() );
268 
269    for( size_t i=0UL; i<n; ++i ) {
270       for( size_t j=0UL; j<i; ++j ) {
271          randomize( matrix(i,j) );
272          matrix(j,i) = conj( matrix(i,j) );
273       }
274       matrix(i,i) = rand<BT>();
275    }
276 
277    BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
278 }
279 /*! \endcond */
280 //*************************************************************************************************
281 
282 
283 //*************************************************************************************************
284 /*! \cond BLAZE_INTERNAL */
285 /*!\brief Setup of a random Hermitian DynamicMatrix.
286 //
287 // \param matrix The matrix to be randomized.
288 // \param min The smallest possible value for a matrix element.
289 // \param max The largest possible value for a matrix element.
290 // \return void
291 // \exception std::invalid_argument Invalid non-square matrix provided.
292 */
293 template< typename Type   // Data type of the matrix
294         , bool SO         // Storage order
295         , typename Tag    // Type tag
296         , typename Arg >  // Min/max argument type
makeHermitian(DynamicMatrix<Type,SO,Tag> & matrix,const Arg & min,const Arg & max)297 void makeHermitian( DynamicMatrix<Type,SO,Tag>& matrix, const Arg& min, const Arg& max )
298 {
299    using blaze::randomize;
300 
301    BLAZE_CONSTRAINT_MUST_BE_SCALAR_TYPE( Type );
302 
303    using BT = UnderlyingBuiltin_t<Type>;
304 
305    if( !isSquare( *matrix ) ) {
306       BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
307    }
308 
309    const size_t n( matrix.rows() );
310 
311    for( size_t i=0UL; i<n; ++i ) {
312       for( size_t j=0UL; j<i; ++j ) {
313          randomize( matrix(i,j), min, max );
314          matrix(j,i) = conj( matrix(i,j) );
315       }
316       matrix(i,i) = rand<BT>( real( min ), real( max ) );
317    }
318 
319    BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
320 }
321 /*! \endcond */
322 //*************************************************************************************************
323 
324 
325 //*************************************************************************************************
326 /*! \cond BLAZE_INTERNAL */
327 /*!\brief Setup of a random (Hermitian) positive definite DynamicMatrix.
328 //
329 // \param matrix The matrix to be randomized.
330 // \return void
331 // \exception std::invalid_argument Invalid non-square matrix provided.
332 */
333 template< typename Type   // Data type of the matrix
334         , bool SO         // Storage order
335         , typename Tag >  // Type tag
makePositiveDefinite(DynamicMatrix<Type,SO,Tag> & matrix)336 void makePositiveDefinite( DynamicMatrix<Type,SO,Tag>& matrix )
337 {
338    using blaze::randomize;
339 
340    BLAZE_CONSTRAINT_MUST_BE_SCALAR_TYPE( Type );
341 
342    if( !isSquare( *matrix ) ) {
343       BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
344    }
345 
346    const size_t n( matrix.rows() );
347 
348    randomize( matrix );
349    matrix *= ctrans( matrix );
350 
351    for( size_t i=0UL; i<n; ++i ) {
352       matrix(i,i) += Type(n);
353    }
354 
355    BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-symmetric matrix detected" );
356 }
357 /*! \endcond */
358 //*************************************************************************************************
359 
360 } // namespace blaze
361 
362 #endif
363