Subversion Repositories gelsvn

Rev

Rev 117 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 117 Rev 393
1
#ifndef __CGLA_ARITHVEC_H__
1
#ifndef __CGLA_ARITHVEC_H__
2
#define __CGLA_ARITHVEC_H__
2
#define __CGLA_ARITHVEC_H__
3
 
3
 
4
#include <iostream>
4
#include <iostream>
5
#include "CGLA.h"
5
#include "CGLA.h"
6
 
6
 
7
#include <numeric>
7
#include <numeric>
8
 
8
 
9
namespace CGLA 
9
namespace CGLA 
10
{
10
{
11
 
11
 
12
  /** \brief Template representing generic arithmetic vectors.  
12
  /** \brief Template representing generic arithmetic vectors.  
13
 
13
 
14
			The three parameters to the template are
14
			The three parameters to the template are
15
 
15
 
16
      T - the scalar type (i.e. float, int, double etc.)
16
      T - the scalar type (i.e. float, int, double etc.)
17
 
17
 
18
      V - the name of the vector type. This template is always (and
18
      V - the name of the vector type. This template is always (and
19
      only) used as ancestor of concrete types, and the name of the
19
      only) used as ancestor of concrete types, and the name of the
20
      class _inheriting_ _from_ this class is used as the V argument.
20
      class _inheriting_ _from_ this class is used as the V argument.
21
 
21
 
22
      N - The final argument is the dimension N. For instance, N=3 for a
22
      N - The final argument is the dimension N. For instance, N=3 for a
23
      3D vector.
23
      3D vector.
24
 
24
 
25
      This class template contains all functions that are assumed to be
25
      This class template contains all functions that are assumed to be
26
      the same for any arithmetic vector - regardless of dimension or
26
      the same for any arithmetic vector - regardless of dimension or
27
      the type of scalars used for coordinates.
27
      the type of scalars used for coordinates.
28
 
28
 
29
      The template contains no virtual functions which is important
29
      The template contains no virtual functions which is important
30
      since they add overhead.
30
      since they add overhead.
31
  */
31
  */
32
 
32
 
33
  template <class T, class V, unsigned int N> 
33
  template <class T, class V, unsigned int N> 
34
    class ArithVec
34
    class ArithVec
35
    {
35
    {
36
 
36
 
37
    protected:
37
    protected:
38
 
38
 
39
      /// The actual contents of the vector.
39
      /// The actual contents of the vector.
40
      T data[N];
40
      T data[N];
41
 
41
 
42
    protected:
42
    protected:
43
 
43
 
44
      //----------------------------------------------------------------------
44
      //----------------------------------------------------------------------
45
      // Constructors
45
      // Constructors
46
      //----------------------------------------------------------------------
46
      //----------------------------------------------------------------------
47
 
47
 
48
      /// Construct uninitialized vector
48
      /// Construct uninitialized vector
49
      ArithVec() 
49
      ArithVec() 
50
	{
50
	{
51
	}
51
	}
52
 
52
 
53
      /// Construct a vector where all coordinates are identical
53
      /// Construct a vector where all coordinates are identical
54
      explicit ArithVec(T _a)
54
      explicit ArithVec(T _a)
55
	{
55
	{
56
	  std::fill_n(data, N, _a);
56
	  std::fill_n(data, N, _a);
57
	}
57
	}
58
 
58
 
59
      /// Construct a 2D vector 
59
      /// Construct a 2D vector 
60
      ArithVec(T _a, T _b)
60
      ArithVec(T _a, T _b)
61
	{
61
	{
62
	  assert(N==2);
62
	  assert(N==2);
63
	  data[0] = _a;
63
	  data[0] = _a;
64
	  data[1] = _b;
64
	  data[1] = _b;
65
	}
65
	}
66
 
66
 
67
      /// Construct a 3D vector
67
      /// Construct a 3D vector
68
      ArithVec(T _a, T _b, T _c)
68
      ArithVec(T _a, T _b, T _c)
69
	{
69
	{
70
	  assert(N==3);
70
	  assert(N==3);
71
	  data[0] = _a;
71
	  data[0] = _a;
72
	  data[1] = _b;
72
	  data[1] = _b;
73
	  data[2] = _c;
73
	  data[2] = _c;
74
	}
74
	}
75
 
75
 
76
      /// Construct a 4D vector
76
      /// Construct a 4D vector
77
      ArithVec(T _a, T _b, T _c, T _d)
77
      ArithVec(T _a, T _b, T _c, T _d)
78
	{
78
	{
79
	  assert(N==4);
79
	  assert(N==4);
80
	  data[0] = _a;
80
	  data[0] = _a;
81
	  data[1] = _b;
81
	  data[1] = _b;
82
	  data[2] = _c;
82
	  data[2] = _c;
83
	  data[3] = _d;
83
	  data[3] = _d;
84
	}
84
	}
85
 
85
 
86
 
86
 
87
    public:
87
    public:
88
 
88
 
89
      /// For convenience we define a more meaningful name for the scalar type
89
      /// For convenience we define a more meaningful name for the scalar type
90
      typedef T ScalarType;
90
      typedef T ScalarType;
91
	
91
	
92
      /// A more meaningful name for vector type
92
      /// A more meaningful name for vector type
93
      typedef V VectorType;
93
      typedef V VectorType;
94
 
94
 
95
      /// Return dimension of vector
95
      /// Return dimension of vector
96
      static unsigned int get_dim() {return N;}
96
      static unsigned int get_dim() {return N;}
97
	
97
	
98
      /// Set all coordinates of a 2D vector.
98
      /// Set all coordinates of a 2D vector.
99
      void set(T _a, T _b)
99
      void set(T _a, T _b)
100
	{
100
	{
101
	  assert(N==2);
101
	  assert(N==2);
102
	  data[0] = _a;
102
	  data[0] = _a;
103
	  data[1] = _b;
103
	  data[1] = _b;
104
	}
104
	}
105
 
105
 
106
      /// Set all coordinates of a 3D vector.
106
      /// Set all coordinates of a 3D vector.
107
      void set(T _a, T _b, T _c)
107
      void set(T _a, T _b, T _c)
108
	{
108
	{
109
	  assert(N==3);
109
	  assert(N==3);
110
	  data[0] = _a;
110
	  data[0] = _a;
111
	  data[1] = _b;
111
	  data[1] = _b;
112
	  data[2] = _c;
112
	  data[2] = _c;
113
	}
113
	}
114
 
114
 
115
      /// Set all coordinates of a 4D vector.
115
      /// Set all coordinates of a 4D vector.
116
      void set(T _a, T _b, T _c, T _d)
116
      void set(T _a, T _b, T _c, T _d)
117
	{
117
	{
118
	  assert(N==4);
118
	  assert(N==4);
119
	  data[0] = _a;
119
	  data[0] = _a;
120
	  data[1] = _b;
120
	  data[1] = _b;
121
	  data[2] = _c;
121
	  data[2] = _c;
122
	  data[3] = _d;
122
	  data[3] = _d;
123
	}
123
	}
124
 
124
 
125
  /// Const index operator
125
  /// Const index operator
126
  const T& operator [] ( unsigned int i ) const
126
  const T& operator [] ( unsigned int i ) const
127
	{
127
	{
128
	  assert(i<N);
128
	  assert(i<N);
129
	  return data[i];
129
	  return data[i];
130
	}
130
	}
131
 
131
 
132
  /// Non-const index operator
132
  /// Non-const index operator
133
  T& operator [] ( unsigned int i ) 
133
  T& operator [] ( unsigned int i ) 
134
	{
134
	{
135
	  assert(i<N);
135
	  assert(i<N);
136
	  return data[i];
136
	  return data[i];
137
	}
137
	}
138
 
138
 
139
	/// Const index operator
139
	/// Const index operator
140
  const T& operator () ( unsigned int i ) const
140
  const T& operator () ( unsigned int i ) const
141
	{
141
	{
142
	  assert(i<N);
142
	  assert(i<N);
143
	  return data[i];
143
	  return data[i];
144
	}
144
	}
145
 
145
 
146
  /// Non-const index operator
146
  /// Non-const index operator
147
  T& operator () ( unsigned int i ) 
147
  T& operator () ( unsigned int i ) 
148
	{
148
	{
149
	  assert(i<N);
149
	  assert(i<N);
150
	  return data[i];
150
	  return data[i];
151
	}
151
	}
152
 
152
 
153
 
153
 
154
      /** Get a pointer to first element in data array.
154
      /** Get a pointer to first element in data array.
155
	  This function may be useful when interfacing with some other API 
155
	  This function may be useful when interfacing with some other API 
156
	  such as OpenGL (TM) */
156
	  such as OpenGL (TM) */
157
      T* get() {return &data[0];}
157
      T* get() {return &data[0];}
158
 
158
 
159
      /** Get a const pointer to first element in data array.
159
      /** Get a const pointer to first element in data array.
160
	  This function may be useful when interfacing with some other API 
160
	  This function may be useful when interfacing with some other API 
161
	  such as OpenGL (TM). */
161
	  such as OpenGL (TM). */
162
      const T* get() const {return &data[0];}
162
      const T* get() const {return &data[0];}
163
 
163
 
164
      //----------------------------------------------------------------------
164
      //----------------------------------------------------------------------
165
      // Comparison operators
165
      // Comparison operators
166
      //----------------------------------------------------------------------
166
      //----------------------------------------------------------------------
167
 
167
 
168
      /// Equality operator
168
      /// Equality operator
169
      bool operator==(const V& v) const 
169
      bool operator==(const V& v) const 
170
	{
170
	{
171
	  return std::inner_product(data, &data[N], v.get(), true,
171
	  return std::inner_product(data, &data[N], v.get(), true,
172
				    std::logical_and<bool>(), std::equal_to<T>());
172
				    std::logical_and<bool>(), std::equal_to<T>());
173
	}
173
	}
174
 
174
 
175
#define for_all_i(expr) for(unsigned int i=0;i<N;i++) {expr;}
175
#define for_all_i(expr) for(unsigned int i=0;i<N;i++) {expr;}
176
      /// Equality wrt scalar. True if all coords are equal to scalar
176
      /// Equality wrt scalar. True if all coords are equal to scalar
177
      bool operator==(T k) const 
177
      bool operator==(T k) const 
178
	{ 
178
	{ 
179
	  for_all_i(if (data[i] != k) return false)
179
	  for_all_i(if (data[i] != k) return false)
180
	    return true;
180
	    return true;
181
	}
181
	}
182
#undef for_all_i  
182
#undef for_all_i  
183
 
183
 
184
      /// Inequality operator
184
      /// Inequality operator
185
      bool operator!=(const V& v) const 
185
      bool operator!=(const V& v) const 
186
	{
186
	{
187
	  return std::inner_product(data, &data[N], v.get(), false,
187
	  return std::inner_product(data, &data[N], v.get(), false,
188
				    std::logical_or<bool>(), std::not_equal_to<T>());
188
				    std::logical_or<bool>(), std::not_equal_to<T>());
189
	}
189
	}
190
 
190
 
191
      /// Inequality wrt scalar. True if any coord not equal to scalar
191
      /// Inequality wrt scalar. True if any coord not equal to scalar
192
      bool operator!=(T k) const 
192
      bool operator!=(T k) const 
193
	{ 
193
	{ 
194
	  return !(*this==k);
194
	  return !(*this==k);
195
	}
195
	}
196
 
196
 
197
 
197
 
198
      //----------------------------------------------------------------------
198
      //----------------------------------------------------------------------
199
      // Comparison functions ... of geometric significance 
199
      // Comparison functions ... of geometric significance 
200
      //----------------------------------------------------------------------
200
      //----------------------------------------------------------------------
201
 
201
 
202
      /** Compare all coordinates against other vector. ( < )
202
      /** Compare all coordinates against other vector. ( < )
203
	  Similar to testing whether we are on one side of three planes. */
203
	  Similar to testing whether we are on one side of three planes. */
204
      bool  all_l  (const V& v) const
204
      bool  all_l  (const V& v) const
205
	{
205
	{
206
	  return std::inner_product(data, &data[N], v.get(), true, 
206
	  return std::inner_product(data, &data[N], v.get(), true, 
207
				    std::logical_and<bool>(), std::less<T>());
207
				    std::logical_and<bool>(), std::less<T>());
208
	}
208
	}
209
 
209
 
210
      /** Compare all coordinates against other vector. ( <= )
210
      /** Compare all coordinates against other vector. ( <= )
211
	  Similar to testing whether we are on one side of three planes. */
211
	  Similar to testing whether we are on one side of three planes. */
212
      bool  all_le (const V& v) const
212
      bool  all_le (const V& v) const
213
	{
213
	{
214
	  return std::inner_product(data, &data[N], v.get(), true, 
214
	  return std::inner_product(data, &data[N], v.get(), true, 
215
				    std::logical_and<bool>(), std::less_equal<T>());
215
				    std::logical_and<bool>(), std::less_equal<T>());
216
	}
216
	}
217
 
217
 
218
      /** Compare all coordinates against other vector. ( > )
218
      /** Compare all coordinates against other vector. ( > )
219
	  Similar to testing whether we are on one side of three planes. */
219
	  Similar to testing whether we are on one side of three planes. */
220
      bool  all_g  (const V& v) const
220
      bool  all_g  (const V& v) const
221
	{
221
	{
222
	  return std::inner_product(data, &data[N], v.get(), true, 
222
	  return std::inner_product(data, &data[N], v.get(), true, 
223
				    std::logical_and<bool>(), std::greater<T>());
223
				    std::logical_and<bool>(), std::greater<T>());
224
	}
224
	}
225
 
225
 
226
      /** Compare all coordinates against other vector. ( >= )
226
      /** Compare all coordinates against other vector. ( >= )
227
	  Similar to testing whether we are on one side of three planes. */
227
	  Similar to testing whether we are on one side of three planes. */
228
      bool  all_ge (const V& v) const
228
      bool  all_ge (const V& v) const
229
	{
229
	{
230
	  return std::inner_product(data, &data[N], v.get(), true, 
230
	  return std::inner_product(data, &data[N], v.get(), true, 
231
				    std::logical_and<bool>(), std::greater_equal<T>());
231
				    std::logical_and<bool>(), std::greater_equal<T>());
232
	}
232
	}
233
 
233
 
234
 
234
 
235
      //----------------------------------------------------------------------
235
      //----------------------------------------------------------------------
236
      // Assignment operators
236
      // Assignment operators
237
      //----------------------------------------------------------------------
237
      //----------------------------------------------------------------------
238
 
238
 
239
      /// Assignment multiplication with scalar.
239
      /// Assignment multiplication with scalar.
240
      const V& operator *=(T k) 
240
      const V& operator *=(T k) 
241
	{ 
241
	{ 
242
	  std::transform(data, &data[N], data, std::bind2nd(std::multiplies<T>(), k));
242
	  std::transform(data, &data[N], data, std::bind2nd(std::multiplies<T>(), k));
243
	  return static_cast<const V&>(*this);
243
	  return static_cast<const V&>(*this);
244
	}
244
	}
245
 
245
 
246
      /// Assignment division with scalar.
246
      /// Assignment division with scalar.
247
      const V& operator /=(T k)
247
      const V& operator /=(T k)
248
	{ 
248
	{ 
249
	  std::transform(data, &data[N], data, std::bind2nd(std::divides<T>(), k));
249
	  std::transform(data, &data[N], data, std::bind2nd(std::divides<T>(), k));
250
	  return static_cast<const V&>(*this);
250
	  return static_cast<const V&>(*this);
251
	}
251
	}
252
 
252
 
253
      /// Assignment addition with scalar. Adds scalar to each coordinate.
253
      /// Assignment addition with scalar. Adds scalar to each coordinate.
254
      const V& operator +=(T k) 
254
      const V& operator +=(T k) 
255
	{
255
	{
256
	  std::transform(data, &data[N], data, std::bind2nd(std::plus<T>(), k));
256
	  std::transform(data, &data[N], data, std::bind2nd(std::plus<T>(), k));
257
	  return  static_cast<const V&>(*this);
257
	  return  static_cast<const V&>(*this);
258
	}
258
	}
259
 
259
 
260
      /// Assignment subtraction with scalar. Subtracts scalar from each coord.
260
      /// Assignment subtraction with scalar. Subtracts scalar from each coord.
261
      const V& operator -=(T k) 
261
      const V& operator -=(T k) 
262
	{ 
262
	{ 
263
	  std::transform(data, &data[N], data, std::bind2nd(std::minus<T>(), k));
263
	  std::transform(data, &data[N], data, std::bind2nd(std::minus<T>(), k));
264
	  return  static_cast<const V&>(*this);
264
	  return  static_cast<const V&>(*this);
265
	}
265
	}
266
 
266
 
267
      /** Assignment multiplication with vector. 
267
      /** Assignment multiplication with vector. 
268
	  Multiply each coord independently. */
268
	  Multiply each coord independently. */
269
      const V& operator *=(const V& v) 
269
      const V& operator *=(const V& v) 
270
	{ 
270
	{ 
271
	  std::transform(data, &data[N], v.get(), data, std::multiplies<T>());
271
	  std::transform(data, &data[N], v.get(), data, std::multiplies<T>());
272
	  return  static_cast<const V&>(*this);
272
	  return  static_cast<const V&>(*this);
273
	}
273
	}
274
 
274
 
275
      /// Assigment division with vector. Each coord divided independently.
275
      /// Assigment division with vector. Each coord divided independently.
276
      const V& operator /=(const V& v)
276
      const V& operator /=(const V& v)
277
	{
277
	{
278
	  std::transform(data, &data[N], v.get(), data, std::divides<T>());
278
	  std::transform(data, &data[N], v.get(), data, std::divides<T>());
279
	  return  static_cast<const V&>(*this);
279
	  return  static_cast<const V&>(*this);
280
	}
280
	}
281
 
281
 
282
      /// Assignmment addition with vector.
282
      /// Assignmment addition with vector.
283
      const V& operator +=(const V& v) 
283
      const V& operator +=(const V& v) 
284
	{
284
	{
285
	  std::transform(data, &data[N], v.get(), data, std::plus<T>());
285
	  std::transform(data, &data[N], v.get(), data, std::plus<T>());
286
	  return  static_cast<const V&>(*this);
286
	  return  static_cast<const V&>(*this);
287
	}
287
	}
288
		
288
		
289
      /// Assignment subtraction with vector.
289
      /// Assignment subtraction with vector.
290
      const V& operator -=(const V& v) 
290
      const V& operator -=(const V& v) 
291
	{ 
291
	{ 
292
	  std::transform(data, &data[N], v.get(), data, std::minus<T>());
292
	  std::transform(data, &data[N], v.get(), data, std::minus<T>());
293
	  return  static_cast<const V&>(*this);
293
	  return  static_cast<const V&>(*this);
294
	}
294
	}
295
 
295
 
296
 
296
 
297
      //----------------------------------------------------------------------
297
      //----------------------------------------------------------------------
298
      // Unary operators on vectors
298
      // Unary operators on vectors
299
      //----------------------------------------------------------------------
299
      //----------------------------------------------------------------------
300
 
300
 
301
      /// Negate vector.
301
      /// Negate vector.
302
      const V operator - () const
302
      const V operator - () const
303
	{
303
	{
304
	  V v_new;
304
	  V v_new;
305
	  std::transform(data, &data[N], v_new.get(), std::negate<T>());
305
	  std::transform(data, &data[N], v_new.get(), std::negate<T>());
306
	  return v_new;
306
	  return v_new;
307
	}
307
	}
308
 
308
 
309
      //----------------------------------------------------------------------
309
      //----------------------------------------------------------------------
310
      // Binary operators on vectors
310
      // Binary operators on vectors
311
      //----------------------------------------------------------------------
311
      //----------------------------------------------------------------------
312
 
312
 
313
      /** Multiply vector with vector. Each coord multiplied independently
313
      /** Multiply vector with vector. Each coord multiplied independently
314
	  Do not confuse this operation with dot product. */
314
	  Do not confuse this operation with dot product. */
315
      const V operator * (const V& v1) const
315
      const V operator * (const V& v1) const
316
	{
316
	{
317
	  V v_new;
317
	  V v_new;
318
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::multiplies<T>());
318
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::multiplies<T>());
319
	  return v_new;
319
	  return v_new;
320
	}
320
	}
321
 
321
 
322
      /// Add two vectors
322
      /// Add two vectors
323
      const V operator + (const V& v1) const
323
      const V operator + (const V& v1) const
324
	{
324
	{
325
	  V v_new;
325
	  V v_new;
326
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::plus<T>());
326
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::plus<T>());
327
	  return v_new;
327
	  return v_new;
328
	}
328
	}
