Subversion Repositories gelsvn

Rev

Rev 630 | Rev 633 | Go to most recent revision | Show entire file | Ignore 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
 
20
namespace CGLA 
22
namespace CGLA
21
{
23
{
22
 
24
    
23
  /** \brief Template representing generic arithmetic vectors.  
25
    /** \brief Template representing generic arithmetic vectors.
24
 
26
     
25
			The three parameters to the template are
27
     The three parameters to the template are
26
 
28
     
27
      T - the scalar type (i.e. float, int, double etc.)
29
     T - the scalar type (i.e. float, int, double etc.)
28
 
30
     
29
      V - the name of the vector type. This template is always (and
31
     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
32
     only) used as ancestor of concrete types, and the name of the
31
      class _inheriting_ _from_ this class is used as the V argument.
33
     class _inheriting_ _from_ this class is used as the V argument.
32
 
34
     
33
      N - The final argument is the dimension N. For instance, N=3 for a
35
     N - The final argument is the dimension N. For instance, N=3 for a
34
      3D vector.
36
     3D vector.
35
 
37
     
36
      This class template contains all functions that are assumed to be
38
     This class template contains all functions that are assumed to be
37
      the same for any arithmetic vector - regardless of dimension or
39
     the same for any arithmetic vector - regardless of dimension or
38
      the type of scalars used for coordinates.
40
     the type of scalars used for coordinates.
39
 
41
     
40
      The template contains no virtual functions which is important
42
     The template contains no virtual functions which is important
41
      since they add overhead.
43
     since they add overhead.
42
  */
44
     */
43
 
45
    
44
  template <class T, class V, unsigned int N> 
46
    template <class T, class V, unsigned int N>
45
    class ArithVec
47
    class ArithVec
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)
71
        ArithVec(T _a, T _b): data({_a,_b}) {assert(N==2);}
72
	{
-
 
73
	  assert(N==2);
-
 
74
	  data[0] = _a;
-
 
75
	  data[1] = _b;
72
        
76
	}
-
 
77
 
-
 
78
      /// Construct a 3D vector
73
        /// Construct a 2D vector
79
      ArithVec(T _a, T _b, T _c)
74
        ArithVec(T _a, T _b, T _c): data({_a,_b,_c}) {assert(N==3);}
80
	{
-
 
81
	  assert(N==3);
-
 
82
	  data[0] = _a;
-
 
83
	  data[1] = _b;
-
 
84
	  data[2] = _c;
75
        
85
	}
-
 
86
 
-
 
87
      /// Construct a 4D vector
76
        /// Construct a 2D vector
88
      ArithVec(T _a, T _b, T _c, T _d)
77
        ArithVec(T _a, T _b, T _c, T _d): data({_a,_b,_c,_d}) {assert(N==4);}
89
	{
-
 
90
	  assert(N==4);
-
 
91
	  data[0] = _a;
-
 
92
	  data[1] = _b;
-
 
93
	  data[2] = _c;
-
 
94
	  data[3] = _d;
78
        
95
	}
-
 
96
 
-
 
97
 
-
 
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;
102
	
83
        
103
      /// A more meaningful name for vector type
84
        /// A more meaningful name for vector type
104
      typedef V VectorType;
85
        typedef V VectorType;
105
 
86
        
106
      /// Return dimension of vector
87
        /// Return dimension of vector
107
      static unsigned int get_dim() {return N;}
88
        static unsigned int get_dim() {return N;}
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;
94
            data = {_a,_b};
114
	  data[1] = _b;
95
        }
115
	}
96
        
116
 
97
        /// Set all coordinates of a 3D vector.
117
      /// Set all coordinates of a 3D vector.
98
        void set(T _a, T _b, T _c)
118
      void set(T _a, T _b, T _c)
99
        {
119
	{
100
            assert(N==3);
120
	  assert(N==3);
101
            data = {_a,_b,_c};
121
	  data[0] = _a;
102
        }
122
	  data[1] = _b;
103
        
123
	  data[2] = _c;
104
        /// Set all coordinates of a 4D vector.
124
	}
105
        void set(T _a, T _b, T _c, T _d)
