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