Subversion Repositories gelsvn

Rev

Rev 89 | Rev 561 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 89 Rev 117
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
-
 
140
  const T& operator () ( unsigned int i ) const
-
 
141
	{
-
 
142
	  assert(i<N);
-
 
143
	  return data[i];
-
 
144
	}
-
 
145
 
-
 
146
  /// Non-const index operator
-
 
147
  T& operator () ( unsigned int i ) 
-
 
148
	{
-
 
149
	  assert(i<N);
-
 
150
	  return data[i];
-
 
151
	}
-
 
152
 
-
 
153
 
139
      /** Get a pointer to first element in data array.
154
      /** Get a pointer to first element in data array.
140
	  This function may be useful when interfacing with some other API 
155
	  This function may be useful when interfacing with some other API 
141
	  such as OpenGL (TM) */
156
	  such as OpenGL (TM) */
142
      T* get() {return &data[0];}
157
      T* get() {return &data[0];}
143
 
158
 
144
      /** Get a const pointer to first element in data array.
159
      /** Get a const pointer to first element in data array.
145
	  This function may be useful when interfacing with some other API 
160
	  This function may be useful when interfacing with some other API 
146
	  such as OpenGL (TM). */
161
	  such as OpenGL (TM). */
147
      const T* get() const {return &data[0];}
162
      const T* get() const {return &data[0];}
148
 
163
 
149
      //----------------------------------------------------------------------
164
      //----------------------------------------------------------------------
150
      // Comparison operators
165
      // Comparison operators
151
      //----------------------------------------------------------------------
166
      //----------------------------------------------------------------------
152
 
167
 
153
      /// Equality operator
168
      /// Equality operator
154
      bool operator==(const V& v) const 
169
      bool operator==(const V& v) const 
155
	{
170
	{
156
	  return std::inner_product(data, &data[N], v.get(), true,
171
	  return std::inner_product(data, &data[N], v.get(), true,
157
				    std::logical_and<bool>(), std::equal_to<T>());
172
				    std::logical_and<bool>(), std::equal_to<T>());
158
	}
173
	}
159
 
174
 
160
#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;}
161
      /// Equality wrt scalar. True if all coords are equal to scalar
176
      /// Equality wrt scalar. True if all coords are equal to scalar
162
      bool operator==(T k) const 
177
      bool operator==(T k) const 
163
	{ 
178
	{ 
164
	  for_all_i(if (data[i] != k) return false)
179
	  for_all_i(if (data[i] != k) return false)
165
	    return true;
180
	    return true;
166
	}
181
	}
167
#undef for_all_i  
182
#undef for_all_i  
168
 
183
 
169
      /// Inequality operator
184
      /// Inequality operator
170
      bool operator!=(const V& v) const 
185
      bool operator!=(const V& v) const 
171
	{
186
	{
172
	  return std::inner_product(data, &data[N], v.get(), false,
187
	  return std::inner_product(data, &data[N], v.get(), false,
173
				    std::logical_or<bool>(), std::not_equal_to<T>());
188
				    std::logical_or<bool>(), std::not_equal_to<T>());
174
	}
189
	}
175
 
190
 
176
      /// Inequality wrt scalar. True if any coord not equal to scalar
191
      /// Inequality wrt scalar. True if any coord not equal to scalar
177
      bool operator!=(T k) const 
192
      bool operator!=(T k) const 
178
	{ 
193
	{ 
179
	  return !(*this==k);
194
	  return !(*this==k);
180
	}
195
	}
181
 
196
 
182
 
197
 
183
      //----------------------------------------------------------------------
198
      //----------------------------------------------------------------------
184
      // Comparison functions ... of geometric significance 
199
      // Comparison functions ... of geometric significance 
185
      //----------------------------------------------------------------------
200
      //----------------------------------------------------------------------
186
 
201
 
