00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef OPENMS_DATASTRUCTURES_DISTANCEMATRIX_H
00036 #define OPENMS_DATASTRUCTURES_DISTANCEMATRIX_H
00037
00038 #include <OpenMS/CONCEPT/Macros.h>
00039 #include <OpenMS/CONCEPT/Types.h>
00040
00041 #include <cmath>
00042 #include <algorithm>
00043 #include <iomanip>
00044 #include <iostream>
00045
00046 namespace OpenMS
00047 {
00048
00056 template <typename Value>
00057 class DistanceMatrix
00058 {
00059 public:
00060
00062
00063 typedef Value value_type;
00065
00067
00068 typedef Size SizeType;
00069 typedef value_type ValueType;
00071
00075 DistanceMatrix() :
00076 matrix_(0), init_size_(0), dimensionsize_(0), min_element_(0, 0)
00077 {
00078 }
00079
00086 DistanceMatrix(SizeType dimensionsize, Value value = Value()) :
00087 matrix_(new ValueType *[dimensionsize]), init_size_(dimensionsize), dimensionsize_(dimensionsize), min_element_(0, 0)
00088 {
00089 matrix_[0] = NULL;
00090 SizeType i = 1;
00091 for (i = 1; i < dimensionsize; ++i)
00092 {
00093 matrix_[i] = new ValueType[i];
00094 if (matrix_[i] == NULL)
00095 {
00096 SizeType j = i;
00097 for (i = 1; i < j; i++)
00098 {
00099 delete[] matrix_[i];
00100 }
00101 delete[] matrix_;
00102 matrix_ = NULL;
00103 dimensionsize_ = 0;
00104 init_size_ = 0;
00105 throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, (UInt)((((dimensionsize - 2) * (dimensionsize - 1)) / 2) * sizeof(ValueType)));
00106 }
00107 }
00108 if (matrix_ != NULL)
00109 {
00110 for (i = 1; i < dimensionsize; ++i)
00111 {
00112 for (SizeType j = 0; j < i; ++j)
00113 {
00114 matrix_[i][j] = value;
00115 }
00116 }
00117 min_element_ = std::make_pair(1, 0);
00118 }
00119 }
00120
00126 DistanceMatrix(const DistanceMatrix & source) :
00127 matrix_(new ValueType *[source.dimensionsize_]),
00128 init_size_(source.dimensionsize_),
00129 dimensionsize_(source.dimensionsize_),
00130 min_element_(source.min_element_)
00131 {
00132 matrix_[0] = NULL;
00133 SizeType i = 1;
00134 for (i = 1; i < dimensionsize_; ++i)
00135 {
00136 matrix_[i] = new ValueType[i];
00137 if (matrix_[i] == NULL)
00138 {
00139 SizeType j = i;
00140 for (i = 1; i < j; i++)
00141 {
00142 delete[] matrix_[i];
00143 }
00144 delete[] matrix_;
00145 matrix_ = NULL;
00146 dimensionsize_ = 0;
00147 init_size_ = 0;
00148 min_element_ = std::make_pair(0, 0);
00149 throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(ValueType)));
00150 }
00151 }
00152 if (matrix_ != NULL)
00153 {
00154 for (i = 1; i < dimensionsize_; ++i)
00155 {
00156 std::copy(source.matrix_[i], source.matrix_[i] + i, matrix_[i]);
00157 }
00158 }
00159 }
00160
00162 ~DistanceMatrix()
00163 {
00164 for (SizeType i = 1; i < init_size_; i++)
00165 {
00166 delete[] matrix_[i];
00167 }
00168 delete[] matrix_;
00169 }
00170
00176 const ValueType operator()(SizeType i, SizeType j) const
00177 {
00178 return getValue(i, j);
00179 }
00180
00186 ValueType operator()(SizeType i, SizeType j)
00187 {
00188 return getValue(i, j);
00189 }
00190
00197 const ValueType getValue(SizeType i, SizeType j) const
00198 {
00199 if (i >= dimensionsize_ || j >= dimensionsize_)
00200 {
00201 throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00202 }
00203
00204 if (i == j)
00205 {
00206 return 0;
00207 }
00208 if (i < j)
00209 {
00210 std::swap(i, j);
00211 }
00212 return (const ValueType)(matrix_[i][j]);
00213 }
00214
00221 ValueType getValue(SizeType i, SizeType j)
00222 {
00223 if (i >= dimensionsize_ || j >= dimensionsize_)
00224 {
00225 throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00226 }
00227
00228 if (i == j)
00229 {
00230 return 0;
00231 }
00232 if (i < j)
00233 {
00234 std::swap(i, j);
00235 }
00236 return matrix_[i][j];
00237 }
00238
00246 void setValue(SizeType i, SizeType j, ValueType value)
00247 {
00248 if (i >= dimensionsize_ || j >= dimensionsize_)
00249 {
00250 throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00251 }
00252
00253 if (i != j)
00254 {
00255 if (i < j)
00256 {
00257 std::swap(i, j);
00258 }
00259 if (i != min_element_.first && j != min_element_.second)
00260 {
00261 matrix_[i][j] = value;
00262 if (value < matrix_[min_element_.first][min_element_.second])
00263 {
00264 min_element_ = std::make_pair(i, j);
00265 }
00266 }
00267 else
00268 {
00269 if (value <= matrix_[min_element_.first][min_element_.second])
00270 {
00271 matrix_[i][j] = value;
00272 }
00273 else
00274 {
00275 matrix_[i][j] = value;
00276 updateMinElement();
00277 }
00278 }
00279 }
00280 }
00281
00291 void setValueQuick(SizeType i, SizeType j, ValueType value)
00292 {
00293 if (i >= dimensionsize_ || j >= dimensionsize_)
00294 {
00295 throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00296 }
00297
00298 if (i != j)
00299 {
00300 if (i < j)
00301 {
00302 std::swap(i, j);
00303 }
00304 matrix_[i][j] = value;
00305 }
00306 }
00307
00309 void clear()
00310 {
00311 for (SizeType i = 1; i < init_size_; i++)
00312 {
00313 delete[] matrix_[i];
00314 }
00315 delete[] matrix_;
00316 matrix_ = NULL;
00317 min_element_ = std::make_pair(0, 0);
00318 dimensionsize_ = 0;
00319 init_size_ = 0;
00320 }
00321
00330 void resize(SizeType dimensionsize, Value value = Value())
00331 {
00332 for (SizeType j = 1; j < init_size_; j++)
00333 {
00334 delete matrix_[j];
00335 }
00336 delete[] matrix_;
00337 dimensionsize_ = dimensionsize;
00338 init_size_ = dimensionsize;
00339 min_element_ = std::make_pair(0, 0);
00340 matrix_ = new ValueType *[dimensionsize_];
00341 for (SizeType j = 1; j < dimensionsize_; ++j)
00342 {
00343 matrix_[j] = new ValueType[j];
00344 if (matrix_[j] == NULL)
00345 {
00346 for (SizeType k = 1; k < j; ++k)
00347 {
00348 delete[] matrix_[k];
00349 }
00350 delete[] matrix_;
00351 matrix_ = NULL;
00352 dimensionsize_ = 0;
00353 init_size_ = 0;
00354 throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(Value)));
00355 }
00356 }
00357 if (matrix_ != NULL)
00358 {
00359 for (SizeType j = 0; j < dimensionsize; ++j)
00360 {
00361 for (SizeType k = 0; k < j; ++k)
00362 {
00363 matrix_[j][k] = value;
00364 }
00365 }
00366 min_element_ = std::make_pair(1, 0);
00367 }
00368 }
00369
00377 void reduce(SizeType j)
00378 {
00379 if (j >= dimensionsize_)
00380 {
00381 throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00382 }
00383
00384 SizeType i = j + 1;
00385 while (i < dimensionsize_ && matrix_[i] != NULL)
00386 {
00387
00388 std::copy(matrix_[i] + j + 1, matrix_[i] + i, std::copy(matrix_[i], matrix_[i] + j, matrix_[i - 1]));
00389 ++i;
00390 }
00391
00392 delete[] matrix_[i - 1];
00393 matrix_[i - 1] = NULL;
00394 --dimensionsize_;
00395 }
00396
00398 SizeType dimensionsize() const
00399 {
00400 return dimensionsize_;
00401 }
00402
00407 void updateMinElement()
00408 {
00409 min_element_ = std::make_pair(1, 0);
00410
00411 if (dimensionsize_ < 1)
00412 {
00413 throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00414 }
00415 if (dimensionsize_ != 1)
00416 {
00417 ValueType * row_min_;
00418 for (SizeType r = 2; r < dimensionsize_ && matrix_[r] != NULL; ++r)
00419 {
00420 row_min_ = std::min_element(matrix_[r], matrix_[r] + r);
00421 if (*row_min_ < matrix_[min_element_.first][min_element_.second])
00422 {
00423 min_element_ = std::make_pair(r, row_min_ - matrix_[r]);
00424 }
00425 }
00426 }
00427 }
00428
00433 bool operator==(DistanceMatrix<ValueType> const & rhs) const
00434 {
00435 OPENMS_PRECONDITION(dimensionsize_ == rhs.dimensionsize_, "DistanceMatrices have different sizes.");
00436 for (Size i = 1; i < rhs.dimensionsize(); ++i)
00437 {
00438 for (Size j = 0; j < i; ++j)
00439 {
00440 if (matrix_[i][j] != rhs.matrix_[i][j])
00441 {
00442 return false;
00443 }
00444 }
00445 }
00446 return true;
00447 }
00448
00453 std::pair<SizeType, SizeType> getMinElementCoordinates() const
00454 {
00455 if (dimensionsize_ == 0)
00456 {
00457 throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00458 }
00459 return min_element_;
00460 }
00461
00462 protected:
00464 ValueType ** matrix_;
00466 SizeType init_size_;
00468 SizeType dimensionsize_;
00470 std::pair<SizeType, SizeType> min_element_;
00471
00472 private:
00474 DistanceMatrix & operator=(const DistanceMatrix & rhs)
00475 {
00476 matrix_ = rhs.matrix_;
00477 init_size_ = rhs.init_size_;
00478 dimensionsize_ = rhs.dimensionsize_;
00479 min_element_ = rhs.min_element_;
00480
00481 return *this;
00482 }
00483
00484 };
00485
00490 template <typename Value>
00491 std::ostream & operator<<(std::ostream & os, const DistanceMatrix<Value> & matrix)
00492 {
00493 typedef typename DistanceMatrix<Value>::SizeType SizeType;
00494
00495 std::ios_base::fmtflags flag_backup = os.setf(std::ios::scientific);
00496 std::streamsize precision_backup = os.precision();
00497
00498 os.precision(writtenDigits<DoubleReal>());
00499
00500
00501 for (SizeType i = 0; i < matrix.dimensionsize(); ++i)
00502 {
00503 for (SizeType j = 0; j < matrix.dimensionsize(); ++j)
00504 {
00505 os << matrix(i, j) << '\t';
00506 }
00507 os << std::endl;
00508 }
00509 os.flags(flag_backup);
00510 os.precision(precision_backup);
00511 return os;
00512 }
00513
00514 }
00515
00516 #endif // OPENMS_DATASTRUCTURES_DISTANCEMATRIX_H