329
 
329
 
330
      /// Subtract two vectors. 
330
      /// Subtract two vectors. 
331
      const V operator - (const V& v1) const
331
      const V operator - (const V& v1) const
332
	{
332
	{
333
	  V v_new;
333
	  V v_new;
334
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::minus<T>());
334
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::minus<T>());
335
	  return v_new;
335
	  return v_new;
336
	}
336
	}
337
 
337
 
338
      /// Divide two vectors. Each coord separately
338
      /// Divide two vectors. Each coord separately
339
      const V operator / (const V& v1) const
339
      const V operator / (const V& v1) const
340
	{
340
	{
341
	  V v_new;
341
	  V v_new;
342
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::divides<T>());
342
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::divides<T>());
343
	  return v_new;
343
	  return v_new;
344
	}
344
	}
345
 
345
 
346
      //----------------------------------------------------------------------
346
      //----------------------------------------------------------------------
347
      // Binary operators on vector and scalar
347
      // Binary operators on vector and scalar
348
      //----------------------------------------------------------------------
348
      //----------------------------------------------------------------------
349
 
349
 
350
      /// Multiply scalar onto vector.
350
      /// Multiply scalar onto vector.
351
      const V operator * (T k) const
351
      const V operator * (T k) const
352
	{
352
	{
353
	  V v_new;
353
	  V v_new;
354
	  std::transform(data, &data[N], v_new.get(), std::bind2nd(std::multiplies<T>(), k));
354
	  std::transform(data, &data[N], v_new.get(), std::bind2nd(std::multiplies<T>(), k));
355
	  return v_new;
355
	  return v_new;
356
	}
356
	}
