1 //=================================================================================================
2 /*!
3 // \file blaze/math/HybridMatrix.h
4 // \brief Header file for the complete HybridMatrix 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_HYBRIDMATRIX_H_
36 #define _BLAZE_MATH_HYBRIDMATRIX_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <blaze/math/constraints/Scalar.h>
44 #include <blaze/math/dense/HybridMatrix.h>
45 #include <blaze/math/DenseMatrix.h>
46 #include <blaze/math/Exception.h>
47 #include <blaze/math/HybridVector.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/StaticMatrix.h>
52 #include <blaze/math/typetraits/UnderlyingBuiltin.h>
53 #include <blaze/math/ZeroMatrix.h>
54 #include <blaze/util/Assert.h>
55 #include <blaze/util/Random.h>
56
57
58 namespace blaze {
59
60 //=================================================================================================
61 //
62 // RAND SPECIALIZATION
63 //
64 //=================================================================================================
65
66 //*************************************************************************************************
67 /*! \cond BLAZE_INTERNAL */
68 /*!\brief Specialization of the Rand class template for HybridMatrix.
69 // \ingroup random
70 //
71 // This specialization of the Rand class creates random instances of HybridMatrix.
72 */
73 template< typename Type // Data type of the matrix
74 , size_t M // Number of rows
75 , size_t N // Number of columns
76 , bool SO // Storage order
77 , AlignmentFlag AF // Alignment flag
78 , PaddingFlag PF // Padding flag
79 , typename Tag > // Type tag
80 class Rand< HybridMatrix<Type,M,N,SO,AF,PF,Tag> >
81 {
82 public:
83 //*************************************************************************************************
84 /*!\brief Generation of a random HybridMatrix.
85 //
86 // \return The generated random matrix.
87 */
88 inline const HybridMatrix<Type,M,N,SO,AF,PF,Tag>
generate(size_t m,size_t n)89 generate( size_t m, size_t n ) const
90 {
91 HybridMatrix<Type,M,N,SO,AF,PF,Tag> matrix( m, n );
92 randomize( matrix );
93 return matrix;
94 }
95 //*************************************************************************************************
96
97 //*************************************************************************************************
98 /*!\brief Generation of a random HybridMatrix.
99 //
100 // \param min The smallest possible value for a matrix element.
101 // \param max The largest possible value for a matrix element.
102 // \return The generated random matrix.
103 */
104 template< typename Arg > // Min/max argument type
105 inline const HybridMatrix<Type,M,N,SO,AF,PF,Tag>
generate(size_t m,size_t n,const Arg & min,const Arg & max)106 generate( size_t m, size_t n, const Arg& min, const Arg& max ) const
107 {
108 HybridMatrix<Type,M,N,SO,AF,PF,Tag> matrix( m, n );
109 randomize( matrix, min, max );
110 return matrix;
111 }
112 //*************************************************************************************************
113
114 //*************************************************************************************************
115 /*!\brief Randomization of a HybridMatrix.
116 //
117 // \param matrix The matrix to be randomized.
118 // \return void
119 */
randomize(HybridMatrix<Type,M,N,SO,AF,PF,Tag> & matrix)120 inline void randomize( HybridMatrix<Type,M,N,SO,AF,PF,Tag>& matrix ) const
121 {
122 using blaze::randomize;
123
124 const size_t m( matrix.rows() );
125 const size_t n( matrix.columns() );
126
127 for( size_t i=0UL; i<m; ++i ) {
128 for( size_t j=0UL; j<n; ++j ) {
129 randomize( matrix(i,j) );
130 }
131 }
132 }
133 //*************************************************************************************************
134
135 //*************************************************************************************************
136 /*!\brief Randomization of a HybridMatrix.
137 //
138 // \param matrix The matrix to be randomized.
139 // \param min The smallest possible value for a matrix element.
140 // \param max The largest possible value for a matrix element.
141 // \return void
142 */
143 template< typename Arg > // Min/max argument type
randomize(HybridMatrix<Type,M,N,SO,AF,PF,Tag> & matrix,const Arg & min,const Arg & max)144 inline void randomize( HybridMatrix<Type,M,N,SO,AF,PF,Tag>& matrix,
145 const Arg& min, const Arg& max ) const
146 {
147 using blaze::randomize;
148
149 const size_t m( matrix.rows() );
150 const size_t n( matrix.columns() );
151
152 for( size_t i=0UL; i<m; ++i ) {
153 for( size_t j=0UL; j<n; ++j ) {
154 randomize( matrix(i,j), min, max );
155 }
156 }
157 }
158 //*************************************************************************************************
159 };
160 /*! \endcond */
161 //*************************************************************************************************
162
163
164
165
166 //=================================================================================================
167 //
168 // MAKE FUNCTIONS
169 //
170 //=================================================================================================
171
172 //*************************************************************************************************
173 /*! \cond BLAZE_INTERNAL */
174 /*!\brief Setup of a random symmetric HybridMatrix.
175 //
176 // \param matrix The matrix to be randomized.
177 // \return void
178 // \exception std::invalid_argument Invalid non-square matrix provided.
179 */
180 template< typename Type // Data type of the matrix
181 , size_t M // Number of rows
182 , size_t N // Number of columns
183 , bool SO // Storage order
184 , AlignmentFlag AF // Alignment flag
185 , PaddingFlag PF // Padding flag
186 , typename Tag > // Type tag
makeSymmetric(HybridMatrix<Type,M,N,SO,AF,PF,Tag> & matrix)187 void makeSymmetric( HybridMatrix<Type,M,N,SO,AF,PF,Tag>& matrix )
188 {
189 using blaze::randomize;
190
191 if( !isSquare( *matrix ) ) {
192 BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
193 }
194
195 const size_t n( matrix.rows() );
196
197 for( size_t i=0UL; i<n; ++i ) {
198 for( size_t j=0UL; j<i; ++j ) {
199 randomize( matrix(i,j) );
200 matrix(j,i) = matrix(i,j);
201 }
202 randomize( matrix(i,i) );
203 }
204
205 BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
206 }
207 /*! \endcond */
208 //*************************************************************************************************
209
210
211 //*************************************************************************************************
212 /*! \cond BLAZE_INTERNAL */
213 /*!\brief Setup of a random symmetric HybridMatrix.
214 //
215 // \param matrix The matrix to be randomized.
216 // \param min The smallest possible value for a matrix element.
217 // \param max The largest possible value for a matrix element.
218 // \return void
219 // \exception std::invalid_argument Invalid non-square matrix provided.
220 */
221 template< typename Type // Data type of the matrix
222 , size_t M // Number of rows
223 , size_t N // Number of columns
224 , bool SO // Storage order
225 , AlignmentFlag AF // Alignment flag
226 , PaddingFlag PF // Padding flag
227 , typename Tag // Type tag
228 , typename Arg > // Min/max argument type
makeSymmetric(HybridMatrix<Type,M,N,SO,AF,PF,Tag> & matrix,const Arg & min,const Arg & max)229 void makeSymmetric( HybridMatrix<Type,M,N,SO,AF,PF,Tag>& matrix, const Arg& min, const Arg& max )
230 {
231 using blaze::randomize;
232
233 if( !isSquare( *matrix ) ) {
234 BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
235 }
236
237 const size_t n( matrix.rows() );
238
239 for( size_t i=0UL; i<n; ++i ) {
240 for( size_t j=0UL; j<i; ++j ) {
241 randomize( matrix(i,j), min, max );
242 matrix(j,i) = matrix(i,j);
243 }
244 randomize( matrix(i,i), min, max );
245 }
246
247 BLAZE_INTERNAL_ASSERT( isSymmetric( matrix ), "Non-symmetric matrix detected" );
248 }
249 /*! \endcond */
250 //*************************************************************************************************
251
252
253 //*************************************************************************************************
254 /*! \cond BLAZE_INTERNAL */
255 /*!\brief Setup of a random Hermitian HybridMatrix.
256 //
257 // \param matrix The matrix to be randomized.
258 // \return void
259 // \exception std::invalid_argument Invalid non-square matrix provided.
260 */
261 template< typename Type // Data type of the matrix
262 , size_t M // Number of rows
263 , size_t N // Number of columns
264 , bool SO // Storage order
265 , AlignmentFlag AF // Alignment flag
266 , PaddingFlag PF // Padding flag
267 , typename Tag > // Type tag
makeHermitian(HybridMatrix<Type,M,N,SO,AF,PF,Tag> & matrix)268 void makeHermitian( HybridMatrix<Type,M,N,SO,AF,PF,Tag>& matrix )
269 {
270 using blaze::randomize;
271
272 BLAZE_CONSTRAINT_MUST_BE_SCALAR_TYPE( Type );
273
274 using BT = UnderlyingBuiltin_t<Type>;
275
276 if( !isSquare( *matrix ) ) {
277 BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
278 }
279
280 const size_t n( matrix.rows() );
281
282 for( size_t i=0UL; i<n; ++i ) {
283 for( size_t j=0UL; j<i; ++j ) {
284 randomize( matrix(i,j) );
285 matrix(j,i) = conj( matrix(i,j) );
286 }
287 matrix(i,i) = rand<BT>();
288 }
289
290 BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
291 }
292 /*! \endcond */
293 //*************************************************************************************************
294
295
296 //*************************************************************************************************
297 /*! \cond BLAZE_INTERNAL */
298 /*!\brief Setup of a random Hermitian HybridMatrix.
299 //
300 // \param matrix The matrix to be randomized.
301 // \param min The smallest possible value for a matrix element.
302 // \param max The largest possible value for a matrix element.
303 // \return void
304 // \exception std::invalid_argument Invalid non-square matrix provided.
305 */
306 template< typename Type // Data type of the matrix
307 , size_t M // Number of rows
308 , size_t N // Number of columns
309 , bool SO // Storage order
310 , AlignmentFlag AF // Alignment flag
311 , PaddingFlag PF // Padding flag
312 , typename Tag // Type tag
313 , typename Arg > // Min/max argument type
makeHermitian(HybridMatrix<Type,M,N,SO,AF,PF,Tag> & matrix,const Arg & min,const Arg & max)314 void makeHermitian( HybridMatrix<Type,M,N,SO,AF,PF,Tag>& matrix, const Arg& min, const Arg& max )
315 {
316 using blaze::randomize;
317
318 BLAZE_CONSTRAINT_MUST_BE_SCALAR_TYPE( Type );
319
320 using BT = UnderlyingBuiltin_t<Type>;
321
322 if( !isSquare( *matrix ) ) {
323 BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
324 }
325
326 const size_t n( matrix.rows() );
327
328 for( size_t i=0UL; i<n; ++i ) {
329 for( size_t j=0UL; j<i; ++j ) {
330 randomize( matrix(i,j), min, max );
331 matrix(j,i) = conj( matrix(i,j) );
332 }
333 matrix(i,i) = rand<BT>( real( min ), real( max ) );
334 }
335
336 BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-Hermitian matrix detected" );
337 }
338 /*! \endcond */
339 //*************************************************************************************************
340
341
342 //*************************************************************************************************
343 /*! \cond BLAZE_INTERNAL */
344 /*!\brief Setup of a random (Hermitian) positive definite HybridMatrix.
345 //
346 // \param matrix The matrix to be randomized.
347 // \return void
348 // \exception std::invalid_argument Invalid non-square matrix provided.
349 */
350 template< typename Type // Data type of the matrix
351 , size_t M // Number of rows
352 , size_t N // Number of columns
353 , bool SO // Storage order
354 , AlignmentFlag AF // Alignment flag
355 , PaddingFlag PF // Padding flag
356 , typename Tag > // Type tag
makePositiveDefinite(HybridMatrix<Type,M,N,SO,AF,PF,Tag> & matrix)357 void makePositiveDefinite( HybridMatrix<Type,M,N,SO,AF,PF,Tag>& matrix )
358 {
359 using blaze::randomize;
360
361 BLAZE_CONSTRAINT_MUST_BE_SCALAR_TYPE( Type );
362
363 if( !isSquare( *matrix ) ) {
364 BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
365 }
366
367 const size_t n( matrix.rows() );
368
369 randomize( matrix );
370 matrix *= ctrans( matrix );
371
372 for( size_t i=0UL; i<n; ++i ) {
373 matrix(i,i) += Type(n);
374 }
375
376 BLAZE_INTERNAL_ASSERT( isHermitian( matrix ), "Non-symmetric matrix detected" );
377 }
378 /*! \endcond */
379 //*************************************************************************************************
380
381 } // namespace blaze
382
383 #endif
384