Subversion Repositories gelsvn

Rev

Rev 630 | Rev 633 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 630 Rev 632
Line 10... Line 10...
10
 */
10
 */
11
 
11
 
12
#ifndef __CGLA_ARITHVEC_H__
12
#ifndef __CGLA_ARITHVEC_H__
13
#define __CGLA_ARITHVEC_H__
13
#define __CGLA_ARITHVEC_H__
14
 
14
 
-
 
15
#include <array>
-
 
16
#include <algorithm>
15
#include <iostream>
17
#include <iostream>
16
#include "CGLA.h"
18
#include "CGLA.h"
17
 
19
 
18
#include <numeric>
20
#include <numeric>
19
 
21
 
Line 46... Line 48...
46
    {
48
    {
47
 
49
        
48
    protected:
50
    protected:
49
 
51
        
50
      /// The actual contents of the vector.
52
        /// The actual contents of the vector.
51
      T data[N];
53
        std::array<T,N> data;
52
 
54
        
53
    protected:
55
    protected:
54
 
56
        
55
      //----------------------------------------------------------------------
57
        //----------------------------------------------------------------------
56
      // Constructors
58
        // Constructors
57
      //----------------------------------------------------------------------
59
        //----------------------------------------------------------------------
58
 
60
        
59
      /// Construct uninitialized vector
61
        /// Construct uninitialized vector
60
      ArithVec() 
62
        ArithVec() {}
61
	{
-
 
62
	}
-
 
63
 
63
        
64
      /// Construct a vector where all coordinates are identical
64
        /// Construct a vector where all coordinates are identical
65
      explicit ArithVec(T _a)
65
        explicit ArithVec(T _a)
66
	{
66
        {
67
	  std::fill_n(data, N, _a);
67
            std::fill_n(data, N, _a);
68
	}
68
        }
69
 
69
        
70
      /// Construct a 2D vector 
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
	}
-
 
77
 
-
 
78
      /// Construct a 3D vector
-
 
79
      ArithVec(T _a, T _b, T _c)
71
        ArithVec(T _a, T _b): data({_a,_b}) {assert(N==2);}
80
	{
-
 
81
	  assert(N==3);
-
 
82
	  data[0] = _a;
-
 
83
	  data[1] = _b;
-
 
84
	  data[2] = _c;
-
 
85
	}
-
 
86
 
72
        
87
      /// Construct a 4D vector
73
        /// Construct a 2D vector
88
      ArithVec(T _a, T _b, T _c, T _d)
74
        ArithVec(T _a, T _b, T _c): data({_a,_b,_c}) {assert(N==3);}
89
	{
-
 
90
	  assert(N==4);
-
 
91
	  data[0] = _a;
-
 
92
	  data[1] = _b;
-
 
93
	  data[2] = _c;
-
 
94
	  data[3] = _d;
-
 
95
	}
-
 
96
 
75
        
-
 
76
        /// Construct a 2D vector
-
 
77
        ArithVec(T _a, T _b, T _c, T _d): data({_a,_b,_c,_d}) {assert(N==4);}
97
 
78
        
98
    public:
79
    public:
99
 
80
        
100
      /// For convenience we define a more meaningful name for the scalar type
81
        /// For convenience we define a more meaningful name for the scalar type
101
      typedef T ScalarType;
82
        typedef T ScalarType;
Line 108... Line 89...
108
	
89
        
109
      /// Set all coordinates of a 2D vector.
90
        /// Set all coordinates of a 2D vector.
110
      void set(T _a, T _b)
91
        void set(T _a, T _b)
111
	{
92
        {
112
	  assert(N==2);
93
            assert(N==2);
113
	  data[0] = _a;
-
 
114
	  data[1] = _b;
94
            data = {_a,_b};
115
	}
95
        }
116
 
96
        
117
      /// Set all coordinates of a 3D vector.
97
        /// Set all coordinates of a 3D vector.
118
      void set(T _a, T _b, T _c)
98
        void set(T _a, T _b, T _c)
119
	{
99
        {
120
	  assert(N==3);
100
            assert(N==3);
121
	  data[0] = _a;
-
 
122
	  data[1] = _b;
-
 
123
	  data[2] = _c;
101
            data = {_a,_b,_c};
124
	}
102
        }
125
 
103
        
126
      /// Set all coordinates of a 4D vector.
104
        /// Set all coordinates of a 4D vector.
127
      void set(T _a, T _b, T _c, T _d)
105
        void set(T _a, T _b, T _c, T _d)
128
	{
106
        {
129
	  assert(N==4);
107
            assert(N==4);
130
	  data[0] = _a;
-
 
131
	  data[1] = _b;
-
 
132
	  data[2] = _c;
-
 
133
	  data[3] = _d;
108
            data = {_a,_b,_c,_d};
134
	}
109
        }
135
 
110
        
136
  /// Const index operator
111
        /// Const index operator
137
  const T& operator [] ( unsigned int i ) const
112
        const T& operator [] ( unsigned int i ) const
138
	{
113
        {
Line 163... Line 138...
163
 
138
        
164
 
139
        
165
      /** Get a pointer to first element in data array.
140
        /** Get a pointer to first element in data array.
166
	  This function may be useful when interfacing with some other API 
141
         This function may be useful when interfacing with some other API
167
	  such as OpenGL (TM) */
142
         such as OpenGL (TM) */
168
      T* get() {return &data[0];}
143
        T* get() {return begin();}
-
 
144
        T* begin() {return data.begin();}
-
 
145
        T* end() {return data.end();}
169
 
146
        
170
      /** Get a const pointer to first element in data array.
147
        /** Get a const pointer to first element in data array.
171
	  This function may be useful when interfacing with some other API 
148
         This function may be useful when interfacing with some other API
172
	  such as OpenGL (TM). */
149
         such as OpenGL (TM). */
173
      const T* get() const {return &data[0];}
150
        const T* get() const {return data.begin();}
-
 
151
        const T* begin() const {return data.begin();}
-
 
152
        const T* end() const {return data.end();}
174
 
153
        
175
      //----------------------------------------------------------------------
154
        //----------------------------------------------------------------------
176
      // Comparison operators
155
        // Comparison operators
177
      //----------------------------------------------------------------------
156
        //----------------------------------------------------------------------
178
 
157
        
179
      /// Equality operator
158
        /// Equality operator
180
      bool operator==(const V& v) const 
159
        bool operator==(const V& v) const
181
	{
160
        {
182
	  return std::inner_product(data, &data[N], v.get(), true,
161
            return std::equal(begin(),end(), v.begin());
183
				    std::logical_and<bool>(), std::equal_to<T>());
-
 
184
	}
162
        }
185
 
163
        
186
#define for_all_i(expr) for(unsigned int i=0;i<N;i++) {expr;}
-
 
187
      /// Equality wrt scalar. True if all coords are equal to scalar
164
        /// Equality wrt scalar. True if all coords are equal to scalar
188
      bool operator==(T k) const 
165
        bool operator==(T k) const
189
	{ 
166
        {
190
	  for_all_i(if (data[i] != k) return false)
167
            return std::count(begin(),end(), k)==N;
191
	    return true;
-
 
192
	}
168
        }
193
#undef for_all_i  
-
 
194
 
169
        
195
      /// Inequality operator
170
        /// Inequality operator
196
      bool operator!=(const V& v) const 
171
        bool operator!=(const V& v) const
197
	{
172
        {
198
	  return std::inner_product(data, &data[N], v.get(), false,
-
 
199
				    std::logical_or<bool>(), std::not_equal_to<T>());
173
            return !(*this==v);
200
	}
174
        }
201
 
175
        
202
      /// Inequality wrt scalar. True if any coord not equal to scalar
176
        /// Inequality wrt scalar. True if any coord not equal to scalar
203
      bool operator!=(T k) const 
177
        bool operator!=(T k) const
204
	{ 
178
        {
Line 212... Line 186...
212
 
186
        
213
      /** Compare all coordinates against other vector. ( < )
187
        /** Compare all coordinates against other vector. ( < )
214
	  Similar to testing whether we are on one side of three planes. */
188
         Similar to testing whether we are on one side of three planes. */
215
      bool  all_l  (const V& v) const
189
        bool  all_l  (const V& v) const
216
	{
190
        {
217
	  return std::inner_product(data, &data[N], v.get(), true, 
191
            return std::inner_product(begin(), end(), v.begin(), true,
218
				    std::logical_and<bool>(), std::less<T>());
192
                                      std::logical_and<bool>(), std::less<T>());
219
	}
193
        }
220
 
194
        
221
      /** Compare all coordinates against other vector. ( <= )
195
        /** Compare all coordinates against other vector. ( <= )
222
	  Similar to testing whether we are on one side of three planes. */
196
         Similar to testing whether we are on one side of three planes. */
223
      bool  all_le (const V& v) const
197
        bool  all_le (const V& v) const
224
	{
198
        {
225
	  return std::inner_product(data, &data[N], v.get(), true, 
199
            return std::inner_product(begin(), end(), v.begin(), true,
226
				    std::logical_and<bool>(), std::less_equal<T>());
200
                                      std::logical_and<bool>(), std::less_equal<T>());
227
	}
201
        }
228
 
202
        
229
      /** Compare all coordinates against other vector. ( > )
203
        /** Compare all coordinates against other vector. ( > )
230
	  Similar to testing whether we are on one side of three planes. */
204
         Similar to testing whether we are on one side of three planes. */
231
      bool  all_g  (const V& v) const
205
        bool  all_g  (const V& v) const
232
	{
206
        {
233
	  return std::inner_product(data, &data[N], v.get(), true, 
207
            return std::inner_product(begin(), end(), v.begin(), true,
234
				    std::logical_and<bool>(), std::greater<T>());
208
                                      std::logical_and<bool>(), std::greater<T>());
235
	}
209
        }
236
 
210
        
237
      /** Compare all coordinates against other vector. ( >= )
211
        /** Compare all coordinates against other vector. ( >= )
238
	  Similar to testing whether we are on one side of three planes. */
212
         Similar to testing whether we are on one side of three planes. */
239
      bool  all_ge (const V& v) const
213
        bool  all_ge (const V& v) const
240
	{
214
        {
241
	  return std::inner_product(data, &data[N], v.get(), true, 
215
            return std::inner_product(begin(), end(), v.begin(), true,
242
				    std::logical_and<bool>(), std::greater_equal<T>());
216
                                      std::logical_and<bool>(), std::greater_equal<T>());
243
	}
217
        }
244
 
218
        
245
 
219
        
246
      //----------------------------------------------------------------------
220
        //----------------------------------------------------------------------
Line 248... Line 222...
248
      //----------------------------------------------------------------------
222
        //----------------------------------------------------------------------
249
 
223
        
250
      /// Assignment multiplication with scalar.
224
        /// Assignment multiplication with scalar.
251
      const V& operator *=(T k) 
225
        const V& operator *=(T k)
252
	{ 
226
        {
253
	  std::transform(data, &data[N], data, std::bind2nd(std::multiplies<T>(), k));
227
            std::for_each(begin(), end(), [k](T& x){x*=k;});
254
	  return static_cast<const V&>(*this);
228
            return static_cast<const V&>(*this);
255
	}
229
        }
256
 
230
        
257
      /// Assignment division with scalar.
231
        /// Assignment division with scalar.
258
      const V& operator /=(T k)
232
        const V& operator /=(T k)
259
	{ 
233
        {
260
	  std::transform(data, &data[N], data, std::bind2nd(std::divides<T>(), k));
234
            std::for_each(begin(), end(), [k](T& x){x/=k;});
261
	  return static_cast<const V&>(*this);
235
            return static_cast<const V&>(*this);
262
	}
236
        }
263
 
237
        
264
      /// Assignment addition with scalar. Adds scalar to each coordinate.
238
        /// Assignment addition with scalar. Adds scalar to each coordinate.
265
      const V& operator +=(T k) 
239
        const V& operator +=(T k)
266
	{
240
        {
267
	  std::transform(data, &data[N], data, std::bind2nd(std::plus<T>(), k));
241
            std::for_each(begin(), end(), [k](T& x){x+=k;});
268
	  return  static_cast<const V&>(*this);
242
            return  static_cast<const V&>(*this);
269
	}
243
        }
270
 
244
        
271
      /// Assignment subtraction with scalar. Subtracts scalar from each coord.
245
        /// Assignment subtraction with scalar. Subtracts scalar from each coord.
272
      const V& operator -=(T k) 
246
        const V& operator -=(T k)
273
	{ 
247
        {
274
	  std::transform(data, &data[N], data, std::bind2nd(std::minus<T>(), k));
248
            std::for_each(begin(), end(), [k](T& x){x-=k;});
275
	  return  static_cast<const V&>(*this);
249
            return  static_cast<const V&>(*this);
276
	}
250
        }
277
 
251
        
278
      /** Assignment multiplication with vector. 
252
        /** Assignment multiplication with vector.
279
	  Multiply each coord independently. */
253
         Multiply each coord independently. */
280
      const V& operator *=(const V& v) 
254
        const V& operator *=(const V& v)
281
	{ 
255
        {
282
	  std::transform(data, &data[N], v.get(), data, std::multiplies<T>());
256
            std::transform(begin(), end(), v.begin(), begin(), std::multiplies<T>());
283
	  return  static_cast<const V&>(*this);
257
            return  static_cast<const V&>(*this);
284
	}
258
        }
285
 
259
        
286
      /// Assigment division with vector. Each coord divided independently.
260
        /// Assigment division with vector. Each coord divided independently.
287
      const V& operator /=(const V& v)
261
        const V& operator /=(const V& v)
288
	{
262
        {
289
	  std::transform(data, &data[N], v.get(), data, std::divides<T>());
263
            std::transform(begin(), end(),  v.begin(), begin(), std::divides<T>());
290
	  return  static_cast<const V&>(*this);
264
            return  static_cast<const V&>(*this);
291
	}
265
        }
292
 
266
        
293
      /// Assignmment addition with vector.
267
        /// Assignmment addition with vector.
294
      const V& operator +=(const V& v) 
268
        const V& operator +=(const V& v)
295
	{
269
        {
296
	  std::transform(data, &data[N], v.get(), data, std::plus<T>());
270
            std::transform(begin(), end(), v.begin(), begin(), std::plus<T>());
297
	  return  static_cast<const V&>(*this);
271
            return  static_cast<const V&>(*this);
298
	}
272
        }
299
		
273
		
300
      /// Assignment subtraction with vector.
274
        /// Assignment subtraction with vector.
301
      const V& operator -=(const V& v) 
275
        const V& operator -=(const V& v)
302
	{ 
276
        {
303
	  std::transform(data, &data[N], v.get(), data, std::minus<T>());
277
            std::transform(begin(), end(), v.begin(), begin(), std::minus<T>());
304
	  return  static_cast<const V&>(*this);
278
            return  static_cast<const V&>(*this);
305
	}
279
        }
306
 
280
        
307
 
281
        
308
      //----------------------------------------------------------------------
282
        //----------------------------------------------------------------------
Line 311... Line 285...
311
 
285
        
312
      /// Negate vector.
286
        /// Negate vector.
313
      const V operator - () const
287
        const V operator - () const
314
	{
288
        {
315
	  V v_new;
289
            V v_new;
316
	  std::transform(data, &data[N], v_new.get(), std::negate<T>());
290
            std::transform(begin(), end(), v_new.begin(), std::negate<T>());
317
	  return v_new;
291
            return v_new;
318
	}
292
        }
319
 
293
        
320
      //----------------------------------------------------------------------
294
        //----------------------------------------------------------------------
321
      // Binary operators on vectors
295
        // Binary operators on vectors
Line 324... Line 298...
324
      /** Multiply vector with vector. Each coord multiplied independently
298
        /** Multiply vector with vector. Each coord multiplied independently
325
	  Do not confuse this operation with dot product. */
299
         Do not confuse this operation with dot product. */
326
      const V operator * (const V& v1) const
300
        const V operator * (const V& v1) const
327
	{
301
        {
328
	  V v_new;
302
            V v_new;
329
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::multiplies<T>());
303
            std::transform(begin(), end(), v1.begin(), v_new.begin(), std::multiplies<T>());
330
	  return v_new;
304
            return v_new;
331
	}
305
        }
332
 
306
        
333
      /// Add two vectors
307
        /// Add two vectors
334
      const V operator + (const V& v1) const
308
        const V operator + (const V& v1) const
335
	{
309
        {
336
	  V v_new;
310
            V v_new;
337
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::plus<T>());
311
            std::transform(begin(), end(), v1.begin(), v_new.begin(), std::plus<T>());
338
	  return v_new;
312
            return v_new;
339
	}
313
        }
340
 
314
        
341
      /// Subtract two vectors. 
315
        /// Subtract two vectors.
342
      const V operator - (const V& v1) const
316
        const V operator - (const V& v1) const
343
	{
317
        {
344
	  V v_new;
318
            V v_new;
345
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::minus<T>());
319
            std::transform(begin(), end(), v1.begin(), v_new.begin(), std::minus<T>());
346
	  return v_new;
320
            return v_new;
347
	}
321
        }
348
 
322
        
349
      /// Divide two vectors. Each coord separately
323
        /// Divide two vectors. Each coord separately
350
      const V operator / (const V& v1) const
324
        const V operator / (const V& v1) const
351
	{
325
        {
352
	  V v_new;
326
            V v_new;
353
	  std::transform(data, &data[N], v1.get(), v_new.get(), std::divides<T>());
327
            std::transform(begin(), end(), v1.begin(), v_new.begin(), std::divides<T>());
354
	  return v_new;
328
            return v_new;
355
	}
329
        }
356
 
330
        
357
      //----------------------------------------------------------------------
331
        //----------------------------------------------------------------------
358
      // Binary operators on vector and scalar
332
        // Binary operators on vector and scalar
Line 360... Line 334...
360
 
334
        
361
      /// Multiply scalar onto vector.
335
        /// Multiply scalar onto vector.
362
      const V operator * (T k) const
336
        const V operator * (T k) const
363
	{
337
        {
364
	  V v_new;
338
            V v_new;
365
	  std::transform(data, &data[N], v_new.get(), std::bind2nd(std::multiplies<T>(), k));
339
            std::transform(begin(), end(), v_new.begin(), [k](T x){return x*k;});
366
	  return v_new;
340
            return v_new;
367
	}
341
        }
368
  
342
        
369
 
343
        
370
      /// Divide vector by scalar.
344
        /// Divide vector by scalar.
371
      const V operator / (T k) const
345
        const V operator / (T k) const
372
	{
346
        {
373
	  V v_new;
347
            V v_new;
374
	  std::transform(data, &data[N], v_new.get(), std::bind2nd(std::divides<T>(), k));
348
            std::transform(begin(), end(), v_new.begin(), [k](T x){return x/k;});
375
	  return v_new;      
349
            return v_new;
376
	}
350
        }
377
 
351
        
378
 
352
        
379
      /// Return the smallest coordinate of the vector
353
        /// Return the smallest coordinate of the vector
380
      const T min_coord() const 
354
        const T min_coord() const
381
	{
355
        {
382
	  return *std::min_element(data, &data[N]);
356
            return *std::min_element(begin(), end());
383
	}
357
        }
384
 
358
        
385
      /// Return the largest coordinate of the vector
359
        /// Return the largest coordinate of the vector
386
      const T max_coord() const
360
        const T max_coord() const
387
	{
361
        {
388
	  return *std::max_element(data, &data[N]);
362
            return *std::max_element(begin(), end());
389
	}
363
        }
390
 
364
        
391
    };
365
    };
