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