casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ArrayMath.h
Go to the documentation of this file.
00001 //# ArrayMath.h: ArrayMath: Simple mathematics done on an entire array.
00002 //# Copyright (C) 1993,1994,1995,1996,1998,1999,2001,2003
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //# 
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //# 
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //# 
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //# 
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: ArrayMath.h 21293 2012-11-30 15:58:59Z gervandiepen $
00027 
00028 #ifndef CASA_ARRAYMATH_H
00029 #define CASA_ARRAYMATH_H
00030 
00031 #include <casa/aips.h>
00032 #include <casa/BasicMath/Math.h>
00033 #include <casa/BasicMath/Functors.h>
00034 #include <casa/Arrays/Array.h>
00035 //# Needed to get the proper Complex typedef's
00036 #include <casa/BasicSL/Complex.h>
00037 #include <casa/Utilities/Assert.h>
00038 #include <casa/Exceptions/Error.h>
00039 #include <numeric>
00040 #include <functional>
00041 
00042 namespace casa { //# NAMESPACE CASA - BEGIN
00043 
00044 template<class T> class Matrix;
00045 
00046 // <summary>
00047 //    Mathematical operations for Arrays.
00048 // </summary>
00049 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tArray">
00050 //
00051 // <prerequisite>
00052 //   <li> <linkto class=Array>Array</linkto>
00053 // </prerequisite>
00054 //
00055 // <etymology>
00056 // This file contains global functions which perform element by element
00057 // mathematical operations on arrays.
00058 // </etymology>
00059 //
00060 // <synopsis>
00061 // These functions perform element by element mathematical operations on
00062 // arrays.  The two arrays must conform.
00063 //
00064 // Furthermore it defines functions a la std::transform to transform one or
00065 // two arrays by means of a unary or binary operator. All math and logical
00066 // operations on arrays can be expressed by means of these transform functions.
00067 // <br>It also defines an in-place transform function because for non-trivial
00068 // iterators it works faster than a transform where the result is an iterator
00069 // on the same data object as the left operand.
00070 // <br>The transform functions distinguish between contiguous and non-contiguous
00071 // arrays because iterating through a contiguous array can be done in a faster
00072 // way.
00073 // <br> Similar to the standard transform function these functions do not check
00074 // if the shapes match. The user is responsible for that.
00075 // </synopsis>
00076 //
00077 // <example>
00078 // <srcblock>
00079 //   Vector<Int> a(10);
00080 //   Vector<Int> b(10);
00081 //   Vector<Int> c(10);
00082 //      . . .
00083 //   c = a + b;
00084 // </srcblock>
00085 // This example sets the elements of c to (a+b). It checks if a and b have the
00086 // same shape.
00087 // The result of this operation is an Array.
00088 // </example>
00089 //
00090 // <example>
00091 // <srcblock>
00092 //   c = arrayTransformResult (a, b, std::plus<Double>());
00093 // </srcblock>
00094 // This example does the same as the previous example, but expressed using
00095 // the transform function (which, in fact, is used by the + operator above).
00096 // However, it is not checked if the shapes match.
00097 // </example>
00098 
00099 // <example>
00100 // <srcblock>
00101 //   arrayContTransform (a, b, c, std::plus<Double>());
00102 // </srcblock>
00103 // This example does the same as the previous example, but is faster because
00104 // the result array already exists and does not need to be allocated.
00105 // Note that the caller must be sure that c is contiguous.
00106 // </example>
00107 
00108 // <example>
00109 // <srcblock>
00110 //   Vector<Double> a(10);
00111 //   Vector<Double> b(10);
00112 //   Vector<Double> c(10);
00113 //      . . .
00114 //   c = atan2 (a, b);
00115 // </srcblock>
00116 // This example sets the elements of c to atan2 (a,b).
00117 // The result of this operation is an Array.
00118 // </example>
00119 //
00120 // <example>
00121 // <srcblock>
00122 //   Vector<Int> a(10);
00123 //   Int result;
00124 //      . . .
00125 //   result = sum (a);
00126 // </srcblock>
00127 // This example sums a.
00128 // </example>
00129 //
00130 // <motivation>
00131 // One wants to be able to perform mathematical operations on arrays.
00132 // </motivation>
00133 //
00134 // <linkfrom anchor="Array mathematical operations" classes="Array Vector Matrix Cube">
00135 //    <here>Array mathematical operations</here> -- Mathematical operations for
00136 //    Arrays.
00137 // </linkfrom>
00138 //
00139 // <group name="Array mathematical operations">
00140 
00141 
00142   // The myxtransform functions are defined to avoid a bug in g++-4.3.
00143   // That compiler generates incorrect code when only -g is used for
00144   // a std::transform with a bind1st or bind2nd for a complex<float>.
00145   // So, for example, the multiplication of a Complex array and Complex scalar
00146   // would fail (see g++ bug 39678).
00147   // <group>
00148   // sequence = scalar OP sequence
00149   template<typename _InputIterator1, typename T,
00150            typename _OutputIterator, typename _BinaryOperation>
00151     void
00152     myltransform(_InputIterator1 __first1, _InputIterator1 __last1,
00153                  _OutputIterator __result, T left,
00154                  _BinaryOperation __binary_op)
00155     {
00156       for ( ; __first1 != __last1; ++__first1, ++__result)
00157         *__result = __binary_op(left, *__first1);
00158     }
00159   // sequence = sequence OP scalar
00160   template<typename _InputIterator1, typename T,
00161            typename _OutputIterator, typename _BinaryOperation>
00162     void
00163     myrtransform(_InputIterator1 __first1, _InputIterator1 __last1,
00164                  _OutputIterator __result, T right,
00165                  _BinaryOperation __binary_op)
00166     {
00167       for ( ; __first1 != __last1; ++__first1, ++__result)
00168         *__result = __binary_op(*__first1, right);
00169     }
00170   // sequence OP= scalar
00171   template<typename _InputIterator1, typename T,
00172            typename _BinaryOperation>
00173     void
00174     myiptransform(_InputIterator1 __first1, _InputIterator1 __last1,
00175                   T right,
00176                   _BinaryOperation __binary_op)
00177     {
00178       for ( ; __first1 != __last1; ++__first1)
00179         *__first1 = __binary_op(*__first1, right);
00180     }
00181   // </group>
00182 
00183 
00184 // Function to check the shapes. It throws an exception if not equal.
00185 // <group>
00186 void throwArrayShapes (const char* name);
00187 inline void checkArrayShapes (const ArrayBase& left, const ArrayBase& right,
00188                               const char* name)
00189 {
00190   if (! left.shape().isEqual (right.shape())) {
00191     throwArrayShapes (name);
00192   }
00193 }
00194 // </group>
00195 
00196 
00197 // Functions to apply a binary or unary operator to arrays.
00198 // They are modeled after std::transform.
00199 // They do not check if the shapes conform; as in std::transform the
00200 // user must take care that the operands conform.
00201 // <group>
00202 // Transform left and right to a result using the binary operator.
00203 // Result MUST be a contiguous array.
00204 template<typename L, typename R, typename RES, typename BinaryOperator>
00205 inline void arrayContTransform (const Array<L>& left, const Array<R>& right,
00206                                 Array<RES>& result, BinaryOperator op)
00207 {
00208   DebugAssert (result.contiguousStorage(), AipsError);
00209   if (left.contiguousStorage()  &&  right.contiguousStorage()) {
00210     std::transform (left.cbegin(), left.cend(), right.cbegin(),
00211                     result.cbegin(), op);
00212   } else {
00213     std::transform (left.begin(), left.end(), right.begin(),
00214                     result.cbegin(), op);
00215   }
00216 }
00217 
00218 // Transform left and right to a result using the binary operator.
00219 // Result MUST be a contiguous array.
00220 template<typename L, typename R, typename RES, typename BinaryOperator>
00221 inline void arrayContTransform (const Array<L>& left, R right,
00222                                 Array<RES>& result, BinaryOperator op)
00223 {
00224   DebugAssert (result.contiguousStorage(), AipsError);
00225   if (left.contiguousStorage()) {
00226     myrtransform (left.cbegin(), left.cend(),
00227                  result.cbegin(), right, op);
00230   } else {
00231     myrtransform (left.begin(), left.end(),
00232                  result.cbegin(), right, op);
00235   }
00236 }
00237 
00238 // Transform left and right to a result using the binary operator.
00239 // Result MUST be a contiguous array.
00240 template<typename L, typename R, typename RES, typename BinaryOperator>
00241 inline void arrayContTransform (L left, const Array<R>& right,
00242                                 Array<RES>& result, BinaryOperator op)
00243 {
00244   DebugAssert (result.contiguousStorage(), AipsError);
00245   if (right.contiguousStorage()) {
00246     myltransform (right.cbegin(), right.cend(),
00247                   result.cbegin(), left, op);
00250   } else {
00251     myltransform (right.begin(), right.end(),
00252                   result.cbegin(), left, op);
00255   }
00256 }
00257 
00258 // Transform array to a result using the unary operator.
00259 // Result MUST be a contiguous array.
00260 template<typename T, typename RES, typename UnaryOperator>
00261 inline void arrayContTransform (const Array<T>& arr,
00262                                 Array<RES>& result, UnaryOperator op)
00263 {
00264   DebugAssert (result.contiguousStorage(), AipsError);
00265   if (arr.contiguousStorage()) {
00266     std::transform (arr.cbegin(), arr.cend(), result.cbegin(), op);
00267   } else {
00268     std::transform (arr.begin(), arr.end(), result.cbegin(), op);
00269   }
00270 }
00271 
00272 // Transform left and right to a result using the binary operator.
00273 // Result need not be a contiguous array.
00274 template<typename L, typename R, typename RES, typename BinaryOperator>
00275 void arrayTransform (const Array<L>& left, const Array<R>& right,
00276                      Array<RES>& result, BinaryOperator op);
00277 
00278 // Transform left and right to a result using the binary operator.
00279 // Result need not be a contiguous array.
00280 template<typename L, typename R, typename RES, typename BinaryOperator>
00281 void arrayTransform (const Array<L>& left, R right,
00282                      Array<RES>& result, BinaryOperator op);
00283 
00284 // Transform left and right to a result using the binary operator.
00285 // Result need not be a contiguous array.
00286 template<typename L, typename R, typename RES, typename BinaryOperator>
00287 void arrayTransform (L left, const Array<R>& right,
00288                      Array<RES>& result, BinaryOperator op);
00289 
00290 // Transform array to a result using the unary operator.
00291 // Result need not be a contiguous array.
00292 template<typename T, typename RES, typename UnaryOperator>
00293 void arrayTransform (const Array<T>& arr,
00294                      Array<RES>& result, UnaryOperator op);
00295 
00296 // Transform left and right to a result using the binary operator.
00297 // The created and returned result array is contiguous.
00298 template<typename T, typename BinaryOperator>
00299 Array<T> arrayTransformResult (const Array<T>& left, const Array<T>& right,
00300                                BinaryOperator op);
00301 
00302 // Transform left and right to a result using the binary operator.
00303 // The created and returned result array is contiguous.
00304 template<typename T, typename BinaryOperator>
00305 Array<T> arrayTransformResult (const Array<T>& left, T right, BinaryOperator op);
00306 
00307 // Transform left and right to a result using the binary operator.
00308 // The created and returned result array is contiguous.
00309 template<typename T, typename BinaryOperator>
00310 Array<T> arrayTransformResult (T left, const Array<T>& right, BinaryOperator op);
00311 
00312 // Transform array to a result using the unary operator.
00313 // The created and returned result array is contiguous.
00314 template<typename T, typename UnaryOperator>
00315 Array<T> arrayTransformResult (const Array<T>& arr, UnaryOperator op);
00316 
00317 // Transform left and right in place using the binary operator.
00318 // The result is stored in the left array (useful for e.g. the += operation).
00319 template<typename L, typename R, typename BinaryOperator>
00320 inline void arrayTransformInPlace (Array<L>& left, const Array<R>& right,
00321                                    BinaryOperator op)
00322 {
00323   if (left.contiguousStorage()  &&  right.contiguousStorage()) {
00324     transformInPlace (left.cbegin(), left.cend(), right.cbegin(), op);
00325   } else {
00326     transformInPlace (left.begin(), left.end(), right.begin(), op);
00327   }
00328 }
00329 
00330 // Transform left and right in place using the binary operator.
00331 // The result is stored in the left array (useful for e.g. the += operation).
00332 template<typename L, typename R, typename BinaryOperator>
00333 inline void arrayTransformInPlace (Array<L>& left, R right, BinaryOperator op)
00334 {
00335   if (left.contiguousStorage()) {
00336     myiptransform (left.cbegin(), left.cend(), right, op);
00338   } else {
00339     myiptransform (left.begin(), left.end(), right, op);
00341   }
00342 }
00343 
00344 // Transform the array in place using the unary operator.
00345 // E.g. doing <src>arrayTransformInPlace(array, Sin<T>())</src> is faster than
00346 // <src>array=sin(array)</src> as it does not need to create a temporary array.
00347 template<typename T, typename UnaryOperator>
00348 inline void arrayTransformInPlace (Array<T>& arr, UnaryOperator op)
00349 {
00350   if (arr.contiguousStorage()) {
00351     transformInPlace (arr.cbegin(), arr.cend(), op);
00352   } else {
00353     transformInPlace (arr.begin(), arr.end(), op);
00354   }
00355 }
00356 // </group>
00357 
00358 // 
00359 // Element by element arithmetic modifying left in-place. left and other
00360 // must be conformant.
00361 // <group>
00362 template<class T> void operator+= (Array<T> &left, const Array<T> &other);
00363 template<class T> void operator-= (Array<T> &left, const Array<T> &other);
00364 template<class T> void operator*= (Array<T> &left, const Array<T> &other);
00365 template<class T> void operator/= (Array<T> &left, const Array<T> &other);
00366 template<class T> void operator%= (Array<T> &left, const Array<T> &other);
00367 template<class T> void operator&= (Array<T> &left, const Array<T> &other);
00368 template<class T> void operator|= (Array<T> &left, const Array<T> &other);
00369 template<class T> void operator^= (Array<T> &left, const Array<T> &other);
00370 // </group>
00371 
00372 // 
00373 // Element by element arithmetic modifying left in-place. The scalar "other"
00374 // behaves as if it were a conformant Array to left filled with constant values.
00375 // <group>
00376 template<class T> void operator+= (Array<T> &left, const T &other);
00377 template<class T> void operator-= (Array<T> &left, const T &other);
00378 template<class T> void operator*= (Array<T> &left, const T &other);
00379 template<class T> void operator/= (Array<T> &left, const T &other);
00380 template<class T> void operator%= (Array<T> &left, const T &other);
00381 template<class T> void operator&= (Array<T> &left, const T &other);
00382 template<class T> void operator|= (Array<T> &left, const T &other);
00383 template<class T> void operator^= (Array<T> &left, const T &other);
00384 // </group>
00385 
00386 // Unary arithmetic operation.
00387 // 
00388 // <group>
00389 template<class T> Array<T> operator+(const Array<T> &a);
00390 template<class T> Array<T> operator-(const Array<T> &a);
00391 template<class T> Array<T> operator~(const Array<T> &a);
00392 // </group>
00393 
00394 // 
00395 // Element by element arithmetic on two arrays, returning an array.
00396 // <group>
00397 template<class T> 
00398   Array<T> operator+ (const Array<T> &left, const Array<T> &right);
00399 template<class T> 
00400   Array<T> operator- (const Array<T> &left, const Array<T> &right);
00401 template<class T> 
00402   Array<T> operator* (const Array<T> &left, const Array<T> &right);
00403 template<class T> 
00404   Array<T> operator/ (const Array<T> &left, const Array<T> &right);
00405 template<class T> 
00406   Array<T> operator% (const Array<T> &left, const Array<T> &right);
00407 template<class T> 
00408   Array<T> operator| (const Array<T> &left, const Array<T> &right);
00409 template<class T> 
00410   Array<T> operator& (const Array<T> &left, const Array<T> &right);
00411 template<class T> 
00412   Array<T> operator^ (const Array<T> &left, const Array<T> &right);
00413 // </group>
00414 
00415 // 
00416 // Element by element arithmetic between an array and a scalar, returning
00417 // an array.
00418 // <group>
00419 template<class T> 
00420     Array<T> operator+ (const Array<T> &left, const T &right);
00421 template<class T> 
00422     Array<T> operator- (const Array<T> &left, const T &right);
00423 template<class T> 
00424     Array<T> operator* (const Array<T> &left, const T &right);
00425 template<class T> 
00426     Array<T> operator/ (const Array<T> &left, const T &right);
00427 template<class T> 
00428     Array<T> operator% (const Array<T> &left, const T &right);
00429 template<class T> 
00430     Array<T> operator| (const Array<T> &left, const T &right);
00431 template<class T> 
00432     Array<T> operator& (const Array<T> &left, const T &right);
00433 template<class T> 
00434     Array<T> operator^ (const Array<T> &left, const T &right);
00435 // </group>
00436 
00437 // 
00438 // Element by element arithmetic between a scalar and an array, returning
00439 // an array.
00440 // <group>
00441 template<class T>  
00442     Array<T> operator+ (const T &left, const Array<T> &right);
00443 template<class T>  
00444     Array<T> operator- (const T &left, const Array<T> &right);
00445 template<class T>  
00446     Array<T> operator* (const T &left, const Array<T> &right);
00447 template<class T>  
00448     Array<T> operator/ (const T &left, const Array<T> &right);
00449 template<class T>  
00450     Array<T> operator% (const T &left, const Array<T> &right);
00451 template<class T>  
00452     Array<T> operator| (const T &left, const Array<T> &right);
00453 template<class T>  
00454     Array<T> operator& (const T &left, const Array<T> &right);
00455 template<class T>  
00456     Array<T> operator^ (const T &left, const Array<T> &right);
00457 // </group>
00458 
00459 // 
00460 // Transcendental function that can be applied to essentially all numeric
00461 // types. Works on an element-by-element basis.
00462 // <group>
00463 template<class T> Array<T> cos(const Array<T> &a);
00464 template<class T> Array<T> cosh(const Array<T> &a);
00465 template<class T> Array<T> exp(const Array<T> &a);
00466 template<class T> Array<T> log(const Array<T> &a);
00467 template<class T> Array<T> log10(const Array<T> &a);
00468 template<class T> Array<T> pow(const Array<T> &a, const Array<T> &b);
00469 template<class T> Array<T> pow(const T &a, const Array<T> &b);
00470 template<class T> Array<T> sin(const Array<T> &a);
00471 template<class T> Array<T> sinh(const Array<T> &a);
00472 template<class T> Array<T> sqrt(const Array<T> &a);
00473 // </group>
00474 
00475 // 
00476 // Transcendental function applied to the array on an element-by-element
00477 // basis. Although a template function, this does not make sense for all
00478 // numeric types.
00479 // <group>
00480 template<class T> Array<T> acos(const Array<T> &a);
00481 template<class T> Array<T> asin(const Array<T> &a);
00482 template<class T> Array<T> atan(const Array<T> &a);
00483 template<class T> Array<T> atan2(const Array<T> &y, const Array<T> &x);
00484 template<class T> Array<T> atan2(const T &y, const Array<T> &x);
00485 template<class T> Array<T> atan2(const Array<T> &y, const T &x);
00486 template<class T> Array<T> ceil(const Array<T> &a);
00487 template<class T> Array<T> fabs(const Array<T> &a);
00488 template<class T> Array<T> abs(const Array<T> &a);
00489 template<class T> Array<T> floor(const Array<T> &a);
00490 template<class T> Array<T> round(const Array<T> &a);
00491 template<class T> Array<T> sign(const Array<T> &a);
00492 template<class T> Array<T> fmod(const Array<T> &a, const Array<T> &b);
00493 template<class T> Array<T> fmod(const T &a, const Array<T> &b);
00494 template<class T> Array<T> fmod(const Array<T> &a, const T &b);
00495 template<class T> Array<T> pow(const Array<T> &a, const Double &b);
00496 template<class T> Array<T> tan(const Array<T> &a);
00497 template<class T> Array<T> tanh(const Array<T> &a);
00498 // N.B. fabs is deprecated. Use abs.
00499 template<class T> Array<T> fabs(const Array<T> &a);
00500 // </group>
00501 
00502 // 
00503 // <group>
00504 // Find the minimum and maximum values of an array, including their locations.
00505 template<class ScalarType>
00506 void minMax(ScalarType &minVal, ScalarType &maxVal, IPosition &minPos, 
00507             IPosition &maxPos, const Array<ScalarType> &array);
00508 // The array is searched at locations where the mask equals <src>valid</src>.
00509 // (at least one such position must exist or an exception will be thrown).
00510 // MaskType should be an Array of Bool.
00511 template<class ScalarType>
00512 void minMax(ScalarType &minVal, ScalarType &maxVal, IPosition &minPos,
00513             IPosition &maxPos, const Array<ScalarType> &array, 
00514             const Array<Bool> &mask, Bool valid=True);
00515 // The array * weight is searched 
00516 template<class ScalarType>
00517 void minMaxMasked(ScalarType &minVal, ScalarType &maxVal, IPosition &minPos,
00518                   IPosition &maxPos, const Array<ScalarType> &array, 
00519                   const Array<ScalarType> &weight);
00520 // </group>
00521 
00522 // 
00523 // The "min" and "max" functions require that the type "T" have comparison 
00524 // operators.
00525 // <group>
00526 //
00527 // This sets min and max to the minimum and maximum of the array to 
00528 // avoid having to do two passes with max() and min() separately.
00529 template<class T> void minMax(T &min, T &max, const Array<T> &a);
00530 //
00531 // The minimum element of the array.
00532 // Requires that the type "T" has comparison operators.
00533 template<class T>  T min(const Array<T> &a);
00534 // The maximum element of the array.
00535 // Requires that the type "T" has comparison operators.
00536 template<class T>  T max(const Array<T> &a);
00537 
00538 // "result" contains the maximum of "a" and "b" at each position. "result",
00539 // "a", and "b" must be conformant.
00540 template<class T> void max(Array<T> &result, const Array<T> &a, 
00541                            const Array<T> &b);
00542 // "result" contains the minimum of "a" and "b" at each position. "result",
00543 // "a", and "b" must be conformant.
00544 template<class T> void min(Array<T> &result, const Array<T> &a, 
00545                            const Array<T> &b);
00546 // Return an array that contains the maximum of "a" and "b" at each position.
00547 // "a" and "b" must be conformant.
00548 template<class T> Array<T> max(const Array<T> &a, const Array<T> &b);
00549 template<class T> Array<T> max(const T &a, const Array<T> &b);
00550 // Return an array that contains the minimum of "a" and "b" at each position.
00551 // "a" and "b" must be conformant.
00552 template<class T> Array<T> min(const Array<T> &a, const Array<T> &b);
00553 
00554 // "result" contains the maximum of "a" and "b" at each position. "result",
00555 // and "a" must be conformant.
00556 template<class T> void max(Array<T> &result, const Array<T> &a, 
00557                            const T &b);
00558 template<class T> inline void max(Array<T> &result, const T &a, 
00559                                   const Array<T> &b)
00560   { max (result, b, a); }
00561 // "result" contains the minimum of "a" and "b" at each position. "result",
00562 // and "a" must be conformant.
00563 template<class T> void min(Array<T> &result, const Array<T> &a, 
00564                            const T &b);
00565 template<class T> inline void min(Array<T> &result, const T &a, 
00566                                   const Array<T> &b)
00567   { min (result, b, a); }
00568 // Return an array that contains the maximum of "a" and "b" at each position.
00569 template<class T> Array<T> max(const Array<T> &a, const T &b);
00570 template<class T> inline Array<T> max(const T &a, const Array<T> &b)
00571   { return max(b, a); }
00572 // Return an array that contains the minimum of "a" and "b" at each position.
00573 template<class T> Array<T> min(const Array<T> &a, const T &b);
00574 template<class T> inline Array<T> min(const T &a, const Array<T> &b)
00575   { return min(b, a); }
00576 // </group>
00577 
00578 // 
00579 // Fills all elements of "array" with a sequence starting with "start"
00580 // and incrementing by "inc" for each element. The first axis varies
00581 // most rapidly.
00582 template<class T> void indgen(Array<T> &a, T start, T inc);
00583 // 
00584 // Fills all elements of "array" with a sequence starting with 0
00585 // and ending with nelements() - 1. The first axis varies
00586 // most rapidly.
00587 template<class T>  void indgen(Array<T> &a);
00588 // 
00589 // Fills all elements of "array" with a sequence starting with start
00590 // incremented by one for each position in the array. The first axis varies
00591 // most rapidly.
00592 template<class T>  void indgen(Array<T> &a, T start);
00593 
00594 
00595 // Sum of every element of the array.
00596 template<class T> T sum(const Array<T> &a);
00597 // 
00598 // Product of every element of the array. This could of course easily
00599 // overflow.
00600 template<class T> T product(const Array<T> &a);
00601 
00602 // 
00603 // The mean of "a" is the sum of all elements of "a" divided by the number
00604 // of elements of "a".
00605 template<class T> T mean(const Array<T> &a);
00606 
00607 // 
00608 // The variance of "a" is the sum of (a(i) - mean(a))**2/(a.nelements() - 1).
00609 // N.B. N-1, not N in the denominator).
00610 template<class T> T variance(const Array<T> &a);
00611 // 
00612 // The variance of "a" is the sum of (a(i) - mean(a))**2/(a.nelements() - 1).
00613 // N.B. N-1, not N in the denominator).
00614 // Rather than using a computed mean, use the supplied value.
00615 template<class T> T variance(const Array<T> &a, T mean);
00616 
00617 // 
00618 // The standard deviation of "a" is the square root of its variance.
00619 template<class T> T stddev(const Array<T> &a);
00620 // 
00621 // The standard deviation of "a" is the square root of its variance.
00622 // Rather than using a computed mean, use the supplied value.
00623 template<class T> T stddev(const Array<T> &a, T mean);
00624 
00625 // 
00626 // The average deviation of "a" is the sum of abs(a(i) - mean(a))/N. (N.B.
00627 // N, not N-1 in the denominator).
00628 template<class T> T avdev(const Array<T> &a);
00629 // 
00630 // The average deviation of "a" is the sum of abs(a(i) - mean(a))/N. (N.B.
00631 // N, not N-1 in the denominator).
00632 // Rather than using a computed mean, use the supplied value.
00633 template<class T> T avdev(const Array<T> &a,T mean);
00634 
00635 //
00636 // The root-mean-square of "a" is the sqrt of sum(a*a)/N.
00637 template<class T> T rms(const Array<T> &a);
00638 
00639 
00640 // The median of "a" is a(n/2).
00641 // If a has an even number of elements and the switch takeEvenMean is set,
00642 // the median is 0.5*(a(n/2) + a((n+1)/2)).
00643 // According to Numerical Recipes (2nd edition) it makes little sense to take
00644 // the mean if the array is large enough (> 100 elements). Therefore
00645 // the default for takeEvenMean is False if the array has > 100 elements,
00646 // otherwise it is True.
00647 // <br>If "sorted"==True we assume the data is already sorted and we
00648 // compute the median directly. Otherwise the function GenSort::kthLargest
00649 // is used to find the median (kthLargest is about 6 times faster
00650 // than a full quicksort).
00651 // <br>Finding the median means that the array has to be (partially)
00652 // sorted. By default a copy will be made, but if "inPlace" is in effect,
00653 // the data themselves will be sorted. That should only be used if the
00654 // data are used not thereafter.
00655 // <note>The function kthLargest in class GenSortIndirect can be used to
00656 // obtain the index of the median in an array. </note>
00657 // <group>
00658 template<class T> inline T median(const Array<T> &a)
00659     { return median (a, False, (a.nelements() <= 100), False); }
00660 template<class T> inline T median(const Array<T> &a, Bool sorted)
00661     { return median (a, sorted, (a.nelements() <= 100), False); }
00662 template<class T> inline T medianInPlace(const Array<T> &a,
00663                                          Bool sorted = False)
00664     { return median (a, sorted, (a.nelements() <= 100), True); }
00665 template<class T> T median(const Array<T> &a, Bool sorted, Bool takeEvenMean,
00666                            Bool inPlace = False)
00667     { Block<T> tmp; return median (a, tmp, sorted, takeEvenMean, inPlace); }
00668 template<class T> T median(const Array<T> &a, Block<T> &tmp, Bool sorted,
00669                            Bool takeEvenMean, Bool inPlace = False);
00670 // </group>
00671 
00672 // Return the fractile of an array.
00673 // It returns the value at the given fraction of the array.
00674 // A fraction of 0.5 is the same as the median, be it that no mean of
00675 // the two middle elements is taken if the array has an even nr of elements.
00676 // It uses kthLargest if the array is not sorted yet.
00677 // <note>The function kthLargest in class GenSortIndirect can be used to
00678 // obtain the index of the fractile in an array. </note>
00679 template<class T> T fractile(const Array<T> &a, Float fraction,
00680                              Bool sorted = False, Bool inPlace = False)
00681   { Block<T> tmp; return fractile (a, tmp, fraction, sorted, inPlace); }
00682 template<class T> T fractile(const Array<T> &a, Block<T> &tmp, Float fraction,
00683                              Bool sorted = False, Bool inPlace = False);
00684 
00685 
00686 // Methods for element-by-element scaling of complex and real.
00687 // Note that Complex and DComplex are typedefs for std::complex.
00688 //<group>
00689 template<typename T>
00690 void operator*= (Array<std::complex<T> > &left, const Array<T> &other);
00691 template<typename T>
00692 void operator*= (Array<std::complex<T> > &left, const T &other);
00693 template<typename T>
00694 void operator/= (Array<std::complex<T> > &left, const Array<T> &other);
00695 template<typename T>
00696 void operator/= (Array<std::complex<T> > &left, const T &other);
00697 template<typename T>
00698 Array<std::complex<T> > operator* (const Array<std::complex<T> > &left,
00699                                    const Array<T> &right);
00700 template<typename T>
00701 Array<std::complex<T> > operator* (const Array<std::complex<T> > &left,
00702                                    const T &right);
00703 template<typename T>
00704 Array<std::complex<T> > operator* (const std::complex<T> &left,
00705                                    const Array<T> &right);
00706 template<typename T>
00707 Array<std::complex<T> > operator/ (const Array<std::complex<T> > &left,
00708                                    const Array<T> &right);
00709 template<typename T>
00710 Array<std::complex<T> > operator/ (const Array<std::complex<T> > &left,
00711                                    const T &right);
00712 template<typename T>
00713 Array<std::complex<T> > operator/ (const std::complex<T> &left,
00714                                    const Array<T> &right);
00715 // </group>
00716 
00717 // Returns the complex conjugate of a complex array.
00718 //<group>
00719 Array<Complex> conj(const Array<Complex> &carray);
00720 Array<DComplex> conj(const Array<DComplex> &carray);
00721 // Modifies rarray in place. rarray must be conformant.
00722 void         conj(Array<Complex> &rarray, const Array<Complex> &carray);
00723 void         conj(Array<DComplex> &rarray, const Array<DComplex> &carray);
00724 //# The following are implemented to make the compiler find the right conversion
00725 //# more often.
00726 Matrix<Complex> conj(const Matrix<Complex> &carray);
00727 Matrix<DComplex> conj(const Matrix<DComplex> &carray);
00728 //</group>
00729 
00730 // Form an array of complex numbers from the given real arrays.
00731 // Note that Complex and DComplex are simply typedefs for std::complex<float>
00732 // and std::complex<double>, so the result is in fact one of these types.
00733 template<typename T>
00734 Array<std::complex<T> > makeComplex(const Array<T> &real, const Array<T>& imag);
00735 
00736 // Set the real part of the left complex array to the right real array.
00737 template<typename L, typename R>
00738 void setReal(Array<L> &carray, const Array<R> &rarray);
00739 
00740 // Set the imaginary part of the left complex array to right real array.
00741 template<typename R, typename L>
00742 void setImag(Array<R> &carray, const Array<L> &rarray);
00743 
00744 // Extracts the real part of a complex array into an array of floats.
00745 // <group>
00746 Array<Float>  real(const Array<Complex> &carray);
00747 Array<Double> real(const Array<DComplex> &carray);
00748 // Modifies rarray in place. rarray must be conformant.
00749 void         real(Array<Float> &rarray, const Array<Complex> &carray);
00750 void         real(Array<Double> &rarray, const Array<DComplex> &carray);
00751 // </group>
00752 
00753 // 
00754 // Extracts the imaginary part of a complex array into an array of floats.
00755 // <group>
00756 Array<Float>  imag(const Array<Complex> &carray);
00757 Array<Double> imag(const Array<DComplex> &carray);
00758 // Modifies rarray in place. rarray must be conformant.
00759 void         imag(Array<Float> &rarray, const Array<Complex> &carray);
00760 void         imag(Array<Double> &rarray, const Array<DComplex> &carray);
00761 // </group>
00762 
00763 // 
00764 // Extracts the amplitude (i.e. sqrt(re*re + im*im)) from an array
00765 // of complex numbers. N.B. this is presently called "fabs" for a single
00766 // complex number.
00767 // <group>
00768 Array<Float>  amplitude(const Array<Complex> &carray);
00769 Array<Double> amplitude(const Array<DComplex> &carray);
00770 // Modifies rarray in place. rarray must be conformant.
00771 void         amplitude(Array<Float> &rarray, const Array<Complex> &carray);
00772 void         amplitude(Array<Double> &rarray, const Array<DComplex> &carray);
00773 // </group>
00774 
00775 // 
00776 // Extracts the phase (i.e. atan2(im, re)) from an array
00777 // of complex numbers. N.B. this is presently called "arg"
00778 // for a single complex number.
00779 // <group>
00780 Array<Float>  phase(const Array<Complex> &carray);
00781 Array<Double> phase(const Array<DComplex> &carray);
00782 // Modifies rarray in place. rarray must be conformant.
00783 void         phase(Array<Float> &rarray, const Array<Complex> &carray);
00784 void         phase(Array<Double> &rarray, const Array<DComplex> &carray);
00785 // </group>
00786 
00787 // Copy an array of complex into an array of real,imaginary pairs. The
00788 // first axis of the real array becomes twice as long as the complex array.
00789 // In the future versions which work by reference will be available; presently
00790 // a copy is made.
00791 Array<Float> ComplexToReal(const Array<Complex> &carray);
00792 Array<Double> ComplexToReal(const Array<DComplex> &carray);
00793 // Modify the array "rarray" in place. "rarray" must be the correct shape.
00794 // <group>
00795 void ComplexToReal(Array<Float> &rarray, const Array<Complex> &carray);
00796 void ComplexToReal(Array<Double> &rarray, const Array<DComplex> &carray);
00797 // </group>
00798 
00799 // Copy an array of real,imaginary pairs into a complex array. The first axis
00800 // must have an even length.
00801 // In the future versions which work by reference will be available; presently
00802 // a copy is made.
00803 Array<Complex>  RealToComplex(const Array<Float> &rarray);
00804 Array<DComplex> RealToComplex(const Array<Double> &rarray);
00805 // Modify the array "carray" in place. "carray" must be the correct shape.
00806 // <group>
00807 void  RealToComplex(Array<Complex> &carray, const Array<Float> &rarray);
00808 void  RealToComplex(Array<DComplex> &carray, const Array<Double> &rarray);
00809 // </group>
00810 
00811 // Make a copy of an array of a different type; for example make an array
00812 // of doubles from an array of floats. Arrays to and from must be conformant
00813 // (same shape). Also, it must be possible to convert a scalar of type U 
00814 // to type T.
00815 template<class T, class U> void convertArray(Array<T> &to,
00816                                              const Array<U> &from);
00817 
00818 
00819 // Returns an array where every element is squared.
00820 template<class T> Array<T> square(const Array<T> &val);
00821 
00822 // Returns an array where every element is cubed.
00823 template<class T> Array<T> cube(const Array<T> &val);
00824 
00825 
00826 // </group>
00827 
00828 
00829 } //# NAMESPACE CASA - END
00830 
00831 #ifndef CASACORE_NO_AUTO_TEMPLATES
00832 #include <casa/Arrays/ArrayMath.tcc>
00833 #endif //# CASACORE_NO_AUTO_TEMPLATES
00834 #endif