OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
Vec.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  *
7  * Visit http://people.web.psi.ch/adelmann/ for more details
8  *
9  ***************************************************************************/
10 
11 #ifndef VEC_H
12 #define VEC_H
13 
14 // include files
15 #include "Message/Message.h"
16 #include "Utility/PAssert.h"
17 
19 
20 template<class T, unsigned Length>
21 class vec
22 {
23 public:
24  vec() {}
25  vec(T v0);
26  vec(T v0, T v1);
27  vec(T v0, T v1, T v2);
28 #ifdef IPPL_USE_FUNKY_VEC_COPIES
29  vec( const vec<T,Length>& );
30  vec<T,Length>& operator=( const vec<T,Length>& );
31 #endif
32  T& operator[](unsigned d) { return Ptr[d]; }
33  const T& operator[](unsigned d) const { return Ptr[d]; }
35 #ifdef IPPL_USE_MEMBER_TEMPLATES
36  m.put(Ptr, Ptr + Length);
37 #else
38  putMessage(m,Ptr,Ptr+Length);
39 #endif
40  return m;
41  }
43 #ifdef IPPL_USE_MEMBER_TEMPLATES
44  m.get_iter(Ptr);
45 #else
47 #endif
48  return m;
49  }
50 
51  static T dot(const T*,const T*);
52 private:
53  T Ptr[Length];
54 };
55 
57 
58 #ifdef IPPL_USE_FUNKY_VEC_COPIES
59 //
60 // Implementation of copy constructor and op=.
61 //
62 // These use a template trick to unroll the loop over elements of the vec.
63 //
64 
65 //
66 // A tag class to let us unroll this loop.
67 // It isn't entirely clear this needs to be done, but
68 // it is an interesting demonstration.
69 //
70 // It is just a record of how many elements to copy,
71 // along with a flag. The flag has the values:
72 // 4: If Length>=4. That means the interval should be split in half.
73 // 0..3: Call an explicit function for this length.
74 //
75 
76 template<unsigned Length, int Flag>
77 class DivideVecCopyTag {
78 #ifdef IPPL_PURIFY
79  // Add explicit default/copy constructors and op= to avoid UMR's.
80 public:
81  DivideVecCopyTag() {}
82  DivideVecCopyTag(const DivideVecCopyTag<Length,Flag> &) {}
83  DivideVecCopyTag<Length,Flag>&
84  operator=(const DivideVecCopyTag<Length,Flag> &) { return *this; }
85 #endif
86 };
87 
88 //
89 // Copy a vector of length 4 or greater.
90 // Split it in half and copy each half.
91 // Do it this way so that the depth of inlining is O(log(Length))
92 // instead of O(Length).
93 //
94 template<class T1, class T2, unsigned L>
95 inline void
96 divide_vec_copy(T1 *p1, T2 *p2, DivideVecCopyTag<L,4> )
97 {
98  divide_vec_copy(p1, p2, DivideVecCopyTag< L/2 , (L>=8 ? 4 : L/2)>());
99  divide_vec_copy(p1+(L/2), p2+(L/2),DivideVecCopyTag<L-L/2,(L>=8?4:L-L/2)>());
100 }
101 
102 //
103 // Copy a vector of length 0, 1, 2 or 3. Just move it.
104 //
105 template<class T1, class T2>
106 inline void
107 divide_vec_copy(T1 *p1, T2 *p2, DivideVecCopyTag<3,3> )
108 {
109  p1[0] = p2[0];
110  p1[1] = p2[1];
111  p1[2] = p2[2];
112 }
113 
114 template<class T1, class T2>
115 inline void
116 divide_vec_copy(T1 *p1, T2 *p2, DivideVecCopyTag<2,2> )
117 {
118  p1[0] = p2[0];
119  p1[1] = p2[1];
120 }
121 
122 template<class T1, class T2>
123 inline void
124 divide_vec_copy(T1 *p1, T2 *p2, DivideVecCopyTag<1,1> )
125 {
126  *p1 = *p2;
127 }
128 
129 template<class T1, class T2>
130 inline void
131 divide_vec_copy(T1 *,T2 *, DivideVecCopyTag<0,0> )
132 {
133 }
134 
135 //
136 // The copy ctor and op= just call divide_vec_copy to do the copy
137 //
138 
139 template<class T, unsigned L>
140 inline
141 vec<T,L>::vec( const vec<T,L>& v )
142 {
143  divide_vec_copy( Ptr , v.Ptr , DivideVecCopyTag<L,( L>=4 ? 4 : L)>() );
144 }
145 
146 template<class T, unsigned L>
147 inline vec<T,L>&
148 vec<T,L>::operator=( const vec<T,L>& v )
149 {
150  if ( this != &v )
151  divide_vec_copy( Ptr , v.Ptr , DivideVecCopyTag<L,( L>=4 ? 4 : L)>() );
152  return *this;
153 }
154 
155 #endif // IPPL_USE_FUNKY_VEC_COPIES
156 
158 
159 template<class T, unsigned Length>
160 inline
162 {
163  CTAssert(Length==1);
164  Ptr[0] = v0;
165 }
166 
167 template<class T, unsigned Length>
168 inline
170 {
171  CTAssert(Length==2);
172  Ptr[0] = v0;
173  Ptr[1] = v1;
174 }
175 
176 template<class T, unsigned Length>
177 inline
178 vec<T,Length>::vec(T v0, T v1, T v2)
179 {
180  CTAssert(Length==3);
181  Ptr[0] = v0;
182  Ptr[1] = v1;
183  Ptr[2] = v2;
184 }
185 
187 
188 //
189 // Define a global function for taking the dot product between two
190 // short arrays of objects of type T.
191 //
192 template<class T, unsigned Length>
193 inline T
194 vec<T,Length>::dot(const T* l, const T* r)
195 {
196  T ret = l[0]*r[0];
197  for (int i=1; i<Length; ++i)
198  ret += l[i]*r[i];
199  return ret;
200 }
201 
203 
204 #endif // VEC_H
205 
206 /***************************************************************************
207  * $RCSfile: Vec.h,v $ $Author: adelmann $
208  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:34 $
209  * IPPL_VERSION_ID: $Id: Vec.h,v 1.1.1.1 2003/01/23 07:40:34 adelmann Exp $
210  ***************************************************************************/
Definition: rbendmap.h:8
Message & getMessage(Message &m)
Definition: Vec.h:42
vec()
Definition: Vec.h:24
#define CTAssert(c)
Definition: PAssert.h:40
void getMessage_iter(Message &m, OutputIterator o)
Definition: Message.h:603
T & operator[](unsigned d)
Definition: Vec.h:32
Message & get_iter(OutputIterator o)
Definition: Message.h:519
Message & putMessage(Message &m)
Definition: Vec.h:34
const T & operator[](unsigned d) const
Definition: Vec.h:33
Message & put(const T &val)
Definition: Message.h:414
Definition: Vec.h:21
static T dot(const T *, const T *)
Definition: Vec.h:194
T Ptr[Length]
Definition: Vec.h:53