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