permutation.h

Go to the documentation of this file.
00001 
00002 /*
00003   -------------------------------------------------------------------
00004   
00005   Copyright (C) 2006, 2007, 2008, Andrew W. Steiner
00006   
00007   This file is part of O2scl.
00008   
00009   O2scl is free software; you can redistribute it and/or modify
00010   it under the terms of the GNU General Public License as published by
00011   the Free Software Foundation; either version 3 of the License, or
00012   (at your option) any later version.
00013   
00014   O2scl is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017   GNU General Public License for more details.
00018   
00019   You should have received a copy of the GNU General Public License
00020   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00021 
00022   -------------------------------------------------------------------
00023 */
00024 #ifndef O2SCL_PERMUTATION_H
00025 #define O2SCL_PERMUTATION_H
00026 
00027 /** \file permutation.h
00028     \brief File for definitions of vectors
00029 */
00030 
00031 #include <iostream>
00032 #include <cstdlib>
00033 #include <string>
00034 #include <fstream>
00035 #include <sstream>
00036 #include <vector>
00037 #include <gsl/gsl_vector.h>
00038 #include <gsl/gsl_permutation.h>
00039 #include <o2scl/err_hnd.h>
00040 #include <o2scl/string_conv.h>
00041 #include <o2scl/uvector_tlate.h>
00042 #include <o2scl/array.h>
00043 
00044 #ifndef DOXYGENP
00045 namespace o2scl {
00046 #endif
00047 
00048   /** 
00049       \brief A permutation
00050   */
00051   class permutation : public gsl_permutation_struct {
00052     
00053   public:
00054     
00055     permutation(size_t dim=0) {
00056       gsl_permutation_struct::size=dim;
00057       if (dim>0) {
00058         data=(size_t *)malloc(dim*sizeof(size_t));
00059       }
00060     }
00061 
00062     /// \name Copy constructors
00063     //@{
00064     permutation(const permutation &v) {
00065       gsl_permutation_struct::size=v.size();
00066       data=new size_t[gsl_permutation_struct::size];
00067       for(size_t i=0;i<gsl_permutation_struct::size;i++) {
00068         data[i]=v.data[i];
00069       }
00070     }
00071     
00072     permutation& operator=(const permutation &v) {
00073       gsl_permutation_struct::size=v.size();
00074       data=new size_t[gsl_permutation_struct::size];
00075       for(size_t i=0;i<gsl_permutation_struct::size;i++) {
00076         data[i]=v.data[i];
00077       }
00078       return *this;
00079     }
00080     //@}
00081 
00082     ~permutation() {
00083       if (gsl_permutation_struct::size>0) {
00084         std::free(data);
00085         gsl_permutation_struct::size=0;
00086       }
00087     };
00088 
00089     /** \brief Get (with optional range-checking) */
00090     size_t get(size_t i) const {
00091 #if O2SCL_NO_RANGE_CHECK
00092 #else
00093       if (i>=gsl_permutation_struct::size) {
00094         set_err((((std::string)"Permutation index ")+itos(i)+" out of bounds"
00095                  +" in permutation::get(). Size: "+
00096                  itos(gsl_permutation_struct::size)+
00097                  " (index should be less than size).").c_str(),gsl_index);
00098         return 0;
00099       }
00100 #endif
00101       return data[i];
00102     }
00103     
00104     /** \brief Set (with optional range-checking) */
00105     int set(size_t i, size_t val) {
00106 #if O2SCL_NO_RANGE_CHECK
00107 #else
00108       if (i>=gsl_permutation_struct::size) {
00109         set_err_ret((((std::string)"Permutation index ")+itos(i)+
00110                      " out of bounds"+" in permutation::set(). Size: "+
00111                      itos(gsl_permutation_struct::size)+
00112                      " (index should be less than size).").c_str(),gsl_index);
00113       }
00114 #endif
00115       data[i]=val;
00116       return 0;
00117     }
00118 
00119     /// Initialize permutation to the identity
00120     int init() {
00121       for(size_t i=0;i<gsl_permutation_struct::size;i++) data[i]=i;
00122       return 0;
00123     }
00124 
00125     /** 
00126         \brief Return permutation size 
00127         
00128         If no memory has been allocated, this will quietly 
00129         return zero.
00130     */
00131     size_t size() const {
00132       return gsl_permutation_struct::size;
00133     }
00134 
00135     /** \brief Allocate memory for a permutation of size \c dim
00136     */
00137     int allocate(size_t dim) {
00138       if (gsl_permutation_struct::size!=dim && 
00139           gsl_permutation_struct::size>0) free();
00140       gsl_permutation_struct::size=dim;
00141       if (dim>0) {
00142         data=(size_t *)malloc(dim*sizeof(size_t));
00143       }
00144       return 0;
00145     }
00146 
00147     /** 
00148         \brief Free the memory 
00149         
00150         This function will safely do nothing if used without first
00151         allocating memory or if called multiple times in succession.
00152     */
00153     int free() {
00154       if (gsl_permutation_struct::size>0) {
00155         std::free(data);
00156         gsl_permutation_struct::size=0;
00157       }
00158       return 0;
00159     }
00160     //@}
00161 
00162     /// Swap two elements of a permutation
00163     int swap(const size_t i, const size_t j) {
00164       size_t tmp=data[i];
00165       data[i]=data[j];
00166       data[j]=tmp;
00167       return 0;
00168     }
00169 
00170     /// Check to see that a permutation is valid
00171     bool valid() {
00172       for(size_t i=0;i<gsl_permutation_struct::size;i++) {
00173         if (data[i]>gsl_permutation_struct::size) return false;
00174         for(size_t j=0;j<i;j++) {
00175           if (data[i]==data[j]) return false;
00176         }
00177       }
00178       return true;
00179     }
00180 
00181     /// Reverse the permutation
00182     int reverse() {
00183       size_t i;
00184       for (i = 0; i < (gsl_permutation_struct::size / 2); i++){
00185         size_t j = gsl_permutation_struct::size - i - 1;
00186         
00187         size_t tmp = this->data[i] ;
00188         this->data[i] = this->data[j] ;
00189         this->data[j] = tmp ;
00190       }
00191       return 0;
00192     }
00193 
00194     /// Compute the inverse of a permutation
00195     permutation inverse() {
00196       permutation p(gsl_permutation_struct::size);
00197       for(size_t i=0;i<gsl_permutation_struct::size;i++) {
00198         p.data[data[i]]=i;
00199       }
00200       return p;
00201     }
00202     
00203     /// Apply the permutation to a vector
00204     template<class vec_t> int apply(vec_t &v) {
00205       size_t i, k, pk;
00206       for(i=0;i<gsl_permutation_struct::size;i++) {
00207         k=data[i];
00208         while (k>i) k=data[k];
00209         if (k<i) continue;
00210         /// Now have k==i, i.e. the least in its cycle
00211         pk=data[k];
00212         if (pk==i) continue;
00213         // Shuffle the elements of the cycle
00214         {
00215           double t=v[i];
00216           while (pk!=i) {
00217             double r1=v[pk];
00218             v[k]=r1;
00219             k=pk;
00220             pk=data[k];
00221           }
00222           v[k]=t;
00223         }
00224       }
00225       return 0;
00226     }
00227 
00228     /// Apply the permutation to a vector
00229     template<class vec_t> int apply_inverse(vec_t &v) {
00230       size_t i, k, pk;
00231       for(i=0;i<gsl_permutation_struct::size;i++) {
00232         k=data[i];
00233         while (k>i) k=data[k];
00234         if (k<i) continue;
00235         /// Now have k==i, i.e. the least in its cycle
00236         pk=data[k];
00237         if (pk==i) continue;
00238         // Shuffle the elements of the cycle
00239         {
00240           double t=v[k];
00241           while (pk!=i) {
00242             double r1=v[pk];
00243             v[pk]=t;
00244             t=r1;
00245             k=pk;
00246             pk=data[k];
00247           }
00248           v[pk]=t;
00249         }
00250       }
00251       return 0;
00252     }
00253 
00254   };
00255 
00256 #ifndef DOXYGENP
00257 }
00258 #endif
00259 
00260 #endif
00261 

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page