BRL-CAD
dvec.h
Go to the documentation of this file.
1 /* D V E C . H
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-2024 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #ifndef BN_DVEC_H
22 #define BN_DVEC_H
23 
24 #include "common.h"
25 
26 #include <math.h>
27 extern "C++" {
28 /* Hide iostream from Doxygen with cond */
29 /** @cond */
30 #include <iostream>
31 #include <ostream>
32 /** @endcond */
33 }
34 
35 /* Needed for fastf_t definition */
36 #include "bu/defines.h"
37 
38 /* Needed for VUNITIZE_TOL and NEAR_ZERO */
39 #include "vmath.h"
40 
41 /** @addtogroup bn_vectormath */
42 /** @{ */
43 /** @file bn/dvec.h */
44 
45 extern "C++" {
46 
47 const double VEQUALITY = 0.0000001;
48 
49 template<int LEN>
51 
52 template<int LEN>
54 
55 template<int LEN>
56 class dvec;
57 
58 template<int LEN>
59 std::ostream& operator<<(std::ostream& out, const dvec<LEN>& v);
60 
61 class dvec_unop {
62 public:
63  virtual double operator()(double a) const = 0;
64  virtual ~dvec_unop() {}
65 };
66 
67 class dvec_op {
68 public:
69  virtual double operator()(double a, double b) const = 0;
70  virtual ~dvec_op() {}
71 };
72 
73 template<int LEN>
74 class dvec {
75 public:
76  dvec(double s);
77  dvec(const double* vals);
78  dvec(const float* vals);
79  dvec(const dvec<LEN>& p);
80 
82  double operator[](int index) const;
83  void u_store(double* arr) const;
84  void u_store(float* arr) const;
85  void a_store(double* arr) const;
86  void a_store(float* arr) const;
87 
88  bool operator==(const dvec<LEN>& b) const;
89 
94 
95  dvec<LEN> madd(const dvec<LEN>& s, const dvec<LEN>& b);
96  dvec<LEN> madd(const double s, const dvec<LEN>& b);
97 
98  dvec<LEN> map(const dvec_unop& operation, int limit = LEN);
99  double foldr(double proto, const dvec_op& operation, int limit = LEN);
100  double foldl(double proto, const dvec_op& operation, int limit = LEN);
101 
102  class mul : public dvec_op {
103  public:
104  double operator()(double a, double b) const { return a * b; }
105  };
106 
107  class add : public dvec_op {
108  public:
109  double operator()(double a, double b) const { return a + b; }
110  };
111 
112  class sub : public dvec_op {
113  public:
114  double operator()(double a, double b) const { return a - b; }
115  };
116 
117  class sqrt : public dvec_unop {
118  public:
119  double operator()(double a) const { return ::sqrt(a); }
120  };
121 private:
122  dvec_internal<LEN> data;
123 
124  dvec(const dvec_internal<LEN>& d);
125  dvec(const fvec_internal<LEN>& f);
126 };
127 
128 //#define DVEC4(V, t, a, b, c, d) double v#t[4] VEC_ALIGN = {(a), (b), (c), (d)}; V(v#t)
129 
130 // use this to create 16-byte aligned memory on platforms that support it
131 #define VEC_ALIGN
132 
133 /* Doxygen doesn't like these includes... */
134 /** @cond */
135 /*#undef __SSE2__*/ // Test FPU version
136 #if defined(__SSE2__) && defined(__GNUC__) && defined(HAVE_EMMINTRIN_H) && defined(HAVE_EMMINTRIN)
137 # define __x86_vector__
138 
139 #ifdef HAVE_EMMINTRIN_H
140 # include <emmintrin.h>
141 #endif
142 
143 #undef VEC_ALIGN
144 #define VEC_ALIGN __attribute__((aligned(16)))
145 
146 typedef double v2df __attribute__((vector_size(16)));
147 typedef double v2f __attribute__((vector_size(8)));
148 
149 template<int LEN>
150 struct dvec_internal {
151  v2df v[LEN/2];
152 };
153 
154 template<int LEN>
155 struct fvec_internal {
156  v2f v[LEN/2];
157 };
158 
159 template<int LEN>
160 inline dvec<LEN>::dvec(double s)
161 {
162  double t[LEN] VEC_ALIGN;
163  for (int i = 0; i < LEN/2; i++) {
164  t[i*2] = s;
165  t[i*2+1] = s;
166  data.v[i] = _mm_load_pd(&t[i*2]);
167  }
168 }
169 
170 template<int LEN>
171 inline dvec<LEN>::dvec(const double* vals)
172 {
173  for (int i = 0; i < LEN/2; i++) {
174  /* NOTE: assumes that vals are 16-byte aligned */
175  data.v[i] = _mm_load_pd(&vals[i*2]);
176  }
177 }
178 
179 template<int LEN>
180 inline dvec<LEN>::dvec(const dvec<LEN>& p)
181 {
182  for (int i = 0; i < LEN/2; i++) {
183  data.v[i] = p.data.v[i];
184  }
185 }
186 
187 template<int LEN>
188 inline dvec<LEN>::dvec(const dvec_internal<LEN>& d)
189 {
190  for (int i = 0; i < LEN/2; i++) data.v[i] = d.v[i];
191 }
192 
193 template<int LEN>
194 inline dvec<LEN>::dvec(const fvec_internal<LEN>& f)
195 {
196  for (int i = 0; i < LEN/2; i++) data.v[i] = f.v[i];
197 }
198 
199 template<int LEN>
200 inline dvec<LEN>&
202 {
203  for (int i = 0; i < LEN/2; i++) {
204  data.v[i] = p.data.v[i];
205  }
206  return *this;
207 }
208 
209 template<int LEN>
210 inline double
211 dvec<LEN>::operator[](const int index) const
212 {
213  double t[2] __attribute__((aligned(16)));
214  _mm_store_pd(t, data.v[index/2]);
215  return t[index%2];
216 }
217 
218 template<int LEN>
219 inline void
220 dvec<LEN>::u_store(double* arr) const
221 {
222  for (int i = 0; i < LEN/2; i++) {
223  _mm_storeu_pd(&arr[i*2], data.v[i]);
224  }
225 }
226 
227 template<int LEN>
228 inline void
229 dvec<LEN>::a_store(double* arr) const
230 {
231  for (int i = 0; i < LEN/2; i++) {
232  _mm_store_pd(&arr[i*2], data.v[i]);
233  }
234 }
235 
236 template<int LEN>
237 inline bool
238 dvec<LEN>::operator==(const dvec<LEN>& b) const
239 {
240  double ta[LEN] VEC_ALIGN;
241  double tb[LEN] VEC_ALIGN;
242  a_store(ta);
243  b.a_store(tb);
244  for (int i = 0; i < LEN; i++)
245  if (fabs(ta[i]-tb[i]) > VEQUALITY) return false;
246  return true;
247 }
248 
249 #define DOP_IMPL(__op__) { \
250  dvec_internal<LEN> result; \
251  for (int i = 0; i < LEN/2; i++) { \
252  result.v[i] = __op__(data.v[i], b.data.v[i]); \
253  } \
254  return dvec<LEN>(result); \
255  }
256 
257 template<int LEN>
258 inline dvec<LEN>
260 {
261  DOP_IMPL(_mm_add_pd);
262 }
263 
264 template<int LEN>
265 inline dvec<LEN>
267 {
268  DOP_IMPL(_mm_sub_pd);
269 }
270 
271 template<int LEN>
272 inline dvec<LEN>
274 {
275  DOP_IMPL(_mm_mul_pd);
276 }
277 
278 template<int LEN>
279 inline dvec<LEN>
281 {
282  DOP_IMPL(_mm_div_pd);
283 }
284 
285 template<int LEN>
286 inline dvec<LEN>
287 dvec<LEN>::madd(const dvec<LEN>& s, const dvec<LEN>& b)
288 {
290  for (int i = 0; i < LEN/2; i++) {
291  r.v[i] = _mm_mul_pd(data.v[i], s.data.v[i]);
292  }
293  for (int i = 0; i < LEN/2; i++) {
294  r.v[i] = _mm_add_pd(r.v[i], b.data.v[i]);
295  }
296  return dvec<LEN>(r);
297 }
298 
299 template<int LEN>
300 inline dvec<LEN>
301 dvec<LEN>::madd(const double s, const dvec<LEN>& b)
302 {
303  double _t[LEN] VEC_ALIGN;
304  for (int i = 0; i < LEN; i++) _t[i] = s;
305  dvec<LEN> t(_t);
306  return madd(t, b);
307 }
308 
309 template<int LEN>
310 inline double
311 dvec<LEN>::foldr(double identity, const dvec_op& op, int limit)
312 {
313  double _t[LEN] VEC_ALIGN;
314  a_store(_t);
315  double val = identity;
316  for (int i = limit-1; i >= 0; i--) {
317  val = op(_t[i], val);
318  }
319  return val;
320 }
321 
322 template<int LEN>
323 inline double
324 dvec<LEN>::foldl(double identity, const dvec_op& op, int limit)
325 {
326  double _t[LEN] VEC_ALIGN;
327  a_store(_t);
328  double val = identity;
329  for (int i = 0; i < limit; i++) {
330  val = op(val, _t[i]);
331  }
332  return val;
333 }
334 
335 
336 template<int LEN>
337 inline dvec<LEN>
338 dvec<LEN>::map(const dvec_unop& op, int limit)
339 {
340  double _t[LEN] VEC_ALIGN;
341  a_store(_t);
342  for (int i = 0; i < limit; i++) {
343  _t[i] = op(_t[i]);
344  }
345  return dvec<LEN>(_t);
346 }
347 
348 
349 template <int LEN>
350 inline std::ostream&
351 operator<<(std::ostream& out, const dvec<LEN>& v)
352 {
353  double _t[LEN] VEC_ALIGN;
354  v.a_store(_t);
355  out << "<";
356  for (int i = 0; i < LEN; i++) {
357  out << _t[i];
358  if (i != LEN-1)
359  out << ",";
360  }
361  out << ">";
362  return out;
363 }
364 
365 class vec2d {
366 public:
367 
368  vec2d() {
369  _init(0, 0);
370  }
371 
372  vec2d(double x_, double y_) {
373  _init(x_, y_);
374  }
375 
376  vec2d(const vec2d& proto) {
377  _vec = proto._vec;
378  }
379 
380  vec2d& operator=(const vec2d& b) {
381  _vec = b._vec;
382  return *this;
383  }
384 
385  double operator[](int index) const {
386  double v[2] __attribute__((aligned(16)));
387  _mm_store_pd(v, _vec);
388  return v[index];
389  }
390 
391  void ustore(double* arr) const {
392  // assume nothing about the alignment of arr
393  double v[2] __attribute__((aligned(16)));
394  _mm_store_pd(v, _vec);
395  arr[0] = v[0];
396  arr[1] = v[1];
397  }
398 
399  double x() const { return (*this)[0]; }
400  double y() const { return (*this)[1]; }
401 
402  vec2d operator+(const vec2d& b) const {
403  return vec2d(_mm_add_pd(_vec, b._vec));
404  }
405 
406  vec2d operator-(const vec2d& b) const {
407  return vec2d(_mm_sub_pd(vec(), b.vec()));
408  }
409 
410  vec2d operator*(const vec2d& b) const {
411  return vec2d(_mm_mul_pd(vec(), b.vec()));
412  }
413 
414  vec2d operator/(const vec2d& b) const {
415  return vec2d(_mm_div_pd(vec(), b.vec()));
416  }
417 
418  vec2d madd(const double& scalar, const vec2d& b) const {
419  return madd(vec2d(scalar, scalar), b);
420  }
421 
422  vec2d madd(const vec2d& s, const vec2d& b) const {
423  return vec2d(_mm_add_pd(_mm_mul_pd(vec(), s.vec()), b.vec()));
424  }
425 
426 private:
427  //double v[2] __attribute__((aligned(16)));
428  v2df _vec;
429 
430  vec2d(const v2df& result) {
431  _vec = result;
432  }
433 
434  v2df vec() const { return _vec; }
435 
436  void _init(double x_, double y_) {
437  double v[2] __attribute__((aligned(16)));
438  v[0] = x_;
439  v[1] = y_;
440  _vec = _mm_load_pd(v);
441  }
442 
443 };
444 
445 inline std::ostream&
446 operator<<(std::ostream& out, const vec2d& v)
447 {
448  out << "<" << v.x() << "," << v.y() << ">";
449  return out;
450 }
451 
452 #else
453 # define __fpu_vector__
454 
455 #ifdef __GNUC__
456 #undef VEC_ALIGN
457 #define VEC_ALIGN __attribute__((aligned(16)))
458 #endif
459 
460 template<int LEN>
461 struct dvec_internal {
462  double v[LEN] VEC_ALIGN;
463 };
464 
465 template<int LEN>
466 struct fvec_internal {
467  float v[LEN] VEC_ALIGN;
468 };
469 
470 template<int LEN>
471 inline dvec<LEN>::dvec(double s)
472 {
473  for (int i = 0; i < LEN; i++)
474  data.v[i] = s;
475 }
476 
477 template<int LEN>
478 inline dvec<LEN>::dvec(const float* vals)
479 {
480  for (int i = 0; i < LEN; i++)
481  data.v[i] = vals[i];
482 }
483 
484 template<int LEN>
485 inline dvec<LEN>::dvec(const double* vals)
486 {
487  for (int i = 0; i < LEN; i++)
488  data.v[i] = vals[i];
489 }
490 
491 template<int LEN>
492 inline dvec<LEN>::dvec(const dvec<LEN>& p)
493 {
494  for (int i = 0; i < LEN; i++)
495  data.v[i] = p.data.v[i];
496 }
497 
498 template<int LEN>
499 inline dvec<LEN>::dvec(const dvec_internal<LEN>& d)
500 {
501  for (int i = 0; i < LEN; i++)
502  data.v[i] = d.v[i];
503 }
504 
505 template<int LEN>
506 inline dvec<LEN>::dvec(const fvec_internal<LEN>& f)
507 {
508  for (int i = 0; i < LEN; i++)
509  data.v[i] = f.v[i];
510 }
511 
512 template<int LEN>
513 inline dvec<LEN>&
515 {
516  for (int i = 0; i < LEN; i++)
517  data.v[i] = p.data.v[i];
518  return *this;
519 }
520 
521 template<int LEN>
522 inline double
523 dvec<LEN>::operator[](int index) const
524 {
525  return data.v[index];
526 }
527 
528 template<int LEN>
529 inline void
530 dvec<LEN>::u_store(float* arr) const
531 {
532  a_store(arr);
533 }
534 
535 template<int LEN>
536 inline void
537 dvec<LEN>::u_store(double* arr) const
538 {
539  a_store(arr);
540 }
541 
542 template<int LEN>
543 inline void
544 dvec<LEN>::a_store(float* arr) const
545 {
546  for (int i = 0; i < LEN; i++)
547  arr[i] = data.v[i];
548 }
549 
550 template<int LEN>
551 inline void
552 dvec<LEN>::a_store(double* arr) const
553 {
554  for (int i = 0; i < LEN; i++)
555  arr[i] = data.v[i];
556 }
557 
558 template<int LEN>
559 inline bool
560 dvec<LEN>::operator==(const dvec<LEN>& b) const
561 {
562  for (int i = 0; i < LEN; i++)
563  if (fabs(data.v[i]-b.data.v[i]) > VEQUALITY) return false;
564  return true;
565 }
566 
567 template<int LEN>
568 inline dvec<LEN>
570 {
572  for (int i = 0; i < LEN; i++)
573  r.v[i] = data.v[i] + b.data.v[i];
574  return dvec<LEN>(r);
575 }
576 
577 template<int LEN>
578 inline dvec<LEN>
580 {
582  for (int i = 0; i < LEN; i++)
583  r.v[i] = data.v[i] - b.data.v[i];
584  return dvec<LEN>(r);
585 }
586 
587 template<int LEN>
588 inline dvec<LEN>
590 {
592  for (int i = 0; i < LEN; i++)
593  r.v[i] = data.v[i] * b.data.v[i];
594  return dvec<LEN>(r);
595 }
596 
597 template<int LEN>
598 inline dvec<LEN>
600 {
602  for (int i = 0; i < LEN; i++)
603  r.v[i] = data.v[i] / b.data.v[i];
604  return dvec<LEN>(r);
605 }
606 
607 template<int LEN>
608 inline dvec<LEN>
609 dvec<LEN>::madd(const dvec<LEN>& s, const dvec<LEN>& b)
610 {
612  for (int i = 0; i < LEN; i++)
613  r.v[i] = data.v[i] * s.data.v[i] + b.data.v[i];
614  return dvec<LEN>(r);
615 }
616 
617 template<int LEN>
618 inline dvec<LEN>
619 dvec<LEN>::madd(const double s, const dvec<LEN>& b)
620 {
622  for (int i = 0; i < LEN; i++)
623  r.v[i] = data.v[i] * s + b.data.v[i];
624  return dvec<LEN>(r);
625 }
626 
627 template<int LEN>
628 inline double
629 dvec<LEN>::foldr(double identity, const dvec_op& op, int limit)
630 {
631  double val = identity;
632  for (int i = limit-1; i >= 0; i--) {
633  val = op(data.v[i], val);
634  }
635  return val;
636 }
637 template<int LEN>
638 inline double
639 dvec<LEN>::foldl(double identity, const dvec_op& op, int limit)
640 {
641  double val = identity;
642  for (int i = 0; i < limit; i++) {
643  val = op(val, data.v[i]);
644  }
645  return val;
646 }
647 
648 template<int LEN>
649 inline dvec<LEN>
650 dvec<LEN>::map(const dvec_unop& op, int limit)
651 {
653  for (int i = 0; i < limit; i++) {
654  r.v[i] = op(data.v[i]);
655  }
656  return dvec<LEN>(r);
657 }
658 
659 
660 template <int LEN>
661 inline std::ostream&
662 operator<<(std::ostream& out, const dvec<LEN>& v)
663 {
664  out << "<";
665  for (int i = 0; i < LEN; i++) {
666  out << v.data.v[i];
667  if (i != LEN-1)
668  out << ",";
669  }
670  out << ">";
671  return out;
672 }
673 
674 class vec2d {
675 public:
676 
677  vec2d() {
678  _init(0, 0);
679  }
680 
681  vec2d(double xin, double yin) {
682  _init(xin, yin);
683  }
684 
685  vec2d(const vec2d& proto) {
686  _init(proto.v[0], proto.v[1]);
687  }
688 
689  vec2d& operator=(const vec2d& b) {
690  v[0] = b.v[0];
691  v[1] = b.v[1];
692  return *this;
693  }
694 
695  double operator[](int index) const { return v[index]; }
696 
697  double x() const { return v[0]; }
698  double y() const { return v[1]; }
699 
700  vec2d operator+(const vec2d& b) const {
701  return vec2d(v[0] + b.v[0], v[1] + b.v[1]);
702  }
703 
704  vec2d operator-(const vec2d& b) const {
705  return vec2d(v[0] - b.v[0], v[1] - b.v[1]);
706  }
707 
708  vec2d operator*(const vec2d& b) const {
709  return vec2d(v[0] * b.v[0], v[1] * b.v[1]);
710  }
711 
712  vec2d operator/(const vec2d& b) const {
713  return vec2d(v[0] / b.v[0], v[1] / b.v[1]);
714  }
715 
716  vec2d madd(const double& scalar, const vec2d& b) const {
717  return vec2d(v[0]*scalar+b.v[0], v[1]*scalar+b.v[1]);
718  }
719 
720  vec2d madd(const vec2d& s, const vec2d& b) const {
721  return vec2d(v[0]*s.v[0]+b.v[0], v[1]*s.v[1]+b.v[1]);
722  }
723 
724 private:
725  double* v;
726  double m[4];
727 
728  void _init(double xin, double yin) {
729  // align to 16-byte boundary
730  v = (double*)((((uintptr_t)m) + 0x10L) & ~0xFL);
731  v[0] = xin;
732  v[1] = yin;
733  }
734 };
735 
736 inline std::ostream&
737 operator<<(std::ostream& out, const vec2d& v)
738 {
739  out << "<" << v.x() << "," << v.y() << ">";
740  return out;
741 }
742 
743 #endif
744 /** @endcond */
745 
746 inline bool vequals(const vec2d& a, const vec2d& b) {
747  return
748  (fabs(a.x()-b.x()) < VEQUALITY) &&
749  (fabs(a.y()-b.y()) < VEQUALITY);
750 }
751 
752 // 2x2 row-major matrix
753 typedef fastf_t mat2d_t[4] VEC_ALIGN;
754 
755 /* Hide from Doxygen with cond */
756 /** @cond */
757 
758 // 2d point
759 typedef fastf_t pt2d_t[2] VEC_ALIGN;
760 
761 /** @endcond */
762 
763 //--------------------------------------------------------------------------------
764 // MATH / VECTOR ops
765 inline
766 bool mat2d_inverse(mat2d_t inv, mat2d_t m) {
767  pt2d_t _a = {m[0], m[1]};
768  pt2d_t _b = {m[3], m[2]};
769  dvec<2> a(_a);
770  dvec<2> b(_b);
771  dvec<2> c = a*b;
772  fastf_t det = c.foldr(0, dvec<2>::sub());
773  if (NEAR_ZERO(det, VUNITIZE_TOL)) return false;
774  fastf_t scale = 1.0 / det;
775  double tmp[4] VEC_ALIGN = {m[3], -m[1], -m[2], m[0]};
776  dvec<4> iv(tmp);
777  dvec<4> sv(scale);
778  dvec<4> r = iv * sv;
779  r.a_store(inv);
780  return true;
781 }
782 inline
783 void mat2d_pt2d_mul(pt2d_t r, mat2d_t m, pt2d_t p) {
784  pt2d_t _a = {m[0], m[2]};
785  pt2d_t _b = {m[1], m[3]};
786  dvec<2> x(p[0]);
787  dvec<2> y(p[1]);
788  dvec<2> a(_a);
789  dvec<2> b(_b);
790  dvec<2> c = a*x + b*y;
791  c.a_store(r);
792 }
793 inline
794 void pt2dsub(pt2d_t r, pt2d_t a, pt2d_t b) {
795  dvec<2> va(a);
796  dvec<2> vb(b);
797  dvec<2> vr = va - vb;
798  vr.a_store(r);
799 }
800 
801 inline
802 fastf_t v2mag(pt2d_t p) {
803  dvec<2> a(p);
804  dvec<2> sq = a*a;
805  return sqrt(sq.foldr(0, dvec<2>::add()));
806 }
807 
808 inline
809 void move(pt2d_t a, const double *b) {
810  a[0] = b[0];
811  a[1] = b[1];
812 }
813 }
814 
815 /** @} */
816 
817 #endif /* BN_DVEC_H */
818 
819 /*
820  * Local Variables:
821  * tab-width: 8
822  * mode: C
823  * indent-tabs-mode: t
824  * c-file-style: "stroustrup"
825  * End:
826  * ex: shiftwidth=4 tabstop=8
827  */
double operator()(double a, double b) const
Definition: dvec.h:109
double operator()(double a, double b) const
Definition: dvec.h:104
double operator()(double a) const
Definition: dvec.h:119
double operator()(double a, double b) const
Definition: dvec.h:114
Definition: dvec.h:67
virtual double operator()(double a, double b) const =0
virtual ~dvec_op()
Definition: dvec.h:70
Definition: dvec.h:61
virtual double operator()(double a) const =0
virtual ~dvec_unop()
Definition: dvec.h:64
Definition: dvec.h:74
dvec(const float *vals)
dvec(const double *vals)
void u_store(double *arr) const
dvec< LEN > operator+(const dvec< LEN > &b)
double foldr(double proto, const dvec_op &operation, int limit=LEN)
void a_store(double *arr) const
dvec< LEN > & operator=(const dvec< LEN > &p)
dvec(const dvec< LEN > &p)
dvec(double s)
bool operator==(const dvec< LEN > &b) const
dvec< LEN > madd(const double s, const dvec< LEN > &b)
void a_store(float *arr) const
dvec< LEN > map(const dvec_unop &operation, int limit=LEN)
dvec< LEN > operator*(const dvec< LEN > &b)
dvec< LEN > madd(const dvec< LEN > &s, const dvec< LEN > &b)
double operator[](int index) const
double foldl(double proto, const dvec_op &operation, int limit=LEN)
void u_store(float *arr) const
dvec< LEN > operator-(const dvec< LEN > &b)
dvec< LEN > operator/(const dvec< LEN > &b)
Header file for the BRL-CAD common definitions.
fastf_t mat2d_t[4] VEC_ALIGN
Definition: dvec.h:753
void pt2dsub(pt2d_t r, pt2d_t a, pt2d_t b)
Definition: dvec.h:794
fastf_t v2mag(pt2d_t p)
Definition: dvec.h:802
void mat2d_pt2d_mul(pt2d_t r, mat2d_t m, pt2d_t p)
Definition: dvec.h:783
bool mat2d_inverse(mat2d_t inv, mat2d_t m)
Definition: dvec.h:766
const double VEQUALITY
Definition: dvec.h:47
bool vequals(const vec2d &a, const vec2d &b)
Definition: dvec.h:746
#define VEC_ALIGN
Definition: dvec.h:131
void move(pt2d_t a, const double *b)
Definition: dvec.h:809
std::ostream & operator<<(std::ostream &out, const dvec< LEN > &v)
void int float float float * scale
Definition: tig.h:142
void float float * y
Definition: tig.h:73
void int * c
Definition: tig.h:139
void float * x
Definition: tig.h:72
#define __attribute__(ignore)
Definition: common.h:296
double fastf_t
fastest 64-bit (or larger) floating point type
Definition: vmath.h:334
#define NEAR_ZERO(val, epsilon)
Definition: vmath.h:465
#define VUNITIZE_TOL
Definition: vmath.h:299
fundamental vector, matrix, quaternion math macros