MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/linalg/vector.h
Go to the documentation of this file.
00001 /************************************************************************
00002  * MechSys - Open Library for Mechanical Systems                        *
00003  * Copyright (C) 2005 Dorival M. Pedroso, Raúl D. D. Farfan             *
00004  *                                                                      *
00005  * This program is free software: you can redistribute it and/or modify *
00006  * it under the terms of the GNU General Public License as published by *
00007  * the Free Software Foundation, either version 3 of the License, or    *
00008  * any later version.                                                   *
00009  *                                                                      *
00010  * This program is distributed in the hope that it will be useful,      *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
00013  * GNU General Public License for more details.                         *
00014  *                                                                      *
00015  * You should have received a copy of the GNU General Public License    *
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>  *
00017  ************************************************************************/
00018 
00019 #ifndef MECHSYS_LINALG_VECTOR_H
00020 #define MECHSYS_LINALG_VECTOR_H
00021 
00022 // STL
00023 #include <iostream>
00024 #include <cmath>
00025 
00026 // MechSys
00027 #include <mechsys/util/fatal.h>
00028 
00029 extern "C"
00030 {
00031     // BLAS
00032     void dscal_(int const *N, double const *alpha, double *X, int const *incX);
00033     void dcopy_(int const *N, double const *X, int const *incX, double *Y, int const *incY);
00034     void daxpy_(int const *N, double const *alpha, double const *X, int const *incX, double *Y, int const *incY);
00035 }
00036 
00037 namespace LinAlg
00038 {
00039 
00040 // Prototype for expression classes
00041 template <class t_exp, class t_res>
00042 class expression; // should not be called (directly) by the user
00043 
00051 template<typename Value_T>
00052 class Vector
00053 {
00054 public:
00055     // Constructors
00056     Vector () : _size(0), _values(NULL), data(_values) {}  
00057     Vector (int Size);                                     
00058     Vector (Vector<Value_T> const & Other);                
00059 
00061     ~Vector () { if (_values!=NULL) delete [] _values; }
00062 
00063     // Access methods
00064     int             Size   () const; 
00065     Value_T const * GetPtr () const; 
00066     Value_T       * GetPtr ();       
00067 
00068     // Methods
00069     void Resize     (int Size);       
00070     void change_dim (int Size) { Resize(Size); }
00071     void SetValues  (Value_T Value);  
00072 
00073     // Operators
00074     void            operator=  (Vector<Value_T> const & R); 
00075     void            operator+= (Vector<Value_T> const & R); 
00076     void            operator-= (Vector<Value_T> const & R); 
00077     void            operator/= (Value_T const & Scalar);    
00078     void            operator*= (Value_T const & Scalar);    
00079     Value_T &       operator() (int i);                     
00080     const Value_T & operator() (int i) const;               
00081 
00082     // Auxiliar structures
00083     // operator to assign values separated by commas \cond
00084     class CommaAssign
00085     {
00086     public:
00087         CommaAssign(Value_T * Values, int & Size, Value_T const & FirstValue):_values(Values),_size(Size),_index(0) 
00088         { 
00089             if (_values==NULL) throw new Fatal("Vector::CommaAssign::CommaAssign (_values==NULL). The vector must be resized before calling this method.");
00090             _values[0] = FirstValue;
00091             for (int i=1; i<_size; ++i)
00092                 _values[i] = static_cast<Value_T>(0);
00093         }
00094         CommaAssign & operator, (Value_T const & Num) 
00095         {
00096             _index++;
00097             if (_index>=_size) throw new Fatal("Vector::CommaAssign::operator, (_index>=_size). There are too many values in the comma expression to be assigned to this vector.");
00098             _values[_index] = Num;
00099             return *this;
00100         }
00101     private:
00102         Value_T * _values;
00103         int     & _size;
00104         int       _index;
00105     };
00106 
00107     CommaAssign operator= (Value_T const & Num) 
00108     {
00109         return CommaAssign(_values, _size, Num);
00110     }
00111 
00112     // Methods required by the expressions evaluation
00113     template<typename t_exp>
00114     void operator= (const expression<t_exp, Vector<Value_T> > & Exp) { Exp.Apply(*this); } 
00115 
00116     template<typename t_exp>
00117     void operator+= (const expression<t_exp, Vector<Value_T> > & Exp) { Exp.Apply_pe(*this); } 
00118 
00119     template<typename t_exp>
00120     void operator-= (const expression<t_exp, Vector<Value_T> > & Exp) { Exp.Apply_me(*this); }
00121     // \endcond
00122 
00123 private:
00124     // Data
00125     int       _size;   
00126     Value_T * _values; 
00127 
00128 public:
00129     Value_T * data;
00130 
00131 }; // class Vector
00132 
00133 
00135 
00136 
00137 // Constructors
00138 
00139 template<typename Value_T>
00140 inline Vector<Value_T>::Vector(int Size)
00141     : _size(0), _values(NULL), data(_values)
00142 {
00143     if (Size>0)
00144     {
00145         _size   = Size;
00146         _values = new Value_T [_size];
00147         for (int i=0; i<_size; ++i) _values[i] = static_cast<Value_T>(0);
00148         data = _values;
00149     }
00150 }
00151 
00152 template<typename Value_T>
00153 inline Vector<Value_T>::Vector(Vector<Value_T> const & R)
00154     : _size(R.Size()), _values(NULL), data(_values)
00155 {
00156     if (_size>0)
00157     {
00158         // allocate memory
00159         _values = new Value_T [_size];
00160         data    = _values;
00161 
00162         // copy
00163         int i = 1;
00164         int j = 1;
00165         dcopy_ (&_size, R.GetPtr(), &i, _values, &j);
00166     }
00167 }
00168 
00169 // Access methods
00170 
00171 template<typename Value_T>
00172 inline int Vector<Value_T>::Size() const
00173 {
00174     return _size;
00175 }
00176 
00177 template<typename Value_T>
00178 inline const Value_T * Vector<Value_T>::GetPtr() const
00179 {
00180 #ifndef DNDEBUG
00181     //if (_values==NULL) throw new Fatal("Vector::Size: (_values==NULL). The vector must be resized before getting the pointer to its values.");
00182 #endif
00183     return _values;
00184 }
00185 
00186 template<typename Value_T>
00187 inline Value_T * Vector<Value_T>::GetPtr()
00188 {
00189 #ifndef DNDEBUG
00190     //if (_values==NULL) throw new Fatal("Vector::Size: (_values==NULL). The vector must be resized before getting the pointer to its values.");
00191 #endif
00192     return _values;
00193 }
00194 
00195 // Methods
00196     
00197 template<typename Value_T>
00198 inline void Vector<Value_T>::Resize(int Size)
00199 {
00200     if (Size>0)
00201     {
00202         if (Size==_size && _values!=NULL) return;   
00203         if (_values!=NULL) delete [] _values;
00204         _size   = Size;
00205         _values = new Value_T [_size];
00206         data    = _values;
00207         for (int i=0; i<_size; ++i) _values[i] = static_cast<Value_T>(0);
00208     }
00209     else
00210     {
00211         if (_values!=NULL) delete [] _values;
00212         _size   = 0;
00213         _values = NULL;
00214         data    = _values;
00215     }
00216 }
00217 
00218 template<typename Value_T>
00219 inline void Vector<Value_T>::SetValues(Value_T Value)
00220 {
00221 #ifndef DNDEBUG
00222     if (_values==NULL) throw new Fatal("Vector::SetValues: (_values==NULL). The vector must be resized before setting its values.");
00223 #endif
00224     for (int i=0; i<_size; ++i)
00225         _values[i] = Value; 
00226 }
00227 
00228 // Operators
00229 
00230 template<typename Value_T>
00231 inline void Vector<Value_T>::operator= (Vector<Value_T> const & R)
00232 {
00233 #ifndef DNDEBUG
00234     if (&R==this) throw new Fatal("Vector::operator= The right-hand-size of this operation (LHS = RHS) must not be equal to the LHS.");
00235 #endif
00236 
00237     // reallocate if they are different (LHS != RHS)
00238     if (_values==NULL || R.Size()!=_size)
00239     {
00240         _size = R.Size();
00241         if (_values!=NULL) delete [] _values;
00242         _values = new Value_T [_size];
00243         data    = _values;
00244     }
00245 
00246     // copy
00247     int i = 1;
00248     int j = 1;
00249     dcopy_ (&_size, R.GetPtr(), &i, _values, &j);
00250 }
00251 
00252 template<typename Value_T>
00253 inline void Vector<Value_T>::operator+= (Vector<Value_T> const & R)
00254 {
00255 #ifndef DNDEBUG
00256     if (_values==NULL  ) return;//throw new Fatal("Vector::operator+= (_values==NULL). The vector must be resized before calling this method.");
00257     if (R.Size()!=_size) throw new Fatal("Vector::operator+= (R.Size()!=_size). The number of components of the LHS (%d) must be equal to the number of components of the RHS (%d).",R.Size(),_size);
00258 #endif
00259     Value_T a = 1.0;
00260     int     i = 1;
00261     int     j = 1;
00262     daxpy_ (&_size, &a, R.GetPtr(), &i, _values, &j);
00263 }
00264 
00265 template<typename Value_T>
00266 inline void Vector<Value_T>::operator-= (Vector<Value_T> const & R)
00267 {
00268 #ifndef DNDEBUG
00269     if (_values==NULL  ) return;//throw new Fatal("Vector::operator-= (_values==NULL). The vector must be resized before calling this method.");
00270     if (R.Size()!=_size) throw new Fatal("Vector::operator-= (R.Size()!=_size). The number of components of the LHS (%d) must be equal to the number of components of the RHS (%d).",R.Size(),_size);
00271 #endif
00272     Value_T a = -1.0;
00273     int     i = 1;
00274     int     j = 1;
00275     daxpy_ (&_size, &a, R.GetPtr(), &i, _values, &j);
00276 }
00277 
00278 template<typename Value_T>
00279 inline void Vector<Value_T>::operator/= (Value_T const & Scalar)
00280 {
00281 #ifndef DNDEBUG
00282     if (_values==NULL) return;//throw new Fatal("Vector::operator/= (_values==NULL). The vector must be resized before calling this method.");
00283 #endif
00284     Value_T a = 1.0/Scalar;
00285     int     d = 1;
00286     dscal_ (&_size, &a, _values, &d);
00287 }
00288 
00289 template<typename Value_T>
00290 inline void Vector<Value_T>::operator*= (Value_T const & Scalar)
00291 {
00292 #ifndef DNDEBUG
00293     if (_values==NULL) return;//throw new Fatal("Vector::operator*= (_values==NULL). The vector must be resized before calling this method.");
00294 #endif
00295     Value_T a = Scalar;
00296     int     d = 1;
00297     dscal_ (&_size, &a, _values, &d);
00298 }
00299 
00300 template<typename Value_T>
00301 inline Value_T & Vector<Value_T>::operator() (int i)
00302 {
00303 #ifndef DNDEBUG
00304     if (_values==NULL  ) throw new Fatal("Vector::operator() (_values==NULL). The vector must be resized before calling this method.");
00305     if (i<0 || i>=_size) throw new Fatal("Vector::operator() (i<0 || i>=_size). The index (i=%d) for a component must be greater than/or equal to zero and smaller than the number of components (size=%d).",i,_size);
00306 #endif
00307     return _values[i];
00308 }
00309 
00310 template<typename Value_T>
00311 inline const Value_T & Vector<Value_T>::operator() (int i) const
00312 {
00313 #ifndef DNDEBUG
00314     if (_values==NULL  ) throw new Fatal("Vector::operator() (_values==NULL). The vector must be resized before calling this method.");
00315     if (i<0 || i>=_size) throw new Fatal("Vector::operator() (i<0 || i>=_size). The index (i=%d) for a component must be greater than/or equal to zero and smaller than the number of components (size=%d).",i,_size);
00316 #endif
00317     return _values[i];
00318 }
00319 
00321 template<typename Value_T>
00322 std::ostream & operator<< (std::ostream & os, const LinAlg::Vector<Value_T> & V)
00323 {
00324     for (int i=0; i<V.Size(); ++i) os << V(i) << " ";
00325     os << std::endl;
00326     return os;
00327 }
00328 
00329 
00330 }; // namespace LinAlg
00331 
00332 #endif // MECHSYS_LINALG_VECTOR_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines