Object-oriented Scientific Computing Library: Version 0.910
permutation.h
Go to the documentation of this file.
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 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.