//# MaskArrMath.cc: Simple mathematics done with MaskedArray's. //# Copyright (C) 1993,1994,1995,1999,2001 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_MASKARRMATH_2_TCC #define CASA_MASKARRMATH_2_TCC #include "ArrayLogical.h" #include "MaskArrMath.h" #include "Array.h" #include "ArrayError.h" #include "ArrayIter.h" #include "VectorIter.h" #include namespace casacore { //# NAMESPACE CASACORE - BEGIN #define MARRM_IOP_MA(IOP,STRIOP) \ template \ const MaskedArray & operator IOP (const MaskedArray &left, \ const Array &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::operator" STRIOP "(const MaskedArray &, const Array &)" \ " - arrays do not conform")); \ } \ \ bool leftarrDelete; \ T *leftarrStorage = left.getRWArrayStorage(leftarrDelete); \ T *leftarrS = leftarrStorage; \ \ bool leftmaskDelete; \ const LogicalArrayElem *leftmaskStorage = \ left.getMaskStorage(leftmaskDelete); \ const LogicalArrayElem *leftmaskS = leftmaskStorage; \ \ bool rightDelete; \ const T *rightStorage = right.getStorage(rightDelete); \ const T *rightS = rightStorage; \ \ size_t ntotal = left.nelements(); \ while (ntotal--) { \ if (*leftmaskS) { \ *leftarrS IOP *rightS; \ } \ leftarrS++; \ leftmaskS++; \ rightS++; \ } \ \ left.putArrayStorage(leftarrStorage, leftarrDelete); \ left.freeMaskStorage(leftmaskStorage, leftmaskDelete); \ right.freeStorage(rightStorage, rightDelete); \ \ return left; \ } #define MARRM_IOP_AM(IOP,STRIOP) \ template \ Array & operator IOP (Array &left, const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::operator" STRIOP "(Array &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ bool leftDelete; \ T *leftStorage = left.getStorage(leftDelete); \ T *leftS = leftStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ bool rightmaskDelete; \ const LogicalArrayElem *rightmaskStorage = \ right.getMaskStorage(rightmaskDelete); \ const LogicalArrayElem *rightmaskS = rightmaskStorage; \ \ size_t ntotal = left.nelements(); \ while (ntotal--) { \ if (*rightmaskS) { \ *leftS IOP *rightarrS; \ } \ leftS++; \ rightarrS++; \ rightmaskS++; \ } \ \ left.putStorage(leftStorage, leftDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ right.freeMaskStorage(rightmaskStorage, rightmaskDelete); \ \ return left; \ } #define MARRM_IOP_MM(IOP,STRIOP) \ template \ const MaskedArray & operator IOP (const MaskedArray &left, \ const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::operator" STRIOP "(const MaskedArray &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ bool leftarrDelete; \ T *leftarrStorage = left.getRWArrayStorage(leftarrDelete); \ T *leftarrS = leftarrStorage; \ \ bool leftmaskDelete; \ const LogicalArrayElem *leftmaskStorage \ = left.getMaskStorage(leftmaskDelete); \ const LogicalArrayElem *leftmaskS = leftmaskStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ bool rightmaskDelete; \ const LogicalArrayElem *rightmaskStorage \ = right.getMaskStorage(rightmaskDelete); \ const LogicalArrayElem *rightmaskS = rightmaskStorage; \ \ size_t ntotal = left.nelements(); \ while (ntotal--) { \ if (*leftmaskS && *rightmaskS) { \ *leftarrS IOP *rightarrS; \ } \ leftarrS++; \ leftmaskS++; \ rightarrS++; \ rightmaskS++; \ } \ \ left.putArrayStorage(leftarrStorage, leftarrDelete); \ left.freeMaskStorage(leftmaskStorage, leftmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ right.freeMaskStorage(rightmaskStorage, rightmaskDelete); \ \ return left; \ } #define MARRM_IOP_MM2(IOP,STRIOP) \ template \ const MaskedArray & operator IOP (const MaskedArray &left, \ const MaskedArray &right) \ { \ if (left.shape()!=right.shape()) { \ throw (ArrayConformanceError \ ("::operator" STRIOP "(const MaskedArray &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ bool leftarrDelete; \ T *leftarrStorage = left.getRWArrayStorage(leftarrDelete); \ T *leftarrS = leftarrStorage; \ \ bool leftmaskDelete; \ const LogicalArrayElem *leftmaskStorage \ = left.getMaskStorage(leftmaskDelete); \ const LogicalArrayElem *leftmaskS = leftmaskStorage; \ \ bool rightarrDelete; \ const S *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const S *rightarrS = rightarrStorage; \ \ bool rightmaskDelete; \ const LogicalArrayElem *rightmaskStorage \ = right.getMaskStorage(rightmaskDelete); \ const LogicalArrayElem *rightmaskS = rightmaskStorage; \ \ size_t ntotal = left.nelements(); \ while (ntotal--) { \ if (*leftmaskS && *rightmaskS) { \ *leftarrS IOP *rightarrS; \ } \ leftarrS++; \ leftmaskS++; \ rightarrS++; \ rightmaskS++; \ } \ \ left.putArrayStorage(leftarrStorage, leftarrDelete); \ left.freeMaskStorage(leftmaskStorage, leftmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ right.freeMaskStorage(rightmaskStorage, rightmaskDelete); \ \ return left; \ } #define MARRM_IOP_MS(IOP) \ template \ const MaskedArray & operator IOP (const MaskedArray &left, \ const T &right) \ { \ bool leftarrDelete; \ T *leftarrStorage = left.getRWArrayStorage(leftarrDelete); \ T *leftarrS = leftarrStorage; \ \ bool leftmaskDelete; \ const LogicalArrayElem *leftmaskStorage \ = left.getMaskStorage(leftmaskDelete); \ const LogicalArrayElem *leftmaskS = leftmaskStorage; \ \ size_t ntotal = left.nelements(); \ while (ntotal--) { \ if (*leftmaskS) { \ *leftarrS IOP right; \ } \ leftarrS++; \ leftmaskS++; \ } \ \ left.putArrayStorage(leftarrStorage, leftarrDelete); \ left.freeMaskStorage(leftmaskStorage, leftmaskDelete); \ \ return left; \ } MARRM_IOP_MA ( += , "+=" ) MARRM_IOP_MA ( -= , "-=" ) MARRM_IOP_MA ( *= , "*=" ) MARRM_IOP_MA ( /= , "/=" ) MARRM_IOP_AM ( += , "+=" ) MARRM_IOP_AM ( -= , "-=" ) MARRM_IOP_AM ( *= , "*=" ) MARRM_IOP_AM ( /= , "/=" ) MARRM_IOP_MM ( += , "+=" ) MARRM_IOP_MM ( -= , "-=" ) MARRM_IOP_MM ( *= , "*=" ) MARRM_IOP_MM ( /= , "/=" ) MARRM_IOP_MM2 ( /= , "/=" ) MARRM_IOP_MS ( += ) MARRM_IOP_MS ( -= ) MARRM_IOP_MS ( *= ) MARRM_IOP_MS ( /= ) template MaskedArray operator+ (const MaskedArray &left) { MaskedArray result (left.copy()); return result; } template MaskedArray operator- (const MaskedArray &left) { MaskedArray result (left.copy()); bool resultarrDelete; T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); T *resultarrS = resultarrStorage; bool resultmaskDelete; const LogicalArrayElem *resultmaskStorage = result.getMaskStorage(resultmaskDelete); const LogicalArrayElem *resultmaskS = resultmaskStorage; size_t ntotal = result.nelements(); while (ntotal--) { if (*resultmaskS) { *resultarrS = -(*resultarrS); } resultarrS++; resultmaskS++; } result.putArrayStorage(resultarrStorage, resultarrDelete); result.freeMaskStorage(resultmaskStorage, resultmaskDelete); return result; } #define MARRM_OP_MA(OP,IOP,STROP) \ template \ MaskedArray operator OP (const MaskedArray &left, \ const Array &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::operator" STROP "(const MaskedArray &, const Array &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result (left.copy()); \ \ result IOP right; \ \ return result; \ } #define MARRM_OP_AM(OP,IOP,STROP) \ template \ MaskedArray operator OP (const Array &left, \ const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::operator" STROP "(const Array &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result (left.copy(), right.getMask()); \ \ result IOP right; \ \ return result; \ } #define MARRM_OP_MM(OP,IOP,STROP) \ template \ MaskedArray operator OP (const MaskedArray &left, \ const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::operator" STROP "(const MaskedArray &," \ " const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result ( left.getArray().copy(), \ (left.getMask() && right.getMask()) ); \ \ result IOP right; \ \ return result; \ } #define MARRM_OP_MS(OP,IOP) \ template \ MaskedArray operator OP (const MaskedArray &left, const T &right) \ { \ MaskedArray result (left.copy()); \ \ result IOP right; \ \ return result; \ } #define MARRM_OP_SM(OP,IOP) \ template \ MaskedArray operator OP (const T &left, const MaskedArray &right) \ { \ Array resultarray (right.shape()); \ resultarray = left; \ \ MaskedArray result (resultarray, right.getMask()); \ \ result IOP right; \ \ return result; \ } MARRM_OP_MA ( +, += , "+" ) MARRM_OP_MA ( -, -= , "-" ) MARRM_OP_MA ( *, *= , "*" ) MARRM_OP_MA ( /, /= , "/" ) MARRM_OP_AM ( +, += , "+" ) MARRM_OP_AM ( -, -= , "-" ) MARRM_OP_AM ( *, *= , "*" ) MARRM_OP_AM ( /, /= , "/" ) MARRM_OP_MM ( +, += , "+" ) MARRM_OP_MM ( -, -= , "-" ) MARRM_OP_MM ( *, *= , "*" ) MARRM_OP_MM ( /, /= , "/" ) MARRM_OP_MS ( +, += ) MARRM_OP_MS ( -, -= ) MARRM_OP_MS ( *, *= ) MARRM_OP_MS ( /, /= ) MARRM_OP_SM ( +, += ) MARRM_OP_SM ( -, -= ) MARRM_OP_SM ( *, *= ) MARRM_OP_SM ( /, /= ) template void indgen(MaskedArray &left, T start, T inc) { bool leftarrDelete; T *leftarrStorage = left.getRWArrayStorage(leftarrDelete); T *leftarrS = leftarrStorage; bool leftmaskDelete; const LogicalArrayElem *leftmaskStorage = left.getMaskStorage(leftmaskDelete); const LogicalArrayElem *leftmaskS = leftmaskStorage; size_t ntotal = left.nelements(); T ind = start; while (ntotal--) { if (*leftmaskS) { *leftarrS = ind; ind += inc; } leftarrS++; leftmaskS++; } left.putArrayStorage(leftarrStorage, leftarrDelete); left.freeMaskStorage(leftmaskStorage, leftmaskDelete); } template void indgen(MaskedArray &a) { indgen(a, T(0), T(1)); } template void indgen(MaskedArray &a, T start) { indgen(a, start, T(1)); } template MaskedArray pow (const MaskedArray &left, const Array &right) { // if (conform2(left, right) == false) { if (left.shape() != right.shape()) { throw (ArrayConformanceError ("::" "pow" "(const MaskedArray &, const Array &)" " - arrays do not conform")); } MaskedArray result (left.copy()); bool resultarrDelete; T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); T *resultarrS = resultarrStorage; bool resultmaskDelete; const LogicalArrayElem *resultmaskStorage = result.getMaskStorage(resultmaskDelete); const LogicalArrayElem *resultmaskS = resultmaskStorage; bool rightDelete; const U *rightStorage = right.getStorage(rightDelete); const U *rightS = rightStorage; size_t ntotal = result.nelements(); while (ntotal--) { if (*resultmaskS) { *resultarrS = std::pow (*resultarrS, *rightS); } resultarrS++; resultmaskS++; rightS++; } result.putArrayStorage(resultarrStorage, resultarrDelete); result.freeMaskStorage(resultmaskStorage, resultmaskDelete); right.freeStorage(rightStorage, rightDelete); return result; } template MaskedArray pow (const Array &left, const MaskedArray &right) { // if (conform2(left, right) == false) { if (left.shape() != right.shape()) { throw (ArrayConformanceError ("::" "pow" "(const Array &, const MaskedArray &)" " - arrays do not conform")); } MaskedArray result (left.copy(), right.getMask()); bool resultarrDelete; T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); T *resultarrS = resultarrStorage; bool resultmaskDelete; const LogicalArrayElem *resultmaskStorage = result.getMaskStorage(resultmaskDelete); const LogicalArrayElem *resultmaskS = resultmaskStorage; bool rightarrDelete; const U *rightarrStorage = right.getArrayStorage(rightarrDelete); const U *rightarrS = rightarrStorage; size_t ntotal = result.nelements(); while (ntotal--) { if (*resultmaskS) { *resultarrS = std::pow (*resultarrS, *rightarrS); } resultarrS++; resultmaskS++; rightarrS++; } result.putArrayStorage(resultarrStorage, resultarrDelete); result.freeMaskStorage(resultmaskStorage, resultmaskDelete); right.freeArrayStorage(rightarrStorage, rightarrDelete); return result; } template MaskedArray pow (const MaskedArray &left, const MaskedArray &right) { // if (conform2(left, right) == false) { if (left.shape() != right.shape()) { throw (ArrayConformanceError ("::" "pow" "(const MaskedArray &, const MaskedArray &)" " - arrays do not conform")); } MaskedArray result ( left.getArray().copy(), (left.getMask() && right.getMask()) ); bool resultarrDelete; T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); T *resultarrS = resultarrStorage; bool resultmaskDelete; const LogicalArrayElem *resultmaskStorage = result.getMaskStorage(resultmaskDelete); const LogicalArrayElem *resultmaskS = resultmaskStorage; bool rightarrDelete; const U *rightarrStorage = right.getArrayStorage(rightarrDelete); const U *rightarrS = rightarrStorage; size_t ntotal = result.nelements(); while (ntotal--) { if (*resultmaskS) { *resultarrS = std::pow (*resultarrS, *rightarrS); } resultarrS++; resultmaskS++; rightarrS++; } result.putArrayStorage(resultarrStorage, resultarrDelete); result.freeMaskStorage(resultmaskStorage, resultmaskDelete); right.freeArrayStorage(rightarrStorage, rightarrDelete); return result; } template MaskedArray pow (const MaskedArray &left, const double &right) { MaskedArray result (left.copy()); bool resultarrDelete; T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); T *resultarrS = resultarrStorage; bool resultmaskDelete; const LogicalArrayElem *resultmaskStorage = result.getMaskStorage(resultmaskDelete); const LogicalArrayElem *resultmaskS = resultmaskStorage; size_t ntotal = result.nelements(); while (ntotal--) { if (*resultmaskS) { *resultarrS = std::pow (*resultarrS, right); } resultarrS++; resultmaskS++; } result.putArrayStorage(resultarrStorage, resultarrDelete); result.freeMaskStorage(resultmaskStorage, resultmaskDelete); return result; } #define MARRM_FUNC_M(DEFNAME, FUNC) \ template \ MaskedArray DEFNAME (const MaskedArray &left) \ { \ MaskedArray result (left.copy()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage \ = result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ *resultarrS = FUNC (*resultarrS); \ } \ resultarrS++; \ resultmaskS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ \ return result; \ } #define MARRM_FUNC_MA(DEFNAME,FUNC,STRFUNC) \ template \ MaskedArray DEFNAME (const MaskedArray &left, const Array &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::" STRFUNC \ "(const MaskedArray &, const Array &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result (left.copy()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage = \ result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightDelete; \ const T *rightStorage = right.getStorage(rightDelete); \ const T *rightS = rightStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ *resultarrS = T(FUNC (*resultarrS, *rightS)); \ } \ resultarrS++; \ resultmaskS++; \ rightS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeStorage(rightStorage, rightDelete); \ \ return result; \ } #define MARRM_FUNC_AM(DEFNAME, FUNC,STRFUNC) \ template \ MaskedArray DEFNAME (const Array &left, const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::" STRFUNC \ "(const Array &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result (left.copy(), right.getMask()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage = \ result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ *resultarrS = T(FUNC (*resultarrS, *rightarrS)); \ } \ resultarrS++; \ resultmaskS++; \ rightarrS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ \ return result; \ } #define MARRM_FUNC_MM(DEFNAME, FUNC,STRFUNC) \ template \ MaskedArray DEFNAME (const MaskedArray &left, \ const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::" STRFUNC\ "(const MaskedArray &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result ( left.getArray().copy(), \ (left.getMask() && right.getMask()) ); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage \ = result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ *resultarrS = T(FUNC (*resultarrS, *rightarrS)); \ } \ resultarrS++; \ resultmaskS++; \ rightarrS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ \ return result; \ } #define MARRM_FUNC_MS(DEFNAME, FUNC) \ template \ MaskedArray DEFNAME (const MaskedArray &left, const T &right) \ { \ MaskedArray result (left.copy()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage \ = result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ *resultarrS = FUNC (*resultarrS, right); \ } \ resultarrS++; \ resultmaskS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ \ return result; \ } #define MARRM_FUNC_SM(DEFNAME, FUNC) \ template \ MaskedArray DEFNAME (const T &left, const MaskedArray &right) \ { \ Array resultarray (right.shape()); \ resultarray = left; \ \ MaskedArray result (resultarray, right.getMask()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage \ = result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ *resultarrS = FUNC (*resultarrS, *rightarrS); \ } \ resultarrS++; \ resultmaskS++; \ rightarrS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ \ return result; \ } MARRM_FUNC_M ( sin, std::sin ) MARRM_FUNC_M ( cos, std::cos ) MARRM_FUNC_M ( tan, std::tan ) MARRM_FUNC_M ( asin, std::sin ) MARRM_FUNC_M ( acos, std::acos ) MARRM_FUNC_M ( atan, std::atan ) MARRM_FUNC_M ( sinh, std::sinh ) MARRM_FUNC_M ( cosh, std::cosh ) MARRM_FUNC_M ( tanh, std::tanh ) MARRM_FUNC_M ( exp, std::exp ) MARRM_FUNC_M ( log, std::log ) MARRM_FUNC_M ( log10, std::log10 ) MARRM_FUNC_M ( sqrt, std::sqrt ) MARRM_FUNC_M ( abs, std::abs ) MARRM_FUNC_M ( fabs, std::abs ) MARRM_FUNC_M ( ceil, std::ceil ) MARRM_FUNC_M ( floor, std::floor ) MARRM_FUNC_MA ( atan2, std::atan2, "atan2" ) MARRM_FUNC_MA ( fmod, std::fmod, "fmod" ) MARRM_FUNC_AM ( atan2, std::atan2, "atan2" ) MARRM_FUNC_AM ( fmod, std::fmod, "fmod" ) MARRM_FUNC_MM ( atan2, std::atan2, "atan2" ) MARRM_FUNC_MM ( fmod, std::fmod, "fmod" ) MARRM_FUNC_MS ( atan2, std::atan2 ) MARRM_FUNC_MS ( fmod, std::fmod ) MARRM_FUNC_SM ( atan2, std::atan2 ) MARRM_FUNC_SM ( fmod, std::fmod ) template void minMax(T &minVal, T &maxVal, IPosition &minPos, IPosition &maxPos, const MaskedArray &marray) { if ((minPos.nelements() != marray.ndim()) || (maxPos.nelements() != marray.ndim())) { throw (ArrayError( "void ::minMax(" "T &minVal, T &maxVal, IPosition &minPos, IPosition &maxPos," " const MaskedArray &marray)" " - minPos, maxPos dimensionality inconsistent with marray")); } bool marrayarrDelete; const T *marrayarrStorage = marray.getArrayStorage(marrayarrDelete); const T *marrayarrS = marrayarrStorage; bool marraymaskDelete; const LogicalArrayElem *marraymaskStorage = marray.getMaskStorage(marraymaskDelete); const LogicalArrayElem *marraymaskS = marraymaskStorage; size_t ntotal = marray.nelements(); bool foundOne = false; T minLocal = T(); T maxLocal = T(); size_t minNtotal=0; size_t maxNtotal=0; while (ntotal--) { if (*marraymaskS) { minLocal = *marrayarrS; maxLocal = minLocal; minNtotal = ntotal + 1; maxNtotal = minNtotal; marrayarrS++; marraymaskS++; foundOne = true; break; } else { marrayarrS++; marraymaskS++; } } if (!foundOne) { marray.freeArrayStorage(marrayarrStorage, marrayarrDelete); marray.freeMaskStorage(marraymaskStorage, marraymaskDelete); throw (ArrayError( "void ::minMax(" "T &minVal, T &maxVal, IPosition &minPos, IPosition &maxPos," " const MaskedArray &marray)" " - Need at least 1 unmasked element")); } while (ntotal--) { if (*marraymaskS) { if (*marrayarrS < minLocal) { \ minLocal = *marrayarrS; minNtotal = ntotal + 1; } if (*marrayarrS > maxLocal) { \ maxLocal = *marrayarrS; maxNtotal = ntotal + 1; } } marrayarrS++; marraymaskS++; } marray.freeArrayStorage(marrayarrStorage, marrayarrDelete); marray.freeMaskStorage(marraymaskStorage, marraymaskDelete); minVal = minLocal; maxVal = maxLocal; minPos = toIPositionInArray (marray.nelements() - minNtotal, marray.shape()); maxPos = toIPositionInArray (marray.nelements() - maxNtotal, marray.shape()); return; } template void minMax(T &minVal, T &maxVal, const MaskedArray &marray) { IPosition minPos (marray.ndim(), 0); IPosition maxPos (minPos); minMax (minVal, maxVal, minPos, maxPos, marray); return; } #define MARRM_MINORMAX_M(FUNC,OP,STRFUNC) \ template T FUNC (const MaskedArray &left) \ { \ bool leftarrDelete; \ const T *leftarrStorage = left.getArrayStorage(leftarrDelete); \ const T *leftarrS = leftarrStorage; \ \ bool leftmaskDelete; \ const LogicalArrayElem *leftmaskStorage \ = left.getMaskStorage(leftmaskDelete); \ const LogicalArrayElem *leftmaskS = leftmaskStorage; \ \ T result = *leftarrS; \ size_t ntotal = left.nelements(); \ bool foundOne = false; \ \ while (ntotal--) { \ if (*leftmaskS) { \ result = *leftarrS; \ leftarrS++; \ leftmaskS++; \ foundOne = true; \ break; \ } else { \ leftarrS++; \ leftmaskS++; \ } \ } \ \ if (!foundOne) { \ left.freeArrayStorage(leftarrStorage, leftarrDelete); \ left.freeMaskStorage(leftmaskStorage, leftmaskDelete); \ \ throw (ArrayError("T ::" STRFUNC "(const MaskedArray &left) - " \ "Need at least 1 unmasked element")); \ } \ \ while (ntotal--) { \ if (*leftmaskS) { \ if (*leftarrS OP result) { \ result = *leftarrS; \ } \ } \ leftarrS++; \ leftmaskS++; \ } \ \ left.freeArrayStorage(leftarrStorage, leftarrDelete); \ left.freeMaskStorage(leftmaskStorage, leftmaskDelete); \ \ return result; \ } #define MARRM_MINORMAX_MA(FUNC,OP,STRFUNC) \ template \ MaskedArray FUNC (const MaskedArray &left, const Array &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::" STRFUNC \ "(const MaskedArray &, const Array &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result (left.copy()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage = \ result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightDelete; \ const T *rightStorage = right.getStorage(rightDelete); \ const T *rightS = rightStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ if (*rightS OP *resultarrS) { \ *resultarrS = *rightS; \ } \ } \ resultarrS++; \ resultmaskS++; \ rightS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeStorage(rightStorage, rightDelete); \ \ return result; \ } #define MARRM_MINORMAX_AM(FUNC,OP,STRFUNC) \ template \ MaskedArray FUNC (const Array &left, const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("::" STRFUNC \ "(const Array &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result (left.copy(), right.getMask()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage = \ result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ if (*rightarrS OP *resultarrS) { \ *resultarrS = *rightarrS; \ } \ } \ resultarrS++; \ resultmaskS++; \ rightarrS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ \ return result; \ } #define MARRM_MINORMAX_MM(FUNC,OP,STRFUNC) \ template \ MaskedArray FUNC (const MaskedArray &left, \ const MaskedArray &right) \ { \ if (left.conform(right) == false) { \ throw (ArrayConformanceError \ ("MaskedArray ::" STRFUNC\ "(const MaskedArray &, const MaskedArray &)" \ " - arrays do not conform")); \ } \ \ MaskedArray result ( left.getArray().copy(), \ (left.getMask() && right.getMask()) ); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage \ = result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ if (*rightarrS OP *resultarrS) { \ *resultarrS = *rightarrS; \ } \ } \ resultarrS++; \ resultmaskS++; \ rightarrS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ \ return result; \ } #define MARRM_MINORMAX_MS(FUNC,OP) \ template \ MaskedArray FUNC (const MaskedArray &left, const T &right) \ { \ MaskedArray result (left.copy()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage \ = result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ if (right OP *resultarrS) { \ *resultarrS = right; \ } \ } \ resultarrS++; \ resultmaskS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ \ return result; \ } #define MARRM_MINORMAX_SM(FUNC,OP) \ template \ MaskedArray FUNC (const T &left, const MaskedArray &right) \ { \ Array resultarray (right.shape()); \ resultarray = left; \ \ MaskedArray result (resultarray, right.getMask()); \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage \ = result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getArrayStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ if (*rightarrS OP *resultarrS) { \ *resultarrS = *rightarrS; \ } \ } \ resultarrS++; \ resultmaskS++; \ rightarrS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ right.freeArrayStorage(rightarrStorage, rightarrDelete); \ \ return result; \ } #define MARRM_MINORMAX_AAM(FUNC,OP,STRFUNC) \ template \ void FUNC (const MaskedArray &result, \ const Array &left, const Array &right) \ { \ if ( ! (result.conform(left) && result.conform(right)) ) { \ throw (ArrayConformanceError \ ("void ::" STRFUNC \ "(const MaskedArray &, const Array &, const Array &)" \ " - arrays do not conform")); \ } \ \ bool resultarrDelete; \ T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); \ T *resultarrS = resultarrStorage; \ \ bool resultmaskDelete; \ const LogicalArrayElem *resultmaskStorage = \ result.getMaskStorage(resultmaskDelete); \ const LogicalArrayElem *resultmaskS = resultmaskStorage; \ \ bool leftarrDelete; \ const T *leftarrStorage = left.getStorage(leftarrDelete); \ const T *leftarrS = leftarrStorage; \ \ bool rightarrDelete; \ const T *rightarrStorage = right.getStorage(rightarrDelete); \ const T *rightarrS = rightarrStorage; \ \ size_t ntotal = result.nelements(); \ while (ntotal--) { \ if (*resultmaskS) { \ *resultarrS = (*leftarrS OP *rightarrS) ? *leftarrS : *rightarrS; \ } \ resultarrS++; \ resultmaskS++; \ leftarrS++; \ rightarrS++; \ } \ \ result.putArrayStorage(resultarrStorage, resultarrDelete); \ result.freeMaskStorage(resultmaskStorage, resultmaskDelete); \ left.freeStorage(leftarrStorage, leftarrDelete); \ right.freeStorage(rightarrStorage, rightarrDelete); \ \ return; \ } MARRM_MINORMAX_M ( min, <, "min" ) MARRM_MINORMAX_M ( max, >, "max" ) MARRM_MINORMAX_MA ( min, < , "min" ) MARRM_MINORMAX_MA ( max, > , "max" ) MARRM_MINORMAX_AM ( min, < , "min" ) MARRM_MINORMAX_AM ( max, > , "max" ) MARRM_MINORMAX_MM ( min, < , "min" ) MARRM_MINORMAX_MM ( max, > , "max" ) MARRM_MINORMAX_MS ( min, < ) MARRM_MINORMAX_MS ( max, > ) MARRM_MINORMAX_SM ( min, < ) MARRM_MINORMAX_SM ( max, > ) MARRM_MINORMAX_AAM ( min, < , "min" ) MARRM_MINORMAX_AAM ( max, > , "max" ) template T sum(const MaskedArray &left) { if (left.nelementsValid() < 1) { throw (ArrayError("T ::sum(const MaskedArray &left) - " "Need at least 1 unmasked element")); } bool leftarrDelete; const T *leftarrStorage = left.getArrayStorage(leftarrDelete); const T *leftarrS = leftarrStorage; bool leftmaskDelete; const LogicalArrayElem *leftmaskStorage = left.getMaskStorage(leftmaskDelete); const LogicalArrayElem *leftmaskS = leftmaskStorage; T sum = 0; size_t ntotal = left.nelements(); while (ntotal--) { if (*leftmaskS) { sum += *leftarrS; } leftarrS++; leftmaskS++; } left.freeArrayStorage(leftarrStorage, leftarrDelete); left.freeMaskStorage(leftmaskStorage, leftmaskDelete); return sum; } template T sumsquares(const MaskedArray &left) { if (left.nelementsValid() < 1) { throw (ArrayError("T ::sumsquares(const MaskedArray &left) - " "Need at least 1 unmasked element")); } bool leftarrDelete; const T *leftarrStorage = left.getArrayStorage(leftarrDelete); const T *leftarrS = leftarrStorage; bool leftmaskDelete; const LogicalArrayElem *leftmaskStorage = left.getMaskStorage(leftmaskDelete); const LogicalArrayElem *leftmaskS = leftmaskStorage; T sumsquares = 0; size_t ntotal = left.nelements(); while (ntotal--) { if (*leftmaskS) { sumsquares += (*leftarrS * *leftarrS); } leftarrS++; leftmaskS++; } left.freeArrayStorage(leftarrStorage, leftarrDelete); left.freeMaskStorage(leftmaskStorage, leftmaskDelete); return sumsquares; } template T product(const MaskedArray &left) { if (left.nelementsValid() < 1) { throw (ArrayError("T ::product(const MaskedArray &left) - " "Need at least 1 unmasked element")); } bool leftarrDelete; const T *leftarrStorage = left.getArrayStorage(leftarrDelete); const T *leftarrS = leftarrStorage; bool leftmaskDelete; const LogicalArrayElem *leftmaskStorage = left.getMaskStorage(leftmaskDelete); const LogicalArrayElem *leftmaskS = leftmaskStorage; T product = 1; size_t ntotal = left.nelements(); while (ntotal--) { if (*leftmaskS) { product *= *leftarrS; } leftarrS++; leftmaskS++; } left.freeArrayStorage(leftarrStorage, leftarrDelete); left.freeMaskStorage(leftmaskStorage, leftmaskDelete); return product; } template T mean(const MaskedArray &left) { if (left.nelementsValid() < 1) { throw (ArrayError("T ::mean(const MaskedArray &left) - " "Need at least 1 unmasked element")); } return sum(left)/T(left.nelementsValid()); } // // ArrayError // // Similar to numpy the ddof argument can be used to get the population // variance (ddof=0) or the sample variance (ddof=1). template T pvariance(const MaskedArray &a, T mean, size_t ddof) { size_t nr = a.nelementsValid(); if (nr < ddof+1) { throw(ArrayError("::variance(const MaskedArray &) - Need at least " + std::to_string(ddof+1) + " unmasked elements")); } MaskedArray deviations (abs(a - mean)); // abs is needed for Complex deviations *= deviations; return sum(deviations) / T(nr - ddof); } template T variance(const MaskedArray &a, T mean) { return pvariance (a, mean, 1); } template T pvariance(const MaskedArray &a, size_t ddof) { return pvariance(a, mean(a), ddof); } template T variance(const MaskedArray &a) { return pvariance(a, mean(a), 1); } // // ArrayError // template T pstddev(const MaskedArray &a, T mean, size_t ddof) { if (a.nelements() < ddof+1) { throw(ArrayError("::stddev(const Array &) - Need at least " + std::to_string(ddof+1) + " unmasked elements")); } return std::sqrt(pvariance(a, mean, ddof)); } template T stddev(const MaskedArray &a, T mean) { return pstddev (a, mean, 1); } template T pstddev(const MaskedArray &a, size_t ddof) { return pstddev (a, mean(a), ddof); } template T stddev(const MaskedArray &a) { return pstddev (a, mean(a), 1); } template T avdev(const MaskedArray &left) { return avdev(left, mean(left)); } template T avdev(const MaskedArray &left, T mean) { if (left.nelementsValid() < 1) { throw (ArrayError("T ::avdev(const MaskedArray &, T) - " "Need at least 1 unmasked element")); } MaskedArray avdeviations (abs(left - mean)); return sum(avdeviations)/T(left.nelementsValid()); } template T rms(const MaskedArray &left) { if (left.nelementsValid() < 1) { throw (ArrayError("T ::rms(const MaskedArray &left) - " "Need at least 1 unmasked element")); } return T(std::sqrt(sumsquares(left)/(1.0*left.nelementsValid()))); } template T median(const MaskedArray &left, bool sorted, bool takeEvenMean) { size_t nelem = left.nelementsValid(); if (nelem < 1) { throw (ArrayError("T ::median(const MaskedArray &) - " "Need at least 1 unmasked element")); } //# Mean does not have to be taken for odd number of elements. if (nelem%2 != 0) { takeEvenMean = false; } T medval; bool leftarrDelete; const T *leftarrStorage = left.getArrayStorage(leftarrDelete); const T *leftarrS = leftarrStorage; bool leftmaskDelete; const LogicalArrayElem *leftmaskStorage = left.getMaskStorage(leftmaskDelete); const LogicalArrayElem *leftmaskS = leftmaskStorage; size_t n2 = (nelem - 1)/2; if (! sorted) { // Make a copy of the masked elements. std::unique_ptr copy(new T[nelem]); T *copyS = copy.get(); size_t ntotal = nelem; while (ntotal) { if (*leftmaskS) { *copyS = *leftarrS; copyS++; ntotal--; } leftarrS++; leftmaskS++; } std::nth_element(©[0], ©[n2], ©[nelem]); if (takeEvenMean) { T a = copy[n2]; std::nth_element(©[0], ©[n2+1], ©[nelem]); medval = T(0.5 * (a + copy[n2+1])); } else { medval = copy[n2]; } copy.reset(); } else { // Sorted. // When mean has to be taken, we need one more element. if (takeEvenMean) { n2++; } const T* prev = 0; for (;;) { if (*leftmaskS) { if (n2 == 0) break; prev = leftarrS; n2--; } leftarrS++; leftmaskS++; } if (takeEvenMean) { medval = T(0.5 * (*prev + *leftarrS)); } else { medval = *leftarrS; } } left.freeArrayStorage(leftarrStorage, leftarrDelete); left.freeMaskStorage(leftmaskStorage, leftmaskDelete); return medval; } template T madfm(const MaskedArray &a, bool sorted, bool takeEvenMean) { T med = median(a, sorted, takeEvenMean); MaskedArray absdiff = abs(a - med); return median(absdiff, false, takeEvenMean); } template MaskedArray square(const MaskedArray &left) { MaskedArray result (left.copy()); bool resultarrDelete; T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); T *resultarrS = resultarrStorage; bool resultmaskDelete; const LogicalArrayElem *resultmaskStorage = result.getMaskStorage(resultmaskDelete); const LogicalArrayElem *resultmaskS = resultmaskStorage; size_t ntotal = result.nelements(); while (ntotal--) { if (*resultmaskS) { *resultarrS *= *resultarrS; } resultarrS++; resultmaskS++; } result.putArrayStorage(resultarrStorage, resultarrDelete); result.freeMaskStorage(resultmaskStorage, resultmaskDelete); return result; } template MaskedArray cube(const MaskedArray &left) { MaskedArray result (left.copy()); bool resultarrDelete; T *resultarrStorage = result.getRWArrayStorage(resultarrDelete); T *resultarrS = resultarrStorage; bool resultmaskDelete; const LogicalArrayElem *resultmaskStorage = result.getMaskStorage(resultmaskDelete); const LogicalArrayElem *resultmaskS = resultmaskStorage; size_t ntotal = result.nelements(); while (ntotal--) { if (*resultmaskS) { *resultarrS *= (*resultarrS * *resultarrS); } resultarrS++; resultmaskS++; } result.putArrayStorage(resultarrStorage, resultarrDelete); result.freeMaskStorage(resultmaskStorage, resultmaskDelete); return result; } template MaskedArray boxedArrayMath (const MaskedArray& array, const IPosition& boxSize, const FuncType& funcObj) { size_t ndim = array.ndim(); const IPosition& shape = array.shape(); // Set missing axes to 1. IPosition boxsz (boxSize); if (boxsz.size() != ndim) { size_t sz = boxsz.size(); boxsz.resize (ndim); for (size_t i=sz; i shape[i]) { boxsz[i] = shape[i]; } resShape[i] = (shape[i] + boxsz[i] - 1) / boxsz[i]; } // Need to make shallow copy because operator() is non-const. MaskedArray arr (array); Array result (resShape); Array resultMask(resShape); T* res = result.data(); bool* resMask = resultMask.data(); // Loop through all data and assemble as needed. IPosition blc(ndim, 0); IPosition trc(boxsz-1); while (true) { MaskedArray subarr (arr(blc,trc)); if (subarr.nelementsValid() == 0) { *resMask++ = false; *res++ = T(); } else { *resMask++ = true; *res++ = funcObj (arr(blc,trc)); } size_t ax; for (ax=0; ax= shape[ax]) { trc[ax] = shape[ax]-1; } break; } blc[ax] = 0; trc[ax] = boxsz[ax]-1; } if (ax == ndim) { break; } } return MaskedArray (result, resultMask); } template Array slidingArrayMath (const MaskedArray& array, const IPosition& halfBoxSize, const FuncType& funcObj, bool fillEdge) { size_t ndim = array.ndim(); const IPosition& shape = array.shape(); // Set full box size (-1) and resize/fill as needed. IPosition hboxsz (2*halfBoxSize); if (hboxsz.size() != array.ndim()) { size_t sz = hboxsz.size(); hboxsz.resize (array.ndim()); for (size_t i=sz; i(); } Array res(shape); res = T(); return res; } } // Need to make shallow copy because operator() is non-const. MaskedArray arr (array); Array result (resShape); assert (result.contiguousStorage() ); T* res = result.data(); // Loop through all data and assemble as needed. IPosition blc(ndim, 0); IPosition trc(hboxsz); IPosition pos(ndim, 0); while (true) { *res++ = funcObj (arr(blc,trc)); size_t ax; for (ax=0; ax fullResult(shape); fullResult = T(); hboxsz /= 2; fullResult(hboxsz, resShape+hboxsz-1).assign_conforming( result ); return fullResult; } } //# NAMESPACE CASACORE - END #endif