1 //=================================================================================================
2 /*!
3 //  \file blaze/math/dense/StaticVector.h
4 //  \brief Header file for the implementation of a fixed-size 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_STATICVECTOR_H_
36 #define _BLAZE_MATH_DENSE_STATICVECTOR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <array>
44 #include <tuple>
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/ReductionFlag.h>
61 #include <blaze/math/RelaxationFlag.h>
62 #include <blaze/math/shims/Clear.h>
63 #include <blaze/math/shims/IsDefault.h>
64 #include <blaze/math/shims/NextMultiple.h>
65 #include <blaze/math/shims/PrevMultiple.h>
66 #include <blaze/math/shims/Serial.h>
67 #include <blaze/math/SIMD.h>
68 #include <blaze/math/traits/AddTrait.h>
69 #include <blaze/math/traits/BandTrait.h>
70 #include <blaze/math/traits/ColumnTrait.h>
71 #include <blaze/math/traits/CrossTrait.h>
72 #include <blaze/math/traits/DivTrait.h>
73 #include <blaze/math/traits/ElementsTrait.h>
74 #include <blaze/math/traits/EvaluateTrait.h>
75 #include <blaze/math/traits/KronTrait.h>
76 #include <blaze/math/traits/MapTrait.h>
77 #include <blaze/math/traits/MultTrait.h>
78 #include <blaze/math/traits/ReduceTrait.h>
79 #include <blaze/math/traits/RepeatTrait.h>
80 #include <blaze/math/traits/RowTrait.h>
81 #include <blaze/math/traits/SolveTrait.h>
82 #include <blaze/math/traits/SubTrait.h>
83 #include <blaze/math/traits/SubvectorTrait.h>
84 #include <blaze/math/typetraits/HasConstDataAccess.h>
85 #include <blaze/math/typetraits/HasMutableDataAccess.h>
86 #include <blaze/math/typetraits/HasSIMDAdd.h>
87 #include <blaze/math/typetraits/HasSIMDDiv.h>
88 #include <blaze/math/typetraits/HasSIMDMult.h>
89 #include <blaze/math/typetraits/HasSIMDSub.h>
90 #include <blaze/math/typetraits/HighType.h>
91 #include <blaze/math/typetraits/IsAligned.h>
92 #include <blaze/math/typetraits/IsColumnVector.h>
93 #include <blaze/math/typetraits/IsContiguous.h>
94 #include <blaze/math/typetraits/IsDenseMatrix.h>
95 #include <blaze/math/typetraits/IsDenseVector.h>
96 #include <blaze/math/typetraits/IsMatrix.h>
97 #include <blaze/math/typetraits/IsPadded.h>
98 #include <blaze/math/typetraits/IsRowVector.h>
99 #include <blaze/math/typetraits/IsScalar.h>
100 #include <blaze/math/typetraits/IsSIMDCombinable.h>
101 #include <blaze/math/typetraits/IsSparseVector.h>
102 #include <blaze/math/typetraits/IsSquare.h>
103 #include <blaze/math/typetraits/IsVector.h>
104 #include <blaze/math/typetraits/LowType.h>
105 #include <blaze/math/typetraits/MaxSize.h>
106 #include <blaze/math/typetraits/Size.h>
107 #include <blaze/math/typetraits/TransposeFlag.h>
108 #include <blaze/system/Inline.h>
109 #include <blaze/system/Optimizations.h>
110 #include <blaze/system/Standard.h>
111 #include <blaze/system/TransposeFlag.h>
112 #include <blaze/util/algorithms/Max.h>
113 #include <blaze/util/algorithms/Min.h>
114 #include <blaze/util/AlignedArray.h>
115 #include <blaze/util/AlignmentCheck.h>
116 #include <blaze/util/Assert.h>
117 #include <blaze/util/constraints/Const.h>
118 #include <blaze/util/constraints/Pointer.h>
119 #include <blaze/util/constraints/Reference.h>
120 #include <blaze/util/constraints/Vectorizable.h>
121 #include <blaze/util/constraints/Volatile.h>
122 #include <blaze/util/EnableIf.h>
123 #include <blaze/util/IntegralConstant.h>
124 #include <blaze/util/MaybeUnused.h>
125 #include <blaze/util/Memory.h>
126 #include <blaze/util/StaticAssert.h>
127 #include <blaze/util/Types.h>
128 #include <blaze/util/typetraits/AlignmentOf.h>
129 #include <blaze/util/typetraits/IsNumeric.h>
130 #include <blaze/util/typetraits/IsVectorizable.h>
131 #include <blaze/util/typetraits/RemoveConst.h>
132 #include <blaze/util/typetraits/RemoveCV.h>
133 
134 
135 namespace blaze {
136 
137 //=================================================================================================
138 //
139 //  CLASS DEFINITION
140 //
141 //=================================================================================================
142 
143 //*************************************************************************************************
144 /*!\defgroup static_vector StaticVector
145 // \ingroup dense_vector
146 */
147 /*!\brief Efficient implementation of a fixed-sized vector.
148 // \ingroup static_vector
149 //
150 // The StaticVector class template is the representation of a fixed-size vector with statically
151 // allocated elements of arbitrary type. The type of the elements, the number of elements, the
152 // transpose flag, the alignment, the padding, and the group tag of the vector can be specified
153 // via the six template parameters:
154 
155    \code
156    namespace blaze {
157 
158    template< typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
159    class StaticVector;
160 
161    } // namespace blaze
162    \endcode
163 
164 //  - Type: specifies the type of the vector elements. StaticVector can be used with any
165 //          non-cv-qualified, non-reference, non-pointer element type.
166 //  - N   : specifies the total number of vector elements. It is expected that StaticVector is
167 //          only used for tiny and small vectors.
168 //  - TF  : specifies whether the vector is a row vector (\c blaze::rowVector) or a column
169 //          vector (\c blaze::columnVector). The default value is \c blaze::defaultTransposeFlag.
170 //  - AF  : specifies whether the first element of the vector is properly aligned with respect to
171 //          the available instruction set (SSE, AVX, ...). Possible values are \c blaze::aligned
172 //          and \c blaze::unaligned. The default value is \c blaze::defaultAlignmentFlag.
173 //  - PF  : specifies whether the vector should be padded to maximize the efficiency of vectorized
174 //          operations. Possible values are \c blaze::padded and \c blaze::unpadded. The default
175 //          value is \c blaze::defaultPaddingFlag.
176 //  - Tag : optional type parameter to tag the vector. The default type is \c blaze::Group0.
177 //          See \ref grouping_tagging for details.
178 //
179 // These contiguously stored elements can be directly accessed with the subscript operator. The
180 // numbering of the vector elements is
181 
182                              \f[\left(\begin{array}{*{4}{c}}
183                              0 & 1 & \cdots & N-1 \\
184                              \end{array}\right)\f]
185 
186 // The use of StaticVector is very natural and intuitive. All operations (addition, subtraction,
187 // multiplication, scaling, ...) can be performed on all possible combinations of dense and sparse
188 // vectors with fitting element types. The following example gives an impression of the use of a
189 // 2-dimensional StaticVector:
190 
191    \code
192    using blaze::StaticVector;
193    using blaze::CompressedVector;
194    using blaze::StaticMatrix;
195 
196    StaticVector<double,2UL> a;  // Default initialized 2D vector
197    a[0] = 1.0;                  // Initialization of the first element
198    a[1] = 2.0;                  // Initialization of the second element
199 
200    StaticVector<double,2UL> b( 3.0, 2.0 );  // Directly initialized 2D vector
201    CompressedVector<float>  c( 2 );         // Empty sparse single precision vector
202    StaticVector<double,2UL> d;              // Default constructed static vector
203    StaticMatrix<double,2UL,2UL> A;          // Default constructed static row-major matrix
204 
205    d = a + b;  // Vector addition between vectors of equal element type
206    d = a - c;  // Vector subtraction between a dense and sparse vector with different element types
207    d = a * b;  // Component-wise vector multiplication
208 
209    a *= 2.0;      // In-place scaling of vector
210    d  = a * 2.0;  // Scaling of vector a
211    d  = 2.0 * a;  // Scaling of vector a
212 
213    d += a - b;  // Addition assignment
214    d -= a + c;  // Subtraction assignment
215    d *= a * b;  // Multiplication assignment
216 
217    double scalar = trans( a ) * b;  // Scalar/dot/inner product between two vectors
218 
219    A = a * trans( b );  // Outer product between two vectors
220    \endcode
221 */
222 template< typename Type     // Data type of the vector
223         , size_t N          // Number of elements
224         , bool TF           // Transpose flag
225         , AlignmentFlag AF  // Alignment flag
226         , PaddingFlag PF    // Padding flag
227         , typename Tag >    // Type tag
228 class StaticVector
229    : public DenseVector< StaticVector<Type,N,TF,AF,PF,Tag>, TF >
230 {
231  public:
232    //**Type definitions****************************************************************************
233    using This       = StaticVector<Type,N,TF,AF,PF,Tag>;  //!< Type of this StaticVector instance.
234    using BaseType   = DenseVector<This,TF>;               //!< Base type of this StaticVector instance.
235    using ResultType = This;                               //!< Result type for expression template evaluations.
236 
237    //! Transpose type for expression template evaluations.
238    using TransposeType = StaticVector<Type,N,!TF,AF,PF,Tag>;
239 
240    using ElementType   = Type;                      //!< Type of the vector elements.
241    using SIMDType      = SIMDTrait_t<ElementType>;  //!< SIMD type of the vector elements.
242    using TagType       = Tag;                       //!< Tag type of this StaticVector instance.
243    using ReturnType    = const Type&;               //!< Return type for expression template evaluations.
244    using CompositeType = const StaticVector&;       //!< Data type for composite expression templates.
245 
246    using Reference      = Type&;        //!< Reference to a non-constant vector value.
247    using ConstReference = const Type&;  //!< Reference to a constant vector value.
248    using Pointer        = Type*;        //!< Pointer to a non-constant vector value.
249    using ConstPointer   = const Type*;  //!< Pointer to a constant vector value.
250 
251    using Iterator      = DenseIterator<Type,AF>;        //!< Iterator over non-constant elements.
252    using ConstIterator = DenseIterator<const Type,AF>;  //!< Iterator over constant elements.
253    //**********************************************************************************************
254 
255    //**Rebind struct definition********************************************************************
256    /*!\brief Rebind mechanism to obtain a StaticVector with different data/element type.
257    */
258    template< typename NewType >  // Data type of the other vector
259    struct Rebind {
260       using Other = StaticVector<NewType,N,TF,AF,PF,Tag>;  //!< The type of the other StaticVector.
261    };
262    //**********************************************************************************************
263 
264    //**Resize struct definition********************************************************************
265    /*!\brief Resize mechanism to obtain a StaticVector with a different fixed number of elements.
266    */
267    template< size_t NewN >  // Number of elements of the other vector
268    struct Resize {
269       using Other = StaticVector<Type,NewN,TF,AF,PF,Tag>;  //!< The type of the other StaticVector.
270    };
271    //**********************************************************************************************
272 
273    //**Compilation flags***************************************************************************
274    //! Compilation flag for SIMD optimization.
275    /*! The \a simdEnabled compilation flag indicates whether expressions the vector is involved
276        in can be optimized via SIMD operations. In case the element type of the vector is a
277        vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
278        it is set to \a false. */
279    static constexpr bool simdEnabled = IsVectorizable_v<Type>;
280 
281    //! Compilation flag for SMP assignments.
282    /*! The \a smpAssignable compilation flag indicates whether the vector can be used in SMP
283        (shared memory parallel) assignments (both on the left-hand and right-hand side of the
284        assignment). */
285    static constexpr bool smpAssignable = false;
286    //**********************************************************************************************
287 
288    //**Constructors********************************************************************************
289    /*!\name Constructors */
290    //@{
291             inline    StaticVector();
292    explicit inline    StaticVector( const Type& init );
293             constexpr StaticVector( initializer_list<Type> list );
294 
295    template< typename Other >
296    inline StaticVector( size_t n, const Other* array );
297 
298    template< typename Other, size_t Dim >
299    constexpr StaticVector( const Other (&array)[Dim] );
300 
301    template< typename Other, size_t Dim >
302    constexpr StaticVector( const std::array<Other,Dim>& array );
303 
304    constexpr StaticVector( const StaticVector& v );
305 
306    template< typename Other, AlignmentFlag AF2, PaddingFlag PF2 >
307    inline StaticVector( const StaticVector<Other,N,TF,AF2,PF2,Tag>& v );
308 
309    template< typename VT >
310    inline StaticVector( const Vector<VT,TF>& v );
311    //@}
312    //**********************************************************************************************
313 
314    //**Destructor**********************************************************************************
315    /*!\name Destructor */
316    //@{
317    ~StaticVector() = default;
318    //@}
319    //**********************************************************************************************
320 
321    //**Data access functions***********************************************************************
322    /*!\name Data access functions */
323    //@{
324    constexpr Reference      operator[]( size_t index ) noexcept;
325    constexpr ConstReference operator[]( size_t index ) const noexcept;
326    inline    Reference      at( size_t index );
327    inline    ConstReference at( size_t index ) const;
328    constexpr Pointer        data  () noexcept;
329    constexpr ConstPointer   data  () const noexcept;
330    constexpr Iterator       begin () noexcept;
331    constexpr ConstIterator  begin () const noexcept;
332    constexpr ConstIterator  cbegin() const noexcept;
333    constexpr Iterator       end   () noexcept;
334    constexpr ConstIterator  end   () const noexcept;
335    constexpr ConstIterator  cend  () const noexcept;
336    //@}
337    //**********************************************************************************************
338 
339    //**Assignment operators************************************************************************
340    /*!\name Assignment operators */
341    //@{
342    constexpr StaticVector& operator=( const Type& rhs ) &;
343    constexpr StaticVector& operator=( initializer_list<Type> list ) &;
344 
345    template< typename Other, size_t Dim >
346    constexpr StaticVector& operator=( const Other (&array)[Dim] ) &;
347 
348    template< typename Other, size_t Dim >
349    constexpr StaticVector& operator=( const std::array<Other,Dim>& array ) &;
350 
351    constexpr StaticVector& operator=( const StaticVector& rhs ) &;
352 
353    template< typename Other, AlignmentFlag AF2, PaddingFlag PF2 >
354    inline StaticVector& operator=( const StaticVector<Other,N,TF,AF2,PF2,Tag>& rhs ) &;
355 
356    template< typename VT > inline StaticVector& operator= ( const Vector<VT,TF>& rhs ) &;
357    template< typename VT > inline StaticVector& operator+=( const Vector<VT,TF>& rhs ) &;
358    template< typename VT > inline StaticVector& operator-=( const Vector<VT,TF>& rhs ) &;
359    template< typename VT > inline StaticVector& operator*=( const Vector<VT,TF>& rhs ) &;
360    template< typename VT > inline StaticVector& operator/=( const DenseVector<VT,TF>& rhs ) &;
361    template< typename VT > inline StaticVector& operator%=( const Vector<VT,TF>& rhs ) &;
362    //@}
363    //**********************************************************************************************
364 
365    //**Utility functions***************************************************************************
366    /*!\name Utility functions */
367    //@{
368    static constexpr size_t size() noexcept;
369    static constexpr size_t spacing() noexcept;
370    static constexpr size_t capacity() noexcept;
371           inline    size_t nonZeros() const;
372           constexpr void   reset();
373           inline    void   swap( StaticVector& v ) noexcept;
374    //@}
375    //**********************************************************************************************
376 
377    //**Numeric functions***************************************************************************
378    /*!\name Numeric functions */
379    //@{
380    template< typename Other > inline StaticVector& scale( const Other& scalar );
381    //@}
382    //**********************************************************************************************
383 
384    //**Memory functions****************************************************************************
385    /*!\name Memory functions */
386    //@{
387    static inline void* operator new  ( std::size_t size );
388    static inline void* operator new[]( std::size_t size );
389    static inline void* operator new  ( std::size_t size, const std::nothrow_t& );
390    static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
391 
392    static inline void operator delete  ( void* ptr );
393    static inline void operator delete[]( void* ptr );
394    static inline void operator delete  ( void* ptr, const std::nothrow_t& );
395    static inline void operator delete[]( void* ptr, const std::nothrow_t& );
396    //@}
397    //**********************************************************************************************
398 
399  private:
400    //**********************************************************************************************
401    //! The number of elements packed within a single SIMD vector.
402    static constexpr size_t SIMDSIZE = SIMDTrait<Type>::size;
403 
404    //! Alignment adjustment.
405    static constexpr size_t NN = ( PF == padded ? nextMultiple( N, SIMDSIZE ) : N );
406    //**********************************************************************************************
407 
408    //**********************************************************************************************
409    /*! \cond BLAZE_INTERNAL */
410    //! Helper variable template for the explicit application of the SFINAE principle.
411    template< typename VT >
412    static constexpr bool VectorizedAssign_v =
413       ( useOptimizedKernels &&
414         NN >= SIMDSIZE &&
415         simdEnabled && VT::simdEnabled &&
416         IsSIMDCombinable_v< Type, ElementType_t<VT> > );
417    /*! \endcond */
418    //**********************************************************************************************
419 
420    //**********************************************************************************************
421    /*! \cond BLAZE_INTERNAL */
422    //! Helper variable template for the explicit application of the SFINAE principle.
423    template< typename VT >
424    static constexpr bool VectorizedAddAssign_v =
425       ( VectorizedAssign_v<VT> &&
426         HasSIMDAdd_v< Type, ElementType_t<VT> > );
427    /*! \endcond */
428    //**********************************************************************************************
429 
430    //**********************************************************************************************
431    /*! \cond BLAZE_INTERNAL */
432    //! Helper variable template for the explicit application of the SFINAE principle.
433    template< typename VT >
434    static constexpr bool VectorizedSubAssign_v =
435       ( VectorizedAssign_v<VT> &&
436         HasSIMDSub_v< Type, ElementType_t<VT> > );
437    /*! \endcond */
438    //**********************************************************************************************
439 
440    //**********************************************************************************************
441    /*! \cond BLAZE_INTERNAL */
442    //! Helper variable template for the explicit application of the SFINAE principle.
443    template< typename VT >
444    static constexpr bool VectorizedMultAssign_v =
445       ( VectorizedAssign_v<VT> &&
446         HasSIMDMult_v< Type, ElementType_t<VT> > );
447    /*! \endcond */
448    //**********************************************************************************************
449 
450    //**********************************************************************************************
451    /*! \cond BLAZE_INTERNAL */
452    //! Helper variable template for the explicit application of the SFINAE principle.
453    template< typename VT >
454    static constexpr bool VectorizedDivAssign_v =
455       ( VectorizedAssign_v<VT> &&
456         HasSIMDDiv_v< Type, ElementType_t<VT> > );
457    /*! \endcond */
458    //**********************************************************************************************
459 
460  public:
461    //**Debugging functions*************************************************************************
462    /*!\name Debugging functions */
463    //@{
464    constexpr bool isIntact() const noexcept;
465    //@}
466    //**********************************************************************************************
467 
468    //**Expression template evaluation functions****************************************************
469    /*!\name Expression template evaluation functions */
470    //@{
471    template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
472    template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
473 
474    static constexpr bool isAligned() noexcept;
475 
476    BLAZE_ALWAYS_INLINE SIMDType load ( size_t index ) const noexcept;
477    BLAZE_ALWAYS_INLINE SIMDType loada( size_t index ) const noexcept;
478    BLAZE_ALWAYS_INLINE SIMDType loadu( size_t index ) const noexcept;
479 
480    BLAZE_ALWAYS_INLINE void store ( size_t index, const SIMDType& value ) noexcept;
481    BLAZE_ALWAYS_INLINE void storea( size_t index, const SIMDType& value ) noexcept;
482    BLAZE_ALWAYS_INLINE void storeu( size_t index, const SIMDType& value ) noexcept;
483    BLAZE_ALWAYS_INLINE void stream( size_t index, const SIMDType& value ) noexcept;
484 
485    template< typename VT >
486    inline auto assign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedAssign_v<VT> >;
487 
488    template< typename VT >
489    inline auto assign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedAssign_v<VT> >;
490 
491    template< typename VT > inline void assign( const SparseVector<VT,TF>& rhs );
492 
493    template< typename VT >
494    inline auto addAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<VT> >;
495 
496    template< typename VT >
497    inline auto addAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<VT> >;
498 
499    template< typename VT > inline void addAssign( const SparseVector<VT,TF>& rhs );
500 
501    template< typename VT >
502    inline auto subAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<VT> >;
503 
504    template< typename VT >
505    inline auto subAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<VT> >;
506 
507    template< typename VT > inline void subAssign( const SparseVector<VT,TF>& rhs );
508 
509    template< typename VT >
510    inline auto multAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedMultAssign_v<VT> >;
511 
512    template< typename VT >
513    inline auto multAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedMultAssign_v<VT> >;
514 
515    template< typename VT > inline void multAssign( const SparseVector<VT,TF>& rhs );
516 
517    template< typename VT >
518    inline auto divAssign( const DenseVector<VT,TF>& rhs ) -> DisableIf_t< VectorizedDivAssign_v<VT> >;
519 
520    template< typename VT >
521    inline auto divAssign( const DenseVector<VT,TF>& rhs ) -> EnableIf_t< VectorizedDivAssign_v<VT> >;
522    //@}
523    //**********************************************************************************************
524 
525  private:
526    //**********************************************************************************************
527    //! Alignment of the data elements.
528    static constexpr size_t Alignment =
529       ( AF == aligned ? AlignmentOf_v<Type> : std::alignment_of<Type>::value );
530 
531    //! Type of the aligned storage.
532    using AlignedStorage = AlignedArray<Type,NN,Alignment>;
533    //**********************************************************************************************
534 
535    //**Member variables****************************************************************************
536    /*!\name Member variables */
537    //@{
538    AlignedStorage v_;  //!< The statically allocated vector elements.
539                        /*!< Access to the vector values is gained via the subscript operator.
540                             The order of the elements is
541                             \f[\left(\begin{array}{*{4}{c}}
542                             0 & 1 & \cdots & N-1 \\
543                             \end{array}\right)\f] */
544    //@}
545    //**********************************************************************************************
546 
547    //**Compile time checks*************************************************************************
548    /*! \cond BLAZE_INTERNAL */
549    BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE  ( Type );
550    BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
551    BLAZE_CONSTRAINT_MUST_NOT_BE_CONST         ( Type );
552    BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE      ( Type );
553    BLAZE_STATIC_ASSERT( PF == unpadded || ( NN % SIMDSIZE == 0UL ) );
554    BLAZE_STATIC_ASSERT( NN >= N );
555    BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
556    /*! \endcond */
557    //**********************************************************************************************
558 };
559 //*************************************************************************************************
560 
561 
562 
563 
564 //=================================================================================================
565 //
566 //  DEDUCTION GUIDES
567 //
568 //=================================================================================================
569 
570 //*************************************************************************************************
571 #if BLAZE_CPP17_MODE
572 
573 template< typename Type, typename... Ts >
574 StaticVector( Type, Ts... ) -> StaticVector<Type,1+sizeof...(Ts)>;
575 
576 template< typename Type, size_t N >
577 StaticVector( Type (&)[N] ) -> StaticVector< RemoveCV_t<Type>, N >;
578 
579 template< typename Type, size_t N >
580 StaticVector( std::array<Type,N> ) -> StaticVector<Type,N>;
581 
582 #endif
583 //*************************************************************************************************
584 
585 
586 
587 
588 //=================================================================================================
589 //
590 //  CONSTRUCTORS
591 //
592 //=================================================================================================
593 
594 //*************************************************************************************************
595 /*!\brief The default constructor for StaticVector.
596 //
597 // All vector elements are initialized to the default value (i.e. 0 for integral data types).
598 //
599 // Note that it is possible to skip the default initialization by means of the
600 // \a BLAZE_USE_DEFAULT_INITIALIZATION configuration switch. In case the switch is set to 1
601 // all elements are initialized to their respective default. In case the switch is set to 0 the
602 // default initialization is skipped and the elements are not initialized. Please note that this
603 // switch is only effective in case the elements are of fundamental type (i.e. integral or
604 // floating point). In case the elements are of class type, this switch has no effect. See
605 // the <tt><blaze/config/Optimizations.h></tt> configuration file for more details.
606 */
607 template< typename Type     // Data type of the vector
608         , size_t N          // Number of elements
609         , bool TF           // Transpose flag
610         , AlignmentFlag AF  // Alignment flag
611         , PaddingFlag PF    // Padding flag
612         , typename Tag >    // Type tag
StaticVector()613 inline StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector()
614 #if BLAZE_USE_DEFAULT_INITIALIZATION
615    : v_()  // The statically allocated vector elements
616 #endif
617 {
618 #if !BLAZE_USE_DEFAULT_INITIALIZATION
619    using blaze::clear;
620 
621    if( IsNumeric_v<Type> && PF == unpadded ) {
622       for( size_t i=N; i<NN; ++i )
623          clear( v_[i] );
624    }
625 #endif
626 
627    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
628 }
629 //*************************************************************************************************
630 
631 
632 //*************************************************************************************************
633 /*!\brief Constructor for a homogenous initialization of all elements.
634 //
635 // \param init Initial value for all vector elements.
636 */
637 template< typename Type     // Data type of the vector
638         , size_t N          // Number of elements
639         , bool TF           // Transpose flag
640         , AlignmentFlag AF  // Alignment flag
641         , PaddingFlag PF    // Padding flag
642         , typename Tag >    // Type tag
StaticVector(const Type & init)643 inline StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( const Type& init )
644    // v_ is intentionally left uninitialized
645 {
646    using blaze::clear;
647 
648    for( size_t i=0UL; i<N; ++i )
649       v_[i] = init;
650 
651    for( size_t i=N; i<NN; ++i )
652       clear( v_[i] );
653 
654    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
655 }
656 //*************************************************************************************************
657 
658 
659 //*************************************************************************************************
660 /*!\brief List initialization of all vector elements.
661 //
662 // \param list The initializer list.
663 // \exception std::invalid_argument Invalid setup of static vector.
664 //
665 // This constructor provides the option to explicitly initialize the elements of the vector by
666 // means of an initializer list:
667 
668    \code
669    blaze::StaticVector<double,3UL> v1{ 4.2, 6.3, -1.2 };
670    \endcode
671 
672 // The vector elements are (copy) assigned the values of the given initializer list. Missing values
673 // are initialized as default. Note that in case the size of the initializer list exceeds the size
674 // of the vector, a \a std::invalid_argument exception is thrown.
675 */
676 template< typename Type     // Data type of the vector
677         , size_t N          // Number of elements
678         , bool TF           // Transpose flag
679         , AlignmentFlag AF  // Alignment flag
680         , PaddingFlag PF    // Padding flag
681         , typename Tag >    // Type tag
StaticVector(initializer_list<Type> list)682 constexpr StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( initializer_list<Type> list )
683    : v_()  // The statically allocated vector elements
684 {
685    if( list.size() > N ) {
686       BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" );
687    }
688 
689    size_t i( 0UL );
690 
691    for( const auto& element : list ) {
692       v_[i] = element;
693       ++i;
694    }
695 
696    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
697 }
698 //*************************************************************************************************
699 
700 
701 //*************************************************************************************************
702 /*!\brief Array initialization of all vector elements.
703 //
704 // \param n The size of the vector.
705 // \param array Dynamic array for the initialization.
706 //
707 // This constructor offers the option to directly initialize the elements of the vector with a
708 // dynamic array:
709 
710    \code
711    const double array* = new double[2];
712    // ... Initialization of the array
713    blaze::StaticVector<double,2> v( 2UL, array );
714    delete[] array;
715    \endcode
716 
717 // The vector is initialized with the values from the given array. Missing values are initialized
718 // with default values. In case the size of the given vector exceeds the maximum size of the
719 // static vector (i.e. is larger than N), a \a std::invalid_argument exception is thrown.\n
720 // Note that it is expected that the given \a array has at least \a n elements. Providing an
721 // array with less elements results in undefined behavior!
722 */
723 template< typename Type     // Data type of the vector
724         , size_t N          // Number of elements
725         , bool TF           // Transpose flag
726         , AlignmentFlag AF  // Alignment flag
727         , PaddingFlag PF    // Padding flag
728         , typename Tag >    // Type tag
729 template< typename Other >  // Data type of the initialization array
StaticVector(size_t n,const Other * array)730 inline StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( size_t n, const Other* array )
731    // v_ is intentionally left uninitialized
732 {
733    using blaze::clear;
734 
735    if( n > N ) {
736       BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" );
737    }
738 
739    for( size_t i=0UL; i<n; ++i )
740       v_[i] = array[i];
741 
742    if( IsNumeric_v<Type> ) {
743       for( size_t i=n; i<NN; ++i )
744          clear( v_[i] );
745    }
746 
747    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
748 }
749 //*************************************************************************************************
750 
751 
752 //*************************************************************************************************
753 /*!\brief Array initialization of all vector elements.
754 //
755 // \param array Static array for the initialization.
756 //
757 // This constructor operator offers the option to directly initialize the elements of the vector
758 // with a static array:
759 
760    \code
761    const double init[3] = { 1.0, 2.0 };
762    blaze::StaticVector<double,3> v( init );
763    \endcode
764 
765 // The vector is initialized with the values from the given static array. Whereas the dimensions
766 // of the vector and the static array must match, it is allowed to provide fewer initializers for
767 // the static array. Missing values are initialized with default values (as e.g. the third value
768 // in the example).
769 */
770 template< typename Type     // Data type of the vector
771         , size_t N          // Number of elements
772         , bool TF           // Transpose flag
773         , AlignmentFlag AF  // Alignment flag
774         , PaddingFlag PF    // Padding flag
775         , typename Tag >    // Type tag
776 template< typename Other    // Data type of the static array
777         , size_t Dim >      // Dimension of the static array
StaticVector(const Other (& array)[Dim])778 constexpr StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( const Other (&array)[Dim] )
779    : v_( array )  // The statically allocated vector elements
780 {
781    BLAZE_STATIC_ASSERT( Dim == N );
782 
783    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
784 }
785 //*************************************************************************************************
786 
787 
788 //*************************************************************************************************
789 /*!\brief Initialization of all vector elements from the given std::array.
790 //
791 // \param array The given std::array for the initialization.
792 //
793 // This constructor operator offers the option to directly initialize the elements of the vector
794 // with a std::array:
795 
796    \code
797    std::array<double,3> init{ 1.0, 2.0 };
798    blaze::StaticVector<double,3> v( init );
799    \endcode
800 
801 // The vector is initialized with the values from the given std::array. Whereas the dimensions
802 // of the vector and the std::array must match, it is allowed to provide fewer initializers for
803 // the std::array. Missing values are initialized with default values (as e.g. the third value
804 // in the example).
805 */
806 template< typename Type     // Data type of the vector
807         , size_t N          // Number of elements
808         , bool TF           // Transpose flag
809         , AlignmentFlag AF  // Alignment flag
810         , PaddingFlag PF    // Padding flag
811         , typename Tag >    // Type tag
812 template< typename Other    // Data type of the std::array
813         , size_t Dim >      // Dimension of the std::array
StaticVector(const std::array<Other,Dim> & array)814 constexpr StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( const std::array<Other,Dim>& array )
815    : v_( array )  // The statically allocated vector elements
816 {
817    BLAZE_STATIC_ASSERT( Dim == N );
818 
819    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
820 }
821 //*************************************************************************************************
822 
823 
824 //*************************************************************************************************
825 /*!\brief The copy constructor for StaticVector.
826 //
827 // \param v Vector to be copied.
828 //
829 // The copy constructor is explicitly defined in order to enable/facilitate NRV optimization.
830 */
831 template< typename Type     // Data type of the vector
832         , size_t N          // Number of elements
833         , bool TF           // Transpose flag
834         , AlignmentFlag AF  // Alignment flag
835         , PaddingFlag PF    // Padding flag
836         , typename Tag >    // Type tag
StaticVector(const StaticVector & v)837 constexpr StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( const StaticVector& v )
838    : BaseType()  // Initialization of the base class
839    , v_( v.v_ )  // The statically allocated vector elements
840 {
841    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
842 }
843 //*************************************************************************************************
844 
845 
846 //*************************************************************************************************
847 /*!\brief Conversion constructor from different StaticVector instances.
848 //
849 // \param v Vector to be copied.
850 */
851 template< typename Type      // Data type of the vector
852         , size_t N           // Number of elements
853         , bool TF            // Transpose flag
854         , AlignmentFlag AF   // Alignment flag
855         , PaddingFlag PF     // Padding flag
856         , typename Tag >     // Type tag
857 template< typename Other     // Data type of the foreign vector
858         , AlignmentFlag AF2  // Alignment flag of the foreign vector
859         , PaddingFlag PF2 >  // Padding flag of the foreign vector
StaticVector(const StaticVector<Other,N,TF,AF2,PF2,Tag> & v)860 inline StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( const StaticVector<Other,N,TF,AF2,PF2,Tag>& v )
861    // v_ is intentionally left uninitialized
862 {
863    using blaze::clear;
864 
865    for( size_t i=0UL; i<N; ++i )
866       v_[i] = v[i];
867 
868    for( size_t i=N; i<NN; ++i )
869       clear( v_[i] );
870 
871    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
872 }
873 //*************************************************************************************************
874 
875 
876 //*************************************************************************************************
877 /*!\brief Conversion constructor from different vectors.
878 //
879 // \param v Vector to be copied.
880 // \exception std::invalid_argument Invalid setup of static vector.
881 //
882 // This constructor initializes the static vector from the given vector. In case the size
883 // of the given vector does not match the size of the static vector (i.e. is not N), a
884 // \a std::invalid_argument exception is thrown.
885 */
886 template< typename Type     // Data type of the vector
887         , size_t N          // Number of elements
888         , bool TF           // Transpose flag
889         , AlignmentFlag AF  // Alignment flag
890         , PaddingFlag PF    // Padding flag
891         , typename Tag >    // Type tag
892 template< typename VT >     // Type of the foreign vector
StaticVector(const Vector<VT,TF> & v)893 inline StaticVector<Type,N,TF,AF,PF,Tag>::StaticVector( const Vector<VT,TF>& v )
894    // v_ is intentionally left uninitialized
895 {
896    using blaze::assign;
897    using blaze::clear;
898 
899    BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
900 
901    if( (*v).size() != N ) {
902       BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" );
903    }
904 
905    for( size_t i=( IsSparseVector_v<VT> ? 0UL : N ); i<NN; ++i ) {
906       clear( v_[i] );
907    }
908 
909    assign( *this, *v );
910 
911    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
912 }
913 //*************************************************************************************************
914 
915 
916 
917 
918 //=================================================================================================
919 //
920 //  DATA ACCESS FUNCTIONS
921 //
922 //=================================================================================================
923 
924 //*************************************************************************************************
925 /*!\brief Subscript operator for the direct access to the vector elements.
926 //
927 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
928 // \return Reference to the accessed value.
929 //
930 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
931 // the at() function is guaranteed to perform a check of the given access index.
932 */
933 template< typename Type     // Data type of the vector
934         , size_t N          // Number of elements
935         , bool TF           // Transpose flag
936         , AlignmentFlag AF  // Alignment flag
937         , PaddingFlag PF    // Padding flag
938         , typename Tag >    // Type tag
939 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::Reference
940    StaticVector<Type,N,TF,AF,PF,Tag>::operator[]( size_t index ) noexcept
941 {
942    BLAZE_USER_ASSERT( index < N, "Invalid vector access index" );
943    return v_[index];
944 }
945 //*************************************************************************************************
946 
947 
948 //*************************************************************************************************
949 /*!\brief Subscript operator for the direct access to the vector elements.
950 //
951 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
952 // \return Reference-to-const to the accessed value.
953 //
954 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
955 // the at() function is guaranteed to perform a check of the given access index.
956 */
957 template< typename Type     // Data type of the vector
958         , size_t N          // Number of elements
959         , bool TF           // Transpose flag
960         , AlignmentFlag AF  // Alignment flag
961         , PaddingFlag PF    // Padding flag
962         , typename Tag >    // Type tag
963 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::ConstReference
964    StaticVector<Type,N,TF,AF,PF,Tag>::operator[]( size_t index ) const noexcept
965 {
966    BLAZE_USER_ASSERT( index < N, "Invalid vector access index" );
967    return v_[index];
968 }
969 //*************************************************************************************************
970 
971 
972 //*************************************************************************************************
973 /*!\brief Checked access to the vector elements.
974 //
975 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
976 // \return Reference to the accessed value.
977 // \exception std::out_of_range Invalid vector access index.
978 //
979 // In contrast to the subscript operator this function always performs a check of the given
980 // access index.
981 */
982 template< typename Type     // Data type of the vector
983         , size_t N          // Number of elements
984         , bool TF           // Transpose flag
985         , AlignmentFlag AF  // Alignment flag
986         , PaddingFlag PF    // Padding flag
987         , typename Tag >    // Type tag
988 inline typename StaticVector<Type,N,TF,AF,PF,Tag>::Reference
at(size_t index)989    StaticVector<Type,N,TF,AF,PF,Tag>::at( size_t index )
990 {
991    if( index >= N ) {
992       BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
993    }
994    return (*this)[index];
995 }
996 //*************************************************************************************************
997 
998 
999 //*************************************************************************************************
1000 /*!\brief Checked access to the vector elements.
1001 //
1002 // \param index Access index. The index has to be in the range \f$[0..N-1]\f$.
1003 // \return Reference to the accessed value.
1004 // \exception std::out_of_range Invalid vector access index.
1005 //
1006 // In contrast to the subscript operator this function always performs a check of the given
1007 // access index.
1008 */
1009 template< typename Type     // Data type of the vector
1010         , size_t N          // Number of elements
1011         , bool TF           // Transpose flag
1012         , AlignmentFlag AF  // Alignment flag
1013         , PaddingFlag PF    // Padding flag
1014         , typename Tag >    // Type tag
1015 inline typename StaticVector<Type,N,TF,AF,PF,Tag>::ConstReference
at(size_t index)1016    StaticVector<Type,N,TF,AF,PF,Tag>::at( size_t index ) const
1017 {
1018    if( index >= N ) {
1019       BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
1020    }
1021    return (*this)[index];
1022 }
1023 //*************************************************************************************************
1024 
1025 
1026 //*************************************************************************************************
1027 /*!\brief Low-level data access to the vector elements.
1028 //
1029 // \return Pointer to the internal element storage.
1030 //
1031 // This function returns a pointer to the internal storage of the static vector.
1032 */
1033 template< typename Type     // Data type of the vector
1034         , size_t N          // Number of elements
1035         , bool TF           // Transpose flag
1036         , AlignmentFlag AF  // Alignment flag
1037         , PaddingFlag PF    // Padding flag
1038         , typename Tag >    // Type tag
1039 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::Pointer
data()1040    StaticVector<Type,N,TF,AF,PF,Tag>::data() noexcept
1041 {
1042    return v_;
1043 }
1044 //*************************************************************************************************
1045 
1046 
1047 //*************************************************************************************************
1048 /*!\brief Low-level data access to the vector elements.
1049 //
1050 // \return Pointer to the internal element storage.
1051 //
1052 // This function returns a pointer to the internal storage of the static vector.
1053 */
1054 template< typename Type     // Data type of the vector
1055         , size_t N          // Number of elements
1056         , bool TF           // Transpose flag
1057         , AlignmentFlag AF  // Alignment flag
1058         , PaddingFlag PF    // Padding flag
1059         , typename Tag >    // Type tag
1060 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::ConstPointer
data()1061    StaticVector<Type,N,TF,AF,PF,Tag>::data() const noexcept
1062 {
1063    return v_;
1064 }
1065 //*************************************************************************************************
1066 
1067 
1068 //*************************************************************************************************
1069 /*!\brief Returns an iterator to the first element of the static vector.
1070 //
1071 // \return Iterator to the first element of the static vector.
1072 */
1073 template< typename Type     // Data type of the vector
1074         , size_t N          // Number of elements
1075         , bool TF           // Transpose flag
1076         , AlignmentFlag AF  // Alignment flag
1077         , PaddingFlag PF    // Padding flag
1078         , typename Tag >    // Type tag
1079 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::Iterator
begin()1080    StaticVector<Type,N,TF,AF,PF,Tag>::begin() noexcept
1081 {
1082    return Iterator( v_ );
1083 }
1084 //*************************************************************************************************
1085 
1086 
1087 //*************************************************************************************************
1088 /*!\brief Returns an iterator to the first element of the static vector.
1089 //
1090 // \return Iterator to the first element of the static vector.
1091 */
1092 template< typename Type     // Data type of the vector
1093         , size_t N          // Number of elements
1094         , bool TF           // Transpose flag
1095         , AlignmentFlag AF  // Alignment flag
1096         , PaddingFlag PF    // Padding flag
1097         , typename Tag >    // Type tag
1098 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::ConstIterator
begin()1099    StaticVector<Type,N,TF,AF,PF,Tag>::begin() const noexcept
1100 {
1101    return ConstIterator( v_ );
1102 }
1103 //*************************************************************************************************
1104 
1105 
1106 //*************************************************************************************************
1107 /*!\brief Returns an iterator to the first element of the static vector.
1108 //
1109 // \return Iterator to the first element of the static vector.
1110 */
1111 template< typename Type     // Data type of the vector
1112         , size_t N          // Number of elements
1113         , bool TF           // Transpose flag
1114         , AlignmentFlag AF  // Alignment flag
1115         , PaddingFlag PF    // Padding flag
1116         , typename Tag >    // Type tag
1117 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::ConstIterator
cbegin()1118    StaticVector<Type,N,TF,AF,PF,Tag>::cbegin() const noexcept
1119 {
1120    return ConstIterator( v_ );
1121 }
1122 //*************************************************************************************************
1123 
1124 
1125 //*************************************************************************************************
1126 /*!\brief Returns an iterator just past the last element of the static vector.
1127 //
1128 // \return Iterator just past the last element of the static vector.
1129 */
1130 template< typename Type     // Data type of the vector
1131         , size_t N          // Number of elements
1132         , bool TF           // Transpose flag
1133         , AlignmentFlag AF  // Alignment flag
1134         , PaddingFlag PF    // Padding flag
1135         , typename Tag >    // Type tag
1136 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::Iterator
end()1137    StaticVector<Type,N,TF,AF,PF,Tag>::end() noexcept
1138 {
1139    return Iterator( v_ + N );
1140 }
1141 //*************************************************************************************************
1142 
1143 
1144 //*************************************************************************************************
1145 /*!\brief Returns an iterator just past the last element of the static vector.
1146 //
1147 // \return Iterator just past the last element of the static vector.
1148 */
1149 template< typename Type     // Data type of the vector
1150         , size_t N          // Number of elements
1151         , bool TF           // Transpose flag
1152         , AlignmentFlag AF  // Alignment flag
1153         , PaddingFlag PF    // Padding flag
1154         , typename Tag >    // Type tag
1155 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::ConstIterator
end()1156    StaticVector<Type,N,TF,AF,PF,Tag>::end() const noexcept
1157 {
1158    return ConstIterator( v_ + N );
1159 }
1160 //*************************************************************************************************
1161 
1162 
1163 //*************************************************************************************************
1164 /*!\brief Returns an iterator just past the last element of the static vector.
1165 //
1166 // \return Iterator just past the last element of the static vector.
1167 */
1168 template< typename Type     // Data type of the vector
1169         , size_t N          // Number of elements
1170         , bool TF           // Transpose flag
1171         , AlignmentFlag AF  // Alignment flag
1172         , PaddingFlag PF    // Padding flag
1173         , typename Tag >    // Type tag
1174 constexpr typename StaticVector<Type,N,TF,AF,PF,Tag>::ConstIterator
cend()1175    StaticVector<Type,N,TF,AF,PF,Tag>::cend() const noexcept
1176 {
1177    return ConstIterator( v_ + N );
1178 }
1179 //*************************************************************************************************
1180 
1181 
1182 
1183 
1184 //=================================================================================================
1185 //
1186 //  ASSIGNMENT OPERATORS
1187 //
1188 //=================================================================================================
1189 
1190 //*************************************************************************************************
1191 /*!\brief Homogenous assignment to all vector elements.
1192 //
1193 // \param rhs Scalar value to be assigned to all vector elements.
1194 // \return Reference to the assigned vector.
1195 */
1196 template< typename Type     // Data type of the vector
1197         , size_t N          // Number of elements
1198         , bool TF           // Transpose flag
1199         , AlignmentFlag AF  // Alignment flag
1200         , PaddingFlag PF    // Padding flag
1201         , typename Tag >    // Type tag
1202 constexpr StaticVector<Type,N,TF,AF,PF,Tag>&
1203    StaticVector<Type,N,TF,AF,PF,Tag>::operator=( const Type& rhs ) &
1204 {
1205    for( size_t i=0UL; i<N; ++i )
1206       v_[i] = rhs;
1207    return *this;
1208 }
1209 //*************************************************************************************************
1210 
1211 
1212 //*************************************************************************************************
1213 /*!\brief List assignment to all vector elements.
1214 //
1215 // \param list The initializer list.
1216 // \exception std::invalid_argument Invalid assignment to static vector.
1217 //
1218 // This assignment operator offers the option to directly assign to all elements of the vector
1219 // by means of an initializer list:
1220 
1221    \code
1222    blaze::StaticVector<double,3UL> v;
1223    v = { 4.2, 6.3, -1.2 };
1224    \endcode
1225 
1226 // The vector elements are (copy) assigned the values from the given initializer list. Missing
1227 // values are reset to their default state. Note that in case the size of the initializer list
1228 // exceeds the size of the vector, a \a std::invalid_argument exception is thrown.
1229 */
1230 template< typename Type     // Data type of the vector
1231         , size_t N          // Number of elements
1232         , bool TF           // Transpose flag
1233         , AlignmentFlag AF  // Alignment flag
1234         , PaddingFlag PF    // Padding flag
1235         , typename Tag >    // Type tag
1236 constexpr StaticVector<Type,N,TF,AF,PF,Tag>&
1237    StaticVector<Type,N,TF,AF,PF,Tag>::operator=( initializer_list<Type> list ) &
1238 {
1239    using blaze::clear;
1240 
1241    if( list.size() > N ) {
1242       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static vector" );
1243    }
1244 
1245    size_t i( 0UL );
1246 
1247    for( const auto& element : list ) {
1248       v_[i] = element;
1249       ++i;
1250    }
1251 
1252    for( ; i<N; ++i ) {
1253       clear( v_[i] );
1254    }
1255 
1256    return *this;
1257 }
1258 //*************************************************************************************************
1259 
1260 
1261 //*************************************************************************************************
1262 /*!\brief Array assignment to all vector elements.
1263 //
1264 // \param array Static array for the assignment.
1265 // \return Reference to the assigned vector.
1266 //
1267 // This assignment operator offers the option to directly set all elements of the vector:
1268 
1269    \code
1270    const double init[3] = { 1.0, 2.0 };
1271    blaze::StaticVector<double,3> v;
1272    v = init;
1273    \endcode
1274 
1275 // The vector is assigned the values from the given static array. Whereas the dimensions of the
1276 // vector and the static array must match, it is allowed to provide fewer initializers for the
1277 // static array. Missing values are initialized with default values (as e.g. the third value in
1278 // the example).
1279 */
1280 template< typename Type     // Data type of the vector
1281         , size_t N          // Number of elements
1282         , bool TF           // Transpose flag
1283         , AlignmentFlag AF  // Alignment flag
1284         , PaddingFlag PF    // Padding flag
1285         , typename Tag >    // Type tag
1286 template< typename Other    // Data type of the static array
1287         , size_t Dim >      // Dimension of the static array
1288 constexpr StaticVector<Type,N,TF,AF,PF,Tag>&
1289    StaticVector<Type,N,TF,AF,PF,Tag>::operator=( const Other (&array)[Dim] ) &
1290 {
1291    BLAZE_STATIC_ASSERT( Dim == N );
1292 
1293    for( size_t i=0UL; i<N; ++i )
1294       v_[i] = array[i];
1295 
1296    return *this;
1297 }
1298 //*************************************************************************************************
1299 
1300 
1301 //*************************************************************************************************
1302 /*!\brief Array assignment to all vector elements.
1303 //
1304 // \param array The given std::array for the assignment.
1305 // \return Reference to the assigned vector.
1306 //
1307 // This assignment operator offers the option to directly set all elements of the vector:
1308 
1309    \code
1310    const std::array<double,3> init{ 1.0, 2.0 };
1311    blaze::StaticVector<double,3> v;
1312    v = init;
1313    \endcode
1314 
1315 // The vector is assigned the values from the given std::array. Whereas the dimensions of the
1316 // vector and the std::array must match, it is allowed to provide fewer initializers for the
1317 // std::array. Missing values are initialized with default values (as e.g. the third value in
1318 // the example).
1319 */
1320 template< typename Type     // Data type of the vector
1321         , size_t N          // Number of elements
1322         , bool TF           // Transpose flag
1323         , AlignmentFlag AF  // Alignment flag
1324         , PaddingFlag PF    // Padding flag
1325         , typename Tag >    // Type tag
1326 template< typename Other    // Data type of the std::array
1327         , size_t Dim >      // Dimension of the std::array
1328 constexpr StaticVector<Type,N,TF,AF,PF,Tag>&
1329    StaticVector<Type,N,TF,AF,PF,Tag>::operator=( const std::array<Other,Dim>& array ) &
1330 {
1331    BLAZE_STATIC_ASSERT( Dim == N );
1332 
1333    for( size_t i=0UL; i<N; ++i )
1334       v_[i] = array[i];
1335 
1336    return *this;
1337 }
1338 //*************************************************************************************************
1339 
1340 
1341 //*************************************************************************************************
1342 /*!\brief Copy assignment operator for StaticVector.
1343 //
1344 // \param rhs Vector to be copied.
1345 // \return Reference to the assigned vector.
1346 //
1347 // Explicit definition of a copy assignment operator for performance reasons.
1348 */
1349 template< typename Type     // Data type of the vector
1350         , size_t N          // Number of elements
1351         , bool TF           // Transpose flag
1352         , AlignmentFlag AF  // Alignment flag
1353         , PaddingFlag PF    // Padding flag
1354         , typename Tag >    // Type tag
1355 constexpr StaticVector<Type,N,TF,AF,PF,Tag>&
1356    StaticVector<Type,N,TF,AF,PF,Tag>::operator=( const StaticVector& rhs ) &
1357 {
1358    v_ = rhs.v_;
1359 
1360    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1361 
1362    return *this;
1363 }
1364 //*************************************************************************************************
1365 
1366 
1367 //*************************************************************************************************
1368 /*!\brief Assignment operator for different StaticVector instances.
1369 //
1370 // \param rhs Vector to be copied.
1371 // \return Reference to the assigned vector.
1372 */
1373 template< typename Type      // Data type of the vector
1374         , size_t N           // Number of elements
1375         , bool TF            // Transpose flag
1376         , AlignmentFlag AF   // Alignment flag
1377         , PaddingFlag PF     // Padding flag
1378         , typename Tag >     // Type tag
1379 template< typename Other     // Data type of the foreign vector
1380         , AlignmentFlag AF2  // Alignment flag of the foreign vector
1381         , PaddingFlag PF2 >  // Padding flag of the foreign vector
1382 inline StaticVector<Type,N,TF,AF,PF,Tag>&
1383    StaticVector<Type,N,TF,AF,PF,Tag>::operator=( const StaticVector<Other,N,TF,AF2,PF2,Tag>& rhs ) &
1384 {
1385    using blaze::assign;
1386 
1387    assign( *this, *rhs );
1388 
1389    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1390 
1391    return *this;
1392 }
1393 //*************************************************************************************************
1394 
1395 
1396 //*************************************************************************************************
1397 /*!\brief Assignment operator for different vectors.
1398 //
1399 // \param rhs Vector to be copied.
1400 // \return Reference to the assigned vector.
1401 // \exception std::invalid_argument Invalid assignment to static vector.
1402 //
1403 // This constructor initializes the vector as a copy of the given vector. In case the
1404 // size of the given vector is not N, a \a std::invalid_argument exception is thrown.
1405 */
1406 template< typename Type     // Data type of the vector
1407         , size_t N          // Number of elements
1408         , bool TF           // Transpose flag
1409         , AlignmentFlag AF  // Alignment flag
1410         , PaddingFlag PF    // Padding flag
1411         , typename Tag >    // Type tag
1412 template< typename VT >     // Type of the right-hand side vector
1413 inline StaticVector<Type,N,TF,AF,PF,Tag>&
1414    StaticVector<Type,N,TF,AF,PF,Tag>::operator=( const Vector<VT,TF>& rhs ) &
1415 {
1416    using blaze::assign;
1417 
1418    BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1419 
1420    if( (*rhs).size() != N ) {
1421       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static vector" );
1422    }
1423 
1424    if( (*rhs).canAlias( this ) ) {
1425       StaticVector tmp( *rhs );
1426       swap( tmp );
1427    }
1428    else {
1429       if( IsSparseVector_v<VT> )
1430          reset();
1431       assign( *this, *rhs );
1432    }
1433 
1434    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1435 
1436    return *this;
1437 }
1438 //*************************************************************************************************
1439 
1440 
1441 //*************************************************************************************************
1442 /*!\brief Addition assignment operator for the addition of a vector (\f$ \vec{a}+=\vec{b} \f$).
1443 //
1444 // \param rhs The right-hand side vector to be added to the vector.
1445 // \return Reference to the vector.
1446 // \exception std::invalid_argument Vector sizes do not match.
1447 //
1448 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1449 // is thrown.
1450 */
1451 template< typename Type     // Data type of the vector
1452         , size_t N          // Number of elements
1453         , bool TF           // Transpose flag
1454         , AlignmentFlag AF  // Alignment flag
1455         , PaddingFlag PF    // Padding flag
1456         , typename Tag >    // Type tag
1457 template< typename VT >     // Type of the right-hand side vector
1458 inline StaticVector<Type,N,TF,AF,PF,Tag>&
1459    StaticVector<Type,N,TF,AF,PF,Tag>::operator+=( const Vector<VT,TF>& rhs ) &
1460 {
1461    using blaze::addAssign;
1462 
1463    BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1464 
1465    if( (*rhs).size() != N ) {
1466       BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1467    }
1468 
1469    if( (*rhs).canAlias( this ) ) {
1470       StaticVector tmp( *rhs );
1471       addAssign( *this, tmp );
1472    }
1473    else {
1474       addAssign( *this, *rhs );
1475    }
1476 
1477    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1478 
1479    return *this;
1480 }
1481 //*************************************************************************************************
1482 
1483 
1484 //*************************************************************************************************
1485 /*!\brief Subtraction assignment operator for the subtraction of a vector (\f$ \vec{a}-=\vec{b} \f$).
1486 //
1487 // \param rhs The right-hand side vector to be subtracted from the vector.
1488 // \return Reference to the vector.
1489 // \exception std::invalid_argument Vector sizes do not match.
1490 //
1491 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1492 // is thrown.
1493 */
1494 template< typename Type     // Data type of the vector
1495         , size_t N          // Number of elements
1496         , bool TF           // Transpose flag
1497         , AlignmentFlag AF  // Alignment flag
1498         , PaddingFlag PF    // Padding flag
1499         , typename Tag >    // Type tag
1500 template< typename VT >     // Type of the right-hand side vector
1501 inline StaticVector<Type,N,TF,AF,PF,Tag>&
1502    StaticVector<Type,N,TF,AF,PF,Tag>::operator-=( const Vector<VT,TF>& rhs ) &
1503 {
1504    using blaze::subAssign;
1505 
1506    BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1507 
1508    if( (*rhs).size() != N ) {
1509       BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1510    }
1511 
1512    if( (*rhs).canAlias( this ) ) {
1513       StaticVector tmp( *rhs );
1514       subAssign( *this, tmp );
1515    }
1516    else {
1517       subAssign( *this, *rhs );
1518    }
1519 
1520    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1521 
1522    return *this;
1523 }
1524 //*************************************************************************************************
1525 
1526 
1527 //*************************************************************************************************
1528 /*!\brief Multiplication assignment operator for the multiplication of a vector
1529 //        (\f$ \vec{a}*=\vec{b} \f$).
1530 //
1531 // \param rhs The right-hand side vector to be multiplied with the vector.
1532 // \return Reference to the vector.
1533 // \exception std::invalid_argument Vector sizes do not match.
1534 //
1535 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1536 // is thrown.
1537 */
1538 template< typename Type     // Data type of the vector
1539         , size_t N          // Number of elements
1540         , bool TF           // Transpose flag
1541         , AlignmentFlag AF  // Alignment flag
1542         , PaddingFlag PF    // Padding flag
1543         , typename Tag >    // Type tag
1544 template< typename VT >     // Type of the right-hand side vector
1545 inline StaticVector<Type,N,TF,AF,PF,Tag>&
1546    StaticVector<Type,N,TF,AF,PF,Tag>::operator*=( const Vector<VT,TF>& rhs ) &
1547 {
1548    using blaze::assign;
1549    using blaze::multAssign;
1550 
1551    BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1552 
1553    if( (*rhs).size() != N ) {
1554       BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1555    }
1556 
1557    if( IsSparseVector_v<VT> || (*rhs).canAlias( this ) ) {
1558       const StaticVector tmp( *this * (*rhs) );
1559       assign( *this, tmp );
1560    }
1561    else {
1562       multAssign( *this, *rhs );
1563    }
1564 
1565    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1566 
1567    return *this;
1568 }
1569 //*************************************************************************************************
1570 
1571 
1572 //*************************************************************************************************
1573 /*!\brief Division assignment operator for the division of a dense vector (\f$ \vec{a}/=\vec{b} \f$).
1574 //
1575 // \param rhs The right-hand side dense vector divisor.
1576 // \return Reference to the vector.
1577 // \exception std::invalid_argument Vector sizes do not match.
1578 //
1579 // In case the current sizes of the two vectors don't match, a \a std::invalid_argument exception
1580 // is thrown.
1581 */
1582 template< typename Type     // Data type of the vector
1583         , size_t N          // Number of elements
1584         , bool TF           // Transpose flag
1585         , AlignmentFlag AF  // Alignment flag
1586         , PaddingFlag PF    // Padding flag
1587         , typename Tag >    // Type tag
1588 template< typename VT >     // Type of the right-hand side vector
1589 inline StaticVector<Type,N,TF,AF,PF,Tag>&
1590    StaticVector<Type,N,TF,AF,PF,Tag>::operator/=( const DenseVector<VT,TF>& rhs ) &
1591 {
1592    using blaze::assign;
1593    using blaze::divAssign;
1594 
1595    BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1596 
1597    if( (*rhs).size() != N ) {
1598       BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" );
1599    }
1600 
1601    if( (*rhs).canAlias( this ) ) {
1602       const StaticVector tmp( *this / (*rhs) );
1603       assign( *this, tmp );
1604    }
1605    else {
1606       divAssign( *this, *rhs );
1607    }
1608 
1609    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1610 
1611    return *this;
1612 }
1613 //*************************************************************************************************
1614 
1615 
1616 //*************************************************************************************************
1617 /*!\brief Cross product assignment operator for the multiplication of a vector
1618 //        (\f$ \vec{a}\times=\vec{b} \f$).
1619 //
1620 // \param rhs The right-hand side vector for the cross product.
1621 // \return Reference to the vector.
1622 // \exception std::invalid_argument Invalid vector size for cross product.
1623 //
1624 // In case the current size of any of the two vectors is not equal to 3, a \a std::invalid_argument
1625 // exception is thrown.
1626 */
1627 template< typename Type     // Data type of the vector
1628         , size_t N          // Number of elements
1629         , bool TF           // Transpose flag
1630         , AlignmentFlag AF  // Alignment flag
1631         , PaddingFlag PF    // Padding flag
1632         , typename Tag >    // Type tag
1633 template< typename VT >     // Type of the right-hand side vector
1634 inline StaticVector<Type,N,TF,AF,PF,Tag>&
1635    StaticVector<Type,N,TF,AF,PF,Tag>::operator%=( const Vector<VT,TF>& rhs ) &
1636 {
1637    using blaze::assign;
1638 
1639    BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<VT> );
1640 
1641    BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( ResultType_t<VT>, TF );
1642    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<VT> );
1643 
1644    using CrossType = CrossTrait_t< This, ResultType_t<VT> >;
1645 
1646    BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE( CrossType );
1647    BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( CrossType, TF );
1648    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( CrossType );
1649 
1650    if( N != 3UL || (*rhs).size() != 3UL ) {
1651       BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" );
1652    }
1653 
1654    const CrossType tmp( *this % (*rhs) );
1655    assign( *this, tmp );
1656 
1657    BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1658 
1659    return *this;
1660 }
1661 //*************************************************************************************************
1662 
1663 
1664 
1665 
1666 //=================================================================================================
1667 //
1668 //  UTILITY FUNCTIONS
1669 //
1670 //=================================================================================================
1671 
1672 //*************************************************************************************************
1673 /*!\brief Returns the current size/dimension of the vector.
1674 //
1675 // \return The size of the vector.
1676 */
1677 template< typename Type     // Data type of the vector
1678         , size_t N          // Number of elements
1679         , bool TF           // Transpose flag
1680         , AlignmentFlag AF  // Alignment flag
1681         , PaddingFlag PF    // Padding flag
1682         , typename Tag >    // Type tag
size()1683 constexpr size_t StaticVector<Type,N,TF,AF,PF,Tag>::size() noexcept
1684 {
1685    return N;
1686 }
1687 //*************************************************************************************************
1688 
1689 
1690 //*************************************************************************************************
1691 /*!\brief Returns the minimum capacity of the vector.
1692 //
1693 // \return The minimum capacity of the vector.
1694 //
1695 // This function returns the minimum capacity of the vector, which corresponds to the current
1696 // size plus padding.
1697 */
1698 template< typename Type     // Data type of the vector
1699         , size_t N          // Number of elements
1700         , bool TF           // Transpose flag
1701         , AlignmentFlag AF  // Alignment flag
1702         , PaddingFlag PF    // Padding flag
1703         , typename Tag >    // Type tag
spacing()1704 constexpr size_t StaticVector<Type,N,TF,AF,PF,Tag>::spacing() noexcept
1705 {
1706    return NN;
1707 }
1708 //*************************************************************************************************
1709 
1710 
1711 //*************************************************************************************************
1712 /*!\brief Returns the maximum capacity of the vector.
1713 //
1714 // \return The maximum capacity of the vector.
1715 */
1716 template< typename Type     // Data type of the vector
1717         , size_t N          // Number of elements
1718         , bool TF           // Transpose flag
1719         , AlignmentFlag AF  // Alignment flag
1720         , PaddingFlag PF    // Padding flag
1721         , typename Tag >    // Type tag
capacity()1722 constexpr size_t StaticVector<Type,N,TF,AF,PF,Tag>::capacity() noexcept
1723 {
1724    return NN;
1725 }
1726 //*************************************************************************************************
1727 
1728 
1729 //*************************************************************************************************
1730 /*!\brief Returns the number of non-zero elements in the vector.
1731 //
1732 // \return The number of non-zero elements in the vector.
1733 //
1734 // This function returns the number of non-zero elements in the vector (i.e. the elements that
1735 // compare unequal to their default value). Note that the number of non-zero elements is always
1736 // less than or equal to the current size of the vector.
1737 */
1738 template< typename Type     // Data type of the vector
1739         , size_t N          // Number of elements
1740         , bool TF           // Transpose flag
1741         , AlignmentFlag AF  // Alignment flag
1742         , PaddingFlag PF    // Padding flag
1743         , typename Tag >    // Type tag
nonZeros()1744 inline size_t StaticVector<Type,N,TF,AF,PF,Tag>::nonZeros() const
1745 {
1746    size_t nonzeros( 0 );
1747 
1748    for( size_t i=0UL; i<N; ++i ) {
1749       if( !isDefault<strict>( v_[i] ) )
1750          ++nonzeros;
1751    }
1752 
1753    return nonzeros;
1754 }
1755 //*************************************************************************************************
1756 
1757 
1758 //*************************************************************************************************
1759 /*!\brief Reset to the default initial values.
1760 //
1761 // \return void
1762 */
1763 template< typename Type     // Data type of the vector
1764         , size_t N          // Number of elements
1765         , bool TF           // Transpose flag
1766         , AlignmentFlag AF  // Alignment flag
1767         , PaddingFlag PF    // Padding flag
1768         , typename Tag >    // Type tag
reset()1769 constexpr void StaticVector<Type,N,TF,AF,PF,Tag>::reset()
1770 {
1771    using blaze::clear;
1772    for( size_t i=0UL; i<N; ++i )
1773       clear( v_[i] );
1774 }
1775 //*************************************************************************************************
1776 
1777 
1778 //*************************************************************************************************
1779 /*!\brief Swapping the contents of two static vectors.
1780 //
1781 // \param v The vector to be swapped.
1782 // \return void
1783 */
1784 template< typename Type     // Data type of the vector
1785         , size_t N          // Number of elements
1786         , bool TF           // Transpose flag
1787         , AlignmentFlag AF  // Alignment flag
1788         , PaddingFlag PF    // Padding flag
1789         , typename Tag >    // Type tag
swap(StaticVector & v)1790 inline void StaticVector<Type,N,TF,AF,PF,Tag>::swap( StaticVector& v ) noexcept
1791 {
1792    using std::swap;
1793 
1794    for( size_t i=0UL; i<N; ++i )
1795       swap( v_[i], v.v_[i] );
1796 }
1797 //*************************************************************************************************
1798 
1799 
1800 
1801 
1802 //=================================================================================================
1803 //
1804 //  NUMERIC FUNCTIONS
1805 //
1806 //=================================================================================================
1807 
1808 //*************************************************************************************************
1809 /*!\brief Scaling of the vector by the scalar value \a scalar (\f$ \vec{a}*=s \f$).
1810 //
1811 // \param scalar The scalar value for the vector scaling.
1812 // \return Reference to the vector.
1813 //
1814 // This function scales the vector by applying the given scalar value \a scalar to each element
1815 // of the vector. For built-in and \c complex data types it has the same effect as using the
1816 // multiplication assignment operator:
1817 
1818    \code
1819    blaze::StaticVector<int,3> a;
1820    // ... Initialization
1821    a *= 4;        // Scaling of the vector
1822    a.scale( 4 );  // Same effect as above
1823    \endcode
1824 */
1825 template< typename Type     // Data type of the vector
1826         , size_t N          // Number of elements
1827         , bool TF           // Transpose flag
1828         , AlignmentFlag AF  // Alignment flag
1829         , PaddingFlag PF    // Padding flag
1830         , typename Tag >    // Type tag
1831 template< typename Other >  // Data type of the scalar value
1832 inline StaticVector<Type,N,TF,AF,PF,Tag>&
scale(const Other & scalar)1833    StaticVector<Type,N,TF,AF,PF,Tag>::scale( const Other& scalar )
1834 {
1835    for( size_t i=0; i<N; ++i )
1836       v_[i] *= scalar;
1837    return *this;
1838 }
1839 //*************************************************************************************************
1840 
1841 
1842 
1843 
1844 //=================================================================================================
1845 //
1846 //  MEMORY FUNCTIONS
1847 //
1848 //=================================================================================================
1849 
1850 //*************************************************************************************************
1851 /*!\brief Class specific implementation of operator new.
1852 //
1853 // \param size The total number of bytes to be allocated.
1854 // \return Pointer to the newly allocated memory.
1855 // \exception std::bad_alloc Allocation failed.
1856 //
1857 // This class-specific implementation of operator new provides the functionality to allocate
1858 // dynamic memory based on the alignment restrictions of the StaticVector class template.
1859 */
1860 template< typename Type     // Data type of the vector
1861         , size_t N          // Number of elements
1862         , bool TF           // Transpose flag
1863         , AlignmentFlag AF  // Alignment flag
1864         , PaddingFlag PF    // Padding flag
1865         , typename Tag >    // Type tag
new(std::size_t size)1866 inline void* StaticVector<Type,N,TF,AF,PF,Tag>::operator new( std::size_t size )
1867 {
1868    MAYBE_UNUSED( size );
1869 
1870    BLAZE_INTERNAL_ASSERT( size == sizeof( StaticVector ), "Invalid number of bytes detected" );
1871 
1872    return allocate<StaticVector>( 1UL );
1873 }
1874 //*************************************************************************************************
1875 
1876 
1877 //*************************************************************************************************
1878 /*!\brief Class specific implementation of operator new[].
1879 //
1880 // \param size The total number of bytes to be allocated.
1881 // \return Pointer to the newly allocated memory.
1882 // \exception std::bad_alloc Allocation failed.
1883 //
1884 // This class-specific implementation of operator new provides the functionality to allocate
1885 // dynamic memory based on the alignment restrictions of the StaticVector class template.
1886 */
1887 template< typename Type     // Data type of the vector
1888         , size_t N          // Number of elements
1889         , bool TF           // Transpose flag
1890         , AlignmentFlag AF  // Alignment flag
1891         , PaddingFlag PF    // Padding flag
1892         , typename Tag >    // Type tag
1893 inline void* StaticVector<Type,N,TF,AF,PF,Tag>::operator new[]( std::size_t size )
1894 {
1895    BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticVector )       , "Invalid number of bytes detected" );
1896    BLAZE_INTERNAL_ASSERT( size %  sizeof( StaticVector ) == 0UL, "Invalid number of bytes detected" );
1897 
1898    return allocate<StaticVector>( size/sizeof(StaticVector) );
1899 }
1900 //*************************************************************************************************
1901 
1902 
1903 //*************************************************************************************************
1904 /*!\brief Class specific implementation of the no-throw operator new.
1905 //
1906 // \param size The total number of bytes to be allocated.
1907 // \return Pointer to the newly allocated memory.
1908 // \exception std::bad_alloc Allocation failed.
1909 //
1910 // This class-specific implementation of operator new provides the functionality to allocate
1911 // dynamic memory based on the alignment restrictions of the StaticVector class template.
1912 */
1913 template< typename Type     // Data type of the vector
1914         , size_t N          // Number of elements
1915         , bool TF           // Transpose flag
1916         , AlignmentFlag AF  // Alignment flag
1917         , PaddingFlag PF    // Padding flag
1918         , typename Tag >    // Type tag
new(std::size_t size,const std::nothrow_t &)1919 inline void* StaticVector<Type,N,TF,AF,PF,Tag>::operator new( std::size_t size, const std::nothrow_t& )
1920 {
1921    MAYBE_UNUSED( size );
1922 
1923    BLAZE_INTERNAL_ASSERT( size == sizeof( StaticVector ), "Invalid number of bytes detected" );
1924 
1925    return allocate<StaticVector>( 1UL );
1926 }
1927 //*************************************************************************************************
1928 
1929 
1930 //*************************************************************************************************
1931 /*!\brief Class specific implementation of the no-throw operator new[].
1932 //
1933 // \param size The total number of bytes to be allocated.
1934 // \return Pointer to the newly allocated memory.
1935 // \exception std::bad_alloc Allocation failed.
1936 //
1937 // This class-specific implementation of operator new provides the functionality to allocate
1938 // dynamic memory based on the alignment restrictions of the StaticVector class template.
1939 */
1940 template< typename Type     // Data type of the vector
1941         , size_t N          // Number of elements
1942         , bool TF           // Transpose flag
1943         , AlignmentFlag AF  // Alignment flag
1944         , PaddingFlag PF    // Padding flag
1945         , typename Tag >    // Type tag
1946 inline void* StaticVector<Type,N,TF,AF,PF,Tag>::operator new[]( std::size_t size, const std::nothrow_t& )
1947 {
1948    BLAZE_INTERNAL_ASSERT( size >= sizeof( StaticVector )       , "Invalid number of bytes detected" );
1949    BLAZE_INTERNAL_ASSERT( size %  sizeof( StaticVector ) == 0UL, "Invalid number of bytes detected" );
1950 
1951    return allocate<StaticVector>( size/sizeof(StaticVector) );
1952 }
1953 //*************************************************************************************************
1954 
1955 
1956 //*************************************************************************************************
1957 /*!\brief Class specific implementation of operator delete.
1958 //
1959 // \param ptr The memory to be deallocated.
1960 // \return void
1961 */
1962 template< typename Type     // Data type of the vector
1963         , size_t N          // Number of elements
1964         , bool TF           // Transpose flag
1965         , AlignmentFlag AF  // Alignment flag
1966         , PaddingFlag PF    // Padding flag
1967         , typename Tag >    // Type tag
delete(void * ptr)1968 inline void StaticVector<Type,N,TF,AF,PF,Tag>::operator delete( void* ptr )
1969 {
1970    deallocate( static_cast<StaticVector*>( ptr ) );
1971 }
1972 //*************************************************************************************************
1973 
1974 
1975 //*************************************************************************************************
1976 /*!\brief Class specific implementation of operator delete[].
1977 //
1978 // \param ptr The memory to be deallocated.
1979 // \return void
1980 */
1981 template< typename Type     // Data type of the vector
1982         , size_t N          // Number of elements
1983         , bool TF           // Transpose flag
1984         , AlignmentFlag AF  // Alignment flag
1985         , PaddingFlag PF    // Padding flag
1986         , typename Tag >    // Type tag
1987 inline void StaticVector<Type,N,TF,AF,PF,Tag>::operator delete[]( void* ptr )
1988 {
1989    deallocate( static_cast<StaticVector*>( ptr ) );
1990 }
1991 //*************************************************************************************************
1992 
1993 
1994 //*************************************************************************************************
1995 /*!\brief Class specific implementation of no-throw operator delete.
1996 //
1997 // \param ptr The memory to be deallocated.
1998 // \return void
1999 */
2000 template< typename Type     // Data type of the vector
2001         , size_t N          // Number of elements
2002         , bool TF           // Transpose flag
2003         , AlignmentFlag AF  // Alignment flag
2004         , PaddingFlag PF    // Padding flag
2005         , typename Tag >    // Type tag
delete(void * ptr,const std::nothrow_t &)2006 inline void StaticVector<Type,N,TF,AF,PF,Tag>::operator delete( void* ptr, const std::nothrow_t& )
2007 {
2008    deallocate( static_cast<StaticVector*>( ptr ) );
2009 }
2010 //*************************************************************************************************
2011 
2012 
2013 //*************************************************************************************************
2014 /*!\brief Class specific implementation of no-throw operator delete[].
2015 //
2016 // \param ptr The memory to be deallocated.
2017 // \return void
2018 */
2019 template< typename Type     // Data type of the vector
2020         , size_t N          // Number of elements
2021         , bool TF           // Transpose flag
2022         , AlignmentFlag AF  // Alignment flag
2023         , PaddingFlag PF    // Padding flag
2024         , typename Tag >    // Type tag
2025 inline void StaticVector<Type,N,TF,AF,PF,Tag>::operator delete[]( void* ptr, const std::nothrow_t& )
2026 {
2027    deallocate( static_cast<StaticVector*>( ptr ) );
2028 }
2029 //*************************************************************************************************
2030 
2031 
2032 
2033 
2034 //=================================================================================================
2035 //
2036 //  DEBUGGING FUNCTIONS
2037 //
2038 //=================================================================================================
2039 
2040 //*************************************************************************************************
2041 /*!\brief Returns whether the invariants of the static vector are intact.
2042 //
2043 // \return \a true in case the static vector's invariants are intact, \a false otherwise.
2044 //
2045 // This function checks whether the invariants of the static vector are intact, i.e. if its
2046 // state is valid. In case the invariants are intact, the function returns \a true, else it
2047 // will return \a false.
2048 */
2049 template< typename Type     // Data type of the vector
2050         , size_t N          // Number of elements
2051         , bool TF           // Transpose flag
2052         , AlignmentFlag AF  // Alignment flag
2053         , PaddingFlag PF    // Padding flag
2054         , typename Tag >    // Type tag
isIntact()2055 constexpr bool StaticVector<Type,N,TF,AF,PF,Tag>::isIntact() const noexcept
2056 {
2057    if( IsNumeric_v<Type> ) {
2058       for( size_t i=N; i<NN; ++i ) {
2059          if( !isDefault<strict>( v_[i] ) )
2060             return false;
2061       }
2062    }
2063 
2064    return true;
2065 }
2066 //*************************************************************************************************
2067 
2068 
2069 
2070 
2071 //=================================================================================================
2072 //
2073 //  EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2074 //
2075 //=================================================================================================
2076 
2077 //*************************************************************************************************
2078 /*!\brief Returns whether the vector can alias with the given address \a alias.
2079 //
2080 // \param alias The alias to be checked.
2081 // \return \a true in case the alias corresponds to this vector, \a false if not.
2082 //
2083 // This function returns whether the given address can alias with the vector. In contrast
2084 // to the isAliased() function this function is allowed to use compile time expressions
2085 // to optimize the evaluation.
2086 */
2087 template< typename Type     // Data type of the vector
2088         , size_t N          // Number of elements
2089         , bool TF           // Transpose flag
2090         , AlignmentFlag AF  // Alignment flag
2091         , PaddingFlag PF    // Padding flag
2092         , typename Tag >    // Type tag
2093 template< typename Other >  // Data type of the foreign expression
canAlias(const Other * alias)2094 inline bool StaticVector<Type,N,TF,AF,PF,Tag>::canAlias( const Other* alias ) const noexcept
2095 {
2096    return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2097 }
2098 //*************************************************************************************************
2099 
2100 
2101 //*************************************************************************************************
2102 /*!\brief Returns whether the vector is aliased with the given address \a alias.
2103 //
2104 // \param alias The alias to be checked.
2105 // \return \a true in case the alias corresponds to this vector, \a false if not.
2106 //
2107 // This function returns whether the given address is aliased with the vector. In contrast
2108 // to the canAlias() function this function is not allowed to use compile time expressions
2109 // to optimize the evaluation.
2110 */
2111 template< typename Type     // Data type of the vector
2112         , size_t N          // Number of elements
2113         , bool TF           // Transpose flag
2114         , AlignmentFlag AF  // Alignment flag
2115         , PaddingFlag PF    // Padding flag
2116         , typename Tag >    // Type tag
2117 template< typename Other >  // Data type of the foreign expression
isAliased(const Other * alias)2118 inline bool StaticVector<Type,N,TF,AF,PF,Tag>::isAliased( const Other* alias ) const noexcept
2119 {
2120    return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2121 }
2122 //*************************************************************************************************
2123 
2124 
2125 //*************************************************************************************************
2126 /*!\brief Returns whether the vector is properly aligned in memory.
2127 //
2128 // \return \a true in case the vector is aligned, \a false if not.
2129 //
2130 // This function returns whether the vector is guaranteed to be properly aligned in memory, i.e.
2131 // whether the beginning and the end of the vector are guaranteed to conform to the alignment
2132 // restrictions of the element type \a Type.
2133 */
2134 template< typename Type     // Data type of the vector
2135         , size_t N          // Number of elements
2136         , bool TF           // Transpose flag
2137         , AlignmentFlag AF  // Alignment flag
2138         , PaddingFlag PF    // Padding flag
2139         , typename Tag >    // Type tag
isAligned()2140 constexpr bool StaticVector<Type,N,TF,AF,PF,Tag>::isAligned() noexcept
2141 {
2142    return AF == aligned;
2143 }
2144 //*************************************************************************************************
2145 
2146 
2147 //*************************************************************************************************
2148 /*!\brief Load of a SIMD element of the vector.
2149 //
2150 // \param index Access index. The index must be smaller than the number of vector elements.
2151 // \return The loaded SIMD element.
2152 //
2153 // This function performs a load of a specific SIMD element of the dense vector. The index
2154 // must be smaller than the number of vector elements and it must be a multiple of the number
2155 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
2156 // used internally for the performance optimized evaluation of expression templates. Calling
2157 // this function explicitly might result in erroneous results and/or in compilation errors.
2158 */
2159 template< typename Type     // Data type of the vector
2160         , size_t N          // Number of elements
2161         , bool TF           // Transpose flag
2162         , AlignmentFlag AF  // Alignment flag
2163         , PaddingFlag PF    // Padding flag
2164         , typename Tag >    // Type tag
2165 BLAZE_ALWAYS_INLINE typename StaticVector<Type,N,TF,AF,PF,Tag>::SIMDType
load(size_t index)2166    StaticVector<Type,N,TF,AF,PF,Tag>::load( size_t index ) const noexcept
2167 {
2168    if( AF == aligned )
2169       return loada( index );
2170    else
2171       return loadu( index );
2172 }
2173 //*************************************************************************************************
2174 
2175 
2176 //*************************************************************************************************
2177 /*!\brief Aligned load of a SIMD element of the vector.
2178 //
2179 // \param index Access index. The index must be smaller than the number of vector elements.
2180 // \return The loaded SIMD element.
2181 //
2182 // This function performs an aligned load of a specific SIMD element of the dense vector. The
2183 // index must be smaller than the number of vector elements and it must be a multiple of the
2184 // number of values inside the SIMD element. This function must \b NOT be called explicitly!
2185 // It is used internally for the performance optimized evaluation of expression templates.
2186 // Calling this function explicitly might result in erroneous results and/or in compilation
2187 // errors.
2188 */
2189 template< typename Type     // Data type of the vector
2190         , size_t N          // Number of elements
2191         , bool TF           // Transpose flag
2192         , AlignmentFlag AF  // Alignment flag
2193         , PaddingFlag PF    // Padding flag
2194         , typename Tag >    // Type tag
2195 BLAZE_ALWAYS_INLINE typename StaticVector<Type,N,TF,AF,PF,Tag>::SIMDType
loada(size_t index)2196    StaticVector<Type,N,TF,AF,PF,Tag>::loada( size_t index ) const noexcept
2197 {
2198    using blaze::loada;
2199 
2200    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2201 
2202    BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
2203    BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
2204    BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
2205    BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
2206 
2207    return loada( &v_[index] );
2208 }
2209 //*************************************************************************************************
2210 
2211 
2212 //*************************************************************************************************
2213 /*!\brief Unaligned load of a SIMD element of the vector.
2214 //
2215 // \param index Access index. The index must be smaller than the number of vector elements.
2216 // \return The loaded SIMD element.
2217 //
2218 // This function performs an unaligned load of a specific SIMD element of the dense vector. The
2219 // index must be smaller than the number of vector elements and it must be a multiple of the
2220 // number of values inside the SIMD element. This function must \b NOT be called explicitly!
2221 // It is used internally for the performance optimized evaluation of expression templates.
2222 // Calling this function explicitly might result in erroneous results and/or in compilation
2223 // errors.
2224 */
2225 template< typename Type     // Data type of the vector
2226         , size_t N          // Number of elements
2227         , bool TF           // Transpose flag
2228         , AlignmentFlag AF  // Alignment flag
2229         , PaddingFlag PF    // Padding flag
2230         , typename Tag >    // Type tag
2231 BLAZE_ALWAYS_INLINE typename StaticVector<Type,N,TF,AF,PF,Tag>::SIMDType
loadu(size_t index)2232    StaticVector<Type,N,TF,AF,PF,Tag>::loadu( size_t index ) const noexcept
2233 {
2234    using blaze::loadu;
2235 
2236    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2237 
2238    BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
2239    BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
2240 
2241    return loadu( &v_[index] );
2242 }
2243 //*************************************************************************************************
2244 
2245 
2246 //*************************************************************************************************
2247 /*!\brief Store of a SIMD element of the vector.
2248 //
2249 // \param index Access index. The index must be smaller than the number of vector elements.
2250 // \param value The SIMD element to be stored.
2251 // \return void
2252 //
2253 // This function performs a store of a specific SIMD element of the dense vector. The index
2254 // must be smaller than the number of vector elements and it must be a multiple of the number
2255 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
2256 // used internally for the performance optimized evaluation of expression templates. Calling
2257 // this function explicitly might result in erroneous results and/or in compilation errors.
2258 */
2259 template< typename Type     // Data type of the vector
2260         , size_t N          // Number of elements
2261         , bool TF           // Transpose flag
2262         , AlignmentFlag AF  // Alignment flag
2263         , PaddingFlag PF    // Padding flag
2264         , typename Tag >    // Type tag
2265 BLAZE_ALWAYS_INLINE void
store(size_t index,const SIMDType & value)2266    StaticVector<Type,N,TF,AF,PF,Tag>::store( size_t index, const SIMDType& value ) noexcept
2267 {
2268    if( AF == aligned )
2269       storea( index, value );
2270    else
2271       storeu( index, value );
2272 }
2273 //*************************************************************************************************
2274 
2275 
2276 //*************************************************************************************************
2277 /*!\brief Aligned store of a SIMD element of the vector.
2278 //
2279 // \param index Access index. The index must be smaller than the number of vector elements.
2280 // \param value The SIMD element to be stored.
2281 // \return void
2282 //
2283 // This function performs an aligned store of a specific SIMD element of the dense vector. The
2284 // index must be smaller than the number of vector elements and it must be a multiple of the
2285 // number of values inside the SIMD element. This function must \b NOT be called explicitly! It
2286 // is used internally for the performance optimized evaluation of expression templates. Calling
2287 // this function explicitly might result in erroneous results and/or in compilation errors.
2288 */
2289 template< typename Type     // Data type of the vector
2290         , size_t N          // Number of elements
2291         , bool TF           // Transpose flag
2292         , AlignmentFlag AF  // Alignment flag
2293         , PaddingFlag PF    // Padding flag
2294         , typename Tag >    // Type tag
2295 BLAZE_ALWAYS_INLINE void
storea(size_t index,const SIMDType & value)2296    StaticVector<Type,N,TF,AF,PF,Tag>::storea( size_t index, const SIMDType& value ) noexcept
2297 {
2298    using blaze::storea;
2299 
2300    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2301 
2302    BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
2303    BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN , "Invalid vector access index" );
2304    BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
2305    BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
2306 
2307    storea( &v_[index], value );
2308 }
2309 //*************************************************************************************************
2310 
2311 
2312 //*************************************************************************************************
2313 /*!\brief Unaligned store of a SIMD element of the vector.
2314 //
2315 // \param index Access index. The index must be smaller than the number of vector elements.
2316 // \param value The SIMD element to be stored.
2317 // \return void
2318 //
2319 // This function performs an unaligned store of a specific SIMD element of the dense vector.
2320 // The index must be smaller than the number of vector elements and it must be a multiple of the
2321 // number of values inside the SIMD element. This function must \b NOT be called explicitly! It
2322 // is used internally for the performance optimized evaluation of expression templates. Calling
2323 // this function explicitly might result in erroneous results and/or in compilation errors.
2324 */
2325 template< typename Type     // Data type of the vector
2326         , size_t N          // Number of elements
2327         , bool TF           // Transpose flag
2328         , AlignmentFlag AF  // Alignment flag
2329         , PaddingFlag PF    // Padding flag
2330         , typename Tag >    // Type tag
2331 BLAZE_ALWAYS_INLINE void
storeu(size_t index,const SIMDType & value)2332    StaticVector<Type,N,TF,AF,PF,Tag>::storeu( size_t index, const SIMDType& value ) noexcept
2333 {
2334    using blaze::storeu;
2335 
2336    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2337 
2338    BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
2339    BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
2340 
2341    storeu( &v_[index], value );
2342 }
2343 //*************************************************************************************************
2344 
2345 
2346 //*************************************************************************************************
2347 /*!\brief Aligned, non-temporal store of a SIMD element of the vector.
2348 //
2349 // \param index Access index. The index must be smaller than the number of vector elements.
2350 // \param value The SIMD element to be stored.
2351 // \return void
2352 //
2353 // This function performs an aligned, non-temporal store of a specific SIMD element of the
2354 // dense vector. The index must be smaller than the number of vector elements and it must be
2355 // a multiple of the number of values inside the SIMD element. This function must \b NOT be
2356 // called explicitly! It is used internally for the performance optimized evaluation of
2357 // expression templates. Calling this function explicitly might result in erroneous results
2358 // and/or in compilation errors.
2359 */
2360 template< typename Type     // Data type of the vector
2361         , size_t N          // Number of elements
2362         , bool TF           // Transpose flag
2363         , AlignmentFlag AF  // Alignment flag
2364         , PaddingFlag PF    // Padding flag
2365         , typename Tag >    // Type tag
2366 BLAZE_ALWAYS_INLINE void
stream(size_t index,const SIMDType & value)2367    StaticVector<Type,N,TF,AF,PF,Tag>::stream( size_t index, const SIMDType& value ) noexcept
2368 {
2369    using blaze::stream;
2370 
2371    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2372 
2373    BLAZE_INTERNAL_ASSERT( index < N, "Invalid vector access index" );
2374    BLAZE_INTERNAL_ASSERT( index + SIMDSIZE <= NN, "Invalid vector access index" );
2375    BLAZE_INTERNAL_ASSERT( index % SIMDSIZE == 0UL, "Invalid vector access index" );
2376    BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[index] ), "Invalid alignment detected" );
2377 
2378    stream( &v_[index], value );
2379 }
2380 //*************************************************************************************************
2381 
2382 
2383 //*************************************************************************************************
2384 /*!\brief Default implementation of the assignment of a dense vector.
2385 //
2386 // \param rhs The right-hand side dense vector to be assigned.
2387 // \return void
2388 //
2389 // This function must \b NOT be called explicitly! It is used internally for the performance
2390 // optimized evaluation of expression templates. Calling this function explicitly might result
2391 // in erroneous results and/or in compilation errors. Instead of using this function use the
2392 // assignment operator.
2393 */
2394 template< typename Type     // Data type of the vector
2395         , size_t N          // Number of elements
2396         , bool TF           // Transpose flag
2397         , AlignmentFlag AF  // Alignment flag
2398         , PaddingFlag PF    // Padding flag
2399         , typename Tag >    // Type tag
2400 template< typename VT >     // Type of the right-hand side dense vector
2401 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::assign( const DenseVector<VT,TF>& rhs )
2402    -> DisableIf_t< VectorizedAssign_v<VT> >
2403 {
2404    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2405 
2406    for( size_t i=0UL; i<N; ++i )
2407       v_[i] = (*rhs)[i];
2408 }
2409 //*************************************************************************************************
2410 
2411 
2412 //*************************************************************************************************
2413 /*!\brief SIMD optimized implementation of the assignment of a dense vector.
2414 //
2415 // \param rhs The right-hand side dense vector to be assigned.
2416 // \return void
2417 //
2418 // This function must \b NOT be called explicitly! It is used internally for the performance
2419 // optimized evaluation of expression templates. Calling this function explicitly might result
2420 // in erroneous results and/or in compilation errors. Instead of using this function use the
2421 // assignment operator.
2422 */
2423 template< typename Type     // Data type of the vector
2424         , size_t N          // Number of elements
2425         , bool TF           // Transpose flag
2426         , AlignmentFlag AF  // Alignment flag
2427         , PaddingFlag PF    // Padding flag
2428         , typename Tag >    // Type tag
2429 template< typename VT >     // Type of the right-hand side dense vector
2430 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::assign( const DenseVector<VT,TF>& rhs )
2431    -> EnableIf_t< VectorizedAssign_v<VT> >
2432 {
2433    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2434 
2435    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2436 
2437    constexpr bool remainder( PF == unpadded || !IsPadded_v<VT> );
2438 
2439    constexpr size_t ipos( remainder ? prevMultiple( N, SIMDSIZE ) : N );
2440    BLAZE_INTERNAL_ASSERT( ipos <= N, "Invalid end calculation" );
2441 
2442    size_t i( 0UL );
2443 
2444    for( ; i<ipos; i+=SIMDSIZE ) {
2445       store( i, (*rhs).load(i) );
2446    }
2447    for( ; remainder && i<N; ++i ) {
2448       v_[i] = (*rhs)[i];
2449    }
2450 }
2451 //*************************************************************************************************
2452 
2453 
2454 //*************************************************************************************************
2455 /*!\brief Default implementation of the assignment of a sparse vector.
2456 //
2457 // \param rhs The right-hand side sparse vector to be assigned.
2458 // \return void
2459 //
2460 // This function must \b NOT be called explicitly! It is used internally for the performance
2461 // optimized evaluation of expression templates. Calling this function explicitly might result
2462 // in erroneous results and/or in compilation errors. Instead of using this function use the
2463 // assignment operator.
2464 */
2465 template< typename Type     // Data type of the vector
2466         , size_t N          // Number of elements
2467         , bool TF           // Transpose flag
2468         , AlignmentFlag AF  // Alignment flag
2469         , PaddingFlag PF    // Padding flag
2470         , typename Tag >    // Type tag
2471 template< typename VT >     // Type of the right-hand side sparse vector
assign(const SparseVector<VT,TF> & rhs)2472 inline void StaticVector<Type,N,TF,AF,PF,Tag>::assign( const SparseVector<VT,TF>& rhs )
2473 {
2474    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2475 
2476    for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2477       v_[element->index()] = element->value();
2478 }
2479 //*************************************************************************************************
2480 
2481 
2482 //*************************************************************************************************
2483 /*!\brief Default implementation of the addition assignment of a dense vector.
2484 //
2485 // \param rhs The right-hand side dense vector to be added.
2486 // \return void
2487 //
2488 // This function must \b NOT be called explicitly! It is used internally for the performance
2489 // optimized evaluation of expression templates. Calling this function explicitly might result
2490 // in erroneous results and/or in compilation errors. Instead of using this function use the
2491 // assignment operator.
2492 */
2493 template< typename Type     // Data type of the vector
2494         , size_t N          // Number of elements
2495         , bool TF           // Transpose flag
2496         , AlignmentFlag AF  // Alignment flag
2497         , PaddingFlag PF    // Padding flag
2498         , typename Tag >    // Type tag
2499 template< typename VT >     // Type of the right-hand side dense vector
2500 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::addAssign( const DenseVector<VT,TF>& rhs )
2501    -> DisableIf_t< VectorizedAddAssign_v<VT> >
2502 {
2503    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2504 
2505    for( size_t i=0UL; i<N; ++i )
2506       v_[i] += (*rhs)[i];
2507 }
2508 //*************************************************************************************************
2509 
2510 
2511 //*************************************************************************************************
2512 /*!\brief SIMD optimized implementation of the addition assignment of a dense vector.
2513 //
2514 // \param rhs The right-hand side dense vector to be added.
2515 // \return void
2516 //
2517 // This function must \b NOT be called explicitly! It is used internally for the performance
2518 // optimized evaluation of expression templates. Calling this function explicitly might result
2519 // in erroneous results and/or in compilation errors. Instead of using this function use the
2520 // assignment operator.
2521 */
2522 template< typename Type     // Data type of the vector
2523         , size_t N          // Number of elements
2524         , bool TF           // Transpose flag
2525         , AlignmentFlag AF  // Alignment flag
2526         , PaddingFlag PF    // Padding flag
2527         , typename Tag >    // Type tag
2528 template< typename VT >     // Type of the right-hand side dense vector
2529 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::addAssign( const DenseVector<VT,TF>& rhs )
2530    -> EnableIf_t< VectorizedAddAssign_v<VT> >
2531 {
2532    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2533 
2534    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2535 
2536    constexpr bool remainder( PF == unpadded || !IsPadded_v<VT> );
2537 
2538    constexpr size_t ipos( remainder ? prevMultiple( N, SIMDSIZE ) : N );
2539    BLAZE_INTERNAL_ASSERT( ipos <= N, "Invalid end calculation" );
2540 
2541    size_t i( 0UL );
2542 
2543    for( ; i<ipos; i+=SIMDSIZE ) {
2544       store( i, load(i) + (*rhs).load(i) );
2545    }
2546    for( ; remainder && i<N; ++i ) {
2547       v_[i] += (*rhs)[i];
2548    }
2549 }
2550 //*************************************************************************************************
2551 
2552 
2553 //*************************************************************************************************
2554 /*!\brief Default implementation of the addition assignment of a sparse vector.
2555 //
2556 // \param rhs The right-hand side sparse vector to be added.
2557 // \return void
2558 //
2559 // This function must \b NOT be called explicitly! It is used internally for the performance
2560 // optimized evaluation of expression templates. Calling this function explicitly might result
2561 // in erroneous results and/or in compilation errors. Instead of using this function use the
2562 // assignment operator.
2563 */
2564 template< typename Type     // Data type of the vector
2565         , size_t N          // Number of elements
2566         , bool TF           // Transpose flag
2567         , AlignmentFlag AF  // Alignment flag
2568         , PaddingFlag PF    // Padding flag
2569         , typename Tag >    // Type tag
2570 template< typename VT >     // Type of the right-hand side sparse vector
addAssign(const SparseVector<VT,TF> & rhs)2571 inline void StaticVector<Type,N,TF,AF,PF,Tag>::addAssign( const SparseVector<VT,TF>& rhs )
2572 {
2573    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2574 
2575    for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2576       v_[element->index()] += element->value();
2577 }
2578 //*************************************************************************************************
2579 
2580 
2581 //*************************************************************************************************
2582 /*!\brief Default implementation of the subtraction assignment of a dense vector.
2583 //
2584 // \param rhs The right-hand side dense vector to be subtracted.
2585 // \return void
2586 //
2587 // This function must \b NOT be called explicitly! It is used internally for the performance
2588 // optimized evaluation of expression templates. Calling this function explicitly might result
2589 // in erroneous results and/or in compilation errors. Instead of using this function use the
2590 // assignment operator.
2591 */
2592 template< typename Type     // Data type of the vector
2593         , size_t N          // Number of elements
2594         , bool TF           // Transpose flag
2595         , AlignmentFlag AF  // Alignment flag
2596         , PaddingFlag PF    // Padding flag
2597         , typename Tag >    // Type tag
2598 template< typename VT >     // Type of the right-hand side dense vector
2599 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::subAssign( const DenseVector<VT,TF>& rhs )
2600    -> DisableIf_t< VectorizedSubAssign_v<VT> >
2601 {
2602    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2603 
2604    for( size_t i=0UL; i<N; ++i )
2605       v_[i] -= (*rhs)[i];
2606 }
2607 //*************************************************************************************************
2608 
2609 
2610 //*************************************************************************************************
2611 /*!\brief SIMD optimized implementation of the subtraction assignment of a dense vector.
2612 //
2613 // \param rhs The right-hand side dense vector to be subtracted.
2614 // \return void
2615 //
2616 // This function must \b NOT be called explicitly! It is used internally for the performance
2617 // optimized evaluation of expression templates. Calling this function explicitly might result
2618 // in erroneous results and/or in compilation errors. Instead of using this function use the
2619 // assignment operator.
2620 */
2621 template< typename Type     // Data type of the vector
2622         , size_t N          // Number of elements
2623         , bool TF           // Transpose flag
2624         , AlignmentFlag AF  // Alignment flag
2625         , PaddingFlag PF    // Padding flag
2626         , typename Tag >    // Type tag
2627 template< typename VT >     // Type of the right-hand side dense vector
2628 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::subAssign( const DenseVector<VT,TF>& rhs )
2629    -> EnableIf_t< VectorizedSubAssign_v<VT> >
2630 {
2631    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2632 
2633    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2634 
2635    constexpr bool remainder( PF == unpadded || !IsPadded_v<VT> );
2636 
2637    constexpr size_t ipos( remainder ? prevMultiple( N, SIMDSIZE ) : N );
2638    BLAZE_INTERNAL_ASSERT( ipos <= N, "Invalid end calculation" );
2639 
2640    size_t i( 0UL );
2641 
2642    for( ; i<ipos; i+=SIMDSIZE ) {
2643       store( i, load(i) - (*rhs).load(i) );
2644    }
2645    for( ; remainder && i<N; ++i ) {
2646       v_[i] -= (*rhs)[i];
2647    }
2648 }
2649 //*************************************************************************************************
2650 
2651 
2652 //*************************************************************************************************
2653 /*!\brief Default implementation of the subtraction assignment of a sparse vector.
2654 //
2655 // \param rhs The right-hand side sparse vector to be subtracted.
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         , size_t N          // Number of elements
2665         , bool TF           // Transpose flag
2666         , AlignmentFlag AF  // Alignment flag
2667         , PaddingFlag PF    // Padding flag
2668         , typename Tag >    // Type tag
2669 template< typename VT >     // Type of the right-hand side sparse vector
subAssign(const SparseVector<VT,TF> & rhs)2670 inline void StaticVector<Type,N,TF,AF,PF,Tag>::subAssign( const SparseVector<VT,TF>& rhs )
2671 {
2672    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2673 
2674    for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2675       v_[element->index()] -= element->value();
2676 }
2677 //*************************************************************************************************
2678 
2679 
2680 //*************************************************************************************************
2681 /*!\brief Default implementation of the multiplication assignment of a dense vector.
2682 //
2683 // \param rhs The right-hand side dense vector to be multiplied.
2684 // \return void
2685 //
2686 // This function must \b NOT be called explicitly! It is used internally for the performance
2687 // optimized evaluation of expression templates. Calling this function explicitly might result
2688 // in erroneous results and/or in compilation errors. Instead of using this function use the
2689 // assignment operator.
2690 */
2691 template< typename Type     // Data type of the vector
2692         , size_t N          // Number of elements
2693         , bool TF           // Transpose flag
2694         , AlignmentFlag AF  // Alignment flag
2695         , PaddingFlag PF    // Padding flag
2696         , typename Tag >    // Type tag
2697 template< typename VT >     // Type of the right-hand side dense vector
2698 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::multAssign( const DenseVector<VT,TF>& rhs )
2699    -> DisableIf_t< VectorizedMultAssign_v<VT> >
2700 {
2701    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2702 
2703    for( size_t i=0UL; i<N; ++i )
2704       v_[i] *= (*rhs)[i];
2705 }
2706 //*************************************************************************************************
2707 
2708 
2709 //*************************************************************************************************
2710 /*!\brief SIMD optimized implementation of the multiplication assignment of a dense vector.
2711 //
2712 // \param rhs The right-hand side dense vector to be multiplied.
2713 // \return void
2714 //
2715 // This function must \b NOT be called explicitly! It is used internally for the performance
2716 // optimized evaluation of expression templates. Calling this function explicitly might result
2717 // in erroneous results and/or in compilation errors. Instead of using this function use the
2718 // assignment operator.
2719 */
2720 template< typename Type     // Data type of the vector
2721         , size_t N          // Number of elements
2722         , bool TF           // Transpose flag
2723         , AlignmentFlag AF  // Alignment flag
2724         , PaddingFlag PF    // Padding flag
2725         , typename Tag >    // Type tag
2726 template< typename VT >     // Type of the right-hand side dense vector
2727 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::multAssign( const DenseVector<VT,TF>& rhs )
2728    -> EnableIf_t< VectorizedMultAssign_v<VT> >
2729 {
2730    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2731 
2732    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2733 
2734    constexpr bool remainder( PF == unpadded || !IsPadded_v<VT> );
2735 
2736    constexpr size_t ipos( remainder ? prevMultiple( N, SIMDSIZE ) : N );
2737    BLAZE_INTERNAL_ASSERT( ipos <= N, "Invalid end calculation" );
2738 
2739    size_t i( 0UL );
2740 
2741    for( ; i<ipos; i+=SIMDSIZE ) {
2742       store( i, load(i) * (*rhs).load(i) );
2743    }
2744    for( ; remainder && i<N; ++i ) {
2745       v_[i] *= (*rhs)[i];
2746    }
2747 }
2748 //*************************************************************************************************
2749 
2750 
2751 //*************************************************************************************************
2752 /*!\brief Default implementation of the multiplication assignment of a sparse vector.
2753 //
2754 // \param rhs The right-hand side sparse vector to be multiplied.
2755 // \return void
2756 //
2757 // This function must \b NOT be called explicitly! It is used internally for the performance
2758 // optimized evaluation of expression templates. Calling this function explicitly might result
2759 // in erroneous results and/or in compilation errors. Instead of using this function use the
2760 // assignment operator.
2761 */
2762 template< typename Type     // Data type of the vector
2763         , size_t N          // Number of elements
2764         , bool TF           // Transpose flag
2765         , AlignmentFlag AF  // Alignment flag
2766         , PaddingFlag PF    // Padding flag
2767         , typename Tag >    // Type tag
2768 template< typename VT >     // Type of the right-hand side sparse vector
multAssign(const SparseVector<VT,TF> & rhs)2769 inline void StaticVector<Type,N,TF,AF,PF,Tag>::multAssign( const SparseVector<VT,TF>& rhs )
2770 {
2771    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2772 
2773    const StaticVector tmp( serial( *this ) );
2774 
2775    reset();
2776 
2777    for( auto element=(*rhs).begin(); element!=(*rhs).end(); ++element )
2778       v_[element->index()] = tmp[element->index()] * element->value();
2779 }
2780 //*************************************************************************************************
2781 
2782 
2783 //*************************************************************************************************
2784 /*!\brief Default implementation of the division assignment of a dense vector.
2785 //
2786 // \param rhs The right-hand side dense vector divisor.
2787 // \return void
2788 //
2789 // This function must \b NOT be called explicitly! It is used internally for the performance
2790 // optimized evaluation of expression templates. Calling this function explicitly might result
2791 // in erroneous results and/or in compilation errors. Instead of using this function use the
2792 // assignment operator.
2793 */
2794 template< typename Type     // Data type of the vector
2795         , size_t N          // Number of elements
2796         , bool TF           // Transpose flag
2797         , AlignmentFlag AF  // Alignment flag
2798         , PaddingFlag PF    // Padding flag
2799         , typename Tag >    // Type tag
2800 template< typename VT >     // Type of the right-hand side dense vector
2801 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::divAssign( const DenseVector<VT,TF>& rhs )
2802    -> DisableIf_t< VectorizedDivAssign_v<VT> >
2803 {
2804    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2805 
2806    for( size_t i=0UL; i<N; ++i )
2807       v_[i] /= (*rhs)[i];
2808 }
2809 //*************************************************************************************************
2810 
2811 
2812 //*************************************************************************************************
2813 /*!\brief SIMD optimized implementation of the division assignment of a dense vector.
2814 //
2815 // \param rhs The right-hand side dense vector divisor.
2816 // \return void
2817 //
2818 // This function must \b NOT be called explicitly! It is used internally for the performance
2819 // optimized evaluation of expression templates. Calling this function explicitly might result
2820 // in erroneous results and/or in compilation errors. Instead of using this function use the
2821 // assignment operator.
2822 */
2823 template< typename Type     // Data type of the vector
2824         , size_t N          // Number of elements
2825         , bool TF           // Transpose flag
2826         , AlignmentFlag AF  // Alignment flag
2827         , PaddingFlag PF    // Padding flag
2828         , typename Tag >    // Type tag
2829 template< typename VT >     // Type of the right-hand side dense vector
2830 inline auto StaticVector<Type,N,TF,AF,PF,Tag>::divAssign( const DenseVector<VT,TF>& rhs )
2831    -> EnableIf_t< VectorizedDivAssign_v<VT> >
2832 {
2833    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2834 
2835    BLAZE_INTERNAL_ASSERT( (*rhs).size() == N, "Invalid vector sizes" );
2836 
2837    constexpr size_t ipos( prevMultiple( N, SIMDSIZE ) );
2838    BLAZE_INTERNAL_ASSERT( ipos <= N, "Invalid end calculation" );
2839 
2840    size_t i( 0UL );
2841 
2842    for( ; i<ipos; i+=SIMDSIZE ) {
2843       store( i, load(i) / (*rhs).load(i) );
2844    }
2845    for( ; i<N; ++i ) {
2846       v_[i] /= (*rhs)[i];
2847    }
2848 }
2849 //*************************************************************************************************
2850 
2851 
2852 
2853 
2854 
2855 
2856 
2857 
2858 //=================================================================================================
2859 //
2860 //  STATICVECTOR OPERATORS
2861 //
2862 //=================================================================================================
2863 
2864 //*************************************************************************************************
2865 /*!\name StaticVector operators */
2866 //@{
2867 template< typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2868 constexpr void reset( StaticVector<Type,N,TF,AF,PF,Tag>& v );
2869 
2870 template< typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2871 constexpr void clear( StaticVector<Type,N,TF,AF,PF,Tag>& v );
2872 
2873 template< RelaxationFlag RF, typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2874 bool isDefault( const StaticVector<Type,N,TF,AF,PF,Tag>& v );
2875 
2876 template< typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2877 constexpr bool isIntact( const StaticVector<Type,N,TF,AF,PF,Tag>& v ) noexcept;
2878 
2879 template< typename Type, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2880 const StaticVector<Type,2UL,TF,AF,PF,Tag> perp( const StaticVector<Type,2UL,TF,AF,PF,Tag>& v );
2881 
2882 template< typename Type, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2883 const StaticVector<Type,3UL,TF,AF,PF,Tag> perp( const StaticVector<Type,3UL,TF,AF,PF,Tag>& v );
2884 
2885 template< typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2886 void swap( StaticVector<Type,N,TF,AF,PF,Tag>& a, StaticVector<Type,N,TF,AF,PF,Tag>& b ) noexcept;
2887 
2888 template< size_t I, typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2889 constexpr Type& get( StaticVector<Type,N,TF,AF,PF,Tag>& v ) noexcept;
2890 
2891 template< size_t I, typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2892 constexpr Type&& get( StaticVector<Type,N,TF,AF,PF,Tag>&& v ) noexcept;
2893 
2894 template< size_t I, typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2895 constexpr const Type& get( const StaticVector<Type,N,TF,AF,PF,Tag>& v) noexcept;
2896 
2897 template< size_t I, typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
2898 constexpr const Type&& get( const StaticVector<Type,N,TF,AF,PF,Tag>&& v ) noexcept;
2899 //@}
2900 //*************************************************************************************************
2901 
2902 
2903 //*************************************************************************************************
2904 /*!\brief Resetting the given static vector.
2905 // \ingroup static_vector
2906 //
2907 // \param v The vector to be resetted.
2908 // \return void
2909 */
2910 template< typename Type     // Data type of the vector
2911         , size_t N          // Number of elements
2912         , bool TF           // Transpose flag
2913         , AlignmentFlag AF  // Alignment flag
2914         , PaddingFlag PF    // Padding flag
2915         , typename Tag >    // Type tag
reset(StaticVector<Type,N,TF,AF,PF,Tag> & v)2916 constexpr void reset( StaticVector<Type,N,TF,AF,PF,Tag>& v )
2917 {
2918    v.reset();
2919 }
2920 //*************************************************************************************************
2921 
2922 
2923 //*************************************************************************************************
2924 /*!\brief Clearing the given static vector.
2925 // \ingroup static_vector
2926 //
2927 // \param v The vector to be cleared.
2928 // \return void
2929 //
2930 // Clearing a static vector is equivalent to resetting it via the reset() function.
2931 */
2932 template< typename Type     // Data type of the vector
2933         , size_t N          // Number of elements
2934         , bool TF           // Transpose flag
2935         , AlignmentFlag AF  // Alignment flag
2936         , PaddingFlag PF    // Padding flag
2937         , typename Tag >    // Type tag
clear(StaticVector<Type,N,TF,AF,PF,Tag> & v)2938 constexpr void clear( StaticVector<Type,N,TF,AF,PF,Tag>& v )
2939 {
2940    v.reset();
2941 }
2942 //*************************************************************************************************
2943 
2944 
2945 //*************************************************************************************************
2946 /*!\brief Returns whether the given static vector is in default state.
2947 // \ingroup static_vector
2948 //
2949 // \param v The vector to be tested for its default state.
2950 // \return \a true in case the given vector is component-wise zero, \a false otherwise.
2951 //
2952 // This function checks whether the static vector is in default state. For instance, in case
2953 // the static vector is instantiated for a built-in integral or floating point data type, the
2954 // function returns \a true in case all vector elements are 0 and \a false in case any vector
2955 // element is not 0. Following example demonstrates the use of the \a isDefault function:
2956 
2957    \code
2958    blaze::StaticVector<double,3> a;
2959    // ... Initialization
2960    if( isDefault( a ) ) { ... }
2961    \endcode
2962 
2963 // Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed
2964 // semantics (blaze::relaxed):
2965 
2966    \code
2967    if( isDefault<relaxed>( a ) ) { ... }
2968    \endcode
2969 */
2970 template< RelaxationFlag RF  // Relaxation flag
2971         , typename Type      // Data type of the vector
2972         , size_t N           // Number of elements
2973         , bool TF            // Transpose flag
2974         , AlignmentFlag AF   // Alignment flag
2975         , PaddingFlag PF     // Padding flag
2976         , typename Tag >     // Type tag
isDefault(const StaticVector<Type,N,TF,AF,PF,Tag> & v)2977 inline bool isDefault( const StaticVector<Type,N,TF,AF,PF,Tag>& v )
2978 {
2979    for( size_t i=0UL; i<N; ++i )
2980       if( !isDefault<RF>( v[i] ) ) return false;
2981    return true;
2982 }
2983 //*************************************************************************************************
2984 
2985 
2986 //*************************************************************************************************
2987 /*!\brief Returns whether the invariants of the given static vector are intact.
2988 // \ingroup static_vector
2989 //
2990 // \param v The static vector to be tested.
2991 // \return \a true in case the given vector's invariants are intact, \a false otherwise.
2992 //
2993 // This function checks whether the invariants of the static vector are intact, i.e. if its
2994 // state is valid. In case the invariants are intact, the function returns \a true, else it
2995 // will return \a false. The following example demonstrates the use of the \a isIntact()
2996 // function:
2997 
2998    \code
2999    blaze::StaticVector<double,3> a;
3000    // ... Resizing and initialization
3001    if( isIntact( a ) ) { ... }
3002    \endcode
3003 */
3004 template< typename Type     // Data type of the vector
3005         , size_t N          // Number of elements
3006         , bool TF           // Transpose flag
3007         , AlignmentFlag AF  // Alignment flag
3008         , PaddingFlag PF    // Padding flag
3009         , typename Tag >    // Type tag
isIntact(const StaticVector<Type,N,TF,AF,PF,Tag> & v)3010 constexpr bool isIntact( const StaticVector<Type,N,TF,AF,PF,Tag>& v ) noexcept
3011 {
3012    return v.isIntact();
3013 }
3014 //*************************************************************************************************
3015 
3016 
3017 //*************************************************************************************************
3018 /*!\brief Unary perp dot product operator for the calculation of a perpendicular vector
3019 //        (\f$ \vec{a}=\vec{b}^\perp \f$).
3020 //
3021 // \param v The vector to be rotated.
3022 // \return The perpendicular vector.
3023 //
3024 // The "perp dot product" \f$ \vec{a}^\perp \cdot b \f$ for the vectors \f$ \vec{a} \f$ and
3025 // \f$ \vec{b} \f$ is a modification of the two-dimensional dot product in which \f$ \vec{a} \f$
3026 // is replaced by the perpendicular vector rotated 90 degrees to the left defined by Hill (1994).
3027 */
3028 template< typename Type     // Data type of the vector
3029         , bool TF           // Transpose flag
3030         , AlignmentFlag AF  // Alignment flag
3031         , PaddingFlag PF    // Padding flag
3032         , typename Tag >    // Type tag
3033 inline const StaticVector<Type,2UL,TF,AF,PF,Tag>
perp(const StaticVector<Type,2UL,TF,AF,PF,Tag> & v)3034    perp( const StaticVector<Type,2UL,TF,AF,PF,Tag>& v )
3035 {
3036    return StaticVector<Type,2UL,TF,AF,PF,Tag>( -v[1UL], v[0UL] );
3037 }
3038 //*************************************************************************************************
3039 
3040 
3041 //*************************************************************************************************
3042 /*!\brief Creates a perpendicular vector b which satisfies \f$ \vec{a} \cdot \vec{b} = 0 \f$.
3043 //
3044 // \param v The vector to be rotated.
3045 // \return The perpendicular vector.
3046 //
3047 // \note The perpendicular vector may have any length!
3048 */
3049 template< typename Type     // Data type of the vector
3050         , bool TF           // Transpose flag
3051         , AlignmentFlag AF  // Alignment flag
3052         , PaddingFlag PF    // Padding flag
3053         , typename Tag >    // Type tag
3054 inline const StaticVector<Type,3UL,TF,AF,PF,Tag>
perp(const StaticVector<Type,3UL,TF,AF,PF,Tag> & v)3055    perp( const StaticVector<Type,3UL,TF,AF,PF,Tag>& v )
3056 {
3057    if( v[0] != Type() || v[1] != Type() )
3058       return StaticVector<Type,3UL,TF,AF,PF,Tag>( v[1UL], -v[0UL], Type() );
3059    else
3060       return StaticVector<Type,3UL,TF,AF,PF,Tag>( Type(), v[2UL], -v[1UL] );
3061 }
3062 //*************************************************************************************************
3063 
3064 
3065 //*************************************************************************************************
3066 /*!\brief Swapping the contents of two static vectors.
3067 // \ingroup static_vector
3068 //
3069 // \param a The first vector to be swapped.
3070 // \param b The second vector to be swapped.
3071 // \return void
3072 */
3073 template< typename Type     // Data type of the vector
3074         , size_t N          // Number of elements
3075         , bool TF           // Transpose flag
3076         , AlignmentFlag AF  // Alignment flag
3077         , PaddingFlag PF    // Padding flag
3078         , typename Tag >    // Type tag
swap(StaticVector<Type,N,TF,AF,PF,Tag> & a,StaticVector<Type,N,TF,AF,PF,Tag> & b)3079 inline void swap( StaticVector<Type,N,TF,AF,PF,Tag>& a, StaticVector<Type,N,TF,AF,PF,Tag>& b ) noexcept
3080 {
3081    a.swap( b );
3082 }
3083 //*************************************************************************************************
3084 
3085 
3086 //*************************************************************************************************
3087 /*!\brief Tuple-like index-based access the contents of a static vector.
3088 // \ingroup static_vector
3089 //
3090 // \param v The vector to be accessed.
3091 // \return Reference to the accessed value.
3092 */
3093 template< size_t I          // Compile time access index
3094         , typename Type     // Data type of the vector
3095         , size_t N          // Number of elements
3096         , bool TF           // Transpose flag
3097         , AlignmentFlag AF  // Alignment flag
3098         , PaddingFlag PF    // Padding flag
3099         , typename Tag >    // Type tag
get(StaticVector<Type,N,TF,AF,PF,Tag> & v)3100 constexpr Type& get( StaticVector<Type,N,TF,AF,PF,Tag>& v ) noexcept
3101 {
3102    BLAZE_STATIC_ASSERT_MSG( I < N, "Invalid vector access index" );
3103    return v[I];
3104 }
3105 //*************************************************************************************************
3106 
3107 
3108 //*************************************************************************************************
3109 /*!\brief Tuple-like index-based access the contents of a temporary static vector.
3110 // \ingroup static_vector
3111 //
3112 // \param v The vector to be accessed.
3113 // \return Reference to the accessed value.
3114 */
3115 template< size_t I          // Compile time access index
3116         , typename Type     // Data type of the vector
3117         , size_t N          // Number of elements
3118         , bool TF           // Transpose flag
3119         , AlignmentFlag AF  // Alignment flag
3120         , PaddingFlag PF    // Padding flag
3121         , typename Tag >    // Type tag
get(StaticVector<Type,N,TF,AF,PF,Tag> && v)3122 constexpr Type&& get( StaticVector<Type,N,TF,AF,PF,Tag>&& v ) noexcept
3123 {
3124    BLAZE_STATIC_ASSERT_MSG( I < N, "Invalid vector access index" );
3125    return std::move( v[I] );
3126 }
3127 //*************************************************************************************************
3128 
3129 
3130 //*************************************************************************************************
3131 /*!\brief Tuple-like index-based access the contents of a constant static vector.
3132 // \ingroup static_vector
3133 //
3134 // \param v The vector to be accessed.
3135 // \return Reference to the accessed value.
3136 */
3137 template< size_t I          // Compile time access index
3138         , typename Type     // Data type of the vector
3139         , size_t N          // Number of elements
3140         , bool TF           // Transpose flag
3141         , AlignmentFlag AF  // Alignment flag
3142         , PaddingFlag PF    // Padding flag
3143         , typename Tag >    // Type tag
get(const StaticVector<Type,N,TF,AF,PF,Tag> & v)3144 constexpr const Type& get( const StaticVector<Type,N,TF,AF,PF,Tag>& v) noexcept
3145 {
3146    BLAZE_STATIC_ASSERT_MSG( I < N, "Invalid vector access index" );
3147    return v[I];
3148 }
3149 //*************************************************************************************************
3150 
3151 
3152 //*************************************************************************************************
3153 /*!\brief Tuple-like index-based access the contents of a constant temporary static vector.
3154 // \ingroup static_vector
3155 //
3156 // \param v The vector to be accessed.
3157 // \return Reference to the accessed value.
3158 */
3159 template< size_t I          // Compile time access index
3160         , typename Type     // Data type of the vector
3161         , size_t N          // Number of elements
3162         , bool TF           // Transpose flag
3163         , AlignmentFlag AF  // Alignment flag
3164         , PaddingFlag PF    // Padding flag
3165         , typename Tag >    // Type tag
get(const StaticVector<Type,N,TF,AF,PF,Tag> && v)3166 constexpr const Type&& get( const StaticVector<Type,N,TF,AF,PF,Tag>&& v ) noexcept
3167 {
3168    BLAZE_STATIC_ASSERT_MSG( I < N, "Invalid vector access index" );
3169    return std::move( v[I] );
3170 }
3171 //*************************************************************************************************
3172 
3173 
3174 
3175 
3176 //=================================================================================================
3177 //
3178 //  SIZE SPECIALIZATIONS
3179 //
3180 //=================================================================================================
3181 
3182 //*************************************************************************************************
3183 /*! \cond BLAZE_INTERNAL */
3184 template< typename T, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
3185 struct Size< StaticVector<T,N,TF,AF,PF,Tag>, 0UL >
3186    : public Ptrdiff_t<N>
3187 {};
3188 /*! \endcond */
3189 //*************************************************************************************************
3190 
3191 
3192 
3193 
3194 //=================================================================================================
3195 //
3196 //  MAXSIZE SPECIALIZATIONS
3197 //
3198 //=================================================================================================
3199 
3200 //*************************************************************************************************
3201 /*! \cond BLAZE_INTERNAL */
3202 template< typename T, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
3203 struct MaxSize< StaticVector<T,N,TF,AF,PF,Tag>, 0UL >
3204    : public Ptrdiff_t<N>
3205 {};
3206 /*! \endcond */
3207 //*************************************************************************************************
3208 
3209 
3210 
3211 
3212 //=================================================================================================
3213 //
3214 //  HASCONSTDATAACCESS SPECIALIZATIONS
3215 //
3216 //=================================================================================================
3217 
3218 //*************************************************************************************************
3219 /*! \cond BLAZE_INTERNAL */
3220 template< typename T, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
3221 struct HasConstDataAccess< StaticVector<T,N,TF,AF,PF,Tag> >
3222    : public TrueType
3223 {};
3224 /*! \endcond */
3225 //*************************************************************************************************
3226 
3227 
3228 
3229 
3230 //=================================================================================================
3231 //
3232 //  HASMUTABLEDATAACCESS SPECIALIZATIONS
3233 //
3234 //=================================================================================================
3235 
3236 //*************************************************************************************************
3237 /*! \cond BLAZE_INTERNAL */
3238 template< typename T, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
3239 struct HasMutableDataAccess< StaticVector<T,N,TF,AF,PF,Tag> >
3240    : public TrueType
3241 {};
3242 /*! \endcond */
3243 //*************************************************************************************************
3244 
3245 
3246 
3247 
3248 //=================================================================================================
3249 //
3250 //  ISALIGNED SPECIALIZATIONS
3251 //
3252 //=================================================================================================
3253 
3254 //*************************************************************************************************
3255 /*! \cond BLAZE_INTERNAL */
3256 template< typename T, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
3257 struct IsAligned< StaticVector<T,N,TF,AF,PF,Tag> >
3258    : public BoolConstant< AF == aligned >
3259 {};
3260 /*! \endcond */
3261 //*************************************************************************************************
3262 
3263 
3264 
3265 
3266 //=================================================================================================
3267 //
3268 //  ISCONTIGUOUS SPECIALIZATIONS
3269 //
3270 //=================================================================================================
3271 
3272 //*************************************************************************************************
3273 /*! \cond BLAZE_INTERNAL */
3274 template< typename T, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
3275 struct IsContiguous< StaticVector<T,N,TF,AF,PF,Tag> >
3276    : public TrueType
3277 {};
3278 /*! \endcond */
3279 //*************************************************************************************************
3280 
3281 
3282 
3283 
3284 //=================================================================================================
3285 //
3286 //  ISPADDED SPECIALIZATIONS
3287 //
3288 //=================================================================================================
3289 
3290 //*************************************************************************************************
3291 /*! \cond BLAZE_INTERNAL */
3292 template< typename T, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
3293 struct IsPadded< StaticVector<T,N,TF,AF,PF,Tag> >
3294    : public BoolConstant< PF == padded >
3295 {};
3296 /*! \endcond */
3297 //*************************************************************************************************
3298 
3299 
3300 
3301 
3302 //=================================================================================================
3303 //
3304 //  ADDTRAIT SPECIALIZATIONS
3305 //
3306 //=================================================================================================
3307 
3308 //*************************************************************************************************
3309 /*! \cond BLAZE_INTERNAL */
3310 template< typename T1, typename T2 >
3311 struct AddTraitEval2< T1, T2
3312                     , EnableIf_t< IsVector_v<T1> &&
3313                                   IsVector_v<T2> &&
3314                                   ( Size_v<T1,0UL> != DefaultSize_v ||
3315                                     Size_v<T2,0UL> != DefaultSize_v ) > >
3316 {
3317    using Type = StaticVector< AddTrait_t< ElementType_t<T1>, ElementType_t<T2> >
3318                             , max( Size_v<T1,0UL>, Size_v<T2,0UL> )
3319                             , TransposeFlag_v<T1>
3320                             , defaultAlignmentFlag
3321                             , defaultPaddingFlag
3322                             , AddTrait_t< TagType_t<T1>, TagType_t<T2> > >;
3323 };
3324 /*! \endcond */
3325 //*************************************************************************************************
3326 
3327 
3328 
3329 
3330 //=================================================================================================
3331 //
3332 //  SUBTRAIT SPECIALIZATIONS
3333 //
3334 //=================================================================================================
3335 
3336 //*************************************************************************************************
3337 /*! \cond BLAZE_INTERNAL */
3338 template< typename T1, typename T2 >
3339 struct SubTraitEval2< T1, T2
3340                     , EnableIf_t< IsVector_v<T1> &&
3341                                   IsVector_v<T2> &&
3342                                   ( Size_v<T1,0UL> != DefaultSize_v ||
3343                                     Size_v<T2,0UL> != DefaultSize_v ) > >
3344 {
3345    using Type = StaticVector< SubTrait_t< ElementType_t<T1>, ElementType_t<T2> >
3346                             , max( Size_v<T1,0UL>, Size_v<T2,0UL> )
3347                             , TransposeFlag_v<T1>
3348                             , defaultAlignmentFlag
3349                             , defaultPaddingFlag
3350                             , SubTrait_t< TagType_t<T1>, TagType_t<T2> > >;
3351 };
3352 /*! \endcond */
3353 //*************************************************************************************************
3354 
3355 
3356 
3357 
3358 //=================================================================================================
3359 //
3360 //  MULTTRAIT SPECIALIZATIONS
3361 //
3362 //=================================================================================================
3363 
3364 //*************************************************************************************************
3365 /*! \cond BLAZE_INTERNAL */
3366 template< typename T1, typename T2 >
3367 struct MultTraitEval2< T1, T2
3368                      , EnableIf_t< IsVector_v<T1> &&
3369                                    IsScalar_v<T2> &&
3370                                    ( Size_v<T1,0UL> != DefaultSize_v ) > >
3371 {
3372    using Type = StaticVector< MultTrait_t< ElementType_t<T1>, T2 >
3373                             , Size_v<T1,0UL>
3374                             , TransposeFlag_v<T1>
3375                             , defaultAlignmentFlag
3376                             , defaultPaddingFlag
3377                             , MultTrait_t< TagType_t<T1>, T2 > >;
3378 };
3379 
3380 template< typename T1, typename T2 >
3381 struct MultTraitEval2< T1, T2
3382                      , EnableIf_t< IsScalar_v<T1> &&
3383                                    IsVector_v<T2> &&
3384                                    ( Size_v<T2,0UL> != DefaultSize_v ) > >
3385 {
3386    using Type = StaticVector< MultTrait_t< T1, ElementType_t<T2> >
3387                             , Size_v<T2,0UL>
3388                             , TransposeFlag_v<T2>
3389                             , defaultAlignmentFlag
3390                             , defaultPaddingFlag
3391                             , MultTrait_t< T1, TagType_t<T2> > >;
3392 };
3393 
3394 template< typename T1, typename T2 >
3395 struct MultTraitEval2< T1, T2
3396                      , EnableIf_t< ( ( IsRowVector_v<T1> && IsRowVector_v<T2> ) ||
3397                                      ( IsColumnVector_v<T1> && IsColumnVector_v<T2> ) ) &&
3398                                    IsDenseVector_v<T1> &&
3399                                    IsDenseVector_v<T2> &&
3400                                    ( Size_v<T1,0UL> != DefaultSize_v || Size_v<T2,0UL> != DefaultSize_v ) > >
3401 {
3402    using Type = StaticVector< MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >
3403                             , max( Size_v<T1,0UL>, Size_v<T2,0UL> )
3404                             , TransposeFlag_v<T1>
3405                             , defaultAlignmentFlag
3406                             , defaultPaddingFlag
3407                             , MultTrait_t< TagType_t<T1>, TagType_t<T2> > >;
3408 };
3409 
3410 template< typename T1, typename T2 >
3411 struct MultTraitEval2< T1, T2
3412                      , EnableIf_t< IsMatrix_v<T1> &&
3413                                    IsColumnVector_v<T2> &&
3414                                    ( Size_v<T1,0UL> != DefaultSize_v ||
3415                                      ( IsSquare_v<T1> && Size_v<T2,0UL> != DefaultSize_v ) ) > >
3416 {
3417    using MultType = MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
3418    using MultTag  = MultTrait_t< TagType_t<T1>, TagType_t<T2> >;
3419 
3420    using Type = StaticVector< AddTrait_t<MultType,MultType>
3421                             , ( Size_v<T1,0UL> != DefaultSize_v ? Size_v<T1,0UL> : Size_v<T2,0UL> )
3422                             , false
3423                             , defaultAlignmentFlag
3424                             , defaultPaddingFlag
3425                             , AddTrait_t<MultTag,MultTag> >;
3426 };
3427 
3428 template< typename T1, typename T2 >
3429 struct MultTraitEval2< T1, T2
3430                      , EnableIf_t< IsRowVector_v<T1> &&
3431                                    IsMatrix_v<T2> &&
3432                                    ( Size_v<T2,1UL> != DefaultSize_v ||
3433                                      ( IsSquare_v<T2> && Size_v<T1,0UL> != DefaultSize_v ) ) > >
3434 {
3435    using MultType = MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
3436    using MultTag  = MultTrait_t< TagType_t<T1>, TagType_t<T2> >;
3437 
3438    using Type = StaticVector< AddTrait_t<MultType,MultType>
3439                             , ( Size_v<T2,1UL> != DefaultSize_v ? Size_v<T2,1UL> : Size_v<T1,0UL> )
3440                             , true
3441                             , defaultAlignmentFlag
3442                             , defaultPaddingFlag
3443                             , AddTrait_t<MultTag,MultTag> >;
3444 };
3445 /*! \endcond */
3446 //*************************************************************************************************
3447 
3448 
3449 
3450 
3451 //=================================================================================================
3452 //
3453 //  KRONTRAIT SPECIALIZATIONS
3454 //
3455 //=================================================================================================
3456 
3457 //*************************************************************************************************
3458 /*! \cond BLAZE_INTERNAL */
3459 template< typename T1, typename T2 >
3460 struct KronTraitEval2< T1, T2
3461                      , EnableIf_t< IsDenseVector_v<T1> &&
3462                                    IsDenseVector_v<T2> &&
3463                                    ( Size_v<T1,0UL> != DefaultSize_v ) &&
3464                                    ( Size_v<T2,0UL> != DefaultSize_v ) > >
3465 {
3466    using Type = StaticVector< MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >
3467                             , Size_v<T1,0UL> * Size_v<T2,0UL>
3468                             , TransposeFlag_v<T2>
3469                             , defaultAlignmentFlag
3470                             , defaultPaddingFlag
3471                             , MultTrait_t< TagType_t<T1>, TagType_t<T2> > >;
3472 };
3473 /*! \endcond */
3474 //*************************************************************************************************
3475 
3476 
3477 
3478 
3479 //=================================================================================================
3480 //
3481 //  DIVTRAIT SPECIALIZATIONS
3482 //
3483 //=================================================================================================
3484 
3485 //*************************************************************************************************
3486 /*! \cond BLAZE_INTERNAL */
3487 template< typename T1, typename T2 >
3488 struct DivTraitEval2< T1, T2
3489                     , EnableIf_t< IsVector_v<T1> &&
3490                                   IsScalar_v<T2> &&
3491                                   ( Size_v<T1,0UL> != DefaultSize_v ) > >
3492 {
3493    using Type = StaticVector< DivTrait_t< ElementType_t<T1>, T2 >
3494                             , Size_v<T1,0UL>
3495                             , TransposeFlag_v<T1>
3496                             , defaultAlignmentFlag
3497                             , defaultPaddingFlag
3498                             , DivTrait_t< TagType_t<T1>, T2 > >;
3499 };
3500 
3501 template< typename T1, typename T2 >
3502 struct DivTraitEval2< T1, T2
3503                     , EnableIf_t< IsDenseVector_v<T1> &&
3504                                   IsDenseVector_v<T2> &&
3505                                   ( Size_v<T1,0UL> != DefaultSize_v ||
3506                                     Size_v<T2,0UL> != DefaultSize_v ) > >
3507 {
3508    using Type = StaticVector< DivTrait_t< ElementType_t<T1>, ElementType_t<T2> >
3509                             , max( Size_v<T1,0UL>, Size_v<T2,0UL> )
3510                             , TransposeFlag_v<T1>
3511                             , defaultAlignmentFlag
3512                             , defaultPaddingFlag
3513                             , DivTrait_t< TagType_t<T1>, TagType_t<T2> > >;
3514 };
3515 /*! \endcond */
3516 //*************************************************************************************************
3517 
3518 
3519 
3520 
3521 //=================================================================================================
3522 //
3523 //  CROSSTRAIT SPECIALIZATIONS
3524 //
3525 //=================================================================================================
3526 
3527 //*************************************************************************************************
3528 /*! \cond BLAZE_INTERNAL */
3529 template< typename T1, typename T2 >
3530 struct CrossTraitEval2< T1, T2
3531                       , EnableIf_t< IsVector_v<T1> && IsVector_v<T2> > >
3532 {
3533    using MultType = MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
3534    using MultTag  = MultTrait_t< TagType_t<T1>, TagType_t<T2> >;
3535 
3536    using Type = StaticVector< SubTrait_t<MultType,MultType>
3537                             , 3UL
3538                             , TransposeFlag_v<T1>
3539                             , defaultAlignmentFlag
3540                             , defaultPaddingFlag
3541                             , SubTrait_t<MultTag,MultTag> >;
3542 };
3543 /*! \endcond */
3544 //*************************************************************************************************
3545 
3546 
3547 
3548 
3549 //=================================================================================================
3550 //
3551 //  MAPTRAIT SPECIALIZATIONS
3552 //
3553 //=================================================================================================
3554 
3555 //*************************************************************************************************
3556 /*! \cond BLAZE_INTERNAL */
3557 template< typename T, typename OP >
3558 struct UnaryMapTraitEval2< T, OP
3559                          , EnableIf_t< IsVector_v<T> &&
3560                                        Size_v<T,0UL> != DefaultSize_v > >
3561 {
3562    using ElementType = decltype( std::declval<OP>()( std::declval< ElementType_t<T> >() ) );
3563 
3564    using Type = StaticVector< EvaluateTrait_t<ElementType>
3565                             , Size_v<T,0UL>
3566                             , TransposeFlag_v<T>
3567                             , defaultAlignmentFlag
3568                             , defaultPaddingFlag
3569                             , MapTrait_t< TagType_t<T>, OP > >;
3570 };
3571 /*! \endcond */
3572 //*************************************************************************************************
3573 
3574 
3575 //*************************************************************************************************
3576 /*! \cond BLAZE_INTERNAL */
3577 template< typename T1, typename T2, typename OP >
3578 struct BinaryMapTraitEval2< T1, T2, OP
3579                           , EnableIf_t< ( ( IsRowVector_v<T1> && IsRowVector_v<T2> ) ||
3580                                           ( IsColumnVector_v<T1> && IsColumnVector_v<T2> ) ) &&
3581                                         ( Size_v<T1,0UL> != DefaultSize_v ||
3582                                           Size_v<T2,0UL> != DefaultSize_v ) > >
3583 {
3584    using ElementType = decltype( std::declval<OP>()( std::declval< ElementType_t<T1> >()
3585                                                    , std::declval< ElementType_t<T2> >() ) );
3586 
3587    using Type = StaticVector< EvaluateTrait_t<ElementType>
3588                             , max( Size_v<T1,0UL>, Size_v<T2,0UL> )
3589                             , TransposeFlag_v<T1>
3590                             , defaultAlignmentFlag
3591                             , defaultPaddingFlag
3592                             , MapTrait_t< TagType_t<T1>, TagType_t<T2>, OP > >;
3593 };
3594 /*! \endcond */
3595 //*************************************************************************************************
3596 
3597 
3598 
3599 
3600 //=================================================================================================
3601 //
3602 //  REDUCETRAIT SPECIALIZATIONS
3603 //
3604 //=================================================================================================
3605 
3606 //*************************************************************************************************
3607 /*! \cond BLAZE_INTERNAL */
3608 template< typename T, typename OP, ReductionFlag RF >
3609 struct PartialReduceTraitEval2< T, OP, RF
3610                               , EnableIf_t< IsMatrix_v<T> &&
3611                                             Size_v<T,0UL> != DefaultSize_v &&
3612                                             Size_v<T,1UL> != DefaultSize_v > >
3613 {
3614    using ET = ElementType_t<T>;
3615 
3616    static constexpr bool TF = ( RF == columnwise );
3617 
3618    using Type = StaticVector< decltype( std::declval<OP>()( std::declval<ET>(), std::declval<ET>() ) )
3619                             , Size_v< T, TF ? 1UL : 0UL >
3620                             , TF
3621                             , defaultAlignmentFlag
3622                             , defaultPaddingFlag
3623                             , MapTrait_t< TagType_t<T>, OP > >;
3624 };
3625 /*! \endcond */
3626 //*************************************************************************************************
3627 
3628 
3629 
3630 
3631 //=================================================================================================
3632 //
3633 //  REPEATTRAIT SPECIALIZATIONS
3634 //
3635 //=================================================================================================
3636 
3637 //*************************************************************************************************
3638 /*! \cond BLAZE_INTERNAL */
3639 template< typename T, size_t R0 >
3640 struct RepeatTraitEval2< T, R0, inf, inf
3641                        , EnableIf_t< IsDenseVector_v<T> &&
3642                                      ( R0 != inf ) &&
3643                                      ( Size_v<T,0UL> != DefaultSize_v ) > >
3644 {
3645    using Type = StaticVector< ElementType_t<T>
3646                             , R0*Size_v<T,0UL>
3647                             , TransposeFlag_v<T>
3648                             , defaultAlignmentFlag
3649                             , defaultPaddingFlag
3650                             , TagType_t<T> >;
3651 };
3652 /*! \endcond */
3653 //*************************************************************************************************
3654 
3655 
3656 
3657 
3658 //=================================================================================================
3659 //
3660 //  SOLVETRAIT SPECIALIZATIONS
3661 //
3662 //=================================================================================================
3663 
3664 //*************************************************************************************************
3665 /*! \cond BLAZE_INTERNAL */
3666 template< typename T1, typename T2 >
3667 struct SolveTraitEval2< T1, T2
3668                       , EnableIf_t< IsDenseMatrix_v<T1> &&
3669                                     IsDenseVector_v<T2> &&
3670                                     ( ( Size_v<T1,0UL> != DefaultSize_v ) ||
3671                                       ( Size_v<T1,1UL> != DefaultSize_v ) ||
3672                                       ( Size_v<T2,0UL> != DefaultSize_v ) ) > >
3673 {
3674    using Type = StaticVector< ElementType_t<T2>
3675                             , max( Size_v<T1,0UL>, Size_v<T1,1UL>, Size_v<T2,0UL> )
3676                             , TransposeFlag_v<T2>
3677                             , defaultAlignmentFlag
3678                             , defaultPaddingFlag
3679                             , TagType_t<T2> >;
3680 };
3681 /*! \endcond */
3682 //*************************************************************************************************
3683 
3684 
3685 
3686 
3687 //=================================================================================================
3688 //
3689 //  HIGHTYPE SPECIALIZATIONS
3690 //
3691 //=================================================================================================
3692 
3693 //*************************************************************************************************
3694 /*! \cond BLAZE_INTERNAL */
3695 template< typename T1, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag, typename T2 >
3696 struct HighType< StaticVector<T1,N,TF,AF,PF,Tag>, StaticVector<T2,N,TF,AF,PF,Tag> >
3697 {
3698    using Type = StaticVector< typename HighType<T1,T2>::Type, N, TF, AF, PF, Tag >;
3699 };
3700 /*! \endcond */
3701 //*************************************************************************************************
3702 
3703 
3704 
3705 
3706 //=================================================================================================
3707 //
3708 //  LOWTYPE SPECIALIZATIONS
3709 //
3710 //=================================================================================================
3711 
3712 //*************************************************************************************************
3713 /*! \cond BLAZE_INTERNAL */
3714 template< typename T1, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag, typename T2 >
3715 struct LowType< StaticVector<T1,N,TF,AF,PF,Tag>, StaticVector<T2,N,TF,AF,PF,Tag> >
3716 {
3717    using Type = StaticVector< typename LowType<T1,T2>::Type, N, TF, AF, PF, Tag >;
3718 };
3719 /*! \endcond */
3720 //*************************************************************************************************
3721 
3722 
3723 
3724 
3725 //=================================================================================================
3726 //
3727 //  SUBVECTORTRAIT SPECIALIZATIONS
3728 //
3729 //=================================================================================================
3730 
3731 //*************************************************************************************************
3732 /*! \cond BLAZE_INTERNAL */
3733 template< typename VT, size_t I, size_t N >
3734 struct SubvectorTraitEval2< VT, I, N
3735                           , EnableIf_t< I != inf && N != inf &&
3736                                         IsDenseVector_v<VT> > >
3737 {
3738    using Type = StaticVector< RemoveConst_t< ElementType_t<VT> >
3739                             , N
3740                             , TransposeFlag_v<VT>
3741                             , defaultAlignmentFlag
3742                             , defaultPaddingFlag
3743                             , TagType_t<VT> >;
3744 };
3745 /*! \endcond */
3746 //*************************************************************************************************
3747 
3748 
3749 
3750 
3751 //=================================================================================================
3752 //
3753 //  ELEMENTSTRAIT SPECIALIZATIONS
3754 //
3755 //=================================================================================================
3756 
3757 //*************************************************************************************************
3758 /*! \cond BLAZE_INTERNAL */
3759 template< typename VT, size_t N >
3760 struct ElementsTraitEval2< VT, N
3761                          , EnableIf_t< N != 0UL &&
3762                                        IsDenseVector_v<VT> > >
3763 {
3764    using Type = StaticVector< RemoveConst_t< ElementType_t<VT> >
3765                             , N
3766                             , TransposeFlag_v<VT>
3767                             , defaultAlignmentFlag
3768                             , defaultPaddingFlag
3769                             , TagType_t<VT> >;
3770 };
3771 /*! \endcond */
3772 //*************************************************************************************************
3773 
3774 
3775 
3776 
3777 //=================================================================================================
3778 //
3779 //  ROWTRAIT SPECIALIZATIONS
3780 //
3781 //=================================================================================================
3782 
3783 //*************************************************************************************************
3784 /*! \cond BLAZE_INTERNAL */
3785 template< typename MT, size_t I >
3786 struct RowTraitEval2< MT, I
3787                     , EnableIf_t< IsDenseMatrix_v<MT> &&
3788                                   Size_v<MT,1UL> != DefaultSize_v > >
3789 {
3790    using Type = StaticVector< RemoveConst_t< ElementType_t<MT> >
3791                             , Size_v<MT,1UL>
3792                             , true
3793                             , defaultAlignmentFlag
3794                             , defaultPaddingFlag
3795                             , TagType_t<MT> >;
3796 };
3797 /*! \endcond */
3798 //*************************************************************************************************
3799 
3800 
3801 
3802 
3803 //=================================================================================================
3804 //
3805 //  COLUMNTRAIT SPECIALIZATIONS
3806 //
3807 //=================================================================================================
3808 
3809 //*************************************************************************************************
3810 /*! \cond BLAZE_INTERNAL */
3811 template< typename MT, size_t I >
3812 struct ColumnTraitEval2< MT, I
3813                        , EnableIf_t< IsDenseMatrix_v<MT> &&
3814                                      Size_v<MT,0UL> != DefaultSize_v > >
3815 {
3816    using Type = StaticVector< RemoveConst_t< ElementType_t<MT> >
3817                             , Size_v<MT,0UL>
3818                             , false
3819                             , defaultAlignmentFlag
3820                             , defaultPaddingFlag
3821                             , TagType_t<MT> >;
3822 };
3823 /*! \endcond */
3824 //*************************************************************************************************
3825 
3826 
3827 
3828 
3829 //=================================================================================================
3830 //
3831 //  BANDTRAIT SPECIALIZATIONS
3832 //
3833 //=================================================================================================
3834 
3835 //*************************************************************************************************
3836 /*! \cond BLAZE_INTERNAL */
3837 template< typename MT, ptrdiff_t I >
3838 struct BandTraitEval2< MT, I
3839                      , EnableIf_t< IsDenseMatrix_v<MT> &&
3840                                    Size_v<MT,0UL> != DefaultSize_v &&
3841                                    Size_v<MT,1UL> != DefaultSize_v > >
3842 {
3843    static constexpr size_t M   = Size_v<MT,0UL>;
3844    static constexpr size_t N   = Size_v<MT,1UL>;
3845    static constexpr size_t Min = min( M - ( I >= 0L ? 0UL : -I ), N - ( I >= 0L ? I : 0UL ) );
3846 
3847    using Type = StaticVector< RemoveConst_t< ElementType_t<MT> >
3848                             , Min
3849                             , defaultTransposeFlag
3850                             , defaultAlignmentFlag
3851                             , defaultPaddingFlag
3852                             , TagType_t<MT> >;
3853 };
3854 /*! \endcond */
3855 //*************************************************************************************************
3856 
3857 } // namespace blaze
3858 
3859 
3860 
3861 
3862 //=================================================================================================
3863 //
3864 //  STD::TUPLE SUPPORT
3865 //
3866 //=================================================================================================
3867 
3868 //*************************************************************************************************
3869 /*! \cond BLAZE_INTERNAL */
3870 namespace std
3871 {
3872 
3873 template< typename Type
3874         , size_t N
3875         , bool TF
3876         , blaze::AlignmentFlag AF
3877         , blaze::PaddingFlag PF
3878         , typename Tag >
3879 class tuple_size< blaze::StaticVector<Type,N,TF,AF,PF,Tag> >
3880    : public integral_constant< size_t, N >
3881 {};
3882 
3883 template< size_t I
3884         , typename Type
3885         , size_t N
3886         , bool TF
3887         , blaze::AlignmentFlag AF
3888         , blaze::PaddingFlag PF
3889         , typename Tag >
3890 class tuple_element< I, blaze::StaticVector<Type,N,TF,AF,PF,Tag> >
3891 {
3892  public:
3893    using type = Type;
3894 };
3895 
3896 }
3897 /*! \endcond */
3898 //*************************************************************************************************
3899 
3900 #endif
3901