125
 
106
        {
126
      /// Set all coordinates of a 4D vector.
107
            assert(N==4);
127
      void set(T _a, T _b, T _c, T _d)
108
            data = {_a,_b,_c,_d};
128
	{
109
        }
129
	  assert(N==4);
110
        
130
	  data[0] = _a;
111
        /// Const index operator
131
	  data[1] = _b;
112
        const T& operator [] ( unsigned int i ) const
132
	  data[2] = _c;
113
        {
133
	  data[3] = _d;
114
            assert(i<N);
134
	}
115
            return data[i];
135
 
116
        }
136
  /// Const index operator
117
        
137
  const T& operator [] ( unsigned int i ) const
118
        /// Non-const index operator
138
	{
119
        T& operator [] ( unsigned int i )
139
	  assert(i<N);
120
        {
140
	  return data[i];
121
            assert(i<N);
141
	}
122
            return data[i];
142
 
123
        }
143
  /// Non-const index operator
124
        
144
  T& operator [] ( unsigned int i ) 
125
        /// Const index operator
145
	{
126
        const T& operator () ( unsigned int i ) const
146
	  assert(i<N);
127
        {
147
	  return data[i];
128
            assert(i<N);
148
	}
129
            return data[i];
149
 
130
        }
150
	/// Const index operator
131
        
151
  const T& operator () ( unsigned int i ) const
132
        /// Non-const index operator
152
	{
133
        T& operator () ( unsigned int i )
153
	  assert(i<N);
134
        {
154
	  return data[i];
135
            assert(i<N);
155
	}
136
            return data[i];
156
 
137
        }
157
  /// Non-const index operator
138
        
158
  T& operator () ( unsigned int i ) 
139
        
159
	{
140
        /** Get a pointer to first element in data array.
160
	  assert(i<N);
141
         This function may be useful when interfacing with some other API
161
	  return data[i];
142
         such as OpenGL (TM) */
162
	}
143
        T* get() {return begin();}
163
 
144
        T* begin() {return data.begin();}
164
 
145
        T* end() {return data.end();}
165
      /** Get a pointer to first element in data array.
146
        
166
	  This function may be useful when interfacing with some other API 
147
        /** Get a const pointer to first element in data array.
167
	  such as OpenGL (TM) */
148
         This function may be useful when interfacing with some other API
168
      T* get() {return &data[0];}
149
         such as OpenGL (TM). */
169
 
150
        const T* get() const {return data.begin();}
170
      /** Get a const pointer to first element in data array.
151
        const T* begin() const {return data.begin();}
171
	  This function may be useful when interfacing with some other API 
152
        const T* end() const {return data.end();}
172
	  such as OpenGL (TM). */
153
        
173
      const T* get() const {return &data[0];}
154
        //----------------------------------------------------------------------
174
 
155
        // Comparison operators
175
      //----------------------------------------------------------------------
156
        //----------------------------------------------------------------------
176
      // Comparison operators
157
        
177
      //----------------------------------------------------------------------
158
        /// Equality operator
178
 
159
        bool operator==(const V& v) const
179
      /// Equality operator
160
        {
180
      bool operator==(const V& v) const 
161
            return std::equal(begin(),end(), v.begin());
181
	{
162
        }
182
	  return std::inner_product(data, &data[N], v.get(), true,
163
        
183
				    std::logical_and<bool>(), std::equal_to<T>());
164
        /// Equality wrt scalar. True if all coords are equal to scalar
184
	}
165
        bool operator==(T k) const
185
 
166
        {
186
#define for_all_i(expr) for(unsigned int i=0;i<N;i++) {expr;}
167
            return std::count(begin(),end(), k)==N;
187
      /// Equality wrt scalar. True if all coords are equal to scalar
168
        }
188
      bool operator==(T k) const 
169
        
189
	{ 
170
        /// Inequality operator
190
	  for_all_i(if (data[i] != k) return false)
171
        bool operator!=(const V& v) const
191
	    return true;
172
        {
192
	}
173
            return !(*this==v);
193
#undef for_all_i  
174
        }
194
 
175
        
