Subversion Repositories gelsvn

Rev

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