MArrayMath.h

Go to the documentation of this file.
00001 //# MArrayMath.h: Mathematical operations on MArray objects
00002 //# Copyright (C) 2012
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: MArrayMath.h 21262 2012-09-07 12:38:36Z gervandiepen $
00027 
00028 #ifndef CASA_MARRAYMATH_H
00029 #define CASA_MARRAYMATH_H
00030 
00031 //# Includes
00032 #include <casacore/casa/aips.h>
00033 #include <casacore/tables/TaQL/MArray.h>
00034 #include <casacore/tables/TaQL/MArrayMathBase.h>
00035 #include <casacore/casa/Arrays/ArrayPartMath.h>
00036 #include <casacore/casa/Arrays/ArrayIter.h>
00037 
00038 namespace casacore {
00039 
00040   // <summary>
00041   // Mathematical operations for MArray objects.
00042   // </summary>
00043   //
00044   // <reviewed reviewer="UNKNOWN" date="" tests="tMArrayMath">
00045   //
00046   // <prerequisite>
00047   //   <li> <linkto class=MArray>MArray</linkto>
00048   // </prerequisite>
00049   //
00050   // <synopsis>
00051   // These functions perform element by element mathematical operations on
00052   // optionally masked arrays and/or scalars.
00053   // If two arrays are used, the arrays must conform, except for allEQ which
00054   // returns False if the arrays do not conform.
00055   //
00056   // The functions in this file can be divided in 3 groups:
00057   // <ul>
00058   //  <li> Full array operations like ==, near, etc.
00059   //       They are defined for array-array and array-scalar operations. Arrays
00060   //       shapes have to be conformant. They operate on all elements
00061   //       (also the masked ones). The result is an MArray with the same
00062   //       shape as the input array(s). It will have a mask if one of the
00063   //       operands has a mask. If both operands have a mask, the resulting
00064   //       mask is the OR of both masks.
00065   //  <li> Full reduction functions like ntrue, all, allEQ, etc.
00066   //       They operate on the unmasked elements only. If there are no unmasked
00067   //       elements, the results is 0 or True.
00068   //  <li> Reduction functions working on unmasked elements in parts of the
00069   //       input array. The result is an MArray that has a mask if the input
00070   //       array has a mask. An output element is masked off if its input
00071   //       part has no unmasked elements.
00072   //       The functors defined at the beginning of this file are used to
00073   //       operate on each part.
00074   //       There are 3 flavours:
00075   //   <ul>
00076   //    <li> partialXXX reduces one or more axes. E.g. one can count the
00077   //         number of True elements for particular array axes.
00078   //         The result is an array with a lower dimensionality.
00079   //         They can be seen as a special versions of the boxedXXX functions.
00080   //    <li> slidingXXX operates in a sliding window over the array. So the
00081   //         result is an array with the same shape as the input, although
00082   //         the output array is smaller if the edge is not filled.
00083   //    <li> boxedXXX divides the input array in boxes with the given size
00084   //         and operates on each box. The result is an array with the same
00085   //         dimensionality, but with a smaller size.
00086   //         If the box size does not fit integrally, the edge box is smaller.
00087   //   </ul>
00088   // </ul>
00089   // </synopsis>
00090   //
00091   // <group name="MArray mathematical operations">
00092 
00093   // Define functors to perform a reduction function on an MArray object.
00094   // <group>
00095   template<typename T> class MSumFunc : public MArrayFunctorBase<T> {
00096   public:
00097     virtual ~MSumFunc() {}
00098     T operator() (const MArray<T>& arr) const { return sum(arr); }
00099   };
00100   template<typename T> class MSumSqrFunc : public MArrayFunctorBase<T> {
00101   public:
00102     virtual ~MSumSqrFunc() {}
00103     T operator() (const MArray<T>& arr) const { return sumsqr(arr); }
00104   };
00105   template<typename T> class MProductFunc : public MArrayFunctorBase<T> {
00106   public:
00107     virtual ~MProductFunc() {}
00108     T operator() (const MArray<T>& arr) const { return product(arr); }
00109   };
00110   template<typename T> class MMinFunc : public MArrayFunctorBase<T> {
00111   public:
00112     virtual ~MMinFunc() {}
00113     T operator() (const MArray<T>& arr) const { return min(arr); }
00114   };
00115   template<typename T> class MMaxFunc : public MArrayFunctorBase<T> {
00116   public:
00117     virtual ~MMaxFunc() {}
00118     T operator() (const MArray<T>& arr) const { return max(arr); }
00119   };
00120   template<typename T> class MMeanFunc : public MArrayFunctorBase<T> {
00121   public:
00122     virtual ~MMeanFunc() {}
00123     T operator() (const MArray<T>& arr) const { return mean(arr); }
00124   };
00125   template<typename T> class MVarianceFunc : public MArrayFunctorBase<T> {
00126   public:
00127     virtual ~MVarianceFunc() {}
00128     T operator() (const MArray<T>& arr) const { return variance(arr); }
00129   };
00130   template<typename T> class MStddevFunc : public MArrayFunctorBase<T> {
00131   public:
00132     virtual ~MStddevFunc() {}
00133     T operator() (const MArray<T>& arr) const { return stddev(arr); }
00134   };
00135   template<typename T> class MAvdevFunc : public MArrayFunctorBase<T> {
00136   public:
00137     virtual ~MAvdevFunc() {}
00138     T operator() (const MArray<T>& arr) const { return avdev(arr); }
00139   };
00140   template<typename T> class MRmsFunc : public MArrayFunctorBase<T> {
00141   public:
00142     virtual ~MRmsFunc() {}
00143     T operator() (const MArray<T>& arr) const { return rms(arr); }
00144   };
00145   template<typename T> class MMedianFunc : public MArrayFunctorBase<T> {
00146   public:
00147     explicit MMedianFunc (Bool sorted=False, Bool takeEvenMean=True,
00148                           Bool inPlace = False)
00149       : itsSorted(sorted), itsTakeEvenMean(takeEvenMean), itsInPlace(inPlace) {}
00150     virtual ~MMedianFunc() {}
00151     T operator() (const MArray<T>& arr) const
00152       { return median(arr, itsSorted, itsTakeEvenMean, itsInPlace); }
00153   private:
00154     Bool itsSorted;
00155     Bool itsTakeEvenMean;
00156     Bool itsInPlace;
00157   };
00158   template<typename T> class MFractileFunc : public MArrayFunctorBase<T> {
00159   public:
00160     explicit MFractileFunc (Float fraction,
00161                             Bool sorted = False, Bool inPlace = False)
00162       : itsFraction(fraction), itsSorted(sorted), itsInPlace(inPlace) {}
00163     virtual ~MFractileFunc() {}
00164     T operator() (const MArray<T>& arr) const
00165       { return fractile(arr, itsFraction, itsSorted, itsInPlace); }
00166   private:
00167     float itsFraction;
00168     Bool  itsSorted;
00169     Bool  itsInPlace;
00170   };
00171 
00172 
00173   // Do partial reduction of an MArray object. I.e., perform the operation
00174   // on a subset of the array axes (the collapse axes).
00175   template<typename T>
00176   inline MArray<T> partialArrayMath (const MArray<T>& a,
00177                                      const IPosition& collapseAxes,
00178                                      const MArrayFunctorBase<T>& funcObj)
00179   {
00180     MArray<T> res;
00181     partialArrayMath (res, a, collapseAxes, funcObj);
00182     return res;
00183   }
00184   template<typename T, typename RES>
00185   void partialArrayMath (MArray<RES>& res,
00186                          const MArray<T>& a,
00187                          const IPosition& collapseAxes,
00188                          const MArrayFunctorBase<T,RES>& funcObj)
00189   {
00190     AlwaysAssert (a.hasMask(), AipsError);
00191     // This can also be done as boxedArrayMath with a removeDegenerate thereafter.
00192     //
00193     // It should be possible to parallelize this loop.
00194     // Determine nr of iteration steps and iterate over that as an int.
00195     // Do not use Array slicing, because that is not thread-safe.
00196     // Instead create ArraySTLIterator directly from Array and blc,trc,
00197     // so funcObj should accept iterators instead of Array.
00198     // However, ArraySTLIterator needs the sliced array, not original.
00199     // Maybe keep ref of itsSteps in iterator instead of array.
00200     // Hmm, tricky for median and fractile.
00201     // Better to make Array copy ctor thread-safe (thus use boost shared_ptr).
00202     ReadOnlyArrayIterator<T>    aiter(a.array(), collapseAxes);
00203     ReadOnlyArrayIterator<Bool> miter(a.mask(),  collapseAxes);
00204     IPosition shape(a.array().shape().removeAxes (collapseAxes));
00205     /*
00206     Int64 nr = 1;
00207     for (uInt i=0; i<collapseAxes.size(); ++i) {
00208       nr *= a.array().shape()[collapseAxes[i]];
00209     }
00211     for (Int64 i=0; i<nr; ++i) {
00212       IPosition pos = findPos(i);
00213       IPosition endPos = pos + cursorShape - 1;
00214       *data[pos] = funcObj(MArray<T>(a.array()(pos,endPos), a.mask()(pos,endpos)));
00215     }
00216     */
00218     res.resize (shape, False);
00219     Array<Bool> resMask(shape);
00220     RES* data = res.array().data();
00221     Bool* mask = resMask.data();
00222     while (!aiter.pastEnd()) {
00223       if (allTrue(miter.array())) {
00224         *mask++ = True;
00225         *data++ = RES();
00226       } else {
00227         *mask++ = False;
00228         *data++ = funcObj(MArray<T> (aiter.array(), miter.array()));
00229       }
00230       aiter.next();
00231       miter.next();
00232     }
00233     res.setMask (resMask);
00234   }
00235   // </group>
00236 
00237 
00238   template<typename T>
00239   inline MArray<T> boxedArrayMath (const MArray<T>& a,
00240                                    const IPosition& boxShape,
00241                                    const MArrayFunctorBase<T>& funcObj)
00242   {
00243     MArray<T> res;
00244     boxedArrayMath (res, a, boxShape, funcObj);
00245     return res;
00246   }
00247   template<typename T, typename RES>
00248   void boxedArrayMath (MArray<RES>& res,
00249                        const MArray<T>& array,
00250                        const IPosition& boxShape,
00251                        const MArrayFunctorBase<T,RES>& funcObj)
00252   {
00253     AlwaysAssert (array.hasMask(), AipsError);
00254     const IPosition& shape = array.shape();
00255     uInt ndim = shape.size();
00256     IPosition fullBoxShape, resShape;
00257     fillBoxedShape (shape, boxShape, fullBoxShape, resShape);
00258     res.resize (resShape, False);
00259     Array<Bool> resMask(resShape);
00260     RES* data = res.array().data();
00261     Bool* mask = resMask.data();
00262     // Loop through all data and assemble as needed.
00263     IPosition blc(ndim, 0);
00264     IPosition trc(fullBoxShape-1);
00265     while (True) {
00266       Array<Bool> subMask (array.mask()(blc,trc));
00267       if (allTrue(subMask)) {
00268         *data++ = RES();
00269         *mask++ = True;
00270       } else {
00271         *data++ = funcObj (MArray<T>(array.array()(blc,trc), subMask));
00272         *mask++ = False;
00273       }
00274       uInt ax;
00275       for (ax=0; ax<ndim; ++ax) {
00276         blc[ax] += fullBoxShape[ax];
00277         if (blc[ax] < shape[ax]) {
00278           trc[ax] += fullBoxShape[ax];
00279           if (trc[ax] >= shape[ax]) {
00280             trc[ax] = shape[ax]-1;
00281           }
00282           break;
00283         }
00284         blc[ax] = 0;
00285         trc[ax] = fullBoxShape[ax]-1;
00286       }
00287       if (ax == ndim) {
00288         break;
00289       }
00290     }
00291     res.setMask (resMask);
00292   }
00293 
00294   template <typename T>
00295   inline MArray<T> slidingArrayMath (const MArray<T>& array,
00296                                      const IPosition& halfBoxShape,
00297                                      const MArrayFunctorBase<T>& funcObj,
00298                                      Bool fillEdge=True)
00299   {
00300     MArray<T> res;
00301     slidingArrayMath (res, array, halfBoxShape, funcObj, fillEdge);
00302     return res;
00303   }
00304   template <typename T, typename RES>
00305   void slidingArrayMath (MArray<RES>& res,
00306                          const MArray<T>& array,
00307                          const IPosition& halfBoxShape,
00308                          const MArrayFunctorBase<T,RES>& funcObj,
00309                          Bool fillEdge=True)
00310   {
00311     AlwaysAssert (array.hasMask(), AipsError);
00312     const IPosition& shape = array.shape();
00313     uInt ndim = shape.size();
00314     IPosition boxEnd, resShape;
00315     Bool empty = fillSlidingShape (shape, halfBoxShape, boxEnd, resShape);
00316     if (fillEdge) {
00317       res.resize (shape, False);
00318       res.array() = RES();
00319       Array<Bool> mask(shape, True);
00320       res.setMask (mask);
00321     } else {
00322       res.resize (resShape, True);
00323     }
00324     if (!empty) {
00325       Array<RES>  resa (res.array());
00326       Array<Bool> resm (res.mask());
00327       if (fillEdge) {
00328         IPosition boxEnd2 (boxEnd/2);
00329         resa.reference (resa(boxEnd2, resShape+boxEnd2-1));
00330         resm.reference (resm(boxEnd2, resShape+boxEnd2-1));
00331       }
00332       typename Array<RES>::iterator  iterarr(resa.begin());
00333       typename Array<Bool>::iterator itermask(resm.begin());
00334       // Loop through all data and assemble as needed.
00335       IPosition blc(ndim, 0);
00336       IPosition trc(boxEnd);
00337       IPosition pos(ndim, 0);
00338       while (True) {
00339         Array<Bool> subMask (array.mask()(blc,trc));
00340         if (allTrue(subMask)) {
00341           *iterarr  = RES();
00342           *itermask = True;
00343         } else {
00344           *iterarr  = funcObj (MArray<T>(array.array()(blc,trc), subMask));
00345           *itermask = False;
00346         }
00347         ++iterarr;
00348         ++itermask;
00349         uInt ax;
00350         for (ax=0; ax<ndim; ++ax) {
00351           if (++pos[ax] < resShape[ax]) {
00352             blc[ax]++;
00353             trc[ax]++;
00354             break;
00355           }
00356           pos(ax) = 0;
00357           blc[ax] = 0;
00358           trc[ax] = boxEnd[ax];
00359         }
00360         if (ax == ndim) {
00361           break;
00362         }
00363       }
00364     }
00365   }
00366 
00367 
00368   // Add, subtract, etc. 2 arrays or array and scalar.
00369   // <group>
00370   template<typename T>
00371   MArray<T> operator+ (const MArray<T>& left, const MArray<T>& right)
00372   { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00373             MArray<T> (left.array() + right.array(),
00374                        left.combineMask(right))); }
00375 
00376   template<typename T>
00377   MArray<T> operator- (const MArray<T>& left, const MArray<T>& right)
00378     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00379               MArray<T> (left.array() - right.array(),
00380                          left.combineMask(right))); }
00381 
00382   template<typename T>
00383   MArray<T> operator* (const MArray<T>& left, const MArray<T>& right)
00384     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00385               MArray<T> (left.array() * right.array(),
00386                          left.combineMask(right))); }
00387 
00388   template<typename T>
00389   MArray<T> operator/ (const MArray<T>& left, const MArray<T>& right)
00390     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00391               MArray<T> (left.array() / right.array(),
00392                          left.combineMask(right))); }
00393 
00394   template<typename T>
00395   MArray<T> operator% (const MArray<T>& left, const MArray<T>& right)
00396     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00397               MArray<T> (left.array() % right.array(),
00398                          left.combineMask(right))); }
00399 
00400   template<typename T>
00401   MArray<T> operator& (const MArray<T>& left, const MArray<T>& right)
00402     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00403               MArray<T> (left.array() & right.array(),
00404                          left.combineMask(right))); }
00405 
00406   template<typename T>
00407   MArray<T> operator| (const MArray<T>& left, const MArray<T>& right)
00408     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00409               MArray<T> (left.array() | right.array(),
00410                          left.combineMask(right))); }
00411 
00412   template<typename T>
00413   MArray<T> operator^ (const MArray<T>& left, const MArray<T>& right)
00414     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00415               MArray<T> (left.array() ^ right.array(),
00416                          left.combineMask(right))); }
00417 
00418   template<typename T>
00419   MArray<T> operator+ (const MArray<T>& left, const T& right)
00420   { return MArray<T> (left.array() + right, left); }
00421 
00422   template<typename T>
00423   MArray<T> operator- (const MArray<T>& left, const T& right)
00424     { return MArray<T> (left.array() - right, left); }
00425 
00426   template<typename T>
00427   MArray<T> operator* (const MArray<T>& left, const T& right)
00428     { return MArray<T> (left.array() * right, left); }
00429 
00430   template<typename T>
00431   MArray<T> operator/ (const MArray<T>& left, const T& right)
00432     { return MArray<T> (left.array() / right, left); }
00433 
00434   template<typename T>
00435   MArray<T> operator% (const MArray<T>& left, const T& right)
00436     { return MArray<T> (left.array() % right, left); }
00437 
00438   template<typename T>
00439   MArray<T> operator& (const MArray<T>& left, const T& right)
00440     { return MArray<T> (left.array() & right, left); }
00441 
00442   template<typename T>
00443   MArray<T> operator| (const MArray<T>& left, const T& right)
00444     { return MArray<T> (left.array() | right, left); }
00445 
00446   template<typename T>
00447   MArray<T> operator^ (const MArray<T>& left, const T& right)
00448     { return MArray<T> (left.array() ^ right, left); }
00449 
00450   template<typename T>
00451   MArray<T> operator+ (const T& left, const MArray<T>& right)
00452     { return MArray<T> (left + right.array(), right); }
00453 
00454   template<typename T>
00455   MArray<T> operator- (const T& left, const MArray<T>& right)
00456     { return MArray<T> (left - right.array(), right); }
00457 
00458   template<typename T>
00459   MArray<T> operator* (const T& left, const MArray<T>& right)
00460     { return MArray<T> (left * right.array(), right); }
00461 
00462   template<typename T>
00463   MArray<T> operator/ (const T& left, const MArray<T>& right)
00464     { return MArray<T> (left / right.array(), right); }
00465 
00466   template<typename T>
00467   MArray<T> operator% (const T& left, const MArray<T>& right)
00468     { return MArray<T> (left % right.array(), right); }
00469 
00470   template<typename T>
00471   MArray<T> operator& (const T& left, const MArray<T>& right)
00472     { return MArray<T> (left & right.array(), right); }
00473 
00474   template<typename T>
00475   MArray<T> operator| (const T& left, const MArray<T>& right)
00476     { return MArray<T> (left | right.array(), right); }
00477 
00478   template<typename T>
00479   MArray<T> operator^ (const T& left, const MArray<T>& right)
00480     { return MArray<T> (left ^ right.array(), right); }
00481   // </group>
00482 
00483   // Negate the elements in an array.
00484   template<typename T>
00485   MArray<T> operator- (const MArray<T>& a)
00486     { return MArray<T> (-a.array(), a); }
00487 
00488   // Take the complement of the elements in an array.
00489   template<typename T>
00490   MArray<T> operator~ (const MArray<T>& a)
00491     { return MArray<T> (~a.array(), a); }
00492 
00493   // Perform mathematical function on each element in an array.
00494   // <group>
00495   template<typename T>
00496   MArray<T> sin(const MArray<T>& a)
00497     { return MArray<T> (sin(a.array()), a); }
00498 
00499   template<typename T>
00500   MArray<T> cos(const MArray<T>& a)
00501     { return MArray<T> (cos(a.array()), a); }
00502 
00503   template<typename T>
00504   MArray<T> tan(const MArray<T>& a)
00505     { return MArray<T> (tan(a.array()), a); }
00506 
00507   template<typename T>
00508   MArray<T> sinh(const MArray<T>& a)
00509     { return MArray<T> (sinh(a.array()), a); }
00510 
00511   template<typename T>
00512   MArray<T> cosh(const MArray<T>& a)
00513     { return MArray<T> (cosh(a.array()), a); }
00514 
00515   template<typename T>
00516   MArray<T> tanh(const MArray<T>& a)
00517     { return MArray<T> (tanh(a.array()), a); }
00518 
00519   template<typename T>
00520   MArray<T> asin(const MArray<T>& a)
00521     { return MArray<T> (asin(a.array()), a); }
00522 
00523   template<typename T>
00524   MArray<T> acos(const MArray<T>& a)
00525     { return MArray<T> (acos(a.array()), a); }
00526 
00527   template<typename T>
00528   MArray<T> atan(const MArray<T>& a)
00529     { return MArray<T> (atan(a.array()), a); }
00530 
00531   template<typename T>
00532   MArray<T> atan2(const MArray<T>& left, const MArray<T>& right)
00533     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00534               MArray<T> (atan2(left.array(), right.array()),
00535                          left.combineMask(right))); }
00536 
00537   template<typename T>
00538   MArray<T> atan2(const MArray<T>& left, const T& right)
00539     { return MArray<T> (atan2(left.array(), right), left); }
00540 
00541   template<typename T>
00542   MArray<T> atan2(const T& left, const MArray<T>& right)
00543     { return MArray<T> (atan2(left, right.array()), right); }
00544 
00545   template<typename T>
00546   MArray<T> exp(const MArray<T>& a)
00547     { return MArray<T> (exp(a.array()), a); }
00548 
00549   template<typename T>
00550   MArray<T> log(const MArray<T>& a)
00551     { return MArray<T> (log(a.array()), a); }
00552 
00553   template<typename T>
00554   MArray<T> log10(const MArray<T>& a)
00555     { return MArray<T> (log10(a.array()), a); }
00556 
00557   template<typename T>
00558   MArray<T> sqrt(const MArray<T>& a)
00559     { return MArray<T> (sqrt(a.array()), a); }
00560 
00561   template<typename T>
00562   MArray<T> square(const MArray<T>& a)
00563     { return MArray<T> (square(a.array()), a); }
00564 
00565   template<typename T>
00566   MArray<T> cube(const MArray<T>& a)
00567     { return MArray<T> (cube(a.array()), a); }
00568 
00569   template<typename T>
00570   MArray<T> pow(const MArray<T>& a, const MArray<T>& exp)
00571     { return (a.isNull() || exp.isNull()  ?  MArray<T>() :
00572               MArray<T> (pow(a.array(), exp.array()),
00573                          a.combineMask(exp))); }
00574 
00575   template<typename T>
00576   MArray<T> pow(const T& a, const MArray<T>& exp)
00577     { return MArray<T> (pow(a, exp.array()), exp); }
00578 
00579   template<typename T>
00580   MArray<T> pow(const MArray<T>& a, const Double& exp)
00581     { return MArray<T> (pow(a.array(), exp), a); }
00582 
00583   template<typename T>
00584   MArray<T> min(const MArray<T>& left, const MArray<T>& right)
00585     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00586               MArray<T> (min(left.array(), right.array()),
00587                          left.combineMask(right))); }
00588 
00589   template<typename T>
00590   MArray<T> min(const MArray<T>& left, const T& right)
00591     { return MArray<T> (min(left.array(), right), left); }
00592 
00593   template<typename T>
00594   MArray<T> min(const T& left, const MArray<T>& right)
00595     { return MArray<T> (min(left, right.array()), right); }
00596 
00597   template<typename T>
00598   MArray<T> max(const MArray<T>& left, const MArray<T>& right)
00599     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00600               MArray<T> (max(left.array(), right.array()),
00601                          left.combineMask(right))); }
00602 
00603   template<typename T>
00604   MArray<T> max(const MArray<T>& left, const T& right)
00605     { return MArray<T> (max(left.array(), right), left); }
00606 
00607   template<typename T>
00608   MArray<T> max(const T& left, const MArray<T>& right)
00609     { return MArray<T> (max(left, right.array()), right); }
00610 
00611   template<typename T>
00612   MArray<T> ceil(const MArray<T>& a)
00613     { return MArray<T> (ceil(a.array()), a); }
00614 
00615   template<typename T>
00616   MArray<T> floor(const MArray<T>& a)
00617     { return MArray<T> (floor(a.array()), a); }
00618 
00619   template<typename T>
00620   MArray<T> round(const MArray<T>& a)
00621     { return MArray<T> (round(a.array()), a); }
00622 
00623   template<typename T>
00624   MArray<T> sign(const MArray<T>& a)
00625     { return MArray<T> (sign(a.array()), a); }
00626 
00627   template<typename T>
00628   MArray<T> abs(const MArray<T>& a)
00629     { return MArray<T> (abs(a.array()), a); }
00630 
00631   template<typename T>
00632   MArray<T> fabs(const MArray<T>& a)
00633     { return MArray<T> (fabs(a.array()), a); }
00634 
00635   template<typename T>
00636   MArray<T> fmod(const MArray<T>& left, const MArray<T>& right)
00637     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00638               MArray<T> (fmod(left.array(), right.array()),
00639                          left.combineMask(right))); }
00640 
00641   template<typename T>
00642   MArray<T> fmod(const MArray<T>& left, const T& right)
00643     { return MArray<T> (fmod(left.array(), right), left); }
00644 
00645   template<typename T>
00646   MArray<T> fmod(const T& left, const MArray<T>& right)
00647     { return MArray<T> (fmod(left, right.array()), right); }
00648 
00649   template<typename T>
00650   MArray<T> floormod(const MArray<T>& left, const MArray<T>& right)
00651     { return (left.isNull() || right.isNull()  ?  MArray<T>() :
00652               MArray<T> (floormod(left.array(), right.array()),
00653                          left.combineMask(right))); }
00654 
00655   template<typename T>
00656   MArray<T> floormod(const MArray<T>& left, const T& right)
00657     { return MArray<T> (floormod(left.array(), right), left); }
00658 
00659   template<typename T>
00660   MArray<T> floormod(const T& left, const MArray<T>& right)
00661     { return MArray<T> (floormod(left, right.array()), right); }
00662 
00663   template<typename T>
00664   MArray<T> conj(const MArray<T>& arr)
00665     { return MArray<T> (conj(arr.array()), arr); }
00666 
00667   inline MArray<Float> real(const MArray<Complex> &arr)
00668     { return MArray<Float> (real(arr.array()), arr); }
00669 
00670   inline MArray<Float> imag(const MArray<Complex> &arr)
00671     { return MArray<Float> (imag(arr.array()), arr); }
00672 
00673   inline MArray<Float> amplitude(const MArray<Complex> &arr)
00674     { return MArray<Float> (amplitude(arr.array()), arr); }
00675 
00676   inline MArray<Float> phase(const MArray<Complex> &arr)
00677     { return MArray<Float> (phase(arr.array()), arr); }
00678 
00679   inline MArray<Double> real(const MArray<DComplex> &arr)
00680     { return MArray<Double> (real(arr.array()), arr); }
00681 
00682   inline MArray<Double> imag(const MArray<DComplex> &arr)
00683     { return MArray<Double> (imag(arr.array()), arr); }
00684 
00685   inline MArray<Double> amplitude(const MArray<DComplex> &arr)
00686     { return MArray<Double> (amplitude(arr.array()), arr); }
00687 
00688   inline MArray<Double> phase(const MArray<DComplex> &arr)
00689     { return MArray<Double> (phase(arr.array()), arr); }
00690   // </group>
00691 
00692 
00693   // Reduce an array to a scalar using the unmasked elements only.
00694   // The result is 0 if there are no unmasked elements.
00695   // <group>
00696   template<typename T>
00697   T sum(const MArray<T>& a)
00698   {
00699     if (a.hasMask()) {
00700       return a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00701         accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00702                             a.mask().cbegin(), T(), std::plus<T>()) :
00703         accumulateMasked<T>(a.array().begin(),  a.array().end(),
00704                             a.mask().begin(),  T(), std::plus<T>());
00705     }
00706     return sum(a.array());
00707   }
00708 
00709   template<typename T>
00710   T sumsqr(const MArray<T>& a)
00711   {
00712     if (a.hasMask()) {
00713       return a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00714         accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00715                             a.mask().cbegin(), T(), SumSqr<T>()) :
00716         accumulateMasked<T>(a.array().begin(),  a.array().end(),
00717                             a.mask().begin(),  T(), SumSqr<T>());
00718     }
00719     return sumsqr(a.array());
00720   }
00721 
00722   template<typename T>
00723   T product(const MArray<T>& a)
00724   {
00725     if (a.hasMask()) {
00726       return a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00727         accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00728                             a.mask().cbegin(), std::multiplies<T>()) :
00729         accumulateMasked<T>(a.array().begin(),  a.array().end(),
00730                             a.mask().begin(),  std::multiplies<T>());
00731     }
00732     return product(a.array());
00733   }
00734 
00735   template<typename T>
00736   T min(const MArray<T>& a)
00737   {
00738     if (a.hasMask()) {
00739       return a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00740         accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00741                             a.mask().cbegin(), Min<T>()) :
00742         accumulateMasked<T>(a.array().begin(),  a.array().end(),
00743                             a.mask().begin(),  Min<T>());
00744     }
00745     return min(a.array());
00746   }
00747 
00748   template<typename T>
00749   T max(const MArray<T>& a)
00750   {
00751     if (a.hasMask()) {
00752       return a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00753         accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00754                             a.mask().cbegin(), Max<T>()) :
00755         accumulateMasked<T>(a.array().begin(),  a.array().end(),
00756                             a.mask().begin(),  Max<T>());
00757     }
00758     return max(a.array());
00759   }
00760 
00761   template<typename T>
00762   T mean(const MArray<T>& a)
00763   {
00764     Int64 nv = a.nvalid();
00765     if (nv == 0) return T();
00766     if (! a.hasMask()) return mean(a.array());
00767     return T(sum(a) / (1.0*nv));
00768   }
00769 
00770   template<typename T>
00771   T variance(const MArray<T>& a, T mean)
00772   {
00773     Int64 nv = a.nvalid();
00774     if (nv < 2) return T();
00775     if (! a.hasMask()) return variance(a.array(), mean);
00776     T sum = a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00777       accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00778                           a.mask().cbegin(), T(), SumSqrDiff<T>(mean)) :
00779       accumulateMasked<T>(a.array().begin(),  a.array().end(),
00780                           a.mask().begin(),  T(), SumSqrDiff<T>(mean));
00781     return T(sum / (1.0*nv - 1));
00782   }
00783 
00784   template<typename T>
00785   T variance(const MArray<T>& a)
00786   {
00787     return variance(a, mean(a));
00788   }
00789 
00790   template<typename T>
00791   T stddev(const MArray<T>& a)
00792   {
00793     return sqrt(variance(a));
00794   }
00795 
00796   template<typename T>
00797   T stddev(const MArray<T>& a, T mean)
00798   {
00799     return sqrt(variance(a, mean));
00800   }
00801 
00802   template<typename T>
00803   T avdev(const MArray<T>& a, T mean)
00804   {
00805     Int64 nv = a.nvalid();
00806     if (nv == 0) return T();
00807     if (! a.hasMask()) return avdev(a.array(), mean);
00808     T sum = a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00809       accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00810                           a.mask().cbegin(), T(), SumAbsDiff<T>(mean)) :
00811       accumulateMasked<T>(a.array().begin(),  a.array().end(),
00812                           a.mask().begin(),  T(), SumAbsDiff<T>(mean));
00813     return T(sum / (1.0*nv));
00814   }
00815 
00816   template<typename T>
00817   T avdev(const MArray<T>& a)
00818   {
00819     return avdev(a, mean(a));
00820   }
00821 
00822   template<typename T>
00823   T rms(const MArray<T>& a)
00824   {
00825     Int64 nv = a.nvalid();
00826     if (nv == 0) return T();
00827     if (! a.hasMask()) return rms(a.array());
00828     T sum = a.array().contiguousStorage() && a.mask().contiguousStorage() ?
00829       accumulateMasked<T>(a.array().cbegin(), a.array().cend(),
00830                           a.mask().cbegin(), T(), SumSqr<T>()) :
00831       accumulateMasked<T>(a.array().begin(),  a.array().end(),
00832                           a.mask().begin(),  T(), SumSqr<T>());
00833     return T(sqrt(sum / (1.0*nv)));
00834   }
00835 
00836   template<typename T>
00837   T median(const MArray<T> &a, Bool sorted, Bool takeEvenMean,
00838            Bool inPlace=False)
00839   {
00840     // The normal median function needs at least one element, so shortcut.
00841     if (a.empty()) return T();
00842     if (! a.hasMask()) return median(a.array(), sorted, takeEvenMean, inPlace);
00843     Block<T> buf(a.size());
00844     Int64 nv = a.flatten (buf.storage(), buf.size());
00845     if (nv == 0) return T();
00846     Array<T> arr(IPosition(1, nv), buf.storage(), SHARE);
00847     // Median can be taken in place.
00848     return median (arr, sorted, takeEvenMean, True);
00849   }
00850   template<typename T>
00851   inline T median(const MArray<T> &a)
00852     { return median (a, False, (a.size() <= 100), False); }
00853   template<typename T>
00854   inline T median(const MArray<T> &a, Bool sorted)
00855     { return median (a, sorted, (a.nelements() <= 100), False); }
00856   template<typename T>
00857   inline T medianInPlace(const MArray<T> &a, Bool sorted = False)
00858     { return median (a, sorted, (a.nelements() <= 100), True); }
00859 
00860   // Return the fractile of an array.
00861   // It returns the value at the given fraction of the array.
00862   // A fraction of 0.5 is the same as the median, be it that no mean of
00863   // the two middle elements is taken if the array has an even nr of elements.
00864   // It uses kthLargest if the array is not sorted yet.
00865   template<typename T>
00866   T fractile(const MArray<T> &a, Float fraction, Bool sorted=False,
00867              Bool inPlace=False)
00868   {
00869     // The normal median function needs at least one element, so shortcut.
00870     if (a.empty()) return T();
00871     if (! a.hasMask()) return fractile(a.array(), fraction, sorted, inPlace);
00872     Block<T> buf(a.size());
00873     Int64 nv = a.flatten (buf.storage(), a.size());
00874     if (nv == 0) return T();
00875     Array<T> arr(IPosition(1, nv), buf.storage(), SHARE);
00876     return fractile (arr, fraction, sorted, True);
00877   }
00878   // </group>
00879 
00880   // Get partial sums, etc.
00881   // <group>
00882   template<typename T>
00883   MArray<T> partialSums (const MArray<T>& a,
00884                          const IPosition& collapseAxes)
00885   {
00886     if (a.isNull()) {
00887       return MArray<T>();
00888     } else if (! a.hasMask()) {
00889       return MArray<T>(partialSums (a.array(), collapseAxes));
00890     }
00891     return partialArrayMath (a, collapseAxes, MSumFunc<T>());
00892   }
00893   template<typename T>
00894   MArray<T> partialSumSqrs (const MArray<T>& a,
00895                             const IPosition& collapseAxes)
00896   {
00897     if (a.isNull()) {
00898       return MArray<T>();
00899     } else if (! a.hasMask()) {
00900       return MArray<T>(partialArrayMath (a.array(), collapseAxes,
00901                                          SumSqrFunc<T>()));
00902     }
00903     return partialArrayMath (a, collapseAxes, MSumSqrFunc<T>());
00904   }
00905   template<typename T>
00906   MArray<T> partialProducts (const MArray<T>& a,
00907                              const IPosition& collapseAxes)
00908   {
00909     if (a.isNull()) {
00910       return MArray<T>();
00911     } else if (! a.hasMask()) {
00912       return MArray<T>(partialProducts (a.array(), collapseAxes));
00913     }
00914     return partialArrayMath (a, collapseAxes, MProductFunc<T>());
00915   }
00916   template<typename T>
00917   MArray<T> partialMins (const MArray<T>& a,
00918                          const IPosition& collapseAxes)
00919   {
00920     if (a.isNull()) {
00921       return MArray<T>();
00922     } else if (! a.hasMask()) {
00923       return MArray<T>(partialMins (a.array(), collapseAxes));
00924     }
00925     return partialArrayMath (a, collapseAxes, MMinFunc<T>());
00926   }
00927   template<typename T>
00928   MArray<T> partialMaxs (const MArray<T>& a,
00929                          const IPosition& collapseAxes)
00930   {
00931     if (a.isNull()) {
00932       return MArray<T>();
00933     } else if (! a.hasMask()) {
00934       return MArray<T>(partialMaxs (a.array(), collapseAxes));
00935     }
00936     return partialArrayMath (a, collapseAxes, MMaxFunc<T>());
00937   }
00938   template<typename T>
00939   MArray<T> partialMeans (const MArray<T>& a,
00940                           const IPosition& collapseAxes)
00941   {
00942     if (a.isNull()) {
00943       return MArray<T>();
00944     } else if (! a.hasMask()) {
00945       return MArray<T>(partialMeans (a.array(), collapseAxes));
00946     }
00947     return partialArrayMath (a, collapseAxes, MMeanFunc<T>());
00948   }
00949   template<typename T>
00950   MArray<T> partialVariances (const MArray<T>& a,
00951                               const IPosition& collapseAxes)
00952   {
00953     if (a.isNull()) {
00954       return MArray<T>();
00955     } else if (! a.hasMask()) {
00956       return MArray<T>(partialVariances (a.array(), collapseAxes));
00957     }
00958     return partialArrayMath (a, collapseAxes, MVarianceFunc<T>());
00959   }
00960   template<typename T>
00961   MArray<T> partialStddevs (const MArray<T>& a,
00962                             const IPosition& collapseAxes)
00963   {
00964     if (a.isNull()) {
00965       return MArray<T>();
00966     } else if (! a.hasMask()) {
00967       return MArray<T>(partialStddevs (a.array(), collapseAxes));
00968     }
00969     return partialArrayMath (a, collapseAxes, MStddevFunc<T>());
00970   }
00971   template<typename T>
00972   MArray<T> partialAvdevs (const MArray<T>& a,
00973                            const IPosition& collapseAxes)
00974   {
00975     if (a.isNull()) {
00976       return MArray<T>();
00977     } else if (! a.hasMask()) {
00978       return MArray<T>(partialAvdevs (a.array(), collapseAxes));
00979     }
00980     return partialArrayMath (a, collapseAxes, MAvdevFunc<T>());
00981   }
00982   template<typename T>
00983   MArray<T> partialRmss (const MArray<T>& a,
00984                          const IPosition& collapseAxes)
00985   {
00986     if (a.isNull()) {
00987       return MArray<T>();
00988     } else if (! a.hasMask()) {
00989       return MArray<T>(partialRmss (a.array(), collapseAxes));
00990     }
00991     return partialArrayMath (a, collapseAxes, MRmsFunc<T>());
00992   }
00993   template<typename T>
00994   MArray<T> partialMedians (const MArray<T>& a,
00995                             const IPosition& collapseAxes,
00996                             Bool takeEvenMean=False,
00997                             Bool inPlace=False)
00998   {
00999     if (a.isNull()) {
01000       return MArray<T>();
01001     } else if (! a.hasMask()) {
01002       return MArray<T>(partialMedians (a.array(), collapseAxes,
01003                                        takeEvenMean, inPlace));
01004     }
01005     return partialArrayMath (a, collapseAxes,
01006                              MMedianFunc<T>(False, takeEvenMean, inPlace));
01007   }
01008   template<typename T>
01009   MArray<T> partialFractiles (const MArray<T>& a,
01010                               const IPosition& collapseAxes,
01011                               Float fraction,
01012                               Bool inPlace=False)
01013   {
01014     if (a.isNull()) {
01015       return MArray<T>();
01016     } else if (! a.hasMask()) {
01017       return MArray<T>(partialFractiles (a.array(), collapseAxes,
01018                                          fraction, inPlace));
01019     }
01020     return partialArrayMath (a, collapseAxes,
01021                              MFractileFunc<T>(fraction, False, inPlace));
01022   }
01023   // </group>
01024 
01025   // Get sliding sums.
01026   // <group>
01027   template<typename T>
01028   MArray<T> slidingSums (const MArray<T>& a,
01029                          const IPosition& halfBoxSize, Bool fillEdge=True)
01030   {
01031     if (a.isNull()) {
01032       return MArray<T>();
01033     } else if (! a.hasMask()) {
01034       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01035                                           SumFunc<T>(), fillEdge));
01036     }
01037     return slidingArrayMath (a, halfBoxSize, MSumFunc<T>(), fillEdge);
01038   }
01039   template<typename T>
01040   MArray<T> slidingSumSqrs (const MArray<T>& a,
01041                             const IPosition& halfBoxSize, Bool fillEdge=True)
01042   {
01043     if (a.isNull()) {
01044       return MArray<T>();
01045     } else if (! a.hasMask()) {
01046       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01047                                          SumSqrFunc<T>(), fillEdge));
01048     }
01049     return slidingArrayMath (a, halfBoxSize, MSumSqrFunc<T>(), fillEdge);
01050   }
01051   template<typename T>
01052   MArray<T> slidingProducts (const MArray<T>& a,
01053                              const IPosition& halfBoxSize, Bool fillEdge=True)
01054   {
01055     if (a.isNull()) {
01056       return MArray<T>();
01057     } else if (! a.hasMask()) {
01058       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01059                                           ProductFunc<T>(), fillEdge));
01060     }
01061     return slidingArrayMath (a, halfBoxSize, MProductFunc<T>(), fillEdge);
01062   }
01063   template<typename T>
01064   MArray<T> slidingMins (const MArray<T>& a,
01065                          const IPosition& halfBoxSize, Bool fillEdge=True)
01066   {
01067     if (a.isNull()) {
01068       return MArray<T>();
01069     } else if (! a.hasMask()) {
01070       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01071                                           MinFunc<T>(), fillEdge));
01072     }
01073     return slidingArrayMath (a, halfBoxSize, MMinFunc<T>(), fillEdge);
01074   }
01075   template<typename T>
01076   MArray<T> slidingMaxs (const MArray<T>& a,
01077                          const IPosition& halfBoxSize, Bool fillEdge=True)
01078   {
01079     if (a.isNull()) {
01080       return MArray<T>();
01081     } else if (! a.hasMask()) {
01082       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01083                                           MaxFunc<T>(), fillEdge));
01084     }
01085     return slidingArrayMath (a, halfBoxSize, MMaxFunc<T>(), fillEdge);
01086   }
01087   template<typename T>
01088   MArray<T> slidingMeans (const MArray<T>& a,
01089                           const IPosition& halfBoxSize, Bool fillEdge=True)
01090   {
01091     if (a.isNull()) {
01092       return MArray<T>();
01093     } else if (! a.hasMask()) {
01094       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01095                                           MeanFunc<T>(), fillEdge));
01096     }
01097     return slidingArrayMath (a, halfBoxSize, MMeanFunc<T>(), fillEdge);
01098   }
01099   template<typename T>
01100   MArray<T> slidingVariances (const MArray<T>& a,
01101                               const IPosition& halfBoxSize, Bool fillEdge=True)
01102   {
01103     if (a.isNull()) {
01104       return MArray<T>();
01105     } else if (! a.hasMask()) {
01106       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01107                                           VarianceFunc<T>(), fillEdge));
01108     }
01109     return slidingArrayMath (a, halfBoxSize, MVarianceFunc<T>(), fillEdge);
01110   }
01111   template<typename T>
01112   MArray<T> slidingStddevs (const MArray<T>& a,
01113                             const IPosition& halfBoxSize, Bool fillEdge=True)
01114   {
01115     if (a.isNull()) {
01116       return MArray<T>();
01117     } else if (! a.hasMask()) {
01118       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01119                                           StddevFunc<T>(), fillEdge));
01120     }
01121     return slidingArrayMath (a, halfBoxSize, MStddevFunc<T>(), fillEdge);
01122   }
01123   template<typename T>
01124   MArray<T> slidingAvdevs (const MArray<T>& a,
01125                            const IPosition& halfBoxSize, Bool fillEdge=True)
01126   {
01127     if (a.isNull()) {
01128       return MArray<T>();
01129     } else if (! a.hasMask()) {
01130       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01131                                           AvdevFunc<T>(), fillEdge));
01132     }
01133     return slidingArrayMath (a, halfBoxSize, MAvdevFunc<T>(), fillEdge);
01134   }
01135   template<typename T>
01136   MArray<T> slidingRmss (const MArray<T>& a,
01137                          const IPosition& halfBoxSize, Bool fillEdge=True)
01138   {
01139     if (a.isNull()) {
01140       return MArray<T>();
01141     } else if (! a.hasMask()) {
01142       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01143                                           RmsFunc<T>(), fillEdge));
01144     }
01145     return slidingArrayMath (a, halfBoxSize, MRmsFunc<T>(), fillEdge);
01146   }
01147   template<typename T>
01148   MArray<T> slidingMedians (const MArray<T>& a,
01149                             const IPosition& halfBoxSize,
01150                             Bool takeEvenMean=False,
01151                             Bool inPlace=False,
01152                             Bool fillEdge=True)
01153   {
01154     if (a.isNull()) {
01155       return MArray<T>();
01156     } else if (! a.hasMask()) {
01157       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01158                                          MedianFunc<T>(False, takeEvenMean,
01159                                                        inPlace),
01160                                          fillEdge));
01161     }
01162     return slidingArrayMath (a, halfBoxSize,
01163                              MMedianFunc<T>(False, takeEvenMean, inPlace),
01164                              fillEdge);
01165   }
01166   template<typename T>
01167   MArray<T> slidingFractiles (const MArray<T>& a,
01168                               const IPosition& halfBoxSize,
01169                               Float fraction,
01170                               Bool inPlace=False,
01171                               Bool fillEdge=True)
01172   {
01173     if (a.isNull()) {
01174       return MArray<T>();
01175     } else if (! a.hasMask()) {
01176       return MArray<T>(slidingArrayMath (a.array(), halfBoxSize,
01177                                          FractileFunc<T>(fraction, False,
01178                                                          inPlace),
01179                                          fillEdge));
01180     }
01181     return slidingArrayMath (a, halfBoxSize,
01182                              MFractileFunc<T>(fraction, False, inPlace),
01183                              fillEdge);
01184   }
01185   // </group>
01186 
01187   // Get boxed sums.
01188   // <group>
01189   template<typename T>
01190   MArray<T> boxedSums (const MArray<T>& a,
01191                        const IPosition& boxSize)
01192   {
01193     if (a.isNull()) {
01194       return MArray<T>();
01195     } else if (! a.hasMask()) {
01196       return MArray<T>(boxedArrayMath (a.array(), boxSize, SumFunc<T>()));
01197     }
01198     return boxedArrayMath (a, boxSize, MSumFunc<T>());
01199   }
01200   template<typename T>
01201   MArray<T> boxedSumSqrs (const MArray<T>& a,
01202                           const IPosition& boxSize)
01203   {
01204     if (a.isNull()) {
01205       return MArray<T>();
01206     } else if (! a.hasMask()) {
01207       return MArray<T>(boxedArrayMath (a.array(), boxSize, SumSqrFunc<T>()));
01208     }
01209     return boxedArrayMath (a, boxSize, MSumSqrFunc<T>());
01210   }
01211   template<typename T>
01212   MArray<T> boxedProducts (const MArray<T>& a,
01213                            const IPosition& boxSize)
01214   {
01215     if (a.isNull()) {
01216       return MArray<T>();
01217     } else if (! a.hasMask()) {
01218       return MArray<T>(boxedArrayMath (a.array(), boxSize, ProductFunc<T>()));
01219     }
01220     return boxedArrayMath (a, boxSize, MProductFunc<T>());
01221   }
01222   template<typename T>
01223   MArray<T> boxedMins (const MArray<T>& a,
01224                        const IPosition& boxSize)
01225   {
01226     if (a.isNull()) {
01227       return MArray<T>();
01228     } else if (! a.hasMask()) {
01229       return MArray<T>(boxedArrayMath (a.array(), boxSize, MinFunc<T>()));
01230     }
01231     return boxedArrayMath (a, boxSize, MMinFunc<T>());
01232   }
01233   template<typename T>
01234   MArray<T> boxedMaxs (const MArray<T>& a,
01235                        const IPosition& boxSize)
01236   {
01237     if (a.isNull()) {
01238       return MArray<T>();
01239     } else if (! a.hasMask()) {
01240       return MArray<T>(boxedArrayMath (a.array(), boxSize, MaxFunc<T>()));
01241     }
01242     return boxedArrayMath (a, boxSize, MMaxFunc<T>());
01243   }
01244   template<typename T>
01245   MArray<T> boxedMeans (const MArray<T>& a,
01246                         const IPosition& boxSize)
01247   {
01248     if (a.isNull()) {
01249       return MArray<T>();
01250     } else if (! a.hasMask()) {
01251       return MArray<T>(boxedArrayMath (a.array(), boxSize, MeanFunc<T>()));
01252     }
01253     return boxedArrayMath (a, boxSize, MMeanFunc<T>());
01254   }
01255   template<typename T>
01256   MArray<T> boxedVariances (const MArray<T>& a,
01257                             const IPosition& boxSize)
01258   {
01259     if (a.isNull()) {
01260       return MArray<T>();
01261     } else if (! a.hasMask()) {
01262       return MArray<T>(boxedArrayMath (a.array(), boxSize, VarianceFunc<T>()));
01263     }
01264     return boxedArrayMath (a, boxSize, MVarianceFunc<T>());
01265   }
01266   template<typename T>
01267   MArray<T> boxedStddevs (const MArray<T>& a,
01268                           const IPosition& boxSize)
01269   {
01270     if (a.isNull()) {
01271       return MArray<T>();
01272     } else if (! a.hasMask()) {
01273       return MArray<T>(boxedArrayMath (a.array(), boxSize, StddevFunc<T>()));
01274     }
01275     return boxedArrayMath (a, boxSize, MStddevFunc<T>());
01276   }
01277   template<typename T>
01278   MArray<T> boxedAvdevs (const MArray<T>& a,
01279                          const IPosition& boxSize)
01280   {
01281     if (a.isNull()) {
01282       return MArray<T>();
01283     } else if (! a.hasMask()) {
01284       return MArray<T>(boxedArrayMath (a.array(), boxSize, AvdevFunc<T>()));
01285     }
01286     return boxedArrayMath (a, boxSize, MAvdevFunc<T>());
01287   }
01288   template<typename T>
01289   MArray<T> boxedRmss (const MArray<T>& a,
01290                        const IPosition& boxSize)
01291   {
01292     if (a.isNull()) {
01293       return MArray<T>();
01294     } else if (! a.hasMask()) {
01295       return MArray<T>(boxedArrayMath (a.array(), boxSize, RmsFunc<T>()));
01296     }
01297     return boxedArrayMath (a, boxSize, MRmsFunc<T>());
01298   }
01299   template<typename T>
01300   MArray<T> boxedMedians (const MArray<T>& a,
01301                           const IPosition& boxSize,
01302                           Bool takeEvenMean=False,
01303                           Bool inPlace=False)
01304   {
01305     if (a.isNull()) {
01306       return MArray<T>();
01307     } else if (! a.hasMask()) {
01308       return MArray<T>(boxedArrayMath (a.array(), boxSize,
01309                                        MedianFunc<T>(False, takeEvenMean,
01310                                                      inPlace)));
01311     }
01312     return boxedArrayMath (a, boxSize,
01313                            MMedianFunc<T>(False, takeEvenMean, inPlace));
01314   }
01315   template<typename T>
01316   MArray<T> boxedFractiles (const MArray<T>& a,
01317                             const IPosition& boxSize,
01318                             Float fraction,
01319                             Bool inPlace=False)
01320   {
01321     if (a.isNull()) {
01322       return MArray<T>();
01323     } else if (! a.hasMask()) {
01324       return MArray<T>(boxedArrayMath (a.array(), boxSize,
01325                                        FractileFunc<T>(fraction, False,
01326                                                        inPlace)));
01327     }
01328     return boxedArrayMath (a, boxSize,
01329                            MFractileFunc<T>(fraction, False, inPlace));
01330   }
01331   // </group>
01332 
01333   // </group>
01334 
01335 } //# end namespace
01336 
01337 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1