cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
Algebra.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2020-2024 Laurent Forthomme
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <gsl/gsl_blas.h>
20#include <gsl/gsl_linalg.h>
21
22#include <string>
23
26
27namespace cepgen {
28 typedef std::unique_ptr<gsl_permutation, void (*)(gsl_permutation*)> Permutation;
29
30 Matrix::Matrix(size_t num_rows, size_t num_cols) : gsl_mat_(gsl_matrix_alloc(num_rows, num_cols), gsl_matrix_free) {}
31
32 Matrix::Matrix(const std::initializer_list<Vector>& mat)
33 : gsl_mat_(gsl_matrix_alloc(mat.size(), mat.begin()->size()), gsl_matrix_free) {
34 if (mat.size() == 0)
35 return;
36
37 size_t ix = 0;
38 for (const auto& line : mat) {
39 if (line.size() != numColumns())
40 throw CG_FATAL("Matrix") << "Invalid initialiser; all lines must have the same number of elements!";
41 for (size_t iy = 0; iy < line.size(); ++iy)
42 operator()(ix, iy) = line(iy);
43 ++ix;
44 }
45 }
46
47 Matrix::Matrix(const Matrix& oth) : gsl_mat_(gsl_matrix_alloc(oth.numRows(), oth.numColumns()), gsl_matrix_free) {
48 if (gsl_matrix_memcpy(gsl_mat_.get(), oth.gsl_mat_.get()) != 0)
49 throw CG_FATAL("Matrix") << "Failed to clone a matrix!";
50 }
51
53 gsl_mat_.reset(gsl_matrix_alloc(oth.numRows(), oth.numColumns()));
54 if (gsl_matrix_memcpy(gsl_mat_.get(), oth.gsl_mat_.get()) != 0)
55 throw CG_FATAL("Matrix") << "Failed to clone a matrix!";
56 return *this;
57 }
58
59 Matrix::operator Vector() const {
60 if (numRows() == 1)
61 return row(0);
62 if (numColumns() == 1)
63 return column(0);
64 throw CG_FATAL("Matrix:Vector") << "Only 1xN matrices can be converted to vectors.";
65 }
66
67 Matrix Matrix::zero(size_t num_rows, size_t num_cols) {
68 if (num_cols == 0ull)
69 num_cols = num_rows;
70 Matrix out(num_rows, num_cols);
71 gsl_matrix_set_zero(out.gsl_mat_.get());
72 return out;
73 }
74
75 Matrix Matrix::uniform(size_t num_rows, size_t num_cols, double value) {
76 Matrix out(num_rows, num_cols);
77 gsl_matrix_set_all(out.gsl_mat_.get(), value);
78 return out;
79 }
80
82 Matrix out(n, n);
83 gsl_matrix_set_identity(out.gsl_mat_.get());
84 return out;
85 }
86
88 auto out = Matrix::uniform(vec.size(), vec.size(), 0.);
89 for (size_t i = 0; i < vec.size(); ++i)
90 out(i, i) = vec(i);
91 return out;
92 }
93
94 size_t Matrix::numColumns() const { return gsl_mat_->size2; }
95
96 size_t Matrix::numRows() const { return gsl_mat_->size1; }
97
98 Matrix Matrix::subset(size_t min_y, size_t min_x, size_t max_y, size_t max_x) const {
99 const size_t num_x = max_x - min_y, num_y = max_y - min_y;
100 Matrix out(num_y, num_x);
101 gsl_matrix_const_submatrix(out.gsl_mat_.get(), min_y, min_x, num_y, num_x);
102 return out;
103 }
104
105 bool Matrix::operator==(const Matrix& oth) const { return gsl_matrix_equal(gsl_mat_.get(), oth.gsl_mat_.get()) == 1; }
106
108 gsl_matrix_scale(gsl_mat_.get(), val);
109 return *this;
110 }
111
113 *this = *this * vec;
114 return *this;
115 }
116
118 *this = *this * mat;
119 return *this;
120 }
121
122 Matrix& Matrix::operator/=(double val) { return operator*=(1. / val); }
123
124 Matrix Matrix::operator-() const { return Matrix::zero(numRows(), numColumns()) - *this; }
125
127 gsl_matrix_add(gsl_mat_.get(), oth.gsl_mat_.get());
128 return *this;
129 }
130
132 gsl_matrix_sub(gsl_mat_.get(), oth.gsl_mat_.get());
133 return *this;
134 }
135
136 Vector Matrix::operator%(const Vector& vec) const {
137 Matrix cpy(*this);
138 Permutation perm(gsl_permutation_alloc(vec.size()), gsl_permutation_free);
139 gsl_vector_view vec_v = gsl_matrix_column(vec.gsl_mat_.get(), 0);
140 int s;
141 gsl_linalg_LU_decomp(cpy.gsl_mat_.get(), perm.get(), &s);
142 std::vector<double> out(vec.size(), 0.);
143 gsl_vector_view res_v = gsl_vector_view_array(out.data(), out.size());
144 gsl_linalg_LU_solve(cpy.gsl_mat_.get(), perm.get(), &vec_v.vector, &res_v.vector);
145 return Vector(static_cast<VectorRef&>(res_v));
146 }
147
148 double& Matrix::operator()(size_t ix, size_t iy) {
149 if (ix >= numRows() || iy >= numColumns())
150 throw CG_ERROR("Matrix:operator()")
151 << "Invalid coordinates for " << numColumns() << "*" << numRows() << " matrix: (" << ix << ", " << iy << ").";
152 return *gsl_matrix_ptr(gsl_mat_.get(), ix, iy);
153 }
154
155 double Matrix::operator()(size_t ix, size_t iy) const {
156 if (ix >= numRows() || iy >= numColumns())
157 throw CG_ERROR("Matrix:operator()")
158 << "Invalid coordinates for " << numColumns() << "*" << numRows() << " matrix: (" << ix << ", " << iy << ").";
159 return gsl_matrix_get(gsl_mat_.get(), ix, iy);
160 }
161
163 size_t imax, jmax;
164 gsl_matrix_min_index(gsl_mat_.get(), &imax, &jmax);
165 return std::make_pair(imax, jmax);
166 }
167
169 size_t imax, jmax;
170 gsl_matrix_max_index(gsl_mat_.get(), &imax, &jmax);
171 return std::make_pair(imax, jmax);
172 }
173
174 double Matrix::min() const { return gsl_matrix_min(gsl_mat_.get()); }
175
176 double Matrix::max() const { return gsl_matrix_max(gsl_mat_.get()); }
177
178 bool Matrix::null() const { return gsl_matrix_isnull(gsl_mat_.get()) == 1; }
179
180 bool Matrix::positive() const { return gsl_matrix_ispos(gsl_mat_.get()) == 1; }
181
182 bool Matrix::negative() const { return gsl_matrix_isneg(gsl_mat_.get()) == 1; }
183
184 bool Matrix::nonNegative() const { return gsl_matrix_isnonneg(gsl_mat_.get()) == 1; }
185
187 for (size_t iy = 0; iy < numRows(); ++iy)
188 for (size_t ix = 0; ix < numColumns(); ++ix) {
189 auto& val = operator()(iy, ix);
190 if (val < min)
191 val = 0.;
192 }
193 return *this;
194 }
195
197 //gsl_matrix_transpose(gsl_mat_.get()); // only works for square matrices in GSL
198 auto transp = Matrix(numColumns(), numRows());
199 for (size_t ix = 0; ix < numRows(); ++ix)
200 for (size_t iy = 0; iy < numColumns(); ++iy)
201 transp(iy, ix) = operator()(ix, iy);
202 *this = transp;
203 return *this;
204 }
205
206 Matrix Matrix::transposed() const { return Matrix(*this).transpose(); }
207
209 if (numRows() != numColumns()) {
210 CG_WARNING("Matrix:inverted") << "Matrix inversion only works on square matrices.";
211 return *this;
212 }
213 Matrix cpy(*this);
214 Permutation perm(gsl_permutation_alloc(numRows()), gsl_permutation_free);
215 int s;
216 gsl_linalg_LU_decomp(cpy.gsl_mat_.get(), perm.get(), &s);
217 gsl_linalg_LU_invert(cpy.gsl_mat_.get(), perm.get(), gsl_mat_.get());
218 return *this;
219 }
220
221 Matrix Matrix::inverted() const { return Matrix(*this).invert(); }
222
223 Vector Matrix::column(size_t i) const { return gsl_matrix_const_column(gsl_mat_.get(), i); }
224
225 VectorRef Matrix::column(size_t i) { return static_cast<VectorRef>(gsl_matrix_column(gsl_mat_.get(), i)); }
226
227 Vector Matrix::row(size_t i) const { return gsl_matrix_const_row(gsl_mat_.get(), i); }
228
229 VectorRef Matrix::row(size_t i) { return static_cast<VectorRef>(gsl_matrix_row(gsl_mat_.get(), i)); }
230
231 Vector Matrix::diagonal() const { return gsl_matrix_const_diagonal(gsl_mat_.get()); }
232
233 VectorRef Matrix::diagonal() { return static_cast<VectorRef>(gsl_matrix_diagonal(gsl_mat_.get())); }
234
235 //--- friend operators
236
237 Matrix operator+(const Matrix& lhs, const Matrix& rhs) {
238 Matrix out(lhs);
239 out += rhs;
240 return out;
241 }
242
243 Matrix operator-(const Matrix& lhs, const Matrix& rhs) {
244 Matrix out(lhs);
245 out -= rhs;
246 return out;
247 }
248
249 Matrix operator*(double val, const Matrix& lhs) {
250 Matrix out(lhs);
251 out *= val;
252 return out;
253 }
254
255 Matrix operator*(const Matrix& lhs, double val) {
256 Matrix out(lhs);
257 out *= val;
258 return out;
259 }
260
261 Vector operator*(const Matrix& mat, const Vector& vec) {
262 gsl_vector_view vec_v = gsl_matrix_column(vec.gsl_mat_.get(), 0);
263 std::vector<double> out(mat.numRows(), 0.);
264 gsl_vector_view res_v = gsl_vector_view_array(out.data(), out.size());
265 gsl_blas_dgemv(CblasNoTrans, 1., mat.gsl_mat_.get(), &vec_v.vector, 0., &res_v.vector);
266 return Vector(static_cast<VectorRef&>(res_v));
267 }
268
269 Matrix operator*(const Matrix& mat1, const Matrix& mat2) {
270 Matrix out(mat1.numRows(), mat2.numColumns());
271 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1., mat1.gsl_mat_.get(), mat2.gsl_mat_.get(), 0., out.gsl_mat_.get());
272 return out;
273 }
274
275 Matrix operator/(const Matrix& lhs, double val) { return lhs * (1. / val); }
276
277 std::ostream& operator<<(std::ostream& os, const Matrix& mat) {
278 os << "(";
279 std::string sep;
280 for (size_t i = 0; i < mat.numRows(); ++i)
281 os << sep << mat.row(i), sep = "\n ";
282 return os << ")";
283 }
284
285 //---------------------------------------------------------------------------
286
287 VectorRef::VectorRef(const gsl_vector_view& view) : gsl_vector_view(view) {}
288
290 for (size_t i = 0; i < vec.size(); ++i)
291 operator()(i) = vec(i);
292 return *this;
293 }
294
295 VectorRef::operator Vector() const { return Vector(*this); }
296
297 bool VectorRef::operator==(const Vector& vec) const { return Vector(*this) == vec; }
298
299 double& VectorRef::operator()(size_t i) { return *gsl_vector_ptr(&vector, i); }
300
301 double VectorRef::operator()(size_t i) const { return gsl_vector_get(&vector, i); }
302
303 std::ostream& operator<<(std::ostream& os, const VectorRef& ref) { return os << "Ref" << Vector(ref); }
304
305 //---------------------------------------------------------------------------
306
307 Vector::Vector(size_t num_coord, double def) : Matrix(Matrix::uniform(num_coord, 1, def)) {}
308
309 Vector::Vector(const std::initializer_list<double>& vec) : Matrix(vec.size(), 1) {
310 size_t i = 0;
311 for (const auto& elem : vec)
312 operator()(i++) = elem;
313 }
314
315 Vector::Vector(const VectorRef& ref) : Matrix(ref.vector.size, 1) {
316 for (size_t i = 0; i < ref.vector.size; ++i)
317 Matrix::operator()(i, 0) = ref(i);
318 }
319
320 Vector::Vector(const gsl_vector_const_view& vec) : Matrix(vec.vector.size, 1) {
321 for (size_t i = 0; i < vec.vector.size; ++i)
322 Matrix::operator()(i, 0) = gsl_vector_get(&vec.vector, i);
323 }
324
325 size_t Vector::size() const { return Matrix::numRows(); }
326
327 Vector Vector::subset(size_t min, size_t max) const { return Vector(Matrix::subset(min, 0, max, 0).column(0)); }
328
329 double& Vector::operator()(size_t i) { return Matrix::operator()(i, 0); }
330
331 double Vector::operator()(size_t i) const { return Matrix::operator()(i, 0); }
332
333 double Vector::dot(const Vector& oth) const {
334 if (size() != oth.size()) {
335 CG_WARNING("Vector:scalarproduct") << "Scalar product of two vectors only defined "
336 << "for same-length vectors.";
337 return 0.;
338 }
339 double out = 0.;
340 for (size_t i = 0; i < size(); ++i)
341 out += operator()(i) * oth(i);
342 return out;
343 }
344
345 Vector Vector::cross(const Vector& oth) const {
346 if (size() != oth.size())
347 throw CG_FATAL("Vector:vectorproduct") << "Vector/cross product of two vectors only defined "
348 << "for same-length vectors.";
349 if (oth.size() != 3)
350 throw CG_FATAL("Vector:vectorproduct") << "Vector product only implemented for 3-vectors.";
351 //FIXME extend to N-dimensional vectors
352 return Vector{(operator()(1) * oth(2) - operator()(2) * oth(1)),
353 (operator()(2) * oth(0) - operator()(0) * oth(2)),
354 (operator()(0) * oth(1) - operator()(1) * oth(0))};
355 }
356
357 std::ostream& operator<<(std::ostream& os, const Vector& vec) {
358 os << "(";
359 std::string sep;
360 for (size_t i = 0; i < vec.size(); ++i)
361 os << sep << vec(i), sep = ", ";
362 return os << ")";
363 }
364} // namespace cepgen
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_ERROR(mod)
Definition Exception.h:60
#define CG_WARNING(mod)
Definition Message.h:228
A matrix object.
Definition Algebra.h:31
Matrix & operator-=(const Matrix &)
Subtraction of another matrix.
Definition Algebra.cpp:131
Matrix(size_t num_rows, size_t num_cols)
Object constructor.
Definition Algebra.cpp:30
bool nonNegative() const
Is the matrix non-negative-defined?
Definition Algebra.cpp:184
Indices imax() const
Index (row, column) of the maximum matrix element.
Definition Algebra.cpp:168
Matrix operator-() const
Unary inverse operator.
Definition Algebra.cpp:124
Vector operator%(const Vector &) const
Solving operator (from LU decomposition)
Definition Algebra.cpp:136
Matrix inverted() const
Return the inverse of this matrix (LU decomposition)
Definition Algebra.cpp:221
Indices imin() const
Index (row, column) of the minimum matrix element.
Definition Algebra.cpp:162
VectorRef column(size_t)
Return whole column of the matrix.
Definition Algebra.cpp:225
Matrix transposed() const
Return a transposition of this matrix.
Definition Algebra.cpp:206
Matrix & operator*=(double)
Multiplication by a scalar operator.
Definition Algebra.cpp:107
bool null() const
Is the matrix uniformly null?
Definition Algebra.cpp:178
std::pair< size_t, size_t > Indices
Definition Algebra.h:90
Matrix & operator+=(const Matrix &)
Addition of another matrix.
Definition Algebra.cpp:126
Matrix subset(size_t min_y, size_t min_x, size_t max_y=0ull, size_t max_x=0ull) const
Extract a subset of the matrix as a new object.
Definition Algebra.cpp:98
double min() const
Minimum matrix element.
Definition Algebra.cpp:174
static Matrix zero(size_t num_rows, size_t num_cols=0ull)
Build a zero'ed matrix.
Definition Algebra.cpp:67
Matrix & operator/=(double)
Division by a scalar operator.
Definition Algebra.cpp:122
Matrix & truncate(double min=1.e-14)
Truncate (specify minimum non-zero value) for all matrix components.
Definition Algebra.cpp:186
bool negative() const
Is the matrix negative-defined?
Definition Algebra.cpp:182
static Matrix uniform(size_t num_rows, size_t num_cols, double value=1.)
Build a uniform matrix.
Definition Algebra.cpp:75
static Matrix identity(size_t)
Build a (square) identity matrix.
Definition Algebra.cpp:81
Matrix & operator=(const Matrix &)
Assignment operator.
Definition Algebra.cpp:52
Matrix & transpose()
Transpose the matrix.
Definition Algebra.cpp:196
bool positive() const
Is the matrix positive-defined?
Definition Algebra.cpp:180
double max() const
Maximum matrix element.
Definition Algebra.cpp:176
bool operator==(const Matrix &) const
Equality operator.
Definition Algebra.cpp:105
VectorRef row(size_t)
Return whole row of the matrix.
Definition Algebra.cpp:229
Matrix & invert()
Invert the matrix.
Definition Algebra.cpp:208
size_t numColumns() const
Number of (vertical) columns.
Definition Algebra.cpp:94
double & operator()(size_t, size_t)
Component access operator.
Definition Algebra.cpp:148
size_t numRows() const
Number of (horizontal) rows.
Definition Algebra.cpp:96
VectorRef diagonal()
Return the diagonal components of the matrix.
Definition Algebra.cpp:233
bool operator==(const Vector &) const
Equality with a vector operator.
Definition Algebra.cpp:297
VectorRef & operator=(const Vector &)
Assignment operator.
Definition Algebra.cpp:289
double & operator()(size_t)
Component access operator.
Definition Algebra.cpp:299
friend class Vector
Definition Algebra.h:135
VectorRef(const gsl_vector_view &)
Definition Algebra.cpp:287
Specialisation of a matrix.
Definition Algebra.h:139
Vector subset(size_t min, size_t max=0ull) const
Extract a subset of the vector.
Definition Algebra.cpp:327
size_t size() const
Vector multiplicity (number of lines)
Definition Algebra.cpp:325
double dot(const Vector &) const
Scalar product of two vectors.
Definition Algebra.cpp:333
double & operator()(size_t)
Component access operator.
Definition Algebra.cpp:329
Vector cross(const Vector &) const
Vector product of two vectors.
Definition Algebra.cpp:345
Vector(size_t num_coord, double def=0.)
Object constructor.
Definition Algebra.cpp:307
Common namespace for this Monte Carlo generator.
Matrix operator+(const Matrix &lhs, const Matrix &rhs)
Definition Algebra.cpp:237
std::unique_ptr< gsl_permutation, void(*)(gsl_permutation *)> Permutation
Definition Algebra.cpp:28
Momentum operator*(double c, const Momentum &mom)
Definition Momentum.cpp:134
Matrix operator/(const Matrix &lhs, double val)
Definition Algebra.cpp:275
std::ostream & operator<<(std::ostream &os, const Exception::Type &type)
Definition Exception.cpp:59
Matrix operator-(const Matrix &lhs, const Matrix &rhs)
Definition Algebra.cpp:243