SHORE API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
mathops.hpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright 2008,2009,2010,2011,2012 Stephan Ossowski, Korbinian Schneeberger,
4  * Felix Ott, Joerg Hagmann, Alf Scotland, Sebastian Bender
5  *
6  * This file is part of SHORE.
7  *
8  * SHORE is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * SHORE is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with SHORE. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
25 
26 #ifndef SHORE_MISC_MATHOPS_HPP__
27 #define SHORE_MISC_MATHOPS_HPP__
28 
29 #include <deque>
30 #include <iterator>
31 #include <numeric>
32 #include <string>
33 
34 #include <boost/random.hpp>
35 
36 namespace shore
37 {
38 
40 template<class U,class T>
41 U round(T floatval)
42 {
43  return static_cast<U>(floatval+T(0.5));
44 }
45 
47 double log2(const double val);
48 
50 template<class Iter>
51 double mean(const Iter begin,const Iter end)
52 {
53  if(begin==end) return 0.0;
54  const double sum=std::accumulate(begin,end,0.0);
55  const double size=end-begin;
56  return sum/size;
57 }
58 
61 {
62  private:
63 
64  size_t m_size;
65  double m_mean;
66  double m_rec;
67 
68  public:
69 
71 
73  void append(const double d);
74 
76  size_t size() const;
78  double mean() const;
80  double var() const;
82  double sd() const;
83 };
84 
87 template<class Iter>
88 double pairs_mean(Iter begin,const Iter end)
89 {
90  if(begin==end) return 0.0;
91  double sum=0.0;
92  size_t nelem=0;
93 
94  while(begin!=end)
95  {
96  sum+=(static_cast<double>(begin->first)*static_cast<double>(begin->second));
97  nelem+=static_cast<size_t>(begin->second);
98  ++begin;
99  }
100 
101  return sum/static_cast<double>(nelem);
102 }
103 
106 template<class Iter>
107 double medianize(const Iter begin,const Iter end)
108 {
109  double ret=0.0;
110 
111  if(begin==end)
112  return ret;
113 
114  const size_t size=end-begin;
115 
116  const Iter median_i=begin+(size>>1);
117 
118  std::nth_element(begin,median_i,end);
119 
120  if((size&1)>0)
121  {
122  ret=(*median_i);
123  }
124  else
125  {
126  const Iter median_i_lower=median_i-1;
127 
128  std::iter_swap(median_i_lower,std::max_element(begin,median_i));
129 
130  const double med_low= *median_i_lower;
131  const double med_high= *median_i;
132  ret=0.5*(med_low+med_high);
133  }
134 
135  return ret;
136 }
137 
139 template<class Iter>
140 double geometric_mean(const Iter begin,const Iter end,const bool skipZ=false)
141 {
142  double logsmean=0.0;
143  size_t s=0;
144 
145  for(Iter i=begin;i!=end;++i)
146  {
147  if((*i)==0.0)
148  {
149  if(skipZ) continue;
150  return 0.0;
151  }
152 
153  logsmean+=log2(*i);
154  ++s;
155  }
156 
157  if(s==0) return 0.0;
158 
159  logsmean/=double(s);
160 
161  return std::pow(2.0,logsmean);
162 }
163 
165 template<class Iter>
166 double harmonic_mean(const Iter begin,const Iter end)
167 {
168  const double amean1=mean(begin,end);
169  const double gmean1=geometric_mean(begin,end);
170  const double gmean2=gmean1*gmean1;
171 
172  return gmean2/amean1;
173 }
174 
180 template<class Iter,class Oter>
181 void skewness_kurtosis(Iter begin,Iter end,Oter dest,const bool var_n)
182 {
183  // use precision of the destination value type
184  const double m=mean(begin,end);
185 
186  double var=0.0;
187  double var3=0.0;
188  double var4=0.0;
189 
190  const size_t size=end-begin;
191 
192  while(begin!=end)
193  {
194  const double diff=(*begin)-m;
195  const double diff2=diff*diff;
196  var+=diff2;
197  var3+=diff*diff2;
198  var4+=diff2*diff2;
199  ++begin;
200  }
201 
202  var/=static_cast<double>(var_n?(size):(size-1));
203 
204  (*dest++)=var3/(var*sqrt(var)*static_cast<double>(size));
205  (*dest)=var4/(var*var*static_cast<double>(size))-3.0;
206 }
207 
210 template<class Iter>
211 double var(const Iter begin,const Iter end,
212  const double mu,const bool var_n=false)
213 {
214  double var=0.0;
215 
216  Iter s=begin;
217 
218  while(s!=end)
219  {
220  const double diff=(*s)-mu;
221  const double diff2=diff*diff;
222  var+=diff2;
223  ++s;
224  }
225 
226  const size_t size=end-begin;
227 
228  if(var_n)
229  {
230  var/=static_cast<double>(size);
231  }
232  else
233  {
234  var=(size>1)?(var/static_cast<double>(size-1)):0.0;
235  }
236 
237  return var;
238 }
239 
242 template<class Iter>
243 double pairs_var(const Iter begin,const Iter end,
244  const double mu,const bool var_n=false)
245 {
246  double var=0.0;
247  size_t size=0;
248 
249  Iter s=begin;
250 
251  while(s!=end)
252  {
253  const double diff=s->first-mu;
254  const double diff2=diff*diff;
255  var+=(diff2*static_cast<double>(s->second));
256  size+=static_cast<size_t>(s->second);
257  ++s;
258  }
259 
260  if(var_n)
261  {
262  var/=static_cast<double>(size);
263  }
264  else
265  {
266  var=(size>1)?(var/(static_cast<double>(size-1))):0.0;
267  }
268 
269  return var;
270 }
271 
273 template<class Iter>
274 double var(const Iter begin,const Iter end,const bool var_n=false)
275 {
276  const double mu=mean(begin,end);
277  return var(begin,end,mu,var_n);
278 }
279 
281 template<class Iter>
282 double stddev(const Iter begin,const Iter end,const bool var_n=false)
283 {
284  return std::sqrt(var(begin,end,var_n));
285 }
286 
289 template<class Iter>
290 double stddev(const Iter begin,const Iter end,
291  const double mu,const bool var_n=false)
292 {
293  return std::sqrt(var(begin,end,mu,var_n));
294 }
295 
298 template<class Iter>
299 double pairs_stddev(const Iter begin,const Iter end,
300  const double mu,const bool var_n=false)
301 {
302  return std::sqrt(pairs_var(begin,end,mu,var_n));
303 }
304 
306 template<class Xter,class Yter>
307 std::pair<double,double> polycog(
308  Xter x_beg,Xter x_end,
309  Yter y_beg,double*const ret_area2)
310 {
311  std::pair<double,double> ret(0.0,0.0);
312  double area2=0.0;
313  Xter xi=x_beg;
314  Yter yi=y_beg;
315 
316  while(xi!=x_end)
317  {
318  const double x=double(*xi);
319  const double y=double(*yi);
320 
321  ++xi;
322  ++yi;
323 
324  double xnext;
325  double ynext;
326  if(xi==x_end)
327  {
328  xnext=double(*x_beg);
329  ynext=double(*y_beg);
330  }
331  else
332  {
333  xnext=double(*xi);
334  ynext=double(*yi);
335  }
336  const double xynext=x*ynext;
337  const double xnexty=xnext*y;
338 
339  area2+=(xynext-xnexty);
340  ret.first+=((x+xnext)*(xynext-xnexty));
341  ret.second+=((y+ynext)*(xynext-xnexty));
342  }
343 
344  if(area2!=0.0)
345  {
346  const double sc=(1.0/(area2+area2+area2));
347  ret.first*=sc;
348  ret.second*=sc;
349  }
350  else
351  {
352  // to-do: correct this? (currently assumes it's a straight line)
353  ret.first=0.5*((*(--xi))+(*x_beg));
354  ret.second=0.5*((*(--yi))+(*y_beg));
355  }
356 
357  if(ret_area2!=0) (*ret_area2)=area2;
358 
359  return ret;
360 }
361 
363 template<class Xter,class Yter>
364 std::pair<double,double> polycog(
365  Xter x_beg,Xter x_end,Yter y_beg)
366 {
367  return polycog(x_beg,x_end,y_beg,0);
368 }
369 
374 template<class Iter>
375 void mean_filter(Iter beg,Iter end,const size_t width)
376 {
377  if(width==1) return; // nothing to do
378 
379  if((width&1)==0)
380  throw std::runtime_error("mean filter width must be odd");
381 
382  Iter w_beg=beg;
383  Iter w_cen=beg;
384  Iter w_end=beg;
385 
386  std::deque<double> w_mod;
387 
388  double w_div=width;
389 
390  double w_total=0.0;
391  for(size_t i=0;i<width;++i)
392  {
393  if(w_end==end)
394  {
395  w_div=i;
396  break;
397  }
398  w_total+=(*w_end);
399  ++w_end;
400  }
401 
402  // set first half of the first window
403  double w_mean=w_total/w_div;
404  for(size_t i=0;i<=(width>>1);++i)
405  {
406  if(w_cen==end)
407  {
408  break;
409  }
410  w_mod.push_back(*w_cen);
411  (*w_cen)=w_mean;
412  ++w_cen;
413  }
414 
415  while(w_end!=end)
416  {
417  w_total+=(double(*w_end)-w_mod.front());
418 
419  w_mod.pop_front();
420  w_mod.push_back(*w_cen);
421 
422  w_mean=w_total/w_div;
423  (*w_cen)=w_mean;
424 
425  ++w_beg;
426  ++w_cen;
427  ++w_end;
428  }
429 
430  while(w_cen!=w_end)
431  {
432  (*w_cen)=w_mean;
433  ++w_cen;
434  }
435 }
436 
438 template<class T,class Iter>
439 void seq(T lb,const T ub,const size_t len,Iter dest)
440 {
441  if(len<2)
442  {
443  if(len==1) (*dest)=lb;
444  return;
445  }
446 
447  const T step=(ub-lb)/(len-1);
448 
449  for(size_t i=0;i<len;++i)
450  {
451  (*dest++)=lb;
452  lb+=step;
453  }
454 }
455 
457 template<class IIter,class OIter,class Rng>
458 void random_copy(IIter b,IIter e,OIter o,Rng& rng)
459 {
460  if(e<=b) return;
461 
462  const size_t size=e-b;
463 
464  std::vector<size_t> vi(size);
465  seq(size_t(0),size-1,size,vi.begin());
466 
467  while(!vi.empty())
468  {
469  boost::uniform_int<size_t> range(0,vi.size()-1);
470 
471  boost::variate_generator<Rng&,boost::uniform_int<size_t> >
472  die(rng,range);
473 
474  const size_t id=die();
475 
476  (*o)=(*(b+vi[id]));
477  vi[id]=vi.back();
478  vi.pop_back();
479  ++o;
480  }
481 }
482 
484 template<typename T>
486 {
487  T m_value;
488 
490  :m_value(T())
491  {}
492 
493  T operator()()
494  {
495  return m_value++;
496  }
497 };
498 
500 template<typename IndexIter>
501 void index_fill(IndexIter ib,IndexIter ie)
502 {
503  typedef typename std::iterator_traits<IndexIter>::value_type value_type;
504 
506 
507  std::generate(ib,ie,gen);
508 }
509 
511 template<typename DataIter,typename Comparator=void>
513 {
514  const DataIter m_data;
515  Comparator m_cmp;
516 
517  index_comparator(const DataIter data,Comparator cmp)
518  :m_data(data),m_cmp(cmp)
519  {}
520 
521  bool operator()(const size_t i,const size_t j)
522  {
523  return m_cmp(m_data[i],m_data[j]);
524  }
525 };
526 
528 template<typename DataIter>
529 struct index_comparator<DataIter,void>
530 {
531  const DataIter m_data;
532 
533  index_comparator(const DataIter data)
534  :m_data(data)
535  {}
536 
537  bool operator()(const size_t i,const size_t j) const
538  {
539  return m_data[i]<m_data[j];
540  }
541 };
542 
544 template<typename DataIter,typename IndexIter>
545 void index_sort(IndexIter ib,IndexIter ie,DataIter db)
546 {
547  const index_comparator<DataIter> cmp(db);
548 
549  std::sort(ib,ie,cmp);
550 }
551 
553 template<typename DataIter,typename IndexIter,typename Comparator>
554 void index_sort(IndexIter ib,IndexIter ie,DataIter db,Comparator data_cmp)
555 {
556  const index_comparator<DataIter,Comparator> cmp(db,data_cmp);
557 
558  std::sort(ib,ie,cmp);
559 }
560 
563 template<typename DataIter,typename OrderingIter,typename RankIter>
564 void ranks(RankIter first,RankIter last,OrderingIter ob,DataIter db)
565 {
566  const size_t size=last-first;
567  if(size>1)
568  {
569  first[ob[size-1]]=size-1;
570  for(size_t i=size-2;i>0;--i)
571  {
572  if(db[ob[i]]<db[ob[i+1]]) first[ob[i]]=i;
573  else first[ob[i]]=first[ob[i+1]];
574  }
575  if(db[ob[0]]<db[ob[1]]) first[ob[0]]=0;
576  else first[ob[0]]=first[ob[1]];
577  }
578 }
579 
582 template<class Abs_t>
583 struct relabs
584 {
585  Abs_t abs;
586  double rel;
587 
588  relabs():abs(0),rel(0.0) {}
589 
590  double calc(const Abs_t& refval) const
591  {
592  if(rel!=0.0) return rel*double(refval);
593  return abs;
594  }
595 
596  Abs_t round(const Abs_t& refval) const
597  {
598  return long(calc(refval)+0.5);
599  }
600 
601  Abs_t floor(const Abs_t& refval) const
602  {
603  return std::floor(calc(refval));
604  }
605 
606  Abs_t ceil(const Abs_t& refval) const
607  {
608  return std::ceil(calc(refval));
609  }
610 
611  bool is_absolute() const
612  {
613  return rel==0.0;
614  }
615 
616  static relabs<Abs_t> mkabs(const Abs_t v)
617  {
618  relabs<Abs_t> ret;
619  ret.abs=v;
620  return ret;
621  }
622 
623  static relabs<Abs_t> mkrel(const double v)
624  {
625  relabs<Abs_t> ret;
626  ret.rel=v;
627  return ret;
628  }
629 };
630 
633 template<class Abs_t>
634 std::istream& operator>>(std::istream& is,relabs<Abs_t>& dest)
635 {
636  dest=relabs<Abs_t>();
637 
638  double d;
639  is>>d;
640 
641  if((!is.eof())&&(is.peek()=='%'))
642  {
643  is.ignore(1);
644  dest.rel=0.01*d;
645  }
646  else dest.abs=d;
647 
648  return is;
649 }
650 
653 template<class Abs_t>
654 std::ostream& operator<<(std::ostream& os,const relabs<Abs_t>& val)
655 {
656  if(val.rel!=0.0) os<<(100.0*val.rel)<<'%';
657  else os<<val.abs;
658  return os;
659 }
660 
661 } // namespace shore
662 
663 #endif // SHORE_MISC_MATHOPS_HPP__
664