187
      /** Compare all coordinates against other vector. ( < )
202
      /** Compare all coordinates against other vector. ( < )
188
	  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. */
189
      bool  all_l  (const V& v) const
204
      bool  all_l  (const V& v) const
190
	{
205
	{
191
	  return std::inner_product(data, &data[N], v.get(), true, 
206
	  return std::inner_product(data, &data[N], v.get(), true, 
192
				    std::logical_and<bool>(), std::less<T>());
207
				    std::logical_and<bool>(), std::less<T>());
193
	}
208
	}
194
 
209
 
195
      /** Compare all coordinates against other vector. ( <= )
210
      /** Compare all coordinates against other vector. ( <= )
196
	  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. */
197
      bool  all_le (const V& v) const
212
      bool  all_le (const V& v) const
198
	{
213
	{
199
	  return std::inner_product(data, &data[N], v.get(), true, 
214
	  return std::inner_product(data, &data[N], v.get(), true, 
200
				    std::logical_and<bool>(), std::less_equal<T>());
215
				    std::logical_and<bool>(), std::less_equal<T>());
201
	}
216
	}
202
 
217
 
203
      /** Compare all coordinates against other vector. ( > )
218
      /** Compare all coordinates against other vector. ( > )
204
	  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. */
205
      bool  all_g  (const V& v) const
220
      bool  all_g  (const V& v) const
206
	{
221
	{
207
	  return std::inner_product(data, &data[N], v.get(), true, 
222
	  return std::inner_product(data, &data[N], v.get(), true, 
208
				    std::logical_and<bool>(), std::greater<T>());
223
				    std::logical_and<bool>(), std::greater<T>());
209
	}
224
	}
210
 
225
 
211
      /** Compare all coordinates against other vector. ( >= )
226
      /** Compare all coordinates against other vector. ( >= )
212
	  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. */
213
      bool  all_ge (const V& v) const
228
      bool  all_ge (const V& v) const
214
	{
229
	{
215
	  return std::inner_product(data, &data[N], v.get(), true, 
230
	  return std::inner_product(data, &data[N], v.get(), true, 
216
				    std::logical_and<bool>(), std::greater_equal<T>());
231
				    std::logical_and<bool>(), std::greater_equal<T>());
217
	}
232
	}
218
 
233
 
219
 
234
 
220
      //----------------------------------------------------------------------
235
      //----------------------------------------------------------------------
221
      // Assignment operators
236
      // Assignment operators
222
      //----------------------------------------------------------------------
237
      //----------------------------------------------------------------------
223
 
238
 
224
      /// Assignment multiplication with scalar.
239
      /// Assignment multiplication with scalar.
225
      const V& operator *=(T k) 
240
      const V& operator *=(T k) 
226
	{ 
241
	{ 
227
	  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));
228
	  return static_cast<const V&>(*this);
243
	  return static_cast<const V&>(*this);
229
	}
244
	}
230
 
245
 
231
      /// Assignment division with scalar.
246
      /// Assignment division with scalar.
232
      const V& operator /=(T k)
247
      const V& operator /=(T k)
233
	{ 
248
	{ 
234
	  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));
235
	  return static_cast<const V&>(*this);
250
	  return static_cast<const V&>(*this);
236
	}
251
	}
237
 
252
 
238
      /// Assignment addition with scalar. Adds scalar to each coordinate.
253
      /// Assignment addition with scalar. Adds scalar to each coordinate.
239
      const V& operator +=(T k) 
254
      const V& operator +=(T k) 
240
	{
255
	{
241
	  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));
242
	  return  static_cast<const V&>(*this);
257
	  return  static_cast<const V&>(*this);
243
	}
258
	}
244
 
259
 
245
      /// Assignment subtraction with scalar. Subtracts scalar from each coord.
260
      /// Assignment subtraction with scalar. Subtracts scalar from each coord.
246
      const V& operator -=(T k) 
261
      const V& operator -=(T k) 
