All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
vector.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2014, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl 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  O2scl 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 O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 #ifndef O2SCL_VECTOR_H
24 #define O2SCL_VECTOR_H
25 
26 /** \file vector.h
27  \brief Assorted generic vector functions
28 
29  This file contains a set of template functions which can be
30  applied to almost any vector or matrix type which allow element
31  access through <tt>operator[]</tt>. Detailed requirements
32  on the template parameters are given in the functions below.
33 
34  For a general discussion of vectors and matrices in \o2, see the
35  \ref vecmat_section of the User's Guide.
36 
37  For statistics operations not included here, see \ref vec_stats.h
38  in the directory \c src/other . Also related are the matrix output
39  functions, \ref o2scl::matrix_out(), which is defined in \ref
40  columnify.h because they utilize the class \ref o2scl::columnify to
41  format the output.
42 
43  For functions which search for a value in an ordered (either
44  increasing or decreasing) vector, see the class \ref
45  o2scl::search_vec .
46 
47  \future Create a matrix transpose copy function?
48  \future Create matrix swap row and column functions
49 */
50 #include <iostream>
51 #include <cmath>
52 #include <string>
53 #include <fstream>
54 #include <sstream>
55 
56 #include <o2scl/misc.h>
57 #include <o2scl/uniform_grid.h>
58 
59 namespace o2scl {
60 
61  /// \name Copying vectors and matrices
62  //@{
63  /** \brief Simple generic vector copy
64 
65  Copy \c src to \c dest, resizing \c dest if it is too small
66  to hold <tt>src.size()</tt> elements.
67 
68  This function will work for any classes \c vec_t and
69  \c vec2_t which have suitably defined <tt>operator[]</tt>,
70  <tt>size()</tt>, and <tt>resize()</tt> methods.
71  */
72  template<class vec_t, class vec2_t>
73  void vector_copy(vec_t &src, vec2_t &dest) {
74  size_t N=src.size();
75  if (dest.size()<N) dest.resize(N);
76  size_t i, m=N%4;
77  for(i=0;i<m;i++) {
78  dest[i]=src[i];
79  }
80  for(i=m;i+3<N;i+=4) {
81  dest[i]=src[i];
82  dest[i+1]=src[i+1];
83  dest[i+2]=src[i+2];
84  dest[i+3]=src[i+3];
85  }
86  return;
87  }
88 
89  /** \brief Simple generic vector copy of the first N elements
90 
91  Copy the first \c N elements of \c src to \c dest.
92  It is assumed that the memory allocation for \c dest
93  has already been performed.
94 
95  This function will work for any class <tt>vec2_t</tt> which has
96  an operator[] which returns a reference to the corresponding
97  element and class <tt>vec_t</tt> with an operator[] which
98  returns either a reference or the value of the corresponding
99  element.
100  */
101  template<class vec_t, class vec2_t>
102  void vector_copy(size_t N, vec_t &src, vec2_t &dest) {
103  size_t i, m=N%4;
104  for(i=0;i<m;i++) {
105  dest[i]=src[i];
106  }
107  for(i=m;i+3<N;i+=4) {
108  dest[i]=src[i];
109  dest[i+1]=src[i+1];
110  dest[i+2]=src[i+2];
111  dest[i+3]=src[i+3];
112  }
113  return;
114  }
115 
116  /** \brief Simple generic matrix copy
117 
118  Copy \c src to \c dest, resizing \c dest if it is too small.
119 
120  This function will work for any classes \c mat_t and
121  \c mat2_t which have suitably defined <tt>operator()</tt>,
122  <tt>size()</tt>, and <tt>resize()</tt> methods.
123  */
124  template<class mat_t, class mat2_t>
125  void matrix_copy(mat_t &src, mat2_t &dest) {
126  size_t m=src.size1();
127  size_t n=src.size2();
128  if (dest.size1()<m || dest.size2()<n) dest.resize(m,n);
129  for(size_t i=0;i<m;i++) {
130  for(size_t j=0;j<n;j++) {
131  dest(i,j)=src(i,j);
132  }
133  }
134  }
135 
136  /** \brief Simple generic matrix copy of the first \f$ (M,N) \f$
137  matrix elements
138 
139  Copy the first <tt>(M,N)</tt> elements of \c src to \c dest. It
140  is assumed that the memory allocation for \c dest has already
141  been performed.
142 
143  This function will work for any class <tt>vec2_t</tt> which has
144  an operator[][] which returns a reference to the corresponding
145  element and class <tt>vec_t</tt> with an operator[][] which
146  returns either a reference or the value of the corresponding
147  element.
148  */
149  template<class mat_t, class mat2_t>
150  void matrix_copy(size_t M, size_t N, mat_t &src, mat2_t &dest) {
151  for(size_t i=0;i<M;i++) {
152  for(size_t j=0;j<N;j++) {
153  dest(i,j)=src(i,j);
154  }
155  }
156  }
157  //@}
158 
159  /// \name Swapping parts of vectors and matrices
160  //@{
161  /** \brief Swap the first N elements of two vectors
162 
163  This function swaps the elements of \c v1 and \c v2, one element
164  at a time.
165  */
166  template<class vec_t, class vec2_t, class data_t>
167  void vector_swap(size_t N, vec_t &v1, vec2_t &v2) {
168  data_t temp;
169  size_t i, m=N%4;
170  for(i=0;i<m;i++) {
171  temp=v1[i];
172  v1[i]=v2[i];
173  v2[i]=temp;
174  }
175  for(i=m;i+3<N;i+=4) {
176  temp=v1[i];
177  v1[i]=v2[i];
178  v2[i]=temp;
179  temp=v1[i+1];
180  v1[i+1]=v2[i+1];
181  v2[i+1]=temp;
182  temp=v1[i+2];
183  v1[i+2]=v2[i+2];
184  v2[i+2]=temp;
185  temp=v1[i+3];
186  v1[i+3]=v2[i+3];
187  v2[i+3]=temp;
188  }
189  return;
190  }
191 
192  /** \brief Generic swap of of the first N elements of two
193  double-precision vectors
194 
195  This function swaps the elements of \c v1 and \c v2, one element
196  at a time.
197  */
198  template<class vec_t, class vec2_t>
199  void vector_swap_double(size_t N, vec_t &v1, vec2_t &v2) {
200  return vector_swap<vec_t,vec2_t,double>(N,v1,v2);
201  }
202 
203  /** \brief Generic swap of two matrices
204 
205  This function swaps the elements of \c v1 and \c v2, one element
206  at a time.
207  */
208  template<class mat_t, class mat2_t, class data_t>
209  void matrix_swap(size_t M, size_t N, mat_t &v1, mat2_t &v2) {
210  data_t temp;
211  for(size_t i=0;i<M;i++) {
212  for(size_t j=0;j<N;j++) {
213  temp=v1[i][j];
214  v1[i][j]=v2[i][j];
215  v2[i][j]=temp;
216  }
217  }
218  return;
219  }
220 
221  /** \brief Generic swap of two matrices
222 
223  This function swaps the elements of \c m1 and \c m2, one element
224  at a time.
225  */
226  template<class mat_t, class mat2_t, class data_t>
227  void matrix_swap_double(size_t M, size_t N, mat_t &m1, mat2_t &m2) {
228  return matrix_swap<mat_t,mat2_t,double>(M,N,m1,m2);
229  }
230 
231  /** \brief Generic swap two elements in a vector
232 
233  This function swaps the element \c i and element \c j of vector
234  \c v1.
235  */
236  template<class vec_t, class data_t>
237  void vector_swap(vec_t &v, size_t i, size_t j) {
238  data_t temp=v[i];
239  v[i]=v[j];
240  v[j]=temp;
241  return;
242  }
243 
244  /** \brief Generic swap two elements in a vector
245 
246  This function swaps the element \c i and element \c j of vector
247  \c v1.
248  */
249  template<class vec_t>
250  void vector_swap_double(vec_t &v, size_t i, size_t j) {
251  return vector_swap<vec_t,double>(v,i,j);
252  }
253 
254  /** \brief Generic swap two elements in a matrix
255 
256  This function swaps the element <tt>(i1,j1)</tt> and
257  element <tt>(i2,j2)</tt> of matrix \c m1.
258  */
259  template<class mat_t, class data_t>
260  void matrix_swap(mat_t &m, size_t i1, size_t j1, size_t i2, size_t j2) {
261  data_t temp=m(i1,j1);
262  m(i1,j1)=m(i2,j2);
263  m(i2,j2)=temp;
264  return;
265  }
266 
267  /** \brief Generic swap two elements in a matrix
268 
269  This function swaps the element \c i and element \c j of matrix
270  \c v1.
271  */
272  template<class mat_t>
273  void matrix_swap_double(mat_t &m, size_t i1, size_t j1,
274  size_t i2, size_t j2) {
275  return matrix_swap<mat_t,double>(m,i1,j1,i2,j2);
276  }
277 
278  /** \brief Generic swap two columns in a matrix
279 
280  This function swaps the element <tt>(i1,j1)</tt> and
281  element <tt>(i2,j2)</tt> of matrix \c m1.
282  */
283  template<class mat_t, class data_t>
284  void matrix_swap_cols(size_t M, mat_t &m, size_t j1, size_t j2) {
285  data_t temp;
286  for(size_t i=0;i<M;i++) {
287  temp=m(i,j1);
288  m(i,j1)=m(i,j2);
289  m(i,j2)=temp;
290  }
291  return;
292  }
293 
294  /** \brief Generic swap two elements in a matrix
295 
296  This function swaps the element \c i and element \c j of matrix
297  \c v1.
298  */
299  template<class mat_t>
300  void matrix_swap_cols_double(size_t M, mat_t &m, size_t j1, size_t j2) {
301  return matrix_swap_cols<mat_t,double>(M,m,j1,j2);
302  }
303 
304  /** \brief Generic swap two columns in a matrix
305 
306  This function swaps the element <tt>(i1,j1)</tt> and
307  element <tt>(i2,j2)</tt> of matrix \c m1.
308  */
309  template<class mat_t, class data_t>
310  void matrix_swap_rows(size_t N, mat_t &m, size_t i1, size_t i2) {
311  data_t temp;
312  for(size_t j=0;j<N;j++) {
313  temp=m(i1,j);
314  m(i1,j)=m(i2,j);
315  m(i2,j)=temp;
316  }
317  return;
318  }
319 
320  /** \brief Generic swap two elements in a matrix
321 
322  This function swaps the element \c i and element \c j of matrix
323  \c v1.
324  */
325  template<class mat_t>
326  void matrix_swap_rows_double(size_t N, mat_t &m, size_t i1, size_t i2) {
327  return matrix_swap_rows<mat_t,double>(N,m,i1,i2);
328  }
329  //@}
330 
331  /// \name Sorting vectors
332  //@{
333  /** \brief Provide a downheap() function for vector_sort()
334  */
335  template<class vec_t, class data_t>
336  void sort_downheap(vec_t &data, size_t n, size_t k) {
337 
338  data_t v=data[k];
339 
340  while (k<=n/2) {
341  size_t j=2*k;
342 
343  if (j<n && data[j] < data[j+1]) j++;
344  if (!(v < data[j])) break;
345  data[k]=data[j];
346  k=j;
347  }
348 
349  data[k]=v;
350  }
351 
352  /** \brief Sort a vector (in increasing order)
353 
354  This is a generic sorting template function using a heapsort
355  algorithm. It will work for any types \c data_t and \c vec_t for
356  which
357  - \c data_t has a non-const version of <tt>operator=</tt>
358  - \c data_t has a less than operator to compare elements
359  - <tt>vec_t::operator[]</tt> returns a non-const reference
360  to an object of type \c data_t
361 
362  In particular, it will work with the STL template class
363  <tt>std::vector</tt>, and arrays and pointers of numeric,
364  character, and string objects.
365 
366  For example,
367  \code
368  std::string list[3]={"dog","cat","fox"};
369  vector_sort<std::string[3],std::string>(3,list);
370  \endcode
371 
372  \note With this function template alone, the user cannot avoid
373  explicitly specifying the template types for this function
374  because there is no parameter of type \c data_t, and function
375  templates cannot handle default template types. For this
376  reason, the function template \ref o2scl::vector_sort_double() was
377  also created which provides the convenience of not requiring
378  the user to specify the vector template type.
379 
380  \note This sorting routine is not stable, i.e. equal elements
381  have arbtrary final ordering
382 
383  \note If \c n is zero, this function will do nothing and will
384  not call the error handler.
385 
386  This works similarly to the GSL function <tt>gsl_sort_vector()</tt>.
387  */
388  template<class vec_t, class data_t>
389  void vector_sort(size_t n, vec_t &data) {
390 
391  size_t N;
392  size_t k;
393 
394  if (n==0) return;
395 
396  N=n-1;
397  k=N/2;
398  k++;
399  do {
400  k--;
401  sort_downheap<vec_t,data_t>(data,N,k);
402  } while (k > 0);
403 
404  while (N > 0) {
405  data_t tmp=data[0];
406  data[0]=data[N];
407  data[N]=tmp;
408  N--;
409  sort_downheap<vec_t,data_t>(data,N,0);
410  }
411 
412  return;
413  }
414 
415  /** \brief Provide a downheap() function for vector_sort_index()
416  */
417  template<class vec_t, class vec_size_t>
418  void sort_index_downheap(size_t N, const vec_t &data, vec_size_t &order,
419  size_t k) {
420 
421  const size_t pki = order[k];
422 
423  while (k <= N / 2) {
424  size_t j = 2 * k;
425 
426  if (j < N && data[order[j]] < data[order[j + 1]]) {
427  j++;
428  }
429 
430  // [GSL] Avoid infinite loop if nan
431  if (!(data[pki] < data[order[j]])) {
432  break;
433  }
434 
435  order[k] = order[j];
436 
437  k = j;
438  }
439 
440  order[k] = pki;
441 
442  return;
443  }
444 
445  /** \brief Create a permutation which sorts a vector (in increasing order)
446 
447  This function takes a vector \c data and arranges a list of
448  indices in \c order, which give a sorted version of the vector.
449  The value <tt>order[i]</tt> gives the index of entry in in \c
450  data which corresponds to the <tt>i</tt>th value in the sorted
451  vector. The vector \c data is unchanged by this function, and
452  the initial values in \c order are ignored. Before calling this
453  function, \c order must already be allocated as a vector of size
454  \c n.
455 
456  For example, after calling this function, a sorted version the
457  vector can be output with
458  \code
459  size_t n=5;
460  double data[5]={3.1,4.1,5.9,2.6,3.5};
461  permutation order(n);
462  vector_sort_index(n,data,order);
463  for(size_t i=0;i<n;i++) {
464  cout << data[order[i]] << endl;
465  }
466  \endcode
467 
468  To create a permutation which stores as its <tt>i</tt>th element,
469  the index of <tt>data[i]</tt> in the sorted vector, you can
470  invert the permutation created by this function.
471 
472  This is a generic sorting template function. It will work for
473  any types \c vec_t and \c vec_size_t for which
474  - \c vec_t has an <tt>operator[]</tt>, and
475  - \c vec_size_t has an <tt>operator[]</tt> which returns
476  a \c size_t .
477  One possible type for \c vec_size_t is \ref o2scl::permutation.
478 
479  This works similarly to the GSL function <tt>gsl_sort_index()</tt>.
480  */
481  template<class vec_t, class vec_size_t>
482  void vector_sort_index(size_t n, const vec_t &data, vec_size_t &order) {
483  size_t N;
484  size_t i, k;
485 
486  if (n == 0) return;
487 
488  // [GSL] Set permutation to identity
489 
490  for (i = 0 ; i < n ; i++) {
491  order[i] = i;
492  }
493 
494  /* [GSL] We have n_data elements, last element is at 'n_data-1',
495  first at '0' Set N to the last element number.
496  */
497  N = n - 1;
498 
499  k = N / 2;
500  // [GSL] Compensate the first use of 'k--'
501  k++;
502  do {
503  k--;
504  sort_index_downheap<vec_t,vec_size_t>(N,data,order,k);
505  } while (k > 0);
506 
507  while (N > 0) {
508 
509  // [GSL] First swap the elements
510  size_t tmp = order[0];
511  order[0] = order[N];
512  order[N] = tmp;
513 
514  // [GSL] Then process the heap
515  N--;
516 
517  sort_index_downheap<vec_t,vec_size_t>(N,data,order,0);
518  }
519 
520  return;
521  }
522 
523  /** \brief Sort a vector of doubles (in increasing order)
524 
525  This function is just a wrapper for
526  \code
527  vector_sort<vec_t,double>(n,data);
528  \endcode
529  See the documentation of \ref o2scl::vector_sort() for more
530  details.
531  */
532  template<class vec_t>
533  void vector_sort_double(size_t n, vec_t &data) {
534  return vector_sort<vec_t,double>(n,data);
535  }
536  //@}
537 
538  /// \name Smallest or largest subset functions
539  //@{
540  /** \brief Find the k smallest entries of a vector
541 
542  Given a vector \c data of size \c n this sets the first \c k
543  entries of the vector \c smallest to the k smallest entries from
544  vector \c data in ascending order. The vector \c smallest must
545  be allocated beforehand to hold at least \c k elements.
546 
547  This works similarly to the GSL function <tt>gsl_sort_smallest()</tt>.
548 
549  \note This \f$ {\cal O}(k N) \f$ algorithm is useful only when
550  \f$ k << N \f$.
551 
552  If \c k is zero, then this function does nothing and
553  returns \ref o2scl::success .
554  */
555  template<class vec_t, class data_t>
556  void vector_smallest(size_t n, vec_t &data, size_t k, vec_t &smallest) {
557  if (k>n) {
558  O2SCL_ERR2("Subset length greater than size in ",
559  "function vector_smallest().",exc_einval);
560  }
561  if (k==0 || n==0) {
562  O2SCL_ERR2("Vector size zero or k zero in ",
563  "function vector_smallest().",exc_einval);
564  }
565 
566  // Take the first element
567  size_t j=1;
568  data_t xbound=data[0];
569  smallest[0]=xbound;
570 
571  // Examine the remaining elements
572  for(size_t i=1;i<n;i++) {
573  data_t xi=data[i];
574  if (j<k) {
575  j++;
576  } else if (xi>=xbound) {
577  continue;
578  }
579  size_t i1;
580  for(i1=j-1;i1>0;i1--) {
581  if (xi>smallest[i1-1]) break;
582  smallest[i1]=smallest[i1-1];
583  }
584  smallest[i1]=xi;
585  xbound=smallest[j-1];
586  }
587  return;
588  }
589 
590  /** \brief Find the k largest entries of a vector
591 
592  Given a vector \c data of size \c n this sets the first \c k
593  entries of the vector \c largest to the k largest entries from
594  vector \c data in descending order. The vector \c largest must
595  be allocated beforehand to hold at least \c k elements.
596 
597  This works similarly to the GSL function <tt>gsl_sort_largest()</tt>.
598 
599  \note This \f$ {\cal O}(k N) \f$ algorithm is useful only when
600  \f$ k << N \f$.
601 
602  If \c k is zero, then this function does nothing and
603  returns \ref o2scl::success .
604  */
605  template<class vec_t, class data_t>
606  void vector_largest(size_t n, vec_t &data, size_t k, vec_t &largest) {
607  if (k>n) {
608  O2SCL_ERR2("Subset length greater than size in ",
609  "function vector_largest().",exc_einval);
610  }
611  if (k==0 || n==0) {
612  O2SCL_ERR2("Vector size zero or k zero in ",
613  "function vector_largest().",exc_einval);
614  }
615 
616  // Take the first element
617  size_t j=1;
618  data_t xbound=data[0];
619  largest[0]=xbound;
620 
621  // Examine the remaining elements
622  for(size_t i=1;i<n;i++) {
623  data_t xi=data[i];
624  if (j<k) {
625  j++;
626  } else if (xi<=xbound) {
627  continue;
628  }
629  size_t i1;
630  for(i1=j-1;i1>0;i1--) {
631  if (xi<largest[i1-1]) break;
632  largest[i1]=largest[i1-1];
633  }
634  largest[i1]=xi;
635  xbound=largest[j-1];
636  }
637  return;
638  }
639  //@}
640 
641  /// \name Vector minimum and maximum functions
642  //@{
643  /** \brief Compute the maximum of the first \c n elements of a vector
644  */
645  template<class vec_t, class data_t>
646  data_t vector_max_value(size_t n, const vec_t &data) {
647 
648  if (n==0) {
649  O2SCL_ERR("Sent size=0 to vector_max_value().",exc_efailed);
650  }
651  data_t max=data[0];
652  for(size_t i=1;i<n;i++) {
653  if (data[i]>max) {
654  max=data[i];
655  }
656  }
657  return max;
658  }
659 
660  /** \brief Compute the index which holds the
661  maximum of the first \c n elements of a vector
662  */
663  template<class vec_t, class data_t>
664  size_t vector_max_index(size_t n, const vec_t &data) {
665 
666  if (n==0) {
667  O2SCL_ERR("Sent size=0 to vector_max_index().",exc_efailed);
668  }
669  data_t max=data[0];
670  size_t ix=0;
671  for(size_t i=1;i<n;i++) {
672  if (data[i]>max) {
673  max=data[i];
674  ix=i;
675  }
676  }
677  return ix;
678  }
679 
680  /** \brief Compute the maximum of the first \c n elements of a vector
681  */
682  template<class vec_t, class data_t>
683  void vector_max(size_t n, const vec_t &data, size_t &index,
684  data_t &val) {
685 
686  if (n==0) {
687  O2SCL_ERR("Sent size=0 to vector_max().",exc_efailed);
688  }
689  val=data[0];
690  index=0;
691  for(size_t i=1;i<n;i++) {
692  if (data[i]>val) {
693  val=data[i];
694  index=i;
695  }
696  }
697  return;
698  }
699 
700  /** \brief Compute the minimum of the first \c n elements of a vector
701  */
702  template<class vec_t, class data_t>
703  data_t vector_min_value(size_t n, const vec_t &data) {
704 
705  if (n==0) {
706  O2SCL_ERR("Sent size=0 to vector_min_value().",exc_efailed);
707  }
708  data_t min=data[0];
709  for(size_t i=1;i<n;i++) {
710  if (data[i]<min) {
711  min=data[i];
712  }
713  }
714  return min;
715  }
716 
717  /** \brief Compute the index which holds the
718  minimum of the first \c n elements of a vector
719  */
720  template<class vec_t, class data_t>
721  size_t vector_min_index(size_t n, const vec_t &data) {
722 
723  if (n==0) {
724  O2SCL_ERR("Sent size=0 to vector_min_index().",exc_efailed);
725  }
726  data_t min=data[0];
727  size_t ix=0;
728  for(size_t i=1;i<n;i++) {
729  if (data[i]<min) {
730  min=data[i];
731  ix=i;
732  }
733  }
734  return ix;
735  }
736 
737  /** \brief Compute the minimum of the first \c n elements of a vector
738  */
739  template<class vec_t, class data_t>
740  void vector_min(size_t n, const vec_t &data, size_t &index,
741  data_t &val) {
742 
743  if (n==0) {
744  O2SCL_ERR("Sent size=0 to vector_min().",exc_efailed);
745  }
746  val=data[0];
747  index=0;
748  for(size_t i=1;i<n;i++) {
749  if (data[i]<val) {
750  val=data[i];
751  index=i;
752  }
753  }
754  return;
755  }
756 
757  /** \brief Compute the minimum and maximum of the first
758  \c n elements of a vector
759  */
760  template<class vec_t, class data_t>
761  void vector_minmax_value(size_t n, vec_t &data,
762  data_t &min, data_t &max) {
763 
764  if (n==0) {
765  O2SCL_ERR("Sent size=0 to vector_min().",exc_efailed);
766  }
767  min=data[0];
768  max=min;
769  for(size_t i=1;i<n;i++) {
770  if (data[i]<min) {
771  min=data[i];
772  }
773  if (data[i]>max) {
774  max=data[i];
775  }
776  }
777  return;
778  }
779 
780  /** \brief Compute the minimum and maximum of the first
781  \c n elements of a vector
782  */
783  template<class vec_t, class data_t>
784  void vector_minmax_index(size_t n, vec_t &data,
785  size_t &ix_min, size_t &ix_max) {
786 
787  if (n==0) {
788  O2SCL_ERR("Sent size=0 to vector_min().",exc_efailed);
789  }
790  data_t min=data[0];
791  data_t max=min;
792  ix_min=0;
793  ix_max=0;
794  for(size_t i=1;i<n;i++) {
795  if (data[i]<min) {
796  min=data[i];
797  ix_min=i;
798  }
799  if (data[i]>max) {
800  max=data[i];
801  ix_max=i;
802  }
803  }
804  return;
805  }
806 
807  /** \brief Compute the minimum and maximum of the first
808  \c n elements of a vector
809  */
810  template<class vec_t, class data_t>
811  void vector_minmax(size_t n, vec_t &data,
812  size_t &ix_min, data_t &min,
813  size_t &ix_max, data_t &max) {
814 
815  if (n==0) {
816  O2SCL_ERR("Sent size=0 to vector_min().",exc_efailed);
817  }
818  min=data[0];
819  max=min;
820  ix_min=0;
821  ix_max=0;
822  for(size_t i=1;i<n;i++) {
823  if (data[i]<min) {
824  min=data[i];
825  ix_min=i;
826  }
827  if (data[i]>max) {
828  max=data[i];
829  ix_max=i;
830  }
831  }
832  return;
833  }
834  //@}
835 
836  /// \name Minima and maxima of vectors through quadratic fit
837  //@{
838  /** \brief Maximum of vector by quadratic fit
839  */
840  template<class vec_t, class data_t>
841  data_t vector_max_quad(size_t n, const vec_t &data) {
842  size_t ix=vector_max_index<vec_t,data_t>(n,data);
843  if (ix==0) {
844  return quadratic_extremum_y<data_t>(0,1,2,data[0],data[1],data[2]);
845  } else if (ix==n-1) {
846  return quadratic_extremum_y<data_t>
847  (n-3,n-2,n-1,data[n-3],data[n-2],data[n-1]);
848  }
849  return quadratic_extremum_y<data_t>
850  (ix-1,ix,ix+1,data[ix-1],data[ix],data[ix+1]);
851  }
852 
853  /** \brief Maximum of vector by quadratic fit
854  */
855  template<class vec_t, class data_t>
856  data_t vector_max_quad(size_t n, const vec_t &x, const vec_t &y) {
857  size_t ix=vector_max_index<vec_t,data_t>(n,y);
858  if (ix==0 || ix==n-1) return y[ix];
859  return quadratic_extremum_y<data_t>(x[ix-1],x[ix],x[ix+1],
860  y[ix-1],y[ix],y[ix+1]);
861  }
862 
863  /** \brief Location of vector maximum by quadratic fit
864  */
865  template<class vec_t, class data_t>
866  data_t vector_max_quad_loc(size_t n, const vec_t &x, const vec_t &y) {
867  size_t ix=vector_max_index<vec_t,data_t>(n,y);
868  if (ix==0 || ix==n-1) return y[ix];
869  return quadratic_extremum_x<data_t>(x[ix-1],x[ix],x[ix+1],
870  y[ix-1],y[ix],y[ix+1]);
871  }
872 
873  /** \brief Minimum of vector by quadratic fit
874  */
875  template<class vec_t, class data_t>
876  data_t vector_min_quad(size_t n, const vec_t &data) {
877  size_t ix=vector_min_index<vec_t,data_t>(n,data);
878  if (ix==0) {
879  return quadratic_extremum_y<data_t>(0,1,2,data[0],data[1],data[2]);
880  } else if (ix==n-1) {
881  return quadratic_extremum_y<data_t>
882  (n-3,n-2,n-1,data[n-3],data[n-2],data[n-1]);
883  }
884  return quadratic_extremum_y<data_t>
885  (ix-1,ix,ix+1,data[ix-1],data[ix],data[ix+1]);
886  }
887 
888  /** \brief Minimum of vector by quadratic fit
889  */
890  template<class vec_t, class data_t>
891  data_t vector_min_quad(size_t n, const vec_t &x, const vec_t &y) {
892  size_t ix=vector_min_index<vec_t,data_t>(n,y);
893  if (ix==0 || ix==n-1) return y[ix];
894  return quadratic_extremum_y<data_t>(x[ix-1],x[ix],x[ix+1],
895  y[ix-1],y[ix],y[ix+1]);
896  }
897 
898  /** \brief Location of vector minimum by quadratic fit
899  */
900  template<class vec_t, class data_t>
901  data_t vector_min_quad_loc(size_t n, const vec_t &x, const vec_t &y) {
902  size_t ix=vector_min_index<vec_t,data_t>(n,y);
903  if (ix==0 || ix==n-1) return y[ix];
904  return quadratic_extremum_x<data_t>(x[ix-1],x[ix],x[ix+1],
905  y[ix-1],y[ix],y[ix+1]);
906  }
907  //@}
908 
909  /// \name Matrix minimum and maximum functions
910  //@{
911  /** \brief Compute the maximum of the lower-left part of a matrix
912  */
913  template<class mat_t, class data_t>
914  data_t matrix_max(size_t m, const size_t n, const mat_t &data) {
915 
916  if (n==0 || m==0) {
917  O2SCL_ERR("Sent size=0 to matrix_max().",exc_efailed);
918  }
919  data_t max=data(0,0);
920  for(size_t i=0;i<m;i++) {
921  for(size_t j=0;j<n;j++) {
922  if (data(i,j)>max) {
923  max=data(i,j);
924  }
925  }
926  }
927  return max;
928  }
929 
930  /** \brief Compute the maximum of a matrix
931  */
932  template<class mat_t, class data_t> data_t matrix_max(const mat_t &data) {
933  size_t m=data.size1();
934  size_t n=data.size2();
935  if (n==0 || m==0) {
936  O2SCL_ERR("Sent size=0 to matrix_max().",exc_efailed);
937  }
938  data_t max=data(0,0);
939  for(size_t i=0;i<n;i++) {
940  for(size_t j=0;j<m;j++) {
941  if (data(i,j)>max) {
942  max=data(i,j);
943  }
944  }
945  }
946  return max;
947  }
948 
949  /** \brief Compute the maximum of a matrix and return
950  the indices of the maximum element
951  */
952  template<class mat_t, class data_t>
953  void matrix_max_index(size_t n, const size_t m, const mat_t &data,
954  size_t &i_max, size_t &j_max, data_t &max) {
955 
956  if (n==0 || m==0) {
957  O2SCL_ERR("Sent size=0 to matrix_max().",exc_efailed);
958  }
959  max=data(0,0);
960  i_max=0;
961  j_max=0;
962  for(size_t i=0;i<n;i++) {
963  for(size_t j=0;j<m;j++) {
964  if (data(i,j)>max) {
965  max=data(i,j);
966  i_max=i;
967  j_max=j;
968  }
969  }
970  }
971  return;
972  }
973 
974  /** \brief Compute the minimum of a matrix
975  */
976  template<class mat_t, class data_t>
977  data_t matrix_min(size_t n, const size_t m, const mat_t &data) {
978 
979  if (n==0 || m==0) {
980  O2SCL_ERR("Sent size=0 to matrix_min().",exc_efailed);
981  }
982  data_t min=data(0,0);
983  for(size_t i=0;i<n;i++) {
984  for(size_t j=0;j<m;j++) {
985  if (data(i,j)<min) {
986  min=data(i,j);
987  }
988  }
989  }
990  return min;
991  }
992 
993  /** \brief Compute the minimum of a matrix and return
994  the indices of the minimum element
995  */
996  template<class mat_t, class data_t>
997  void matrix_min_index(size_t n, const size_t m, const mat_t &data,
998  size_t &i_min, size_t &j_min, data_t &min) {
999 
1000  if (n==0 || m==0) {
1001  O2SCL_ERR("Sent size=0 to matrix_min().",exc_efailed);
1002  }
1003  min=data(0,0);
1004  i_min=0;
1005  j_min=0;
1006  for(size_t i=0;i<n;i++) {
1007  for(size_t j=0;j<m;j++) {
1008  if (data(i,j)<min) {
1009  min=data(i,j);
1010  i_min=i;
1011  j_min=j;
1012  }
1013  }
1014  }
1015  return;
1016  }
1017 
1018  /** \brief Compute the minimum and maximum of a matrix
1019  */
1020  template<class mat_t, class data_t>
1021  void matrix_minmax(size_t n, const size_t m, const mat_t &data,
1022  data_t &min, data_t &max) {
1023 
1024  if (n==0 || m==0) {
1025  O2SCL_ERR("Sent size=0 to matrix_min().",exc_efailed);
1026  }
1027  min=data(0,0);
1028  max=data(0,0);
1029  for(size_t i=0;i<n;i++) {
1030  for(size_t j=0;j<m;j++) {
1031  if (data(i,j)<min) {
1032  min=data(i,j);
1033  } else if (data(i,j)>max) {
1034  max=data(i,j);
1035  }
1036  }
1037  }
1038  return;
1039  }
1040 
1041  /** \brief Compute the minimum and maximum of a matrix and
1042  return their locations
1043  */
1044  template<class mat_t, class data_t>
1045  void matrix_minmax_index(size_t n, const size_t m, const mat_t &data,
1046  size_t &i_min, size_t &j_min, data_t &min,
1047  size_t &i_max, size_t &j_max, data_t &max) {
1048 
1049  if (n==0 || m==0) {
1050  O2SCL_ERR2("Sent size=0 to function ",
1051  "matrix_minmax_index().",exc_efailed);
1052  }
1053  min=data(0,0);
1054  i_min=0;
1055  j_min=0;
1056  max=data(0,0);
1057  i_max=0;
1058  j_max=0;
1059  for(size_t i=0;i<n;i++) {
1060  for(size_t j=0;j<m;j++) {
1061  if (data(i,j)<min) {
1062  min=data(i,j);
1063  i_min=i;
1064  j_min=j;
1065  } else if (data(i,j)>max) {
1066  max=data(i,j);
1067  i_max=i;
1068  j_max=j;
1069  }
1070  }
1071  }
1072  return;
1073  }
1074  //@}
1075 
1076  /// \name Searching vectors and matrices
1077  //@{
1078  /** \brief Lookup element \c x0 in vector \c x of length \c n
1079 
1080  This function finds the element in vector \c x which is closest
1081  to \c x0. It ignores all elements in \c x which are not finite.
1082  If the vector is empty (i.e. \c n is zero), or if all of the
1083  elements in \c x are not finite, then the error handler will be
1084  called.
1085 
1086  This function works for all classes \c vec_t where an operator[]
1087  is defined which returns a double (either as a value or a
1088  reference).
1089  */
1090  template<class vec_t>
1091  size_t vector_lookup(size_t n, const vec_t &x, double x0) {
1092  if (n==0) {
1093  O2SCL_ERR("Empty vector in function vector_lookup().",
1094  exc_einval);
1095  return 0;
1096  }
1097  size_t row=0, i=0;
1098  while(!o2scl::is_finite(x[i]) && i<n-1) i++;
1099  if (i==n-1) {
1100  O2SCL_ERR2("Entire vector not finite in ",
1101  "function vector_lookup()",exc_einval);
1102  return 0;
1103  }
1104  double best=x[i], bdiff=fabs(x[i]-x0);
1105  for(;i<n;i++) {
1106  if (o2scl::is_finite(x[i]) && fabs(x[i]-x0)<bdiff) {
1107  row=i;
1108  best=x[i];
1109  bdiff=fabs(x[i]-x0);
1110  }
1111  }
1112  return row;
1113  }
1114 
1115  /** \brief Lookup an element in a matrix
1116 
1117  Return the location <tt>(i,j)</tt> of the element closest to
1118  \c x0.
1119  */
1120  template<class mat_t>
1121  void matrix_lookup(size_t m, size_t n, const mat_t &A,
1122  double x0, size_t &i, size_t &j) {
1123  if (m==0 || n==0) {
1124  O2SCL_ERR("Empty matrix in matrix_lookup().",
1125  exc_einval);
1126  }
1127  double dist=0.0;
1128  bool found_one=false;
1129  for(size_t i2=0;i2<m;i2++) {
1130  for(size_t j2=0;j2<n;j2++) {
1131  if (o2scl::is_finite(A(i,j))) {
1132  if (found_one==false) {
1133  dist=fabs(A(i,j)-x0);
1134  found_one=true;
1135  i=i2;
1136  j=j2;
1137  } else {
1138  if (fabs(A(i,j)-x0)<dist) {
1139  dist=fabs(A(i,j)-x0);
1140  i=i2;
1141  j=j2;
1142  }
1143  }
1144  }
1145  }
1146  }
1147  if (found_one==false) {
1148  O2SCL_ERR2("Entire matrix not finite in ",
1149  "function matrix_lookup()",exc_einval);
1150  }
1151  return;
1152  }
1153 
1154  /** \brief Binary search a part of an increasing vector for
1155  <tt>x0</tt>.
1156 
1157  This function performs a binary search of between
1158  <tt>x[lo]</tt> and <tt>x[hi]</tt>. It returns
1159  - \c lo if \c x0 < <tt>x[lo]</tt>
1160  - \c i if <tt>x[i]</tt> <= \c x0 < <tt>x[i+2]</tt>
1161  for \c lo <= \c i < \c hi
1162  - \c hi-1 if \c x0 >= \c <tt>x[hi-1]</tt>
1163 
1164  This function is designed to find the interval containing \c x0,
1165  not the index of the element closest to x0. To perform the
1166  latter operation, you can use \ref vector_lookup().
1167 
1168  The element at <tt>x[hi]</tt> is never referenced by this
1169  function. The parameter \c hi can be either the index of the
1170  last element (e.g. <tt>n-1</tt> for a vector of size <tt>n</tt>
1171  with starting index <tt>0</tt>), or the index of one element
1172  (e.g. <tt>n</tt> for a vector of size <tt>n</tt> and a starting
1173  index <tt>0</tt>) for a depending on whether or not the user
1174  wants to allow the function to return the index of the last
1175  element.
1176 
1177  This function operates in the same way as
1178  <tt>gsl_interp_bsearch()</tt>.
1179 
1180  The operation of this function is undefined if the data is
1181  not strictly monotonic, i.e. if some of the data elements are
1182  equal.
1183 
1184  This function will call the error handler if \c lo is
1185  greater than \c hi.
1186  */
1187  template<class vec_t, class data_t>
1188  size_t vector_bsearch_inc(const data_t x0, const vec_t &x,
1189  size_t lo, size_t hi) {
1190  if (lo>hi) {
1191  O2SCL_ERR2("Low and high indexes backwards in ",
1192  "function vector_bsearch_inc().",exc_einval);
1193  }
1194  while (hi>lo+1) {
1195  size_t i=(hi+lo)/2;
1196  if (x[i]>x0) {
1197  hi=i;
1198  } else {
1199  lo=i;
1200  }
1201  }
1202 
1203  return lo;
1204  }
1205 
1206  /** \brief Binary search a part of an decreasing vector for
1207  <tt>x0</tt>.
1208 
1209  This function performs a binary search of between
1210  <tt>x[lo]</tt> and <tt>x[hi]</tt> (inclusive). It returns
1211  - \c lo if \c x0 > <tt>x[lo]</tt>
1212  - \c i if <tt>x[i]</tt> >= \c x0 > <tt>x[i+1]</tt>
1213  for \c lo <= \c i < \c hi
1214  - \c hi-1 if \c x0 <= \c <tt>x[hi-1]</tt>
1215 
1216  The element at <tt>x[hi]</tt> is never referenced by this
1217  function. The parameter \c hi can be either the index of the
1218  last element (e.g. <tt>n-1</tt> for a vector of size <tt>n</tt>
1219  with starting index <tt>0</tt>), or the index of one element
1220  (e.g. <tt>n</tt> for a vector of size <tt>n</tt> and a starting
1221  index <tt>0</tt>) for a depending on whether or not the user
1222  wants to allow the function to return the index of the last
1223  element.
1224 
1225  The operation of this function is undefined if the data is
1226  not strictly monotonic, i.e. if some of the data elements are
1227  equal.
1228 
1229  This function will call the error handler if \c lo is
1230  greater than \c hi.
1231  */
1232  template<class vec_t, class data_t>
1233  size_t vector_bsearch_dec(const data_t x0, const vec_t &x,
1234  size_t lo, size_t hi) {
1235  if (lo>hi) {
1236  O2SCL_ERR2("Low and high indexes backwards in ",
1237  "function vector_bsearch_dec().",exc_einval);
1238  }
1239  while (hi>lo+1) {
1240  size_t i=(hi+lo)/2;
1241  if (x[i]<x0) {
1242  hi=i;
1243  } else {
1244  lo=i;
1245  }
1246  }
1247 
1248  return lo;
1249  }
1250 
1251  /** \brief Binary search a part of a monotonic vector for
1252  <tt>x0</tt>.
1253 
1254  This wrapper just calls \ref o2scl::vector_bsearch_inc() or
1255  \ref o2scl::vector_bsearch_dec() depending on the ordering
1256  of \c x.
1257  */
1258  template<class vec_t, class data_t>
1259  size_t vector_bsearch(const data_t x0, const vec_t &x,
1260  size_t lo, size_t hi) {
1261  if (x[lo]<x[hi-1]) {
1262  return vector_bsearch_inc<vec_t,data_t>(x0,x,lo,hi);
1263  }
1264  return vector_bsearch_dec<vec_t,data_t>(x0,x,lo,hi);
1265  }
1266  //@}
1267 
1268  /// \name Miscellaneous mathematical functions
1269  //@{
1270  /** \brief Compute the sum of the first \c n elements of a vector
1271 
1272  If \c n is zero, this will return 0 without throwing
1273  an exception.
1274  */
1275  template<class vec_t, class data_t>
1276  data_t vector_sum(size_t n, vec_t &data) {
1277 
1278  data_t sum=0.0;
1279  for(size_t i=0;i<n;i++) {
1280  sum+=data[i];
1281  }
1282  return sum;
1283  }
1284 
1285  /** \brief Compute the sum of all the elements of a vector
1286 
1287  If the vector has zero size, this will return 0 without
1288  throwing an exception.
1289  */
1290  template<class vec_t, class data_t> data_t vector_sum(vec_t &data) {
1291  data_t sum=0.0;
1292  for(size_t i=0;i<data.size();i++) {
1293  sum+=data[i];
1294  }
1295  return sum;
1296  }
1297 
1298  /** \brief Compute the norm of a vector of floating-point
1299  (single or double precision) numbers
1300 
1301  This function is a more generic version of
1302  \ref o2scl_cblas::dnrm2 .
1303  */
1304  template<class vec_t, class data_t>
1305  data_t vector_norm(size_t n, const vec_t &x) {
1306 
1307  data_t scale = 0.0;
1308  data_t ssq = 1.0;
1309 
1310  if (n <= 0) {
1311  return 0.0;
1312  } else if (n == 1) {
1313  return fabs(x[0]);
1314  }
1315 
1316  for (size_t i = 0; i < n; i++) {
1317  const data_t xx = x[i];
1318 
1319  if (xx != 0.0) {
1320  const data_t ax = fabs(xx);
1321 
1322  if (scale < ax) {
1323  ssq = 1.0 + ssq * (scale / ax) * (scale / ax);
1324  scale = ax;
1325  } else {
1326  ssq += (ax / scale) * (ax / scale);
1327  }
1328  }
1329 
1330  }
1331 
1332  return scale * sqrt(ssq);
1333  }
1334  //@}
1335 
1336  /// \name Other vector and matrix functions
1337  //@{
1338  /** \brief "Rotate" a vector so that the kth element is now the beginning
1339 
1340  This is a generic template function which will work for
1341  any types \c data_t and \c vec_t for which
1342  - \c data_t has an <tt>operator=</tt>
1343  - <tt>vec_t::operator[]</tt> returns a reference
1344  to an object of type \c data_t
1345 
1346  This function is used, for example, in \ref o2scl::pinside.
1347 
1348  \note This function is not the same as a Givens rotation,
1349  which is typically referred to in BLAS routines as <tt>drot()</tt>.
1350  */
1351  template<class vec_t, class data_t>
1352  void vector_rotate(size_t n, vec_t &data, size_t k) {
1353 
1354  data_t *tmp=new data_t[n];
1355  for(size_t i=0;i<n;i++) {
1356  tmp[i]=data[(i+k)%n];
1357  }
1358  for(size_t i=0;i<n;i++) {
1359  data[i]=tmp[i];
1360  }
1361  delete[] tmp;
1362 
1363  return;
1364  }
1365 
1366  /** \brief Reverse a vector
1367 
1368  If \c n is zero, this function will silently do nothing.
1369  */
1370  template<class vec_t, class data_t>
1371  void vector_reverse(size_t n, vec_t &data) {
1372  data_t tmp;
1373 
1374  for(size_t i=0;i<n/2;i++) {
1375  tmp=data[n-1-i];
1376  data[n-1-i]=data[i];
1377  data[i]=tmp;
1378  }
1379  return;
1380  }
1381 
1382  /** \brief Reverse a vector
1383 
1384  If \c n is zero, this function will silently do nothing.
1385  */
1386  template<class vec_t, class data_t>
1387  void vector_reverse(vec_t &data) {
1388  data_t tmp;
1389  size_t n=data.size();
1390 
1391  for(size_t i=0;i<n/2;i++) {
1392  tmp=data[n-1-i];
1393  data[n-1-i]=data[i];
1394  data[i]=tmp;
1395  }
1396  return;
1397  }
1398 
1399  /** \brief Construct a row of a matrix
1400 
1401  This class template works with combinations of ublas
1402  <tt>matrix</tt> and <tt>matrix_row</tt> objects,
1403  <tt>arma::mat</tt> and <tt>arma::rowvec</tt>, and
1404  <tt>Eigen::MatrixXd</tt> and <tt>Eigen::VectorXd</tt>.
1405 
1406  \note When calling this function with ublas objects, the
1407  namespace prefix <tt>"o2scl::"</tt> must often be specified,
1408  otherwise some compilers will use argument dependent lookup and
1409  get (justifiably) confused with matrix_row in the ublas
1410  namespace.
1411 
1412  \note The template parameters must be explicitly specified
1413  when calling this template function.
1414  */
1415  template<class mat_t, class mat_row_t>
1416  mat_row_t matrix_row(mat_t &M, size_t row) {
1417  return mat_row_t(M,row);
1418  }
1419 
1420  /** \brief Generic object which represents a row of a matrix
1421 
1422  \note This class is experimental.
1423  */
1424  template<class mat_t> class matrix_row_gen {
1425  public:
1426  mat_t &m_;
1427  size_t row_;
1428  matrix_row_gen(mat_t &m, size_t row) : m_(m), row_(row) {
1429  }
1430  double &operator[](size_t i) {
1431  return m_(row_,i);
1432  }
1433  const double &operator[](size_t i) const {
1434  return m_(row_,i);
1435  }
1436  };
1437 
1438  /** \brief Construct a column of a matrix
1439 
1440  This class template works with combinations of ublas
1441  <tt>matrix</tt> and <tt>matrix_column</tt> objects,
1442  <tt>arma::mat</tt> and <tt>arma::colvec</tt>, and
1443  <tt>Eigen::MatrixXd</tt> and <tt>Eigen::VectorXd</tt>.
1444 
1445  \note When calling this function with ublas objects, the
1446  namespace prefix <tt>"o2scl::"</tt> must often be specified,
1447  otherwise some compilers will use argument dependent lookup and
1448  get (justifiably) confused with matrix_column in the ublas
1449  namespace.
1450 
1451  \note The template parameters must be explicitly specified
1452  when calling this template function.
1453  */
1454  template<class mat_t, class mat_column_t>
1455  mat_column_t matrix_column(mat_t &M, size_t column) {
1456  return mat_column_t(M,column);
1457  }
1458 
1459  /** \brief Generic object which represents a column of a matrix
1460 
1461  \note This class is experimental.
1462  */
1463  template<class mat_t> class matrix_column_gen {
1464  public:
1465  mat_t &m_;
1466  size_t column_;
1467  matrix_column_gen(mat_t &m, size_t column) : m_(m), column_(column) {
1468  }
1469  double &operator[](size_t i) {
1470  return m_(i,column_);
1471  }
1472  const double &operator[](size_t i) const {
1473  return m_(i,column_);
1474  }
1475  };
1476 
1477  /** \brief Output a vector to a stream
1478 
1479  No trailing space is output after the last element, and an
1480  endline is output only if \c endline is set to \c true. If the
1481  parameter \c n is zero, this function silently does nothing.
1482 
1483  Note that the \o2 vector classes also have their own
1484  \c operator<<() defined for them.
1485 
1486  This works with any class <tt>vec_t</tt> which has an operator[]
1487  which returns either the value of or a reference to the ith
1488  element and the element type has its own output operator which
1489  has been defined.
1490  */
1491  template<class vec_t>
1492  void vector_out(std::ostream &os, size_t n, const vec_t &v,
1493  bool endline=false) {
1494 
1495  // This next line is important since n-1 is not well-defined if n=0
1496  if (n==0) return;
1497 
1498  for(size_t i=0;i<n-1;i++) os << v[i] << " ";
1499  os << v[n-1];
1500  if (endline) os << std::endl;
1501  return;
1502  }
1503 
1504  /** \brief Output a vector to a stream
1505 
1506  No trailing space is output after the last element, and an
1507  endline is output only if \c endline is set to \c true. If the
1508  parameter \c n is zero, this function silently does nothing.
1509 
1510  Note that the \o2 vector classes also have their own
1511  \c operator<<() defined for them.
1512 
1513  This works with any class <tt>vec_t</tt> which has an operator[]
1514  which returns either the value of or a reference to the ith
1515  element and the element type has its own output operator which
1516  has been defined.
1517  */
1518  template<class vec_t>
1519  void vector_out(std::ostream &os, const vec_t &v, bool endline=false) {
1520 
1521  size_t n=v.size();
1522 
1523  // This next line is important since n-1 is not well-defined if n=0
1524  if (n==0) return;
1525 
1526  for(size_t i=0;i<n-1;i++) os << v[i] << " ";
1527  os << v[n-1];
1528  if (endline) os << std::endl;
1529  return;
1530  }
1531 
1532  /** \brief Fill a vector with a specified grid
1533  */
1534  template<class vec_t, class data_t>
1535  void vector_grid(uniform_grid<data_t> g, vec_t &v) {
1536  g.template vector<vec_t>(v);
1537  return;
1538  }
1539 
1540  /// Set a matrix to unity on the diagonal and zero otherwise
1541  template<class mat_t>
1542  void matrix_set_identity(size_t M, size_t N, mat_t &m) {
1543  for(size_t i=0;i<M;i++) {
1544  for(size_t j=0;j<N;j++) {
1545  if (i==j) m(i,j)=1.0;
1546  else m(i,j)=0.0;
1547  }
1548  }
1549  }
1550  //@}
1551 
1552 }
1553 
1554 #if defined (O2SCL_COND_FLAG) || defined (DOXYGEN)
1555 
1556 #if defined (O2SCL_ARMA) || defined (DOXYGEN)
1557 #include <armadillo>
1558 namespace o2scl {
1559 
1560  /// \name Armadillo specializations
1561  //@{
1562  /// Armadillo version of \ref matrix_max()
1563  double matrix_max(const arma::mat &data);
1564 
1565  /// Armadillo version of \ref matrix_row()
1566  template<> arma::subview_row<double>
1567  matrix_row<arma::mat,arma::subview_row<double> >
1568  (arma::mat &M, size_t row);
1569 
1570  /// Armadillo version of \ref matrix_column()
1571  template<> arma::subview_col<double>
1572  matrix_column<arma::mat,arma::subview_col<double> >
1573  (arma::mat &M, size_t column);
1574  //@}
1575 
1576 }
1577 
1578 #endif
1579 
1580 #if defined (O2SCL_EIGEN) || defined (DOXYGEN)
1581 #include <Eigen/Dense>
1582 
1583 namespace o2scl {
1584 
1585  /// \name Eigen specializations
1586  //@{
1587  /// Eigen version of \ref matrix_max()
1588  double matrix_max(const Eigen::MatrixXd &data);
1589 
1590  /// Eigen version of \ref matrix_row()
1591  template<> Eigen::MatrixXd::RowXpr
1592  matrix_row<Eigen::MatrixXd,Eigen::MatrixXd::RowXpr>
1593  (Eigen::MatrixXd &M, size_t row);
1594 
1595  /// Eigen version of \ref matrix_column()
1596  template<> Eigen::MatrixXd::ColXpr
1597  matrix_column<Eigen::MatrixXd,Eigen::MatrixXd::ColXpr>
1598  (Eigen::MatrixXd &M, size_t column);
1599  //@}
1600 
1601 }
1602 
1603 #endif
1604 
1605 #else
1606 
1607 #include <o2scl/vector_special.h>
1608 
1609 // End of "#if defined (O2SCL_COND_FLAG) || defined (DOXYGEN)"
1610 #endif
1611 
1612 #ifdef DOXYGEN
1613 /** \brief Placeholder documentation of some related Boost objects
1614 */
1615 namespace boost {
1616  /** \brief Documentation of Boost::numeric objects
1617  */
1618  namespace numeric {
1619  /** \brief Documentation of uBlas objects
1620  */
1621  namespace ublas {
1622  /** \brief The default vector type from uBlas
1623 
1624  The uBlas types aren't documented here, but the full documentation
1625  is available at
1626  http://www.boost.org/doc/libs/release/libs/numeric/ublas/doc/index.htm
1627 
1628  Internally in \o2, this is often typedef'd using
1629  \code
1630  typedef boost::numeric::ublas::vector<double> ubvector;
1631  typedef boost::numeric::ublas::vector<size_t> ubvector_size_t;
1632  typedef boost::numeric::ublas::vector<int> ubvector_int;
1633  \endcode
1634 
1635  This is documented in \ref vector.h .
1636  */
1637  template<class T, class A> class vector {
1638  };
1639  /** \brief The default matrix type from uBlas
1640 
1641  The uBlas types aren't documented here, but the full documentation
1642  is available at
1643  http://www.boost.org/doc/libs/release/libs/numeric/ublas/doc/index.htm
1644 
1645  Internally in \o2, this is often typedef'd using
1646  \code
1647  typedef boost::numeric::ublas::matrix<double> ubmatrix;
1648  typedef boost::numeric::ublas::matrix<size_t> ubmatrix_size_t;
1649  typedef boost::numeric::ublas::matrix<int> ubmatrix_int;
1650  \endcode
1651 
1652  This is documented in \ref vector.h .
1653  */
1654  template<class T, class F, class A> class matrix {
1655  };
1656  }
1657  }
1658 }
1659 // End of "#ifdef DOXYGEN"
1660 #endif
1661 
1662 // End of "#ifndef O2SCL_VECTOR_H"
1663 #endif
data_t vector_min_quad(size_t n, const vec_t &data)
Minimum of vector by quadratic fit.
Definition: vector.h:876
size_t vector_lookup(size_t n, const vec_t &x, double x0)
Lookup element x0 in vector x of length n.
Definition: vector.h:1091
size_t vector_min_index(size_t n, const vec_t &data)
Compute the index which holds the minimum of the first n elements of a vector.
Definition: vector.h:721
data_t vector_min_value(size_t n, const vec_t &data)
Compute the minimum of the first n elements of a vector.
Definition: vector.h:703
data_t vector_max_quad_loc(size_t n, const vec_t &x, const vec_t &y)
Location of vector maximum by quadratic fit.
Definition: vector.h:866
data_t vector_min_quad_loc(size_t n, const vec_t &x, const vec_t &y)
Location of vector minimum by quadratic fit.
Definition: vector.h:901
void matrix_swap_rows(size_t N, mat_t &m, size_t i1, size_t i2)
Generic swap two columns in a matrix.
Definition: vector.h:310
size_t vector_bsearch_dec(const data_t x0, const vec_t &x, size_t lo, size_t hi)
Binary search a part of an decreasing vector for x0.
Definition: vector.h:1233
Generic object which represents a column of a matrix.
Definition: vector.h:1463
void matrix_minmax(size_t n, const size_t m, const mat_t &data, data_t &min, data_t &max)
Compute the minimum and maximum of a matrix.
Definition: vector.h:1021
size_t vector_bsearch_inc(const data_t x0, const vec_t &x, size_t lo, size_t hi)
Binary search a part of an increasing vector for x0.
Definition: vector.h:1188
bool is_finite(double x)
Return false if x is infinite or not a number.
invalid argument supplied by user
Definition: err_hnd.h:59
Generic object which represents a row of a matrix.
Definition: vector.h:1424
void vector_reverse(size_t n, vec_t &data)
Reverse a vector.
Definition: vector.h:1371
void vector_rotate(size_t n, vec_t &data, size_t k)
"Rotate" a vector so that the kth element is now the beginning
Definition: vector.h:1352
void vector_swap_double(size_t N, vec_t &v1, vec2_t &v2)
Generic swap of of the first N elements of two double-precision vectors.
Definition: vector.h:199
The default matrix type from uBlas.
Definition: vector.h:1654
void vector_min(size_t n, const vec_t &data, size_t &index, data_t &val)
Compute the minimum of the first n elements of a vector.
Definition: vector.h:740
generic failure
Definition: err_hnd.h:61
data_t vector_sum(size_t n, vec_t &data)
Compute the sum of the first n elements of a vector.
Definition: vector.h:1276
void vector_swap(size_t N, vec_t &v1, vec2_t &v2)
Swap the first N elements of two vectors.
Definition: vector.h:167
void vector_largest(size_t n, vec_t &data, size_t k, vec_t &largest)
Find the k largest entries of a vector.
Definition: vector.h:606
void matrix_swap_double(size_t M, size_t N, mat_t &m1, mat2_t &m2)
Generic swap of two matrices.
Definition: vector.h:227
void vector_sort_index(size_t n, const vec_t &data, vec_size_t &order)
Create a permutation which sorts a vector (in increasing order)
Definition: vector.h:482
void matrix_swap_cols(size_t M, mat_t &m, size_t j1, size_t j2)
Generic swap two columns in a matrix.
Definition: vector.h:284
void matrix_copy(mat_t &src, mat2_t &dest)
Simple generic matrix copy.
Definition: vector.h:125
data_t vector_max_value(size_t n, const vec_t &data)
Compute the maximum of the first n elements of a vector.
Definition: vector.h:646
#define O2SCL_ERR2(d, d2, n)
Set an error, two-string version.
Definition: err_hnd.h:281
data_t matrix_min(size_t n, const size_t m, const mat_t &data)
Compute the minimum of a matrix.
Definition: vector.h:977
void vector_minmax_value(size_t n, vec_t &data, data_t &min, data_t &max)
Compute the minimum and maximum of the first n elements of a vector.
Definition: vector.h:761
void matrix_set_identity(size_t M, size_t N, mat_t &m)
Set a matrix to unity on the diagonal and zero otherwise.
Definition: vector.h:1542
data_t vector_max_quad(size_t n, const vec_t &data)
Maximum of vector by quadratic fit.
Definition: vector.h:841
mat_column_t matrix_column(mat_t &M, size_t column)
Construct a column of a matrix.
Definition: vector.h:1455
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
Definition: err_hnd.h:273
void matrix_max_index(size_t n, const size_t m, const mat_t &data, size_t &i_max, size_t &j_max, data_t &max)
Compute the maximum of a matrix and return the indices of the maximum element.
Definition: vector.h:953
mat_row_t matrix_row(mat_t &M, size_t row)
Construct a row of a matrix.
Definition: vector.h:1416
void vector_out(std::ostream &os, size_t n, const vec_t &v, bool endline=false)
Output a vector to a stream.
Definition: vector.h:1492
void vector_smallest(size_t n, vec_t &data, size_t k, vec_t &smallest)
Find the k smallest entries of a vector.
Definition: vector.h:556
void vector_grid(uniform_grid< data_t > g, vec_t &v)
Fill a vector with a specified grid.
Definition: vector.h:1535
void vector_minmax(size_t n, vec_t &data, size_t &ix_min, data_t &min, size_t &ix_max, data_t &max)
Compute the minimum and maximum of the first n elements of a vector.
Definition: vector.h:811
data_t vector_norm(size_t n, const vec_t &x)
Compute the norm of a vector of floating-point (single or double precision) numbers.
Definition: vector.h:1305
size_t vector_max_index(size_t n, const vec_t &data)
Compute the index which holds the maximum of the first n elements of a vector.
Definition: vector.h:664
void vector_max(size_t n, const vec_t &data, size_t &index, data_t &val)
Compute the maximum of the first n elements of a vector.
Definition: vector.h:683
void vector_minmax_index(size_t n, vec_t &data, size_t &ix_min, size_t &ix_max)
Compute the minimum and maximum of the first n elements of a vector.
Definition: vector.h:784
data_t matrix_max(size_t m, const size_t n, const mat_t &data)
Compute the maximum of the lower-left part of a matrix.
Definition: vector.h:914
A class representing a uniform linear or logarithmic grid.
Definition: uniform_grid.h:38
size_t vector_bsearch(const data_t x0, const vec_t &x, size_t lo, size_t hi)
Binary search a part of a monotonic vector for x0.
Definition: vector.h:1259
void sort_index_downheap(size_t N, const vec_t &data, vec_size_t &order, size_t k)
Provide a downheap() function for vector_sort_index()
Definition: vector.h:418
void matrix_minmax_index(size_t n, const size_t m, const mat_t &data, size_t &i_min, size_t &j_min, data_t &min, size_t &i_max, size_t &j_max, data_t &max)
Compute the minimum and maximum of a matrix and return their locations.
Definition: vector.h:1045
void matrix_swap_cols_double(size_t M, mat_t &m, size_t j1, size_t j2)
Generic swap two elements in a matrix.
Definition: vector.h:300
void vector_copy(vec_t &src, vec2_t &dest)
Simple generic vector copy.
Definition: vector.h:73
void matrix_swap(size_t M, size_t N, mat_t &v1, mat2_t &v2)
Generic swap of two matrices.
Definition: vector.h:209
void matrix_swap_rows_double(size_t N, mat_t &m, size_t i1, size_t i2)
Generic swap two elements in a matrix.
Definition: vector.h:326
void matrix_min_index(size_t n, const size_t m, const mat_t &data, size_t &i_min, size_t &j_min, data_t &min)
Compute the minimum of a matrix and return the indices of the minimum element.
Definition: vector.h:997
void matrix_lookup(size_t m, size_t n, const mat_t &A, double x0, size_t &i, size_t &j)
Lookup an element in a matrix.
Definition: vector.h:1121
void vector_sort_double(size_t n, vec_t &data)
Sort a vector of doubles (in increasing order)
Definition: vector.h:533
The default vector type from uBlas.
Definition: vector.h:1637
void vector_sort(size_t n, vec_t &data)
Sort a vector (in increasing order)
Definition: vector.h:389
void sort_downheap(vec_t &data, size_t n, size_t k)
Provide a downheap() function for vector_sort()
Definition: vector.h:336

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).
Hosted at Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads..