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