casa
$Rev:20696$
|
00001 //# LELInterface.h: Abstract base class for lattice expressions 00002 //# Copyright (C) 1997,1998,1999,2000,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: LELInterface.h 20508 2009-01-20 11:09:47Z gervandiepen $ 00027 00028 #ifndef LATTICES_LELINTERFACE_H 00029 #define LATTICES_LELINTERFACE_H 00030 00031 00032 //# Includes 00033 #include <casa/aips.h> 00034 #include <lattices/Lattices/LELAttribute.h> 00035 #include <casa/Arrays/IPosition.h> 00036 #include <casa/Utilities/CountedPtr.h> 00037 #include <casa/Utilities/DataType.h> 00038 #include <casa/IO/FileLocker.h> 00039 00040 namespace casa { //# NAMESPACE CASA - BEGIN 00041 00042 //# Forward Declarations 00043 template <class T> class LELScalar; 00044 template <class T> class LELArray; 00045 template <class T> class LELArrayRef; 00046 class Slicer; 00047 00048 00049 // <summary> This base class provides the interface for Lattice expressions </summary> 00050 00051 // <use visibility=local> 00052 00053 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos=""> 00054 // </reviewed> 00055 00056 // <prerequisite> 00057 // <li> <linkto class="Lattice"> Lattice</linkto> 00058 // <li> <linkto class="LatticeExpr"> LatticeExpr</linkto> 00059 // <li> <linkto class="LatticeExprNode"> LatticeExprNode</linkto> 00060 // </prerequisite> 00061 00062 // <etymology> 00063 // The name means "Lattice Expression Language Interface". 00064 // This class provides the declaration for the interface for classes 00065 // that are to provide Lattice expression computational functionality 00066 // </etymology> 00067 00068 // <synopsis> 00069 // This class is part of the Letter/envelope scheme which enables 00070 // the C++ programmer to write mathematical expressions involving 00071 // Lattices. The envelope class LatticeExpr invokes the bridge 00072 // class LatticeExprNode. LatticeExprNode activates the letter 00073 // classes which provide the real functionality. 00074 // 00075 // A description of the implementation details of these classes can 00076 // be found in 00077 // <a href="../notes/216.html">Note 216</a> 00078 // 00079 // This class, LELInterface, is the abstract base class for all of 00080 // the letter classes. Its purpose is to declare the interface inherited 00081 // by all of its derived classes which are used polymorphically. The derived 00082 // classes offer the functionality to create and evaluate the expression 00083 // tree that results from the compiler parsing the expression. 00084 // For example, these derived classes are activated by LatticeExprNode to 00085 // handle operations like reading pixels from a Lattice, applying binary 00086 // operations to Lattices, applying mathematical functions to Lattices 00087 // and so on. 00088 // 00089 // The heart of the interface is in the functions <src>eval</src> and 00090 // <src>getScalar</src>. These recursively evaluate the result of the 00091 // current expression when the result is either an array or a scalar, 00092 // respectively. The need for recursion can be understood with a simple 00093 // example. 00094 // 00095 // Consider an expression summing two Lattices such as "2*(b+c)". 00096 // The expression tree consists of nodes (leaves) that 1) get Lattice 00097 // pixels from the Lattice (expressions "b" and "c"), 2) add the pixel 00098 // values of the Lattices together (operator "+"), and 3) multiply a Lattice 00099 // by a scalar (operator "*"). At the top of the tree, 00100 // we have a scalar (2.0) and a Lattice (the 00101 // result of "b+c"). The top-of-the-tree expression has to multiply 00102 // them together. That's what the <src>eval</src> function for the "*" 00103 // operation needs to do. The key is that each of the "2.0" and 00104 // "b+c" are really Lattice expressions themselves and they can be evaluated. 00105 // So before the "*" <src>eval</src> function can 00106 // multiply its two expressions together, it must individually evaluate them. 00107 // Thus, it first calls the <src>getScalar</src> function of 00108 // the object housing the expression "2.0". This will in fact return 00109 // the scalar value "2.0". Then it calls 00110 // <src>eval</src> on the expression object housing "b+c". This 00111 // object in turn first calls <src>eval</src> on the left ("b") and 00112 // right ("c") expressions which results in the pixels for the Lattices 00113 // being returned. It then adds them together, returning the result 00114 // to the top of the tree where they are multiplied by 2. You can see 00115 // that since all these different expression objects call the 00116 // <src>eval</src> or <src>getScalar</src> function that they all inherit 00117 // from LELInterface. Indeed for our example above, the actual classes 00118 // involved are are LELLattice (get pixels from Lattice) and LELBinary 00119 // ("+" and "*" operators) which inherit from LELInterface. When these 00120 // objects are constructed, they work out whether the result of their 00121 // evaluation is a scalar or not. This is how the classes higher up 00122 // the tree know whether to call <src>eval</src> or <src>getScalar</src>. 00123 // 00124 // The results of the computations are either returned in the buffer in 00125 // the <src>eval</src> function or by value by <src>getScalar</src> 00126 // 00127 // The classes evaluate the expression for each specified Lattice 00128 // chunk (usually tile by tile). The <src>section</src> argument 00129 // in the <src>eval</src> function specifies the section of the 00130 // Lattice being evaluated. The absence of the <src>section</src> 00131 // argument in the <src>getScalar</src> function emphasises the 00132 // scalar nature; a scalar expression does not have a shape. For most 00133 // of the letter classes, the <src>section</src> argument is irrelevant; 00134 // the only one it really matters for is LELLattice which fetches the 00135 // pixels from the Lattice. The rest only care about the shape of the 00136 // buffer in the <src>eval</src> call. 00137 // 00138 // </synopsis> 00139 // 00140 // <motivation> 00141 // The many letter classes that actually do the computational work 00142 // are used polymorphically. Therefore, they must have a base 00143 // class declaring the interface. 00144 // </motivation> 00145 00146 // <todo asof="1998/02/20"> 00147 // </todo> 00148 00149 00150 template <class T> class LELInterface 00151 { 00152 public: 00153 00154 // Virtual destructor 00155 virtual ~LELInterface(); 00156 00157 // Evaluate the expression and fill the result array 00158 virtual void eval (LELArray<T>& result, 00159 const Slicer& section) const = 0; 00160 virtual void evalRef (LELArrayRef<T>& result, 00161 const Slicer& section) const; 00162 00163 // Get the result of a scalar subexpression. 00164 virtual LELScalar<T> getScalar() const = 0; 00165 00166 // Get the result of an array subexpression. 00167 // It does eval for the entire array. 00168 // An exception is thrown if the shape of the subexpression is unknown. 00169 LELArray<T> getArray() const; 00170 00171 // Do further preparations (e.g. optimization) on the expression. 00172 // It returns True if the expression is an invalid scalar 00173 // (i.e. with a False mask). 00174 // That can happen if the expression has a component with an invalid 00175 // scalar value (e.g. min(lattice) where lattice contains no valid elements). 00176 virtual Bool prepareScalarExpr() = 0; 00177 00178 // Is the result of evaluating this expression a scalar ? 00179 Bool isScalar() const {return attr_p.isScalar();} 00180 00181 // Get the shape of the expression result. 00182 const IPosition& shape() const {return attr_p.shape();} 00183 00184 // Get expression attribute 00185 const LELAttribute& getAttribute() const {return attr_p;} 00186 00187 // Get class name 00188 virtual String className() const = 0; 00189 00190 // If the given expression is a valid scalar, replace it by its result. 00191 // It returns False if the expression is no scalar or if the expression 00192 // is an invalid scalar (i.e. with a False mask). 00193 static Bool replaceScalarExpr (CountedPtr<LELInterface<T> >& expr); 00194 00195 // Handle locking/syncing of the parts of a lattice expression. 00196 // <br>By default the functions do not do anything at all. 00197 // lock() and hasLock return True. 00198 // <group> 00199 virtual Bool lock (FileLocker::LockType, uInt nattempts); 00200 virtual void unlock(); 00201 virtual Bool hasLock (FileLocker::LockType) const; 00202 virtual void resync(); 00203 // </group> 00204 00205 protected: 00206 // Set the expression attributes of this object. 00207 void setAttr(const LELAttribute& attrib); 00208 00209 private: 00210 LELAttribute attr_p; 00211 }; 00212 00213 00214 00215 } //# NAMESPACE CASA - END 00216 00217 //# There is a problem in including LELInterface.tcc, because it needs 00218 //# LELUnary.h which in its turn includes LELInterface.h again. 00219 //# So in a source file including LELUnary.h, LELInterface::replaceScalarExpr 00220 //# fails to compile, because the LELUnary declarations are not seen yet. 00221 //# Therefore LELUnary.h is included here, while LELUnary.h includes 00222 //# LELInterface.tcc. 00223 #ifndef CASACORE_NO_AUTO_TEMPLATES 00224 #include <lattices/Lattices/LELUnary.h> 00225 #endif //# CASACORE_NO_AUTO_TEMPLATES 00226 #endif