Subversion Repositories gelsvn

Rev

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

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