Subversion Repositories gelsvn

Rev

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

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