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

Generated on Tue Oct 7 06:10:11 2008 for RDCode by  doxygen 1.5.5