195
      /// Inequality operator
176
        /// Inequality wrt scalar. True if any coord not equal to scalar
196
      bool operator!=(const V& v) const 
177
        bool operator!=(T k) const
197
	{
178
        {
198
	  return std::inner_product(data, &data[N], v.get(), false,
179
            return !(*this==k);
199
				    std::logical_or<bool>(), std::not_equal_to<T>());
180
        }
200
	}
181
        
201
 
182
        
202
      /// Inequality wrt scalar. True if any coord not equal to scalar
183
        //----------------------------------------------------------------------
203
      bool operator!=(T k) const 
184
        // Comparison functions ... of geometric significance
204
	{ 
185
        //----------------------------------------------------------------------
205
	  return !(*this==k);
186
        
206
	}
187
        /** Compare all coordinates against other vector. ( < )
207
 
188
         Similar to testing whether we are on one side of three planes. */
208
 
189
        bool  all_l  (const V& v) const
209
      //----------------------------------------------------------------------
190
        {
210
      // Comparison functions ... of geometric significance 
191
            return std::inner_product(begin(), end(), v.begin(), true,
211
      //----------------------------------------------------------------------
192
                                      std::logical_and<bool>(), std::less<T>());
212
 
193
        }
213
      /** Compare all coordinates against other vector. ( < )
194
        
214
	  Similar to testing whether we are on one side of three planes. */
195
        /** Compare all coordinates against other vector. ( <= )
215
      bool  all_l  (const V& v) const
196
         Similar to testing whether we are on one side of three planes. */
216
	{
197
        bool  all_le (const V& v) const
217
	  return std::inner_product(data, &data[N], v.get(), true, 
198
        {
218
				    std::logical_and<bool>(), std::less<T>());
199
            return std::inner_product(begin(), end(), v.begin(), true,
219
	}
200
                                      std::logical_and<bool>(), std::less_equal<T>());
220
 
201
        }
221
      /** Compare all coordinates against other vector. ( <= )
202
        
222
	  Similar to testing whether we are on one side of three planes. */
203
        /** Compare all coordinates against other vector. ( > )
223
      bool  all_le (const V& v) const
204
         Similar to testing whether we are on one side of three planes. */
224
	{
205
        bool  all_g  (const V& v) const
225
	  return std::inner_product(data, &data[N], v.get(), true, 
206
        {
226
				    std::logical_and<bool>(), std::less_equal<T>());
207
            return std::inner_product(begin(), end(), v.begin(), true,
227
	}
208
                                      std::logical_and<bool>(), std::greater<T>());
228
 
209
        }
229
      /** Compare all coordinates against other vector. ( > )
210
        
230
	  Similar to testing whether we are on one side of three planes. */
211
        /** Compare all coordinates against other vector. ( >= )
231
      bool  all_g  (const V& v) const
212
         Similar to testing whether we are on one side of three planes. */
232
	{
213
        bool  all_ge (const V& v) const
233
	  return std::inner_product(data, &data[N], v.get(), true, 
214
        {
234
				    std::logical_and<bool>(), std::greater<T>());
215
            return std::inner_product(begin(), end(), v.begin(), true,
235
	}
216
                                      std::logical_and<bool>(), std::greater_equal<T>());
236
 
217
        }
237
      /** Compare all coordinates against other vector. ( >= )
218
        
238
	  Similar to testing whether we are on one side of three planes. */
219
        
239
      bool  all_ge (const V& v) const
220
        //----------------------------------------------------------------------
240
	{
221
        // Assignment operators
241
	  return std::inner_product(data, &data[N], v.get(), true, 
222
        //----------------------------------------------------------------------
242
				    std::logical_and<bool>(), std::greater_equal<T>());
223
        
243
	}
224
        /// Assignment multiplication with scalar.
244
 
225
        const V& operator *=(T k)
245
 
226
        {
246
      //----------------------------------------------------------------------
227
            std::for_each(begin(), end(), [k](T& x){x*=k;});
247
      // Assignment operators
228
            return static_cast<const V&>(*this);
248
      //----------------------------------------------------------------------
229
        }
249
 
