Math.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_Math_H
21 #define MIRTK_Math_H
22 
23 #include "mirtk/CommonExport.h"
24 
25 #include "mirtk/Config.h"
26 #include "mirtk/Stream.h"
27 #include "mirtk/CutilMath.h"
28 
29 #include <cmath>
30 #include <cfloat>
31 #include <limits>
32 #include <iostream>
33 #include <algorithm>
34 
35 
36 namespace mirtk {
37 
38 
39 // =============================================================================
40 // Constants
41 // =============================================================================
42 
43 /// Positive infinity
44 MIRTK_Common_EXPORT extern const double inf;
45 
46 /// Not A Number (NaN)
47 MIRTK_Common_EXPORT extern const double nan;
48 MIRTK_Common_EXPORT extern const double NaN;
49 
50 /// Constant value of \f$ \pi \f$
51 MIRTK_Common_EXPORT extern const double pi;
52 
53 /// Constant value of \f$ 2\pi \f$
54 MIRTK_Common_EXPORT extern const double two_pi;
55 
56 /// Constant value of \f$ \pi / 2 \f$
57 MIRTK_Common_EXPORT extern const double pi_half;
58 
59 /// Radians per degree, i.e., \f$ \pi / 180 \f$
60 MIRTK_Common_EXPORT extern const double rad_per_deg;
61 
62 /// Degree per radian, i.e., \f$ 180 / \pi \f$
63 MIRTK_Common_EXPORT extern const double deg_per_rad;
64 
65 // =============================================================================
66 // C/C++ library functions
67 // =============================================================================
68 
69 using std::max;
70 using std::min;
71 using std::abs;
72 using std::sqrt;
73 using std::pow;
74 using std::exp;
75 using std::log;
76 using std::sin;
77 using std::cos;
78 using std::tan;
79 using std::floor;
80 using std::ceil;
81 using std::round;
82 using std::numeric_limits;
83 using std::copysign;
84 
85 // =============================================================================
86 // Custom floating point functions
87 // =============================================================================
88 
89 // -----------------------------------------------------------------------------
90 /// Check if floating point value is not a number (NaN)
91 MIRTKCU_API inline bool IsNaN(double x)
92 {
93 #ifdef WINDOWS
94  return (_isnan(x) != 0);
95 #else
96  using std::isnan;
97  return isnan(x);
98 #endif
99 }
100 
101 // -----------------------------------------------------------------------------
102 /// Check if floating point value represents infinity
103 MIRTKCU_API inline bool IsInf(double x)
104 {
105 #ifdef WINDOWS
106  return !_finite(x);
107 #else
108  using std::isinf;
109  return isinf(x);
110 #endif
111 }
112 
113 // -----------------------------------------------------------------------------
114 /// Determine equality of two floating point numbers
115 MIRTKCU_API inline bool AreEqual(double a, double b, double tol = 1e-12)
116 {
117  return abs(a - b) < tol;
118 }
119 
120 // -----------------------------------------------------------------------------
121 /// Determine equality of two floating point numbers including check if both are NaN
122 MIRTKCU_API inline bool AreEqualOrNaN(double a, double b, double tol = 1e-12)
123 {
124  if (IsNaN(a)) return IsNaN(b);
125  if (IsNaN(b)) return IsNaN(a);
126  return AreEqual(a, b, tol);
127 }
128 
129 // -----------------------------------------------------------------------------
130 /// Determine equality of a floating point number with zero
131 MIRTKCU_API inline bool IsZero(double a, double tol = 1e-12)
132 {
133  return abs(a) < tol;
134 }
135 
136 // -----------------------------------------------------------------------------
137 /// \deprecated Use AreEqual instead.
138 MIRTKCU_API inline bool fequal(double a, double b, double tol = 1e-12)
139 {
140  return AreEqual(a, b, tol);
141 }
142 
143 // -----------------------------------------------------------------------------
144 /// Sign function - https://en.wikipedia.org/wiki/Sign_function
145 template <typename T>
146 MIRTKCU_API int sgn(T val)
147 {
148  return (T(0) < val) - (val < T(0));
149 }
150 
151 // -----------------------------------------------------------------------------
152 /// Round floating-point value to next smaller integer and cast to int
153 template <class T>
154 MIRTKCU_API inline int ifloor(T x)
155 {
156  return static_cast<int>(floor(x));
157 }
158 
159 // -----------------------------------------------------------------------------
160 /// Round floating-point value to next greater integer and cast to int
161 template <class T>
162 MIRTKCU_API inline int iceil(T x)
163 {
164  return static_cast<int>(ceil(x));
165 }
166 
167 // -----------------------------------------------------------------------------
168 /// Round floating-point value and cast to int
169 template <class T>
170 MIRTKCU_API inline int iround(T x)
171 {
172  return static_cast<int>(round(x));
173 }
174 
175 // -----------------------------------------------------------------------------
176 /// Increment floating-point number by the smallest possible amount such that
177 /// the resulting number is greater than the original number.
178 MIRTKCU_API inline double finc(double f)
179 {
180  int e;
181  double m = frexp(f, &e);
182  return ::ldexp(m + numeric_limits<double>::epsilon(), e);
183 }
184 
185 // -----------------------------------------------------------------------------
186 /// Decrement floating-point number by the smallest possible amount such that
187 /// the resulting number is less than the original number.
188 MIRTKCU_API inline double fdec(double f)
189 {
190  int e;
191  double m = frexp(f, &e);
192  return ::ldexp(m - numeric_limits<double>::epsilon(), e);
193 }
194 
195 // -----------------------------------------------------------------------------
196 /// Increment floating point number by a given amount, ensuring that the result
197 /// is not equal f.
198 ///
199 /// Note that due to roundoff errors, adding a small number to
200 /// a big number, may result in a number which is yet equal the initial big number.
201 /// This function adjusts the increment if necessary such that the result is
202 /// guaranteed to be greater (df > 0) or smaller (df < 0) than f.
203 /// If df is zero, f remains unchanged.
204 MIRTKCU_API inline double finc(double f, double df)
205 {
206  if (df == 0) return f;
207  double s = f + df;
208  if (s == f) {
209  if (df < 0) s = fdec(f);
210  else s = finc(f);
211  }
212  return s;
213 }
214 
215 // -----------------------------------------------------------------------------
216 /// Decrement floating point number by a given amount, ensuring that the result
217 /// is not equal f.
218 ///
219 /// Note that due to roundoff errors, subtracting a small number
220 /// from a big number, may result in a number which is yet equal the initial big
221 /// number. This function adjusts the decrement if necessary such that the result
222 /// is guaranteed to be smaller (df > 0) or greater (df < 0) than f.
223 /// If df is zero, f remains unchanged.
224 MIRTKCU_API inline double fdec(double f, double df)
225 {
226  if (df == 0) return f;
227  double s = f - df;
228  if (s == f) {
229  if (df < 0) s = finc(f);
230  else s = fdec(f);
231  }
232  return s;
233 }
234 
235 // -----------------------------------------------------------------------------
236 /// S-shaped monotone increasing membership function whose value is in [0, 1]
237 /// for x in [a, b]. It is equivalent to MATLAB's smf function.
238 inline double SShapedMembershipFunction(double x, double a, double b)
239 {
240  if (x <= a) {
241  return 0.;
242  } else if (x >= b) {
243  return 1.;
244  } else if (x <= .5 * (a + b)) {
245  const double t = (x - a) / (b - a);
246  return 2. * t * t;
247  } else {
248  const double t = (x - b) / (b - a);
249  return 1. - 2. * t * t;
250  }
251 }
252 
253 // =============================================================================
254 // Data structures
255 // =============================================================================
256 
257 // -----------------------------------------------------------------------------
258 // Single-precision floating points
259 // -----------------------------------------------------------------------------
260 
261 // -----------------------------------------------------------------------------
262 /// 2x2 single-precision matrix
263 struct float2x2 {
264  float2 a;
265  float2 b;
266 
267  MIRTKCU_API float2x2 &operator =(float s)
268  {
269  a.x = a.y = b.x = b.y = s;
270  return *this;
271  }
272 
273  MIRTKCU_API float2x2 &operator =(const float2x2& rhs)
274  {
275  a = rhs.a, b = rhs.b;
276  return *this;
277  }
278 
279 };
280 typedef struct float2x2 float2x2;
281 
282 // -----------------------------------------------------------------------------
283 /// 3x3 single-precision matrix
284 struct float3x3 {
285  float3 a;
286  float3 b;
287  float3 c;
288 
289  MIRTKCU_API float3x3 &operator =(float s)
290  {
291  a.x = a.y = a.z = b.x = b.y = b.z = c.x = c.y = c.z = s;
292  return *this;
293  }
294 
295  MIRTKCU_API float3x3 &operator =(const float3x3& rhs)
296  {
297  a = rhs.a, b = rhs.b, c = rhs.c;
298  return *this;
299  }
300 
301 };
302 typedef struct float3x3 float3x3;
303 
304 // -----------------------------------------------------------------------------
305 /// 4x4 single-precision matrix
306 struct float4x4 {
307  float4 a;
308  float4 b;
309  float4 c;
310  float4 d;
311 
312  MIRTKCU_API float4x4 &operator =(float s)
313  {
314  a.x = a.y = a.z = a.w = b.x = b.y = b.z = b.w = c.x = c.y = c.z = c.w = d.x = d.y = d.z = d.w = s;
315  return *this;
316  }
317 
318  MIRTKCU_API float4x4 &operator =(const float4x4& rhs)
319  {
320  a = rhs.a, b = rhs.b, c = rhs.c, d = rhs.d;
321  return *this;
322  }
323 
324 };
325 typedef struct float4x4 float4x4;
326 
327 // -----------------------------------------------------------------------------
328 /// 3x4 single-precision coordinate transformation matrix
329 struct float3x4 {
330  float4 a;
331  float4 b;
332  float4 c;
333 
334  MIRTKCU_API float3x4 &operator =(float s)
335  {
336  a.x = a.y = a.z = a.w = b.x = b.y = b.z = b.w = c.x = c.y = c.z = c.w = s;
337  return *this;
338  }
339 
340  MIRTKCU_API float3x4 &operator =(const float3x4& rhs)
341  {
342  a = rhs.a, b = rhs.b, c = rhs.c;
343  return *this;
344  }
345 
346 };
347 typedef struct float3x4 float3x4;
348 
349 // -----------------------------------------------------------------------------
350 // Double-precision floating points
351 // -----------------------------------------------------------------------------
352 
353 // -----------------------------------------------------------------------------
354 /// 2x2 double-precision matrix
355 struct double2x2 {
356  double2 a;
357  double2 b;
358 
359  MIRTKCU_API double2x2 &operator =(double s)
360  {
361  a.x = a.y = b.x = b.y = s;
362  return *this;
363  }
364 
365  MIRTKCU_API double2x2 &operator =(const double2x2& rhs)
366  {
367  a = rhs.a, b = rhs.b;
368  return *this;
369  }
370 };
371 typedef struct double2x2 double2x2;
372 
373 // -----------------------------------------------------------------------------
374 /// 3x3 double-precision matrix
375 struct double3x3 {
376  double3 a;
377  double3 b;
378  double3 c;
379 
380  MIRTKCU_API double3x3 &operator =(double s)
381  {
382  a.x = a.y = a.z = b.x = b.y = b.z = c.x = c.y = c.z = s;
383  return *this;
384  }
385 
386  MIRTKCU_API double3x3 &operator =(const double3x3& rhs)
387  {
388  a = rhs.a, b = rhs.b, c = rhs.c;
389  return *this;
390  }
391 };
392 typedef struct double3x3 double3x3;
393 
394 // -----------------------------------------------------------------------------
395 /// 4x4 double-precision matrix
396 struct double4x4 {
397  double4 a;
398  double4 b;
399  double4 c;
400  double4 d;
401 
402  MIRTKCU_API double4x4 &operator =(double s)
403  {
404  a.x = a.y = a.z = a.w = b.x = b.y = b.z = b.w = c.x = c.y = c.z = c.w = d.x = d.y = d.z = d.w = s;
405  return *this;
406  }
407 
408  MIRTKCU_API double4x4 &operator =(const double4x4& rhs)
409  {
410  a = rhs.a, b = rhs.b, c = rhs.c, d = rhs.d;
411  return *this;
412  }
413 };
414 typedef struct double4x4 double4x4;
415 
416 // -----------------------------------------------------------------------------
417 /// 3x4 double-precision coordinate transformation matrix
418 struct double3x4 {
419  double4 a;
420  double4 b;
421  double4 c;
422 
423  MIRTKCU_API double3x4 &operator =(double s)
424  {
425  a.x = a.y = a.z = a.w = b.x = b.y = b.z = b.w = c.x = c.y = c.z = c.w = s;
426  return *this;
427  }
428 
429  MIRTKCU_API double3x4 &operator =(const double3x4& rhs)
430  {
431  a = rhs.a, b = rhs.b, c = rhs.c;
432  return *this;
433  }
434 };
435 typedef struct double3x4 double3x4;
436 
437 // =============================================================================
438 // Initialization
439 // =============================================================================
440 
441 // -----------------------------------------------------------------------------
442 // Integral types
443 // -----------------------------------------------------------------------------
444 
445 // -----------------------------------------------------------------------------
446 MIRTKCU_API inline int4 make_int4(double4 a)
447 {
448  return make_int4(int(a.x), int(a.y), int(a.z), int(a.w));
449 }
450 
451 // -----------------------------------------------------------------------------
452 // Single-precision floating points
453 // -----------------------------------------------------------------------------
454 
455 // -----------------------------------------------------------------------------
456 // Construct single-precision floating point scalar from double-precision
457 MIRTKCU_API inline float1 make_float1(double x)
458 {
459  return make_float1(float(x));
460 }
461 
462 // -----------------------------------------------------------------------------
463 // Construct single-precision floating point scalar from double-precision
464 MIRTKCU_API inline float1 make_float1(double1 d)
465 {
466  return make_float1(d.x);
467 }
468 
469 // -----------------------------------------------------------------------------
470 // Construct single-precision floating point 2D vector from double-precision
471 MIRTKCU_API inline float2 make_float2(double x, double y)
472 {
473  return make_float2(float(x), float(y));
474 }
475 
476 // -----------------------------------------------------------------------------
477 // Construct single-precision floating point 2D vector from double-precision
478 MIRTKCU_API inline float2 make_float2(double2 d)
479 {
480  return make_float2(d.x, d.y);
481 }
482 
483 // -----------------------------------------------------------------------------
484 // Construct single-precision floating point 3D vector from double-precision
485 MIRTKCU_API inline float3 make_float3(double x, double y, double z)
486 {
487  return make_float3(float(x), float(y), float(z));
488 }
489 
490 // -----------------------------------------------------------------------------
491 // Construct single-precision floating point 3D vector from double-precision
492 MIRTKCU_API inline float3 make_float3(double3 d)
493 {
494  return make_float3(d.x, d.y, d.z);
495 }
496 
497 // -----------------------------------------------------------------------------
498 // Construct single-precision floating point 4D vector from double-precision
499 MIRTKCU_API inline float4 make_float4(double x, double y, double z, double w)
500 {
501  return make_float4(float(x), float(y), float(z), float(w));
502 }
503 
504 // -----------------------------------------------------------------------------
505 // Construct single-precision floating point 4D vector from double-precision
506 MIRTKCU_API inline float4 make_float4(double4 d)
507 {
508  return make_float4(d.x, d.y, d.z, d.w);
509 }
510 
511 // -----------------------------------------------------------------------------
512 // Construct float3x3 matrix from scalar
513 MIRTKCU_API inline float3x3 make_float3x3(float s)
514 {
515  float3x3 m;
516  m.a = make_float3(s);
517  m.b = make_float3(s);
518  m.c = make_float3(s);
519  return m;
520 }
521 
522 // -----------------------------------------------------------------------------
523 // Construct 3x3 matrix from upper left sub-matrix of 3x4 matrix
524 MIRTKCU_API inline float3x3 make_float3x3(float3x4 m)
525 {
526  float3x3 d;
527  d.a = make_float3(m.a.x, m.a.y, m.a.z);
528  d.b = make_float3(m.b.x, m.b.y, m.b.z);
529  d.c = make_float3(m.c.x, m.c.y, m.c.z);
530  return d;
531 }
532 
533 // -----------------------------------------------------------------------------
534 // Construct single-precision floating point 3x3 matrix from double-precision
535 MIRTKCU_API inline float3x3 make_float3x3(double3x3 m)
536 {
537  float3x3 d;
538  d.a = make_float3(m.a.x, m.a.y, m.a.z);
539  d.b = make_float3(m.b.x, m.b.y, m.b.z);
540  d.c = make_float3(m.c.x, m.c.y, m.c.z);
541  return d;
542 }
543 
544 // -----------------------------------------------------------------------------
545 /// Copy and cast image to single-precision floating point
546 template <class VoxelType>
547 MIRTKCU_HOST_API float *to_float(const VoxelType *in, unsigned int N)
548 {
549  float *out = new float[N];
550  for (unsigned int i = 0; i < N; i++) out[i] = float(in[i]);
551  return out;
552 }
553 
554 // -----------------------------------------------------------------------------
555 // Double-precision floating points
556 // -----------------------------------------------------------------------------
557 
558 // -----------------------------------------------------------------------------
559 /// Create double scalar value
560 MIRTKCU_API inline double1 make_double1(float1 f)
561 {
562  return make_double1(f.x);
563 }
564 
565 // -----------------------------------------------------------------------------
566 /// Create double 2D vector from scalar
567 MIRTKCU_API inline double2 make_double2(double s)
568 {
569  return make_double2(s, s);
570 }
571 
572 // -----------------------------------------------------------------------------
573 /// Create double 2D vector from single-precision
574 MIRTKCU_API inline double2 make_double2(float2 f)
575 {
576  return make_double2(f.x, f.y);
577 }
578 
579 // -----------------------------------------------------------------------------
580 /// Create double 2D vector from integer vector
581 MIRTKCU_API inline double2 make_double2(int2 i)
582 {
583  return make_double2(double(i.x), double(i.y));
584 }
585 
586 // -----------------------------------------------------------------------------
587 /// Create double 2D vector from integer vector
588 MIRTKCU_API inline double2 make_double2(uint2 i)
589 {
590  return make_double2(double(i.x), double(i.y));
591 }
592 
593 // -----------------------------------------------------------------------------
594 /// Create double 3D vector from scalar
595 MIRTKCU_API inline double3 make_double3(double s)
596 {
597  return make_double3(s, s, s);
598 }
599 
600 // -----------------------------------------------------------------------------
601 /// Create double 3D vector from integer vector
602 MIRTKCU_API inline double3 make_double3(int3 i)
603 {
604  return make_double3(double(i.x), double(i.y), double(i.z));
605 }
606 
607 // -----------------------------------------------------------------------------
608 /// Create double 3D vector from integer vector
609 MIRTKCU_API inline double3 make_double3(uint3 i)
610 {
611  return make_double3(double(i.x), double(i.y), double(i.z));
612 }
613 
614 // -----------------------------------------------------------------------------
615 /// Create double 3D vector from single-precision
616 MIRTKCU_API inline double3 make_double3(float3 f)
617 {
618  return make_double3(f.x, f.y, f.z);
619 }
620 
621 // -----------------------------------------------------------------------------
622 /// Create double 4D vector from scalar
623 MIRTKCU_API inline double4 make_double4(double s)
624 {
625  return make_double4(s, s, s, s);
626 }
627 
628 // -----------------------------------------------------------------------------
629 /// Create double 4D vector from integer vector
630 MIRTKCU_API inline double4 make_double4(int4 i)
631 {
632  return make_double4(double(i.x), double(i.y), double(i.z), double(i.w));
633 }
634 
635 // -----------------------------------------------------------------------------
636 /// Create double 4D vector from single-precision
637 MIRTKCU_API inline double4 make_double4(float4 f)
638 {
639  return make_double4(f.x, f.y, f.z, f.w);
640 }
641 
642 // -----------------------------------------------------------------------------
643 // Construct double3x3 matrix from scalar
644 MIRTKCU_API inline double3x3 make_double3x3(double s)
645 {
646  double3x3 d;
647  d.a = make_double3(s);
648  d.b = make_double3(s);
649  d.c = make_double3(s);
650  return d;
651 }
652 
653 // -----------------------------------------------------------------------------
654 // Construct double-precision floating point 3x3 matrix from single-precision
655 MIRTKCU_API inline double3x3 make_double3x3(float3x3 m)
656 {
657  double3x3 d;
658  d.a = make_double3(m.a.x, m.a.y, m.a.z);
659  d.b = make_double3(m.b.x, m.b.y, m.b.z);
660  d.c = make_double3(m.c.x, m.c.y, m.c.z);
661  return d;
662 }
663 
664 // -----------------------------------------------------------------------------
665 // Construct 3x3 matrix from upper left sub-matrix of 3x4 matrix
666 MIRTKCU_API inline double3x3 make_double3x3(double3x4 m)
667 {
668  double3x3 d;
669  d.a = make_double3(m.a.x, m.a.y, m.a.z);
670  d.b = make_double3(m.b.x, m.b.y, m.b.z);
671  d.c = make_double3(m.c.x, m.c.y, m.c.z);
672  return d;
673 }
674 
675 // =============================================================================
676 // Transpose
677 // =============================================================================
678 
679 // -----------------------------------------------------------------------------
680 /// Transpose 2x2 matrix
681 MIRTKCU_API inline float2x2 transpose(float2x2 m)
682 {
683  float2x2 t;
684  t.a = make_float2(m.a.x, m.b.x);
685  t.b = make_float2(m.a.y, m.b.y);
686  return t;
687 }
688 
689 // -----------------------------------------------------------------------------
690 /// Transpose 3x3 matrix
691 MIRTKCU_API inline float3x3 transpose(float3x3 m)
692 {
693  float3x3 t;
694  t.a = make_float3(m.a.x, m.b.x, m.c.x);
695  t.b = make_float3(m.a.y, m.b.y, m.c.y);
696  t.c = make_float3(m.a.z, m.b.z, m.c.z);
697  return t;
698 }
699 
700 // -----------------------------------------------------------------------------
701 /// Transpose 2x2 matrix
702 MIRTKCU_API inline double2x2 transpose(double2x2 m)
703 {
704  double2x2 t;
705  t.a = make_double2(m.a.x, m.b.x);
706  t.b = make_double2(m.a.y, m.b.y);
707  return t;
708 }
709 
710 // -----------------------------------------------------------------------------
711 /// Transpose 3x3 matrix
712 MIRTKCU_API inline double3x3 transpose(double3x3 m)
713 {
714  double3x3 t;
715  t.a = make_double3(m.a.x, m.b.x, m.c.x);
716  t.b = make_double3(m.a.y, m.b.y, m.c.y);
717  t.c = make_double3(m.a.z, m.b.z, m.c.z);
718  return t;
719 }
720 
721 // =============================================================================
722 // Comparison operators
723 // =============================================================================
724 
725 // -----------------------------------------------------------------------------
726 // Equality
727 // -----------------------------------------------------------------------------
728 
729 // -----------------------------------------------------------------------------
730 /// Check two 1D vectors for equality
731 MIRTKCU_API inline bool operator ==(const float1 &a, const float1 &b)
732 {
733  return (a.x == b.x);
734 }
735 
736 // -----------------------------------------------------------------------------
737 /// Check two 2D vectors for equality
738 MIRTKCU_API inline bool operator ==(const float2 &a, const float2 &b)
739 {
740  return (a.x == b.x && a.y == b.y);
741 }
742 
743 // -----------------------------------------------------------------------------
744 /// Check two 3D vectors for equality
745 MIRTKCU_API inline bool operator ==(const float3 &a, const float3 &b)
746 {
747  return (a.x == b.x && a.y == b.y && a.z == b.z);
748 }
749 
750 // -----------------------------------------------------------------------------
751 /// Check two 4D vectors for equality
752 MIRTKCU_API inline bool operator ==(const float4 &a, const float4 &b)
753 {
754  return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
755 }
756 
757 // -----------------------------------------------------------------------------
758 /// Check two 3x3 matrices for equality
759 MIRTKCU_API inline bool operator ==(const float3x3 &a, const float3x3 &b)
760 {
761  return (a.a == b.a && a.b == b.b && a.c == b.c);
762 }
763 
764 // -----------------------------------------------------------------------------
765 /// Check two 3x4 matrices for equality
766 MIRTKCU_API inline bool operator ==(const float3x4 &a, const float3x4 &b)
767 {
768  return (a.a == b.a && a.b == b.b && a.c == b.c);
769 }
770 
771 // -----------------------------------------------------------------------------
772 /// Check two 4x4 matrices for equality
773 MIRTKCU_API inline bool operator ==(const float4x4 &a, const float4x4 &b)
774 {
775  return (a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d);
776 }
777 
778 // -----------------------------------------------------------------------------
779 /// Check two 1D vectors for equality
780 MIRTKCU_API inline bool operator ==(const double1 &a, const double1 &b)
781 {
782  return (a.x == b.x);
783 }
784 
785 // -----------------------------------------------------------------------------
786 /// Check two 2D vectors for equality
787 MIRTKCU_API inline bool operator ==(const double2 &a, const double2 &b)
788 {
789  return (a.x == b.x && a.y == b.y);
790 }
791 
792 // -----------------------------------------------------------------------------
793 /// Check two 3D vectors for equality
794 MIRTKCU_API inline bool operator ==(const double3 &a, const double3 &b)
795 {
796  return (a.x == b.x && a.y == b.y && a.z == b.z);
797 }
798 
799 // -----------------------------------------------------------------------------
800 /// Check two 4D vectors for equality
801 MIRTKCU_API inline bool operator ==(const double4 &a, const double4 &b)
802 {
803  return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
804 }
805 
806 // -----------------------------------------------------------------------------
807 /// Check two 3x3 matrices for equality
808 MIRTKCU_API inline bool operator ==(const double3x3 &a, const double3x3 &b)
809 {
810  return (a.a == b.a && a.b == b.b && a.c == b.c);
811 }
812 
813 // -----------------------------------------------------------------------------
814 /// Check two 3x4 matrices for equality
815 MIRTKCU_API inline bool operator ==(const double3x4 &a, const double3x4 &b)
816 {
817  return (a.a == b.a && a.b == b.b && a.c == b.c);
818 }
819 
820 // -----------------------------------------------------------------------------
821 /// Check two 4x4 matrices for equality
822 MIRTKCU_API inline bool operator ==(const double4x4 &a, const double4x4 &b)
823 {
824  return (a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d);
825 }
826 
827 // -----------------------------------------------------------------------------
828 // Lexicographical less than (cf. STL lexicographical_compare)
829 // -----------------------------------------------------------------------------
830 
831 // -----------------------------------------------------------------------------
832 /// Check if 1D vector is lexicographically less than another
833 MIRTKCU_API inline bool operator <(const float1 &a, const float1 &b)
834 {
835  return (a.x < b.x);
836 }
837 
838 // -----------------------------------------------------------------------------
839 /// Check if 2D vector is lexicographically less than another
840 MIRTKCU_API inline bool operator <(const float2 &a, const float2 &b)
841 {
842  return (a.x < b.x || (a.x == b.x && a.y < b.y));
843 }
844 
845 // -----------------------------------------------------------------------------
846 /// Check if 3D vector is lexicographically less than another
847 MIRTKCU_API inline bool operator <(const float3 &a, const float3 &b)
848 {
849  return (a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z))));
850 }
851 
852 // -----------------------------------------------------------------------------
853 /// Check if 4D vector is lexicographically less than another
854 MIRTKCU_API inline bool operator <(const float4 &a, const float4 &b)
855 {
856  return (a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && (a.z < b.z || (a.z == b.z && a.w < b.w))))));
857 }
858 
859 // -----------------------------------------------------------------------------
860 /// Check if 1D vector is lexicographically less than another
861 MIRTKCU_API inline bool operator <(const double1 &a, const double1 &b)
862 {
863  return (a.x < b.x);
864 }
865 
866 // -----------------------------------------------------------------------------
867 /// Check if 2D vector is lexicographically less than another
868 MIRTKCU_API inline bool operator <(const double2 &a, const double2 &b)
869 {
870  return (a.x < b.x || (a.x == b.x && a.y < b.y));
871 }
872 
873 // -----------------------------------------------------------------------------
874 /// Check if 3D vector is lexicographically less than another
875 MIRTKCU_API inline bool operator <(const double3 &a, const double3 &b)
876 {
877  return (a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z))));
878 }
879 
880 // -----------------------------------------------------------------------------
881 /// Check if 4D vector is lexicographically less than another
882 MIRTKCU_API inline bool operator <(const double4 &a, const double4 &b)
883 {
884  return (a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && (a.z < b.z || (a.z == b.z && a.w < b.w))))));
885 }
886 
887 // -----------------------------------------------------------------------------
888 // Other comparison operators based on equality and less than comparison
889 // -----------------------------------------------------------------------------
890 
891 #define __other_comp(T) \
892  MIRTKCU_API inline bool operator !=(const T &a, const T &b) { return !(a == b); } \
893  MIRTKCU_API inline bool operator <=(const T &a, const T &b) { return !(b < a); } \
894  MIRTKCU_API inline bool operator > (const T &a, const T &b) { return (b < a); } \
895  MIRTKCU_API inline bool operator >=(const T &a, const T &b) { return !(a < b); }
896 
897 // -----------------------------------------------------------------------------
898 __other_comp(float1);
899 __other_comp(float2);
900 __other_comp(float3);
901 __other_comp(float4);
902 
903 // -----------------------------------------------------------------------------
904 __other_comp(double1);
905 __other_comp(double2);
906 __other_comp(double3);
907 __other_comp(double4);
908 
909 // -----------------------------------------------------------------------------
910 MIRTKCU_API inline bool operator !=(const float3x3 &a, const float3x3 &b) { return !(a == b); }
911 MIRTKCU_API inline bool operator !=(const float3x4 &a, const float3x4 &b) { return !(a == b); }
912 MIRTKCU_API inline bool operator !=(const float4x4 &a, const float4x4 &b) { return !(a == b); }
913 
914 // -----------------------------------------------------------------------------
915 MIRTKCU_API inline bool operator !=(const double3x3 &a, const double3x3 &b) { return !(a == b); }
916 MIRTKCU_API inline bool operator !=(const double3x4 &a, const double3x4 &b) { return !(a == b); }
917 MIRTKCU_API inline bool operator !=(const double4x4 &a, const double4x4 &b) { return !(a == b); }
918 
919 #undef __other_comp
920 
921 // -----------------------------------------------------------------------------
922 // Clamp -- additional overloads to those defined in cutil_math.h
923 // -----------------------------------------------------------------------------
924 
925 // -----------------------------------------------------------------------------
926 /// Clamp the value v to be in the range [a, b]
927 MIRTKCU_API inline double clamp(double f, double a, double b)
928 {
929  return max(a, min(f, b));
930 }
931 
932 // -----------------------------------------------------------------------------
933 // Miscellaneous
934 // -----------------------------------------------------------------------------
935 
936 // -----------------------------------------------------------------------------
937 /// Component-wise comparison operator for voxel coordinates with scalar value
938 MIRTKCU_API inline bool operator ==(uint3 p, unsigned int s)
939 {
940  return p.x == s && p.y == s && p.z == s;
941 }
942 
943 // -----------------------------------------------------------------------------
944 /// Comparison operator for voxel coordinates with image dimensions
945 MIRTKCU_API inline bool operator <(uint3 p, uint3 dim)
946 {
947  return p.x < dim.x || p.y < dim.y || p.z < dim.z;
948 }
949 
950 // -----------------------------------------------------------------------------
951 /// Comparison operator for voxel coordinates with image dimensions
952 MIRTKCU_API inline bool operator >(uint3 p, uint3 dim)
953 {
954  return p.x > dim.x || p.y > dim.y || p.z > dim.z;
955 }
956 
957 // -----------------------------------------------------------------------------
958 /// Comparison operator for voxel coordinates with image dimensions
959 MIRTKCU_API inline bool operator >=(uint3 p, uint3 dim)
960 {
961  return p.x >= dim.x || p.y >= dim.y || p.z >= dim.z;
962 }
963 
964 // =============================================================================
965 // Arithmetic operators
966 // =============================================================================
967 
968 // -----------------------------------------------------------------------------
969 // Miscellaneous
970 // -----------------------------------------------------------------------------
971 
972 // -----------------------------------------------------------------------------
973 /// Multiply blockIdx and blockDim
974 MIRTKCU_API inline uint3 operator *(uint3 idx, dim3 dim)
975 {
976  return make_uint3(idx.x * dim.x, idx.y * dim.y, idx.z * dim.z);
977 }
978 
979 // -----------------------------------------------------------------------------
980 /// Multiply blockDim and blockIdx
981 MIRTKCU_API inline uint3 operator *(dim3 dim, uint3 idx)
982 {
983  return idx * dim;
984 }
985 
986 // -----------------------------------------------------------------------------
987 // Single-precision floating points
988 // -----------------------------------------------------------------------------
989 
990 // -----------------------------------------------------------------------------
991 /// Add two 1D vectors
992 MIRTKCU_API inline void operator +=(float1 &a, float1 b)
993 {
994  a.x += b.x;
995 }
996 
997 // -----------------------------------------------------------------------------
998 // cutil_math.h
999 // - Add two 2D vectors
1000 // - Add two 3D vectors
1001 // - Add two 4D vectors
1002 
1003 // -----------------------------------------------------------------------------
1004 /// Add scalar to 2x2 matrix
1005 MIRTKCU_API inline void operator +=(float2x2 &m, float s)
1006 {
1007  m.a += s, m.b += s;
1008 }
1009 
1010 // -----------------------------------------------------------------------------
1011 /// Add scalar to 3x3 matrix
1012 MIRTKCU_API inline void operator +=(float3x3 &m, float s)
1013 {
1014  m.a += s, m.b += s, m.c += s;
1015 }
1016 
1017 // -----------------------------------------------------------------------------
1018 /// Add scalar to 3x4 matrix
1019 MIRTKCU_API inline void operator +=(float3x4 &m, float s)
1020 {
1021  m.a += s, m.b += s, m.c += s;
1022 }
1023 
1024 // -----------------------------------------------------------------------------
1025 /// Add scalar to 4x4 matrix
1026 MIRTKCU_API inline void operator +=(float4x4 &m, float s)
1027 {
1028  m.a += s, m.b += s, m.c += s, m.d += s;
1029 }
1030 
1031 // -----------------------------------------------------------------------------
1032 /// Add two 2x2 matrices
1033 MIRTKCU_API inline void operator +=(float2x2 &a, float2x2 b)
1034 {
1035  a.a += b.a, a.b += b.b;
1036 }
1037 
1038 // -----------------------------------------------------------------------------
1039 /// Add two 3x3 matrices
1040 MIRTKCU_API inline void operator +=(float3x3 &a, float3x3 b)
1041 {
1042  a.a += b.a, a.b += b.b, a.c += b.c;
1043 }
1044 
1045 // -----------------------------------------------------------------------------
1046 /// Add two 3x4 matrices
1047 MIRTKCU_API inline void operator +=(float3x4 &a, float3x4 b)
1048 {
1049  a.a += b.a, a.b += b.b, a.c += b.c;
1050 }
1051 
1052 // -----------------------------------------------------------------------------
1053 /// Add two 4x4 matrices
1054 MIRTKCU_API inline void operator +=(float4x4 &a, float4x4 b)
1055 {
1056  a.a += b.a, a.b += b.b, a.c += b.c, a.d += b.d;
1057 }
1058 
1059 // -----------------------------------------------------------------------------
1060 /// Add two 1D vectors
1061 MIRTKCU_API inline float1 operator +(float1 a, float1 b)
1062 {
1063  return make_float1(a.x + b.x);
1064 }
1065 
1066 // -----------------------------------------------------------------------------
1067 // cutil_math.h
1068 // - Add two 2D vectors
1069 // - Add two 3D vectors
1070 // - Add two 4D vectors
1071 
1072 // -----------------------------------------------------------------------------
1073 /// Add scalar to 2x2 matrix
1074 MIRTKCU_API inline float2x2 operator +(float2x2 m, float s)
1075 {
1076  float2x2 o = m;
1077  o += s;
1078  return o;
1079 }
1080 
1081 // -----------------------------------------------------------------------------
1082 /// Add scalar to 3x3 matrix
1083 MIRTKCU_API inline float3x3 operator +(float3x3 m, float s)
1084 {
1085  float3x3 o = m;
1086  o += s;
1087  return o;
1088 }
1089 
1090 // -----------------------------------------------------------------------------
1091 /// Add scalar to 3x4 matrix
1092 MIRTKCU_API inline float3x4 operator +(float3x4 m, float s)
1093 {
1094  float3x4 o = m;
1095  o += s;
1096  return o;
1097 }
1098 
1099 // -----------------------------------------------------------------------------
1100 /// Add scalar to 4x4 matrix
1101 MIRTKCU_API inline float4x4 operator +(float4x4 m, float s)
1102 {
1103  float4x4 o = m;
1104  o += s;
1105  return o;
1106 }
1107 
1108 // -----------------------------------------------------------------------------
1109 /// Add two 2x2 matrices
1110 MIRTKCU_API inline float2x2 operator +(float2x2 a, float2x2 b)
1111 {
1112  float2x2 o;
1113  o.a = a.a + b.a;
1114  o.b = a.b + b.b;
1115  return o;
1116 }
1117 
1118 // -----------------------------------------------------------------------------
1119 /// Add two 3x3 matrices
1120 MIRTKCU_API inline float3x3 operator +(float3x3 a, float3x3 b)
1121 {
1122  float3x3 o;
1123  o.a = a.a + b.a;
1124  o.b = a.b + b.b;
1125  o.c = a.c + b.c;
1126  return o;
1127 }
1128 
1129 // -----------------------------------------------------------------------------
1130 /// Add two 3x4 matrices
1131 MIRTKCU_API inline float3x4 operator +(float3x4 a, float3x4 b)
1132 {
1133  float3x4 o;
1134  o.a = a.a + b.a;
1135  o.b = a.b + b.b;
1136  o.c = a.c + b.c;
1137  return o;
1138 }
1139 
1140 // -----------------------------------------------------------------------------
1141 /// Add two 4x4 matrices
1142 MIRTKCU_API inline float4x4 operator +(float4x4 a, float4x4 b)
1143 {
1144  float4x4 o;
1145  o.a = a.a + b.a;
1146  o.b = a.b + b.b;
1147  o.c = a.c + b.c;
1148  o.d = a.d + b.d;
1149  return o;
1150 }
1151 
1152 // -----------------------------------------------------------------------------
1153 /// Subtract two 1D vectors
1154 MIRTKCU_API inline void operator -=(float1 &a, float1 b)
1155 {
1156  a.x -= b.x;
1157 }
1158 
1159 // -----------------------------------------------------------------------------
1160 // cutil_math.h
1161 // - Subtract two 2D vectors
1162 // - Subtract two 3D vectors
1163 // - Subtract two 4D vectors
1164 
1165 // -----------------------------------------------------------------------------
1166 /// Subtract scalar from 2x2 matrix
1167 MIRTKCU_API inline void operator -=(float2x2 &m, float s)
1168 {
1169  m.a -= s, m.b -= s;
1170 }
1171 
1172 // -----------------------------------------------------------------------------
1173 /// Subtract scalar from 3x3 matrix
1174 MIRTKCU_API inline void operator -=(float3x3 &m, float s)
1175 {
1176  m.a -= s, m.b -= s, m.c -= s;
1177 }
1178 
1179 // -----------------------------------------------------------------------------
1180 /// Subtract scalar from 3x4 matrix
1181 MIRTKCU_API inline void operator -=(float3x4 &m, float s)
1182 {
1183  m.a -= s, m.b -= s, m.c -= s;
1184 }
1185 
1186 // -----------------------------------------------------------------------------
1187 /// Subtract scalar from 4x4 matrix
1188 MIRTKCU_API inline void operator -=(float4x4 &m, float s)
1189 {
1190  m.a -= s, m.b -= s, m.c -= s, m.d -= s;
1191 }
1192 
1193 // -----------------------------------------------------------------------------
1194 /// Subtract two 2x2 matrices
1195 MIRTKCU_API inline void operator -=(float2x2 &a, float2x2 b)
1196 {
1197  a.a -= b.a, a.b -= b.b;
1198 }
1199 
1200 // -----------------------------------------------------------------------------
1201 /// Subtract two 3x3 matrices
1202 MIRTKCU_API inline void operator -=(float3x3 &a, float3x3 b)
1203 {
1204  a.a -= b.a, a.b -= b.b, a.c -= b.c;
1205 }
1206 
1207 // -----------------------------------------------------------------------------
1208 /// Subtract two 3x4 matrices
1209 MIRTKCU_API inline void operator -=(float3x4 &a, float3x4 b)
1210 {
1211  a.a -= b.a, a.b -= b.b, a.c -= b.c;
1212 }
1213 
1214 // -----------------------------------------------------------------------------
1215 /// Subtract two 4x4 matrices
1216 MIRTKCU_API inline void operator -=(float4x4 &a, float4x4 b)
1217 {
1218  a.a -= b.a, a.b -= b.b, a.c -= b.c, a.d -= b.d;
1219 }
1220 
1221 // -----------------------------------------------------------------------------
1222 /// Subtract two 1D vectors
1223 MIRTKCU_API inline float1 operator -(float1 a, float1 b)
1224 {
1225  return make_float1(a.x - b.x);
1226 }
1227 
1228 // -----------------------------------------------------------------------------
1229 // cutil_math.h
1230 // - Subtract two 2D vectors
1231 // - Subtract two 3D vectors
1232 // - Subtract two 4D vectors
1233 
1234 // -----------------------------------------------------------------------------
1235 /// Subtract scalar from 2x2 matrix
1236 MIRTKCU_API inline float2x2 operator -(float2x2 m, float s)
1237 {
1238  float2x2 o = m;
1239  o -= s;
1240  return o;
1241 }
1242 
1243 // -----------------------------------------------------------------------------
1244 /// Subtract scalar from 3x3 matrix
1245 MIRTKCU_API inline float3x3 operator -(float3x3 m, float s)
1246 {
1247  float3x3 o = m;
1248  o -= s;
1249  return o;
1250 }
1251 
1252 // -----------------------------------------------------------------------------
1253 /// Subtract scalar from 3x4 matrix
1254 MIRTKCU_API inline float3x4 operator -(float3x4 m, float s)
1255 {
1256  float3x4 o = m;
1257  o -= s;
1258  return o;
1259 }
1260 
1261 // -----------------------------------------------------------------------------
1262 /// Subtract scalar from 4x4 matrix
1263 MIRTKCU_API inline float4x4 operator -(float4x4 m, float s)
1264 {
1265  float4x4 o = m;
1266  o -= s;
1267  return o;
1268 }
1269 
1270 // -----------------------------------------------------------------------------
1271 /// Subtract two 2x2 matrices
1272 MIRTKCU_API inline float2x2 operator -(float2x2 a, float2x2 b)
1273 {
1274  float2x2 o;
1275  o.a = a.a - b.a;
1276  o.b = a.b - b.b;
1277  return o;
1278 }
1279 
1280 // -----------------------------------------------------------------------------
1281 /// Subtract two 3x3 matrices
1282 MIRTKCU_API inline float3x3 operator -(float3x3 a, float3x3 b)
1283 {
1284  float3x3 o;
1285  o.a = a.a - b.a;
1286  o.b = a.b - b.b;
1287  o.c = a.c - b.c;
1288  return o;
1289 }
1290 
1291 // -----------------------------------------------------------------------------
1292 /// Subtract two 3x4 matrices
1293 MIRTKCU_API inline float3x4 operator -(float3x4 a, float3x4 b)
1294 {
1295  float3x4 o;
1296  o.a = a.a - b.a;
1297  o.b = a.b - b.b;
1298  o.c = a.c - b.c;
1299  return o;
1300 }
1301 
1302 // -----------------------------------------------------------------------------
1303 /// Subtract two 4x4 matrices
1304 MIRTKCU_API inline float4x4 operator -(float4x4 a, float4x4 b)
1305 {
1306  float4x4 o;
1307  o.a = a.a - b.a;
1308  o.b = a.b - b.b;
1309  o.c = a.c - b.c;
1310  o.d = a.d - b.d;
1311  return o;
1312 }
1313 
1314 // -----------------------------------------------------------------------------
1315 /// Compute product of 1D vector and scalar
1316 MIRTKCU_API inline float1 operator *(float1 v, float s)
1317 {
1318  return make_float1(v.x * s);
1319 }
1320 
1321 // -----------------------------------------------------------------------------
1322 // cutil_math.h
1323 // - Multiply 2D vector by a scalar
1324 // - Multiply 3D vector by a scalar
1325 // - Multiply 4D vector by a scalar
1326 
1327 // -----------------------------------------------------------------------------
1328 /// Multiply 2x2 matrix by a scalar
1329 MIRTKCU_API inline void operator *=(float2x2 &m, float s)
1330 {
1331  m.a *= s, m.b *= s;
1332 }
1333 
1334 // -----------------------------------------------------------------------------
1335 /// Multiply 3x3 matrix by a scalar
1336 MIRTKCU_API inline void operator *=(float3x3 &m, float s)
1337 {
1338  m.a *= s, m.b *= s, m.c *= s;
1339 }
1340 
1341 // -----------------------------------------------------------------------------
1342 /// Multiply 3x4 matrix by a scalar
1343 MIRTKCU_API inline void operator *=(float3x4 &m, float s)
1344 {
1345  m.a *= s, m.b *= s, m.c *= s;
1346 }
1347 
1348 // -----------------------------------------------------------------------------
1349 /// Multiply 4x4 matrix by a scalar
1350 MIRTKCU_API inline void operator *=(float4x4 &m, float s)
1351 {
1352  m.a *= s, m.b *= s, m.c *= s, m.d *= s;
1353 }
1354 
1355 // -----------------------------------------------------------------------------
1356 /// Compute product of 2x2 matrix and scalar
1357 MIRTKCU_API inline float2x2 operator *(float2x2 m, float s)
1358 {
1359  float2x2 o;
1360  o.a = make_float2(m.a.x * s, m.a.y * s);
1361  o.b = make_float2(m.b.x * s, m.b.y * s);
1362  return o;
1363 }
1364 
1365 // -----------------------------------------------------------------------------
1366 /// Compute product of scalar and 2x2 matrix
1367 MIRTKCU_API inline float2x2 operator *(float s, float2x2 m)
1368 {
1369  return m * s;
1370 }
1371 
1372 // -----------------------------------------------------------------------------
1373 /// Compute product of 2x2 matrix and 2D column vector
1374 MIRTKCU_API inline float2 operator *(float2x2 m, float2 p)
1375 {
1376  float2 o;
1377  o.x = m.a.x * p.x + m.a.y * p.y;
1378  o.y = m.b.x * p.x + m.b.y * p.y;
1379  return o;
1380 }
1381 
1382 // -----------------------------------------------------------------------------
1383 /// Compute product of 2D row vector and 2x2 matrix
1384 MIRTKCU_API inline float2 operator *(float2 p, float2x2 m)
1385 {
1386  float2 o;
1387  o.x = p.x * m.a.x + p.y * m.b.x;
1388  o.y = p.x * m.a.y + p.y * m.b.y;
1389  return o;
1390 }
1391 
1392 // -----------------------------------------------------------------------------
1393 /// Compute product of 3x3 matrix and scalar
1394 MIRTKCU_API inline float3x3 operator *(float3x3 m, float s)
1395 {
1396  float3x3 o;
1397  o.a = make_float3(m.a.x * s, m.a.y * s, m.a.z * s);
1398  o.b = make_float3(m.b.x * s, m.b.y * s, m.b.z * s);
1399  o.c = make_float3(m.c.x * s, m.c.y * s, m.c.z * s);
1400  return o;
1401 }
1402 
1403 // -----------------------------------------------------------------------------
1404 /// Compute product of scalar and 3x3 matrix
1405 MIRTKCU_API inline float3x3 operator *(float s, float3x3 m)
1406 {
1407  return m * s;
1408 }
1409 
1410 // -----------------------------------------------------------------------------
1411 /// Compute product of 3x3 matrix and 3D column vector
1412 MIRTKCU_API inline float3 operator *(float3x3 m, float3 p)
1413 {
1414  float3 o;
1415  o.x = m.a.x * p.x + m.a.y * p.y + m.a.z * p.z;
1416  o.y = m.b.x * p.x + m.b.y * p.y + m.b.z * p.z;
1417  o.z = m.c.x * p.x + m.c.y * p.y + m.c.z * p.z;
1418  return o;
1419 }
1420 
1421 // -----------------------------------------------------------------------------
1422 /// Compute product of 3D row vector and 3x3 matrix
1423 MIRTKCU_API inline float3 operator *(float3 p, float3x3 m)
1424 {
1425  float3 o;
1426  o.x = p.x * m.a.x + p.y * m.b.x + p.z * m.c.x;
1427  o.y = p.x * m.a.y + p.y * m.b.y + p.z * m.c.y;
1428  o.z = p.x * m.a.z + p.y * m.b.z + p.z * m.c.z;
1429  return o;
1430 }
1431 
1432 // -----------------------------------------------------------------------------
1433 /// Compute product of 3x4 matrix and scalar
1434 MIRTKCU_API inline float3x4 operator *(float3x4 m, float s)
1435 {
1436  float3x4 o;
1437  o.a = m.a * s;
1438  o.b = m.b * s;
1439  o.c = m.c * s;
1440  return o;
1441 }
1442 
1443 // -----------------------------------------------------------------------------
1444 /// Compute product of scalar and 3x4 matrix
1445 MIRTKCU_API inline float3x4 operator *(float s, float3x4 m)
1446 {
1447  return m * s;
1448 }
1449 
1450 // -----------------------------------------------------------------------------
1451 /// Compute product of 3x4 coordinate transformation matrix and 2D point
1452 MIRTKCU_API inline float2 operator *(float3x4 m, float2 p)
1453 {
1454  float2 o;
1455  o.x = m.a.x * p.x + m.a.y * p.y + m.a.w;
1456  o.y = m.b.x * p.x + m.b.y * p.y + m.b.w;
1457  return o;
1458 }
1459 
1460 // -----------------------------------------------------------------------------
1461 /// Compute product of 3x4 coordinate transformation matrix and 2D voxel
1462 MIRTKCU_API inline float2 operator *(float3x4 m, int2 p)
1463 {
1464  return m * make_float2(p);
1465 }
1466 
1467 // -----------------------------------------------------------------------------
1468 /// Compute product of 3x4 coordinate transformation matrix and 2D voxel
1469 MIRTKCU_API inline float2 operator *(float3x4 m, uint2 p)
1470 {
1471  return m * make_float2(p);
1472 }
1473 
1474 // -----------------------------------------------------------------------------
1475 /// Compute product of 3x4 coordinate transformation matrix and 3D point
1476 MIRTKCU_API inline float3 operator *(float3x4 m, float3 p)
1477 {
1478  float3 o;
1479  o.x = m.a.x * p.x + m.a.y * p.y + m.a.z * p.z + m.a.w;
1480  o.y = m.b.x * p.x + m.b.y * p.y + m.b.z * p.z + m.b.w;
1481  o.z = m.c.x * p.x + m.c.y * p.y + m.c.z * p.z + m.c.w;
1482  return o;
1483 }
1484 
1485 // -----------------------------------------------------------------------------
1486 /// Compute product of 3x4 coordinate transformation matrix and 3D voxel
1487 MIRTKCU_API inline float3 operator *(float3x4 m, int3 p)
1488 {
1489  return m * make_float3(p);
1490 }
1491 
1492 // -----------------------------------------------------------------------------
1493 /// Compute product of 3x4 coordinate transformation matrix and 3D voxel
1494 MIRTKCU_API inline float3 operator *(float3x4 m, uint3 p)
1495 {
1496  return m * make_float3(p);
1497 }
1498 
1499 // -----------------------------------------------------------------------------
1500 /// Compute product of 4x4 matrix and scalar
1501 MIRTKCU_API inline float4x4 operator *(float4x4 m, float s)
1502 {
1503  float4x4 o;
1504  o.a = m.a * s;
1505  o.b = m.b * s;
1506  o.c = m.c * s;
1507  o.d = m.d * s;
1508  return o;
1509 }
1510 
1511 // -----------------------------------------------------------------------------
1512 /// Compute product of scalar and 4x4 matrix
1513 MIRTKCU_API inline float4x4 operator *(float s, float4x4 m)
1514 {
1515  return m * s;
1516 }
1517 
1518 // -----------------------------------------------------------------------------
1519 /// Compute product of 2x2 matrices
1520 MIRTKCU_API inline float2x2 operator *(float2x2 m, float2x2 n)
1521 {
1522  float2x2 o;
1523  o.a.x = m.a.x * n.a.x + m.a.y * n.b.x;
1524  o.a.y = m.a.x * n.a.y + m.a.y * n.b.y;
1525  o.b.x = m.b.x * n.a.x + m.b.y * n.b.x;
1526  o.b.y = m.b.x * n.a.y + m.b.y * n.b.y;
1527  return o;
1528 }
1529 
1530 // -----------------------------------------------------------------------------
1531 /// Compute product of 3x3 matrices
1532 MIRTKCU_API inline float3x3 operator *(float3x3 m, float3x3 n)
1533 {
1534  float3x3 o;
1535  o.a.x = m.a.x * n.a.x + m.a.y * n.b.x + m.a.z * n.c.x;
1536  o.a.y = m.a.x * n.a.y + m.a.y * n.b.y + m.a.z * n.c.y;
1537  o.a.z = m.a.x * n.a.z + m.a.y * n.b.z + m.a.z * n.c.z;
1538  o.b.x = m.b.x * n.a.x + m.b.y * n.b.x + m.b.z * n.c.x;
1539  o.b.y = m.b.x * n.a.y + m.b.y * n.b.y + m.b.z * n.c.y;
1540  o.b.z = m.b.x * n.a.z + m.b.y * n.b.z + m.b.z * n.c.z;
1541  o.c.x = m.c.x * n.a.x + m.c.y * n.b.x + m.c.z * n.c.x;
1542  o.c.y = m.c.x * n.a.y + m.c.y * n.b.y + m.c.z * n.c.y;
1543  o.c.z = m.c.x * n.a.z + m.c.y * n.b.z + m.c.z * n.c.z;
1544  return o;
1545 }
1546 
1547 // -----------------------------------------------------------------------------
1548 /// Compute product of 2x2 matrices
1549 MIRTKCU_API inline void operator *=(float2x2 &m, float2x2 n)
1550 {
1551  m = m * n;
1552 }
1553 
1554 // -----------------------------------------------------------------------------
1555 /// Compute product of 3x3 matrices
1556 MIRTKCU_API inline void operator *=(float3x3 &m, float3x3 n)
1557 {
1558  m = m * n;
1559 }
1560 
1561 // -----------------------------------------------------------------------------
1562 /// Divide 2x2 matrix by a scalar
1563 MIRTKCU_API inline void operator /=(float2x2 &m, float s)
1564 {
1565  m.a /= s, m.b /= s;
1566 }
1567 
1568 // -----------------------------------------------------------------------------
1569 /// Divide 3x3 matrix by a scalar
1570 MIRTKCU_API inline void operator /=(float3x3 &m, float s)
1571 {
1572  m.a /= s, m.b /= s, m.c /= s;
1573 }
1574 
1575 // -----------------------------------------------------------------------------
1576 /// Divide 3x4 matrix by a scalar
1577 MIRTKCU_API inline void operator /=(float3x4 &m, float s)
1578 {
1579  m.a /= s, m.b /= s, m.c /= s;
1580 }
1581 
1582 // -----------------------------------------------------------------------------
1583 /// Divide 4x4 matrix by a scalar
1584 MIRTKCU_API inline void operator /=(float4x4 &m, float s)
1585 {
1586  m.a /= s, m.b /= s, m.c /= s, m.d /= s;
1587 }
1588 
1589 // -----------------------------------------------------------------------------
1590 /// Compute division of 2x2 matrix by scalar
1591 MIRTKCU_API inline float2x2 operator /(float2x2 m, float s)
1592 {
1593  m /= s;
1594  return m;
1595 }
1596 
1597 // -----------------------------------------------------------------------------
1598 /// Compute division of 3x3 matrix by scalar
1599 MIRTKCU_API inline float3x3 operator /(float3x3 m, float s)
1600 {
1601  m /= s;
1602  return m;
1603 }
1604 
1605 // -----------------------------------------------------------------------------
1606 /// Compute division of 3x4 matrix by scalar
1607 MIRTKCU_API inline float3x4 operator /(float3x4 m, float s)
1608 {
1609  m /= s;
1610  return m;
1611 }
1612 
1613 // -----------------------------------------------------------------------------
1614 /// Compute division of 4x4 matrix by scalar
1615 MIRTKCU_API inline float4x4 operator /(float4x4 m, float s)
1616 {
1617  m /= s;
1618  return m;
1619 }
1620 
1621 // -----------------------------------------------------------------------------
1622 // Double-precision floating points
1623 // -----------------------------------------------------------------------------
1624 
1625 // -----------------------------------------------------------------------------
1626 /// Add scalar to 1D vector
1627 MIRTKCU_API inline void operator +=(double1 &a, double s)
1628 {
1629  a.x += s;
1630 }
1631 
1632 // -----------------------------------------------------------------------------
1633 /// Add scalar to 2D vector
1634 MIRTKCU_API inline void operator +=(double2 &a, double s)
1635 {
1636  a.x += s, a.y += s;
1637 }
1638 
1639 // -----------------------------------------------------------------------------
1640 /// Add scalar to 3D vector
1641 MIRTKCU_API inline void operator +=(double3 &a, double s)
1642 {
1643  a.x += s, a.y += s, a.z += s;
1644 }
1645 
1646 // -----------------------------------------------------------------------------
1647 /// Add scalar to 4D vector
1648 MIRTKCU_API inline void operator +=(double4 &a, double s)
1649 {
1650  a.x += s, a.y += s, a.z += s, a.w += s;
1651 }
1652 
1653 // -----------------------------------------------------------------------------
1654 /// Add scalar to 2x2 matrix
1655 MIRTKCU_API inline void operator +=(double2x2 &m, double s)
1656 {
1657  m.a += s, m.b += s;
1658 }
1659 
1660 // -----------------------------------------------------------------------------
1661 /// Add scalar to 3x3 matrix
1662 MIRTKCU_API inline void operator +=(double3x3 &m, double s)
1663 {
1664  m.a += s, m.b += s, m.c += s;
1665 }
1666 
1667 // -----------------------------------------------------------------------------
1668 /// Add scalar to 3x4 matrix
1669 MIRTKCU_API inline void operator +=(double3x4 &m, double s)
1670 {
1671  m.a += s, m.b += s, m.c += s;
1672 }
1673 
1674 // -----------------------------------------------------------------------------
1675 /// Add scalar to 4x4 matrix
1676 MIRTKCU_API inline void operator +=(double4x4 &m, double s)
1677 {
1678  m.a += s, m.b += s, m.c += s, m.d += s;
1679 }
1680 
1681 // -----------------------------------------------------------------------------
1682 /// Add scalar to 1D vector
1683 MIRTKCU_API inline double1 operator +(double1 a, double s)
1684 {
1685  double1 o;
1686  o.x = a.x + s;
1687  return o;
1688 }
1689 
1690 // -----------------------------------------------------------------------------
1691 /// Add scalar to 1D vector
1692 MIRTKCU_API inline double1 operator +(double s, double1 a)
1693 {
1694  return a + s;
1695 }
1696 
1697 // -----------------------------------------------------------------------------
1698 /// Add scalar to 2D vector
1699 MIRTKCU_API inline double2 operator +(double2 a, double s)
1700 {
1701  double2 o;
1702  o.x = a.x + s;
1703  o.y = a.y + s;
1704  return o;
1705 }
1706 
1707 // -----------------------------------------------------------------------------
1708 /// Add scalar to 2D vector
1709 MIRTKCU_API inline double2 operator +(double s, double2 a)
1710 {
1711  return a + s;
1712 }
1713 
1714 // -----------------------------------------------------------------------------
1715 /// Add scalar to 3D vector
1716 MIRTKCU_API inline double3 operator +(double3 a, double s)
1717 {
1718  double3 o;
1719  o.x = a.x + s;
1720  o.y = a.y + s;
1721  o.z = a.z + s;
1722  return o;
1723 }
1724 
1725 // -----------------------------------------------------------------------------
1726 /// Add scalar to 3D vector
1727 MIRTKCU_API inline double3 operator +(double s, double3 a)
1728 {
1729  return a + s;
1730 }
1731 
1732 // -----------------------------------------------------------------------------
1733 /// Add scalar to 4D vector
1734 MIRTKCU_API inline double4 operator +(double4 a, double s)
1735 {
1736  double4 o;
1737  o.x = a.x + s;
1738  o.y = a.y + s;
1739  o.z = a.z + s;
1740  o.w = a.w + s;
1741  return o;
1742 }
1743 
1744 // -----------------------------------------------------------------------------
1745 /// Add scalar to 4D vector
1746 MIRTKCU_API inline double4 operator +(double s, double4 a)
1747 {
1748  return a + s;
1749 }
1750 
1751 // -----------------------------------------------------------------------------
1752 /// Add scalar to 2x2 matrix
1753 MIRTKCU_API inline double2x2 operator +(double2x2 m, double s)
1754 {
1755  double2x2 o = m;
1756  o += s;
1757  return o;
1758 }
1759 
1760 // -----------------------------------------------------------------------------
1761 /// Add scalar to 3x3 matrix
1762 MIRTKCU_API inline double3x3 operator +(double3x3 m, double s)
1763 {
1764  double3x3 o = m;
1765  o += s;
1766  return o;
1767 }
1768 
1769 // -----------------------------------------------------------------------------
1770 /// Add scalar to 3x4 matrix
1771 MIRTKCU_API inline double3x4 operator +(double3x4 m, double s)
1772 {
1773  double3x4 o = m;
1774  o += s;
1775  return o;
1776 }
1777 
1778 // -----------------------------------------------------------------------------
1779 /// Add scalar to 4x4 matrix
1780 MIRTKCU_API inline double4x4 operator +(double4x4 m, double s)
1781 {
1782  double4x4 o = m;
1783  o += s;
1784  return o;
1785 }
1786 
1787 // -----------------------------------------------------------------------------
1788 /// Add two 1D vectors
1789 MIRTKCU_API inline void operator +=(double1 &a, double1 b)
1790 {
1791  a.x += b.x;
1792 }
1793 
1794 // -----------------------------------------------------------------------------
1795 /// Add two 2D vectors
1796 MIRTKCU_API inline void operator +=(double2 &a, double2 b)
1797 {
1798  a.x += b.x, a.y += b.y;
1799 }
1800 
1801 // -----------------------------------------------------------------------------
1802 /// Add two 3D vectors
1803 MIRTKCU_API inline void operator +=(double3 &a, double3 b)
1804 {
1805  a.x += b.x, a.y += b.y, a.z += b.z;
1806 }
1807 
1808 // -----------------------------------------------------------------------------
1809 /// Add two 4D vectors
1810 MIRTKCU_API inline void operator +=(double4 &a, double4 b)
1811 {
1812  a.x += b.x, a.y += b.y, a.z += b.z, a.w += b.w;
1813 }
1814 
1815 // -----------------------------------------------------------------------------
1816 /// Add two 2x2 matrices
1817 MIRTKCU_API inline void operator +=(double2x2 &a, double2x2 b)
1818 {
1819  a.a += b.a, a.b += b.b;
1820 }
1821 
1822 // -----------------------------------------------------------------------------
1823 /// Add two 3x3 matrices
1824 MIRTKCU_API inline void operator +=(double3x3 &a, double3x3 b)
1825 {
1826  a.a += b.a, a.b += b.b, a.c += b.c;
1827 }
1828 
1829 // -----------------------------------------------------------------------------
1830 /// Add two 3x4 matrices
1831 MIRTKCU_API inline void operator +=(double3x4 &a, double3x4 b)
1832 {
1833  a.a += b.a, a.b += b.b, a.c += b.c;
1834 }
1835 
1836 // -----------------------------------------------------------------------------
1837 /// Add two 4x4 matrices
1838 MIRTKCU_API inline void operator +=(double4x4 &a, double4x4 b)
1839 {
1840  a.a += b.a, a.b += b.b, a.c += b.c, a.d += b.d;
1841 }
1842 
1843 // -----------------------------------------------------------------------------
1844 /// Add two 1D vectors
1845 MIRTKCU_API inline double1 operator +(double1 a, double1 b)
1846 {
1847  return make_double1(a.x + b.x);
1848 }
1849 
1850 // -----------------------------------------------------------------------------
1851 /// Add two 2D vectors
1852 MIRTKCU_API inline double2 operator +(double2 a, double2 b)
1853 {
1854  return make_double2(a.x + b.x, a.y + b.y);
1855 }
1856 
1857 // -----------------------------------------------------------------------------
1858 /// Add two 3D vectors
1859 MIRTKCU_API inline double3 operator +(double3 a, double3 b)
1860 {
1861  return make_double3(a.x + b.x, a.y + b.y, a.z + b.z);
1862 }
1863 
1864 // -----------------------------------------------------------------------------
1865 /// Add two 4D vectors
1866 MIRTKCU_API inline double4 operator +(double4 a, double4 b)
1867 {
1868  return make_double4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
1869 }
1870 
1871 // -----------------------------------------------------------------------------
1872 /// Add two 2x2 matrices
1873 MIRTKCU_API inline double2x2 operator +(double2x2 a, double2x2 b)
1874 {
1875  double2x2 o;
1876  o.a = a.a + b.a;
1877  o.b = a.b + b.b;
1878  return o;
1879 }
1880 
1881 // -----------------------------------------------------------------------------
1882 /// Add two 3x3 matrices
1883 MIRTKCU_API inline double3x3 operator +(double3x3 a, double3x3 b)
1884 {
1885  double3x3 o;
1886  o.a = a.a + b.a;
1887  o.b = a.b + b.b;
1888  o.c = a.c + b.c;
1889  return o;
1890 }
1891 
1892 // -----------------------------------------------------------------------------
1893 /// Add two 3x4 matrices
1894 MIRTKCU_API inline double3x4 operator +(double3x4 a, double3x4 b)
1895 {
1896  double3x4 o;
1897  o.a = a.a + b.a;
1898  o.b = a.b + b.b;
1899  o.c = a.c + b.c;
1900  return o;
1901 }
1902 
1903 // -----------------------------------------------------------------------------
1904 /// Add two 4x4 matrices
1905 MIRTKCU_API inline double4x4 operator +(double4x4 a, double4x4 b)
1906 {
1907  double4x4 o;
1908  o.a = a.a + b.a;
1909  o.b = a.b + b.b;
1910  o.c = a.c + b.c;
1911  o.d = a.d + b.d;
1912  return o;
1913 }
1914 
1915 // -----------------------------------------------------------------------------
1916 /// Subtract scalar from 1D vector
1917 MIRTKCU_API inline void operator -=(double1 &a, double s)
1918 {
1919  a.x -= s;
1920 }
1921 
1922 // -----------------------------------------------------------------------------
1923 /// Subtract scalar from 2D vector
1924 MIRTKCU_API inline void operator -=(double2 &a, double s)
1925 {
1926  a.x -= s, a.y -= s;
1927 }
1928 
1929 // -----------------------------------------------------------------------------
1930 /// Subtract scalar from 3D vector
1931 MIRTKCU_API inline void operator -=(double3 &a, double s)
1932 {
1933  a.x -= s, a.y -= s, a.z -= s;
1934 }
1935 
1936 // -----------------------------------------------------------------------------
1937 /// Subtract scalar from 4D vector
1938 MIRTKCU_API inline void operator -=(double4 &a, double s)
1939 {
1940  a.x -= s, a.y -= s, a.z -= s, a.w -= s;
1941 }
1942 
1943 // -----------------------------------------------------------------------------
1944 /// Subtract scalar from 2x2 matrix
1945 MIRTKCU_API inline void operator -=(double2x2 &m, double s)
1946 {
1947  m.a -= s, m.b -= s;
1948 }
1949 
1950 // -----------------------------------------------------------------------------
1951 /// Subtract scalar from 3x3 matrix
1952 MIRTKCU_API inline void operator -=(double3x3 &m, double s)
1953 {
1954  m.a -= s, m.b -= s, m.c -= s;
1955 }
1956 
1957 // -----------------------------------------------------------------------------
1958 /// Subtract scalar from 3x4 matrix
1959 MIRTKCU_API inline void operator -=(double3x4 &m, double s)
1960 {
1961  m.a -= s, m.b -= s, m.c -= s;
1962 }
1963 
1964 // -----------------------------------------------------------------------------
1965 /// Subtract scalar from 4x4 matrix
1966 MIRTKCU_API inline void operator -=(double4x4 &m, double s)
1967 {
1968  m.a -= s, m.b -= s, m.c -= s, m.d -= s;
1969 }
1970 
1971 // -----------------------------------------------------------------------------
1972 /// Subtract scalar from 1D vector
1973 MIRTKCU_API inline double1 operator -(double1 a, double s)
1974 {
1975  double1 o;
1976  o.x = a.x - s;
1977  return o;
1978 }
1979 
1980 // -----------------------------------------------------------------------------
1981 /// Subtract 1D vector from scalar
1982 MIRTKCU_API inline double1 operator -(double s, double1 a)
1983 {
1984  return a - s;
1985 }
1986 
1987 // -----------------------------------------------------------------------------
1988 /// Subtract scalar from 2D vector
1989 MIRTKCU_API inline double2 operator -(double2 a, double s)
1990 {
1991  double2 o;
1992  o.x = a.x - s;
1993  o.y = a.y - s;
1994  return o;
1995 }
1996 
1997 // -----------------------------------------------------------------------------
1998 /// Subtract 2D vector from scalar
1999 MIRTKCU_API inline double2 operator -(double s, double2 a)
2000 {
2001  return a - s;
2002 }
2003 
2004 // -----------------------------------------------------------------------------
2005 /// Subtract scalar from 3D vector
2006 MIRTKCU_API inline double3 operator -(double3 a, double s)
2007 {
2008  double3 o;
2009  o.x = a.x - s;
2010  o.y = a.y - s;
2011  o.z = a.z - s;
2012  return o;
2013 }
2014 
2015 // -----------------------------------------------------------------------------
2016 /// Subtract 3D vector from scalar
2017 MIRTKCU_API inline double3 operator -(double s, double3 a)
2018 {
2019  return a - s;
2020 }
2021 
2022 // -----------------------------------------------------------------------------
2023 /// Subtract scalar from 4D vector
2024 MIRTKCU_API inline double4 operator -(double4 a, double s)
2025 {
2026  double4 o;
2027  o.x = a.x - s;
2028  o.y = a.y - s;
2029  o.z = a.z - s;
2030  o.w = a.w - s;
2031  return o;
2032 }
2033 
2034 // -----------------------------------------------------------------------------
2035 /// Subtract 4D vector from scalar
2036 MIRTKCU_API inline double4 operator -(double s, double4 a)
2037 {
2038  return a - s;
2039 }
2040 
2041 // -----------------------------------------------------------------------------
2042 /// Subtract scalar from 2x2 matrix
2043 MIRTKCU_API inline double2x2 operator -(double2x2 m, double s)
2044 {
2045  double2x2 o = m;
2046  o -= s;
2047  return o;
2048 }
2049 
2050 // -----------------------------------------------------------------------------
2051 /// Subtract scalar from 3x3 matrix
2052 MIRTKCU_API inline double3x3 operator -(double3x3 m, double s)
2053 {
2054  double3x3 o = m;
2055  o -= s;
2056  return o;
2057 }
2058 
2059 // -----------------------------------------------------------------------------
2060 /// Subtract scalar from 3x4 matrix
2061 MIRTKCU_API inline double3x4 operator -(double3x4 m, double s)
2062 {
2063  double3x4 o = m;
2064  o -= s;
2065  return o;
2066 }
2067 
2068 // -----------------------------------------------------------------------------
2069 /// Subtract scalar from 4x4 matrix
2070 MIRTKCU_API inline double4x4 operator -(double4x4 m, double s)
2071 {
2072  double4x4 o = m;
2073  o -= s;
2074  return o;
2075 }
2076 
2077 // -----------------------------------------------------------------------------
2078 /// Subtract two 1D vectors
2079 MIRTKCU_API inline void operator -=(double1 &a, double1 b)
2080 {
2081  a.x -= b.x;
2082 }
2083 
2084 // -----------------------------------------------------------------------------
2085 /// Subtract two 2D vectors
2086 MIRTKCU_API inline void operator -=(double2 &a, double2 b)
2087 {
2088  a.x -= b.x, a.y -= b.y;
2089 }
2090 
2091 // -----------------------------------------------------------------------------
2092 /// Subtract two 3D vectors
2093 MIRTKCU_API inline void operator -=(double3 &a, double3 b)
2094 {
2095  a.x -= b.x, a.y -= b.y, a.z -= b.z;
2096 }
2097 
2098 // -----------------------------------------------------------------------------
2099 /// Subtract two 4D vectors
2100 MIRTKCU_API inline void operator -=(double4 &a, double4 b)
2101 {
2102  a.x -= b.x, a.y -= b.y, a.z -= b.z, a.w -= b.w;
2103 }
2104 
2105 // -----------------------------------------------------------------------------
2106 /// Subtract two 2x2 matrices
2107 MIRTKCU_API inline void operator -=(double2x2 &a, double2x2 b)
2108 {
2109  a.a -= b.a, a.b -= b.b;
2110 }
2111 
2112 // -----------------------------------------------------------------------------
2113 /// Subtract two 3x3 matrices
2114 MIRTKCU_API inline void operator -=(double3x3 &a, double3x3 b)
2115 {
2116  a.a -= b.a, a.b -= b.b, a.c -= b.c;
2117 }
2118 
2119 // -----------------------------------------------------------------------------
2120 /// Subtract two 3x4 matrices
2121 MIRTKCU_API inline void operator -=(double3x4 &a, double3x4 b)
2122 {
2123  a.a -= b.a, a.b -= b.b, a.c -= b.c;
2124 }
2125 
2126 // -----------------------------------------------------------------------------
2127 /// Subtract two 4x4 matrices
2128 MIRTKCU_API inline void operator -=(double4x4 &a, double4x4 b)
2129 {
2130  a.a -= b.a, a.b -= b.b, a.c -= b.c, a.d -= b.d;
2131 }
2132 
2133 // -----------------------------------------------------------------------------
2134 /// Subtract two 1D vectors
2135 MIRTKCU_API inline double1 operator -(double1 a, double1 b)
2136 {
2137  return make_double1(a.x - b.x);
2138 }
2139 
2140 // -----------------------------------------------------------------------------
2141 /// Subtract two 2D vectors
2142 MIRTKCU_API inline double2 operator -(double2 a, double2 b)
2143 {
2144  return make_double2(a.x - b.x, a.y - b.y);
2145 }
2146 
2147 // -----------------------------------------------------------------------------
2148 /// Subtract two 3D vectors
2149 MIRTKCU_API inline double3 operator -(double3 a, double3 b)
2150 {
2151  return make_double3(a.x - b.x, a.y - b.y, a.z - b.z);
2152 }
2153 
2154 // -----------------------------------------------------------------------------
2155 /// Subtract two 4D vectors
2156 MIRTKCU_API inline double4 operator -(double4 a, double4 b)
2157 {
2158  return make_double4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
2159 }
2160 
2161 // -----------------------------------------------------------------------------
2162 /// Subtract two 2x2 matrices
2163 MIRTKCU_API inline double2x2 operator -(double2x2 a, double2x2 b)
2164 {
2165  double2x2 o;
2166  o.a = a.a - b.a;
2167  o.b = a.b - b.b;
2168  return o;
2169 }
2170 
2171 // -----------------------------------------------------------------------------
2172 /// Subtract two 3x3 matrices
2173 MIRTKCU_API inline double3x3 operator -(double3x3 a, double3x3 b)
2174 {
2175  double3x3 o;
2176  o.a = a.a - b.a;
2177  o.b = a.b - b.b;
2178  o.c = a.c - b.c;
2179  return o;
2180 }
2181 
2182 // -----------------------------------------------------------------------------
2183 /// Subtract two 3x4 matrices
2184 MIRTKCU_API inline double3x4 operator -(double3x4 a, double3x4 b)
2185 {
2186  double3x4 o;
2187  o.a = a.a - b.a;
2188  o.b = a.b - b.b;
2189  o.c = a.c - b.c;
2190  return o;
2191 }
2192 
2193 // -----------------------------------------------------------------------------
2194 /// Subtract two 4x4 matrices
2195 MIRTKCU_API inline double4x4 operator -(double4x4 a, double4x4 b)
2196 {
2197  double4x4 o;
2198  o.a = a.a - b.a;
2199  o.b = a.b - b.b;
2200  o.c = a.c - b.c;
2201  o.d = a.d - b.d;
2202  return o;
2203 }
2204 
2205 // -----------------------------------------------------------------------------
2206 /// Compute product of 1D vector and scalar
2207 MIRTKCU_API inline void operator *=(double1 &a, double s)
2208 {
2209  a.x *= s;
2210 }
2211 
2212 // -----------------------------------------------------------------------------
2213 /// Compute product of 2D vector and scalar
2214 MIRTKCU_API inline void operator *=(double2 &a, double s)
2215 {
2216  a.x *= s, a.y *= s;
2217 }
2218 
2219 // -----------------------------------------------------------------------------
2220 /// Compute product of 3D vector and scalar
2221 MIRTKCU_API inline void operator *=(double3 &a, double s)
2222 {
2223  a.x *= s, a.y *= s, a.z *= s;
2224 }
2225 
2226 // -----------------------------------------------------------------------------
2227 /// Compute product of 4D vector and scalar
2228 MIRTKCU_API inline void operator *=(double4 &a, double s)
2229 {
2230  a.x *= s, a.y *= s, a.z *= s, a.w *= s;
2231 }
2232 
2233 // -----------------------------------------------------------------------------
2234 /// Compute product of 1D vector and scalar
2235 MIRTKCU_API inline double1 operator *(double1 v, double s)
2236 {
2237  return make_double1(v.x * s);
2238 }
2239 
2240 // -----------------------------------------------------------------------------
2241 /// Compute product of scalar and 1D vector
2242 MIRTKCU_API inline double1 operator *(double s, double1 a)
2243 {
2244  return a * s;
2245 }
2246 
2247 // -----------------------------------------------------------------------------
2248 /// Compute product of 2D vector and scalar
2249 MIRTKCU_API inline double2 operator *(double2 v, double s)
2250 {
2251  return make_double2(v.x * s, v.y * s);
2252 }
2253 
2254 // -----------------------------------------------------------------------------
2255 /// Compute product of scalar and 2D vector
2256 MIRTKCU_API inline double2 operator *(double s, double2 a)
2257 {
2258  return a * s;
2259 }
2260 
2261 // -----------------------------------------------------------------------------
2262 /// Compute product of 3D vector and scalar
2263 MIRTKCU_API inline double3 operator *(double3 v, double s)
2264 {
2265  return make_double3(v.x * s, v.y * s, v.z * s);
2266 }
2267 
2268 // -----------------------------------------------------------------------------
2269 /// Compute product of scalar and 3D vector
2270 MIRTKCU_API inline double3 operator *(double s, double3 a)
2271 {
2272  return a * s;
2273 }
2274 
2275 // -----------------------------------------------------------------------------
2276 /// Compute product of 4D vector and scalar
2277 MIRTKCU_API inline double4 operator *(double4 v, double s)
2278 {
2279  return make_double4(v.x * s, v.y * s, v.z * s, v.w * s);
2280 }
2281 
2282 // -----------------------------------------------------------------------------
2283 /// Compute product of scalar and 4D vector
2284 MIRTKCU_API inline double4 operator *(double s, double4 a)
2285 {
2286  return a * s;
2287 }
2288 
2289 // -----------------------------------------------------------------------------
2290 /// Compute element-wise product of 1D vectors
2291 MIRTKCU_API inline void operator *=(double1 &a, double1 b)
2292 {
2293  a.x *= b.x;
2294 }
2295 
2296 // -----------------------------------------------------------------------------
2297 /// Compute element-wise product of 2D vectors
2298 MIRTKCU_API inline void operator *=(double2 &a, double2 b)
2299 {
2300  a.x *= b.x, a.y *= b.y;
2301 }
2302 
2303 // -----------------------------------------------------------------------------
2304 /// Compute element-wise product of 3D vectors
2305 MIRTKCU_API inline void operator *=(double3 &a, double3 b)
2306 {
2307  a.x *= b.x, a.y *= b.y, a.z *= b.z;
2308 }
2309 
2310 // -----------------------------------------------------------------------------
2311 /// Compute element-wise product of 4D vectors
2312 MIRTKCU_API inline void operator *=(double4 &a, double4 b)
2313 {
2314  a.x *= b.x, a.y *= b.y, a.z *= b.z, a.w *= b.w;
2315 }
2316 
2317 // -----------------------------------------------------------------------------
2318 /// Compute element-wise product of 1D vectors
2319 MIRTKCU_API inline double1 operator *(double1 a, double1 b)
2320 {
2321  return make_double1(a.x * b.x);
2322 }
2323 
2324 // -----------------------------------------------------------------------------
2325 /// Compute element-wise product of 2D vectors
2326 MIRTKCU_API inline double2 operator *(double2 a, double2 b)
2327 {
2328  return make_double2(a.x * b.x, a.y * b.y);
2329 }
2330 
2331 // -----------------------------------------------------------------------------
2332 /// Compute element-wise product of 3D vectors
2333 MIRTKCU_API inline double3 operator *(double3 a, double3 b)
2334 {
2335  return make_double3(a.x * b.x, a.y * b.y, a.z * b.z);
2336 }
2337 
2338 // -----------------------------------------------------------------------------
2339 /// Compute element-wise product of 4D vectors
2340 MIRTKCU_API inline double4 operator *(double4 a, double4 b)
2341 {
2342  return make_double4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
2343 }
2344 
2345 // -----------------------------------------------------------------------------
2346 /// Compute division of 1D vector by scalar
2347 MIRTKCU_API inline void operator /=(double1 &a, double s)
2348 {
2349  a.x /= s;
2350 }
2351 
2352 // -----------------------------------------------------------------------------
2353 /// Compute division of 2D vector by scalar
2354 MIRTKCU_API inline void operator /=(double2 &a, double s)
2355 {
2356  a.x /= s, a.y /= s;
2357 }
2358 
2359 // -----------------------------------------------------------------------------
2360 /// Compute division of 3D vector by scalar
2361 MIRTKCU_API inline void operator /=(double3 &a, double s)
2362 {
2363  a.x /= s, a.y /= s, a.z /= s;
2364 }
2365 
2366 // -----------------------------------------------------------------------------
2367 /// Compute division of 4D vector by scalar
2368 MIRTKCU_API inline void operator /=(double4 &a, double s)
2369 {
2370  a.x /= s, a.y /= s, a.z /= s, a.w /= s;
2371 }
2372 
2373 // -----------------------------------------------------------------------------
2374 /// Divide 2x2 matrix by a scalar
2375 MIRTKCU_API inline void operator /=(double2x2 &m, double s)
2376 {
2377  m.a /= s, m.b /= s;
2378 }
2379 
2380 // -----------------------------------------------------------------------------
2381 /// Divide 3x3 matrix by a scalar
2382 MIRTKCU_API inline void operator /=(double3x3 &m, double s)
2383 {
2384  m.a /= s, m.b /= s, m.c /= s;
2385 }
2386 
2387 // -----------------------------------------------------------------------------
2388 /// Divide 3x4 matrix by a scalar
2389 MIRTKCU_API inline void operator /=(double3x4 &m, double s)
2390 {
2391  m.a /= s, m.b /= s, m.c /= s;
2392 }
2393 
2394 // -----------------------------------------------------------------------------
2395 /// Divide 4x4 matrix by a scalar
2396 MIRTKCU_API inline void operator /=(double4x4 &m, double s)
2397 {
2398  m.a /= s, m.b /= s, m.c /= s, m.d /= s;
2399 }
2400 
2401 // -----------------------------------------------------------------------------
2402 /// Compute division of 1D vector by scalar
2403 MIRTKCU_API inline double1 operator /(double1 v, double s)
2404 {
2405  return make_double1(v.x / s);
2406 }
2407 
2408 // -----------------------------------------------------------------------------
2409 /// Compute division of 2D vector by scalar
2410 MIRTKCU_API inline double2 operator /(double2 v, double s)
2411 {
2412  return make_double2(v.x / s, v.y / s);
2413 }
2414 
2415 // -----------------------------------------------------------------------------
2416 /// Compute division of 3D vector by scalar
2417 MIRTKCU_API inline double3 operator /(double3 v, double s)
2418 {
2419  return make_double3(v.x / s, v.y / s, v.z / s);
2420 }
2421 
2422 // -----------------------------------------------------------------------------
2423 /// Compute division of 4D vector by scalar
2424 MIRTKCU_API inline double4 operator /(double4 v, double s)
2425 {
2426  return make_double4(v.x / s, v.y / s, v.z / s, v.w / s);
2427 }
2428 
2429 // -----------------------------------------------------------------------------
2430 /// Compute division of 2x2 matrix by scalar
2431 MIRTKCU_API inline double2x2 operator /(double2x2 m, double s)
2432 {
2433  m /= s;
2434  return m;
2435 }
2436 
2437 // -----------------------------------------------------------------------------
2438 /// Compute division of 3x3 matrix by scalar
2439 MIRTKCU_API inline double3x3 operator /(double3x3 m, double s)
2440 {
2441  m /= s;
2442  return m;
2443 }
2444 
2445 // -----------------------------------------------------------------------------
2446 /// Compute division of 3x4 matrix by scalar
2447 MIRTKCU_API inline double3x4 operator /(double3x4 m, double s)
2448 {
2449  m /= s;
2450  return m;
2451 }
2452 
2453 // -----------------------------------------------------------------------------
2454 /// Compute division of 4x4 matrix by scalar
2455 MIRTKCU_API inline double4x4 operator /(double4x4 m, double s)
2456 {
2457  m /= s;
2458  return m;
2459 }
2460 
2461 // -----------------------------------------------------------------------------
2462 /// Compute element-wise division of 1D vectors
2463 MIRTKCU_API inline void operator /=(double1 &a, double1 b)
2464 {
2465  a.x /= b.x;
2466 }
2467 
2468 // -----------------------------------------------------------------------------
2469 /// Compute element-wise division of 2D vectors
2470 MIRTKCU_API inline void operator /=(double2 &a, double2 b)
2471 {
2472  a.x /= b.x, a.y /= b.y;
2473 }
2474 
2475 // -----------------------------------------------------------------------------
2476 /// Compute element-wise division of 3D vectors
2477 MIRTKCU_API inline void operator /=(double3 &a, double3 b)
2478 {
2479  a.x /= b.x, a.y /= b.y, a.z /= b.z;
2480 }
2481 
2482 // -----------------------------------------------------------------------------
2483 /// Compute element-wise division of 4D vectors
2484 MIRTKCU_API inline void operator /=(double4 &a, double4 b)
2485 {
2486  a.x /= b.x, a.y /= b.y, a.z /= b.z, a.w /= b.w;
2487 }
2488 
2489 // -----------------------------------------------------------------------------
2490 /// Compute element-wise division of 1D vectors
2491 MIRTKCU_API inline double1 operator /(double1 a, double1 b)
2492 {
2493  return make_double1(a.x / b.x);
2494 }
2495 
2496 // -----------------------------------------------------------------------------
2497 /// Compute element-wise division of 2D vectors
2498 MIRTKCU_API inline double2 operator /(double2 a, double2 b)
2499 {
2500  return make_double2(a.x / b.x, a.y / b.y);
2501 }
2502 
2503 // -----------------------------------------------------------------------------
2504 /// Compute element-wise division of 3D vectors
2505 MIRTKCU_API inline double3 operator /(double3 a, double3 b)
2506 {
2507  return make_double3(a.x / b.x, a.y / b.y, a.z / b.z);
2508 }
2509 
2510 // -----------------------------------------------------------------------------
2511 /// Compute element-wise division of 4D vectors
2512 MIRTKCU_API inline double4 operator /(double4 a, double4 b)
2513 {
2514  return make_double4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
2515 }
2516 
2517 // -----------------------------------------------------------------------------
2518 /// Multiply 2x2 matrix by a scalar
2519 MIRTKCU_API inline void operator *=(double2x2 &m, double s)
2520 {
2521  m.a *= s, m.b *= s;
2522 }
2523 
2524 // -----------------------------------------------------------------------------
2525 /// Multiply 3x3 matrix by a scalar
2526 MIRTKCU_API inline void operator *=(double3x3 &m, double s)
2527 {
2528  m.a *= s, m.b *= s, m.c *= s;
2529 }
2530 
2531 // -----------------------------------------------------------------------------
2532 /// Multiply 3x4 matrix by a scalar
2533 MIRTKCU_API inline void operator *=(double3x4 &m, double s)
2534 {
2535  m.a *= s, m.b *= s, m.c *= s;
2536 }
2537 
2538 // -----------------------------------------------------------------------------
2539 /// Multiply 4x4 matrix by a scalar
2540 MIRTKCU_API inline void operator *=(double4x4 &m, double s)
2541 {
2542  m.a *= s, m.b *= s, m.c *= s, m.d *= s;
2543 }
2544 
2545 // -----------------------------------------------------------------------------
2546 /// Compute product of 2x2 matrix and scalar
2547 MIRTKCU_API inline double2x2 operator *(double2x2 m, double s)
2548 {
2549  double2x2 o;
2550  o.a = make_double2(m.a.x * s, m.a.y * s);
2551  o.b = make_double2(m.b.x * s, m.b.y * s);
2552  return o;
2553 }
2554 
2555 // -----------------------------------------------------------------------------
2556 /// Compute product of scalar and 2x2 matrix
2557 MIRTKCU_API inline double2x2 operator *(double s, double2x2 m)
2558 {
2559  return m * s;
2560 }
2561 
2562 // -----------------------------------------------------------------------------
2563 /// Compute product of 2x2 matrix and 2D column vector
2564 MIRTKCU_API inline double2 operator *(double2x2 m, double2 p)
2565 {
2566  double2 o;
2567  o.x = m.a.x * p.x + m.a.y * p.y;
2568  o.y = m.b.x * p.x + m.b.y * p.y;
2569  return o;
2570 }
2571 
2572 // -----------------------------------------------------------------------------
2573 /// Compute product of transpose of 2D row vector and 2x2 matrix
2574 MIRTKCU_API inline double2 operator *(double2 p, double2x2 m)
2575 {
2576  double2 o;
2577  o.x = p.x * m.a.x + p.y * m.b.x;
2578  o.y = p.x * m.a.y + p.y * m.b.y;
2579  return o;
2580 }
2581 
2582 // -----------------------------------------------------------------------------
2583 /// Compute product of 3x3 matrix and scalar
2584 MIRTKCU_API inline double3x3 operator *(double3x3 m, double s)
2585 {
2586  double3x3 o;
2587  o.a = make_double3(m.a.x * s, m.a.y * s, m.a.z * s);
2588  o.b = make_double3(m.b.x * s, m.b.y * s, m.b.z * s);
2589  o.c = make_double3(m.c.x * s, m.c.y * s, m.c.z * s);
2590  return o;
2591 }
2592 
2593 // -----------------------------------------------------------------------------
2594 /// Compute product of scalar and 3x3 matrix
2595 MIRTKCU_API inline double3x3 operator *(double s, double3x3 m)
2596 {
2597  return m * s;
2598 }
2599 
2600 // -----------------------------------------------------------------------------
2601 /// Compute product of 3x3 matrix and 3D column vector
2602 MIRTKCU_API inline double3 operator *(double3x3 m, double3 p)
2603 {
2604  double3 o;
2605  o.x = m.a.x * p.x + m.a.y * p.y + m.a.z * p.z;
2606  o.y = m.b.x * p.x + m.b.y * p.y + m.b.z * p.z;
2607  o.z = m.c.x * p.x + m.c.y * p.y + m.c.z * p.z;
2608  return o;
2609 }
2610 
2611 // -----------------------------------------------------------------------------
2612 /// Compute product of transpose of 3D row vector and 3x3 matrix
2613 MIRTKCU_API inline double3 operator *(double3 p, double3x3 m)
2614 {
2615  double3 o;
2616  o.x = p.x * m.a.x + p.y * m.b.x + p.z * m.c.x;
2617  o.y = p.x * m.a.y + p.y * m.b.y + p.z * m.c.y;
2618  o.z = p.x * m.a.z + p.y * m.b.z + p.z * m.c.z;
2619  return o;
2620 }
2621 
2622 // -----------------------------------------------------------------------------
2623 /// Compute product of 3x4 matrix and scalar
2624 MIRTKCU_API inline double3x4 operator *(double3x4 m, double s)
2625 {
2626  double3x4 o;
2627  o.a = m.a * s;
2628  o.b = m.b * s;
2629  o.c = m.c * s;
2630  return o;
2631 }
2632 
2633 // -----------------------------------------------------------------------------
2634 /// Compute product of scalar and 3x4 matrix
2635 MIRTKCU_API inline double3x4 operator *(double s, double3x4 m)
2636 {
2637  return m * s;
2638 }
2639 
2640 // -----------------------------------------------------------------------------
2641 /// Compute product of 4x4 matrix and scalar
2642 MIRTKCU_API inline double4x4 operator *(double4x4 m, double s)
2643 {
2644  double4x4 o;
2645  o.a = m.a * s;
2646  o.b = m.b * s;
2647  o.c = m.c * s;
2648  return o;
2649 }
2650 
2651 // -----------------------------------------------------------------------------
2652 /// Compute product of scalar and 4x4 matrix
2653 MIRTKCU_API inline double4x4 operator *(double s, double4x4 m)
2654 {
2655  return m * s;
2656 }
2657 
2658 // -----------------------------------------------------------------------------
2659 /// Compute product of 3x4 coordinate transformation matrix and 2D point
2660 MIRTKCU_API inline double2 operator *(double3x4 m, double2 p)
2661 {
2662  double2 o;
2663  o.x = m.a.x * p.x + m.a.y * p.y + m.a.w;
2664  o.y = m.b.x * p.x + m.b.y * p.y + m.b.w;
2665  return o;
2666 }
2667 
2668 // -----------------------------------------------------------------------------
2669 /// Compute product of 3x4 coordinate transformation matrix and 2D voxel
2670 MIRTKCU_API inline double2 operator *(double3x4 m, int2 p)
2671 {
2672  return m * make_double2(p);
2673 }
2674 
2675 // -----------------------------------------------------------------------------
2676 /// Compute product of 3x4 coordinate transformation matrix and 2D voxel
2677 MIRTKCU_API inline double2 operator *(double3x4 m, uint2 p)
2678 {
2679  return m * make_double2(p);
2680 }
2681 
2682 // -----------------------------------------------------------------------------
2683 /// Compute product of 3x4 coordinate transformation matrix and 3D point
2684 MIRTKCU_API inline double3 operator *(double3x4 m, double3 p)
2685 {
2686  double3 o;
2687  o.x = m.a.x * p.x + m.a.y * p.y + m.a.z * p.z + m.a.w;
2688  o.y = m.b.x * p.x + m.b.y * p.y + m.b.z * p.z + m.b.w;
2689  o.z = m.c.x * p.x + m.c.y * p.y + m.c.z * p.z + m.c.w;
2690  return o;
2691 }
2692 
2693 // -----------------------------------------------------------------------------
2694 /// Compute product of 3x4 coordinate transformation matrix and 3D voxel
2695 MIRTKCU_API inline double3 operator *(double3x4 m, int3 p)
2696 {
2697  return m * make_double3(p);
2698 }
2699 
2700 // -----------------------------------------------------------------------------
2701 /// Compute product of 3x4 coordinate transformation matrix and 3D voxel
2702 MIRTKCU_API inline double3 operator *(double3x4 m, uint3 p)
2703 {
2704  return m * make_double3(p);
2705 }
2706 
2707 // -----------------------------------------------------------------------------
2708 /// Compute product of 2x2 matrices
2709 MIRTKCU_API inline double2x2 operator *(double2x2 m, double2x2 n)
2710 {
2711  double2x2 o;
2712  o.a.x = m.a.x * n.a.x + m.a.y * n.b.x;
2713  o.a.y = m.a.x * n.a.y + m.a.y * n.b.y;
2714  o.b.x = m.b.x * n.a.x + m.b.y * n.b.x;
2715  o.b.y = m.b.x * n.a.y + m.b.y * n.b.y;
2716  return o;
2717 }
2718 
2719 // -----------------------------------------------------------------------------
2720 /// Compute product of 3x3 matrices
2721 MIRTKCU_API inline double3x3 operator *(double3x3 m, double3x3 n)
2722 {
2723  double3x3 o;
2724  o.a.x = m.a.x * n.a.x + m.a.y * n.b.x + m.a.z * n.c.x;
2725  o.a.y = m.a.x * n.a.y + m.a.y * n.b.y + m.a.z * n.c.y;
2726  o.a.z = m.a.x * n.a.z + m.a.y * n.b.z + m.a.z * n.c.z;
2727  o.b.x = m.b.x * n.a.x + m.b.y * n.b.x + m.b.z * n.c.x;
2728  o.b.y = m.b.x * n.a.y + m.b.y * n.b.y + m.b.z * n.c.y;
2729  o.b.z = m.b.x * n.a.z + m.b.y * n.b.z + m.b.z * n.c.z;
2730  o.c.x = m.c.x * n.a.x + m.c.y * n.b.x + m.c.z * n.c.x;
2731  o.c.y = m.c.x * n.a.y + m.c.y * n.b.y + m.c.z * n.c.y;
2732  o.c.z = m.c.x * n.a.z + m.c.y * n.b.z + m.c.z * n.c.z;
2733  return o;
2734 }
2735 
2736 // -----------------------------------------------------------------------------
2737 /// Compute product of 2x2 matrices
2738 MIRTKCU_API inline void operator *=(double2x2 &m, double2x2 n)
2739 {
2740  m = m * n;
2741 }
2742 
2743 // -----------------------------------------------------------------------------
2744 /// Compute product of 3x3 matrices
2745 MIRTKCU_API inline void operator *=(double3x3 &m, double3x3 n)
2746 {
2747  m = m * n;
2748 }
2749 
2750 // =============================================================================
2751 // Rounding
2752 // =============================================================================
2753 
2754 // -----------------------------------------------------------------------------
2755 // Single-precision floating points
2756 // -----------------------------------------------------------------------------
2757 
2758 // -----------------------------------------------------------------------------
2759 MIRTKCU_API inline float1 floor(float1 v)
2760 {
2761  return make_float1(floorf(v.x));
2762 }
2763 
2764 // -----------------------------------------------------------------------------
2765 MIRTKCU_API inline float2 floor(float2 v)
2766 {
2767  return make_float2(floorf(v.x), floorf(v.y));
2768 }
2769 
2770 // -----------------------------------------------------------------------------
2771 MIRTKCU_API inline float3 floor(float3 v)
2772 {
2773  return make_float3(floorf(v.x), floorf(v.y), floorf(v.z));
2774 }
2775 
2776 // -----------------------------------------------------------------------------
2777 MIRTKCU_API inline float4 floor(float4 v)
2778 {
2779  return make_float4(floorf(v.x), floorf(v.y), floorf(v.z), floorf(v.w));
2780 }
2781 
2782 // -----------------------------------------------------------------------------
2783 MIRTKCU_API inline float1 ceil(float1 v)
2784 {
2785  return make_float1(ceilf(v.x));
2786 }
2787 
2788 // -----------------------------------------------------------------------------
2789 MIRTKCU_API inline float2 ceil(float2 v)
2790 {
2791  return make_float2(ceilf(v.x), ceilf(v.y));
2792 }
2793 
2794 // -----------------------------------------------------------------------------
2795 MIRTKCU_API inline float3 ceil(float3 v)
2796 {
2797  return make_float3(ceilf(v.x), ceilf(v.y), ceilf(v.z));
2798 }
2799 
2800 // -----------------------------------------------------------------------------
2801 MIRTKCU_API inline float4 ceil(float4 v)
2802 {
2803  return make_float4(ceilf(v.x), ceilf(v.y), ceilf(v.z), ceilf(v.w));
2804 }
2805 
2806 // -----------------------------------------------------------------------------
2807 MIRTKCU_API inline float1 round(float1 v)
2808 {
2809  return make_float1(round(v.x));
2810 }
2811 
2812 // -----------------------------------------------------------------------------
2813 MIRTKCU_API inline float2 round(float2 v)
2814 {
2815  return make_float2(round(v.x), round(v.y));
2816 }
2817 
2818 // -----------------------------------------------------------------------------
2819 MIRTKCU_API inline float3 round(float3 v)
2820 {
2821  return make_float3(float(round(v.x)), float(round(v.y)), float(round(v.z)));
2822 }
2823 
2824 // -----------------------------------------------------------------------------
2825 MIRTKCU_API inline float4 round(float4 v)
2826 {
2827  return make_float4(float(round(v.x)), float(round(v.y)), float(round(v.z)), float(round(v.w)));
2828 }
2829 
2830 // -----------------------------------------------------------------------------
2831 // Double-precision floating points
2832 // -----------------------------------------------------------------------------
2833 
2834 // -----------------------------------------------------------------------------
2835 MIRTKCU_API inline double1 floor(double1 v)
2836 {
2837  return make_double1(floor(v.x));
2838 }
2839 
2840 // -----------------------------------------------------------------------------
2841 MIRTKCU_API inline double2 floor(double2 v)
2842 {
2843  return make_double2(floor(v.x), floor(v.y));
2844 }
2845 
2846 // -----------------------------------------------------------------------------
2847 MIRTKCU_API inline double3 floor(double3 v)
2848 {
2849  return make_double3(floor(v.x), floor(v.y), floor(v.z));
2850 }
2851 
2852 // -----------------------------------------------------------------------------
2853 MIRTKCU_API inline double4 floor(double4 v)
2854 {
2855  return make_double4(floor(v.x), floor(v.y), floor(v.z), floor(v.w));
2856 }
2857 
2858 // -----------------------------------------------------------------------------
2859 MIRTKCU_API inline double1 ceil(double1 v)
2860 {
2861  return make_double1(ceil(v.x));
2862 }
2863 
2864 // -----------------------------------------------------------------------------
2865 MIRTKCU_API inline double2 ceil(double2 v)
2866 {
2867  return make_double2(ceil(v.x), ceil(v.y));
2868 }
2869 
2870 // -----------------------------------------------------------------------------
2871 MIRTKCU_API inline double3 ceil(double3 v)
2872 {
2873  return make_double3(ceil(v.x), ceil(v.y), ceil(v.z));
2874 }
2875 
2876 // -----------------------------------------------------------------------------
2877 MIRTKCU_API inline double4 ceil(double4 v)
2878 {
2879  return make_double4(ceil(v.x), ceil(v.y), ceil(v.z), ceil(v.w));
2880 }
2881 
2882 // -----------------------------------------------------------------------------
2883 MIRTKCU_API inline double1 round(double1 v)
2884 {
2885  return make_double1(double(round(v.x)));
2886 }
2887 
2888 // -----------------------------------------------------------------------------
2889 MIRTKCU_API inline double2 round(double2 v)
2890 {
2891  return make_double2(double(round(v.x)), double(round(v.y)));
2892 }
2893 
2894 // -----------------------------------------------------------------------------
2895 MIRTKCU_API inline double3 round(double3 v)
2896 {
2897  return make_double3(double(round(v.x)), double(round(v.y)), double(round(v.z)));
2898 }
2899 
2900 // -----------------------------------------------------------------------------
2901 MIRTKCU_API inline double4 round(double4 v)
2902 {
2903  return make_double4(double(round(v.x)), double(round(v.y)), double(round(v.z)), double(round(v.w)));
2904 }
2905 
2906 // =============================================================================
2907 // Fraction
2908 // =============================================================================
2909 
2910 // -----------------------------------------------------------------------------
2911 // Single-precision floating points
2912 // -----------------------------------------------------------------------------
2913 
2914 // -----------------------------------------------------------------------------
2915 MIRTKCU_API inline float frac(float v)
2916 {
2917  return v - floorf(v);
2918 }
2919 
2920 // -----------------------------------------------------------------------------
2921 MIRTKCU_API inline float2 frac(float2 v)
2922 {
2923  return make_float2(frac(v.x), frac(v.y));
2924 }
2925 
2926 // -----------------------------------------------------------------------------
2927 MIRTKCU_API inline float3 frac(float3 v)
2928 {
2929  return make_float3(frac(v.x), frac(v.y), frac(v.z));
2930 }
2931 
2932 // -----------------------------------------------------------------------------
2933 MIRTKCU_API inline float4 frac(float4 v)
2934 {
2935  return make_float4(frac(v.x), frac(v.y), frac(v.z), frac(v.w));
2936 }
2937 
2938 // -----------------------------------------------------------------------------
2939 // Double-precision floating points
2940 // -----------------------------------------------------------------------------
2941 
2942 // -----------------------------------------------------------------------------
2943 MIRTKCU_API inline double frac(double v)
2944 {
2945  return v - floor(v);
2946 }
2947 
2948 // -----------------------------------------------------------------------------
2949 MIRTKCU_API inline double2 frac(double2 v)
2950 {
2951  return make_double2(frac(v.x), frac(v.y));
2952 }
2953 
2954 // -----------------------------------------------------------------------------
2955 MIRTKCU_API inline double3 frac(double3 v)
2956 {
2957  return make_double3(frac(v.x), frac(v.y), frac(v.z));
2958 }
2959 
2960 // -----------------------------------------------------------------------------
2961 MIRTKCU_API inline double4 frac(double4 v)
2962 {
2963  return make_double4(frac(v.x), frac(v.y), frac(v.z), frac(v.w));
2964 }
2965 
2966 // =============================================================================
2967 // Minimum/Maximum
2968 // =============================================================================
2969 
2970 // -----------------------------------------------------------------------------
2971 // Double-precision floating points
2972 // -----------------------------------------------------------------------------
2973 
2974 // -----------------------------------------------------------------------------
2975 MIRTKCU_API inline double min(double2 a)
2976 {
2977  return min(a.x, a.y);
2978 }
2979 
2980 // -----------------------------------------------------------------------------
2981 MIRTKCU_API inline double min(double3 a)
2982 {
2983  return min(a.x, min(a.y, a.z));
2984 }
2985 
2986 // -----------------------------------------------------------------------------
2987 MIRTKCU_API inline double min(double4 a)
2988 {
2989  return min(min(a.x, a.y), min(a.z, a.w));
2990 }
2991 
2992 // -----------------------------------------------------------------------------
2993 MIRTKCU_API inline double max(double2 a)
2994 {
2995  return max(a.x, a.y);
2996 }
2997 
2998 // -----------------------------------------------------------------------------
2999 MIRTKCU_API inline double max(double3 a)
3000 {
3001  return max(a.x, max(a.y, a.z));
3002 }
3003 
3004 // -----------------------------------------------------------------------------
3005 MIRTKCU_API inline double max(double4 a)
3006 {
3007  return max(max(a.x, a.y), max(a.z, a.w));
3008 }
3009 
3010 // =============================================================================
3011 // Absolute value
3012 // =============================================================================
3013 
3014 // -----------------------------------------------------------------------------
3015 // Double-precision floating points
3016 // -----------------------------------------------------------------------------
3017 
3018 // -----------------------------------------------------------------------------
3019 MIRTKCU_API inline double2 fabs(double2 v)
3020 {
3021  return make_double2(fabs(v.x), fabs(v.y));
3022 }
3023 
3024 // -----------------------------------------------------------------------------
3025 MIRTKCU_API inline double3 fabs(double3 v)
3026 {
3027  return make_double3(fabs(v.x), fabs(v.y), fabs(v.z));
3028 }
3029 
3030 // -----------------------------------------------------------------------------
3031 MIRTKCU_API inline double4 fabs(double4 v)
3032 {
3033  return make_double4(fabs(v.x), fabs(v.y), fabs(v.z), fabs(v.w));
3034 }
3035 
3036 // =============================================================================
3037 // Exponential, square root,...
3038 // =============================================================================
3039 
3040 // -----------------------------------------------------------------------------
3041 // Single-precision floating points
3042 // -----------------------------------------------------------------------------
3043 
3044 // -----------------------------------------------------------------------------
3045 MIRTKCU_API inline float1 pow(float1 v, int e)
3046 {
3047  return make_float1(pow(v.x, e));
3048 }
3049 
3050 // -----------------------------------------------------------------------------
3051 MIRTKCU_API inline float2 pow(float2 v, int e)
3052 {
3053  return make_float2(pow(v.x, e), pow(v.y, e));
3054 }
3055 
3056 // -----------------------------------------------------------------------------
3057 MIRTKCU_API inline float3 pow(float3 v, int e)
3058 {
3059  return make_float3(pow(v.x, e), pow(v.y, e), pow(v.z, e));
3060 }
3061 
3062 // -----------------------------------------------------------------------------
3063 MIRTKCU_API inline float4 pow(float4 v, int e)
3064 {
3065  return make_float4(pow(v.x, e), pow(v.y, e), pow(v.z, e), pow(v.w, e));
3066 }
3067 
3068 // -----------------------------------------------------------------------------
3069 MIRTKCU_API inline float1 pow(float1 v, float e)
3070 {
3071  return make_float1(pow(v.x, e));
3072 }
3073 
3074 // -----------------------------------------------------------------------------
3075 MIRTKCU_API inline float2 pow(float2 v, float e)
3076 {
3077  return make_float2(pow(v.x, e), pow(v.y, e));
3078 }
3079 
3080 // -----------------------------------------------------------------------------
3081 MIRTKCU_API inline float3 pow(float3 v, float e)
3082 {
3083  return make_float3(pow(v.x, e), pow(v.y, e), pow(v.z, e));
3084 }
3085 
3086 // -----------------------------------------------------------------------------
3087 MIRTKCU_API inline float4 pow(float4 v, float e)
3088 {
3089  return make_float4(pow(v.x, e), pow(v.y, e), pow(v.z, e), pow(v.w, e));
3090 }
3091 
3092 // -----------------------------------------------------------------------------
3093 MIRTKCU_API inline float1 sqrt(float1 v)
3094 {
3095  return make_float1(sqrt(v.x));
3096 }
3097 
3098 // -----------------------------------------------------------------------------
3099 MIRTKCU_API inline float2 sqrt(float2 v)
3100 {
3101  return make_float2(sqrt(v.x), sqrt(v.y));
3102 }
3103 
3104 // -----------------------------------------------------------------------------
3105 MIRTKCU_API inline float3 sqrt(float3 v)
3106 {
3107  return make_float3(sqrt(v.x), sqrt(v.y), sqrt(v.z));
3108 }
3109 
3110 // -----------------------------------------------------------------------------
3111 MIRTKCU_API inline float4 sqrt(float4 v)
3112 {
3113  return make_float4(sqrt(v.x), sqrt(v.y), sqrt(v.z), sqrt(v.w));
3114 }
3115 
3116 // -----------------------------------------------------------------------------
3117 // Double-precision floating points
3118 // -----------------------------------------------------------------------------
3119 
3120 // -----------------------------------------------------------------------------
3121 MIRTKCU_API inline double1 pow(double1 v, int e)
3122 {
3123  return make_double1(pow(v.x, e));
3124 }
3125 
3126 // -----------------------------------------------------------------------------
3127 MIRTKCU_API inline double2 pow(double2 v, int e)
3128 {
3129  return make_double2(pow(v.x, e), pow(v.y, e));
3130 }
3131 
3132 // -----------------------------------------------------------------------------
3133 MIRTKCU_API inline double3 pow(double3 v, int e)
3134 {
3135  return make_double3(pow(v.x, e), pow(v.y, e), pow(v.z, e));
3136 }
3137 
3138 // -----------------------------------------------------------------------------
3139 MIRTKCU_API inline double4 pow(double4 v, int e)
3140 {
3141  return make_double4(pow(v.x, e), pow(v.y, e), pow(v.z, e), pow(v.w, e));
3142 }
3143 
3144 // -----------------------------------------------------------------------------
3145 MIRTKCU_API inline double1 pow(double1 v, double e)
3146 {
3147  return make_double1(pow(v.x, e));
3148 }
3149 
3150 // -----------------------------------------------------------------------------
3151 MIRTKCU_API inline double2 pow(double2 v, double e)
3152 {
3153  return make_double2(pow(v.x, e), pow(v.y, e));
3154 }
3155 
3156 // -----------------------------------------------------------------------------
3157 MIRTKCU_API inline double3 pow(double3 v, double e)
3158 {
3159  return make_double3(pow(v.x, e), pow(v.y, e), pow(v.z, e));
3160 }
3161 
3162 // -----------------------------------------------------------------------------
3163 MIRTKCU_API inline double4 pow(double4 v, double e)
3164 {
3165  return make_double4(pow(v.x, e), pow(v.y, e), pow(v.z, e), pow(v.w, e));
3166 }
3167 
3168 // -----------------------------------------------------------------------------
3169 MIRTKCU_API inline double1 sqrt(double1 v)
3170 {
3171  return make_double1(sqrt(v.x));
3172 }
3173 
3174 // -----------------------------------------------------------------------------
3175 MIRTKCU_API inline double2 sqrt(double2 v)
3176 {
3177  return make_double2(sqrt(v.x), sqrt(v.y));
3178 }
3179 
3180 // -----------------------------------------------------------------------------
3181 MIRTKCU_API inline double3 sqrt(double3 v)
3182 {
3183  return make_double3(sqrt(v.x), sqrt(v.y), sqrt(v.z));
3184 }
3185 
3186 // -----------------------------------------------------------------------------
3187 MIRTKCU_API inline double4 sqrt(double4 v)
3188 {
3189  return make_double4(sqrt(v.x), sqrt(v.y), sqrt(v.z), sqrt(v.w));
3190 }
3191 
3192 // =============================================================================
3193 // Indexed element access
3194 // =============================================================================
3195 
3196 // -----------------------------------------------------------------------------
3197 // Single-precision floating points
3198 // -----------------------------------------------------------------------------
3199 
3200 // -----------------------------------------------------------------------------
3201 MIRTKCU_API inline float get(const float &v, int n)
3202 {
3203  switch (n) {
3204  case 0: return v;
3205  default:
3206  cerr << "Invalid vector element index: " << n << endl;
3207  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3208  exit(1);
3209  }
3210 }
3211 
3212 // -----------------------------------------------------------------------------
3213 MIRTKCU_API inline float get(const float1 &v, int n)
3214 {
3215  switch (n) {
3216  case 0: return v.x;
3217  default:
3218  cerr << "Invalid vector element index: " << n << endl;
3219  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3220  exit(1);
3221  }
3222 }
3223 
3224 // -----------------------------------------------------------------------------
3225 MIRTKCU_API inline float get(const float2 &v, int n)
3226 {
3227  switch (n) {
3228  case 0: return v.x;
3229  case 1: return v.y;
3230  default:
3231  cerr << "Invalid vector element index: " << n << endl;
3232  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3233  exit(1);
3234  }
3235 }
3236 
3237 // -----------------------------------------------------------------------------
3238 MIRTKCU_API inline float get(const float3 &v, int n)
3239 {
3240  switch (n) {
3241  case 0: return v.x;
3242  case 1: return v.y;
3243  case 2: return v.z;
3244  default:
3245  cerr << "Invalid vector element index: " << n << endl;
3246  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3247  exit(1);
3248  }
3249 }
3250 
3251 // -----------------------------------------------------------------------------
3252 MIRTKCU_API inline float get(const float4 &v, int n)
3253 {
3254  switch (n) {
3255  case 0: return v.x;
3256  case 1: return v.y;
3257  case 2: return v.z;
3258  case 3: return v.w;
3259  default:
3260  cerr << "Invalid vector element index: " << n << endl;
3261  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3262  exit(1);
3263  }
3264 }
3265 
3266 // -----------------------------------------------------------------------------
3267 MIRTKCU_API inline float get(const float2x2 &m, int n)
3268 {
3269  switch (n) {
3270  case 0: return m.a.x;
3271  case 1: return m.a.y;
3272  case 2: return m.b.x;
3273  case 3: return m.b.y;
3274  default:
3275  cerr << "Invalid matrix element index: " << n << endl;
3276  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3277  exit(1);
3278  }
3279 }
3280 
3281 // -----------------------------------------------------------------------------
3282 MIRTKCU_API inline float get(const float3x3 &m, int n)
3283 {
3284  switch (n) {
3285  case 0: return m.a.x;
3286  case 1: return m.a.y;
3287  case 2: return m.a.z;
3288  case 3: return m.b.x;
3289  case 4: return m.b.y;
3290  case 5: return m.b.z;
3291  case 6: return m.c.x;
3292  case 7: return m.c.y;
3293  case 8: return m.c.z;
3294  default:
3295  cerr << "Invalid matrix element index: " << n << endl;
3296  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3297  exit(1);
3298  }
3299 }
3300 
3301 // -----------------------------------------------------------------------------
3302 MIRTKCU_API inline float get(const float3x4 &m, int n)
3303 {
3304  switch (n) {
3305  case 0: return m.a.x;
3306  case 1: return m.a.y;
3307  case 2: return m.a.z;
3308  case 3: return m.a.w;
3309  case 4: return m.b.x;
3310  case 5: return m.b.y;
3311  case 6: return m.b.z;
3312  case 7: return m.b.w;
3313  case 8: return m.c.x;
3314  case 9: return m.c.y;
3315  case 10: return m.c.z;
3316  case 11: return m.c.w;
3317  default:
3318  cerr << "Invalid matrix element index: " << n << endl;
3319  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3320  exit(1);
3321  }
3322 }
3323 
3324 // -----------------------------------------------------------------------------
3325 MIRTKCU_API inline float get(const float4x4 &m, int n)
3326 {
3327  switch (n) {
3328  case 0: return m.a.x;
3329  case 1: return m.a.y;
3330  case 2: return m.a.z;
3331  case 3: return m.a.w;
3332  case 4: return m.b.x;
3333  case 5: return m.b.y;
3334  case 6: return m.b.z;
3335  case 7: return m.b.w;
3336  case 8: return m.c.x;
3337  case 9: return m.c.y;
3338  case 10: return m.c.z;
3339  case 11: return m.c.w;
3340  case 12: return m.d.x;
3341  case 13: return m.d.y;
3342  case 14: return m.d.z;
3343  case 15: return m.d.w;
3344  default:
3345  cerr << "Invalid matrix element index: " << n << endl;
3346  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3347  exit(1);
3348  }
3349 }
3350 
3351 // -----------------------------------------------------------------------------
3352 MIRTKCU_API inline void put(float &v, int n, float s)
3353 {
3354  switch (n) {
3355  case 0: v = s;
3356  default:
3357  cerr << "Invalid vector element index: " << n << endl;
3358  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3359  exit(1);
3360  }
3361 }
3362 
3363 // -----------------------------------------------------------------------------
3364 MIRTKCU_API inline void put(float1 &v, int n, float s)
3365 {
3366  switch (n) {
3367  case 0: v.x = s;
3368  default:
3369  cerr << "Invalid vector element index: " << n << endl;
3370  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3371  exit(1);
3372  }
3373 }
3374 
3375 // -----------------------------------------------------------------------------
3376 MIRTKCU_API inline void put(float2 &v, int n, float s)
3377 {
3378  switch (n) {
3379  case 0: v.x = s;
3380  case 1: v.y = s;
3381  default:
3382  cerr << "Invalid vector element index: " << n << endl;
3383  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3384  exit(1);
3385  }
3386 }
3387 
3388 // -----------------------------------------------------------------------------
3389 MIRTKCU_API inline void put(float3 &v, int n, float s)
3390 {
3391  switch (n) {
3392  case 0: v.x = s;
3393  case 1: v.y = s;
3394  case 2: v.z = s;
3395  default:
3396  cerr << "Invalid vector element index: " << n << endl;
3397  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3398  exit(1);
3399  }
3400 }
3401 
3402 // -----------------------------------------------------------------------------
3403 MIRTKCU_API inline void put(float4 &v, int n, float s)
3404 {
3405  switch (n) {
3406  case 0: v.x = s;
3407  case 1: v.y = s;
3408  case 2: v.z = s;
3409  case 3: v.w = s;
3410  default:
3411  cerr << "Invalid vector element index: " << n << endl;
3412  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3413  exit(1);
3414  }
3415 }
3416 
3417 // -----------------------------------------------------------------------------
3418 MIRTKCU_API inline void put(float2x2 &m, int n, float s)
3419 {
3420  switch (n) {
3421  case 0: m.a.x = s;
3422  case 1: m.a.y = s;
3423  case 2: m.b.x = s;
3424  case 3: m.b.y = s;
3425  default:
3426  cerr << "Invalid matrix element index: " << n << endl;
3427  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3428  exit(1);
3429  }
3430 }
3431 
3432 // -----------------------------------------------------------------------------
3433 MIRTKCU_API inline void put(float3x3 &m, int n, float s)
3434 {
3435  switch (n) {
3436  case 0: m.a.x = s;
3437  case 1: m.a.y = s;
3438  case 2: m.a.z = s;
3439  case 3: m.b.x = s;
3440  case 4: m.b.y = s;
3441  case 5: m.b.z = s;
3442  case 6: m.c.x = s;
3443  case 7: m.c.y = s;
3444  case 8: m.c.z = s;
3445  default:
3446  cerr << "Invalid matrix element index: " << n << endl;
3447  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3448  exit(1);
3449  }
3450 }
3451 
3452 // -----------------------------------------------------------------------------
3453 MIRTKCU_API inline void put(float3x4 &m, int n, float s)
3454 {
3455  switch (n) {
3456  case 0: m.a.x = s;
3457  case 1: m.a.y = s;
3458  case 2: m.a.z = s;
3459  case 3: m.a.w = s;
3460  case 4: m.b.x = s;
3461  case 5: m.b.y = s;
3462  case 6: m.b.z = s;
3463  case 7: m.b.w = s;
3464  case 8: m.c.x = s;
3465  case 9: m.c.y = s;
3466  case 10: m.c.z = s;
3467  case 11: m.c.w = s;
3468  default:
3469  cerr << "Invalid matrix element index: " << n << endl;
3470  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3471  exit(1);
3472  }
3473 }
3474 
3475 // -----------------------------------------------------------------------------
3476 MIRTKCU_API inline void put(float4x4 &m, int n, float s)
3477 {
3478  switch (n) {
3479  case 0: m.a.x = s;
3480  case 1: m.a.y = s;
3481  case 2: m.a.z = s;
3482  case 3: m.a.w = s;
3483  case 4: m.b.x = s;
3484  case 5: m.b.y = s;
3485  case 6: m.b.z = s;
3486  case 7: m.b.w = s;
3487  case 8: m.c.x = s;
3488  case 9: m.c.y = s;
3489  case 10: m.c.z = s;
3490  case 11: m.c.w = s;
3491  case 12: m.d.x = s;
3492  case 13: m.d.y = s;
3493  case 14: m.d.z = s;
3494  case 15: m.d.w = s;
3495  default:
3496  cerr << "Invalid matrix element index: " << n << endl;
3497  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3498  exit(1);
3499  }
3500 }
3501 
3502 // -----------------------------------------------------------------------------
3503 // Double-precision floating points
3504 // -----------------------------------------------------------------------------
3505 
3506 // -----------------------------------------------------------------------------
3507 MIRTKCU_API inline double get(const double &v, int n)
3508 {
3509  switch (n) {
3510  case 0: return v;
3511  default:
3512  cerr << "Invalid vector element index: " << n << endl;
3513  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3514  exit(1);
3515  }
3516 }
3517 
3518 // -----------------------------------------------------------------------------
3519 MIRTKCU_API inline double get(const double1 &v, int n)
3520 {
3521  switch (n) {
3522  case 0: return v.x;
3523  default:
3524  cerr << "Invalid vector element index: " << n << endl;
3525  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3526  exit(1);
3527  }
3528 }
3529 
3530 // -----------------------------------------------------------------------------
3531 MIRTKCU_API inline double get(const double2 &v, int n)
3532 {
3533  switch (n) {
3534  case 0: return v.x;
3535  case 1: return v.y;
3536  default:
3537  cerr << "Invalid vector element index: " << n << endl;
3538  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3539  exit(1);
3540  }
3541 }
3542 
3543 // -----------------------------------------------------------------------------
3544 MIRTKCU_API inline double get(const double3 &v, int n)
3545 {
3546  switch (n) {
3547  case 0: return v.x;
3548  case 1: return v.y;
3549  case 2: return v.z;
3550  default:
3551  cerr << "Invalid vector element index: " << n << endl;
3552  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3553  exit(1);
3554  }
3555 }
3556 
3557 // -----------------------------------------------------------------------------
3558 MIRTKCU_API inline double get(const double4 &v, int n)
3559 {
3560  switch (n) {
3561  case 0: return v.x;
3562  case 1: return v.y;
3563  case 2: return v.z;
3564  case 3: return v.w;
3565  default:
3566  cerr << "Invalid vector element index: " << n << endl;
3567  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3568  exit(1);
3569  }
3570 }
3571 
3572 // -----------------------------------------------------------------------------
3573 MIRTKCU_API inline double get(const double2x2 &m, int n)
3574 {
3575  switch (n) {
3576  case 0: return m.a.x;
3577  case 1: return m.a.y;
3578  case 2: return m.b.x;
3579  case 3: return m.b.y;
3580  default:
3581  cerr << "Invalid matrix element index: " << n << endl;
3582  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3583  exit(1);
3584  }
3585 }
3586 
3587 // -----------------------------------------------------------------------------
3588 MIRTKCU_API inline double get(const double3x3 &m, int n)
3589 {
3590  switch (n) {
3591  case 0: return m.a.x;
3592  case 1: return m.a.y;
3593  case 2: return m.a.z;
3594  case 3: return m.b.x;
3595  case 4: return m.b.y;
3596  case 5: return m.b.z;
3597  case 6: return m.c.x;
3598  case 7: return m.c.y;
3599  case 8: return m.c.z;
3600  default:
3601  cerr << "Invalid matrix element index: " << n << endl;
3602  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3603  exit(1);
3604  }
3605 }
3606 
3607 // -----------------------------------------------------------------------------
3608 MIRTKCU_API inline double get(const double3x4 &m, int n)
3609 {
3610  switch (n) {
3611  case 0: return m.a.x;
3612  case 1: return m.a.y;
3613  case 2: return m.a.z;
3614  case 3: return m.a.w;
3615  case 4: return m.b.x;
3616  case 5: return m.b.y;
3617  case 6: return m.b.z;
3618  case 7: return m.b.w;
3619  case 8: return m.c.x;
3620  case 9: return m.c.y;
3621  case 10: return m.c.z;
3622  case 11: return m.c.w;
3623  default:
3624  cerr << "Invalid matrix element index: " << n << endl;
3625  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3626  exit(1);
3627  }
3628 }
3629 
3630 // -----------------------------------------------------------------------------
3631 MIRTKCU_API inline double get(const double4x4 &m, int n)
3632 {
3633  switch (n) {
3634  case 0: return m.a.x;
3635  case 1: return m.a.y;
3636  case 2: return m.a.z;
3637  case 3: return m.a.w;
3638  case 4: return m.b.x;
3639  case 5: return m.b.y;
3640  case 6: return m.b.z;
3641  case 7: return m.b.w;
3642  case 8: return m.c.x;
3643  case 9: return m.c.y;
3644  case 10: return m.c.z;
3645  case 11: return m.c.w;
3646  case 12: return m.d.x;
3647  case 13: return m.d.y;
3648  case 14: return m.d.z;
3649  case 15: return m.d.w;
3650  default:
3651  cerr << "Invalid matrix element index: " << n << endl;
3652  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3653  exit(1);
3654  }
3655 }
3656 
3657 // -----------------------------------------------------------------------------
3658 MIRTKCU_API inline void put(double &v, int n, double s)
3659 {
3660  switch (n) {
3661  case 0: v = s;
3662  default:
3663  cerr << "Invalid vector element index: " << n << endl;
3664  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3665  exit(1);
3666  }
3667 }
3668 
3669 // -----------------------------------------------------------------------------
3670 MIRTKCU_API inline void put(double1 &v, int n, double s)
3671 {
3672  switch (n) {
3673  case 0: v.x = s;
3674  default:
3675  cerr << "Invalid vector element index: " << n << endl;
3676  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3677  exit(1);
3678  }
3679 }
3680 
3681 // -----------------------------------------------------------------------------
3682 MIRTKCU_API inline void put(double2 &v, int n, double s)
3683 {
3684  switch (n) {
3685  case 0: v.x = s;
3686  case 1: v.y = s;
3687  default:
3688  cerr << "Invalid vector element index: " << n << endl;
3689  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3690  exit(1);
3691  }
3692 }
3693 
3694 // -----------------------------------------------------------------------------
3695 MIRTKCU_API inline void put(double3 &v, int n, double s)
3696 {
3697  switch (n) {
3698  case 0: v.x = s;
3699  case 1: v.y = s;
3700  case 2: v.z = s;
3701  default:
3702  cerr << "Invalid vector element index: " << n << endl;
3703  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3704  exit(1);
3705  }
3706 }
3707 
3708 // -----------------------------------------------------------------------------
3709 MIRTKCU_API inline void put(double4 &v, int n, double s)
3710 {
3711  switch (n) {
3712  case 0: v.x = s;
3713  case 1: v.y = s;
3714  case 2: v.z = s;
3715  case 3: v.w = s;
3716  default:
3717  cerr << "Invalid vector element index: " << n << endl;
3718  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3719  exit(1);
3720  }
3721 }
3722 
3723 // -----------------------------------------------------------------------------
3724 MIRTKCU_API inline void put(double2x2 &m, int n, double s)
3725 {
3726  switch (n) {
3727  case 0: m.a.x = s;
3728  case 1: m.a.y = s;
3729  case 2: m.b.x = s;
3730  case 3: m.b.y = s;
3731  default:
3732  cerr << "Invalid matrix element index: " << n << endl;
3733  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3734  exit(1);
3735  }
3736 }
3737 
3738 // -----------------------------------------------------------------------------
3739 MIRTKCU_API inline void put(double3x3 &m, int n, double s)
3740 {
3741  switch (n) {
3742  case 0: m.a.x = s;
3743  case 1: m.a.y = s;
3744  case 2: m.a.z = s;
3745  case 3: m.b.x = s;
3746  case 4: m.b.y = s;
3747  case 5: m.b.z = s;
3748  case 6: m.c.x = s;
3749  case 7: m.c.y = s;
3750  case 8: m.c.z = s;
3751  default:
3752  cerr << "Invalid matrix element index: " << n << endl;
3753  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3754  exit(1);
3755  }
3756 }
3757 
3758 // -----------------------------------------------------------------------------
3759 MIRTKCU_API inline void put(double3x4 &m, int n, double s)
3760 {
3761  switch (n) {
3762  case 0: m.a.x = s;
3763  case 1: m.a.y = s;
3764  case 2: m.a.z = s;
3765  case 3: m.a.w = s;
3766  case 4: m.b.x = s;
3767  case 5: m.b.y = s;
3768  case 6: m.b.z = s;
3769  case 7: m.b.w = s;
3770  case 8: m.c.x = s;
3771  case 9: m.c.y = s;
3772  case 10: m.c.z = s;
3773  case 11: m.c.w = s;
3774  default:
3775  cerr << "Invalid matrix element index: " << n << endl;
3776  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3777  exit(1);
3778  }
3779 }
3780 
3781 // -----------------------------------------------------------------------------
3782 MIRTKCU_API inline void put(double4x4 &m, int n, double s)
3783 {
3784  switch (n) {
3785  case 0: m.a.x = s;
3786  case 1: m.a.y = s;
3787  case 2: m.a.z = s;
3788  case 3: m.a.w = s;
3789  case 4: m.b.x = s;
3790  case 5: m.b.y = s;
3791  case 6: m.b.z = s;
3792  case 7: m.b.w = s;
3793  case 8: m.c.x = s;
3794  case 9: m.c.y = s;
3795  case 10: m.c.z = s;
3796  case 11: m.c.w = s;
3797  case 12: m.d.x = s;
3798  case 13: m.d.y = s;
3799  case 14: m.d.z = s;
3800  case 15: m.d.w = s;
3801  default:
3802  cerr << "Invalid matrix element index: " << n << endl;
3803  cerr << "Set breakpoint in " << __FILE__ << ":" << __LINE__ << " to debug." << endl;
3804  exit(1);
3805  }
3806 }
3807 
3808 // =============================================================================
3809 // Aliases for default precision
3810 // =============================================================================
3811 
3812 #if MIRTK_USE_FLOAT_BY_DEFAULT // (i.e., use float)
3813  typedef float realt;
3814  typedef float1 real1;
3815  typedef float2 real2;
3816  typedef float3 real3;
3817  typedef float4 real4;
3818  typedef float2x2 real2x2;
3819  typedef float3x3 real3x3;
3820  typedef float3x4 real3x4;
3821  typedef float4x4 real4x4;
3822  #define make_real1 make_float1
3823  #define make_real2 make_float2
3824  #define make_real3 make_float3
3825  #define make_real4 make_float4
3826  #define make_real3x3 make_float3x3
3827  #define make_real3x4 make_float3x4
3828  #define make_real4x4 make_float4x4
3829 #else // MIRTK_USE_FLOAT_BY_DEFAULT (i.e., use double)
3830  typedef double realt;
3831  typedef double1 real1;
3832  typedef double2 real2;
3833  typedef double3 real3;
3834  typedef double4 real4;
3835  typedef double2x2 real2x2;
3836  typedef double3x3 real3x3;
3837  typedef double3x4 real3x4;
3838  typedef double4x4 real4x4;
3839  #define make_real1 make_double1
3840  #define make_real2 make_double2
3841  #define make_real3 make_double3
3842  #define make_real4 make_double4
3843  #define make_real3x3 make_double3x3
3844  #define make_real3x4 make_double3x4
3845  #define make_real4x4 make_double4x4
3846 #endif // MIRTK_USE_FLOAT_BY_DEFAULT
3847 
3848 
3849 } // namespace mirtk
3850 
3851 #endif // MIRTK_Math_H
2x2 single-precision matrix
Definition: Math.h:263
MIRTK_Common_EXPORT const double nan
Not A Number (NaN)
MIRTKCU_API int sgn(T val)
Sign function - https://en.wikipedia.org/wiki/Sign_function.
Definition: Math.h:146
MIRTKCU_HOST_API float * to_float(const VoxelType *in, unsigned int N)
Copy and cast image to single-precision floating point.
Definition: Math.h:547
MIRTK_Common_EXPORT const double pi_half
Constant value of .
3x4 single-precision coordinate transformation matrix
Definition: Math.h:329
4x4 single-precision matrix
Definition: Math.h:306
MIRTKCU_API bool IsZero(double a, double tol=1e-12)
Determine equality of a floating point number with zero.
Definition: Math.h:131
MIRTKCU_API bool operator<(const float1 &a, const float1 &b)
Check if 1D vector is lexicographically less than another.
Definition: Math.h:833
MIRTKCU_API int iceil(T x)
Round floating-point value to next greater integer and cast to int.
Definition: Math.h:162
MIRTKCU_API bool IsNaN(double x)
Check if floating point value is not a number (NaN)
Definition: Math.h:91
3x3 double-precision matrix
Definition: Math.h:375
MIRTK_Common_EXPORT const double two_pi
Constant value of .
MIRTK_Common_EXPORT const double pi
Constant value of .
3x3 single-precision matrix
Definition: Math.h:284
MIRTKCU_API int ifloor(T x)
Round floating-point value to next smaller integer and cast to int.
Definition: Math.h:154
MIRTKCU_API double finc(double f)
Definition: Math.h:178
MIRTKCU_API bool fequal(double a, double b, double tol=1e-12)
Definition: Math.h:138
MIRTKCU_API bool AreEqualOrNaN(double a, double b, double tol=1e-12)
Determine equality of two floating point numbers including check if both are NaN. ...
Definition: Math.h:122
MIRTKCU_API double fdec(double f)
Definition: Math.h:188
Definition: IOConfig.h:41
3x4 double-precision coordinate transformation matrix
Definition: Math.h:418
4x4 double-precision matrix
Definition: Math.h:396
MIRTKCU_API bool IsInf(double x)
Check if floating point value represents infinity.
Definition: Math.h:103
2x2 double-precision matrix
Definition: Math.h:355
MIRTKCU_API bool operator==(const float1 &a, const float1 &b)
Check two 1D vectors for equality.
Definition: Math.h:731
MIRTKCU_API float2x2 transpose(float2x2 m)
Transpose 2x2 matrix.
Definition: Math.h:681
double SShapedMembershipFunction(double x, double a, double b)
Definition: Math.h:238
MIRTKCU_API bool AreEqual(double a, double b, double tol=1e-12)
Determine equality of two floating point numbers.
Definition: Math.h:115
MIRTKCU_API int iround(T x)
Round floating-point value and cast to int.
Definition: Math.h:170
MIRTK_Common_EXPORT const double deg_per_rad
Degree per radian, i.e., .
MIRTK_Common_EXPORT const double inf
Positive infinity.
MIRTK_Common_EXPORT const double rad_per_deg
Radians per degree, i.e., .