GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/vecg.h
Date: 2026-09-07 02:36:43
Exec Total Coverage
Lines: 216 305 70.8%
Functions: 84 161 52.2%
Branches: 35 190 18.4%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #ifndef GEOGRAM_BASIC_VECG
41 #define GEOGRAM_BASIC_VECG
42
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/numeric.h>
45 #include <geogram/basic/determinant.h>
46 #include <geogram/basic/memory.h>
47 #include <geogram/basic/assert.h>
48 #include <initializer_list>
49
50 #include <iostream>
51 #include <cfloat>
52 #include <cmath>
53
54 #ifndef GOMGEN
55 #include <type_traits>
56 #endif
57
58 /**
59 * \file geogram/basic/vecg.h
60 * \brief Generic implementation of geometric vectors
61 */
62
63 namespace GEO {
64
65 /**
66 * \brief Generic maths vector
67 * \details Vecng implements a maths vector of dimension \p DIM containing
68 * coordinates of type \p T and provides operations for manipulating it.
69 * Type \p T is expected to be a numeric type.
70 * \tparam DIM dimension of the vector
71 * \tparam T type of the vector coordinates.
72 */
73 template <index_t DIM, class T>
74 class vecng {
75 public:
76 /** \brief The dimension of the vector */
77 static constexpr index_t dim = DIM;
78
79 /** \brief This vector type */
80 typedef vecng<DIM, T> vector_type;
81
82 /** \brief The type of the vector coordinates */
83 typedef T value_type;
84
85 /**
86 * \brief Default vector constructor
87 * \details All coordinates are initialized to 0 (zero).
88 */
89 124800 vecng() {
90
2/2
✓ Branch 0 taken 376800 times.
✓ Branch 1 taken 62400 times.
878400 for(index_t i = 0; i < DIM; i++) {
91 753600 data_[i] = T(0);
92 }
93 124800 }
94
95 // This one should never be called :
96 // a template constructor cannot be a copy constructor
97
98 /**
99 * \brief Constructs a vector by copy
100 * \details This copies coordinates of vector \p v to this vector.
101 * The type \p T2 of the coordinates in \p v must be convertible to
102 * the type \p T of this vector.
103 * \param[in] v an vector of same dimension with coordinates of type
104 * \p T2
105 * \tparam T2 the type of coordinates in vector \p v
106 */
107 template <class T2>
108 explicit vecng(const vecng<DIM, T2>& v) {
109 for(index_t i = 0; i < DIM; i++) {
110 data_[i] = T(v[i]);
111 }
112 }
113
114 // to avoid compilation problems
115 template <class T2, index_t DIM2>
116 explicit vecng(
117 const vecng<DIM2, T2>& v
118 ) {
119 geo_debug_assert(DIM2 == DIM);
120 for(index_t i = 0; i < DIM; i++) {
121 data_[i] = T(v[i]);
122 }
123 }
124
125 /**
126 * \brief Constructs a vector from an array
127 * \details This copies coordinates the first \p DIM coordinates of
128 * array \p v to this vector. The type \p T2 of the coordinates in
129 * \p v must be convertible to the type \p T of this vector.
130 * \param[in] v an array of values of type \p T2
131 * \tparam T2 the type of coordinates in vector \p v
132 */
133 template <class T2>
134 explicit vecng(const T2* v) {
135 for(index_t i = 0; i < DIM; i++) {
136 data_[i] = T(v[i]);
137 }
138 }
139
140 /**
141 * \brief Constructs a vector from an initializer list.
142 * \param[in] Vi the initializer list, should contain DIM elements.
143 */
144 vecng(const std::initializer_list<T>& Vi) {
145 index_t i = 0;
146 for(auto& it: Vi) {
147 geo_debug_assert(i < DIM);
148 data()[i] = it;
149 ++i;
150 }
151 }
152
153 /**
154 * \brief Gets the vector dimension
155 * \return the value of \p DIM
156 */
157 index_t dimension() const {
158 return DIM;
159 }
160
161 /**
162 * \brief Gets modifiable vector data
163 * \return a pointer to the first element of the vector
164 */
165 1002000 T* data() {
166 1002000 return data_;
167 }
168
169 /**
170 * \brief Gets non-modifiable vector data
171 * \return a const pointer to the first element of the vector
172 */
173 753600 const T* data() const {
174 753600 return data_;
175 }
176
177 /**
178 * \brief Gets a modifiable vector coordinate
179 * \param[in] i index of the coordinate
180 * \return a reference to coordinate at index \p i
181 */
182 1002000 inline T& operator[] (index_t i) {
183
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 501000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1002000 geo_debug_assert(i < DIM);
184 1002000 return data()[i];
185 }
186
187 /**
188 * \brief Gets a non-modifiable vector coordinate
189 * \param[in] i index of the coordinate
190 * \return a const reference to coordinate at index \p i
191 */
192 753600 inline const T& operator[] (index_t i) const {
193
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 376800 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
753600 geo_debug_assert(i < DIM);
194 753600 return data()[i];
195 }
196
197 /**
198 * \brief Gets the squared length of the vector
199 */
200 inline T length2() const {
201 T result = T(0);
202 for(index_t i = 0; i < DIM; i++) {
203 result += data_[i] * data_[i];
204 }
205 return result;
206 }
207
208 /**
209 * \brief Gets the length of the vector
210 */
211 inline T length() const {
212 return sqrt(length2());
213 }
214
215 /**
216 * \brief Gets the squared distance to a vector
217 * \param[in] v another vector
218 * \return (\p v - \p this).length2()
219 */
220 106512 inline T distance2(const vector_type& v) const {
221 106512 T result(0);
222
2/2
✓ Branch 0 taken 328752 times.
✓ Branch 1 taken 53256 times.
764016 for(index_t i = 0; i < DIM; i++) {
223 657504 result += geo_sqr(v.data_[i] - data_[i]);
224 }
225 106512 return result;
226 }
227
228 /**
229 * \brief Gets the distance to a vector
230 * \param[in] v another vector
231 * \return (\p v - \p this).length()
232 */
233 106512 inline T distance(const vector_type& v) const {
234 106512 return sqrt(distance2(v));
235 }
236
237 // operators
238
239 /**
240 * \brief Adds a vector in place
241 * \details Adds coordinates of vector \p v to this vector
242 * coordinates
243 * \param[in] v another vector
244 * \return a reference to this vector
245 */
246 inline vector_type& operator+= (const vector_type& v) {
247 for(index_t i = 0; i < DIM; i++) {
248 data_[i] += v.data_[i];
249 }
250 return *this;
251 }
252
253 /**
254 * \brief Subtracts a vector in place
255 * \details Subtracts coordinates of vector \p v from this vector
256 * coordinates
257 * \param[in] v another vector
258 * \return a reference to this vector
259 */
260 inline vector_type& operator-= (const vector_type& v) {
261 for(index_t i = 0; i < DIM; i++) {
262 data_[i] -= v.data_[i];
263 }
264 return *this;
265 }
266
267 /**
268 * \brief Multiplies by a scalar in place
269 * \details Multiplies this vector coordinates by value \p s. The type
270 * \p T2 of \p s must be convertible to the type \p T of this vector
271 * coordinates.
272 * \param[in] s a value of type \p T2
273 * \tparam T2 the type of value \p s
274 * \return a reference to this vector
275 */
276 template <class T2>
277 inline vector_type& operator*= (T2 s) {
278 for(index_t i = 0; i < DIM; i++) {
279 data_[i] *= T(s);
280 }
281 return *this;
282 }
283
284 /**
285 * \brief Divides by a scalar in place
286 * \details Divides this vector coordinates by value \p s. The type
287 * \p T2 of \p s must be convertible to the type \p T of this vector
288 * coordinates.
289 * \param[in] s a value of type \p T2
290 * \tparam T2 the type of value \p s
291 * \return a reference to this vector
292 */
293 template <class T2>
294 inline vector_type& operator/= (T2 s) {
295 for(index_t i = 0; i < DIM; i++) {
296 data_[i] /= T(s);
297 }
298 return *this;
299 }
300
301 /**
302 * \brief Adds 2 vectors
303 * \details Builds a vector by adding coordinates of this vector and
304 * coordinates of vector \p v.
305 * \param[in] v another vector
306 * \return the result vector (\p this + \p v)
307 */
308 83600 inline vector_type operator+ (const vector_type& v) const {
309 83600 vector_type result(*this);
310
2/2
✓ Branch 0 taken 252600 times.
✓ Branch 1 taken 41800 times.
588800 for(index_t i = 0; i < DIM; i++) {
311 505200 result.data_[i] += v.data_[i];
312 }
313 83600 return result;
314 }
315
316 /**
317 * \brief Subtracts 2 vectors
318 * \details Builds a vector by subtracting coordinates of vector \p v
319 * to coordinates of this vector.
320 * \param[in] v another vector
321 * \return the result vector (\p this - \p v)
322 */
323 inline vector_type operator- (const vector_type& v) const {
324 vector_type result(*this);
325 for(index_t i = 0; i < DIM; i++) {
326 result.data_[i] -= v.data_[i];
327 }
328 return result;
329 }
330
331
332 /**
333 * \brief Divides a vector by a scalar
334 * \details Builds a vector by dividing this vector coordinates by
335 * value \p s. The type \p T2 of \p s must be convertible to the type
336 * \p T of this vector coordinates.
337 * \param[in] s a value of type \p T2
338 * \tparam T2 the type of value \p s
339 * \return the result vector (\p this / \p s)
340 */
341 template <class T2>
342 inline vector_type operator/ (T2 s) const {
343 vector_type result(*this);
344 for(index_t i = 0; i < DIM; i++) {
345 result.data_[i] /= T(s);
346 }
347 return result;
348 }
349
350 /**
351 * \brief Negates a vector
352 * \details Builds a vector by negating coordinates of this vector.
353 * \return the result vector (-\p this)
354 */
355 inline vector_type operator- () const {
356 vector_type result;
357 for(index_t i = 0; i < DIM; i++) {
358 result.data_[i] = -data_[i];
359 }
360 return result;
361 }
362
363 private:
364 T data_[DIM];
365 };
366
367 /**
368 * \brief Computes the dot product of 2 vectors
369 * \param[in] v1 the first vector
370 * \param[in] v2 the second vector
371 * \return the dot product (\p v1 . \p v2)
372 * \relates vecng
373 */
374 template <index_t DIM, class T>
375 inline T dot(
376 const vecng<DIM, T>& v1, const vecng<DIM, T>& v2
377 ) {
378 T result = 0;
379 for(index_t i = 0; i < DIM; i++) {
380 result += v1[i] * v2[i];
381 }
382 return result;
383 }
384
385 #ifndef GOMGEN
386 /**
387 * \brief Multiplies a scalar by a vector
388 * \details Builds a vector by multipying this vector coordinates by
389 * value \p s. The type \p T2 of \p s must be convertible to the type \p
390 * T of this vector coordinates.
391 * \param[in] s a value of type \p T2
392 * \param[in] v the vector to multiply
393 * \tparam T2 the type of value \p s
394 * \return the result vector (\p s * \p v)
395 * \relates vecng
396 */
397 template <
398 class T2, index_t DIM, class T,
399 typename = std::enable_if_t<is_scalar<T2>::value>
400 124800 > inline vecng<DIM, T> operator* (
401 T2 s, const vecng<DIM, T>& v
402 ) {
403 124800 vecng<DIM, T> result;
404
2/2
✓ Branch 0 taken 376800 times.
✓ Branch 1 taken 62400 times.
878400 for(index_t i = 0; i < DIM; i++) {
405 753600 result[i] = T(s) * v[i];
406 }
407 124800 return result;
408 }
409
410
411 /**
412 * \brief Multiplies a scalar by a vector
413 * \details Builds a vector by multipying this vector coordinates by
414 * value \p s. The type \p T2 of \p s must be convertible to the type \p
415 * T of this vector coordinates.
416 * \param[in] v the vector to multiply
417 * \param[in] s a value of type \p T2
418 * \tparam T2 the type of value \p s
419 * \return the result vector (\p s * \p v)
420 * \relates vecng
421 */
422 template <
423 class T2, index_t DIM, class T,
424 typename = std::enable_if_t<is_scalar<T2>::value>
425 > inline vecng<DIM, T> operator* (
426 const vecng<DIM, T>& v, T2 s
427 ) {
428 vecng<DIM, T> result;
429 for(index_t i = 0; i < DIM; i++) {
430 result[i] = T(s) * v[i];
431 }
432 return result;
433 }
434 #endif
435
436 // Compatibility with GLSL
437
438 /**
439 * \brief Gets the norm of a vector
440 * \param[in] v a vector
441 * \return the norm of vector \p v
442 * \see vecng::length()
443 * \relates vecng
444 */
445 template <index_t DIM, class T>
446 924404 inline T length(const vecng<DIM, T>& v) {
447 924404 return v.length();
448 }
449
450 /**
451 * \brief Gets the square norm of a vector
452 * \param[in] v a vector
453 * \return the square norm of vector \p v
454 * \see vecng::length2()
455 * \relates vecng
456 */
457 template <index_t DIM, class T>
458 6744002 inline T length2(const vecng<DIM, T>& v) {
459 6744002 return v.length2();
460 }
461
462 /**
463 * \brief Gets the square distance between 2 vectors
464 * \param[in] v1 the first vector
465 * \param[in] v2 the second vector
466 * \return the square distance between \p v1 and \p v2.
467 * \see vecng::distance2()
468 * \relates vecng
469 */
470 template <index_t DIM, class T>
471 10839796 inline T distance2(
472 const vecng<DIM, T>& v1, const vecng<DIM, T>& v2
473 ) {
474 10839796 return v2.distance2(v1);
475 }
476
477 /**
478 * \brief Gets the distance between 2 vectors
479 * \param[in] v1 the first vector
480 * \param[in] v2 the second vector
481 * \return the distance between \p v1 and \p v2.
482 * \see vecng::distance()
483 * \relates vecng
484 */
485 template <index_t DIM, class T>
486 115728 inline T distance(
487 const vecng<DIM, T>& v1, const vecng<DIM, T>& v2
488 ) {
489 115728 return v2.distance(v1);
490 }
491
492 /**
493 * \brief Normalizes a vector
494 * \details Returns a normalized vector constructed by dividing
495 * coordinates of vector \p v by it norm. If the norm is 0, then the
496 * result is undefined.
497 * \param[in] v a vector
498 * \return the normalized vector
499 * \relates vecng
500 */
501 template <index_t DIM, class T> GEO_NODISCARD
502 815068 inline vecng<DIM, T> normalize(
503 const vecng<DIM, T>& v
504 ) {
505 815068 T s = length(v);
506
1/2
✓ Branch 0 taken 815068 times.
✗ Branch 1 not taken.
815068 if(s > 1e-30) {
507 815068 s = T(1) / s;
508 }
509 815068 return s * v;
510 }
511
512 /**
513 * \brief Computes a weighted barycenter
514 * \details Computes the barycenter of \p v1 and \p v2 weighted by value
515 * 1 - \p s and \p s.
516 * \param[in] v1 the first vector
517 * \param[in] v2 the second vector
518 * \param[in] s the weight value
519 * \return the barycenter (1 - \p s) * \p v1 + \p s * \p v2
520 * \relates vecng
521 */
522 template <index_t DIM, class T>
523 inline vecng<DIM, T> mix(
524 const vecng<DIM, T>& v1, const vecng<DIM, T>& v2, T s
525 ) {
526 return (T(1) - s) * v1 + s * v2;
527 }
528
529 /************************************************************************/
530
531 /**
532 * \brief Specialization of class vecng for DIM == 2
533 * \see vecng
534 */
535 template <class T>
536 class vecng<2, T> {
537 public:
538 /** \copydoc vecng::dim */
539 static constexpr index_t dim = 2;
540
541 /** \copydoc vecng::vector_type */
542 typedef vecng<dim, T> vector_type;
543
544 /** \copydoc vecng::value_type */
545 typedef T value_type;
546
547 /** \copydoc vecng::vecng() */
548 vecng() :
549 x(0),
550 y(0) {
551 }
552
553 /**
554 * \brief Constructs a vector from coordinates
555 * \param[in] x_in , y_in references to vector coordinates
556 */
557 1095849 vecng(const T& x_in, const T& y_in) :
558 1095849 x(x_in),
559 1095849 y(y_in) {
560 1095849 }
561
562 /**
563 * \brief Constructs a vector from coordinates
564 * \param[in] x_in , y_in vector coordinates as rvalue references
565 */
566 1138862 vecng(T&& x_in, T&& y_in) :
567 1138862 x(x_in),
568
1/2
✓ Branch 1 taken 465777 times.
✗ Branch 2 not taken.
1138862 y(y_in) {
569 1138862 }
570
571 vecng(const vecng<2,T>& rhs) = default;
572 vecng(vecng<2,T>&& rhs) = default;
573
574 /** \copydoc vecng::vecng(const vecng<DIM, T2>&) */
575 template <class T2>
576 explicit vecng(const vecng<dim, T2>& v) :
577 x(v.x),
578 y(v.y) {
579 }
580
581 /** \copydoc vecng::vecng(const T2*) */
582 template <class T2>
583 222814 explicit vecng(const T2* v) :
584 222814 x(v[0]),
585 222814 y(v[1]) {
586 222814 }
587
588 /** \copydoc vecng::vecng(const std::initializer_list<T>) */
589 231 vecng(const std::initializer_list<T>& Vi) {
590 231 index_t i = 0;
591
2/2
✓ Branch 2 taken 462 times.
✓ Branch 3 taken 231 times.
693 for(auto& it: Vi) {
592
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
462 geo_debug_assert(i < dim);
593 462 data()[i] = it;
594 462 ++i;
595 }
596 231 }
597
598 vecng<2,T>& operator=(const vecng<2,T>& rhs) = default;
599 vecng<2,T>& operator=(vecng<2,T>&& rhs) = default;
600
601 /** \copydoc vecng::length2() const */
602 278 inline T length2() const {
603 278 return x * x + y * y;
604 }
605
606 /** \copydoc vecng::length() const */
607 inline T length() const {
608 return sqrt(x * x + y * y);
609 }
610
611 /** \copydoc vecng::distance2(const vector_type&) const */
612 inline T distance2(const vector_type& v) const {
613 T dx = v.x - x;
614 T dy = v.y - y;
615 return dx * dx + dy * dy;
616 }
617
618 /** \copydoc vecng::distance(const vector_type&) const */
619 inline T distance(const vector_type& v) const {
620 return sqrt(distance2(v));
621 }
622
623 /** \copydoc vecng::operator+=(const vector_type&) */
624 inline vector_type& operator+= (const vector_type& v) {
625 x += v.x;
626 y += v.y;
627 return *this;
628 }
629
630 /** \copydoc vecng::operator-=(const vector_type&) */
631 inline vector_type& operator-= (const vector_type& v) {
632 x -= v.x;
633 y -= v.y;
634 return *this;
635 }
636
637 /** \copydoc vecng::operator*=(T2) */
638 template <class T2>
639 inline vector_type& operator*= (T2 s) {
640 x *= T(s);
641 y *= T(s);
642 return *this;
643 }
644
645 /** \copydoc vecng::operator/=(T2) */
646 template <class T2>
647 inline vector_type& operator/= (T2 s) {
648 x /= T(s);
649 y /= T(s);
650 return *this;
651 }
652
653 /** \copydoc vecng::operator+(const vector_type&) const */
654 6385 inline vector_type operator+ (const vector_type& v) const {
655 6385 return vector_type(x + v.x, y + v.y);
656 }
657
658 /** \copydoc vecng::operator-(const vector_type&) const */
659 643 inline vector_type operator- (const vector_type& v) const {
660 643 return vector_type(x - v.x, y - v.y);
661 }
662
663 /** \copydoc vecng::operator/(T2) const */
664 template <class T2>
665 inline vector_type operator/ (T2 s) const {
666 return vector_type(x / T(s), y / T(s));
667 }
668
669 /** \copydoc vecng::operator-() const */
670 inline vector_type operator- () const {
671 return vector_type(-x, -y);
672 }
673
674 /** \copydoc vecng::dimension() const */
675 index_t dimension() const {
676 return dim;
677 }
678
679 /** \copydoc vecng::data() */
680 462 T* data() {
681 462 return &x;
682 }
683
684 /** \copydoc vecng::data() const */
685 31427240 const T* data() const {
686 31427240 return &x;
687 }
688
689 /** \copydoc vecng::operator[](index_t) */
690 inline T& operator[] (index_t i) {
691 geo_debug_assert(i < dim);
692 return data()[i];
693 }
694
695 /** \copydoc vecng::operator[](index_t) const */
696 inline const T& operator[] (index_t i) const {
697 geo_debug_assert(i < dim);
698 return data()[i];
699 }
700
701 /** \brief Optimizes coordinate representation */
702 void optimize() {
703 Numeric::optimize_number_representation(x);
704 Numeric::optimize_number_representation(y);
705 }
706
707 /** \brief Vector x coordinate */
708 T x;
709 /** \brief Vector y coordinate */
710 T y;
711 };
712
713 /**
714 * \copydoc vecng::dot(const vecng<DIM,T>&,const vecng<DIM,T>&)
715 * \relates vecng
716 */
717 template <class T>
718 inline T dot(
719 const vecng<2, T>& v1, const vecng<2, T>& v2
720 ) {
721 return v1.x * v2.x + v1.y * v2.y;
722 }
723
724 /**
725 * \brief Computes the determinant of 2 vectors
726 * \param[in] v1 the first vector
727 * \param[in] v2 the second vector
728 * \return the value of the determinant
729 * \relates vecng
730 */
731 template <class T>
732 336 inline T det(
733 const vecng<2, T>& v1, const vecng<2, T>& v2
734 ) {
735 336 return v1.x * v2.y - v1.y * v2.x;
736 }
737
738 #ifndef GOMGEN
739 /**
740 * \copydoc vecng::operator*(T2,const vecng<DIM,T>&)
741 * \relates vecng
742 */
743 template <
744 class T2, class T,
745 typename = std::enable_if_t<is_scalar<T2>::value>
746 13104 > inline vecng<2, T> operator* (
747 T2 s, const vecng<2, T>& v
748 ) {
749 13104 return vecng<2, T>(T(s) * v.x, T(s) * v.y);
750 }
751
752 /**
753 * \copydoc vecng::operator*(const vecng<DIM,T>&, T2)
754 * \relates vecng
755 */
756 template <
757 class T2, class T,
758 typename = std::enable_if_t<is_scalar<T2>::value>
759 > inline vecng<2, T> operator* (
760 const vecng<2, T>& v, T2 s
761 ) {
762 return vecng<2, T>(T(s) * v.x, T(s) * v.y);
763 }
764 #endif
765
766 /************************************************************************/
767
768 /**
769 * \brief Specialization of class vecng for DIM == 3
770 * \see vecng
771 */
772 template <class T>
773 class vecng<3, T> {
774 public:
775 /** \copydoc vecng::dim */
776 static constexpr index_t dim = 3;
777
778 /** \copydoc vecng::vector_type */
779 typedef vecng<dim, T> vector_type;
780
781 /** \copydoc vecng::value_type */
782 typedef T value_type;
783
784 /** \copydoc vecng::vecng() */
785 13030002 vecng() :
786 13030002 x(T(0.0)),
787
1/2
✓ Branch 1 taken 189 times.
✗ Branch 2 not taken.
13030002 y(T(0.0)),
788
1/2
✓ Branch 1 taken 189 times.
✗ Branch 2 not taken.
13030002 z(T(0.0)) {
789 13030002 }
790
791 /**
792 * \brief Constructs a vector from coordinates
793 * \param[in] x_in , y_in , z_in references to vector coordinates
794 */
795 742949 vecng(const T& x_in, const T& y_in, const T& z_in) :
796 742949 x(x_in),
797
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
742949 y(y_in),
798
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
742949 z(z_in) {
799 742949 }
800
801 /**
802 * \brief Constructs a vector from coordinates
803 * \param[in] x_in , y_in , z_in vector coordinates as rvalues
804 */
805 248905287 vecng(T&& x_in, T&& y_in, T&& z_in) :
806 248905287 x(x_in),
807
1/2
✓ Branch 1 taken 1533671 times.
✗ Branch 2 not taken.
248905287 y(y_in),
808
1/2
✓ Branch 1 taken 1533671 times.
✗ Branch 2 not taken.
248905287 z(z_in) {
809 248905287 }
810
811 vecng(const vecng<3,T>& rhs) = default;
812 32035 vecng(vecng<3,T>&& rhs) = default;
813
814 /** \copydoc vecng::vecng(const vecng<DIM, T2>&) */
815 template <class T2>
816 2190030 explicit vecng(const vecng<dim, T2>& v) :
817 2190030 x(v.x),
818
1/2
✓ Branch 1 taken 17052 times.
✗ Branch 2 not taken.
2190030 y(v.y),
819
1/2
✓ Branch 1 taken 17052 times.
✗ Branch 2 not taken.
2190030 z(v.z) {
820 2190030 }
821
822 /** \copydoc vecng::vecng(const T2*) */
823 template <class T2>
824 1569299 explicit vecng(const T2* v) :
825 1569299 x(v[0]),
826 1569299 y(v[1]),
827 1569299 z(v[2]) {
828 1569299 }
829
830 /** \copydoc vecng::vecng(const std::initializer_list<T>) */
831 130 vecng(const std::initializer_list<T>& Vi) {
832 130 index_t i = 0;
833
2/2
✓ Branch 2 taken 390 times.
✓ Branch 3 taken 130 times.
520 for(auto& it: Vi) {
834
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 390 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
390 geo_debug_assert(i < dim);
835 390 data()[i] = it;
836 390 ++i;
837 }
838 130 }
839
840 vecng<3,T>& operator=(const vecng<3,T>& rhs) = default;
841 3820 vecng<3,T>& operator=(vecng<3,T>&& rhs) = default;
842
843 /**
844 * \brief Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification)
845 */
846 template<typename A, typename B>
847 vecng(const vecng<2, A>& _xy, B _z);
848 /**
849 * \brief Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification)
850 */
851 template<typename A, typename B>
852 vecng(const vecng<2, A>& _xy, const vecng<1, B>& _z);
853 /**
854 * \brief Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification)
855 */
856 template<typename A, typename B>
857 vecng(A _x, const vecng<2, B>& _yz);
858 /**
859 * \brief Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification)
860 */
861 template<typename A, typename B>
862 vecng(const vecng<1, A>& _x, const vecng<2, B>& _yz);
863 /**
864 * \brief Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification)
865 */
866 template<typename U>
867 explicit vecng(vecng<4, U> const& v);
868
869
870 /** \copydoc vecng::length2() const */
871 6743724 inline T length2() const {
872
0/10
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
6743724 return x * x + y * y + z * z;
873 }
874
875 /** \copydoc vecng::length() const */
876 924404 inline T length() const {
877 924404 return sqrt(x * x + y * y + z * z);
878 }
879
880 /** \copydoc vecng::distance2(const vector_type&) const */
881 10839796 inline T distance2(const vector_type& v) const {
882 10839796 T dx = v.x - x;
883 10839796 T dy = v.y - y;
884 10839796 T dz = v.z - z;
885 10839796 return dx * dx + dy * dy + dz * dz;
886 }
887
888 /** \copydoc vecng::distance(const vector_type&) const */
889 inline T distance(const vector_type& v) const {
890 return sqrt(distance2(v));
891 }
892
893 /** \copydoc vecng::operator+=(const vector_type&) */
894 933524 inline vector_type& operator+= (const vector_type& v) {
895 933524 x += v.x;
896 933524 y += v.y;
897 933524 z += v.z;
898 933524 return *this;
899 }
900
901 /** \copydoc vecng::operator-=(const vector_type&) */
902 95392 inline vector_type& operator-= (const vector_type& v) {
903 95392 x -= v.x;
904 95392 y -= v.y;
905 95392 z -= v.z;
906 95392 return *this;
907 }
908
909 /** \copydoc vecng::operator*=(T2) */
910 template <class T2>
911 inline vector_type& operator*= (T2 s) {
912 x *= T(s);
913 y *= T(s);
914 z *= T(s);
915 return *this;
916 }
917
918 /** \copydoc vecng::operator/=(T2) */
919 template <class T2>
920 36 inline vector_type& operator/= (T2 s) {
921 36 x /= T(s);
922 36 y /= T(s);
923 36 z /= T(s);
924 36 return *this;
925 }
926
927 /** \copydoc vecng::operator+(const vector_type&) const */
928 6020472 inline vector_type operator+ (const vector_type& v) const {
929 6020472 return vector_type(x + v.x, y + v.y, z + v.z);
930 }
931
932 /** \copydoc vecng::operator-(const vector_type&) const */
933 13691407 inline vector_type operator- (const vector_type& v) const {
934
3/6
✓ Branch 1 taken 1448652 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1448652 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1448652 times.
✗ Branch 8 not taken.
13691407 return vector_type(x - v.x, y - v.y, z - v.z);
935 }
936
937 /** \copydoc vecng::operator/(T2) const */
938 template <class T2>
939 inline vector_type operator/ (T2 s) const {
940 return vector_type(x / T(s), y / T(s), z / T(s));
941 }
942
943 /** \copydoc vecng::operator-() const */
944 89998 inline vector_type operator- () const {
945 89998 return vector_type(-x, -y, -z);
946 }
947
948 /** \copydoc vecng::dimension() const */
949 3606882 index_t dimension() const {
950 3606882 return dim;
951 }
952
953 /** \copydoc vecng::data() */
954 4874326 T* data() {
955 4874326 return &x;
956 }
957
958 /** \copydoc vecng::data() const */
959 551548508 const T* data() const {
960 551548508 return &x;
961 }
962
963 /** \copydoc vecng::operator[](index_t) */
964 4848897 inline T& operator[] (index_t i) {
965
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4848897 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4848897 geo_debug_assert(i < dim);
966 4848897 return data()[i];
967 }
968
969 /** \copydoc vecng::operator[](index_t) const */
970 466227776 inline const T& operator[] (index_t i) const {
971
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 466227776 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
466227776 geo_debug_assert(i < dim);
972 466227776 return data()[i];
973 }
974
975 /** \brief Optimizes coordinate representation */
976 32035 void optimize() {
977 32035 Numeric::optimize_number_representation(x);
978 32035 Numeric::optimize_number_representation(y);
979 32035 Numeric::optimize_number_representation(z);
980 32035 }
981
982 /** \brief Vector x coordinate */
983 T x;
984 /** \brief Vector y coordinate */
985 T y;
986 /** \brief Vector z coordinate */
987 T z;
988 };
989
990 /**
991 * \copydoc vecng::dot(const vecng<DIM,T>&, const vecng<DIM,T>&)\
992 * \relates vecng
993 */
994 template <class T>
995 23650680 inline T dot(
996 const vecng<3, T>& v1, const vecng<3, T>& v2
997 ) {
998 23650680 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
999 }
1000
1001 /**
1002 * \brief Computes the cross product of 2 vectors
1003 * \param[in] v1 the first vector
1004 * \param[in] v2 the second vector
1005 * \return the cross product (\p v1 x \p v2)
1006 * \relates vecng
1007 */
1008 template <class T>
1009 5337729 inline vecng<3, T> cross(
1010 const vecng<3, T>& v1, const vecng<3, T>& v2
1011 ) {
1012 return vecng<3, T>(
1013
1/2
✓ Branch 1 taken 1285503 times.
✗ Branch 2 not taken.
13442181 det2x2(v1.y, v2.y, v1.z, v2.z),
1014
1/2
✓ Branch 1 taken 1285503 times.
✗ Branch 2 not taken.
6460083 det2x2(v1.z, v2.z, v1.x, v2.x),
1015
1/2
✓ Branch 1 taken 1285503 times.
✗ Branch 2 not taken.
10675458 det2x2(v1.x, v2.x, v1.y, v2.y)
1016
1/2
✓ Branch 1 taken 561177 times.
✗ Branch 2 not taken.
7184409 );
1017 }
1018
1019 #ifndef GOMGEN
1020 /**
1021 * \copydoc vecng::operator*(T2, const vecng<DIM,T>&)
1022 * \relates vecng
1023 */
1024 template <
1025 class T2, class T,
1026 typename = std::enable_if_t<is_scalar<T2>::value>
1027 7067482 > inline vecng<3, T> operator* (
1028 T2 s, const vecng<3, T>& v
1029 ) {
1030 7067482 return vecng<3, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z);
1031 }
1032
1033 /**
1034 * \copydoc vecng::operator*(const vecng<DIM,T>&, T2)
1035 * \relates vecng
1036 */
1037 template <
1038 class T2, class T,
1039 typename = std::enable_if_t<is_scalar<T2>::value>
1040 > inline vecng<3, T> operator* (
1041 const vecng<3, T>& v, T2 s
1042 ) {
1043 return vecng<3, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z);
1044 }
1045
1046 #endif
1047
1048 /************************************************************************/
1049
1050 /**
1051 * \brief Specialization of class vecn3 for DIM == 4
1052 * \see vecng
1053 */
1054 template <class T>
1055 class vecng<4, T> {
1056 public:
1057 /** \copydoc vecng::dim */
1058 static constexpr index_t dim = 4;
1059
1060 /** \copydoc vecng::vector_type */
1061 typedef vecng<dim, T> vector_type;
1062
1063 /** \copydoc vecng::value_type */
1064 typedef T value_type;
1065
1066 /** \copydoc vecng::vecng() */
1067 60625 vecng() :
1068 60625 x(0),
1069 60625 y(0),
1070 60625 z(0),
1071 60625 w(0) {
1072 60625 }
1073
1074 /**
1075 * \brief Constructs a vector from coordinates
1076 * \param[in] x_in , y_in , z_in , w_in references to vector coordinates
1077 */
1078 vecng(const T& x_in, const T& y_in, const T& z_in, const T& w_in) :
1079 x(x_in),
1080 y(y_in),
1081 z(z_in),
1082 w(w_in) {
1083 }
1084
1085 /**
1086 * \brief Constructs a vector from coordinates
1087 * \param[in] x_in , y_in , z_in , w_in vector coordinates as rvalues
1088 */
1089 2101 vecng(T&& x_in, T&& y_in, T&& z_in, T&& w_in) :
1090 2101 x(x_in),
1091 2101 y(y_in),
1092 2101 z(z_in),
1093 2101 w(w_in) {
1094 2101 }
1095
1096 vecng(const vecng<4,T>& rhs) = default;
1097 vecng(vecng<4,T>&& rhs) = default;
1098
1099 /** \copydoc vecng::vecng(const vecng<DIM, T2>&) */
1100 template <class T2>
1101 explicit vecng(const vecng<dim, T2>& v) :
1102 x(v.x),
1103 y(v.y),
1104 z(v.z),
1105 w(v.w) {
1106 }
1107
1108 /** \copydoc vecng::vecng(const T2*) */
1109 template <class T2>
1110 explicit vecng(const T2* v) :
1111 x(v[0]),
1112 y(v[1]),
1113 z(v[2]),
1114 w(v[3]) {
1115 }
1116
1117 /** \copydoc vecng::vecng(const std::initializer_list<T>) */
1118 vecng(const std::initializer_list<T>& Vi) {
1119 index_t i = 0;
1120 for(auto& it: Vi) {
1121 geo_debug_assert(i < dim);
1122 data()[i] = it;
1123 ++i;
1124 }
1125 }
1126
1127 vecng<4,T>& operator=(const vecng<4,T>& rhs) = default;
1128 vecng<4,T>& operator=(vecng<4,T>&& rhs) = default;
1129
1130 // -- Conversion scalar constructors --
1131
1132 template<typename U>
1133 explicit vecng(vecng<1, U> const& v);
1134
1135 template<typename X, typename Y, typename Z, typename W>
1136 vecng(X _x, Y _y, Z _z, W _w);
1137 template<typename X, typename Y, typename Z, typename W>
1138 vecng(const vecng<1, X>& _x, Y _y, Z _z, W _w);
1139 template<typename X, typename Y, typename Z, typename W>
1140 vecng(X _x, const vecng<1, Y>& _y, Z _z, W _w);
1141 template<typename X, typename Y, typename Z, typename W>
1142 vecng(const vecng<1, X>& _x, const vecng<1, Y>& _y, Z _z, W _w);
1143 template<typename X, typename Y, typename Z, typename W>
1144 vecng(X _x, Y _y, const vecng<1, Z>& _z, W _w);
1145 template<typename X, typename Y, typename Z, typename W>
1146 vecng(const vecng<1, X>& _x, Y _y, const vecng<1, Z>& _z, W _w);
1147 template<typename X, typename Y, typename Z, typename W>
1148 vecng(X _x, const vecng<1, Y>& _y, const vecng<1, Z>& _z, W _w);
1149 template<typename X, typename Y, typename Z, typename W>
1150 vecng(
1151 const vecng<1, X>& _x, const vecng<1, Y>& _y,
1152 const vecng<1, Z>& _z, W _w
1153 );
1154 template<typename X, typename Y, typename Z, typename W>
1155 vecng(const vecng<1, X>& _x, Y _y, Z _z, const vecng<1, W>& _w);
1156 template<typename X, typename Y, typename Z, typename W>
1157 vecng(X _x, const vecng<1, Y>& _y, Z _z, const vecng<1, W>& _w);
1158 template<typename X, typename Y, typename Z, typename W>
1159 vecng(
1160 const vecng<1, X>& _x, const vecng<1, Y>& _y, Z _z,
1161 const vecng<1, W>& _w
1162 );
1163 template<typename X, typename Y, typename Z, typename W>
1164 vecng(X _x, Y _y, const vecng<1, Z>& _z, const vecng<1, W>& _w);
1165 template<typename X, typename Y, typename Z, typename W>
1166 vecng(
1167 const vecng<1, X>& _x, Y _y, const vecng<1, Z>& _z,
1168 const vecng<1, W>& _w
1169 );
1170 template<typename X, typename Y, typename Z, typename W>
1171 vecng(
1172 X _x, const vecng<1, Y>& _y, const vecng<1, Z>& _z,
1173 const vecng<1, W>& _w
1174 );
1175 template<typename X, typename Y, typename Z, typename W>
1176 vecng(
1177 const vecng<1, X>& _x, const vecng<1, Y>& _y,
1178 const vecng<1, Z>& _z, const vecng<1, W>& _w
1179 );
1180
1181 // -- Conversion vector constructors --
1182
1183 template<typename A, typename B, typename C>
1184 vecng(const vecng<2, A>& _xy, B _z, C _w);
1185 template<typename A, typename B, typename C>
1186 vecng(const vecng<2, A>& _xy, const vecng<1, B> & _z, C _w);
1187 template<typename A, typename B, typename C>
1188 vecng(const vecng<2, A>& _xy, B _z, const vecng<1, C>& _w);
1189 template<typename A, typename B, typename C>
1190 vecng(
1191 const vecng<2, A>& _xy, const vecng<1, B>& _z,
1192 const vecng<1, C>& _w
1193 );
1194 template<typename A, typename B, typename C>
1195 vecng(A _x, const vecng<2, B>& _yz, C _w);
1196 template<typename A, typename B, typename C>
1197 vecng(const vecng<1, A>& _x, const vecng<2, B>& _yz, C _w);
1198 template<typename A, typename B, typename C>
1199 vecng(A _x, const vecng<2, B>& _yz, const vecng<1, C>& _w);
1200 template<typename A, typename B, typename C>
1201 vecng(
1202 const vecng<1, A>& _x, const vecng<2, B>& _yz,
1203 const vecng<1, C>& _w
1204 );
1205 template<typename A, typename B, typename C>
1206 vecng(A _x, B _y, const vecng<2, C>& _zw);
1207 template<typename A, typename B, typename C>
1208 vecng(const vecng<1, A>& _x, B _y, const vecng<2, C>& _zw);
1209 template<typename A, typename B, typename C>
1210 vecng(A _x, const vecng<1, B>& _y, const vecng<2, C>& _zw);
1211 template<typename A, typename B, typename C>
1212 vecng(
1213 const vecng<1, A>& _x, const vecng<1, B>& _y, const vecng<2, C>& _zw
1214 );
1215 template<typename A, typename B>
1216 vecng(const vecng<3, A>& _xyz, B _w);
1217 template<typename A, typename B>
1218 vecng(const vecng<3, A>& _xyz, const vecng<1, B>& _w);
1219 template<typename A, typename B>
1220 vecng(A _x, const vecng<3, B>& _yzw);
1221 template<typename A, typename B>
1222 vecng(const vecng<1, A>& _x, const vecng<3, B>& _yzw);
1223 template<typename A, typename B>
1224 vecng(const vecng<2, A>& _xy, const vecng<2, B>& _zw);
1225
1226 /** \copydoc vecng::length2() const */
1227 inline T length2() const {
1228 return x * x + y * y + z * z + w * w;
1229 }
1230
1231 /** \copydoc vecng::length() const */
1232 inline T length() const {
1233 return sqrt(x * x + y * y + z * z + w * w);
1234 }
1235
1236 /** \copydoc vecng::distance2(const vector_type&) const */
1237 4608 inline T distance2(const vector_type& v) const {
1238 4608 T dx = v.x - x;
1239 4608 T dy = v.y - y;
1240 4608 T dz = v.z - z;
1241 4608 T dw = v.w - w;
1242 4608 return dx * dx + dy * dy + dz * dz + dw * dw;
1243 }
1244
1245 /** \copydoc vecng::distance(const vector_type&) const */
1246 4608 inline T distance(const vector_type& v) const {
1247 4608 return sqrt(distance2(v));
1248 }
1249
1250 /** \copydoc vecng::dimension() const */
1251 index_t dimension() const {
1252 return dim;
1253 }
1254
1255 /** \copydoc vecng::operator+=(const vector_type&) */
1256 inline vector_type& operator+= (const vector_type& v) {
1257 x += v.x;
1258 y += v.y;
1259 z += v.z;
1260 w += v.w;
1261 return *this;
1262 }
1263
1264 /** \copydoc vecng::operator-=(const vector_type&) */
1265 inline vector_type& operator-= (const vector_type& v) {
1266 x -= v.x;
1267 y -= v.y;
1268 z -= v.z;
1269 w -= v.w;
1270 return *this;
1271 }
1272
1273 /** \copydoc vecng::operator*=(T2) */
1274 template <class T2>
1275 inline vector_type& operator*= (T2 s) {
1276 x *= T(s);
1277 y *= T(s);
1278 z *= T(s);
1279 w *= T(s);
1280 return *this;
1281 }
1282
1283 /** \copydoc vecng::operator/=(T2) */
1284 template <class T2>
1285 inline vector_type& operator/= (T2 s) {
1286 x /= T(s);
1287 y /= T(s);
1288 z /= T(s);
1289 w /= T(s);
1290 return *this;
1291 }
1292
1293 /** \copydoc vecng::operator+(const vector_type&) const */
1294 900 inline vector_type operator+ (const vector_type& v) const {
1295 900 return vector_type(x + v.x, y + v.y, z + v.z, w + v.w);
1296 }
1297
1298 /** \copydoc vecng::operator-(const vector_type&) const */
1299 inline vector_type operator- (const vector_type& v) const {
1300 return vector_type(x - v.x, y - v.y, z - v.z, w - v.w);
1301 }
1302
1303 /** \copydoc vecng::operator/(T2) const */
1304 template <class T2>
1305 inline vector_type operator/ (T2 s) const {
1306 return vector_type(x / T(s), y / T(s), z / T(s), w / T(s));
1307 }
1308
1309 /** \copydoc vecng::operator-() const */
1310 inline vector_type operator- () const {
1311 return vector_type(-x, -y, -z, -w);
1312 }
1313
1314 /** \copydoc vecng::data() */
1315 1213700 T* data() {
1316 1213700 return &x;
1317 }
1318
1319 /** \copydoc vecng::data() const */
1320 970000 const T* data() const {
1321 970000 return &x;
1322 }
1323
1324 /** \copydoc vecng::operator[](index_t) */
1325 1213700 inline T& operator[] (index_t i) {
1326
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1213700 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1213700 geo_debug_assert(i < dim);
1327 1213700 return data()[i];
1328 }
1329
1330 /** \copydoc vecng::operator[](index_t) const */
1331 970000 inline const T& operator[] (index_t i) const {
1332
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 970000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
970000 geo_debug_assert(i < dim);
1333 970000 return data()[i];
1334 }
1335
1336 /** \brief Vector x coordinate */
1337 T x;
1338 /** \brief Vector y coordinate */
1339 T y;
1340 /** \brief Vector z coordinate */
1341 T z;
1342 /** \brief Vector w coordinate */
1343 T w;
1344 };
1345
1346 /**
1347 * \copydoc vecng::dot(const vecng<DIM,T>&, const vecng<DIM,T>&)
1348 * \relates vecng
1349 */
1350 template <class T>
1351 inline T dot(
1352 const vecng<4, T>& v1, const vecng<4, T>& v2
1353 ) {
1354 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
1355 }
1356
1357 #ifndef GOMGEN
1358 /**
1359 * \copydoc vecng::operator*(T2, const vecng<DIM,T>&)
1360 * \relates vecng
1361 */
1362 template <
1363 class T2, class T,
1364 typename = std::enable_if_t<is_scalar<T2>::value>
1365 1200 > inline vecng<4, T> operator* (
1366 T2 s, const vecng<4, T>& v
1367 ) {
1368 1200 return vecng<4, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z, T(s) * v.w);
1369 }
1370
1371 /**
1372 * \copydoc vecng::operator*(const vecng<DIM,T>&, T2)
1373 * \relates vecng
1374 */
1375 template <
1376 class T2, class T,
1377 typename = std::enable_if_t<is_scalar<T2>::value>
1378 > inline vecng<4, T> operator* (
1379 const vecng<4, T>& v, T2 s
1380 ) {
1381 return vecng<4, T>(T(s) * v.x, T(s) * v.y, T(s) * v.z, T(s) * v.w);
1382 }
1383
1384 #endif
1385
1386 /**
1387 * \brief Writes a vector to a stream
1388 * \details This writes the coordinates of vector \p v separated by a
1389 * space character to the output stream \p out.
1390 * \param[in] out the output stream
1391 * \param[in] v the vector to write
1392 * \return a reference to the output stream \p out
1393 * \relates vecng
1394 */
1395 template <index_t DIM, class T>
1396 inline std::ostream& operator<< (
1397 std::ostream& out, const GEO::vecng<DIM, T>& v
1398 ) {
1399 const char* sep = "";
1400 for(index_t i = 0; i < DIM; i++) {
1401 out << sep << v[i];
1402 sep = " ";
1403 }
1404 return out;
1405 }
1406
1407 /**
1408 * \brief Reads a vector from a stream
1409 * \details This reads \p DIM coordinates from the input stream \p in and
1410 * stores them in vector \p v. Understands both "x y z",
1411 * "[x, y, z]" and "{x, y, z}" formats.
1412 * \param[in] in the input stream
1413 * \param[out] v the vector to read
1414 * \return a reference to the input stream \p in
1415 * \relates vecng
1416 */
1417 template <index_t DIM, class T>
1418 inline std::istream& operator>> (
1419 std::istream& in, GEO::vecng<DIM, T>& v
1420 ) {
1421 char c;
1422 while(isspace(in.peek())) {
1423 in.get(c);
1424 }
1425 if(in.peek() == '[' || in.peek() == '{') {
1426 in.get(c);
1427 }
1428 while(isspace(in.peek())) {
1429 in.get(c);
1430 }
1431 for(index_t i = 0; i < DIM; i++) {
1432 in >> v[i];
1433 while(isspace(in.peek())) {
1434 in.get(c);
1435 }
1436 if(in.peek() == ',') {
1437 in.get(c);
1438 }
1439 while(isspace(in.peek())) {
1440 in.get(c);
1441 }
1442 }
1443 if(in.peek() == ']' || in.peek() == '}') {
1444 in.get(c);
1445 }
1446 return in;
1447 }
1448
1449 /************************************************************************/
1450 // -- Conversion vector constructors --
1451
1452 template<typename T>
1453 template<typename A, typename B>
1454 vecng<3, T>::vecng(const vecng<2, A>& _xy, B _z)
1455 : x{static_cast<T>(_xy.x)}
1456 , y{static_cast<T>(_xy.y)}
1457 , z{static_cast<T>(_z)}
1458 {}
1459
1460 template<typename T>
1461 template<typename A, typename B>
1462 vecng<3, T>::vecng(const vecng<2, A>& _xy, const vecng<1, B>& _z)
1463 : x(static_cast<T>(_xy.x))
1464 , y(static_cast<T>(_xy.y))
1465 , z(static_cast<T>(_z.x))
1466 {}
1467
1468 template<typename T>
1469 template<typename A, typename B>
1470 vecng<3, T>::vecng(A _x, const vecng<2, B>& _yz)
1471 : x(static_cast<T>(_x))
1472 , y(static_cast<T>(_yz.x))
1473 , z(static_cast<T>(_yz.y))
1474 {}
1475
1476 template<typename T>
1477 template<typename A, typename B>
1478 vecng<3, T>::vecng(const vecng<1, A>& _x, const vecng<2, B>& _yz)
1479 : x(static_cast<T>(_x.x))
1480 , y(static_cast<T>(_yz.x))
1481 , z(static_cast<T>(_yz.y))
1482 {}
1483
1484 template<typename T>
1485 template<typename U>
1486 vecng<3, T>::vecng(const vecng<4, U>& v)
1487 : x(static_cast<T>(v.x))
1488 , y(static_cast<T>(v.y))
1489 , z(static_cast<T>(v.z))
1490 {}
1491
1492 template<typename T>
1493 template<typename U>
1494 vecng<4, T>::vecng(const vecng<1, U>& v)
1495 : x(static_cast<T>(v.x))
1496 , y(static_cast<T>(v.x))
1497 , z(static_cast<T>(v.x))
1498 , w(static_cast<T>(v.x))
1499 {}
1500
1501 template<typename T>
1502 template<typename X, typename Y, typename Z, typename W>
1503 vecng<4, T>::vecng(X _x, Y _y, Z _z, W _w)
1504 : x(static_cast<T>(_x))
1505 , y(static_cast<T>(_y))
1506 , z(static_cast<T>(_z))
1507 , w(static_cast<T>(_w))
1508 {}
1509
1510 template<typename T>
1511 template<typename X, typename Y, typename Z, typename W>
1512 vecng<4, T>::vecng(const vecng<1, X>& _x, Y _y, Z _z, W _w)
1513 : x(static_cast<T>(_x.x))
1514 , y(static_cast<T>(_y))
1515 , z(static_cast<T>(_z))
1516 , w(static_cast<T>(_w))
1517 {}
1518
1519 template<typename T>
1520 template<typename X, typename Y, typename Z, typename W>
1521 vecng<4, T>::vecng(X _x, const vecng<1, Y>& _y, Z _z, W _w)
1522 : x(static_cast<T>(_x))
1523 , y(static_cast<T>(_y.x))
1524 , z(static_cast<T>(_z))
1525 , w(static_cast<T>(_w))
1526 {}
1527
1528 template<typename T>
1529 template<typename X, typename Y, typename Z, typename W>
1530 vecng<4, T>::vecng(const vecng<1, X>& _x, const vecng<1, Y>& _y, Z _z, W _w)
1531 : x(static_cast<T>(_x.x))
1532 , y(static_cast<T>(_y.x))
1533 , z(static_cast<T>(_z))
1534 , w(static_cast<T>(_w))
1535 {}
1536
1537 template<typename T>
1538 template<typename X, typename Y, typename Z, typename W>
1539 vecng<4, T>::vecng(X _x, Y _y, const vecng<1, Z>& _z, W _w)
1540 : x(static_cast<T>(_x))
1541 , y(static_cast<T>(_y))
1542 , z(static_cast<T>(_z.x))
1543 , w(static_cast<T>(_w))
1544 {}
1545
1546 template<typename T>
1547 template<typename X, typename Y, typename Z, typename W>
1548 vecng<4, T>::vecng(const vecng<1, X>& _x, Y _y, const vecng<1, Z>& _z, W _w)
1549 : x(static_cast<T>(_x.x))
1550 , y(static_cast<T>(_y))
1551 , z(static_cast<T>(_z.x))
1552 , w(static_cast<T>(_w))
1553 {}
1554
1555 template<typename T>
1556 template<typename X, typename Y, typename Z, typename W>
1557 vecng<4, T>::vecng(X _x, const vecng<1, Y>& _y, const vecng<1, Z>& _z, W _w)
1558 : x(static_cast<T>(_x))
1559 , y(static_cast<T>(_y.x))
1560 , z(static_cast<T>(_z.x))
1561 , w(static_cast<T>(_w))
1562 {}
1563
1564 template<typename T>
1565 template<typename X, typename Y, typename Z, typename W>
1566 vecng<4, T>::vecng(
1567 const vecng<1, X>& _x, const vecng<1, Y>& _y,
1568 const vecng<1, Z>& _z, W _w
1569 ) : x(static_cast<T>(_x.x))
1570 , y(static_cast<T>(_y.x))
1571 , z(static_cast<T>(_z.x))
1572 , w(static_cast<T>(_w))
1573 {}
1574
1575 template<typename T>
1576 template<typename X, typename Y, typename Z, typename W>
1577 vecng<4, T>::vecng(
1578 const vecng<1, X>& _x, Y _y, Z _z, const vecng<1, W>& _w
1579 ) : x(static_cast<T>(_x.x))
1580 , y(static_cast<T>(_y))
1581 , z(static_cast<T>(_z))
1582 , w(static_cast<T>(_w.x))
1583 {}
1584
1585 template<typename T>
1586 template<typename X, typename Y, typename Z, typename W>
1587 vecng<4, T>::vecng(
1588 X _x, const vecng<1, Y>& _y, Z _z, const vecng<1, W>& _w
1589 ) : x(static_cast<T>(_x))
1590 , y(static_cast<T>(_y.x))
1591 , z(static_cast<T>(_z))
1592 , w(static_cast<T>(_w.x))
1593 {}
1594
1595 template<typename T>
1596 template<typename X, typename Y, typename Z, typename W>
1597 vecng<4, T>::vecng(
1598 const vecng<1, X>& _x, const vecng<1, Y>& _y, Z _z,
1599 const vecng<1, W>& _w
1600 ) : x(static_cast<T>(_x.x))
1601 , y(static_cast<T>(_y.x))
1602 , z(static_cast<T>(_z))
1603 , w(static_cast<T>(_w.x))
1604 {}
1605
1606 template<typename T>
1607 template<typename X, typename Y, typename Z, typename W>
1608 vecng<4, T>::vecng(X _x, Y _y, const vecng<1, Z>& _z, const vecng<1, W>& _w)
1609 : x(static_cast<T>(_x))
1610 , y(static_cast<T>(_y))
1611 , z(static_cast<T>(_z.x))
1612 , w(static_cast<T>(_w.x))
1613 {}
1614
1615 template<typename T>
1616 template<typename X, typename Y, typename Z, typename W>
1617 vecng<4, T>::vecng(
1618 const vecng<1, X>& _x, Y _y, const vecng<1, Z>& _z,
1619 const vecng<1, W>& _w
1620 ) : x(static_cast<T>(_x.x))
1621 , y(static_cast<T>(_y))
1622 , z(static_cast<T>(_z.x))
1623 , w(static_cast<T>(_w.x))
1624 {}
1625
1626 template<typename T>
1627 template<typename X, typename Y, typename Z, typename W>
1628 vecng<4, T>::vecng(
1629 X _x, const vecng<1, Y>& _y, const vecng<1, Z>& _z,
1630 const vecng<1, W>& _w
1631 ) : x(static_cast<T>(_x))
1632 , y(static_cast<T>(_y.x))
1633 , z(static_cast<T>(_z.x))
1634 , w(static_cast<T>(_w.x))
1635 {}
1636
1637 template<typename T>
1638 template<typename X, typename Y, typename Z, typename W>
1639 vecng<4, T>::vecng(
1640 const vecng<1, X>& _x, const vecng<1, Y>& _y,
1641 const vecng<1, Z>& _z, const vecng<1, W>& _w
1642 ) : x(static_cast<T>(_x.x))
1643 , y(static_cast<T>(_y.x))
1644 , z(static_cast<T>(_z.x))
1645 , w(static_cast<T>(_w.x))
1646 {}
1647
1648 // -- Conversion vector constructors --
1649
1650 template<typename T>
1651 template<typename A, typename B, typename C>
1652 502 vecng<4, T>::vecng(const vecng<2, A>& _xy, B _z, C _w)
1653 502 : x(static_cast<T>(_xy.x))
1654 502 , y(static_cast<T>(_xy.y))
1655 502 , z(static_cast<T>(_z))
1656 502 , w(static_cast<T>(_w))
1657 502 {}
1658
1659 template<typename T>
1660 template<typename A, typename B, typename C>
1661 vecng<4, T>::vecng(const vecng<2, A>& _xy, const vecng<1, B>& _z, C _w)
1662 : x(static_cast<T>(_xy.x))
1663 , y(static_cast<T>(_xy.y))
1664 , z(static_cast<T>(_z.x))
1665 , w(static_cast<T>(_w))
1666 {}
1667
1668 template<typename T>
1669 template<typename A, typename B, typename C>
1670 vecng<4, T>::vecng(const vecng<2, A>& _xy, B _z, const vecng<1, C>& _w)
1671 : x(static_cast<T>(_xy.x))
1672 , y(static_cast<T>(_xy.y))
1673 , z(static_cast<T>(_z))
1674 , w(static_cast<T>(_w.x))
1675 {}
1676
1677 template<typename T>
1678 template<typename A, typename B, typename C>
1679 vecng<4, T>::vecng(
1680 const vecng<2, A>& _xy, const vecng<1, B>& _z, const vecng<1, C>& _w
1681 ) : x(static_cast<T>(_xy.x))
1682 , y(static_cast<T>(_xy.y))
1683 , z(static_cast<T>(_z.x))
1684 , w(static_cast<T>(_w.x))
1685 {}
1686
1687 template<typename T>
1688 template<typename A, typename B, typename C>
1689 vecng<4, T>::vecng(A _x, const vecng<2, B>& _yz, C _w)
1690 : x(static_cast<T>(_x))
1691 , y(static_cast<T>(_yz.x))
1692 , z(static_cast<T>(_yz.y))
1693 , w(static_cast<T>(_w))
1694 {}
1695
1696 template<typename T>
1697 template<typename A, typename B, typename C>
1698 vecng<4, T>::vecng(const vecng<1, A>& _x, const vecng<2, B>& _yz, C _w)
1699 : x(static_cast<T>(_x.x))
1700 , y(static_cast<T>(_yz.x))
1701 , z(static_cast<T>(_yz.y))
1702 , w(static_cast<T>(_w))
1703 {}
1704
1705 template<typename T>
1706 template<typename A, typename B, typename C>
1707 vecng<4, T>::vecng(A _x, const vecng<2, B>& _yz, const vecng<1, C>& _w)
1708 : x(static_cast<T>(_x))
1709 , y(static_cast<T>(_yz.x))
1710 , z(static_cast<T>(_yz.y))
1711 , w(static_cast<T>(_w.x))
1712 {}
1713
1714 template<typename T>
1715 template<typename A, typename B, typename C>
1716 vecng<4, T>::vecng(
1717 const vecng<1, A>& _x, const vecng<2, B>& _yz, const vecng<1, C>& _w
1718 ) : x(static_cast<T>(_x.x))
1719 , y(static_cast<T>(_yz.x))
1720 , z(static_cast<T>(_yz.y))
1721 , w(static_cast<T>(_w.x))
1722 {}
1723
1724 template<typename T>
1725 template<typename A, typename B, typename C>
1726 vecng<4, T>::vecng(A _x, B _y, const vecng<2, C>& _zw)
1727 : x(static_cast<T>(_x))
1728 , y(static_cast<T>(_y))
1729 , z(static_cast<T>(_zw.x))
1730 , w(static_cast<T>(_zw.y))
1731 {}
1732
1733 template<typename T>
1734 template<typename A, typename B, typename C>
1735 vecng<4, T>::vecng(const vecng<1, A>& _x, B _y, const vecng<2, C>& _zw)
1736 : x(static_cast<T>(_x.x))
1737 , y(static_cast<T>(_y))
1738 , z(static_cast<T>(_zw.x))
1739 , w(static_cast<T>(_zw.y))
1740 {}
1741
1742 template<typename T>
1743 template<typename A, typename B, typename C>
1744 vecng<4, T>::vecng(A _x, const vecng<1, B>& _y, const vecng<2, C>& _zw)
1745 : x(static_cast<T>(_x))
1746 , y(static_cast<T>(_y.x))
1747 , z(static_cast<T>(_zw.x))
1748 , w(static_cast<T>(_zw.y))
1749 {}
1750
1751 template<typename T>
1752 template<typename A, typename B, typename C>
1753 vecng<4, T>::vecng(
1754 const vecng<1, A>& _x, const vecng<1, B>& _y, const vecng<2, C>& _zw
1755 ) : x(static_cast<T>(_x.x))
1756 , y(static_cast<T>(_y.x))
1757 , z(static_cast<T>(_zw.x))
1758 , w(static_cast<T>(_zw.y))
1759 {}
1760
1761 template<typename T>
1762 template<typename A, typename B>
1763 60123 vecng<4, T>::vecng(const vecng<3, A>& _xyz, B _w)
1764 60123 : x(static_cast<T>(_xyz.x))
1765 60123 , y(static_cast<T>(_xyz.y))
1766 60123 , z(static_cast<T>(_xyz.z))
1767 60123 , w(static_cast<T>(_w))
1768 60123 {}
1769
1770 template<typename T>
1771 template<typename A, typename B>
1772 vecng<4, T>::vecng(const vecng<3, A>& _xyz, const vecng<1, B>& _w)
1773 : x(static_cast<T>(_xyz.x))
1774 , y(static_cast<T>(_xyz.y))
1775 , z(static_cast<T>(_xyz.z))
1776 , w(static_cast<T>(_w.x))
1777 {}
1778
1779 template<typename T>
1780 template<typename A, typename B>
1781 vecng<4, T>::vecng(A _x, const vecng<3, B>& _yzw)
1782 : x(static_cast<T>(_x))
1783 , y(static_cast<T>(_yzw.x))
1784 , z(static_cast<T>(_yzw.y))
1785 , w(static_cast<T>(_yzw.z))
1786 {}
1787
1788 template<typename T>
1789 template<typename A, typename B>
1790 vecng<4, T>::vecng(const vecng<1, A>& _x, const vecng<3, B>& _yzw)
1791 : x(static_cast<T>(_x.x))
1792 , y(static_cast<T>(_yzw.x))
1793 , z(static_cast<T>(_yzw.y))
1794 , w(static_cast<T>(_yzw.z))
1795 {}
1796
1797 template<typename T>
1798 template<typename A, typename B>
1799 vecng<4, T>::vecng(const vecng<2, A>& _xy, const vecng<2, B>& _zw)
1800 : x(static_cast<T>(_xy.x))
1801 , y(static_cast<T>(_xy.y))
1802 , z(static_cast<T>(_zw.x))
1803 , w(static_cast<T>(_zw.y))
1804 {}
1805
1806 /************************************************************************/
1807
1808 namespace Numeric {
1809
1810 template<class T>
1811 inline void optimize_number_representation(
1812 vecng<2,T>& v
1813 ) {
1814 v.optimize();
1815 }
1816
1817 template<class T>
1818 32035 inline void optimize_number_representation(
1819 vecng<3,T>& v
1820 ) {
1821 32035 v.optimize();
1822 32035 }
1823
1824 }
1825
1826 /************************************************************************/
1827 }
1828
1829 #endif
1830