casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
LatticeExprNode.h
Go to the documentation of this file.
00001 //# LatticeExprNode.h:  LatticeExprNode.h
00002 //# Copyright (C) 1997,1998,1999,2000,2001,2002,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: LatticeExprNode.h 20739 2009-09-29 01:15:15Z Malte.Marquarding $
00027 
00028 #ifndef LATTICES_LATTICEEXPRNODE_H
00029 #define LATTICES_LATTICEEXPRNODE_H
00030 
00031 
00032 //# Includes
00033 #include <lattices/Lattices/LELInterface.h>
00034 #include <lattices/Lattices/LELAttribute.h>
00035 #include <lattices/Lattices/LELBinaryEnums.h>
00036 #include <lattices/Lattices/LELUnaryEnums.h>
00037 #include <lattices/Lattices/LELFunctionEnums.h>
00038 #include <casa/Arrays/IPosition.h>
00039 #include <casa/Utilities/CountedPtr.h>
00040 #include <casa/Utilities/DataType.h>
00041 
00042 namespace casa { //# NAMESPACE CASA - BEGIN
00043 
00044 //# Forward Declarations
00045 template <class T> class LatticeExpr;
00046 template <class T> class Lattice;
00047 template <class T> class MaskedLattice;
00048 template <class T> class Array;
00049 template <class T> class Block;
00050 class LCRegion;
00051 class Slicer;
00052 class LattRegionHolder;
00053 class LatticeExprNode;
00054 
00055 // Global functions operating on a LatticeExprNode.
00056 // <group name=GlobalLatticeExprNode>
00057   // Unary functions.
00058   // <group>
00059    LatticeExprNode operator+ (const LatticeExprNode& expr);
00060    LatticeExprNode operator- (const LatticeExprNode& expr);
00061    LatticeExprNode operator! (const LatticeExprNode& expr);
00062   // </group>
00063 
00064   // Numerical binary operators
00065   // <group>
00066    LatticeExprNode operator+ (const LatticeExprNode& left,
00067                               const LatticeExprNode& right);
00068    LatticeExprNode operator- (const LatticeExprNode& left,
00069                               const LatticeExprNode& right);
00070    LatticeExprNode operator* (const LatticeExprNode& left,
00071                               const LatticeExprNode& right);
00072    LatticeExprNode operator/ (const LatticeExprNode& left,
00073                               const LatticeExprNode& right);
00074    LatticeExprNode operator% (const LatticeExprNode& left,
00075                               const LatticeExprNode& right);
00076    LatticeExprNode operator^ (const LatticeExprNode& left,
00077                               const LatticeExprNode& right);
00078   // </group>
00079 
00080   // Relational binary operators
00081   // <group>
00082    LatticeExprNode operator== (const LatticeExprNode& left,
00083                                const LatticeExprNode& right);
00084    LatticeExprNode operator>  (const LatticeExprNode& left,
00085                                const LatticeExprNode& right);
00086    LatticeExprNode operator>= (const LatticeExprNode& left,
00087                                const LatticeExprNode& right);
00088    LatticeExprNode operator<  (const LatticeExprNode& left,
00089                                const LatticeExprNode& right);
00090    LatticeExprNode operator<= (const LatticeExprNode& left,
00091                                const LatticeExprNode& right);
00092    LatticeExprNode operator!= (const LatticeExprNode& left,
00093                                const LatticeExprNode& right);
00094   // </group>
00095 
00096   // Logical binary operators
00097   // <group>
00098    LatticeExprNode operator&& (const LatticeExprNode& left,
00099                                const LatticeExprNode& right);
00100    LatticeExprNode operator|| (const LatticeExprNode& left,
00101                                const LatticeExprNode& right);
00102   // </group>
00103 
00104   // Numerical 1-argument functions
00105   // <group>
00106    LatticeExprNode sin  (const LatticeExprNode& expr);
00107    LatticeExprNode sinh (const LatticeExprNode& expr);
00108    LatticeExprNode asin (const LatticeExprNode& expr);
00109    LatticeExprNode cos  (const LatticeExprNode& expr);
00110    LatticeExprNode cosh (const LatticeExprNode& expr);
00111    LatticeExprNode acos (const LatticeExprNode& expr);
00112    LatticeExprNode tan  (const LatticeExprNode& expr);
00113    LatticeExprNode tanh (const LatticeExprNode& expr);
00114    LatticeExprNode atan (const LatticeExprNode& expr);
00115    LatticeExprNode exp  (const LatticeExprNode& expr);
00116    LatticeExprNode log  (const LatticeExprNode& expr);
00117    LatticeExprNode log10(const LatticeExprNode& expr);
00118    LatticeExprNode sqrt (const LatticeExprNode& expr);
00119    LatticeExprNode sign (const LatticeExprNode& expr);
00120    LatticeExprNode round(const LatticeExprNode& expr);
00121    LatticeExprNode ceil (const LatticeExprNode& expr);
00122    LatticeExprNode floor(const LatticeExprNode& expr);
00123    LatticeExprNode conj (const LatticeExprNode& expr);
00124   // </group>
00125 
00126   // Numerical 2-argument functions
00127   // <group>
00128    LatticeExprNode atan2 (const LatticeExprNode& left,
00129                           const LatticeExprNode& right);
00130    LatticeExprNode pow  (const LatticeExprNode& left,
00131                          const LatticeExprNode& right);
00132    LatticeExprNode fmod (const LatticeExprNode& left,
00133                          const LatticeExprNode& right);
00134    LatticeExprNode min  (const LatticeExprNode& left,
00135                          const LatticeExprNode& right);
00136    LatticeExprNode max  (const LatticeExprNode& left,
00137                          const LatticeExprNode& right);
00138   // </group>
00139 
00140   // Form a complex number from two real numbers.
00141    LatticeExprNode formComplex (const LatticeExprNode& left,
00142                                 const LatticeExprNode& right);
00143 
00144   // Numerical 1-argument functions which result in a real number
00145   // regardless of input expression type
00146   // <group>
00147    LatticeExprNode abs  (const LatticeExprNode& expr);
00148    LatticeExprNode arg  (const LatticeExprNode& expr);
00149    LatticeExprNode real (const LatticeExprNode& expr);
00150    LatticeExprNode imag (const LatticeExprNode& expr);
00151   // </group>
00152 
00153   // 1-argument functions operating on a numeric expression resulting 
00154   // in a scalar
00155   // <group>
00156    LatticeExprNode min      (const LatticeExprNode& expr);
00157    LatticeExprNode max      (const LatticeExprNode& expr);
00158    LatticeExprNode sum      (const LatticeExprNode& expr);
00159    LatticeExprNode median   (const LatticeExprNode& expr);
00160    LatticeExprNode mean     (const LatticeExprNode& expr);
00161    LatticeExprNode variance (const LatticeExprNode& expr);
00162    LatticeExprNode stddev   (const LatticeExprNode& expr);
00163    LatticeExprNode avdev    (const LatticeExprNode& expr);
00164   // </group>
00165 
00166   // Determine the value of the element at the part <src>fraction</src>
00167   // from the beginning of the given lattice.
00168   // Thus <src>fraction=0.5</src> is equal to the median.
00169    LatticeExprNode fractile (const LatticeExprNode& expr,
00170                              const LatticeExprNode& fraction);
00171 
00172   // Determine the value range of the elements at the part <src>fraction1</src>
00173   // and fraction2 from the beginning of the given lattice. Both fractions
00174   // must be >=0 and <=1 and fraction1 must be <= fraction2.
00175   // By default <src>fraction2</src> is equal to <src>1-fraction1</src>.
00176   // Thus <src>fraction=0.25</src> gives the quartile range of the lattice.
00177   // <group>
00178    LatticeExprNode fractileRange (const LatticeExprNode& expr,
00179                                   const LatticeExprNode& fraction1,
00180                                   const LatticeExprNode& fraction2);
00181    LatticeExprNode fractileRange (const LatticeExprNode& expr,
00182                                   const LatticeExprNode& fraction);
00183   // </group>
00184 
00185   // 1-argument function to get the number of elements in a lattice.
00186   // If the lattice is masked, only the True elements are counted.
00187   // Results in a scalar Double.
00188    LatticeExprNode nelements (const LatticeExprNode& expr);
00189 
00190   // 1-argument function to get the dimensionality of a lattice.
00191   // 0 is returned if it is a scalar.
00192   // Results in a scalar Float.
00193    LatticeExprNode ndim (const LatticeExprNode& expr);
00194 
00195   // 2-argument function to get the length of an axis.
00196   // Results in a scalar Float.
00197   // The 2nd expression (giving the axis number) has to be a real scalar.
00198   // <note role=caution>
00199   // Axes start counting at 0.
00200   // If the axis is a number < 0, an exception is thrown.
00201   // If the axis is a number exceeding the dimensionality, 1 is returned.
00202   // </note>
00203    LatticeExprNode length (const LatticeExprNode& expr,
00204                            const LatticeExprNode& axis);
00205 
00206   // 2-argument function telling per pixel if its index on the given axis
00207   // is contained in the 2nd argument. The 2nd argument should be a boolean
00208   // vector where True means that the index is contained.
00209   // For indices >= vector_length, the 2nd argument defaults to False.
00210   // Results in a Bool array.
00211   // <note role=caution>
00212   // Axes start counting at 0.
00213   // If the axis is a number < 0 or >= ndim, an exception is thrown.
00214   // </note>
00215    LatticeExprNode indexin (const LatticeExprNode& axis,
00216                             const LatticeExprNode& indexFlags);
00217 
00218   // 2-argument function rebinning Lattice by given factors. The 2nd argument
00219   // should be a vector (preferably Float - really Int but Int not well
00220   // supported in LEL yet).  Results in a T array.
00221    LatticeExprNode rebin (const LatticeExprNode& expr,
00222                           const LatticeExprNode& bin);
00223 
00224 // Test if a value is a NaN.
00225    LatticeExprNode isNaN (const LatticeExprNode& expr);
00226 
00227   // Functions operating on a logical expression resulting in a scalar;
00228   // Functions "any" (are any pixels "True") and "all" (are all pixels
00229   // "True") result in a Bool; functions "ntrue" and "nfalse" result 
00230   // in a Double.
00231   // <group>
00232    LatticeExprNode any   (const LatticeExprNode& expr);
00233    LatticeExprNode all   (const LatticeExprNode& expr);
00234    LatticeExprNode ntrue (const LatticeExprNode& expr);
00235    LatticeExprNode nfalse(const LatticeExprNode& expr);
00236   // </group>
00237 
00238   // This function returns the mask of the given expression.
00239   // If it has no mask, the result is an array with all True values.
00240    LatticeExprNode mask (const LatticeExprNode& expr);
00241 
00242   // This function returns the value of the expression without a mask.
00243    LatticeExprNode value (const LatticeExprNode& expr);
00244 
00245   // This function finds <src>sqrt(left^2+right^2)</src>.  This
00246   // could be used to find the (biased) polarized intensity if
00247   // left and right are images of Stokes Q and U.
00248    LatticeExprNode amp (const LatticeExprNode& left,
00249                         const LatticeExprNode& right);
00250 
00251   // This function finds <src>180/pi*atan2(left,right)/2</src>.  This could be 
00252   // used to find the position of linear polarization if left 
00253   // and right are images of Stokes U and Q, respectively.
00254    LatticeExprNode pa (const LatticeExprNode& left,
00255                        const LatticeExprNode& right);
00256 
00257   // This function finds the spectral index
00258   // <src>alpha = log(s1/s2) / log(f1/f2)</src>.
00259    LatticeExprNode spectralindex (const LatticeExprNode& left,
00260                                   const LatticeExprNode& right);
00261 
00262   // Function resembling the ternary <src>?:</src> construct in C++.
00263   // The argument "condition" has to be a Bool scalar or lattice.
00264   // If an element in "condition" is True, the corresponding element from
00265   // "arg1" is taken, otherwise it is taken from "arg2".
00266    LatticeExprNode iif (const LatticeExprNode& condition,
00267                         const LatticeExprNode& arg1,
00268                         const LatticeExprNode& arg2);
00269 
00270   // This function replaces every masked-off element in the first argument
00271   // with the corresponding element from the second argument.
00272   // The first argument has to be a lattice (expression), the second can
00273   // be a scalar or lattice. The mask of the first argument is not changed.
00274   // If the first argument does not have a mask, this function does nothing.
00275    LatticeExprNode replace (const LatticeExprNode& arg1,
00276                             const LatticeExprNode& arg2);
00277 
00278   // Functions to convert to the given data type.  These are mostly 
00279   // meaningful for down-conversions (e.g. double to float),
00280   // since up-conversions are automatically done to get matching data types
00281   // when needed.  Note that some conversions are not supported, such
00282   // as Complex to Double or Float.
00283   // <br>The conversion to Bool is useful to convert a region to a
00284   // boolean lattice, which is only possible if the region is given
00285   // in world coordinates. Otherwise an exception is thrown.
00286   // <group>
00287    LatticeExprNode toFloat   (const LatticeExprNode& expr);
00288    LatticeExprNode toDouble  (const LatticeExprNode& expr);
00289    LatticeExprNode toComplex (const LatticeExprNode& expr);
00290    LatticeExprNode toDComplex(const LatticeExprNode& expr);
00291    LatticeExprNode toBool    (const LatticeExprNode& expr);
00292    LatticeExprNode convertType (const LatticeExprNode& expr, const Float*);
00293    LatticeExprNode convertType (const LatticeExprNode& expr, const Double*);
00294    LatticeExprNode convertType (const LatticeExprNode& expr, const Complex*);
00295    LatticeExprNode convertType (const LatticeExprNode& expr, const DComplex*);
00296    LatticeExprNode convertType (const LatticeExprNode& expr, const Bool*);
00297   // </group>
00298 // </group>
00299 
00300 
00301 
00302 // <summary>
00303 // Bridging class to allow C++ expressions involving lattices
00304 // </summary>
00305 //
00306 // <use visibility=export>
00307 //
00308 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00309 // </reviewed>
00310 //
00311 // <prerequisite>
00312 //   <li> <linkto class="Lattice"> Lattice</linkto>
00313 //   <li> <linkto class="LatticeExpr"> LatticeExpr</linkto>
00314 //   <li> <linkto class="LELInterface"> LELInterface</linkto>
00315 // </prerequisite>
00316 //
00317 // <etymology>
00318 // The name is derived from the fact that this class provides
00319 // an expression interface to the user which s/he may use to
00320 // write C++ expressions involving Lattices.  This class actually
00321 // constructs the nodes of the expression tree, hence its name.
00322 // It is used by the envelope class LatticeExpr and provides a 
00323 // bridge to the letter classes derived from LELInterface.
00324 // </etymology>
00325 //
00326 // <synopsis>
00327 //    This class is part of the interface which allows the C++ programmer
00328 //    to enter mathematical expressions involving Lattices. It is
00329 //    is part of a Letter/envelope scheme.  It's actually a bridge
00330 //    between the envelope class (LatticeExpr) and the letter classes
00331 //    (derived from LELInterface) and it exists largely to handle
00332 //    type conversions.  In a single type environment, the envelope
00333 //    class could have directly called the letter classes.
00334 //
00335 //    The envelope and bridge provide the interface which the programmer
00336 //    sees.  The letter classes do the real work and are hidden from
00337 //    the programmer.
00338 //
00339 //    All the expression manipulation functionality that the user has 
00340 //    access to is viewable in this class; it is here that the operators,
00341 //    functions and constructors are defined.  These allow the programmer
00342 //    to write mathematical expressions which involve Lattices.  The
00343 //    letter classes take care of the optimal traversal of the Lattice
00344 //    and the memory mangement thereof.  Thus the Lattices are iterated
00345 //    through and the expressions evaluated for each chunk (usually 
00346 //    a tile shape) of the iteration.
00347 //
00348 //    A description of the implementation details of these classes can
00349 //    be found in
00350 //    <a href="../notes/216.html">Note 216</a>
00351 //
00352 //    The available functionality is defined by the global friend functions
00353 //    and operators, plus the public constructors.  The other public members
00354 //    functions are generally not of interest to the user of this class.
00355 //
00356 //    Generally, if one writes an expression such as <src>a.copyData(sin(b))</src>,
00357 //    the expression is automatically converted first to a LatticeExprNode and
00358 //    then to a LatticeExpr (which is a Lattice) before evaluation occurs.
00359 //    However, it may occur that you wish to build an expression from
00360 //    subexpressions.  To do this, you must explcitly create objects of 
00361 //    class LatticeExprNode.  You cannot manipulate subexpressions of type
00362 //    LatticeExpr<T>.  See below for an example.
00363 // </synopsis> 
00364 //
00365 // <example>
00366 // <srcblock>
00367 //  ArrayLattice<Float>   f1(IPosition (2,nx,ny));
00368 //  ArrayLattice<Float>   f2(IPosition (2,nx,ny));
00369 //  f2.set(2.0);
00370 //  f1.copyData(2*f2+f2);
00371 // </srcblock>
00372 //  In this example, the values of the pixels in Lattice f1 are set
00373 //  to the values resulting from the expression "2*f2 + f2"
00374 //  I.e. the expression is evaluated for each pixel in the Lattices
00375 //
00376 //  Note that :
00377 //
00378 //  1) the Lattice::copyData function is expecting a Lattice argument.  
00379 //  2) LatticeExpr inherits from Lattice and therefore a LatticeExpr
00380 //     object is a valid argument object type
00381 //  3) The expression in the copyData call is automatically converted to 
00382 //     a LatticeExprNode by the constructors and operators in LatticeExprNode
00383 //  4) The LatticeExprNode object so created is automatically converted
00384 //     to a LatticeExpr by casting functions in LatticeExprNode.
00385 //
00386 // </example>
00387 //
00388 // <example>
00389 // <srcblock>
00390 //  ArrayLattice<Float>   f1(IPosition (2,nx,ny));
00391 //  ArrayLattice<Float>   f2(IPosition (2,nx,ny));
00392 //  ArrayLattice<Double>  d(IPosition (2,nx,ny));
00393 //  ArrayLattice<Complex> c(IPosition (2,nx,ny));
00394 //  ArrayLattice<Bool>    b(IPosition (2,nx,ny));
00395 //
00396 //  f2.set(1.0); d.set(2.0); c.set(Complex(2.0,3.0)); b.set(True);
00397 //  f1.copyData( (3.5*f2) + (cos(d)) - (10/min(d,f2)*(-abs(c))*ntrue(b)) - (C::pi) );
00398 // </srcblock>
00399 //  
00400 //  In this rather silly example, we fill Lattice "f1" with the result of the
00401 //  expression.  The expression shows the use of constants, unary operations, 
00402 //  binary operations, 1D and 2D functions.  It also shows how mixed types can 
00403 //  be handled.  The output Lattice is a Float, whereas  mixed into the 
00404 //  expression are subexpressions involving Float, Double, Complex and Bool
00405 //  Lattices.
00406 //
00407 // </example>
00408 //
00409 // <example>
00410 // <srcblock>
00411 //  ArrayLattice<Float>   f1(IPosition (2,nx,ny));
00412 //  ArrayLattice<Float>   f2(IPosition (2,nx,ny));
00413 //  f2.set(2.0);
00414 //  LatticeExprNode exp1(sin(f2));
00415 //  LatticeExprNode exp2(pow(f2,2.0));
00416 //  f1.copyData(exp1+exp2);
00417 // </srcblock>
00418 //  In this example, the expression is "sin(f2) + pow(f2,2.0)",
00419 //  but we have put it together from two subexpressions contained
00420 //  in LatticeExprNode objects exp1 and exp2.  Again the LatticeExprNode
00421 //  object formed from summing exp1 and exp2 is automatically converted
00422 //  to a LatticeExpr for consumption by copyData
00423 //
00424 // </example>
00425 //
00426 // <motivation>
00427 //  The Lattice expression classes enable the C++ programmer much simpler 
00428 //  handling of mathematical expressions involving lattices.  In addition, 
00429 //  these classes provide the infrastructure on top of which we can build 
00430 //  an image calculator for Glish users
00431 // </motivation>
00432 //
00433 // <todo asof="1997/01/15">
00434 //   <li> masks
00435 //   <li> regions
00436 // </todo>
00437 
00438 
00439 class LatticeExprNode
00440 {
00441 // All global functions need to be declared as friends.
00442 // <group>
00443    friend LatticeExprNode operator+ (const LatticeExprNode& expr);
00444    friend LatticeExprNode operator- (const LatticeExprNode& expr);
00445    friend LatticeExprNode operator! (const LatticeExprNode& expr);
00446    friend LatticeExprNode operator+ (const LatticeExprNode& left,
00447                                      const LatticeExprNode& right);
00448    friend LatticeExprNode operator- (const LatticeExprNode& left,
00449                                      const LatticeExprNode& right);
00450    friend LatticeExprNode operator* (const LatticeExprNode& left,
00451                                      const LatticeExprNode& right);
00452    friend LatticeExprNode operator/ (const LatticeExprNode& left,
00453                                      const LatticeExprNode& right);
00454    friend LatticeExprNode operator% (const LatticeExprNode& left,
00455                                      const LatticeExprNode& right);
00456    friend LatticeExprNode operator^ (const LatticeExprNode& left,
00457                                      const LatticeExprNode& right);
00458    friend LatticeExprNode operator== (const LatticeExprNode& left,
00459                                       const LatticeExprNode& right);
00460    friend LatticeExprNode operator>  (const LatticeExprNode& left,
00461                                       const LatticeExprNode& right);
00462    friend LatticeExprNode operator>= (const LatticeExprNode& left,
00463                                       const LatticeExprNode& right);
00464    friend LatticeExprNode operator<  (const LatticeExprNode& left,
00465                                       const LatticeExprNode& right);
00466    friend LatticeExprNode operator<= (const LatticeExprNode& left,
00467                                       const LatticeExprNode& right);
00468    friend LatticeExprNode operator!= (const LatticeExprNode& left,
00469                                       const LatticeExprNode& right);
00470    friend LatticeExprNode operator&& (const LatticeExprNode& left,
00471                                       const LatticeExprNode& right);
00472    friend LatticeExprNode operator|| (const LatticeExprNode& left,
00473                                       const LatticeExprNode& right);
00474    friend LatticeExprNode sin  (const LatticeExprNode& expr);
00475    friend LatticeExprNode sinh (const LatticeExprNode& expr);
00476    friend LatticeExprNode asin (const LatticeExprNode& expr);
00477    friend LatticeExprNode cos  (const LatticeExprNode& expr);
00478    friend LatticeExprNode cosh (const LatticeExprNode& expr);
00479    friend LatticeExprNode acos (const LatticeExprNode& expr);
00480    friend LatticeExprNode tan  (const LatticeExprNode& expr);
00481    friend LatticeExprNode tanh (const LatticeExprNode& expr);
00482    friend LatticeExprNode atan (const LatticeExprNode& expr);
00483    friend LatticeExprNode exp  (const LatticeExprNode& expr);
00484    friend LatticeExprNode log  (const LatticeExprNode& expr);
00485    friend LatticeExprNode log10(const LatticeExprNode& expr);
00486    friend LatticeExprNode sqrt (const LatticeExprNode& expr);
00487    friend LatticeExprNode sign (const LatticeExprNode& expr);
00488    friend LatticeExprNode round(const LatticeExprNode& expr);
00489    friend LatticeExprNode ceil (const LatticeExprNode& expr);
00490    friend LatticeExprNode floor(const LatticeExprNode& expr);
00491    friend LatticeExprNode conj (const LatticeExprNode& expr);
00492    friend LatticeExprNode atan2 (const LatticeExprNode& left,
00493                                  const LatticeExprNode& right);
00494    friend LatticeExprNode pow  (const LatticeExprNode& left,
00495                                 const LatticeExprNode& right);
00496    friend LatticeExprNode fmod (const LatticeExprNode& left,
00497                                 const LatticeExprNode& right);
00498    friend LatticeExprNode min  (const LatticeExprNode& left,
00499                                 const LatticeExprNode& right);
00500    friend LatticeExprNode max  (const LatticeExprNode& left,
00501                                 const LatticeExprNode& right);
00502    friend LatticeExprNode formComplex (const LatticeExprNode& left,
00503                                        const LatticeExprNode& right);
00504    friend LatticeExprNode abs  (const LatticeExprNode& expr);
00505    friend LatticeExprNode arg  (const LatticeExprNode& expr);
00506    friend LatticeExprNode real (const LatticeExprNode& expr);
00507    friend LatticeExprNode imag (const LatticeExprNode& expr);
00508    friend LatticeExprNode min      (const LatticeExprNode& expr);
00509    friend LatticeExprNode max      (const LatticeExprNode& expr);
00510    friend LatticeExprNode sum      (const LatticeExprNode& expr);
00511    friend LatticeExprNode median   (const LatticeExprNode& expr);
00512    friend LatticeExprNode mean     (const LatticeExprNode& expr);
00513    friend LatticeExprNode variance (const LatticeExprNode& expr);
00514    friend LatticeExprNode stddev   (const LatticeExprNode& expr);
00515    friend LatticeExprNode avdev    (const LatticeExprNode& expr);
00516    friend LatticeExprNode fractile (const LatticeExprNode& expr,
00517                                     const LatticeExprNode& fraction);
00518    friend LatticeExprNode fractileRange (const LatticeExprNode& expr,
00519                                          const LatticeExprNode& fraction1,
00520                                          const LatticeExprNode& fraction2);
00521    friend LatticeExprNode fractileRange (const LatticeExprNode& expr,
00522                                          const LatticeExprNode& fraction);
00523    friend LatticeExprNode nelements (const LatticeExprNode& expr);
00524    friend LatticeExprNode ndim (const LatticeExprNode& expr);
00525    friend LatticeExprNode length (const LatticeExprNode& expr,
00526                                   const LatticeExprNode& axis);
00527    friend LatticeExprNode indexin (const LatticeExprNode& axis,
00528                                    const LatticeExprNode& indexFlags);
00529    friend LatticeExprNode rebin (const LatticeExprNode& expr,
00530                                  const LatticeExprNode& bin);
00531    friend LatticeExprNode isNaN (const LatticeExprNode& expr);
00532    friend LatticeExprNode any   (const LatticeExprNode& expr);
00533    friend LatticeExprNode all   (const LatticeExprNode& expr);
00534    friend LatticeExprNode ntrue (const LatticeExprNode& expr);
00535    friend LatticeExprNode nfalse(const LatticeExprNode& expr);
00536    friend LatticeExprNode mask (const LatticeExprNode& expr);
00537    friend LatticeExprNode value (const LatticeExprNode& expr);
00538    friend LatticeExprNode amp (const LatticeExprNode& left,
00539                                const LatticeExprNode& right);
00540    friend LatticeExprNode pa (const LatticeExprNode& left,
00541                               const LatticeExprNode& right);
00542    friend LatticeExprNode spectralindex (const LatticeExprNode& left,
00543                                          const LatticeExprNode& right);
00544    friend LatticeExprNode iif (const LatticeExprNode& condition,
00545                                const LatticeExprNode& arg1,
00546                                const LatticeExprNode& arg2);
00547    friend LatticeExprNode replace (const LatticeExprNode& arg1,
00548                                    const LatticeExprNode& arg2);
00549    friend LatticeExprNode toFloat   (const LatticeExprNode& expr);
00550    friend LatticeExprNode toDouble  (const LatticeExprNode& expr);
00551    friend LatticeExprNode toComplex (const LatticeExprNode& expr);
00552    friend LatticeExprNode toDComplex(const LatticeExprNode& expr);
00553    friend LatticeExprNode toBool    (const LatticeExprNode& expr);
00554 // </group>
00555 
00556 public:
00557 
00558 // Default constructor
00559    LatticeExprNode();
00560 
00561 // Unary constant expression constructors.
00562 // <group>
00563    LatticeExprNode (Int64 constant);
00564    LatticeExprNode (Int constant);
00565    LatticeExprNode (uInt constant);
00566    LatticeExprNode (Long constant);
00567    LatticeExprNode (Float constant);
00568    LatticeExprNode (Double constant);
00569    LatticeExprNode (const Complex& constant);
00570    LatticeExprNode (const DComplex& constant);
00571    LatticeExprNode (Bool constant);
00572 // </group>
00573 
00574 // Constructor from an IPosition (containing indices or axes).
00575    LatticeExprNode (const IPosition&);
00576 
00577 // Lattice expression (gets Lattice pixels) constructors.
00578 // <group>
00579    LatticeExprNode (const Lattice<Float>& lattice);
00580    LatticeExprNode (const Lattice<Double>& lattice);
00581    LatticeExprNode (const Lattice<Complex>& lattice);
00582    LatticeExprNode (const Lattice<DComplex>& lattice);
00583    LatticeExprNode (const Lattice<Bool>& lattice);
00584    LatticeExprNode (const MaskedLattice<Float>& lattice);
00585    LatticeExprNode (const MaskedLattice<Double>& lattice);
00586    LatticeExprNode (const MaskedLattice<Complex>& lattice);
00587    LatticeExprNode (const MaskedLattice<DComplex>& lattice);
00588    LatticeExprNode (const MaskedLattice<Bool>& lattice);
00589 // </group>
00590 
00591 // Create a lattice expression from a region.
00592 // It results in a boolean expression node.
00593 // <group>
00594    LatticeExprNode (const LCRegion& region);
00595    LatticeExprNode (const Slicer& slicer);
00596    LatticeExprNode (const LattRegionHolder& region);
00597 // </group>
00598 
00599 // Masking operator using a condition.
00600 // The given boolean expression forms a mask/region for this expression node.
00601    LatticeExprNode operator[] (const LatticeExprNode& cond) const;
00602 
00603 // Copy constructor (reference semantics)
00604    LatticeExprNode (const LatticeExprNode& other);
00605 
00606 // Destructor, does nothing
00607    virtual ~LatticeExprNode();
00608 
00609 // Assignment (reference semantics)
00610    LatticeExprNode& operator= (const LatticeExprNode& other);
00611 
00612 // Get the IPosition.
00613 // It throws an exception if the node does not contain an IPosition.
00614    const IPosition& getIPosition() const;
00615 
00616 // Convert the expression to another data type.
00617 // <group>
00618    CountedPtr<LELInterface<Float> >    makeFloat() const;
00619    CountedPtr<LELInterface<Double> >   makeDouble() const;
00620    CountedPtr<LELInterface<Complex> >  makeComplex() const;
00621    CountedPtr<LELInterface<DComplex> > makeDComplex() const;
00622    CountedPtr<LELInterface<Bool> >     makeBool() const;
00623 // </group>
00624 
00625 // Evaluate the expression.
00626 // One can be sure that the result is not a reference to another array.
00627 // This function should be used by LatticeExpr and other users.
00628 // <group>
00629    void eval (LELArray<Float>& result, const Slicer& section) const;
00630    void eval (LELArray<Double>& result, const Slicer& section) const;
00631    void eval (LELArray<Complex>& result, const Slicer& section) const;
00632    void eval (LELArray<DComplex>& result, const Slicer& section) const;
00633    void eval (LELArray<Bool>& result, const Slicer& section) const;
00634 // </group>
00635 
00636 // Evaluate the expression.
00637 // The result can be a reference to some internal array (in particular
00638 // to an array in an ArrayLattice object used as a lattice).
00639 // This function is meant for internal use by the LEL classes and
00640 // should not be used externally.
00641 // <group>
00642    void evalRef (LELArrayRef<Float>& result, const Slicer& section) const
00643     { pExprFloat_p->evalRef (result, section); }
00644    void evalRef (LELArrayRef<Double>& result, const Slicer& section) const
00645     { pExprDouble_p->evalRef (result, section); }
00646    void evalRef (LELArrayRef<Complex>& result, const Slicer& section) const
00647     { pExprComplex_p->evalRef (result, section); }
00648    void evalRef (LELArrayRef<DComplex>& result, const Slicer& section) const
00649     { pExprDComplex_p->evalRef (result, section); }
00650    void evalRef (LELArrayRef<Bool>& result, const Slicer& section) const
00651     { pExprBool_p->evalRef (result, section); }
00652 // </group>
00653 
00654 // Evaluate the expression (in case it is a scalar).  The "eval"
00655 // and "get*" functions do the same thing, they just have
00656 // a slightly different interface.
00657 // <group>
00658    void eval (Float& result) const;
00659    void eval (Double& result) const;
00660    void eval (Complex& result) const;
00661    void eval (DComplex& result) const;
00662    void eval (Bool& result) const;
00663    Float getFloat() const;
00664    Double getDouble() const;
00665    Complex getComplex() const;
00666    DComplex getDComplex() const;
00667    Bool getBool() const;
00668 // </group>
00669 
00670 // Evaluate the expression (in case it is a constant array).
00671 // <group>
00672    Array<Float> getArrayFloat() const;
00673    Array<Double> getArrayDouble() const;
00674    Array<Complex> getArrayComplex() const;
00675    Array<DComplex> getArrayDComplex() const;
00676    Array<Bool> getArrayBool() const;
00677 // </group>
00678 
00679 // Get the data type of the expression.
00680    DataType dataType() const
00681       {return dtype_p;}
00682 
00683 // Is the expression node a region?
00684    Bool isRegion() const
00685       {return pAttr_p->isRegion();}
00686 
00687 // Is the result of "eval" a scalar?
00688    Bool isScalar() const
00689       {return pAttr_p->isScalar();}
00690 
00691 // Is the result of "eval" masked?
00692    Bool isMasked() const
00693       {return pAttr_p->isMasked();}
00694 
00695 // Holds the node an invalid scalar?
00696    Bool isInvalidScalar() const
00697     {
00698       if (!donePrepare_p) doPrepare();
00699       return isInvalid_p;
00700     }
00701 
00702 // Return the shape of the Lattice including all degenerate axes
00703 // (ie. axes with a length of one)
00704    const IPosition& shape() const
00705       {return pAttr_p->shape();}
00706 
00707 // Get the attribute object of the expression.
00708    const LELAttribute& getAttribute() const
00709       {return *pAttr_p;}
00710 
00711 // Replace a scalar subexpression by its result.
00712    Bool replaceScalarExpr();
00713   
00714 // Make the object from a Counted<LELInterface> pointer.
00715 // Ideally this function is private, but alas it is needed in LELFunction1D,
00716 // operator==, and more (too many to make them friend).
00717 // <group>
00718    LatticeExprNode(const CountedPtr<LELInterface<Float> >& expr);
00719    LatticeExprNode(const CountedPtr<LELInterface<Double> >& expr);
00720    LatticeExprNode(const CountedPtr<LELInterface<Complex> >& expr);
00721    LatticeExprNode(const CountedPtr<LELInterface<DComplex> >& expr);
00722    LatticeExprNode(const CountedPtr<LELInterface<Bool> >& expr);
00723 // </group>
00724 
00725 // Determine the resulting data type from the given data types.
00726 // An exception is thrown if they are incompatible.
00727    static DataType resultDataType (DataType left, DataType right);
00728 
00729 // Check the arguments of a function and return the resulting attribute object.
00730 // The matchAxes argument tells if the axes have to match exactly or
00731 // whether it is possible that one expression is a subset of another
00732 // (i.e. that axes may be missing).
00733 // <br>The expectArray argument tells if the result should be an array
00734 // which is the case if one of the arguments is an array.
00735    static LELAttribute checkArg (const Block<LatticeExprNode>& arg,
00736                                  const Block<Int>& argType,
00737                                  Bool expectArray,
00738                                  Bool matchAxes = True);
00739 
00740   // Handle locking of the LatticeExpr which is delegated to all of its parts.
00741   // <group>
00742   Bool lock (FileLocker::LockType, uInt nattempts);
00743   void unlock();
00744   Bool hasLock (FileLocker::LockType) const;
00745   void resync();
00746   // </group>
00747 
00748 
00749 private:
00750 // Make the object from a LELInterface* pointer.
00751 // <group>
00752    LatticeExprNode(LELInterface<Float>* expr);
00753    LatticeExprNode(LELInterface<Double>* expr);
00754    LatticeExprNode(LELInterface<Complex>* expr);
00755    LatticeExprNode(LELInterface<DComplex>* expr);
00756    LatticeExprNode(LELInterface<Bool>* expr);
00757 // </group>
00758 
00759 // Test if both operands represent a region.
00760 // An exception is thrown if only one of them is a region.
00761    static Bool areRegions (const LatticeExprNode& left,
00762                            const LatticeExprNode& right);
00763 
00764 // Create a new node for a numerical unary operation.
00765 // The result has the same data type as the input.
00766    static LatticeExprNode newNumUnary (LELUnaryEnums::Operation oper,
00767                                        const LatticeExprNode& expr);
00768 
00769 // Create a new node for a numerical function with 1 argument.
00770 // The result has the same data type as the input.
00771    static LatticeExprNode newNumFunc1D (LELFunctionEnums::Function func,
00772                                         const LatticeExprNode& expr);
00773 
00774 // Create a new node for a real numerical function with 1 argument.
00775 // The result has the same data type as the input.
00776    static LatticeExprNode newRealFunc1D (LELFunctionEnums::Function func,
00777                                          const LatticeExprNode& expr);
00778 
00779 // Create a new node for a complex numerical function with 1 argument.
00780 // The result has the same data type as the input.
00781    static LatticeExprNode newComplexFunc1D (LELFunctionEnums::Function func,
00782                                             const LatticeExprNode& expr);
00783 
00784 // Create a new node for a numerical function with 1 argument that 
00785 // returns a real number
00786    static LatticeExprNode newNumReal1D (LELFunctionEnums::Function func,
00787                                         const LatticeExprNode& expr);
00788 
00789 // Create a new node for a numerical function with 2 arguments.
00790 // The result has the same data type as the combined input type.
00791    static LatticeExprNode newNumFunc2D (LELFunctionEnums::Function func,
00792                                         const LatticeExprNode& left,
00793                                         const LatticeExprNode& right);
00794 
00795 // Create a new node for a numerical binary operator.
00796 // The result has the same data type as the combined input type.
00797    static LatticeExprNode newNumBinary (LELBinaryEnums::Operation oper,
00798                                         const LatticeExprNode& left,
00799                                         const LatticeExprNode& right);
00800 
00801 // Create a new node for a comparison binary operator.
00802 // The result has the same data type as the combined input type.
00803    static LatticeExprNode newBinaryCmp (LELBinaryEnums::Operation oper,
00804                                         const LatticeExprNode& left,
00805                                         const LatticeExprNode& right);
00806 
00807 // Make (if needed and if possible) the expression nodes such that
00808 // the dimensionalities are equal. This is only possible if both
00809 // nodes have a coordinate system.
00810 // It is done by creating an ExtendLattice object for the node
00811 // with the lower dimensionality.
00812    static Int makeEqualDim (LatticeExprNode& expr0,
00813                             LatticeExprNode& expr1);
00814 
00815 // Do the preparation for the evaluation.
00816    void doPrepare() const;
00817 
00818    
00819 // Member variables.  
00820 
00821    Bool                donePrepare_p;
00822    DataType            dtype_p;
00823    Bool                isInvalid_p;
00824    IPosition           iposition_p;
00825    const LELAttribute* pAttr_p;
00826    CountedPtr<LELInterface<Float> >    pExprFloat_p;
00827    CountedPtr<LELInterface<Double> >   pExprDouble_p;
00828    CountedPtr<LELInterface<Complex> >  pExprComplex_p;
00829    CountedPtr<LELInterface<DComplex> > pExprDComplex_p;
00830    CountedPtr<LELInterface<Bool> >     pExprBool_p;
00831 };
00832 
00833 
00834 
00835 inline LatticeExprNode operator% (const LatticeExprNode& left,
00836                                   const LatticeExprNode& right)
00837   { return fmod (left, right); }
00838 inline LatticeExprNode operator^ (const LatticeExprNode& left,
00839                                   const LatticeExprNode& right)
00840   { return pow (left, right); }
00841 
00842 inline LatticeExprNode convertType(const LatticeExprNode& expr, const Float*)
00843   { return toFloat (expr); }
00844 inline LatticeExprNode convertType(const LatticeExprNode& expr, const Double*)
00845   { return toDouble (expr); }
00846 inline LatticeExprNode convertType(const LatticeExprNode& expr, const Complex*)
00847   { return toComplex (expr); }
00848 inline LatticeExprNode convertType(const LatticeExprNode& expr, const DComplex*)
00849   { return toDComplex (expr); }
00850 inline LatticeExprNode convertType(const LatticeExprNode& expr, const Bool*)
00851   { return toBool (expr); }
00852 
00853 } //# NAMESPACE CASA - END
00854 
00855 #endif