Subversion Repositories gelsvn

Rev

Rev 561 | Details | Compare with Previous | Last modification | View Log | RSS feed

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