357
  
357
  
358
 
358
 
359
      /// Divide vector by scalar.
359
      /// Divide vector by scalar.
360
      const V operator / (T k) const
360
      const V operator / (T k) const
361
	{
361
	{
362
	  V v_new;
362
	  V v_new;
363
	  std::transform(data, &data[N], v_new.get(), std::bind2nd(std::divides<T>(), k));
363
	  std::transform(data, &data[N], v_new.get(), std::bind2nd(std::divides<T>(), k));
364
	  return v_new;      
364
	  return v_new;      
365
	}
365
	}
366
 
366
 
367
 
367
 
368
      /// Return the smallest coordinate of the vector
368
      /// Return the smallest coordinate of the vector
369
      const T min_coord() const 
369
      const T min_coord() const 
370
	{
370
	{
371
	  return *std::min_element(data, &data[N]);
371
	  return *std::min_element(data, &data[N]);
372
	}
372
	}
373
 
373
 
374
      /// Return the largest coordinate of the vector
374
      /// Return the largest coordinate of the vector
375
      const T max_coord() const
375
      const T max_coord() const
376
	{
376
	{
377
	  return *std::max_element(data, &data[N]);
377
	  return *std::max_element(data, &data[N]);
378
	}
378
	}
379
 
379
 
380
    };
