1 //=================================================================================================
2 /*!
3 // \file blaze/math/expressions/SMatReduceExpr.h
4 // \brief Header file for the sparse matrix reduce expression
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_EXPRESSIONS_SMATREDUCEEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATREDUCEEXPR_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <iterator>
44 #include <blaze/math/Aliases.h>
45 #include <blaze/math/constraints/ColumnMajorMatrix.h>
46 #include <blaze/math/constraints/ColumnVector.h>
47 #include <blaze/math/constraints/DenseVector.h>
48 #include <blaze/math/constraints/RequiresEvaluation.h>
49 #include <blaze/math/constraints/RowMajorMatrix.h>
50 #include <blaze/math/constraints/RowVector.h>
51 #include <blaze/math/constraints/SparseMatrix.h>
52 #include <blaze/math/Exception.h>
53 #include <blaze/math/expressions/Computation.h>
54 #include <blaze/math/expressions/DenseVector.h>
55 #include <blaze/math/expressions/Forward.h>
56 #include <blaze/math/expressions/MatReduceExpr.h>
57 #include <blaze/math/expressions/SparseMatrix.h>
58 #include <blaze/math/functors/Add.h>
59 #include <blaze/math/functors/Max.h>
60 #include <blaze/math/functors/Min.h>
61 #include <blaze/math/functors/Mult.h>
62 #include <blaze/math/ReductionFlag.h>
63 #include <blaze/math/shims/Serial.h>
64 #include <blaze/math/traits/ReduceTrait.h>
65 #include <blaze/math/typetraits/IsExpression.h>
66 #include <blaze/math/typetraits/RequiresEvaluation.h>
67 #include <blaze/math/views/Check.h>
68 #include <blaze/system/MacroDisable.h>
69 #include <blaze/system/Thresholds.h>
70 #include <blaze/util/Assert.h>
71 #include <blaze/util/EnableIf.h>
72 #include <blaze/util/FunctionTrace.h>
73 #include <blaze/util/mpl/If.h>
74 #include <blaze/util/StaticAssert.h>
75 #include <blaze/util/Types.h>
76 #include <blaze/util/typetraits/HasMember.h>
77
78
79 namespace blaze {
80
81 //=================================================================================================
82 //
83 // CLASS DEFINITION
84 //
85 //=================================================================================================
86
87 //*************************************************************************************************
88 /*!\brief Base template for row-major sparse matrix partial reduction operations.
89 // \ingroup dense_vector_expression
90 //
91 // The SMatReduceExpr class represents the compile time expression for partial reduction operations
92 // of row-major sparse matrices.
93 */
94 template< typename MT // Type of the sparse matrix
95 , typename OP // Type of the reduction operation
96 , ReductionFlag RF > // Reduction flag
97 class SMatReduceExpr
98 {};
99 //*************************************************************************************************
100
101
102
103
104 //=================================================================================================
105 //
106 // CLASS TEMPLATE SPECIALIZATION FOR COLUMN-WISE REDUCTION OPERATIONS OF ROW-MAJOR MATRICES
107 //
108 //=================================================================================================
109
110 //*************************************************************************************************
111 /*!\brief Expression object for column-wise row-major sparse matrix reduction operations.
112 // \ingroup dense_vector_expression
113 //
114 // This specialization of the SMatReduceExpr class template represents the compile time expression
115 // for column-wise reduction operations of row-major sparse matrices.
116 */
117 template< typename MT // Type of the sparse matrix
118 , typename OP > // Type of the reduction operation
119 class SMatReduceExpr<MT,OP,columnwise>
120 : public MatReduceExpr< DenseVector< SMatReduceExpr<MT,OP,columnwise>, true >, columnwise >
121 , private Computation
122 {
123 private:
124 //**Type definitions****************************************************************************
125 using RT = ResultType_t<MT>; //!< Result type of the sparse matrix expression.
126 using OT = OppositeType_t<MT>; //!< Opposite type of the sparse matrix expression.
127 using ET = ElementType_t<MT>; //!< Element type of the sparse matrix expression.
128 using CT = CompositeType_t<MT>; //!< Composite type of the sparse matrix expression.
129 //**********************************************************************************************
130
131 //**Parallel evaluation strategy****************************************************************
132 /*! \cond BLAZE_INTERNAL */
133 //! Helper variable template for the explicit application of the SFINAE principle.
134 /*! This variable template is a helper for the selection of the parallel evaluation strategy.
135 In case the sparse matrix operand is not SMP assignable and requires an intermediate
136 evaluation, the variable is set to 1 and the expression specific evaluation strategy is
137 selected. Otherwise the variable is set to 0 and the default strategy is chosen. */
138 template< typename VT >
139 static constexpr bool UseSMPAssign_v = ( !MT::smpAssignable && RequiresEvaluation_v<MT> );
140 /*! \endcond */
141 //**********************************************************************************************
142
143 public:
144 //**Type definitions****************************************************************************
145 //! Type of this SMatReduceExpr instance.
146 using This = SMatReduceExpr<MT,OP,columnwise>;
147
148 //! Base type of this SMatReduceExpr instance.
149 using BaseType = MatReduceExpr< DenseVector<This,true>, columnwise >;
150
151 using ResultType = ReduceTrait_t<RT,OP,columnwise>; //!< Result type for expression template evaluations.
152 using TransposeType = TransposeType_t<ResultType>; //!< Transpose type for expression template evaluations.
153 using ElementType = ElementType_t<ResultType>; //!< Resulting element type.
154 using SIMDType = SIMDTrait_t<ElementType>; //!< Resulting SIMD element type.
155 using ReturnType = const ElementType; //!< Return type for expression template evaluations.
156 using CompositeType = const ResultType; //!< Data type for composite expression templates.
157
158 //! Composite type of the left-hand side sparse matrix expression.
159 using Operand = If_t< IsExpression_v<MT>, const MT, const MT& >;
160
161 //! Data type of the custom unary operation.
162 using Operation = OP;
163 //**********************************************************************************************
164
165 //**Compilation flags***************************************************************************
166 //! Compilation switch for the expression template evaluation strategy.
167 static constexpr bool simdEnabled = false;
168
169 //! Compilation switch for the expression template assignment strategy.
170 static constexpr bool smpAssignable = MT::smpAssignable;
171 //**********************************************************************************************
172
173 //**Constructor*********************************************************************************
174 /*!\brief Constructor for the SMatReduceExpr class.
175 //
176 // \param sm The matrix operand of the reduction expression.
177 // \param op The reduction operation.
178 */
SMatReduceExpr(const MT & sm,OP op)179 inline SMatReduceExpr( const MT& sm, OP op ) noexcept
180 : sm_( sm ) // Sparse matrix of the reduction expression
181 , op_( std::move(op) ) // The reduction operation
182 {}
183 //**********************************************************************************************
184
185 //**Subscript operator**************************************************************************
186 /*!\brief Subscript operator for the direct access to the vector elements.
187 //
188 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
189 // \return The resulting value.
190 */
191 inline ReturnType operator[]( size_t index ) const {
192 BLAZE_INTERNAL_ASSERT( index < sm_.columns(), "Invalid vector access index" );
193 return reduce( column( sm_, index, unchecked ), op_ );
194 }
195 //**********************************************************************************************
196
197 //**At function*********************************************************************************
198 /*!\brief Checked access to the vector elements.
199 //
200 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
201 // \return The resulting value.
202 // \exception std::out_of_range Invalid vector access index.
203 */
at(size_t index)204 inline ReturnType at( size_t index ) const {
205 if( index >= sm_.columns() ) {
206 BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
207 }
208 return (*this)[index];
209 }
210 //**********************************************************************************************
211
212 //**Size function*******************************************************************************
213 /*!\brief Returns the current size/dimension of the vector.
214 //
215 // \return The size of the vector.
216 */
size()217 inline size_t size() const noexcept {
218 return sm_.columns();
219 }
220 //**********************************************************************************************
221
222 //**Operand access******************************************************************************
223 /*!\brief Returns the sparse matrix operand.
224 //
225 // \return The sparse matrix operand.
226 */
operand()227 inline Operand operand() const noexcept {
228 return sm_;
229 }
230 //**********************************************************************************************
231
232 //**Operation access****************************************************************************
233 /*!\brief Returns a copy of the reduction operation.
234 //
235 // \return A copy of the reduction operation.
236 */
operation()237 inline Operation operation() const {
238 return op_;
239 }
240 //**********************************************************************************************
241
242 //**********************************************************************************************
243 /*!\brief Returns whether the expression can alias with the given address \a alias.
244 //
245 // \param alias The alias to be checked.
246 // \return \a true in case an aliasing effect is possible, \a false if not.
247 */
248 template< typename T >
canAlias(const T * alias)249 inline bool canAlias( const T* alias ) const noexcept {
250 return ( sm_.isAliased( alias ) );
251 }
252 //**********************************************************************************************
253
254 //**********************************************************************************************
255 /*!\brief Returns whether the expression is aliased with the given address \a alias.
256 //
257 // \param alias The alias to be checked.
258 // \return \a true in case the given alias is contained in this expression, \a false if not.
259 */
260 template< typename T >
isAliased(const T * alias)261 inline bool isAliased( const T* alias ) const noexcept {
262 return ( sm_.isAliased( alias ) );
263 }
264 //**********************************************************************************************
265
266 //**********************************************************************************************
267 /*!\brief Returns whether the operands of the expression are properly aligned in memory.
268 //
269 // \return \a true in case the operands are aligned, \a false if not.
270 */
isAligned()271 inline bool isAligned() const noexcept {
272 return false;
273 }
274 //**********************************************************************************************
275
276 //**********************************************************************************************
277 /*!\brief Returns whether the expression can be used in SMP assignments.
278 //
279 // \return \a true in case the expression can be used in SMP assignments, \a false if not.
280 */
canSMPAssign()281 inline bool canSMPAssign() const noexcept {
282 return sm_.canSMPAssign() || ( size() > SMP_SMATREDUCE_THRESHOLD );
283 }
284 //**********************************************************************************************
285
286 private:
287 //**Member variables****************************************************************************
288 Operand sm_; //!< Sparse matrix of the reduction expression.
289 Operation op_; //!< The reduction operation.
290 //**********************************************************************************************
291
292 //**Assignment to dense vectors*****************************************************************
293 /*! \cond BLAZE_INTERNAL */
294 /*!\brief Assignment of a column-wise row-major sparse matrix reduction operation to a dense vector.
295 // \ingroup dense_vector
296 //
297 // \param lhs The target left-hand side dense vector.
298 // \param rhs The right-hand side reduction expression to be assigned.
299 // \return void
300 //
301 // This function implements the performance optimized assignment of a column-wise row-major
302 // sparse matrix reduction expression to a dense vector.
303 */
304 template< typename VT1 > // Type of the target dense vector
assign(DenseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)305 friend inline void assign( DenseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
306 {
307 BLAZE_FUNCTION_TRACE;
308
309 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( OT );
310 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OT );
311 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( OT );
312
313 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
314
315 const OT tmp( serial( rhs.sm_ ) );
316 assign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
317 }
318 /*! \endcond */
319 //**********************************************************************************************
320
321 //**Assignment to sparse vectors****************************************************************
322 /*! \cond BLAZE_INTERNAL */
323 /*!\brief Assignment of a column-wise row-major sparse matrix reduction operation to a dense
324 // vector.
325 // \ingroup dense_vector
326 //
327 // \param lhs The target left-hand side dense vector.
328 // \param rhs The right-hand side reduction expression to be assigned.
329 // \return void
330 //
331 // This function implements the performance optimized assignment of a column-wise row-major
332 // sparse matrix reduction expression to a dense vector.
333 */
334 template< typename VT1 > // Type of the target dense vector
assign(SparseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)335 friend inline void assign( SparseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
336 {
337 BLAZE_FUNCTION_TRACE;
338
339 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
340 BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE( ResultType );
341 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
342
343 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
344
345 const ResultType tmp( serial( rhs ) );
346 assign( *lhs, tmp );
347 }
348 /*! \endcond */
349 //**********************************************************************************************
350
351 //**Addition assignment to dense vectors********************************************************
352 /*! \cond BLAZE_INTERNAL */
353 /*!\brief Addition assignment of a column-wise row-major sparse matrix reduction operation to a
354 // dense vector.
355 // \ingroup dense_vector
356 //
357 // \param lhs The target left-hand side dense vector.
358 // \param rhs The right-hand side reduction expression to be added.
359 // \return void
360 //
361 // This function implements the performance optimized addition assignment of a column-wise
362 // row-major sparse matrix reduction expression to a dense vector.
363 */
364 template< typename VT1 > // Type of the target dense vector
addAssign(DenseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)365 friend inline void addAssign( DenseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
366 {
367 BLAZE_FUNCTION_TRACE;
368
369 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( OT );
370 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OT );
371 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( OT );
372
373 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
374
375 const OT tmp( serial( rhs.sm_ ) );
376 addAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
377 }
378 /*! \endcond */
379 //**********************************************************************************************
380
381 //**Addition assignment to sparse vectors*******************************************************
382 /*! \cond BLAZE_INTERNAL */
383 /*!\brief Addition assignment of a column-wise row-major sparse matrix reduction operation
384 // to a dense vector.
385 // \ingroup dense_vector
386 //
387 // \param lhs The target left-hand side dense vector.
388 // \param rhs The right-hand side reduction expression to be added.
389 // \return void
390 //
391 // This function implements the performance optimized addition assignment of a column-wise
392 // row-major sparse matrix reduction expression to a dense vector.
393 */
394 template< typename VT1 > // Type of the target dense vector
addAssign(SparseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)395 friend inline void addAssign( SparseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
396 {
397 BLAZE_FUNCTION_TRACE;
398
399 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
400 BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE( ResultType );
401 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
402
403 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
404
405 const ResultType tmp( serial( rhs ) );
406 addAssign( *lhs, tmp );
407 }
408 /*! \endcond */
409 //**********************************************************************************************
410
411 //**Subtraction assignment to dense vectors*****************************************************
412 /*! \cond BLAZE_INTERNAL */
413 /*!\brief Subtraction assignment of a column-wise row-major sparse matrix reduction operation
414 // to a dense vector.
415 // \ingroup dense_vector
416 //
417 // \param lhs The target left-hand side dense vector.
418 // \param rhs The right-hand side reduction expression to be subtracted.
419 // \return void
420 //
421 // This function implements the performance optimized subtraction assignment of a column-wise
422 // row-major sparse matrix reduction expression to a dense vector.
423 */
424 template< typename VT1 > // Type of the target dense vector
subAssign(DenseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)425 friend inline void subAssign( DenseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
426 {
427 BLAZE_FUNCTION_TRACE;
428
429 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( OT );
430 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OT );
431 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( OT );
432
433 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
434
435 const OT tmp( serial( rhs.sm_ ) );
436 subAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
437 }
438 /*! \endcond */
439 //**********************************************************************************************
440
441 //**Subtraction assignment to sparse vectors****************************************************
442 /*! \cond BLAZE_INTERNAL */
443 /*!\brief Subtraction assignment of a column-wise row-major sparse matrix reduction operation
444 // to a dense vector.
445 // \ingroup dense_vector
446 //
447 // \param lhs The target left-hand side dense vector.
448 // \param rhs The right-hand side reduction expression to be subtracted.
449 // \return void
450 //
451 // This function implements the performance optimized subtraction assignment of a column-wise
452 // row-major sparse matrix reduction expression to a dense vector.
453 */
454 template< typename VT1 > // Type of the target dense vector
subAssign(SparseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)455 friend inline void subAssign( SparseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
456 {
457 BLAZE_FUNCTION_TRACE;
458
459 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
460 BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE( ResultType );
461 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
462
463 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
464
465 const ResultType tmp( serial( rhs ) );
466 subAssign( *lhs, tmp );
467 }
468 /*! \endcond */
469 //**********************************************************************************************
470
471 //**Multiplication assignment to dense vectors**************************************************
472 /*! \cond BLAZE_INTERNAL */
473 /*!\brief Multiplication assignment of a column-wise row-major sparse matrix reduction operation
474 // to a dense vector.
475 // \ingroup dense_vector
476 //
477 // \param lhs The target left-hand side dense vector.
478 // \param rhs The right-hand side reduction expression to be multiplied.
479 // \return void
480 //
481 // This function implements the performance optimized multiplication assignment of a column-wise
482 // row-major sparse matrix reduction expression to a dense vector.
483 */
484 template< typename VT1 > // Type of the target dense vector
multAssign(DenseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)485 friend inline void multAssign( DenseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
486 {
487 BLAZE_FUNCTION_TRACE;
488
489 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( OT );
490 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OT );
491 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( OT );
492
493 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
494
495 const OT tmp( serial( rhs.sm_ ) );
496 multAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
497 }
498 /*! \endcond */
499 //**********************************************************************************************
500
501 //**Multiplication assignment to sparse vectors*************************************************
502 /*! \cond BLAZE_INTERNAL */
503 /*!\brief Multiplication assignment of a column-wise row-major sparse matrix reduction operation
504 // to a dense vector.
505 // \ingroup dense_vector
506 //
507 // \param lhs The target left-hand side dense vector.
508 // \param rhs The right-hand side reduction expression to be multiplied.
509 // \return void
510 //
511 // This function implements the performance optimized multiplication assignment of a column-wise
512 // row-major sparse matrix reduction expression to a dense vector.
513 */
514 template< typename VT1 > // Type of the target dense vector
multAssign(SparseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)515 friend inline void multAssign( SparseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
516 {
517 BLAZE_FUNCTION_TRACE;
518
519 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
520 BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE( ResultType );
521 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
522
523 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
524
525 const ResultType tmp( serial( rhs ) );
526 multAssign( *lhs, tmp );
527 }
528 /*! \endcond */
529 //**********************************************************************************************
530
531 //**Division assignment to dense vectors********************************************************
532 /*! \cond BLAZE_INTERNAL */
533 /*!\brief Division assignment of a column-wise row-major sparse matrix reduction operation
534 // to a dense vector.
535 // \ingroup dense_vector
536 //
537 // \param lhs The target left-hand side dense vector.
538 // \param rhs The right-hand side reduction expression divisor.
539 // \return void
540 //
541 // This function implements the performance optimized division assignment of a column-wise
542 // row-major sparse matrix reduction expression to a dense vector.
543 */
544 template< typename VT1 > // Type of the target dense vector
divAssign(DenseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)545 friend inline void divAssign( DenseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
546 {
547 BLAZE_FUNCTION_TRACE;
548
549 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( OT );
550 BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OT );
551 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( OT );
552
553 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
554
555 const OT tmp( serial( rhs.sm_ ) );
556 divAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
557 }
558 /*! \endcond */
559 //**********************************************************************************************
560
561 //**Division assignment to sparse vectors*******************************************************
562 /*! \cond BLAZE_INTERNAL */
563 /*!\brief Division assignment of a column-wise row-major sparse matrix reduction operation
564 // to a dense vector.
565 // \ingroup dense_vector
566 //
567 // \param lhs The target left-hand side dense vector.
568 // \param rhs The right-hand side reduction expression divisor.
569 // \return void
570 //
571 // This function implements the performance optimized division assignment of a column-wise
572 // row-major sparse matrix reduction expression to a dense vector.
573 */
574 template< typename VT1 > // Type of the target dense vector
divAssign(SparseVector<VT1,true> & lhs,const SMatReduceExpr & rhs)575 friend inline void divAssign( SparseVector<VT1,true>& lhs, const SMatReduceExpr& rhs )
576 {
577 BLAZE_FUNCTION_TRACE;
578
579 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( ResultType );
580 BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE( ResultType );
581 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
582
583 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
584
585 const ResultType tmp( serial( rhs ) );
586 divAssign( *lhs, tmp );
587 }
588 /*! \endcond */
589 //**********************************************************************************************
590
591 //**SMP assignment to vectors*******************************************************************
592 /*! \cond BLAZE_INTERNAL */
593 /*!\brief SMP assignment of a column-wise row-major sparse matrix reduction operation to a vector.
594 // \ingroup dense_vector
595 //
596 // \param lhs The target left-hand side vector.
597 // \param rhs The right-hand side reduction expression to be assigned.
598 // \return void
599 //
600 // This function implements the performance optimized SMP assignment of a column-wise row-major
601 // sparse matrix reduction expression to a vector. Due to the explicit application of the SFINAE
602 // principle, this function can only be selected by the compiler in case the expression specific
603 // parallel evaluation strategy is selected.
604 */
605 template< typename VT1 > // Type of the target vector
606 friend inline auto smpAssign( Vector<VT1,true>& lhs, const SMatReduceExpr& rhs )
607 -> EnableIf_t< UseSMPAssign_v<VT1> >
608 {
609 BLAZE_FUNCTION_TRACE;
610
611 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
612
613 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
614 smpAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
615 }
616 /*! \endcond */
617 //**********************************************************************************************
618
619 //**SMP addition assignment to vectors**********************************************************
620 /*! \cond BLAZE_INTERNAL */
621 /*!\brief SMP addition assignment of a column-wise row-major sparse matrix reduction operation
622 // to a vector.
623 // \ingroup dense_vector
624 //
625 // \param lhs The target left-hand side vector.
626 // \param rhs The right-hand side reduction expression to be added.
627 // \return void
628 //
629 // This function implements the performance optimized SMP addition assignment of a column-wise
630 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
631 // of the SFINAE principle, this function can only be selected by the compiler in case the
632 // expression specific parallel evaluation strategy is selected.
633 */
634 template< typename VT1 > // Type of the target vector
635 friend inline auto smpAddAssign( Vector<VT1,true>& lhs, const SMatReduceExpr& rhs )
636 -> EnableIf_t< UseSMPAssign_v<VT1> >
637 {
638 BLAZE_FUNCTION_TRACE;
639
640 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
641
642 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
643 smpAddAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
644 }
645 /*! \endcond */
646 //**********************************************************************************************
647
648 //**SMP subtraction assignment to vectors*******************************************************
649 /*! \cond BLAZE_INTERNAL */
650 /*!\brief SMP subtraction assignment of a column-wise row-major sparse matrix reduction operation
651 // to a vector.
652 // \ingroup dense_vector
653 //
654 // \param lhs The target left-hand side vector.
655 // \param rhs The right-hand side reduction expression to be subtracted.
656 // \return void
657 //
658 // This function implements the performance optimized SMP subtraction assignment of a column-wise
659 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
660 // of the SFINAE principle, this function can only be selected by the compiler in case the
661 // expression specific parallel evaluation strategy is selected.
662 */
663 template< typename VT1 > // Type of the target vector
664 friend inline auto smpSubAssign( Vector<VT1,true>& lhs, const SMatReduceExpr& rhs )
665 -> EnableIf_t< UseSMPAssign_v<VT1> >
666 {
667 BLAZE_FUNCTION_TRACE;
668
669 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
670
671 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
672 smpSubAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
673 }
674 /*! \endcond */
675 //**********************************************************************************************
676
677 //**SMP multiplication assignment to vectors****************************************************
678 /*! \cond BLAZE_INTERNAL */
679 /*!\brief SMP multiplication assignment of a column-wise row-major sparse matrix reduction
680 // operation to a vector.
681 // \ingroup dense_vector
682 //
683 // \param lhs The target left-hand side vector.
684 // \param rhs The right-hand side reduction expression to be multiplied.
685 // \return void
686 //
687 // This function implements the performance optimized SMP multiplication assignment of a
688 // column-wise row-major sparse matrix reduction expression to a vector. Due to the explicit
689 // application of the SFINAE principle, this function can only be selected by the compiler
690 // in case the expression specific parallel evaluation strategy is selected.
691 */
692 template< typename VT1 > // Type of the target vector
693 friend inline auto smpMultAssign( Vector<VT1,true>& lhs, const SMatReduceExpr& rhs )
694 -> EnableIf_t< UseSMPAssign_v<VT1> >
695 {
696 BLAZE_FUNCTION_TRACE;
697
698 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
699
700 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
701 smpMultAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
702 }
703 /*! \endcond */
704 //**********************************************************************************************
705
706 //**SMP division assignment to vectors**********************************************************
707 /*! \cond BLAZE_INTERNAL */
708 /*!\brief SMP division assignment of a column-wise row-major sparse matrix reduction operation
709 // to a vector.
710 // \ingroup dense_vector
711 //
712 // \param lhs The target left-hand side vector.
713 // \param rhs The right-hand side reduction expression divisor.
714 // \return void
715 //
716 // This function implements the performance optimized SMP division assignment of a column-wise
717 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
718 // of the SFINAE principle, this function can only be selected by the compiler in case the
719 // expression specific parallel evaluation strategy is selected.
720 */
721 template< typename VT1 > // Type of the target vector
722 friend inline auto smpDivAssign( Vector<VT1,true>& lhs, const SMatReduceExpr& rhs )
723 -> EnableIf_t< UseSMPAssign_v<VT1> >
724 {
725 BLAZE_FUNCTION_TRACE;
726
727 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
728
729 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
730 smpDivAssign( *lhs, reduce<columnwise>( tmp, rhs.op_ ) );
731 }
732 /*! \endcond */
733 //**********************************************************************************************
734
735 //**Compile time checks*************************************************************************
736 /*! \cond BLAZE_INTERNAL */
737 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
738 BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
739 /*! \endcond */
740 //**********************************************************************************************
741 };
742 //*************************************************************************************************
743
744
745
746
747 //=================================================================================================
748 //
749 // CLASS TEMPLATE SPECIALIZATION FOR ROW-WISE REDUCTION OPERATIONS OF ROW-MAJOR MATRICES
750 //
751 //=================================================================================================
752
753 //*************************************************************************************************
754 /*!\brief Expression object for row-wise row-major sparse matrix reduction operations.
755 // \ingroup dense_vector_expression
756 //
757 // This specialization of the SMatReduceExpr class template represents the compile time expression
758 // for row-wise reduction operations of row-major sparse matrices.
759 */
760 template< typename MT // Type of the sparse matrix
761 , typename OP > // Type of the reduction operation
762 class SMatReduceExpr<MT,OP,rowwise>
763 : public MatReduceExpr< DenseVector< SMatReduceExpr<MT,OP,rowwise>, false >, rowwise >
764 , private Computation
765 {
766 private:
767 //**Type definitions****************************************************************************
768 using RT = ResultType_t<MT>; //!< Result type of the sparse matrix expression.
769 using ET = ElementType_t<MT>; //!< Element type of the sparse matrix expression.
770 //**********************************************************************************************
771
772 //**Serial evaluation strategy******************************************************************
773 //! Compilation switch for the serial evaluation strategy of the reduction expression.
774 /*! The \a useAssign compile time constant expression represents a compilation switch for
775 the serial evaluation strategy of the reduction expression. In case the sparse matrix
776 operand requires an intermediate evaluation, \a useAssign will be set to 1 and the
777 reduction expression will be evaluated via the \a assign function family. Otherwise
778 \a useAssign will be set to 0 and the expression will be evaluated via the subscript
779 operator. */
780 static constexpr bool useAssign = RequiresEvaluation_v<MT>;
781
782 /*! \cond BLAZE_INTERNAL */
783 //! Helper variable template for the explicit application of the SFINAE principle.
784 template< typename VT >
785 static constexpr bool UseAssign_v = useAssign;
786 /*! \endcond */
787 //**********************************************************************************************
788
789 //**Parallel evaluation strategy****************************************************************
790 /*! \cond BLAZE_INTERNAL */
791 //! Helper variable template for the explicit application of the SFINAE principle.
792 /*! This variable template is a helper for the selection of the parallel evaluation strategy.
793 In case the sparse matrix operand is not SMP assignable and requires an intermediate
794 evaluation, the variable is set to 1 and the expression specific evaluation strategy is
795 selected. Otherwise the variable is set to 0 and the default strategy is chosen. */
796 template< typename VT >
797 static constexpr bool UseSMPAssign_v = ( !MT::smpAssignable && useAssign );
798 /*! \endcond */
799 //**********************************************************************************************
800
801 public:
802 //**Type definitions****************************************************************************
803 //! Type of this SMatReduceExpr instance.
804 using This = SMatReduceExpr<MT,OP,rowwise>;
805
806 //! Base type of this SMatReduceExpr instance.
807 using BaseType = MatReduceExpr< DenseVector<This,false>, rowwise >;
808
809 using ResultType = ReduceTrait_t<RT,OP,rowwise>; //!< Result type for expression template evaluations.
810 using TransposeType = TransposeType_t<ResultType>; //!< Transpose type for expression template evaluations.
811 using ElementType = ElementType_t<ResultType>; //!< Resulting element type.
812 using SIMDType = SIMDTrait_t<ElementType>; //!< Resulting SIMD element type.
813 using ReturnType = const ElementType; //!< Return type for expression template evaluations.
814
815 //! Data type for composite expression templates.
816 using CompositeType = If_t< useAssign, const ResultType, const SMatReduceExpr& >;
817
818 //! Composite type of the left-hand side sparse matrix expression.
819 using Operand = If_t< IsExpression_v<MT>, const MT, const MT& >;
820
821 //! Data type of the custom unary operation.
822 using Operation = OP;
823 //**********************************************************************************************
824
825 //**ConstIterator class definition**************************************************************
826 /*!\brief Iterator over the elements of the dense vector.
827 */
828 class ConstIterator
829 {
830 public:
831 //**Type definitions*************************************************************************
832 using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category.
833 using ValueType = ElementType; //!< Type of the underlying elements.
834 using PointerType = ElementType*; //!< Pointer return type.
835 using ReferenceType = ElementType&; //!< Reference return type.
836 using DifferenceType = ptrdiff_t; //!< Difference between two iterators.
837
838 // STL iterator requirements
839 using iterator_category = IteratorCategory; //!< The iterator category.
840 using value_type = ValueType; //!< Type of the underlying elements.
841 using pointer = PointerType; //!< Pointer return type.
842 using reference = ReferenceType; //!< Reference return type.
843 using difference_type = DifferenceType; //!< Difference between two iterators.
844 //*******************************************************************************************
845
846 //**Constructor******************************************************************************
847 /*!\brief Constructor for the ConstIterator class.
848 //
849 // \param sm The sparse matrix operand of the reduction expression.
850 // \param index Index to the initial matrix row.
851 // \param op The reduction operation.
852 */
ConstIterator(Operand sm,size_t index,OP op)853 inline ConstIterator( Operand sm, size_t index, OP op )
854 : sm_ ( sm ) // Sparse matrix of the reduction expression
855 , index_( index ) // Index to the current matrix row
856 , op_ ( std::move(op) ) // The reduction operation
857 {}
858 //*******************************************************************************************
859
860 //**Addition assignment operator*************************************************************
861 /*!\brief Addition assignment operator.
862 //
863 // \param inc The increment of the iterator.
864 // \return The incremented iterator.
865 */
866 inline ConstIterator& operator+=( size_t inc ) {
867 index_ += inc;
868 return *this;
869 }
870 //*******************************************************************************************
871
872 //**Subtraction assignment operator**********************************************************
873 /*!\brief Subtraction assignment operator.
874 //
875 // \param dec The decrement of the iterator.
876 // \return The decremented iterator.
877 */
878 inline ConstIterator& operator-=( size_t dec ) {
879 index_ -= dec;
880 return *this;
881 }
882 //*******************************************************************************************
883
884 //**Prefix increment operator****************************************************************
885 /*!\brief Pre-increment operator.
886 //
887 // \return Reference to the incremented iterator.
888 */
889 inline ConstIterator& operator++() {
890 ++index_;
891 return *this;
892 }
893 //*******************************************************************************************
894
895 //**Postfix increment operator***************************************************************
896 /*!\brief Post-increment operator.
897 //
898 // \return The previous position of the iterator.
899 */
900 inline const ConstIterator operator++( int ) {
901 return ConstIterator( index_++ );
902 }
903 //*******************************************************************************************
904
905 //**Prefix decrement operator****************************************************************
906 /*!\brief Pre-decrement operator.
907 //
908 // \return Reference to the decremented iterator.
909 */
910 inline ConstIterator& operator--() {
911 --index_;
912 return *this;
913 }
914 //*******************************************************************************************
915
916 //**Postfix decrement operator***************************************************************
917 /*!\brief Post-decrement operator.
918 //
919 // \return The previous position of the iterator.
920 */
921 inline const ConstIterator operator--( int ) {
922 return ConstIterator( index_-- );
923 }
924 //*******************************************************************************************
925
926 //**Element access operator******************************************************************
927 /*!\brief Direct access to the element at the current iterator position.
928 //
929 // \return The resulting value.
930 */
931 inline ReturnType operator*() const {
932 return reduce( row( sm_, index_, unchecked ), op_ );
933 }
934 //*******************************************************************************************
935
936 //**Equality operator************************************************************************
937 /*!\brief Equality comparison between two ConstIterator objects.
938 //
939 // \param rhs The right-hand side iterator.
940 // \return \a true if the iterators refer to the same element, \a false if not.
941 */
942 inline bool operator==( const ConstIterator& rhs ) const {
943 return index_ == rhs.index_;
944 }
945 //*******************************************************************************************
946
947 //**Inequality operator**********************************************************************
948 /*!\brief Inequality comparison between two ConstIterator objects.
949 //
950 // \param rhs The right-hand side iterator.
951 // \return \a true if the iterators don't refer to the same element, \a false if they do.
952 */
953 inline bool operator!=( const ConstIterator& rhs ) const {
954 return index_ != rhs.index_;
955 }
956 //*******************************************************************************************
957
958 //**Less-than operator***********************************************************************
959 /*!\brief Less-than comparison between two ConstIterator objects.
960 //
961 // \param rhs The right-hand side iterator.
962 // \return \a true if the left-hand side iterator is smaller, \a false if not.
963 */
964 inline bool operator<( const ConstIterator& rhs ) const {
965 return index_ < rhs.index_;
966 }
967 //*******************************************************************************************
968
969 //**Greater-than operator********************************************************************
970 /*!\brief Greater-than comparison between two ConstIterator objects.
971 //
972 // \param rhs The right-hand side iterator.
973 // \return \a true if the left-hand side iterator is greater, \a false if not.
974 */
975 inline bool operator>( const ConstIterator& rhs ) const {
976 return index_ > rhs.index_;
977 }
978 //*******************************************************************************************
979
980 //**Less-or-equal-than operator**************************************************************
981 /*!\brief Less-than comparison between two ConstIterator objects.
982 //
983 // \param rhs The right-hand side iterator.
984 // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
985 */
986 inline bool operator<=( const ConstIterator& rhs ) const {
987 return index_ <= rhs.index_;
988 }
989 //*******************************************************************************************
990
991 //**Greater-or-equal-than operator***********************************************************
992 /*!\brief Greater-than comparison between two ConstIterator objects.
993 //
994 // \param rhs The right-hand side iterator.
995 // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
996 */
997 inline bool operator>=( const ConstIterator& rhs ) const {
998 return index_ >= rhs.index_;
999 }
1000 //*******************************************************************************************
1001
1002 //**Subtraction operator*********************************************************************
1003 /*!\brief Calculating the number of elements between two iterators.
1004 //
1005 // \param rhs The right-hand side iterator.
1006 // \return The number of elements between the two iterators.
1007 */
1008 inline DifferenceType operator-( const ConstIterator& rhs ) const {
1009 return index_ - rhs.index_;
1010 }
1011 //*******************************************************************************************
1012
1013 //**Addition operator************************************************************************
1014 /*!\brief Addition between a ConstIterator and an integral value.
1015 //
1016 // \param it The iterator to be incremented.
1017 // \param inc The number of elements the iterator is incremented.
1018 // \return The incremented iterator.
1019 */
1020 friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) {
1021 return ConstIterator( it.index_ + inc );
1022 }
1023 //*******************************************************************************************
1024
1025 //**Addition operator************************************************************************
1026 /*!\brief Addition between an integral value and a ConstIterator.
1027 //
1028 // \param inc The number of elements the iterator is incremented.
1029 // \param it The iterator to be incremented.
1030 // \return The incremented iterator.
1031 */
1032 friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) {
1033 return ConstIterator( it.index_ + inc );
1034 }
1035 //*******************************************************************************************
1036
1037 //**Subtraction operator*********************************************************************
1038 /*!\brief Subtraction between a ConstIterator and an integral value.
1039 //
1040 // \param it The iterator to be decremented.
1041 // \param dec The number of elements the iterator is decremented.
1042 // \return The decremented iterator.
1043 */
1044 friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) {
1045 return ConstIterator( it.index_ - dec );
1046 }
1047 //*******************************************************************************************
1048
1049 private:
1050 //**Member variables*************************************************************************
1051 Operand sm_; //!< Sparse matrix of the reduction expression.
1052 size_t index_; //!< Index to the current matrix row.
1053 OP op_; //!< The reduction operation.
1054 //*******************************************************************************************
1055 };
1056 //**********************************************************************************************
1057
1058 //**Compilation flags***************************************************************************
1059 //! Compilation switch for the expression template evaluation strategy.
1060 static constexpr bool simdEnabled = false;
1061
1062 //! Compilation switch for the expression template assignment strategy.
1063 static constexpr bool smpAssignable = MT::smpAssignable;
1064 //**********************************************************************************************
1065
1066 //**Constructor*********************************************************************************
1067 /*!\brief Constructor for the SMatReduceExpr class.
1068 //
1069 // \param sm The matrix operand of the reduction expression.
1070 // \param op The reduction operation.
1071 */
SMatReduceExpr(const MT & sm,OP op)1072 inline SMatReduceExpr( const MT& sm, OP op ) noexcept
1073 : sm_( sm ) // Sparse matrix of the reduction expression
1074 , op_( std::move(op) ) // The reduction operation
1075 {}
1076 //**********************************************************************************************
1077
1078 //**Subscript operator**************************************************************************
1079 /*!\brief Subscript operator for the direct access to the vector elements.
1080 //
1081 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
1082 // \return The resulting value.
1083 */
1084 inline ReturnType operator[]( size_t index ) const {
1085 BLAZE_INTERNAL_ASSERT( index < sm_.rows(), "Invalid vector access index" );
1086 return reduce( row( sm_, index, unchecked ), op_ );
1087 }
1088 //**********************************************************************************************
1089
1090 //**At function*********************************************************************************
1091 /*!\brief Checked access to the vector elements.
1092 //
1093 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
1094 // \return The resulting value.
1095 // \exception std::out_of_range Invalid vector access index.
1096 */
at(size_t index)1097 inline ReturnType at( size_t index ) const {
1098 if( index >= sm_.rows() ) {
1099 BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
1100 }
1101 return (*this)[index];
1102 }
1103 //**********************************************************************************************
1104
1105 //**Begin function******************************************************************************
1106 /*!\brief Returns an iterator to the first non-zero element of the dense vector.
1107 //
1108 // \return Iterator to the first non-zero element of the dense vector.
1109 */
begin()1110 inline ConstIterator begin() const {
1111 return ConstIterator( sm_, 0UL, op_ );
1112 }
1113 //**********************************************************************************************
1114
1115 //**End function********************************************************************************
1116 /*!\brief Returns an iterator just past the last non-zero element of the dense vector.
1117 //
1118 // \return Iterator just past the last non-zero element of the dense vector.
1119 */
end()1120 inline ConstIterator end() const {
1121 return ConstIterator( sm_, size(), op_ );
1122 }
1123 //**********************************************************************************************
1124
1125 //**Size function*******************************************************************************
1126 /*!\brief Returns the current size/dimension of the vector.
1127 //
1128 // \return The size of the vector.
1129 */
size()1130 inline size_t size() const noexcept {
1131 return sm_.rows();
1132 }
1133 //**********************************************************************************************
1134
1135 //**Operand access******************************************************************************
1136 /*!\brief Returns the sparse matrix operand.
1137 //
1138 // \return The sparse matrix operand.
1139 */
operand()1140 inline Operand operand() const noexcept {
1141 return sm_;
1142 }
1143 //**********************************************************************************************
1144
1145 //**Operation access****************************************************************************
1146 /*!\brief Returns a copy of the reduction operation.
1147 //
1148 // \return A copy of the reduction operation.
1149 */
operation()1150 inline Operation operation() const {
1151 return op_;
1152 }
1153 //**********************************************************************************************
1154
1155 //**********************************************************************************************
1156 /*!\brief Returns whether the expression can alias with the given address \a alias.
1157 //
1158 // \param alias The alias to be checked.
1159 // \return \a true in case an aliasing effect is possible, \a false if not.
1160 */
1161 template< typename T >
canAlias(const T * alias)1162 inline bool canAlias( const T* alias ) const noexcept {
1163 return ( sm_.isAliased( alias ) );
1164 }
1165 //**********************************************************************************************
1166
1167 //**********************************************************************************************
1168 /*!\brief Returns whether the expression is aliased with the given address \a alias.
1169 //
1170 // \param alias The alias to be checked.
1171 // \return \a true in case the given alias is contained in this expression, \a false if not.
1172 */
1173 template< typename T >
isAliased(const T * alias)1174 inline bool isAliased( const T* alias ) const noexcept {
1175 return ( sm_.isAliased( alias ) );
1176 }
1177 //**********************************************************************************************
1178
1179 //**********************************************************************************************
1180 /*!\brief Returns whether the operands of the expression are properly aligned in memory.
1181 //
1182 // \return \a true in case the operands are aligned, \a false if not.
1183 */
isAligned()1184 inline bool isAligned() const noexcept {
1185 return false;
1186 }
1187 //**********************************************************************************************
1188
1189 //**********************************************************************************************
1190 /*!\brief Returns whether the expression can be used in SMP assignments.
1191 //
1192 // \return \a true in case the expression can be used in SMP assignments, \a false if not.
1193 */
canSMPAssign()1194 inline bool canSMPAssign() const noexcept {
1195 return sm_.canSMPAssign() || ( size() > SMP_SMATREDUCE_THRESHOLD );
1196 }
1197 //**********************************************************************************************
1198
1199 private:
1200 //**Member variables****************************************************************************
1201 Operand sm_; //!< Sparse matrix of the reduction expression.
1202 Operation op_; //!< The reduction operation.
1203 //**********************************************************************************************
1204
1205 //**Assignment to vectors***********************************************************************
1206 /*! \cond BLAZE_INTERNAL */
1207 /*!\brief Assignment of a row-wise row-major sparse matrix reduction operation to a vector.
1208 // \ingroup dense_vector
1209 //
1210 // \param lhs The target left-hand side vector.
1211 // \param rhs The right-hand side reduction expression to be assigned.
1212 // \return void
1213 //
1214 // This function implements the performance optimized assignment of a row-wise row-major
1215 // sparse matrix reduction expression to a vector. Due to the explicit application of the
1216 // SFINAE principle, this function can only be selected by the compiler in case the expression
1217 // specific parallel evaluation strategy is selected.
1218 */
1219 template< typename VT1 > // Type of the target vector
1220 friend inline auto assign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1221 -> EnableIf_t< UseAssign_v<VT1> >
1222 {
1223 BLAZE_FUNCTION_TRACE;
1224
1225 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1226
1227 const RT tmp( serial( rhs.sm_ ) ); // Evaluation of the sparse matrix operand
1228 assign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1229 }
1230 /*! \endcond */
1231 //**********************************************************************************************
1232
1233 //**Addition assignment to vectors**************************************************************
1234 /*! \cond BLAZE_INTERNAL */
1235 /*!\brief Addition assignment of a row-wise row-major sparse matrix reduction operation to a vector.
1236 // \ingroup dense_vector
1237 //
1238 // \param lhs The target left-hand side vector.
1239 // \param rhs The right-hand side reduction expression to be added.
1240 // \return void
1241 //
1242 // This function implements the performance optimized addition assignment of a row-wise
1243 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
1244 // of the SFINAE principle, this function can only be selected by the compiler in case the
1245 // expression specific parallel evaluation strategy is selected.
1246 */
1247 template< typename VT1 > // Type of the target vector
1248 friend inline auto addAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1249 -> EnableIf_t< UseAssign_v<VT1> >
1250 {
1251 BLAZE_FUNCTION_TRACE;
1252
1253 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1254
1255 const RT tmp( serial( rhs.sm_ ) ); // Evaluation of the sparse matrix operand
1256 addAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1257 }
1258 /*! \endcond */
1259 //**********************************************************************************************
1260
1261 //**Subtraction assignment to vectors***********************************************************
1262 /*! \cond BLAZE_INTERNAL */
1263 /*!\brief Subtraction assignment of a row-wise row-major sparse matrix reduction operation
1264 // to a vector.
1265 // \ingroup dense_vector
1266 //
1267 // \param lhs The target left-hand side vector.
1268 // \param rhs The right-hand side reduction expression to be subtracted.
1269 // \return void
1270 //
1271 // This function implements the performance optimized subtraction assignment of a row-wise
1272 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
1273 // of the SFINAE principle, this function can only be selected by the compiler in case the
1274 // expression specific parallel evaluation strategy is selected.
1275 */
1276 template< typename VT1 > // Type of the target vector
1277 friend inline auto subAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1278 -> EnableIf_t< UseAssign_v<VT1> >
1279 {
1280 BLAZE_FUNCTION_TRACE;
1281
1282 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1283
1284 const RT tmp( serial( rhs.sm_ ) ); // Evaluation of the sparse matrix operand
1285 subAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1286 }
1287 /*! \endcond */
1288 //**********************************************************************************************
1289
1290 //**Multiplication assignment to vectors********************************************************
1291 /*! \cond BLAZE_INTERNAL */
1292 /*!\brief Multiplication assignment of a row-wise row-major sparse matrix reduction operation
1293 // to a vector.
1294 // \ingroup dense_vector
1295 //
1296 // \param lhs The target left-hand side vector.
1297 // \param rhs The right-hand side reduction expression to be multiplied.
1298 // \return void
1299 //
1300 // This function implements the performance optimized multiplication assignment of a row-wise
1301 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
1302 // of the SFINAE principle, this function can only be selected by the compiler in case the
1303 // expression specific parallel evaluation strategy is selected.
1304 */
1305 template< typename VT1 > // Type of the target vector
1306 friend inline auto multAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1307 -> EnableIf_t< UseAssign_v<VT1> >
1308 {
1309 BLAZE_FUNCTION_TRACE;
1310
1311 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1312
1313 const RT tmp( serial( rhs.sm_ ) ); // Evaluation of the sparse matrix operand
1314 multAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1315 }
1316 /*! \endcond */
1317 //**********************************************************************************************
1318
1319 //**Division assignment to vectors**************************************************************
1320 /*! \cond BLAZE_INTERNAL */
1321 /*!\brief Division assignment of a row-wise row-major sparse matrix reduction operation to a vector.
1322 // \ingroup dense_vector
1323 //
1324 // \param lhs The target left-hand side vector.
1325 // \param rhs The right-hand side reduction expression divisor.
1326 // \return void
1327 //
1328 // This function implements the performance optimized division assignment of a row-wise
1329 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
1330 // of the SFINAE principle, this function can only be selected by the compiler in case the
1331 // expression specific parallel evaluation strategy is selected.
1332 */
1333 template< typename VT1 > // Type of the target vector
1334 friend inline auto divAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1335 -> EnableIf_t< UseAssign_v<VT1> >
1336 {
1337 BLAZE_FUNCTION_TRACE;
1338
1339 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1340
1341 const RT tmp( serial( rhs.sm_ ) ); // Evaluation of the sparse matrix operand
1342 divAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1343 }
1344 /*! \endcond */
1345 //**********************************************************************************************
1346
1347 //**SMP assignment to vectors*******************************************************************
1348 /*! \cond BLAZE_INTERNAL */
1349 /*!\brief SMP assignment of a row-wise row-major sparse matrix reduction operation to a vector.
1350 // \ingroup dense_vector
1351 //
1352 // \param lhs The target left-hand side vector.
1353 // \param rhs The right-hand side reduction expression to be assigned.
1354 // \return void
1355 //
1356 // This function implements the performance optimized SMP assignment of a row-wise row-major
1357 // sparse matrix reduction expression to a vector. Due to the explicit application of the
1358 // SFINAE principle, this function can only be selected by the compiler in case the expression
1359 // specific parallel evaluation strategy is selected.
1360 */
1361 template< typename VT1 > // Type of the target vector
1362 friend inline auto smpAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1363 -> EnableIf_t< UseSMPAssign_v<VT1> >
1364 {
1365 BLAZE_FUNCTION_TRACE;
1366
1367 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1368
1369 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
1370 smpAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1371 }
1372 /*! \endcond */
1373 //**********************************************************************************************
1374
1375 //**SMP addition assignment to vectors**********************************************************
1376 /*! \cond BLAZE_INTERNAL */
1377 /*!\brief SMP addition assignment of a row-wise row-major sparse matrix reduction operation
1378 // to a vector.
1379 // \ingroup dense_vector
1380 //
1381 // \param lhs The target left-hand side vector.
1382 // \param rhs The right-hand side reduction expression to be added.
1383 // \return void
1384 //
1385 // This function implements the performance optimized SMP addition assignment of a row-wise
1386 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
1387 // of the SFINAE principle, this function can only be selected by the compiler in case the
1388 // expression specific parallel evaluation strategy is selected.
1389 */
1390 template< typename VT1 > // Type of the target vector
1391 friend inline auto smpAddAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1392 -> EnableIf_t< UseSMPAssign_v<VT1> >
1393 {
1394 BLAZE_FUNCTION_TRACE;
1395
1396 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1397
1398 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
1399 smpAddAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1400 }
1401 /*! \endcond */
1402 //**********************************************************************************************
1403
1404 //**SMP subtraction assignment to vectors*******************************************************
1405 /*! \cond BLAZE_INTERNAL */
1406 /*!\brief SMP subtraction assignment of a row-wise row-major sparse matrix reduction operation
1407 // to a vector.
1408 // \ingroup dense_vector
1409 //
1410 // \param lhs The target left-hand side vector.
1411 // \param rhs The right-hand side reduction expression to be subtracted.
1412 // \return void
1413 //
1414 // This function implements the performance optimized SMP subtraction assignment of a row-wise
1415 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
1416 // of the SFINAE principle, this function can only be selected by the compiler in case the
1417 // expression specific parallel evaluation strategy is selected.
1418 */
1419 template< typename VT1 > // Type of the target vector
1420 friend inline auto smpSubAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1421 -> EnableIf_t< UseSMPAssign_v<VT1> >
1422 {
1423 BLAZE_FUNCTION_TRACE;
1424
1425 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1426
1427 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
1428 smpSubAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1429 }
1430 /*! \endcond */
1431 //**********************************************************************************************
1432
1433 //**SMP multiplication assignment to vectors****************************************************
1434 /*! \cond BLAZE_INTERNAL */
1435 /*!\brief SMP multiplication assignment of a row-wise row-major sparse matrix reduction operation
1436 // to a vector.
1437 // \ingroup dense_vector
1438 //
1439 // \param lhs The target left-hand side vector.
1440 // \param rhs The right-hand side reduction expression to be multiplied.
1441 // \return void
1442 //
1443 // This function implements the performance optimized SMP multiplication assignment of a
1444 // row-wise row-major sparse matrix reduction expression to a vector. Due to the explicit
1445 // application of the SFINAE principle, this function can only be selected by the compiler
1446 // in case the expression specific parallel evaluation strategy is selected.
1447 */
1448 template< typename VT1 > // Type of the target vector
1449 friend inline auto smpMultAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1450 -> EnableIf_t< UseSMPAssign_v<VT1> >
1451 {
1452 BLAZE_FUNCTION_TRACE;
1453
1454 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1455
1456 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
1457 smpMultAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1458 }
1459 /*! \endcond */
1460 //**********************************************************************************************
1461
1462 //**SMP division assignment to vectors**********************************************************
1463 /*! \cond BLAZE_INTERNAL */
1464 /*!\brief SMP division assignment of a row-wise row-major sparse matrix reduction operation
1465 // to a vector.
1466 // \ingroup dense_vector
1467 //
1468 // \param lhs The target left-hand side vector.
1469 // \param rhs The right-hand side reduction expression divisor.
1470 // \return void
1471 //
1472 // This function implements the performance optimized SMP division assignment of a row-wise
1473 // row-major sparse matrix reduction expression to a vector. Due to the explicit application
1474 // of the SFINAE principle, this function can only be selected by the compiler in case the
1475 // expression specific parallel evaluation strategy is selected.
1476 */
1477 template< typename VT1 > // Type of the target vector
1478 friend inline auto smpDivAssign( Vector<VT1,false>& lhs, const SMatReduceExpr& rhs )
1479 -> EnableIf_t< UseSMPAssign_v<VT1> >
1480 {
1481 BLAZE_FUNCTION_TRACE;
1482
1483 BLAZE_INTERNAL_ASSERT( (*lhs).size() == rhs.size(), "Invalid vector sizes" );
1484
1485 const RT tmp( rhs.sm_ ); // Evaluation of the sparse matrix operand
1486 smpDivAssign( *lhs, reduce<rowwise>( tmp, rhs.op_ ) );
1487 }
1488 /*! \endcond */
1489 //**********************************************************************************************
1490
1491 //**Compile time checks*************************************************************************
1492 /*! \cond BLAZE_INTERNAL */
1493 BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT );
1494 BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
1495 /*! \endcond */
1496 //**********************************************************************************************
1497 };
1498 //*************************************************************************************************
1499
1500
1501
1502
1503 //=================================================================================================
1504 //
1505 // GLOBAL FUNCTIONS
1506 //
1507 //=================================================================================================
1508
1509 //*************************************************************************************************
1510 /*!\brief Performs a custom reduction operation on the given sparse matrix.
1511 // \ingroup sparse_matrix
1512 //
1513 // \param sm The given sparse matrix for the reduction computation.
1514 // \param op The reduction operation.
1515 // \return The result of the reduction operation.
1516 //
1517 // This function reduces the non-zero elements of the given sparse matrix \a sm by means of the
1518 // given reduction operation \a op:
1519
1520 \code
1521 blaze::CompressedMatrix<double> A;
1522 // ... Resizing and initialization
1523
1524 const double totalsum1 = reduce( A, blaze::Add() );
1525 const double totalsum2 = reduce( A, []( double a, double b ){ return a + b; } );
1526 \endcode
1527
1528 // As demonstrated in the example it is possible to pass any binary callable as custom reduction
1529 // operation. See \ref custom_operations for a detailed overview of the possibilities of custom
1530 // operations.
1531
1532 // Please note that the evaluation order of the reduction operation is unspecified. Thus the
1533 // behavior is non-deterministic if \a op is not associative or not commutative. Also, the
1534 // operation is undefined if the given reduction operation modifies the values.
1535 */
1536 template< typename MT // Type of the sparse matrix
1537 , bool SO // Storage order
1538 , typename OP > // Type of the reduction operation
decltype(auto)1539 inline decltype(auto) reduce( const SparseMatrix<MT,SO>& sm, OP op )
1540 {
1541 BLAZE_FUNCTION_TRACE;
1542
1543 using CT = CompositeType_t<MT>;
1544 using ET = ElementType_t<MT>;
1545
1546 const size_t M( (*sm).rows() );
1547 const size_t N( (*sm).columns() );
1548
1549 if( M == 0UL || N == 0UL ) return ET{};
1550
1551 const size_t iend( SO ? N : M );
1552
1553 CT tmp( *sm );
1554
1555 BLAZE_INTERNAL_ASSERT( tmp.rows() == M, "Invalid number of rows" );
1556 BLAZE_INTERNAL_ASSERT( tmp.columns() == N, "Invalid number of columns" );
1557
1558 ET redux0{};
1559
1560 for( size_t i=0UL; i<iend; ++i )
1561 {
1562 const auto end( tmp.end(i) );
1563 auto element( tmp.begin(i) );
1564
1565 if( element == end ) continue;
1566
1567 ET redux1( element->value() );
1568 ++element;
1569
1570 for( ; element!=end; ++element ) {
1571 redux1 = op( redux1, element->value() );
1572 }
1573
1574 if( i == 0UL ) redux0 = redux1;
1575 else redux0 = op( redux0, redux1 );
1576 }
1577
1578 return redux0;
1579 }
1580 //*************************************************************************************************
1581
1582
1583 //*************************************************************************************************
1584 /*! \cond BLAZE_INTERNAL */
1585 /*!\brief Backend implementation for custom reduction operations on row-major sparse matrices.
1586 // \ingroup sparse_matrix
1587 //
1588 // \param sm The given row-major sparse matrix for the reduction computation.
1589 // \param op The reduction operation.
1590 // \return The result of the reduction operation.
1591 */
1592 template< ReductionFlag RF // Reduction flag
1593 , typename MT // Type of the sparse matrix
1594 , typename OP > // Type of the reduction operation
reduce_backend(const SparseMatrix<MT,false> & sm,OP op)1595 inline const SMatReduceExpr<MT,OP,RF> reduce_backend( const SparseMatrix<MT,false>& sm, OP op )
1596 {
1597 using ReturnType = const SMatReduceExpr<MT,OP,RF>;
1598 return ReturnType( *sm, std::move(op) );
1599 }
1600 /*! \endcond */
1601 //*************************************************************************************************
1602
1603
1604 //*************************************************************************************************
1605 /*! \cond BLAZE_INTERNAL */
1606 /*!\brief Backend implementation for custom reduction operations on column-major sparse matrices.
1607 // \ingroup sparse_matrix
1608 //
1609 // \param sm The given column-major sparse matrix for the reduction computation.
1610 // \param op The reduction operation.
1611 // \return The result of the reduction operation.
1612 */
1613 template< ReductionFlag RF // Reduction flag
1614 , typename MT // Type of the sparse matrix
1615 , typename OP > // Type of the reduction operation
decltype(auto)1616 inline decltype(auto) reduce_backend( const SparseMatrix<MT,true>& sm, OP op )
1617 {
1618 constexpr ReductionFlag RF2( RF == rowwise ? columnwise : rowwise );
1619 return trans( reduce<RF2>( trans( *sm ), std::move(op) ) );
1620 }
1621 /*! \endcond */
1622 //*************************************************************************************************
1623
1624
1625 //*************************************************************************************************
1626 /*!\brief Performs a custom reduction operation on the given sparse matrix.
1627 // \ingroup sparse_matrix
1628 //
1629 // \param sm The given sparse matrix for the reduction computation.
1630 // \param op The reduction operation.
1631 // \return The result of the reduction operation.
1632 //
1633 // This function reduces the rows or columns of the given sparse matrix \a sm by means of the
1634 // given reduction operation \a op. In case the reduction flag \a RF is set to \a blaze::columnwise,
1635 // the elements of the matrix are reduced column-wise and the result is a row vector. In case
1636 // \a RF is set to \a blaze::rowwise, the elements of the matrix are reduced row-wise and the
1637 // result is a column vector:
1638
1639 \code
1640 using blaze::columnwise;
1641
1642 blaze::CompressedMatrix<double> A;
1643 blaze::DynamicVector<double,rowVector> colsum1, colsum2;
1644 // ... Resizing and initialization
1645
1646 colsum1 = reduce<columnwise>( A, blaze::Add() );
1647 colsum2 = reduce<columnwise>( A, []( double a, double b ){ return a + b; } );
1648 \endcode
1649
1650 \code
1651 using blaze::rowwise;
1652
1653 blaze::CompressedMatrix<double> A;
1654 blaze::DynamicVector<double,columnVector> rowsum1, rowsum2;
1655 // ... Resizing and initialization
1656
1657 rowsum1 = reduce<rowwise>( A, blaze::Add() );
1658 rowsum2 = reduce<rowwise>( A, []( double a, double b ){ return a + b; } );
1659 \endcode
1660
1661 // Please note that the evaluation order of the reduction operation is unspecified. Thus the
1662 // behavior is non-deterministic if \a op is not associative or not commutative. Also, the
1663 // operation is undefined if the given reduction operation modifies the values.
1664 */
1665 template< ReductionFlag RF // Reduction flag
1666 , typename MT // Type of the sparse matrix
1667 , bool SO // Storage order
1668 , typename OP > // Type of the reduction operation
decltype(auto)1669 inline decltype(auto) reduce( const SparseMatrix<MT,SO>& sm, OP op )
1670 {
1671 BLAZE_FUNCTION_TRACE;
1672
1673 BLAZE_STATIC_ASSERT_MSG( RF < 2UL, "Invalid reduction flag" );
1674
1675 return reduce_backend<RF>( *sm, std::move(op) );
1676 }
1677 //*************************************************************************************************
1678
1679
1680 //*************************************************************************************************
1681 /*!\brief Reduces the given sparse matrix by means of addition.
1682 // \ingroup sparse_matrix
1683 //
1684 // \param sm The given sparse matrix for the reduction operation.
1685 // \return The result of the reduction operation.
1686 //
1687 // This function reduces the non-zero elements of the given sparse matrix \a sm by means of
1688 // addition:
1689
1690 \code
1691 blaze::CompressedMatrix<int> A{ { 1, 2 }, { 3, 4 } };
1692
1693 const int totalsum = sum( A ); // Results in 10
1694 \endcode
1695
1696 // Please note that the evaluation order of the reduction operation is unspecified.
1697 */
1698 template< typename MT // Type of the sparse matrix
1699 , bool SO > // Storage order
decltype(auto)1700 inline decltype(auto) sum( const SparseMatrix<MT,SO>& sm )
1701 {
1702 BLAZE_FUNCTION_TRACE;
1703
1704 return reduce( *sm, Add() );
1705 }
1706 //*************************************************************************************************
1707
1708
1709 //*************************************************************************************************
1710 /*!\brief Reduces the given sparse matrix by means of addition.
1711 // \ingroup sparse_matrix
1712 //
1713 // \param sm The given sparse matrix for the reduction operation.
1714 // \return The result of the reduction operation.
1715 //
1716 // This function reduces the non-zero elements of the rows or columns of the given sparse matrix
1717 // \a sm by means of addition. In case the reduction flag \a RF is set to \a blaze::columnwise,
1718 // the elements of the matrix are reduced column-wise and the result is a row vector. In case
1719 // \a RF is set to \a blaze::rowwise, the elements of the matrix are reduced row-wise and the
1720 // result is a column vector:
1721
1722 \code
1723 using blaze::columnwise;
1724
1725 blaze::CompressedMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
1726 blaze::DynamicVector<int,rowVector> colsum;
1727
1728 colsum = sum<columnwise>( A ); // Results in ( 2, 3, 6 )
1729 \endcode
1730
1731 \code
1732 using blaze::rowwise;
1733
1734 blaze::CompressedMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
1735 blaze::DynamicVector<int,columnVector> rowsum;
1736
1737 rowsum = sum<rowwise>( A ); // Results in ( 3, 8 )
1738 \endcode
1739
1740 // Please note that the evaluation order of the reduction operation is unspecified.
1741 */
1742 template< ReductionFlag RF // Reduction flag
1743 , typename MT // Type of the sparse matrix
1744 , bool SO > // Storage order
decltype(auto)1745 inline decltype(auto) sum( const SparseMatrix<MT,SO>& sm )
1746 {
1747 BLAZE_FUNCTION_TRACE;
1748
1749 return reduce<RF>( *sm, Add() );
1750 }
1751 //*************************************************************************************************
1752
1753
1754 //*************************************************************************************************
1755 /*!\brief Reduces the given sparse matrix by means of multiplication.
1756 // \ingroup sparse_matrix
1757 //
1758 // \param sm The given sparse matrix for the reduction operation.
1759 // \return The result of the reduction operation.
1760 //
1761 // This function reduces the non-zero elements of the given sparse matrix \a sm by means of
1762 // multiplication:
1763
1764 \code
1765 blaze::CompressedMatrix<int> A{ { 1, 2 }, { 3, 4 } };
1766
1767 const int totalprod = prod( A ); // Results in 24
1768 \endcode
1769
1770 // Please note that the evaluation order of the reduction operation is unspecified.
1771 */
1772 template< typename MT // Type of the sparse matrix
1773 , bool SO > // Storage order
decltype(auto)1774 inline decltype(auto) prod( const SparseMatrix<MT,SO>& sm )
1775 {
1776 BLAZE_FUNCTION_TRACE;
1777
1778 return reduce( *sm, Mult() );
1779 }
1780 //*************************************************************************************************
1781
1782
1783 //*************************************************************************************************
1784 /*!\brief Reduces the given sparse matrix by means of multiplication.
1785 // \ingroup sparse_matrix
1786 //
1787 // \param sm The given sparse matrix for the reduction operation.
1788 // \return The result of the reduction operation.
1789 //
1790 // This function reduces the non-zero elements of the rows or columns of the given sparse
1791 // matrix \a sm by means of multiplication. In case the reduction flag \a RF is set to
1792 // \a blaze::columnwise, the elements of the matrix are reduced column-wise and the result
1793 // is a row vector. In case \a RF is set to \a blaze::rowwise, the elements of the matrix
1794 // are reduced row-wise and the result is a column vector:
1795
1796 \code
1797 using blaze::columnwise;
1798
1799 blaze::CompressedMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
1800 blaze::DynamicVector<int,rowVector> colsum;
1801
1802 colsum = sum<columnwise>( A ); // Results in ( 1, 3, 8 )
1803 \endcode
1804
1805 \code
1806 using blaze::rowwise;
1807
1808 blaze::CompressedMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
1809 blaze::DynamicVector<int,columnVector> rowsum;
1810
1811 rowsum = sum<rowwise>( A ); // Results in ( 2, 12 )
1812 \endcode
1813
1814 // Please note that the evaluation order of the reduction operation is unspecified.
1815 */
1816 template< ReductionFlag RF // Reduction flag
1817 , typename MT // Type of the sparse matrix
1818 , bool SO > // Storage order
decltype(auto)1819 inline decltype(auto) prod( const SparseMatrix<MT,SO>& sm )
1820 {
1821 BLAZE_FUNCTION_TRACE;
1822
1823 return reduce<RF>( *sm, Mult() );
1824 }
1825 //*************************************************************************************************
1826
1827
1828 //*************************************************************************************************
1829 /*!\brief Returns the smallest element of the sparse matrix.
1830 // \ingroup sparse_matrix
1831 //
1832 // \param sm The given sparse matrix.
1833 // \return The smallest sparse matrix element.
1834 //
1835 // This function returns the smallest non-zero element of the given sparse matrix. This function
1836 // can only be used for element types that support the smaller-than relationship. In case the
1837 // given matrix currently has either 0 rows or 0 columns, the returned value is the default
1838 // value (e.g. 0 in case of fundamental data types).
1839 //
1840 // \note In case the sparse matrix is not completely filled, the implicit zero elements are NOT
1841 // taken into account. Example: the following compressed matrix has only 2 non-zero elements.
1842 // However, the minimum of this matrix is 1:
1843
1844 \code
1845 blaze::CompressedMatrix<int> A{ { 1, 0 }, { 3, 0 } };
1846
1847 const int totalmin = min( A ); // Results in 1
1848 \endcode
1849 */
1850 template< typename MT // Type of the sparse matrix
1851 , bool SO > // Storage order
decltype(auto)1852 inline decltype(auto) min( const SparseMatrix<MT,SO>& sm )
1853 {
1854 BLAZE_FUNCTION_TRACE;
1855
1856 return reduce( *sm, Min() );
1857 }
1858 //*************************************************************************************************
1859
1860
1861 //*************************************************************************************************
1862 /*!\brief Returns the smallest element of each row/columns of the sparse matrix.
1863 // \ingroup sparse_matrix
1864 //
1865 // \param sm The given sparse matrix.
1866 // \return The smallest elements in each row/column.
1867 //
1868 // This function returns the smallest non-zero element of each row/column of the given sparse
1869 // matrix \a sm. In case the reduction flag \a RF is set to \a blaze::columnwise, a row
1870 // vector containing the smallest element of each column is returned. In case \a RF is set to
1871 // \a blaze::rowwise, a column vector containing the smallest element of each row is returned.
1872 //
1873 // \note In case the sparse matrix is not completely filled, the implicit zero elements are NOT
1874 // taken into account:
1875
1876 \code
1877 using blaze::columnwise;
1878
1879 blaze::CompressedMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
1880 blaze::DynamicVector<int,rowVector> colmin;
1881
1882 colmin = min<columnwise>( A ); // Results in ( 1, 3, 2 )
1883 \endcode
1884
1885 \code
1886 using blaze::rowwise;
1887
1888 blaze::CompressedMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
1889 blaze::DynamicVector<int,columnVector> rowmin;
1890
1891 rowmin = min<rowwise>( A ); // Results in ( 1, 1 )
1892 \endcode
1893 */
1894 template< ReductionFlag RF // Reduction flag
1895 , typename MT // Type of the sparse matrix
1896 , bool SO > // Storage order
decltype(auto)1897 inline decltype(auto) min( const SparseMatrix<MT,SO>& sm )
1898 {
1899 BLAZE_FUNCTION_TRACE;
1900
1901 return reduce<RF>( *sm, Min() );
1902 }
1903 //*************************************************************************************************
1904
1905
1906 //*************************************************************************************************
1907 /*!\brief Returns the largest element of the sparse matrix.
1908 // \ingroup sparse_matrix
1909 //
1910 // \param sm The given sparse matrix.
1911 // \return The largest sparse matrix element.
1912 //
1913 // This function returns the largest non-zero element of the given sparse matrix. This function
1914 // can only be used for element types that support the smaller-than relationship. In case the
1915 // given matrix currently has either 0 rows or 0 columns, the returned value is the default
1916 // value (e.g. 0 in case of fundamental data types).
1917 //
1918 // \note In case the sparse matrix is not completely filled, the implicit zero elements are NOT
1919 // taken into account. Example: the following compressed matrix has only 2 non-zero elements.
1920 // However, the maximum of this matrix is -1:
1921
1922 \code
1923 blaze::CompressedMatrix<int> A{ { -1, 0 }, { -3, 0 } };
1924
1925 const int totalmax = max( A ); // Results in -1
1926 \endcode
1927 */
1928 template< typename MT // Type of the sparse matrix
1929 , bool SO > // Storage order
decltype(auto)1930 inline decltype(auto) max( const SparseMatrix<MT,SO>& sm )
1931 {
1932 BLAZE_FUNCTION_TRACE;
1933
1934 return reduce( *sm, Max() );
1935 }
1936 //*************************************************************************************************
1937
1938
1939 //*************************************************************************************************
1940 /*!\brief Returns the largest element of each row/columns of the sparse matrix.
1941 // \ingroup sparse_matrix
1942 //
1943 // \param sm The given sparse matrix.
1944 // \return The largest elements in each row/column.
1945 //
1946 // This function returns the largest element of each row/column of the given sparse matrix \a sm.
1947 // In case the reduction flag \a RF is set to \a blaze::columnwise, a row vector containing the
1948 // largest element of each column is returned. In case \a RF is set to \a blaze::rowwise, a column
1949 // vector containing the largest element of each row is returned.
1950 //
1951 // \note In case the sparse matrix is not completely filled, the implicit zero elements are NOT
1952 // taken into account:
1953
1954 \code
1955 using blaze::columnwise;
1956
1957 blaze::CompressedMatrix<int> A{ { -1, 0, -2 }, { -1, -3, -4 } };
1958 blaze::DynamicVector<int,rowVector> colmax;
1959
1960 colmax = max<columnwise>( A ); // Results in ( -1, -3, -2 )
1961 \endcode
1962
1963 \code
1964 using blaze::rowwise;
1965
1966 blaze::CompressedMatrix<int> A{ { -1, 0, -2 }, { -1, -3, -4 } };
1967 blaze::DynamicVector<int,columnVector> rowmax;
1968
1969 rowmax = max<rowwise>( A ); // Results in ( -1, -1 )
1970 \endcode
1971 */
1972 template< ReductionFlag RF // Reduction flag
1973 , typename MT // Type of the sparse matrix
1974 , bool SO > // Storage order
decltype(auto)1975 inline decltype(auto) max( const SparseMatrix<MT,SO>& sm )
1976 {
1977 BLAZE_FUNCTION_TRACE;
1978
1979 return reduce<RF>( *sm, Max() );
1980 }
1981 //*************************************************************************************************
1982
1983 } // namespace blaze
1984
1985 #endif
1986