Vector.h

Go to the documentation of this file.
00001 //
00002 //  Copyright (C) 2004-2008 Greg Landrum and Rational Discovery LLC
00003 //
00004 //   @@ All Rights Reserved  @@
00005 //
00006 #ifndef __RD_VECTOR_H__
00007 #define __RD_VECTOR_H__
00008 
00009 #include <RDGeneral/Invariant.h>
00010 #include <RDGeneral/utils.h>
00011 #include <math.h>
00012 #include <iostream>
00013 #include <iomanip>
00014 #include <cstdlib>
00015 #include <time.h>
00016 #include <boost/random.hpp>
00017 #include <boost/smart_ptr.hpp>
00018 
00019 namespace RDNumeric {
00020 
00021   
00022   //! A class to represent vectors of numbers.
00023   template <class TYPE> class Vector {
00024     
00025   public:
00026 
00027     typedef boost::shared_array<TYPE> DATA_SPTR;
00028 
00029     //! Initialize with only a size.
00030     explicit Vector(unsigned int N) {
00031       d_size = N;
00032       TYPE *data = new TYPE[N];
00033       memset(static_cast<void *>(data),0,d_size*sizeof(TYPE));
00034       d_data.reset(data);
00035     }
00036     
00037     //! Initialize with a size and default value.
00038     Vector(unsigned int N, TYPE val) { //: Vector(N) {
00039       d_size = N;
00040       TYPE *data = new TYPE[N];
00041       
00042       unsigned int i;
00043       for (i = 0; i < N; i++) {
00044         data[i] = val;
00045       }
00046       d_data.reset(data);
00047     }
00048 
00049     //! Initialize from a smart pointer.
00050     /*!
00051       <b>NOTE:</b> the data is not copied in this case
00052     */
00053     Vector(unsigned int N, DATA_SPTR data) {//TYPE *data) {
00054       d_size = N;
00055       d_data = data;
00056     }
00057 
00058     //! copy constructor
00059     /*! We make a copy of the other vector's data.
00060      */
00061     Vector(const Vector &other) {
00062       d_size = other.size();
00063       const TYPE *otherData = other.getData();
00064       TYPE *data = new TYPE[d_size];
00065             
00066       memcpy(static_cast<void *>(data), static_cast<const void *>(otherData), d_size*sizeof(TYPE));
00067       d_data.reset(data);
00068     }
00069       
00070     ~Vector() {
00071     }
00072 
00073     //! return the size (dimension) of the vector
00074     unsigned int size() const {
00075       return d_size;
00076     }
00077 
00078     //! returns the value at a particular index
00079     inline TYPE getVal(unsigned int i) const {
00080       RANGE_CHECK(0, i, d_size-1);
00081       return d_data[i];
00082     }
00083 
00084     //! sets the index at a particular value
00085     inline void setVal(unsigned int i, TYPE val) {
00086       RANGE_CHECK(0, i, d_size-1);
00087       d_data[i] = val;
00088     }
00089 
00090     inline TYPE operator[](unsigned int i) const {
00091       RANGE_CHECK(0, i, d_size-1);
00092       return d_data[i];
00093     }
00094 
00095     inline TYPE& operator[](unsigned int i) {
00096       RANGE_CHECK(0, i, d_size-1);
00097       return d_data[i];
00098     }
00099 
00100     //! returns a pointer to our data array
00101     inline TYPE *getData() {
00102       return d_data.get();
00103     }
00104 
00105     //! returns a const pointer to our data array
00106     inline const TYPE *getData() const {
00107       //return dp_data;
00108       return d_data.get();
00109     }
00110 
00111     //! Copy operator.
00112     /*! We make a copy of the other Vector's data.
00113      */
00114     
00115     Vector<TYPE>& assign(const Vector<TYPE> &other) {
00116       CHECK_INVARIANT(d_size == other.size(), "Size mismatch in vector copying");
00117       const TYPE *otherData = other.getData();
00118       memcpy(static_cast<void *>(d_data.get()), static_cast<const void *>(otherData), d_size*sizeof(TYPE));
00119       return *this;
00120     }
00121 
00122     //! elementwise addition, vectors must be the same size.
00123     Vector<TYPE>& operator+=(const Vector<TYPE> &other) {
00124       CHECK_INVARIANT(d_size == other.size(), "Size mismatch in vector addition");
00125       const TYPE *otherData = other.getData();
00126       TYPE *data = d_data.get();
00127       unsigned int i;
00128       for (i = 0; i < d_size; i++) {
00129         data[i] += otherData[i];
00130       }
00131       return *this;
00132     }
00133 
00134     //! elementwise subtraction, vectors must be the same size.
00135     Vector<TYPE>& operator-=(const Vector<TYPE> &other) {
00136       CHECK_INVARIANT(d_size == other.size(), "Size mismatch in vector subtraction");
00137       const TYPE *otherData = other.getData();
00138       TYPE *data = d_data.get();
00139       unsigned int i;
00140       for (i = 0; i < d_size; i++) {
00141         data[i] -= otherData[i];
00142       }
00143       return *this;
00144     }
00145 
00146     //! multiplication by a scalar
00147     Vector<TYPE>& operator *=(TYPE scale) {
00148       unsigned int i;
00149       for (i = 0; i < d_size; i++) {
00150         d_data[i] *= scale;
00151       }
00152       return *this;
00153     }
00154 
00155     //! division by a scalar
00156     Vector<TYPE>& operator /=(TYPE scale) {
00157       unsigned int i;
00158       for (i = 0; i < d_size; i++) {
00159         d_data[i] /= scale;
00160       }
00161       return *this;
00162     }
00163 
00164     //! L2 norm squared
00165     inline TYPE normL2Sq() const {
00166       TYPE res = (TYPE)0.0;
00167       unsigned int i;
00168       TYPE *data = d_data.get();
00169       for (i = 0; i < d_size; i++) {
00170         res += data[i]*data[i];
00171       }
00172       return res;
00173     }
00174 
00175     //! L2 norm
00176     inline TYPE normL2() const {
00177       return sqrt(this->normL2Sq());
00178     }
00179     
00180     //! L1 norm
00181     inline TYPE normL1() const {
00182       TYPE res = (TYPE)0.0;
00183       unsigned int i;
00184       TYPE *data = d_data.get();
00185       for (i = 0; i < d_size; i++) {
00186         res += fabs(data[i]);
00187       }
00188       return res;
00189     }
00190 
00191     //! L-infinity norm
00192     inline TYPE normLinfinity() const {
00193       TYPE res = (TYPE)(-1.0);
00194       unsigned int i;
00195       TYPE *data = d_data.get();
00196       for (i = 0; i < d_size; i++) {
00197         if (fabs(data[i]) > res) {
00198           res = fabs(data[i]);
00199         }
00200       }
00201       return res;
00202     }
00203 
00204     //! \brief Gets the ID of the entry that has the largest absolute value
00205     //! i.e. the entry being used for the L-infinity norm
00206     inline unsigned int largestAbsValId() const {
00207       TYPE res = (TYPE)(-1.0);
00208       unsigned int i, id=d_size;
00209       TYPE *data = d_data.get();
00210       for (i = 0; i < d_size; i++) {
00211         if (fabs(data[i]) > res) {
00212           res = fabs(data[i]);
00213           id = i;
00214         }
00215       }
00216       return id;
00217     }
00218 
00219     //! \brief Gets the ID of the entry that has the largest value
00220     inline unsigned int largestValId() const {
00221       TYPE res = (TYPE)(-1.e8);
00222       unsigned int i, id=d_size;
00223       TYPE *data = d_data.get();
00224       for (i = 0; i < d_size; i++) {
00225         if (data[i] > res) {
00226           res = data[i];
00227           id = i;
00228         }
00229       }
00230       return id;
00231     }
00232 
00233     //! returns the dot product between two Vectors
00234     inline TYPE dotProduct(const Vector<TYPE> other) {
00235       CHECK_INVARIANT(d_size == other.size(), "Size mismatch in vector doct product");
00236       const TYPE *oData = other.getData();
00237       unsigned int i;
00238       TYPE res = (TYPE)(0.0);
00239       TYPE *data = d_data.get();
00240       for (i = 0; i < d_size; i++) {
00241         res += (data[i]*oData[i]);
00242       }
00243       return res;
00244     }
00245 
00246     //! Normalize the vector using the L2 norm
00247     inline void normalize() {
00248       TYPE val = this->normL2();
00249       (*this) /= val;
00250     }
00251 
00252     //! Set to a random unit vector
00253     inline void setToRandom(unsigned int seed=0) {
00254       // we want to get our own RNG here instead of using the global
00255       // one.  This is related to Issue285.
00256       RDKit::rng_type generator(42u);
00257       RDKit::uniform_double dist(0,1.0);
00258       RDKit::double_source_type randSource(generator,dist);
00259       if (seed > 0) {
00260         generator.seed(seed);
00261       } else {
00262         // we can't initialize using only clock(), because it's possible
00263         // that we'll get here fast enough that clock() will return 0
00264         // and generator.seed(0) is an error:
00265         generator.seed(clock()+1);
00266       }
00267             
00268       unsigned int i;
00269       TYPE *data = d_data.get();
00270       for (i = 0; i < d_size; i++) {
00271         data[i] = randSource();
00272       }
00273       this->normalize();
00274     }
00275       
00276   private:
00277     unsigned int d_size;     //! < our length
00278     DATA_SPTR d_data;
00279     Vector<TYPE>& operator=(const Vector<TYPE> &other);
00280   };
00281 
00282   typedef Vector<double> DoubleVector;
00283 }
00284 
00285 //! ostream operator for Vectors
00286 template <typename TYPE> std::ostream & operator<<(std::ostream& target, 
00287                                                    const RDNumeric::Vector<TYPE> &vec) {
00288   unsigned int siz = vec.size();
00289   target << "Size: " << siz << " [";
00290   unsigned int i;
00291   for (i = 0; i < siz; i++) {
00292     target << std::setw(7) << std::setprecision(3) << vec.getVal(i) << ", ";
00293   }
00294   target << "]\n";
00295   return target;
00296 }
00297 
00298 #endif
00299 
00300     

Generated on Sat May 24 08:36:32 2008 for RDCode by  doxygen 1.5.3