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 #ifndef OPENMS_MATH_MISC_LINEARINTERPOLATION_H
00028 #define OPENMS_MATH_MISC_LINEARINTERPOLATION_H
00029
00030 #include <cmath>
00031 #include <vector>
00032
00033 namespace OpenMS
00034 {
00035
00036 namespace Math
00037 {
00038
00064 template < typename Key = double, typename Value = Key >
00065 class LinearInterpolation
00066 {
00067
00068 public:
00069
00071
00072 typedef Value value_type;
00073
00074 typedef Key key_type;
00075 typedef std::vector < value_type > container_type;
00076
00077 typedef value_type ValueType;
00078 typedef key_type KeyType;
00079 typedef container_type ContainerType;
00081
00082 public:
00083
00091 LinearInterpolation ( KeyType scale = 1., KeyType offset = 0. )
00092 : scale_ ( scale ),
00093 offset_ ( offset ),
00094 inside_ (),
00095 outside_(),
00096 data_ ()
00097 {}
00098
00100 LinearInterpolation ( LinearInterpolation const & arg )
00101 : scale_ ( arg.scale_ ),
00102 offset_ ( arg.offset_ ),
00103 inside_ ( arg.inside_ ),
00104 outside_ (arg.outside_ ),
00105 data_ ( arg.data_ )
00106 {}
00107
00109 LinearInterpolation & operator= ( LinearInterpolation const & arg )
00110 {
00111 if (&arg == this)
00112 return *this;
00113
00114 scale_ = arg.scale_;
00115 offset_ = arg.offset_;
00116 inside_ = arg.inside_;
00117 outside_ = arg.outside_;
00118 data_ = arg.data_;
00119
00120 return *this;
00121 }
00122
00124 ~LinearInterpolation () {}
00125
00126
00127
00129
00130
00132 ValueType value ( KeyType arg_pos ) const throw()
00133 {
00134
00135 typedef typename container_type::difference_type DiffType;
00136
00137
00138 KeyType left_key;
00139 KeyType pos = key2index(arg_pos);
00140 KeyType frac = std::modf(pos, &left_key);
00141 DiffType const left = DiffType(left_key);
00142
00143
00144 if ( pos < 0 )
00145 {
00146 if ( left )
00147 {
00148 return 0;
00149 }
00150 else
00151 {
00152 return data_[ 0 ] * ( 1 + frac );
00153 }
00154 }
00155 else
00156 {
00157
00158 DiffType const back = data_.size() - 1;
00159 if ( left >= back )
00160 {
00161 if ( left != back )
00162 {
00163 return 0;
00164 }
00165 else
00166 {
00167 return data_[ left ] * ( 1 - frac );
00168 }
00169 }
00170 else
00171 {
00172
00173 return data_[ left + 1 ] * frac + data_[ left ] * ( 1 - frac );
00174 }
00175 }
00176 }
00177
00178
00182 void addValue ( KeyType arg_pos, ValueType arg_value ) throw()
00183 {
00184
00185 typedef typename container_type::difference_type DiffType;
00186
00187
00188 KeyType left_key;
00189 KeyType const pos = key2index(arg_pos);
00190 KeyType const frac = std::modf(pos, &left_key);
00191 DiffType const left = DiffType(left_key);
00192
00193
00194 if ( pos < 0 )
00195 {
00196 if ( left )
00197 {
00198 return;
00199 }
00200 else
00201 {
00202 data_[ 0 ] += ( 1 + frac ) * arg_value;
00203 return;
00204 }
00205 }
00206 else
00207 {
00208
00209 DiffType const back = data_.size() - 1;
00210 if ( left >= back )
00211 {
00212 if ( left != back )
00213 {
00214 return;
00215 }
00216 else
00217 {
00218 data_[ left ] += ( 1 - frac ) * arg_value;
00219 return;
00220 }
00221 }
00222 else
00223 {
00224
00225 data_[ left + 1 ] += frac * arg_value;
00226 data_[ left ] += ( 1 - frac ) * arg_value;
00227 return;
00228 }
00229 }
00230 }
00231
00236 ValueType derivative ( KeyType arg_pos ) const throw()
00237 {
00238
00239
00240 KeyType const pos = key2index(arg_pos);
00241
00242 int const size_ = data_.size();
00243 int const left = int(pos+0.5);
00244
00245 if ( left < 0 )
00246 return 0;
00247 else
00248 if ( left == 0 )
00249 if ( pos >= -0.5 )
00250 return
00251 ( data_[1] - data_[0] ) * ( pos + 0.5 ) +
00252 ( data_[0] ) * ( 0.5 - pos );
00253 else
00254 return
00255 ( data_[0] ) * ( pos + 1.5 );
00256
00257
00258
00259
00260 KeyType factor = KeyType(left) - pos + 0.5;
00261
00262 if ( left > size_ )
00263 return 0;
00264 else
00265 if ( left < size_ - 1 )
00266 return
00267 ( data_[left] - data_[left-1] ) * factor +
00268 ( data_[left+1] - data_[left] ) * ( 1. - factor );
00269 else
00270 if ( left == size_ - 1 )
00271 return
00272 ( data_[left] - data_[left-1] ) * factor +
00273 ( - data_[left] ) * ( 1. - factor );
00274
00275
00276
00277
00278
00279 return
00280 ( - data_[left-1] ) * factor;
00281
00282 }
00283
00285
00286
00287
00289
00290
00292 ContainerType & getData () throw()
00293 {
00294 return data_;
00295 }
00296
00298 ContainerType const & getData () const throw()
00299 {
00300 return data_;
00301 }
00302
00308 template < typename SourceContainer >
00309 void setData ( SourceContainer const & data ) throw()
00310 {
00311 data_ = data;
00312 }
00313
00314
00316 bool empty () const throw()
00317 {
00318 return data_.empty();
00319 }
00320
00322
00323
00324
00326
00327
00329 KeyType key2index ( KeyType pos ) const throw()
00330 {
00331 if ( scale_ )
00332 {
00333 pos -= offset_;
00334 pos /= scale_;
00335 return pos;
00336 }
00337 else
00338 {
00339 return 0;
00340 }
00341 }
00342
00344 KeyType index2key ( KeyType pos ) const throw()
00345 {
00346 pos *= scale_;
00347 pos += offset_;
00348 return pos;
00349 }
00350
00352 KeyType const & getScale () const throw()
00353 {
00354 return scale_;
00355 }
00356
00362 void setScale ( KeyType const & scale ) throw()
00363 {
00364 scale_ = scale;
00365 }
00366
00368 KeyType const & getOffset () const throw()
00369 {
00370 return offset_;
00371 }
00372
00379 void setOffset ( KeyType const & offset ) throw()
00380 {
00381 offset_ = offset;
00382 }
00383
00397 void setMapping ( KeyType const & scale, KeyType const & inside, KeyType const & outside )
00398 {
00399 scale_ = scale;
00400 inside_ = inside;
00401 outside_ = outside;
00402 offset_ = outside - scale * inside;
00403 }
00404
00411 void setMapping ( KeyType const & inside_low, KeyType const & outside_low,
00412 KeyType const & inside_high, KeyType const & outside_high )
00413 {
00414 if ( inside_high != inside_low )
00415 {
00416 setMapping ( ( outside_high - outside_low ) / ( inside_high - inside_low ),
00417 inside_low, outside_low );
00418 }
00419 else
00420 {
00421 setMapping ( 0, inside_low, outside_low );
00422 }
00423 return;
00424 }
00425
00427 KeyType const & getInsideReferencePoint () const throw()
00428 {
00429 return inside_;
00430 }
00431
00433 KeyType const & getOutsideReferencePoint () const throw()
00434 {
00435 return outside_;
00436 }
00437
00439 KeyType supportMin() const throw()
00440 {
00441 return index2key ( empty() ? 0 : -1 );
00442 }
00443
00445 KeyType supportMax() const throw()
00446 {
00447 return index2key ( data_.size() );
00448 }
00449
00451
00452 protected:
00453
00454 KeyType scale_;
00455 KeyType offset_;
00456 KeyType inside_;
00457 KeyType outside_;
00458
00459 ContainerType data_;
00460
00461 };
00462
00463 }
00464
00465 }
00466
00467 #endif // OPENMS_MATH_MISC_LINEARINTERPOLATION_H