380
    };
381
 
381
 
382
  template <class T, class V, unsigned int N> 
382
  template <class T, class V, unsigned int N> 
383
    inline std::ostream& operator<<(std::ostream&os, const ArithVec<T,V,N>& v)
383
    inline std::ostream& operator<<(std::ostream&os, const ArithVec<T,V,N>& v)
384
    {
384
    {
385
      os << "[ ";
385
      os << "[ ";
386
      for(unsigned int i=0;i<N;i++) os << v[i] << " ";
386
      for(unsigned int i=0;i<N;i++) os << v[i] << " ";
387
      os << "]";
387
      os << "]";
388
      return os;
388
      return os;
389
    }
389
    }
390
 
390
 
391
  /// Get from operator for ArithVec descendants. 
391
  /// Get from operator for ArithVec descendants. 
392
  template <class T,class V, unsigned int N>
392
  template <class T,class V, unsigned int N>
393
    inline std::istream& operator>>(std::istream&is, ArithVec<T,V,N>& v)
393
    inline std::istream& operator>>(std::istream&is, ArithVec<T,V,N>& v)
394
    {
394
    {
395
      for(unsigned int i=0;i<N;i++) is>>v[i];
395
      for(unsigned int i=0;i<N;i++) is>>v[i];
396
      return is;
396
      return is;
397
    }
397
    }
