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