Subversion Repositories gelsvn

Rev

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

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