Subversion Repositories gelsvn

Rev

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

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