![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006-2012, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_VECTOR_H 00024 #define O2SCL_VECTOR_H 00025 00026 /** \file vector.h 00027 \brief File for generic vector functions 00028 00029 This file contains a set of template functions which can be 00030 applied to almost any vector or matrix type which allow element 00031 access through <tt>operator[]</tt>. Detailed requirements 00032 on the template parameters are given in the functions below. 00033 00034 For a general discussion of vectors and matrices in \o2, see the 00035 \ref vecmat_section of the User's Guide. 00036 00037 For overloaded arithmetic operators involving vectors and 00038 matrices, see \ref vec_arith.h . For statistics operations not 00039 included here, see \ref vec_stats.h in the directory \c src/other 00040 . For assorted functions and classes which are specific to C-style 00041 arrays, see \ref array.h . Also related are the matrix output 00042 functions, \ref matrix_out(), \ref matrix_cx_out_paren(), and \ref 00043 matrix_out_paren() which are defined in \ref columnify.h because 00044 they utilize the class \ref columnify to format the output. 00045 00046 For functions which search for a value in an ordered (either 00047 increasing or decreasing) vector, see the class \ref search_vec . 00048 00049 \future Create a matrix transpose copy function? 00050 \future Create matrix swap row and column functions 00051 */ 00052 #include <iostream> 00053 #include <cmath> 00054 #include <string> 00055 #include <fstream> 00056 #include <sstream> 00057 #include <o2scl/err_hnd.h> 00058 #include <o2scl/uniform_grid.h> 00059 #include <gsl/gsl_ieee_utils.h> 00060 #include <gsl/gsl_sort.h> 00061 00062 #ifndef DOXYGENP 00063 namespace o2scl { 00064 #endif 00065 00066 /// \name Copying functions 00067 //@{ 00068 /** \brief Simple vector copy 00069 00070 \note This ordering is reversed from the GSL function 00071 <tt>gsl_vector_memcpy()</tt>. This is to be used with 00072 \code 00073 vector_copy(N,source,destination); 00074 \endcode 00075 instead of 00076 \code 00077 gsl_vector_memcpy(destination,source); 00078 \endcode 00079 00080 It is assumed that the memory allocation for \c dest 00081 has already been performed. 00082 00083 This function will work for any class <tt>vec2_t</tt> which has 00084 an operator[] which returns a reference to the corresponding 00085 element and class <tt>vec_t</tt> with an operator[] which 00086 returns either a reference or the value of the corresponding 00087 element. 00088 */ 00089 template<class vec_t, class vec2_t> 00090 void vector_copy(size_t N, vec_t &src, vec2_t &dest) { 00091 size_t i, m=N%4; 00092 for(i=0;i<m;i++) { 00093 dest[i]=src[i]; 00094 } 00095 for(i=m;i+3<N;i+=4) { 00096 dest[i]=src[i]; 00097 dest[i+1]=src[i+1]; 00098 dest[i+2]=src[i+2]; 00099 dest[i+3]=src[i+3]; 00100 } 00101 return; 00102 } 00103 00104 /** \brief Generic vector swap 00105 00106 This function swaps the elements of \c v1 and \c v2, one element 00107 at a time. 00108 */ 00109 template<class vec_t, class vec2_t, class base_t> 00110 void vector_swap(size_t N, vec_t &v1, vec2_t &v2) { 00111 base_t temp; 00112 size_t i, m=N%4; 00113 for(i=0;i<m;i++) { 00114 temp=v1[i]; 00115 v1[i]=v2[i]; 00116 v2[i]=temp; 00117 } 00118 for(i=m;i+3<N;i+=4) { 00119 temp=v1[i]; 00120 v1[i]=v2[i]; 00121 v2[i]=temp; 00122 temp=v1[i+1]; 00123 v1[i+1]=v2[i+1]; 00124 v2[i+1]=temp; 00125 temp=v1[i+2]; 00126 v1[i+2]=v2[i+2]; 00127 v2[i+2]=temp; 00128 temp=v1[i+3]; 00129 v1[i+3]=v2[i+3]; 00130 v2[i+3]=temp; 00131 } 00132 return; 00133 } 00134 00135 /** \brief Simple matrix copy 00136 00137 \note This ordering is reversed from the GSL function 00138 <tt>gsl_matrix_memcpy()</tt>. This is to be used with 00139 \code 00140 matrix_copy(N,source,destination); 00141 \endcode 00142 instead of 00143 \code 00144 gsl_matrix_memcpy(destination,source); 00145 \endcode 00146 00147 It is assumed that the memory allocation for \c dest 00148 has already been performed. 00149 00150 This function will work for any class <tt>vec2_t</tt> which has 00151 an operator[][] which returns a reference to the corresponding 00152 element and class <tt>vec_t</tt> with an operator[][] which 00153 returns either a reference or the value of the corresponding 00154 element. 00155 */ 00156 template<class mat_t, class mat2_t> 00157 void matrix_copy(size_t M, size_t N, mat_t &src, mat2_t &dest) { 00158 for(size_t i=0;i<M;i++) { 00159 for(size_t j=0;j<N;j++) { 00160 dest[i][j]=src[i][j]; 00161 } 00162 } 00163 } 00164 00165 /** \brief GSL complex vector copy 00166 00167 \future At present this works only with complex types based 00168 directly on the GSL complex format. This could be improved. 00169 */ 00170 template<class vec_t, class vec2_t> 00171 void vector_cx_copy_gsl(size_t N, vec_t &src, vec2_t &dest) { 00172 for(size_t i=0;i<N;i++) { 00173 dest[i].dat[0]=src[i].dat[0]; 00174 dest[i].dat[1]=src[i].dat[1]; 00175 } 00176 } 00177 00178 /** \brief GSL complex matrix copy 00179 00180 \future At present this works only with complex types based 00181 directly on the GSL complex format. This could be improved. 00182 */ 00183 template<class mat_t, class mat2_t> 00184 void matrix_cx_copy_gsl(size_t M, size_t N, mat_t &src, mat2_t &dest) { 00185 for(size_t i=0;i<M;i++) { 00186 for(size_t j=0;j<N;j++) { 00187 dest[i][j].dat[0]=src[i][j].dat[0]; 00188 dest[i][j].dat[1]=src[i][j].dat[1]; 00189 } 00190 } 00191 } 00192 //@} 00193 00194 /// \name Sorting functions 00195 //@{ 00196 /** \brief Provide a downheap() function for vector_sort() 00197 */ 00198 template<class vec_t, class data_t> 00199 void sort_downheap(vec_t &data, size_t n, size_t k) { 00200 00201 data_t v=data[k]; 00202 00203 while (k<=n/2) { 00204 size_t j=2*k; 00205 00206 if (j<n && data[j] < data[j+1]) j++; 00207 if (!(v < data[j])) break; 00208 data[k]=data[j]; 00209 k=j; 00210 } 00211 00212 data[k]=v; 00213 } 00214 00215 /** \brief Sort a vector (in increasing order) 00216 00217 This is a generic sorting template function using a heapsort 00218 algorithm. It will work for any types \c data_t and \c vec_t for 00219 which 00220 - \c data_t has a non-const version of <tt>operator=</tt> 00221 - \c data_t has a less than operator to compare elements 00222 - <tt>vec_t::operator[]</tt> returns a non-const reference 00223 to an object of type \c data_t 00224 00225 In particular, it will work with \ref ovector, \ref uvector, 00226 \ref ovector_int, \ref uvector_int (and other related \o2 00227 vector classes), the STL template class <tt>std::vector</tt>, 00228 and arrays and pointers of numeric, character, and string 00229 objects. 00230 00231 For example, 00232 \code 00233 std::string list[3]={"dog","cat","fox"}; 00234 vector_sort<std::string[3],std::string>(3,list); 00235 \endcode 00236 00237 \note With this function template alone, the user cannot avoid 00238 explicitly specifying the template types for this function 00239 because there is no parameter of type \c data_t, and function 00240 templates cannot handle default template types. For this 00241 reason, the function template \ref vector_sort_double() was 00242 also created which provides the convenience of not requiring 00243 the user to specify the vector template type. 00244 00245 \note This sorting routine is not stable, i.e. equal elements 00246 have arbtrary final ordering 00247 00248 This works similarly to the GSL function <tt>gsl_sort_vector()</tt>. 00249 */ 00250 template<class vec_t, class data_t> 00251 int vector_sort(size_t n, vec_t &data) { 00252 00253 size_t N; 00254 size_t k; 00255 00256 if (n==0) return 0; 00257 00258 N=n-1; 00259 k=N/2; 00260 k++; 00261 do { 00262 k--; 00263 sort_downheap<vec_t,data_t>(data,N,k); 00264 } while (k > 0); 00265 00266 while (N > 0) { 00267 data_t tmp=data[0]; 00268 data[0]=data[N]; 00269 data[N]=tmp; 00270 N--; 00271 sort_downheap<vec_t,data_t>(data,N,0); 00272 } 00273 00274 return 0; 00275 } 00276 00277 /** \brief Provide a downheap() function for vector_sort_index() 00278 */ 00279 template<class vec_t, class vec_size_t> 00280 int sort_index_downheap(size_t N, const vec_t &data, vec_size_t &order, 00281 size_t k) { 00282 00283 const size_t pki = order[k]; 00284 00285 while (k <= N / 2) { 00286 size_t j = 2 * k; 00287 00288 if (j < N && data[order[j]] < data[order[j + 1]]) { 00289 j++; 00290 } 00291 00292 // avoid infinite loop if nan 00293 if (!(data[pki] < data[order[j]])) { 00294 break; 00295 } 00296 00297 order[k] = order[j]; 00298 00299 k = j; 00300 } 00301 00302 order[k] = pki; 00303 00304 return 0; 00305 } 00306 00307 /** \brief Create a permutation which sorts a vector (in increasing order) 00308 00309 This function takes a vector \c data and arranges a list of 00310 indices in \c order, which give a sorted version of the vector. 00311 The value <tt>order[i]</tt> gives the index of entry in in \c 00312 data which corresponds to the <tt>i</tt>th value in the sorted 00313 vector. The vector \c data is unchanged by this function, and 00314 the initial values in \c order are ignored. Before calling this 00315 function, \c order must already be allocated as a vector of size 00316 \c n. 00317 00318 For example, after calling this function, a sorted version the 00319 vector can be output with 00320 \code 00321 size_t n=5; 00322 double data[5]={3.1,4.1,5.9,2.6,3.5}; 00323 permutation order(n); 00324 vector_sort_index(n,data,order); 00325 for(size_t i=0;i<n;i++) { 00326 cout << data[order[i]] << endl; 00327 } 00328 \endcode 00329 00330 To create a permutation which stores as its <tt>i</tt>th element, 00331 the index of <tt>data[i]</tt> in the sorted vector, you can 00332 invert the permutation created by this function. 00333 00334 This is a generic sorting template function. It will work for 00335 any types \c vec_t and \c vec_size_t for which 00336 - \c vec_t has an <tt>operator[]</tt>, and 00337 - \c vec_size_t has an <tt>operator[]</tt> which returns 00338 a \c size_t . 00339 One possible type for \c vec_size_t is \ref permutation. 00340 00341 This works similarly to the GSL function <tt>gsl_sort_index()</tt>. 00342 */ 00343 template<class vec_t, class vec_size_t> 00344 int vector_sort_index(size_t n, const vec_t &data, vec_size_t &order) { 00345 size_t N; 00346 size_t i, k; 00347 00348 if (n == 0) return 0; 00349 00350 // set permutation to identity 00351 00352 for (i = 0 ; i < n ; i++) { 00353 order[i] = i ; 00354 } 00355 00356 /* We have n_data elements, last element is at 'n_data-1', first 00357 at '0' Set N to the last element number. 00358 */ 00359 N = n - 1; 00360 00361 k = N / 2; 00362 // Compensate the first use of 'k--' 00363 k++; 00364 do { 00365 k--; 00366 sort_index_downheap<vec_t,vec_size_t>(N,data,order,k); 00367 } while (k > 0); 00368 00369 00370 while (N > 0) { 00371 00372 // first swap the elements 00373 size_t tmp = order[0]; 00374 order[0] = order[N]; 00375 order[N] = tmp; 00376 00377 // then process the heap 00378 N--; 00379 00380 sort_index_downheap<vec_t,vec_size_t>(N,data,order,0); 00381 } 00382 00383 return 0; 00384 } 00385 00386 /** \brief Sort a vector of doubles (in increasing order) 00387 00388 This function is just a wrapper for 00389 \code 00390 vector_sort<vec_t,double>(n,data); 00391 \endcode 00392 See the documentation of \ref vector_sort() for more 00393 details. 00394 */ 00395 template<class vec_t> 00396 int vector_sort_double(size_t n, vec_t &data) { 00397 return vector_sort<vec_t,double>(n,data); 00398 } 00399 //@} 00400 00401 /// \name Smallest and largest functions 00402 //@{ 00403 /** \brief Find the k smallest entries of a vector 00404 00405 Given a vector \c data of size \c n this sets the first \c k 00406 entries of the vector \c smallest to the k smallest entries from 00407 vector \c data in ascending order. The vector \c smallest must 00408 be allocated beforehand to hold at least \c k elements. 00409 00410 This works similarly to the GSL function <tt>gsl_sort_smallest()</tt>. 00411 00412 \note This \f$ {\cal O}(k N) \f$ algorithm is useful only when 00413 \f$ k << N \f$. 00414 00415 If \c k is zero, then this function does nothing and 00416 returns \ref gsl_success . 00417 */ 00418 template<class vec_t, class data_t> 00419 int vector_smallest(size_t n, vec_t &data, size_t k, vec_t &smallest) { 00420 if (k>n) { 00421 O2SCL_ERR2_RET("Subset length greater than size in ", 00422 "function vector_smallest().",gsl_einval); 00423 } 00424 if (k==0 || n==0) return gsl_success; 00425 00426 // Take the first element 00427 size_t j=1; 00428 data_t xbound=data[0]; 00429 smallest[0]=xbound; 00430 00431 // Examine the remaining elements 00432 for(size_t i=1;i<n;i++) { 00433 data_t xi=data[i]; 00434 if (j<k) { 00435 j++; 00436 } else if (xi>=xbound) { 00437 continue; 00438 } 00439 size_t i1; 00440 for(i1=j-1;i1>0;i1--) { 00441 if (xi>smallest[i1-1]) break; 00442 smallest[i1]=smallest[i1-1]; 00443 } 00444 smallest[i1]=xi; 00445 xbound=smallest[j-1]; 00446 } 00447 return 0; 00448 } 00449 00450 /** \brief Find the k largest entries of a vector 00451 00452 Given a vector \c data of size \c n this sets the first \c k 00453 entries of the vector \c largest to the k largest entries from 00454 vector \c data in descending order. The vector \c largest must 00455 be allocated beforehand to hold at least \c k elements. 00456 00457 This works similarly to the GSL function <tt>gsl_sort_largest()</tt>. 00458 00459 \note This \f$ {\cal O}(k N) \f$ algorithm is useful only when 00460 \f$ k << N \f$. 00461 00462 If \c k is zero, then this function does nothing and 00463 returns \ref gsl_success . 00464 */ 00465 template<class vec_t, class data_t> 00466 int vector_largest(size_t n, vec_t &data, size_t k, vec_t &largest) { 00467 if (k>n) { 00468 O2SCL_ERR2_RET("Subset length greater than size in ", 00469 "function vector_largest().",gsl_einval); 00470 } 00471 if (k==0 || n==0) return gsl_success; 00472 00473 // Take the first element 00474 size_t j=1; 00475 data_t xbound=data[0]; 00476 largest[0]=xbound; 00477 00478 // Examine the remaining elements 00479 for(size_t i=1;i<n;i++) { 00480 data_t xi=data[i]; 00481 if (j<k) { 00482 j++; 00483 } else if (xi<=xbound) { 00484 continue; 00485 } 00486 size_t i1; 00487 for(i1=j-1;i1>0;i1--) { 00488 if (xi<largest[i1-1]) break; 00489 largest[i1]=largest[i1-1]; 00490 } 00491 largest[i1]=xi; 00492 xbound=largest[j-1]; 00493 } 00494 return 0; 00495 } 00496 //@} 00497 00498 /// \name Vector minimum and maximum functions 00499 //@{ 00500 /** \brief Compute the maximum of the first \c n elements of a vector 00501 */ 00502 template<class vec_t, class data_t> 00503 data_t vector_max_value(size_t n, const vec_t &data) { 00504 00505 if (n==0) { 00506 O2SCL_ERR_RET("Sent size=0 to vector_max_value().",gsl_efailed); 00507 } 00508 data_t max=data[0]; 00509 for(size_t i=1;i<n;i++) { 00510 if (data[i]>max) { 00511 max=data[i]; 00512 } 00513 } 00514 return max; 00515 } 00516 00517 /** \brief Compute the index which holds the 00518 maximum of the first \c n elements of a vector 00519 */ 00520 template<class vec_t, class data_t> 00521 size_t vector_max_index(size_t n, const vec_t &data) { 00522 00523 if (n==0) { 00524 O2SCL_ERR_RET("Sent size=0 to vector_max_index().",gsl_efailed); 00525 } 00526 data_t max=data[0]; 00527 size_t ix=0; 00528 for(size_t i=1;i<n;i++) { 00529 if (data[i]>max) { 00530 max=data[i]; 00531 ix=i; 00532 } 00533 } 00534 return ix; 00535 } 00536 00537 /** \brief Compute the maximum of the first \c n elements of a vector 00538 */ 00539 template<class vec_t, class data_t> 00540 void vector_max(size_t n, const vec_t &data, size_t &index, 00541 data_t &val) { 00542 00543 if (n==0) { 00544 O2SCL_ERR_RET("Sent size=0 to vector_max().",gsl_efailed); 00545 } 00546 val=data[0]; 00547 index=0; 00548 for(size_t i=1;i<n;i++) { 00549 if (data[i]>val) { 00550 val=data[i]; 00551 index=i; 00552 } 00553 } 00554 return index; 00555 } 00556 00557 /** \brief Compute the minimum of the first \c n elements of a vector 00558 */ 00559 template<class vec_t, class data_t> 00560 data_t vector_min_value(size_t n, const vec_t &data) { 00561 00562 if (n==0) { 00563 O2SCL_ERR_RET("Sent size=0 to vector_min_value().",gsl_efailed); 00564 } 00565 data_t min=data[0]; 00566 for(size_t i=1;i<n;i++) { 00567 if (data[i]<min) { 00568 min=data[i]; 00569 } 00570 } 00571 return min; 00572 } 00573 00574 /** \brief Compute the index which holds the 00575 minimum of the first \c n elements of a vector 00576 */ 00577 template<class vec_t, class data_t> 00578 size_t vector_min_index(size_t n, const vec_t &data) { 00579 00580 if (n==0) { 00581 O2SCL_ERR_RET("Sent size=0 to vector_min_index().",gsl_efailed); 00582 } 00583 data_t min=data[0]; 00584 size_t ix=0; 00585 for(size_t i=1;i<n;i++) { 00586 if (data[i]<min) { 00587 min=data[i]; 00588 ix=i; 00589 } 00590 } 00591 return ix; 00592 } 00593 00594 /** \brief Compute the minimum of the first \c n elements of a vector 00595 */ 00596 template<class vec_t, class data_t> 00597 void vector_min(size_t n, const vec_t &data, size_t &index, 00598 data_t &val) { 00599 00600 if (n==0) { 00601 O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed); 00602 } 00603 val=data[0]; 00604 index=0; 00605 for(size_t i=1;i<n;i++) { 00606 if (data[i]<val) { 00607 val=data[i]; 00608 index=i; 00609 } 00610 } 00611 return; 00612 } 00613 00614 /** \brief Compute the minimum and maximum of the first 00615 \c n elements of a vector 00616 */ 00617 template<class vec_t, class data_t> 00618 void vector_minmax_value(size_t n, vec_t &data, 00619 data_t &min, data_t &max) { 00620 00621 if (n==0) { 00622 O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed); 00623 } 00624 min=data[0]; 00625 max=min; 00626 for(size_t i=1;i<n;i++) { 00627 if (data[i]<min) { 00628 min=data[i]; 00629 } 00630 if (data[i]>max) { 00631 max=data[i]; 00632 } 00633 } 00634 return; 00635 } 00636 00637 /** \brief Compute the minimum and maximum of the first 00638 \c n elements of a vector 00639 */ 00640 template<class vec_t, class data_t> 00641 void vector_minmax_index(size_t n, vec_t &data, 00642 size_t &ix_min, size_t &ix_max) { 00643 00644 if (n==0) { 00645 O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed); 00646 } 00647 data_t min=data[0]; 00648 data_t max=min; 00649 ix_min=0; 00650 ix_max=0; 00651 for(size_t i=1;i<n;i++) { 00652 if (data[i]<min) { 00653 min=data[i]; 00654 ix_min=i; 00655 } 00656 if (data[i]>max) { 00657 max=data[i]; 00658 ix_max=i; 00659 } 00660 } 00661 return; 00662 } 00663 00664 /** \brief Compute the minimum and maximum of the first 00665 \c n elements of a vector 00666 */ 00667 template<class vec_t, class data_t> 00668 void vector_minmax(size_t n, vec_t &data, 00669 size_t &ix_min, data_t &min, 00670 size_t &ix_max, data_t &max) { 00671 00672 if (n==0) { 00673 O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed); 00674 } 00675 min=data[0]; 00676 max=min; 00677 ix_min=0; 00678 ix_max=0; 00679 for(size_t i=1;i<n;i++) { 00680 if (data[i]<min) { 00681 min=data[i]; 00682 ix_min=i; 00683 } 00684 if (data[i]>max) { 00685 max=data[i]; 00686 ix_max=i; 00687 } 00688 } 00689 return; 00690 } 00691 //@} 00692 00693 /// \name Matrix minimum and maximum functions 00694 //@{ 00695 /** \brief Compute the maximum of a matrix 00696 00697 \future Write matrix_max_index() and related functions similar 00698 to the way vector_max_index() works. 00699 */ 00700 template<class mat_t, class data_t> 00701 data_t matrix_max(size_t n, const size_t m, const mat_t &data) { 00702 00703 if (n==0 || m==0) { 00704 O2SCL_ERR_RET("Sent size=0 to matrix_max().",gsl_efailed); 00705 } 00706 data_t max=data[0][0]; 00707 for(size_t i=0;i<n;i++) { 00708 for(size_t j=0;j<m;j++) { 00709 if (data[i][j]>max) { 00710 max=data[i][j]; 00711 } 00712 } 00713 } 00714 return max; 00715 } 00716 00717 /** \brief Compute the minimum of a matrix 00718 */ 00719 template<class mat_t, class data_t> 00720 data_t matrix_min(size_t n, const size_t m, const mat_t &data) { 00721 00722 if (n==0 || m==0) { 00723 O2SCL_ERR_RET("Sent size=0 to matrix_min().",gsl_efailed); 00724 } 00725 data_t min=data[0][0]; 00726 for(size_t i=0;i<n;i++) { 00727 for(size_t j=0;j<m;j++) { 00728 if (data[i][j]<min) { 00729 min=data[i][j]; 00730 } 00731 } 00732 } 00733 return min; 00734 } 00735 00736 /** \brief Compute the minimum and maximum of a matrix 00737 */ 00738 template<class mat_t, class data_t> 00739 int matrix_minmax(size_t n, const size_t m, const mat_t &data, 00740 data_t &min, data_t &max) { 00741 00742 if (n==0 || m==0) { 00743 O2SCL_ERR_RET("Sent size=0 to matrix_min().",gsl_efailed); 00744 } 00745 min=data[0][0]; 00746 max=data[0][0]; 00747 for(size_t i=0;i<n;i++) { 00748 for(size_t j=0;j<m;j++) { 00749 if (data[i][j]<min) { 00750 min=data[i][j]; 00751 } else if (data[i][j]>max) { 00752 max=data[i][j]; 00753 } 00754 } 00755 } 00756 return 0; 00757 } 00758 //@} 00759 00760 /** \brief Create a vector-like class from a row of a matrix 00761 00762 \comment 00763 This class isn't used in o2scl at present, but we 00764 keep it here for posterity for now. 00765 \endcomment 00766 00767 \future Generalize to operator(,) 00768 */ 00769 template <class mat_t> class matrix_row { 00770 00771 #ifndef DOXYGEN_INTERNAL 00772 00773 protected: 00774 00775 /// The row index 00776 size_t r2; 00777 00778 /// The pointer to the matrix 00779 mat_t *m2; 00780 00781 #endif 00782 00783 public: 00784 00785 /// Create an object which represents row \c r of matrix \c m 00786 matrix_row(mat_t &m, size_t r) { 00787 r2=r; 00788 m2=&m; 00789 } 00790 00791 /// Access element of column \c c from the specified row 00792 double &operator[](size_t c) { 00793 return (*m2)[r2][c]; 00794 } 00795 00796 /// Access element of column \c c from the specified row 00797 const double &operator[](size_t c) const { 00798 return (*m2)[r2][c]; 00799 } 00800 00801 }; 00802 00803 /// \name Searching functions 00804 //@{ 00805 /** \brief Lookup element \c x0 in vector \c x of length \c n 00806 00807 This function finds the element in vector \c x which is closest 00808 to \c x0. It ignores all elements in \c x which are not finite. 00809 If the vector is empty (i.e. \c n is zero), or if all of the 00810 elements in \c x are not finite, then the error handler will be 00811 called. 00812 00813 This function works for all classes \c vec_t where an operator[] 00814 is defined which returns a double (either as a value or a 00815 reference). 00816 00817 \future Write matrix_lookup(). 00818 */ 00819 template<class vec_t> 00820 size_t vector_lookup(size_t n, const vec_t &x, double x0) { 00821 if (n==0) { 00822 O2SCL_ERR("Empty vector in vector_lookup().", 00823 gsl_einval); 00824 return 0; 00825 } 00826 size_t row=0, i=0; 00827 while(!finite(x[i]) && i<n-1) i++; 00828 if (i==n-1) { 00829 O2SCL_ERR2("Entire vector not finite in ", 00830 "vector_lookup()",gsl_einval); 00831 return 0; 00832 } 00833 double best=x[i], bdiff=fabs(x[i]-x0); 00834 for(;i<n;i++) { 00835 if (finite(x[i]) && fabs(x[i]-x0)<bdiff) { 00836 row=i; 00837 best=x[i]; 00838 bdiff=fabs(x[i]-x0); 00839 } 00840 } 00841 return row; 00842 } 00843 00844 /** \brief Binary search a part of an increasing vector for 00845 <tt>x0</tt>. 00846 00847 This function performs a binary search of between 00848 <tt>x[lo]</tt> and <tt>x[hi]</tt>. It returns 00849 - \c lo if \c x0 < <tt>x[lo]</tt> 00850 - \c i if <tt>x[i]</tt> <= \c x0 < <tt>x[i+2]</tt> 00851 for \c lo <= \c i < \c hi 00852 - \c hi-1 if \c x0 >= \c <tt>x[hi-1]</tt> 00853 00854 The element at <tt>x[hi]</tt> is never referenced by this 00855 function. The parameter \c hi can be either the index of the 00856 last element (e.g. <tt>n-1</tt> for a vector of size <tt>n</tt> 00857 with starting index <tt>0</tt>), or the index of one element 00858 (e.g. <tt>n</tt> for a vector of size <tt>n</tt> and a starting 00859 index <tt>0</tt>) for a depending on whether or not the user 00860 wants to allow the function to return the index of the last 00861 element. 00862 00863 This function operates in the same way as 00864 <tt>gsl_interp_bsearch()</tt>. 00865 00866 The operation of this function is undefined if the data is 00867 not strictly monotonic, i.e. if some of the data elements are 00868 equal. 00869 00870 This function will call the error handler if \c lo is 00871 greater than \c hi. 00872 */ 00873 template<class vec_t, class data_t> 00874 size_t vector_bsearch_inc(const data_t x0, const vec_t &x, 00875 size_t lo, size_t hi) { 00876 if (lo>hi) { 00877 O2SCL_ERR2("Low and high indexes backwards in ", 00878 "vector_bsearch_inc().",gsl_einval); 00879 } 00880 while (hi>lo+1) { 00881 size_t i=(hi+lo)/2; 00882 if (x[i]>x0) { 00883 hi=i; 00884 } else { 00885 lo=i; 00886 } 00887 } 00888 00889 return lo; 00890 } 00891 00892 /** \brief Binary search a part of an decreasing vector for 00893 <tt>x0</tt>. 00894 00895 This function performs a binary search of between 00896 <tt>x[lo]</tt> and <tt>x[hi]</tt> (inclusive). It returns 00897 - \c lo if \c x0 > <tt>x[lo]</tt> 00898 - \c i if <tt>x[i]</tt> >= \c x0 > <tt>x[i+1]</tt> 00899 for \c lo <= \c i < \c hi 00900 - \c hi-1 if \c x0 <= \c <tt>x[hi-1]</tt> 00901 00902 The element at <tt>x[hi]</tt> is never referenced by this 00903 function. The parameter \c hi can be either the index of the 00904 last element (e.g. <tt>n-1</tt> for a vector of size <tt>n</tt> 00905 with starting index <tt>0</tt>), or the index of one element 00906 (e.g. <tt>n</tt> for a vector of size <tt>n</tt> and a starting 00907 index <tt>0</tt>) for a depending on whether or not the user 00908 wants to allow the function to return the index of the last 00909 element. 00910 00911 The operation of this function is undefined if the data is 00912 not strictly monotonic, i.e. if some of the data elements are 00913 equal. 00914 00915 This function will call the error handler if \c lo is 00916 greater than \c hi. 00917 */ 00918 template<class vec_t, class data_t> 00919 size_t vector_bsearch_dec(const data_t x0, const vec_t &x, 00920 size_t lo, size_t hi) { 00921 if (lo>hi) { 00922 O2SCL_ERR2("Low and high indexes backwards in ", 00923 "vector_bsearch_dec().",gsl_einval); 00924 } 00925 while (hi>lo+1) { 00926 size_t i=(hi+lo)/2; 00927 if (x[i]<x0) { 00928 hi=i; 00929 } else { 00930 lo=i; 00931 } 00932 } 00933 00934 return lo; 00935 } 00936 00937 /** \brief Binary search a part of a monotonic vector for 00938 <tt>x0</tt>. 00939 00940 This wrapper just calls \ref vector_bsearch_inc() or 00941 \ref vector_bsearch_dec() depending on the ordering 00942 of \c x. 00943 */ 00944 template<class vec_t, class data_t> 00945 size_t vector_bsearch(const data_t x0, const vec_t &x, 00946 size_t lo, size_t hi) { 00947 if (x[lo]<x[hi-1]) { 00948 return vector_bsearch_inc<vec_t,data_t>(x0,x,lo,hi); 00949 } 00950 return vector_bsearch_dec<vec_t,data_t>(x0,x,lo,hi); 00951 } 00952 //@} 00953 00954 /// \name Miscellaneous mathematical functions 00955 //@{ 00956 /** \brief Compute the sum of the first \c n elements of a vector 00957 00958 If \c n is zero, this will set \c sum to zero and return 00959 \ref gsl_success. 00960 */ 00961 template<class vec_t, class data_t> 00962 data_t vector_sum(size_t n, vec_t &data) { 00963 00964 data_t sum=0.0; 00965 for(size_t i=0;i<n;i++) { 00966 sum+=data[i]; 00967 } 00968 return sum; 00969 } 00970 00971 /** \brief Compute the norm of a vector of floating-point 00972 (single or double precision) numbers 00973 00974 This function is a more generic version of 00975 \ref o2scl_cblas::dnrm2 . 00976 */ 00977 template<class vec_t, class data_t> 00978 data_t vector_norm(size_t n, const vec_t &x) { 00979 00980 data_t scale = 0.0; 00981 data_t ssq = 1.0; 00982 00983 if (n <= 0) { 00984 return 0.0; 00985 } else if (n == 1) { 00986 return fabs(x[0]); 00987 } 00988 00989 for (size_t i = 0; i < n; i++) { 00990 const data_t xx = x[i]; 00991 00992 if (xx != 0.0) { 00993 const data_t ax = fabs(xx); 00994 00995 if (scale < ax) { 00996 ssq = 1.0 + ssq * (scale / ax) * (scale / ax); 00997 scale = ax; 00998 } else { 00999 ssq += (ax / scale) * (ax / scale); 01000 } 01001 } 01002 01003 } 01004 01005 return scale * sqrt(ssq); 01006 } 01007 //@} 01008 01009 /// \name Other functions 01010 //@{ 01011 /** \brief "Rotate" a vector so that the kth element is now the beginning 01012 01013 This is a generic template function which will work for 01014 any types \c data_t and \c vec_t for which 01015 - \c data_t has an <tt>operator=</tt> 01016 - <tt>vec_t::operator[]</tt> returns a reference 01017 to an object of type \c data_t 01018 01019 This function is used, for example, in \ref pinside. 01020 01021 \note This function is not the same as a Givens rotation, 01022 which is typically referred to in BLAS routines as <tt>drot()</tt>. 01023 */ 01024 template<class vec_t, class data_t> 01025 int vector_rotate(size_t n, vec_t &data, size_t k) { 01026 01027 data_t *tmp=new data_t[n]; 01028 for(size_t i=0;i<n;i++) { 01029 tmp[i]=data[(i+k)%n]; 01030 } 01031 for(size_t i=0;i<n;i++) { 01032 data[i]=tmp[i]; 01033 } 01034 delete[] tmp; 01035 01036 return 0; 01037 } 01038 01039 /** \brief Reverse a vector 01040 01041 If \c n is zero, this function will silently do nothing. 01042 */ 01043 template<class vec_t, class data_t> 01044 int vector_reverse(size_t n, vec_t &data) { 01045 data_t tmp; 01046 01047 for(size_t i=0;i<n/2;i++) { 01048 tmp=data[n-1-i]; 01049 data[n-1-i]=data[i]; 01050 data[i]=tmp; 01051 } 01052 return 0; 01053 } 01054 01055 /** \brief Output a vector to a stream 01056 01057 No trailing space is output after the last element, and an 01058 endline is output only if \c endline is set to \c true. If the 01059 parameter \c n is zero, this function silently does nothing. 01060 01061 Note that the \o2 vector classes also have their own 01062 \c operator<<() defined for them. 01063 01064 This works with any class <tt>vec_t</tt> which has an operator[] 01065 which returns either the value of or a reference to the ith 01066 element and the element type has its own output operator which 01067 has been defined. 01068 */ 01069 template<class vec_t> 01070 int vector_out(std::ostream &os, size_t n, const vec_t &v, 01071 bool endline=false) { 01072 01073 // This next line is important since n-1 is not well-defined if n=0 01074 if (n==0) return 0; 01075 01076 for(size_t i=0;i<n-1;i++) os << v[i] << " "; 01077 os << v[n-1]; 01078 if (endline) os << std::endl; 01079 return 0; 01080 } 01081 //@} 01082 01083 /** \brief Fill a vector with a specified grid 01084 */ 01085 template<class vec_t, class data_t> 01086 void vector_grid(uniform_grid<data_t> g, vec_t &v) { 01087 g.template vector<vec_t>(v); 01088 return; 01089 } 01090 01091 01092 #ifndef DOXYGENP 01093 } 01094 #endif 01095 01096 #endif
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).