1 //=================================================================================================
2 /*!
3 //  \file blaze/math/Submatrix.h
4 //  \brief Header file for the complete Submatrix 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_SUBMATRIX_H_
36 #define _BLAZE_MATH_SUBMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
44 #include <blaze/math/constraints/DenseMatrix.h>
45 #include <blaze/math/constraints/SparseMatrix.h>
46 #include <blaze/math/constraints/Submatrix.h>
47 #include <blaze/math/Exception.h>
48 #include <blaze/math/smp/DenseMatrix.h>
49 #include <blaze/math/smp/SparseMatrix.h>
50 #include <blaze/math/views/Submatrix.h>
51 #include <blaze/math/views/Subvector.h>
52 #include <blaze/util/Random.h>
53 #include <blaze/util/typetraits/RemoveReference.h>
54 
55 
56 namespace blaze {
57 
58 //=================================================================================================
59 //
60 //  RAND SPECIALIZATION FOR DENSE SUBMATRICES
61 //
62 //=================================================================================================
63 
64 //*************************************************************************************************
65 /*! \cond BLAZE_INTERNAL */
66 /*!\brief Specialization of the Rand class template for dense submatrices.
67 // \ingroup random
68 //
69 // This specialization of the Rand class randomizes dense submatrices.
70 */
71 template< typename MT       // Type of the matrix
72         , AlignmentFlag AF  // Alignment flag
73         , bool SO           // Storage order
74         , size_t... CSAs >  // Compile time submatrix arguments
75 class Rand< Submatrix<MT,AF,SO,true,CSAs...> >
76 {
77  public:
78    //**********************************************************************************************
79    /*!\brief Randomization of a dense submatrix.
80    //
81    // \param submatrix The submatrix to be randomized.
82    // \return void
83    */
84    template< typename SMT >  // Type of the submatrix
randomize(SMT && submatrix)85    inline void randomize( SMT&& submatrix ) const
86    {
87       using blaze::randomize;
88 
89       using SubmatrixType = RemoveReference_t<SMT>;
90 
91       BLAZE_CONSTRAINT_MUST_BE_SUBMATRIX_TYPE( SubmatrixType );
92       BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( SubmatrixType );
93 
94       if( SO == rowMajor ) {
95          for( size_t i=0UL; i<submatrix.rows(); ++i ) {
96             for( size_t j=0UL; j<submatrix.columns(); ++j ) {
97                randomize( submatrix(i,j) );
98             }
99          }
100       }
101       else {
102          for( size_t j=0UL; j<submatrix.columns(); ++j ) {
103             for( size_t i=0UL; i<submatrix.rows(); ++i ) {
104                randomize( submatrix(i,j) );
105             }
106          }
107       }
108    }
109    //**********************************************************************************************
110 
111    //**********************************************************************************************
112    /*!\brief Randomization of a dense submatrix.
113    //
114    // \param submatrix The submatrix to be randomized.
115    // \param min The smallest possible value for a matrix element.
116    // \param max The largest possible value for a matrix element.
117    // \return void
118    */
119    template< typename SMT    // Type of the submatrix
120            , typename Arg >  // Min/max argument type
randomize(SMT && submatrix,const Arg & min,const Arg & max)121    inline void randomize( SMT&& submatrix, const Arg& min, const Arg& max ) const
122    {
123       using blaze::randomize;
124 
125       using SubmatrixType = RemoveReference_t<SMT>;
126 
127       BLAZE_CONSTRAINT_MUST_BE_SUBMATRIX_TYPE( SubmatrixType );
128       BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( SubmatrixType );
129 
130       if( SO == rowMajor ) {
131          for( size_t i=0UL; i<submatrix.rows(); ++i ) {
132             for( size_t j=0UL; j<submatrix.columns(); ++j ) {
133                randomize( submatrix(i,j), min, max );
134             }
135          }
136       }
137       else {
138          for( size_t j=0UL; j<submatrix.columns(); ++j ) {
139             for( size_t i=0UL; i<submatrix.rows(); ++i ) {
140                randomize( submatrix(i,j), min, max );
141             }
142          }
143       }
144    }
145    //**********************************************************************************************
146 };
147 /*! \endcond */
148 //*************************************************************************************************
149 
150 
151 
152 
153 //=================================================================================================
154 //
155 //  RAND SPECIALIZATION FOR SPARSE SUBMATRICES
156 //
157 //=================================================================================================
158 
159 //*************************************************************************************************
160 /*! \cond BLAZE_INTERNAL */
161 /*!\brief Specialization of the Rand class template for sparse submatrices.
162 // \ingroup random
163 //
164 // This specialization of the Rand class randomizes sparse submatrices.
165 */
166 template< typename MT       // Type of the dense matrix
167         , AlignmentFlag AF  // Alignment flag
168         , bool SO           // Storage order
169         , size_t... CSAs >  // Compile time submatrix arguments
170 class Rand< Submatrix<MT,AF,SO,false,CSAs...> >
171 {
172  public:
173    //**********************************************************************************************
174    /*!\brief Randomization of a sparse submatrix.
175    //
176    // \param submatrix The submatrix to be randomized.
177    // \return void
178    */
179    template< typename SMT >  // Type of the submatrix
randomize(SMT && submatrix)180    inline void randomize( SMT&& submatrix ) const
181    {
182       using SubmatrixType = RemoveReference_t<SMT>;
183       using ElementType   = ElementType_t<SubmatrixType>;
184 
185       BLAZE_CONSTRAINT_MUST_BE_SUBMATRIX_TYPE( SubmatrixType );
186       BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( SubmatrixType );
187 
188       const size_t m( submatrix.rows()    );
189       const size_t n( submatrix.columns() );
190 
191       if( m == 0UL || n == 0UL ) return;
192 
193       const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*m*n ) ) );
194 
195       submatrix.reset();
196       submatrix.reserve( nonzeros );
197 
198       while( submatrix.nonZeros() < nonzeros ) {
199          submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>();
200       }
201    }
202    //**********************************************************************************************
203 
204    //**********************************************************************************************
205    /*!\brief Randomization of a sparse submatrix.
206    //
207    // \param submatrix The submatrix to be randomized.
208    // \param nonzeros The number of non-zero elements of the random submatrix.
209    // \return void
210    // \exception std::invalid_argument Invalid number of non-zero elements.
211    */
212    template< typename SMT >  // Type of the submatrix
randomize(SMT && submatrix,size_t nonzeros)213    inline void randomize( SMT&& submatrix, size_t nonzeros ) const
214    {
215       using SubmatrixType = RemoveReference_t<SMT>;
216       using ElementType   = ElementType_t<SubmatrixType>;
217 
218       BLAZE_CONSTRAINT_MUST_BE_SUBMATRIX_TYPE( SubmatrixType );
219       BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( SubmatrixType );
220 
221       const size_t m( submatrix.rows()    );
222       const size_t n( submatrix.columns() );
223 
224       if( nonzeros > m*n ) {
225          BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
226       }
227 
228       if( m == 0UL || n == 0UL ) return;
229 
230       submatrix.reset();
231       submatrix.reserve( nonzeros );
232 
233       while( submatrix.nonZeros() < nonzeros ) {
234          submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>();
235       }
236    }
237    //**********************************************************************************************
238 
239    //**********************************************************************************************
240    /*!\brief Randomization of a sparse submatrix.
241    //
242    // \param submatrix The submatrix to be randomized.
243    // \param min The smallest possible value for a submatrix element.
244    // \param max The largest possible value for a submatrix element.
245    // \return void
246    */
247    template< typename SMT    // Type of the submatrix
248            , typename Arg >  // Min/max argument type
randomize(SMT && submatrix,const Arg & min,const Arg & max)249    inline void randomize( SMT&& submatrix, const Arg& min, const Arg& max ) const
250    {
251       using SubmatrixType = RemoveReference_t<SMT>;
252       using ElementType   = ElementType_t<SubmatrixType>;
253 
254       BLAZE_CONSTRAINT_MUST_BE_SUBMATRIX_TYPE( SubmatrixType );
255       BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( SubmatrixType );
256 
257       const size_t m( submatrix.rows()    );
258       const size_t n( submatrix.columns() );
259 
260       if( m == 0UL || n == 0UL ) return;
261 
262       const size_t nonzeros( rand<size_t>( 1UL, std::ceil( 0.5*m*n ) ) );
263 
264       submatrix.reset();
265       submatrix.reserve( nonzeros );
266 
267       while( submatrix.nonZeros() < nonzeros ) {
268          submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>( min, max );
269       }
270    }
271    //**********************************************************************************************
272 
273    //**********************************************************************************************
274    /*!\brief Randomization of a sparse submatrix.
275    //
276    // \param submatrix The submatrix to be randomized.
277    // \param nonzeros The number of non-zero elements of the random submatrix.
278    // \param min The smallest possible value for a submatrix element.
279    // \param max The largest possible value for a submatrix element.
280    // \return void
281    // \exception std::invalid_argument Invalid number of non-zero elements.
282    */
283    template< typename SMT    // Type of the submatrix
284            , typename Arg >  // Min/max argument type
randomize(SMT && submatrix,size_t nonzeros,const Arg & min,const Arg & max)285    inline void randomize( SMT&& submatrix, size_t nonzeros, const Arg& min, const Arg& max ) const
286    {
287       using SubmatrixType = RemoveReference_t<SMT>;
288       using ElementType   = ElementType_t<SubmatrixType>;
289 
290       BLAZE_CONSTRAINT_MUST_BE_SUBMATRIX_TYPE( SubmatrixType );
291       BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( SubmatrixType );
292 
293       const size_t m( submatrix.rows()    );
294       const size_t n( submatrix.columns() );
295 
296       if( nonzeros > m*n ) {
297          BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" );
298       }
299 
300       if( m == 0UL || n == 0UL ) return;
301 
302       submatrix.reset();
303       submatrix.reserve( nonzeros );
304 
305       while( submatrix.nonZeros() < nonzeros ) {
306          submatrix( rand<size_t>( 0UL, m-1UL ), rand<size_t>( 0UL, n-1UL ) ) = rand<ElementType>( min, max );
307       }
308    }
309    //**********************************************************************************************
310 };
311 /*! \endcond */
312 //*************************************************************************************************
313 
314 } // namespace blaze
315 
316 #endif
317