casa
$Rev:20696$
|
00001 //# Matrix.h: A 2-D Specialization of the Array Class 00002 //# Copyright (C) 1993,1994,1995,1996,1999,2000,2001,2003 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: Matrix.h 21130 2011-10-18 07:39:05Z gervandiepen $ 00027 00028 #ifndef CASA_MATRIX_H 00029 #define CASA_MATRIX_H 00030 00031 00032 //# Includes 00033 #include <casa/Arrays/Array.h> 00034 00035 namespace casa { //#Begin casa namespace 00036 00037 //# Forward Declarations 00038 template<class T> class Vector; 00039 00040 00041 // <summary> A 2-D Specialization of the Array class </summary> 00042 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00043 // </reviewed> 00044 // 00045 // Matrix objects are two-dimensional specializations (e.g., more convenient 00046 // and efficient indexing) of the general Array class. You might also want 00047 // to look at the Array documentation to see inherited functionality. A 00048 // tutorial on using the array classes in general is available in the 00049 // "AIPS++ Programming Manual". 00050 // 00051 // Generally the member functions of Array are also available in 00052 // Matrix versions which take a pair of integers where the array 00053 // needs an IPosition. Since the Matrix 00054 // is two-dimensional, the IPositions are overkill, although you may 00055 // use those versions if you want to. 00056 // <srcblock> 00057 // Matrix<Int> mi(100,100); // Shape is 100x100 00058 // mi.resize(50,50); // Shape now 50x50 00059 // </srcblock> 00060 // 00061 // Slices may be taken with the Slice class. To take a slice, one "indexes" 00062 // with one Slice(start, length, inc) for each axis, 00063 // where end and inc are optional. 00064 // Additionally, there are row(), column() and diagonal() 00065 // member functions which return Vector's which refer to the storage back 00066 // in the Matrix: 00067 // <srcblock> 00068 // Matrix<Float> mf(100, 100); 00069 // mf.diagonal() = 1; 00070 // </srcblock> 00071 // 00072 // Correct indexing order of a matrix is: 00073 // <srcblock> 00074 // Matrix<Int> mi(n1,n2) // [nrow, ncolumn] 00075 // for (uInt j=0; j<mi.ncolumn(); j++) { 00076 // for (uInt i=0; i<mi.nrow(); i++) { 00077 // mi(i,j) = i*j; 00078 // } 00079 // } 00080 // </srcblock> 00081 // 00082 // 00083 // Element-by-element arithmetic and logical operations are available (in 00084 // aips/ArrayMath.h and aips/ArrayLogical.h). Other Matrix operations (e.g. 00085 // LU decomposition) are available, and more appear periodically. 00086 // 00087 // As with the Arrays, if the preprocessor symbol AIPS_DEBUG is 00088 // defined at compile time invariants will be checked on entry to most 00089 // member functions. Additionally, if AIPS_ARRAY_INDEX_CHECK is defined 00090 // index operations will be bounds-checked. Neither of these should 00091 // be defined for production code. 00092 00093 template<class T> class Matrix : public Array<T> 00094 { 00095 public: 00096 // A Matrix of length zero in each dimension; zero origin. 00097 Matrix(); 00098 00099 // A Matrix with "l1" rows and "l2" columns. 00100 Matrix(uInt l1, uInt l2); 00101 00102 // A Matrix with "l1" rows and "l2" columns. 00103 // Fill it with the initial value. 00104 Matrix(uInt l1, uInt l2, const T &initialValue); 00105 00106 // A matrix of shape with shape "len". 00107 Matrix(const IPosition &len); 00108 00109 // A matrix of shape with shape "len". 00110 // Fill it with the initial value. 00111 Matrix(const IPosition &len, const T &initialValue); 00112 00113 // The copy constructor uses reference semantics. 00114 Matrix(const Matrix<T> &other); 00115 00116 // Construct a Matrix by reference from "other". "other must have 00117 // ndim() of 2 or less. 00118 Matrix(const Array<T> &other); 00119 00120 // Create an Matrix of a given shape from a pointer. 00121 Matrix(const IPosition &shape, T *storage, StorageInitPolicy policy = COPY); 00122 // Create an Matrix of a given shape from a pointer. Because the pointer 00123 // is const, a copy is always made. 00124 Matrix(const IPosition &shape, const T *storage); 00125 00126 // Define a destructor, otherwise the (SUN) compiler makes a static one. 00127 virtual ~Matrix(); 00128 00129 // Assign the other array (which must be dimension 2) to this matrix. 00130 // If the shapes mismatch, this array is resized. 00131 virtual void assign (const Array<T>& other); 00132 00133 // Make this matrix a reference to other. Other must be of dimensionality 00134 // 2 or less. 00135 virtual void reference(const Array<T> &other); 00136 00137 // Resize to the given shape (must be 2-dimensional). 00138 // Resize without argument is equal to resize(0,0). 00139 // <group> 00140 void resize(uInt nx, uInt ny, Bool copyValues=False); 00141 virtual void resize(); 00142 virtual void resize(const IPosition &newShape, Bool copyValues=False); 00143 // </group> 00144 00145 // Copy the values from other to this Matrix. If this matrix has zero 00146 // elements then it will resize to be the same shape as other; otherwise 00147 // other must conform to this. 00148 // Note that the assign function can be used to assign a 00149 // non-conforming matrix. 00150 // <group> 00151 Matrix<T> &operator=(const Matrix<T> &other); 00152 virtual Array<T> &operator=(const Array<T> &other); 00153 // </group> 00154 00155 // Copy val into every element of this Matrix; i.e. behaves as if 00156 // val were a constant conformant matrix. 00157 Array<T> &operator=(const T &val) 00158 { return Array<T>::operator=(val); } 00159 00160 // Copy to this those values in marray whose corresponding elements 00161 // in marray's mask are True. 00162 Matrix<T> &operator= (const MaskedArray<T> &marray) 00163 { Array<T> (*this) = marray; return *this; } 00164 00165 00166 // Single-pixel addressing. If AIPS_ARRAY_INDEX_CHECK is defined, 00167 // bounds checking is performed. 00168 // <group> 00169 T &operator()(const IPosition &i) 00170 { return Array<T>::operator()(i); } 00171 const T &operator()(const IPosition &i) const 00172 { return Array<T>::operator()(i); } 00173 T &operator()(uInt i1, uInt i2) 00174 { 00175 #if defined(AIPS_ARRAY_INDEX_CHECK) 00176 this->validateIndex(i1, i2); // Throws an exception on failure 00177 #endif 00178 return this->contiguous_p ? this->begin_p[i1 + i2*yinc_p] : 00179 this->begin_p[i1*xinc_p + i2*yinc_p]; 00180 } 00181 00182 const T &operator()(uInt i1, uInt i2) const 00183 { 00184 #if defined(AIPS_ARRAY_INDEX_CHECK) 00185 this->validateIndex(i1, i2); // Throws an exception on failure 00186 #endif 00187 return this->contiguous_p ? this->begin_p[i1 + i2*yinc_p] : 00188 this->begin_p[i1*xinc_p + i2*yinc_p]; 00189 } 00190 // </group> 00191 00192 00193 // The array is masked by the input LogicalArray. 00194 // This mask must conform to the array. 00195 // <group> 00196 00197 // Return a MaskedArray. 00198 MaskedArray<T> operator() (const LogicalArray &mask) const 00199 { return Array<T>::operator() (mask); } 00200 00201 // Return a MaskedArray. 00202 MaskedArray<T> operator() (const LogicalArray &mask) 00203 { return Array<T>::operator() (mask); } 00204 00205 // </group> 00206 00207 00208 // The array is masked by the input MaskedLogicalArray. 00209 // The mask is effectively the AND of the internal LogicalArray 00210 // and the internal mask of the MaskedLogicalArray. 00211 // The MaskedLogicalArray must conform to the array. 00212 // <group> 00213 00214 // Return a MaskedArray. 00215 MaskedArray<T> operator() (const MaskedLogicalArray &mask) const 00216 { return Array<T>::operator() (mask); } 00217 00218 // Return a MaskedArray. 00219 MaskedArray<T> operator() (const MaskedLogicalArray &mask) 00220 { return Array<T>::operator() (mask); } 00221 00222 // </group> 00223 00224 00225 // Returns a reference to the i'th row. 00226 // <group> 00227 Vector<T> row(uInt i); 00228 #if defined (AIPS_IRIX) 00229 Vector<T> row(uInt i) const; 00230 #else 00231 const Vector<T> row(uInt i) const; 00232 #endif 00233 // </group> 00234 00235 // Returns a reference to the j'th column 00236 // <group> 00237 Vector<T> column(uInt j); 00238 #if defined (AIPS_IRIX) 00239 Vector<T> column(uInt j) const; 00240 #else 00241 const Vector<T> column(uInt j) const; 00242 #endif 00243 // </group> 00244 00245 // Returns a diagonal from the Matrix. The Matrix must be square. 00246 // <group> 00247 Vector<T> diagonal( ) 00248 { return diagonal (0); } 00249 #if defined (AIPS_IRIX) 00250 Vector<T> diagonal( ) const 00251 { return diagonal (0); } 00252 #else 00253 const Vector<T> diagonal( ) const 00254 { return diagonal (0); } 00255 #endif 00256 // n==0 is the main diagonal. n>0 is above the main diagonal, n<0 00257 // is below it. 00258 Vector<T> diagonal(Int n); 00259 #if defined (AIPS_IRIX) 00260 Vector<T> diagonal(Int n) const; 00261 #else 00262 const Vector<T> diagonal(Int n) const; 00263 #endif 00264 // </group> 00265 00266 // Take a slice of this matrix. Slices are always indexed starting 00267 // at zero. This uses reference semantics, i.e. changing a value 00268 // in the slice changes the original. 00269 // <srcblock> 00270 // Matrix<Double> vd(100,100); 00271 // //... 00272 // vd(Slice(0,10),Slice(10,10)) = -1.0; // 10x10 sub-matrix set to -1.0 00273 // </srcblock> 00274 // <group> 00275 Matrix<T> operator()(const Slice &sliceX, const Slice &sliceY); 00276 const Matrix<T> operator()(const Slice &sliceX, const Slice &sliceY) const; 00277 // </group> 00278 00279 // Slice using IPositions. Required to be defined, otherwise the base 00280 // class versions are hidden. 00281 // <group> 00282 Array<T> operator()(const IPosition &blc, const IPosition &trc, 00283 const IPosition &incr) 00284 { return Array<T>::operator()(blc,trc,incr); } 00285 const Array<T> operator()(const IPosition &blc, const IPosition &trc, 00286 const IPosition &incr) const 00287 { return Array<T>::operator()(blc,trc,incr); } 00288 Array<T> operator()(const IPosition &blc, const IPosition &trc) 00289 { return Array<T>::operator()(blc,trc); } 00290 const Array<T> operator()(const IPosition &blc, const IPosition &trc) const 00291 { return Array<T>::operator()(blc,trc); } 00292 Array<T> operator()(const Slicer& slicer) 00293 { return Array<T>::operator()(slicer); } 00294 const Array<T> operator()(const Slicer& slicer) const 00295 { return Array<T>::operator()(slicer); } 00296 // </group> 00297 00298 // The length of each axis of the Matrix. 00299 // <group> 00300 void shape(Int &s1, Int &s2) const 00301 { s1 = this->length_p(0); s2=this->length_p(1); } 00302 const IPosition &shape() const 00303 { return this->length_p; } 00304 // </group> 00305 00306 // The number of rows in the Matrix, i.e. the length of the first axis. 00307 uInt nrow() const 00308 { return this->length_p(0); } 00309 00310 // The number of columns in the Matrix, i.e. the length of the 2nd axis. 00311 uInt ncolumn() const 00312 { return this->length_p(1); } 00313 00314 // Replace the data values with those in the pointer <src>storage</src>. 00315 // The results are undefined is storage does not point at nelements() or 00316 // more data elements. After takeStorage() is called, <src>unique()</src> 00317 // is True. 00318 // <group> 00319 virtual void takeStorage(const IPosition &shape, T *storage, 00320 StorageInitPolicy policy = COPY); 00321 // Since the pointer is const, a copy is always taken. 00322 virtual void takeStorage(const IPosition &shape, const T *storage); 00323 // </group> 00324 00325 // Checks that the Matrix is consistent (invariants check out). 00326 virtual Bool ok() const; 00327 00328 protected: 00329 // Remove the degenerate axes from other and store result in this matrix. 00330 // An exception is thrown if removing degenerate axes does not result 00331 // in a matrix. 00332 virtual void doNonDegenerate(const Array<T> &other, 00333 const IPosition &ignoreAxes); 00334 00335 private: 00336 // Cached constants to improve indexing. 00337 Int xinc_p, yinc_p; 00338 00339 // Helper fn to calculate the indexing constants. 00340 void makeIndexingConstants(); 00341 }; 00342 00343 } //#End casa namespace 00344 #ifndef CASACORE_NO_AUTO_TEMPLATES 00345 #include <casa/Arrays/Matrix.tcc> 00346 #endif //# CASACORE_NO_AUTO_TEMPLATES 00347 #endif