00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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_PERMUTATION_H 00024 #define O2SCL_PERMUTATION_H 00025 00026 /** \file permutation.h 00027 \brief File containing permutation class and associated functions 00028 */ 00029 00030 #include <iostream> 00031 #include <cstdlib> 00032 #include <string> 00033 #include <fstream> 00034 #include <sstream> 00035 #include <vector> 00036 #include <gsl/gsl_vector.h> 00037 #include <gsl/gsl_permutation.h> 00038 #include <o2scl/err_hnd.h> 00039 #include <o2scl/string_conv.h> 00040 #include <o2scl/uvector_tlate.h> 00041 #include <o2scl/array.h> 00042 #include <o2scl/vector.h> 00043 00044 #ifndef DOXYGENP 00045 namespace o2scl { 00046 #endif 00047 00048 /** 00049 \brief A permutation 00050 00051 This permutation is completely compatible with the GSL 00052 permutation object. 00053 */ 00054 class permutation : public gsl_permutation_struct { 00055 00056 public: 00057 00058 permutation(size_t dim=0) { 00059 gsl_permutation_struct::size=dim; 00060 if (dim>0) { 00061 data=(size_t *)malloc(dim*sizeof(size_t)); 00062 } else { 00063 data=0; 00064 } 00065 } 00066 00067 /// \name Copy constructors 00068 //@{ 00069 permutation(const permutation &v) { 00070 gsl_permutation_struct::size=v.size(); 00071 data=new size_t[gsl_permutation_struct::size]; 00072 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00073 data[i]=v.data[i]; 00074 } 00075 } 00076 00077 permutation& operator=(const permutation &v) { 00078 gsl_permutation_struct::size=v.size(); 00079 data=new size_t[gsl_permutation_struct::size]; 00080 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00081 data[i]=v.data[i]; 00082 } 00083 return *this; 00084 } 00085 //@} 00086 00087 ~permutation() { 00088 if (gsl_permutation_struct::size>0) { 00089 std::free(data); 00090 gsl_permutation_struct::size=0; 00091 } 00092 }; 00093 00094 /** 00095 \brief Array-like indexing 00096 */ 00097 size_t &operator[](size_t i) { 00098 #if O2SCL_NO_RANGE_CHECK 00099 #else 00100 if (i>=gsl_permutation_struct::size) { 00101 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00102 +" in permutation::operator[]. Size: "+ 00103 itos(gsl_permutation_struct::size)+ 00104 " (index should be less than size).").c_str(),gsl_index); 00105 return data[0]; 00106 } 00107 #endif 00108 return data[i]; 00109 } 00110 00111 /** 00112 \brief Array-like indexing 00113 */ 00114 const size_t &operator[](size_t i) const { 00115 #if O2SCL_NO_RANGE_CHECK 00116 #else 00117 if (i>=gsl_permutation_struct::size) { 00118 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00119 +" in permutation::operator[]. Size: "+ 00120 itos(gsl_permutation_struct::size)+ 00121 " (index should be less than size).").c_str(),gsl_index); 00122 return data[0]; 00123 } 00124 #endif 00125 return data[i]; 00126 } 00127 00128 /** 00129 \brief Array-like indexing 00130 */ 00131 size_t &operator()(size_t i) { 00132 #if O2SCL_NO_RANGE_CHECK 00133 #else 00134 if (i>=gsl_permutation_struct::size) { 00135 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00136 +" in permutation::operator(). Size: "+ 00137 itos(gsl_permutation_struct::size)+ 00138 " (index should be less than size).").c_str(),gsl_index); 00139 return data[0]; 00140 } 00141 #endif 00142 return data[i]; 00143 } 00144 00145 /** 00146 \brief Array-like indexing 00147 */ 00148 const size_t &operator()(size_t i) const { 00149 #if O2SCL_NO_RANGE_CHECK 00150 #else 00151 if (i>=gsl_permutation_struct::size) { 00152 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00153 +" in permutation::operator(). Size: "+ 00154 itos(gsl_permutation_struct::size)+ 00155 " (index should be less than size).").c_str(),gsl_index); 00156 return data[0]; 00157 } 00158 #endif 00159 return data[i]; 00160 } 00161 00162 /** \brief Get (with optional range-checking) */ 00163 size_t get(size_t i) const { 00164 #if O2SCL_NO_RANGE_CHECK 00165 #else 00166 if (i>=gsl_permutation_struct::size) { 00167 set_err((((std::string)"Permutation index ")+itos(i)+" out of bounds" 00168 +" in permutation::get(). Size: "+ 00169 itos(gsl_permutation_struct::size)+ 00170 " (index should be less than size).").c_str(),gsl_index); 00171 return 0; 00172 } 00173 #endif 00174 return data[i]; 00175 } 00176 00177 /** \brief Set (with optional range-checking) */ 00178 int set(size_t i, size_t val) { 00179 #if O2SCL_NO_RANGE_CHECK 00180 #else 00181 if (i>=gsl_permutation_struct::size) { 00182 set_err_ret((((std::string)"Permutation index ")+itos(i)+ 00183 " out of bounds"+" in permutation::set(). Size: "+ 00184 itos(gsl_permutation_struct::size)+ 00185 " (index should be less than size).").c_str(),gsl_index); 00186 } 00187 #endif 00188 data[i]=val; 00189 return 0; 00190 } 00191 00192 /// Initialize permutation to the identity 00193 int init() { 00194 for(size_t i=0;i<gsl_permutation_struct::size;i++) data[i]=i; 00195 return 0; 00196 } 00197 00198 /** 00199 \brief Return permutation size 00200 00201 If no memory has been allocated, this will quietly 00202 return zero. 00203 */ 00204 size_t size() const { 00205 return gsl_permutation_struct::size; 00206 } 00207 00208 /** \brief Allocate memory for a permutation of size \c dim 00209 */ 00210 int allocate(size_t dim) { 00211 if (gsl_permutation_struct::size!=dim && 00212 gsl_permutation_struct::size>0) free(); 00213 gsl_permutation_struct::size=dim; 00214 if (dim>0) { 00215 data=(size_t *)malloc(dim*sizeof(size_t)); 00216 } 00217 return 0; 00218 } 00219 00220 /** 00221 \brief Free the memory 00222 00223 This function will safely do nothing if used without first 00224 allocating memory or if called multiple times in succession. 00225 */ 00226 int free() { 00227 if (gsl_permutation_struct::size>0) { 00228 std::free(data); 00229 gsl_permutation_struct::size=0; 00230 } 00231 return 0; 00232 } 00233 //@} 00234 00235 /// Swap two elements of a permutation 00236 int swap(const size_t i, const size_t j) { 00237 size_t tmp=data[i]; 00238 data[i]=data[j]; 00239 data[j]=tmp; 00240 return 0; 00241 } 00242 00243 /// Check to see that a permutation is valid 00244 bool valid() const { 00245 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00246 if (data[i]>gsl_permutation_struct::size) return false; 00247 for(size_t j=0;j<i;j++) { 00248 if (data[i]==data[j]) return false; 00249 } 00250 } 00251 return true; 00252 } 00253 00254 /// Reverse the permutation 00255 int reverse() { 00256 size_t i; 00257 for (i = 0; i < (gsl_permutation_struct::size / 2); i++){ 00258 size_t j = gsl_permutation_struct::size - i - 1; 00259 00260 size_t tmp = this->data[i] ; 00261 this->data[i] = this->data[j] ; 00262 this->data[j] = tmp ; 00263 } 00264 return 0; 00265 } 00266 00267 /// Compute the inverse of a permutation 00268 permutation inverse() const { 00269 permutation p(gsl_permutation_struct::size); 00270 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00271 p.data[data[i]]=i; 00272 } 00273 return p; 00274 } 00275 00276 /// Apply the permutation to a vector 00277 template<class vec_t> int apply(vec_t &v) const { 00278 size_t i, k, pk; 00279 for(i=0;i<gsl_permutation_struct::size;i++) { 00280 k=data[i]; 00281 while (k>i) k=data[k]; 00282 if (k<i) continue; 00283 /// Now have k==i, i.e. the least in its cycle 00284 pk=data[k]; 00285 if (pk==i) continue; 00286 // Shuffle the elements of the cycle 00287 { 00288 double t=v[i]; 00289 while (pk!=i) { 00290 double r1=v[pk]; 00291 v[k]=r1; 00292 k=pk; 00293 pk=data[k]; 00294 } 00295 v[k]=t; 00296 } 00297 } 00298 return 0; 00299 } 00300 00301 /// Apply the inverse permutation to a vector 00302 template<class vec_t> int apply_inverse(vec_t &v) const { 00303 size_t i, k, pk; 00304 for(i=0;i<gsl_permutation_struct::size;i++) { 00305 k=data[i]; 00306 while (k>i) k=data[k]; 00307 if (k<i) continue; 00308 /// Now have k==i, i.e. the least in its cycle 00309 pk=data[k]; 00310 if (pk==i) continue; 00311 // Shuffle the elements of the cycle 00312 { 00313 double t=v[k]; 00314 while (pk!=i) { 00315 double r1=v[pk]; 00316 v[pk]=t; 00317 t=r1; 00318 k=pk; 00319 pk=data[k]; 00320 } 00321 v[pk]=t; 00322 } 00323 } 00324 return 0; 00325 } 00326 00327 // End of permutation class 00328 }; 00329 00330 /** 00331 \brief Output operator for permutations 00332 00333 A space is output between the permutation elements but no 00334 space or endline character is output after the last element. 00335 00336 If the size is zero, this function outputs nothing and does 00337 not call the error handler. 00338 */ 00339 std::ostream &operator<<(std::ostream &os, const permutation &p); 00340 00341 #ifndef DOXYGENP 00342 } 00343 #endif 00344 00345 #endif 00346
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page