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