247
	{ 
262
	{ 
248
	  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));
249
	  return  static_cast<const V&>(*this);
264
	  return  static_cast<const V&>(*this);
250
	}
265
	}
251
 
266
 
252
      /** Assignment multiplication with vector. 
267
      /** Assignment multiplication with vector. 
253
	  Multiply each coord independently. */
268
	  Multiply each coord independently. */
254
      const V& operator *=(const V& v) 
269
      const V& operator *=(const V& v) 
255
	{ 
270
	{ 
256
	  std::transform(data, &data[N], v.get(), data, std::multiplies<T>());
271
	  std::transform(data, &data[N], v.get(), data, std::multiplies<T>());
257
	  return  static_cast<const V&>(*this);
272
	  return  static_cast<const V&>(*this);
258
	}
273
	}
259
 
274
 
260
      /// Assigment division with vector. Each coord divided independently.
275
      /// Assigment division with vector. Each coord divided independently.
261
      const V& operator /=(const V& v)
276
      const V& operator /=(const V& v)
262
	{
277
	{
263
	  std::transform(data, &data[N], v.get(), data, std::divides<T>());
278
	  std::transform(data, &data[N], v.get(), data, std::divides<T>());
264
	  return  static_cast<const V&>(*this);
279
	  return  static_cast<const V&>(*this);
265
	}
280
	}
266
 
281
 
267
      /// Assignmment addition with vector.
282
      /// Assignmment addition with vector.
268
      const V& operator +=(const V& v) 
283
      const V& operator +=(const V& v) 
269
	{
284
	{
270
	  std::transform(data, &data[N], v.get(), data, std::plus<T>());
285
	  std::transform(data, &data[N], v.get(), data, std::plus<T>());
271
	  return  static_cast<const V&>(*this);
286
	  return  static_cast<const V&>(*this);
272
	}
287
	}
273
		
288
		
274
      /// Assignment subtraction with vector.
289
      /// Assignment subtraction with vector.
275
      const V& operator -=(const V& v) 
290
      const V& operator -=(const V& v) 
276
	{ 
291
	{ 
277
	  std::transform(data, &data[N], v.get(), data, std::minus<T>());
292
	  std::transform(data, &data[N], v.get(), data, std::minus<T>());
278
	  return  static_cast<const V&>(*this);
293
	  return  static_cast<const V&>(*this);
279
	}
294
	}
280
 
295
 
281
 
296
 
282
      //----------------------------------------------------------------------
297
      //----------------------------------------------------------------------
283
      // Unary operators on vectors
298
      // Unary operators on vectors
284
      //----------------------------------------------------------------------
299
      //----------------------------------------------------------------------
285
 
300
 
286
      /// Negate vector.
301
      /// Negate vector.
287
      const V operator - () const
302
      const V operator - () const
288
	{
303
	{
289
	  V v_new;
304
	  V v_new;
290
	  std::transform(data, &data[N], v_new.get(), std::negate<T>());
305
	  std::transform(data, &data[N], v_new.get(), std::negate<T>());
291
	  return v_new;
306
	  return v_new;
292
	}
307
	}
293
 
308
 
294
      //----------------------------------------------------------------------
309
      //----------------------------------------------------------------------
295
      // Binary operators on vectors
310
      // Binary operators on vectors
296
      //----------------------------------------------------------------------
311
      //----------------------------------------------------------------------
297
 
312
 
298
      /** Multiply vector with vector. Each coord multiplied independently
313
      /** Multiply vector with vector. Each coord multiplied independently
299
	  Do not confuse this operation with dot product. */
314
	  Do not confuse this operation with dot product. */
300
      const V operator * (const V& v1) const
315
      const V operator * (const V& v1) const
301
	{
316
	{
302
	  V v_new;
317
	  V v_new;
303
	  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>());
304
	  return v_new;
319
	  return v_new;
305
	}
320
	}
306
 
321
 
