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