Go to the documentation of this file.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_MATH_MISC_LINEARINTERPOLATION_H
00036 #define OPENMS_MATH_MISC_LINEARINTERPOLATION_H
00037
00038 #include <OpenMS/CONCEPT/Types.h>
00039
00040 #include <cmath>
00041 #include <vector>
00042
00043 namespace OpenMS
00044 {
00045
00046 namespace Math
00047 {
00048
00074 template <typename Key = DoubleReal, typename Value = Key>
00075 class LinearInterpolation
00076 {
00077
00078 public:
00079
00081
00082 typedef Value value_type;
00083
00084 typedef Key key_type;
00085 typedef std::vector<value_type> container_type;
00086
00087 typedef value_type ValueType;
00088 typedef key_type KeyType;
00089 typedef container_type ContainerType;
00091
00092 public:
00093
00101 LinearInterpolation(KeyType scale = 1., KeyType offset = 0.) :
00102 scale_(scale),
00103 offset_(offset),
00104 inside_(),
00105 outside_(),
00106 data_()
00107 {}
00108
00110 LinearInterpolation(LinearInterpolation const & arg) :
00111 scale_(arg.scale_),
00112 offset_(arg.offset_),
00113 inside_(arg.inside_),
00114 outside_(arg.outside_),
00115 data_(arg.data_)
00116 {}
00117
00119 LinearInterpolation & operator=(LinearInterpolation const & arg)
00120 {
00121 if (&arg == this)
00122 return *this;
00123
00124 scale_ = arg.scale_;
00125 offset_ = arg.offset_;
00126 inside_ = arg.inside_;
00127 outside_ = arg.outside_;
00128 data_ = arg.data_;
00129
00130 return *this;
00131 }
00132
00134 ~LinearInterpolation() {}
00135
00136
00137
00139
00140
00142 ValueType value(KeyType arg_pos) const
00143 {
00144
00145 typedef typename container_type::difference_type DiffType;
00146
00147
00148 KeyType left_key;
00149 KeyType pos = key2index(arg_pos);
00150 KeyType frac = std::modf(pos, &left_key);
00151 DiffType const left = DiffType(left_key);
00152
00153
00154 if (pos < 0)
00155 {
00156 if (left )
00157 {
00158 return 0;
00159 }
00160 else
00161 {
00162 return data_[0] * (1 + frac);
00163 }
00164 }
00165 else
00166 {
00167
00168 DiffType const back = data_.size() - 1;
00169 if (left >= back)
00170 {
00171 if (left != back)
00172 {
00173 return 0;
00174 }
00175 else
00176 {
00177 return data_[left] * (1 - frac);
00178 }
00179 }
00180 else
00181 {
00182
00183 return data_[left + 1] * frac + data_[left] * (1 - frac);
00184 }
00185 }
00186 }
00187
00191 void addValue(KeyType arg_pos, ValueType arg_value)
00192 {
00193
00194 typedef typename container_type::difference_type DiffType;
00195
00196
00197 KeyType left_key;
00198 KeyType const pos = key2index(arg_pos);
00199 KeyType const frac = std::modf(pos, &left_key);
00200 DiffType const left = DiffType(left_key);
00201
00202
00203 if (pos < 0)
00204 {
00205 if (left )
00206 {
00207 return;
00208 }
00209 else
00210 {
00211 data_[0] += (1 + frac) * arg_value;
00212 return;
00213 }
00214 }
00215 else
00216 {
00217
00218 DiffType const back = data_.size() - 1;
00219 if (left >= back)
00220 {
00221 if (left != back)
00222 {
00223 return;
00224 }
00225 else
00226 {
00227 data_[left] += (1 - frac) * arg_value;
00228 return;
00229 }
00230 }
00231 else
00232 {
00233
00234 data_[left + 1] += frac * arg_value;
00235 data_[left] += (1 - frac) * arg_value;
00236 return;
00237 }
00238 }
00239 }
00240
00245 ValueType derivative(KeyType arg_pos) const
00246 {
00247
00248
00249 KeyType const pos = key2index(arg_pos);
00250
00251 SignedSize const size_ = data_.size();
00252 SignedSize const left = int(pos + 0.5);
00253
00254 if (left < 0)
00255 {
00256 return 0;
00257 }
00258 else
00259 {
00260 if (left == 0)
00261 {
00262 if (pos >= -0.5)
00263 {
00264 return (data_[1] - data_[0]) * (pos + 0.5) + (data_[0]) * (0.5 - pos);
00265 }
00266 else
00267 {
00268 return (data_[0]) * (pos + 1.5);
00269 }
00270 }
00271 }
00272
00273
00274
00275 KeyType factor = KeyType(left) - pos + KeyType(0.5);
00276
00277 if (left > size_)
00278 {
00279 return 0;
00280 }
00281 else
00282 {
00283 if (left < size_ - 1)
00284 {
00285
00286 return (data_[left] - data_[left - 1]) * factor + (data_[left + 1] - data_[left]) * (1. - factor);
00287 }
00288 else
00289 {
00290
00291 if (left == size_ - 1)
00292 {
00293 return (data_[left] - data_[left - 1]) * factor + (-data_[left]) * (1. - factor);
00294 }
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303 return (-data_[left - 1]) * factor;
00304 }
00305
00307
00308
00309
00311
00312
00314 ContainerType & getData()
00315 {
00316 return data_;
00317 }
00318
00320 ContainerType const & getData() const
00321 {
00322 return data_;
00323 }
00324
00330 template <typename SourceContainer>
00331 void setData(SourceContainer const & data)
00332 {
00333 data_ = data;
00334 }
00335
00337 bool empty() const
00338 {
00339 return data_.empty();
00340 }
00341
00343
00344
00345
00347
00348
00350 KeyType key2index(KeyType pos) const
00351 {
00352 if (scale_)
00353 {
00354 pos -= offset_;
00355 pos /= scale_;
00356 return pos;
00357 }
00358 else
00359 {
00360 return 0;
00361 }
00362 }
00363
00365 KeyType index2key(KeyType pos) const
00366 {
00367 pos *= scale_;
00368 pos += offset_;
00369 return pos;
00370 }
00371
00373 KeyType const & getScale() const
00374 {
00375 return scale_;
00376 }
00377
00383 void setScale(KeyType const & scale)
00384 {
00385 scale_ = scale;
00386 }
00387
00389 KeyType const & getOffset() const
00390 {
00391 return offset_;
00392 }
00393
00400 void setOffset(KeyType const & offset)
00401 {
00402 offset_ = offset;
00403 }
00404
00418 void setMapping(KeyType const & scale, KeyType const & inside, KeyType const & outside)
00419 {
00420 scale_ = scale;
00421 inside_ = inside;
00422 outside_ = outside;
00423 offset_ = outside - scale * inside;
00424 }
00425
00432 void setMapping(KeyType const & inside_low, KeyType const & outside_low,
00433 KeyType const & inside_high, KeyType const & outside_high)
00434 {
00435 if (inside_high != inside_low)
00436 {
00437 setMapping((outside_high - outside_low) / (inside_high - inside_low),
00438 inside_low, outside_low);
00439 }
00440 else
00441 {
00442 setMapping(0, inside_low, outside_low);
00443 }
00444 return;
00445 }
00446
00448 KeyType const & getInsideReferencePoint() const
00449 {
00450 return inside_;
00451 }
00452
00454 KeyType const & getOutsideReferencePoint() const
00455 {
00456 return outside_;
00457 }
00458
00460 KeyType supportMin() const
00461 {
00462 return index2key(KeyType(empty() ? 0 : -1));
00463 }
00464
00466 KeyType supportMax() const
00467 {
00468 return index2key(KeyType(data_.size()));
00469 }
00470
00472
00473 protected:
00474
00475 KeyType scale_;
00476 KeyType offset_;
00477 KeyType inside_;
00478 KeyType outside_;
00479
00480 ContainerType data_;
00481
00482 };
00483
00484 }
00485
00486 }
00487
00488 #endif // OPENMS_MATH_MISC_LINEARINTERPOLATION_H