307
      /// Add two vectors
322
      /// Add two vectors
308
      const V operator + (const V& v1) const
323
      const V operator + (const V& v1) const
309
	{
324
	{
310
	  V v_new;
325
	  V v_new;
311
	  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>());
312
	  return v_new;
327
	  return v_new;
313
	}
328
	}
314
 
329
 
315
      /// Subtract two vectors. 
330
      /// Subtract two vectors. 
316
      const V operator - (const V& v1) const
331
      const V operator - (const V& v1) const
317
	{
332
	{
318
	  V v_new;
333
	  V v_new;
319
	  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>());
320
	  return v_new;
335
	  return v_new;
321
	}
336
	}
322
 
337
 
323
      /// Divide two vectors. Each coord separately
338
      /// Divide two vectors. Each coord separately
324
      const V operator / (const V& v1) const
339
      const V operator / (const V& v1) const
325
	{
340
	{
326
	  V v_new;
341
	  V v_new;
327
	  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>());
328
	  return v_new;
343
	  return v_new;
329
	}
344
	}
330
 
345
 
331
      //----------------------------------------------------------------------
346
      //----------------------------------------------------------------------
332
      // Binary operators on vector and scalar
347
      // Binary operators on vector and scalar
333
      //----------------------------------------------------------------------
348
      //----------------------------------------------------------------------
334
 
349
 
335
      /// Multiply scalar onto vector.
350
      /// Multiply scalar onto vector.
336
      const V operator * (T k) const
351
      const V operator * (T k) const
337
	{
352
	{
338
	  V v_new;
353
	  V v_new;
339
	  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));
340
	  return v_new;
355
	  return v_new;
341
	}
356
	}
342
  
357
  
343
 
358
 
344
      /// Divide vector by scalar.
359
      /// Divide vector by scalar.
345
      const V operator / (T k) const
360
      const V operator / (T k) const
346
	{
361
	{
347
	  V v_new;
362
	  V v_new;
348
	  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));
349
	  return v_new;      
364
	  return v_new;      
350
	}
365
	}
351
 
366
 
352
 
367
 
353
      /// Return the smallest coordinate of the vector
368
      /// Return the smallest coordinate of the vector
354
      const T min_coord() const 
369
      const T min_coord() const 
355
	{
370
	{
356
	  return *std::min_element(data, &data[N]);
371
	  return *std::min_element(data, &data[N]);
357
	}
372
	}
358
 
373
 
359
      /// Return the largest coordinate of the vector
374
      /// Return the largest coordinate of the vector
360
      const T max_coord() const
375
      const T max_coord() const
361
	{
376
	{
362
	  return *std::max_element(data, &data[N]);
377
	  return *std::max_element(data, &data[N]);
363
	}
378
	}
364
 
379
 
365
    };
380
    };
366
 
381
 
367
  template <class T, class V, unsigned int N> 
382
  template <class T, class V, unsigned int N> 
368
    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)
369
    {
384
    {
370
      os << "[ ";
385
      os << "[ ";
371
      for(unsigned int i=0;i<N;i++) os << v[i] << " ";
386
      for(unsigned int i=0;i<N;i++) os << v[i] << " ";
372
      os << "]";
387
      os << "]";
373
      return os;
388
      return os;
374
    }
389
    }
375
 
390
 
376
  /// Get from operator for ArithVec descendants. 
391
  /// Get from operator for ArithVec descendants. 
377
  template <class T,class V, unsigned int N>
392
  template <class T,class V, unsigned int N>
378
    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)
379
    {
394
    {
380
      for(unsigned int i=0;i<N;i++) is>>v[i];
395
      for(unsigned int i=0;i<N;i++) is>>v[i];
381
      return is;
396
      return is;
382
    }
397
    }
383
 
398
 
384
 
399
 
385
  /** Dot product for two vectors. The `*' operator is 
400
  /** Dot product for two vectors. The `*' operator is 
386
      reserved for coordinatewise	multiplication of vectors. */