230
        
250
      /// Assignment multiplication with scalar.
231
        /// Assignment division with scalar.
251
      const V& operator *=(T k) 
232
        const V& operator /=(T k)
252
	{ 
233
        {
253
	  std::transform(data, &data[N], data, std::bind2nd(std::multiplies<T>(), k));
234
            std::for_each(begin(), end(), [k](T& x){x/=k;});
254
	  return static_cast<const V&>(*this);
235
            return static_cast<const V&>(*this);
255
	}
236
        }
256
 
237
        
257
      /// Assignment division with scalar.
238
        /// Assignment addition with scalar. Adds scalar to each coordinate.
258
      const V& operator /=(T k)
239
        const V& operator +=(T k)
259
	{ 
240
        {
260
	  std::transform(data, &data[N], data, std::bind2nd(std::divides<T>(), k));
241
            std::for_each(begin(), end(), [k](T& x){x+=k;});
261
	  return static_cast<const V&>(*this);
242
            return  static_cast<const V&>(*this);
262
	}
243
        }
263
 
244
        
264
      /// Assignment addition with scalar. Adds scalar to each coordinate.
245
        /// Assignment subtraction with scalar. Subtracts scalar from each coord.
265
      const V& operator +=(T k) 
246
        const V& operator -=(T k)
266
	{
247
        {
267
	  std::transform(data, &data[N], data, std::bind2nd(std::plus<T>(), k));
248
            std::for_each(begin(), end(), [k](T& x){x-=k;});
268
	  return  static_cast<const V&>(*this);
249
            return  static_cast<const V&>(*this);
269
	}
250
        }
270
 
251
        
271
      /// Assignment subtraction with scalar. Subtracts scalar from each coord.
252
        /** Assignment multiplication with vector.
272
      const V& operator -=(T k) 
253
         Multiply each coord independently. */
273
	{ 
254
        const V& operator *=(const V& v)
274
	  std::transform(data, &data[N], data, std::bind2nd(std::minus<T>(), k));
255
        {
275
	  return  static_cast<const V&>(*this);
256
            std::transform(begin(), end(), v.begin(), begin(), std::multiplies<T>());
276
	}
257
            return  static_cast<const V&>(*this);
277
 
258
        }
278
      /** Assignment multiplication with vector. 
259
        
279
	  Multiply each coord independently. */
260
        /// Assigment division with vector. Each coord divided independently.
280
      const V& operator *=(const V& v) 
261
        const V& operator /=(const V& v)
281
	{ 
262
        {
282
	  std::transform(data, &data[N], v.get(), data, std::multiplies<T>());
263
            std::transform(begin(), end(),  v.begin(), begin(), std::divides<T>());
283
	  return  static_cast<const V&>(*this);
264
            return  static_cast<const V&>(*this);
284
	}
265
        }
285
 
266
        
286
      /// Assigment division with vector. Each coord divided independently.
267
        /// Assignmment addition with vector.
287
      const V& operator /=(const V& v)
268
        const V& operator +=(const V& v)
288
	{
269
        {
289
	  std::transform(data, &data[N], v.get(), data, std::divides<T>());
270
            std::transform(begin(), end(), v.begin(), begin(), std::plus<T>());
290
	  return  static_cast<const V&>(*this);
271
            return  static_cast<const V&>(*this);
291
	}
272
        }
292
 
-
 
293
      /// Assignmment addition with vector.
-
 
294
      const V& operator +=(const V& v) 
-
 
295
	{
-
 
296
	  std::transform(data, &data[N], v.get(), data, std::plus<T>());
-
 
297
	  return  static_cast<const V&>(*this);
-
 
298
	}
-
 
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
        //----------------------------------------------------------------------
309
      // Unary operators on vectors
283
        // Unary operators on vectors
310
      //----------------------------------------------------------------------
284
        //----------------------------------------------------------------------
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
322
      //----------------------------------------------------------------------
296
        //----------------------------------------------------------------------
323
 
297
        
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
359
      //----------------------------------------------------------------------
333
        //----------------------------------------------------------------------
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.
403
    template <class T,class V, unsigned int N>
