Num2DArray.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // Num2DArray.h
00012 //
00021 #ifndef __Num2DArray_h
00022 #define __Num2DArray_h
00023 
00024 #ifdef __GNUC__
00025 #pragma interface
00026 #endif
00027 
00028 #ifndef ANSI_HDRS
00029 #include <math.h>
00030 #else
00031 #include <cmath>
00032 #endif
00033 
00034 #include "_math.h"
00035 #include "NumArray.h"
00036 #include "Simple2DArray.h"
00037 
00038 template <class T>
00039 class UTILIB_API Num2DArray;
00040 
00041 
00042 template <class T>
00043 Num2DArray<T> operator%    (const Num2DArray<T> & m1, const Num2DArray<T> & m2)
00044 {
00045 static Num2DArray<T> temp_mat(m1.nrows(), m2.ncols());
00046 matmult(temp_mat, m1, m2);
00047 return temp_mat;
00048 }
00049  
00050 
00051 template <class T>
00052 NumArray<T> operator%    (const Num2DArray<T> & m, const NumArray<T> & v)
00053 {
00054 static NumArray<T> temp_vec(m.nrows());
00055 matmult(temp_vec, m, v);
00056 return temp_vec;
00057 }
00058  
00059 
00060 template <class T>
00061 NumArray<T> operator%    (const NumArray<T> & v, const Num2DArray<T> & m)
00062 {
00063 static NumArray<T> temp_vec(m.ncols());
00064 matmult(temp_vec,v,m);
00065 return temp_vec;
00066 }
00067  
00068  
00069 template <class T>
00070 void matmult(Num2DArray<T>& res, const Num2DArray<T> & m1, 
00071                                         const Num2DArray<T> & m2)
00072 {
00073 if (m1.ncols() != m2.nrows())
00074    ErrAbort(errmsg("matmult: ncols(M1) != nrows(M2) %d %d",m1.ncols(),
00075                                                 m2.nrows()) );
00076 if ((res.nrows() != m1.nrows()) || (res.ncols() != m2.ncols()))
00077    ErrAbort("matmult: bad dimensions for result.");
00078  
00079 T temp;
00080 size_type M1Ncols = m1.ncols();
00081 size_type M1Nrows = m1.nrows();
00082 size_type M2Ncols = m2.ncols();
00083 for (size_type i=0; i<M1Nrows; i++){
00084   for (size_type j=0; j<M2Ncols; j++){
00085     temp = m1[i][0] * m2[0][j];
00086     for (size_type k=1; k<M1Ncols; k++){
00087       temp += m1[i][k] * m2[k][j];
00088       }
00089     res[i][j] = temp;
00090     }
00091   }
00092 }
00093  
00094 
00095 template <class T>
00096 void matmult(NumArray<T>& res, const Num2DArray<T>& m, const NumArray<T>& v)
00097 {
00098 if (m.ncols() != v.size())
00099    ErrAbort( "matmult: ncols(M) != size(V)" );
00100 if (res.size() != m.nrows())
00101    ErrAbort( "matmult: size(RES) != nrows(M)" );
00102  
00103 T temp;
00104 size_type NRows = m.nrows();
00105 size_type NCols = v.size();
00106 for (size_type i=0; i<NRows; i++) {
00107   temp = m[i][0] * v[0];
00108   for (size_type j=1; j<NCols; j++)
00109     temp += m[i][j] * v[j];
00110   res[i] = temp;
00111   }
00112 }
00113  
00114  
00115 template <class T>
00116 void matmult(NumArray<T>& res, const NumArray<T> & v, const Num2DArray<T> & m)
00117 {
00118 if (m.nrows() != v.size())
00119    ErrAbort( "matmult: size(V) != nrows(M)" );
00120 if (res.size() != m.ncols())
00121    ErrAbort( "matmult: size(RES) != ncols(M)" );
00122  
00123 T temp;
00124 size_type NRows = v.size();
00125 size_type NCols = m.ncols();
00126 for (size_type i=0; i<NCols; i++) {
00127   temp = m[0][i] * v[0];
00128   for (size_type j=1; j<NRows; j++)
00129     temp += m[j][i] * v[j];
00130   res[i] = temp;
00131   }
00132 }
00133 
00134 
00135 
00136 #ifdef SWIG
00137 template <class T>
00138 class Num2DArray: public Simple2DArray<T>
00139 #else
00140 template <class T>
00141 class UTILIB_API Num2DArray: public Simple2DArray<T>
00142 #endif
00143 {
00144 public:
00145 
00147   Num2DArray()  : Simple2DArray<T>() {}
00153   Num2DArray(const BasicArray<T>& array, const int nrows=1,
00154                 const EnumDataOwned own=DataNotOwned)
00155                 : Simple2DArray<T>(array,nrows,own) {}
00161   Num2DArray(const int nrows, const int ncols, T *d=((T*)0),
00162                 const EnumDataOwned own=DataNotOwned)
00163                 : Simple2DArray<T>(nrows,ncols,d,own) {}
00169   Num2DArray(const int nrows, const int ncols, const BasicArray<T>& array,
00170                 const EnumDataOwned own=DataNotOwned)
00171                 : Simple2DArray<T>(nrows,ncols,array,own) {}
00173   Num2DArray(const Num2DArray& array)
00174                 : Simple2DArray<T>(array) {}
00175 
00177   Num2DArray<T>& operator=(const Num2DArray<T>& array)
00178                 {Simple2DArray<T>::operator=(array); return *this;}
00180   Num2DArray<T>& operator=(const T& array)
00181                 {Simple2DArray<T>::operator=(array); return *this;}
00182  
00183 
00185   void plus  (const Num2DArray<T>& x, const Num2DArray<T>& y);
00187   void minus (const Num2DArray<T>& x, const Num2DArray<T>& y);
00189   void times (const Num2DArray<T>& x, const Num2DArray<T>& y);
00191   void divide(const Num2DArray<T>& x, const Num2DArray<T>& y);
00192 
00194   void plus  (const Num2DArray<T>& x, const NumArray<T>& y);
00196   void minus (const Num2DArray<T>& x, const NumArray<T>& y);
00198   void times (const Num2DArray<T>& x, const NumArray<T>& y);
00200   void divide(const Num2DArray<T>& x, const NumArray<T>& y);
00201 
00203   void plus  (const Num2DArray<T>& x, const T& z);
00205   void minus (const Num2DArray<T>& x, const T& z);
00207   void times (const Num2DArray<T>& x, const T& z);
00209   void divide(const Num2DArray<T>& x, const T& z);
00210 
00212   Num2DArray<T> operator-    ();
00213  
00215   Num2DArray<T>& operator+= (const Num2DArray<T>& x);
00217   Num2DArray<T>& operator-= (const Num2DArray<T>& x);
00219   Num2DArray<T>& operator*= (const Num2DArray<T>& x);
00221   Num2DArray<T>& operator/= (const Num2DArray<T>& x);
00222 
00224   Num2DArray<T>& operator+=  (const NumArray<T>& y);
00226   Num2DArray<T>& operator-=  (const NumArray<T>& y);
00228   Num2DArray<T>& operator*=  (const NumArray<T>& y);
00230   Num2DArray<T>& operator/=  (const NumArray<T>& y);
00231 
00233   Num2DArray<T>& operator+=  (const T& z);
00235   Num2DArray<T>& operator-=  (const T& z);
00237   Num2DArray<T>& operator*=  (const T& z);
00239   Num2DArray<T>& operator/=  (const T& z);
00240 
00241   friend void matmult<>(Num2DArray<T>& res, const Num2DArray<T>&, 
00242                                 const Num2DArray<T>&);
00243   friend void matmult<>(NumArray<T>& res, const Num2DArray<T>&, 
00244                                 const NumArray<T>&);
00245   friend void matmult<>(NumArray<T>& res, const NumArray<T>&, 
00246                                 const Num2DArray<T>&);
00247   friend Num2DArray<T> operator%<>(const Num2DArray<T> &, const Num2DArray<T> &);
00248   friend NumArray<T> operator%<>(const Num2DArray<T> &, const NumArray<T> &);
00249   friend NumArray<T> operator%<>(const NumArray<T> &, const Num2DArray<T> &);
00250 
00251 };
00252  
00253 
00254 
00255 
00256 #define BINARYOP(opname,pseudonym)\
00257 template <class T>\
00258 inline UTILIB_API Num2DArray<T> opname (const Num2DArray<T>& a1, const Num2DArray<T>& a2)\
00259 {\
00260 Num2DArray<T> res;\
00261 res.pseudonym(a1,a2);\
00262 return res;\
00263 }\
00264 \
00265 template <class T>\
00266 inline UTILIB_API Num2DArray<T> opname (const Num2DArray<T>& a1, const NumArray<T>& val)\
00267 {\
00268 Num2DArray<T> res;\
00269 res.pseudonym(a1,val);\
00270 return res;\
00271 }\
00272 \
00273 template <class T>\
00274 inline UTILIB_API Num2DArray<T> opname (const NumArray<T>& val, const Num2DArray<T>& a1)\
00275 {\
00276 Num2DArray<T> res;\
00277 res.pseudonym(a1,val);\
00278 return res;\
00279 }\
00280 \
00281 template <class T>\
00282 inline UTILIB_API Num2DArray<T> opname (const Num2DArray<T>& a1, const T& val)\
00283 {\
00284 Num2DArray<T> res;\
00285 res.pseudonym(a1,val);\
00286 return res;\
00287 }\
00288 \
00289 template <class T>\
00290 inline UTILIB_API Num2DArray<T> opname (const T& val, const Num2DArray<T>& a1)\
00291 {\
00292 Num2DArray<T> res;\
00293 res.pseudonym(a1,val);\
00294 return res;\
00295 }
00296 
00297 BINARYOP( operator+ , plus )
00298 BINARYOP( operator- , minus )
00299 BINARYOP( operator* , times )
00300 BINARYOP( operator/ , divide )
00301 
00302 #undef BINARYOP
00303 
00304 
00305 #define BINARYOP(opname,op1,pseudonym, op)\
00306 template <class T>\
00307 void Num2DArray<T>::pseudonym(const Num2DArray<T>& a1, const Num2DArray<T>& a2)\
00308 {\
00309 if ((a1.nrows() != a2.nrows()) || (a1.ncols() != a2.ncols()))\
00310    ErrAbort(errmsg("Num2DArray<T>::pseudonym : Unequal 2D array sizes %dx%d and %dx%d",a1.nrows(),a1.ncols(),a2.nrows(),a2.ncols()));\
00311 resize(a1.nrows(),a2.ncols());\
00312 for (size_type i=0; i<a->Nrows; i++)\
00313   for (size_type j=0; j<a->Ncols; j++)\
00314     a->Data[i][j] = a1[i][j] op a2[i][j];\
00315 }\
00316 \
00317 template <class T>\
00318 void Num2DArray<T>::pseudonym(const Num2DArray<T>& a1, const NumArray<T>& array)\
00319 {\
00320 if (a1.ncols() != array.size())\
00321    ErrAbort(errmsg("Num2DArray<T>::pseudonym : Number of columns %d does not equal array length %d", a1.ncols(), array.size()));\
00322 resize(a1.nrows(),a1.ncols());\
00323 for (size_type i=0; i<a->Nrows; i++)\
00324   for (size_type j=0; j<a->Ncols; j++)\
00325     a->Data[i][j] = a1[i][j] op array[j];\
00326 }\
00327 \
00328 template <class T>\
00329 void Num2DArray<T>::pseudonym(const Num2DArray<T>& a1, const T& val)\
00330 {\
00331 resize(a1.nrows(),a1.ncols());\
00332 for (size_type i=0; i<a->Nrows; i++)\
00333   for (size_type j=0; j<a->Ncols; j++)\
00334     a->Data[i][j] = a1[i][j] op val;\
00335 }\
00336 template <class T>\
00337 Num2DArray<T>& Num2DArray<T>::opname(const Num2DArray<T>& a1)\
00338 {\
00339 if ((nrows() != a1.nrows()) || (ncols() != a1.ncols()))\
00340    ErrAbort(errmsg("Num2DArray<T>::opname : Unequal 2D array sizes %dx%d and %dx%d",nrows(),ncols(),a1.nrows(),a1.ncols()));\
00341 for (size_type i=0; i<nrows(); i++)\
00342   for (size_type j=0; j<ncols(); j++)\
00343     a->Data[i][j] op1 a1.a->Data[i][j];\
00344 return *this;\
00345 }\
00346 \
00347 template <class T>\
00348 Num2DArray<T>& Num2DArray<T>::opname(const NumArray<T>& a1)\
00349 {\
00350 if (ncols() != a1.size())\
00351    ErrAbort(errmsg("Num2DArray<T>::opname : Number of columns %d does not equal array length %d", ncols(), a1.size()));\
00352 for (size_type i=0; i<nrows(); i++)\
00353   for (size_type j=0; j<ncols(); j++)\
00354     a->Data[i][j] op1 a1.data()[j];\
00355 return *this;\
00356 }\
00357 \
00358 template <class T>\
00359 Num2DArray<T>& Num2DArray<T>::opname(const T& val)\
00360 {\
00361 for (size_type i=0; i<nrows(); i++)\
00362   for (size_type j=0; j<ncols(); j++)\
00363     a->Data[i][j] op1 val;\
00364 return *this;\
00365 }
00366 
00367 BINARYOP(operator+=,+=,plus, + )
00368 BINARYOP(operator-=,-=,minus, - )
00369 BINARYOP(operator*=,*=,times, * )
00370 BINARYOP(operator/=,/=,divide, / )
00371 
00372 #undef BINARYOP
00373 
00374 
00375 template <class T>
00376 Num2DArray<T> Num2DArray<T>::operator-    ()
00377 {
00378 Num2DArray<T> res;
00379 for (size_type i=0; i<a->Nrows; i++)
00380   for (size_type j=0; j<a->Ncols; j++)
00381     res.a->Data[i][j] = - a->Data[i][j];
00382 return res;
00383 }
00384 
00385 
00386 #endif