![]() |
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 /* permutation/permute_source.c 00024 * 00025 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough 00026 * 00027 * This program is free software; you can redistribute it and/or modify 00028 * it under the terms of the GNU General Public License as published by 00029 * the Free Software Foundation; either version 3 of the License, or (at 00030 * your option) any later version. 00031 * 00032 * This program is distributed in the hope that it will be useful, but 00033 * WITHOUT ANY WARRANTY; without even the implied warranty of 00034 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00035 * General Public License for more details. 00036 * 00037 * You should have received a copy of the GNU General Public License 00038 * along with this program; if not, write to the Free Software 00039 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00040 * 02110-1301, USA. 00041 */ 00042 #ifndef O2SCL_PERMUTATION_H 00043 #define O2SCL_PERMUTATION_H 00044 00045 /** \file permutation.h 00046 \brief File containing permutation class and associated functions 00047 */ 00048 00049 #include <iostream> 00050 #include <cstdlib> 00051 #include <string> 00052 #include <fstream> 00053 #include <sstream> 00054 #include <vector> 00055 #include <gsl/gsl_vector.h> 00056 #include <gsl/gsl_permutation.h> 00057 #include <o2scl/err_hnd.h> 00058 #include <o2scl/string_conv.h> 00059 #include <o2scl/uvector_tlate.h> 00060 #include <o2scl/array.h> 00061 #include <o2scl/vector.h> 00062 00063 #ifndef DOXYGENP 00064 namespace o2scl { 00065 #endif 00066 00067 /** \brief A class for representing permutations 00068 00069 A class for representing permutations. This \permutation class 00070 is completely compatible with the GSL \permutation object since 00071 it is derived from <tt>gsl_permutation_struct</tt> (and thus 00072 also <tt>gsl_permutation</tt>). For example, the last line in 00073 the code below is a trivial upcast, and permitted since 00074 <tt>gsl_permutation</tt> is a base type of this class. 00075 \code 00076 permuation p(5); 00077 p.init(); 00078 gsl_permutation *gp=&p; 00079 \endcode 00080 00081 See also the \ref permute_section section of the User's guide. 00082 00083 */ 00084 class permutation : public gsl_permutation_struct { 00085 00086 public: 00087 00088 /// Create a permutation of size \c dim 00089 permutation(size_t dim=0) { 00090 gsl_permutation_struct::size=dim; 00091 if (dim>0) { 00092 data=(size_t *)malloc(dim*sizeof(size_t)); 00093 } else { 00094 data=0; 00095 } 00096 } 00097 00098 /// \name Copy constructors 00099 //@{ 00100 permutation(const permutation &v) { 00101 gsl_permutation_struct::size=v.size(); 00102 data=new size_t[gsl_permutation_struct::size]; 00103 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00104 data[i]=v.data[i]; 00105 } 00106 } 00107 00108 permutation& operator=(const permutation &v) { 00109 00110 // Check for self-assignment 00111 if (this==&v) return *this; 00112 00113 gsl_permutation_struct::size=v.size(); 00114 data=new size_t[gsl_permutation_struct::size]; 00115 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00116 data[i]=v.data[i]; 00117 } 00118 return *this; 00119 } 00120 //@} 00121 00122 ~permutation() { 00123 if (gsl_permutation_struct::size>0) { 00124 std::free(data); 00125 gsl_permutation_struct::size=0; 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 O2SCL_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_eindex); 00139 return data[0]; 00140 } 00141 #endif 00142 return data[i]; 00143 } 00144 00145 /** \brief Array-like indexing 00146 */ 00147 const size_t &operator[](size_t i) const { 00148 #if O2SCL_NO_RANGE_CHECK 00149 #else 00150 if (i>=gsl_permutation_struct::size) { 00151 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00152 +" in permutation::operator[]. Size: "+ 00153 itos(gsl_permutation_struct::size)+ 00154 " (index should be less than size).").c_str(),gsl_eindex); 00155 return data[0]; 00156 } 00157 #endif 00158 return data[i]; 00159 } 00160 00161 /** \brief Array-like indexing 00162 */ 00163 size_t &operator()(size_t i) { 00164 #if O2SCL_NO_RANGE_CHECK 00165 #else 00166 if (i>=gsl_permutation_struct::size) { 00167 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00168 +" in permutation::operator(). Size: "+ 00169 itos(gsl_permutation_struct::size)+ 00170 " (index should be less than size).").c_str(),gsl_eindex); 00171 return data[0]; 00172 } 00173 #endif 00174 return data[i]; 00175 } 00176 00177 /** \brief Array-like indexing 00178 */ 00179 const size_t &operator()(size_t i) const { 00180 #if O2SCL_NO_RANGE_CHECK 00181 #else 00182 if (i>=gsl_permutation_struct::size) { 00183 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00184 +" in permutation::operator(). Size: "+ 00185 itos(gsl_permutation_struct::size)+ 00186 " (index should be less than size).").c_str(),gsl_eindex); 00187 return data[0]; 00188 } 00189 #endif 00190 return data[i]; 00191 } 00192 00193 /** \brief Get (with optional range-checking) */ 00194 size_t get(size_t i) const { 00195 #if O2SCL_NO_RANGE_CHECK 00196 #else 00197 if (i>=gsl_permutation_struct::size) { 00198 O2SCL_ERR((((std::string)"Permutation index ")+itos(i)+" out of bounds" 00199 +" in permutation::get(). Size: "+ 00200 itos(gsl_permutation_struct::size)+ 00201 " (index should be less than size).").c_str(),gsl_eindex); 00202 return 0; 00203 } 00204 #endif 00205 return data[i]; 00206 } 00207 00208 /** \brief Set (with optional range-checking) */ 00209 int set(size_t i, size_t val) { 00210 #if O2SCL_NO_RANGE_CHECK 00211 #else 00212 if (i>=gsl_permutation_struct::size) { 00213 O2SCL_ERR_RET((((std::string)"Permutation index ")+itos(i)+ 00214 " out of bounds"+" in permutation::set(). Size: "+ 00215 itos(gsl_permutation_struct::size)+ 00216 " (index should be less than size).").c_str(),gsl_eindex); 00217 } 00218 #endif 00219 data[i]=val; 00220 return 0; 00221 } 00222 00223 /// Initialize permutation to the identity 00224 int init() { 00225 for(size_t i=0;i<gsl_permutation_struct::size;i++) data[i]=i; 00226 return 0; 00227 } 00228 00229 /** \brief Return permutation size 00230 00231 If no memory has been allocated, this will quietly 00232 return zero. 00233 */ 00234 size_t size() const { 00235 return gsl_permutation_struct::size; 00236 } 00237 00238 /** \brief Allocate memory for a permutation of size \c dim 00239 */ 00240 int allocate(size_t dim) { 00241 if (gsl_permutation_struct::size!=dim && 00242 gsl_permutation_struct::size>0) free(); 00243 gsl_permutation_struct::size=dim; 00244 if (dim>0) { 00245 data=(size_t *)malloc(dim*sizeof(size_t)); 00246 } 00247 return 0; 00248 } 00249 00250 /** \brief Free the memory 00251 00252 This function will safely do nothing if used without first 00253 allocating memory or if called multiple times in succession. 00254 */ 00255 int free() { 00256 if (gsl_permutation_struct::size>0) { 00257 std::free(data); 00258 gsl_permutation_struct::size=0; 00259 } 00260 return 0; 00261 } 00262 //@} 00263 00264 /// Swap two elements of a permutation 00265 int swap(const size_t i, const size_t j) { 00266 size_t tmp=data[i]; 00267 data[i]=data[j]; 00268 data[j]=tmp; 00269 return 0; 00270 } 00271 00272 /// Check to see that a permutation is valid 00273 bool valid() const { 00274 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00275 if (data[i]>gsl_permutation_struct::size) return false; 00276 for(size_t j=0;j<i;j++) { 00277 if (data[i]==data[j]) return false; 00278 } 00279 } 00280 return true; 00281 } 00282 00283 /// Reverse the permutation 00284 int reverse() { 00285 size_t i; 00286 for (i = 0; i < (gsl_permutation_struct::size / 2); i++){ 00287 size_t j = gsl_permutation_struct::size - i - 1; 00288 00289 size_t tmp = this->data[i] ; 00290 this->data[i] = this->data[j] ; 00291 this->data[j] = tmp ; 00292 } 00293 return 0; 00294 } 00295 00296 /// Compute the inverse of a permutation 00297 permutation inverse() const { 00298 permutation p(gsl_permutation_struct::size); 00299 for(size_t i=0;i<gsl_permutation_struct::size;i++) { 00300 p.data[data[i]]=i; 00301 } 00302 return p; 00303 } 00304 00305 /// Apply the permutation to a vector 00306 template<class vec_t> int apply(vec_t &v) const { 00307 size_t i, k, pk; 00308 for(i=0;i<gsl_permutation_struct::size;i++) { 00309 k=data[i]; 00310 while (k>i) k=data[k]; 00311 if (k<i) continue; 00312 // Now have k==i, i.e. the least in its cycle 00313 pk=data[k]; 00314 if (pk==i) continue; 00315 // Shuffle the elements of the cycle 00316 { 00317 double t=v[i]; 00318 while (pk!=i) { 00319 double r1=v[pk]; 00320 v[k]=r1; 00321 k=pk; 00322 pk=data[k]; 00323 } 00324 v[k]=t; 00325 } 00326 } 00327 return 0; 00328 } 00329 00330 /// Apply the inverse permutation to a vector 00331 template<class vec_t> int apply_inverse(vec_t &v) const { 00332 size_t i, k, pk; 00333 for(i=0;i<gsl_permutation_struct::size;i++) { 00334 k=data[i]; 00335 while (k>i) k=data[k]; 00336 if (k<i) continue; 00337 // Now have k==i, i.e. the least in its cycle 00338 pk=data[k]; 00339 if (pk==i) continue; 00340 // Shuffle the elements of the cycle 00341 { 00342 double t=v[k]; 00343 while (pk!=i) { 00344 double r1=v[pk]; 00345 v[pk]=t; 00346 t=r1; 00347 k=pk; 00348 pk=data[k]; 00349 } 00350 v[pk]=t; 00351 } 00352 } 00353 return 0; 00354 } 00355 00356 // End of permutation class 00357 }; 00358 00359 /** \brief Output operator for permutations 00360 00361 A space is output between the permutation elements but no 00362 space or endline character is output after the last element. 00363 00364 If the size is zero, this function outputs nothing and does 00365 not call the error handler. 00366 */ 00367 std::ostream &operator<<(std::ostream &os, const permutation &p); 00368 00369 #ifndef DOXYGENP 00370 } 00371 #endif 00372 00373 #endif 00374
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).