377
        template <class T,class V, unsigned int N>
404
    inline std::istream& operator>>(std::istream&is, ArithVec<T,V,N>& v)
378
        inline std::istream& operator>>(std::istream&is, ArithVec<T,V,N>& v)
405
    {
379
        {
406
        is >> std::ws;
380
            is >> std::ws;
407
        if (is.peek() == '[')
381
            if (is.peek() == '[')
408
            is.ignore();
382
                is.ignore();
409
        is >> std::ws;
383
            is >> std::ws;
410
        for (int c=0; c<N; ++c)
384
            for (int c=0; c<N; ++c)
411
        {
385
            {
412
            is >> v(c) >> std::ws;
386
                is >> v(c) >> std::ws;
413
        }
387
            }
414
        if (is.peek() == ']')
388
            if (is.peek() == ']')
415
            is.ignore();
389
                is.ignore();
416
        return is;
390
            return is;
417
    }
391
        }
418
 
392
        
419
 
393
        
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)
431
    {
405
        {
432
      return dot(v,v);
406
            return dot(v,v);
433
    }
407
        }
434
 
408
        
435
  /** Multiply double onto vector. This operator handles the case 
409
        /** Multiply double onto vector. This operator handles the case
436
      where the vector is on the righ side of the `*'.
410
         where the vector is on the righ side of the `*'.
437
	 
411
         
438
      \note It seems to be optimal to put the binary operators inside the
412
         \note It seems to be optimal to put the binary operators inside the
439
      ArithVec class template, but the operator functions whose 
413
         ArithVec class template, but the operator functions whose
440
      left operand is _not_ a vector cannot be inside, hence they
414
         left operand is _not_ a vector cannot be inside, hence they
441
      are here.
415
         are here.
442
      We need three operators for scalar * vector although they are
416
         We need three operators for scalar * vector although they are
443
      identical, because, if we use a separate template argument for
417
         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 
418
         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
419
         type for the left operand hoping that other built-in types will
446
      be automatically converted, we will be disappointed. It seems that 
420
         be automatically converted, we will be disappointed. It seems that
447
      a float * ArithVec<float,Vec3f,3> function is not found if the
421
         a float * ArithVec<float,Vec3f,3> function is not found if the
448
      left operand is really a double.
422
         left operand is really a double.
449
  */
423
         */
450
 
424
        
451
  template<class T, class V, unsigned int N>
425
        template<class T, class V, unsigned int N>
452
    inline const V operator * (double k, const ArithVec<T,V,N>& v) 
426
        inline const V operator * (double k, const ArithVec<T,V,N>& v)
453
    {
427
        {
454
      return v * k;
428
            return v * k;
455
    }
429
        }
456
 
430
        
457
  /** Multiply float onto vector. See the note in the documentation
431
        /** Multiply float onto vector. See the note in the documentation
458
      regarding multiplication of a double onto a vector. */
432
         regarding multiplication of a double onto a vector. */
459
  template<class T, class V, unsigned int N>
433
        template<class T, class V, unsigned int N>
460
    inline const V operator * (float k, const ArithVec<T,V,N>& v) 
434
        inline const V operator * (float k, const ArithVec<T,V,N>& v)
461
    {
435
        {
462
      return v * k;
436
            return v * k;
463
    }
437
        }
464
 
438
        
465
  /** Multiply unsigned int onto vector. See the note in the documentation
439
        /** Multiply unsigned int onto vector. See the note in the documentation
466
      regarding multiplication of a double onto a vector. */
440
         regarding multiplication of a double onto a vector. */
467
  template<class T, class V, unsigned int N>
441
        template<class T, class V, unsigned int N>
468
    inline const V operator * (int k, const ArithVec<T,V,N>& v) 
442
        inline const V operator * (int k, const ArithVec<T,V,N>& v)
469
    {
443
        {
470
      return v * k;
444
            return v * k;
471
    }
445
        }
472
 
446
        
473
  /** Returns the vector containing for each coordinate the smallest
447
        /** Returns the vector containing for each coordinate the smallest
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
}
495
 
471
        
496
#endif
472
#endif