Subversion Repositories gelsvn

Rev

Rev 632 | Rev 634 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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