401
      reserved for coordinatewise	multiplication of vectors. */
387
  template <class T,class V, unsigned int N>
402
  template <class T,class V, unsigned int N>
388
    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)
389
    {
404
    {
390
      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));
391
    }
406
    }
392
 
407
 
393
  /** 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. */
394
  template <class T,class V, unsigned int N>
409
  template <class T,class V, unsigned int N>
395
    inline T sqr_length(const ArithVec<T,V,N>& v)
410
    inline T sqr_length(const ArithVec<T,V,N>& v)
396
    {
411
    {
397
      return dot(v,v);
412
      return dot(v,v);
398
    }
413
    }
399
 
414
 
400
  /** Multiply double onto vector. This operator handles the case 
415
  /** Multiply double onto vector. This operator handles the case 
401
      where the vector is on the righ side of the `*'.
416
      where the vector is on the righ side of the `*'.
402
	 
417
	 
403
      \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
404
      ArithVec class template, but the operator functions whose 
419
      ArithVec class template, but the operator functions whose 
405
      left operand is _not_ a vector cannot be inside, hence they
420
      left operand is _not_ a vector cannot be inside, hence they
406
      are here.
421
      are here.
407
      We need three operators for scalar * vector although they are
422
      We need three operators for scalar * vector although they are
408
      identical, because, if we use a separate template argument for
423
      identical, because, if we use a separate template argument for
409
      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 
410
      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
411
      be automatically converted, we will be disappointed. It seems that 
426
      be automatically converted, we will be disappointed. It seems that 
412
      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
413
      left operand is really a double.
428
      left operand is really a double.
414
  */
429
  */
415
 
430
 
416
  template<class T, class V, unsigned int N>
431
  template<class T, class V, unsigned int N>
417
    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) 
418
    {
433
    {
419
      return v * k;
434
      return v * k;
420
    }
435
    }
421
 
436
 
422
  /** Multiply float onto vector. See the note in the documentation
437
  /** Multiply float onto vector. See the note in the documentation
423
      regarding multiplication of a double onto a vector. */
438
      regarding multiplication of a double onto a vector. */
424
  template<class T, class V, unsigned int N>
439
  template<class T, class V, unsigned int N>
425
    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) 
426
    {
441
    {
427
      return v * k;
442
      return v * k;
428
    }
443
    }
429
 
444
 
430
  /** Multiply unsigned int onto vector. See the note in the documentation
445
  /** Multiply unsigned int onto vector. See the note in the documentation
431
      regarding multiplication of a double onto a vector. */
446
      regarding multiplication of a double onto a vector. */
432
  template<class T, class V, unsigned int N>
447
  template<class T, class V, unsigned int N>
433
    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) 
434
    {
449
    {
435
      return v * k;
450
      return v * k;
436
    }
451
    }
437
 
452
 
438
  /** Returns the vector containing for each coordinate the smallest
453
  /** Returns the vector containing for each coordinate the smallest
439
      value from two vectors. */
454
      value from two vectors. */
440
  template <class T,class V, unsigned int N>
455
  template <class T,class V, unsigned int N>
441
    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)
442
    {
457
    {
443
      V v;
458
      V v;
444
      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>));
445
      return v;
460
      return v;
446
    }
461
    }
447
 
462
 
448
  /** Returns the vector containing for each coordinate the largest 
463
  /** Returns the vector containing for each coordinate the largest 
449
      value from two vectors. */
464
      value from two vectors. */
450
  template <class T,class V, unsigned int N>
465
  template <class T,class V, unsigned int N>
451
    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)
452
    {
467
    {
453
      V v;
468
      V v;
454
      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>));
455
      return v;
470
      return v;
456
    }
471
    }
457
 
472
 
458
 
473
 
459
}
474
}
460
 
475
 
461
#endif
476
#endif
462
 
477