bpp-core  2.1.0
 All Classes Namespaces Files Functions Variables Typedefs Friends
VectorTools.h
Go to the documentation of this file.
1 //
2 // File: VectorTools.h
3 // Created by: Julien Dutheil
4 // Created on: Fri Mar 14 14:16:32 2003
5 //
6 
7 /*
8  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
9 
10  This software is a computer program whose purpose is to provide classes
11  for numerical calculus.
12 
13  This software is governed by the CeCILL license under French law and
14  abiding by the rules of distribution of free software. You can use,
15  modify and/ or redistribute the software under the terms of the CeCILL
16  license as circulated by CEA, CNRS and INRIA at the following URL
17  "http://www.cecill.info".
18 
19  As a counterpart to the access to the source code and rights to copy,
20  modify and redistribute granted by the license, users are provided only
21  with a limited warranty and the software's author, the holder of the
22  economic rights, and the successive licensors have only limited
23  liability.
24 
25  In this respect, the user's attention is drawn to the risks associated
26  with loading, using, modifying and/or developing or reproducing the
27  software by the user in light of its specific status of free software,
28  that may mean that it is complicated to manipulate, and that also
29  therefore means that it is reserved for developers and experienced
30  professionals having in-depth computer knowledge. Users are therefore
31  encouraged to load and test the software's suitability as regards their
32  requirements in conditions enabling the security of their systems and/or
33  data to be ensured and, more generally, to use and operate it in the
34  same conditions as regards security.
35 
36  The fact that you are presently reading this means that you have had
37  knowledge of the CeCILL license and that you accept its terms.
38  */
39 
40 #ifndef _VECTORTOOLS_H_
41 #define _VECTORTOOLS_H_
42 
43 #include "VectorExceptions.h"
44 #include "NumTools.h"
46 #include "Matrix/Matrix.h"
47 #include "../Io/OutputStream.h"
48 #include "../App/ApplicationTools.h"
49 
50 // From the STL:
51 #include <vector>
52 #include <map>
53 #include <cmath>
54 #include <algorithm>
55 #include <complex>
56 
57 namespace bpp
58 {
59 typedef std::vector<std::complex<double> > Vcomplex;
60 typedef std::vector<Vcomplex> VVcomplex;
61 typedef std::vector<VVcomplex> VVVcomplex;
62 
63 typedef std::vector<std::complex<long double> > Vlcomplex;
64 typedef std::vector<Vlcomplex> VVlcomplex;
65 typedef std::vector<VVlcomplex> VVVlcomplex;
66 
67 typedef std::vector<double> Vdouble;
68 typedef std::vector<Vdouble> VVdouble;
69 typedef std::vector<VVdouble> VVVdouble;
70 typedef std::vector<VVVdouble> VVVVdouble;
71 
72 typedef std::vector<long double> Vldouble;
73 typedef std::vector<Vldouble> VVldouble;
74 typedef std::vector<VVldouble> VVVldouble;
75 typedef std::vector<VVVldouble> VVVVldouble;
76 
77 typedef std::vector<int> Vint;
78 typedef std::vector<Vint> VVint;
79 typedef std::vector<VVint> VVVint;
80 typedef std::vector<VVVint> VVVVint;
81 
87 template<class T>
88 std::vector<T> operator+(const std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
89 {
90  size_t size;
91  if (v1.size() != v2.size())
92  {
93  throw DimensionException("VectorTools::operator+", v1.size(), v2.size());
94  }
95  else
96  {
97  size = v1.size();
98  }
99  std::vector<T> result(size);
100  for (size_t i = 0; i < size; i++)
101  {
102  result[i] = v1[i] + v2[i];
103  }
104  return result;
105 }
106 
107 template<class T>
108 std::vector<T> operator-(const std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
109 {
110  size_t size;
111  if (v1.size() != v2.size())
112  {
113  throw DimensionException("VectorTools::operator-", v1.size(), v2.size());
114  }
115  else
116  {
117  size = v1.size();
118  }
119  std::vector<T> result(size);
120  for (size_t i = 0; i < size; i++)
121  {
122  result[i] = v1[i] - v2[i];
123  }
124  return result;
125 }
126 
127 template<class T>
128 std::vector<T> operator*(const std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
129 {
130  size_t size;
131  if (v1.size() != v2.size())
132  {
133  throw DimensionException("VectorTools::operator*", v1.size(), v2.size());
134  }
135  else
136  {
137  size = v1.size();
138  }
139  std::vector<T> result(size);
140  for (size_t i = 0; i < size; i++)
141  {
142  result[i] = v1[i] * v2[i];
143  }
144  return result;
145 }
146 
147 template<class T>
148 std::vector<T> operator/(const std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
149 {
150  size_t size;
151  if (v1.size() != v2.size())
152  {
153  throw DimensionException("VectorTools::operator/", v1.size(), v2.size());
154  }
155  else
156  {
157  size = v1.size();
158  }
159  std::vector<T> result(size);
160  for (size_t i = 0; i < size; i++)
161  {
162  result[i] = v1[i] / v2[i];
163  }
164  return result;
165 }
166 
167 
168 template<class T, class C>
169 std::vector<T> operator+(const std::vector<T>& v1, const C& c)
170 {
171  std::vector<T> result(v1.size());
172  for (size_t i = 0; i < result.size(); i++)
173  {
174  result[i] = v1[i] + c;
175  }
176  return result;
177 }
178 template<class T, class C>
179 std::vector<T> operator+(const C& c, const std::vector<T>& v1)
180 {
181  std::vector<T> result(v1.size());
182  for (size_t i = 0; i < result.size(); i++)
183  {
184  result[i] = c + v1[i];
185  }
186  return result;
187 }
188 
189 template<class T, class C>
190 std::vector<T> operator-(const std::vector<T>& v1, const C& c)
191 {
192  std::vector<T> result(v1.size());
193  for (size_t i = 0; i < result.size(); i++)
194  {
195  result[i] = v1[i] - c;
196  }
197  return result;
198 }
199 template<class T, class C>
200 std::vector<T> operator-(const C& c, const std::vector<T>& v1)
201 {
202  std::vector<T> result(v1.size());
203  for (size_t i = 0; i < result.size(); i++)
204  {
205  result[i] = c - v1[i];
206  }
207  return result;
208 }
209 
210 template<class T, class C>
211 std::vector<T> operator*(const std::vector<T>& v1, const C& c)
212 {
213  std::vector<T> result(v1.size());
214  for (size_t i = 0; i < result.size(); i++)
215  {
216  result[i] = v1[i] * c;
217  }
218  return result;
219 }
220 template<class T, class C>
221 std::vector<T> operator*(const C& c, const std::vector<T>& v1)
222 {
223  std::vector<T> result(v1.size());
224  for (size_t i = 0; i < result.size(); i++)
225  {
226  result[i] = c * v1[i];
227  }
228  return result;
229 }
230 
231 template<class T, class C>
232 std::vector<T> operator/(const std::vector<T>& v1, const C& c)
233 {
234  std::vector<T> result(v1.size());
235  for (size_t i = 0; i < result.size(); i++)
236  {
237  result[i] = v1[i] / c;
238  }
239  return result;
240 }
241 template<class T, class C>
242 std::vector<T> operator/(const C& c, const std::vector<T>& v1)
243 {
244  std::vector<T> result(v1.size());
245  for (size_t i = 0; i < result.size(); i++)
246  {
247  result[i] = c / v1[i];
248  }
249  return result;
250 }
251 
252 
253 template<class T>
254 void operator+=(std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
255 {
256  for (size_t i = 0; i < v1.size(); i++)
257  {
258  v1[i] += v2[i];
259  }
260 }
261 
262 template<class T>
263 void operator-=(std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
264 {
265  for (size_t i = 0; i < v1.size(); i++)
266  {
267  v1[i] -= v2[i];
268  }
269 }
270 
271 template<class T>
272 void operator*=(std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
273 {
274  for (size_t i = 0; i < v1.size(); i++)
275  {
276  v1[i] *= v2[i];
277  }
278 }
279 
280 template<class T>
281 void operator/=(std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
282 {
283  for (size_t i = 0; i < v1.size(); i++)
284  {
285  v1[i] /= v2[i];
286  }
287 }
288 
289 
290 template<class T, class C>
291 void operator+=(std::vector<T>& v1, const C& c)
292 {
293  for (size_t i = 0; i < v1.size(); i++)
294  {
295  v1[i] += c;
296  }
297 }
298 
299 template<class T, class C>
300 void operator-=(std::vector<T>& v1, const C& c)
301 {
302  for (size_t i = 0; i < v1.size(); i++)
303  {
304  v1[i] -= c;
305  }
306 }
307 
308 template<class T, class C>
309 void operator*=(std::vector<T>& v1, const C& c)
310 {
311  for (size_t i = 0; i < v1.size(); i++)
312  {
313  v1[i] *= c;
314  }
315 }
316 
317 template<class T, class C>
318 void operator/=(std::vector<T>& v1, const C& c)
319 {
320  for (size_t i = 0; i < v1.size(); i++)
321  {
322  v1[i] /= c;
323  }
324 }
327 /******************************************************************************/
328 
330 {
331 public:
333  virtual ~VectorTools() {}
334 
335 public:
341  template<class T>
342  static void resize2(VVdouble& vv, size_t n1, size_t n2)
343  {
344  vv.resize(n1);
345  for (size_t i = 0; i < n1; i++) { vv[i].resize(n2); }
346  }
347 
348  template<class T>
349  static void resize3(VVVdouble& vvv, size_t n1, size_t n2, size_t n3)
350  {
351  vvv.resize(n1);
352  for (size_t i = 0; i < n1; i++)
353  {
354  vvv[i].resize(n2);
355  for (size_t j = 0; j < n2; j++)
356  {
357  vvv[i][j].resize(n3);
358  }
359  }
360  }
361 
362  static void resize4(VVVVdouble& vvvv, size_t n1, size_t n2, size_t n3, size_t n4)
363  {
364  vvvv.resize(n1);
365  for (size_t i = 0; i < n1; i++)
366  {
367  vvvv[i].resize(n2);
368  for (size_t j = 0; j < n2; j++)
369  {
370  vvvv[i][j].resize(n3);
371  for (size_t k = 0; k < n3; k++)
372  {
373  vvvv[i][j][k].resize(n4);
374  }
375  }
376  }
377  }
380  template<class T>
381  static void fill(std::vector<T>& v, T value)
382  {
383  for (typename std::vector<T>::iterator it = v.begin(); it < v.end(); it++)
384  {
385  *it = value;
386  }
387  }
388 
401  template<class T>
402  static std::vector<T> seq(T from, T to, T by)
403  {
404  std::vector<T> v;
405  if (from < to)
406  {
407  // for (T i = from ; i <= to ; i += by) { // Not good for double, 'to'
408  for (T i = from; i <= to + (by / 100); i += by)
409  { // must be a little bit larger
410  v.push_back(i);
411  }
412  }
413  else
414  {
415  for (T i = from; i >= to - (by / 100); i -= by)
416  {
417  v.push_back(i);
418  }
419  }
420  return v;
421  }
422 
433  template<class T>
434  static size_t which(const std::vector<T>& v, const T& which) throw (ElementNotFoundException<T> )
435  {
436  for (size_t i = 0; i < v.size(); i++)
437  {
438  if (v[i] == which) return i;
439  }
440  throw ElementNotFoundException<T>("VectorTools::which.", &v, &which);
441  }
442 
453  template<class T>
454  static std::vector<size_t> whichAll(const std::vector<T>& v, const T& which) throw (ElementNotFoundException<T> )
455  {
456  std::vector<size_t> w;
457  for (size_t i = 0; i < v.size(); i++)
458  {
459  if (v[i] == which) w.push_back(i);
460  }
461  if (w.size())
462  return w;
463  throw ElementNotFoundException<T>("VectorTools::whichAll.", &v, &which);
464  }
465 
477  template<class T>
478  static std::vector<T> unique(const std::vector<T>& v)
479  {
480  if (v.size() == 0) return v;
481  std::vector<T> sortedV(v.begin(), v.end());
482  sort(sortedV.begin(), sortedV.end());
483  std::vector<T> uniq;
484  uniq.push_back(sortedV[0]);
485  for (size_t i = 1; i < sortedV.size(); i++)
486  {
487  if (sortedV[i] != sortedV[i - 1]) uniq.push_back(sortedV[i]);
488  }
489  return uniq;
490  }
491 
502  template<class T>
503  static bool isUnique(const std::vector<T>& v)
504  {
505  if (v.size() == 0) return true;
506  std::vector<T> sortedV(v.begin(), v.end());
507  sort(sortedV.begin(), sortedV.end());
508  for (size_t i = 1; i < sortedV.size(); i++)
509  {
510  if (sortedV[i] == sortedV[i - 1]) return false;
511  }
512  return true;
513  }
514 
522  template<class T>
523  static std::vector<T> extract(const std::vector<T>& v1, const std::vector<int>& v2)
524  {
525  std::vector<T> v(v2.size());
526  for (size_t i = 0; i < v2.size(); i++)
527  {
528  v[i] = v1[v2[i]];
529  }
530  return v;
531  }
532 
539  template<class T>
540  static std::map<T, size_t> countValues(const std::vector<T>& v)
541  {
542  std::map<T, size_t> c;
543  for (size_t i = 0; i < v.size(); i++)
544  {
545  c[v[i]]++;
546  }
547  return c;
548  }
549 
560  static std::vector<double> breaks(const std::vector<double>& v, unsigned int n);
561 
572  template<class T>
573  static size_t nclassScott(const std::vector<T>& v)
574  {
575  std::vector<T> r1 = VectorTools::range(v);
576  T r = r1[1] - r1[0];
577  double n = v.size();
578  double h = 3.5 * VectorTools::sd<T, double>(v) * std::pow(n, -1. / 3);
579  return (size_t) ceil(r / h);
580  }
581 
586  template<class T>
587  static T prod(const std::vector<T>& v1)
588  {
589  T p = 1;
590  for (size_t i = 0; i < v1.size(); i++) { p *= v1[i]; }
591  return p;
592  }
593 
599  template<class T>
600  static std::vector<T> cumProd(const std::vector<T>& v1)
601  {
602  std::vector<T> p(v1.size());
603  if (v1.size() == 0) return p;
604  p[0] = v1[0];
605  for (size_t i = 1; i < v1.size(); i++) { p[i] = v1[i] * p[i - 1]; }
606  return p;
607  }
608 
613  template<class T>
614  static T sum(const std::vector<T>& v1)
615  {
616  T s = 0;
617  for (size_t i = 0; i < v1.size(); i++) { s += v1[i]; }
618  return s;
619  }
620 
626  template<class T>
627  static std::vector<T> cumSum(const std::vector<T>& v1)
628  {
629  std::vector<T> s(v1.size());
630  if (v1.size() == 0) return s;
631  s[0] = v1[0];
632  for (size_t i = 1; i < v1.size(); i++) { s[i] = v1[i] + s[i - 1]; }
633  return s;
634  }
635 
642  template<class T>
643  static void logNorm(std::vector<T>& v)
644  {
645  T M = max(v);
646  T x = std::exp(v[0] - M);
647  for (size_t i = 1; i < v.size(); i++)
648  {
649  x += std::exp(v[i] - M);
650  }
651  v -= M + std::log(x);
652  }
653 
659  template<class T>
660  static T logSumExp(const std::vector<T>& v1)
661  {
662  T M = max(v1);
663  T x = std::exp(v1[0] - M);
664  for (size_t i = 1; i < v1.size(); i++)
665  {
666  x += std::exp(v1[i] - M);
667  }
668  return std::log(x) + M;
669  }
670 
677  template<class T>
678  static T logSumExp(const std::vector<T>& v1, const std::vector<T>& v2)
679  {
680  size_t size;
681  if (v1.size() != v2.size())
682  throw DimensionException("VectorTools::logsumexp", v1.size(), v2.size());
683  else
684  size = v1.size();
685 
686  T M = max(v1);
687  T x = v2[0] * std::exp(v1[0] - M);
688  for (size_t i = 1; i < size; i++)
689  {
690  x += v2[i] * std::exp(v1[i] - M);
691  }
692  return std::log(x) + M;
693  }
694 
700  template<class T>
701  static T logMeanExp(const std::vector<T>& v1)
702  {
703  T M = max(v1);
704  T x = std::exp(v1[0] - M);
705  for (size_t i = 1; i < v1.size(); i++)
706  {
707  x += std::exp(v1[i] - M);
708  }
709  return std::log(x) + M - std::log(v1.size());
710  }
711 
712 
718  template<class T>
719  static T sumExp(const std::vector<T>& v1)
720  {
721  T M = max(v1);
722  T x = std::exp(v1[0] - M);
723  for (size_t i = 1; i < v1.size(); i++)
724  {
725  x += std::exp(v1[i] - M);
726  }
727  return x * std::exp(M);
728  }
729 
736  template<class T>
737  static T sumExp(const std::vector<T>& v1, const std::vector<T>& v2)
738  {
739  size_t size;
740  if (v1.size() != v2.size())
741  throw DimensionException("VectorTools::logsumexp", v1.size(), v2.size());
742  else
743  size = v1.size();
744 
745  T M = max(v1);
746  T x = v2[0] * std::exp(v1[0] - M);
747  for (size_t i = 1; i < size; i++)
748  {
749  x += v2[i] * std::exp(v1[i] - M);
750  }
751  return x * std::exp(M);
752  }
753 
760  template<class T>
761  static std::vector<double> log(const std::vector<T>& v1)
762  {
763  std::vector<double> v2(v1.size());
764  for (size_t i = 0; i < v2.size(); i++) { v2[i] = std::log(v1[i]); }
765  return v2;
766  }
767  template<class T>
768  static std::vector<double> log(const std::vector<T>& v1, double base)
769  {
770  std::vector<double> v2(v1.size());
771  for (size_t i = 0; i < v2.size(); i++) { v2[i] = std::log(v1[i]) / std::log(base); }
772  return v2;
773  }
774 
775  template<class T>
776  static std::vector<double> exp(const std::vector<T>& v1)
777  {
778  std::vector<double> v2(v1.size());
779  for (size_t i = 0; i < v2.size(); i++) { v2[i] = std::exp(v1[i]); }
780  return v2;
781  }
782 
783  template<class T>
784  static std::vector<double> cos(const std::vector<T>& v1)
785  {
786  std::vector<double> v2(v1.size());
787  for (size_t i = 0; i < v2.size(); i++) { v2[i] = std::cos(v1[i]); }
788  return v2;
789  }
790 
791  template<class T>
792  static std::vector<double> sin(const std::vector<T>& v1)
793  {
794  std::vector<double> v2(v1.size());
795  for (size_t i = 0; i < v2.size(); i++) { v2[i] = std::sin(v1[i]); }
796  return v2;
797  }
798 
799  template<class T>
800  static std::vector<double> log10(const std::vector<T>& v1)
801  {
802  std::vector<double> v2(v1.size());
803  for (size_t i = 0; i < v1.size(); i++) { v2[i] = std::log10(v1[i]); }
804  return v2;
805  }
806 
807  template<class T>
808  static std::vector<T> fact(const std::vector<T>& v1)
809  {
810  std::vector<T> v2(v1.size());
811  for (size_t i = 0; i < v1.size(); i++) { v2[i] = NumTools::fact<T>(v1[i]); }
812  return v2;
813  }
814 
815  template<class T>
816  static std::vector<T> sqr(const std::vector<T>& v1)
817  {
818  std::vector<T> v2(v1.size());
819  for (size_t i = 0; i < v1.size(); i++) { v2[i] = NumTools::sqr<T>(v1[i]); }
820  return v2;
821  }
822 
823  template<class T>
824  static std::vector<T> pow(const std::vector<T>& v1, T& b)
825  {
826  std::vector<T> v2(v1.size());
827  for (size_t i = 0; i < v1.size(); i++) { v2[i] = std::pow(v1[i], b); }
828  return v2;
829  }
838  template<class T>
839  static std::string paste(const std::vector<T>& v, const std::string& delim = " ")
840  {
841  std::ostringstream out;
842  for (size_t i = 0; i < v.size(); i++)
843  {
844  out << v[i];
845  if (i < v.size() - 1)
846  out << delim;
847  }
848  return out.str();
849  }
850 
857  template<class T>
858  static void print(const std::vector<T>& v1, OutputStream& out = * ApplicationTools::message, const std::string& delim = " ")
859  {
860  for (size_t i = 0; i < v1.size(); i++)
861  {
862  out << v1[i];
863  if (i < v1.size() - 1)
864  out << delim;
865  }
866  out.endLine();
867  }
868 
875  template<class T>
876  static void printForR(const std::vector<T>& v1, std::string variableName = "x", std::ostream& out = std::cout)
877  {
878  out.precision(12);
879  out << variableName << "<-c(";
880  for (size_t i = 0; i < v1.size(); i++)
881  {
882  out << v1[i];
883  if (i < v1.size() - 1)
884  out << ", ";
885  }
886  out << ")" << std::endl;
887  }
888 
895  template<class InputType, class OutputType>
896  static OutputType scalar(const std::vector<InputType>& v1, const std::vector<InputType>& v2) throw (DimensionException)
897  {
898  if (v1.size() != v2.size())
899  {
900  throw DimensionException("VectorFunctions::scalar", v1.size(), v2.size());
901  }
902  OutputType result = 0;
903  for (size_t i = 0; i < v1.size(); i++)
904  {
905  result += v1[i] * v2[i];
906  }
907  return result;
908  }
925  template<class InputType, class OutputType>
926  static OutputType scalar(const std::vector<InputType>& v1, const std::vector<InputType>& v2, const std::vector<InputType>& w) throw (DimensionException)
927  {
928  if (v1.size() != w.size())
929  {
930  throw DimensionException("VectorFunctions::scalar", v1.size(), w.size());
931  }
932  if (v2.size() != w.size())
933  {
934  throw DimensionException("VectorFunctions::scalar", v2.size(), w.size());
935  }
936  OutputType result = 0;
937  for (size_t i = 0; i < v1.size(); i++)
938  {
939  result += v1[i] * v2[i] * w[i];
940  }
941  return result;
942  }
943 
950  template<class T>
951  static std::vector<T> kroneckerMult(const std::vector<T>& v1, const std::vector<T>& v2) throw (DimensionException)
952  {
953  size_t n1 = v1.size();
954  size_t n2 = v2.size();
955  std::vector<T> v3(n1 * n2);
956  for (size_t i = 0; i < n1; i++)
957  {
958  T v1i = v1[i];
959  for (size_t j = 0; j < n2; j++)
960  {
961  v3[i * n2 + j] = v1i * v2[j];
962  }
963  }
964  return v3;
965  }
966 
971  template<class InputType, class OutputType>
972  static OutputType norm(const std::vector<InputType>& v1)
973  {
974  OutputType result = 0;
975  for (size_t i = 0; i < v1.size(); i++)
976  {
977  result += v1[i] * v1[i];
978  }
979  return sqrt(result);
980  }
981 
989  template<class InputType, class OutputType>
990  static OutputType norm(const std::vector<InputType>& v1, const std::vector<InputType>& w) throw (DimensionException)
991  {
992  if (v1.size() != w.size())
993  {
994  throw DimensionException("VectorFunctions::norm", v1.size(), w.size());
995  }
996  OutputType result = 0;
997  for (size_t i = 0; i < v1.size(); i++)
998  {
999  result += v1[i] * v1[i] * w[i];
1000  }
1001  return sqrt(result);
1002  }
1003 
1010  template<class InputType, class OutputType>
1011  static OutputType cos(const std::vector<InputType>& v1, const std::vector<InputType>& v2) throw (DimensionException)
1012  {
1013  return scalar<InputType, OutputType>(v1, v2)
1014  / (norm<InputType, OutputType>(v1) * norm<InputType, OutputType>(v2));
1015  }
1016 
1024  template<class InputType, class OutputType>
1025  static OutputType cos(const std::vector<InputType>& v1, const std::vector<InputType>& v2, const std::vector<InputType>& w) throw (DimensionException)
1026  {
1027  return scalar<InputType, OutputType>(v1, v2, w)
1028  / (norm<InputType, OutputType>(v1, w) * norm<InputType, OutputType>(v2, w));
1029  }
1030 
1046  template<class T>
1047  static T min(const std::vector<T>& v) throw (EmptyVectorException<T> )
1048  {
1049  if (v.size() == 0) throw EmptyVectorException<T>("VectorFunctions::min()", &v);
1050  T mini = v[0];
1051  for (size_t i = 1; i < v.size(); i++)
1052  {
1053  if (v[i] < mini) mini = v[i];
1054  }
1055  return mini;
1056  }
1057 
1067  template<class T>
1068  static T max(const std::vector<T>& v) throw (EmptyVectorException<T> )
1069  {
1070  if (v.size() == 0) throw EmptyVectorException<T>("VectorFuntions::max()", &v);
1071  T maxi = v[0];
1072  for (size_t i = 1; i < v.size(); i++)
1073  {
1074  if (v[i] > maxi) maxi = v[i];
1075  }
1076  return maxi;
1077  }
1078 
1089  template<class T>
1090  static size_t whichMax(const std::vector<T>& v) throw (EmptyVectorException<T> )
1091  {
1092  if (v.size() == 0) throw EmptyVectorException<T>("VectorFuntions::whichMax()", &v);
1093  T maxi = v[0];
1094  size_t pos = 0;
1095  for (size_t i = 1; i < v.size(); i++)
1096  {
1097  if (v[i] > maxi)
1098  {
1099  maxi = v[i];
1100  pos = i;
1101  }
1102  }
1103  return pos;
1104  }
1105 
1116  template<class T>
1117  static size_t whichMin(const std::vector<T>& v) throw (EmptyVectorException<T> )
1118  {
1119  if (v.size() == 0) throw EmptyVectorException<T>("VectorFunctions::whichMin()", &v);
1120  T mini = v[0];
1121  size_t pos = 0;
1122  for (size_t i = 1; i < v.size(); i++)
1123  {
1124  if (v[i] < mini)
1125  {
1126  mini = v[i];
1127  pos = i;
1128  }
1129  }
1130  return pos;
1131  }
1132 
1143  template<class T>
1144  static std::vector<size_t> whichMaxAll(const std::vector<T>& v) throw (EmptyVectorException<T> )
1145  {
1146  if (v.size() == 0) throw EmptyVectorException<T>("VectorFuntions::whichMaxAll()", &v);
1147  T maxi = max(v);
1148  std::vector<size_t> pos;
1149  for (size_t i = 0; i < v.size(); i++)
1150  {
1151  if (v[i] == maxi)
1152  {
1153  pos.push_back(i);
1154  }
1155  }
1156  return pos;
1157  }
1158 
1169  template<class T>
1170  static std::vector<size_t> whichMinAll(const std::vector<T>& v) throw (EmptyVectorException<T> )
1171  {
1172  if (v.size() == 0) throw EmptyVectorException<T>("VectorFuntions::whichMinAll()", &v);
1173  T mini = min(v);
1174  std::vector<size_t> pos;
1175  for (size_t i = 0; i < v.size(); i++)
1176  {
1177  if (v[i] == mini)
1178  {
1179  pos.push_back(i);
1180  }
1181  }
1182  return pos;
1183  }
1184 
1185 
1195  template<class T>
1196  static std::vector<T> range(const std::vector<T>& v) throw (EmptyVectorException<T> )
1197  {
1198  if (v.size() == 0)
1199  throw EmptyVectorException<T>("VectorTools::range()", &v);
1200  std::vector<T> r(2);
1201  r[0] = r[1] = v[0];
1202  for (size_t i = 1; i < v.size(); i++)
1203  {
1204  if (v[i] < r[0]) r[0] = v[i];
1205  if (v[i] > r[1]) r[1] = v[i];
1206  }
1207  return r;
1208  }
1209 
1210 private:
1211  template<class T> class order_Cmp_
1212  {
1213  const std::vector<T>& values_;
1214 
1215 public:
1216  order_Cmp_(const std::vector<T>& v) : values_(v) {}
1217  bool operator()(size_t a, size_t b) { return values_[a] < values_[b]; }
1218  };
1219 
1220 public:
1230  template<class T>
1231  static std::vector<size_t> order(const std::vector<T>& v) throw (EmptyVectorException<T> )
1232  {
1233  if (v.size() == 0)
1234  throw EmptyVectorException<T>("VectorTools::sort()", &v);
1235  // Private inner class:
1236  std::vector<size_t> index(v.size());
1237  for (size_t i = 0; i < index.size(); ++i)
1238  {
1239  index[i] = i;
1240  }
1241  sort(index.begin(), index.end(), order_Cmp_<T>(v));
1242  return index;
1243  }
1244 
1254  template<class T>
1255  static std::vector<T> abs(const std::vector<T>& v) throw (EmptyVectorException<T> )
1256  {
1257  std::vector<T> vabs(v.size());
1258  for (size_t i = 1; i < v.size(); i++)
1259  {
1260  vabs[i] = std::abs(v[i]);
1261  }
1262  return vabs;
1263  }
1264 
1269  template<class InputType, class OutputType>
1270  static OutputType mean(const std::vector<InputType>& v1)
1271  {
1272  return (OutputType)sum<InputType>(v1) / (OutputType)v1.size();
1273  }
1280  template<class InputType, class OutputType>
1281  static OutputType mean(const std::vector<InputType>& v1, const std::vector<InputType>& w, bool normalizeWeights = true)
1282  {
1283  if (normalizeWeights)
1284  {
1285  std::vector<InputType> wn = w / sum(w);
1286  return scalar<InputType, OutputType>(v1, wn);
1287  }
1288  else
1289  {
1290  return scalar<InputType, OutputType>(v1, w);
1291  }
1292  }
1293 
1298  template<class InputType>
1299  static InputType median(std::vector<InputType>& v1)
1300  {
1301  InputType med = 0;
1302  if (v1.size() == 0) return med;
1303  if (v1.size() == 1) return v1[0];
1304  sort(v1.begin(), v1.end());
1305  size_t i = v1.size() / 2;
1306  if (v1.size() % 2 == 0)
1307  {
1308  // Vector size is pair
1309  med = double((v1[i - 1] + v1[i]) / 2);
1310  }
1311  else
1312  {
1313  // Vector size is impair
1314  med = v1[i];
1315  }
1316  return med;
1317  }
1318 
1325  template<class InputType, class OutputType>
1326  static std::vector<OutputType> center(const std::vector<InputType>& v1)
1327  {
1328  OutputType m = mean<InputType, OutputType>(v1);
1329  std::vector<OutputType> v(v1.size());
1330  for (size_t i = 0; i < v1.size(); i++)
1331  {
1332  v[i] = (OutputType)v1[i] - m;
1333  }
1334  return v;
1335  }
1344  template<class InputType, class OutputType>
1345  static std::vector<OutputType> center(const std::vector<InputType>& v1, const std::vector<InputType>& w, bool normalizeWeights = true)
1346  {
1347  OutputType m = mean<InputType, OutputType>(v1, w, normalizeWeights);
1348  std::vector<OutputType> v(v1.size());
1349  for (size_t i = 0; i < v1.size(); i++)
1350  {
1351  v[i] = (OutputType)v1[i] - m;
1352  }
1353  return v;
1354  }
1355 
1363  template<class InputType, class OutputType>
1364  static OutputType cov(const std::vector<InputType>& v1, const std::vector<InputType>& v2, bool unbiased = true) throw (DimensionException)
1365  {
1366  OutputType n = (OutputType)v1.size();
1367  OutputType x = scalar<InputType, OutputType>(
1368  center<InputType, OutputType>(v1),
1369  center<InputType, OutputType>(v2)
1370  ) / n;
1371  if (unbiased) x = x * n / (n - 1);
1372  return x;
1373  }
1374 
1385  template<class InputType, class OutputType>
1386  static OutputType cov(const std::vector<InputType>& v1, const std::vector<InputType>& v2, const std::vector<InputType>& w, bool unbiased = true, bool normalizeWeights = true) throw (DimensionException)
1387  {
1388  if (normalizeWeights)
1389  {
1390  std::vector<InputType> wn = w / sum(w);
1391  OutputType x = scalar<InputType, OutputType>(
1392  center<InputType, OutputType>(v1, wn, false),
1393  center<InputType, OutputType>(v2, wn, false),
1394  wn
1395  );
1396  if (unbiased)
1397  {
1398  x = x / (1 - sum(sqr<double>(wn)));
1399  }
1400  return x;
1401  }
1402  else
1403  {
1404  OutputType x = scalar<InputType, OutputType>(
1405  center<InputType, OutputType>(v1, w, false),
1406  center<InputType, OutputType>(v2, w, false),
1407  w
1408  );
1409  if (unbiased)
1410  {
1411  x = x / (1 - sum(sqr(w)));
1412  }
1413  return x;
1414  }
1415  }
1421  template<class InputType, class OutputType>
1422  static OutputType var(const std::vector<InputType>& v1, bool unbiased = true)
1423  {
1424  return cov<InputType, OutputType>(v1, v1, unbiased);
1425  }
1434  template<class InputType, class OutputType>
1435  static OutputType var(const std::vector<InputType>& v1, const std::vector<InputType>& w, bool unbiased = true, bool normalizeWeights = true) throw (DimensionException)
1436  {
1437  return cov<InputType, OutputType>(v1, v1, w, unbiased, normalizeWeights);
1438  }
1439 
1445  template<class InputType, class OutputType>
1446  static OutputType sd(const std::vector<InputType>& v1, bool unbiased = true)
1447  {
1448  return sqrt(var<InputType, OutputType>(v1, unbiased));
1449  }
1450 
1459  template<class InputType, class OutputType>
1460  static OutputType sd(const std::vector<InputType>& v1, const std::vector<InputType>& w, bool unbiased = true, bool normalizeWeights = true) throw (DimensionException)
1461  {
1462  return sqrt(var<InputType, OutputType>(v1, w, unbiased, normalizeWeights));
1463  }
1464 
1471  template<class InputType, class OutputType>
1472  static OutputType cor(const std::vector<InputType>& v1, const std::vector<InputType>& v2) throw (DimensionException)
1473  {
1474  return cov<InputType, OutputType>(v1, v2)
1475  / ( sd<InputType, OutputType>(v1) * sd<InputType, OutputType>(v2) );
1476  }
1477 
1486  template<class InputType, class OutputType>
1487  static OutputType cor(const std::vector<InputType>& v1, const std::vector<InputType>& v2, const std::vector<InputType>& w, bool normalizeWeights = true) throw (DimensionException)
1488  {
1489  if (normalizeWeights)
1490  {
1491  std::vector<InputType> wn = w / sum(w);
1492  return cov<InputType, OutputType>(v1, v2, wn, false, false)
1493  / ( sd<InputType, OutputType>(v1, wn, false, false) * sd<InputType, OutputType>(v2, wn, false, false) );
1494  }
1495  else
1496  {
1497  return cov<InputType, OutputType>(v1, v2, w, false, false)
1498  / ( sd<InputType, OutputType>(v1, w, false, false) * sd<InputType, OutputType>(v2, w, false, false) );
1499  }
1500  }
1501 
1516  template<class InputType, class OutputType>
1517  static OutputType shannon(const std::vector<InputType>& v, double base = 2.7182818)
1518  {
1519  OutputType s = 0;
1520  for (size_t i = 0; i < v.size(); i++)
1521  {
1522  if (v[i] > 0) s += static_cast<OutputType>(v[i] * std::log(v[i]) / std::log(base));
1523  }
1524  return -s;
1525  }
1526 
1541  template<class InputType, class OutputType>
1542  static OutputType shannonDiscrete(const std::vector<InputType>& v, double base = 2.7182818)
1543  {
1544  std::map<InputType, double> counts;
1545  for (size_t i = 0; i < v.size(); i++)
1546  {
1547  counts[v[i]]++;
1548  }
1549  OutputType s = 0;
1550  double n = static_cast<double>(v.size());
1551  for (typename std::map<InputType, double>::iterator it = counts.begin(); it != counts.end(); it++)
1552  {
1553  s += static_cast<OutputType>((it->second / n) * std::log(it->second / n) / std::log(base));
1554  }
1555  return -s;
1556  }
1557 
1573  template<class InputType, class OutputType>
1574  static OutputType miDiscrete(const std::vector<InputType>& v1, const std::vector<InputType>& v2, double base = 2.7182818) throw (DimensionException)
1575  {
1576  if (v1.size() != v2.size())
1577  throw DimensionException("VectorTools::miDiscrete. The two samples must have the same length.", v2.size(), v1.size());
1578  std::map<InputType, double> counts1;
1579  std::map<InputType, double> counts2;
1580  std::map<InputType, std::map<InputType, double> > counts12;
1581  for (size_t i = 0; i < v1.size(); i++)
1582  {
1583  counts1[v1[i]]++;
1584  counts2[v2[i]]++;
1585  counts12[v1[i]][v2[i]]++;
1586  }
1587  OutputType s = 0;
1588  double n = static_cast<double>(v1.size());
1589  for (typename std::map<InputType, std::map<InputType, double> >::iterator it1 = counts12.begin(); it1 != counts12.end(); it1++)
1590  {
1591  for (typename std::map<InputType, double>::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
1592  {
1593  s += static_cast<OutputType>((it2->second / n) * std::log(it2->second * n / (counts1[it1->first] * counts2[it2->first])) / std::log(base));
1594  }
1595  }
1596  return s;
1597  }
1598 
1614  template<class InputType, class OutputType>
1615  static OutputType shannonContinuous(const std::vector<InputType>& v, double base = 2.7182818)
1616  {
1617  LinearMatrix<InputType> m(1, v.size());
1618  for (size_t i = 0; i < v.size(); i++)
1619  {
1620  m(0, i) = v[i];
1621  }
1623  OutputType s = 0;
1624  std::vector<double> x(1);
1625  for (size_t i = 0; i < v.size(); i++)
1626  {
1627  x[0] = static_cast<double>(v[i]);
1628  s += static_cast<OutputType>(std::log(kd.kDensity(x)) / std::log(base));
1629  }
1630  return -s / static_cast<double>(v.size());
1631  }
1632 
1652  template<class InputType, class OutputType>
1653  static OutputType miContinuous(const std::vector<InputType>& v1, const std::vector<InputType>& v2, double base = 2.7182818) throw (DimensionException)
1654  {
1655  if (v1.size() != v2.size())
1656  throw DimensionException("VectorTools::miContinuous. The two samples must have the same length.", v2.size(), v1.size());
1657  LinearMatrix<InputType> m1(1, v1.size());
1658  LinearMatrix<InputType> m2(1, v2.size());
1659  LinearMatrix<InputType> m12(2, v1.size());
1660  for (size_t i = 0; i < v1.size(); i++)
1661  {
1662  m1(0, i) = m12(0, i) = v1[i];
1663  m2(0, i) = m12(1, i) = v2[i];
1664  }
1668  OutputType s = 0;
1669  std::vector<double> x1(1);
1670  std::vector<double> x2(1);
1671  std::vector<double> x12(2);
1672  for (size_t i = 0; i < v1.size(); i++)
1673  {
1674  x1[0] = x12[0] = static_cast<double>(v1[i]);
1675  x2[0] = x12[1] = static_cast<double>(v2[i]);
1676  s += static_cast<OutputType>(std::log(kd12.kDensity(x12) / (kd1.kDensity(x1) * kd2.kDensity(x2))) / std::log(base));
1677  }
1678  return s / static_cast<double>(v1.size());
1679  }
1680 
1686  template<class T>
1687  static bool haveSameElements(const std::vector<T>& v1, const std::vector<T>& v2)
1688  {
1689  std::vector<T> u1(v1);
1690  std::vector<T> u2(v2);
1691  if (u1.size() != u2.size()) return false;
1692  std::sort(u1.begin(), u1.end());
1693  std::sort(u2.begin(), u2.end());
1694  return u1 == u2;
1695  }
1696 
1705  template<class T>
1706  static bool haveSameElements(std::vector<T>& v1, std::vector<T>& v2)
1707  {
1708  if (v1.size() != v2.size()) return false;
1709  std::sort(v1.begin(), v1.end());
1710  std::sort(v2.begin(), v2.end());
1711  return v1 == v2;
1712  }
1713 
1719  template<class T>
1720  static bool contains(const std::vector<T>& vec, T el)
1721  {
1722  for (size_t i = 0; i < vec.size(); i++)
1723  {
1724  if (vec[i] == el) return true;
1725  }
1726  return false;
1727  }
1728 
1737  template<class T>
1738  static bool containsAll(std::vector<T>& v1, std::vector<T>& v2)
1739  {
1740  std::sort(v1.begin(), v1.end());
1741  std::sort(v2.begin(), v2.end());
1742  size_t j = 0;
1743  for (size_t i = 0; i < v2.size(); i++)
1744  {
1745  if (i > 0 && v2[i] == v2[i - 1]) continue;
1746  while (j < v1.size() - 1 && v1[j] < v2[i]) j++;
1747  if (v1[j] != v2[i]) return false;
1748  }
1749  return true;
1750  }
1751 
1758  template<class T>
1759  static std::vector<T> vectorUnion(const std::vector<T>& vec1, const std::vector<T>& vec2)
1760  {
1761  std::vector<T> unionEl = vec1;
1762  for (size_t j = 0; j < vec2.size(); j++)
1763  {
1764  if (!contains(unionEl, vec2[j]))
1765  unionEl.push_back(vec2[j]);
1766  }
1767  return unionEl;
1768  }
1769 
1775  template<class T>
1776  static std::vector<T> vectorUnion(const std::vector< std::vector<T> >& vecElementL)
1777  {
1778  std::vector<T> unionEl;
1779  for (size_t i = 0; i < vecElementL.size(); i++)
1780  {
1781  for (size_t j = 0; j < vecElementL[i].size(); j++)
1782  {
1783  if (!contains(unionEl, vecElementL[i][j]))
1784  unionEl.push_back(vecElementL[i][j]);
1785  }
1786  }
1787  return unionEl;
1788  }
1789 
1795  template<class T>
1796  static std::vector<T> vectorIntersection(const std::vector<T>& vec1, const std::vector<T>& vec2)
1797  {
1798  std::vector<T> interEl;
1799  for (size_t i = 0; i < vec1.size(); i++)
1800  {
1801  if (contains(vec2, vec1[i])) interEl.push_back(vec1[i]);
1802  }
1803  return interEl;
1804  }
1805 
1810  template<class T>
1811  static std::vector<T> vectorIntersection(const std::vector< std::vector<T> >& vecElementL)
1812  {
1813  if (vecElementL.size() == 1) return vecElementL[0];
1814  std::vector<T> interEl;
1815  if (vecElementL.size() == 0) return interEl;
1816  for (size_t i = 0; i < vecElementL[0].size(); i++)
1817  {
1818  bool test = true;
1819  for (size_t j = 1; test && j < vecElementL.size(); j++)
1820  {
1821  if (!contains(vecElementL[j], vecElementL[0][i])) test = false;
1822  }
1823  if (test) interEl.push_back(vecElementL[0][i]);
1824  }
1825  return interEl;
1826  }
1827 
1833  template<class T>
1834  static void append(std::vector<T>& vec1, const std::vector<T>& vec2)
1835  {
1836  vec1.insert(vec1.end(), vec2.begin(), vec2.end());
1837  // for(size_t i = 0; i < vec2.size(); i++)
1838  // {
1839  // vec1.push_back(vec2[i]);
1840  // }
1841  }
1842 
1848  template<class T>
1849  static void prepend(std::vector<T>& vec1, const std::vector<T>& vec2)
1850  {
1851  vec1.insert(vec1.begin(), vec2.begin(), vec2.end());
1852  }
1853 
1854 
1859  template<class T>
1860  static std::vector<T> append(const std::vector< std::vector<T> >& vecElementL)
1861  {
1862  if (vecElementL.size() == 1) return vecElementL[0];
1863  std::vector<T> v;
1864  if (vecElementL.size() == 0) return v;
1865  for (size_t i = 0; i < vecElementL[0].size(); i++)
1866  {
1867  v.push_back(vecElementL[0][i]);
1868  }
1869  return v;
1870  }
1871 
1877  template<class T>
1878  static void extend(std::vector<T>& vec1, const std::vector<T>& vec2)
1879  {
1880  for (size_t i = 0; i < vec2.size(); i++)
1881  {
1882  if (!contains(vec1, vec2[i]))
1883  vec1.push_back(vec2[i]);
1884  }
1885  }
1886 
1892  template<class T>
1893  static std::vector<T> rep(const std::vector<T>& vec, size_t n)
1894  {
1895  if (n == 1) return vec;
1896  std::vector<T> v;
1897  if (n == 0) return v;
1898  v.resize(vec.size() * n);
1899  for (size_t i = 0; i < v.size(); i++)
1900  {
1901  v[i] = vec[i % vec.size()];
1902  }
1903  return v;
1904  }
1905 
1915  template<class T>
1916  static void diff(std::vector<T>& v1, std::vector<T>& v2, std::vector<T>& v3)
1917  {
1918  if (v2.size() == 0) append(v3, v1);
1919  std::sort(v1.begin(), v1.end());
1920  std::sort(v2.begin(), v2.end());
1921  size_t j = 0;
1922  for (size_t i = 0; i < v1.size(); i++)
1923  {
1924  if (i > 0 && v1[i] == v1[i - 1]) continue;
1925  while (j < v2.size() - 1 && v2[j] < v1[i]) j++;
1926  if (v2[j] != v1[i]) v3.push_back(v1[i]);
1927  }
1928  }
1929 
1934  static bool test();
1935 };
1936 } // end of namespace bpp.
1937 
1938 #endif // _VECTORTOOLS_H_
1939