398
 
398
 
399
 
399
 
400
  /** Dot product for two vectors. The `*' operator is 
400
  /** Dot product for two vectors. The `*' operator is 
401
      reserved for coordinatewise	multiplication of vectors. */
401
      reserved for coordinatewise	multiplication of vectors. */
402
  template <class T,class V, unsigned int N>
402
  template <class T,class V, unsigned int N>
403
    inline T dot(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
403
    inline T dot(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
404
    {
404
    {
405
      return std::inner_product(v0.get(), v0.get() + N, v1.get(), T(0));
405
      return std::inner_product(v0.get(), v0.get() + N, v1.get(), T(0));
406
    }
406
    }
407
 
407
 
408
  /** Compute the sqr length by taking dot product of vector with itself. */
408
  /** Compute the sqr length by taking dot product of vector with itself. */
409
  template <class T,class V, unsigned int N>
409
  template <class T,class V, unsigned int N>
410
    inline T sqr_length(const ArithVec<T,V,N>& v)
410
    inline T sqr_length(const ArithVec<T,V,N>& v)
411
    {
411
    {
412
      return dot(v,v);
412
      return dot(v,v);
413
    }
413
    }
414
 
414
 
415
  /** Multiply double onto vector. This operator handles the case 
415
  /** Multiply double onto vector. This operator handles the case 
416
      where the vector is on the righ side of the `*'.
416
      where the vector is on the righ side of the `*'.
417
	 
417
	 
418
      \note It seems to be optimal to put the binary operators inside the
418
      \note It seems to be optimal to put the binary operators inside the
419
      ArithVec class template, but the operator functions whose 
419
      ArithVec class template, but the operator functions whose 
420
      left operand is _not_ a vector cannot be inside, hence they
420
      left operand is _not_ a vector cannot be inside, hence they
421
      are here.
421
      are here.
422
      We need three operators for scalar * vector although they are
422
      We need three operators for scalar * vector although they are
423
      identical, because, if we use a separate template argument for
423
      identical, because, if we use a separate template argument for
424
      the left operand, it will match any type. If we use just T as 
424
      the left operand, it will match any type. If we use just T as 
425
      type for the left operand hoping that other built-in types will
425
      type for the left operand hoping that other built-in types will
426
      be automatically converted, we will be disappointed. It seems that 
426
      be automatically converted, we will be disappointed. It seems that 
427
      a float * ArithVec<float,Vec3f,3> function is not found if the
427
      a float * ArithVec<float,Vec3f,3> function is not found if the
428
      left operand is really a double.
428
      left operand is really a double.
429
  */
429
  */
430
 
430
 
431
  template<class T, class V, unsigned int N>
431
  template<class T, class V, unsigned int N>
432
    inline const V operator * (double k, const ArithVec<T,V,N>& v) 
432
    inline const V operator * (double k, const ArithVec<T,V,N>& v) 
433
    {
433
    {
434
      return v * k;
434
      return v * k;
435
    }
435
    }
436
 
436
 
437
  /** Multiply float onto vector. See the note in the documentation
437
  /** Multiply float onto vector. See the note in the documentation
438
      regarding multiplication of a double onto a vector. */
438
      regarding multiplication of a double onto a vector. */
439
  template<class T, class V, unsigned int N>
439
  template<class T, class V, unsigned int N>
440
    inline const V operator * (float k, const ArithVec<T,V,N>& v) 
440
    inline const V operator * (float k, const ArithVec<T,V,N>& v) 
441
    {
441
    {
442
      return v * k;
442
      return v * k;
443
    }
443
    }
444
 
444
 
445
  /** Multiply unsigned int onto vector. See the note in the documentation
445
  /** Multiply unsigned int onto vector. See the note in the documentation
446
      regarding multiplication of a double onto a vector. */
446
      regarding multiplication of a double onto a vector. */
447
  template<class T, class V, unsigned int N>
447
  template<class T, class V, unsigned int N>
448
    inline const V operator * (int k, const ArithVec<T,V,N>& v) 
448
    inline const V operator * (int k, const ArithVec<T,V,N>& v) 
449
    {
449
    {
450
      return v * k;
450
      return v * k;
451
    }
451
    }
452
 
452
 
453
  /** Returns the vector containing for each coordinate the smallest
453
  /** Returns the vector containing for each coordinate the smallest
454
      value from two vectors. */
454
      value from two vectors. */
455
  template <class T,class V, unsigned int N>
455
  template <class T,class V, unsigned int N>
456
    inline V v_min(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
456
    inline V v_min(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
457
    {
457
    {
458
      V v;
458
      V v;
459
      std::transform(v0.get(), v0.get() + N, v1.get(), v.get(), std::ptr_fun(s_min<T>));
459
      std::transform(v0.get(), v0.get() + N, v1.get(), v.get(), std::ptr_fun(s_min<T>));
460
      return v;
460
      return v;
461
    }
461
    }
462
 
462
 
463
  /** Returns the vector containing for each coordinate the largest 
463
  /** Returns the vector containing for each coordinate the largest 
464
      value from two vectors. */
464
      value from two vectors. */
465
  template <class T,class V, unsigned int N>
465
  template <class T,class V, unsigned int N>
466
    inline V v_max(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
466
    inline V v_max(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
467
    {
467
    {
468
      V v;
468
      V v;
469
      std::transform(v0.get(), v0.get() + N, v1.get(), v.get(), std::ptr_fun(s_max<T>));
469
      std::transform(v0.get(), v0.get() + N, v1.get(), v.get(), std::ptr_fun(s_max<T>));
470
      return v;
470
      return v;
471
    }
471
    }
472
 
472
 
473
 
473
 
474
}
474
}
475
 
475
 
476
#endif
476
#endif
477
 
477