2
/***************************************************************************
3
* blitz/tinyvec.h Declaration of the TinyVector<T, N> class
7
* Copyright (C) 1997-2011 Todd Veldhuizen <tveldhui@acm.org>
9
* This file is a part of Blitz.
11
* Blitz is free software: you can redistribute it and/or modify
12
* it under the terms of the GNU Lesser General Public License
13
* as published by the Free Software Foundation, either version 3
14
* of the License, or (at your option) any later version.
16
* Blitz is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU Lesser General Public License for more details.
21
* You should have received a copy of the GNU Lesser General Public
22
* License along with Blitz. If not, see <http://www.gnu.org/licenses/>.
24
* Suggestions: blitz-devel@lists.sourceforge.net
25
* Bugs: blitz-support@lists.sourceforge.net
27
* For more information, please see the Blitz++ Home Page:
28
* https://sourceforge.net/projects/blitz/
30
***************************************************************************/
35
#include <blitz/blitz.h>
36
#include <blitz/listinit.h>
37
#include <blitz/et-forward.h>
38
#include <blitz/etbase.h>
39
#include <blitz/simdtypes.h>
40
#include <blitz/array/slice.h>
42
#ifdef BZ_HAVE_BOOST_SERIALIZATION
43
#include <boost/serialization/serialization.hpp>
45
#ifdef BZ_HAVE_BOOST_MPI
46
#include <boost/mpi/datatype.hpp>
49
#ifdef BZ_HAVE_CSTRING
50
#include <cstring> // For memcpy
55
/*****************************************************************************
56
* Forward declarations
59
template<typename P_numtype, int N_length>
60
class FastTV2Iterator;
61
template<typename P_numtype, int N_length>
62
class FastTV2CopyIterator;
65
/** The TinyVector class is a one-dimensional, fixed length vector
66
that implements the blitz expression template
67
machinery. TinyVector-only expressions are very fast because they
68
usually get reduced to just the unrolled (and vectorized, if
69
enabled) assembly instructions. TinyVectors can also be used in
70
mixed expressions with other ET classes. */
71
template<typename P_numtype, int N_length>
72
class TinyVector : public ETBase<TinyVector<P_numtype, N_length> >
76
//////////////////////////////////////////////
78
//////////////////////////////////////////////
80
typedef P_numtype T_numtype;
81
typedef TinyVector<T_numtype,N_length> T_vector;
82
typedef FastTV2Iterator<T_numtype,N_length> T_iterator;
83
typedef T_numtype* iterator;
84
typedef const T_numtype* const_iterator;
85
typedef FastTV2CopyIterator<P_numtype, N_length> T_range_result;
88
//numArrayOperands = 1,
89
//numIndexPlaceholders = 0,
95
TinyVector(const TinyVector<T_numtype,N_length>& x);
97
template <typename T_numtype2>
98
TinyVector(const TinyVector<T_numtype2,N_length>& x);
100
/** This constructor creates a TinyVector from another ETBase
101
object. It needs to be explicit to avoid all kinds of
103
template <typename T_expr>
104
inline explicit TinyVector(const ETBase<T_expr>& expr) {
107
/** This constructor creates a TinyVector specifically from an
108
expression. This one we do NOT want to be explicit because that
109
breaks simple construction assignments like "TinyVector<double,
110
1> v = a+b;", forcing the user to explicitly write it like a
112
template <typename T_expr>
113
inline TinyVector(const _bz_ArrayExpr<T_expr>& expr) {
116
inline TinyVector(const T_numtype initValue);
118
inline TinyVector(const T_numtype x[]) {
119
memcpy(data_,x,N_length*sizeof(T_numtype));
123
TinyVector(T_numtype x0, T_numtype x1)
129
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2)
136
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
145
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
146
T_numtype x3, T_numtype x4)
155
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
156
T_numtype x3, T_numtype x4, T_numtype x5)
166
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
167
T_numtype x3, T_numtype x4, T_numtype x5, T_numtype x6)
178
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
179
T_numtype x3, T_numtype x4, T_numtype x5, T_numtype x6,
192
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
193
T_numtype x3, T_numtype x4, T_numtype x5, T_numtype x6,
194
T_numtype x7, T_numtype x8)
207
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
208
T_numtype x3, T_numtype x4, T_numtype x5, T_numtype x6,
209
T_numtype x7, T_numtype x8, T_numtype x9)
223
TinyVector(T_numtype x0, T_numtype x1, T_numtype x2,
224
T_numtype x3, T_numtype x4, T_numtype x5, T_numtype x6,
225
T_numtype x7, T_numtype x8, T_numtype x9, T_numtype x10)
243
static int base(int rank)
244
{ BZPRECONDITION(rank==0); return 0; }
247
T_iterator beginFast() const { return T_iterator(*this); }
249
iterator begin() { return data_; }
250
const_iterator begin() const { return data_; }
252
static int dimensions()
255
iterator end() { return data_ + N_length; }
256
const_iterator end() const { return data_ + N_length; }
258
T_numtype * restrict data()
261
const T_numtype * restrict data() const
264
T_numtype * restrict dataFirst()
267
const T_numtype * restrict dataFirst() const
270
const TinyVector<int, rank_> shape() const
273
static int lbound(int rank)
274
{ BZPRECONDITION(rank==0); return 0; }
278
static int length(int rank)
279
{ BZPRECONDITION(rank==0); return N_length; }
283
static int extent(int rank)
284
{ BZPRECONDITION(rank==0); return N_length; }
286
static int ordering(int storageRankIndex)
289
static int ordering()
295
static sizeType numElements()
298
static diffType stride()
301
static diffType stride(int rank)
302
{ BZPRECONDITION(rank==0); return 1; }
304
static int ubound(int rank)
305
{ BZPRECONDITION(rank==0); return length()-1; }
308
{ return length()-1; }
310
template<typename P_expr, typename P_updater>
311
void _bz_assign(P_expr, P_updater);
313
T_numtype operator*() const
316
//////////////////////////////////////////////
317
// Subscripting operators
318
//////////////////////////////////////////////
320
T_vector& noConst() const
321
{ return const_cast<T_vector&>(*this); }
323
static bool lengthCheck(unsigned i)
325
BZPRECHECK(i < N_length,
326
"TinyVector<" << BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(T_numtype)
327
<< "," << N_length << "> index out of bounds: " << i);
331
const T_numtype& operator()(unsigned i) const
333
BZPRECONDITION(lengthCheck(i));
337
T_numtype& restrict operator()(unsigned i)
339
BZPRECONDITION(lengthCheck(i));
343
T_numtype operator()(TinyVector<int,1> i) const
345
BZPRECONDITION(lengthCheck(i[0]));
350
_bz_ArrayExpr<ArrayIndexMapping<typename asExpr<T_vector>::T_expr, N0> >
351
operator()(IndexPlaceholder<N0>) const;
353
const T_numtype& operator[](unsigned i) const
355
BZPRECONDITION(lengthCheck(i));
359
T_numtype& restrict operator[](unsigned i)
361
BZPRECONDITION(lengthCheck(i));
365
// must return reference so the iterator can turn it into an
366
// iterator for the contained in case we have a multicomponent.
367
const T_numtype& fastRead(diffType i) const
370
/** Since data_ is simd aligned by construction, we just have
371
to check the offest. */
372
bool isVectorAligned(diffType offset) const
373
{ return (offset%simdTypes<T_numtype>::vecWidth)==0; }
375
bool canCollapse(int outerLoopRank, int innerLoopRank) const
377
BZPRECONDITION(outerLoopRank==0);
378
BZPRECONDITION(innerLoopRank==0);
382
//////////////////////////////////////////////
383
// Assignment operators
384
//////////////////////////////////////////////
387
ListInitializationSwitch<T_vector,T_numtype*> operator=(T_numtype x)
389
return ListInitializationSwitch<T_vector,T_numtype*>(*this, x);
392
T_vector& initialize(T_numtype);
394
template<typename T_expr>
395
T_vector& operator=(const ETBase<T_expr>&);
397
template<typename T> T_vector& operator+=(const T&);
398
template<typename T> T_vector& operator-=(const T&);
399
template<typename T> T_vector& operator*=(const T&);
400
template<typename T> T_vector& operator/=(const T&);
401
template<typename T> T_vector& operator%=(const T&);
402
template<typename T> T_vector& operator^=(const T&);
403
template<typename T> T_vector& operator&=(const T&);
404
template<typename T> T_vector& operator|=(const T&);
405
template<typename T> T_vector& operator>>=(const T&);
406
template<typename T> T_vector& operator<<=(const T&);
408
T_numtype* restrict getInitializationIterator()
409
{ return dataFirst(); }
411
// // vectors can't be sliced
412
// template<typename T1, typename T2 = nilArraySection,
413
// class T3 = nilArraySection, typename T4 = nilArraySection,
414
// class T5 = nilArraySection, typename T6 = nilArraySection,
415
// class T7 = nilArraySection, typename T8 = nilArraySection,
416
// class T9 = nilArraySection, typename T10 = nilArraySection,
417
// class T11 = nilArraySection>
420
// typedef void T_slice;
424
template<typename T_expr, typename T_update>
425
void _tv_evaluate(const T_expr& expr, T_update);
427
#ifdef BZ_HAVE_BOOST_SERIALIZATION
428
friend class boost::serialization::access;
430
template<class T_arch>
431
void serialize(T_arch& ar, const unsigned int version) {
437
BZ_ALIGN_VARIABLE(T_numtype, data_[N_length], BZ_SIMD_WIDTH)
440
// Specialization for N = 0: KCC is giving some
441
// peculiar errors, perhaps this will fix.
444
class TinyVector<T,0> {
449
#ifdef BZ_HAVE_BOOST_SERIALIZATION
452
template<typename T> struct is_mpi_datatype;
453
template <typename T, int N>
454
struct is_mpi_datatype<blitz::TinyVector<T, N> >
455
: public is_mpi_datatype<T> { };
460
#endif // BZ_TINYVEC_H