SparseVector.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SPARSE_SPARSEVECTOR_H_
36 #define _BLAZE_MATH_SPARSE_SPARSEVECTOR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <cmath>
44 #include <blaze/math/Aliases.h>
45 #include <blaze/math/Exception.h>
47 #include <blaze/math/shims/Equal.h>
49 #include <blaze/math/shims/IsNaN.h>
51 #include <blaze/math/shims/Pow2.h>
52 #include <blaze/math/shims/Sqrt.h>
64 #include <blaze/util/Assert.h>
66 #include <blaze/util/mpl/And.h>
67 #include <blaze/util/mpl/If.h>
68 #include <blaze/util/mpl/Or.h>
69 #include <blaze/util/Types.h>
74 
75 
76 namespace blaze {
77 
78 //=================================================================================================
79 //
80 // GLOBAL OPERATORS
81 //
82 //=================================================================================================
83 
84 //*************************************************************************************************
87 template< typename T1, bool TF1, typename T2, bool TF2 >
88 inline bool operator==( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs );
89 
90 template< typename T1, bool TF1, typename T2, bool TF2 >
91 inline bool operator!=( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs );
92 
93 template< typename VT, bool TF, typename ST >
94 inline EnableIf_< IsNumeric<ST>, VT& > operator*=( SparseVector<VT,TF>& vec, ST scalar );
95 
96 template< typename VT, bool TF, typename ST >
97 inline EnableIf_< IsNumeric<ST>, VT& > operator*=( SparseVector<VT,TF>&& vec, ST scalar );
98 
99 template< typename VT, bool TF, typename ST >
100 inline EnableIf_< IsNumeric<ST>, VT& > operator/=( SparseVector<VT,TF>& vec, ST scalar );
101 
102 template< typename VT, bool TF, typename ST >
103 inline EnableIf_< IsNumeric<ST>, VT& > operator/=( SparseVector<VT,TF>&& vec, ST scalar );
105 //*************************************************************************************************
106 
107 
108 //*************************************************************************************************
116 template< typename T1 // Type of the left-hand side sparse vector
117  , bool TF1 // Transpose flag of the left-hand side sparse vector
118  , typename T2 // Type of the right-hand side sparse vector
119  , bool TF2 > // Transpose flag of the right-hand side sparse vector
120 inline bool operator==( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs )
121 {
122  using CT1 = CompositeType_<T1>;
123  using CT2 = CompositeType_<T2>;
124  using LhsConstIterator = ConstIterator_< RemoveReference_<CT1> >;
125  using RhsConstIterator = ConstIterator_< RemoveReference_<CT2> >;
126 
127  // Early exit in case the vector sizes don't match
128  if( (~lhs).size() != (~rhs).size() ) return false;
129 
130  // Evaluation of the two sparse vector operands
131  CT1 a( ~lhs );
132  CT2 b( ~rhs );
133 
134  // In order to compare the two vectors, the data values of the lower-order data
135  // type are converted to the higher-order data type within the equal function.
136  const LhsConstIterator lend( a.end() );
137  const RhsConstIterator rend( b.end() );
138 
139  LhsConstIterator lelem( a.begin() );
140  RhsConstIterator relem( b.begin() );
141 
142  while( lelem != lend && relem != rend )
143  {
144  if( isDefault( lelem->value() ) ) { ++lelem; continue; }
145  if( isDefault( relem->value() ) ) { ++relem; continue; }
146 
147  if( lelem->index() != relem->index() || !equal( lelem->value(), relem->value() ) ) {
148  return false;
149  }
150  else {
151  ++lelem;
152  ++relem;
153  }
154  }
155 
156  while( lelem != lend ) {
157  if( !isDefault( lelem->value() ) )
158  return false;
159  ++lelem;
160  }
161 
162  while( relem != rend ) {
163  if( !isDefault( relem->value() ) )
164  return false;
165  ++relem;
166  }
167 
168  return true;
169 }
170 //*************************************************************************************************
171 
172 
173 //*************************************************************************************************
181 template< typename T1 // Type of the left-hand side sparse vector
182  , bool TF1 // Transpose flag of the left-hand side sparse vector
183  , typename T2 // Type of the right-hand side sparse vector
184  , bool TF2 > // Transpose flag of the right-hand side sparse vector
185 inline bool operator!=( const SparseVector<T1,TF1>& lhs, const SparseVector<T2,TF2>& rhs )
186 {
187  return !( lhs == rhs );
188 }
189 //*************************************************************************************************
190 
191 
192 //*************************************************************************************************
205 template< typename VT // Type of the left-hand side sparse vector
206  , bool TF // Transpose flag
207  , typename ST > // Data type of the right-hand side scalar
208 inline EnableIf_< IsNumeric<ST>, VT& > operator*=( SparseVector<VT,TF>& vec, ST scalar )
209 {
211  if( !tryMult( ~vec, 0UL, (~vec).size(), scalar ) ) {
212  BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted vector" );
213  }
214  }
215 
216  if( !IsResizable< ElementType_<VT> >::value && isZero( scalar ) )
217  {
218  reset( ~vec );
219  }
220  else
221  {
222  BLAZE_DECLTYPE_AUTO( left, derestrict( ~vec ) );
223 
224  const auto last( left.end() );
225  for( auto element=left.begin(); element!=last; ++element ) {
226  element->value() *= scalar;
227  }
228  }
229 
230  BLAZE_INTERNAL_ASSERT( isIntact( ~vec ), "Invariant violation detected" );
231 
232  return ~vec;
233 }
234 //*************************************************************************************************
235 
236 
237 //*************************************************************************************************
250 template< typename VT // Type of the left-hand side sparse vector
251  , bool TF // Transpose flag
252  , typename ST > // Data type of the right-hand side scalar
253 inline EnableIf_< IsNumeric<ST>, VT& > operator*=( SparseVector<VT,TF>&& vec, ST scalar )
254 {
255  return operator*=( ~vec, scalar );
256 }
257 //*************************************************************************************************
258 
259 
260 //*************************************************************************************************
275 template< typename VT // Type of the left-hand side sparse vector
276  , bool TF // Transpose flag
277  , typename ST > // Data type of the right-hand side scalar
278 inline EnableIf_< IsNumeric<ST>, VT& > operator/=( SparseVector<VT,TF>& vec, ST scalar )
279 {
280  BLAZE_USER_ASSERT( !isZero( scalar ), "Division by zero detected" );
281 
283  if( !tryDiv( ~vec, 0UL, (~vec).size(), scalar ) ) {
284  BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted vector" );
285  }
286  }
287 
291  , IsBuiltin<ST> >
294  , ST >;
295 
296  BLAZE_DECLTYPE_AUTO( left, derestrict( ~vec ) );
297 
299  const ScalarType tmp( ScalarType(1)/static_cast<ScalarType>( scalar ) );
300  for( auto element=left.begin(); element!=left.end(); ++element ) {
301  element->value() *= tmp;
302  }
303  }
304  else {
305  for( auto element=left.begin(); element!=left.end(); ++element ) {
306  element->value() /= scalar;
307  }
308  }
309 
310  BLAZE_INTERNAL_ASSERT( isIntact( ~vec ), "Invariant violation detected" );
311 
312  return ~vec;
313 }
314 //*************************************************************************************************
315 
316 
317 //*************************************************************************************************
332 template< typename VT // Type of the left-hand side sparse vector
333  , bool TF // Transpose flag
334  , typename ST > // Data type of the right-hand side scalar
335 inline EnableIf_< IsNumeric<ST>, VT& > operator/=( SparseVector<VT,TF>&& vec, ST scalar )
336 {
337  return operator/=( ~vec, scalar );
338 }
339 //*************************************************************************************************
340 
341 
342 
343 
344 //=================================================================================================
345 //
346 // GLOBAL FUNCTIONS
347 //
348 //=================================================================================================
349 
350 //*************************************************************************************************
353 template< typename VT, bool TF >
354 bool isnan( const SparseVector<VT,TF>& sv );
355 
356 template< typename VT, bool TF >
357 bool isUniform( const SparseVector<VT,TF>& dv );
358 
359 template< typename VT, bool TF >
361 
362 template< typename VT, bool TF >
363 inline auto length( const SparseVector<VT,TF>& sv ) -> decltype( sqrt( sqrLength( ~sv ) ) );
364 
365 template< typename VT, bool TF >
366 const ElementType_<VT> min( const SparseVector<VT,TF>& sv );
367 
368 template< typename VT, bool TF >
369 const ElementType_<VT> max( const SparseVector<VT,TF>& sv );
371 //*************************************************************************************************
372 
373 
374 //*************************************************************************************************
394 template< typename VT // Type of the sparse vector
395  , bool TF > // Transpose flag
396 inline bool isnan( const SparseVector<VT,TF>& sv )
397 {
398  using CT = CompositeType_<VT>;
400 
401  CT a( ~sv ); // Evaluation of the sparse vector operand
402 
403  const ConstIterator end( a.end() );
404  for( ConstIterator element=a.begin(); element!=end; ++element ) {
405  if( isnan( element->value() ) ) return true;
406  }
407  return false;
408 }
409 //*************************************************************************************************
410 
411 
412 //*************************************************************************************************
438 template< typename VT // Type of the sparse vector
439  , bool TF > // Transpose flag
441 {
442  using CT = CompositeType_<VT>;
445 
446  if( IsUniform<VT>::value || (~sv).size() < 2UL )
447  return true;
448 
449  CT a( ~sv ); // Evaluation of the sparse vector operand
450 
451  if( a.nonZeros() != a.size() )
452  {
453  for( ConstIterator element=a.begin(); element!=a.end(); ++element ) {
454  if( !isDefault( element->value() ) )
455  return false;
456  }
457  }
458  else
459  {
460  ConstReference cmp( a[0] );
461  ConstIterator element( a.begin() );
462 
463  ++element;
464 
465  for( ; element!=a.end(); ++element ) {
466  if( element->value() != cmp )
467  return false;
468  }
469  }
470 
471  return true;
472 }
473 //*************************************************************************************************
474 
475 
476 //*************************************************************************************************
489 template< typename VT // Type of the sparse vector
490  , bool TF > // Transpose flag
492 {
495 
497 
498  ElementType sum( 0 );
499  for( ConstIterator element=(~sv).begin(); element!=(~sv).end(); ++element )
500  sum += pow2( element->value() );
501  return sum;
502 }
503 //*************************************************************************************************
504 
505 
506 //*************************************************************************************************
543 template< typename VT // Type of the sparse vector
544  , bool TF > // Transpose flag
545 inline auto length( const SparseVector<VT,TF>& sv ) -> decltype( sqrt( sqrLength( ~sv ) ) )
546 {
547  return sqrt( sqrLength( ~sv ) );
548 }
549 //*************************************************************************************************
550 
551 
552 //*************************************************************************************************
574 template< typename VT // Type of the sparse vector
575  , bool TF > // Transpose flag
577 {
578  using blaze::min;
579 
580  using ET = ElementType_<VT>;
581  using CT = CompositeType_<VT>;
583 
584  CT a( ~sv ); // Evaluation of the sparse vector operand
585 
586  const ConstIterator end( a.end() );
587  ConstIterator element( a.begin() );
588 
589  if( element == end ) {
590  return ET();
591  }
592  else if( a.nonZeros() == a.size() ) {
593  ET minimum( element->value() );
594  ++element;
595  for( ; element!=end; ++element )
596  minimum = min( minimum, element->value() );
597  return minimum;
598  }
599  else {
600  ET minimum{};
601  for( ; element!=end; ++element )
602  minimum = min( minimum, element->value() );
603  return minimum;
604  }
605 }
606 //*************************************************************************************************
607 
608 
609 //*************************************************************************************************
631 template< typename VT // Type of the sparse vector
632  , bool TF > // Transpose flag
634 {
635  using blaze::max;
636 
637  using ET = ElementType_<VT>;
638  using CT = CompositeType_<VT>;
640 
641  CT a( ~sv ); // Evaluation of the sparse vector operand
642 
643  const ConstIterator end( a.end() );
644  ConstIterator element( a.begin() );
645 
646  if( element == end ) {
647  return ET();
648  }
649  else if( a.nonZeros() == a.size() ) {
650  ET maximum( element->value() );
651  ++element;
652  for( ; element!=end; ++element )
653  maximum = max( maximum, element->value() );
654  return maximum;
655  }
656  else {
657  ET maximum{};
658  for( ; element!=end; ++element )
659  maximum = max( maximum, element->value() );
660  return maximum;
661  }
662 }
663 //*************************************************************************************************
664 
665 } // namespace blaze
666 
667 #endif
Header file for the isnan shim.
Header file for the UnderlyingNumeric type trait.
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Header file for auxiliary alias declarations.
Headerfile for the generic min algorithm.
Constraint on the data type.
#define BLAZE_USER_ASSERT(expr, msg)
Run time assertion macro for user checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_USER_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERT flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:117
Header file for basic type definitions.
Header file for the SparseVector base class.
constexpr bool equal(const T1 &a, const T2 &b)
Generic equality check.
Definition: Equal.h:76
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:265
const ElementType_< VT > sqrLength(const DenseVector< VT, TF > &dv)
Calculation of the square length (magnitude) of the dense vector .
Definition: DenseVector.h:661
BLAZE_ALWAYS_INLINE MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:364
Compile time check for uniform vectors and matrices.This type trait tests whether or not the given te...
Definition: IsUniform.h:67
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:588
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1903
const Type & ConstReference
Reference to a constant matrix value.
Definition: CompressedMatrix.h:3083
Header file for the decltype(auto) workaround.
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1950
Header file for the vector transpose flag types.
auto length(const DenseVector< VT, TF > &dv) -> decltype(sqrt(sqrLength(~dv)))
Calculation of the length (magnitude) of the dense vector .
Definition: DenseVector.h:714
Compile time check for data types with restricted data access.This type trait tests whether the given...
Definition: IsRestricted.h:82
bool isZero(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is 0.
Definition: DiagonalProxy.h:670
Header file for the sqrt shim.
typename T::CompositeType CompositeType_
Alias declaration for nested CompositeType type definitions.The CompositeType_ alias declaration prov...
Definition: Aliases.h:83
Headerfile for the generic max algorithm.
Header file for the IsUniform type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the If class template.
Header file for the IsFloatingPoint type trait.
Header file for the UnderlyingBuiltin type trait.
Type ElementType
Type of the compressed matrix elements.
Definition: CompressedMatrix.h:3079
Header file for the Or class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:3085
Header file for the isZero shim.
constexpr bool operator==(const NegativeAccuracy< A > &lhs, const T &rhs)
Equality comparison between a NegativeAccuracy object and a floating point value. ...
Definition: Accuracy.h:250
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
Header file for the pow2 shim.
Header file for the equal shim.
bool isnan(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is not a number.
Definition: DiagonalProxy.h:710
Header file for the exception macros of the math module.
Compile time check for floating point data types.This type trait tests whether or not the given templ...
Definition: IsFloatingPoint.h:75
bool isUniform(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a uniform matrix.
Definition: DenseMatrix.h:1151
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:430
constexpr bool operator!=(const NegativeAccuracy< A > &lhs, const T &rhs)
Inequality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:290
typename DivTrait< T1, T2 >::Type DivTrait_
Auxiliary alias declaration for the DivTrait class template.The DivTrait_ alias declaration provides ...
Definition: DivTrait.h:292
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
BLAZE_ALWAYS_INLINE ValueType_< T > sum(const SIMDi8< T > &a) noexcept
Returns the sum of all elements in the 8-bit integral SIMD vector.
Definition: Reduction.h:65
Header file for run time assertion macros.
Header file for the division trait.
typename If< T1, T2, T3 >::Type If_
Auxiliary alias declaration for the If class template.The If_ alias declaration provides a convenient...
Definition: If.h:154
#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE(T)
Constraint on the data type.In case the given data type T is not a numeric (integral or floating poin...
Definition: Numeric.h:61
Header file for the isDefault shim.
Compile time check for built-in data types.This type trait tests whether or not the given template pa...
Definition: IsBuiltin.h:75
Compile time check for data types.This type trait tests whether or not the given template parameter i...
Definition: IsInvertible.h:82
BLAZE_ALWAYS_INLINEdecltype(auto) constexpr pow2(const T &a) noexcept(noexcept(a *a))
Squaring the given value/object.
Definition: Pow2.h:65
Header file for the RemoveReference type trait.
Header file for the IsInvertible type trait.
typename T::ConstReference ConstReference_
Alias declaration for nested ConstReference type definitions.The ConstReference_ alias declaration pr...
Definition: Aliases.h:143
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
EnableIf_< IsNumeric< ST >, MT &> operator/=(DenseMatrix< MT, SO > &mat, ST scalar)
Division assignment operator for the division of a dense matrix by a scalar value ( )...
Definition: DenseMatrix.h:655
decltype(auto) sqrt(const DenseMatrix< MT, SO > &dm)
Computes the square root of each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1448
Header file for the IsBuiltin type trait.
Base class for sparse vectors.The SparseVector class is a base class for all arbitrarily sized (N-dim...
Definition: Forward.h:130
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:254
Header file for the IsComplex type trait.
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:628
EnableIf_< IsNumeric< ST >, MT &> operator*=(DenseMatrix< MT, SO > &mat, ST scalar)
Multiplication assignment operator for the multiplication of a dense matrix and a scalar value ( )...
Definition: DenseMatrix.h:593
Header file for the IsResizable type trait.
Header file for the IsRestricted type trait.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101