Matrix3.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include "boost/range/numeric.hpp"
4 
5 #include "TQuaternion.h"
6 
8 #include "boca/math/Matrix2.hh"
9 
10 namespace boca
11 {
12 
13 template<typename Value_>
14 using Array3 = std::array<Value_, 3>;
15 
20 template <typename Value_>
21 class Matrix3 : public boost::totally_ordered<Matrix3<Value_>>
22  , boost::additive<Matrix3<Value_>>
23 {
24 
25  template<typename Value_2_>
26  using ValueProduct = ValueProduct<Value_, Value_2_>;
27  using ValueSquare = boca::ValueSquare<Value_>;
28  using ValueCubed = boca::ValueCubed<Value_>;
29  template<typename Value_2>
30  using ValueQuotient = ValueQuotient<Value_, Value_2>;
31  using ValueInverse = boost::units::divide_typeof_helper<double, Value_>;
32  template<typename Value_2>
33  using OnlyIfNotOrSameQuantity = typename std::enable_if < !IsQuantity<Value_2>::value || std::is_same<Value_, Value_2>::value >::type;
34  template<typename Value_2>
35  using OnlyIfNotQuantity = typename std::enable_if < !IsQuantity<Value_2>::value >::type;
36 
37 public:
38 
47  constexpr Matrix3() {}
48 
52  Matrix3(Value_ scalar, Matrix matrix = Matrix::diagonal)
53  {
54  switch (matrix) {
55  case Matrix::diagonal :
56  SetDiagonal(scalar);
57  break;
58  case Matrix::uniform :
59  SetUniform(scalar);
60  break;
61  default :
62  std::cout << "Maformed matrix constructor: " << Name(matrix) << '\n';
63  }
64  }
65 
70  {
71  switch (matrix) {
72  case Matrix::row:
73  SetRows(x, y, z);
74  break;
75  case Matrix::column :
76  SetColumns(x, y, z);
77  break;
78  default :
79  std::cout << "Maformed matrix constructor: " << Name(matrix) << '\n';
80  }
81  }
82 
86  Matrix3(Vector3<Value_> const &vector_1, Vector3<Value_> const &vector_2, Matrix matrix = Matrix::symmetric)
87  {
88  switch (matrix) {
89  case Matrix::symmetric:
90  *this = MatrixProduct(vector_1, vector_2);
91  break;
92  default :
93  std::cout << "Maformed matrix constructor: " << Name(matrix) << '\n';
94  }
95  }
96 
101  {
102  switch (matrix) {
104  SetAntisymmetric(vector);
105  break;
106  case Matrix::diagonal:
107  SetDiagonal(vector);
108  break;
109  default :
110  std::cout << "Maformed matrix constructor: " << Name(matrix) << '\n';
111  }
112  }
113 
117  Matrix3(Vector3<Value_> const &vector, Dim3 dim, Matrix matrix = Matrix::row)
118  {
119  switch (matrix) {
120  case Matrix::row:
121  SetRow(vector, dim);
122  break;
123  case Matrix::column:
124  SetColumn(vector, dim);
125  break;
126  default :
127  std::cout << "Maformed matrix constructor: " << Name(matrix) << '\n';
128  }
129  }
130 
131 
132 
138  Matrix3(TQuaternion const &quaternion)
139  {
140  auto const mag2 = quaternion.QMag2();
141  if (mag2 <= 0) *this = Matrix3(1.);
142  else {
143  *this = 2 * (Matrix3(sqr(quaternion.fRealPart)) + Matrix3(Vector3<double>(quaternion.fVectorPart), Vector3<double>(quaternion.fVectorPart)) - Matrix3(Vector3<double>(quaternion.fVectorPart * quaternion.fRealPart)));
144  // protect agains non-unit quaternion
145  if (std::abs(mag2 - 1) > 1e-10) *this /= mag2;
146  // diago : remove identity
147  *this -= Matrix3(1);
148  }
149  }
150 
154  template<typename Value_2>
155  constexpr Matrix3(Matrix3<Value_2> const &matrix) :
156  x_(matrix.X()),
157  y_(matrix.Y()),
158  z_(matrix.Z())
159  {}
160 
162 
171  Matrix3 &SetDiagonal(Value_ value)
172  {
173  x_ = {value, Dim3::x};
174  y_ = {value, Dim3::y};
175  z_ = {value, Dim3::z};
176  return *this;
177  }
178 
183  {
184  x_ = {vector.X(), Dim3::x};
185  y_ = {vector.Y(), Dim3::y};
186  z_ = {vector.Z(), Dim3::z};
187  return *this;
188  }
189 
194  {
195  x_.Y() = vector.X();
196  x_.Z() = vector.Y();
197  y_.Z() = vector.Z();
198  return *this;
199  }
200 
205  {
206  y_.X() = vector.X();
207  z_.X() = vector.Y();
208  z_.Y() = vector.Z();
209  return *this;
210  }
211 
216  {
217  SetUpperTriangle({0});
218  SetLowerTriangle({0});
219  return SetDiagonal(1);
220  }
221 
225  Matrix3 &SetUniform(Value_ value)
226  {
227  x_ = {value, value, value};
228  y_ = {value, value, value};
229  z_ = {value, value, value};
230  return *this;
231  }
232 
237  {
238  x_ = x;
239  y_ = y;
240  z_ = z;
241  }
242 
246  void SetRow(Vector3<Value_> const &vector, Dim3 dim)
247  {
248  switch (dim) {
249  case Dim3::x :
250  x_ = vector;
251  break;
252  case Dim3::y :
253  y_ = vector;
254  break;
255  case Dim3::z :
256  z_ = vector;
257  break;
258  default :
259  ;
260  }
261  }
262 
267  {
268  x_ = {x.X(), y.X(), z.X()};
269  y_ = {x.Y(), y.Y(), z.Y()};
270  z_ = {x.Z(), y.Z(), z.Z()};
271  }
272 
276  void SetColumn(Vector3<Value_> const &vector, Dim3 dim)
277  {
278  x_ = {vector.X(), dim};
279  y_ = {vector.Y(), dim};
280  z_ = {vector.Z(), dim};
281  }
282 
286  void SetAntisymmetric(Vector3<Value_> const &vector)
287  {
288  x_ = {Value_(0), vector.Z(), -vector.Y()};
289  y_ = { -vector.Z(), Value_(0), vector.X()};
290  z_ = {vector.Y(), -vector.X(), Value_(0)};
291  }
292 
298  Matrix3 &SetEulerAngles(Angle const &phi, Angle const &theta, Angle const &psi, Dim2 dim = Dim2::x)
299  {
300  SetToIdentity();
301  Rotate(phi, Dim3::z);
302  switch (dim) {
303  case Dim2::x :
304  Rotate(theta, Dim3::x);
305  break;
306  case Dim2::y :
307  Rotate(theta, Dim3::y);
308  break;
309  default :
310  ;
311  }
312  Rotate(psi, Dim3::z);
313  return *this;
314  }
315 
320  void SetPhi(Angle const &phi, Dim2 dim = Dim2::x)
321  {
322  SetEulerAngles(phi, Theta(dim), Psi(dim), dim);
323  }
324 
328  void SetTheta(Angle const &theta, Dim2 dim = Dim2::x)
329  {
330  SetEulerAngles(Phi(dim), theta, Psi(dim), dim);
331  }
332 
336  void SetPsi(Angle const &psi, Dim2 dim = Dim2::x)
337  {
338  SetEulerAngles(Phi(), Theta(dim), psi, dim);
339  }
340 
345  Matrix3 &SetAxis(Vector3<Value_> const &axis, Dim3 dim)
346  {
347  return SetAxis(axis, {axis.Mag(), Next(dim)});
348  }
349 
354  Matrix3 &SetAxis(Vector3<Value_> const &axis, Vector3<Value_> const &plane, Dim3 dim)
355  {
356  *this = MakeBasis(plane, axis).MoveTo(dim, Dim3::x).Transpose();
357  return *this;
358  }
359 
361 
371  constexpr Vector3<Value_> const &X() const
372  {
373  return x_;
374  }
375 
377  {
378  return x_;
379  }
381 
386  constexpr Vector3<Value_> const &Y() const
387  {
388  return y_;
389  }
390 
392  {
393  return y_;
394  }
396 
402  {
403  return z_;
404  }
405 
406  constexpr Vector3<Value_> const &Z() const
407  {
408  return z_;
409  }
411 
413 
414  constexpr Matrix Symmetry()
415  {
416  if (UpperTriangle() == LowerTriangle()) return Matrix::symmetric;
417  if (UpperTriangle() == -LowerTriangle() && Diagonal() == Vector3<Value_> {0, 0, 0}) return Matrix::antisymmetric;
418  return Matrix::none;
419  }
420 
429  constexpr Vector3<Value_> ColumnX() const
430  {
431  return {x_.X(), y_.X(), z_.X()};
432  }
433 
437  constexpr Vector3<Value_> ColumnY() const
438  {
439  return {x_.Y(), y_.Y(), z_.Y()};
440  }
441 
445  constexpr Vector3<Value_> ColumnZ() const
446  {
447  return {x_.Z(), y_.Z(), z_.Z()};
448  }
449 
454  {
455  return {x_.X(), y_.Y(), z_.Z()};
456  }
457 
462  {
463  return {x_.Y(), x_.Z(), y_.Z()};
464  }
465 
470  {
471  return {y_.X(), z_.X(), z_.Y()};
472  }
473 
475 
484  constexpr auto Sign(Dim3 i, Dim3 j) const
485  {
486  return (static_cast<int>(i) + static_cast<int>(j)) % 2 ? -1 : 1;
487  }
488 
492  constexpr auto Trace()const
493  {
494  return x_.X() + y_.Y() + z_.Z();
495  }
496 
500  template<typename Value_2_>
501  constexpr auto ProductTrace(Matrix3<Value_2_> const &matrix) const
502  {
503  return x_ * matrix.ColumnX() + y_ * matrix.ColumnY() + z_ * matrix.ColumnZ();
504  }
505 
509  constexpr auto Determinant()const
510  {
511  return boost::accumulate(Dimensions3(), ValueCubed(0), [&](ValueCubed & sum, Dim3 dim) {
512  return sum + Laplace(Dim3::x, dim);
513  });
514  }
515 
519  constexpr auto Laplace(Dim3 dim_1, Dim3 dim_2) const
520  {
521  return (*this)[dim_1][dim_2] * Cofactor(dim_1, dim_2);
522  }
523 
527  constexpr auto Cofactor(Dim3 dim_1, Dim3 dim_2) const
528  {
529  return static_cast<double>(Sign(dim_1, dim_2)) * Minor(dim_1, dim_2);
530  }
531 
535  constexpr auto Minor(Dim3 delete_1, Dim3 delete_2) const
536  {
537  return SubMatrix(delete_1, delete_2).Determinant();
538  }
539 
543  constexpr auto ReducedDeterminant(Dim3 dim_1, Dim3 dim_2) const
544  {
545  return Determinant() - Laplace(dim_1, dim_2);
546  }
547 
556  Angle Phi(Dim3 dim) const
557  {
558  return Vector2<Value_>(x_(dim), y_(dim)).Phi();
559  }
560 
564  Angle Theta(Dim3 dim) const
565  {
566  return acos(z_(dim));
567  }
568 
572  Angle Phi(Dim2 dim) const
573  {
574  switch (dim) {
575  case Dim2::x :
576  return XPhi();
577  case Dim2::y :
578  return XPhi() + PiRad() / 2.;
579  default :
580  return XPhi();
581  }
582  }
583 
588  {
589  return Theta(Dim3::z);
590  }
591 
595  Angle Psi(Dim2 dim) const
596  {
597  switch (dim) {
598  case Dim2::x :
599  return XPsi();
600  case Dim2::y :
601  return XPsi() - PiRad() / 2.;
602  default :
603  return XPhi();
604  }
605  }
606 
608 
610 
619  constexpr Matrix3 Transposed() const
620  {
621  return {ColumnX(), ColumnY(), ColumnZ()};
622  }
623 
627  constexpr Matrix3 &Transpose()
628  {
629  return *this = Transposed();
630  }
631 
638  {
639  auto const det = Determinant();
640  if (det == ValueCubed(0)) return {};
641  auto const x = ColumnX();
642  auto const y = ColumnY();
643  auto const z = ColumnZ();
644  return Matrix3<ValueSquare>(y ^ z, z ^ x, x ^ y) / det;
645  }
646 
650  auto SubMatrix(Dim3 delete_1, Dim3 delete_2) const
651  {
652  auto dim2_1 = EnumIterator<Dim2> {Dim2::x};
653  auto dim2_2 = EnumIterator<Dim2> {Dim2::x};
654  auto matrix = Matrix2<Value_> {};
655  for (auto dim3_1 : Dimensions3()) {
656  if (dim3_1 == delete_1) continue;
657  for (auto dim3_2 : Dimensions3()) {
658  if (dim3_2 == delete_2) continue;
659  matrix[*dim2_1][*dim2_2] = (*this)[dim3_1][dim3_2];
660  ++dim2_2;
661  }
662  ++dim2_1;
663  dim2_2.Set(Dim2::x);
664  }
665  return matrix;
666  }
667 
671  constexpr Matrix3 &MoveTo(Dim3 dim_1, Dim3 dim_2)
672  {
673  std::swap((*this)(dim_1), (*this)(dim_2));
674  std::swap((*this)(dim_1), (*this)(Third(dim_1, dim_2)));
675  return *this;
676  }
677 
679 
688  Matrix3 &Rotate(Angle const &phi, Dim3 dim_1, Dim3 dim_2)
689  {
690  if (phi == 0_rad) return *this;
691  auto const cos = boost::units::cos(phi);
692  auto const sin = boost::units::sin(phi);
693  auto const row = (*this)(dim_1);
694  (*this)(dim_1) = cos * row - sin * (*this)(dim_2);
695  (*this)(dim_2) = sin * row + cos * (*this)(dim_2);
696  return *this;
697  }
698 
702  constexpr Matrix3 &Rotate(Angle const &phi, Dim3 dim)
703  {
704  switch (dim) {
705  case Dim3::x :
706  return Rotate(phi, Dim3::y, Dim3::z);
707  case Dim3::y :
708  return Rotate(phi, Dim3::z, Dim3::x);
709  case Dim3::z :
710  return Rotate(phi, Dim3::x, Dim3::y);
711  default :
712  ;
713  }
714  }
715 
719  Matrix3 &Rotate(Angle const &phi, Vector3<Value_> const &axis)
720  {
721  if (phi == 0_rad) return *this;
722  auto const sin = boost::units::sin(phi);
723  auto const cos = boost::units::cos(phi);
724  auto const unit = axis.Unit();
725  return Transform(Matrix3(cos) + Matrix3(unit, unit) * (1 - cos) - Matrix3(unit * sin));
726  }
727 
731  constexpr Matrix3 &RotateAxes(Vector3<Value_> const &vector_x, Vector3<Value_> const &vector_y, Vector3<Value_> const &vector_z)
732  {
733  auto const epsilon = 0.001;
734  auto const cross = vector_x.Cross(vector_y);
735  if (std::abs(vector_z.X() - cross.X()) > epsilon || std::abs(vector_z.Y() - cross.Y()) > epsilon || std::abs(vector_z.Z() - cross.Z()) > epsilon || std::abs(vector_x.Mag2() - 1) > epsilon || std::abs(vector_y.Mag2() - 1) > epsilon || std::abs(vector_z.Mag2() - 1) > epsilon || std::abs(vector_x.Dot(vector_y)) > epsilon || std::abs(vector_y.Dot(vector_z)) > epsilon || std::abs(vector_z.Dot(vector_x)) > epsilon) {
736  std::cout << "RotateAxes bad axis vectors" << '\n';
737  return *this;
738  }
739  return Transform(Matrix3(vector_x.X(), vector_y.X(), vector_z.X(), vector_x.Y(), vector_y.Y(), vector_z.Y(), vector_x.Z(), vector_y.Z(), vector_z.Z()));
740  }
741 
742 
746  constexpr Matrix3 &RotateEulerAngles(Angle const &phi, Angle const &theta, Angle const &psi, Dim2 dim = Dim2::x)
747  {
748  auto euler = Matrix3 {};
749  euler.SetEulerAngles(phi, theta, psi, dim);
750  return Transform(euler);
751  }
752 
756  std::pair<Vector3<Value_>, Angle> AngleAxis() const
757  {
758  auto const cosa = 0.5 * (x_.X() + y_.Y() + z_.Z() - 1);
759  auto const cosa1 = 1 - cosa;
760  if (cosa1 <= Value_(0)) return std::make_pair<Vector3<Value_>, Angle>({0, 0, 1}, 0_rad);
761  auto x = x_.X() > cosa ? sqrt((x_.X() - cosa) / cosa1) : 0;
762  auto y = y_.Y() > cosa ? sqrt((y_.Y() - cosa) / cosa1) : 0;
763  auto z = z_.Z() > cosa ? sqrt((z_.Z() - cosa) / cosa1) : 0;
764  if (z_.Y() < y_.Z()) x = -x;
765  if (x_.Z() < z_.X()) y = -y;
766  if (y_.X() < x_.Y()) z = -z;
767  return std::make_pair<Vector3<Value_>, Angle>({x, y, z}, acos(cosa));
768  }
769 
771 
780  template<typename Value_2_>
782  {
783  return {{x_ * matrix.ColumnX(), x_ * matrix.ColumnY(), x_ * matrix.ColumnZ()}, {y_ * matrix.ColumnX(), y_ * matrix.ColumnY(), y_ * matrix.ColumnZ()}, {z_ * matrix.ColumnX(), z_ * matrix.ColumnY(), z_ * matrix.ColumnZ()}};
784  }
785 
789  template<typename Value_2_>
791  {
792  return {x_ * vector, y_ * vector, z_ * vector};
793  }
794 
798  template<typename Value_2_>
799  constexpr Matrix3<ValueProduct<Value_2_>> Scale(Value_2_ scalar) const
800  {
801  return {x_ * scalar, y_ * scalar, z_ * scalar};
802  }
803 
807  template<typename Value_2_, typename = OnlyIfNotOrSameQuantity<Value_2_>>
809  {
810  return *this = matrix * (*this);
811  }
812 
816  template<typename Value_2_>
818  {
819  return matrix * (*this);
820  }
821 
822 
824 
833  constexpr bool operator<(Matrix3 const &matrix) const
834  {
835  return abs(Determinant()) < abs(matrix.Determinant());
836  }
837 
841  constexpr bool operator==(Matrix3 const &matrix) const
842  {
843  return x_ == matrix.x_ && y_ == matrix.y_ && z_ == matrix.z_;
844  }
845 
849  template <typename Value_2_, typename = OnlyIfNotOrSameQuantity<Value_2_>>
851  {
852  x_ += matrix.x_;
853  y_ += matrix.y_;
854  z_ += matrix.z_;
855  return *this;
856  }
857 
861  template <typename Value_2_, typename = OnlyIfNotOrSameQuantity<Value_2_>>
863  {
864  x_ -= matrix.x_;
865  y_ -= matrix.y_;
866  z_ -= matrix.z_;
867  return *this;
868  }
869 
873  template<typename Value_2_, typename = OnlyIfNotQuantity<Value_2_>>
874  constexpr Matrix3 &operator*=(Matrix3<Value_2_> const &matrix)
875  {
876  return *this = Multiply(matrix);
877  }
878 
882  template<typename Value_2_>
884  {
885  return Multiply(matrix);
886  }
887 
891  template<typename Value_2_>
893  {
894  return Multiply(vector);
895  }
896 
900  template<typename Value_2_, typename = OnlyIfNotOrSameQuantity<Value_2_>>
902  {
903  x_ /= scalar;
904  y_ /= scalar;
905  z_ /= scalar;
906  return *this;
907  }
908 
912  template<typename Value_2_>
913  constexpr Matrix3<ValueQuotient<Value_2_>> operator/(Value_2_ scalar) const
914  {
915  return Scale(1. / scalar);
916  }
917 
921  constexpr Vector3<Value_> const &operator()(Dim3 dim) const
922  {
923  switch (dim) {
924  case Dim3::x :
925  return x_;
926  case Dim3::y :
927  return y_;
928  case Dim3::z :
929  return z_;
930  default :
931  Default("Matrix3", to_int(dim));
932  return x_;
933  }
934  }
935 
940  {
941  switch (dim) {
942  case Dim3::x :
943  return x_;
944  case Dim3::y :
945  return y_;
946  case Dim3::z :
947  return z_;
948  default :
949  Default("Matrix3", to_int(dim));
950  return x_;
951  }
952  }
953 
957  constexpr Value_ operator()(Dim3 i, Dim3 j) const
958  {
959  return operator()(i)(j);
960  }
961 
965  Value_ &operator()(Dim3 i, Dim3 j)
966  {
967  return operator()(i)(j);
968  }
969 
973  constexpr Vector3<Value_> const& operator[](Dim3 dim_3) const
974  {
975  switch (dim_3) {
976  case Dim3::x :
977  return x_;
978  case Dim3::y :
979  return y_;
980  case Dim3::z :
981  return z_;
982  default :
983  Default("Matrix3", to_int(dim_3));
984  return x_;
985  }
986  }
987 
992  {
993  return const_cast<Vector3<Value_> &>(static_cast<Matrix3<Value_> const &>(*this)[dim_3]);
994  }
995 
999  friend auto &operator<<(std::ostream &stream, Matrix3<Value_> const &matrix)
1000  {
1001  for(auto const& vector : matrix) stream << vector;
1002  return stream;
1003  }
1004 
1006 
1012  using Dimension = Dim3;
1013 
1018  {
1019  return {this, Dim3::x};
1020  }
1021 
1026  {
1027  return {this, Dim3::last};
1028  }
1029 
1034  {
1035  return {this, Dim3::x};
1036  }
1037 
1042  {
1043  return {this, Dim3::last};
1044  }
1045 
1047 
1056  constexpr Array3<Value_> EigenValues() const
1057  {
1058  return Eigen().Values();
1059  }
1060 
1065  {
1066  return Eigen().Vectors();
1067  }
1068 
1073  {
1074  return Eigen().System();
1075  }
1076 
1078 
1079 private:
1080 
1081  class Characteristic_
1082  {
1083 
1084  public:
1085 
1086  Characteristic_(Matrix3 const &matrix)
1087  {
1088  qudratic_ = - matrix.Trace();
1089  linear_ = - (matrix.ProductTrace(matrix) - sqr(qudratic_)) / 2;
1090  constant_ = - matrix.Determinant();
1091  }
1092 
1093  constexpr Value_ Qudratic() const
1094  {
1095  return qudratic_;
1096  }
1097 
1098  constexpr ValueSquare Linear() const
1099  {
1100  return linear_;
1101  }
1102 
1103  constexpr ValueCubed Constant() const
1104  {
1105  return constant_;
1106  }
1107 
1108  private:
1109 
1110  Value_ qudratic_;
1111 
1112  ValueSquare linear_;
1113 
1114  ValueCubed constant_;
1115 
1116  };
1117 
1118  class Depressed_
1119  {
1120 
1121  public:
1122 
1123  Depressed_(Characteristic_ const &c)
1124  {
1125  auto const quadratic = c.Qudratic() / 3;
1126  linear_ = c.Linear() - sqr(quadratic) * 3;
1127  constant_ = 2. * cube(quadratic) - quadratic * c.Linear() + c.Constant();
1128  }
1129 
1130  constexpr ValueSquare Linear() const
1131  {
1132  return linear_;
1133  }
1134 
1135  constexpr ValueCubed Constant() const
1136  {
1137  return constant_;
1138  }
1139 
1140  private:
1141 
1142  ValueSquare linear_;
1143 
1144  ValueCubed constant_;
1145 
1146  };
1147 
1148  class Eigen_
1149  {
1150 
1151  public:
1152 
1153  constexpr Eigen_() {}
1154 
1155  Eigen_(Depressed_ const &d, Matrix3<Value_> const &matrix)
1156  {
1157  factor_ = 2. * sqrt(- d.Linear() / 3.);
1158  angle_ = acos(3. * d.Constant() / d.Linear() / factor_);
1159  complex_ = 4 * cube(d.Linear()) > - 27 * sqr(d.Constant());
1160  matrix_ = &matrix;
1161  }
1162 
1163  constexpr Array3<Value_> Values() const
1164  {
1165  return values_.Get([&]() {
1166  auto values = Array3<Value_> {};
1167  if (complex_) {
1168  for (auto &value : values) value = -1;
1169  std::cerr << "Eigensystem has no real Eigenvalues!\n";
1170  return values;
1171  }
1172  for (auto const index : IntegerRange(values.size())) values.at(index) = Value(index);
1173  return boost::range::sort(values, [](Value_ i, Value_ j) {
1174  return abs(i) > abs(j);
1175  });
1176  });
1177  }
1178 
1179  constexpr Array3<Vector3<Value_>> Vectors() const
1180  {
1181  return vectors_.Get([&]() {
1182  auto vectors = Array3<Vector3<Value_>> {};
1183  for (auto const index : IntegerRange(vectors.size())) vectors.at(index) = Vector(index);
1184  return vectors;
1185  });
1186  }
1187 
1188  constexpr Array3<GradedVector3<Value_>> System() const
1189  {
1190  auto system = Array3<GradedVector3<Value_>> {};
1191  for (auto const index : IntegerRange(system.size())) system.at(index) = {Vectors().at(index), Values().at(index)};
1192  return system;
1193  }
1194 
1195  private:
1196 
1197  constexpr Value_ Factor() const
1198  {
1199  return factor_;
1200  }
1201 
1202  boca::Angle Angle() const
1203  {
1204  return angle_;
1205  }
1206 
1207  constexpr Value_ Value(int index) const
1208  {
1209  return Factor() * cos((Angle() - TwoPiRad() * static_cast<double>(index)) / 3.) + matrix_->Trace() / 3;
1210  }
1211 
1212  constexpr Vector3<Value_> Vector(int index) const
1213  {
1214  auto const matrix = *matrix_ - Matrix3<Value_>(Values().at(index));
1215  return Vector3<Value_>(matrix.Cofactor(Dim3::x, Dim3::x), matrix.Cofactor(Dim3::x, Dim3::y), matrix.Cofactor(Dim3::x, Dim3::z)).Unit();
1216  }
1217 
1218  Value_ factor_;
1219 
1220  boca::Angle angle_;
1221 
1222  bool complex_;
1223 
1224  Mutable<Array3<Value_>> values_;
1225 
1226  Mutable<Array3<Vector3<Value_>>> vectors_;
1227 
1228  Matrix3<Value_> const *matrix_;
1229 
1230  };
1231 
1232  constexpr Eigen_ const &Eigen() const
1233  {
1234  return eigen_.Get([&]() {
1235  return Eigen_(Depressed_(Characteristic_(*this)), *this);
1236  });
1237  }
1238 
1239  Mutable<Eigen_> eigen_;
1240 
1241  Vector3<Value_> x_;
1242 
1243  Vector3<Value_> y_;
1244 
1245  Vector3<Value_> z_;
1246 
1250  Angle XPhi() const
1251  {
1252  auto s2 = ValueSquare(1) - z_.Z() * z_.Z();
1253  if (s2 < ValueSquare(0)) {
1254  std::cout << "Phi() |z_.Z()| > 1 " << '\n';
1255  s2 = 0;
1256  }
1257  auto const sinTheta = std::sqrt(s2);
1258  if (sinTheta != Value_(0)) {
1259  auto const cscTheta = 1 / sinTheta;
1260  auto const cosAbsPhi = z_.Y() * cscTheta;
1261  if (std::abs(cosAbsPhi) > 1) { // NaN-proofing
1262  std::cout << "Phi() finds | cos phi | > 1" << '\n';
1263  cosAbsPhi = 1;
1264  }
1265  auto const absPhi = acos(cosAbsPhi);
1266  if (z_.X() > 0) return absPhi;
1267  if (z_.X() < 0) return -absPhi;
1268  if (z_.Y() > 0) return 0_rad;
1269  return PiRad();
1270  } else { // sinTheta == Value(0) so |Fzz| = 1
1271  auto const absPhi = .5 * acos(x_.X());
1272  if (x_.Y() > 0) return -absPhi;
1273  if (x_.Y() < 0) return absPhi;
1274  if (x_.X() > 0) return 0_rad;
1275  return z_.Z() * PiRad() / 2;
1276  }
1277  }
1278 
1279 // Return the euler angles of the rotation. See SetYEulerAngles for a
1280 // note about conventions.
1281  Angle XPsi() const
1282  {
1283  // psi angle
1284  auto s2 = 1 - sqr(z_.Z());
1285  if (s2 < 0) {
1286  std::cout << "Psi() |z_.Z()| > 1 " << '\n';
1287  s2 = 0;
1288  }
1289  auto const sinTheta = std::sqrt(s2);
1290  if (sinTheta != 0) {
1291  auto const cscTheta = 1 / sinTheta;
1292  auto const cosAbsPsi = - y_.Z() * cscTheta;
1293  if (std::abs(cosAbsPsi) > 1) { // NaN-proofing
1294  std::cout << "Psi() | cos psi | > 1 " << '\n';
1295  cosAbsPsi = 1;
1296  }
1297  auto const absPsi = boca::acos(cosAbsPsi);
1298  if (x_.Z() > 0) return absPsi;
1299  if (x_.Z() < 0) return -absPsi;
1300  return (y_.Z() < 0) ? 0_rad : PiRad();
1301  } else { // sinTheta == Value(0) so |Fzz| = 1
1302  auto absPsi = x_.X();
1303  // NaN-proofing
1304  if (std::abs(x_.X()) > 1) {
1305  std::cout << "Psi() | x_.X() | > 1 " << '\n';
1306  absPsi = 1;
1307  }
1308  auto const absPsi2 = .5 * acos(absPsi);
1309  if (y_.X() > 0) return absPsi2;
1310  if (y_.X() < 0) return -absPsi2;
1311  return (x_.X() > 0) ? 0_rad : PiRad() / 2.;
1312  }
1313  }
1314 
1318  Matrix3<double> MakeBasis(Vector3<Value_> const &plane, Vector3<Value_> const &axis) const
1319  {
1320  auto const mag_z = axis.Mag();
1321  if (mag_z == Value_(0)) {
1322  if (plane.Mag() != Value_(0)) return MakeBasis(axis, plane);
1323  return {};
1324  }
1325  auto matrix = Matrix3<double> {axis / mag_z, Dim3::z};
1326 
1327  auto mag_x = plane.Mag();
1328  if (mag_x == Value_(0)) {
1329  matrix.X() = matrix.Z().Orthogonal();
1330  mag_x = 1;
1331  } else matrix.X() = plane;
1332 
1333  matrix.Y() = matrix.Z().Cross(matrix.X()) / mag_x;
1334  auto const mag_y = matrix.Y().Mag();
1335  matrix.Y() = mag_y == Value_(0) ? matrix.Z().Orthogonal() : matrix.Y() / mag_y;
1336  matrix.X() = matrix.Y().Cross(matrix.Z());
1337  return matrix;
1338  }
1339 
1340 };
1341 
1342 template <typename>
1343 struct IsMatrix3 : std::false_type { };
1344 
1345 template <typename Value>
1346 struct IsMatrix3<Matrix3<Value>> : std::true_type { };
1347 
1348 template<typename Value>
1349 using OnlyIfNotMatrix3 = typename std::enable_if < !IsMatrix3<Value>::value >::type;
1350 
1354 template < class Value_, class Value_2_, typename = OnlyIfNotMatrix3<Value_2_> >
1355 constexpr auto operator*(Matrix3<Value_> const &matrix, Value_2_ scalar)
1356 {
1357  return matrix.Scale(scalar);
1358 }
1359 
1363 template < class Value_, class Value_2_, typename = OnlyIfNotMatrix3<Value_2_> >
1364 constexpr auto operator*(Value_2_ scalar, Matrix3<Value_> const &matrix)
1365 {
1366  return matrix.Scale(scalar);
1367 }
1368 
1372 template < class Value_, class Value_2_>
1373 constexpr auto operator*(Matrix3<Value_> const &matrix, Vector3<Value_2_> const &vector)
1374 {
1375  return matrix.Multiply(vector);
1376 }
1377 
1381 template < class Value_, class Value_2_>
1383 {
1384  return {vector.X() *matrix.ColumnX(), vector.Y() *matrix.ColumnY(), vector.Z() *matrix.ColumnZ()};
1385 }
1386 
1390 template<typename Value_1_, typename Value_2_>
1392 {
1393  return {vector_1.X() *vector_2, vector_1.Y() *vector_2, vector_1.Z() *vector_2};
1394 }
1395 
1396 
1401 template<typename Value_1_>
1402 template<typename Value_2_>
1404 {
1405  Matrix3<double> matrix;
1406  matrix.Rotate(angle, axis);
1407  operator*=(matrix);
1408 }
1409 
1413 template<typename Value_1_>
1414 template<typename Value_2_>
1416 {
1417  return *this = matrix * (*this);
1418 }
1419 
1423 template<typename Value_1_>
1424 template<typename Value_2_>
1426 {
1427  return *this = matrix * (*this);
1428 }
1429 
1430 }
1431 
1432 namespace boost
1433 {
1434 
1435 template<typename Value_>
1436 struct range_const_iterator< boca::Matrix3<Value_> > {
1438 };
1439 
1440 template<typename Value_>
1441 struct range_mutable_iterator< boca::Matrix3<Value_> > {
1443 };
1444 
1445 }
auto cube(Value const &value)
cube of value
Definition: Math.hh:34
decltype(auto) IntegerRange(Integer last)
Definition: Types.hh:18
auto & Transform(Matrix3< Value_2_ > const &matrix)
Transformation with a Rotation matrix.
Definition: Matrix3.hh:1415
Vector3< Value_ > & operator()(Dim3 dim)
Components by index.
Definition: Matrix3.hh:939
Const sub-iterator.
Definition: Iterator.hh:204
Matrix3 & SetEulerAngles(Angle const &phi, Angle const &theta, Angle const &psi, Dim2 dim=Dim2::x)
Set the Euler angles.
Definition: Matrix3.hh:298
auto SubMatrix(Dim3 delete_1, Dim3 delete_2) const
Sub matrix .
Definition: Matrix3.hh:650
Enables the use of strongly typed enumerators as iterators.
Definition: EnumIterator.hh:17
typename boost::units::multiply_typeof_helper< ValueSquare< Value >, Value >::type ValueCubed
Definition: Units.hh:149
Two dimensional matrix.
Definition: Matrix2.hh:39
constexpr ConstSubIterator< boca::Matrix3, Vector3, Value_ > end() const
Const end.
Definition: Matrix3.hh:1025
Dim3
Three dimensions.
Definition: Vector3.hh:13
Boost provides free peer-reviewed portable C++ source libraries.
Definition: LorentzVectorBase.hh:726
constexpr ConstSubIterator< boca::Matrix3, Vector3, Value_ > begin() const
Const begin.
Definition: Matrix3.hh:1017
constexpr auto Cofactor(Dim3 dim_1, Dim3 dim_2) const
Cofactor .
Definition: Matrix3.hh:527
constexpr Matrix3 & RotateAxes(Vector3< Value_ > const &vector_x, Vector3< Value_ > const &vector_y, Vector3< Value_ > const &vector_z)
Rotation of local axes.
Definition: Matrix3.hh:731
Matrix3 & operator-=(Matrix3< Value_2_ > const &matrix)
Substraction.
Definition: Matrix3.hh:862
Angle Theta(Dim3 dim) const
Theta.
Definition: Matrix3.hh:564
constexpr Vector3< Value_ > Diagonal()
vector of the diagonal
Definition: Matrix3.hh:453
boost::units::quantity< boost::units::si::plane_angle > Angle
Angle measured in radian.
Definition: Si.hh:35
constexpr auto ReducedDeterminant(Dim3 dim_1, Dim3 dim_2) const
Reduced determinant .
Definition: Matrix3.hh:543
Angle acos(Value const &value_1)
Arccosine.
Definition: Units.hh:210
constexpr Vector3< ValueProduct< Value_2_ > > operator*(Vector3< Value_2_ > const &vector) const
Multiplication with a Vector.
Definition: Matrix3.hh:892
constexpr Vector3< Value_ > ColumnX() const
x-column
Definition: Matrix3.hh:429
constexpr Matrix3 & MoveTo(Dim3 dim_1, Dim3 dim_2)
Move row cyclic from dim1 to dim 2.
Definition: Matrix3.hh:671
Matrix3 & SetDiagonal(Value_ value)
Set the diagonal to uniform value.
Definition: Matrix3.hh:171
constexpr Array3< Vector3< Value_ > > EigenVectors() const
Eigen vectors.
Definition: Matrix3.hh:1064
Lazy caching of variables.
Definition: Mutable.hh:19
Matrix3 & SetDiagonal(Vector3< Value_ > vector)
Set the diagonal to given vector.
Definition: Matrix3.hh:182
Angle PiRad()
Constant in rad.
Definition: Si.cpp:16
Matrix3 & SetUniform(Value_ value)
Set the matrix to uniform value.
Definition: Matrix3.hh:225
constexpr auto Sign(Dim3 i, Dim3 j) const
Sign of a given element .
Definition: Matrix3.hh:484
constexpr Value_ const & Z() const
Getter for Z.
Definition: Vector3.hh:216
void SetRow(Vector3< Value_ > const &vector, Dim3 dim)
Set a row according to vector and direction.
Definition: Matrix3.hh:246
constexpr Vector3< Value_ > ColumnY() const
y-column
Definition: Matrix3.hh:437
Vector3 & operator*=(Value_2_ scalar)
Scaling with real numbers.
Definition: Vector3.hh:633
constexpr Matrix3 & Rotate(Angle const &phi, Dim3 dim)
Rotate by phi around axis dim.
Definition: Matrix3.hh:702
Angle Phi(Dim2 dim) const
Phi.
Definition: Matrix3.hh:572
constexpr ValueSquare Mag2() const
The magnitude squared .
Definition: Vector3.hh:385
void SetRows(Vector3< Value_ > const &x, Vector3< Value_ > const &y, Vector3< Value_ > const &z)
Set the rows according to given vectors.
Definition: Matrix3.hh:236
constexpr Matrix3< ValueProduct< Value_2_ > > & Transformed(Matrix3< Value_2_ > const &matrix)
Transform this matrix by another.
Definition: Matrix3.hh:817
void SetAntisymmetric(Vector3< Value_ > const &vector)
Fill the matrix antisymmetrically with the values of the vector.
Definition: Matrix3.hh:286
Dim3 Third(Dim3 dim_1, Dim3 dim_2)
Definition: Vector3.cpp:26
slighly more complicated estimator for significance
constexpr Vector3< Value_ > const & X() const
x-row
Definition: Matrix3.hh:371
boca::ConstSubIterator< boca::Matrix3, boca::Vector3, Value_ > type
Definition: Matrix3.hh:1437
Vector3< double > Unit() const
Unit vector parallel to this.
Definition: Vector3.hh:517
constexpr Vector3< ValueProduct< Value_2_ > > Cross(Vector3< Value_2_ > const &vector) const
Cross product between two vector.
Definition: Vector3.hh:571
Three dimensional matrix.
Definition: Matrix3.hh:21
Angle Phi(Dim3 dim) const
Phi.
Definition: Matrix3.hh:556
Matrix
Matrix types.
Definition: Matrix2.hh:18
constexpr Matrix3< ValueQuotient< Value_2_ > > operator/(Value_2_ scalar) const
Division by scalar.
Definition: Matrix3.hh:913
void SetPhi(Angle const &phi, Dim2 dim=Dim2::x)
Set phi.
Definition: Matrix3.hh:320
auto sqr(Value const &value)
square of value
Definition: Math.hh:24
SubIterator< boca::Matrix3, Vector3, Value_ > end()
End.
Definition: Matrix3.hh:1041
constexpr Matrix3 Transposed() const
transposed matrix
Definition: Matrix3.hh:619
constexpr Vector3< Value_ > LowerTriangle()
vector of lower triangle
Definition: Matrix3.hh:469
void SetColumns(Vector3< Value_ > const &x, Vector3< Value_ > const &y, Vector3< Value_ > const &z)
Set columns according to given vectors.
Definition: Matrix3.hh:266
ValueSqrt< Value > sqrt(Value const &value)
Square Root.
Definition: Units.hh:160
Matrix3 & SetAxis(Vector3< Value_ > const &axis, Dim3 dim)
Set axis.
Definition: Matrix3.hh:345
void SetTheta(Angle const &theta, Dim2 dim=Dim2::x)
Set theta.
Definition: Matrix3.hh:328
Matrix3(Vector3< Value_ > const &x, Vector3< Value_ > const &y, Vector3< Value_ > const &z, Matrix matrix=Matrix::row)
Constructor accepting three vectors.
Definition: Matrix3.hh:69
constexpr Vector3< Value_ > UpperTriangle()
vector of upper triangle
Definition: Matrix3.hh:461
constexpr Matrix2< ValueProduct< Value_1_, Value_2_ > > MatrixProduct(Vector2< Value_1_ > const &vector_1, Vector2< Value_2_ > const &vector_2)
Definition: Matrix2.hh:703
constexpr Array3< GradedVector3< Value_ > > EigenSystem() const
Eigen system.
Definition: Matrix3.hh:1072
Matrix3 & SetUpperTriangle(Vector3< Value_ > vector)
vector of upper triangle
Definition: Matrix3.hh:193
boost::units::make_system< boost::units::metric::barn_base_unit >::type System
Definition: Barn.hh:22
void Default(std::string const &variable, const Value value)
Definition: Debug.hh:165
constexpr Array3< Value_ > EigenValues() const
Eigen values.
Definition: Matrix3.hh:1056
Vector3< Value_ > & operator[](Dim3 dim_3)
Components by index.
Definition: Matrix3.hh:991
constexpr Matrix3< ValueInverse > Inverse()
Inverse matrix.
Definition: Matrix3.hh:637
typename std::enable_if< !IsMatrix3< Value >::value >::type OnlyIfNotMatrix3
Definition: Matrix3.hh:1349
constexpr Matrix Symmetry()
Definition: Matrix3.hh:414
constexpr Matrix3 & operator*=(Matrix3< Value_2_ > const &matrix)
Multiplication with a matrix.
Definition: Matrix3.hh:874
SubIterator< boca::Matrix3, Vector3, Value_ > begin()
Begin.
Definition: Matrix3.hh:1033
constexpr Matrix3 & Transpose()
transpose this matrix
Definition: Matrix3.hh:627
Vector3 & Rotate(boca::Angle const &phi, Dim3 dim_1, Dim3 dim_2)
Rotate by phi in (dim_1, dim_2) plain.
Definition: Vector3.hh:445
constexpr Vector3< Value_ > ColumnZ() const
z-column
Definition: Matrix3.hh:445
constexpr Value_ Mag() const
The magnitude .
Definition: Vector3.hh:393
Matrix3 & operator+=(Matrix3< Value_2_ > const &matrix)
Addition.
Definition: Matrix3.hh:850
Matrix3 & SetToIdentity()
Set to the diagonal to identiy.
Definition: Matrix3.hh:215
Matrix3(Vector3< Value_ > const &vector, Matrix matrix=Matrix::antisymmetric)
Constructor accepting one vector.
Definition: Matrix3.hh:100
void SetPsi(Angle const &psi, Dim2 dim=Dim2::x)
Set psi.
Definition: Matrix3.hh:336
Vector3< Value_ > & Z()
z-row
Definition: Matrix3.hh:401
Matrix3< ValueQuotient< Value_2_ > > operator/=(Value_2_ scalar)
Division by scalar.
Definition: Matrix3.hh:901
constexpr Matrix3 & RotateEulerAngles(Angle const &phi, Angle const &theta, Angle const &psi, Dim2 dim=Dim2::x)
Set the euler angles of the rotation.
Definition: Matrix3.hh:746
decltype(auto) to_int(Enumeration value)
Definition: Types.hh:29
Matrix3 & SetLowerTriangle(Vector3< Value_ > vector)
vector of lower triangle
Definition: Matrix3.hh:204
std::array< Value_, 3 > Array3
Definition: Matrix3.hh:14
Boosted Collider Analysis.
Definition: Analysis.hh:15
constexpr Vector3< Value_ > const & operator[](Dim3 dim_3) const
Components by index.
Definition: Matrix3.hh:973
Value abs(Value const &value)
Absolute value.
Definition: Units.hh:235
Matrix3(Vector3< Value_ > const &vector_1, Vector3< Value_ > const &vector_2, Matrix matrix=Matrix::symmetric)
Constructor accepting two vectors.
Definition: Matrix3.hh:86
typename boost::units::multiply_typeof_helper< Value, Value >::type ValueSquare
Definition: Units.hh:143
Three dimensionial vector.
Definition: PseudoJet.hh:20
constexpr Matrix3()
Default constructor.
Definition: Matrix3.hh:47
Angle Psi(Dim2 dim) const
Psi.
Definition: Matrix3.hh:595
Dim3 Next(Dim3 dim)
Definition: Vector3.cpp:40
Angle Theta(Dim2=Dim2::x) const
Theta.
Definition: Matrix3.hh:587
Definition: Matrix3.hh:1343
Matrix3 & SetAxis(Vector3< Value_ > const &axis, Vector3< Value_ > const &plane, Dim3 dim)
Set axis.
Definition: Matrix3.hh:354
constexpr Value_ operator()(Dim3 i, Dim3 j) const
Components by index.
Definition: Matrix3.hh:957
constexpr ValueProduct< Value_2_ > Dot(Vector3< Value_2_ > const &vector) const
Dot product between two vector.
Definition: Vector3.hh:562
void SetColumn(Vector3< Value_ > const &vector, Dim3 dim)
Set a column according to vector and its direction.
Definition: Matrix3.hh:276
Matrix3 & Rotate(Angle const &phi, Dim3 dim_1, Dim3 dim_2)
Rotate by phi in (dim_1, dim_2) plain.
Definition: Matrix3.hh:688
Iterator
Definition: Iterator.hh:144
constexpr Matrix3< ValueProduct< Value_2_ > > Multiply(Matrix3< Value_2_ > const &matrix) const
Multiplication with a matrix.
Definition: Matrix3.hh:781
std::pair< Vector3< Value_ >, Angle > AngleAxis() const
rotation defined by an angle and a vector
Definition: Matrix3.hh:756
constexpr Value_ const & X() const
Getter for X.
Definition: Vector3.hh:200
Vector3< Value_ > & X()
x-row
Definition: Matrix3.hh:376
constexpr bool operator==(Matrix3 const &matrix) const
Equality comnparison.
Definition: Matrix3.hh:841
constexpr Matrix3< ValueProduct< Value_2_ > > Scale(Value_2_ scalar) const
Scale by scalar.
Definition: Matrix3.hh:799
Vector3< Value_ > & Y()
y-row
Definition: Matrix3.hh:391
constexpr Value_ const & Y() const
Getter for Y.
Definition: Vector3.hh:208
constexpr Matrix3(Matrix3< Value_2 > const &matrix)
Copy construct with casting.
Definition: Matrix3.hh:155
std::string Name(Output output)
Definition: Base.cpp:23
constexpr auto Determinant() const
Determinant .
Definition: Matrix3.hh:509
constexpr Matrix3< ValueProduct< Value_2_ > > & Transform(Matrix3< Value_2_ > const &matrix)
Transform this matrix by another.
Definition: Matrix3.hh:808
constexpr auto ProductTrace(Matrix3< Value_2_ > const &matrix) const
Trace of the product of two matrices .
Definition: Matrix3.hh:501
constexpr Vector3< Value_ > const & operator()(Dim3 dim) const
Components by index.
Definition: Matrix3.hh:921
Two dimensional Vector.
Definition: PseudoJet.hh:23
constexpr bool operator<(Matrix3 const &matrix) const
Less than comparison according to the absolute value of the determinant.
Definition: Matrix3.hh:833
Angle TwoPiRad()
Constant in rad.
Definition: Si.cpp:21
constexpr auto Trace() const
Trace .
Definition: Matrix3.hh:492
boca::SubIterator< boca::Matrix3, boca::Vector3, Value_ > type
Definition: Matrix3.hh:1442
constexpr Vector3< Value_ > const & Y() const
y-row
Definition: Matrix3.hh:386
Matrix3 & Rotate(Angle const &phi, Vector3< Value_ > const &axis)
Rotation by phi around axis.
Definition: Matrix3.hh:719
constexpr auto Laplace(Dim3 dim_1, Dim3 dim_2) const
Laplace .
Definition: Matrix3.hh:519
Dim2
Two dimensionss.
Definition: Vector2.hh:21
Matrix3(Value_ scalar, Matrix matrix=Matrix::diagonal)
Constructor accepting a scalar.
Definition: Matrix3.hh:52
Matrix3(TQuaternion const &quaternion)
Constructor accepting a root::TQuaternion.
Definition: Matrix3.hh:138
constexpr Vector3< ValueProduct< Value_2_ > > Multiply(Vector3< Value_2_ > const &vector) const
Multiplication with a Vector.
Definition: Matrix3.hh:790
constexpr Vector3< Value_ > const & Z() const
z-row
Definition: Matrix3.hh:406
constexpr Matrix3< ValueProduct< Value_2_ > > operator*(Matrix3< Value_2_ > const &matrix) const
Multiplication with a matrix.
Definition: Matrix3.hh:883
constexpr auto Minor(Dim3 delete_1, Dim3 delete_2) const
Minor .
Definition: Matrix3.hh:535
Matrix3(Vector3< Value_ > const &vector, Dim3 dim, Matrix matrix=Matrix::row)
Constructor accepting one vector and its direction.
Definition: Matrix3.hh:117
Value_ & operator()(Dim3 i, Dim3 j)
Components by index.
Definition: Matrix3.hh:965
std::vector< Dim3 > Dimensions3()
Definition: Vector3.cpp:21