392
 
366
    
393
    template <class T, class V, unsigned int N> 
367
    template <class T, class V, unsigned int N>
394
    inline std::ostream& operator<<(std::ostream&os, const ArithVec<T,V,N>& v)
368
    inline std::ostream& operator<<(std::ostream&os, const ArithVec<T,V,N>& v)
395
    {
369
    {
396
      os << "[ ";
370
        os << "[ ";
397
      for(unsigned int i=0;i<N;i++) os << v[i] << " ";
371
        for(const T& x : v) os << x << " ";
398
      os << "]";
372
        os << "]";
399
      return os;
373
        return os;
400
    }
374
        }
401
 
375
        
402
  /// Get from operator for ArithVec descendants. 
376
        /// Get from operator for ArithVec descendants.
Line 420... Line 394...
420
  /** Dot product for two vectors. The `*' operator is 
394
        /** Dot product for two vectors. The `*' operator is
421
      reserved for coordinatewise	multiplication of vectors. */
395
         reserved for coordinatewise	multiplication of vectors. */
422
  template <class T,class V, unsigned int N>
396
        template <class T,class V, unsigned int N>
423
    inline T dot(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
397
        inline T dot(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
424
    {
398
        {
425
      return std::inner_product(v0.get(), v0.get() + N, v1.get(), T(0));
399
            return std::inner_product(v0.begin(), v0.end(), v1.begin(), T(0));
426
    }
400
        }
427
 
401
        
428
  /** Compute the sqr length by taking dot product of vector with itself. */
402
        /** Compute the sqr length by taking dot product of vector with itself. */
429
  template <class T,class V, unsigned int N>
403
        template <class T,class V, unsigned int N>
430
    inline T sqr_length(const ArithVec<T,V,N>& v)
404
        inline T sqr_length(const ArithVec<T,V,N>& v)
Line 474... Line 448...
474
      value from two vectors. */
448
         value from two vectors. */
475
  template <class T,class V, unsigned int N>
449
        template <class T,class V, unsigned int N>
476
    inline V v_min(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
450
        inline V v_min(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
477
    {
451
        {
478
      V v;
452
            V v;
479
      std::transform(v0.get(), v0.get() + N, v1.get(), v.get(), std::ptr_fun(s_min<T>));
453
            std::transform(v0.begin(), v0.end(), v1.begin(), v.begin(),
-
 
454
                           [](T a, T b){return std::min(a,b);});
480
      return v;
455
            return v;
481
    }
456
        }
482
 
457
        
483
  /** Returns the vector containing for each coordinate the largest 
458
        /** Returns the vector containing for each coordinate the largest
484
      value from two vectors. */
459
         value from two vectors. */
485
  template <class T,class V, unsigned int N>
460
        template <class T,class V, unsigned int N>
486
    inline V v_max(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
461
        inline V v_max(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
487
    {
462
        {
488
      V v;
463
            V v;
489
      std::transform(v0.get(), v0.get() + N, v1.get(), v.get(), std::ptr_fun(s_max<T>));
464
            std::transform(v0.begin(), v0.end(), v1.begin(), v.begin(),
-
 
465
                           [](T a, T b){return std::max(a,b);});
490
      return v;
466
            return v;
491
    }
467
        }
492
 
468
        
493
 
469
        
494
}
470
}