![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
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