Subversion Repositories gelsvn

Rev

Rev 10 | Rev 43 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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