Matrix2.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <array>
4 
5 #include "boost/range/algorithm/sort.hpp"
6 
7 #include "boca/generic/Types.hh"
10 
11 namespace boca
12 {
13 
18 enum class Matrix
19 {
20  none,
21  diagonal,
22  symmetric,
24  row,
25  column,
26  uniform
27 };
28 
29 std::string Name(Matrix matrix);
30 
31 template<typename Value_2_>
32 using Array2 = std::array<Value_2_, 2>;
33 
38 template <typename Value_>
39 class Matrix2 : boost::totally_ordered<Matrix2<Value_>>
40  , boost::additive<Matrix2<Value_>>
41 {
42 
43  template<typename Value_2_>
44  using ValueProduct = ValueProduct<Value_, Value_2_>;
45  using ValueSquare = boca::ValueSquare<Value_>;
46  template<typename Value_2>
47  using ValueQuotient = ValueQuotient<Value_, Value_2>;
48  using ValueInverse = boost::units::divide_typeof_helper<double, Value_>;
49  template<typename Value_2>
50  using OnlyIfNotOrSameQuantity = typename std::enable_if < !IsQuantity<Value_2>::value || std::is_same<Value_, Value_2>::value >::type;
51  template<typename Value_2>
52  using OnlyIfNotQuantity = typename std::enable_if < !IsQuantity<Value_2>::value >::type;
53 
54 public:
55 
64  constexpr Matrix2() {}
65 
69  Matrix2(Value_ scalar, Matrix matrix = Matrix::diagonal)
70  {
71  switch (matrix) {
72  case Matrix::diagonal :
73  SetDiagonal(scalar);
74  break;
75  case Matrix::uniform :
76  SetUniform(scalar);
77  break;
78  default :
79  std::cout << "Maformed matrix constructor: " << Name(matrix) << '\n';
80  }
81  }
82 
86  Matrix2(Vector2<Value_> const &vector_1, Vector2<Value_> const &vector_2, Matrix matrix = Matrix::row)
87  {
88  switch (matrix) {
89  case Matrix::row:
90  SetRows(vector_1, vector_2);
91  break;
92  case Matrix::column :
93  SetColumns(vector_1, vector_2);
94  break;
95 // case Matrix::symmetric:
96 // *this = MatrixProduct(vector_1, vector_2);
97 // break;
98  default :
99  std::cout << "Maformed matrix constructor: " << Name(matrix) << '\n';
100  }
101  }
102 
106  template<typename Value_2>
107  constexpr Matrix2(Matrix2<Value_2> const &matrix) : x_(matrix.X()), y_(matrix.Y()) {}
108 
110 
120  {
121  return SetDiagonal(1);
122  }
123 
127  Matrix2 &SetDiagonal(Value_ value)
128  {
129  x_ = {value, Value_(0)};
130  y_ = {Value_(0), value};
131  return *this;
132  }
133 
137  Matrix2 &SetUniform(Value_ value)
138  {
139  x_ = {value, value};
140  y_ = {value, value};
141  return *this;
142  }
143 
148  {
149  x_ = x;
150  y_ = y;
151  }
152 
157  {
158  x_ = {x.X(), y.X()};
159  y_ = {x.Y(), y.Y()};
160  }
161 
163 
173  constexpr Vector2<Value_> const& X() const
174  {
175  return x_;
176  }
177 
179  {
180  return x_;
181  }
183 
187  constexpr Vector2<Value_> const& Y() const
188  {
189  return y_;
190  }
191 
193  {
194  return y_;
195  }
196 
198 
200 
209  Angle PhiX() const
210  {
211  return ColumnX().Phi();
212  }
213 
217  Angle PhiY() const
218  {
219  return ColumnY().Phi();
220  }
221 
223 
232  constexpr Value_ Trace()const
233  {
234  return x_.X() + y_.Y();
235  }
236 
240  constexpr ValueSquare Determinant()const
241  {
242  return x_.X() * y_.Y() - x_.Y() * y_.X();
243  }
244 
248  constexpr Value_ Minor(Dim2 delete_1, Dim2 delete_2) const
249  {
250  for (auto const &x : Dimensions2()) {
251  if (x == delete_1) continue;
252  for (auto const &y : Dimensions2()) {
253  if (y == delete_2) continue;
254  return (*this)[x][y];
255  }
256  }
257  }
258 
260 
269  constexpr Vector2<Value_> ColumnX() const
270  {
271  return {x_.X(), y_.X()};
272  }
273 
277  constexpr Vector2<Value_> ColumnY() const
278  {
279  return {x_.Y(), y_.Y()};
280  }
281 
283 
292  constexpr Matrix2 Transposed() const
293  {
294  return {ColumnX(), ColumnY()};
295  }
296 
300  constexpr Matrix2 &Transpose()
301  {
302  return *this = Transposed();
303  }
304 
309  {
310  auto const det = Determinant();
311  return det == ValueSquare(0) ? Matrix2<ValueInverse>{} : (Matrix2(Trace()) - *this) / det;
312  }
313 
317  Matrix2 &Rotate(Angle const &phi)
318  {
319  auto const cos = boost::units::cos(phi);
320  auto const sin = boost::units::sin(phi);
321  auto const vector = x_;
322  x_ = cos * vector - sin * y_;
323  y_ = sin * vector + cos * y_;
324  return *this;
325  }
326 
328 
337  template<typename Value_2_>
338  constexpr Matrix2<ValueProduct<Value_2_>> Scale(Value_2_ scalar) const
339  {
340  return {x_ * scalar, y_ * scalar};
341  }
342 
346  template<typename Value_2_>
348  {
349  return {Vector2<ValueProduct<Value_2_>>(x_ * matrix.ColumnX(), x_ * matrix.ColumnY()), Vector2<ValueProduct<Value_2_>>(y_ * matrix.ColumnX(), y_ * matrix.ColumnY())};
350  }
351 
355  template<typename Value_2_>
357  {
358  return {x_ * vector, y_ * vector};
359  }
360 
364  constexpr Matrix2<ValueSquare> Square() const
365  {
366  return sqr(*this);
367  }
368 
370 
379  constexpr bool operator<(Matrix2 const &matrix) const
380  {
381  return abs(Determinant()) < abs(matrix.Determinant());
382  }
383 
387  constexpr bool operator==(Matrix2 const &matrix) const
388  {
389  return x_ == matrix.x_ && y_ == matrix.y_;
390  }
391 
395  template <typename Value_2, typename = OnlyIfNotOrSameQuantity<Value_2>>
397  {
398  x_ += matrix.x_;
399  y_ += matrix.y_;
400  return *this;
401  }
402 
406  template <typename Value_2, typename = OnlyIfNotOrSameQuantity<Value_2>>
408  {
409  x_ -= matrix.x_;
410  y_ -= matrix.y_;
411  return *this;
412  }
413 
417  template<typename Value_2_, typename = OnlyIfNotOrSameQuantity<Value_2_>>
419  {
420  x_ /= scalar;
421  y_ /= scalar;
422  return *this;
423  }
424 
428  template<typename Value_2_>
429  constexpr Matrix2<ValueQuotient<Value_2_>> operator/(Value_2_ scalar)
430  {
431  return Scale(1. / scalar);
432  }
433 
437  template<typename Value_2_, typename = OnlyIfNotQuantity<Value_2_>>
439  {
440  return *this = Multiply(matrix);
441  }
442 
446  template<typename Value_2_>
448  {
449  return Multiply(matrix);
450  }
451 
455  template<typename Value_2_>
457  {
458  return Multiply(vector);
459  }
460 
464  constexpr Vector2<Value_> const &operator[](Dim2 dim_2) const
465  {
466  switch (dim_2) {
467  case Dim2::x : return x_;
468  case Dim2::y : return y_;
469  default :
470  Default("Matrix2", Name(dim_2));
471  return x_;
472  }
473  }
474 
479  {
480  return const_cast<Vector2<Value_> &>(static_cast<Matrix2<Value_> const &>(*this)[dim_2]);
481  }
482 
486  friend auto &operator<<(std::ostream &stream, Matrix2<Value_> const &matrix)
487  {
488  for(auto const& vector : matrix) stream << vector;
489  return stream;
490  }
491 
493 
499  using Dimension = Dim2;
500 
505  {
506  return {this, Dim2::x};
507  }
508 
513  {
514  return {this, Dim2::last};
515  }
516 
521  {
522  return {this, Dim2::x};
523  }
524 
529  {
530  return {this, Dim2::last};
531  }
532 
534 
543  constexpr Array2<Value_> EigenValues() const
544  {
545  return Eigen().Values();
546  }
547 
552  {
553  return Eigen().Vectors();
554  }
555 
560  {
561  return Eigen().System();
562  }
563 
565 
566 private:
567 
568  class Eigen_
569  {
570 
571  public:
572 
573  constexpr Eigen_() {}
574 
575  Eigen_(Matrix2<Value_> const &matrix)
576  {
577  trace_ = matrix.Trace();
578  auto const radicant = sqr(trace_) - 4 * matrix.Determinant();
579  complex_ = radicant < 0;
580  sqrt_ = sqrt(radicant);
581  matrix_ = &matrix;
582  }
583 
584  constexpr Array2<Value_> Values() const
585  {
586  return values_.Get([&]() {
587  Array2<Value_> values;
588  if (complex_) {
589  for (auto &value : values) value = -1;
590  Error("Eigensystem has no real Eigenvalues");
591  return values;
592  }
593  for (auto const index : IntegerRange(values.size())) values.at(index) = Value(index);
594  return values;
595  });
596  }
597 
598  constexpr Array2<Vector2<Value_>> Vectors() const
599  {
600  return vectors_.Get([&]() {
601  auto vectors = Array2<Vector2<Value_>> {};
602  for (auto const index : IntegerRange(vectors.size())) vectors.at(index) = Vector(index);
603  return vectors;
604  });
605  }
606 
607  constexpr Array2<GradedVector2<Value_>> System() const
608  {
609  auto system = Array2<GradedVector2<Value_>> {};
610  for (auto const index : IntegerRange(system.size())) system.at(index) = {Vectors().at(index), Values().at(index)};
611  return system;
612  }
613 
614  private:
615 
616  constexpr Value_ Sqrt() const
617  {
618  return sqrt_;
619  }
620 
621  constexpr Value_ Trace() const
622  {
623  return trace_;
624  }
625 
626  constexpr Value_ Value(int i) const
627  {
628  switch (i) {
629  case 0 : return (Trace() - Sqrt()) / 2;
630  case 1 : return (Trace() + Sqrt()) / 2;
631  default : return Value_(0);
632  }
633  }
634 
635  constexpr Vector2<Value_> Vector(int index) const
636  {
637  auto const matrix = *matrix_ - Matrix2<Value_>(Values().at(index));
638  return Vector2<Value_>(matrix.X().Y(), -matrix.X().X()).Unit();
639  }
640 
641  Value_ sqrt_;
642 
643  Value_ trace_;
644 
645  bool complex_ = false;
646 
647  Mutable<Array2<Value_>> values_;
648 
650 
651  Matrix2<Value_> const *matrix_;
652  };
653 
654  Mutable<Eigen_> eigen_;
655 
656  constexpr Eigen_ const &Eigen() const
657  {
658  return eigen_.Get([&]() {
659  return Eigen_(*this);
660  });
661  }
662 
663  Vector2<Value_> x_;
664 
665  Vector2<Value_> y_;
666 
667 };
668 
669 template <typename>
670 struct IsMatrix2 : std::false_type { };
671 
672 template <typename Value>
673 struct IsMatrix2<Matrix2<Value>> : std::true_type { };
674 
675 template<typename Value>
676 using OnlyIfNotMatrix2 = typename std::enable_if < !IsMatrix2<Value>::value >::type;
677 
678 template < class Value_, class Value_2_, typename = OnlyIfNotMatrix2<Value_2_> >
679 constexpr auto operator*(Matrix2<Value_> const &matrix, Value_2_ scalar)
680 {
681  return matrix.Scale(scalar);
682 }
683 
684 template < class Value_, class Value_2_, typename = OnlyIfNotMatrix2<Value_2_> >
685 constexpr auto operator*(Value_2_ scalar, Matrix2<Value_> const &matrix)
686 {
687  return matrix.Scale(scalar);
688 }
689 
690 template < class Value_, class Value_2_>
691 constexpr auto operator*(Matrix2<Value_> const &matrix, Vector2<Value_2_> const &vector)
692 {
693  return matrix.Multiply(vector);
694 }
695 
696 template < class Value_, class Value_2_>
698 {
699  return {vector.X() *matrix.ColumnX(), vector.Y() *matrix.ColumnY()};
700 }
701 
702 template<typename Value_1_, typename Value_2_>
704 {
705  return {vector_1.X() *vector_2, vector_1.Y() *vector_2};
706 }
707 
708 }
709 
710 namespace boost{
711 
712 template<typename Value_>
713 struct range_const_iterator< boca::Matrix2<Value_> > {
715 };
716 
717 template<typename Value_>
718 struct range_mutable_iterator< boca::Matrix2<Value_> > {
720 };
721 
722 }
constexpr Matrix2 & Transpose()
transpose this matrix
Definition: Matrix2.hh:300
boca::ConstSubIterator< boca::Matrix2, boca::Vector2, Value_ > type
Definition: Matrix2.hh:714
Angle PhiY() const
Phi y.
Definition: Matrix2.hh:217
constexpr Matrix2< ValueQuotient< Value_2_ > > operator/(Value_2_ scalar)
Division by scalar.
Definition: Matrix2.hh:429
decltype(auto) IntegerRange(Integer last)
Definition: Types.hh:18
Const sub-iterator.
Definition: Iterator.hh:204
constexpr ValueSquare Determinant() const
Determinant.
Definition: Matrix2.hh:240
constexpr Vector2< Value_ > const & X() const
x
Definition: Matrix2.hh:173
std::vector< Dim2 > Dimensions2()
Definition: Vector2.cpp:15
Two dimensional matrix.
Definition: Matrix2.hh:39
Boost provides free peer-reviewed portable C++ source libraries.
Definition: LorentzVectorBase.hh:726
constexpr bool operator<(Matrix2 const &matrix) const
Less than comparison according to absolute value of the determinant.
Definition: Matrix2.hh:379
Matrix2< ValueQuotient< Value_2_ > > operator/=(Value_2_ scalar)
Division by scalar.
Definition: Matrix2.hh:418
boost::units::quantity< boost::units::si::plane_angle > Angle
Angle measured in radian.
Definition: Si.hh:35
void SetRows(Vector2< Value_ > const &x, Vector2< Value_ > const &y)
Set rows.
Definition: Matrix2.hh:147
typename std::enable_if< !IsMatrix2< Value >::value >::type OnlyIfNotMatrix2
Definition: Matrix2.hh:676
constexpr Matrix2< ValueSquare > Square() const
Square.
Definition: Matrix2.hh:364
Matrix2 & operator*=(Matrix2< Value_2_ > const &matrix)
Multiplication with a matrix.
Definition: Matrix2.hh:438
Lazy caching of variables.
Definition: Mutable.hh:19
constexpr Value_ Trace() const
Trace.
Definition: Matrix2.hh:232
constexpr ConstSubIterator< boca::Matrix2, Vector2, Value_ > begin() const
const begin
Definition: Matrix2.hh:504
constexpr Vector2< ValueProduct< Value_2_ > > Multiply(Vector2< Value_2_ > const &vector) const
multiply with a vector
Definition: Matrix2.hh:356
SubIterator< boca::Matrix2, Vector2, Value_ > end()
end
Definition: Matrix2.hh:528
constexpr Value_ Minor(Dim2 delete_1, Dim2 delete_2) const
Minor.
Definition: Matrix2.hh:248
Matrix2 & Rotate(Angle const &phi)
Rotation.
Definition: Matrix2.hh:317
constexpr auto operator*(LorentzVectorBase< Value > const &lorentz_vector_1, LorentzVectorBase< Value_2 > const &lorentz_vector_2)
Scalar product of lorentzvectors.
Definition: LorentzVectorBase.hh:701
constexpr Vector2< ValueProduct< Value_2_ > > operator*(Vector2< Value_2_ > const &vector) const
Multiplication with a Vector.
Definition: Matrix2.hh:456
constexpr Matrix2< ValueInverse > Inverse()
inverse of this matrix
Definition: Matrix2.hh:308
Matrix2(Vector2< Value_ > const &vector_1, Vector2< Value_ > const &vector_2, Matrix matrix=Matrix::row)
Constructor accepting two vectors.
Definition: Matrix2.hh:86
Matrix
Matrix types.
Definition: Matrix2.hh:18
std::array< Value_2_, 2 > Array2
Definition: Matrix2.hh:32
constexpr Array2< GradedVector2< Value_ > > EigenSystem() const
Eigen system.
Definition: Matrix2.hh:559
constexpr Vector2< Value_ > const & Y() const
y
Definition: Matrix2.hh:187
auto sqr(Value const &value)
square of value
Definition: Math.hh:24
Matrix2 & SetUniform(Value_ value)
Set uniform.
Definition: Matrix2.hh:137
constexpr Array2< Vector2< Value_ > > EigenVectors() const
Eigen vectors.
Definition: Matrix2.hh:551
Angle PhiX() const
Phi x.
Definition: Matrix2.hh:209
ValueSqrt< Value > sqrt(Value const &value)
Square Root.
Definition: Units.hh:160
constexpr Matrix2< ValueProduct< Value_1_, Value_2_ > > MatrixProduct(Vector2< Value_1_ > const &vector_1, Vector2< Value_2_ > const &vector_2)
Definition: Matrix2.hh:703
boost::units::make_system< boost::units::metric::barn_base_unit >::type System
Definition: Barn.hh:22
constexpr Array2< Value_ > EigenValues() const
Eigen values.
Definition: Matrix2.hh:543
void Default(std::string const &variable, const Value value)
Definition: Debug.hh:165
Vector2< Value_ > & Y()
Definition: Matrix2.hh:192
boca::SubIterator< boca::Matrix2, boca::Vector2, Value_ > type
Definition: Matrix2.hh:719
constexpr bool operator==(Matrix2 const &matrix) const
Equality comparison.
Definition: Matrix2.hh:387
void SetColumns(Vector2< Value_ > const &x, Vector2< Value_ > const &y)
Set columns.
Definition: Matrix2.hh:156
Boosted Collider Analysis.
Definition: Analysis.hh:15
constexpr Matrix2(Matrix2< Value_2 > const &matrix)
Constructor with type conversion.
Definition: Matrix2.hh:107
Value abs(Value const &value)
Absolute value.
Definition: Units.hh:235
typename boost::units::multiply_typeof_helper< Value, Value >::type ValueSquare
Definition: Units.hh:143
constexpr Vector2< Value_ > const & operator[](Dim2 dim_2) const
rows
Definition: Matrix2.hh:464
constexpr Value_ const & X() const
Getter for X.
Definition: Vector2.hh:150
Vector2< Value_ > & operator[](Dim2 dim_2)
rows
Definition: Matrix2.hh:478
void Error(std::string const &variable)
Definition: Debug.cpp:69
constexpr Matrix2()
Default constructor.
Definition: Matrix2.hh:64
constexpr Value_ const & Y() const
Getter for Y.
Definition: Vector2.hh:158
Iterator
Definition: Iterator.hh:144
Matrix2 & operator+=(Matrix2< Value_2 > const &matrix)
Addition.
Definition: Matrix2.hh:396
constexpr Vector2< Value_ > ColumnX() const
x column
Definition: Matrix2.hh:269
Definition: Matrix2.hh:670
constexpr Matrix2< ValueProduct< Value_2_ > > Scale(Value_2_ scalar) const
scale with a scalar
Definition: Matrix2.hh:338
Matrix2 & operator-=(Matrix2< Value_2 > const &matrix)
Substraction.
Definition: Matrix2.hh:407
SubIterator< boca::Matrix2, Vector2, Value_ > begin()
begin
Definition: Matrix2.hh:520
constexpr Matrix2< ValueProduct< Value_2_ > > Multiply(Matrix2< Value_2_ > const &matrix) const
multiply with a matrix
Definition: Matrix2.hh:347
Matrix2(Value_ scalar, Matrix matrix=Matrix::diagonal)
Diagonal Matrix.
Definition: Matrix2.hh:69
Member_ const & Get(std::function< Member_()> const &function) const
Definition: Mutable.hh:23
constexpr Matrix2 Transposed() const
transposed
Definition: Matrix2.hh:292
std::string Name(Output output)
Definition: Base.cpp:23
constexpr Matrix2< ValueProduct< Value_2_ > > operator*(Matrix2< Value_2_ > const &matrix) const
Multiplication with a matrix.
Definition: Matrix2.hh:447
Matrix2 & SetDiagonal(Value_ value)
Set diagonal.
Definition: Matrix2.hh:127
Vector2< Value_ > & X()
x
Definition: Matrix2.hh:178
Two dimensional Vector.
Definition: PseudoJet.hh:23
Dim2
Two dimensionss.
Definition: Vector2.hh:21
constexpr Vector2< Value_ > ColumnY() const
y column
Definition: Matrix2.hh:277
constexpr ConstSubIterator< boca::Matrix2, Vector2, Value_ > end() const
const end
Definition: Matrix2.hh:512
Matrix2 & SetToIdentity()
Set equal to the identity rotation.
Definition: Matrix2.hh:119