1 //=================================================================================================
2 /*!
3 // \file blaze/math/dense/CustomVector.h
4 // \brief Header file for the implementation of a customizable vector
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_DENSE_CUSTOMVECTOR_H_
36 #define _BLAZE_MATH_DENSE_CUSTOMVECTOR_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <algorithm>
44 #include <array>
45 #include <utility>
46 #include <blaze/math/Aliases.h>
47 #include <blaze/math/AlignmentFlag.h>
48 #include <blaze/math/constraints/DenseVector.h>
49 #include <blaze/math/constraints/RequiresEvaluation.h>
50 #include <blaze/math/constraints/SameTag.h>
51 #include <blaze/math/constraints/TransposeFlag.h>
52 #include <blaze/math/dense/DenseIterator.h>
53 #include <blaze/math/dense/Forward.h>
54 #include <blaze/math/Exception.h>
55 #include <blaze/math/expressions/DenseVector.h>
56 #include <blaze/math/expressions/SparseVector.h>
57 #include <blaze/math/Forward.h>
58 #include <blaze/math/InitializerList.h>
59 #include <blaze/math/PaddingFlag.h>
60 #include <blaze/math/RelaxationFlag.h>
61 #include <blaze/math/shims/Clear.h>
62 #include <blaze/math/shims/IsDefault.h>
63 #include <blaze/math/shims/NextMultiple.h>
64 #include <blaze/math/shims/PrevMultiple.h>
65 #include <blaze/math/shims/Serial.h>
66 #include <blaze/math/SIMD.h>
67 #include <blaze/math/traits/CrossTrait.h>
68 #include <blaze/math/traits/DivTrait.h>
69 #include <blaze/math/traits/MultTrait.h>
70 #include <blaze/math/typetraits/CustomTransposeType.h>
71 #include <blaze/math/typetraits/HasConstDataAccess.h>
72 #include <blaze/math/typetraits/HasMutableDataAccess.h>
73 #include <blaze/math/typetraits/HasSIMDAdd.h>
74 #include <blaze/math/typetraits/HasSIMDDiv.h>
75 #include <blaze/math/typetraits/HasSIMDMult.h>
76 #include <blaze/math/typetraits/HasSIMDSub.h>
77 #include <blaze/math/typetraits/IsAligned.h>
78 #include <blaze/math/typetraits/IsContiguous.h>
79 #include <blaze/math/typetraits/IsCustom.h>
80 #include <blaze/math/typetraits/IsPadded.h>
81 #include <blaze/math/typetraits/IsSIMDCombinable.h>
82 #include <blaze/math/typetraits/IsSMPAssignable.h>
83 #include <blaze/math/typetraits/IsSparseVector.h>
84 #include <blaze/system/CacheSize.h>
85 #include <blaze/system/Inline.h>
86 #include <blaze/system/Optimizations.h>
87 #include <blaze/system/Thresholds.h>
88 #include <blaze/util/AlignmentCheck.h>
89 #include <blaze/util/Assert.h>
90 #include <blaze/util/constraints/Const.h>
91 #include <blaze/util/constraints/Pointer.h>
92 #include <blaze/util/constraints/Reference.h>
93 #include <blaze/util/constraints/Vectorizable.h>
94 #include <blaze/util/constraints/Volatile.h>
95 #include <blaze/util/EnableIf.h>
96 #include <blaze/util/IntegralConstant.h>
97 #include <blaze/util/MaybeUnused.h>
98 #include <blaze/util/StaticAssert.h>
99 #include <blaze/util/Types.h>
100 #include <blaze/util/typetraits/IsVectorizable.h>
101 #include <blaze/util/typetraits/RemoveConst.h>
102
103
104 namespace blaze {
105
106 //=================================================================================================
107 //
108 // CLASS DEFINITION
109 //
110 //=================================================================================================
111
112 //*************************************************************************************************
113 /*!\defgroup custom_vector CustomVector
114 // \ingroup dense_vector
115 */
116 /*!\brief Efficient implementation of a customizable vector.
117 // \ingroup custom_vector
118 //
119 // \section customvector_general General
120 //
121 // The CustomVector class template provides the functionality to represent an external array of
122 // elements of arbitrary type and a fixed size as a native \b Blaze dense vector data structure.
123 // Thus in contrast to all other dense vector types a custom vector does not perform any kind
124 // of memory allocation by itself, but it is provided with an existing array of element during
125 // construction. A custom vector can therefore be considered an alias to the existing array.
126 //
127 // The type of the elements, the properties of the given array of elements, the transpose flag,
128 // and the group tag of the vector can be specified via the following five template parameters:
129
130 \code
131 namespace blaze {
132
133 template< typename Type, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag >
134 class CustomVector;
135
136 } // namespace blaze
137 \endcode
138
139 // - Type: specifies the type of the vector elements. CustomVector can be used with any
140 // non-cv-qualified, non-reference, non-pointer element type.
141 // - AF : specifies whether the represented, external arrays are properly aligned with
142 // respect to the available instruction set (SSE, AVX, ...) or not (\c blaze::aligned
143 // or \c blaze::unaligned).
144 // - PF : specified whether the represented, external arrays are properly padded with
145 // respect to the available instruction set (SSE, AVX, ...) or not (\c blaze::padded
146 // or \c blaze::unpadded).
147 // - TF : specifies whether the vector is a row vector (\c blaze::rowVector) or a column
148 // vector (\c blaze::columnVector). The default value is \c blaze::defaultTransposeFlag.
149 // - Tag : optional type parameter to tag the vector. The default type is \c blaze::Group0.
150 // See \ref grouping_tagging for details.
151 //
152 // The following examples give an impression of several possible types of custom vectors:
153
154 \code
155 using blaze::CustomVector;
156 using blaze::aligned;
157 using blaze::unaligned;
158 using blaze::padded;
159 using blaze::unpadded;
160
161 // Definition of a custom column vector for unaligned, unpadded integer arrays
162 using UnalignedUnpadded = CustomVector<int,unaligned,unpadded,columnVector>;
163
164 // Definition of a custom column vector for unaligned but padded 'float' arrays
165 using UnalignedPadded = CustomVector<float,unaligned,padded,columnVector>;
166
167 // Definition of a custom row vector for aligned, unpadded 'double' arrays
168 using AlignedUnpadded = CustomVector<double,aligned,unpadded,rowVector>;
169
170 // Definition of a custom row vector for aligned, padded 'complex<double>' arrays
171 using AlignedPadded = CustomVector<complex<double>,aligned,padded,rowVector>;
172 \endcode
173
174 // \n \section customvector_special_properties Special Properties of Custom Vectors
175 //
176 // In comparison with the remaining \b Blaze dense vector types CustomVector has several special
177 // characteristics. All of these result from the fact that a custom vector is not performing any
178 // kind of memory allocation, but instead is given an existing array of elements. The following
179 // sections discuss all of these characteristics:
180 //
181 // -# <b>\ref customvector_memory_management</b>
182 // -# <b>\ref customvector_copy_operations</b>
183 // -# <b>\ref customvector_alignment</b>
184 // -# <b>\ref customvector_padding</b>
185 //
186 // \n \subsection customvector_memory_management Memory Management
187 //
188 // The CustomVector class template acts as an adaptor for an existing array of elements. As such
189 // it provides everything that is required to use the array just like a native \b Blaze dense
190 // vector data structure. However, this flexibility comes with the price that the user of a custom
191 // vector is responsible for the resource management.
192 //
193 // The following examples give an impression of several possible types of custom vectors:
194
195 \code
196 using blaze::CustomVector;
197 using blaze::Deallocate;
198 using blaze::allocate;
199 using blaze::aligned;
200 using blaze::unaligned;
201 using blaze::padded;
202 using blaze::unpadded;
203
204 // Definition of a 3-dimensional custom vector with unaligned, unpadded and externally
205 // managed integer array. Note that the std::vector must be guaranteed to outlive the
206 // custom vector!
207 std::vector<int> vec( 3UL );
208 CustomVector<int,unaligned,unpadded> a( &vec[0], 3UL );
209
210 // Definition of a custom vector with size 3 and capacity 16 with aligned, padded and
211 // externally managed integer array. Note that the std::unique_ptr must be guaranteed
212 // to outlive the custom vector!
213 std::unique_ptr<int[],Deallocate> memory( allocate<int>( 16UL ) );
214 CustomVector<int,aligned,padded> b( memory.get(), 3UL, 16UL );
215 \endcode
216
217 // \n \subsection customvector_copy_operations Copy Operations
218 //
219 // As with all dense vectors it is possible to copy construct a custom vector:
220
221 \code
222 using blaze::CustomVector;
223 using blaze::unaligned;
224 using blaze::unpadded;
225
226 using CustomType = CustomVector<int,unaligned,unpadded>;
227
228 std::vector<int> vec( 5UL, 10 ); // Vector of 5 integers of the value 10
229 CustomType a( &vec[0], 5UL ); // Represent the std::vector as Blaze dense vector
230 a[1] = 20; // Also modifies the std::vector
231
232 CustomType b( a ); // Creating a copy of vector a
233 b[2] = 20; // Also affects vector a and the std::vector
234 \endcode
235
236 // It is important to note that a custom vector acts as a reference to the specified array. Thus
237 // the result of the copy constructor is a new custom vector that is referencing and representing
238 // the same array as the original custom vector.
239 //
240 // In contrast to copy construction, just as with references, copy assignment does not change
241 // which array is referenced by the custom vector, but modifies the values of the array:
242
243 \code
244 std::vector<int> vec2( 5UL, 4 ); // Vector of 5 integers of the value 4
245 CustomType c( &vec2[0], 5UL ); // Represent the std::vector as Blaze dense vector
246
247 a = c; // Copy assignment: Set all values of vector a and b to 4.
248 \endcode
249
250 // \n \subsection customvector_alignment Alignment
251 //
252 // In case the custom vector is specified as \c aligned the passed array must be guaranteed to
253 // be aligned according to the requirements of the used instruction set (SSE, AVX, ...). For
254 // instance, if AVX is active an array of integers must be 32-bit aligned:
255
256 \code
257 using blaze::CustomVector;
258 using blaze::Deallocate;
259 using blaze::allocate;
260 using blaze::aligned;
261 using blaze::unpadded;
262
263 // Allocation of 32-bit aligned memory
264 std::unique_ptr<int[],Deallocate> memory( allocate<int>( 5UL ) );
265
266 CustomVector<int,aligned,unpadded> a( memory.get(), 5UL );
267 \endcode
268
269 // In case the alignment requirements are violated, a \c std::invalid_argument exception is
270 // thrown.
271 //
272 // \n \subsection customvector_padding Padding
273 //
274 // Adding padding elements to the end of an array can have a significant impact on performance.
275 // For instance, assuming that AVX is available, then two aligned, padded, 3-dimensional vectors
276 // of double precision values can be added via a single SIMD addition operations:
277
278 \code
279 using blaze::CustomVector;
280 using blaze::Deallocate;
281 using blaze::allocate;
282 using blaze::aligned;
283 using blaze::padded;
284
285 using CustomType = CustomVector<double,aligned,padded>;
286
287 std::unique_ptr<double[],Deallocate> memory1( allocate<double>( 4UL ) );
288 std::unique_ptr<double[],Deallocate> memory2( allocate<double>( 4UL ) );
289 std::unique_ptr<double[],Deallocate> memory3( allocate<double>( 4UL ) );
290
291 // Creating padded custom vectors of size 3 and a capacity of 4
292 CustomType a( memory1.get(), 3UL, 4UL );
293 CustomType b( memory2.get(), 3UL, 4UL );
294 CustomType c( memory3.get(), 3UL, 4UL );
295
296 // ... Initialization
297
298 c = a + b; // AVX-based vector addition
299 \endcode
300
301 // In this example, maximum performance is possible. However, in case no padding elements are
302 // inserted, a scalar addition has to be used:
303
304 \code
305 using blaze::CustomVector;
306 using blaze::Deallocate;
307 using blaze::allocate;
308 using blaze::aligned;
309 using blaze::unpadded;
310
311 using CustomType = CustomVector<double,aligned,unpadded>;
312
313 std::unique_ptr<double[],Deallocate> memory1( allocate<double>( 3UL ) );
314 std::unique_ptr<double[],Deallocate> memory2( allocate<double>( 3UL ) );
315 std::unique_ptr<double[],Deallocate> memory3( allocate<double>( 3UL ) );
316
317 // Creating unpadded custom vector of size 3
318 CustomType a( allocate<double>( 3UL ), 3UL );
319 CustomType b( allocate<double>( 3UL ), 3UL );
320 CustomType c( allocate<double>( 3UL ), 3UL );
321
322 // ... Initialization
323
324 c = a + b; // Scalar vector addition
325 \endcode
326
327 // Note the different number of constructor parameters for unpadded and padded custom vectors:
328 // In contrast to unpadded vectors, where during the construction only the size of the array
329 // has to be specified, during the construction of a padded custom vector it is additionally
330 // necessary to explicitly specify the capacity of the array.
331 //
332 // The number of padding elements is required to be sufficient with respect to the available
333 // instruction set: In case of an aligned padded custom vector the added padding elements must
334 // guarantee that the capacity is greater or equal than the size and a multiple of the SIMD vector
335 // width. In case of unaligned padded vectors the number of padding elements can be greater or
336 // equal the number of padding elements of an aligned padded custom vector. In case the padding
337 // is insufficient with respect to the available instruction set, a \c std::invalid_argument
338 // exception is thrown.
339 //
340 // Please also note that \b Blaze will zero initialize the padding elements in order to achieve
341 // maximum performance!
342 //
343 //
344 // \n \section customvector_arithmetic_operations Arithmetic Operations
345 //
346 // The use of custom vectors in arithmetic operations is designed to be as natural and intuitive
347 // as possible. All operations (addition, subtraction, multiplication, scaling, ...) can be
348 // expressed similar to a text book representation. Also, custom vectors can be combined with all
349 // other dense and sparse vectors and matrices. The following example gives an impression of the
350 // use of CustomVector:
351
352 \code
353 using blaze::CustomVector;
354 using blaze::CompressedVector;
355 using blaze::DynamicMatrix;
356 using blaze::Deallocate;
357 using blaze::allocate;
358 using blaze::aligned;
359 using blaze::unaligned;
360 using blaze::padded;
361 using blaze::unpadded;
362
363 // Non-initialized custom column vector of size 2. All given arrays are considered to be
364 // unaligned and unpadded. The memory is managed via a 'std::vector'.
365 std::vector<double> memory1( 2UL );
366 CustomVector<double,unaligned,unpadded> a( memory1.data(), 2UL );
367
368 a[0] = 1.0; // Initialization of the first element
369 a[1] = 2.0; // Initialization of the second element
370
371 // Non-initialized custom column vector of size 2 and capacity 4. All given arrays are required
372 // to be properly aligned and padded. The memory is managed via a 'std::unique_ptr'.
373 std::unique_ptr<double[],Deallocate> memory2( allocate<double>( 4UL ) );
374 CustomVector<double,aligned,padded> b( memory2.get(), 2UL, 4UL );
375
376 b = 2.0; // Homogeneous initialization of all elements
377
378 CompressedVector<float> c( 2 ); // Empty sparse single precision vector
379 DynamicVector<double> d; // Default constructed dynamic vector
380 DynamicMatrix<double> A; // Default constructed row-major matrix
381
382 d = a + b; // Vector addition between custom vectors of equal element type
383 d = a - c; // Vector subtraction between a dense and sparse vector with different element types
384 d = a * b; // Component-wise vector multiplication
385
386 a *= 2.0; // In-place scaling of vector
387 d = a * 2.0; // Scaling of vector a
388 d = 2.0 * a; // Scaling of vector a
389
390 d += a - b; // Addition assignment
391 d -= a + c; // Subtraction assignment
392 d *= a * b; // Multiplication assignment
393
394 double scalar = trans( a ) * b; // Scalar/dot/inner product between two vectors
395
396 A = a * trans( b ); // Outer product between two vectors
397 \endcode
398 */
399 template< typename Type // Data type of the vector
400 , AlignmentFlag AF // Alignment flag
401 , PaddingFlag PF // Padding flag
402 , bool TF // Transpose flag
403 , typename Tag // Type tag
404 , typename RT > // Result type
405 class CustomVector
406 : public DenseVector< CustomVector<Type,AF,PF,TF,Tag,RT>, TF >
407 {
408 public:
409 //**Type definitions****************************************************************************
410 using This = CustomVector<Type,AF,PF,TF,Tag,RT>; //!< Type of this CustomVector instance.
411 using BaseType = DenseVector<This,TF>; //!< Base type of this CustomVector instance.
412
413 //! Result type for expression template evaluations.
414 using ResultType = RT;
415
416 //! Transpose type for expression template evaluations.
417 using TransposeType = CustomTransposeType_t<RT>;
418
419 using ElementType = Type; //!< Type of the vector elements.
420 using SIMDType = SIMDTrait_t<ElementType>; //!< SIMD type of the vector elements.
421 using TagType = Tag; //!< Tag type of this CustomVector instance.
422 using ReturnType = const Type&; //!< Return type for expression template evaluations
423 using CompositeType = const CustomVector&; //!< Data type for composite expression templates.
424
425 using Reference = Type&; //!< Reference to a non-constant vector value.
426 using ConstReference = const Type&; //!< Reference to a constant vector value.
427 using Pointer = Type*; //!< Pointer to a non-constant vector value.
428 using ConstPointer = const Type*; //!< Pointer to a constant vector value.
429
430 using Iterator = DenseIterator<Type,AF>; //!< Iterator over non-constant elements.
431 using ConstIterator = DenseIterator<const Type,AF>; //!< Iterator over constant elements.
432 //**********************************************************************************************
433
434 //**Rebind struct definition********************************************************************
435 /*!\brief Rebind mechanism to obtain a CustomVector with different data/element type.
436 */
437 template< typename NewType > // Data type of the other vector
438 struct Rebind {
439 using RRT = Rebind_t< RT, RemoveConst_t<NewType> >; //!< The rebound result type.
440 using Other = CustomVector<NewType,AF,PF,TF,Tag,RRT>; //!< The type of the other CustomVector.
441 };
442 //**********************************************************************************************
443
444 //**Resize struct definition********************************************************************
445 /*!\brief Resize mechanism to obtain a CustomVector with a different fixed number of elements.
446 */
447 template< size_t NewN > // Number of elements of the other vector
448 struct Resize {
449 using RRT = Resize_t<RT,NewN>; //!< The resized result type.
450 using Other = CustomVector<Type,AF,PF,TF,Tag,RRT>; //!< The type of the other CustomVector.
451 };
452 //**********************************************************************************************
453
454 //**Compilation flags***************************************************************************
455 //! Compilation flag for SIMD optimization.
456 /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
457 in can be optimized via SIMD operations. In case the element type of the vector is a
458 vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
459 it is set to \a false. */
460 static constexpr bool simdEnabled = IsVectorizable_v<Type>;
461
462 //! Compilation flag for SMP assignments.
463 /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
464 (shared memory parallel) assignments (both on the left-hand and right-hand side of the
465 assignment). */
466 static constexpr bool smpAssignable = !IsSMPAssignable_v<Type>;
467 //**********************************************************************************************
468
469 //**Constructors********************************************************************************
470 /*!\name Constructors */
471 //@{
472 inline CustomVector();
473 inline CustomVector( Type* ptr, size_t n );
474 inline CustomVector( Type* ptr, size_t n, size_t nn );
475 inline CustomVector( const CustomVector& v );
476 inline CustomVector( CustomVector&& v ) noexcept;
477 //@}
478 //**********************************************************************************************
479
480 //**Destructor**********************************************************************************
481 /*!\name Destructor */
482 //@{
483 inline ~CustomVector();
484 //@}
485 //**********************************************************************************************
486
487 //**Data access functions***********************************************************************
488 /*!\name Data access functions */
489 //@{
490 inline Reference operator[]( size_t index ) noexcept;
491 inline ConstReference operator[]( size_t index ) const noexcept;
492 inline Reference at( size_t index );
493 inline ConstReference at( size_t index ) const;
494 inline Pointer data () noexcept;
495 inline ConstPointer data () const noexcept;
496 inline Iterator begin () noexcept;
497 inline ConstIterator begin () const noexcept;
498 inline ConstIterator cbegin() const noexcept;
499 inline Iterator end () noexcept;
500 inline ConstIterator end () const noexcept;
501 inline ConstIterator cend () const noexcept;
502 //@}
503 //**********************************************************************************************
504
505 //**Assignment operators************************************************************************
506 /*!\name Assignment operators */
507 //@{
508 inline CustomVector& operator=( const Type& rhs );
509 inline CustomVector& operator=( initializer_list<Type> list );
510
511 template< typename Other, size_t Dim >
512 inline CustomVector& operator=( const Other (&array)[Dim] );
513
514 template< typename Other, size_t Dim >
515 inline CustomVector& operator=( const std::array<Other,Dim>& array );
516
517 inline CustomVector& operator=( const CustomVector& rhs );
518 inline CustomVector& operator=( CustomVector&& rhs ) noexcept;
519
520 template< typename VT > inline CustomVector& operator= ( const Vector<VT,TF>& rhs );
521 template< typename VT > inline CustomVector& operator+=( const Vector<VT,TF>& rhs );
522 template< typename VT > inline CustomVector& operator-=( const Vector<VT,TF>& rhs );
523 template< typename VT > inline CustomVector& operator*=( const Vector<VT,TF>& rhs );
524 template< typename VT > inline CustomVector& operator/=( const DenseVector<VT,TF>& rhs );
525 template< typename VT > inline CustomVector& operator%=( const Vector<VT,TF>& rhs );
526 //@}
527 //**********************************************************************************************
528
529 //**Utility functions***************************************************************************
530 /*!\name Utility functions */
531 //@{
532 inline size_t size() const noexcept;
533 inline size_t spacing() const noexcept;
534 inline size_t capacity() const noexcept;
535 inline size_t nonZeros() const;
536 inline void reset();
537 inline void clear();
538 inline void swap( CustomVector& v ) noexcept;
539 //@}
540 //**********************************************************************************************
541
542 //**Numeric functions***************************************************************************
543 /*!\name Numeric functions */
544 //@{
545 template< typename Other > inline CustomVector& scale( const Other& scalar );
546 //@}
547 //**********************************************************************************************
548
549 //**Resource management functions***************************************************************
550 /*!\name Resource management functions */
551 //@{
552 inline void reset( Type* ptr, size_t n );
553 inline void reset( Type* ptr, size_t n, size_t nn );
554 //@}
555 //**********************************************************************************************
556
557 private:
558 //**********************************************************************************************
559 /*! \cond BLAZE_INTERNAL */
560 //! Helper variable template for the explicit application of the SFINAE principle.
561 template< typename VT >
562 static constexpr bool VectorizedAssign_v =
563 ( useOptimizedKernels &&
564 simdEnabled && VT::simdEnabled &&
565 IsSIMDCombinable_v< Type, ElementType_t<VT> > );
566 /*! \endcond */
567 //**********************************************************************************************
568
569 //**********************************************************************************************
570 /*! \cond BLAZE_INTERNAL */
571 //! Helper variable template for the explicit application of the SFINAE principle.
572 template< typename VT >
573 static constexpr bool VectorizedAddAssign_v =
574 ( VectorizedAssign_v<VT> &&
575 HasSIMDAdd_v< Type, ElementType_t<VT> > );
576 /*! \endcond */
577 //**********************************************************************************************
578
579 //**********************************************************************************************
580 /*! \cond BLAZE_INTERNAL */
581 //! Helper variable template for the explicit application of the SFINAE principle.
582 template< typename VT >
583 static constexpr bool VectorizedSubAssign_v =
584 ( VectorizedAssign_v<VT> &&
585 HasSIMDSub_v< Type, ElementType_t<VT> > );
586 /*! \endcond */
587 //**********************************************************************************************
588
589 //**********************************************************************************************
590 /*! \cond BLAZE_INTERNAL */
591 //! Helper variable template for the explicit application of the SFINAE principle.
592 template< typename VT >
593 static constexpr bool VectorizedMultAssign_v =
594 ( VectorizedAssign_v<VT> &&
595 HasSIMDMult_v< Type, ElementType_t<VT> > );
596 /*! \endcond */
597 //**********************************************************************************************
598
599 //**********************************************************************************************
600 /*! \cond BLAZE_INTERNAL */
601 //! Helper variable template for the explicit application of the SFINAE principle.
602 template< typename VT >
603 static constexpr bool VectorizedDivAssign_v =
604 ( VectorizedAssign_v<VT> &&
605 HasSIMDDiv_v< Type, ElementType_t<VT> > );
606 /*! \endcond */
607 //**********************************************************************************************
608
609 //**SIMD properties*****************************************************************************
610 //! The number of elements packed within a single SIMD element.
611 static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
612 //**********************************************************************************************
613
614 public:
615 //**Expression template evaluation functions****************************************************
616 /*!\name Expression template evaluation functions */
617 //@{
618 template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
619 template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
620
621 inline bool isAligned () const noexcept;
622 inline bool canSMPAssign() const noexcept;
623
624 BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
625 BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
626 BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
627
628 BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
629 BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
630 BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
631 BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
632
633 template< typename VT >
634 inline auto assign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedAssign_v<VT> >;
635
636 template< typename VT >
637 inline auto assign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedAssign_v<VT> >;
638
639 template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
640
641 template< typename VT >
642 inline auto addAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<VT> >;
643
644 template< typename VT >
645 inline auto addAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<VT> >;
646
647 template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
648
649 template< typename VT >
650 inline auto subAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<VT> >;
651
652 template< typename VT >
653 inline auto subAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<VT> >;
654
655 template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
656
657 template< typename VT >
658 inline auto multAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedMultAssign_v<VT> >;
659
660 template< typename VT >
661 inline auto multAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedMultAssign_v<VT> >;
662
663 template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
664
665 template< typename VT >
666 inline auto divAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedDivAssign_v<VT> >;
667
668 template< typename VT >
669 inline auto divAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedDivAssign_v<VT> >;
670 //@}
671 //**********************************************************************************************
672
673 private:
674 //**Member variables****************************************************************************
675 /*!\name Member variables */
676 //@{
677 size_t size_; //!< The size/dimension of the custom vector.
678 Type* v_; //!< The custom array of elements.
679 /*!< Access to the array of elements is gained via the
680 subscript operator. The order of the elements is
681 \f[\left(\begin{array}{*{5}{c}}
682 0 & 1 & 2 & \cdots & N-1 \\
683 \end{array}\right)\f] */
684 //@}
685 //**********************************************************************************************
686
687 //**Compile time checks*************************************************************************
688 /*! \cond BLAZE_INTERNAL */
689 BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE( Type );
690 BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
691 BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE( Type );
692 /*! \endcond */
693 //**********************************************************************************************
694 };
695 //*************************************************************************************************
696
697
698
699
700 //=================================================================================================
701 //
702 // CONSTRUCTORS
703 //
704 //=================================================================================================
705
706 //*************************************************************************************************
707 /*!\brief The default constructor for CustomVector.
708 */
709 template< typename Type // Data type of the vector
710 , AlignmentFlag AF // Alignment flag
711 , PaddingFlag PF // Padding flag
712 , bool TF // Transpose flag
713 , typename Tag // Type tag
714 , typename RT > // Result type
CustomVector()715 inline CustomVector<Type,AF,PF,TF,Tag,RT>::CustomVector()
716 : size_( 0UL ) // The size/dimension of the vector
717 , v_ ( nullptr ) // The custom array of elements
718 {}
719 //*************************************************************************************************
720
721
722 //*************************************************************************************************
723 /*!\brief Constructor for an unpadded custom vector of size \a n.
724 //
725 // \param ptr The array of elements to be used by the vector.
726 // \param n The number of array elements to be used by the custom vector.
727 // \exception std::invalid_argument Invalid setup of custom vector.
728 //
729 // This constructor creates an unpadded custom vector of size \a n. The construction fails if ...
730 //
731 // - ... the passed pointer is \c nullptr;
732 // - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
733 // aligned according to the available instruction set (SSE, AVX, ...).
734 //
735 // In all failure cases a \a std::invalid_argument exception is thrown.
736 //
737 // \note This constructor is \b NOT available for padded custom vectors!
738 // \note The custom vector does \b NOT take responsibility for the given array of elements!
739 */
740 template< typename Type // Data type of the vector
741 , AlignmentFlag AF // Alignment flag
742 , PaddingFlag PF // Padding flag
743 , bool TF // Transpose flag
744 , typename Tag // Type tag
745 , typename RT > // Result type
CustomVector(Type * ptr,size_t n)746 inline CustomVector<Type,AF,PF,TF,Tag,RT>::CustomVector( Type* ptr, size_t n )
747 : size_( n ) // The size/dimension of the vector
748 , v_ ( ptr ) // The custom array of elements
749 {
750 if( ptr == nullptr ) {
751 BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
752 }
753
754 if( AF && !checkAlignment( ptr ) ) {
755 BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
756 }
757 }
758 //*************************************************************************************************
759
760
761 //*************************************************************************************************
762 /*!\brief Constructor for a padded custom vector of size \a n and capacity \a nn.
763 //
764 // \param ptr The array of elements to be used by the vector.
765 // \param n The number of array elements to be used by the custom vector.
766 // \param nn The maximum size of the given array.
767 // \exception std::invalid_argument Invalid setup of custom vector.
768 //
769 // This constructor creates a padded custom vector of size \a n and capacity \a nn. The
770 // construction fails if ...
771 //
772 // - ... the passed pointer is \c nullptr;
773 // - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
774 // aligned according to the available instruction set (SSE, AVX, ...);
775 // - ... the specified capacity \a nn is insufficient for the given data type \a Type and the
776 // available instruction set.
777 //
778 // In all failure cases a \a std::invalid_argument exception is thrown.
779 //
780 // \note This constructor is \b NOT available for unpadded custom vectors!
781 // \note The custom vector does \b NOT take responsibility for the given array of elements!
782 */
783 template< typename Type // Data type of the vector
784 , AlignmentFlag AF // Alignment flag
785 , PaddingFlag PF // Padding flag
786 , bool TF // Transpose flag
787 , typename Tag // Type tag
788 , typename RT > // Result type
CustomVector(Type * ptr,size_t n,size_t nn)789 inline CustomVector<Type,AF,PF,TF,Tag,RT>::CustomVector( Type* ptr, size_t n, size_t nn )
790 : size_( 0UL ) // The size/dimension of the vector
791 , v_ ( nullptr ) // The custom array of elements
792 {
793 BLAZE_STATIC_ASSERT( PF == padded );
794
795 MAYBE_UNUSED( ptr, n, nn );
796 }
797 //*************************************************************************************************
798
799
800 //*************************************************************************************************
801 /*!\brief The copy constructor for CustomVector.
802 //
803 // \param v Vector to be copied.
804 //
805 // The copy constructor initializes the custom vector as an exact copy of the given custom vector.
806 */
807 template< typename Type // Data type of the vector
808 , AlignmentFlag AF // Alignment flag
809 , PaddingFlag PF // Padding flag
810 , bool TF // Transpose flag
811 , typename Tag // Type tag
812 , typename RT > // Result type
CustomVector(const CustomVector & v)813 inline CustomVector<Type,AF,PF,TF,Tag,RT>::CustomVector( const CustomVector& v )
814 : size_( v.size_ ) // The size/dimension of the vector
815 , v_ ( v.v_ ) // The custom array of elements
816 {}
817 //*************************************************************************************************
818
819
820 //*************************************************************************************************
821 /*!\brief The move constructor for CustomVector.
822 //
823 // \param v The vector to be moved into this instance.
824 */
825 template< typename Type // Data type of the vector
826 , AlignmentFlag AF // Alignment flag
827 , PaddingFlag PF // Padding flag
828 , bool TF // Transpose flag
829 , typename Tag // Type tag
830 , typename RT > // Result type
CustomVector(CustomVector && v)831 inline CustomVector<Type,AF,PF,TF,Tag,RT>::CustomVector( CustomVector&& v ) noexcept
832 : size_( v.size_ ) // The size/dimension of the vector
833 , v_ ( v.v_ ) // The custom array of elements
834 {
835 v.size_ = 0UL;
836 v.v_ = nullptr;
837
838 BLAZE_INTERNAL_ASSERT( v.data() == nullptr, "Invalid data reference detected" );
839 }
840 //*************************************************************************************************
841
842
843
844
845 //=================================================================================================
846 //
847 // DESTRUCTOR
848 //
849 //=================================================================================================
850
851 //*************************************************************************************************
852 /*!\brief The destructor for CustomVector.
853 */
854 template< typename Type // Data type of the vector
855 , AlignmentFlag AF // Alignment flag
856 , PaddingFlag PF // Padding flag
857 , bool TF // Transpose flag
858 , typename Tag // Type tag
859 , typename RT > // Result type
~CustomVector()860 inline CustomVector<Type,AF,PF,TF,Tag,RT>::~CustomVector()
861 {
862 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
863 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
864 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<RT> );
865 BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( RT );
866 BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE( RT );
867 }
868 //*************************************************************************************************
869
870
871
872
873 //=================================================================================================
874 //
875 // DATA ACCESS FUNCTIONS
876 //
877 //=================================================================================================
878
879 //*************************************************************************************************
880 /*!\brief Subscript operator for the direct access to the vector elements.
881 //
882 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
883 // \return Reference to the accessed value.
884 //
885 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
886 // the at() function is guaranteed to perform a check of the given access index.
887 */
888 template< typename Type // Data type of the vector
889 , AlignmentFlag AF // Alignment flag
890 , PaddingFlag PF // Padding flag
891 , bool TF // Transpose flag
892 , typename Tag // Type tag
893 , typename RT > // Result type
894 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::Reference
895 CustomVector<Type,AF,PF,TF,Tag,RT>::operator[]( size_t index ) noexcept
896 {
897 BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
898 return v_[index];
899 }
900 //*************************************************************************************************
901
902
903 //*************************************************************************************************
904 /*!\brief Subscript operator for the direct access to the vector elements.
905 //
906 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
907 // \return Reference to the accessed value.
908 //
909 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
910 // the at() function is guaranteed to perform a check of the given access index.
911 */
912 template< typename Type // Data type of the vector
913 , AlignmentFlag AF // Alignment flag
914 , PaddingFlag PF // Padding flag
915 , bool TF // Transpose flag
916 , typename Tag // Type tag
917 , typename RT > // Result type
918 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::ConstReference
919 CustomVector<Type,AF,PF,TF,Tag,RT>::operator[]( size_t index ) const noexcept
920 {
921 BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
922 return v_[index];
923 }
924 //*************************************************************************************************
925
926
927 //*************************************************************************************************
928 /*!\brief Checked access to the vector elements.
929 //
930 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
931 // \return Reference to the accessed value.
932 // \exception std::out_of_range Invalid vector access index.
933 //
934 // In contrast to the subscript operator this function always performs a check of the given
935 // access index.
936 */
937 template< typename Type // Data type of the vector
938 , AlignmentFlag AF // Alignment flag
939 , PaddingFlag PF // Padding flag
940 , bool TF // Transpose flag
941 , typename Tag // Type tag
942 , typename RT > // Result type
943 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::Reference
at(size_t index)944 CustomVector<Type,AF,PF,TF,Tag,RT>::at( size_t index )
945 {
946 if( index >= size_ ) {
947 BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
948 }
949 return (*this)[index];
950 }
951 //*************************************************************************************************
952
953
954 //*************************************************************************************************
955 /*!\brief Checked access to the vector elements.
956 //
957 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
958 // \return Reference to the accessed value.
959 // \exception std::out_of_range Invalid vector access index.
960 //
961 // In contrast to the subscript operator this function always performs a check of the given
962 // access index.
963 */
964 template< typename Type // Data type of the vector
965 , AlignmentFlag AF // Alignment flag
966 , PaddingFlag PF // Padding flag
967 , bool TF // Transpose flag
968 , typename Tag // Type tag
969 , typename RT > // Result type
970 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::ConstReference
at(size_t index)971 CustomVector<Type,AF,PF,TF,Tag,RT>::at( size_t index ) const
972 {
973 if( index >= size_ ) {
974 BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
975 }
976 return (*this)[index];
977 }
978 //*************************************************************************************************
979
980
981 //*************************************************************************************************
982 /*!\brief Low-level data access to the vector elements.
983 //
984 // \return Pointer to the internal element storage.
985 //
986 // This function returns a pointer to the internal storage of the custom vector.
987 */
988 template< typename Type // Data type of the vector
989 , AlignmentFlag AF // Alignment flag
990 , PaddingFlag PF // Padding flag
991 , bool TF // Transpose flag
992 , typename Tag // Type tag
993 , typename RT > // Result type
994 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::Pointer
data()995 CustomVector<Type,AF,PF,TF,Tag,RT>::data() noexcept
996 {
997 return v_;
998 }
999 //*************************************************************************************************
1000
1001
1002 //*************************************************************************************************
1003 /*!\brief Low-level data access to the vector elements.
1004 //
1005 // \return Pointer to the internal element storage.
1006 //
1007 // This function returns a pointer to the internal storage of the custom vector.
1008 */
1009 template< typename Type // Data type of the vector
1010 , AlignmentFlag AF // Alignment flag
1011 , PaddingFlag PF // Padding flag
1012 , bool TF // Transpose flag
1013 , typename Tag // Type tag
1014 , typename RT > // Result type
1015 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::ConstPointer
data()1016 CustomVector<Type,AF,PF,TF,Tag,RT>::data() const noexcept
1017 {
1018 return v_;
1019 }
1020 //*************************************************************************************************
1021
1022
1023 //*************************************************************************************************
1024 /*!\brief Returns an iterator to the first element of the custom vector.
1025 //
1026 // \return Iterator to the first element of the custom vector.
1027 */
1028 template< typename Type // Data type of the vector
1029 , AlignmentFlag AF // Alignment flag
1030 , PaddingFlag PF // Padding flag
1031 , bool TF // Transpose flag
1032 , typename Tag // Type tag
1033 , typename RT > // Result type
1034 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::Iterator
begin()1035 CustomVector<Type,AF,PF,TF,Tag,RT>::begin() noexcept
1036 {
1037 return Iterator( v_ );
1038 }
1039 //*************************************************************************************************
1040
1041
1042 //*************************************************************************************************
1043 /*!\brief Returns an iterator to the first element of the custom vector.
1044 //
1045 // \return Iterator to the first element of the custom vector.
1046 */
1047 template< typename Type // Data type of the vector
1048 , AlignmentFlag AF // Alignment flag
1049 , PaddingFlag PF // Padding flag
1050 , bool TF // Transpose flag
1051 , typename Tag // Type tag
1052 , typename RT > // Result type
1053 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::ConstIterator
begin()1054 CustomVector<Type,AF,PF,TF,Tag,RT>::begin() const noexcept
1055 {
1056 return ConstIterator( v_ );
1057 }
1058 //*************************************************************************************************
1059
1060
1061 //*************************************************************************************************
1062 /*!\brief Returns an iterator to the first element of the custom vector.
1063 //
1064 // \return Iterator to the first element of the custom vector.
1065 */
1066 template< typename Type // Data type of the vector
1067 , AlignmentFlag AF // Alignment flag
1068 , PaddingFlag PF // Padding flag
1069 , bool TF // Transpose flag
1070 , typename Tag // Type tag
1071 , typename RT > // Result type
1072 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::ConstIterator
cbegin()1073 CustomVector<Type,AF,PF,TF,Tag,RT>::cbegin() const noexcept
1074 {
1075 return ConstIterator( v_ );
1076 }
1077 //*************************************************************************************************
1078
1079
1080 //*************************************************************************************************
1081 /*!\brief Returns an iterator just past the last element of the custom vector.
1082 //
1083 // \return Iterator just past the last element of the custom vector.
1084 */
1085 template< typename Type // Data type of the vector
1086 , AlignmentFlag AF // Alignment flag
1087 , PaddingFlag PF // Padding flag
1088 , bool TF // Transpose flag
1089 , typename Tag // Type tag
1090 , typename RT > // Result type
1091 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::Iterator
end()1092 CustomVector<Type,AF,PF,TF,Tag,RT>::end() noexcept
1093 {
1094 return Iterator( v_+size_ );
1095 }
1096 //*************************************************************************************************
1097
1098
1099 //*************************************************************************************************
1100 /*!\brief Returns an iterator just past the last element of the custom vector.
1101 //
1102 // \return Iterator just past the last element of the custom vector.
1103 */
1104 template< typename Type // Data type of the vector
1105 , AlignmentFlag AF // Alignment flag
1106 , PaddingFlag PF // Padding flag
1107 , bool TF // Transpose flag
1108 , typename Tag // Type tag
1109 , typename RT > // Result type
1110 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::ConstIterator
end()1111 CustomVector<Type,AF,PF,TF,Tag,RT>::end() const noexcept
1112 {
1113 return ConstIterator( v_+size_ );
1114 }
1115 //*************************************************************************************************
1116
1117
1118 //*************************************************************************************************
1119 /*!\brief Returns an iterator just past the last element of the custom vector.
1120 //
1121 // \return Iterator just past the last element of the custom vector.
1122 */
1123 template< typename Type // Data type of the vector
1124 , AlignmentFlag AF // Alignment flag
1125 , PaddingFlag PF // Padding flag
1126 , bool TF // Transpose flag
1127 , typename Tag // Type tag
1128 , typename RT > // Result type
1129 inline typename CustomVector<Type,AF,PF,TF,Tag,RT>::ConstIterator
cend()1130 CustomVector<Type,AF,PF,TF,Tag,RT>::cend() const noexcept
1131 {
1132 return ConstIterator( v_+size_ );
1133 }
1134 //*************************************************************************************************
1135
1136
1137
1138
1139 //=================================================================================================
1140 //
1141 // ASSIGNMENT OPERATORS
1142 //
1143 //=================================================================================================
1144
1145 //*************************************************************************************************
1146 /*!\brief Homogenous assignment to all vector elements.
1147 //
1148 // \param rhs Scalar value to be assigned to all vector elements.
1149 // \return Reference to the assigned vector.
1150 */
1151 template< typename Type // Data type of the vector
1152 , AlignmentFlag AF // Alignment flag
1153 , PaddingFlag PF // Padding flag
1154 , bool TF // Transpose flag
1155 , typename Tag // Type tag
1156 , typename RT > // Result type
1157 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1158 CustomVector<Type,AF,PF,TF,Tag,RT>::operator=( const Type& rhs )
1159 {
1160 for( size_t i=0UL; i<size_; ++i )
1161 v_[i] = rhs;
1162 return *this;
1163 }
1164 //*************************************************************************************************
1165
1166
1167 //*************************************************************************************************
1168 /*!\brief List assignment to all vector elements.
1169 //
1170 // \param list The initializer list.
1171 // \exception std::invalid_argument Invalid assignment to custom vector.
1172 //
1173 // This assignment operator offers the option to directly assign to all elements of the vector
1174 // by means of an initializer list:
1175
1176 \code
1177 using blaze::CustomVector;
1178 using blaze::unaliged;
1179 using blaze::unpadded;
1180
1181 const int array[4] = { 1, 2, 3, 4 };
1182
1183 CustomVector<double,unaligned,unpadded> v( array, 4UL );
1184 v = { 5, 6, 7 };
1185 \endcode
1186
1187 // The vector elements are assigned the values from the given initializer list. Missing values
1188 // are reset to their default state. Note that in case the size of the initializer list exceeds
1189 // the size of the vector, a \a std::invalid_argument exception is thrown.
1190 */
1191 template< typename Type // Data type of the vector
1192 , AlignmentFlag AF // Alignment flag
1193 , PaddingFlag PF // Padding flag
1194 , bool TF // Transpose flag
1195 , typename Tag // Type tag
1196 , typename RT > // Result type
1197 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1198 CustomVector<Type,AF,PF,TF,Tag,RT>::operator=( initializer_list<Type> list )
1199 {
1200 if( list.size() > size_ ) {
1201 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to custom vector" );
1202 }
1203
1204 std::fill( std::copy( list.begin(), list.end(), v_ ), v_+size_, Type() );
1205
1206 return *this;
1207 }
1208 //*************************************************************************************************
1209
1210
1211 //*************************************************************************************************
1212 /*!\brief Array assignment to all vector elements.
1213 //
1214 // \param array Static array for the assignment.
1215 // \return Reference to the assigned vector.
1216 // \exception std::invalid_argument Invalid array size.
1217 //
1218 // This assignment operator offers the option to directly set all elements of the vector. The
1219 // following example demonstrates this by means of an unaligned, unpadded custom vector:
1220
1221 \code
1222 using blaze::CustomVector;
1223 using blaze::unaliged;
1224 using blaze::unpadded;
1225
1226 const int array[4] = { 1, 2, 3, 4 };
1227 const int init[4] = { 5, 6, 7 };
1228
1229 CustomVector<double,unaligned,unpadded> v( array, 4UL );
1230 v = init;
1231 \endcode
1232
1233 // The vector is assigned the values from the given static array. Missing values are initialized
1234 // with default values (as e.g. the fourth element in the example). Note that the size of the
1235 // static array must match the size of the custom vector. Otherwise a \a std::invalid_argument
1236 // exception is thrown. Also note that after the assignment \a array will have the same entries
1237 // as \a init.
1238 */
1239 template< typename Type // Data type of the vector
1240 , AlignmentFlag AF // Alignment flag
1241 , PaddingFlag PF // Padding flag
1242 , bool TF // Transpose flag
1243 , typename Tag // Type tag
1244 , typename RT > // Result type
1245 template< typename Other // Data type of the static array
1246 , size_t Dim > // Dimension of the static array
1247 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1248 CustomVector<Type,AF,PF,TF,Tag,RT>::operator=( const Other (&array)[Dim] )
1249 {
1250 if( size_ != Dim ) {
1251 BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
1252 }
1253
1254 for( size_t i=0UL; i<Dim; ++i )
1255 v_[i] = array[i];
1256
1257 return *this;
1258 }
1259 //*************************************************************************************************
1260
1261
1262 //*************************************************************************************************
1263 /*!\brief Array assignment to all vector elements.
1264 //
1265 // \param array The given std::array for the assignment.
1266 // \return Reference to the assigned vector.
1267 // \exception std::invalid_argument Invalid std::array size.
1268 //
1269 // This assignment operator offers the option to directly set all elements of the vector. The
1270 // following example demonstrates this by means of an unaligned, unpadded custom vector:
1271
1272 \code
1273 using blaze::CustomVector;
1274 using blaze::unaliged;
1275 using blaze::unpadded;
1276
1277 const int array[4] = { 1, 2, 3, 4 };
1278 const std::array<int,4UL> init{ 5, 6, 7 };
1279
1280 CustomVector<double,unaligned,unpadded> v( array, 4UL );
1281 v = init;
1282 \endcode
1283
1284 // The vector is assigned the values from the given std::array. Missing values are initialized
1285 // with default values (as e.g. the fourth element in the example). Note that the size of the
1286 // std::array must match the size of the custom vector. Otherwise a \a std::invalid_argument
1287 // exception is thrown. Also note that after the assignment \a array will have the same entries
1288 // as \a init.
1289 */
1290 template< typename Type // Data type of the vector
1291 , AlignmentFlag AF // Alignment flag
1292 , PaddingFlag PF // Padding flag
1293 , bool TF // Transpose flag
1294 , typename Tag // Type tag
1295 , typename RT > // Result type
1296 template< typename Other // Data type of the std::array
1297 , size_t Dim > // Dimension of the std::array
1298 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1299 CustomVector<Type,AF,PF,TF,Tag,RT>::operator=( const std::array<Other,Dim>& array )
1300 {
1301 if( size_ != Dim ) {
1302 BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
1303 }
1304
1305 for( size_t i=0UL; i<Dim; ++i )
1306 v_[i] = array[i];
1307
1308 return *this;
1309 }
1310 //*************************************************************************************************
1311
1312
1313 //*************************************************************************************************
1314 /*!\brief Copy assignment operator for CustomVector.
1315 //
1316 // \param rhs Vector to be copied.
1317 // \return Reference to the assigned vector.
1318 // \exception std::invalid_argument Vector sizes do not match.
1319 //
1320 // The vector is initialized as a copy of the given vector. In case the current sizes of the two
1321 // vectors don't match, a \a std::invalid_argument exception is thrown.
1322 */
1323 template< typename Type // Data type of the vector
1324 , AlignmentFlag AF // Alignment flag
1325 , PaddingFlag PF // Padding flag
1326 , bool TF // Transpose flag
1327 , typename Tag // Type tag
1328 , typename RT > // Result type
1329 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1330 CustomVector<Type,AF,PF,TF,Tag,RT>::operator=( const CustomVector& rhs )
1331 {
1332 if( rhs.size() != size_ ) {
1333 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1334 }
1335
1336 smpAssign( *this, *rhs );
1337
1338 return *this;
1339 }
1340 //*************************************************************************************************
1341
1342
1343 //*************************************************************************************************
1344 /*!\brief Move assignment operator for CustomVector.
1345 //
1346 // \param rhs The vector to be moved into this instance.
1347 // \return Reference to the assigned vector.
1348 */
1349 template< typename Type // Data type of the vector
1350 , AlignmentFlag AF // Alignment flag
1351 , PaddingFlag PF // Padding flag
1352 , bool TF // Transpose flag
1353 , typename Tag // Type tag
1354 , typename RT > // Result type
1355 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1356 CustomVector<Type,AF,PF,TF,Tag,RT>::operator=( CustomVector&& rhs ) noexcept
1357 {
1358 size_ = rhs.size_;
1359 v_ = rhs.v_;
1360
1361 rhs.size_ = 0UL;
1362 rhs.v_ = nullptr;
1363
1364 BLAZE_INTERNAL_ASSERT( rhs.data() == nullptr, "Invalid data reference detected" );
1365
1366 return *this;
1367 }
1368 //*************************************************************************************************
1369
1370
1371 //*************************************************************************************************
1372 /*!\brief Assignment operator for different vectors.
1373 //
1374 // \param rhs Vector to be copied.
1375 // \return Reference to the assigned vector.
1376 // \exception std::invalid_argument Vector sizes do not match.
1377 //
1378 // The vector is initialized as a copy of the given vector. In case the current sizes of the two
1379 // vectors don't match, a \a std::invalid_argument exception is thrown.
1380 */
1381 template< typename Type // Data type of the vector
1382 , AlignmentFlag AF // Alignment flag
1383 , PaddingFlag PF // Padding flag
1384 , bool TF // Transpose flag
1385 , typename Tag // Type tag
1386 , typename RT > // Result type
1387 template< typename VT > // Type of the right-hand side vector
1388 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1389 CustomVector<Type,AF,PF,TF,Tag,RT>::operator=( const Vector<VT,TF>& rhs )
1390 {
1391 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1392
1393 if( (*rhs).size() != size_ ) {
1394 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1395 }
1396
1397 if( (*rhs).canAlias( this ) ) {
1398 const ResultType_t<VT> tmp( *rhs );
1399 smpAssign( *this, tmp );
1400 }
1401 else {
1402 if( IsSparseVector_v<VT> )
1403 reset();
1404 smpAssign( *this, *rhs );
1405 }
1406
1407 return *this;
1408 }
1409 //*************************************************************************************************
1410
1411
1412 //*************************************************************************************************
1413 /*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
1414 //
1415 // \param rhs The right-hand side vector to be added to the vector.
1416 // \return Reference to the vector.
1417 // \exception std::invalid_argument Vector sizes do not match.
1418 //
1419 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1420 // is thrown.
1421 */
1422 template< typename Type // Data type of the vector
1423 , AlignmentFlag AF // Alignment flag
1424 , PaddingFlag PF // Padding flag
1425 , bool TF // Transpose flag
1426 , typename Tag // Type tag
1427 , typename RT > // Result type
1428 template< typename VT > // Type of the right-hand side vector
1429 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1430 CustomVector<Type,AF,PF,TF,Tag,RT>::operator+=( const Vector<VT,TF>& rhs )
1431 {
1432 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1433
1434 if( (*rhs).size() != size_ ) {
1435 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1436 }
1437
1438 if( (*rhs).canAlias( this ) ) {
1439 const ResultType_t<VT> tmp( *rhs );
1440 smpAddAssign( *this, tmp );
1441 }
1442 else {
1443 smpAddAssign( *this, *rhs );
1444 }
1445
1446 return *this;
1447 }
1448 //*************************************************************************************************
1449
1450
1451 //*************************************************************************************************
1452 /*!\brief Subtraction assignment operator for the subtraction of a vector
1453 // (\f$ \vec{a}-=\vec{b} \f$).
1454 //
1455 // \param rhs The right-hand side vector to be subtracted from the vector.
1456 // \return Reference to the vector.
1457 // \exception std::invalid_argument Vector sizes do not match.
1458 //
1459 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1460 // is thrown.
1461 */
1462 template< typename Type // Data type of the vector
1463 , AlignmentFlag AF // Alignment flag
1464 , PaddingFlag PF // Padding flag
1465 , bool TF // Transpose flag
1466 , typename Tag // Type tag
1467 , typename RT > // Result type
1468 template< typename VT > // Type of the right-hand side vector
1469 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1470 CustomVector<Type,AF,PF,TF,Tag,RT>::operator-=( const Vector<VT,TF>& rhs )
1471 {
1472 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1473
1474 if( (*rhs).size() != size_ ) {
1475 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1476 }
1477
1478 if( (*rhs).canAlias( this ) ) {
1479 const ResultType_t<VT> tmp( *rhs );
1480 smpSubAssign( *this, tmp );
1481 }
1482 else {
1483 smpSubAssign( *this, *rhs );
1484 }
1485
1486 return *this;
1487 }
1488 //*************************************************************************************************
1489
1490
1491 //*************************************************************************************************
1492 /*!\brief Multiplication assignment operator for the multiplication of a vector
1493 // (\f$ \vec{a}*=\vec{b} \f$).
1494 //
1495 // \param rhs The right-hand side vector to be multiplied with the vector.
1496 // \return Reference to the vector.
1497 // \exception std::invalid_argument Vector sizes do not match.
1498 //
1499 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1500 // is thrown.
1501 */
1502 template< typename Type // Data type of the vector
1503 , AlignmentFlag AF // Alignment flag
1504 , PaddingFlag PF // Padding flag
1505 , bool TF // Transpose flag
1506 , typename Tag // Type tag
1507 , typename RT > // Result type
1508 template< typename VT > // Type of the right-hand side vector
1509 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1510 CustomVector<Type,AF,PF,TF,Tag,RT>::operator*=( const Vector<VT,TF>& rhs )
1511 {
1512 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1513
1514 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
1515 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<VT> );
1516
1517 using MultType = MultTrait_t< ResultType, ResultType_t<VT> >;
1518
1519 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( MultType, TF );
1520 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
1521
1522 if( (*rhs).size() != size_ ) {
1523 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1524 }
1525
1526 if( IsSparseVector_v<VT> || (*rhs).canAlias( this ) ) {
1527 const MultType tmp( *this * (*rhs) );
1528 if( IsSparseVector_v<MultType> )
1529 reset();
1530 smpAssign( *this, tmp );
1531 }
1532 else {
1533 smpMultAssign( *this, *rhs );
1534 }
1535
1536 return *this;
1537 }
1538 //*************************************************************************************************
1539
1540
1541 //*************************************************************************************************
1542 /*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
1543 //
1544 // \param rhs The right-hand side dense vector divisor.
1545 // \return Reference to the vector.
1546 // \exception std::invalid_argument Vector sizes do not match.
1547 //
1548 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1549 // is thrown.
1550 */
1551 template< typename Type // Data type of the vector
1552 , AlignmentFlag AF // Alignment flag
1553 , PaddingFlag PF // Padding flag
1554 , bool TF // Transpose flag
1555 , typename Tag // Type tag
1556 , typename RT > // Result type
1557 template< typename VT > // Type of the right-hand side vector
1558 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1559 CustomVector<Type,AF,PF,TF,Tag,RT>::operator/=( const DenseVector<VT,TF>& rhs )
1560 {
1561 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1562
1563 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
1564 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<VT> );
1565
1566 using DivType = DivTrait_t< ResultType, ResultType_t<VT> >;
1567
1568 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( DivType );
1569 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( DivType, TF );
1570 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
1571
1572 if( (*rhs).size() != size_ ) {
1573 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1574 }
1575
1576 if( (*rhs).canAlias( this ) ) {
1577 const DivType tmp( *this / (*rhs) );
1578 smpAssign( *this, tmp );
1579 }
1580 else {
1581 smpDivAssign( *this, *rhs );
1582 }
1583
1584 return *this;
1585 }
1586 //*************************************************************************************************
1587
1588
1589 //*************************************************************************************************
1590 /*!\brief Cross product assignment operator for the multiplication of a vector
1591 // (\f$ \vec{a}\times=\vec{b} \f$).
1592 //
1593 // \param rhs The right-hand side vector for the cross product.
1594 // \return Reference to the vector.
1595 // \exception std::invalid_argument Invalid vector size for cross product.
1596 //
1597 // In case the current size of any of the two vectors is not equal to 3, a \a std::invalid_argument
1598 // exception is thrown.
1599 */
1600 template< typename Type // Data type of the vector
1601 , AlignmentFlag AF // Alignment flag
1602 , PaddingFlag PF // Padding flag
1603 , bool TF // Transpose flag
1604 , typename Tag // Type tag
1605 , typename RT > // Result type
1606 template< typename VT > // Type of the right-hand side vector
1607 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
1608 CustomVector<Type,AF,PF,TF,Tag,RT>::operator%=( const Vector<VT,TF>& rhs )
1609 {
1610 using blaze::assign;
1611
1612 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1613
1614 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_t<VT>, TF );
1615 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<VT> );
1616
1617 using CrossType = CrossTrait_t< ResultType, ResultType_t<VT> >;
1618
1619 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( CrossType );
1620 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( CrossType, TF );
1621 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( CrossType );
1622
1623 if( size_ != 3UL || (*rhs).size() != 3UL ) {
1624 BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" );
1625 }
1626
1627 const CrossType tmp( *this % (*rhs) );
1628 assign( *this, tmp );
1629
1630 return *this;
1631 }
1632 //*************************************************************************************************
1633
1634
1635
1636
1637 //=================================================================================================
1638 //
1639 // UTILITY FUNCTIONS
1640 //
1641 //=================================================================================================
1642
1643 //*************************************************************************************************
1644 /*!\brief Returns the size/dimension of the vector.
1645 //
1646 // \return The size of the vector.
1647 */
1648 template< typename Type // Data type of the vector
1649 , AlignmentFlag AF // Alignment flag
1650 , PaddingFlag PF // Padding flag
1651 , bool TF // Transpose flag
1652 , typename Tag // Type tag
1653 , typename RT > // Result type
size()1654 inline size_t CustomVector<Type,AF,PF,TF,Tag,RT>::size() const noexcept
1655 {
1656 return size_;
1657 }
1658 //*************************************************************************************************
1659
1660
1661 //*************************************************************************************************
1662 /*!\brief Returns the minimum capacity of the vector.
1663 //
1664 // \return The minimum capacity of the vector.
1665 //
1666 // This function returns the minimum capacity of the vector, which corresponds to the current
1667 // size plus padding.
1668 */
1669 template< typename Type // Data type of the vector
1670 , AlignmentFlag AF // Alignment flag
1671 , PaddingFlag PF // Padding flag
1672 , bool TF // Transpose flag
1673 , typename Tag // Type tag
1674 , typename RT > // Result type
spacing()1675 inline size_t CustomVector<Type,AF,PF,TF,Tag,RT>::spacing() const noexcept
1676 {
1677 return size_;
1678 }
1679 //*************************************************************************************************
1680
1681
1682 //*************************************************************************************************
1683 /*!\brief Returns the maximum capacity of the vector.
1684 //
1685 // \return The maximum capacity of the vector.
1686 */
1687 template< typename Type // Data type of the vector
1688 , AlignmentFlag AF // Alignment flag
1689 , PaddingFlag PF // Padding flag
1690 , bool TF // Transpose flag
1691 , typename Tag // Type tag
1692 , typename RT > // Result type
capacity()1693 inline size_t CustomVector<Type,AF,PF,TF,Tag,RT>::capacity() const noexcept
1694 {
1695 return size_;
1696 }
1697 //*************************************************************************************************
1698
1699
1700 //*************************************************************************************************
1701 /*!\brief Returns the number of non-zero elements in the vector.
1702 //
1703 // \return The number of non-zero elements in the vector.
1704 //
1705 // This function returns the number of non-zero elements in the vector (i.e. the elements that
1706 // compare unequal to their default value). Note that the number of non-zero elements is always
1707 // less than or equal to the current size of the vector.
1708 */
1709 template< typename Type // Data type of the vector
1710 , AlignmentFlag AF // Alignment flag
1711 , PaddingFlag PF // Padding flag
1712 , bool TF // Transpose flag
1713 , typename Tag // Type tag
1714 , typename RT > // Result type
nonZeros()1715 inline size_t CustomVector<Type,AF,PF,TF,Tag,RT>::nonZeros() const
1716 {
1717 size_t nonzeros( 0 );
1718
1719 for( size_t i=0UL; i<size_; ++i ) {
1720 if( !isDefault<strict>( v_[i] ) )
1721 ++nonzeros;
1722 }
1723
1724 return nonzeros;
1725 }
1726 //*************************************************************************************************
1727
1728
1729 //*************************************************************************************************
1730 /*!\brief Reset to the default initial values.
1731 //
1732 // \return void
1733 */
1734 template< typename Type // Data type of the vector
1735 , AlignmentFlag AF // Alignment flag
1736 , PaddingFlag PF // Padding flag
1737 , bool TF // Transpose flag
1738 , typename Tag // Type tag
1739 , typename RT > // Result type
reset()1740 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::reset()
1741 {
1742 using blaze::clear;
1743 for( size_t i=0UL; i<size_; ++i )
1744 clear( v_[i] );
1745 }
1746 //*************************************************************************************************
1747
1748
1749 //*************************************************************************************************
1750 /*!\brief Clearing the vector to its default state.
1751 //
1752 // \return void
1753 //
1754 // This function clears the vector to its default state. In case the vector has been passed the
1755 // responsibility to manage the given array, it disposes the resource via the specified deleter.
1756 */
1757 template< typename Type // Data type of the vector
1758 , AlignmentFlag AF // Alignment flag
1759 , PaddingFlag PF // Padding flag
1760 , bool TF // Transpose flag
1761 , typename Tag // Type tag
1762 , typename RT > // Result type
clear()1763 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::clear()
1764 {
1765 size_ = 0UL;
1766 v_ = nullptr;
1767 }
1768 //*************************************************************************************************
1769
1770
1771 //*************************************************************************************************
1772 /*!\brief Swapping the contents of two vectors.
1773 //
1774 // \param v The vector to be swapped.
1775 // \return void
1776 */
1777 template< typename Type // Data type of the vector
1778 , AlignmentFlag AF // Alignment flag
1779 , PaddingFlag PF // Padding flag
1780 , bool TF // Transpose flag
1781 , typename Tag // Type tag
1782 , typename RT > // Result type
swap(CustomVector & v)1783 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::swap( CustomVector& v ) noexcept
1784 {
1785 using std::swap;
1786
1787 swap( size_, v.size_ );
1788 swap( v_, v.v_ );
1789 }
1790 //*************************************************************************************************
1791
1792
1793
1794
1795 //=================================================================================================
1796 //
1797 // NUMERIC FUNCTIONS
1798 //
1799 //=================================================================================================
1800
1801 //*************************************************************************************************
1802 /*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
1803 //
1804 // \param scalar The scalar value for the vector scaling.
1805 // \return Reference to the vector.
1806 //
1807 // This function scales the vector by applying the given scalar value \a scalar to each element
1808 // of the vector. For built-in and \c complex data types it has the same effect as using the
1809 // multiplication assignment operator:
1810
1811 \code
1812 using blaze::CustomVector;
1813 using blaze::unaliged;
1814 using blaze::unpadded;
1815
1816 CustomVector<double,unaligned,unpadded> v( ... );
1817
1818 a *= 4; // Scaling of the vector
1819 a.scale( 4 ); // Same effect as above
1820 \endcode
1821 */
1822 template< typename Type // Data type of the vector
1823 , AlignmentFlag AF // Alignment flag
1824 , PaddingFlag PF // Padding flag
1825 , bool TF // Transpose flag
1826 , typename Tag // Type tag
1827 , typename RT > // Result type
1828 template< typename Other > // Data type of the scalar value
1829 inline CustomVector<Type,AF,PF,TF,Tag,RT>&
scale(const Other & scalar)1830 CustomVector<Type,AF,PF,TF,Tag,RT>::scale( const Other& scalar )
1831 {
1832 for( size_t i=0UL; i<size_; ++i )
1833 v_[i] *= scalar;
1834 return *this;
1835 }
1836 //*************************************************************************************************
1837
1838
1839
1840
1841 //=================================================================================================
1842 //
1843 // RESOURCE MANAGEMENT FUNCTIONS
1844 //
1845 //=================================================================================================
1846
1847 //*************************************************************************************************
1848 /*!\brief Resets the custom vector and replaces the array of elements with the given array.
1849 //
1850 // \param ptr The array of elements to be used by the vector.
1851 // \param n The number of array elements to be used by the custom vector.
1852 // \return void
1853 // \exception std::invalid_argument Invalid setup of custom vector.
1854 //
1855 // This function resets the custom vector to the given array of elements of size \a n. The
1856 // function fails if ...
1857 //
1858 // - ... the passed pointer is \c nullptr;
1859 // - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
1860 // aligned according to the available instruction set (SSE, AVX, ...).
1861 //
1862 // In all failure cases a \a std::invalid_argument exception is thrown.
1863 //
1864 // \note This function is \b NOT available for padded custom vectors!
1865 // \note In case a deleter was specified, the previously referenced array will only be destroyed
1866 // when the last custom vector referencing the array goes out of scope.
1867 // \note The custom vector does NOT take responsibility for the new array of elements!
1868 */
1869 template< typename Type // Data type of the vector
1870 , AlignmentFlag AF // Alignment flag
1871 , PaddingFlag PF // Padding flag
1872 , bool TF // Transpose flag
1873 , typename Tag // Type tag
1874 , typename RT > // Result type
reset(Type * ptr,size_t n)1875 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::reset( Type* ptr, size_t n )
1876 {
1877 CustomVector tmp( ptr, n );
1878 swap( tmp );
1879 }
1880 //*************************************************************************************************
1881
1882
1883 //*************************************************************************************************
1884 /*!\brief Resets the custom vector and replaces the array of elements with the given array.
1885 //
1886 // \param ptr The array of elements to be used by the vector.
1887 // \param n The number of array elements to be used by the custom vector.
1888 // \param nn The maximum size of the given array.
1889 // \return void
1890 // \exception std::invalid_argument Invalid setup of custom vector.
1891 //
1892 // This function resets the custom vector to the given array of elements of size \a n and
1893 // capacity \a nn. The function fails if ...
1894 //
1895 // - ... the passed pointer is \c nullptr;
1896 // - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
1897 // aligned according to the available instruction set (SSE, AVX, ...);
1898 // - ... the specified capacity \a nn is insufficient for the given data type \a Type and
1899 // the available instruction set.
1900 //
1901 // In all failure cases a \a std::invalid_argument exception is thrown.
1902 //
1903 // \note This function is \a NOT available for unpadded custom vectors!
1904 // \note In case a deleter was specified, the previously referenced array will only be destroyed
1905 // when the last custom vector referencing the array goes out of scope.
1906 // \note The custom vector does NOT take responsibility for the new array of elements!
1907 */
1908 template< typename Type // Data type of the vector
1909 , AlignmentFlag AF // Alignment flag
1910 , PaddingFlag PF // Padding flag
1911 , bool TF // Transpose flag
1912 , typename Tag // Type tag
1913 , typename RT > // Result type
reset(Type * ptr,size_t n,size_t nn)1914 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::reset( Type* ptr, size_t n, size_t nn )
1915 {
1916 BLAZE_STATIC_ASSERT( PF == padded );
1917
1918 MAYBE_UNUSED( ptr, n, nn );
1919 }
1920 //*************************************************************************************************
1921
1922
1923
1924
1925 //=================================================================================================
1926 //
1927 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
1928 //
1929 //=================================================================================================
1930
1931 //*************************************************************************************************
1932 /*!\brief Returns whether the vector can alias with the given address \a alias.
1933 //
1934 // \param alias The alias to be checked.
1935 // \return \a true in case the alias corresponds to this vector, \a false if not.
1936 //
1937 // This function returns whether the given address can alias with the vector. In contrast
1938 // to the isAliased() function this function is allowed to use compile time expressions
1939 // to optimize the evaluation.
1940 */
1941 template< typename Type // Data type of the vector
1942 , AlignmentFlag AF // Alignment flag
1943 , PaddingFlag PF // Padding flag
1944 , bool TF // Transpose flag
1945 , typename Tag // Type tag
1946 , typename RT > // Result type
1947 template< typename Other > // Data type of the foreign expression
canAlias(const Other * alias)1948 inline bool CustomVector<Type,AF,PF,TF,Tag,RT>::canAlias( const Other* alias ) const noexcept
1949 {
1950 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
1951 }
1952 //*************************************************************************************************
1953
1954
1955 //*************************************************************************************************
1956 /*!\brief Returns whether the vector is aliased with the given address \a alias.
1957 //
1958 // \param alias The alias to be checked.
1959 // \return \a true in case the alias corresponds to this vector, \a false if not.
1960 //
1961 // This function returns whether the given address is aliased with the vector. In contrast
1962 // to the canAlias() function this function is not allowed to use compile time expressions
1963 // to optimize the evaluation.
1964 */
1965 template< typename Type // Data type of the vector
1966 , AlignmentFlag AF // Alignment flag
1967 , PaddingFlag PF // Padding flag
1968 , bool TF // Transpose flag
1969 , typename Tag // Type tag
1970 , typename RT > // Result type
1971 template< typename Other > // Data type of the foreign expression
isAliased(const Other * alias)1972 inline bool CustomVector<Type,AF,PF,TF,Tag,RT>::isAliased( const Other* alias ) const noexcept
1973 {
1974 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
1975 }
1976 //*************************************************************************************************
1977
1978
1979 //*************************************************************************************************
1980 /*!\brief Returns whether the vector is properly aligned in memory.
1981 //
1982 // \return \a true in case the vector is aligned, \a false if not.
1983 //
1984 // This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
1985 // whether the beginning and the end of the vector are guaranteed to conform to the alignment
1986 // restrictions of the element type \a Type.
1987 */
1988 template< typename Type // Data type of the vector
1989 , AlignmentFlag AF // Alignment flag
1990 , PaddingFlag PF // Padding flag
1991 , bool TF // Transpose flag
1992 , typename Tag // Type tag
1993 , typename RT > // Result type
isAligned()1994 inline bool CustomVector<Type,AF,PF,TF,Tag,RT>::isAligned() const noexcept
1995 {
1996 return ( AF || checkAlignment( v_ ) );
1997 }
1998 //*************************************************************************************************
1999
2000
2001 //*************************************************************************************************
2002 /*!\brief Returns whether the vector can be used in SMP assignments.
2003 //
2004 // \return \a true in case the vector can be used in SMP assignments, \a false if not.
2005 //
2006 // This function returns whether the vector can be used in SMP assignments. In contrast to the
2007 // \a smpAssignable member enumeration, which is based solely on compile time information, this
2008 // function additionally provides runtime information (as for instance the current size of the
2009 // vector).
2010 */
2011 template< typename Type // Data type of the vector
2012 , AlignmentFlag AF // Alignment flag
2013 , PaddingFlag PF // Padding flag
2014 , bool TF // Transpose flag
2015 , typename Tag // Type tag
2016 , typename RT > // Result type
canSMPAssign()2017 inline bool CustomVector<Type,AF,PF,TF,Tag,RT>::canSMPAssign() const noexcept
2018 {
2019 return ( size() > SMP_DVECASSIGN_THRESHOLD );
2020 }
2021 //*************************************************************************************************
2022
2023
2024 //*************************************************************************************************
2025 /*!\brief Load of a SIMD element of the vector.
2026 //
2027 // \param index Access index. The index must be smaller than the number of vector elements.
2028 // \return The loaded SIMD element.
2029 //
2030 // This function performs a load of a specific SIMD element of the dense vector. The index
2031 // must be smaller than the number of vector elements and it must be a multiple of the number
2032 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
2033 // used internally for the performance optimized evaluation of expression templates. Calling
2034 // this function explicitly might result in erroneous results and/or in compilation errors.
2035 */
2036 template< typename Type // Data type of the vector
2037 , AlignmentFlag AF // Alignment flag
2038 , PaddingFlag PF // Padding flag
2039 , bool TF // Transpose flag
2040 , typename Tag // Type tag
2041 , typename RT > // Result type
2042 BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,PF,TF,Tag,RT>::SIMDType
load(size_t index)2043 CustomVector<Type,AF,PF,TF,Tag,RT>::load( size_t index ) const noexcept
2044 {
2045 if( AF )
2046 return loada( index );
2047 else
2048 return loadu( index );
2049 }
2050 //*************************************************************************************************
2051
2052
2053 //*************************************************************************************************
2054 /*!\brief Aligned load of a SIMD element of the vector.
2055 //
2056 // \param index Access index. The index must be smaller than the number of vector elements.
2057 // \return The loaded SIMD element.
2058 //
2059 // This function performs an aligned load of a specific SIMD element of the dense vector. The
2060 // index must be smaller than the number of vector elements and it must be a multiple of the
2061 // number of values inside the SIMD element. This function must \b NOT be called explicitly!
2062 // It is used internally for the performance optimized evaluation of expression templates.
2063 // Calling this function explicitly might result in erroneous results and/or in compilation
2064 // errors.
2065 */
2066 template< typename Type // Data type of the vector
2067 , AlignmentFlag AF // Alignment flag
2068 , PaddingFlag PF // Padding flag
2069 , bool TF // Transpose flag
2070 , typename Tag // Type tag
2071 , typename RT > // Result type
2072 BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,PF,TF,Tag,RT>::SIMDType
loada(size_t index)2073 CustomVector<Type,AF,PF,TF,Tag,RT>::loada( size_t index ) const noexcept
2074 {
2075 using blaze::loada;
2076
2077 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2078
2079 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
2080 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
2081 BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
2082 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid vector access index" );
2083
2084 return loada( v_+index );
2085 }
2086 //*************************************************************************************************
2087
2088
2089 //*************************************************************************************************
2090 /*!\brief Unaligned load of a SIMD element of the vector.
2091 //
2092 // \param index Access index. The index must be smaller than the number of vector elements.
2093 // \return The loaded SIMD element.
2094 //
2095 // This function performs an unaligned load of a specific SIMD element of the dense vector. The
2096 // index must be smaller than the number of vector elements and it must be a multiple of the
2097 // number of values inside the SIMD element. This function must \b NOT be called explicitly!
2098 // It is used internally for the performance optimized evaluation of expression templates.
2099 // Calling this function explicitly might result in erroneous results and/or in compilation
2100 // errors.
2101 */
2102 template< typename Type // Data type of the vector
2103 , AlignmentFlag AF // Alignment flag
2104 , PaddingFlag PF // Padding flag
2105 , bool TF // Transpose flag
2106 , typename Tag // Type tag
2107 , typename RT > // Result type
2108 BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,PF,TF,Tag,RT>::SIMDType
loadu(size_t index)2109 CustomVector<Type,AF,PF,TF,Tag,RT>::loadu( size_t index ) const noexcept
2110 {
2111 using blaze::loadu;
2112
2113 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2114
2115 BLAZE_INTERNAL_ASSERT( index< size_, "Invalid vector access index" );
2116 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
2117
2118 return loadu( v_+index );
2119 }
2120 //*************************************************************************************************
2121
2122
2123 //*************************************************************************************************
2124 /*!\brief Store of a SIMD element of the vector.
2125 //
2126 // \param index Access index. The index must be smaller than the number of vector elements.
2127 // \param value The SIMD element to be stored.
2128 // \return void
2129 //
2130 // This function performs a store of a specific SIMD element of the dense vector. The index
2131 // must be smaller than the number of vector elements and it must be a multiple of the number
2132 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
2133 // used internally for the performance optimized evaluation of expression templates. Calling
2134 // this function explicitly might result in erroneous results and/or in compilation errors.
2135 */
2136 template< typename Type // Data type of the vector
2137 , AlignmentFlag AF // Alignment flag
2138 , PaddingFlag PF // Padding flag
2139 , bool TF // Transpose flag
2140 , typename Tag // Type tag
2141 , typename RT > // Result type
2142 BLAZE_ALWAYS_INLINE void
store(size_t index,const SIMDType & value)2143 CustomVector<Type,AF,PF,TF,Tag,RT>::store( size_t index, const SIMDType& value ) noexcept
2144 {
2145 if( AF )
2146 storea( index, value );
2147 else
2148 storeu( index, value );
2149 }
2150 //*************************************************************************************************
2151
2152
2153 //*************************************************************************************************
2154 /*!\brief Aligned store of a SIMD element of the vector.
2155 //
2156 // \param index Access index. The index must be smaller than the number of vector elements.
2157 // \param value The SIMD element to be stored.
2158 // \return void
2159 //
2160 // This function performs an aligned store of a specific SIMD element of the dense vector. The
2161 // index must be smaller than the number of vector elements and it must be a multiple of the
2162 // number of values inside the SIMD element. This function must \b NOT be called explicitly! It
2163 // is used internally for the performance optimized evaluation of expression templates. Calling
2164 // this function explicitly might result in erroneous results and/or in compilation errors.
2165 */
2166 template< typename Type // Data type of the vector
2167 , AlignmentFlag AF // Alignment flag
2168 , PaddingFlag PF // Padding flag
2169 , bool TF // Transpose flag
2170 , typename Tag // Type tag
2171 , typename RT > // Result type
2172 BLAZE_ALWAYS_INLINE void
storea(size_t index,const SIMDType & value)2173 CustomVector<Type,AF,PF,TF,Tag,RT>::storea( size_t index, const SIMDType& value ) noexcept
2174 {
2175 using blaze::storea;
2176
2177 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2178
2179 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
2180 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
2181 BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
2182 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid vector access index" );
2183
2184 storea( v_+index, value );
2185 }
2186 //*************************************************************************************************
2187
2188
2189 //*************************************************************************************************
2190 /*!\brief Unaligned store of a SIMD element of the vector.
2191 //
2192 // \param index Access index. The index must be smaller than the number of vector elements.
2193 // \param value The SIMD element to be stored.
2194 // \return void
2195 //
2196 // This function performs an unaligned store of a specific SIMD element of the dense vector.
2197 // The index must be smaller than the number of vector elements and it must be a multiple of the
2198 // number of values inside the SIMD element. This function must \b NOT be called explicitly! It
2199 // is used internally for the performance optimized evaluation of expression templates. Calling
2200 // this function explicitly might result in erroneous results and/or in compilation errors.
2201 */
2202 template< typename Type // Data type of the vector
2203 , AlignmentFlag AF // Alignment flag
2204 , PaddingFlag PF // Padding flag
2205 , bool TF // Transpose flag
2206 , typename Tag // Type tag
2207 , typename RT > // Result type
2208 BLAZE_ALWAYS_INLINE void
storeu(size_t index,const SIMDType & value)2209 CustomVector<Type,AF,PF,TF,Tag,RT>::storeu( size_t index, const SIMDType& value ) noexcept
2210 {
2211 using blaze::storeu;
2212
2213 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2214
2215 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
2216 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
2217
2218 storeu( v_+index, value );
2219 }
2220 //*************************************************************************************************
2221
2222
2223 //*************************************************************************************************
2224 /*!\brief Aligned, non-temporal store of a SIMD element of the vector.
2225 //
2226 // \param index Access index. The index must be smaller than the number of vector elements.
2227 // \param value The SIMD element to be stored.
2228 // \return void
2229 //
2230 // This function performs an aligned, non-temporal store of a specific SIMD element of the
2231 // dense vector. The index must be smaller than the number of vector elements and it must be
2232 // a multiple of the number of values inside the SIMD element. This function must \b NOT be
2233 // called explicitly! It is used internally for the performance optimized evaluation of
2234 // expression templates. Calling this function explicitly might result in erroneous results
2235 // and/or in compilation errors.
2236 */
2237 template< typename Type // Data type of the vector
2238 , AlignmentFlag AF // Alignment flag
2239 , PaddingFlag PF // Padding flag
2240 , bool TF // Transpose flag
2241 , typename Tag // Type tag
2242 , typename RT > // Result type
2243 BLAZE_ALWAYS_INLINE void
stream(size_t index,const SIMDType & value)2244 CustomVector<Type,AF,PF,TF,Tag,RT>::stream( size_t index, const SIMDType& value ) noexcept
2245 {
2246 using blaze::stream;
2247
2248 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2249
2250 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
2251 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= size_, "Invalid vector access index" );
2252 BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
2253 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid vector access index" );
2254
2255 stream( v_+index, value );
2256 }
2257 //*************************************************************************************************
2258
2259
2260 //*************************************************************************************************
2261 /*!\brief Default implementation of the assignment of a dense vector.
2262 //
2263 // \param rhs The right-hand side dense vector to be assigned.
2264 // \return void
2265 //
2266 // This function must \b NOT be called explicitly! It is used internally for the performance
2267 // optimized evaluation of expression templates. Calling this function explicitly might result
2268 // in erroneous results and/or in compilation errors. Instead of using this function use the
2269 // assignment operator.
2270 */
2271 template< typename Type // Data type of the vector
2272 , AlignmentFlag AF // Alignment flag
2273 , PaddingFlag PF // Padding flag
2274 , bool TF // Transpose flag
2275 , typename Tag // Type tag
2276 , typename RT > // Result type
2277 template< typename VT > // Type of the right-hand side dense vector
2278 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::assign( const DenseVector<VT,TF>& rhs )
2279 -> DisableIf_t< VectorizedAssign_v<VT> >
2280 {
2281 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2282
2283 const size_t ipos( prevMultiple( size_, 2UL ) );
2284 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2285
2286 for( size_t i=0UL; i<ipos; i+=2UL ) {
2287 v_[i ] = (*rhs)[i ];
2288 v_[i+1UL] = (*rhs)[i+1UL];
2289 }
2290 if( ipos < (*rhs).size() )
2291 v_[ipos] = (*rhs)[ipos];
2292 }
2293 //*************************************************************************************************
2294
2295
2296 //*************************************************************************************************
2297 /*!\brief SIMD optimized implementation of the assignment of a dense vector.
2298 //
2299 // \param rhs The right-hand side dense vector to be assigned.
2300 // \return void
2301 //
2302 // This function must \b NOT be called explicitly! It is used internally for the performance
2303 // optimized evaluation of expression templates. Calling this function explicitly might result
2304 // in erroneous results and/or in compilation errors. Instead of using this function use the
2305 // assignment operator.
2306 */
2307 template< typename Type // Data type of the vector
2308 , AlignmentFlag AF // Alignment flag
2309 , PaddingFlag PF // Padding flag
2310 , bool TF // Transpose flag
2311 , typename Tag // Type tag
2312 , typename RT > // Result type
2313 template< typename VT > // Type of the right-hand side dense vector
2314 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::assign( const DenseVector<VT,TF>& rhs )
2315 -> EnableIf_t< VectorizedAssign_v<VT> >
2316 {
2317 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2318
2319 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2320
2321 const size_t ipos( prevMultiple( size_, SIMDSIZE ) );
2322 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2323
2324 if( AF && useStreaming && size_ > ( cacheSize/( sizeof(Type) * 3UL ) ) && !(*rhs).isAliased( this ) )
2325 {
2326 size_t i( 0UL );
2327
2328 for( ; i<ipos; i+=SIMDSIZE ) {
2329 stream( i, (*rhs).load(i) );
2330 }
2331 for( ; i<size_; ++i ) {
2332 v_[i] = (*rhs)[i];
2333 }
2334 }
2335 else
2336 {
2337 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
2338 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
2339
2340 size_t i( 0UL );
2341 ConstIterator_t<VT> it( (*rhs).begin() );
2342
2343 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
2344 store( i , it.load() ); it += SIMDSIZE;
2345 store( i+SIMDSIZE , it.load() ); it += SIMDSIZE;
2346 store( i+SIMDSIZE*2UL, it.load() ); it += SIMDSIZE;
2347 store( i+SIMDSIZE*3UL, it.load() ); it += SIMDSIZE;
2348 }
2349 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
2350 store( i, it.load() );
2351 }
2352 for( ; i<size_; ++i, ++it ) {
2353 v_[i] = *it;
2354 }
2355 }
2356 }
2357 //*************************************************************************************************
2358
2359
2360 //*************************************************************************************************
2361 /*!\brief Default implementation of the assignment of a sparse vector.
2362 //
2363 // \param rhs The right-hand side sparse vector to be assigned.
2364 // \return void
2365 //
2366 // This function must \b NOT be called explicitly! It is used internally for the performance
2367 // optimized evaluation of expression templates. Calling this function explicitly might result
2368 // in erroneous results and/or in compilation errors. Instead of using this function use the
2369 // assignment operator.
2370 */
2371 template< typename Type // Data type of the vector
2372 , AlignmentFlag AF // Alignment flag
2373 , PaddingFlag PF // Padding flag
2374 , bool TF // Transpose flag
2375 , typename Tag // Type tag
2376 , typename RT > // Result type
2377 template< typename VT > // Type of the right-hand side sparse vector
assign(const SparseVector<VT,TF> & rhs)2378 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::assign( const SparseVector<VT,TF>& rhs )
2379 {
2380 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2381
2382 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2383 v_[element->index()] = element->value();
2384 }
2385 //*************************************************************************************************
2386
2387
2388 //*************************************************************************************************
2389 /*!\brief Default implementation of the addition assignment of a dense vector.
2390 //
2391 // \param rhs The right-hand side dense vector to be added.
2392 // \return void
2393 //
2394 // This function must \b NOT be called explicitly! It is used internally for the performance
2395 // optimized evaluation of expression templates. Calling this function explicitly might result
2396 // in erroneous results and/or in compilation errors. Instead of using this function use the
2397 // assignment operator.
2398 */
2399 template< typename Type // Data type of the vector
2400 , AlignmentFlag AF // Alignment flag
2401 , PaddingFlag PF // Padding flag
2402 , bool TF // Transpose flag
2403 , typename Tag // Type tag
2404 , typename RT > // Result type
2405 template< typename VT > // Type of the right-hand side dense vector
2406 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::addAssign( const DenseVector<VT,TF>& rhs )
2407 -> DisableIf_t< VectorizedAddAssign_v<VT> >
2408 {
2409 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2410
2411 const size_t ipos( prevMultiple( size_, 2UL ) );
2412 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2413
2414 for( size_t i=0UL; i<ipos; i+=2UL ) {
2415 v_[i ] += (*rhs)[i ];
2416 v_[i+1UL] += (*rhs)[i+1UL];
2417 }
2418 if( ipos < (*rhs).size() )
2419 v_[ipos] += (*rhs)[ipos];
2420 }
2421 //*************************************************************************************************
2422
2423
2424 //*************************************************************************************************
2425 /*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
2426 //
2427 // \param rhs The right-hand side dense vector to be added.
2428 // \return void
2429 //
2430 // This function must \b NOT be called explicitly! It is used internally for the performance
2431 // optimized evaluation of expression templates. Calling this function explicitly might result
2432 // in erroneous results and/or in compilation errors. Instead of using this function use the
2433 // assignment operator.
2434 */
2435 template< typename Type // Data type of the vector
2436 , AlignmentFlag AF // Alignment flag
2437 , PaddingFlag PF // Padding flag
2438 , bool TF // Transpose flag
2439 , typename Tag // Type tag
2440 , typename RT > // Result type
2441 template< typename VT > // Type of the right-hand side dense vector
2442 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::addAssign( const DenseVector<VT,TF>& rhs )
2443 -> EnableIf_t< VectorizedAddAssign_v<VT> >
2444 {
2445 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2446
2447 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2448
2449 const size_t ipos( prevMultiple( size_, SIMDSIZE ) );
2450 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2451
2452 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
2453 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
2454
2455 size_t i( 0UL );
2456 ConstIterator_t<VT> it( (*rhs).begin() );
2457
2458 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
2459 store( i , load(i ) + it.load() ); it += SIMDSIZE;
2460 store( i+SIMDSIZE , load(i+SIMDSIZE ) + it.load() ); it += SIMDSIZE;
2461 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) + it.load() ); it += SIMDSIZE;
2462 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) + it.load() ); it += SIMDSIZE;
2463 }
2464 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
2465 store( i, load(i) + it.load() );
2466 }
2467 for( ; i<size_; ++i, ++it ) {
2468 v_[i] += *it;
2469 }
2470 }
2471 //*************************************************************************************************
2472
2473
2474 //*************************************************************************************************
2475 /*!\brief Default implementation of the addition assignment of a sparse vector.
2476 //
2477 // \param rhs The right-hand side sparse vector to be added.
2478 // \return void
2479 //
2480 // This function must \b NOT be called explicitly! It is used internally for the performance
2481 // optimized evaluation of expression templates. Calling this function explicitly might result
2482 // in erroneous results and/or in compilation errors. Instead of using this function use the
2483 // assignment operator.
2484 */
2485 template< typename Type // Data type of the vector
2486 , AlignmentFlag AF // Alignment flag
2487 , PaddingFlag PF // Padding flag
2488 , bool TF // Transpose flag
2489 , typename Tag // Type tag
2490 , typename RT > // Result type
2491 template< typename VT > // Type of the right-hand side sparse vector
addAssign(const SparseVector<VT,TF> & rhs)2492 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::addAssign( const SparseVector<VT,TF>& rhs )
2493 {
2494 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2495
2496 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2497 v_[element->index()] += element->value();
2498 }
2499 //*************************************************************************************************
2500
2501
2502 //*************************************************************************************************
2503 /*!\brief Default implementation of the subtraction assignment of a dense vector.
2504 //
2505 // \param rhs The right-hand side dense vector to be subtracted.
2506 // \return void
2507 //
2508 // This function must \b NOT be called explicitly! It is used internally for the performance
2509 // optimized evaluation of expression templates. Calling this function explicitly might result
2510 // in erroneous results and/or in compilation errors. Instead of using this function use the
2511 // assignment operator.
2512 */
2513 template< typename Type // Data type of the vector
2514 , AlignmentFlag AF // Alignment flag
2515 , PaddingFlag PF // Padding flag
2516 , bool TF // Transpose flag
2517 , typename Tag // Type tag
2518 , typename RT > // Result type
2519 template< typename VT > // Type of the right-hand side dense vector
2520 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::subAssign( const DenseVector<VT,TF>& rhs )
2521 -> DisableIf_t< VectorizedSubAssign_v<VT> >
2522 {
2523 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2524
2525 const size_t ipos( prevMultiple( size_, 2UL ) );
2526 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2527
2528 for( size_t i=0UL; i<ipos; i+=2UL ) {
2529 v_[i ] -= (*rhs)[i ];
2530 v_[i+1UL] -= (*rhs)[i+1UL];
2531 }
2532 if( ipos < (*rhs).size() )
2533 v_[ipos] -= (*rhs)[ipos];
2534 }
2535 //*************************************************************************************************
2536
2537
2538 //*************************************************************************************************
2539 /*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
2540 //
2541 // \param rhs The right-hand side dense vector to be subtracted.
2542 // \return void
2543 //
2544 // This function must \b NOT be called explicitly! It is used internally for the performance
2545 // optimized evaluation of expression templates. Calling this function explicitly might result
2546 // in erroneous results and/or in compilation errors. Instead of using this function use the
2547 // assignment operator.
2548 */
2549 template< typename Type // Data type of the vector
2550 , AlignmentFlag AF // Alignment flag
2551 , PaddingFlag PF // Padding flag
2552 , bool TF // Transpose flag
2553 , typename Tag // Type tag
2554 , typename RT > // Result type
2555 template< typename VT > // Type of the right-hand side dense vector
2556 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::subAssign( const DenseVector<VT,TF>& rhs )
2557 -> EnableIf_t< VectorizedSubAssign_v<VT> >
2558 {
2559 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2560
2561 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2562
2563 const size_t ipos( prevMultiple( size_, SIMDSIZE ) );
2564 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2565
2566 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
2567 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
2568
2569 size_t i( 0UL );
2570 ConstIterator_t<VT> it( (*rhs).begin() );
2571
2572 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
2573 store( i , load(i ) - it.load() ); it += SIMDSIZE;
2574 store( i+SIMDSIZE , load(i+SIMDSIZE ) - it.load() ); it += SIMDSIZE;
2575 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) - it.load() ); it += SIMDSIZE;
2576 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) - it.load() ); it += SIMDSIZE;
2577 }
2578 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
2579 store( i, load(i) - it.load() );
2580 }
2581 for( ; i<size_; ++i, ++it ) {
2582 v_[i] -= *it;
2583 }
2584 }
2585 //*************************************************************************************************
2586
2587
2588 //*************************************************************************************************
2589 /*!\brief Default implementation of the subtraction assignment of a sparse vector.
2590 //
2591 // \param rhs The right-hand side sparse vector to be subtracted.
2592 // \return void
2593 //
2594 // This function must \b NOT be called explicitly! It is used internally for the performance
2595 // optimized evaluation of expression templates. Calling this function explicitly might result
2596 // in erroneous results and/or in compilation errors. Instead of using this function use the
2597 // assignment operator.
2598 */
2599 template< typename Type // Data type of the vector
2600 , AlignmentFlag AF // Alignment flag
2601 , PaddingFlag PF // Padding flag
2602 , bool TF // Transpose flag
2603 , typename Tag // Type tag
2604 , typename RT > // Result type
2605 template< typename VT > // Type of the right-hand side sparse vector
subAssign(const SparseVector<VT,TF> & rhs)2606 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::subAssign( const SparseVector<VT,TF>& rhs )
2607 {
2608 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2609
2610 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2611 v_[element->index()] -= element->value();
2612 }
2613 //*************************************************************************************************
2614
2615
2616 //*************************************************************************************************
2617 /*!\brief Default implementation of the multiplication assignment of a dense vector.
2618 //
2619 // \param rhs The right-hand side dense vector to be multiplied.
2620 // \return void
2621 //
2622 // This function must \b NOT be called explicitly! It is used internally for the performance
2623 // optimized evaluation of expression templates. Calling this function explicitly might result
2624 // in erroneous results and/or in compilation errors. Instead of using this function use the
2625 // assignment operator.
2626 */
2627 template< typename Type // Data type of the vector
2628 , AlignmentFlag AF // Alignment flag
2629 , PaddingFlag PF // Padding flag
2630 , bool TF // Transpose flag
2631 , typename Tag // Type tag
2632 , typename RT > // Result type
2633 template< typename VT > // Type of the right-hand side dense vector
2634 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::multAssign( const DenseVector<VT,TF>& rhs )
2635 -> DisableIf_t< VectorizedMultAssign_v<VT> >
2636 {
2637 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2638
2639 const size_t ipos( prevMultiple( size_, 2UL ) );
2640 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2641
2642 for( size_t i=0UL; i<ipos; i+=2UL ) {
2643 v_[i ] *= (*rhs)[i ];
2644 v_[i+1UL] *= (*rhs)[i+1UL];
2645 }
2646 if( ipos < (*rhs).size() )
2647 v_[ipos] *= (*rhs)[ipos];
2648 }
2649 //*************************************************************************************************
2650
2651
2652 //*************************************************************************************************
2653 /*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
2654 //
2655 // \param rhs The right-hand side dense vector to be multiplied.
2656 // \return void
2657 //
2658 // This function must \b NOT be called explicitly! It is used internally for the performance
2659 // optimized evaluation of expression templates. Calling this function explicitly might result
2660 // in erroneous results and/or in compilation errors. Instead of using this function use the
2661 // assignment operator.
2662 */
2663 template< typename Type // Data type of the vector
2664 , AlignmentFlag AF // Alignment flag
2665 , PaddingFlag PF // Padding flag
2666 , bool TF // Transpose flag
2667 , typename Tag // Type tag
2668 , typename RT > // Result type
2669 template< typename VT > // Type of the right-hand side dense vector
2670 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::multAssign( const DenseVector<VT,TF>& rhs )
2671 -> EnableIf_t< VectorizedMultAssign_v<VT> >
2672 {
2673 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2674
2675 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2676
2677 const size_t ipos( prevMultiple( size_, SIMDSIZE ) );
2678 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2679
2680 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
2681 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
2682
2683 size_t i( 0UL );
2684 ConstIterator_t<VT> it( (*rhs).begin() );
2685
2686 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
2687 store( i , load(i ) * it.load() ); it += SIMDSIZE;
2688 store( i+SIMDSIZE , load(i+SIMDSIZE ) * it.load() ); it += SIMDSIZE;
2689 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) * it.load() ); it += SIMDSIZE;
2690 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) * it.load() ); it += SIMDSIZE;
2691 }
2692 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
2693 store( i, load(i) * it.load() );
2694 }
2695 for( ; i<size_; ++i, ++it ) {
2696 v_[i] *= *it;
2697 }
2698 }
2699 //*************************************************************************************************
2700
2701
2702 //*************************************************************************************************
2703 /*!\brief Default implementation of the multiplication assignment of a sparse vector.
2704 //
2705 // \param rhs The right-hand side sparse vector to be multiplied.
2706 // \return void
2707 //
2708 // This function must \b NOT be called explicitly! It is used internally for the performance
2709 // optimized evaluation of expression templates. Calling this function explicitly might result
2710 // in erroneous results and/or in compilation errors. Instead of using this function use the
2711 // assignment operator.
2712 */
2713 template< typename Type // Data type of the vector
2714 , AlignmentFlag AF // Alignment flag
2715 , PaddingFlag PF // Padding flag
2716 , bool TF // Transpose flag
2717 , typename Tag // Type tag
2718 , typename RT > // Result type
2719 template< typename VT > // Type of the right-hand side sparse vector
multAssign(const SparseVector<VT,TF> & rhs)2720 inline void CustomVector<Type,AF,PF,TF,Tag,RT>::multAssign( const SparseVector<VT,TF>& rhs )
2721 {
2722 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2723
2724 const ResultType tmp( serial( *this ) );
2725
2726 reset();
2727
2728 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2729 v_[element->index()] = tmp[element->index()] * element->value();
2730 }
2731 //*************************************************************************************************
2732
2733
2734 //*************************************************************************************************
2735 /*!\brief Default implementation of the division assignment of a dense vector.
2736 //
2737 // \param rhs The right-hand side dense vector divisor.
2738 // \return void
2739 //
2740 // This function must \b NOT be called explicitly! It is used internally for the performance
2741 // optimized evaluation of expression templates. Calling this function explicitly might result
2742 // in erroneous results and/or in compilation errors. Instead of using this function use the
2743 // assignment operator.
2744 */
2745 template< typename Type // Data type of the vector
2746 , AlignmentFlag AF // Alignment flag
2747 , PaddingFlag PF // Padding flag
2748 , bool TF // Transpose flag
2749 , typename Tag // Type tag
2750 , typename RT > // Result type
2751 template< typename VT > // Type of the right-hand side dense vector
2752 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::divAssign( const DenseVector<VT,TF>& rhs )
2753 -> DisableIf_t< VectorizedDivAssign_v<VT> >
2754 {
2755 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2756
2757 const size_t ipos( prevMultiple( size_, 2UL ) );
2758 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2759
2760 for( size_t i=0UL; i<ipos; i+=2UL ) {
2761 v_[i ] /= (*rhs)[i ];
2762 v_[i+1UL] /= (*rhs)[i+1UL];
2763 }
2764 if( ipos < (*rhs).size() )
2765 v_[ipos] /= (*rhs)[ipos];
2766 }
2767 //*************************************************************************************************
2768
2769
2770 //*************************************************************************************************
2771 /*!\brief SIMD optimized implementation of the division assignment of a dense vector.
2772 //
2773 // \param rhs The right-hand side dense vector divisor.
2774 // \return void
2775 //
2776 // This function must \b NOT be called explicitly! It is used internally for the performance
2777 // optimized evaluation of expression templates. Calling this function explicitly might result
2778 // in erroneous results and/or in compilation errors. Instead of using this function use the
2779 // assignment operator.
2780 */
2781 template< typename Type // Data type of the vector
2782 , AlignmentFlag AF // Alignment flag
2783 , PaddingFlag PF // Padding flag
2784 , bool TF // Transpose flag
2785 , typename Tag // Type tag
2786 , typename RT > // Result type
2787 template< typename VT > // Type of the right-hand side dense vector
2788 inline auto CustomVector<Type,AF,PF,TF,Tag,RT>::divAssign( const DenseVector<VT,TF>& rhs )
2789 -> EnableIf_t< VectorizedDivAssign_v<VT> >
2790 {
2791 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2792
2793 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
2794
2795 const size_t ipos( prevMultiple( size_, SIMDSIZE ) );
2796 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
2797
2798 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
2799 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
2800
2801 size_t i( 0UL );
2802 ConstIterator_t<VT> it( (*rhs).begin() );
2803
2804 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
2805 store( i , load(i ) / it.load() ); it += SIMDSIZE;
2806 store( i+SIMDSIZE , load(i+SIMDSIZE ) / it.load() ); it += SIMDSIZE;
2807 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) / it.load() ); it += SIMDSIZE;
2808 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) / it.load() ); it += SIMDSIZE;
2809 }
2810 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
2811 store( i, load(i) / it.load() );
2812 }
2813 for( ; i<size_; ++i, ++it ) {
2814 v_[i] /= *it;
2815 }
2816 }
2817 //*************************************************************************************************
2818
2819
2820
2821
2822
2823
2824
2825
2826 //=================================================================================================
2827 //
2828 // CLASS TEMPLATE SPECIALIZATION FOR PADDED VECTORS
2829 //
2830 //=================================================================================================
2831
2832 //*************************************************************************************************
2833 /*! \cond BLAZE_INTERNAL */
2834 /*!\brief Specialization of CustomVector for padded vectors.
2835 // \ingroup custom_vector
2836 //
2837 // This specialization of CustomVector adapts the class template to the requirements of padded
2838 // vectors.
2839 */
2840 template< typename Type // Data type of the vector
2841 , AlignmentFlag AF // Alignment flag
2842 , bool TF // Transpose flag
2843 , typename Tag // Type tag
2844 , typename RT > // Result type
2845 class CustomVector<Type,AF,padded,TF,Tag,RT>
2846 : public DenseVector< CustomVector<Type,AF,padded,TF,Tag,RT>, TF >
2847 {
2848 public:
2849 //**Type definitions****************************************************************************
2850 using This = CustomVector<Type,AF,padded,TF,Tag,RT>; //!< Type of this CustomVector instance.
2851 using BaseType = DenseVector<This,TF>; //!< Base type of this CustomVector instance.
2852
2853 //! Result type for expression template evaluations.
2854 using ResultType = RT;
2855
2856 //! Transpose type for expression template evaluations.
2857 using TransposeType = CustomTransposeType_t<RT>;
2858
2859 using ElementType = Type; //!< Type of the vector elements.
2860 using SIMDType = SIMDTrait_t<ElementType>; //!< SIMD type of the vector elements.
2861 using TagType = Tag; //!< Tag type of this CustomVector instance.
2862 using ReturnType = const Type&; //!< Return type for expression template evaluations
2863 using CompositeType = const CustomVector&; //!< Data type for composite expression templates.
2864
2865 using Reference = Type&; //!< Reference to a non-constant vector value.
2866 using ConstReference = const Type&; //!< Reference to a constant vector value.
2867 using Pointer = Type*; //!< Pointer to a non-constant vector value.
2868 using ConstPointer = const Type*; //!< Pointer to a constant vector value.
2869
2870 using Iterator = DenseIterator<Type,AF>; //!< Iterator over non-constant elements.
2871 using ConstIterator = DenseIterator<const Type,AF>; //!< Iterator over constant elements.
2872 //**********************************************************************************************
2873
2874 //**Rebind struct definition********************************************************************
2875 /*!\brief Rebind mechanism to obtain a CustomVector with different data/element type.
2876 */
2877 template< typename NewType > // Data type of the other vector
2878 struct Rebind {
2879 using RRT = Rebind_t< RT, RemoveConst_t<NewType> >; //!< The rebound result type.
2880 using Other = CustomVector<NewType,AF,padded,TF,Tag,RRT>; //!< The type of the other CustomVector.
2881 };
2882 //**********************************************************************************************
2883
2884 //**Resize struct definition********************************************************************
2885 /*!\brief Resize mechanism to obtain a CustomVector with a different fixed number of elements.
2886 */
2887 template< size_t NewN > // Number of elements of the other vector
2888 struct Resize {
2889 using RRT = Resize_t<RT,NewN>; //!< The resized result type.
2890 using Other = CustomVector<Type,AF,padded,TF,Tag,RRT>; //!< The type of the other CustomVector.
2891 };
2892 //**********************************************************************************************
2893
2894 //**Compilation flags***************************************************************************
2895 //! Compilation flag for SIMD optimization.
2896 /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
2897 in can be optimized via SIMD operations. In case the element type of the vector is a
2898 vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
2899 it is set to \a false. */
2900 static constexpr bool simdEnabled = IsVectorizable_v<Type>;
2901
2902 //! Compilation flag for SMP assignments.
2903 /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
2904 (shared memory parallel) assignments (both on the left-hand and right-hand side of the
2905 assignment). */
2906 static constexpr bool smpAssignable = !IsSMPAssignable_v<Type>;
2907 //**********************************************************************************************
2908
2909 //**Constructors********************************************************************************
2910 /*!\name Constructors */
2911 //@{
2912 inline CustomVector();
2913 inline CustomVector( Type* ptr, size_t n, size_t nn );
2914 inline CustomVector( const CustomVector& v );
2915 inline CustomVector( CustomVector&& v ) noexcept;
2916 //@}
2917 //**********************************************************************************************
2918
2919 //**Destructor**********************************************************************************
2920 /*!\name Destructor */
2921 //@{
2922 inline ~CustomVector();
2923 //@}
2924 //**********************************************************************************************
2925
2926 //**Data access functions***********************************************************************
2927 /*!\name Data access functions */
2928 //@{
2929 inline Reference operator[]( size_t index ) noexcept;
2930 inline ConstReference operator[]( size_t index ) const noexcept;
2931 inline Reference at( size_t index );
2932 inline ConstReference at( size_t index ) const;
2933 inline Pointer data () noexcept;
2934 inline ConstPointer data () const noexcept;
2935 inline Iterator begin () noexcept;
2936 inline ConstIterator begin () const noexcept;
2937 inline ConstIterator cbegin() const noexcept;
2938 inline Iterator end () noexcept;
2939 inline ConstIterator end () const noexcept;
2940 inline ConstIterator cend () const noexcept;
2941 //@}
2942 //**********************************************************************************************
2943
2944 //**Assignment operators************************************************************************
2945 /*!\name Assignment operators */
2946 //@{
2947 inline CustomVector& operator=( const Type& rhs );
2948 inline CustomVector& operator=( initializer_list<Type> list );
2949
2950 template< typename Other, size_t Dim >
2951 inline CustomVector& operator=( const Other (&array)[Dim] );
2952
2953 template< typename Other, size_t Dim >
2954 inline CustomVector& operator=( const std::array<Other,Dim>& array );
2955
2956 inline CustomVector& operator=( const CustomVector& rhs );
2957 inline CustomVector& operator=( CustomVector&& rhs ) noexcept;
2958
2959 template< typename VT > inline CustomVector& operator= ( const Vector<VT,TF>& rhs );
2960 template< typename VT > inline CustomVector& operator+=( const Vector<VT,TF>& rhs );
2961 template< typename VT > inline CustomVector& operator-=( const Vector<VT,TF>& rhs );
2962 template< typename VT > inline CustomVector& operator*=( const Vector<VT,TF>& rhs );
2963 template< typename VT > inline CustomVector& operator/=( const DenseVector<VT,TF>& rhs );
2964 template< typename VT > inline CustomVector& operator%=( const Vector<VT,TF>& rhs );
2965 //@}
2966 //**********************************************************************************************
2967
2968 //**Utility functions***************************************************************************
2969 /*!\name Utility functions */
2970 //@{
2971 inline size_t size() const noexcept;
2972 inline size_t spacing() const noexcept;
2973 inline size_t capacity() const noexcept;
2974 inline size_t nonZeros() const;
2975 inline void reset();
2976 inline void clear();
2977 inline void swap( CustomVector& v ) noexcept;
2978 //@}
2979 //**********************************************************************************************
2980
2981 //**Numeric functions***************************************************************************
2982 /*!\name Numeric functions */
2983 //@{
2984 template< typename Other > inline CustomVector& scale( const Other& scalar );
2985 //@}
2986 //**********************************************************************************************
2987
2988 //**Resource management functions***************************************************************
2989 /*!\name Resource management functions */
2990 //@{
2991 inline void reset( Type* ptr, size_t n, size_t nn );
2992 //@}
2993 //**********************************************************************************************
2994
2995 private:
2996 //**********************************************************************************************
2997 //! Helper variable template for the explicit application of the SFINAE principle.
2998 template< typename VT >
2999 static constexpr bool VectorizedAssign_v =
3000 ( useOptimizedKernels &&
3001 simdEnabled && VT::simdEnabled &&
3002 IsSIMDCombinable_v< Type, ElementType_t<VT> > );
3003 //**********************************************************************************************
3004
3005 //**********************************************************************************************
3006 //! Helper variable template for the explicit application of the SFINAE principle.
3007 template< typename VT >
3008 static constexpr bool VectorizedAddAssign_v =
3009 ( VectorizedAssign_v<VT> &&
3010 HasSIMDAdd_v< Type, ElementType_t<VT> > );
3011 //**********************************************************************************************
3012
3013 //**********************************************************************************************
3014 //! Helper variable template for the explicit application of the SFINAE principle.
3015 template< typename VT >
3016 static constexpr bool VectorizedSubAssign_v =
3017 ( VectorizedAssign_v<VT> &&
3018 HasSIMDSub_v< Type, ElementType_t<VT> > );
3019 //**********************************************************************************************
3020
3021 //**********************************************************************************************
3022 //! Helper variable template for the explicit application of the SFINAE principle.
3023 template< typename VT >
3024 static constexpr bool VectorizedMultAssign_v =
3025 ( VectorizedAssign_v<VT> &&
3026 HasSIMDMult_v< Type, ElementType_t<VT> > );
3027 //**********************************************************************************************
3028
3029 //**********************************************************************************************
3030 //! Helper variable template for the explicit application of the SFINAE principle.
3031 template< typename VT >
3032 static constexpr bool VectorizedDivAssign_v =
3033 ( VectorizedAssign_v<VT> &&
3034 HasSIMDDiv_v< Type, ElementType_t<VT> > );
3035 //**********************************************************************************************
3036
3037 //**SIMD properties*****************************************************************************
3038 //! The number of elements packed within a single SIMD element.
3039 static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
3040 //**********************************************************************************************
3041
3042 public:
3043 //**Expression template evaluation functions****************************************************
3044 /*!\name Expression template evaluation functions */
3045 //@{
3046 template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
3047 template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
3048
3049 inline bool isAligned () const noexcept;
3050 inline bool canSMPAssign() const noexcept;
3051
3052 BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
3053 BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
3054 BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
3055
3056 BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
3057 BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
3058 BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
3059 BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
3060
3061 template< typename VT >
3062 inline auto assign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedAssign_v<VT> >;
3063
3064 template< typename VT >
3065 inline auto assign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedAssign_v<VT> >;
3066
3067 template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
3068
3069 template< typename VT >
3070 inline auto addAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<VT> >;
3071
3072 template< typename VT >
3073 inline auto addAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<VT> >;
3074
3075 template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
3076
3077 template< typename VT >
3078 inline auto subAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<VT> >;
3079
3080 template< typename VT >
3081 inline auto subAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<VT> >;
3082
3083 template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
3084
3085 template< typename VT >
3086 inline auto multAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedMultAssign_v<VT> >;
3087
3088 template< typename VT >
3089 inline auto multAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedMultAssign_v<VT> >;
3090
3091 template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
3092
3093 template< typename VT >
3094 inline auto divAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedDivAssign_v<VT> >;
3095
3096 template< typename VT >
3097 inline auto divAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedDivAssign_v<VT> >;
3098 //@}
3099 //**********************************************************************************************
3100
3101 private:
3102 //**Member variables****************************************************************************
3103 /*!\name Member variables */
3104 //@{
3105 size_t size_; //!< The size/dimension of the custom vector.
3106 size_t capacity_; //!< The maximum capacity of the custom vector.
3107 Type* v_; //!< The custom array of elements.
3108 /*!< Access to the array of elements is gained via the
3109 subscript operator. The order of the elements is
3110 \f[\left(\begin{array}{*{5}{c}}
3111 0 & 1 & 2 & \cdots & N-1 \\
3112 \end{array}\right)\f] */
3113 //@}
3114 //**********************************************************************************************
3115
3116 //**Compile time checks*************************************************************************
3117 BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE( Type );
3118 BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
3119 BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE( Type );
3120 //**********************************************************************************************
3121 };
3122 /*! \endcond */
3123 //*************************************************************************************************
3124
3125
3126
3127
3128 //=================================================================================================
3129 //
3130 // CONSTRUCTORS
3131 //
3132 //=================================================================================================
3133
3134 //*************************************************************************************************
3135 /*! \cond BLAZE_INTERNAL */
3136 /*!\brief The default constructor for CustomVector.
3137 */
3138 template< typename Type // Data type of the vector
3139 , AlignmentFlag AF // Alignment flag
3140 , bool TF // Transpose flag
3141 , typename Tag // Type tag
3142 , typename RT > // Result type
CustomVector()3143 inline CustomVector<Type,AF,padded,TF,Tag,RT>::CustomVector()
3144 : size_ ( 0UL ) // The size/dimension of the vector
3145 , capacity_( 0UL ) // The maximum capacity of the vector
3146 , v_ ( nullptr ) // The custom array of elements
3147 {}
3148 /*! \endcond */
3149 //*************************************************************************************************
3150
3151
3152 //*************************************************************************************************
3153 /*! \cond BLAZE_INTERNAL */
3154 /*!\brief Constructor for a padded custom vector of size \a n and capacity \a nn.
3155 //
3156 // \param ptr The array of elements to be used by the vector.
3157 // \param n The number of array elements to be used by the custom vector.
3158 // \param nn The maximum size of the given array.
3159 // \exception std::invalid_argument Invalid setup of custom vector.
3160 //
3161 // This constructor creates a padded custom vector of size \a n and capacity \a nn. The
3162 // construction of the vector fails if ...
3163 //
3164 // - ... the passed pointer is \c nullptr;
3165 // - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
3166 // aligned according to the available instruction set (SSE, AVX, ...);
3167 // - ... the specified capacity \a nn is insufficient for the given data type \a Type and
3168 // the available instruction set.
3169 //
3170 // In all failure cases a \a std::invalid_argument exception is thrown.
3171 //
3172 // \note The custom vector does NOT take responsibility for the given array of elements!
3173 */
3174 template< typename Type // Data type of the vector
3175 , AlignmentFlag AF // Alignment flag
3176 , bool TF // Transpose flag
3177 , typename Tag // Type tag
3178 , typename RT > // Result type
CustomVector(Type * ptr,size_t n,size_t nn)3179 inline CustomVector<Type,AF,padded,TF,Tag,RT>::CustomVector( Type* ptr, size_t n, size_t nn )
3180 : size_ ( n ) // The size/dimension of the vector
3181 , capacity_( nn ) // The maximum capacity of the vector
3182 , v_ ( ptr ) // The custom array of elements
3183 {
3184 using blaze::clear;
3185
3186 if( ptr == nullptr ) {
3187 BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" );
3188 }
3189
3190 if( AF && !checkAlignment( ptr ) ) {
3191 BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" );
3192 }
3193
3194 if( IsVectorizable_v<Type> && capacity_ < nextMultiple<size_t>( size_, SIMDSIZE ) ) {
3195 BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded vector" );
3196 }
3197
3198 if( IsVectorizable_v<Type> ) {
3199 for( size_t i=size_; i<capacity_; ++i )
3200 clear( v_[i] );
3201 }
3202 }
3203 /*! \endcond */
3204 //*************************************************************************************************
3205
3206
3207 //*************************************************************************************************
3208 /*! \cond BLAZE_INTERNAL */
3209 /*!\brief The copy constructor for CustomVector.
3210 //
3211 // \param v Vector to be copied.
3212 //
3213 // The copy constructor initializes the custom vector as an exact copy of the given custom vector.
3214 */
3215 template< typename Type // Data type of the vector
3216 , AlignmentFlag AF // Alignment flag
3217 , bool TF // Transpose flag
3218 , typename Tag // Type tag
3219 , typename RT > // Result type
CustomVector(const CustomVector & v)3220 inline CustomVector<Type,AF,padded,TF,Tag,RT>::CustomVector( const CustomVector& v )
3221 : size_ ( v.size_ ) // The size/dimension of the vector
3222 , capacity_( v.capacity_ ) // The maximum capacity of the vector
3223 , v_ ( v.v_ ) // The custom array of elements
3224 {}
3225 /*! \endcond */
3226 //*************************************************************************************************
3227
3228
3229 //*************************************************************************************************
3230 /*! \cond BLAZE_INTERNAL */
3231 /*!\brief The move constructor for CustomVector.
3232 //
3233 // \param v The vector to be moved into this instance.
3234 */
3235 template< typename Type // Data type of the vector
3236 , AlignmentFlag AF // Alignment flag
3237 , bool TF // Transpose flag
3238 , typename Tag // Type tag
3239 , typename RT > // Result type
CustomVector(CustomVector && v)3240 inline CustomVector<Type,AF,padded,TF,Tag,RT>::CustomVector( CustomVector&& v ) noexcept
3241 : size_ ( v.size_ ) // The size/dimension of the vector
3242 , capacity_( v.capacity_ ) // The maximum capacity of the vector
3243 , v_ ( v.v_ ) // The custom array of elements
3244 {
3245 v.size_ = 0UL;
3246 v.capacity_ = 0UL;
3247 v.v_ = nullptr;
3248
3249 BLAZE_INTERNAL_ASSERT( v.data() == nullptr, "Invalid data reference detected" );
3250 }
3251 /*! \endcond */
3252 //*************************************************************************************************
3253
3254
3255
3256
3257 //=================================================================================================
3258 //
3259 // DESTRUCTOR
3260 //
3261 //=================================================================================================
3262
3263 //*************************************************************************************************
3264 /*! \cond BLAZE_INTERNAL */
3265 /*!\brief The destructor for CustomVector.
3266 */
3267 template< typename Type // Data type of the vector
3268 , AlignmentFlag AF // Alignment flag
3269 , bool TF // Transpose flag
3270 , typename Tag // Type tag
3271 , typename RT > // Result type
~CustomVector()3272 inline CustomVector<Type,AF,padded,TF,Tag,RT>::~CustomVector()
3273 {
3274 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( RT );
3275 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( RT, TF );
3276 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<RT> );
3277 BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( RT );
3278 BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE( RT );
3279 }
3280 /*! \endcond */
3281 //*************************************************************************************************
3282
3283
3284
3285
3286 //=================================================================================================
3287 //
3288 // DATA ACCESS FUNCTIONS
3289 //
3290 //=================================================================================================
3291
3292 //*************************************************************************************************
3293 /*! \cond BLAZE_INTERNAL */
3294 /*!\brief Subscript operator for the direct access to the vector elements.
3295 //
3296 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
3297 // \return Reference to the accessed value.
3298 //
3299 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
3300 // the at() function is guaranteed to perform a check of the given access index.
3301 */
3302 template< typename Type // Data type of the vector
3303 , AlignmentFlag AF // Alignment flag
3304 , bool TF // Transpose flag
3305 , typename Tag // Type tag
3306 , typename RT > // Result type
3307 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::Reference
3308 CustomVector<Type,AF,padded,TF,Tag,RT>::operator[]( size_t index ) noexcept
3309 {
3310 BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
3311 return v_[index];
3312 }
3313 /*! \endcond */
3314 //*************************************************************************************************
3315
3316
3317 //*************************************************************************************************
3318 /*! \cond BLAZE_INTERNAL */
3319 /*!\brief Subscript operator for the direct access to the vector elements.
3320 //
3321 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
3322 // \return Reference to the accessed value.
3323 //
3324 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
3325 // the at() function is guaranteed to perform a check of the given access index.
3326 */
3327 template< typename Type // Data type of the vector
3328 , AlignmentFlag AF // Alignment flag
3329 , bool TF // Transpose flag
3330 , typename Tag // Type tag
3331 , typename RT > // Result type
3332 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::ConstReference
3333 CustomVector<Type,AF,padded,TF,Tag,RT>::operator[]( size_t index ) const noexcept
3334 {
3335 BLAZE_USER_ASSERT( index < size_, "Invalid vector access index" );
3336 return v_[index];
3337 }
3338 /*! \endcond */
3339 //*************************************************************************************************
3340
3341
3342 //*************************************************************************************************
3343 /*! \cond BLAZE_INTERNAL */
3344 /*!\brief Checked access to the vector elements.
3345 //
3346 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
3347 // \return Reference to the accessed value.
3348 // \exception std::out_of_range Invalid vector access index.
3349 //
3350 // In contrast to the subscript operator this function always performs a check of the given
3351 // access index.
3352 */
3353 template< typename Type // Data type of the vector
3354 , AlignmentFlag AF // Alignment flag
3355 , bool TF // Transpose flag
3356 , typename Tag // Type tag
3357 , typename RT > // Result type
3358 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::Reference
at(size_t index)3359 CustomVector<Type,AF,padded,TF,Tag,RT>::at( size_t index )
3360 {
3361 if( index >= size_ ) {
3362 BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
3363 }
3364 return (*this)[index];
3365 }
3366 /*! \endcond */
3367 //*************************************************************************************************
3368
3369
3370 //*************************************************************************************************
3371 /*! \cond BLAZE_INTERNAL */
3372 /*!\brief Checked access to the vector elements.
3373 //
3374 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
3375 // \return Reference to the accessed value.
3376 // \exception std::out_of_range Invalid vector access index.
3377 //
3378 // In contrast to the subscript operator this function always performs a check of the given
3379 // access index.
3380 */
3381 template< typename Type // Data type of the vector
3382 , AlignmentFlag AF // Alignment flag
3383 , bool TF // Transpose flag
3384 , typename Tag // Type tag
3385 , typename RT > // Result type
3386 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::ConstReference
at(size_t index)3387 CustomVector<Type,AF,padded,TF,Tag,RT>::at( size_t index ) const
3388 {
3389 if( index >= size_ ) {
3390 BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
3391 }
3392 return (*this)[index];
3393 }
3394 /*! \endcond */
3395 //*************************************************************************************************
3396
3397
3398 //*************************************************************************************************
3399 /*! \cond BLAZE_INTERNAL */
3400 /*!\brief Low-level data access to the vector elements.
3401 //
3402 // \return Pointer to the internal element storage.
3403 //
3404 // This function returns a pointer to the internal storage of the custom vector.
3405 */
3406 template< typename Type // Data type of the vector
3407 , AlignmentFlag AF // Alignment flag
3408 , bool TF // Transpose flag
3409 , typename Tag // Type tag
3410 , typename RT > // Result type
3411 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::Pointer
data()3412 CustomVector<Type,AF,padded,TF,Tag,RT>::data() noexcept
3413 {
3414 return v_;
3415 }
3416 /*! \endcond */
3417 //*************************************************************************************************
3418
3419
3420 //*************************************************************************************************
3421 /*! \cond BLAZE_INTERNAL */
3422 /*!\brief Low-level data access to the vector elements.
3423 //
3424 // \return Pointer to the internal element storage.
3425 //
3426 // This function returns a pointer to the internal storage of the custom vector.
3427 */
3428 template< typename Type // Data type of the vector
3429 , AlignmentFlag AF // Alignment flag
3430 , bool TF // Transpose flag
3431 , typename Tag // Type tag
3432 , typename RT > // Result type
3433 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::ConstPointer
data()3434 CustomVector<Type,AF,padded,TF,Tag,RT>::data() const noexcept
3435 {
3436 return v_;
3437 }
3438 /*! \endcond */
3439 //*************************************************************************************************
3440
3441
3442 //*************************************************************************************************
3443 /*! \cond BLAZE_INTERNAL */
3444 /*!\brief Returns an iterator to the first element of the custom vector.
3445 //
3446 // \return Iterator to the first element of the custom vector.
3447 */
3448 template< typename Type // Data type of the vector
3449 , AlignmentFlag AF // Alignment flag
3450 , bool TF // Transpose flag
3451 , typename Tag // Type tag
3452 , typename RT > // Result type
3453 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::Iterator
begin()3454 CustomVector<Type,AF,padded,TF,Tag,RT>::begin() noexcept
3455 {
3456 return Iterator( v_ );
3457 }
3458 /*! \endcond */
3459 //*************************************************************************************************
3460
3461
3462 //*************************************************************************************************
3463 /*! \cond BLAZE_INTERNAL */
3464 /*!\brief Returns an iterator to the first element of the custom vector.
3465 //
3466 // \return Iterator to the first element of the custom vector.
3467 */
3468 template< typename Type // Data type of the vector
3469 , AlignmentFlag AF // Alignment flag
3470 , bool TF // Transpose flag
3471 , typename Tag // Type tag
3472 , typename RT > // Result type
3473 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::ConstIterator
begin()3474 CustomVector<Type,AF,padded,TF,Tag,RT>::begin() const noexcept
3475 {
3476 return ConstIterator( v_ );
3477 }
3478 /*! \endcond */
3479 //*************************************************************************************************
3480
3481
3482 //*************************************************************************************************
3483 /*! \cond BLAZE_INTERNAL */
3484 /*!\brief Returns an iterator to the first element of the custom vector.
3485 //
3486 // \return Iterator to the first element of the custom vector.
3487 */
3488 template< typename Type // Data type of the vector
3489 , AlignmentFlag AF // Alignment flag
3490 , bool TF // Transpose flag
3491 , typename Tag // Type tag
3492 , typename RT > // Result type
3493 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::ConstIterator
cbegin()3494 CustomVector<Type,AF,padded,TF,Tag,RT>::cbegin() const noexcept
3495 {
3496 return ConstIterator( v_ );
3497 }
3498 /*! \endcond */
3499 //*************************************************************************************************
3500
3501
3502 //*************************************************************************************************
3503 /*! \cond BLAZE_INTERNAL */
3504 /*!\brief Returns an iterator just past the last element of the custom vector.
3505 //
3506 // \return Iterator just past the last element of the custom vector.
3507 */
3508 template< typename Type // Data type of the vector
3509 , AlignmentFlag AF // Alignment flag
3510 , bool TF // Transpose flag
3511 , typename Tag // Type tag
3512 , typename RT > // Result type
3513 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::Iterator
end()3514 CustomVector<Type,AF,padded,TF,Tag,RT>::end() noexcept
3515 {
3516 return Iterator( v_+size_ );
3517 }
3518 /*! \endcond */
3519 //*************************************************************************************************
3520
3521
3522 //*************************************************************************************************
3523 /*! \cond BLAZE_INTERNAL */
3524 /*!\brief Returns an iterator just past the last element of the custom vector.
3525 //
3526 // \return Iterator just past the last element of the custom vector.
3527 */
3528 template< typename Type // Data type of the vector
3529 , AlignmentFlag AF // Alignment flag
3530 , bool TF // Transpose flag
3531 , typename Tag // Type tag
3532 , typename RT > // Result type
3533 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::ConstIterator
end()3534 CustomVector<Type,AF,padded,TF,Tag,RT>::end() const noexcept
3535 {
3536 return ConstIterator( v_+size_ );
3537 }
3538 /*! \endcond */
3539 //*************************************************************************************************
3540
3541
3542 //*************************************************************************************************
3543 /*! \cond BLAZE_INTERNAL */
3544 /*!\brief Returns an iterator just past the last element of the custom vector.
3545 //
3546 // \return Iterator just past the last element of the custom vector.
3547 */
3548 template< typename Type // Data type of the vector
3549 , AlignmentFlag AF // Alignment flag
3550 , bool TF // Transpose flag
3551 , typename Tag // Type tag
3552 , typename RT > // Result type
3553 inline typename CustomVector<Type,AF,padded,TF,Tag,RT>::ConstIterator
cend()3554 CustomVector<Type,AF,padded,TF,Tag,RT>::cend() const noexcept
3555 {
3556 return ConstIterator( v_+size_ );
3557 }
3558 /*! \endcond */
3559 //*************************************************************************************************
3560
3561
3562
3563
3564 //=================================================================================================
3565 //
3566 // ASSIGNMENT OPERATORS
3567 //
3568 //=================================================================================================
3569
3570 //*************************************************************************************************
3571 /*! \cond BLAZE_INTERNAL */
3572 /*!\brief Homogenous assignment to all vector elements.
3573 //
3574 // \param rhs Scalar value to be assigned to all vector elements.
3575 // \return Reference to the assigned vector.
3576 */
3577 template< typename Type // Data type of the vector
3578 , AlignmentFlag AF // Alignment flag
3579 , bool TF // Transpose flag
3580 , typename Tag // Type tag
3581 , typename RT > // Result type
3582 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3583 CustomVector<Type,AF,padded,TF,Tag,RT>::operator=( const Type& rhs )
3584 {
3585 for( size_t i=0UL; i<size_; ++i )
3586 v_[i] = rhs;
3587 return *this;
3588 }
3589 /*! \endcond */
3590 //*************************************************************************************************
3591
3592
3593 //*************************************************************************************************
3594 /*! \cond BLAZE_INTERNAL */
3595 /*!\brief List assignment to all vector elements.
3596 //
3597 // \param list The initializer list.
3598 // \exception std::invalid_argument Invalid assignment to custom vector.
3599 //
3600 // This assignment operator offers the option to directly assign to all elements of the vector
3601 // by means of an initializer list:
3602
3603 \code
3604 using blaze::CustomVector;
3605 using blaze::unaliged;
3606 using blaze::padded;
3607
3608 const int array[8] = { 1, 2, 3, 4, 0, 0, 0, 0 };
3609
3610 CustomVector<double,unaligned,padded> v( array, 4UL, 8UL );
3611 v = { 5, 6, 7 };
3612 \endcode
3613
3614 // The vector elements are assigned the values from the given initializer list. Missing values
3615 // are reset to their default state. Note that in case the size of the initializer list exceeds
3616 // the size of the vector, a \a std::invalid_argument exception is thrown.
3617 */
3618 template< typename Type // Data type of the vector
3619 , AlignmentFlag AF // Alignment flag
3620 , bool TF // Transpose flag
3621 , typename Tag // Type tag
3622 , typename RT > // Result type
3623 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3624 CustomVector<Type,AF,padded,TF,Tag,RT>::operator=( initializer_list<Type> list )
3625 {
3626 if( list.size() > size_ ) {
3627 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to custom vector" );
3628 }
3629
3630 std::fill( std::copy( list.begin(), list.end(), v_ ), v_+capacity_, Type() );
3631
3632 return *this;
3633 }
3634 /*! \endcond */
3635 //*************************************************************************************************
3636
3637
3638 //*************************************************************************************************
3639 /*! \cond BLAZE_INTERNAL */
3640 /*!\brief Array assignment to all vector elements.
3641 //
3642 // \param array Static array for the assignment.
3643 // \return Reference to the assigned vector.
3644 // \exception std::invalid_argument Invalid array size.
3645 //
3646 // This assignment operator offers the option to directly set all elements of the vector. The
3647 // following example demonstrates this by means of an unaligned, padded custom vector:
3648
3649 \code
3650 using blaze::CustomVector;
3651 using blaze::unaliged;
3652 using blaze::padded;
3653
3654 const int array[8] = { 1, 2, 3, 4, 0, 0, 0, 0 };
3655 const int init[4] = { 5, 6, 7 };
3656
3657 CustomVector<double,unaligned,padded> v( array, 4UL, 8UL );
3658 v = init;
3659 \endcode
3660
3661 // The vector is assigned the values from the given static array. Missing values are initialized
3662 // with default values (as e.g. the fourth element in the example). Note that the size of the
3663 // static array must match the size of the custom vector. Otherwise a \a std::invalid_argument
3664 // exception is thrown. Also note that after the assignment \a array will have the same entries
3665 // as \a init.
3666 */
3667 template< typename Type // Data type of the vector
3668 , AlignmentFlag AF // Alignment flag
3669 , bool TF // Transpose flag
3670 , typename Tag // Type tag
3671 , typename RT > // Result type
3672 template< typename Other // Data type of the static array
3673 , size_t Dim > // Dimension of the static array
3674 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3675 CustomVector<Type,AF,padded,TF,Tag,RT>::operator=( const Other (&array)[Dim] )
3676 {
3677 if( size_ != Dim ) {
3678 BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
3679 }
3680
3681 for( size_t i=0UL; i<Dim; ++i )
3682 v_[i] = array[i];
3683
3684 return *this;
3685 }
3686 /*! \endcond */
3687 //*************************************************************************************************
3688
3689
3690 //*************************************************************************************************
3691 /*! \cond BLAZE_INTERNAL */
3692 /*!\brief Array assignment to all vector elements.
3693 //
3694 // \param array The given std::array for the assignment.
3695 // \return Reference to the assigned vector.
3696 // \exception std::invalid_argument Invalid std::array size.
3697 //
3698 // This assignment operator offers the option to directly set all elements of the vector. The
3699 // following example demonstrates this by means of an unaligned, padded custom vector:
3700
3701 \code
3702 using blaze::CustomVector;
3703 using blaze::unaliged;
3704 using blaze::padded;
3705
3706 const int array[8] = { 1, 2, 3, 4, 0, 0, 0, 0 };
3707 const std::array<int,4UL> init{ 5, 6, 7 };
3708
3709 CustomVector<double,unaligned,padded> v( array, 4UL, 8UL );
3710 v = init;
3711 \endcode
3712
3713 // The vector is assigned the values from the given std::array. Missing values are initialized
3714 // with default values (as e.g. the fourth element in the example). Note that the size of the
3715 // std::array must match the size of the custom vector. Otherwise a \a std::invalid_argument
3716 // exception is thrown. Also note that after the assignment \a array will have the same entries
3717 // as \a init.
3718 */
3719 template< typename Type // Data type of the vector
3720 , AlignmentFlag AF // Alignment flag
3721 , bool TF // Transpose flag
3722 , typename Tag // Type tag
3723 , typename RT > // Result type
3724 template< typename Other // Data type of the std::array
3725 , size_t Dim > // Dimension of the std::array
3726 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3727 CustomVector<Type,AF,padded,TF,Tag,RT>::operator=( const std::array<Other,Dim>& array )
3728 {
3729 if( size_ != Dim ) {
3730 BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" );
3731 }
3732
3733 for( size_t i=0UL; i<Dim; ++i )
3734 v_[i] = array[i];
3735
3736 return *this;
3737 }
3738 /*! \endcond */
3739 //*************************************************************************************************
3740
3741
3742 //*************************************************************************************************
3743 /*! \cond BLAZE_INTERNAL */
3744 /*!\brief Copy assignment operator for CustomVector.
3745 //
3746 // \param rhs Vector to be copied.
3747 // \return Reference to the assigned vector.
3748 // \exception std::invalid_argument Vector sizes do not match.
3749 //
3750 // The vector is initialized as a copy of the given vector. In case the current sizes of the two
3751 // vectors don't match, a \a std::invalid_argument exception is thrown.
3752 */
3753 template< typename Type // Data type of the vector
3754 , AlignmentFlag AF // Alignment flag
3755 , bool TF // Transpose flag
3756 , typename Tag // Type tag
3757 , typename RT > // Result type
3758 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3759 CustomVector<Type,AF,padded,TF,Tag,RT>::operator=( const CustomVector& rhs )
3760 {
3761 if( rhs.size() != size_ ) {
3762 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
3763 }
3764
3765 smpAssign( *this, *rhs );
3766
3767 return *this;
3768 }
3769 /*! \endcond */
3770 //*************************************************************************************************
3771
3772
3773 //*************************************************************************************************
3774 /*! \cond BLAZE_INTERNAL */
3775 /*!\brief Move assignment operator for CustomVector.
3776 //
3777 // \param rhs The vector to be moved into this instance.
3778 // \return Reference to the assigned vector.
3779 */
3780 template< typename Type // Data type of the vector
3781 , AlignmentFlag AF // Alignment flag
3782 , bool TF // Transpose flag
3783 , typename Tag // Type tag
3784 , typename RT > // Result type
3785 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3786 CustomVector<Type,AF,padded,TF,Tag,RT>::operator=( CustomVector&& rhs ) noexcept
3787 {
3788 size_ = rhs.size_;
3789 capacity_ = rhs.capacity_;
3790 v_ = rhs.v_;
3791
3792 rhs.size_ = 0UL;
3793 rhs.capacity_ = 0UL;
3794 rhs.v_ = nullptr;
3795
3796 BLAZE_INTERNAL_ASSERT( rhs.data() == nullptr, "Invalid data reference detected" );
3797
3798 return *this;
3799 }
3800 /*! \endcond */
3801 //*************************************************************************************************
3802
3803
3804 //*************************************************************************************************
3805 /*! \cond BLAZE_INTERNAL */
3806 /*!\brief Assignment operator for different vectors.
3807 //
3808 // \param rhs Vector to be copied.
3809 // \return Reference to the assigned vector.
3810 // \exception std::invalid_argument Vector sizes do not match.
3811 //
3812 // The vector is initialized as a copy of the given vector. In case the current sizes of the two
3813 // vectors don't match, a \a std::invalid_argument exception is thrown.
3814 */
3815 template< typename Type // Data type of the vector
3816 , AlignmentFlag AF // Alignment flag
3817 , bool TF // Transpose flag
3818 , typename Tag // Type tag
3819 , typename RT > // Result type
3820 template< typename VT > // Type of the right-hand side vector
3821 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3822 CustomVector<Type,AF,padded,TF,Tag,RT>::operator=( const Vector<VT,TF>& rhs )
3823 {
3824 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
3825
3826 if( (*rhs).size() != size_ ) {
3827 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
3828 }
3829
3830 if( (*rhs).canAlias( this ) ) {
3831 const ResultType_t<VT> tmp( *rhs );
3832 smpAssign( *this, tmp );
3833 }
3834 else {
3835 if( IsSparseVector_v<VT> )
3836 reset();
3837 smpAssign( *this, *rhs );
3838 }
3839
3840 return *this;
3841 }
3842 /*! \endcond */
3843 //*************************************************************************************************
3844
3845
3846 //*************************************************************************************************
3847 /*! \cond BLAZE_INTERNAL */
3848 /*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
3849 //
3850 // \param rhs The right-hand side vector to be added to the vector.
3851 // \return Reference to the vector.
3852 // \exception std::invalid_argument Vector sizes do not match.
3853 //
3854 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
3855 // is thrown.
3856 */
3857 template< typename Type // Data type of the vector
3858 , AlignmentFlag AF // Alignment flag
3859 , bool TF // Transpose flag
3860 , typename Tag // Type tag
3861 , typename RT > // Result type
3862 template< typename VT > // Type of the right-hand side vector
3863 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3864 CustomVector<Type,AF,padded,TF,Tag,RT>::operator+=( const Vector<VT,TF>& rhs )
3865 {
3866 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
3867
3868 if( (*rhs).size() != size_ ) {
3869 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
3870 }
3871
3872 if( (*rhs).canAlias( this ) ) {
3873 const ResultType_t<VT> tmp( *rhs );
3874 smpAddAssign( *this, tmp );
3875 }
3876 else {
3877 smpAddAssign( *this, *rhs );
3878 }
3879
3880 return *this;
3881 }
3882 /*! \endcond */
3883 //*************************************************************************************************
3884
3885
3886 //*************************************************************************************************
3887 /*! \cond BLAZE_INTERNAL */
3888 /*!\brief Subtraction assignment operator for the subtraction of a vector
3889 // (\f$ \vec{a}-=\vec{b} \f$).
3890 //
3891 // \param rhs The right-hand side vector to be subtracted from the vector.
3892 // \return Reference to the vector.
3893 // \exception std::invalid_argument Vector sizes do not match.
3894 //
3895 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
3896 // is thrown.
3897 */
3898 template< typename Type // Data type of the vector
3899 , AlignmentFlag AF // Alignment flag
3900 , bool TF // Transpose flag
3901 , typename Tag // Type tag
3902 , typename RT > // Result type
3903 template< typename VT > // Type of the right-hand side vector
3904 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3905 CustomVector<Type,AF,padded,TF,Tag,RT>::operator-=( const Vector<VT,TF>& rhs )
3906 {
3907 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
3908
3909 if( (*rhs).size() != size_ ) {
3910 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
3911 }
3912
3913 if( (*rhs).canAlias( this ) ) {
3914 const ResultType_t<VT> tmp( *rhs );
3915 smpSubAssign( *this, tmp );
3916 }
3917 else {
3918 smpSubAssign( *this, *rhs );
3919 }
3920
3921 return *this;
3922 }
3923 /*! \endcond */
3924 //*************************************************************************************************
3925
3926
3927 //*************************************************************************************************
3928 /*! \cond BLAZE_INTERNAL */
3929 /*!\brief Multiplication assignment operator for the multiplication of a vector
3930 // (\f$ \vec{a}*=\vec{b} \f$).
3931 //
3932 // \param rhs The right-hand side vector to be multiplied with the vector.
3933 // \return Reference to the vector.
3934 // \exception std::invalid_argument Vector sizes do not match.
3935 //
3936 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
3937 // is thrown.
3938 */
3939 template< typename Type // Data type of the vector
3940 , AlignmentFlag AF // Alignment flag
3941 , bool TF // Transpose flag
3942 , typename Tag // Type tag
3943 , typename RT > // Result type
3944 template< typename VT > // Type of the right-hand side vector
3945 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3946 CustomVector<Type,AF,padded,TF,Tag,RT>::operator*=( const Vector<VT,TF>& rhs )
3947 {
3948 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
3949
3950 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
3951 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<VT> );
3952
3953 using MultType = MultTrait_t< ResultType, ResultType_t<VT> >;
3954
3955 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( MultType, TF );
3956 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MultType );
3957
3958 if( (*rhs).size() != size_ ) {
3959 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
3960 }
3961
3962 if( IsSparseVector_v<VT> || (*rhs).canAlias( this ) ) {
3963 const MultType tmp( *this * (*rhs) );
3964 if( IsSparseVector_v<MultType> )
3965 reset();
3966 smpAssign( *this, tmp );
3967 }
3968 else {
3969 smpMultAssign( *this, *rhs );
3970 }
3971
3972 return *this;
3973 }
3974 /*! \endcond */
3975 //*************************************************************************************************
3976
3977
3978 //*************************************************************************************************
3979 /*! \cond BLAZE_INTERNAL */
3980 /*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
3981 //
3982 // \param rhs The right-hand side dense vector divisor.
3983 // \return Reference to the vector.
3984 // \exception std::invalid_argument Vector sizes do not match.
3985 //
3986 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
3987 // is thrown.
3988 */
3989 template< typename Type // Data type of the vector
3990 , AlignmentFlag AF // Alignment flag
3991 , bool TF // Transpose flag
3992 , typename Tag // Type tag
3993 , typename RT > // Result type
3994 template< typename VT > // Type of the right-hand side vector
3995 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
3996 CustomVector<Type,AF,padded,TF,Tag,RT>::operator/=( const DenseVector<VT,TF>& rhs )
3997 {
3998 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
3999
4000 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
4001 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<VT> );
4002
4003 using DivType = DivTrait_t< ResultType, ResultType_t<VT> >;
4004
4005 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( DivType );
4006 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( DivType, TF );
4007 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( DivType );
4008
4009 if( (*rhs).size() != size_ ) {
4010 BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
4011 }
4012
4013 if( (*rhs).canAlias( this ) ) {
4014 const DivType tmp( *this / (*rhs) );
4015 smpAssign( *this, tmp );
4016 }
4017 else {
4018 smpDivAssign( *this, *rhs );
4019 }
4020
4021 return *this;
4022 }
4023 /*! \endcond */
4024 //*************************************************************************************************
4025
4026
4027 //*************************************************************************************************
4028 /*! \cond BLAZE_INTERNAL */
4029 /*!\brief Cross product assignment operator for the multiplication of a vector
4030 // (\f$ \vec{a}\times=\vec{b} \f$).
4031 //
4032 // \param rhs The right-hand side vector for the cross product.
4033 // \return Reference to the vector.
4034 // \exception std::invalid_argument Invalid vector size for cross product.
4035 //
4036 // In case the current size of any of the two vectors is not equal to 3, a \a std::invalid_argument
4037 // exception is thrown.
4038 */
4039 template< typename Type // Data type of the vector
4040 , AlignmentFlag AF // Alignment flag
4041 , bool TF // Transpose flag
4042 , typename Tag // Type tag
4043 , typename RT > // Result type
4044 template< typename VT > // Type of the right-hand side vector
4045 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
4046 CustomVector<Type,AF,padded,TF,Tag,RT>::operator%=( const Vector<VT,TF>& rhs )
4047 {
4048 using blaze::assign;
4049
4050 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
4051
4052 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF );
4053 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<VT> );
4054
4055 using CrossType = CrossTrait_t< ResultType, ResultType_t<VT> >;
4056
4057 BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( CrossType );
4058 BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( CrossType, TF );
4059 BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( CrossType );
4060
4061 if( size_ != 3UL || (*rhs).size() != 3UL ) {
4062 BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" );
4063 }
4064
4065 const CrossType tmp( *this % (*rhs) );
4066 assign( *this, tmp );
4067
4068 return *this;
4069 }
4070 /*! \endcond */
4071 //*************************************************************************************************
4072
4073
4074
4075
4076 //=================================================================================================
4077 //
4078 // UTILITY FUNCTIONS
4079 //
4080 //=================================================================================================
4081
4082 //*************************************************************************************************
4083 /*! \cond BLAZE_INTERNAL */
4084 /*!\brief Returns the size/dimension of the vector.
4085 //
4086 // \return The size of the vector.
4087 */
4088 template< typename Type // Data type of the vector
4089 , AlignmentFlag AF // Alignment flag
4090 , bool TF // Transpose flag
4091 , typename Tag // Type tag
4092 , typename RT > // Result type
size()4093 inline size_t CustomVector<Type,AF,padded,TF,Tag,RT>::size() const noexcept
4094 {
4095 return size_;
4096 }
4097 /*! \endcond */
4098 //*************************************************************************************************
4099
4100
4101 //*************************************************************************************************
4102 /*! \cond BLAZE_INTERNAL */
4103 /*!\brief Returns the minimum capacity of the vector.
4104 //
4105 // \return The minimum capacity of the vector.
4106 //
4107 // This function returns the minimum capacity of the vector, which corresponds to the current
4108 // size plus padding.
4109 */
4110 template< typename Type // Data type of the vector
4111 , AlignmentFlag AF // Alignment flag
4112 , bool TF // Transpose flag
4113 , typename Tag // Type tag
4114 , typename RT > // Result type
spacing()4115 inline size_t CustomVector<Type,AF,padded,TF,Tag,RT>::spacing() const noexcept
4116 {
4117 return capacity_;
4118 }
4119 /*! \endcond */
4120 //*************************************************************************************************
4121
4122
4123 //*************************************************************************************************
4124 /*! \cond BLAZE_INTERNAL */
4125 /*!\brief Returns the maximum capacity of the vector.
4126 //
4127 // \return The maximum capacity of the vector.
4128 */
4129 template< typename Type // Data type of the vector
4130 , AlignmentFlag AF // Alignment flag
4131 , bool TF // Transpose flag
4132 , typename Tag // Type tag
4133 , typename RT > // Result type
capacity()4134 inline size_t CustomVector<Type,AF,padded,TF,Tag,RT>::capacity() const noexcept
4135 {
4136 return capacity_;
4137 }
4138 /*! \endcond */
4139 //*************************************************************************************************
4140
4141
4142 //*************************************************************************************************
4143 /*! \cond BLAZE_INTERNAL */
4144 /*!\brief Returns the number of non-zero elements in the vector.
4145 //
4146 // \return The number of non-zero elements in the vector.
4147 //
4148 // This function returns the number of non-zero elements in the vector (i.e. the elements that
4149 // compare unequal to their default value). Note that the number of non-zero elements is always
4150 // less than or equal to the current size of the vector.
4151 */
4152 template< typename Type // Data type of the vector
4153 , AlignmentFlag AF // Alignment flag
4154 , bool TF // Transpose flag
4155 , typename Tag // Type tag
4156 , typename RT > // Result type
nonZeros()4157 inline size_t CustomVector<Type,AF,padded,TF,Tag,RT>::nonZeros() const
4158 {
4159 size_t nonzeros( 0 );
4160
4161 for( size_t i=0UL; i<size_; ++i ) {
4162 if( !isDefault<strict>( v_[i] ) )
4163 ++nonzeros;
4164 }
4165
4166 return nonzeros;
4167 }
4168 /*! \endcond */
4169 //*************************************************************************************************
4170
4171
4172 //*************************************************************************************************
4173 /*! \cond BLAZE_INTERNAL */
4174 /*!\brief Reset to the default initial values.
4175 //
4176 // \return void
4177 */
4178 template< typename Type // Data type of the vector
4179 , AlignmentFlag AF // Alignment flag
4180 , bool TF // Transpose flag
4181 , typename Tag // Type tag
4182 , typename RT > // Result type
reset()4183 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::reset()
4184 {
4185 using blaze::clear;
4186 for( size_t i=0UL; i<size_; ++i )
4187 clear( v_[i] );
4188 }
4189 /*! \endcond */
4190 //*************************************************************************************************
4191
4192
4193 //*************************************************************************************************
4194 /*! \cond BLAZE_INTERNAL */
4195 /*!\brief Clearing the vector to its default state.
4196 //
4197 // \return void
4198 //
4199 // This function clears the vector to its default state. In case the vector has been passed the
4200 // responsibility to manage the given array, it disposes the resource via the specified deleter.
4201 */
4202 template< typename Type // Data type of the vector
4203 , AlignmentFlag AF // Alignment flag
4204 , bool TF // Transpose flag
4205 , typename Tag // Type tag
4206 , typename RT > // Result type
clear()4207 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::clear()
4208 {
4209 size_ = 0UL;
4210 capacity_ = 0UL;
4211 v_ = nullptr;
4212 }
4213 /*! \endcond */
4214 //*************************************************************************************************
4215
4216
4217 //*************************************************************************************************
4218 /*! \cond BLAZE_INTERNAL */
4219 /*!\brief Swapping the contents of two vectors.
4220 //
4221 // \param v The vector to be swapped.
4222 // \return void
4223 */
4224 template< typename Type // Data type of the vector
4225 , AlignmentFlag AF // Alignment flag
4226 , bool TF // Transpose flag
4227 , typename Tag // Type tag
4228 , typename RT > // Result type
swap(CustomVector & v)4229 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::swap( CustomVector& v ) noexcept
4230 {
4231 using std::swap;
4232
4233 swap( size_, v.size_ );
4234 swap( capacity_, v.capacity_ );
4235 swap( v_, v.v_ );
4236 }
4237 /*! \endcond */
4238 //*************************************************************************************************
4239
4240
4241
4242
4243 //=================================================================================================
4244 //
4245 // NUMERIC FUNCTIONS
4246 //
4247 //=================================================================================================
4248
4249 //*************************************************************************************************
4250 /*! \cond BLAZE_INTERNAL */
4251 /*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$).
4252 //
4253 // \param scalar The scalar value for the vector scaling.
4254 // \return Reference to the vector.
4255 //
4256 // This function scales the vector by applying the given scalar value \a scalar to each element
4257 // of the vector. For built-in and \c complex data types it has the same effect as using the
4258 // multiplication assignment operator:
4259
4260 \code
4261 using blaze::CustomVector;
4262 using blaze::unaliged;
4263 using blaze::padded;
4264
4265 CustomVector<double,unaligned,padded> v( ... );
4266
4267 a *= 4; // Scaling of the vector
4268 a.scale( 4 ); // Same effect as above
4269 \endcode
4270 */
4271 template< typename Type // Data type of the vector
4272 , AlignmentFlag AF // Alignment flag
4273 , bool TF // Transpose flag
4274 , typename Tag // Type tag
4275 , typename RT > // Result type
4276 template< typename Other > // Data type of the scalar value
4277 inline CustomVector<Type,AF,padded,TF,Tag,RT>&
scale(const Other & scalar)4278 CustomVector<Type,AF,padded,TF,Tag,RT>::scale( const Other& scalar )
4279 {
4280 for( size_t i=0UL; i<size_; ++i )
4281 v_[i] *= scalar;
4282 return *this;
4283 }
4284 /*! \endcond */
4285 //*************************************************************************************************
4286
4287
4288
4289
4290 //=================================================================================================
4291 //
4292 // RESOURCE MANAGEMENT FUNCTIONS
4293 //
4294 //=================================================================================================
4295
4296 //*************************************************************************************************
4297 /*! \cond BLAZE_INTERNAL */
4298 /*!\brief Resets the custom vector and replaces the array of elements with the given array.
4299 //
4300 // \param ptr The array of elements to be used by the vector.
4301 // \param n The number of array elements to be used by the custom vector.
4302 // \param nn The maximum size of the given array.
4303 // \return void
4304 // \exception std::invalid_argument Invalid setup of custom vector.
4305 //
4306 // This function resets the custom vector to the given array of elements of size \a n and capacity
4307 // \a nn. The function fails if ...
4308 //
4309 // - ... the passed pointer is \c nullptr;
4310 // - ... the specified capacity \a nn is insufficient for the given data type \a Type and
4311 // the available instruction set.
4312 //
4313 // In all failure cases a \a std::invalid_argument exception is thrown.
4314 //
4315 // \note In case a deleter was specified, the previously referenced array will only be destroyed
4316 // when the last custom vector referencing the array goes out of scope.
4317 // \note The custom vector does NOT take responsibility for the new array of elements!
4318 */
4319 template< typename Type // Data type of the vector
4320 , AlignmentFlag AF // Alignment flag
4321 , bool TF // Transpose flag
4322 , typename Tag // Type tag
4323 , typename RT > // Result type
reset(Type * ptr,size_t n,size_t nn)4324 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::reset( Type* ptr, size_t n, size_t nn )
4325 {
4326 CustomVector tmp( ptr, n, nn );
4327 swap( tmp );
4328 }
4329 /*! \endcond */
4330 //*************************************************************************************************
4331
4332
4333
4334
4335 //=================================================================================================
4336 //
4337 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
4338 //
4339 //=================================================================================================
4340
4341 //*************************************************************************************************
4342 /*! \cond BLAZE_INTERNAL */
4343 /*!\brief Returns whether the vector can alias with the given address \a alias.
4344 //
4345 // \param alias The alias to be checked.
4346 // \return \a true in case the alias corresponds to this vector, \a false if not.
4347 //
4348 // This function returns whether the given address can alias with the vector. In contrast
4349 // to the isAliased() function this function is allowed to use compile time expressions
4350 // to optimize the evaluation.
4351 */
4352 template< typename Type // Data type of the vector
4353 , AlignmentFlag AF // Alignment flag
4354 , bool TF // Transpose flag
4355 , typename Tag // Type tag
4356 , typename RT > // Result type
4357 template< typename Other > // Data type of the foreign expression
canAlias(const Other * alias)4358 inline bool CustomVector<Type,AF,padded,TF,Tag,RT>::canAlias( const Other* alias ) const noexcept
4359 {
4360 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
4361 }
4362 /*! \endcond */
4363 //*************************************************************************************************
4364
4365
4366 //*************************************************************************************************
4367 /*! \cond BLAZE_INTERNAL */
4368 /*!\brief Returns whether the vector is aliased with the given address \a alias.
4369 //
4370 // \param alias The alias to be checked.
4371 // \return \a true in case the alias corresponds to this vector, \a false if not.
4372 //
4373 // This function returns whether the given address is aliased with the vector. In contrast
4374 // to the canAlias() function this function is not allowed to use compile time expressions
4375 // to optimize the evaluation.
4376 */
4377 template< typename Type // Data type of the vector
4378 , AlignmentFlag AF // Alignment flag
4379 , bool TF // Transpose flag
4380 , typename Tag // Type tag
4381 , typename RT > // Result type
4382 template< typename Other > // Data type of the foreign expression
isAliased(const Other * alias)4383 inline bool CustomVector<Type,AF,padded,TF,Tag,RT>::isAliased( const Other* alias ) const noexcept
4384 {
4385 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
4386 }
4387 /*! \endcond */
4388 //*************************************************************************************************
4389
4390
4391 //*************************************************************************************************
4392 /*! \cond BLAZE_INTERNAL */
4393 /*!\brief Returns whether the vector is properly aligned in memory.
4394 //
4395 // \return \a true in case the vector is aligned, \a false if not.
4396 //
4397 // This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
4398 // whether the beginning and the end of the vector are guaranteed to conform to the alignment
4399 // restrictions of the element type \a Type.
4400 */
4401 template< typename Type // Data type of the vector
4402 , AlignmentFlag AF // Alignment flag
4403 , bool TF // Transpose flag
4404 , typename Tag // Type tag
4405 , typename RT > // Result type
isAligned()4406 inline bool CustomVector<Type,AF,padded,TF,Tag,RT>::isAligned() const noexcept
4407 {
4408 return ( AF || checkAlignment( v_ ) );
4409 }
4410 /*! \endcond */
4411 //*************************************************************************************************
4412
4413
4414 //*************************************************************************************************
4415 /*! \cond BLAZE_INTERNAL */
4416 /*!\brief Returns whether the vector can be used in SMP assignments.
4417 //
4418 // \return \a true in case the vector can be used in SMP assignments, \a false if not.
4419 //
4420 // This function returns whether the vector can be used in SMP assignments. In contrast to the
4421 // \a smpAssignable member enumeration, which is based solely on compile time information, this
4422 // function additionally provides runtime information (as for instance the current size of the
4423 // vector).
4424 */
4425 template< typename Type // Data type of the vector
4426 , AlignmentFlag AF // Alignment flag
4427 , bool TF // Transpose flag
4428 , typename Tag // Type tag
4429 , typename RT > // Result type
canSMPAssign()4430 inline bool CustomVector<Type,AF,padded,TF,Tag,RT>::canSMPAssign() const noexcept
4431 {
4432 return ( size() > SMP_DVECASSIGN_THRESHOLD );
4433 }
4434 /*! \endcond */
4435 //*************************************************************************************************
4436
4437
4438 //*************************************************************************************************
4439 /*! \cond BLAZE_INTERNAL */
4440 /*!\brief Load of a SIMD element of the vector.
4441 //
4442 // \param index Access index. The index must be smaller than the number of vector elements.
4443 // \return The loaded SIMD element.
4444 //
4445 // This function performs a load of a specific SIMD element of the dense vector. The index
4446 // must be smaller than the number of vector elements and it must be a multiple of the number
4447 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
4448 // used internally for the performance optimized evaluation of expression templates. Calling
4449 // this function explicitly might result in erroneous results and/or in compilation errors.
4450 */
4451 template< typename Type // Data type of the vector
4452 , AlignmentFlag AF // Alignment flag
4453 , bool TF // Transpose flag
4454 , typename Tag // Type tag
4455 , typename RT > // Result type
4456 BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,padded,TF,Tag,RT>::SIMDType
load(size_t index)4457 CustomVector<Type,AF,padded,TF,Tag,RT>::load( size_t index ) const noexcept
4458 {
4459 if( AF )
4460 return loada( index );
4461 else
4462 return loadu( index );
4463 }
4464 /*! \endcond */
4465 //*************************************************************************************************
4466
4467
4468 //*************************************************************************************************
4469 /*! \cond BLAZE_INTERNAL */
4470 /*!\brief Aligned load of a SIMD element of the vector.
4471 //
4472 // \param index Access index. The index must be smaller than the number of vector elements.
4473 // \return The loaded SIMD element.
4474 //
4475 // This function performs an aligned load of a specific SIMD element of the dense vector. The
4476 // index must be smaller than the number of vector elements and it must be a multiple of the
4477 // number of values inside the SIMD element. This function must \b NOT be called explicitly!
4478 // It is used internally for the performance optimized evaluation of expression templates.
4479 // Calling this function explicitly might result in erroneous results and/or in compilation
4480 // errors.
4481 */
4482 template< typename Type // Data type of the vector
4483 , AlignmentFlag AF // Alignment flag
4484 , bool TF // Transpose flag
4485 , typename Tag // Type tag
4486 , typename RT > // Result type
4487 BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,padded,TF,Tag,RT>::SIMDType
loada(size_t index)4488 CustomVector<Type,AF,padded,TF,Tag,RT>::loada( size_t index ) const noexcept
4489 {
4490 using blaze::loada;
4491
4492 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4493
4494 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
4495 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
4496 BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
4497 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid vector access index" );
4498
4499 return loada( v_+index );
4500 }
4501 /*! \endcond */
4502 //*************************************************************************************************
4503
4504
4505 //*************************************************************************************************
4506 /*! \cond BLAZE_INTERNAL */
4507 /*!\brief Unaligned load of a SIMD element of the vector.
4508 //
4509 // \param index Access index. The index must be smaller than the number of vector elements.
4510 // \return The loaded SIMD element.
4511 //
4512 // This function performs an unaligned load of a specific SIMD element of the dense vector. The
4513 // index must be smaller than the number of vector elements and it must be a multiple of the
4514 // number of values inside the SIMD element. This function must \b NOT be called explicitly!
4515 // It is used internally for the performance optimized evaluation of expression templates.
4516 // Calling this function explicitly might result in erroneous results and/or in compilation
4517 // errors.
4518 */
4519 template< typename Type // Data type of the vector
4520 , AlignmentFlag AF // Alignment flag
4521 , bool TF // Transpose flag
4522 , typename Tag // Type tag
4523 , typename RT > // Result type
4524 BLAZE_ALWAYS_INLINE typename CustomVector<Type,AF,padded,TF,Tag,RT>::SIMDType
loadu(size_t index)4525 CustomVector<Type,AF,padded,TF,Tag,RT>::loadu( size_t index ) const noexcept
4526 {
4527 using blaze::loadu;
4528
4529 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4530
4531 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
4532 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
4533
4534 return loadu( v_+index );
4535 }
4536 /*! \endcond */
4537 //*************************************************************************************************
4538
4539
4540 //*************************************************************************************************
4541 /*! \cond BLAZE_INTERNAL */
4542 /*!\brief Store of a SIMD element of the vector.
4543 //
4544 // \param index Access index. The index must be smaller than the number of vector elements.
4545 // \param value The SIMD element to be stored.
4546 // \return void
4547 //
4548 // This function performs a store of a specific SIMD element of the dense vector. The index
4549 // must be smaller than the number of vector elements and it must be a multiple of the number
4550 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
4551 // used internally for the performance optimized evaluation of expression templates. Calling
4552 // this function explicitly might result in erroneous results and/or in compilation errors.
4553 */
4554 template< typename Type // Data type of the vector
4555 , AlignmentFlag AF // Alignment flag
4556 , bool TF // Transpose flag
4557 , typename Tag // Type tag
4558 , typename RT > // Result type
4559 BLAZE_ALWAYS_INLINE void
store(size_t index,const SIMDType & value)4560 CustomVector<Type,AF,padded,TF,Tag,RT>::store( size_t index, const SIMDType& value ) noexcept
4561 {
4562 if( AF )
4563 storea( index, value );
4564 else
4565 storeu( index, value );
4566 }
4567 /*! \endcond */
4568 //*************************************************************************************************
4569
4570
4571 //*************************************************************************************************
4572 /*! \cond BLAZE_INTERNAL */
4573 /*!\brief Aligned store of a SIMD element of the vector.
4574 //
4575 // \param index Access index. The index must be smaller than the number of vector elements.
4576 // \param value The SIMD element to be stored.
4577 // \return void
4578 //
4579 // This function performs an aligned store of a specific SIMD element of the dense vector. The
4580 // index must be smaller than the number of vector elements and it must be a multiple of the
4581 // number of values inside the SIMD element. This function must \b NOT be called explicitly! It
4582 // is used internally for the performance optimized evaluation of expression templates. Calling
4583 // this function explicitly might result in erroneous results and/or in compilation errors.
4584 */
4585 template< typename Type // Data type of the vector
4586 , AlignmentFlag AF // Alignment flag
4587 , bool TF // Transpose flag
4588 , typename Tag // Type tag
4589 , typename RT > // Result type
4590 BLAZE_ALWAYS_INLINE void
storea(size_t index,const SIMDType & value)4591 CustomVector<Type,AF,padded,TF,Tag,RT>::storea( size_t index, const SIMDType& value ) noexcept
4592 {
4593 using blaze::storea;
4594
4595 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4596
4597 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
4598 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
4599 BLAZE_INTERNAL_ASSERT( !AF || index % SIMDSIZE == 0UL, "Invalid vector access index" );
4600 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid vector access index" );
4601
4602 storea( v_+index, value );
4603 }
4604 /*! \endcond */
4605 //*************************************************************************************************
4606
4607
4608 //*************************************************************************************************
4609 /*! \cond BLAZE_INTERNAL */
4610 /*!\brief Unaligned store of a SIMD element of the vector.
4611 //
4612 // \param index Access index. The index must be smaller than the number of vector elements.
4613 // \param value The SIMD element to be stored.
4614 // \return void
4615 //
4616 // This function performs an unaligned store of a specific SIMD element of the dense vector.
4617 // The index must be smaller than the number of vector elements and it must be a multiple of the
4618 // number of values inside the SIMD element. This function must \b NOT be called explicitly! It
4619 // is used internally for the performance optimized evaluation of expression templates. Calling
4620 // this function explicitly might result in erroneous results and/or in compilation errors.
4621 */
4622 template< typename Type // Data type of the vector
4623 , AlignmentFlag AF // Alignment flag
4624 , bool TF // Transpose flag
4625 , typename Tag // Type tag
4626 , typename RT > // Result type
4627 BLAZE_ALWAYS_INLINE void
storeu(size_t index,const SIMDType & value)4628 CustomVector<Type,AF,padded,TF,Tag,RT>::storeu( size_t index, const SIMDType& value ) noexcept
4629 {
4630 using blaze::storeu;
4631
4632 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4633
4634 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
4635 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
4636
4637 storeu( v_+index, value );
4638 }
4639 /*! \endcond */
4640 //*************************************************************************************************
4641
4642
4643 //*************************************************************************************************
4644 /*! \cond BLAZE_INTERNAL */
4645 /*!\brief Aligned, non-temporal store of a SIMD element of the vector.
4646 //
4647 // \param index Access index. The index must be smaller than the number of vector elements.
4648 // \param value The SIMD element to be stored.
4649 // \return void
4650 //
4651 // This function performs an aligned, non-temporal store of a specific SIMD element of the
4652 // dense vector. The index must be smaller than the number of vector elements and it must be
4653 // a multiple of the number of values inside the SIMD element. This function must \b NOT be
4654 // called explicitly! It is used internally for the performance optimized evaluation of
4655 // expression templates. Calling this function explicitly might result in erroneous results
4656 // and/or in compilation errors.
4657 */
4658 template< typename Type // Data type of the vector
4659 , AlignmentFlag AF // Alignment flag
4660 , bool TF // Transpose flag
4661 , typename Tag // Type tag
4662 , typename RT > // Result type
4663 BLAZE_ALWAYS_INLINE void
stream(size_t index,const SIMDType & value)4664 CustomVector<Type,AF,padded,TF,Tag,RT>::stream( size_t index, const SIMDType& value ) noexcept
4665 {
4666 using blaze::stream;
4667
4668 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4669
4670 BLAZE_INTERNAL_ASSERT( index < size_, "Invalid vector access index" );
4671 BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= capacity_, "Invalid vector access index" );
4672 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+index ), "Invalid vector access index" );
4673
4674 stream( v_+index, value );
4675 }
4676 /*! \endcond */
4677 //*************************************************************************************************
4678
4679
4680 //*************************************************************************************************
4681 /*! \cond BLAZE_INTERNAL */
4682 /*!\brief Default implementation of the assignment of a dense vector.
4683 //
4684 // \param rhs The right-hand side dense vector to be assigned.
4685 // \return void
4686 //
4687 // This function must \b NOT be called explicitly! It is used internally for the performance
4688 // optimized evaluation of expression templates. Calling this function explicitly might result
4689 // in erroneous results and/or in compilation errors. Instead of using this function use the
4690 // assignment operator.
4691 */
4692 template< typename Type // Data type of the vector
4693 , AlignmentFlag AF // Alignment flag
4694 , bool TF // Transpose flag
4695 , typename Tag // Type tag
4696 , typename RT > // Result type
4697 template< typename VT > // Type of the right-hand side dense vector
4698 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::assign( const DenseVector<VT,TF>& rhs )
4699 -> DisableIf_t< VectorizedAssign_v<VT> >
4700 {
4701 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4702
4703 const size_t ipos( prevMultiple( size_, 2UL ) );
4704 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
4705
4706 for( size_t i=0UL; i<ipos; i+=2UL ) {
4707 v_[i ] = (*rhs)[i ];
4708 v_[i+1UL] = (*rhs)[i+1UL];
4709 }
4710 if( ipos < (*rhs).size() )
4711 v_[ipos] = (*rhs)[ipos];
4712 }
4713 /*! \endcond */
4714 //*************************************************************************************************
4715
4716
4717 //*************************************************************************************************
4718 /*! \cond BLAZE_INTERNAL */
4719 /*!\brief SIMD optimized implementation of the assignment of a dense vector.
4720 //
4721 // \param rhs The right-hand side dense vector to be assigned.
4722 // \return void
4723 //
4724 // This function must \b NOT be called explicitly! It is used internally for the performance
4725 // optimized evaluation of expression templates. Calling this function explicitly might result
4726 // in erroneous results and/or in compilation errors. Instead of using this function use the
4727 // assignment operator.
4728 */
4729 template< typename Type // Data type of the vector
4730 , AlignmentFlag AF // Alignment flag
4731 , bool TF // Transpose flag
4732 , typename Tag // Type tag
4733 , typename RT > // Result type
4734 template< typename VT > // Type of the right-hand side dense vector
4735 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::assign( const DenseVector<VT,TF>& rhs )
4736 -> EnableIf_t< VectorizedAssign_v<VT> >
4737 {
4738 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4739
4740 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4741
4742 constexpr bool remainder( !IsPadded_v<VT> );
4743
4744 const size_t ipos( remainder ? prevMultiple( size_, SIMDSIZE ) : size_ );
4745 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
4746
4747 if( AF && useStreaming && size_ > ( cacheSize/( sizeof(Type) * 3UL ) ) && !(*rhs).isAliased( this ) )
4748 {
4749 size_t i( 0UL );
4750
4751 for( ; i<ipos; i+=SIMDSIZE ) {
4752 stream( i, (*rhs).load(i) );
4753 }
4754 for( ; remainder && i<size_; ++i ) {
4755 v_[i] = (*rhs)[i];
4756 }
4757 }
4758 else
4759 {
4760 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
4761 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
4762
4763 size_t i( 0UL );
4764 ConstIterator_t<VT> it( (*rhs).begin() );
4765
4766 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
4767 store( i , it.load() ); it += SIMDSIZE;
4768 store( i+SIMDSIZE , it.load() ); it += SIMDSIZE;
4769 store( i+SIMDSIZE*2UL, it.load() ); it += SIMDSIZE;
4770 store( i+SIMDSIZE*3UL, it.load() ); it += SIMDSIZE;
4771 }
4772 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
4773 store( i, it.load() );
4774 }
4775 for( ; remainder && i<size_; ++i, ++it ) {
4776 v_[i] = *it;
4777 }
4778 }
4779 }
4780 /*! \endcond */
4781 //*************************************************************************************************
4782
4783
4784 //*************************************************************************************************
4785 /*! \cond BLAZE_INTERNAL */
4786 /*!\brief Default implementation of the assignment of a sparse vector.
4787 //
4788 // \param rhs The right-hand side sparse vector to be assigned.
4789 // \return void
4790 //
4791 // This function must \b NOT be called explicitly! It is used internally for the performance
4792 // optimized evaluation of expression templates. Calling this function explicitly might result
4793 // in erroneous results and/or in compilation errors. Instead of using this function use the
4794 // assignment operator.
4795 */
4796 template< typename Type // Data type of the vector
4797 , AlignmentFlag AF // Alignment flag
4798 , bool TF // Transpose flag
4799 , typename Tag // Type tag
4800 , typename RT > // Result type
4801 template< typename VT > // Type of the right-hand side sparse vector
assign(const SparseVector<VT,TF> & rhs)4802 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::assign( const SparseVector<VT,TF>& rhs )
4803 {
4804 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4805
4806 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
4807 v_[element->index()] = element->value();
4808 }
4809 /*! \endcond */
4810 //*************************************************************************************************
4811
4812
4813 //*************************************************************************************************
4814 /*! \cond BLAZE_INTERNAL */
4815 /*!\brief Default implementation of the addition assignment of a dense vector.
4816 //
4817 // \param rhs The right-hand side dense vector to be added.
4818 // \return void
4819 //
4820 // This function must \b NOT be called explicitly! It is used internally for the performance
4821 // optimized evaluation of expression templates. Calling this function explicitly might result
4822 // in erroneous results and/or in compilation errors. Instead of using this function use the
4823 // assignment operator.
4824 */
4825 template< typename Type // Data type of the vector
4826 , AlignmentFlag AF // Alignment flag
4827 , bool TF // Transpose flag
4828 , typename Tag // Type tag
4829 , typename RT > // Result type
4830 template< typename VT > // Type of the right-hand side dense vector
4831 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::addAssign( const DenseVector<VT,TF>& rhs )
4832 -> DisableIf_t< VectorizedAddAssign_v<VT> >
4833 {
4834 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4835
4836 const size_t ipos( prevMultiple( size_, 2UL ) );
4837 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
4838
4839 for( size_t i=0UL; i<ipos; i+=2UL ) {
4840 v_[i ] += (*rhs)[i ];
4841 v_[i+1UL] += (*rhs)[i+1UL];
4842 }
4843 if( ipos < (*rhs).size() )
4844 v_[ipos] += (*rhs)[ipos];
4845 }
4846 /*! \endcond */
4847 //*************************************************************************************************
4848
4849
4850 //*************************************************************************************************
4851 /*! \cond BLAZE_INTERNAL */
4852 /*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
4853 //
4854 // \param rhs The right-hand side dense vector to be added.
4855 // \return void
4856 //
4857 // This function must \b NOT be called explicitly! It is used internally for the performance
4858 // optimized evaluation of expression templates. Calling this function explicitly might result
4859 // in erroneous results and/or in compilation errors. Instead of using this function use the
4860 // assignment operator.
4861 */
4862 template< typename Type // Data type of the vector
4863 , AlignmentFlag AF // Alignment flag
4864 , bool TF // Transpose flag
4865 , typename Tag // Type tag
4866 , typename RT > // Result type
4867 template< typename VT > // Type of the right-hand side dense vector
4868 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::addAssign( const DenseVector<VT,TF>& rhs )
4869 -> EnableIf_t< VectorizedAddAssign_v<VT> >
4870 {
4871 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4872
4873 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4874
4875 constexpr bool remainder( !IsPadded_v<VT> );
4876
4877 const size_t ipos( remainder ? prevMultiple( size_, SIMDSIZE ) : size_ );
4878 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
4879
4880 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
4881 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
4882
4883 size_t i( 0UL );
4884 ConstIterator_t<VT> it( (*rhs).begin() );
4885
4886 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
4887 store( i , load(i ) + it.load() ); it += SIMDSIZE;
4888 store( i+SIMDSIZE , load(i+SIMDSIZE ) + it.load() ); it += SIMDSIZE;
4889 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) + it.load() ); it += SIMDSIZE;
4890 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) + it.load() ); it += SIMDSIZE;
4891 }
4892 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
4893 store( i, load(i) + it.load() );
4894 }
4895 for( ; remainder && i<size_; ++i, ++it ) {
4896 v_[i] += *it;
4897 }
4898 }
4899 /*! \endcond */
4900 //*************************************************************************************************
4901
4902
4903 //*************************************************************************************************
4904 /*! \cond BLAZE_INTERNAL */
4905 /*!\brief Default implementation of the addition assignment of a sparse vector.
4906 //
4907 // \param rhs The right-hand side sparse vector to be added.
4908 // \return void
4909 //
4910 // This function must \b NOT be called explicitly! It is used internally for the performance
4911 // optimized evaluation of expression templates. Calling this function explicitly might result
4912 // in erroneous results and/or in compilation errors. Instead of using this function use the
4913 // assignment operator.
4914 */
4915 template< typename Type // Data type of the vector
4916 , AlignmentFlag AF // Alignment flag
4917 , bool TF // Transpose flag
4918 , typename Tag // Type tag
4919 , typename RT > // Result type
4920 template< typename VT > // Type of the right-hand side sparse vector
addAssign(const SparseVector<VT,TF> & rhs)4921 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::addAssign( const SparseVector<VT,TF>& rhs )
4922 {
4923 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4924
4925 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
4926 v_[element->index()] += element->value();
4927 }
4928 /*! \endcond */
4929 //*************************************************************************************************
4930
4931
4932 //*************************************************************************************************
4933 /*! \cond BLAZE_INTERNAL */
4934 /*!\brief Default implementation of the subtraction assignment of a dense vector.
4935 //
4936 // \param rhs The right-hand side dense vector to be subtracted.
4937 // \return void
4938 //
4939 // This function must \b NOT be called explicitly! It is used internally for the performance
4940 // optimized evaluation of expression templates. Calling this function explicitly might result
4941 // in erroneous results and/or in compilation errors. Instead of using this function use the
4942 // assignment operator.
4943 */
4944 template< typename Type // Data type of the vector
4945 , AlignmentFlag AF // Alignment flag
4946 , bool TF // Transpose flag
4947 , typename Tag // Type tag
4948 , typename RT > // Result type
4949 template< typename VT > // Type of the right-hand side dense vector
4950 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::subAssign( const DenseVector<VT,TF>& rhs )
4951 -> DisableIf_t< VectorizedSubAssign_v<VT> >
4952 {
4953 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4954
4955 const size_t ipos( prevMultiple( size_, 2UL ) );
4956 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
4957
4958 for( size_t i=0UL; i<ipos; i+=2UL ) {
4959 v_[i ] -= (*rhs)[i ];
4960 v_[i+1UL] -= (*rhs)[i+1UL];
4961 }
4962 if( ipos < (*rhs).size() )
4963 v_[ipos] -= (*rhs)[ipos];
4964 }
4965 /*! \endcond */
4966 //*************************************************************************************************
4967
4968
4969 //*************************************************************************************************
4970 /*! \cond BLAZE_INTERNAL */
4971 /*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
4972 //
4973 // \param rhs The right-hand side dense vector to be subtracted.
4974 // \return void
4975 //
4976 // This function must \b NOT be called explicitly! It is used internally for the performance
4977 // optimized evaluation of expression templates. Calling this function explicitly might result
4978 // in erroneous results and/or in compilation errors. Instead of using this function use the
4979 // assignment operator.
4980 */
4981 template< typename Type // Data type of the vector
4982 , AlignmentFlag AF // Alignment flag
4983 , bool TF // Transpose flag
4984 , typename Tag // Type tag
4985 , typename RT > // Result type
4986 template< typename VT > // Type of the right-hand side dense vector
4987 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::subAssign( const DenseVector<VT,TF>& rhs )
4988 -> EnableIf_t< VectorizedSubAssign_v<VT> >
4989 {
4990 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
4991
4992 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
4993
4994 constexpr bool remainder( !IsPadded_v<VT> );
4995
4996 const size_t ipos( remainder ? prevMultiple( size_, SIMDSIZE ) : size_ );
4997 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
4998
4999 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
5000 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
5001
5002 size_t i( 0UL );
5003 ConstIterator_t<VT> it( (*rhs).begin() );
5004
5005 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
5006 store( i , load(i ) - it.load() ); it += SIMDSIZE;
5007 store( i+SIMDSIZE , load(i+SIMDSIZE ) - it.load() ); it += SIMDSIZE;
5008 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) - it.load() ); it += SIMDSIZE;
5009 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) - it.load() ); it += SIMDSIZE;
5010 }
5011 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
5012 store( i, load(i) - it.load() );
5013 }
5014 for( ; remainder && i<size_; ++i, ++it ) {
5015 v_[i] -= *it;
5016 }
5017 }
5018 /*! \endcond */
5019 //*************************************************************************************************
5020
5021
5022 //*************************************************************************************************
5023 /*! \cond BLAZE_INTERNAL */
5024 /*!\brief Default implementation of the subtraction assignment of a sparse vector.
5025 //
5026 // \param rhs The right-hand side sparse vector to be subtracted.
5027 // \return void
5028 //
5029 // This function must \b NOT be called explicitly! It is used internally for the performance
5030 // optimized evaluation of expression templates. Calling this function explicitly might result
5031 // in erroneous results and/or in compilation errors. Instead of using this function use the
5032 // assignment operator.
5033 */
5034 template< typename Type // Data type of the vector
5035 , AlignmentFlag AF // Alignment flag
5036 , bool TF // Transpose flag
5037 , typename Tag // Type tag
5038 , typename RT > // Result type
5039 template< typename VT > // Type of the right-hand side sparse vector
subAssign(const SparseVector<VT,TF> & rhs)5040 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::subAssign( const SparseVector<VT,TF>& rhs )
5041 {
5042 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
5043
5044 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
5045 v_[element->index()] -= element->value();
5046 }
5047 /*! \endcond */
5048 //*************************************************************************************************
5049
5050
5051 //*************************************************************************************************
5052 /*! \cond BLAZE_INTERNAL */
5053 /*!\brief Default implementation of the multiplication assignment of a dense vector.
5054 //
5055 // \param rhs The right-hand side dense vector to be multiplied.
5056 // \return void
5057 //
5058 // This function must \b NOT be called explicitly! It is used internally for the performance
5059 // optimized evaluation of expression templates. Calling this function explicitly might result
5060 // in erroneous results and/or in compilation errors. Instead of using this function use the
5061 // assignment operator.
5062 */
5063 template< typename Type // Data type of the vector
5064 , AlignmentFlag AF // Alignment flag
5065 , bool TF // Transpose flag
5066 , typename Tag // Type tag
5067 , typename RT > // Result type
5068 template< typename VT > // Type of the right-hand side dense vector
5069 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::multAssign( const DenseVector<VT,TF>& rhs )
5070 -> DisableIf_t< VectorizedMultAssign_v<VT> >
5071 {
5072 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
5073
5074 const size_t ipos( prevMultiple( size_, 2UL ) );
5075 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
5076
5077 for( size_t i=0UL; i<ipos; i+=2UL ) {
5078 v_[i ] *= (*rhs)[i ];
5079 v_[i+1UL] *= (*rhs)[i+1UL];
5080 }
5081 if( ipos < (*rhs).size() )
5082 v_[ipos] *= (*rhs)[ipos];
5083 }
5084 /*! \endcond */
5085 //*************************************************************************************************
5086
5087
5088 //*************************************************************************************************
5089 /*! \cond BLAZE_INTERNAL */
5090 /*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
5091 //
5092 // \param rhs The right-hand side dense vector to be multiplied.
5093 // \return void
5094 //
5095 // This function must \b NOT be called explicitly! It is used internally for the performance
5096 // optimized evaluation of expression templates. Calling this function explicitly might result
5097 // in erroneous results and/or in compilation errors. Instead of using this function use the
5098 // assignment operator.
5099 */
5100 template< typename Type // Data type of the vector
5101 , AlignmentFlag AF // Alignment flag
5102 , bool TF // Transpose flag
5103 , typename Tag // Type tag
5104 , typename RT > // Result type
5105 template< typename VT > // Type of the right-hand side dense vector
5106 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::multAssign( const DenseVector<VT,TF>& rhs )
5107 -> EnableIf_t< VectorizedMultAssign_v<VT> >
5108 {
5109 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
5110
5111 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
5112
5113 constexpr bool remainder( !IsPadded_v<VT> );
5114
5115 const size_t ipos( remainder ? prevMultiple( size_, SIMDSIZE ) : size_ );
5116 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
5117
5118 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
5119 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
5120
5121 size_t i( 0UL );
5122 ConstIterator_t<VT> it( (*rhs).begin() );
5123
5124 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
5125 store( i , load(i ) * it.load() ); it += SIMDSIZE;
5126 store( i+SIMDSIZE , load(i+SIMDSIZE ) * it.load() ); it += SIMDSIZE;
5127 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) * it.load() ); it += SIMDSIZE;
5128 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) * it.load() ); it += SIMDSIZE;
5129 }
5130 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
5131 store( i, load(i) * it.load() );
5132 }
5133 for( ; remainder && i<size_; ++i, ++it ) {
5134 v_[i] *= *it;
5135 }
5136 }
5137 /*! \endcond */
5138 //*************************************************************************************************
5139
5140
5141 //*************************************************************************************************
5142 /*! \cond BLAZE_INTERNAL */
5143 /*!\brief Default implementation of the multiplication assignment of a sparse vector.
5144 //
5145 // \param rhs The right-hand side sparse vector to be multiplied.
5146 // \return void
5147 //
5148 // This function must \b NOT be called explicitly! It is used internally for the performance
5149 // optimized evaluation of expression templates. Calling this function explicitly might result
5150 // in erroneous results and/or in compilation errors. Instead of using this function use the
5151 // assignment operator.
5152 */
5153 template< typename Type // Data type of the vector
5154 , AlignmentFlag AF // Alignment flag
5155 , bool TF // Transpose flag
5156 , typename Tag // Type tag
5157 , typename RT > // Result type
5158 template< typename VT > // Type of the right-hand side sparse vector
multAssign(const SparseVector<VT,TF> & rhs)5159 inline void CustomVector<Type,AF,padded,TF,Tag,RT>::multAssign( const SparseVector<VT,TF>& rhs )
5160 {
5161 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
5162
5163 const ResultType tmp( serial( *this ) );
5164
5165 reset();
5166
5167 for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
5168 v_[element->index()] = tmp[element->index()] * element->value();
5169 }
5170 /*! \endcond */
5171 //*************************************************************************************************
5172
5173
5174 //*************************************************************************************************
5175 /*! \cond BLAZE_INTERNAL */
5176 /*!\brief Default implementation of the division assignment of a dense vector.
5177 //
5178 // \param rhs The right-hand side dense vector divisor.
5179 // \return void
5180 //
5181 // This function must \b NOT be called explicitly! It is used internally for the performance
5182 // optimized evaluation of expression templates. Calling this function explicitly might result
5183 // in erroneous results and/or in compilation errors. Instead of using this function use the
5184 // assignment operator.
5185 */
5186 template< typename Type // Data type of the vector
5187 , AlignmentFlag AF // Alignment flag
5188 , bool TF // Transpose flag
5189 , typename Tag // Type tag
5190 , typename RT > // Result type
5191 template< typename VT > // Type of the right-hand side dense vector
5192 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::divAssign( const DenseVector<VT,TF>& rhs )
5193 -> DisableIf_t< VectorizedDivAssign_v<VT> >
5194 {
5195 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
5196
5197 const size_t ipos( prevMultiple( size_, 2UL ) );
5198 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
5199
5200 for( size_t i=0UL; i<ipos; i+=2UL ) {
5201 v_[i ] /= (*rhs)[i ];
5202 v_[i+1UL] /= (*rhs)[i+1UL];
5203 }
5204 if( ipos < (*rhs).size() )
5205 v_[ipos] /= (*rhs)[ipos];
5206 }
5207 /*! \endcond */
5208 //*************************************************************************************************
5209
5210
5211 //*************************************************************************************************
5212 /*! \cond BLAZE_INTERNAL */
5213 /*!\brief SIMD optimized implementation of the division assignment of a dense vector.
5214 //
5215 // \param rhs The right-hand side dense vector divisor.
5216 // \return void
5217 //
5218 // This function must \b NOT be called explicitly! It is used internally for the performance
5219 // optimized evaluation of expression templates. Calling this function explicitly might result
5220 // in erroneous results and/or in compilation errors. Instead of using this function use the
5221 // assignment operator.
5222 */
5223 template< typename Type // Data type of the vector
5224 , AlignmentFlag AF // Alignment flag
5225 , bool TF // Transpose flag
5226 , typename Tag // Type tag
5227 , typename RT > // Result type
5228 template< typename VT > // Type of the right-hand side dense vector
5229 inline auto CustomVector<Type,AF,padded,TF,Tag,RT>::divAssign( const DenseVector<VT,TF>& rhs )
5230 -> EnableIf_t< VectorizedDivAssign_v<VT> >
5231 {
5232 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
5233
5234 BLAZE_INTERNAL_ASSERT( size_ == (*rhs).size(), "Invalid vector sizes" );
5235
5236 const size_t ipos( prevMultiple( size_, SIMDSIZE ) );
5237 BLAZE_INTERNAL_ASSERT( ipos <= size_, "Invalid end calculation" );
5238
5239 const size_t i4way( prevMultiple( size_, SIMDSIZE*4UL ) );
5240 BLAZE_INTERNAL_ASSERT( i4way <= size_, "Invalid end calculation" );
5241
5242 size_t i( 0UL );
5243 ConstIterator_t<VT> it( (*rhs).begin() );
5244
5245 for( ; i<i4way; i+=SIMDSIZE*4UL ) {
5246 store( i , load(i ) / it.load() ); it += SIMDSIZE;
5247 store( i+SIMDSIZE , load(i+SIMDSIZE ) / it.load() ); it += SIMDSIZE;
5248 store( i+SIMDSIZE*2UL, load(i+SIMDSIZE*2UL) / it.load() ); it += SIMDSIZE;
5249 store( i+SIMDSIZE*3UL, load(i+SIMDSIZE*3UL) / it.load() ); it += SIMDSIZE;
5250 }
5251 for( ; i<ipos; i+=SIMDSIZE, it+=SIMDSIZE ) {
5252 store( i, load(i) / it.load() );
5253 }
5254 for( ; i<size_; ++i, ++it ) {
5255 v_[i] /= *it;
5256 }
5257 }
5258 /*! \endcond */
5259 //*************************************************************************************************
5260
5261
5262
5263
5264
5265
5266
5267
5268 //=================================================================================================
5269 //
5270 // CUSTOMVECTOR OPERATORS
5271 //
5272 //=================================================================================================
5273
5274 //*************************************************************************************************
5275 /*!\name CustomVector operators */
5276 //@{
5277 template< typename Type, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5278 void reset( CustomVector<Type,AF,PF,TF,Tag,RT>& v );
5279
5280 template< typename Type, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5281 void clear( CustomVector<Type,AF,PF,TF,Tag,RT>& v );
5282
5283 template< RelaxationFlag RF, typename Type, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5284 bool isDefault( const CustomVector<Type,AF,PF,TF,Tag,RT>& v );
5285
5286 template< typename Type, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5287 bool isIntact( const CustomVector<Type,AF,PF,TF,Tag,RT>& v ) noexcept;
5288
5289 template< typename Type, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5290 void swap( CustomVector<Type,AF,PF,TF,Tag,RT>& a, CustomVector<Type,AF,PF,TF,Tag,RT>& b ) noexcept;
5291 //@}
5292 //*************************************************************************************************
5293
5294
5295 //*************************************************************************************************
5296 /*!\brief Resetting the given custom vector.
5297 // \ingroup custom_vector
5298 //
5299 // \param v The custom vector to be resetted.
5300 // \return void
5301 */
5302 template< typename Type // Data type of the vector
5303 , AlignmentFlag AF // Alignment flag
5304 , PaddingFlag PF // Padding flag
5305 , bool TF // Transpose flag
5306 , typename Tag // Type tag
5307 , typename RT > // Result type
reset(CustomVector<Type,AF,PF,TF,Tag,RT> & v)5308 inline void reset( CustomVector<Type,AF,PF,TF,Tag,RT>& v )
5309 {
5310 v.reset();
5311 }
5312 //*************************************************************************************************
5313
5314
5315 //*************************************************************************************************
5316 /*!\brief Clearing the given custom vector.
5317 // \ingroup custom_vector
5318 //
5319 // \param v The custom vector to be cleared.
5320 // \return void
5321 */
5322 template< typename Type // Data type of the vector
5323 , AlignmentFlag AF // Alignment flag
5324 , PaddingFlag PF // Padding flag
5325 , bool TF // Transpose flag
5326 , typename Tag // Type tag
5327 , typename RT > // Result type
clear(CustomVector<Type,AF,PF,TF,Tag,RT> & v)5328 inline void clear( CustomVector<Type,AF,PF,TF,Tag,RT>& v )
5329 {
5330 v.clear();
5331 }
5332 //*************************************************************************************************
5333
5334
5335 //*************************************************************************************************
5336 /*!\brief Returns whether the given custom vector is in default state.
5337 // \ingroup custom_vector
5338 //
5339 // \param v The custom vector to be tested for its default state.
5340 // \return \a true in case the given vector is component-wise zero, \a false otherwise.
5341 //
5342 // This function checks whether the custom vector is in default state. For instance, in case
5343 // the static vector is instantiated for a built-in integral or floating point data type, the
5344 // function returns \a true in case all vector elements are 0 and \a false in case any vector
5345 // element is not 0. Following example demonstrates the use of the \a isDefault function:
5346
5347 \code
5348 using blaze::aligned;
5349 using blaze::padded;
5350
5351 blaze::CustomVector<int,aligned,padded> a( ... );
5352 // ... Resizing and initialization
5353 if( isDefault( a ) ) { ... }
5354 \endcode
5355
5356 // Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed
5357 // semantics (blaze::relaxed):
5358
5359 \code
5360 if( isDefault<relaxed>( a ) ) { ... }
5361 \endcode
5362 */
5363 template< RelaxationFlag RF // Relaxation flag
5364 , typename Type // Data type of the vector
5365 , AlignmentFlag AF // Alignment flag
5366 , PaddingFlag PF // Padding flag
5367 , bool TF // Transpose flag
5368 , typename Tag // Type tag
5369 , typename RT > // Result type
isDefault(const CustomVector<Type,AF,PF,TF,Tag,RT> & v)5370 inline bool isDefault( const CustomVector<Type,AF,PF,TF,Tag,RT>& v )
5371 {
5372 return ( v.size() == 0UL );
5373 }
5374 //*************************************************************************************************
5375
5376
5377 //*************************************************************************************************
5378 /*!\brief Returns whether the invariants of the given custom vector are intact.
5379 // \ingroup custom_vector
5380 //
5381 // \param v The custom vector to be tested.
5382 // \return \a true in case the given vector's invariants are intact, \a false otherwise.
5383 //
5384 // This function checks whether the invariants of the custom vector are intact, i.e. if its
5385 // state is valid. In case the invariants are intact, the function returns \a true, else it
5386 // will return \a false. The following example demonstrates the use of the \a isIntact()
5387 // function:
5388
5389 \code
5390 using blaze::aligned;
5391 using blaze::padded;
5392
5393 blaze::CustomVector<int,aligned,padded> a( ... );
5394 // ... Resizing and initialization
5395 if( isIntact( a ) ) { ... }
5396 \endcode
5397 */
5398 template< typename Type // Data type of the vector
5399 , AlignmentFlag AF // Alignment flag
5400 , PaddingFlag PF // Padding flag
5401 , bool TF // Transpose flag
5402 , typename Tag // Type tag
5403 , typename RT > // Result type
isIntact(const CustomVector<Type,AF,PF,TF,Tag,RT> & v)5404 inline bool isIntact( const CustomVector<Type,AF,PF,TF,Tag,RT>& v ) noexcept
5405 {
5406 return ( v.size() <= v.capacity() );
5407 }
5408 //*************************************************************************************************
5409
5410
5411 //*************************************************************************************************
5412 /*!\brief Swapping the contents of two vectors.
5413 // \ingroup custom_vector
5414 //
5415 // \param a The first vector to be swapped.
5416 // \param b The second vector to be swapped.
5417 // \return void
5418 */
5419 template< typename Type // Data type of the vector
5420 , AlignmentFlag AF // Alignment flag
5421 , PaddingFlag PF // Padding flag
5422 , bool TF // Transpose flag
5423 , typename Tag // Type tag
5424 , typename RT > // Result type
swap(CustomVector<Type,AF,PF,TF,Tag,RT> & a,CustomVector<Type,AF,PF,TF,Tag,RT> & b)5425 inline void swap( CustomVector<Type,AF,PF,TF,Tag,RT>& a, CustomVector<Type,AF,PF,TF,Tag,RT>& b ) noexcept
5426 {
5427 a.swap( b );
5428 }
5429 //*************************************************************************************************
5430
5431
5432
5433
5434 //=================================================================================================
5435 //
5436 // HASCONSTDATAACCESS SPECIALIZATIONS
5437 //
5438 //=================================================================================================
5439
5440 //*************************************************************************************************
5441 /*! \cond BLAZE_INTERNAL */
5442 template< typename T, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5443 struct HasConstDataAccess< CustomVector<T,AF,PF,TF,Tag,RT> >
5444 : public TrueType
5445 {};
5446 /*! \endcond */
5447 //*************************************************************************************************
5448
5449
5450
5451
5452 //=================================================================================================
5453 //
5454 // HASMUTABLEDATAACCESS SPECIALIZATIONS
5455 //
5456 //=================================================================================================
5457
5458 //*************************************************************************************************
5459 /*! \cond BLAZE_INTERNAL */
5460 template< typename T, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5461 struct HasMutableDataAccess< CustomVector<T,AF,PF,TF,Tag,RT> >
5462 : public TrueType
5463 {};
5464 /*! \endcond */
5465 //*************************************************************************************************
5466
5467
5468
5469
5470 //=================================================================================================
5471 //
5472 // ISCUSTOM SPECIALIZATIONS
5473 //
5474 //=================================================================================================
5475
5476 //*************************************************************************************************
5477 /*! \cond BLAZE_INTERNAL */
5478 template< typename T, AlignmentFlag AF, PaddingFlag PF, bool TF, typename Tag, typename RT >
5479 struct IsCustom< CustomVector<T,AF,PF,TF,Tag,RT> >
5480 : public TrueType
5481 {};
5482 /*! \endcond */
5483 //*************************************************************************************************
5484
5485
5486
5487
5488 //=================================================================================================
5489 //
5490 // ISALIGNED SPECIALIZATIONS
5491 //
5492 //=================================================================================================
5493
5494 //*************************************************************************************************
5495 /*! \cond BLAZE_INTERNAL */
5496 template< typename T, PaddingFlag PF, bool TF, typename Tag, typename RT >
5497 struct IsAligned< CustomVector<T,aligned,PF,TF,Tag,RT> >
5498 : public TrueType
5499 {};
5500 /*! \endcond */
5501 //*************************************************************************************************
5502
5503
5504
5505
5506 //=================================================================================================
5507 //
5508 // ISALIGNED SPECIALIZATIONS
5509 //
5510 //=================================================================================================
5511
5512 //*************************************************************************************************
5513 /*! \cond BLAZE_INTERNAL */
5514 template< typename T, PaddingFlag PF, bool TF, typename Tag, typename RT >
5515 struct IsContiguous< CustomVector<T,aligned,PF,TF,Tag,RT> >
5516 : public TrueType
5517 {};
5518 /*! \endcond */
5519 //*************************************************************************************************
5520
5521
5522
5523
5524 //=================================================================================================
5525 //
5526 // ISPADDED SPECIALIZATIONS
5527 //
5528 //=================================================================================================
5529
5530 //*************************************************************************************************
5531 /*! \cond BLAZE_INTERNAL */
5532 template< typename T, AlignmentFlag AF, bool TF, typename Tag, typename RT >
5533 struct IsPadded< CustomVector<T,AF,padded,TF,Tag,RT> >
5534 : public TrueType
5535 {};
5536 /*! \endcond */
5537 //*************************************************************************************************
5538
5539 } // namespace blaze
5540
5541 #endif
5542