Subversion Repositories gelsvn

Rev

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

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