OpenMS
Loading...
Searching...
No Matches
DistanceMatrix.h
Go to the documentation of this file.
1// Copyright (c) 2002-present, OpenMS Inc. -- EKU Tuebingen, ETH Zurich, and FU Berlin
2// SPDX-License-Identifier: BSD-3-Clause
3//
4// --------------------------------------------------------------------------
5// $Maintainer: Mathias Walzer $
6// $Authors: $
7// --------------------------------------------------------------------------
8
9#pragma once
10
15#include <OpenMS/config.h>
16#include <algorithm>
17#include <cmath>
18#include <iomanip>
19#include <iostream>
20
21namespace OpenMS
22{
23
40template<typename Value>
42{
43public:
45
46 typedef Value value_type;
48
50
51 typedef Size SizeType;
54
59 {
60 }
61
69 DistanceMatrix(SizeType dimensionsize, Value value = Value()):
73 min_element_(0, 0)
74 {
75 matrix_[0] = NULL;
76 SizeType i = 1;
77 for (i = 1; i < dimensionsize; ++i)
78 {
79 matrix_[i] = new ValueType[i];
80 if (matrix_[i] == NULL)
81 {
82 SizeType j = i;
83 for (i = 1; i < j; i++)
84 {
85 delete[] matrix_[i];
86 }
87 delete[] matrix_;
88 matrix_ = NULL;
90 init_size_ = 0;
91 throw Exception::OutOfMemory(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
92 (UInt)((((dimensionsize - 2) * (dimensionsize - 1)) / 2) * sizeof(ValueType)));
93 }
94 }
95 if (matrix_ != NULL)
96 {
97 for (i = 1; i < dimensionsize; ++i)
98 {
99 for (SizeType j = 0; j < i; ++j)
100 {
101 matrix_[i][j] = value;
102 }
103 }
104 min_element_ = std::make_pair(1, 0);
105 }
106 }
107
115 matrix_(new ValueType*[source.dimensionsize_]),
119 {
120 matrix_[0] = NULL;
121 SizeType i = 1;
122 for (i = 1; i < dimensionsize_; ++i)
123 {
124 matrix_[i] = new ValueType[i];
125 if (matrix_[i] == NULL)
126 {
127 SizeType j = i;
128 for (i = 1; i < j; i++)
129 {
130 delete[] matrix_[i];
131 }
132 delete[] matrix_;
133 matrix_ = NULL;
134 dimensionsize_ = 0;
135 init_size_ = 0;
136 min_element_ = std::make_pair(0, 0);
137 throw Exception::OutOfMemory(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
138 (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(ValueType)));
139 }
140 }
141 if (matrix_ != NULL)
142 {
143 for (i = 1; i < dimensionsize_; ++i)
144 {
145 std::copy(source.matrix_[i], source.matrix_[i] + i, matrix_[i]);
146 }
147 }
148 }
149
152 {
153 for (SizeType i = 1; i < init_size_; i++)
154 {
155 delete[] matrix_[i];
156 }
157 delete[] matrix_;
158 }
159
167 {
168 return getValue(i, j);
169 }
170
178 {
179 return getValue(i, j);
180 }
181
190 {
191 if (i >= dimensionsize_ || j >= dimensionsize_) { throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION); }
192 // elements on main diagonal are not stored and assumed to be 0
193 if (i == j) { return 0; }
194 if (i < j) { std::swap(i, j); }
195 return (const ValueType)(matrix_[i][j]);
196 }
197
206 {
207 if (i >= dimensionsize_ || j >= dimensionsize_) { throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION); }
208 // elements on main diagonal are not stored and assumed to be 0
209 if (i == j) { return 0; }
210 if (i < j) { std::swap(i, j); }
211 return matrix_[i][j];
212 }
213
223 {
224 if (i >= dimensionsize_ || j >= dimensionsize_) { throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION); }
225 // elements on main diagonal are not stored and assumed to be 0
226 if (i != j)
227 {
228 if (i < j) { std::swap(i, j); }
229 // Fast path whenever (i,j) is NOT the current minimum cell: writing into any
230 // other cell can only introduce a new (smaller) minimum, never invalidate the
231 // existing one. Using '||' (i.e. "not the min cell") instead of '&&' is required:
232 // with '&&' a cell that shares exactly one index with the min coordinate fell into
233 // the else-branch, which never refreshes min_element_ when the new value is smaller,
234 // leaving a stale cached minimum (issue #9488, DATA-24).
235 if (i != min_element_.first || j != min_element_.second)
236 {
237 matrix_[i][j] = value;
238 if (value < matrix_[min_element_.first][min_element_.second]) // keep min_element_ up-to-date
239 {
240 min_element_ = std::make_pair(i, j);
241 }
242 }
243 else
244 {
245 if (value <= matrix_[min_element_.first][min_element_.second]) { matrix_[i][j] = value; }
246 else
247 {
248 matrix_[i][j] = value;
250 }
251 }
252 }
253 }
254
266 {
267 if (i >= dimensionsize_ || j >= dimensionsize_) { throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION); }
268 // elements on main diagonal are not stored and assumed to be 0
269 if (i != j)
270 {
271 if (i < j) { std::swap(i, j); }
272 matrix_[i][j] = value;
273 }
274 }
275
277 void clear()
278 {
279 for (SizeType i = 1; i < init_size_; i++)
280 {
281 delete[] matrix_[i];
282 }
283 delete[] matrix_;
284 matrix_ = nullptr;
285 min_element_ = std::make_pair(0, 0);
286 dimensionsize_ = 0;
287 init_size_ = 0;
288 }
289
299 void resize(SizeType dimensionsize, Value value = Value())
300 {
301 for (SizeType j = 1; j < init_size_; j++)
302 {
303 delete[] matrix_[j];
304 }
305 delete[] matrix_;
308 min_element_ = std::make_pair(0, 0);
310 for (SizeType j = 1; j < dimensionsize_; ++j)
311 {
312 matrix_[j] = new ValueType[j];
313 if (matrix_[j] == nullptr)
314 {
315 for (SizeType k = 1; k < j; ++k)
316 {
317 delete[] matrix_[k];
318 }
319 delete[] matrix_;
320 matrix_ = nullptr;
321 dimensionsize_ = 0;
322 init_size_ = 0;
323 throw Exception::OutOfMemory(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
324 (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(Value)));
325 }
326 }
327 if (matrix_ != nullptr)
328 {
329 for (SizeType j = 0; j < dimensionsize; ++j)
330 {
331 for (SizeType k = 0; k < j; ++k)
332 {
333 matrix_[j][k] = value;
334 }
335 }
336 min_element_ = std::make_pair(1, 0);
337 }
338 }
339
349 {
350 if (j >= dimensionsize_) { throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION); }
351 // delete row j and therefor overwrite with row j+1 and iterate like this to last row
352 SizeType i = j + 1;
353 while (i < dimensionsize_ && matrix_[i] != nullptr)
354 {
355 // left out in the copy is each rows jth element, pointer working here as iterators just fine
356 std::copy(matrix_[i] + j + 1, matrix_[i] + i, std::copy(matrix_[i], matrix_[i] + j, matrix_[i - 1]));
357 ++i;
358 }
359 // last row is freed and the pointer set to NULL (outer array's size is not changed)
360 delete[] matrix_[i - 1];
361 matrix_[i - 1] = nullptr;
363 }
364
367 {
368 return dimensionsize_;
369 }
370
377 {
378 min_element_ = std::make_pair(1, 0);
379 // error if dimensionsize_<1, return if dimensionsize_ == 1, else
380 if (dimensionsize_ < 1) { throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION); }
381 if (dimensionsize_ != 1) // else matrix has one element: (1,0)
382 {
383 ValueType* row_min_;
384 for (SizeType r = 2; r < dimensionsize_ && matrix_[r] != nullptr; ++r)
385 {
386 row_min_ = std::min_element(matrix_[r], matrix_[r] + r);
387 if (*row_min_ < matrix_[min_element_.first][min_element_.second]) { min_element_ = std::make_pair(r, row_min_ - matrix_[r]); }
388 }
389 }
390 }
391
398 {
399 if (dimensionsize_ != rhs.dimensionsize_) { return false; }
400 for (Size i = 1; i < rhs.dimensionsize(); ++i)
401 {
402 for (Size j = 0; j < i; ++j)
403 {
404 if (matrix_[i][j] != rhs.matrix_[i][j]) { return false; }
405 }
406 }
407 return true;
408 }
409
415 std::pair<SizeType, SizeType> getMinElementCoordinates() const
416 {
417 if (dimensionsize_ == 0) { throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION); }
418 return min_element_;
419 }
420
421protected:
425 SizeType init_size_; // actual size of outer array
427 SizeType dimensionsize_; // number of virtual elements: ((dimensionsize-1)*(dimensionsize))/2
429 std::pair<SizeType, SizeType> min_element_;
430
431private:
434 {
435 matrix_ = rhs.matrix_;
439
440 return *this;
441 }
442
443}; // class DistanceMatrix
444
450template<typename Value>
451std::ostream& operator<<(std::ostream& os, const DistanceMatrix<Value>& matrix)
452{
454
455 // we need to print a square matrix. So we set the width
456 //std::ios_base::fmtflags flag_backup = os.setf(std::ios::scientific); // 'scientific' messes with the width; don't do it
457 std::streamsize precision_backup = os.precision(6); // we could go with `writtenDigits<Value>(Value())`, but it becomes unreadable...
458 auto width_backup = os.width(8);
459
460 for (SizeType i = 0; i < matrix.dimensionsize(); ++i)
461 {
462 for (SizeType j = 0; j < matrix.dimensionsize(); ++j)
463 {
464 if (i == j)
465 { // color the diagonal in red (conditional, see Colorizer)
466 os << red(matrix(i, j)) << '\t';
467 }
468 else
469 {
470 os << matrix(i, j) << '\t';
471 }
472 }
473 os << '\n';
474 }
475 //os.flags(flag_backup);
476 os.precision(precision_backup);
477 os.width(width_backup);
478 return os;
479}
480
481} // namespace OpenMS
A two-dimensional distance matrix, similar to OpenMS::Matrix.
Definition DistanceMatrix.h:42
SizeType dimensionsize() const
gives the number of rows (i.e. number of columns)
Definition DistanceMatrix.h:366
Value value_type
Definition DistanceMatrix.h:46
std::ostream & operator<<(std::ostream &os, const DistanceMatrix< Value > &matrix)
Print the contents to a stream (and colors the diagonal, if the stream is cout/cerr)
Definition DistanceMatrix.h:451
DistanceMatrix()
default constructor
Definition DistanceMatrix.h:58
bool operator==(DistanceMatrix< ValueType > const &rhs) const
Equality comparator.
Definition DistanceMatrix.h:397
void setValue(SizeType i, SizeType j, ValueType value)
sets a value at a given position:
Definition DistanceMatrix.h:222
void updateMinElement()
keep track of the actual minimum element after altering the matrix
Definition DistanceMatrix.h:376
const ValueType getValue(SizeType i, SizeType j) const
gets a value at a given position:
Definition DistanceMatrix.h:189
ValueType getValue(SizeType i, SizeType j)
gets a value at a given position:
Definition DistanceMatrix.h:205
const ValueType operator()(SizeType i, SizeType j) const
gets a value at a given position (read only):
Definition DistanceMatrix.h:166
DistanceMatrix(const DistanceMatrix &source)
copy constructor
Definition DistanceMatrix.h:114
Size SizeType
Definition DistanceMatrix.h:51
std::pair< SizeType, SizeType > min_element_
index of minimal element(i.e. number in underlying SparseVector)
Definition DistanceMatrix.h:429
ValueType operator()(SizeType i, SizeType j)
gets a value at a given position (read only):
Definition DistanceMatrix.h:177
ValueType ** matrix_
sparse element not to be included in base container
Definition DistanceMatrix.h:423
void setValueQuick(SizeType i, SizeType j, ValueType value)
sets a value at a given position:
Definition DistanceMatrix.h:265
value_type ValueType
Definition DistanceMatrix.h:52
~DistanceMatrix()
destructor
Definition DistanceMatrix.h:151
SizeType init_size_
number of actually stored rows
Definition DistanceMatrix.h:425
DistanceMatrix(SizeType dimensionsize, Value value=Value())
detailed constructor
Definition DistanceMatrix.h:69
DistanceMatrix & operator=(const DistanceMatrix &rhs)
assignment operator (unsafe)
Definition DistanceMatrix.h:433
void clear()
reset all
Definition DistanceMatrix.h:277
SizeType dimensionsize_
number of accessibly stored rows (i.e. number of columns)
Definition DistanceMatrix.h:427
std::pair< SizeType, SizeType > getMinElementCoordinates() const
Indexpair of minimal element.
Definition DistanceMatrix.h:415
void resize(SizeType dimensionsize, Value value=Value())
resizing the container
Definition DistanceMatrix.h:299
void reduce(SizeType j)
reduces DistanceMatrix by one dimension. first the jth row, then jth column
Definition DistanceMatrix.h:348
Out of memory exception.
Definition Exception.h:429
Out of range exception.
Definition Exception.h:291
unsigned int UInt
Unsigned integer type.
Definition Types.h:64
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition Types.h:97
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19
Colorizer red